From 3242cff61e0f1e539eb806fd026ba76a60b35cc8 Mon Sep 17 00:00:00 2001 From: byterock Date: Mon, 24 Jul 2006 17:42:39 +0000 Subject: [PATCH 001/637] made a copy git-svn-id: http://svn.perl.org/modules/dbd-oracle/tags/DBD-Oracle-1.18@6697 50811bd7-b8ce-0310-adc1-d9db26280581 From e760b4e59275c85cf63c289bec8b97a2ddd2b073 Mon Sep 17 00:00:00 2001 From: byterock Date: Mon, 24 Jul 2006 17:56:04 +0000 Subject: [PATCH 002/637] tag version 1.18 git-svn-id: http://svn.perl.org/modules/dbd-oracle/tags/DBD-Oracle-1.18@6699 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 10 ++++ err_executearray.msg | 129 ------------------------------------------- 2 files changed, 10 insertions(+), 129 deletions(-) delete mode 100644 err_executearray.msg diff --git a/Changes b/Changes index b4c14fb5..22c4c13a 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,13 @@ +=head1 Changes in DBD-Oracle 1.18 (scn rev 6697) + + Added support for native Oracle Array interface thanks Kristian Nielsen + Added suppot for LOB Locators from Jeffrey Klein. + Updated README.win32.txt for Oracle 10xe and new Visual C++ version + Updated README.win32.txt for work-araound for UTF8 bug + Fixed a number of compile warings + +please enjoy. + =head1 Changes in DBD-Oracle 1.17 (scn rev 3726) Updated README.win32.txt fixed some typos diff --git a/err_executearray.msg b/err_executearray.msg deleted file mode 100644 index f80c4980..00000000 --- a/err_executearray.msg +++ /dev/null @@ -1,129 +0,0 @@ -From kn@sifira.dk Mon Mar 1 07:12:20 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i217CIwY019357 - for ; Mon, 1 Mar 2004 07:12:20 GMT - (envelope-from kn@sifira.dk) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 01 Mar 2004 07:12:20 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AxXyq-00025R-43; - Sun, 29 Feb 2004 20:56:08 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AxXyq-00025R-43 - for pobox@dbi.demon.co.uk; Sun, 29 Feb 2004 20:56:08 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1AxXyp-0007In-Tg - for pobox@dbi.demon.co.uk; Sun, 29 Feb 2004 20:56:08 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 082DD53C0A - for ; Sun, 29 Feb 2004 15:56:07 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 7412553CFB - for ; Sun, 29 Feb 2004 15:56:06 -0500 (EST) -Received: from mail.int.sifira.dk (stone.sifira.dk [217.157.24.2]) - by boggle.pobox.com (Postfix) with ESMTP - for ; Sun, 29 Feb 2004 15:56:03 -0500 (EST) -Received: from ash.int.sifira.dk (ash.int.sifira.dk [192.168.1.7]) - by mail.int.sifira.dk (Postfix) with ESMTP id 1C16974F58 - for ; Sun, 29 Feb 2004 21:55:36 +0100 (MET) -Sender: kn@sifira.dk -To: Tim Bunce -Subject: Re: Theory/Algorithm question -References: <48FB76BF31A47C4B9893827DEDF7DF2A03A08CF7@sacexch01.lan.towerrecords.com> - <7sfzjdrkv2.fsf@ash.int.sifira.dk> - <20030905085909.GR12308@dansat.data-plan.com> - <7ssmnbr44t.fsf@ash.int.sifira.dk> - <20040228153840.GA9857@dansat.data-plan.com> -From: Kristian Nielsen -Date: 29 Feb 2004 21:56:00 +0100 -In-Reply-To: <20040228153840.GA9857@dansat.data-plan.com> -Message-ID: <7sd67xk3kv.fsf@ash.int.sifira.dk> -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -Content-Length: 3630 -Lines: 78 - -Hi Tim, - -Tim Bunce writes: - -> Where did we get to with this? - -> > Ok, I will merge it into the new DBD::Oracle when that is out. It really -> > needs to be made to fit better into the execute_for_fetch() and stuff in -> > the new DBI, and I will be happy to modify it to whatever preferences - -What I have is a patch for DBD::Oracle 1.14. This patch contains its own -implementation of execute_array(), based on the one in DBI 1.30. - -The problem with this is of course that DBD::Oracle should not implement -execute_array itself. The way I understand it is that currently drivers -are supposed to implement execute_for_fetch(), and DBI will use that to -implement the higher-level execute_array() functionality. I see three -possibilities: - -1. As you may remember, the count of bind values must be known up-front -before calling into OCI because of OCI limitations. So to switch to the -execute_for_fetch() approach DBD::Oracle must buffer bind tuples in -chunks that are passed to OCI individually. This introduces the annoying -requirement to think about the chunk size. It also introduces some -inefficiencies in the array->tuple_fetch_sub->array conversion. However -if this is what you prefer it would be simple for me to adapt the patch. - -2. A better way might be to add an optional third parameter to -execute_for_fetch(): the number of bind tuples. If this parameter is -supplied, DBD::Oracle should be able to implement execute_for_fetch() -without buffering in chunks; this would be utilised by DBI in -execute_array() by passing the third parameter in the cases where an -array is supplied by the programmer. If the count parameter is not -supplied, DBD::Oracle would fall-back to buffering in chunks. The -disadvantage of this is that I would probably have to do some work to -adapt the patch to implement this, but I would be willing to take a shot -if you feel this is the best solution (I think it probably is). - -3. The final option would be for DBI to be extended so that it could -somehow detect both native array execute and native execute_for_fetch() -in the driver. It would thus detect that DBD::Oracle supports array -execute directly, but not execute_for_fetch(). DBI would then implement -the bind_param_array() version of execute_array() using the DBD::Oracle -array exec functionality, but would emulate execute_for_fetch() by -buffering tuples. Another driver might implement only execute_for_fetch(), -and DBI would emulate bind_param_array() using that (as it currently -does). - -So I would like to hear your opinion on which approach to settle on. If -you have no strong opinions I guess we should go for method 1 since it -needs no changes to DBI and requires the least amount of work for me... - - -A couple of other issues: - -I think there should be added to DBI an easy way to supply a row-wise -array of bind tuples to execute_array(). In my patch I implemented this -with an ArrayTuple attribute for execute_array(). - -There is also the issue that this will only work for Oracle >= 8.1.5. -Any thoughts on the need to fall back to default DBI behaviour for early -Oracle 8.x.y (this would require detecting server version)? And what -about OCI 7, is support for that going out? - -Currently this doesn't work for returning results. I will want to add -that later; while SELECT is maybe not so useful, it will be needed for -stuff like - - INSERT INTO mytable(a,b) VALUES(mysequence.nextval, ?) RETURNING a - -Maybe there will be some issues here for the interface to DBI similar to -the issues with drivers permitting multiple result sets? - - - Kristian. - --- -Kristian Nielsen kn@sifira.dk -Development Manager, Sifira A/S - - From 402dea6b9c230fb7950642ea75d6512549801356 Mon Sep 17 00:00:00 2001 From: byterock Date: Mon, 1 Feb 2010 15:19:09 +0000 Subject: [PATCH 003/637] git-svn-id: http://svn.perl.org/modules/dbd-oracle/tags/DBD-Oracle-1.24@13794 50811bd7-b8ce-0310-adc1-d9db26280581 From 5b19ac766a7a988125c8690fd261fb5c072f2c0a Mon Sep 17 00:00:00 2001 From: byterock Date: Wed, 26 May 2010 12:01:33 +0000 Subject: [PATCH 004/637] New branch for Debian pod and copyright changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/branches/DBD-Oracle-1.24_01@14058 50811bd7-b8ce-0310-adc1-d9db26280581 From 1bc472bb71d87c376754ae0a2f1f11edf22441a1 Mon Sep 17 00:00:00 2001 From: byterock Date: Wed, 26 May 2010 12:37:50 +0000 Subject: [PATCH 005/637] Changes in DBD-Oracle 1.24_01(svn rev xxxx) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This release has been prepared specifivally for the 'Debian' http://www.debian.org project. It contains no changes to functionality or usage. The following has been changed Fixed some formatting and typos in Pod from Julián Patiño The Copyright terms for ora_explain have changed and now read as follows: You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. git-svn-id: http://svn.perl.org/modules/dbd-oracle/branches/DBD-Oracle-1.24_01@14059 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 20 +++++++++++++++++--- Oracle.pm | 44 +++++++++++++++++++++++++++++++------------- README.explain.txt | 4 +--- ora_explain.PL | 12 +++--------- 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/Changes b/Changes index ddf69882..ff82a068 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,18 @@ +=head1 Changes in DBD-Oracle 1.24_01(svn rev 13790) + + This release has been prepared specifivally for the 'Debian' http://www.debian.org project. It contains no changes + to functionality or usage. The following has been changed + + Fixed some formatting and typos in Pod from Julián Patiño + + The Copyright terms for ora_explain have changed and now read as follows: + + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the Perl README file. + + =head1 Changes in DBD-Oracle 1.24(svn rev 13790) + Extened precision for OCIDateTimeToText to 6 instead of 0 for embedded types from John Scoles Extened support of Oracle Embedded objects from Charles Jardine Added support for RowsInCache as RO and RowCacheSize as a setable value on the Statement Handle. So it would comply with DBI spec By John Scoles with thanks to Martin J. Evans @@ -22,6 +36,7 @@ Fix for bug in 58object.t when test run as externally identified user from Charles Jardine =head1 Changes in DBD-Oracle 1.23(svn rev 12724) + Fix from rt.cpan.org ticket #=44788 bool in_lite should be char in_literal Fix for UTF8 and blobs by John Scoles with Milo van der Leij Fix for some warnings and one bug in ocitrace.h from Charles Jardine @@ -46,8 +61,8 @@ Fix for rt.cpan.org Ticket #=38749 Warning of a NULL column in an aggregate function also added ora_oci_success_warn to display silent OCI warnings from John Scoles Patch for UTF8 check on execute_array from David Mansfield and a little by John Scoles - =head1 Changes in DBD-Oracle 1.22(svn rev 11618) 1st Aug 2008 + Patch to remove compiler warnings from H.Merijn Brand Patch to Makfile for 64bit boxes from Alex Laslavic Added OCILobGetLength to lob functions from Milo van der Leij @@ -73,8 +88,7 @@ Fix for rt.cpan.org Ticket #=28811 ORA_CHAR(s) not returning correct length in functions and procedures from John Scoles Makefile.PL now working without flags for Linux 11.1.0.6 instant client and regular client from John Scoles, Andy Sautins, H.Merijn Brand, Nathan Vonnahme and Karun Dutt Fixed how persistent lob fetch works now uses callback correctly, from John Scoles & Darren Kipp - - + =head1 Changes in DBD-Oracle 1.21(svn rev 11067) 11th April 2008 Added Notes to README.win32.txt on installing Instant Client 11.1.0.6.0 from John Scoles diff --git a/Oracle.pm b/Oracle.pm index 57512fb6..b8a34eb5 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1467,7 +1467,8 @@ These constants are used to set the orientation of a fetch on a scrollable curso =item :ora_exe_modes OCI_STMT_SCROLLABLE_READONLY - + +=back =head1 Attributes @@ -1479,7 +1480,7 @@ These constants are used to set the orientation of a fetch on a scrollable curso You can now customize the size of the buffer when selecting LOBs with the built in AUTO Lob. The default value is 4 which should is actully exessive -for most situations but is needed for backward compatibilty. +for most situations but is needed for backward compatibility. If you not converting between a NCS on the DB and the Client then you might want to set this to 1 to free up memory. @@ -1871,6 +1872,8 @@ TABLE OF ... . Specify internal data representation. Currently is supported only for ORA_NUMBER_TABLE. +=back + =head1 Optimizing Results =head2 Prepare postponed till execute @@ -1908,7 +1911,7 @@ The default value is 0, which means that memory size is not included in computin the C value is set to a negative number then the positive value of RowCacheSize is used to compute the number of rows to prefetch. -By default C is automaticaly set. If you want to totaly turn off prefetching set this to 1. +By default C is automatically set. If you want to totaly turn off prefetching set this to 1. For any SQL statment that contains a LOB, Long or Object Type Row Caching will be turned off. However server side caching still works. If you are only selecting a LOB Locator then Row Caching will still work. @@ -1939,8 +1942,6 @@ If the ora_prefetch_memory less than 1 or not present then memory size is not in number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it is not included in the computing of the prefetch rows. -=back - =head1 Spaces & Padding =head2 Trailing Spaces @@ -2853,8 +2854,12 @@ $refresh parameter to it. 3 = Both character sets are Unicode encodings. +=back + =head1 Private statement handle functions +=over + =item ora_stmt_type Returns the OCI Statement Type number for the SQL of a statement handle. @@ -2904,6 +2909,8 @@ non-scrolling cursor. As well scrollable cursors are compatible with any applica The following driver-specific methods are used with scrollable cursors. +=over + =item ora_scroll_position $position = $sth->ora_scroll_position(); @@ -2965,6 +2972,8 @@ The effects of the differing orientation constants on the first fetch (current_p OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent to a OCI_FETCH_CURRENT. OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records in the record set, is equivalent to a OCI_FETCH_CURRENT. +=back + =head2 Scrollable Cursor Usage Given a simple code like this: @@ -2983,6 +2992,8 @@ Given a simple code like this: and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll method; +=over + =item Fetching the Last Row $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); @@ -3079,6 +3090,8 @@ The current_positon attribute will be 6 after this snippet. When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of cursor has to be explicitly canceled on the server. If you do not do this you may cause resource problems on your database. +=back + =head1 LOBs and LONGs The key to working with LOBs (CLOB, BLOBs) is to remember the value of an Oracle LOB column is not the content of the LOB. It's a @@ -3088,6 +3101,8 @@ functionality than CLOB or BLOB fields. DBD::Oracle now offers three interfaces to LOB and LONG data, +=over + =item L With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of @@ -3103,11 +3118,13 @@ This allows the user direct access to the LOB Locator methods, so you have to ta =back -Generally speaking the interface that you will chose will be dependant on what end you are trying to achieve. All have their benefits and +Generally speaking the interface that you will chose will be dependent on what end you are trying to achieve. All have their benefits and drawbacks. One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB column can be in one of three states; +=over + =item NULL The table cell is created, but the cell holds no locator or value. @@ -3131,6 +3148,8 @@ A LOB instance with a locator exists in the cell, but it has no value. The lengt A LOB instance with a locator and a value exists in the cell. You actually get the LOB value. +=back + =head2 Data Interface for Persistent LOBs This is the original interface for LONG and LONG RAW datatypes and from Oracle 9iR1 and later the OCI API was extended to work directly with the other LOB datatypes. @@ -3143,7 +3162,7 @@ used, normally one can get an entire LOB is a single round trip. As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG data types as a single large piece. There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. -The maximum value of 'LongReadLen' seems to be dependant on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. For example give this table; @@ -3172,7 +3191,7 @@ before the execute will return all the long1 fields but they will be truncated a =head3 Using ora_ncs_buff_mtpl When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the -Client's. If they happen to be the same or at least compatable then all of these actions are a 1 char to 1 char bases. +Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer @@ -3208,7 +3227,7 @@ In the case above the query Got 28 characters (well really only 20 characters of To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. -The maximum value of 'LongReadLen' seems to be dependant on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. @@ -3251,7 +3270,7 @@ you want to return on the callback. Finally set the database handle's 'LongReadL size of the LOB. Like the L and L the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is -dependant on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. Using the table from the last example this code; @@ -3432,9 +3451,8 @@ so the following returns an error: =head3 Simple Usage -When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob up dependant on the settings of -LongReadLen and LongTruncOk attributes. The value for 'LongReadLen' is -dependant on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob with the LongReadLen and LongTruncOk attributes. +The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. When inserting or updating LOBs some I magic has to be performed diff --git a/README.explain.txt b/README.explain.txt index ca03be3e..7af116a6 100644 --- a/README.explain.txt +++ b/README.explain.txt @@ -7,9 +7,7 @@ DISCLAIMER & COPYRIGHT Copyright (c) 1998 Alan Burlison You may distribute under the terms of either the GNU General Public License -or the Artistic License, as specified in the Perl README file, with the -exception that it cannot be placed on a CD-ROM or similar media for commercial -distribution without the prior approval of the author. +or the Artistic License, as specified in the Perl README file. This code is provided with no warranty of any kind, and is used entirely at your own risk. diff --git a/ora_explain.PL b/ora_explain.PL index a0cd92a5..b262246e 100644 --- a/ora_explain.PL +++ b/ora_explain.PL @@ -9,9 +9,7 @@ my $script = <<'SCRIPT'; # Copyright (c) 1999 Alan Burlison # # You may distribute under the terms of either the GNU General Public License -# or the Artistic License, as specified in the Perl README file, with the -# exception that it cannot be placed on a CD-ROM or similar media for commercial -# distribution without the prior approval of the author. +# or the Artistic License, as specified in the Perl README file. # # This code is provided with no warranty of any kind, and is used entirely at # your own risk. @@ -161,9 +159,7 @@ my $msg = < Date: Wed, 26 May 2010 12:39:17 +0000 Subject: [PATCH 006/637] setting the revision # git-svn-id: http://svn.perl.org/modules/dbd-oracle/branches/DBD-Oracle-1.24_01@14060 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index ff82a068..7f1307af 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,4 @@ -=head1 Changes in DBD-Oracle 1.24_01(svn rev 13790) +=head1 Changes in DBD-Oracle 1.24_01(svn rev 14060) This release has been prepared specifivally for the 'Debian' http://www.debian.org project. It contains no changes to functionality or usage. The following has been changed From 070c56b2da5859443c02c5af6aea22c31b045e6e Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Sat, 26 Aug 1995 13:59:56 -0500 Subject: [PATCH 007/637] initial import of DBD-Oracle 0.25 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.25 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/DBD-Oracle-0.25.tar.Z --- DBD-Oracle-0.25.tar | Bin 0 -> 98304 bytes DBD-Oracle-0.25.tar.Z | Bin 0 -> 44688 bytes temp_git_index.lock | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 DBD-Oracle-0.25.tar create mode 100644 DBD-Oracle-0.25.tar.Z create mode 100644 temp_git_index.lock diff --git a/DBD-Oracle-0.25.tar b/DBD-Oracle-0.25.tar new file mode 100644 index 0000000000000000000000000000000000000000..b824503d32fbdd67baa3d4c5d3b83557c78c9670 GIT binary patch literal 98304 zcmeFa`$HQ?w(q-tMSn#HlSnuq9)2bG5inqz2?lS3on*&38X+~Hv5<&b!e+d^|Mv6w zu2t3D0*vDs=iYnHjrX3=>aORiRqI`=c89HYFI{-PwzKtQv$6jlf5yKgNp9c1o&1OX z-toW5(z5;LRgx?(-AarHyt?WOe>+m&5Il=|sOe0rC~r(->wro*1Tb`Cn-lhgWfd}voj zX*Q~#_9~-=gI1Q-M?9Rgx_uswyZuqNkev;0>wCBVW@X`caFQ+zcuY!<{lhF7zMVTb znmcX{J9E?;&UMnWhuV?{RpIlRW=~C_Gg?5`!Hix|| zS?H&u1vL>`E`PhG(d8=|&4%qOn$z2B8oG5wL#M;RKdxxWUSHGHZEH$!U0G;%hJ%wN z{PAU7@YSD0jW70#4Smi2U%qvlRV?=Z9qs?+r8|G^|1Y)x*EF>8cw=S7kswLt=aZz> zPr}c82^%dP9=6(PayS?!FWBM9oqDCh0<8~D&xhTk<55y;&n8RXe}8+9|FCrX-IL_; zxZh5#*e`=|a?(0aI^AqE>>i9qX)^A2(qS?>P7~Tb$&$fgl6Lv&@1E|wOrECwblB=8 zFUAMGZd<)=ciU+{OA`j6ifh9W?RDGn{an(@lI%2XcMrR1hf!N88?NJZVnnP`nVR}( zZEt65=jlqa|7@#~@c(PuFP^O>jol~veA=v2g#MDPeSO>7S>JvBVtaFc^DEx_yBE8S z#@6HQUy_$Qdz;%^Ymc}2SlMS(gMRNkX^)4)v_Il08=s0A*?1xpyIFG9Z3(`CTF%)> z2mZT~o{W2~QFqW!dad(xSWotksloprwz@+#J~%n;rK6N3s65_$vb(pLJbt;gy}^X$ zl6|;056Rlj1_N*GuWfJZ=SWSQvkY&$y4k~fZ-q+Tl zjrWd*879CSJDTH^pq!MMnDpV+FU<7zzgKN9cV8~5{vfQBdPt;Ja+fRjM z3v6NyuiHPe#^bn)p|ZBct)X(o z#DP?4^?*#4vLY?Iwi>5KbB5{fWA(;NE(~Bkd|Ey0zN<4!AQT{BFzBQs256LA3zUPT z#^fVrXr)Aad~8CRSvsm*=qPqz)M$NOb2u?119L`VEp=lptKB1pQ6Il42GZ@fd*e>Z z8ZFh6wH&G0AV=C*tweM!8>Oc8n8S81T7Brh{oNXt`}p;)knOCs&$1#|_$=_CWe8iO7q z&XOe-=lOY-_70IX{x&%7CmYGr;ee^7(7Xpn;c>N%rgWN(>uG2Fs4}&FOx;lzyn8+# zo*thk4~9$M-}kRvKoP_`Z#Nc3H{-j|80;a&k$46gQ3v>!EtzAZK0u|{@ts0 z(tiEqq#Xw-kZyNRN3A!Ev1bpf?Lm5Y(z#VX@j<+0|Apc&Xs>&k{Mh{`xc1<*{YDR~ zqt;1;{2By3(P%SP_CbqZ^?&%U)uXf*J4NVyGI*CfI2^oNZH-x}e!az9v)+N1s62Zy z|MKVLdsbvW9kQXG4%4*XYrRb#{PWJ@cT0CyPrBkA)aeb{Z;qjqq3Labd^kWHOdgDu z7w>(y+G%IY_5R^F?|o-5JV=KlCXs?y$%Foz)$Xa5ktTZe?CpFnJqJoG4!s^FYZAb1 zHb?wiJsh3Z0gILAua1vnDEPfH$zHzd3SMfapBhDA~QEoJ{}LjD1+recwB8eTR9!W<=&`=@f)G>`fhTI zYG6Pw*&BeGjrK82bM#LZmUpY8w0+#yB(1zp?rADmFybS7SUnoHRV=HYwdy>_(KW>D zpduT;>}>tKa5{RIXtS*KdR^cEc5kFvo1TFEgHCu{J!w-1T(eEasQSo);Kp`(qS^cd zDPYiFWm60hmHMNz0EeCZ6%#uD_DK|ZKA>l)MDqN*@0QSrYmHZXx9ZEY4D7SE|HkGz z%E{Kx36-hq8~<;0=JeB`cbFy*8b5FRZDVyXY`5y*bM~g?dlCtfnrp0KYcAPsJXu&u z&eXu(;2dS_SqlY>c@Dd0gW);oijD?M+fWBSr}?%HP}xPw5L6BZdRT?ekCAQwUREEE zTF0Td;o~1&vZq_gmMG{}ztcS$Bzss57WL*GI;rpkydI`+lc&i~g8_u1b@X;s@(;*8 zY|mqPs<+yXSZfX&!>r*^(m+IhGkDt_WiVY~*6?T*7z|HZ?els!lHf1TLn3#Oj2IaF ztHAPuE{kz!01m=E=D+MeCr2p3pGAu*Th8<)IR+sQt#WjnO!qn~EX!G|2a6G7X9pg3 z-;Ga$$TuyvEYU#xzS8R+4BFjxy;Vs`9(m}j9L7-RvNXoDa5v?E@Nj1+{Q|kC9bQhF^V8G;47s1di z6JbE;R*chao>?z(k!+Zr_K@QKH|=h9e63V0PEH zkdel4VE9C@S81J|rY!^sCSxW95kU!2XeS7*=W$psVIW8{C`i>pk#{L}LI5e%R7=bl zq0hlDX*)US_FKdAD@9%m20!lq@?!I$w=p5yTHPoS>u*hxS|(H|T9q~xEFhSChG`p$ zhH6?U!pW1D+uKs7AJ$EWrWxeEpzoSEYk1OUAD5a%x&5;EKc9RxEchqH*?TzHH*E&iLB_8wRVbX4^tUdNRb?juQftAxCIxaRg zSF;Zhlb}N=dTh(VQ2SmR>#&7UW+lnaPavkr-w~So-KrEvtVN^lDHzhhNZ(I8&S-3H zOt4-UoQ@V6FL!>**sTk!`$E0G&{$utFV>e9+St(Q=rv%d6*ea2>l+O3?iiwKXWSkw z+^a9uZ!dt%q2}!UD+kBeM*p7}9P5*%rkKkJ@K!noOQ0Ra?qyG)Y4EvF;!AIpz?*~sw^owIIb`~sW2m+}Byx0q3ZXs53W{Kh=@)~K)V^Tf zsorq(OtS6~NLqy;VhEz9x2t-8=7<+=uSnzVLyM$LqZSy^>J2o!E?S&+fK1fVc%|@G zB2zdRA0_?q3F72Rvb=on*7A}pM2OYJu8(spE2al2DqmWGomrpi2Ey))1P~39w}auE zq%|DCZdh>kF&)jxj3v&7y32^plX8nu)s=lys{gP;b4DIz?l~1ZRF`HA6N0NZ^y{N; z-#L&WzYH++q3^05zdKjPl);FO#->@Hpuf%YFKcYs+lN+5(sa&aw4i;zEqbx-t+jw$l~{Pfe9x!*VzPa2!-l5%i_S>pQz} zh!~M3H90)ecP$y*=L&$733i_uH4gGd-xqX}trB6CAR-Z z13(TX^0xTvjnxq8Gc{`5Vb<)k62{cBi9a;9Ch<~w0cvqYUU_R-n_I?PcW|^j=-taA z8Arp`i4#0A_d=+KFvX#0)|s|HDwFx?U)P& zqO?%rg|{HqW7P=YW_=*ptnEzMkg2WF=86*}oK%IC576RhIlChA0P%n!K@m>-(kU@9IbuNhK#0 zz7SXbH&B^Cv?`bbx?uWFIxuUO&TL?iflev3zMB+<_NJ``fl-0kgmii z7Vj=1SlLER25r;%FbhDt;L^A)5D6Opxs5*#ii?gX134Q42+Eb+OFK|*DL`OeA5O_$ zWm6m``#io8;HFr?ilKEb{8fc6Q z=SIM3p;BGn-g?}4n9S66_n)Dc^J6x-R5dhh+dJyG|E~d__(1a>tjhx+pkt}k!zw`` z^KCBRN48 zF;-`+`Yn+yrW|&X0|Z;P4`P8vp{PyhAeNe*_?75j3=x149^eGFVZX&+c9hdpSUvV> z{1)IuO;vtgTH3pd5Cr{E?UVrrQHXcEs?3z+bE(Jb3Mk+XmB!KQo|sIiun6O0!!!;e z?3C6KHoZR`RVEGBbKuA4n4t?y+1%UP-AgucXY8*iP-SJMGko}Lt?{h3_-^U;;?mM# zntnGs|Hwb3wir#E038fRh4p38WogXQiz_H~$n?Frl5}ArFOdpTN3W!eIXWb3olcVL z&udML@@(Tlt~n>Ig8>AndL#N~AAlD@8-G+a>09D8;-944NW7>7O@(QibO{c3hsiN3 z4_eC-WHRyH+t>*ak)8Rme)(p4nai(%BA3wDP{RpyCJHF&5FAku48(o~nV>xw5mDL2 zIkP%idA8fwZ*ILTj&R5tr;zW=}be|(=Vtb@gb z{azC&_-}kdNVz8dGr7mVQv9dIf8V|JSN!+C0r5XxH7q=|eu6bF)|c^T2MqK znWl0ig^41{PVGWPi&!VxMN>hgIUUHWj&_Fu&`Naho&p5H4ARb*v8*U!x$<}*nl#t; z_xH9QH*X?gw1)%J#C~oVYh8zLbWp&i2(WKD^o|j?N8=$nlPt;rpTTYqGU$xR z5$v(l^gfYeq=*Co=jX=W=KjmQo#xA(jm;-oz+h>k{JIu}QEF98yCk;E1bEr`DEVY_ zfBhNd_E5pkD7P~{d7%|Wmxd#$|7zx|i;$x4FP}GepEU8dtUYh20r)7@U!G$B(dW(0 zjV7;%6(T;ev9-ISGESgmCXQzlyk-%$46dRmE-(KfT)l*S;#2sG72}x7{>eaUic|yk z7-NLVEAwE7WJh15t)$cj8a-=eO=ND_6|hP|CXDM}L67;QK`a8{)zP~&NE-VJ_&vnH zF44hI1F&iXgebXy407I$vkGy{s8rJDnGsUt44clHsG&j3YFP8h9u`JfA7z@S5~~U- zmhmh0W*CUWL`}(q7`CoD3Gmaji33Xz6h;HvvW^q3_J=beg%qOoEDa!9cSB=r7)*%@ z6ZVMij}1xv4-NVB2Qf#>#om`}9DV4J9QDNdHs8HFZX(o-hB&mCEaXN(d25iJtNr7o{QR`f^=0A<4J1Qbk{n!+I( zcAKcF`-Y?f^wL9&v6ySj*(V*q)PZ)pOY~E*wKGJ`9)t<=t!5|ZqlJH@_2=EAUbl6| zC|j!-njv6#Xj<4+wYe)(qPAI5>l|q1n%xZRcwbHlNKL-+HF>?rMokPtorB)s05l3j zMQ3;tJI>?XeqO8(lt$u*x1V6%lRT}Ai5k8xv5YuuV&tlwSaO^6Ym+UI-yop4BsnA174;Z`j` zv`Rpw$R7rd^j+Jc?pQMvI|q2MMH{}BSwkI5k;V10ehf#0pzkDdX>}%iR_EZkX|><* z(8RS9!loh7!A5ALx7IRFYEyE$)fv=gwQyS_971#>EN4=0k{XD1*n$BQV`G*XEZaS! z6lSXlQ`cM}G4iaWeRFnbVLZ;fXWQ0vzNBV?KeTyKorQQ|vu~qpoOOHW*RR+TD|TmM z#RzWSES=lfA;^hS4uobW9K_gMYv_;$a|&w)eFR2kGQlGh9e0A|V*SqdrF9g%%iwje zn<*P-xLFNFb3FZIq>wRcm=WrBHLJOEs#j$ zpnn}%Sp-QZaMTHT9z5-F2jZ97=&YVXj1Hk*5Ksvk?6ekA(e^e1#^YEj$hsy0v()Cc zA<%UZiZAfk1jQY5;g}iyRJar|5}0|)=#sFHwG~ybo7G-cc4UJW+Y7SKt`L`kC}9lI z8}7U0EoqkEaCIY+@8WibA?q4wEPam;YHY}m6_!DbKz+e)_2v93!%_F+ zw3UQo4Bo<783V*R?lV!ud|ueaF^uCoaiIqiwY~fF$qUy2D7ZtrMmIeQ&V(?^%D)71 zfV23UX=Bh|&@wHs-xl=qPyy!GE!THaLvm~Gi|rL+@rY5@H0*4IPz|%*g`lwF=nM-e z065AAlQzIq-{aB35#oW!qv!$R7GS2Vqr*o__%xZDrpt+7YB*&kOrR_qncYp&AHi^gYD4yxHa|ApIAfr@@gFdv}v$tdL1W=yD? zOJ;y6;R!qtLVpBkew|BR&uE6TK?G^cZ=YpxcdVC zL+Ep|T8-USrGF;L`|8W;!$-f~p1U(wy>cKniq|s-eEp-bj47h+W}+$CXlUiR1rAAgA|@DvMXJCq`MeQlO`?_D&{FVw zemD4IWU0P<&!oGB z#qSm{4=>$Yx%K_Z;*w%14`8IY`)4W&&QCVqjb0Mpo~^8?1^sWB{QkD~%}?ms_R|E^ znOB_Ck(~ZDQ6$6^tL9UD=cfo_jZw#6to!*zf}%_vPpXH#adwP=P`&Sc!9ed%-7qI8 zkA%>|*3pB5FA~`?L`c4skcbsUM?aCgG1FBlU(;7cfOgFyY^pnJ&o`@Jptx_fWXG${ z`S&2o8h5VBO3nwy4YYQhCP7oqPebUw#q%?zXhOxPBT=t1L!ZqPI;~dkPcd-wpTe%O z8Mo^voai=55x%S+1}8p>c~>d~5oo}*>d8tKI*4JmnczT|iQF#FzMFI6s?eqDA+8_R&&D|SMr zlh&|pPDhbX?<0;}OUheCLDfJ*Lwb0OEQJ=V9iJ5nuG85ZQ`g5?`kuNppocTfIZjTY zs~i$6o=nd)7lxgKlT7jPKuLXlu>acP6fRTF_>%L2!Nvd6QYgs$xHSRbPPi~-DS z(0*Daua;MlcvH;L?+cWcSUZ{pK11k_S!5q68crFW8Mni%{)2QaRr{;eY)MM%yO#=d?D1=bS30 zUp!3yPVNLPN`WK`#rMBMJ;JsMOH_PY!PSsA6qa>@Y3D9kEOd1s2qQR zX@&?oGhX`SCj?^#PFE=&?V?Kvp9}*x9$*vdy&)zFq z>H|f7EiY5@+x_sFS|8veTAQN5`KB~&UVGXwCN;l3Q)46|C9}kFDP_&>)qJwGz1f)6 zl$=68V{=632~w#=hKh9Sd&8W1W+Z@%k^$p{vzPPmy5t+^aNnM4^_D`3V6I`{#u{`c zPsTSIF>arY#Xn`I;p!F0Z7o7;Kz#K{`XNbwPpZeK z<9BdFXA@yFCyhlTwG#sM)oWgsuaHO zyi&z|4WkLgpzhrR@edJ=@Vjp9Y}&{9pMV!IO?B)Mz|Q~FAIvMjj}6R^QxbT=LFPHy zi1}guCzfY458XcMn|mrr>Pc0vE&AP(N6i03o(5%GF(uI7S0lz3gc(ppdwJ7R)5e{jGIFuPPGpDCG$VGI4X9z z*>*3qyUwiB;kNkY`Z~%OD2VM`p+#DjGtrYtX%cd1Y9WnA#jbjiR?UNJxFg8|>zaf- zpMr_47AoZow$bD$;In4qCxnh9xd9%-214+2a)cI}8A-~;)`!WG^LwA4LYbOuM)p1b zARb|B2i~bsYa?H(qE4;ar7Dpq7{1()bq&t|NmimUtAut!@ng>5Ybornj_1Io+HZR2 zkq9;{qHD!YSI+#FtcLL+5uKcKG(n396|#p8r&imuP87o~SPzFJSIQMxZNdG7%n2N^ zlYKRttQ9y;B>itKyN{XZO*BSigcn!{gU&*6SP$P8vXmK>RB46a8A;h7MVD*POu56iO_v6KjF!)i24f}JpPot_65zBXc5UXo;> z1h``;3|BPM$Q3cS1?zx42+417^1#m36+Ov(lndiLfhmFmdZE~-PKP>;LZg2F;`xX9 zNAIge> za2ikL)Qo)kc76|W%8xdhB!)9)QWy`A)yzUO_c)0C&ZZj97?AQKW(k@N#e?766Pwv# z8F5U*7CG-ZKZOM#c=0(ggd5Nr1mWUrZ~XiJDmN;nsY!IKU(!bFB$09pOyTSprSC?z z`|RW!KLDTHp60ZnjX}^ZRF|L6fAmI(%aw~gl)tLzR0;<~CCqOWltUmwI zsPWgpBksoy%QzRqybZJSWC7(4ki7LV&-xd7ien?P4YElQ^ii6pcdXu-jw{%9$=Pt& zD$IV>G6_DE<*xB;b9);>EO6Cit>HSz9x!6oh32|W2(AR3{zPI<@ zS`{IxRcD&~nVv>^f9D?q4VqE;_feTq+27#-PMzE-XfurkM1Rt{HV`6=>$1`?gI;99 zekh8o-CKc1L)W9eG#fJ_Oukv-jDG1&vw4_}I`u(p1E<d!fUdS{S zx|(TsAm9E${^)Sfy`LF;2C8*ICfr{3*CNH8+I&rf)pH_>*BBSFyk{aBO+uBVy5G@&PH%=1=CYaQlJ|YP)Vt6yDaw!i@k+~ z4Cw_TGVKRn)W}@=9`$3&PAG0Co1+x%uw=8x+I#Dbc#K2RGrNP6M-J?-lAnm=vTYAT z4cteJ$k>E!hk!W3ju`<$>nlv+#s4JP!mqDi8^jlq1tG6}&1b1P5f5jU2&4w|d0kd( z<{6Zd12XlSKfK0XRR6a2y7TSpI{%qnpfLm;fblWs(+f(73KG9-2w zJpo4;#mth(!_2alTnm@otg(2r{C%kB`b~8c7CSHUI+q{pqhSk?M_?c#tkN?&0itc$ z6>=DvW<+ObefBP8oUy3cBZMw7_R9h`5T1;N&NRJ-i?N$fw`9gztA(Dd`mDuQlglNU zS!JUckys5tD)5_Kr5W9DLoNCeF%QHUdN>{d96wCeSZ&0_aC8i$vA`c_A1b7Ddz&w? z!!otKA-V2@B#9c}uK8NdJ|sD<(H~0f?^}^sdezdqZQEk&a`K@8>D%Ro4So|;2}vn- zYo;e_lQ7&&l}kfN9->}b_1G#ojUQ8Yy;zhB4aWkqg!!n|1Jst*)3}fmb>`6%u(Xtl z1EZgR{yBO2a8d!ciNe{Ws8yTHZ>bocQ^%a4?`G8`R>4uNJhSI_r9E&}&|g zu5uH+wKMw)R3Rsntes{3KtrNEaQ`1r*BVY8l2btc!YbwCGt+^IwisxDf$E){*Ji*9 zj%^dp5(MH|T3XfSH$~5UY_-Pz#_r4gx#>`tGhDQORe@h)E5A|1&^EMMa3I^#^zq;k zO&HNmX6zk5L!ht!7AnT(eDG$R{CCpCloV3sB8M)s$_k0GEogS+JN3oIrPQEPt!!*H z_RTi>5W2c>vr=hy;YjoCZZbaxSMtxZ$?~IbbgYD2il@o^Su$-Abc))9&J(VU%VB=l z&XW1xllh&qzjGpdfI+wx9BUj5{cn=0VYh4kU4lf>Zlyvk!rzt5Ris)WrxOM4%YhQg zB=bX>1m|ZC^%|-jMkT*e1yek6ZArr5@o2UBKsyX5Gk^V4VxzOIx;|IzPc<$c?^pCEC5@qn4(1RsiJx+&1OQfW3fcQ%^M%BTE4E)B>CKtDvGeW9>| ziDtm0>*Bxe+`CO4^!)x8i~m@>d+)FKj|m|DNk49An=8&E#{iG=So~y^2TC|~KXwts zetr*xm-_`1*uQ%dg!=nZS3x)%JVotL&{!z~BFHf@)lpcE0i-XrV2Dho#|;2jB*{`ONtg}iFJ78)jGpt>R70HQO%DoB5<02 zaA3##f>9TG?hum6*UP;xIJ#Oxe4F7fv{`Zo`G_(sS2Nfrhf(H;$`d-9d^FXPy{W4B z4->W-?Y|Vi;Q<_zZGIwz!}|MB$o(hT5iq$TG$r{#sctNa_>xU*Ize8tpvH9c6-u); z>hgbSekf1bktx-t3ORVpW~%f9RFlxIR$58* z#6auEO=&>TXZ*I*O~jrizw?C%(5>#^{_(gbrv*ed*@&yJ-0ooCB1Xq=o5NuYmwG)@ z+D3+kr9xnr)xTVbFR|QOIK<2DC=W!NL9$d%Q{u=zXy4f6d@BZfKoby z^*~&r_JIUW9_R#9!VIU7k7r%%u1IgDoRye;&!S_@j`wcJ<{#Xv+OzR+qa8nz1sX7@ z`%(*1+!t0Btf4Jk;9)VhN#pn4&7IAC#D3ny z1sT{mKEnjn`sJqW7?wlRuG&#BvFCP?bJpe*baCA%bR&6@4oQDx5f4_LLXbF2OV}Z# zM%pPq1T!lfre%RTcDQbVSgM6l-vS{lbzV}lSK049((vhE`b6j&z%oNgu};AmWrQoj z1nZ)&NVLqf84*TfsLugG)^Dnu2-4wQS&VE#6J+H8vSOGH)(asEq7qR*ynor)+;f8B zJE6M%a&M2kE6ocZ!eDHp-$>RK9^urV|&)e1rh|!)!8MjS*@HHTu+A%%5-Rr!;I)ce*z`) z<6CC_FiLbFN~AaxJHCg_K%AJso175cNUm9Q(l<=75`K$n(PmupMr_&_xajE8wvsG(j%C2d)uFqe8od65x-BQB%Mjr#!$Jd`a ze{A_P{2@6T;wbC>=5sc{ms@{u4^H@r_z&MRQU81Qr(}SE4qT)EE#0}x!Rib8-_r75 z=YRerjc>A9Y+Ec(Sp$5RnFe_4)+aSU)%=+LR|sn+5q$~ukKVqN_IGmuZ*_F1P6xhm zJdMz}aML2yUlH`8h(*jY#I37%1>xB?DK`zRZ?ElbA{(Ah@X0M0j z%!r16#_-W*;G5SqbMVKS5&6BQ8E9)UnhqzEtxuTOBm+04#_2TaW_H^f#*0NeE3;_R&XTQ+QlG-}--5i&8f z-0oREr-&S6y{>J&nq6XEq0nhjC{A2sMaP?}ftJIYv(uAPG36GB#{4_xVqk2?P0Pf$ ztTD_b=38l+hO4F`Y)j*augbk@STV&BOB5NiHq_6AYMyMps_78Ft;&_VStYOB(5%cs zSeYO%nhX>bJW}4y$+TNuBjjc^Cm?{7Ub6g#I_00#zObed&4l@#gKN9RF7XYEb`Aww zv8VnZ-yuz?1{p(0_X1pV>Fnbp&5K+Z&epAEJKjD)jfxvkOG~Ou2f-^^3(_b@vnA!R zXjq-&&a%Vu4=v{a^SeAm?+Mhle>E=-Aq8n!X4dnCt*4IP&)yGSJM;W$H&|)TR2QXv z_4R(TG~S`92x~zx*uo^t8;MawHgpI0T>-R$%)}(0RExr8=r7z$@oNGY3e4(I0j;tT=7D?TR6{ygd ze*~FnN*{6Tyf8wFYURtF8D1OYEFD>?+NbAJS}NE?m>6U{4Ea)nrCH@Ln<}dL1Vmjg zOd!ymIP6g4{uB(n+!djlM1-9+mz{@bQ(U6`pG1p5x>3Z1p2dihuZ%vft?y&+a;nMq zBzLddSMEUGDZYts7zYVpm+7)rBHjv}l)2(uVd+ZWM1q8`jCx0s+x%s-;X`l_Iul-3 zQaNL-1sC8%_W_w>k0MuApbt)35;$N8B1?@Wfyp9~pb-zL@kouj-KAskHKeFf{Fj}_ z2&bp(Y~{eVgSdpHE81EVkoZO2JPPT9_icPt1SA9TSfFXOK8;-hNB07qM^l@<=B5T*SJ7X(gx& zL9U||Ars2KgmSUh%k;p8i!j>Q+|NNL`pxnv)tO)WOBQ}~dl}Zpr-Hgsh--oC;4!Hg z$tGMV5&ackXGu)!66}u2eCWyh5O}8=CD;PO5R_2H-+bXOY@^TFMIRaB<;+PO^2hv( zNwZio+gw*KWOcVj_D?sCa>>YR;TAh|NOAx40 zvBWsyGzv~p5*tI8c{N59=yj1IQSBiJDlKMUwD|-+4m9JlR;K`$F^%HqABJ8rluyIY z%N}1d=4;^>B|Mul2d}S%qw^_>8pI1e<;wA+5cmaA2uBh%Hn9jhE7&znS=VTZKa>;9 zII*QlAEZE!Qm0Y2aDykm1~D_dXlOUYMe!)`Z~pwzRI8f9W|t`4at=~!ED zYSVdapX-kna`82%Jv6*rdB?j685fsHJ4RX5K><)!mZYoqhd zwag$Qkg4=-;}vQdiW>#7eb%}UiOKB}O5=dMpM3jm*T|FV=V}}VhdUH1PP}Iz~aZKFzk@jA^D9FN9=)4B9wayCEe!BJix$OJN z(`GO;AYmC(Q*8R0v%`RNf}4yx*ruej8+dqS25=p=g`jdb=1{3EICRwIRxo9o0-AQ9 zmQ8_m3)#%wd9gMvfg)s3BRMZ_JbAnZ-hPsD?_4-H)zW3dwa_uj*{oI1*A=D7#w-ke zvbDJ#Bp@4inF+Pdf+P)9F2gn=TS$&2Cz(l0vF7oR2(|HaG3v#hpuwzjvo_KVv7wfmbYM~sVvTjH!Tn>q;$ ziN9jrFVcRIfJaRAEYNQM>E9nNUP12|{gkz06iBH!r@VCWn^p_5?yVOe^}AG|z&F#F zyfmBAA1;xGy;n{kL>`!JgnZ;%e{inlNzO_Yh`Yyo^>$6mjvor0Il|SoKX7DD$5*db zI{8`v;tMF9;N8c&WgZ4XP`RvhUNu5ZnSbTUm5eE_Bo_6qK!OWebg_u~P^gb#SuQnL zEZkS2Fe56e`3!QcvosQ~7{?uI}M=EIXib)l-xQg`UT4+-iRs^%) z6N@m93RhVJsEFom666f|!Et|u_^ZrcC`c*?T+IMB5+d`Er4e#=5mWLX?hBj@(Nd_Unk_)iK zse^~=T~;A^+!sCn=`Bb9@A0H_@C*HdcwXcGO>W(~Mb5{G_}{yC@BJ13`-Px?eKVK+ zzsKhO{qFyA?{6huOMJzx6ZcBa;RleApBwe#M^mDD#j$(B5ye#aszkKoUMiw)?&A?j ziZ9%P45zWPbZlKhQ*_>zaH_0)lQMaxaS18^6vt-lJ_fj#Wo}QhgYHoiF&%=T0Z3vG zd8*8c>KoXuq`Os5{GhNpG2>-VNyfdzS5#k+dpl0t?_)OKHgBKF5^5akUE-HrhI-}x zh_zCB={2RvtdkGu=(w(F-(X&L3OVi6n$1CW*lZfPFWy;V%~=(+1lV?!RlWk@7o@Ix zSh?YU3h#XRPOI{|aB8b_*k@t%@=#D)U)yPN9q<0G?y!e;M*sc;indONDtbd=>V;2l z;wS6hmQY%Nff}tU_hPwrL<%=HAzFAOtm`BqD2s{1kl5{pr$c8D@Ds z6)gd{unWd+#F{UH$oq}f#WHZIZ_dLUyc58Rrj78GhBc00^2^76ZR^phG|>U(1D`A1 zn*yB={%oRueRhd9R+k`p-@JXc3KY1o3ML1YutyUN+F;&^Af#mqO0W^5TocyqOj3uj z2Tf^;);?HgrS!u~UL5DYwA2jllS>T+n-rCfwL|~1|0R=VkjwTzXAYA8WM=wv4uD-R z|1B*qE^+5uF8?Y2_r2wNcm6v6b-m>FWxiTc8!dgZnOgw26ew-6WD2Hzp^tZvbn*x{ zNj>C*2?>G=)bW#JOP`b+|BpU7ror#~RSg#c?}*>iRjSdlTI9jOy{qh(oND3j6rVge zZf7k5@RX>Ndzf^CE8EjH^Gg&_Kb{Vf4M$e!JYoyZgU7fOtdcQ1~JLXe%fCoPZi>4#@ciDmFlpR^N-;1b}T}RI-{#JbTCC; zal3UZ5Dw94hgkWTKP|`3tsSfXic4t(9I^qk~pM87LhzTl^x7EeRD+9 zwHc-&+P<=)b(P;tF`srUu{5Uu$k*SzpPqS7%?~RpmYHOlqd*FIyD|0eWL~hkqEb^c zy-tf!`JR)$V`-9!g>EWV(z@i2ojK!{ZL~$dT*tRB={7nojx-4f+Doo5MIce*_`mlr@QImrCJ(m3OjOUn zV5fIZM!NZB#%RiK0E@|4DN#g@c4j(VNKEq_2@Y_?=bzmZXU(d*QJ->kVlD;g&_$`D zr+ZPw(kd7sE*7Dv7)O?$?~Tan^HCS`k7BF_$81ixLkC&o!eJ^^f-#owQ}Yb+T$l1zTB;AdWL3kE5Ory2{0GC#`DNeZyPjjz!~(9`wSEoJ5}Q%F_Nr` zxVu;9M)Jr?P~g#GASx3$z#z1J>{HCsV(TYdv8B^7ak6+2WA$Y1<@SE^d~^TV?nbh; zBMyU3;dK!;w>Of)Zv?v$Hpn=Jc*Gs)9_N>z5H$$Mp{tnd2AtK7g#&+SXQHD(&s78zD)-!Bp))1kC@otGW9~7i!fr1EDu@#Jh z$X~kk{;P6aVkjQkN#C`&1;7nTlDcB7V)%^2ZKpz^IWQsth>JakTvQqpJlS#c%RT;J z^#voANiZ@T59OTx*+Kc9I#y=PMYhf5~ZP>=CTJ zz;{OT@a;( zY2|#$rQf?j-MUKOj?EWhN=Ouyi@Tvw8WCx5Y4)O2b6H3ZwXPDY^DZxl*Vf~g-S$zl z=?_dEi9e<2@WMiypmpd?iv5jhi6y<|-cGW#h;Lz2&sw@Ma!ei!@+PAYLqVyIoO>8! zn|LrG(G@D%WRkRaBK?$vzV*t@um~$F?82rOV-YVWr+~R%EXr`NEXw;YEcYmR5vo6D*VXoN42_;oCKiEo+}Df3M|fN0_3WthSZz}T$&94RfWC0VZD z#*{Dte;?Gt0ghf9&$Pn454fhDmLZnz1k9$Tv6dbBg6!hh#P(bQm< z=^~z+KpI~H@)FUMOd7u!(M12WFoXKXb1I{Yl=Id6mH!!h|Gy>wGrJ2$LS{R6V15~+ z@`Y9a*LCq9cb2(RuCV{#rTE=@xBjyKUx4DD^RpEH5plrG_}>>+{N-fv&dQxTD@%7L zZ~0@L{?9%AkHZjE4f7g$9M?1VPPnFGHsQLO4h+acC6lk@LyX}P&)0r#uJ3L)lJCF2 z_^zp3m(A_Xor~WdZ;^xX)!JTTib{F(!?TSwJBXh*6JI2EmX`AX2#NZNYCx>u@;2guU*EqLYm%f`MO0DdU~_fXiaLg=~P z$arWmEHZ)soDI8F5BD(=L_C^}2%#X#qP*Z!9)XXqJc5INVFaedZg*Nu#*iSoxFkM4 zAW0b!(&bqYNPiS*`bHzW***gpI?+G^OIkI zZBrwm*KB_J@fpzs{_mzNT2194L-UV4abNEhUCI9+{wb}j!U)=-E4%81EOdHB@*pG{ zbBAdG&apoH5J#J1YjP8$y>Fq^jI=czw$9}$E517><;Ofr(-gM11sIKm%Hb+_iTSeW zTZDpT^3B3v1EjKp+q{s}*Q7S8xiw%-xSnniRQk@9>HVW&>n&%34l#q-kq5O!LdITb z!Q{r~;7uF^5~RJtjDsM?)n#(&C~i3(X8|=M@vz(*`_G!(i?IH3pHvG|i|-JEm%!c9 z{t5g0eIoqvNipn0!l7}7ZSHL;J2Ncr?7L%4F3aktZ+@tOXkRGP`es zFlk#hyDuwuSn32uTs8w;=Rlc2eE($!%ZgSKS&A>%kT-2vjJ%wp7a_k|LS@!9gTS;$ z^L7QIjv~cjTf?f=bE*^;;;I_fRCy^oHXQ5ir1eg^14q9&CdwdXq;Zh3F0BySt6Q<&N=X95#1F=L zMip;rYZz2)SOI5h1q2qmB=zzR zuO5jzdciy`#2jZW}xr@vxOb z9XnBcMcMLRieL;wunB6BLp5bgH7f(JOeV-@nSE@%WMuX!YbHf`AU=r_`sv8vC)92B z3Y?n)>tvDuONxlH$PRD94?Qev*p2~gN)jLAy{1G%beFj57Nk|A*Q<3^(n7;XK+>`N zIVu_h6E6lS+JIEhZQ;mEq1{Q!6Ni%1oDleBeMAmXn$Bg~Wy2EUV-9C6cV2Q0bUz(( zyTXex_o%joDPJ=C6J7l!|G_6F^}qI?qGYgi*XVzD?%ultIhu(7x_j^L;$QJ!f68K9 zX!NrF*Eaoc>C<6c+LHh0Du6}swr>Fo-o7fyn`jyrgeb~Ylv!fleOS%JOJncQRnM>! z32RPO-O+j#jlExaZ#)q90k`=gUwN#!ODeHD`4?mm%@cPqV*PgOwFbn|{^aSa=Gw-_ zbNsJcka*U{OyDkfTvy*p(7gutw5yn%zET_4R9s#-}ph z$D5o1-f%ERN=`|gD=|t+rQDv<6-+Rom9<``^12|(s_Ft$1m95645Mfj9Pd5g?Ke_E zz4y%_UOrAVpG)NHAK@7A$Rw_5YMqe4PvH+02?v%UNDwvFT7w-LD-|0x25Jz~B8QWT zWsaK*j@+E#&mLW`iunp&P6|h3bjDCwKNk2>F1S)tqyYbQ8I9n#`-vVGe|uPcjg8y} zr3fp=%F#keh8Ejr(x{GsGa>nbY)*cJQ7W5+H9JkYjy^(oKxgcUq>)~ADHILHBHnTnS5pb4}sjMrpaA%xK09Vi&u!A{(Og)&us&Dj zs8iBC&r!#1w&jB4sq@w0tCrK|8cJw3cJ~g`anM_KJ7o7#t!bSv+z40V5LrF>)sPCn zT>3CQt1K?spFSlpBhPdPR+jVJw!-H~}zzwo;_Pc2AToYc5SXRhtwt1IB`b z-MBGyjSjm1sc!-skC%$0JUnH5G|A9blIqu4m0|Hl!y<_XALbuPUu2o=*;O?QQP_F8 zy{#;r7SR@=I?=4DPG1vV2GKD!kz5^|XD=R4fk*ar$HAaQu|8bSrAHCh+3-r0CSTbb zKOJsmq-2H>n}QiuX<|fl0Wn;0U5_bCEbpA!gETUG(8lryyW8Q?@Jvq(9jSJBRQ>R% z7UHAYU?f_`z_y?f6`x|Wn;A!gRS8sKNm;(A>AyEjWt(n!cJ*X?cjxJx{WsZL`zbtO z<6M76+DwSMz9;Jf{?3J#Y*;EA8(O}7u_Zw_wicqUh~8xpuUtdt zhjA4JhN{x}V>A#{wWq~G6TZ!-fnYHH^N#?^r~c z`uUBa^$^>dY~Q{CBMHeVdSz<5Hf$$G&d!$o?;*Fkio6X^!-vy!5Wa*L1J;ltvrg`u zy3x!0Bjfl+?Cj^+a`VEQL)b&P{AnBdTzWxQ69o<>LKF?su>m^Jp)UtpCuN^ZhiaYM zK{ag9_QNH(co%}9p5Jxb{*j4h`7it+K-h&eoeP~`%6~Fu{fy~uMT=Oz2N53`n(NG2;5FYcRg-)t_yw3Qc{jDF2Q-((e9C#5RO9L5_` z`4P7A)+wl_X)>{AXSh^P`I$?(JaCtwIk^0a;2-yQ*s<(lakmmKTuvRU!NlT$tthlq zQ(-g! z{N=%W^c(cIly`+6vHLu?ij{C=)f($K$|SmYI+D*_bMHP}MEcQ1kFYe*mmnV_@;-m~ z)cg{|j|2Fu2~6Nl9?kz*a{w!d4~D~zNkM8?Y!}A@Lfo-maH~sXBDzt@?{kv>IjC`l zSi0CkaXROvO^|kSL1<#@9EMcw+H*$R3>)m+#FqeQX&OewK8g|!0UU)@1#(HzbkY^3 z*kb=7d8EodR!-nrg2g_D_L!(M?i<`}ytP9BehqU{RpZs*1qVJ=J}pY1_%GZ z4@IgUIf^W{DqQgE4jsHjY^|^27$&f~u;wTkbt#$VBsY0)KR>oBODmOAMpQJ}h}7yN zuKDu$Ot^CC2;CqDBJ!J@_e?$aG+En`@J?XC1#;+lu$bt_({CAp5mgoiw8Qs482yZ? zqpo3uhM*&RuB+K4u!FALoD53mB?aEdUYM)Wbx2oY#{u3RPAm%U2(IrdE#F zZ+cu!yeLBh^3vvi)@T_AYd2FZdx3!I6b8%i>v=&hP$=Y^f(}C|LL_9(-v$D^4TecAHE{7Z1t$|7PcU>;S zwP5mp{$QOPV}rrJnbvC0UfrB+ob6e%Vhk|0N^f+?gUiHHC8&tvNf?Kg+u68q1NF4X z@gOoB5Z47|mADFD-y4!J<_nuqLo?L=d?aOb7f@8qd#tHcDosZlm1}8*{FVB`r5B9Rf28yGNlK1_V#IeP2DYtuS8;S_RF#N;ZHGSo&C!aOPGm220PxL06; zXq{blKkCAqYG>V+gs<}0X072*FQ37~7jLR2g+`0K`DC4&yU4d9IWs$R$xrs&JeN5) zrxjcw_g+t^T}9#8iV1aJQV)w_3K=Eh*&b}rr8^Mv+`I*zQNSVWBrRtw{!*A2R%uc^ zqgu%0CB)0|@j^O0cOwr7*~k=JqfifvRo1>E5p83$xwFfCGf%jnFre_*LRvzN9*8IB z02yCZL+2inv%9jwoZZvG)NI@ZB|8Vv+$)RAKnv~I<^d$w4r6GKbw2qGb&$8FCom-} zapedlk&2iv1v7zV0>PEfnQ&dI7V0A7>@R=c`#I2b76=Nw-^DJ~+9r7C;yO$xE0=B-BdN_Vy@CUFrzl4aa0eV(Kp z0(d&JN#j4aOCt#gNu5IMQuI_An;!x$NpCEKg7at1pX9NHUFAcF6jAexQw$fpA?t*b zYn-u`P|zlGV>~0$f@}YSiJ$76U2J3$*0O!rfp-DeR^6r+XK$FCYs`7od=z{lQfZcz zw}ptSq`x)WwX@}UQksn!U$HG+1~HN$ugCY_{{}V}qlkN5XYE9#mH0lt(ay$6`e;;T z5qou+1%tj^9@F`{_*xkz2}J6RMxY_sw2>kBFXE#N>TXLfAtq;U)4{j07(fzdk)!0v zxeNrmwC9S~%;l0JX4>K5I!v_1YwVx7KbWF+{=m;0=bb}$oUQn|SRs`k7mcg0u7W6W zX%EQ`6(Rsvc)6s#ixe^5xq6|V+z3d* z>OseB7#n7K9hTKn%G(%rvtj2)yUZ=Ck&tbKKv8r3%8O}dE@P0LmLteeVVk!H<02f9 zLC9mAqkeX*uTqGN#>-tSLVHPfvhS~dWzleQ-Ku#!W`7R4<5b6XQkQ<0g(N=L!mPC}` zqVdgK4*s-pUJ_DVB(^ZtZoi3p-D0X9CMB^y)RDdKCiHKJCCl=8xrAe(cOHOu8k9Q; zJr-mabDJa2k}O`t-dKL%Wu!3sIbx)dTRZe%Yl(0Doxy0Dl zZV`Fe9i5k!P<6zPByt-EgnkWpI)xb`aN_R}yOhskaM14z&vNTPj;BRWB*@UzZ_X+? z#)*v$k z-xxqo(S+nZM0pIq(UGD?6yDU$&BrcWvP~GBE|LTdpc(dmzUE`~^^%=}x0mPZpLMlP zTDwVI(^7@k`r)4XYV_1kpvwOgzXB8UD%_e-U8zbDw-)sChw7|+az%w)6*i3e_FG1# z!ry*NOWIc`ysYJzP+U^6Pcapaxf2G%9NZsfhdn)}81;hUfEa)#m8mNl^vQS|VKA;r z{k*VC?hHZ7a^`DACfKU=J2$<8GZ2_^Ul9lvU*xvnN@w?nVR8%np9*TXM%c|Zww`Y7`x*o-O{naCO4X!$fIysZx2AOp?G+QQo^pCp zbXnErAKB>gIawDp@F>xVmHY&XEeo$7NaVn?9Gh)%_M#SvUE%|KB zE#Z+ck@~rrN@6+NBd3WhfYv#z!Fo%o@k#exnQA!t;4u2Sv+#9ic6!cWIaf5nwDKPe z%s%tZmOn~*#X%44Z&}$w&pCA{m%u{s_SvhN@GVjxGkuh@`P&D3X%~+W3=>G`N2!`x z%dHAmbZeYVET`rc#MzoQmaey8Cn*F(Ly6`hA%LgkF2?O4BXVeJe{1^*hXh`?E=;VP zz5fV^j8qx3zT$2cAZ()Yv$G#JfAK57Om{5Cp^2*HE5dO!m`e`aWLlb?_yyYzGcaTj z>?`q&7@A}Ker#Oy>QgNnd~HytW`E%7p<_SlgT;+CGc(?GRu1Rwp^7)ISFvjG<_}ms zRME`=8e^~!>rh7%`O;f**+cLAw;`TM7eQ(WwQSr)H3>=x>i(94C!w(5-#FXZ+Wir( z8s=bE+zD|M`~bA2X@xjKBQ`byMBZP&C-|;1WoJ$vDoBDKQSH)8>4EP>4Z_a%yFhTE;h7D%TYX?e^l%PpGh&FLafp1 zVB;x~qCfy;od`Hv-T*$0asLgPu(o#znxKhxq+!d=*_s(5Wo~})>SvhB*(qU)#vn`E z3F;vFt~Jl80QI?W5)T9xF3gX1&8IlBbU!~OX;78WX@}cN%^B|G^|iGcTsL$hQxp(_X3=tR2D;G;hgmsv+lD3auq=ZbKomoK^>s;_P*^IhMTS8crA~9= z6wUz;^>!_4%uE^qpNkC{*4_s-u@J>rSfXGH{2)M@A%pRYJF*UT=axg#9ht43EGosq zm`0(BW{YZ_o^mf3W`3y;q*dZrTK8mpGLel0Uy~WSRB4!Ms?uK2aMIT0EH znvsKb)YVjj?JJwL{tSDlzDDLJEFUN6wdh=EJ1uu96J`MZvhdj%cce&D_KvKw7Kpmr z=C`4a99{!X{+&pNF}y}|GKaNYoav)+O-k4ns@o}6Q`a;CcLxz1>&6t)%&(;O*CU|or!tiG8*6z7?oDY=`D-*xe;rQa_+jiTLpP#~hyM=Rx4+a3OW+1zho6c8MCN72`gA$^rEG*{` zBZaoSLry^qWzUKZmmmT^DfR4ZJPO>CAf2AhVXPq=@SI!*U@8_y0}T5U*cf`2ZnPI* z1|2keXabu+?yQKTf``MZU`tpHkt{t(%7-n3u8}MZwo5l>^A)FNYgw%|jX8Rp8itmB*(z*(cY~C7(ks9W(0aD=;HQ*&BS($Ru!08j*@nmT0Of zyb^_5D>$`6pA&YZ_qGNZ=k4uuZ`0%}^&`LK$PQxnWYy6to#s9CSHH##35Zepq}#zu z*Rk0nH5CqvXcz#XF0)ETVQQ0<_BkifAQLH=;ena&zAP0)`VNFK@-o zS&;A>?^7GqqvpRUnkyBf{IZq5_&_HDo&IS@;-Q-Vq!UOLSi# zRk>nz;VMK*6;%p!%q^gfZ7eE2U(Q0CT&I3^(zpMt-Ci#F5jk1F@df=W8uZV6Y0BKB zZ(vv6b}Phqi&)CGqc0{mU_Kk4aJO|C$FJ$49Y{F&? zza-7FhTVgC?$o7qJeQcVAzX6H_8dPKjg<{O6v;0H!3BB5Ih*_SInxqiy0uw~SvuB9@;53uNL zAu_Yr)QR<1NOT%MrNzLc30OqYK`Ox;>DJ5w++RSxMKC}@Wcse1o_fRCY(8`vP<)E% zi7;M_p(+X_gF0IJ6ML&~U z%o{34sANRUAz#o{ZpGQ?`6TuC^CJuAaIaf8zww&$WeTJJ^=*JvR*dD8gAs z9J^m<*uUh}vF1f?ORP08903EB!?yet#x@~5wJoiNU_=Ad(A%J=Tq!4gl(GFkF4W}m z^u!?vV&H;}!Q#|xJ~G&%nS3mg&B|!9U*)8&klSSn()RkJUVh(R)|$n7MrFk`qtL$H zHVm9|rALIPTsqeZbX){}Aj^@(!_GnIm#0t%vzjiu(1QT;rGf3%bk03h|cg+4}0ey~Ep!4Y9*uWCfW0A?vm zv1y$Lc{tbWXh-n{QD81=PEE6K3j2KLb-OZ6I z;u~>}A~a!*6uTSmhIiFS7KR-B}x8`#8ePQC|_AZlG z8IY}d3AF`XdJ17Ya7ChlG*gA;dn7sG02-<%JPzmDRqG1ZhhB>+L^Katp3bvB6zxa6 zE{{;Qm5;83?GC%To@H;$KSC%%`DmR*n1!8IpgtUO^2Yj{N=^*@j|>}gw;L$Tn^|;0 zpVp`=QP{ww|}X%&Srl_b=M*( zymLju-7uAqB0Q9Nla1Ly%n(laQh5{!cyw1<-8BNU)SZ&rXX3F5?L^t-?3|8wgC#iT zE3mFh(mir&K*ata2>C(JVJ8OS%T^x5-DvjbZdr+*zILV9 zlza*A1XAD{98}4)$N9*K%~O`oJPM(bBRPenenE+-G1!7MI1Ls=GebG(?@^EyJO?3b zsnltmLEF=qXiC6w-*U8y-AX$VNahdD=k2`r2%FQ$XdvoFe>8@gpBL*$-G(S=pfEDE zktqUB00OHbxC@n&%!rnvL-EBzQdJrOUPmFl5kadW^s~FwRMVskPhw}_zm_7}QQANQ zZTiLuG{vhxSIDBqd_PV5)R1y#7`ZdAsh{sw`V4h#t_;w^(|H&vnK*eNJ_JIRPS8S0 z71(yr8yvW)+VFtr{KG?>OeikOE&&G~4M8^j^$&$?VWNe`B{{(=yIf%Ur57%}Ff3MS zks)uk^tEXJV}hxw>R<%CwG^TVvs79^o3A~yYy3o#4LneC-|(kreJSJsX&NV|Z}DI^ zF~ae7*c~a;NKjdY`ZnIPr+d3Ug_?rOx5Z$;UGiocRtC&YGsXEpm%d%Hji&~jRTD5C z$xMt(cV~n_jyP@K;CmaS%Zi5t0snz!o+Sq#e04=PFxKWRD3+wo%*_ z+u5l=5SAt+VD0Qyr^lf`?R%;Y#z)7t^cF)cL}2tDsqCJk)~Py(Yes$dbt%G)sp8vB z?%uh>9rV^7D`IX?2|?a{+R2X?P}gKM2x6VL+*QN@EAf6uwTU#IwL=^yFLS zhrsq6vH8^ZsStet%xi}nJ#nEHqMDjI9v@fB2 zO-HwS3Jx1f?K60-?;ctten~1LylQ!TO_F zSR1}FGQx{+L1dzyqw9+PutKZRgqAK~@hN$}F0|}7Z+%wVEckkh6$c~6LvRFpnvP1c z+?ECc3t1LUG1N7biGP8@(1ZyyA{`fxK45!emBM-H%Pm9~nISE!E0K+udnvwRs3<@| z`$CG5-V=HhNxD+yL1r^4y$mW>gyO(In@$MN3o;RwVq&+KMqOXs-lBD*6vCxpO8LDZ38e%vbSpG5`8 zADcfQ1afO6k|E;-ktgX1GLjP-LxDW1~YVhif3lALGRiFvo8Qk&3R0$#Ax37f!WQ^`dE$r{2e*r%@Px*5Sd}SbqqLZUze7f+Uuz@}#PNVqzL|G6J zcXF=AkLZlbY1xEYXZWrF)C>N^Kkg1Q-!lPvbe-!9j=V1PDfr4h=KB~4AqqoReKR-S zM+@Y34oVnl7EG08{9+)sG*WZd?zY^ z%97`d5CM=v5;8{QIB5n6#8HVZ;gnsNf5h>U%6y@d@2~2_%m7#R63rg;GeDC!;6}wc zw-uJoY86ow0d`*`MT2naUrW&dr+u=yzy3^ka4AK@RS5OP@TbI-g`iLfqW}dWL4G&B ze4d8SM#3w6B|?$O!-NLCfPb!XG5QHd2hu~%SFdn(MBa)Nk4%NE7$hS%Gy7#@2dU{A zrmVa}@WdWt#^zWT7T$Mrhvf+rN6*7v{RkGSh6s)X2U~UL$03|>BYJ*3TNnw@6a0VdT-bNytG;S?`;D7n>$y{c=85@S zdu0b*BHHj~?-edqs4|w%oUP2yca>8$hB>ujc9RyI1>*{}8n3Vw$}pHy59!<8-|FTf zmdaD!)8dU627WccKq1fm>``ADv8MpNV#uPNw=cq1mmdA8Lo7}gT^y;oafw5p1n&Es zU<&Ia_qsqaEisBLAVxpk(1*0(VGN&@7==AsCYpvxe%K-R%Kzz!QU2f^5M@7($; z|Nj>P|FzBB_-bLC4M~CkQ&~U`T`-Ah{;h7ooY}&t95BN#1-Mt-3U@bIy0>!c`<2Bd z?VW=G$$fjtj9puQ=~4jFvh0)O`!V+{r&i*Z!PsmNI`_uqQ5<-&8_PpP5ix2y6p^GD zfv}l~5k0+pA;^s{b|1(vB}o(JkSaa~JR}(#fz<1jng51WU}5shbANx&Rx#iRA`{k> znZ5L^D}{L_S*kDHOJ+XQr?J4R37TtmXhwda8<+zQ#z+1VBUyNfg6yy4lv5nj4OlbD z42(AQ$QG0N=aalf@tHH_7}!!=>x`-L%~KzLt$MQ3S!u8I{4{olJ94MD`iQU`nv(|z zGg}zm=FY44+$^=-gyE8B=<&;^y8oD~Y7P@0`u)m`%9O7ERDr7D42+Cy5LH&LhwDDM zR8aHx{Hj!$S=)R1ioEuUAFk^7GU%n2_kY@L?yog|{GbozCK_8C_O99<9%U>CO<^ci zplP|(%f{wjx!^)5T}hd4QY|izmDWpL(ggTF&G0wz_B;1OS@|}@65m%j#v{nhtQs_8 z*~&LeTetFRy_sRSS^0H;eZXN(EIn?gsfL+z49_e(%BiU!gB}OELRM=t`v$-=*@XxR zTbj^p7_9yv|EW>IfJT+UE7Wxm5aoH+9S-{D5L4tHG8)Dl%ev!>{T`4T>SAWqNG%#2 z!&8?V3OGwF0>CZVGRWE#K}({!!Zf%@-Mc35ka7g*Ux1J0aAK$sJb* z0TN#X$R>*{vbaNQLaJM&L_Mb|+b!9$69Kl{8Of6jx*Hl%q#n_O9zHBHMrWH%fB?xZ z>wJmi+vH1Ro!`IeoO>@RiEU{*=s`fY-J*EUJ&!tds_N9UH18kD6u`wU!(?vujuK$H z!Z%PNVE&*o`?k*H%g(XzI`3oyJc);ZSChX~_sbPK6c^TO{Ji1M>Jle&Y}li@P@&s? zN03Ti34sIH7nJ^K!Sr|wxe~BZ-1X-lFiBJA8nR@`G9iU6%r$)+C2=h27*Pz>5qkdO z!y8w%O?@=wptCc*ks!9W3014qYc*SkGC;&4<+J-~X(P2&F0m41@eHv=$Fg6vE?vUO zBH~(2k?E)e^+owsnoA9Go2y5Ij@rpi=q#+#?5kxdE^1`8x@CQ;V7>GSmsnhFYQT>o7OVMW^fMf`WmasUxl|qGXk2{s2|YQee1z zle-G=G!XhxpM_Crf7X2Z0~=tY_%1+EQ347x*oCoeC_I}CJ5AcUi&=w1 zha`s@=sR5CtM{V+%T!XOaYaMzw@DP|s~wgaN1n2IeM4)GQj#$x4_9nd&ayXJk8 z^IFg_ROdoN_KsdSq*BMDU&7W`GU7e5x>kW$-$Zh40Jt?>2M@r?QoMO_46-Z`f|z=GVyWP6vE$Zr&xi2PQ;mQ{0mc1BJigntd*i zW)|RlL~&@mCvMQF6~e%;6@kOJDXH21o}h|KsXYH}pI;mq;TY_T@5;_p!`0h*B zX<)Fq@m-Xb*oSX>c~6Rk2?Oi#*tpri+gPS3$aEEW&Vz?ueBOjwLy4e^-!yLn1?Z2% zAXB>Mbk4!)+A7RMwNfp-UMsoZ2*DzxW-$alN>_eX3V0(;N@)4B$1C8Y;e_qd8%kp# zX!ZIFH*HZ#d_BBLBH{4jtk3zI-wY*7qC+wx+qRhG^O4x|}Gz{Py zhhod6pPW66QTxJ!$>b#>ffM5R8<>iu;r;;3RFUL((-y6dbA&X6cOH(Pi*Zr{`|$C{9L58xmFZ$VAY3V}`+ClQ&LF_P8i6Escpw8Rs+!==Mw39fc*$DzfKn zh;YD*0`WZYrlWt0%oR)?x$CKe$>7Mx-Gp5Pu}2>xk%#7)={>bbCV}u+^6NyeKNg^0J*vEqFey(yPm$RR9h%UaJf1}?ebMxde=*}vY#0X`(i_71E-Iz=;YlZ*J>5uW-}Po^{aRb8 z(ER7PH_($z6dcp+{${-fbN`*XVD%4GfUlMu?t7F;wB-k<61?;?ZMKtSUvS^)y-E82r}EV$1$(;PMS<0|i)p3{k`}3tHYli)qYfQKRHjVmoTYUa zIw2X#hBNkX$sf-4xaA_xnb|kj&21z&lcJ>!Pussu%e>!cw7N!LBX2)TmnFzGBL9{9 z7z67|sOxO2Tj-ceGxx`qt)^0T)R#c#1F7llqpaLCioRr&d@ieMCB-3~pxsXo z&C}<9weuQmK6^9s2mk%AGk-SoM;FwlLil7qKWoi=_Fw-t z^XD^vT>Bv3r|#j*XaDmreBbA1g|>ev%LJeQlkfhSw*Nl!7c+lagBcy+9aTHLsKNf! z&wudjpLq5sT}&43tL9mD{u%7@r#b&?>xcCx>+kw zBYKaW_#ElOA-{&<^#X=VuJ}Z2^$pE3Yb4>>B06r3T$MF)Wud;ffHirk-l(rMmY0Jy zlB>#X)=0twexI$8C;;Ub&RdWrkk?D8O;i}sNa6fIxqT%k6JWWbBpGKU=&SLtdu96cU)DkWZ(P^H3xr# z-C%IpJ2^e-S2lNEKjVr~Q=k(vWsXbw|A;6qhWoD~_Ou6ZzDziL+8}Jw8>Tj1&LiZ6Eh!zmjoGR?)YrFwK2nG5rSV{qj40 zoY)WN5wa|O=Oq4O$hFKEhXnT#Yi8ghIos3Z9~WmCnL=T4Bdt%0txvAECQO^-qiib& zy)&~5EBP6Uv7;=3eda%|{oFN%nrP0>JvC<@6q##y5>>i|>Ed6??k+uUwfk205ufhM z7NJil2r%DAYT#o4J0AgNSKhKDl~j7C*3b8t4D%;}50<5K(Jtpt%={J&Rb^SK3NvYq zO~hs(m5)WI1nU-Nwm7Ge&PJv-@+3|pP_V7{EYpI!T+Ts18a1n+@Vvq8Ahrq8L$8vl zh7HW}x~B*aa5H=AyoW2gq16O@83ThqgH%=?)@YR>dyPcO%*8qGdstaBaV6LbE3@G^ zG=+__zxuz3jhru~u;gV&QM~`Ny&jQw@)x28#g}XPRRGE~p&}AoY?I<#^aVFKU&^(~ z_ytu{@|bjFGaYz8T$ct^a5UOJ6{|F|9QFwCHX3M@AOR)2wnldXKp|A&$IUpJxIy=0 z+8tc(iz!HNqFq4R3OhUcB!q>dIG^2gm3nN)`QMfSGOb(>I`DY>qmJ@>q75_HM6t~^ zI&l;?f!Qu72E)|^wxlqfXBj>ipql{N&jW}f1G~Xl79-ZJuhf+nIoao;&B?GPv2s~+^)<@R9Hvz2iNgMeRL&mc?pBxXBo{OUPkkVWi+oXBU z>%m2ns}g72Eeb$6hs(#ZB0Ii*5rR7c9TNBghTQ#a0Ixu0^JZ)%e(+2Qta}jYG_d)} z3UA3GIN?-~69Fy^X;vKtfcl&{hd%SMiDRVO+TZ*2o9E^4t55Lb$siVH9%zYZ)cBhr zph+)&EPFfuEGt-~#Wtk^s6uF3#axXEP`&y0RBiyo>HCq{@-1 ziStB=xC;gYbqjt9^TJMX)*cDiR^E;cL?`JoS;Y30H7F#~DXa(qMFfR% z#24x7%1R=d_*w{!b0dRRkPUq8@MTYKrGpo82*Rfv!N`Q6uOc1HUM*lvt+qgpuiFqt zQ8ZFlTR)=^$)W8VY1Z3vTAnYAlI?jg9*?ce14&15Rs74NcPeJgz+4~d)`oO2Zp`Zp zIm4WHhghzxy}$i0-2XWz{oX?FeRt*mzzdl5udTV??@j){i)-uX{P6!>TdUXC*Vk#j zzP`LR_5Z!^o&GNGJtRi4bJ0k*D8z_^ZWp^bNA}S{Gkn}UJpE9UJJ0~v#WOzD24_#W zjKDS^^m``*99!1Yt-*2nCD-w_2L9boclWAwU05su$L_Cwxstk==tY=g;zsr7q41!7 z_54t@hLneADf#e;j8;|-S%#BYf>1ub+wD29%A@`ZYl5zU6|SOUXe=$I)y0*?#kBH#dvDIh0fH(Av+bkxhv}n<13yW2 z2X??4_)Ry`Z(hCn&OX>VgaJcCB{%!&O!jcm$y65UBRKW%ZX3>S0xF zAAPyH_=`IKtuEINn)RjS<>gIEr}b+s(qUc3S6)FctKnuQ&*jAg0aelWRe6ap;`6`T zTX^$wYv=Wb5;IbwwEy_+Zgp$-+0IUqe0>S#j6$cNS4pqB${Lg;Pg4Fqxfhb@J$sq; z&f5q74R>%C$HiX?07GLEw9uYj8O?R0;SdxX5^JwEAs*XDZw;vKZ82Zs&Z zQ#n|v+>j77l`bWl$_sX;5w>MvglOh%ek{b-pm#<7FwwUc7hK7tB=D=*P(KQXs$3&6 z0k;Cydx+c9>Cx~j=Fi{1JsGCt1+>Hv`_e)263Ktawc2ixgBxT26)j>elUE04ZT&-= zBEZoygnp~H%Cl!>%g`$S{k)}=+S)id=+w|s?UCLBD|P40k2^_{nmDV)8gG7APQTuM zN<=iUAB8#i_3+j|jvA4trMI@b8=)f78^>OpYw!T8o(~S2I;V8eX*DlM!C)j$*%d5( z-Cao?W`M)@{n{AGgW}P77)?|TB6sU*KK((Glr&q+6|tn&+sji3wKVZiHmHyA$B@Pd zF&li)pJR>6(xebW)n!SgyWrqteH>hd#II6HsIkNv&wLZwqzv-`kC%43R3lfO=jKWi zKa{b}^B!zRZ@|pGm`UptK$iF4@fhJYc~$wr$-3(u`eApNap1+i~ehK`j(0- z(b0K-a6C|D35;>)Rh56}X}NnjhhztFasqKGbH+5nHd;NA?BHnQyheq=L(G?Dq=|Wj zBI3(Dr_sFZ4OwG)f=_QqWDm)JOky{5fM@i4BPv>bl7DH*q2;DJC$eIDgx*JYPvEN4 zZoXPRZA%#;Qmhj)$9ga|D%-KL`Y;P{L-_GIIwiJU5=52CAlM+;O><}PO|zE13;9cl zUShmHE|gTRJMHv_B(bKBWV^RvD{M;CZh}HUjftuvs1_laUpT8Qak@h!S{`K~sVNF` zpsJ1?d4Wh|-&r(CCbbB8F*MKh5|1y$Fj$d<{;d&_;K755A_4wEE{g39p_hk$Gf?)7 zNBv=YlT!$4wEL37?j|_gCdI5t)LH%#DP~n?{h6egXNQe+qS!|*F^r6@X4U-vf#T+S zmksArTkQp$K>xa%NBAE9L+$FS)*n>ShJb8H9!c_?RM1`GtNdOiP#SoH`hTlhglzB$azfVT$C4A&;a%l~IY4wDAz@Ci{n3Pkxla@l zY}6g3i_2j=rf5L4tz$AC2T@{Ppb}|CO0Zr>5>78&n)~Xyv|;2+GzqR|BCD8=(s5Hu z2$ctQg<)=@1a`g^LL+V`i3NJ>A$r2&o>~W4#e_#`YL1B)Jb@DIl3|>HtdhnuT5U8} zX}y#uUF=X?*9n{7!!)24YN0*}r%rb=OY4RCti=>dh#1yYV0aKgPL&FX^;n3T0WEo$ zG#D5tD>j3dC&-()_vV^kuQ5+1DkcY^`yCaHJiecO2jKy)m zI&HyQH7UsoL5wR=$;!wquRBW))AHN|#4Soo>S=(2NQH996Lfkq`6H#{H6jdvFU8o7 z*-Qwwt4~nc5tgFsit56%Xd7Icqi*({9Rhq&0aQ(9IE878=mYd&;Hq(QycVStQ84w4 zowDCa0GI?`p7WxM!G;b|2J&2MR-#68qbiZ{Cu1z<054Q~u`mvGa>PtsoME2K-UVdl zV+%W0Ap)8qBCw{XgMPvF4E z#|i1jgyb9`!Rc6fUg$l4Pe$HM2oK1UACf6_R_9 zDyRIb=QTTRIu+)0Z*1KZRt|C{+vHYYyJ&3LW7lj7#!f8*6s71@@k|^aneMbhHY_^C zs)B4Mm|~^zIyste6sb-4)YcS{8XJ<;bqE7oNszFxsH9p=lOkUgcP{=JXS3#%Obv$i zW~x#aB)3 z|A;hG`@bi0fD2FU|5N*a!J>)Xero?OTBkD;Z1 mCz#pxr}qEMpqjh>U2_tg+W)8ae@eHxOXbx5fBF;H|Nj?5)0!0k literal 0 HcmV?d00001 diff --git a/DBD-Oracle-0.25.tar.Z b/DBD-Oracle-0.25.tar.Z new file mode 100644 index 0000000000000000000000000000000000000000..03221cecf15caa562a2c56bf870af569eb53c6e9 GIT binary patch literal 44688 zcmWKX_dgVV9LH~;?QCat_U1U7>g>(gN9e3GLYGbQy|cG7vensC3dyd{CgjX0WTd1; z3(ar;z~}LKzdt{`Uhn7o^*K{RwSSe09BG=#kuj{6QgifY;R7Hft*R|L>c(;eF(G%D z>Ll|DP=F|iVLdF5Drq=MrKs;&Ak~ObT|mikc45uXQL=cX412kRHjAiLSId08MX`d{ zldjgqW?Zd=^CY7dByXCG2zE3XLTLD`SIc9}f!DSDH|2u3iMB{gFiSsq*u;=diP-My zP^1!&0&!0^zr6#ozeJOsO#18^-2i|nUu00-3`0x;3o674k35)!xdF&arnC7q% z9nL7+h}pOX2V1|AFW<~y&$g%%@#Ae4&p0^}+(|hPtML6#3B**N3tnNmVWS( zxjFE$EL)tZkt#Bmd9XBZmH$Ws%)UMAylAWY!Fj|&i|%ZUOHWrgXlW=7IcRNZvPwmm z?9)bW21G3xv5Kbc1zvqjFn}2`4uWW76!UkwKE|M=+82$-;4D5CaHe z@oS(ta_BPXMr`ZhEFivO3d%$@JlA2oQ!?PlOcd2p3TG;s755YJU7ANS?T5?4nWAW1 zmjWZYhSr6NWSp50P!ZNnM~Q5k@Nt#Z)?z1&95Mt$8#>l3Y~n&Yf>CTQ&`gGdW$6#a zQV^Z};pO8XrbY_d+}E!G=!QJ)_)fYrrUFZ*UEl+PJR_8=upl>xc$$%&NbN|kg_IhU z$+dn4!fOEm4)fXz8k#QROV^uEBoJA9>o)>z3CzU3R`E|2xr??wN(z4b;# zkbaXwaIwr3@CZ2;;E0i8hD+6e;!P`H<4lChnOi{l$;VuO?xhNOmV#2TXW#i0B&piq z8LREB+a2kt&?$S5*RegLOnJ)ThR-kVC!5@npU2z!=kwg4b<6%iXMarq^YIYI{Ctj- zudGS%WV%4)(c7#})L}%zAxLMPgWcz#z9Z<13JPhW9;3JPw*PsxXUI<5Ovt1TOw5Wy=rXw-k@FKm>YdSGT?*-Q#-Iuwo z!R5{5G%||So`!#>W2q!>V0gv09K=_PL$EZ?v&*)-UX{Yjx{p{o=W5Gq?b-g1{+ zk#(W{IX;Cy%8nxv=enD&4Nsl-xlt-y^IGQ(YVP{SDA`Mr{vHg)X-k~u6`xsTOi$;W zb9Cdo#ipc9Lfe$f$B3=YQ3xMDgM(p@ity1laZ|mA( z*lA-mIieY7AkvDkC&^Dcqk<@V)OSc!2?wW&oZOd5g=Ku(vd4?li=G^%?d>zS+n{Qz z57Gl1JE%~|E6CeRSqJ=K8|J{7XqBN`S2x~&w@ft_9G?4}I)^_k@eCsk^)0x-P&U(# zRa!=by05;#cci1DS2_6n4)yO%EmsX(9U(fz>v=rC%|=4qWB&5ZFs*NkO$F~KY>0N~ zV~k1bm>F8z%UVwZ8LHjMtc16KX^2H;;^pv;$D`S7 z(KMTPuSjzu-sS8_t@hbJ+OUgHETV|?MF?xT36FRC3gDgfon)SRO$?mX=>){}c`F@_ z2AGBP_E&+PMy;rKZrb6YRbW2VaQ$F4Sy*zok(kX03{!5)d>NZ^WhfS+()zRN zbbAPy_%R*Q31sps56OPF1-h|31dsihJ$)tcwhWGgBdA<}^A+GOa*M#maRdBed@H#M z+RfhZ?XoZ}{7AbiF-|@6bmnpJmjNzuw#I3Dp3TGAFK|7w28 z{-(od`1cbOjPjKVZ}%CA=|2NQ_3oQ&QHIz(+iO+?OWs4zK6>g^3ft+19*69g|9(b} zdQ?@*?oSO2Lraas!f({Z$AY2TZvUa$A;B~_#|W5&yTsWdh&?>t<#eq|01^cS=`=^C z1$Y_&us++M5OSh86U1*w@F@1$o-gDw8Qv?a6h}ykhB>IC;5uogY;+Z#}~apHjUCC~_lsT^Q)=ZZl6$qI0C32zE7F)dQw1&cS%80hIWj>9ZXif87RZhyBt-%KyG%`qYL8D9 zP;@1zMW#Z`Xdz|MT4JA#F{@t{%8+naAG8CAkK4!uw(95bYslnA`emB@sw6O^l%0hu&Gl8oM#>S3NM8WYRMi75B z@lQwI2JND^_athD;{32){5<|R^g>zQ`cFN%Z2*?7#-z1*A;0ym)2*<~%fhsVR zw2FxBsELfCsaLYHJGmh!Sa?~ot24Y{S;$hr=Whxus{)XRFF3Zy{xMl#tPT4sNcBNe zb-$!Iks$IV5S0wgUl?UwDQJnKJfi}pUaqvMQ~1kISMR~)_$>Zj0azdjp4%Ky)gtJ} z05x#o!CXF{dzB0iOE>mG>ZEIlvhXTRD8Ccz64io(@qeElS^|BO2g~8nXIK7-4$jJMiu z(C#Gq(hBHBq2RAwY-6|RWwT2knGUhm2^{n_ca)sOnO9 z9&>p@#3|vb698(rt5m{e{#PCHcrpH_w#qH@gr?*8)-rhgM8e%zSo=hbJcK{j!||sE z8gai}1$>T3(673F>6-6Z6ay^HCxuAuNl;9B3^q_qxma3^rSUi-B$a?tG_Jcm}L9UWq^syHg00rQy3qV7BLjZ`S0#Uf3X^X-U6v1#1(cyx>81q4gEU&XNGIcuip7XOBdWK+!UAuA-tuGJ5 z1$tc=_Xi|Rg9*Ch%y!{r*Z?kfT&4F+eOHv{M9exUV_TqqXFz2u@8U@4U&)mGpQ`7+ z=tWWCSzP#ZAAajh73f}gWq^?^8gy_Q7ZL+&`Ps)D;4=DPk&setBZvEmpm z)fm389$uD0JmQCiOB;-**=Bv!!^n7k%V@dm6H*IPeVd?k&nZk|TnHm+Bvd{3ZqX6i z27o`be)=BPR@@t`WT+AWYt@?Tk~F*x?=NZ+!tvDcD$9)#qlQMdOrV8QH* z?<~mH?pl$y~JrJgAR9~4l$^A0y)g@meMcxo8oWRL_3gpmZjurPBz1UXY7<~VaK0P1ZD zp|$}EYC!VsjJn$nOP`(8MHMq{86WW&Bu78pR)W(7pDxR5R;xbL8 zZt_a`Ylj!>&hj7ceH|8k`BkaygHwo%uypGrXY;%I z@3greWky7iRT#XwnBwlZ9u?i6x`?kAW?$bw7qEx<;E^k}N7`r+Ho|nxo~N*aOt&1| zWDIq014_rnPS`;8-*?8PK@8;$ZO84EYgboiue_-7WQ%D^nK8H;gNvqCKstm3ek}lZ zO(NM{wx#-&@(m0BQJ61p0<)J(CFie&39&y|_M@%-ExP|$(1G&jS-Utt$z`K;vg$*p zxQiVo-jPu$J+Bo$FU@lhKwE7%hmj-mBU@Lm-%;-R+C@p)7v+L0OCmXSt+q`P~DsfRqiN@7a7mx#oXQI2K+O zGQNkAHTJs0|1oo5i1WPfbpwn`wW1iO8deF^@eo$&a_IT_1Jg|-sF%9flm~nCXPujc z`hUmFcX7yzA?;e^!E~*0=_+Tv5B^u?U!)q|vwPn>ec?XXrSV7yyJ2K(;?Wa$c;ih+ zRijUb`%aE)d_2M;yi6%SLb#Ls*prADr7JkzTfZ2PI*Dgy3ABY>VA; z@Z2rx)O!;np{4pq9^P2Lqv8NoBZEzaw1vj+0EbDg}-$GU|o{( z<79aI*UM_gk)MC7;sH_cXbzcJF>qV}YgNPNzl35sk$3D!7tDtMS? z&R@DKmCeR;9p;?Nia&7`RrSfulRbpCU=igYYix(J`dp#v9jNXU@lwIX@{T6r5>~+XqM4uqi{TAG==8j19-J3@eJtpNu?|wX&iRyCt1WEs- z%W=HTvDKt&GK6Iv6x6Ivvm;?uIvJ9~A1PjKmo()lS&Co1b9E1DLAMSdM}<7A{4A1?0X!5R*psPJ-?a-`SZ0B|cRVu?IO(cDIQH zwMFWgQM!kum?xX~4%7~23VL=!O|t9Ni!9(XBN)q$C_%ew@6#2Limv2rah6pK9ssbS zNFD1uA$OxC)uhk2>)AEp@F^e^(B`n!RP)y!PZ^?sD@YW4FIC(8i}_~m9w1wKbhf;C znITjn$_O0A-cYl_ z`Ch3IGQ_4*jI6$o`I;h5K-4V0*9iNVtM8HT)iflxmPduw{U#B}14Hn+tw-TBeAv^vU8ukhPG7I{HdT!`X1(@b@EK?bs+R9IKge2rUBeGJs)ziM@IM)U#B` zTwEE2WnZT$Jn*n!&Cn@~Ab(V5Wi^$`X(+s-Xf~xj{eG@z3&Esn!sT)czbmr{-M% zjb-vvn9)jE6YAP+jkgW&HeO*QdOgsU7p;Y#03d3AI7UzWn4b-Etdi5xof*08aln`@ z*i3GxqTZF;8luN~e9aMrFAEHS}Kf9^5~LuLa8&Cv=fa z+7gzeZdrJ_VT3Q%5)$%r%D#A5w=>kWW&_a>1vG?8UOUkalBK+Y%ThyV^LzpOI@ zF&9g-xc^FaYH`=Z`s~VpKe=ZzNlE-dI6rAf`PpR8FM)0Di@DR?&_0ExN3Y863|$1x z7z~L|73)=qmW@Qx08~eN17oR0pfYVTlX^eP2umJYFFQxO%puX+C!RDy_c^npwEvqm z=BIdY3cbMG@Kh?7%b-BZczkxst`kU%x%6>xopABIh&CkG*Io2tEdj74a|Zh`D6GU&_4ZdzqL% zOgi&zS+>5;Sh9ECB#ojXJMk!}-WWRHf|zQ@G+6i_)}1b1PInLys(ZaFl%~*uam91Y z6djnc2@WFVb6&lYX*5(+9}%E~;{fc5lo%Pw122Sf1aj8HgfC=VtyoS@N$%#Q2Q`36 zDvSY8(X6|iPI0xblhBS|NklSD9tG`-AKgcljU6Ydo=Ztd9{SwJK7I4Ydg;dJ@M`P1 zD+13a56Z6;+{>=1h_AEWG>WlK@P6+`>Imsxk%D;nR`Xb<`Zz4(jDA_%QHt(PY*sF)qN#29ILAH0H5Z&19FQcPO)B_vSAPv5o;Z2E8$gp0;yYfG0nwaSa)yS@5 ze9@Ubf?zy>c#>;tcG9vmRjwkI8eB)+{|Bv-)!(TQ{pJAauAs;1@QJ9%o~}Ez>m|eb z$8d2M0igel4K4Nr?I4r9pVw}2q$SL1e9`|^9D;H9#pSEP2()s0=nh)Ne8mNolT%h4 z)t?NsyNQ3;GgZ&e0s$s>SC#CiDVz3ZsQg;&7Pf#uW#z%LWmnfk%ivk{zjegbLE1uW z`9Z+hz|#6*xl&g3%Sz(|I$;8H4nAzsK?G3#92S^_b}g|NJoM4%k^nA&E(bD znuDj5TZ_Es$Np6+eyMbCFOz*FKC&eMB{v;A9>PdD&VQX>Fq{vNF7 ztu-v#t^Z5&x`I}U(Vj;(M)Xogh~2z23Vpm8AX4E*H;q~_4e^0V>AO_+bkvOTjggz_ zLhteULE_J($#KXfa<+u2Qca1j&gf?yb*Eucip-LY_G=a^on4#f!uz79hHJko79XfH z=uNfAm1J(vVm?k)N=lSm*Y{2#q&0ur;7ZoKMyIYHy|Q#z0*<4LU}Gp+u^a5AnV-B{ z%WBkuGH_FC#|!7IEOOWdi>TKu+-HYH4op{^ikQjV5wnPFg^OP3V#`myT3dY8pH*3G zI^soaAFQO?C-S)*@vsGv<%}L-~fzkiH9T@(f?Y-Kk40WyzB zV+td2^GZP7c-_=v)$c~TH_PwrdA*@D**#TCsCO~*rDjg?jR&CG;2&>rb-9Cyc&EidI zd;;dl^&X@^c(Mvp`dYidUC>J%$UO<2kXCw&=CJXEtyj}+!?(zK=xw6k{hbFZx0H2W z+w+Ca7|tnEFwsY&BiR8QJ(_;Mb7uMjl0Hs@T_l?7YO6%*EF3IG3_xZ87KD?EkCs#& z2htg4cH?fF*JmX$SeSm8xY~bS>jI?yrm{?~ETZvl@?5i3=*YWo7bIt>DmHnjrCU10 zhyAqHT>35lsM2-(AEBD@DzUFoCZIxBOyZ_6@FL zNQr`lm)Uw(KI&^-zMgKBbpL=|XM-O{M1=<;6--hT5rnxTY(RYhg>6LuN+s8bClO)H zh^)PF@Xs2|KkiDO*#b$Ce}&{|g=pdErbwp=XZ zVofGW%^>qbuALW{f6sJv3*t=Sp{e(fds<3m31C&HUq=+MJyQ%V2@WYIoJmjql7`#| z$3WK zV8L~P?AfQNmUfR1LEG)mRszL_m)nWcDT)B*5)zd|HOmZthN%Rf`j z63Z)H)=A<6G$Y2UKAEPnb(Xst5?S@{Bj4X8qP<^l-<+|PGM1hL1^sb94G2BB%hy}s zN^oQF<-2N`W-<(vPbprTNb=`pViNt{~6!v z-C?2#H9Mte!KJsw^O=O;K?uuD}Sz_UZPV1y8^r=Jv8G&N+y4>&KgK2{DNZ@voX zD)2h_X3Ut&HK6l8)YJMp2^@vpTLfwX2{y1bUW)=KGoC-Yi^-%zfvj(rdOJ??@~exZ z6n!$thR#RjuK|X)u3s$)u_mup5we%WHsCuu3hBbgN$+gu1+>@P%7Y_04m0Eb4d^~X+t=ekPXgHqvn+(RB9k-3Vm z56u3Komd7I9V9h*ofq>n!ByA(y_ zC4tbp%nbe!BlS@hE^1??VA=B^QDw6kAQ!IuYD9LCU8y;xts>wkC_IyC3lxr3jqJ*b zzo&Os%qja!dG8G6ETBr1c!rh=s65A`Vj&44ym?PIzwlH?SuZ-8Vrv2EuDv1!0qiq* z-E^vbJpe*=J+bq@5oboHHn})2`;P^0No+yx(8ZW?E&^^{NjpaceJ39n-FIPu?goj5 zX}G>Xh2Gh+x@ppx^JXeSAj{S3nbK}8xg!@85|Ns7@!mVDXRn6U!#P&%c*D-=0jU6? zu=#me?E`2YoD8~-{iz^y0!6}a4ZSqa!brd{EUW0Pa2T-0Bmdmu+9mr7Lhv6DDt0r1meY?Dpq#^%|GfX;pBYvv>OD~fCa-)BWTF_&=OP=I@;J-g6AGHd_ zTfUrml)rdA!Oj?_|4@{XUl!AnZDaK5HHX)Q&I`i?Cy$wC&$qur-0!AI>Y2pvAjWc) zB|q$gMHuwb9Qf26{7w%YpkKRWf%SRzb`AT`QLF0KDuIw3f1nU>i}-Z*qmq;4#UJml zhpE~V=x3Czxdd0HNcnc*So#zJB$S(D&wp!6Nw{?TXMBLk%ZYKd40K{ z+_}&MWn&MPPe@86G<>lBy0VzR=J0~W_CxRNN&A=D{P~$}!o3eQnKk#_Zo-ylVYpav z3%&~uxQ7oqi7m|~jC-|zwQ#fv10zU014JLEec=DXZAdQi&PrDd&b4?enfStW$= z@hoGYg8pf92}KJ|F&Z9J;_eDv1wSOQe5F`FggU=tycXo_W%XBm^N@D+`0Jx3`>NOh z_FeYD`KrfFi)=ro8;7N^|Jbq^iR(wI?Kj{V&$H4R$D3e(tm8HxKyB2#Z-5L-kNL$bOI&x-Vyx00t6G$k z=XYSgtft9zKG^w%T#K=*$(X)jPWQ{&_Qn6P!ZIRtwnZu=;arN%e2R8q9H$SBdA;Ow z9P20>$2vlxi^Ad*BaN-VLwY<6cur5c>tn=*rJ{&Wr7EG?_uu6~|;s01T&&<8U+pPsG=9IN#3G&7`MUwLfV$AjHeq3bpq zDIs7_+=fwal7Cez=0+ufm_YjWGiT$OAUIuwI^AN^=x!y z@Ar0bV+HrG&eR%|QRdRHKFr87i<&|S=Yd&H| z3M7=7TsW73_8x`imEvTmSMuTA4PeuK)x0a`2J3%@o)5m+FUdv$CDF%NT<(2b7o}Lo z9&l`o419g`k+)wG&-o=EdQ<y33AM8FdyAh>({i;+6w~jK1fakh>5ySRhjXYN}!(LyUlVg9q z`0>g0p+Uo6|8>8b1~oMAk-5!rfIwG9fBacAk07pm;`umD&7JO&Sf+}8HPxI@hg+T43#f|uV!*68gmLOi8n5P$rtA>DAgzJ+x|qZg1x-v=Pql_35txchIe!i zf6#dmsHQsl_Jg=A@1}Pc9I?pQ|Ax^Ibm=IP{G5+?;$&oBdTm>(gY@I_fyqjOe`!Z+ z!`C_^lZB+c5L~D+fU+{+lX;)rnmHxAS)Wg%v|c+ zsapj?)Pu@1DPgaCZ%5UKWwufb{e2qvCFs!UOQ%;%;E(9Tzt4O|&Ro8#ol-P3tTQ8xCwg%{403#>EHeXEc)s!Ua3jgZo1vD69O1&i$$(Lg?2X&i%OX_}zcMRnFWU`K8F&|1E3(DY9XpeE3L3z11f+ zA^3$BSSz=x-FpcfZ1(l{{gE;YZe?|h+2bqE2QlAsj#`V(Z3@B`|HFJYqJ3jPj@JWW z2-?QwCP>sDm4)IQW)EG|ThNN&@u+DE@)@z!fAPG%ys`fAO^8w4z@OsbPLh4I)cJ8ff&o*k= zs^=RZ%k8?nH*W%le;bXyY;Xk`@aFvsGH<^Bhc8DMQ-y&cLMJky!7J((tQK%yV)?pp z2i$~&qeEmLYLb1PcOTnSAPi`npt389KNEI~5(N;J zn{5@56BIy0?*PtYzjZ=K0e1`q=ujqAPqN^aLN##B8ianB7fDSM-tA;QT#3v? z2c!Or5l$dhzZG}MmNa4g4C5%tOn=n~k%P0KmUVF#>5b#yRMW01PDT)c)QobEX1xX^ zdDAl@PuR4LCkV=+>NAEUxXGG%gJGMRJwTXsDJ_kiMM#bCFqVz~nkiOY=e9^u01W<55kQbc=3mOFQ*nnvED9$X}%|Ztn;N?qhG{zv%&7qqQyczY`fpduMIjjG5 zBSVBtvXBw4v8`0dC_!SisUqrVn04#lVX<@;I&=o8fV~WuU(OLj}4Z#61;i>1BY`_CukaFmY`+j3!|vTEr2Lsnvn3=@l9 z3SX^;0LwVbS@IbIW)N_+rLV);5A>q5;zUr%A=`&Uo|p(JvaR6Y7$6pWEhDWlIowA- zGg%x6SO|IpY5|<5qcUsy0E&QrrBH!lwGYjZ9#^vnasr3(X&Na8hW0Z;pjjZ(```bi z&uNZy^V$^7Ff(mB+l&Y^Bfy7gN`~_D9O0>`TK`q9Ccv3m76$lLI@r*vj4FPTiFRb@|-$3(7VPje-l#I0MZnS8asuTc$sP#$x=0j}JI7vxz#qLuK zQ>K0FSA1QFO+ZN>Pti2cA}19<1MGt%(LC`S;Af4|+LO`ED65 zTGKaZ68Vs;zUF8iZ&ufxMQ-+68IE+~lE%aE)(bPEyayZ(<=&Z63b1SR`1E!0cxHO< zIFteWuQHbZH*-ieu43Ei-^Q4+DDkc_(^mAPxu+U+hvLUm8~-0#;z&R)grxei6Y=Fb z?2(B`tmtc?5WWKYJ&w?1UD_yR6mt=KK63*|{7W;&Lj3uhu}T)8{p=|B>qVRiA)|FS z1C%6kI=1+!$u)^}(|*UVw=*6}2sp760Up<=wXkin|3n3BVSmSDZN2<9k(M(u{Gi1y zOQmBcJYB#Nd;g5c3dBEN5Brdy{2n;JR$k}ipV8{li4YqFyfd1LJ*xwet9I~Xeaq!U zXQhFZSanlqT+@xfR>UBgRW#QbJKQoHaQ+;bc}smwx7$iVqa+KUlXf%kZndtK!}SPl z3js@Wg_5Ta0Cr?i01SOz*W__JNF&G&%R*|(J+D5jaSSB`T~XsLYJZHTK~yvx?MNBl zARPtay=aW`;X?Ae-1$t6CZh;|ia*qVB#f^w{289yHE3YUb)EIuv2)kg>~oUxN%xajqSbd<*a{pGC?pK|Lj2H+UkU-xcMvtdy zmrAyP3n4-pjr7vkBh?<|4fuV^#5m@wB(u_>CfvpqpIh`-qMq)4+D97}M3BGkV+#Q$ zm9xXJK>!u_+YI7)HEHOd-M6}sC&COkmv0&dIb~{Zjc+V^-z%F~udf#vShXz0kAPc}5uM z$Kk}I#2Sps(>i+%IFr1x@{GnW%{~t7jy4=M5^WlcQ%^9oY2tnFBT{kZd!Z={a?L`< zir4qyf*pxF3ZjjLMS)&04GO~eW<8k`u#S<&a$B6rQ-LXD6PFfoFY1(JhSBCV@M zaf(Sb33$NfGOneEOMJVv}2%LaE`{Dpu=@)I!m{?}2)+d(hl(KJP~F0z?9(8%4Q5*F*{ky?bWn&zuyf^g7;G)h<2kdjMN}{sM>)SB zN0N}V-bu@KVo+t}c#}&e#yg2|?;23Os%E^&B8a|z12z+u97!i0Rj?;j3fY~24=n;Y zAcoHUB_=Fm@su_)CcSE9bwdyzXyC@up-)qmXwI{ClB7h+gCRM_|#}E2co<*bb zkP>EyG{hZp6)^JNT3x2=D`myvCyi(Ifd1u|Tp`XJP3}*+)N2WK{)TirSB~qAh!}Sc zWCXx>%01ale?HLCBfV5~h#3JP+ng9#ebqsg3P}qtfxO(A()+e1??l~^W}??CXUOA? zEER64IM%%HQ9?wAa>?oP8x*$>I>@Jqe-V;{_!mU}lfT%hALes~A^fZCtUEV(HB};MnHO=V z1@O1}IU(pnAjQXi9JwGhb6tvORVloV2~crEE?8*zP4cr^Zb}|aya}o`R2>O}FeUxo zdt1l^OO&E>EP;Px4G{$y^~;(Z&pHqbHmrmEb2N?pU_Xf|!0T^0MPfExqj_9*Slv#a znDWMSVcM*YxiQhP7?gVHw=b547vzIgoR3EDxsIo$Pr*p#k;bKc0S6rR^L%vhDHh8p zL;5DM?;E}*sf!2+!L!{nsX#^I?fVPCI1#I?G{Y&a0K>;R-@GcqUT3_uvvH`Z4O!&* z!_T+i{R~xvbI9IcsKVH_5d!d(Hf7ODrtNoe?ny&6eT_?O{=$KU{)tSjnb!~)HZ4Rx zmZaQX=_uSj3}a))6_=N`_LW4lUo7{7!S!F?>JcAhNx4~I8K?pj@w9K1RbW4hyfhRx zB_s=&K=9uI-eg_ovnD4yzV`03I{;kUOM4J?>i%hO28+)oW=Q)7tjV(cckJw`1BD`~E&d4k0cZI&m zs9P!zHZ2feygchn%g1p|1e-E=%-w(AF386M4u2F*rA^&k^{S{(+~va-n3rW1qr+~w zI%jtyg|1X3H9l&fIC$+eX~cpC-TmhFw!-adEZiQoRzVYYaGns@@2WmQ0+*7GI{1y9 zhMR5#5j<`V9=f39QzE&G*VpD$1-2}Cg(WAjDNDhL4mGZ_p-9inYEj@+a5hpvCeW=_wXxa=GJWcoR#ej**a}`{#RNv_ zo@20k0`2M|Wkd|#Jlcs2FS}*Uu=M_(yA|+J-kZPXwREfC6TUJrlQy5#2jN+w?=hNP zT=}B@$6A9_$Qu!=2{%;Z)$OH!nnT80l=Aet^e;3rjO+ZdudLcL(;&Nnzk~nVym`_* zvTsBM*uKivax*P_PPHMGNC#NE^PiSnDb)3HftmFqo`Sk?W*)48ueuw|(plwgh5If@ za7Fl|4OOG~qy6uY%$vBgDG3y-!$MRE^O3nLTcuzJ)*^vT1tL{p5s@it{DiEpQ}h)+ zgZ;3?#zfrlGa?k_RbxApS^x)<_Dy133JLjV(qKy#)5#v;C} z4RiJjzH}d`i#N|91OY_n%+tbFy!9PGs0UkF@M?i4o(GDvBRp8MuV&&k3AH`=Vk@~# zHIY~F3^O#w;#A|anc-m{&Arfux00KNa1P38_-8prZ*mLC@{2nX1CA8m7iY@$X=t9* zN&;EtCC1n-^7wHO9WC^mnk@wzFZQPbG$Iy7wfzX8px7Ex7ohfc9p&l{B(h|HB`q%r zS-y2oWykumD(hDq4=d8%{sytk_40bBMC&Qa;rx2&Ca9Hjv1hE|7KTfz?uxkIe;v^N{< zF)C9395n)aPKTZ5wqXj2E8YwM0kUEsi^cM3R;TXbvPW+aG_%LPVf1QE1QpThmL~%Q zloPvRuGf+1^4F~z>!y?WpQH(CmU+aknMY%fiwCnWN%hP&vTZlL`HAHx|lMlL_kLx=3%?&Uy}P z-(Qozzs@Bg^&PN=bE}(WOzla41fJ3$sp>d7pMZ>=v`mZJjIZgr})iU9NhCHR-&ZJ3x@C24r6mixeZaH&pA*TSc z@`+Qgd9&w@CH#AxYbe|9KcGQom*lPVFmg>StsZ*OwGF4JJq>M7J39c@N}&ldnJzOA zi)(Cg07vEBgJ3z$07K|goTl$T@J*tax%98e`FX0Hn5XRGI(+Y45-sObz6zSc+3rd9&#kaEMA9Z-9;wb%t?N z=WqHoSOLcAaGIPJrz|Pmc{xO<R^wmk14_7b)7y^kO6!up9-e_=~6}fl@hCqhq@$ES2X~|= z%B0r8Dy`Y^!GH6d)T3r4gmGDy~MOUxS|dD}JhpnGy=7eybZOAtaW{09@4%v7rhP zv*}zqk{Ty+s+(o0+Ns(dp8AJAr41?7b)}N4*8&J|t5#0{7*TWCa1v`N)1@smiM49B zrI?ZpndvU7E#RaQYfUOlq=!XTVqx`k4V!Wo4R2T&9>)7SIrE zrUlF@5jp`Iq?1Uh&HP!eMI>WOr95!XTkz^kT93=Wni43XJ0T$z9a1ZH6`7)DVH}a% z!*Es=U6gkCa9wdbWr}EPZ;!X0ej%pxV5msmyD#s;m}8hnJ;= zUp}!^th5?wD6AvFj|!R!sa=#t70BvK5a}PQ0H9F^k02|U?oYz1B#Fl^v0%omO33O< zgzWxA$o_VOEFQbXs-mod7t1!)LSpPLgeN*Sl&t5W#tNo*EWB#0>MdQ=7v*Qwv6!sg zm0T<|s%IX{ycVj5YG0YC{;+N8cxcJa3{li48^wmI*eX7HysDj$?DN`&G6yRYSjt{1 zp)TBRRLziE5ycgkJm?|$foQl~&`V{2y%dRnuaHI>(EN2k|H2ze{9Ums09}FyB!Wev zg46;W2qA#k34jGp#go%On)R)w6ePR2u83ShTj1D?hrg2ttHJqypjG}v&-^s^%*=4P zewsW3{|d}qv-|90nzsV9#?wHnl^V3$VIq68T27dg=JY)1hXjm0%S-O7{VD)4KwVf- ziB-y!CW66W8W2h}8Wf}Hc+G+Ujm8SF0;B;4t>x|e7P6-sDHNxoqt zTk{dNmh3e;n-aDwR%GkU8nRFT6abTQvD0k85ZMxcK>(eKcRa7oNfW>oRF@G09^sB& zp@*wt$^)uRBQ1V;y@stt2&V_WDxowGPEo{pVgiTZBh%y#l*6z#HVtPG#D#&>xh-YD zZM#ZX5xY%NxD|a`1H|lLc`84=gTs&uJ$jv98;}BkuVgJ|+9JiMiYY*g!qr!*Ye6g9 zvaomux9W*LwtvoNi>j7Zl-!fj7tYNxX>yTYskh1 z34nsDx}aM=la4#&o>mEf-$BTdU((N!D;Bh*o&gB9AtbhUYpTlRI*4|$%R!85G0eDHE}fg>#<@hs6o}Ve zxy0W$K{DXAPHOBa*jgM^Kn*3;!m7S3S>VJTwxH}`yQz+{lB%Lhal97KCh~3 zMpg5*s&y=)YpxauJ^QserBSS`>Y&hwi(2*%GpkE;QSv z(y8cbUR(3Qx~49$3a{F#=IY&$>x#PUDzDn>&Z_=srK`8lt7`2k;n;ow_^M=}uYLhu z?t1`0{Hud5pY;zyva_zOtBQ8Eg>66j?e3!32A;6qDwOYS^jfhF0T=5fs=$V6N@x+F z!8r`J0*D~Of)^?5p=Ar&IpP=g#c-Kl$}KC_YUR70!z?o1oD2%)ZR2HhE*S;r5>s?i ziCVy`paN-8sE>Nmdbc|36u`oUx_K)C>+U+Evh6mzO4K2V=htL>!ddeS1flJs0o?7y zo3rk$Naq{-rK-7{%P+F+;+K7`lS<6?v4O25E5G`#mMx?E%-*TRt2ArghP$?`vg_BL zs!eUGs+h8(PyqEB+lHL8t*V70&^Z4B_gd0;uW$f6Yrq0vAnVjSvgV{FtE#KMHa3z? z6?;Rxukq{aIKLv9_G>DHzy1sQD;%KF`mf7u0Glqpo*VDin>Mk#YOC10xH7PLYuJ1A zj=hNM1gq*=uxT&KyY_0Z{$H!b!QxqEl}1teF}!}(=NcH|y+o|uTUgP&E3bR2r}1et zFOz#`xwjadP80h1pMe1tgAq!ZWgmy=uCX&}pKJqpl7*q!>i7D!ex(w5gnw!T;gz_aGaADvBEDcI%S4RYmDyQTy6>6~%*scPggbEdojF?JL(K6=@ zSyf7q6BSVy6C;EHf($&n<1h;>sY7MD?Ai4?=s7=MaU;z^lY&0&J+fKb*kh7IZRI zoc&h?^HI73WWtz$1&x*2*0n~V=~2Qk2%!LJ;5cFiq=AUMoc^sxJOIG;9` z?xVB5luFNhEdAfI*?(8Ma`Qt(n!CqxQqw6G!S#c5o8 z0p9RRdYd|@-DwQ=Qe( zM3_fq7YnA4#+!?7!MRu1VJzbYhDvHjOyeRerxlJX?gr-}d!?a}(smH-iL4}phfJ@C#&D_@u?ZK;f?&yH81(LY-S2u~rc zZ+!SNwI*%lF7lDSrZO`D1axt*&{I}G-;6U18q)Pev)El~>` z8?|F8?vT_{wM%XG()(h!s{{4RDtQF1lJJXu7QcU(fzT5uzlWHuWXyaD^rwIA*lnW`1AH#ZTc1`R;)jo&51_Zy z0C}?F2Qioim_~7yC+tv9G2>-3uonM})kK_CzPp*y1L$D42xo}QJhYr;6P{c&_GSDP zXp|?HnBq`ZlD(*sTG?Mwm`Rq|6Y$7OsunWBFBwd#8IQx%up%D_#-vJsOfCzso6Mxv}(~JfL zZBnxjum`-BNvv$?28>~1^0tm2$)0mGoK&v_!#^_u)8aG;eS4xME{k$aY~!2qWC_5y{CWi* z8d&!{OvHTPv(L~;wnXAH>{C8_VCSOwovq%IpyUyuC07jlc1`TA7G_aB{*J!GiJs&qhvICWL#IyRc=mx07 z&(4$S*#=k(TbNggFq^nl^0wSBHI%J~2jeb7L*US;c{g?V7DRJuSzi;?DX ze2T%f&}8Qe?Ff$q;PNhE8sN|prL1`6Wy_D}{rq%x&o1;)EJG7a6J3IB;f zv>dSP0kmO5KzlspcYJi~5i3&Ac+DMssbSCnnB^dVIbA8zH(3^U2IpD!0!drTZ?WD& zNo&xUw5veb<`kW@0`N&=8-LCueM42!ZvlA*dY;mEKq|dTvxu(r>ugEO(wX$in@U@G za2RKmL)_0j*(ydfVO!UqcyKzeOoEpPupqWue?}{16dw zAwY}K9qQ|eg*i`Cvl4ADIME|v>S#1E)Xvba-b&f-w0*JvQfrvS5>`3R1Ho?8VVh{vFyZy~YtN}cc+ghzag(Y1( zTz~7qq=J%EQs&Io>RE7oib1DIYN|YHmTG{99EhjQYSU74)B^_1;9R)@;aWlsLX{IL(vmWyBsjkgeUY9-4US6RWKDjKVQ-D@>@+7XwmNF2~9*h%waU~H?AEt z>2gqW=Q+%f3Q1>N=v;^m)tS-ahjjHTxd#-|%bsXf(>;6DGcfICRU3LWKyp6=0eiry zGH!&{d9_%uSCiKL;+2MAZU%cA{Twe>!K-y^Z9Bu(yLBQ%TL*l$H3W=Xr@m`730)_r z(DgD4oy7Uj12aTiYdF__bqdWdH`hz_u=0UzT_RC+4KO>FKPbKIFEhotbOyak?@|?K zy=+S#H288vEK0x9q%;Su1GLw*#xJc~@5@L=CMNrS2hF2VzU5L2itGxM4!(<2{1R`HesZG7dOT&bPwHk-vL=K!aBC!=oUAbZo8j0 z?LZ}pwX@E!U2c2-#_^XZ=6{I|A;qN3m8Dzs=kxVq)gMA#Qe%Hf339vV{c*4$WC#9< z5dR93BAMsf=isE_<3$G;fp`Y=b@zen=A;w0;l{BM(Nfsf0f)&H@R+f@la&0KytDLVyK`u}=UKa5ZoXl<*l$V*~-~_uFts?2gnPjb?=80P!~`q<((^ z)zkN|NjMEtKmq`N3!$s<5sU;70pF1;+7+0=oX`T^fF}W#DEX707{i?KvS0+i1^?Ld zXG)m?OxJqrpkf;#IO|+~9S~5dDkVYO&%Bf>bteE|r3G-1m^HgJhK8#)gft+ZER|l& zGt}S-E>8Tb3Z4?$^Kn8{mxH>4#|Y_}hxPAzT2bf{K7vzSA~*|fu(;r201U3+%-~9B z6JUeSYdQFsNOdMSOZX4I2B!o}fb*nmaNylD@wYLE5+eZ`;5=;s61Xs`y}@-=o)BIM z>q|yB)tQ9<4;?rYu0A^9M{g8P`u0-mtrcESVBxET7VZ#m;jxq#PR;b-+SeEc`X!(vxW*zlWe!OxMqT%ZY(N5-vn#6;;RHFhWq>( zviO)$jGx0e#?}}#WhA>e*s9yb3YA$!MHF3{czEw%Ehvaz>jz$fyA&X}LJ7>pp_PLM zib|N{RaYNA2NdJCcuJrGq~kW97nY4{<3m?yQg_i33a)-|dN2n##@9Lrhylzmy5&V_ zD}Kj5&WrC3sde3jZn<7!fk2>BP#M@XbybWnlgGls)G)u!y~IAA0@o9i^^3DG`Bijn z6w1Lt;0guQi$?@-iz&r71XKZ+P1KM8q(;FJU??k|;3GIbzJhDpN@zgtg)L1Wpv=OG z(r7-=98r#gyzzKF%am*4pwI~!Bfv{W@ieTuD4~j_YJtG8>9cnjGg>iC-JYa3;DXw%Pp( z=p+nkk6m7|#m9L4w$P3GDy8}tCTbq2u2u?-#zlMUfvOu<({M(la|9w zA4xQse2M`uQ!ul*tO3lppAg(;e*(dBc{AV|CIdzTbkGYPR?WaL9BYIv&+wI#=0_C& z00$uA5^extA7I<$7CSL4EXQueSFS!E4GtAlzHSRP<5z>@PziU0Ps0mAj2gxG8qOBG z_zBzDi znr9HxiE%Cmc&+NAg7?SzOn9~sj1|ueWq2yifvW)AG^7C}%nZ({r$`xRqd{&69&Jg) z@VGd9kI$#=EJVttcTwChKTHmvo^tx04o#$@clskGdXfzMa3F3iIOPo~QOutP#Q1QG zAe{E8Je5Ut78AxyxtzWo7iOz*4-thD-zn(v&4MQ12QZe*NY0?nxAMKvMBgNb4tg?( z$(khLc>yQGy`6!PSa{#yw>Le0_X+0rG|ZAOL-aTM?SAjy{kKB#f7{=?aZQ(hI|0D@ zu0DUS-vRjaWCal51~~tXfJ4G@xC0)nXCDl>FlvEs!i=ZKRZ6Z$%gmEH7Q0OoWaoOdakpPUAGs8h4Ifzit@yu}W%o~E%8a$i2*?bTRAeeH~XZoyiJM_5d zE*V~lkLhXnXf6XJ06+rqm!^{{X#2RUbnTb)1IS>+bM zZfS4vLQuH{zyMu94{!o-0WiQSSmi=j&QsM(Dc4=PZ3}Rv4Knk1#S3XPgO7tKmxSz!UvTo52*sLQl-t2S(>*prtLdddM$XRDFBdg#UHg~DN*WO3OjEp z2_IDcy4jYRez?ld?4>};PL!o6z!`7vRiiGD341rl@wWpVZ^x_YVX4j6$D8pKb7Z44 z!mCCqU%Ht7rOx}zpcxgWa-~Nry>jv6`$PK9l9p_In!7SY+S-z$oc$CTW&pH!kX~My zS7Zafo|6}?8UsMHFOl!67#OPQ#(M~l_nz^dugW>uy6Nl~>q4j7r*ZnBo{pcW0dDx7 z5@?L*xU^+%9mTcxDq{@?a;0>H1I3;Y_{w59Is(ZF=cMs2yaBJ8B& zveA^@O9ap0788*5Je5_79uEwP@}YcWGo4?qGXrjFi$b*c!@yCQBggmy9B|Rj0hg;Q z56pq{td$txPzgKeRtf;ni{%vvL4R5q^xHgZWsCNf0DZ<3!UOc7xmBdhv-8gUnbLad z3l+{gk3Zy3(iS}bogWJ#{bImKl=RzVKYz$U^bP&E;U3Kl06j<#(>L^f`AiQ%ne@C4 zKwqG52a@|vu2e`oF~ViwP;q$~I=UsFI#j&;$s*9B)VFRL_L|bnxh~FmLS}&w8O41Y7|CgL_1d2j~y^zY$13DQ|%i5Y+av_hR*pn{ z6^tWM9jVjOG@fmpqYf1h^mo2Ay-U-$Qs106^+USWtlV2g`?W1@R;UCz01f`xcMVd&_Wrdp zJ&kvHuY@9a^!Rv>1Gx9A#8>a6i}xf0#KAeB%m-$=%nlA~dEAMuY>5gyo7OsAl3@anv5I|IF zPGZ(vr^e29tWXfTnMsfaubK1bmzsN^P?cr7sBBcGWBRg@8$PUP zTO)i5u$y+YB779%8}_CwKu0?)H@!pthOoFY@15&yY68^yKESR2z(P>nGlvtxTPchU z@eoJorF(CP&%!>vaRc=#x-~W;D^$LV@)m55v?VZ!_P*!=3;1#pac41|9ijO z2GIJrezYIJFZ*43^X}|J`_lfmY3n;r)_!E8U(bhnJY(n@tSBKvp}8$k0<`#*mYhx1#@gG{gb?AQD~Kh@Rs2mMvb)35DE5k)_6 z&%*Ni#${#fwY#tyG4MJY=fvo4+V1i*T~~k43IcG3a!p6m|JC~!wPzTNygbD?)EZ>f z>d%+(fY_`xE^Ag)|9a5c3>Z?3qpk1$Q6mz``|qvuW3~ujV?Wn#^Lzd5C9_{??fhgv z6V3Aj{n5MQO8F;2gG}2mP6ziNzTeLoZjC)0zW;>NU3SJkdDOM_Cd)nO}?U}%#_p|)@D5l@{qq$e<-`no4u0;k4`}(V}8Y={q z0)*=k$?zGR`;IF07c#}=FK-3)68CNX%6)Oark@L|RTZw{j3v4}SyI21-xF(7<&W}= z$*OX6RKH8#wD0~Gud*ZP-wHbnzq-z)2JZ!{D(sl=E^!F6@|@nHoCnN1r>p>ZQc?h) zl(|ZpM8+xXh={}kBrB6f5g-bH0;uamHnJu6fdU)D;LWqRa>doJ5(_)2o|Msm4<#0u z8Zcq@P;@jVjQ)TrUK!2;h zBn}7w!)5vt`^5p1E~39`U+WJI*ihgmBn*gtCoa4mVQE4@Fp&Y40clq{ufLX>Dp5s) zBLw~|E-dt^X_$?QPb3H&?XC5U0OW(zQQu2P76XiLnWGS9i7ts8G+~1>OgRAzcIs<)~k<8r=&J3r(H2}10ZqPc(?v)l0X3PY=MKG|7 zK*rH#@r!71B_lkR(qw&+9}vfJ_{3>8E)Zbt5C69dWEfPvc7X&ulv^!>u<=+Ru*3uB zfvgiG0D4Y+1dehAni^n%vcMDoE%1M(vAP9@Rp>hYG;m+yU23OxxSNW z;KtVpdT?puj3=q1-53vKb5cim^=%B8UuwY$!L7;EcBvT#Y2)~1HWLm}&SaA0LC|qP z23UQ@iPyp;PR7HOE2n7)URXhb*qDr{G3W!p#2u@SUfewAi9U`Wm~E+Lv6og-IJ)1Q z-655wHd$o}0lom44NU@Qs#XxpifsH${7xqmu|OzlHDVmG132^Yg4KqnNg}9=RT>0i zp$6v$05~<&ehZJ~8pLauOpY;-jTk_+#AaX{RBRjvfq#fR&ft2X6@(eA3^LKwfM&nZ zpRl7dAnZ#42&sU5z&>7Icknw1mf~0uFzSGHtm+^p4i9+l$_$19x_qudM@Z}sUX}C{ zqR{@(OXI+ggmEDtR(Eliux3CZskej>LjmWa0}vMIbjU385@5lIE`f*rv$zPcrf5g6 zB9_B1m-LVuHJuE8QsW45iHQZgK^^%Tpg=xqH-xX15=#5m|G~)N29GfgE~kgIOw!~2lR9M&|F|}zNWl+vn2FM{u24j90 z7xf?$O*}{k@C{W5se->agj{T7ydoP5Vpv+#XDNUaA@EPwaTm-InoRbBO{p-Aaw>ku zEttbGhqQ!5xfK<2&+3(U+R$VUd>uEEI{^4A~6QaT0J?LQ3wo%JsuR8cEWXLfR zU}ifh&{U}{AH*(n7Sh#3H^85GVT>wqhsdi0mSHG^?ZUamyO7xihgu~-OqMT0wGGz0 zhz`Kc0vOs09cK8#zTj}_X|+ngNcb~C8f28k1qF{aS2nqLr~_pKJHk@KMnOg>YRVAi z34=eM70Ha!#I2VfD7(Z3BvghJt{mO#I3Od$ZouM{83PvG2AECxF+9l4B`HLE_A20? zk_p+D>4FTJPI^`3LW0ulk5u%v0{2C|fP;?%u@~_N?q|ybNjV77SP(*{oP;p$v{VW6 zRO$|OM=ypSSFjn#k^3A}8$vqE6}<%}(ET>G(+c{-qIV6y_rT16BIX&ungJxlVH-N! zhlTBlg`!gk%6I}?RIL=@tU+EPIBe4(2pwFhxg81xk4w-exOi|Apap`Cs$6R2HJ4bJ z5PXurDl)>0$3vlA5+DTjoB(tHaDYMCPJuc{Vp61dRK6272_a#k?qV|Ps>*$4(s+=< zn;AW&3n9qD=?StXg!D0C*|2OJ*yZsjc^BSgZ!H91*{CX#jByyW=+ap)x?3UkZ|G8P zD9hvxlLsceQIr7YdAMch1;VSShb{n@USCfo0F^uMISp6>-@?rtk&l<8i{sPi5A+t7 zLayP|Z6uKLXc3{s#CQv=Y|HyFGU%M)0uY26Oj{RgkN`|?;Rj$1oDB&EG_#J?wEzV$ zKa^NGXDmL4s{&#_3l#D$5r2$7{D=BOi~)v=ZfGwMYF%pPheEBAmM!ja08vOTe6=nJ zcnDlp-7rZ7wYqW$wmiR#q+Fic2;`y39+7JD)xs@A1O zN|FY!w21LEh~qHN01PoI2c2mn1_)&%pTp4M2>^(Q|8r@rO#W}px&d7FBzf~dlq2#0 z#A<;dxrstc1YmM-(TN`%20DO2AtXWuvFb<|cpt_Bp(uM+7jYd_5FjO-5iuKSgBqe3 zuV+F*qyy{`Wr%o01fj%GX+TD_Fxy6RA-wsZ>w<~NDGnlQz=ODKf+k83>WBTi+@8ZJe^Ylcnn_-~UNXE>kSs9>cuh1Q z?hf>c*F;s9Byl+Q!0X}Q6=V>{!x7!!u*~A*VJKX#K353BnNltxplA^SD9TI7hw>5{ zVs%g%H;_YZmGe|x8^uTptm#q%w1@?68u~$ZL%m_yVavt5iaoIr?uLdy^cWovTRtP}Yd)2t&D1IKSfYiKI(GZ1;n3!qesV-WHK)iV3drPS3FM%~JuEJZ_F-4k4>+p4{ zAtfwTkN|doB|s4%3qa7K3|bY*0`$VYp21=cz{%Szc=DpY(N0x(_=u3DGGClZSHvf8K)VQHWN=j`hasimOAam-I=9AOX~6Nwu&JeWiiiN)TxA z+o=k+v3gutL3$Qw5!U24y!(+BBVAp=uV6Fq8F=mz3*P-ggUK!vAhK?-fm(9|F#H~U zGPaZ=r4Jw>O_~Pk-+nv2MdA-gOj{M{`j^NEc!1fKos>d=toD;qrLYz^RyiRh)C0|N zw#3ohDG$j-#VIe$79a)tn7(s~Alk)Xae&f5t5OsZp<|{im>_6swJ2I#kMR~) zcoGvAo_{Gt+w}jka>}fJK8Dl zk?5SE=3NW$SW^S|)s;`9#c{%Wy%wDqECAA#Y4KOl*TQ=d2T51Nvoi&SkU40~i)o0Z zAX{X`(BkI-!PQ>8FV4AGg72-`fH7|d2(w@U$c++O!?CKE{-o<6qDvlvLM)8vg0Rm@ z?}TX43ohQbs*4%ACZST%B}kW;1p*kc05wG0Ac_bumryh^F5wn~_&*F?u4>CwsuD|K zTY6O5xGvls&08}(=rUdszl$$LzT&8hrHCHWOjQv860#BPAvV#&haW`tc?RKKtAtvN zn8GeJ1Sl)yR#ZRJW7R0?b?665e79Rvk{So{pO4SNU*LNLqMRt|JD zR=l8c3aT++#LCiQ8|(r66d_wEfLNfFu@+d%Dh^u994bpG>!Ff}#~5z8kKzARRYN_9 zO7Bk7pfAia!U04ZYeJSr(&Nu?f7wfbuk=AcMpzb9D~%HQI<0y1%u2bF%o;ig-QXV4 zXe9tRPHsgaL$5J3xE_<^;2C`Ydd3?dXo}mYA3{1I>2Oq~gmPYS0KT$0xil_(Izvx| zESAXR`q#ia{+%;6J_)Te1Ennd2OXjvCg{t!fss(y z_!rQXUO0VX2y!X~hr-m)qVj=S3*@H(xY*LOp5`sysA>eiK(9gjYzBtnY>YiMKn;~Di6AWd% zE&DkBOJfM~P2R;Te7tParEe$wMoyQv^=rMXQdc*>h9{Yuw!Z3~8v1jDA;VA_l zjSI1{I3tDazj3J{`Nh1(fl{VMRNI1^K?e9vP?{k|SlIEZQ)^NU|jASPha5umu>_ zwcn-yb2zjCfhxf@h4HHO<_-wZ#aaSo&>9CBEHd!>RCM(Y(l1Bi!r_Ucbc)yl zFHAm&*dbgvKduLP1;P%nTmW)rU;=RLwWVs1oXABaL#`2-iA2b4BBO*dfK#NUg*2y% zEXxHT>4X2fL}8bYk%*hh>_HNNIo*et0&4DVK!fzl(Z@bF`M6PJiE9&RiCps$`AAl> zNP=6CV1d{txdEIN_kOCB17uc^O9%FYXNe#ikkmd@Ar=z-2p`M^l};*<+&)VnP-R!> zTk;xiBO{QJK~IqCf(U8fy3|mNXa#&meAGuPtvKE~@QA%giW9CeWa3a`2&oXt^=j5x z?7ooz>*Eff2S5S*1lWVCm2_M@Ptlf-EJCse&2{jqI21n;#bVv_fAMuhJ)NOrfq!M= zF@Rt)G6+={1IdEqL2?AiI>g6;A^`@$$hk%CkR8cPLDNwOR*W@B7-UJZg}`C?H*H4 zY1Gg=dbuN2kZrmH8Yxbz6O)`f;o0JCy2F zCZ%BMf=$XiBReFXo6oJmXmFkv4cLw@DbX>E&GihYFy^`BglJFc2-PDseD$(=R=u$v za1yM?)#HqK^=5k?uCbni=+Q`+17}E@<_pfSSX;D>TB!U03&34GjT}MT);R;0K`u#f zoDMoIHVp)ege6IZPh=2%_dZm)#-iS7MVALbaqKmvFkE1{ksc!fedsV03oPUWhQ7rH zQ?>&2lerbzC%V2k{EIl?+ANV+EKQ)M(xeAq!DOZc8x6=^gKJqU_lE+0f?^iA!gssK=cBY*`2-@u-1JKm>iJ}|0$5G`=T<1h&v#QP|E z9ZoXe+`WNtIRrEF-A$?xcij)=2`%I8u*PQKC?+ zV$l7b$T+cz2r>~6_a!X<}ki; zm6IPKnC<|6m0^T0LMDHe$;dn6vPppW4U;n_+Wv~FE___Hg+19HyFMcO!j(dtAr8FK zpV*9iMj9Z^UDL=qpkN9c+4Vz6vJTOauEB34Ah6pvj(q#A|4M$SfoIoV%di!^$_ncJ zj$WuQqG5HA37PX~0y?`ukQbGVq@2w7^g38Bc?`({bdGhQQ|kkHF{ERyv9@E<9Jik~ zj-rCGbZbfe8d_Qr1>~k-DA+4J{^@GcEhiSP+)3x;r9KQu;{W&#g_O2rnD8OTo!mZ( zE7k*`n|~s~pcuyrl3AJx&ym{5_8>P>8R;4%bv$2We@DNCVEWGE74JKIO$`s0aX$sX zTI^x;?1F5OAcI$hEU+NNvYI7>1TUD()^_GflUWV$3rXP`ILs{tT&jz)uX$I;D(5voA{!+m{$S2hHh6(t z>t(g}mRd{g?Il-=ozvj#6WZTVL7_+;GAram!IMIalHUzOchoui$p?6 zWhA|lQZNIkdS$Ox8(y&9f&tGAu&?=Zv>wreC(Bf!zw&@)jJ)=3I$|AH%TXfKN~2(} zsLaGTfS3Of%fTv;Bj{5i?;tf?M>Ztek$Q^`SHfsGNU1VYN(YyUj}LUE(nx;^ zVf0^$#eQOMv5VFiQmgorbYnqj+GB`A2$$)og&BuDN|x)AlF+;+Rdp~OSC*_*ar)Ac zIz3cOB4{OL2<&hrCqrD6szLNSMkd`qI$NCxC^ z<=8v!8TIUv?vb8JP;wiokh>R-^K6aUI1HI8FCjAW2&$wD225;*oF7gBJ1M1HCEWf7 z7O)ukfR(MUvfAitSZquP4V1{u=5a_z#?z1G|0sEx#nKgzGK`lkfXb~gK^Uz^ET$)j zn@GP(GPyDTJh}rC!@{Jlr8FSpU@^sNSo01snh| z_|6+Pkyy@k#m7Jgpk~OG+=Ph;ai)t$K9K53#y~058uOZM%Ydb3Km~;DpfebT=){NI z#e-u~nel?@GqW944_ZRa0D*VPY&|(G!oJ%DWzf# z-7i0R`AcSAVX>5F!gL8-uBHY+0snBYj3X0SAmMW)Z z0aS3!wQzHDO<`VKcrIkcjq%E5=bDV676S%zO9dD4=P))ITWUte7d0`}UU4*YDOK~K)RMc{f@$zG3sm6v_GZwUzk`=BJMh2;q zzRFRAVE`f7HQMOx0Fuflz!kvXrmeVBS`1bIRZSh2f6J`_7B1=0`CrUylJ(p*K*5%R ze{1MSew1&jLL|q3R4kkh?t;)ZJw_wSnba_l z5weRsi5r4rflmP^Py?6&Yzm~CvLS&+_DWsEGf4k23lW!h4+#MP?U{kc{5L5&G80Z8 zXiW~Izyz7rA?x8^IPrjrp43%4Ai2qY7yQOk8y zx?^tRmN>T~-~h{UYM?Wa5mq<7ZM%v!#=L;MY2KvH1^(m%j!RmCcW%9z72$6Jr&5`h zll&N8b2+dQ^lX+JB11R9W5JS$#0lH$Yh__jn&HhemrG$MRp8oeh82Z)o4BM(XW)jA zTIpvLGSiww$}s@Nk!sk1Ojy#q9$5^_yPv~Se3x0YE%N7pD&fir1j2Ier%?%goh`MT zNX@I}+7iDc0DRy9R>COnff7`1?xfNukTTf{*Bqjc65TlPjtLaRrTJGlSG|_P$ImMZ zfalC}zWTJ21_mrnze4$e%SbFRwBRT{OAFEIGVsM#Bw4*Lg_d)`@SaPcwu#$BKXy6+ zmboAjlW#MDX&?Odb-Xfv&rAV~*HU#sWd3H0P!d z3CXv7yZ91H3H7cJmd9X(mG9cc{0pit9+mM+_QjO~=qU}z2sL5_FFGfI0b&r`BpG-* z3=HOmkw)1gu0T+8aY{N*ov2GpAL7eZCw~nvk(UXr3`n2WktKC3@hh(S$HAP&8y#dRNZgvi=MwNbCTzf@C(;uIh+gxkRJw#Gv?XVeSxh*= zfq-OH_R4eyG*4?`zo(_t@)8NJbPeLtMx8-9T0+3!^m2P>;%z?0ffEk@iv=yYso{CY zG36+Z4Xy_le5|qv?P5pSBfXaNu?yD%3n|%@%VFN6M4M=U9_Ei2m7p?`l@HK6aJUiz5&LjX9I>F4Cz@NuKP19dkP+A*m0>7RXBKM~!a1#d#3>P&XQH~81Q(*Op+LQ{MU)~LV zimbU7QK~T{NY;d8nFMozXu3|IRFTyQ49o$x4OLFVz-Je)YmN1+dSay(x1ZuFwI%qI z&6%gtEusWdfauTpr}~o{$o_0w@(Q|wD#1&QIMC$S^U1PANHQK_N08+@5Lq)!aR;I= zFM{7Hd*C@xV2}?S7dS!VpP;h+r?{~HnaF&5h5#m(RT0Qw`HE#(vXp8i4V8|JP)r%x z#@iD48+gJjVV>4VVqC=wd-e1H3KoDT zhad@uS!G#ekB`$b!iyyUNOziR}#l0cwm$fN!YAo!jpPr zdCUL#_Oz5?Kt)6=Pu`u3zypc^jjg%M<}=kwz2%_t4iMTpDOv(!iWinzAn#Mel?YmV z&I%|-o;>P`GzaehR2)6w9e9=gqM8;_YLSWcY(%mjY*7#?CX=Sn0y<-OhV}q9pwiF| z=m8W2ngD$@R>4T16A97QHnbaBy99@ZxeAq03EvPoG|n?jL;;*b7mWT%U=BMp2nyeV zhoZ-(3|$Z z`2>2}2AUE<66N>9pU^qaX$aD5(2;etH#ig?Q0w*AJmC8mi1`DxubDRyj{))X?ks z7M(+tO2Q4G0nA%QW+P*MvLO+_7;h^9p1=+%^5!dKU)M@>^H@FP-M%}j)fDodr0TT^LPcAN^{I1Lzg_q)fA^5!`+gX_r@ zo8(MCCLqZ4MtKt?b=35lXps#a{)C~Ba+WX9I0SEUq)iYFmyC`GFeM#-WJzH=zzf(; zk*7O!EQrDs(29+F#>`UFtNY~1W0c7b{A7G4LQSAdB|s<}e;CSu0EjY-sGU>+@LdB@ zs6hEM7&ZV6D`V|J-vos~odz493)Y3M;gR92SYI@Ma8y|gKLM{PsbSfGk{+9qI~cam zN6jD#0~rWxL`o}yI2ti&+XQ@|2$_bw8$fjFnR4KUu`t6g>d9bN)=MuBy2_9tq0&!_ zpZ$v5XW_F)X?qds1aCUeFvgY!CDQdw{mcyzv|--i6q=A|r98Kr1IHbelBQP1DDXq>a0 z*&DJ+K_P3Ez*&WD+4D9_XFMC8XW*N5sfd9-W169t5*Mlsg&7k-xM2o>x;dC?w=6^u zQtejuLSgC|hyi#*jXVIFB!o~R9f)FRj_Ak8LmxEPg~cF3Ku{we<+~52!nDL z5YqM6|7ONk45H86q{0n=DJ9~brgd|wp_;k@G^Xeu0HXPY|0V3q8I%@ErsT3JL(kyC z%DiE7FuHg=S^?{PBYAQer*-!IDwU6d-~#MVW4Ix@Rnb@0qp~;}j1gmTDXZ zLaDSuTHZ8;)(Xn5O;wOe1%cC{9ha(2 z{WI3MQPHx1Vrnm7m_|%jeGSu^kHoZjgK9vbO$6m$788)fdh}D1G1VV1NA?A4r`24_ z;&HIx(w**OraV=im`}LjKyW`xjZ)W+Rm;+~Q*J80R4nb8Bmf|%1ySvk>~vO>WILU* zNK*pfvhmvYv?I_t6{4h1v1{_P_37x;c1rxYmr2*+RM|DwX|~i__VlB!=}&2=;!^i1 z@@!jnU6Y??*F;nO(}P9>^&oa=d7$DLuRmDR)7rM?p+y~N15kttcv{LCp}@>q)>^Tk zrag3KoC(rTh@wL?oO$yw#_Fee4q@5>wS77llGto}vTJ?CN!yAsOyfN*r2R^nmDx<06xbL%IP6!Oj5}gp(u7)C{?hANA098QvEYj zfGSvXr;-{;HKnouD5<_r)wEG5G%doTPFKxtIw2akQO&9n<|2o1rrA_@`BbL@67!byG$|>SR#_ zC@2T&2a}80`8bfGIBD3ZBLEyKYvpo=Os$xd(e$R0(-qnSl?T8BV4ePL%%~Ps(`gNL z#}q=9uQWk+M@T&K!5zV;+7Ni<(b0&icu1o`bj46LBFYbV6|MlmlL%K0fZ3!{rJA`# zTQ^34R@!0iufZH6re4olH{%xmf$ikrkxdeU4cztsVO27~SoQ1C+4+&KIL@kR)wQa@ z08O*gx*OQg@+VZZflvwHm&Oxq@+?%Fsi3rHszfOo^h@>6WL57e+Y6^@>t><4Rq`oG zQ-NrGwVZ10RDp^ga+U_R3ag)*45~1#^2LfN7<^D42RfO$94p1)SEXo6B>;qc?u=VQ z%s_>zJ7A%fSZ1Xe)wL-<=J~UVkt@9!=%!-FYFrDp^gS?o_)7t()#y!c)-kIQ$E6SK~$6Q_lcPpnKXYwUz=_wNv8L^I56%Z@RoO zpQ2BfrR7!cl8LP&&_i8+!BkafK~#Sl5j6>NkZiC{RUE7=00%4MRE+9hC8O?9W2(VI zH7e=UxoTY{u=YxU04o-F6^PY$a$tq5!mBc;Q#7yAwKTaJUVW%)PO}B=9n0$eRDl{n z)s|LEw+!b~7OVZ#yV@<)ur^mOsx;QPUwpN9s_87SQb+-8DS;kpiea$@r#S&2ecm`n zr8{BXM%seTld>8^kY_zq`xxp>nAqeIYLNhXTDOn|DOGfjH$Gcv?SmXB0;@v{VSuoOwnqA&})una@(6hb?RBO*ft?1m2_CWY|EKTb5M4Z# zolCf8=SR}y2<>bcN;^#m)lQz7X-Mp$?QE2?h`gPIFL&Rf_1iS=q^Lex&z*hCE7)Un zG$3K21MKU7NH>5@L1olmhahta=me5q;enBiF(N$B6KH-NzY=z((Ri!8RfcpLH7TV= zaWaI4*63~qBXXEw6`T-MY*_xKgpwlu#U*2@QNp}J$>ysk8>Pwgb+=sSL7`D~M!qw!;B7HAO z*eGmJgu$6dfjpyFnqX{P4N3_mNKk5K+Z1x8T`63B2{eF{>&VqVqjCkhR!t+WzJwY; z|JvKU{^)}+*KE#2><|a0000FfW`oqK%g)NNH9<|+ODL4#p@x!@d^N7 z02D6t5O)AEz#3rN%1Lnzd|Pz|;no@wxs~xodD~*PpVSXDfOTsS$zT^AfVa+DZ?Cx5 zM@+r76moA}jpkcZXDzTKK&J-7MsTgV<`RysBv*zji!|!mHh|;I)vT^jopPksRUNrx zE4LjjT%-LbUP`z@`=uO|KuIQG0Fnuo08AkDrph>e=|*!1u`)1{jm$R+vfGi--h`v@ zuM1Rh^kg^r3!CA;Sa!-$mz~0(IT|Z?j?U}`V1*>=sPfG^swFGc9l*Au5HO(K1Wag9 z0rO@Mg{U!Jut`k=1-qhe6RYqsaU?Pky^6;taZ=%l6|{7k2Sos>D|>0iCLRC+97(MJ zTcw>%dvpRDLQr&KGXFTcGW)3SVpBi@(2s7F(4!K=jzF{NH*m7?Dglr#HDG|=RL-W+ zfG%*Y9a>;XZiC2%Hnpc$d8wWhX5upBQM!x{;MpJ+z{{x4v`e!xPKvedVCo;`9)3l% zu(!5@X*?;o*B7FTY+-9YMN;PsYe7v~n32mo0l1klgAG~_z;iJWLIccU|AXkY!A1|j zP*`M0&zMNd80L+jjd)-S0H>h~X<=Fbw+BP)7T~Tl*boGC|!6C;W;qu8+?EV#PJqkwaC*GD|_Rxe+B|PeumN1Biy9 z5%Nh)3i(&o%;L&5)0&0WY;5YwRw zX&E3Sd^5tCD3z3&DhfqGHu9zal(<0FL*^QZaIM6GPBoC&0N~gy2RAdogBV((oso?G z*WzVoNit}oKrYBQ)Riy|)al|{J>lkI@G7XR*m&4;25`zNx+h7{o_J0t_mWiV<*F}@ zx!#r5PBz(B>Zc|ln-x-lMX26OH`pTFEu`s+KqCRfWXGqTobeeR*65;-NTuy*{x+GS z4;f<69O#rq#vZ4FHuNZpS&hVUgSR<1p}YKM4Lz!vF_sl8?z)p^CjK`$i&cteKz!Pd z@-2yC8LnlqvxEK%Mu$G?BtX&{(IFZ6Ba0EGtn0%Wj(ltcM)8>Jr5?n~6iOV%To8 zC#0h+adyC3{P8LQI%O_7)Rw9?t)cXs{iptl__vk_bfn7 z4gj4c$2Mr2p5!eEt!$_GQ%gaZ6-7c)>zNGdYD4Rlhl5bLSZt`+RsT#dwX7F05kofO z6kH10=d7YI2?Is_j%;#@0M8!TNRpH}dyiGI4K{ML8`=&nkG67W8VJ&oV~Mhg0Viz| zrjfeR3CHr$bhLgnjv9GJ7?MiE9e;Q&1@Za~7+8+B@x`Rt&(L)eKopk$_2s;|n4M;rLXjGn7pfkGuiq?7fugnjLJe z?NU+=mWDS@vT0mXA3D_#R4Fv_Spv=31O-E!^{Jp3&{_X9hKCQsIh&*n0}xYVtNxjc zkBu;JV^=bnNnTn!oH%pfJOO=qo72iAW=pEfSzaxmR#A9NT`@{)-2*b0>uf_$H5)>G zp@ko3n(~41#t(otE7n=iTGh0)K9`zB?&6pBsx_>tX;mExg%t}DZ&rJ)<gbY|R{5n6$O8#|! z7$MSvtS0ao1%Tj6Y$eBx`BUz7XUntIy@og_9PtEY#7m_aA%bwJL?d7lGL>pXO=T64 zjo8h!2<<$;gE|0JCE2oB@R3;|bO4P4UkDXopS5ID0^O&q6JZS4NBD1E&~(g$j5D5U z5(HHUb&s&aFOaq%Wc-=Ym9L1gXG5g7sNRG^UK6#3Gl$4VRspgxhD;lbA*&D&z#NV? zwU`pXk&qMs6OKH}*6L9K1h5@Q`NkNI+hD?mV0qx-*gF^(t|`e3^+SvdYkMHLst^;P z2~&d!M>fxzqHLi+DF>Z0-iXp$bmKa4Es&m20bmJZ z7eu!W5bTF}gis0kASznZ$0fBOQp93emPa0gZsEARV+5GZkwD zoj`ue!NsO+K03JXuYv;%w}rbhS^TtrOm5EG%8H7{lq86}Vd)M~wlf2A0$w3UM#EJ# z4Ge}C+7V_#+3FD}5fV?53_h?kTo|s1!?U!a@eP<%Xalx^lx=7ritED7=wKY85@6dr zt9%TXQMSc|065dOkdU=4ut7}mw#`*Q5@5LT4RZtZ=0-%l0fihQGFNT^Yr)?3SkSjU zMEq@4A)kvm92d6=U{Dwc$zrFn!2~>P8`p^IbKy577DRDxhsjO2W`nyjLD7)Ja%v*Z zV$ihkoKd`cGn5%h7kmdtP!9(zV@WX1z!vTvmC*dnB==enVA!RgDc%;Ags==zA+r!s zsMs9b7zZy6(u={wh`YqO<|qu3IT;oc!WK#hkPM9@SaIbuSlrtHXn=}9bgTR1aFe-O z+@el1SMGDe`Ql0?P6A?F^#U1}>*#>dgPd{oEAEcdU4r8fQSX4mAXM~Z3!8oj)=C3q z?I`0C2fn$0TQ#mPfsNZCapSHFifPIU&q5rR4lu{{g>-VZ0C(GkjWML03%Cu#qz?cKR2w((rU>M;iIWWONR+LLs42Bfth45}veiF?F9}itq!rS&p zW!3;MgmQs`xUh&W9$*`j{qS7?ef|v0gk5ax4Hs4fP%~f`UI={^6@ZTc_^?U<5cq`7 z9LN;P!R1LCXz8~I2imH;B)%|1wcG7 zb5JudT%-jy4pv9P3DRin_-=44!8=4v_e_pK(M9{ynot0M1!@i^1f3yFgCh0@SS3_M zPCTPK5(S#UtgBc!ikwyg7l@(%W(lDn0&iIA2zMw1wNLd~Gerb2SXih;R~)+8qC?1P1&$NIuxsdVs1fTqx&@ovOIOm6_JR|$8g40;UM_L?XUNrY5qwSivq?7?mrb>D2bPP}JMBCF$C%!vGF)i5_;ktYqCQ&5`}?mLAZrG!n-|q966)IBZ#d)+Jxd17~~0BI&Qa- zKoEd`FfXXxQVVXkOM~3)fp>T7xb@veZpCqwThzz0;Db9Z=pE1)#sE=(O1o0L?n<5FMByUYy%v-3f$risGy)6iQZu=cS+tIBAw{&Z@J@C~8v`DEC z7{C<5Pcj4`0=#a$0wGeGK?#>=d%~qgAP-cy6Nc{X8h|%tESM}*7WfM&+=9Z)V2ox- zkR-?fED_!ZJ%9_K_YviAPZ$eW1B!@cfmTLc(3N=J>KaZ4^IhDk?~-K4V3;3h3p}_$ z+mwoK>1bQD9r8*eqP$1mrR_~6H{-(P^VV?LKXkWb7=Vylo!W7&5XkhJEw};=0bIFD++|2Cx0E}}b;a0ni@l;=tU=aA zeV|a#6l&Qv3qD+f%ziM78@3<nnN~S)Wf{xW+7y%jG5Pa+j*E-4$gD!LPeKcp>a5 zVHw*5T?Uz{CSp4X4k!RF9!7<0kW`^U>Lk0rBpIGt!J(#!c_OUAo1l;o5B>#dkA|*d zVK}3v!+H%4Y+k{LY;Mq2;4AduR7_3q3y}!jL5pQk5x5Wm$O|C5hK~nP&kiNz@v(WN z4D$yi1mDIk*2Ka;Fpgjxo?CpJNrgtOOEET)cc#sp7C{%S2r%KpbM3q|fhqo(JB~H) z_D9-v{wew*WFEdBl3P@~0HwAra4n2NoxU3dPbdJzLfi1HRfKc7aW#Y0M$syrBsq!i zwn9)2W(#xR%Bv;9TL2v}7|a^z13d^cA$yewk?b;6_6!vjIILm;uTt10oY;Mpy1SEc zFHlgH(3v0^+!y2n;@)}3)$7~qTj(LA5O9Bx9}^-nrKp18(fOXUf(f~WG)JE0p*8PF z7zjC@Y?*_3!r=lGC!FN0Sg=8q$X}6XhHx{Fv>HI27SS{bJS3R zIvspyR*EE*iw7pjafx{H#OdC&d%^&O z3y%sRG8{BtP=1PgpSsVjW|Dg$^6Ssku>>CB5fPBhM=W(2g5lNh8W#+m9f1xn<6%Pp z;#EuZ322dJy#_;Cz@y?js53k$P#<|te#eS(c;Hbf9pqZtv*ZNPLeEi`t0B4Qx_fX8 zw~yS%3t;!r`}puyMO?t`AU{Bd*Dj>69WKaB&9?B4L&b{nSCB3^SxGw@3=ak+FVx|C z8@`PkjBjT(JOJ}8_v8AJzO`qp1dd-b0QarE0DjAT5d*IU!jCP0o~<5u56lPd1N(vh zz<}UDFigf_V3hUvAY~~kuA;fyF1&7&;CrQ<~u$aB!UiqFhklF0%m4_D0&z;WNg7p>yw9G7p zW;5Gud7Lp_KC@kf&}?OJyhfT$tm$Y`v)kJ2YzVbAI|YEE!e;vf;8`XBxpo7!o{81w zX3+>57~X7pb{=(}B`pzBN5RBdgDtE!jYgmC)!JwOwAfl|ElYL9SemWQf`cI_+*;A< z*MK`)1n|zHqhzz{VDYSNmOP6KjR)6*=fUe)$|@lZKdTS+&$xs8!GKyyt%UYItEkn_ zrZaS?aJ1!z1i|~)k3lrz5(u>ZnF=jF!bY2+9oRBx(~60-2W^B_!-ip#2_I-Nw9FJF z?X>nLEIi2xJ3RwDJK>pAi8ksIHZqZ_XmKPg+UTU`KpY37?aTpFJuK5X8*RM~M+*?P z*ZyN~PCXFfi<5RpE1@mY63&>6Lg9e$KbA>brTxd=lccodrr9Wy99GeRL&`QS*W*q5xFDt~&FHjtTF4Hb_M_rh ztB4wE>$HAan=rWXUpuJ%s}*V?!wk2suoq=f8|w(Mc9aUkRSL-PumUt(sof80R57&~ zwdEgqf>Y}-@YF7sK(&tHk-#cg8*HlGWu$7g1*_WdYOD5riW;UQ3b95jkU(0kj@DLt zJj~V3GnB)<+FvbZwMrqZ)oDOT?1{ISv5TBiS&NRHARKE(svp~Et+}>Z3!1IfE@i{P zxLL^tc&#SIcQW3f*Ai!Q!}nopfxZ?L z!UE6?3u*(l$TI^m=Bp$8sX^G5gcP*J;tY+hD=4B({y(Cr!oH;)b!6DtuHo zwjtH`0(iK%0J8O^rc@bf$J9G}djq$F+YplB zcETI?Sllvrd$*8V;4OsrFHpJF9bj$`1e)6$uk{0)^5TWsLU2_AGv4)y>DIY%{L%ra zZs7z^3D+&`HqJ}n^#$v0ZBiWxJ8}7;!J8-k73_(Jw;KZz@9`FDtGrF|P7MaV@QW7j zx`2F}TZ(_-9$f))f;Ny>jxV+&)^1T-^PKz3v}Q)$ex#ed)~O; z`pR+`UV%Vrj9`509s%Hvdjz-!oVI}h7ihBMQs6RhlK@Eo2X2fvf=jgxj+RzLdkeb5-Xd-b_tXaG4ZqacM$E3kVJCx0IS>53M* z4Aikb=H{c(i~d2{)pSv~INf87P8ax_2k7bcwytwPT?v6ucVD10Eb6ia@&HKPQRq{* zsY?i9>TbcJx?hc{EkI=DJ+pulsw+P}wHm-3X>%^YN{ zQWBewx9-j|uaiR{C(w26xqNpm*d^m2A_I7y+;F2G{rAki>1k#_MAX^PXX)lowt#_*># zYn4K;-OlR9R)j#?1wU>raJ$w7-L5(FbkN)7EUbiqyZ%h!?)m_vP~0sI9Cv>P$=z7N za@V}j+_g?TcU36TU9s(Y6}x-grK5=!w!7iu?yky1GBA!{Hn0}PyJUg#F3$|4A@6u~ z+ze&0?Oig_dzal2-<=(38R)x3mHE$ocbc$U(C;QaI=*H%LsbGLz}xJo6dQO!D2I#$ zucnxH`?zHcJa{L!d}0YN;udH-0>1EOcnhAm2Nkdrm;fQ-4Hd6FM#U%I<*kV~hs)ya zP@tinwxL^T0k?R9yD7NZ-gqk?Io=&FE7!*hOBezKd5OeCUL!HPSkEhAVDc^ooV?Ek zD6f$h;X&nf3s`xvykP+?FPFCt;N@jTv<9{VV%`>|Vn9KI#6$DGk=48$hgR`!$<0eH zj`Ny}>AWP|bFsR3mrPSZ5;JY*6QSNmZ@swjBj`1$;CF`yJX|_xqW6dUFJ|-#j6=Ny zW8v1|Bi=ivNEi!OKCt2BQ17M}Vw^rw8?%T*1Nr1G?mW|OeCm}V=Z!}%9^=I^$hfT$ zCguR!b7{RNV}EWPS7n^y*!AvleZ6jCnDHDA-%B$V^2mj6#>`$&h_g5D3+)vxKys{V z%QeRL@_8ja=7lse$>866hLV=(4(yZ!U!Cv%N6XT*Q263hc;39#r z1{dFvg0l&{0i?tue|+C4nns9Rg-ApRi#hr3k5j$?lWzysffjQT0@1~Mg9AuknlGus z=3Cj#`Hs(azHf#$+0WOCAc+|I(nN~BM_=1UQWw#%^aauBRz!yOiq1gP7f&$tRef1~ z{f!fc>+3o2`u1Xym%jwuZ`oJMboLGIw8?gsc>=a?TEXqx>VW&Y1&(bUgAgwzjcekuO&oaU|c}_;z;0NHm}>mq^2{mILnun=!Ed4^}Uc>x1C=?nTDd@zmqEsbB(uUY{0nL%9K1MLjwum0tS6a5WZ lJXxr}A`I&<88Z8eBia5IMc#3cAMmfW#mX?!CI8BH^8;$-nsxvH literal 0 HcmV?d00001 diff --git a/temp_git_index.lock b/temp_git_index.lock new file mode 100644 index 00000000..e69de29b From 00c664861fc9e61d488a5ccf201ebbd487adaa5e Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Thu, 16 Nov 1995 19:05:36 -0500 Subject: [PATCH 008/637] import DBD-Oracle 0.27 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.27 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/DBD-Oracle-0.27.tar.Z --- DBD-Oracle-0.25.tar.Z | Bin 44688 -> 0 bytes DBD-Oracle-0.25.tar => DBD-Oracle-0.27.tar | Bin 98304 -> 143360 bytes DBD-Oracle-0.27.tar.Z | Bin 0 -> 59715 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 DBD-Oracle-0.25.tar.Z rename DBD-Oracle-0.25.tar => DBD-Oracle-0.27.tar (56%) create mode 100644 DBD-Oracle-0.27.tar.Z diff --git a/DBD-Oracle-0.25.tar.Z b/DBD-Oracle-0.25.tar.Z deleted file mode 100644 index 03221cecf15caa562a2c56bf870af569eb53c6e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44688 zcmWKX_dgVV9LH~;?QCat_U1U7>g>(gN9e3GLYGbQy|cG7vensC3dyd{CgjX0WTd1; z3(ar;z~}LKzdt{`Uhn7o^*K{RwSSe09BG=#kuj{6QgifY;R7Hft*R|L>c(;eF(G%D z>Ll|DP=F|iVLdF5Drq=MrKs;&Ak~ObT|mikc45uXQL=cX412kRHjAiLSId08MX`d{ zldjgqW?Zd=^CY7dByXCG2zE3XLTLD`SIc9}f!DSDH|2u3iMB{gFiSsq*u;=diP-My zP^1!&0&!0^zr6#ozeJOsO#18^-2i|nUu00-3`0x;3o674k35)!xdF&arnC7q% z9nL7+h}pOX2V1|AFW<~y&$g%%@#Ae4&p0^}+(|hPtML6#3B**N3tnNmVWS( zxjFE$EL)tZkt#Bmd9XBZmH$Ws%)UMAylAWY!Fj|&i|%ZUOHWrgXlW=7IcRNZvPwmm z?9)bW21G3xv5Kbc1zvqjFn}2`4uWW76!UkwKE|M=+82$-;4D5CaHe z@oS(ta_BPXMr`ZhEFivO3d%$@JlA2oQ!?PlOcd2p3TG;s755YJU7ANS?T5?4nWAW1 zmjWZYhSr6NWSp50P!ZNnM~Q5k@Nt#Z)?z1&95Mt$8#>l3Y~n&Yf>CTQ&`gGdW$6#a zQV^Z};pO8XrbY_d+}E!G=!QJ)_)fYrrUFZ*UEl+PJR_8=upl>xc$$%&NbN|kg_IhU z$+dn4!fOEm4)fXz8k#QROV^uEBoJA9>o)>z3CzU3R`E|2xr??wN(z4b;# zkbaXwaIwr3@CZ2;;E0i8hD+6e;!P`H<4lChnOi{l$;VuO?xhNOmV#2TXW#i0B&piq z8LREB+a2kt&?$S5*RegLOnJ)ThR-kVC!5@npU2z!=kwg4b<6%iXMarq^YIYI{Ctj- zudGS%WV%4)(c7#})L}%zAxLMPgWcz#z9Z<13JPhW9;3JPw*PsxXUI<5Ovt1TOw5Wy=rXw-k@FKm>YdSGT?*-Q#-Iuwo z!R5{5G%||So`!#>W2q!>V0gv09K=_PL$EZ?v&*)-UX{Yjx{p{o=W5Gq?b-g1{+ zk#(W{IX;Cy%8nxv=enD&4Nsl-xlt-y^IGQ(YVP{SDA`Mr{vHg)X-k~u6`xsTOi$;W zb9Cdo#ipc9Lfe$f$B3=YQ3xMDgM(p@ity1laZ|mA( z*lA-mIieY7AkvDkC&^Dcqk<@V)OSc!2?wW&oZOd5g=Ku(vd4?li=G^%?d>zS+n{Qz z57Gl1JE%~|E6CeRSqJ=K8|J{7XqBN`S2x~&w@ft_9G?4}I)^_k@eCsk^)0x-P&U(# zRa!=by05;#cci1DS2_6n4)yO%EmsX(9U(fz>v=rC%|=4qWB&5ZFs*NkO$F~KY>0N~ zV~k1bm>F8z%UVwZ8LHjMtc16KX^2H;;^pv;$D`S7 z(KMTPuSjzu-sS8_t@hbJ+OUgHETV|?MF?xT36FRC3gDgfon)SRO$?mX=>){}c`F@_ z2AGBP_E&+PMy;rKZrb6YRbW2VaQ$F4Sy*zok(kX03{!5)d>NZ^WhfS+()zRN zbbAPy_%R*Q31sps56OPF1-h|31dsihJ$)tcwhWGgBdA<}^A+GOa*M#maRdBed@H#M z+RfhZ?XoZ}{7AbiF-|@6bmnpJmjNzuw#I3Dp3TGAFK|7w28 z{-(od`1cbOjPjKVZ}%CA=|2NQ_3oQ&QHIz(+iO+?OWs4zK6>g^3ft+19*69g|9(b} zdQ?@*?oSO2Lraas!f({Z$AY2TZvUa$A;B~_#|W5&yTsWdh&?>t<#eq|01^cS=`=^C z1$Y_&us++M5OSh86U1*w@F@1$o-gDw8Qv?a6h}ykhB>IC;5uogY;+Z#}~apHjUCC~_lsT^Q)=ZZl6$qI0C32zE7F)dQw1&cS%80hIWj>9ZXif87RZhyBt-%KyG%`qYL8D9 zP;@1zMW#Z`Xdz|MT4JA#F{@t{%8+naAG8CAkK4!uw(95bYslnA`emB@sw6O^l%0hu&Gl8oM#>S3NM8WYRMi75B z@lQwI2JND^_athD;{32){5<|R^g>zQ`cFN%Z2*?7#-z1*A;0ym)2*<~%fhsVR zw2FxBsELfCsaLYHJGmh!Sa?~ot24Y{S;$hr=Whxus{)XRFF3Zy{xMl#tPT4sNcBNe zb-$!Iks$IV5S0wgUl?UwDQJnKJfi}pUaqvMQ~1kISMR~)_$>Zj0azdjp4%Ky)gtJ} z05x#o!CXF{dzB0iOE>mG>ZEIlvhXTRD8Ccz64io(@qeElS^|BO2g~8nXIK7-4$jJMiu z(C#Gq(hBHBq2RAwY-6|RWwT2knGUhm2^{n_ca)sOnO9 z9&>p@#3|vb698(rt5m{e{#PCHcrpH_w#qH@gr?*8)-rhgM8e%zSo=hbJcK{j!||sE z8gai}1$>T3(673F>6-6Z6ay^HCxuAuNl;9B3^q_qxma3^rSUi-B$a?tG_Jcm}L9UWq^syHg00rQy3qV7BLjZ`S0#Uf3X^X-U6v1#1(cyx>81q4gEU&XNGIcuip7XOBdWK+!UAuA-tuGJ5 z1$tc=_Xi|Rg9*Ch%y!{r*Z?kfT&4F+eOHv{M9exUV_TqqXFz2u@8U@4U&)mGpQ`7+ z=tWWCSzP#ZAAajh73f}gWq^?^8gy_Q7ZL+&`Ps)D;4=DPk&setBZvEmpm z)fm389$uD0JmQCiOB;-**=Bv!!^n7k%V@dm6H*IPeVd?k&nZk|TnHm+Bvd{3ZqX6i z27o`be)=BPR@@t`WT+AWYt@?Tk~F*x?=NZ+!tvDcD$9)#qlQMdOrV8QH* z?<~mH?pl$y~JrJgAR9~4l$^A0y)g@meMcxo8oWRL_3gpmZjurPBz1UXY7<~VaK0P1ZD zp|$}EYC!VsjJn$nOP`(8MHMq{86WW&Bu78pR)W(7pDxR5R;xbL8 zZt_a`Ylj!>&hj7ceH|8k`BkaygHwo%uypGrXY;%I z@3greWky7iRT#XwnBwlZ9u?i6x`?kAW?$bw7qEx<;E^k}N7`r+Ho|nxo~N*aOt&1| zWDIq014_rnPS`;8-*?8PK@8;$ZO84EYgboiue_-7WQ%D^nK8H;gNvqCKstm3ek}lZ zO(NM{wx#-&@(m0BQJ61p0<)J(CFie&39&y|_M@%-ExP|$(1G&jS-Utt$z`K;vg$*p zxQiVo-jPu$J+Bo$FU@lhKwE7%hmj-mBU@Lm-%;-R+C@p)7v+L0OCmXSt+q`P~DsfRqiN@7a7mx#oXQI2K+O zGQNkAHTJs0|1oo5i1WPfbpwn`wW1iO8deF^@eo$&a_IT_1Jg|-sF%9flm~nCXPujc z`hUmFcX7yzA?;e^!E~*0=_+Tv5B^u?U!)q|vwPn>ec?XXrSV7yyJ2K(;?Wa$c;ih+ zRijUb`%aE)d_2M;yi6%SLb#Ls*prADr7JkzTfZ2PI*Dgy3ABY>VA; z@Z2rx)O!;np{4pq9^P2Lqv8NoBZEzaw1vj+0EbDg}-$GU|o{( z<79aI*UM_gk)MC7;sH_cXbzcJF>qV}YgNPNzl35sk$3D!7tDtMS? z&R@DKmCeR;9p;?Nia&7`RrSfulRbpCU=igYYix(J`dp#v9jNXU@lwIX@{T6r5>~+XqM4uqi{TAG==8j19-J3@eJtpNu?|wX&iRyCt1WEs- z%W=HTvDKt&GK6Iv6x6Ivvm;?uIvJ9~A1PjKmo()lS&Co1b9E1DLAMSdM}<7A{4A1?0X!5R*psPJ-?a-`SZ0B|cRVu?IO(cDIQH zwMFWgQM!kum?xX~4%7~23VL=!O|t9Ni!9(XBN)q$C_%ew@6#2Limv2rah6pK9ssbS zNFD1uA$OxC)uhk2>)AEp@F^e^(B`n!RP)y!PZ^?sD@YW4FIC(8i}_~m9w1wKbhf;C znITjn$_O0A-cYl_ z`Ch3IGQ_4*jI6$o`I;h5K-4V0*9iNVtM8HT)iflxmPduw{U#B}14Hn+tw-TBeAv^vU8ukhPG7I{HdT!`X1(@b@EK?bs+R9IKge2rUBeGJs)ziM@IM)U#B` zTwEE2WnZT$Jn*n!&Cn@~Ab(V5Wi^$`X(+s-Xf~xj{eG@z3&Esn!sT)czbmr{-M% zjb-vvn9)jE6YAP+jkgW&HeO*QdOgsU7p;Y#03d3AI7UzWn4b-Etdi5xof*08aln`@ z*i3GxqTZF;8luN~e9aMrFAEHS}Kf9^5~LuLa8&Cv=fa z+7gzeZdrJ_VT3Q%5)$%r%D#A5w=>kWW&_a>1vG?8UOUkalBK+Y%ThyV^LzpOI@ zF&9g-xc^FaYH`=Z`s~VpKe=ZzNlE-dI6rAf`PpR8FM)0Di@DR?&_0ExN3Y863|$1x z7z~L|73)=qmW@Qx08~eN17oR0pfYVTlX^eP2umJYFFQxO%puX+C!RDy_c^npwEvqm z=BIdY3cbMG@Kh?7%b-BZczkxst`kU%x%6>xopABIh&CkG*Io2tEdj74a|Zh`D6GU&_4ZdzqL% zOgi&zS+>5;Sh9ECB#ojXJMk!}-WWRHf|zQ@G+6i_)}1b1PInLys(ZaFl%~*uam91Y z6djnc2@WFVb6&lYX*5(+9}%E~;{fc5lo%Pw122Sf1aj8HgfC=VtyoS@N$%#Q2Q`36 zDvSY8(X6|iPI0xblhBS|NklSD9tG`-AKgcljU6Ydo=Ztd9{SwJK7I4Ydg;dJ@M`P1 zD+13a56Z6;+{>=1h_AEWG>WlK@P6+`>Imsxk%D;nR`Xb<`Zz4(jDA_%QHt(PY*sF)qN#29ILAH0H5Z&19FQcPO)B_vSAPv5o;Z2E8$gp0;yYfG0nwaSa)yS@5 ze9@Ubf?zy>c#>;tcG9vmRjwkI8eB)+{|Bv-)!(TQ{pJAauAs;1@QJ9%o~}Ez>m|eb z$8d2M0igel4K4Nr?I4r9pVw}2q$SL1e9`|^9D;H9#pSEP2()s0=nh)Ne8mNolT%h4 z)t?NsyNQ3;GgZ&e0s$s>SC#CiDVz3ZsQg;&7Pf#uW#z%LWmnfk%ivk{zjegbLE1uW z`9Z+hz|#6*xl&g3%Sz(|I$;8H4nAzsK?G3#92S^_b}g|NJoM4%k^nA&E(bD znuDj5TZ_Es$Np6+eyMbCFOz*FKC&eMB{v;A9>PdD&VQX>Fq{vNF7 ztu-v#t^Z5&x`I}U(Vj;(M)Xogh~2z23Vpm8AX4E*H;q~_4e^0V>AO_+bkvOTjggz_ zLhteULE_J($#KXfa<+u2Qca1j&gf?yb*Eucip-LY_G=a^on4#f!uz79hHJko79XfH z=uNfAm1J(vVm?k)N=lSm*Y{2#q&0ur;7ZoKMyIYHy|Q#z0*<4LU}Gp+u^a5AnV-B{ z%WBkuGH_FC#|!7IEOOWdi>TKu+-HYH4op{^ikQjV5wnPFg^OP3V#`myT3dY8pH*3G zI^soaAFQO?C-S)*@vsGv<%}L-~fzkiH9T@(f?Y-Kk40WyzB zV+td2^GZP7c-_=v)$c~TH_PwrdA*@D**#TCsCO~*rDjg?jR&CG;2&>rb-9Cyc&EidI zd;;dl^&X@^c(Mvp`dYidUC>J%$UO<2kXCw&=CJXEtyj}+!?(zK=xw6k{hbFZx0H2W z+w+Ca7|tnEFwsY&BiR8QJ(_;Mb7uMjl0Hs@T_l?7YO6%*EF3IG3_xZ87KD?EkCs#& z2htg4cH?fF*JmX$SeSm8xY~bS>jI?yrm{?~ETZvl@?5i3=*YWo7bIt>DmHnjrCU10 zhyAqHT>35lsM2-(AEBD@DzUFoCZIxBOyZ_6@FL zNQr`lm)Uw(KI&^-zMgKBbpL=|XM-O{M1=<;6--hT5rnxTY(RYhg>6LuN+s8bClO)H zh^)PF@Xs2|KkiDO*#b$Ce}&{|g=pdErbwp=XZ zVofGW%^>qbuALW{f6sJv3*t=Sp{e(fds<3m31C&HUq=+MJyQ%V2@WYIoJmjql7`#| z$3WK zV8L~P?AfQNmUfR1LEG)mRszL_m)nWcDT)B*5)zd|HOmZthN%Rf`j z63Z)H)=A<6G$Y2UKAEPnb(Xst5?S@{Bj4X8qP<^l-<+|PGM1hL1^sb94G2BB%hy}s zN^oQF<-2N`W-<(vPbprTNb=`pViNt{~6!v z-C?2#H9Mte!KJsw^O=O;K?uuD}Sz_UZPV1y8^r=Jv8G&N+y4>&KgK2{DNZ@voX zD)2h_X3Ut&HK6l8)YJMp2^@vpTLfwX2{y1bUW)=KGoC-Yi^-%zfvj(rdOJ??@~exZ z6n!$thR#RjuK|X)u3s$)u_mup5we%WHsCuu3hBbgN$+gu1+>@P%7Y_04m0Eb4d^~X+t=ekPXgHqvn+(RB9k-3Vm z56u3Komd7I9V9h*ofq>n!ByA(y_ zC4tbp%nbe!BlS@hE^1??VA=B^QDw6kAQ!IuYD9LCU8y;xts>wkC_IyC3lxr3jqJ*b zzo&Os%qja!dG8G6ETBr1c!rh=s65A`Vj&44ym?PIzwlH?SuZ-8Vrv2EuDv1!0qiq* z-E^vbJpe*=J+bq@5oboHHn})2`;P^0No+yx(8ZW?E&^^{NjpaceJ39n-FIPu?goj5 zX}G>Xh2Gh+x@ppx^JXeSAj{S3nbK}8xg!@85|Ns7@!mVDXRn6U!#P&%c*D-=0jU6? zu=#me?E`2YoD8~-{iz^y0!6}a4ZSqa!brd{EUW0Pa2T-0Bmdmu+9mr7Lhv6DDt0r1meY?Dpq#^%|GfX;pBYvv>OD~fCa-)BWTF_&=OP=I@;J-g6AGHd_ zTfUrml)rdA!Oj?_|4@{XUl!AnZDaK5HHX)Q&I`i?Cy$wC&$qur-0!AI>Y2pvAjWc) zB|q$gMHuwb9Qf26{7w%YpkKRWf%SRzb`AT`QLF0KDuIw3f1nU>i}-Z*qmq;4#UJml zhpE~V=x3Czxdd0HNcnc*So#zJB$S(D&wp!6Nw{?TXMBLk%ZYKd40K{ z+_}&MWn&MPPe@86G<>lBy0VzR=J0~W_CxRNN&A=D{P~$}!o3eQnKk#_Zo-ylVYpav z3%&~uxQ7oqi7m|~jC-|zwQ#fv10zU014JLEec=DXZAdQi&PrDd&b4?enfStW$= z@hoGYg8pf92}KJ|F&Z9J;_eDv1wSOQe5F`FggU=tycXo_W%XBm^N@D+`0Jx3`>NOh z_FeYD`KrfFi)=ro8;7N^|Jbq^iR(wI?Kj{V&$H4R$D3e(tm8HxKyB2#Z-5L-kNL$bOI&x-Vyx00t6G$k z=XYSgtft9zKG^w%T#K=*$(X)jPWQ{&_Qn6P!ZIRtwnZu=;arN%e2R8q9H$SBdA;Ow z9P20>$2vlxi^Ad*BaN-VLwY<6cur5c>tn=*rJ{&Wr7EG?_uu6~|;s01T&&<8U+pPsG=9IN#3G&7`MUwLfV$AjHeq3bpq zDIs7_+=fwal7Cez=0+ufm_YjWGiT$OAUIuwI^AN^=x!y z@Ar0bV+HrG&eR%|QRdRHKFr87i<&|S=Yd&H| z3M7=7TsW73_8x`imEvTmSMuTA4PeuK)x0a`2J3%@o)5m+FUdv$CDF%NT<(2b7o}Lo z9&l`o419g`k+)wG&-o=EdQ<y33AM8FdyAh>({i;+6w~jK1fakh>5ySRhjXYN}!(LyUlVg9q z`0>g0p+Uo6|8>8b1~oMAk-5!rfIwG9fBacAk07pm;`umD&7JO&Sf+}8HPxI@hg+T43#f|uV!*68gmLOi8n5P$rtA>DAgzJ+x|qZg1x-v=Pql_35txchIe!i zf6#dmsHQsl_Jg=A@1}Pc9I?pQ|Ax^Ibm=IP{G5+?;$&oBdTm>(gY@I_fyqjOe`!Z+ z!`C_^lZB+c5L~D+fU+{+lX;)rnmHxAS)Wg%v|c+ zsapj?)Pu@1DPgaCZ%5UKWwufb{e2qvCFs!UOQ%;%;E(9Tzt4O|&Ro8#ol-P3tTQ8xCwg%{403#>EHeXEc)s!Ua3jgZo1vD69O1&i$$(Lg?2X&i%OX_}zcMRnFWU`K8F&|1E3(DY9XpeE3L3z11f+ zA^3$BSSz=x-FpcfZ1(l{{gE;YZe?|h+2bqE2QlAsj#`V(Z3@B`|HFJYqJ3jPj@JWW z2-?QwCP>sDm4)IQW)EG|ThNN&@u+DE@)@z!fAPG%ys`fAO^8w4z@OsbPLh4I)cJ8ff&o*k= zs^=RZ%k8?nH*W%le;bXyY;Xk`@aFvsGH<^Bhc8DMQ-y&cLMJky!7J((tQK%yV)?pp z2i$~&qeEmLYLb1PcOTnSAPi`npt389KNEI~5(N;J zn{5@56BIy0?*PtYzjZ=K0e1`q=ujqAPqN^aLN##B8ianB7fDSM-tA;QT#3v? z2c!Or5l$dhzZG}MmNa4g4C5%tOn=n~k%P0KmUVF#>5b#yRMW01PDT)c)QobEX1xX^ zdDAl@PuR4LCkV=+>NAEUxXGG%gJGMRJwTXsDJ_kiMM#bCFqVz~nkiOY=e9^u01W<55kQbc=3mOFQ*nnvED9$X}%|Ztn;N?qhG{zv%&7qqQyczY`fpduMIjjG5 zBSVBtvXBw4v8`0dC_!SisUqrVn04#lVX<@;I&=o8fV~WuU(OLj}4Z#61;i>1BY`_CukaFmY`+j3!|vTEr2Lsnvn3=@l9 z3SX^;0LwVbS@IbIW)N_+rLV);5A>q5;zUr%A=`&Uo|p(JvaR6Y7$6pWEhDWlIowA- zGg%x6SO|IpY5|<5qcUsy0E&QrrBH!lwGYjZ9#^vnasr3(X&Na8hW0Z;pjjZ(```bi z&uNZy^V$^7Ff(mB+l&Y^Bfy7gN`~_D9O0>`TK`q9Ccv3m76$lLI@r*vj4FPTiFRb@|-$3(7VPje-l#I0MZnS8asuTc$sP#$x=0j}JI7vxz#qLuK zQ>K0FSA1QFO+ZN>Pti2cA}19<1MGt%(LC`S;Af4|+LO`ED65 zTGKaZ68Vs;zUF8iZ&ufxMQ-+68IE+~lE%aE)(bPEyayZ(<=&Z63b1SR`1E!0cxHO< zIFteWuQHbZH*-ieu43Ei-^Q4+DDkc_(^mAPxu+U+hvLUm8~-0#;z&R)grxei6Y=Fb z?2(B`tmtc?5WWKYJ&w?1UD_yR6mt=KK63*|{7W;&Lj3uhu}T)8{p=|B>qVRiA)|FS z1C%6kI=1+!$u)^}(|*UVw=*6}2sp760Up<=wXkin|3n3BVSmSDZN2<9k(M(u{Gi1y zOQmBcJYB#Nd;g5c3dBEN5Brdy{2n;JR$k}ipV8{li4YqFyfd1LJ*xwet9I~Xeaq!U zXQhFZSanlqT+@xfR>UBgRW#QbJKQoHaQ+;bc}smwx7$iVqa+KUlXf%kZndtK!}SPl z3js@Wg_5Ta0Cr?i01SOz*W__JNF&G&%R*|(J+D5jaSSB`T~XsLYJZHTK~yvx?MNBl zARPtay=aW`;X?Ae-1$t6CZh;|ia*qVB#f^w{289yHE3YUb)EIuv2)kg>~oUxN%xajqSbd<*a{pGC?pK|Lj2H+UkU-xcMvtdy zmrAyP3n4-pjr7vkBh?<|4fuV^#5m@wB(u_>CfvpqpIh`-qMq)4+D97}M3BGkV+#Q$ zm9xXJK>!u_+YI7)HEHOd-M6}sC&COkmv0&dIb~{Zjc+V^-z%F~udf#vShXz0kAPc}5uM z$Kk}I#2Sps(>i+%IFr1x@{GnW%{~t7jy4=M5^WlcQ%^9oY2tnFBT{kZd!Z={a?L`< zir4qyf*pxF3ZjjLMS)&04GO~eW<8k`u#S<&a$B6rQ-LXD6PFfoFY1(JhSBCV@M zaf(Sb33$NfGOneEOMJVv}2%LaE`{Dpu=@)I!m{?}2)+d(hl(KJP~F0z?9(8%4Q5*F*{ky?bWn&zuyf^g7;G)h<2kdjMN}{sM>)SB zN0N}V-bu@KVo+t}c#}&e#yg2|?;23Os%E^&B8a|z12z+u97!i0Rj?;j3fY~24=n;Y zAcoHUB_=Fm@su_)CcSE9bwdyzXyC@up-)qmXwI{ClB7h+gCRM_|#}E2co<*bb zkP>EyG{hZp6)^JNT3x2=D`myvCyi(Ifd1u|Tp`XJP3}*+)N2WK{)TirSB~qAh!}Sc zWCXx>%01ale?HLCBfV5~h#3JP+ng9#ebqsg3P}qtfxO(A()+e1??l~^W}??CXUOA? zEER64IM%%HQ9?wAa>?oP8x*$>I>@Jqe-V;{_!mU}lfT%hALes~A^fZCtUEV(HB};MnHO=V z1@O1}IU(pnAjQXi9JwGhb6tvORVloV2~crEE?8*zP4cr^Zb}|aya}o`R2>O}FeUxo zdt1l^OO&E>EP;Px4G{$y^~;(Z&pHqbHmrmEb2N?pU_Xf|!0T^0MPfExqj_9*Slv#a znDWMSVcM*YxiQhP7?gVHw=b547vzIgoR3EDxsIo$Pr*p#k;bKc0S6rR^L%vhDHh8p zL;5DM?;E}*sf!2+!L!{nsX#^I?fVPCI1#I?G{Y&a0K>;R-@GcqUT3_uvvH`Z4O!&* z!_T+i{R~xvbI9IcsKVH_5d!d(Hf7ODrtNoe?ny&6eT_?O{=$KU{)tSjnb!~)HZ4Rx zmZaQX=_uSj3}a))6_=N`_LW4lUo7{7!S!F?>JcAhNx4~I8K?pj@w9K1RbW4hyfhRx zB_s=&K=9uI-eg_ovnD4yzV`03I{;kUOM4J?>i%hO28+)oW=Q)7tjV(cckJw`1BD`~E&d4k0cZI&m zs9P!zHZ2feygchn%g1p|1e-E=%-w(AF386M4u2F*rA^&k^{S{(+~va-n3rW1qr+~w zI%jtyg|1X3H9l&fIC$+eX~cpC-TmhFw!-adEZiQoRzVYYaGns@@2WmQ0+*7GI{1y9 zhMR5#5j<`V9=f39QzE&G*VpD$1-2}Cg(WAjDNDhL4mGZ_p-9inYEj@+a5hpvCeW=_wXxa=GJWcoR#ej**a}`{#RNv_ zo@20k0`2M|Wkd|#Jlcs2FS}*Uu=M_(yA|+J-kZPXwREfC6TUJrlQy5#2jN+w?=hNP zT=}B@$6A9_$Qu!=2{%;Z)$OH!nnT80l=Aet^e;3rjO+ZdudLcL(;&Nnzk~nVym`_* zvTsBM*uKivax*P_PPHMGNC#NE^PiSnDb)3HftmFqo`Sk?W*)48ueuw|(plwgh5If@ za7Fl|4OOG~qy6uY%$vBgDG3y-!$MRE^O3nLTcuzJ)*^vT1tL{p5s@it{DiEpQ}h)+ zgZ;3?#zfrlGa?k_RbxApS^x)<_Dy133JLjV(qKy#)5#v;C} z4RiJjzH}d`i#N|91OY_n%+tbFy!9PGs0UkF@M?i4o(GDvBRp8MuV&&k3AH`=Vk@~# zHIY~F3^O#w;#A|anc-m{&Arfux00KNa1P38_-8prZ*mLC@{2nX1CA8m7iY@$X=t9* zN&;EtCC1n-^7wHO9WC^mnk@wzFZQPbG$Iy7wfzX8px7Ex7ohfc9p&l{B(h|HB`q%r zS-y2oWykumD(hDq4=d8%{sytk_40bBMC&Qa;rx2&Ca9Hjv1hE|7KTfz?uxkIe;v^N{< zF)C9395n)aPKTZ5wqXj2E8YwM0kUEsi^cM3R;TXbvPW+aG_%LPVf1QE1QpThmL~%Q zloPvRuGf+1^4F~z>!y?WpQH(CmU+aknMY%fiwCnWN%hP&vTZlL`HAHx|lMlL_kLx=3%?&Uy}P z-(Qozzs@Bg^&PN=bE}(WOzla41fJ3$sp>d7pMZ>=v`mZJjIZgr})iU9NhCHR-&ZJ3x@C24r6mixeZaH&pA*TSc z@`+Qgd9&w@CH#AxYbe|9KcGQom*lPVFmg>StsZ*OwGF4JJq>M7J39c@N}&ldnJzOA zi)(Cg07vEBgJ3z$07K|goTl$T@J*tax%98e`FX0Hn5XRGI(+Y45-sObz6zSc+3rd9&#kaEMA9Z-9;wb%t?N z=WqHoSOLcAaGIPJrz|Pmc{xO<R^wmk14_7b)7y^kO6!up9-e_=~6}fl@hCqhq@$ES2X~|= z%B0r8Dy`Y^!GH6d)T3r4gmGDy~MOUxS|dD}JhpnGy=7eybZOAtaW{09@4%v7rhP zv*}zqk{Ty+s+(o0+Ns(dp8AJAr41?7b)}N4*8&J|t5#0{7*TWCa1v`N)1@smiM49B zrI?ZpndvU7E#RaQYfUOlq=!XTVqx`k4V!Wo4R2T&9>)7SIrE zrUlF@5jp`Iq?1Uh&HP!eMI>WOr95!XTkz^kT93=Wni43XJ0T$z9a1ZH6`7)DVH}a% z!*Es=U6gkCa9wdbWr}EPZ;!X0ej%pxV5msmyD#s;m}8hnJ;= zUp}!^th5?wD6AvFj|!R!sa=#t70BvK5a}PQ0H9F^k02|U?oYz1B#Fl^v0%omO33O< zgzWxA$o_VOEFQbXs-mod7t1!)LSpPLgeN*Sl&t5W#tNo*EWB#0>MdQ=7v*Qwv6!sg zm0T<|s%IX{ycVj5YG0YC{;+N8cxcJa3{li48^wmI*eX7HysDj$?DN`&G6yRYSjt{1 zp)TBRRLziE5ycgkJm?|$foQl~&`V{2y%dRnuaHI>(EN2k|H2ze{9Ums09}FyB!Wev zg46;W2qA#k34jGp#go%On)R)w6ePR2u83ShTj1D?hrg2ttHJqypjG}v&-^s^%*=4P zewsW3{|d}qv-|90nzsV9#?wHnl^V3$VIq68T27dg=JY)1hXjm0%S-O7{VD)4KwVf- ziB-y!CW66W8W2h}8Wf}Hc+G+Ujm8SF0;B;4t>x|e7P6-sDHNxoqt zTk{dNmh3e;n-aDwR%GkU8nRFT6abTQvD0k85ZMxcK>(eKcRa7oNfW>oRF@G09^sB& zp@*wt$^)uRBQ1V;y@stt2&V_WDxowGPEo{pVgiTZBh%y#l*6z#HVtPG#D#&>xh-YD zZM#ZX5xY%NxD|a`1H|lLc`84=gTs&uJ$jv98;}BkuVgJ|+9JiMiYY*g!qr!*Ye6g9 zvaomux9W*LwtvoNi>j7Zl-!fj7tYNxX>yTYskh1 z34nsDx}aM=la4#&o>mEf-$BTdU((N!D;Bh*o&gB9AtbhUYpTlRI*4|$%R!85G0eDHE}fg>#<@hs6o}Ve zxy0W$K{DXAPHOBa*jgM^Kn*3;!m7S3S>VJTwxH}`yQz+{lB%Lhal97KCh~3 zMpg5*s&y=)YpxauJ^QserBSS`>Y&hwi(2*%GpkE;QSv z(y8cbUR(3Qx~49$3a{F#=IY&$>x#PUDzDn>&Z_=srK`8lt7`2k;n;ow_^M=}uYLhu z?t1`0{Hud5pY;zyva_zOtBQ8Eg>66j?e3!32A;6qDwOYS^jfhF0T=5fs=$V6N@x+F z!8r`J0*D~Of)^?5p=Ar&IpP=g#c-Kl$}KC_YUR70!z?o1oD2%)ZR2HhE*S;r5>s?i ziCVy`paN-8sE>Nmdbc|36u`oUx_K)C>+U+Evh6mzO4K2V=htL>!ddeS1flJs0o?7y zo3rk$Naq{-rK-7{%P+F+;+K7`lS<6?v4O25E5G`#mMx?E%-*TRt2ArghP$?`vg_BL zs!eUGs+h8(PyqEB+lHL8t*V70&^Z4B_gd0;uW$f6Yrq0vAnVjSvgV{FtE#KMHa3z? z6?;Rxukq{aIKLv9_G>DHzy1sQD;%KF`mf7u0Glqpo*VDin>Mk#YOC10xH7PLYuJ1A zj=hNM1gq*=uxT&KyY_0Z{$H!b!QxqEl}1teF}!}(=NcH|y+o|uTUgP&E3bR2r}1et zFOz#`xwjadP80h1pMe1tgAq!ZWgmy=uCX&}pKJqpl7*q!>i7D!ex(w5gnw!T;gz_aGaADvBEDcI%S4RYmDyQTy6>6~%*scPggbEdojF?JL(K6=@ zSyf7q6BSVy6C;EHf($&n<1h;>sY7MD?Ai4?=s7=MaU;z^lY&0&J+fKb*kh7IZRI zoc&h?^HI73WWtz$1&x*2*0n~V=~2Qk2%!LJ;5cFiq=AUMoc^sxJOIG;9` z?xVB5luFNhEdAfI*?(8Ma`Qt(n!CqxQqw6G!S#c5o8 z0p9RRdYd|@-DwQ=Qe( zM3_fq7YnA4#+!?7!MRu1VJzbYhDvHjOyeRerxlJX?gr-}d!?a}(smH-iL4}phfJ@C#&D_@u?ZK;f?&yH81(LY-S2u~rc zZ+!SNwI*%lF7lDSrZO`D1axt*&{I}G-;6U18q)Pev)El~>` z8?|F8?vT_{wM%XG()(h!s{{4RDtQF1lJJXu7QcU(fzT5uzlWHuWXyaD^rwIA*lnW`1AH#ZTc1`R;)jo&51_Zy z0C}?F2Qioim_~7yC+tv9G2>-3uonM})kK_CzPp*y1L$D42xo}QJhYr;6P{c&_GSDP zXp|?HnBq`ZlD(*sTG?Mwm`Rq|6Y$7OsunWBFBwd#8IQx%up%D_#-vJsOfCzso6Mxv}(~JfL zZBnxjum`-BNvv$?28>~1^0tm2$)0mGoK&v_!#^_u)8aG;eS4xME{k$aY~!2qWC_5y{CWi* z8d&!{OvHTPv(L~;wnXAH>{C8_VCSOwovq%IpyUyuC07jlc1`TA7G_aB{*J!GiJs&qhvICWL#IyRc=mx07 z&(4$S*#=k(TbNggFq^nl^0wSBHI%J~2jeb7L*US;c{g?V7DRJuSzi;?DX ze2T%f&}8Qe?Ff$q;PNhE8sN|prL1`6Wy_D}{rq%x&o1;)EJG7a6J3IB;f zv>dSP0kmO5KzlspcYJi~5i3&Ac+DMssbSCnnB^dVIbA8zH(3^U2IpD!0!drTZ?WD& zNo&xUw5veb<`kW@0`N&=8-LCueM42!ZvlA*dY;mEKq|dTvxu(r>ugEO(wX$in@U@G za2RKmL)_0j*(ydfVO!UqcyKzeOoEpPupqWue?}{16dw zAwY}K9qQ|eg*i`Cvl4ADIME|v>S#1E)Xvba-b&f-w0*JvQfrvS5>`3R1Ho?8VVh{vFyZy~YtN}cc+ghzag(Y1( zTz~7qq=J%EQs&Io>RE7oib1DIYN|YHmTG{99EhjQYSU74)B^_1;9R)@;aWlsLX{IL(vmWyBsjkgeUY9-4US6RWKDjKVQ-D@>@+7XwmNF2~9*h%waU~H?AEt z>2gqW=Q+%f3Q1>N=v;^m)tS-ahjjHTxd#-|%bsXf(>;6DGcfICRU3LWKyp6=0eiry zGH!&{d9_%uSCiKL;+2MAZU%cA{Twe>!K-y^Z9Bu(yLBQ%TL*l$H3W=Xr@m`730)_r z(DgD4oy7Uj12aTiYdF__bqdWdH`hz_u=0UzT_RC+4KO>FKPbKIFEhotbOyak?@|?K zy=+S#H288vEK0x9q%;Su1GLw*#xJc~@5@L=CMNrS2hF2VzU5L2itGxM4!(<2{1R`HesZG7dOT&bPwHk-vL=K!aBC!=oUAbZo8j0 z?LZ}pwX@E!U2c2-#_^XZ=6{I|A;qN3m8Dzs=kxVq)gMA#Qe%Hf339vV{c*4$WC#9< z5dR93BAMsf=isE_<3$G;fp`Y=b@zen=A;w0;l{BM(Nfsf0f)&H@R+f@la&0KytDLVyK`u}=UKa5ZoXl<*l$V*~-~_uFts?2gnPjb?=80P!~`q<((^ z)zkN|NjMEtKmq`N3!$s<5sU;70pF1;+7+0=oX`T^fF}W#DEX707{i?KvS0+i1^?Ld zXG)m?OxJqrpkf;#IO|+~9S~5dDkVYO&%Bf>bteE|r3G-1m^HgJhK8#)gft+ZER|l& zGt}S-E>8Tb3Z4?$^Kn8{mxH>4#|Y_}hxPAzT2bf{K7vzSA~*|fu(;r201U3+%-~9B z6JUeSYdQFsNOdMSOZX4I2B!o}fb*nmaNylD@wYLE5+eZ`;5=;s61Xs`y}@-=o)BIM z>q|yB)tQ9<4;?rYu0A^9M{g8P`u0-mtrcESVBxET7VZ#m;jxq#PR;b-+SeEc`X!(vxW*zlWe!OxMqT%ZY(N5-vn#6;;RHFhWq>( zviO)$jGx0e#?}}#WhA>e*s9yb3YA$!MHF3{czEw%Ehvaz>jz$fyA&X}LJ7>pp_PLM zib|N{RaYNA2NdJCcuJrGq~kW97nY4{<3m?yQg_i33a)-|dN2n##@9Lrhylzmy5&V_ zD}Kj5&WrC3sde3jZn<7!fk2>BP#M@XbybWnlgGls)G)u!y~IAA0@o9i^^3DG`Bijn z6w1Lt;0guQi$?@-iz&r71XKZ+P1KM8q(;FJU??k|;3GIbzJhDpN@zgtg)L1Wpv=OG z(r7-=98r#gyzzKF%am*4pwI~!Bfv{W@ieTuD4~j_YJtG8>9cnjGg>iC-JYa3;DXw%Pp( z=p+nkk6m7|#m9L4w$P3GDy8}tCTbq2u2u?-#zlMUfvOu<({M(la|9w zA4xQse2M`uQ!ul*tO3lppAg(;e*(dBc{AV|CIdzTbkGYPR?WaL9BYIv&+wI#=0_C& z00$uA5^extA7I<$7CSL4EXQueSFS!E4GtAlzHSRP<5z>@PziU0Ps0mAj2gxG8qOBG z_zBzDi znr9HxiE%Cmc&+NAg7?SzOn9~sj1|ueWq2yifvW)AG^7C}%nZ({r$`xRqd{&69&Jg) z@VGd9kI$#=EJVttcTwChKTHmvo^tx04o#$@clskGdXfzMa3F3iIOPo~QOutP#Q1QG zAe{E8Je5Ut78AxyxtzWo7iOz*4-thD-zn(v&4MQ12QZe*NY0?nxAMKvMBgNb4tg?( z$(khLc>yQGy`6!PSa{#yw>Le0_X+0rG|ZAOL-aTM?SAjy{kKB#f7{=?aZQ(hI|0D@ zu0DUS-vRjaWCal51~~tXfJ4G@xC0)nXCDl>FlvEs!i=ZKRZ6Z$%gmEH7Q0OoWaoOdakpPUAGs8h4Ifzit@yu}W%o~E%8a$i2*?bTRAeeH~XZoyiJM_5d zE*V~lkLhXnXf6XJ06+rqm!^{{X#2RUbnTb)1IS>+bM zZfS4vLQuH{zyMu94{!o-0WiQSSmi=j&QsM(Dc4=PZ3}Rv4Knk1#S3XPgO7tKmxSz!UvTo52*sLQl-t2S(>*prtLdddM$XRDFBdg#UHg~DN*WO3OjEp z2_IDcy4jYRez?ld?4>};PL!o6z!`7vRiiGD341rl@wWpVZ^x_YVX4j6$D8pKb7Z44 z!mCCqU%Ht7rOx}zpcxgWa-~Nry>jv6`$PK9l9p_In!7SY+S-z$oc$CTW&pH!kX~My zS7Zafo|6}?8UsMHFOl!67#OPQ#(M~l_nz^dugW>uy6Nl~>q4j7r*ZnBo{pcW0dDx7 z5@?L*xU^+%9mTcxDq{@?a;0>H1I3;Y_{w59Is(ZF=cMs2yaBJ8B& zveA^@O9ap0788*5Je5_79uEwP@}YcWGo4?qGXrjFi$b*c!@yCQBggmy9B|Rj0hg;Q z56pq{td$txPzgKeRtf;ni{%vvL4R5q^xHgZWsCNf0DZ<3!UOc7xmBdhv-8gUnbLad z3l+{gk3Zy3(iS}bogWJ#{bImKl=RzVKYz$U^bP&E;U3Kl06j<#(>L^f`AiQ%ne@C4 zKwqG52a@|vu2e`oF~ViwP;q$~I=UsFI#j&;$s*9B)VFRL_L|bnxh~FmLS}&w8O41Y7|CgL_1d2j~y^zY$13DQ|%i5Y+av_hR*pn{ z6^tWM9jVjOG@fmpqYf1h^mo2Ay-U-$Qs106^+USWtlV2g`?W1@R;UCz01f`xcMVd&_Wrdp zJ&kvHuY@9a^!Rv>1Gx9A#8>a6i}xf0#KAeB%m-$=%nlA~dEAMuY>5gyo7OsAl3@anv5I|IF zPGZ(vr^e29tWXfTnMsfaubK1bmzsN^P?cr7sBBcGWBRg@8$PUP zTO)i5u$y+YB779%8}_CwKu0?)H@!pthOoFY@15&yY68^yKESR2z(P>nGlvtxTPchU z@eoJorF(CP&%!>vaRc=#x-~W;D^$LV@)m55v?VZ!_P*!=3;1#pac41|9ijO z2GIJrezYIJFZ*43^X}|J`_lfmY3n;r)_!E8U(bhnJY(n@tSBKvp}8$k0<`#*mYhx1#@gG{gb?AQD~Kh@Rs2mMvb)35DE5k)_6 z&%*Ni#${#fwY#tyG4MJY=fvo4+V1i*T~~k43IcG3a!p6m|JC~!wPzTNygbD?)EZ>f z>d%+(fY_`xE^Ag)|9a5c3>Z?3qpk1$Q6mz``|qvuW3~ujV?Wn#^Lzd5C9_{??fhgv z6V3Aj{n5MQO8F;2gG}2mP6ziNzTeLoZjC)0zW;>NU3SJkdDOM_Cd)nO}?U}%#_p|)@D5l@{qq$e<-`no4u0;k4`}(V}8Y={q z0)*=k$?zGR`;IF07c#}=FK-3)68CNX%6)Oark@L|RTZw{j3v4}SyI21-xF(7<&W}= z$*OX6RKH8#wD0~Gud*ZP-wHbnzq-z)2JZ!{D(sl=E^!F6@|@nHoCnN1r>p>ZQc?h) zl(|ZpM8+xXh={}kBrB6f5g-bH0;uamHnJu6fdU)D;LWqRa>doJ5(_)2o|Msm4<#0u z8Zcq@P;@jVjQ)TrUK!2;h zBn}7w!)5vt`^5p1E~39`U+WJI*ihgmBn*gtCoa4mVQE4@Fp&Y40clq{ufLX>Dp5s) zBLw~|E-dt^X_$?QPb3H&?XC5U0OW(zQQu2P76XiLnWGS9i7ts8G+~1>OgRAzcIs<)~k<8r=&J3r(H2}10ZqPc(?v)l0X3PY=MKG|7 zK*rH#@r!71B_lkR(qw&+9}vfJ_{3>8E)Zbt5C69dWEfPvc7X&ulv^!>u<=+Ru*3uB zfvgiG0D4Y+1dehAni^n%vcMDoE%1M(vAP9@Rp>hYG;m+yU23OxxSNW z;KtVpdT?puj3=q1-53vKb5cim^=%B8UuwY$!L7;EcBvT#Y2)~1HWLm}&SaA0LC|qP z23UQ@iPyp;PR7HOE2n7)URXhb*qDr{G3W!p#2u@SUfewAi9U`Wm~E+Lv6og-IJ)1Q z-655wHd$o}0lom44NU@Qs#XxpifsH${7xqmu|OzlHDVmG132^Yg4KqnNg}9=RT>0i zp$6v$05~<&ehZJ~8pLauOpY;-jTk_+#AaX{RBRjvfq#fR&ft2X6@(eA3^LKwfM&nZ zpRl7dAnZ#42&sU5z&>7Icknw1mf~0uFzSGHtm+^p4i9+l$_$19x_qudM@Z}sUX}C{ zqR{@(OXI+ggmEDtR(Eliux3CZskej>LjmWa0}vMIbjU385@5lIE`f*rv$zPcrf5g6 zB9_B1m-LVuHJuE8QsW45iHQZgK^^%Tpg=xqH-xX15=#5m|G~)N29GfgE~kgIOw!~2lR9M&|F|}zNWl+vn2FM{u24j90 z7xf?$O*}{k@C{W5se->agj{T7ydoP5Vpv+#XDNUaA@EPwaTm-InoRbBO{p-Aaw>ku zEttbGhqQ!5xfK<2&+3(U+R$VUd>uEEI{^4A~6QaT0J?LQ3wo%JsuR8cEWXLfR zU}ifh&{U}{AH*(n7Sh#3H^85GVT>wqhsdi0mSHG^?ZUamyO7xihgu~-OqMT0wGGz0 zhz`Kc0vOs09cK8#zTj}_X|+ngNcb~C8f28k1qF{aS2nqLr~_pKJHk@KMnOg>YRVAi z34=eM70Ha!#I2VfD7(Z3BvghJt{mO#I3Od$ZouM{83PvG2AECxF+9l4B`HLE_A20? zk_p+D>4FTJPI^`3LW0ulk5u%v0{2C|fP;?%u@~_N?q|ybNjV77SP(*{oP;p$v{VW6 zRO$|OM=ypSSFjn#k^3A}8$vqE6}<%}(ET>G(+c{-qIV6y_rT16BIX&ungJxlVH-N! zhlTBlg`!gk%6I}?RIL=@tU+EPIBe4(2pwFhxg81xk4w-exOi|Apap`Cs$6R2HJ4bJ z5PXurDl)>0$3vlA5+DTjoB(tHaDYMCPJuc{Vp61dRK6272_a#k?qV|Ps>*$4(s+=< zn;AW&3n9qD=?StXg!D0C*|2OJ*yZsjc^BSgZ!H91*{CX#jByyW=+ap)x?3UkZ|G8P zD9hvxlLsceQIr7YdAMch1;VSShb{n@USCfo0F^uMISp6>-@?rtk&l<8i{sPi5A+t7 zLayP|Z6uKLXc3{s#CQv=Y|HyFGU%M)0uY26Oj{RgkN`|?;Rj$1oDB&EG_#J?wEzV$ zKa^NGXDmL4s{&#_3l#D$5r2$7{D=BOi~)v=ZfGwMYF%pPheEBAmM!ja08vOTe6=nJ zcnDlp-7rZ7wYqW$wmiR#q+Fic2;`y39+7JD)xs@A1O zN|FY!w21LEh~qHN01PoI2c2mn1_)&%pTp4M2>^(Q|8r@rO#W}px&d7FBzf~dlq2#0 z#A<;dxrstc1YmM-(TN`%20DO2AtXWuvFb<|cpt_Bp(uM+7jYd_5FjO-5iuKSgBqe3 zuV+F*qyy{`Wr%o01fj%GX+TD_Fxy6RA-wsZ>w<~NDGnlQz=ODKf+k83>WBTi+@8ZJe^Ylcnn_-~UNXE>kSs9>cuh1Q z?hf>c*F;s9Byl+Q!0X}Q6=V>{!x7!!u*~A*VJKX#K353BnNltxplA^SD9TI7hw>5{ zVs%g%H;_YZmGe|x8^uTptm#q%w1@?68u~$ZL%m_yVavt5iaoIr?uLdy^cWovTRtP}Yd)2t&D1IKSfYiKI(GZ1;n3!qesV-WHK)iV3drPS3FM%~JuEJZ_F-4k4>+p4{ zAtfwTkN|doB|s4%3qa7K3|bY*0`$VYp21=cz{%Szc=DpY(N0x(_=u3DGGClZSHvf8K)VQHWN=j`hasimOAam-I=9AOX~6Nwu&JeWiiiN)TxA z+o=k+v3gutL3$Qw5!U24y!(+BBVAp=uV6Fq8F=mz3*P-ggUK!vAhK?-fm(9|F#H~U zGPaZ=r4Jw>O_~Pk-+nv2MdA-gOj{M{`j^NEc!1fKos>d=toD;qrLYz^RyiRh)C0|N zw#3ohDG$j-#VIe$79a)tn7(s~Alk)Xae&f5t5OsZp<|{im>_6swJ2I#kMR~) zcoGvAo_{Gt+w}jka>}fJK8Dl zk?5SE=3NW$SW^S|)s;`9#c{%Wy%wDqECAA#Y4KOl*TQ=d2T51Nvoi&SkU40~i)o0Z zAX{X`(BkI-!PQ>8FV4AGg72-`fH7|d2(w@U$c++O!?CKE{-o<6qDvlvLM)8vg0Rm@ z?}TX43ohQbs*4%ACZST%B}kW;1p*kc05wG0Ac_bumryh^F5wn~_&*F?u4>CwsuD|K zTY6O5xGvls&08}(=rUdszl$$LzT&8hrHCHWOjQv860#BPAvV#&haW`tc?RKKtAtvN zn8GeJ1Sl)yR#ZRJW7R0?b?665e79Rvk{So{pO4SNU*LNLqMRt|JD zR=l8c3aT++#LCiQ8|(r66d_wEfLNfFu@+d%Dh^u994bpG>!Ff}#~5z8kKzARRYN_9 zO7Bk7pfAia!U04ZYeJSr(&Nu?f7wfbuk=AcMpzb9D~%HQI<0y1%u2bF%o;ig-QXV4 zXe9tRPHsgaL$5J3xE_<^;2C`Ydd3?dXo}mYA3{1I>2Oq~gmPYS0KT$0xil_(Izvx| zESAXR`q#ia{+%;6J_)Te1Ennd2OXjvCg{t!fss(y z_!rQXUO0VX2y!X~hr-m)qVj=S3*@H(xY*LOp5`sysA>eiK(9gjYzBtnY>YiMKn;~Di6AWd% zE&DkBOJfM~P2R;Te7tParEe$wMoyQv^=rMXQdc*>h9{Yuw!Z3~8v1jDA;VA_l zjSI1{I3tDazj3J{`Nh1(fl{VMRNI1^K?e9vP?{k|SlIEZQ)^NU|jASPha5umu>_ zwcn-yb2zjCfhxf@h4HHO<_-wZ#aaSo&>9CBEHd!>RCM(Y(l1Bi!r_Ucbc)yl zFHAm&*dbgvKduLP1;P%nTmW)rU;=RLwWVs1oXABaL#`2-iA2b4BBO*dfK#NUg*2y% zEXxHT>4X2fL}8bYk%*hh>_HNNIo*et0&4DVK!fzl(Z@bF`M6PJiE9&RiCps$`AAl> zNP=6CV1d{txdEIN_kOCB17uc^O9%FYXNe#ikkmd@Ar=z-2p`M^l};*<+&)VnP-R!> zTk;xiBO{QJK~IqCf(U8fy3|mNXa#&meAGuPtvKE~@QA%giW9CeWa3a`2&oXt^=j5x z?7ooz>*Eff2S5S*1lWVCm2_M@Ptlf-EJCse&2{jqI21n;#bVv_fAMuhJ)NOrfq!M= zF@Rt)G6+={1IdEqL2?AiI>g6;A^`@$$hk%CkR8cPLDNwOR*W@B7-UJZg}`C?H*H4 zY1Gg=dbuN2kZrmH8Yxbz6O)`f;o0JCy2F zCZ%BMf=$XiBReFXo6oJmXmFkv4cLw@DbX>E&GihYFy^`BglJFc2-PDseD$(=R=u$v za1yM?)#HqK^=5k?uCbni=+Q`+17}E@<_pfSSX;D>TB!U03&34GjT}MT);R;0K`u#f zoDMoIHVp)ege6IZPh=2%_dZm)#-iS7MVALbaqKmvFkE1{ksc!fedsV03oPUWhQ7rH zQ?>&2lerbzC%V2k{EIl?+ANV+EKQ)M(xeAq!DOZc8x6=^gKJqU_lE+0f?^iA!gssK=cBY*`2-@u-1JKm>iJ}|0$5G`=T<1h&v#QP|E z9ZoXe+`WNtIRrEF-A$?xcij)=2`%I8u*PQKC?+ zV$l7b$T+cz2r>~6_a!X<}ki; zm6IPKnC<|6m0^T0LMDHe$;dn6vPppW4U;n_+Wv~FE___Hg+19HyFMcO!j(dtAr8FK zpV*9iMj9Z^UDL=qpkN9c+4Vz6vJTOauEB34Ah6pvj(q#A|4M$SfoIoV%di!^$_ncJ zj$WuQqG5HA37PX~0y?`ukQbGVq@2w7^g38Bc?`({bdGhQQ|kkHF{ERyv9@E<9Jik~ zj-rCGbZbfe8d_Qr1>~k-DA+4J{^@GcEhiSP+)3x;r9KQu;{W&#g_O2rnD8OTo!mZ( zE7k*`n|~s~pcuyrl3AJx&ym{5_8>P>8R;4%bv$2We@DNCVEWGE74JKIO$`s0aX$sX zTI^x;?1F5OAcI$hEU+NNvYI7>1TUD()^_GflUWV$3rXP`ILs{tT&jz)uX$I;D(5voA{!+m{$S2hHh6(t z>t(g}mRd{g?Il-=ozvj#6WZTVL7_+;GAram!IMIalHUzOchoui$p?6 zWhA|lQZNIkdS$Ox8(y&9f&tGAu&?=Zv>wreC(Bf!zw&@)jJ)=3I$|AH%TXfKN~2(} zsLaGTfS3Of%fTv;Bj{5i?;tf?M>Ztek$Q^`SHfsGNU1VYN(YyUj}LUE(nx;^ zVf0^$#eQOMv5VFiQmgorbYnqj+GB`A2$$)og&BuDN|x)AlF+;+Rdp~OSC*_*ar)Ac zIz3cOB4{OL2<&hrCqrD6szLNSMkd`qI$NCxC^ z<=8v!8TIUv?vb8JP;wiokh>R-^K6aUI1HI8FCjAW2&$wD225;*oF7gBJ1M1HCEWf7 z7O)ukfR(MUvfAitSZquP4V1{u=5a_z#?z1G|0sEx#nKgzGK`lkfXb~gK^Uz^ET$)j zn@GP(GPyDTJh}rC!@{Jlr8FSpU@^sNSo01snh| z_|6+Pkyy@k#m7Jgpk~OG+=Ph;ai)t$K9K53#y~058uOZM%Ydb3Km~;DpfebT=){NI z#e-u~nel?@GqW944_ZRa0D*VPY&|(G!oJ%DWzf# z-7i0R`AcSAVX>5F!gL8-uBHY+0snBYj3X0SAmMW)Z z0aS3!wQzHDO<`VKcrIkcjq%E5=bDV676S%zO9dD4=P))ITWUte7d0`}UU4*YDOK~K)RMc{f@$zG3sm6v_GZwUzk`=BJMh2;q zzRFRAVE`f7HQMOx0Fuflz!kvXrmeVBS`1bIRZSh2f6J`_7B1=0`CrUylJ(p*K*5%R ze{1MSew1&jLL|q3R4kkh?t;)ZJw_wSnba_l z5weRsi5r4rflmP^Py?6&Yzm~CvLS&+_DWsEGf4k23lW!h4+#MP?U{kc{5L5&G80Z8 zXiW~Izyz7rA?x8^IPrjrp43%4Ai2qY7yQOk8y zx?^tRmN>T~-~h{UYM?Wa5mq<7ZM%v!#=L;MY2KvH1^(m%j!RmCcW%9z72$6Jr&5`h zll&N8b2+dQ^lX+JB11R9W5JS$#0lH$Yh__jn&HhemrG$MRp8oeh82Z)o4BM(XW)jA zTIpvLGSiww$}s@Nk!sk1Ojy#q9$5^_yPv~Se3x0YE%N7pD&fir1j2Ier%?%goh`MT zNX@I}+7iDc0DRy9R>COnff7`1?xfNukTTf{*Bqjc65TlPjtLaRrTJGlSG|_P$ImMZ zfalC}zWTJ21_mrnze4$e%SbFRwBRT{OAFEIGVsM#Bw4*Lg_d)`@SaPcwu#$BKXy6+ zmboAjlW#MDX&?Odb-Xfv&rAV~*HU#sWd3H0P!d z3CXv7yZ91H3H7cJmd9X(mG9cc{0pit9+mM+_QjO~=qU}z2sL5_FFGfI0b&r`BpG-* z3=HOmkw)1gu0T+8aY{N*ov2GpAL7eZCw~nvk(UXr3`n2WktKC3@hh(S$HAP&8y#dRNZgvi=MwNbCTzf@C(;uIh+gxkRJw#Gv?XVeSxh*= zfq-OH_R4eyG*4?`zo(_t@)8NJbPeLtMx8-9T0+3!^m2P>;%z?0ffEk@iv=yYso{CY zG36+Z4Xy_le5|qv?P5pSBfXaNu?yD%3n|%@%VFN6M4M=U9_Ei2m7p?`l@HK6aJUiz5&LjX9I>F4Cz@NuKP19dkP+A*m0>7RXBKM~!a1#d#3>P&XQH~81Q(*Op+LQ{MU)~LV zimbU7QK~T{NY;d8nFMozXu3|IRFTyQ49o$x4OLFVz-Je)YmN1+dSay(x1ZuFwI%qI z&6%gtEusWdfauTpr}~o{$o_0w@(Q|wD#1&QIMC$S^U1PANHQK_N08+@5Lq)!aR;I= zFM{7Hd*C@xV2}?S7dS!VpP;h+r?{~HnaF&5h5#m(RT0Qw`HE#(vXp8i4V8|JP)r%x z#@iD48+gJjVV>4VVqC=wd-e1H3KoDT zhad@uS!G#ekB`$b!iyyUNOziR}#l0cwm$fN!YAo!jpPr zdCUL#_Oz5?Kt)6=Pu`u3zypc^jjg%M<}=kwz2%_t4iMTpDOv(!iWinzAn#Mel?YmV z&I%|-o;>P`GzaehR2)6w9e9=gqM8;_YLSWcY(%mjY*7#?CX=Sn0y<-OhV}q9pwiF| z=m8W2ngD$@R>4T16A97QHnbaBy99@ZxeAq03EvPoG|n?jL;;*b7mWT%U=BMp2nyeV zhoZ-(3|$Z z`2>2}2AUE<66N>9pU^qaX$aD5(2;etH#ig?Q0w*AJmC8mi1`DxubDRyj{))X?ks z7M(+tO2Q4G0nA%QW+P*MvLO+_7;h^9p1=+%^5!dKU)M@>^H@FP-M%}j)fDodr0TT^LPcAN^{I1Lzg_q)fA^5!`+gX_r@ zo8(MCCLqZ4MtKt?b=35lXps#a{)C~Ba+WX9I0SEUq)iYFmyC`GFeM#-WJzH=zzf(; zk*7O!EQrDs(29+F#>`UFtNY~1W0c7b{A7G4LQSAdB|s<}e;CSu0EjY-sGU>+@LdB@ zs6hEM7&ZV6D`V|J-vos~odz493)Y3M;gR92SYI@Ma8y|gKLM{PsbSfGk{+9qI~cam zN6jD#0~rWxL`o}yI2ti&+XQ@|2$_bw8$fjFnR4KUu`t6g>d9bN)=MuBy2_9tq0&!_ zpZ$v5XW_F)X?qds1aCUeFvgY!CDQdw{mcyzv|--i6q=A|r98Kr1IHbelBQP1DDXq>a0 z*&DJ+K_P3Ez*&WD+4D9_XFMC8XW*N5sfd9-W169t5*Mlsg&7k-xM2o>x;dC?w=6^u zQtejuLSgC|hyi#*jXVIFB!o~R9f)FRj_Ak8LmxEPg~cF3Ku{we<+~52!nDL z5YqM6|7ONk45H86q{0n=DJ9~brgd|wp_;k@G^Xeu0HXPY|0V3q8I%@ErsT3JL(kyC z%DiE7FuHg=S^?{PBYAQer*-!IDwU6d-~#MVW4Ix@Rnb@0qp~;}j1gmTDXZ zLaDSuTHZ8;)(Xn5O;wOe1%cC{9ha(2 z{WI3MQPHx1Vrnm7m_|%jeGSu^kHoZjgK9vbO$6m$788)fdh}D1G1VV1NA?A4r`24_ z;&HIx(w**OraV=im`}LjKyW`xjZ)W+Rm;+~Q*J80R4nb8Bmf|%1ySvk>~vO>WILU* zNK*pfvhmvYv?I_t6{4h1v1{_P_37x;c1rxYmr2*+RM|DwX|~i__VlB!=}&2=;!^i1 z@@!jnU6Y??*F;nO(}P9>^&oa=d7$DLuRmDR)7rM?p+y~N15kttcv{LCp}@>q)>^Tk zrag3KoC(rTh@wL?oO$yw#_Fee4q@5>wS77llGto}vTJ?CN!yAsOyfN*r2R^nmDx<06xbL%IP6!Oj5}gp(u7)C{?hANA098QvEYj zfGSvXr;-{;HKnouD5<_r)wEG5G%doTPFKxtIw2akQO&9n<|2o1rrA_@`BbL@67!byG$|>SR#_ zC@2T&2a}80`8bfGIBD3ZBLEyKYvpo=Os$xd(e$R0(-qnSl?T8BV4ePL%%~Ps(`gNL z#}q=9uQWk+M@T&K!5zV;+7Ni<(b0&icu1o`bj46LBFYbV6|MlmlL%K0fZ3!{rJA`# zTQ^34R@!0iufZH6re4olH{%xmf$ikrkxdeU4cztsVO27~SoQ1C+4+&KIL@kR)wQa@ z08O*gx*OQg@+VZZflvwHm&Oxq@+?%Fsi3rHszfOo^h@>6WL57e+Y6^@>t><4Rq`oG zQ-NrGwVZ10RDp^ga+U_R3ag)*45~1#^2LfN7<^D42RfO$94p1)SEXo6B>;qc?u=VQ z%s_>zJ7A%fSZ1Xe)wL-<=J~UVkt@9!=%!-FYFrDp^gS?o_)7t()#y!c)-kIQ$E6SK~$6Q_lcPpnKXYwUz=_wNv8L^I56%Z@RoO zpQ2BfrR7!cl8LP&&_i8+!BkafK~#Sl5j6>NkZiC{RUE7=00%4MRE+9hC8O?9W2(VI zH7e=UxoTY{u=YxU04o-F6^PY$a$tq5!mBc;Q#7yAwKTaJUVW%)PO}B=9n0$eRDl{n z)s|LEw+!b~7OVZ#yV@<)ur^mOsx;QPUwpN9s_87SQb+-8DS;kpiea$@r#S&2ecm`n zr8{BXM%seTld>8^kY_zq`xxp>nAqeIYLNhXTDOn|DOGfjH$Gcv?SmXB0;@v{VSuoOwnqA&})una@(6hb?RBO*ft?1m2_CWY|EKTb5M4Z# zolCf8=SR}y2<>bcN;^#m)lQz7X-Mp$?QE2?h`gPIFL&Rf_1iS=q^Lex&z*hCE7)Un zG$3K21MKU7NH>5@L1olmhahta=me5q;enBiF(N$B6KH-NzY=z((Ri!8RfcpLH7TV= zaWaI4*63~qBXXEw6`T-MY*_xKgpwlu#U*2@QNp}J$>ysk8>Pwgb+=sSL7`D~M!qw!;B7HAO z*eGmJgu$6dfjpyFnqX{P4N3_mNKk5K+Z1x8T`63B2{eF{>&VqVqjCkhR!t+WzJwY; z|JvKU{^)}+*KE#2><|a0000FfW`oqK%g)NNH9<|+ODL4#p@x!@d^N7 z02D6t5O)AEz#3rN%1Lnzd|Pz|;no@wxs~xodD~*PpVSXDfOTsS$zT^AfVa+DZ?Cx5 zM@+r76moA}jpkcZXDzTKK&J-7MsTgV<`RysBv*zji!|!mHh|;I)vT^jopPksRUNrx zE4LjjT%-LbUP`z@`=uO|KuIQG0Fnuo08AkDrph>e=|*!1u`)1{jm$R+vfGi--h`v@ zuM1Rh^kg^r3!CA;Sa!-$mz~0(IT|Z?j?U}`V1*>=sPfG^swFGc9l*Au5HO(K1Wag9 z0rO@Mg{U!Jut`k=1-qhe6RYqsaU?Pky^6;taZ=%l6|{7k2Sos>D|>0iCLRC+97(MJ zTcw>%dvpRDLQr&KGXFTcGW)3SVpBi@(2s7F(4!K=jzF{NH*m7?Dglr#HDG|=RL-W+ zfG%*Y9a>;XZiC2%Hnpc$d8wWhX5upBQM!x{;MpJ+z{{x4v`e!xPKvedVCo;`9)3l% zu(!5@X*?;o*B7FTY+-9YMN;PsYe7v~n32mo0l1klgAG~_z;iJWLIccU|AXkY!A1|j zP*`M0&zMNd80L+jjd)-S0H>h~X<=Fbw+BP)7T~Tl*boGC|!6C;W;qu8+?EV#PJqkwaC*GD|_Rxe+B|PeumN1Biy9 z5%Nh)3i(&o%;L&5)0&0WY;5YwRw zX&E3Sd^5tCD3z3&DhfqGHu9zal(<0FL*^QZaIM6GPBoC&0N~gy2RAdogBV((oso?G z*WzVoNit}oKrYBQ)Riy|)al|{J>lkI@G7XR*m&4;25`zNx+h7{o_J0t_mWiV<*F}@ zx!#r5PBz(B>Zc|ln-x-lMX26OH`pTFEu`s+KqCRfWXGqTobeeR*65;-NTuy*{x+GS z4;f<69O#rq#vZ4FHuNZpS&hVUgSR<1p}YKM4Lz!vF_sl8?z)p^CjK`$i&cteKz!Pd z@-2yC8LnlqvxEK%Mu$G?BtX&{(IFZ6Ba0EGtn0%Wj(ltcM)8>Jr5?n~6iOV%To8 zC#0h+adyC3{P8LQI%O_7)Rw9?t)cXs{iptl__vk_bfn7 z4gj4c$2Mr2p5!eEt!$_GQ%gaZ6-7c)>zNGdYD4Rlhl5bLSZt`+RsT#dwX7F05kofO z6kH10=d7YI2?Is_j%;#@0M8!TNRpH}dyiGI4K{ML8`=&nkG67W8VJ&oV~Mhg0Viz| zrjfeR3CHr$bhLgnjv9GJ7?MiE9e;Q&1@Za~7+8+B@x`Rt&(L)eKopk$_2s;|n4M;rLXjGn7pfkGuiq?7fugnjLJe z?NU+=mWDS@vT0mXA3D_#R4Fv_Spv=31O-E!^{Jp3&{_X9hKCQsIh&*n0}xYVtNxjc zkBu;JV^=bnNnTn!oH%pfJOO=qo72iAW=pEfSzaxmR#A9NT`@{)-2*b0>uf_$H5)>G zp@ko3n(~41#t(otE7n=iTGh0)K9`zB?&6pBsx_>tX;mExg%t}DZ&rJ)<gbY|R{5n6$O8#|! z7$MSvtS0ao1%Tj6Y$eBx`BUz7XUntIy@og_9PtEY#7m_aA%bwJL?d7lGL>pXO=T64 zjo8h!2<<$;gE|0JCE2oB@R3;|bO4P4UkDXopS5ID0^O&q6JZS4NBD1E&~(g$j5D5U z5(HHUb&s&aFOaq%Wc-=Ym9L1gXG5g7sNRG^UK6#3Gl$4VRspgxhD;lbA*&D&z#NV? zwU`pXk&qMs6OKH}*6L9K1h5@Q`NkNI+hD?mV0qx-*gF^(t|`e3^+SvdYkMHLst^;P z2~&d!M>fxzqHLi+DF>Z0-iXp$bmKa4Es&m20bmJZ z7eu!W5bTF}gis0kASznZ$0fBOQp93emPa0gZsEARV+5GZkwD zoj`ue!NsO+K03JXuYv;%w}rbhS^TtrOm5EG%8H7{lq86}Vd)M~wlf2A0$w3UM#EJ# z4Ge}C+7V_#+3FD}5fV?53_h?kTo|s1!?U!a@eP<%Xalx^lx=7ritED7=wKY85@6dr zt9%TXQMSc|065dOkdU=4ut7}mw#`*Q5@5LT4RZtZ=0-%l0fihQGFNT^Yr)?3SkSjU zMEq@4A)kvm92d6=U{Dwc$zrFn!2~>P8`p^IbKy577DRDxhsjO2W`nyjLD7)Ja%v*Z zV$ihkoKd`cGn5%h7kmdtP!9(zV@WX1z!vTvmC*dnB==enVA!RgDc%;Ags==zA+r!s zsMs9b7zZy6(u={wh`YqO<|qu3IT;oc!WK#hkPM9@SaIbuSlrtHXn=}9bgTR1aFe-O z+@el1SMGDe`Ql0?P6A?F^#U1}>*#>dgPd{oEAEcdU4r8fQSX4mAXM~Z3!8oj)=C3q z?I`0C2fn$0TQ#mPfsNZCapSHFifPIU&q5rR4lu{{g>-VZ0C(GkjWML03%Cu#qz?cKR2w((rU>M;iIWWONR+LLs42Bfth45}veiF?F9}itq!rS&p zW!3;MgmQs`xUh&W9$*`j{qS7?ef|v0gk5ax4Hs4fP%~f`UI={^6@ZTc_^?U<5cq`7 z9LN;P!R1LCXz8~I2imH;B)%|1wcG7 zb5JudT%-jy4pv9P3DRin_-=44!8=4v_e_pK(M9{ynot0M1!@i^1f3yFgCh0@SS3_M zPCTPK5(S#UtgBc!ikwyg7l@(%W(lDn0&iIA2zMw1wNLd~Gerb2SXih;R~)+8qC?1P1&$NIuxsdVs1fTqx&@ovOIOm6_JR|$8g40;UM_L?XUNrY5qwSivq?7?mrb>D2bPP}JMBCF$C%!vGF)i5_;ktYqCQ&5`}?mLAZrG!n-|q966)IBZ#d)+Jxd17~~0BI&Qa- zKoEd`FfXXxQVVXkOM~3)fp>T7xb@veZpCqwThzz0;Db9Z=pE1)#sE=(O1o0L?n<5FMByUYy%v-3f$risGy)6iQZu=cS+tIBAw{&Z@J@C~8v`DEC z7{C<5Pcj4`0=#a$0wGeGK?#>=d%~qgAP-cy6Nc{X8h|%tESM}*7WfM&+=9Z)V2ox- zkR-?fED_!ZJ%9_K_YviAPZ$eW1B!@cfmTLc(3N=J>KaZ4^IhDk?~-K4V3;3h3p}_$ z+mwoK>1bQD9r8*eqP$1mrR_~6H{-(P^VV?LKXkWb7=Vylo!W7&5XkhJEw};=0bIFD++|2Cx0E}}b;a0ni@l;=tU=aA zeV|a#6l&Qv3qD+f%ziM78@3<nnN~S)Wf{xW+7y%jG5Pa+j*E-4$gD!LPeKcp>a5 zVHw*5T?Uz{CSp4X4k!RF9!7<0kW`^U>Lk0rBpIGt!J(#!c_OUAo1l;o5B>#dkA|*d zVK}3v!+H%4Y+k{LY;Mq2;4AduR7_3q3y}!jL5pQk5x5Wm$O|C5hK~nP&kiNz@v(WN z4D$yi1mDIk*2Ka;Fpgjxo?CpJNrgtOOEET)cc#sp7C{%S2r%KpbM3q|fhqo(JB~H) z_D9-v{wew*WFEdBl3P@~0HwAra4n2NoxU3dPbdJzLfi1HRfKc7aW#Y0M$syrBsq!i zwn9)2W(#xR%Bv;9TL2v}7|a^z13d^cA$yewk?b;6_6!vjIILm;uTt10oY;Mpy1SEc zFHlgH(3v0^+!y2n;@)}3)$7~qTj(LA5O9Bx9}^-nrKp18(fOXUf(f~WG)JE0p*8PF z7zjC@Y?*_3!r=lGC!FN0Sg=8q$X}6XhHx{Fv>HI27SS{bJS3R zIvspyR*EE*iw7pjafx{H#OdC&d%^&O z3y%sRG8{BtP=1PgpSsVjW|Dg$^6Ssku>>CB5fPBhM=W(2g5lNh8W#+m9f1xn<6%Pp z;#EuZ322dJy#_;Cz@y?js53k$P#<|te#eS(c;Hbf9pqZtv*ZNPLeEi`t0B4Qx_fX8 zw~yS%3t;!r`}puyMO?t`AU{Bd*Dj>69WKaB&9?B4L&b{nSCB3^SxGw@3=ak+FVx|C z8@`PkjBjT(JOJ}8_v8AJzO`qp1dd-b0QarE0DjAT5d*IU!jCP0o~<5u56lPd1N(vh zz<}UDFigf_V3hUvAY~~kuA;fyF1&7&;CrQ<~u$aB!UiqFhklF0%m4_D0&z;WNg7p>yw9G7p zW;5Gud7Lp_KC@kf&}?OJyhfT$tm$Y`v)kJ2YzVbAI|YEE!e;vf;8`XBxpo7!o{81w zX3+>57~X7pb{=(}B`pzBN5RBdgDtE!jYgmC)!JwOwAfl|ElYL9SemWQf`cI_+*;A< z*MK`)1n|zHqhzz{VDYSNmOP6KjR)6*=fUe)$|@lZKdTS+&$xs8!GKyyt%UYItEkn_ zrZaS?aJ1!z1i|~)k3lrz5(u>ZnF=jF!bY2+9oRBx(~60-2W^B_!-ip#2_I-Nw9FJF z?X>nLEIi2xJ3RwDJK>pAi8ksIHZqZ_XmKPg+UTU`KpY37?aTpFJuK5X8*RM~M+*?P z*ZyN~PCXFfi<5RpE1@mY63&>6Lg9e$KbA>brTxd=lccodrr9Wy99GeRL&`QS*W*q5xFDt~&FHjtTF4Hb_M_rh ztB4wE>$HAan=rWXUpuJ%s}*V?!wk2suoq=f8|w(Mc9aUkRSL-PumUt(sof80R57&~ zwdEgqf>Y}-@YF7sK(&tHk-#cg8*HlGWu$7g1*_WdYOD5riW;UQ3b95jkU(0kj@DLt zJj~V3GnB)<+FvbZwMrqZ)oDOT?1{ISv5TBiS&NRHARKE(svp~Et+}>Z3!1IfE@i{P zxLL^tc&#SIcQW3f*Ai!Q!}nopfxZ?L z!UE6?3u*(l$TI^m=Bp$8sX^G5gcP*J;tY+hD=4B({y(Cr!oH;)b!6DtuHo zwjtH`0(iK%0J8O^rc@bf$J9G}djq$F+YplB zcETI?Sllvrd$*8V;4OsrFHpJF9bj$`1e)6$uk{0)^5TWsLU2_AGv4)y>DIY%{L%ra zZs7z^3D+&`HqJ}n^#$v0ZBiWxJ8}7;!J8-k73_(Jw;KZz@9`FDtGrF|P7MaV@QW7j zx`2F}TZ(_-9$f))f;Ny>jxV+&)^1T-^PKz3v}Q)$ex#ed)~O; z`pR+`UV%Vrj9`509s%Hvdjz-!oVI}h7ihBMQs6RhlK@Eo2X2fvf=jgxj+RzLdkeb5-Xd-b_tXaG4ZqacM$E3kVJCx0IS>53M* z4Aikb=H{c(i~d2{)pSv~INf87P8ax_2k7bcwytwPT?v6ucVD10Eb6ia@&HKPQRq{* zsY?i9>TbcJx?hc{EkI=DJ+pulsw+P}wHm-3X>%^YN{ zQWBewx9-j|uaiR{C(w26xqNpm*d^m2A_I7y+;F2G{rAki>1k#_MAX^PXX)lowt#_*># zYn4K;-OlR9R)j#?1wU>raJ$w7-L5(FbkN)7EUbiqyZ%h!?)m_vP~0sI9Cv>P$=z7N za@V}j+_g?TcU36TU9s(Y6}x-grK5=!w!7iu?yky1GBA!{Hn0}PyJUg#F3$|4A@6u~ z+ze&0?Oig_dzal2-<=(38R)x3mHE$ocbc$U(C;QaI=*H%LsbGLz}xJo6dQO!D2I#$ zucnxH`?zHcJa{L!d}0YN;udH-0>1EOcnhAm2Nkdrm;fQ-4Hd6FM#U%I<*kV~hs)ya zP@tinwxL^T0k?R9yD7NZ-gqk?Io=&FE7!*hOBezKd5OeCUL!HPSkEhAVDc^ooV?Ek zD6f$h;X&nf3s`xvykP+?FPFCt;N@jTv<9{VV%`>|Vn9KI#6$DGk=48$hgR`!$<0eH zj`Ny}>AWP|bFsR3mrPSZ5;JY*6QSNmZ@swjBj`1$;CF`yJX|_xqW6dUFJ|-#j6=Ny zW8v1|Bi=ivNEi!OKCt2BQ17M}Vw^rw8?%T*1Nr1G?mW|OeCm}V=Z!}%9^=I^$hfT$ zCguR!b7{RNV}EWPS7n^y*!AvleZ6jCnDHDA-%B$V^2mj6#>`$&h_g5D3+)vxKys{V z%QeRL@_8ja=7lse$>866hLV=(4(yZ!U!Cv%N6XT*Q263hc;39#r z1{dFvg0l&{0i?tue|+C4nns9Rg-ApRi#hr3k5j$?lWzysffjQT0@1~Mg9AuknlGus z=3Cj#`Hs(azHf#$+0WOCAc+|I(nN~BM_=1UQWw#%^aauBRz!yOiq1gP7f&$tRef1~ z{f!fc>+3o2`u1Xym%jwuZ`oJMboLGIw8?gsc>=a?TEXqx>VW&Y1&(bUgAgwzjcekuO&oaU|c}_;z;0NHm}>mq^2{mILnun=!Ed4^}Uc>x1C=?nTDd@zmqEsbB(uUY{0nL%9K1MLjwum0tS6a5WZ lJXxr}A`I&<88Z8eBia5IMc#3cAMmfW#mX?!CI8BH^8;$-nsxvH diff --git a/DBD-Oracle-0.25.tar b/DBD-Oracle-0.27.tar similarity index 56% rename from DBD-Oracle-0.25.tar rename to DBD-Oracle-0.27.tar index b824503d32fbdd67baa3d4c5d3b83557c78c9670..8c42378cb348447b71f4a00e4ae755d70e330181 100644 GIT binary patch delta 46908 zcmd75ZE##ydgnJiBgyJ3%?oYK=xsD}1wuqaA{y_Y2)>9Q2}+nDK^g!hjYS#NKsSIE z8{L@h1}Tn2-|>D)oONnL!MiADlNrmiV<%f%NoJW?wb{y+Q?)63Q~40vwIA{!UOVwt z?K-tp`@!+9w~}mr|L2@@?`^!0k~bg1Dhb`U&pj{CdETGrJm>r0f9(5z^!QgUp1(MB zwOv_l)P_dNV<(31eZ2HoJTY=&a`N7L&pjK*BXK-6GC6i)Vrpu9Dvn1-`S!VZ^4`bQ zFK&0bm3AC|u3O(+Y27>W{G)tdTf6u1@Bj4PPP@bRjw~G7?IhifjZB<)ShvsY?{=lq zsg=9;j$D3pbYx_5a<@KRIR5zP_}Iwk=i-qE&hfWS7yiS-y^lKwbh=roH+wogTX^B= zalv6?d}I>POfcc`vB|NAjqx|m75>ZE^>+MLJX#)&M^B!d93CAR9-D|q#-_(lPLEH1 z@_XkBi-k{KI$!wsiF-%RJhyj|Y|d7#-6(Hu-aGQGlPq&$Vj})r9LE#PLw^CD`>Pp_ zjWRj6VUv@iCp6KisfSMVqaQ4MbKFmEba-?s9vhz?pO~IF5!>Fzv+r-+|LzYS`+Q-1 z=lx$BdNk6g_ka9rPZxInyN@S!p8WN1KNa_PZpUZhi|6Nt&eogVTDw_k?5zFzCts|u z#ijmgdt)&EAS&*>@T2Lci~2frwpv@+UgszM89c>rjUPSpod4~Ew<_)CU5&!OGx5l& z=%_c+-R-ueD80)xbvU>_?4ai@y9Rh{PQ1wBZ=KltBqEtR_b5vvZ`4;e;!2~@x=o8i z_pKa7OB=O#jp=oHy%W3lHY+!4@%C2S-Jt)h^GdrGS8JWsq+MUBRpUCtvEH?oMyWT~ z<4(=>QjTXDja;YgT6eqMj4Sb4rO~N@Bk^{#T3f3(>7?X)u~~OmMQt#?RcUP3w3K?Y zT3@YnnP8>f*lyR#ar~XucAQjOakJHpn>9M1nR;u(HJjCl3B~Q&TCH7cf~$tA7v}s- z8CtU!Vrs4Bn5Ex|wWtl+tL;Xuu|*f)9e`-Xx9gn^JvIn1lKO6Kck4-$u2}^?ZME86 z{jjMo&Dw4F)anKc>v+g^dDjgOB&)5}?af+~2c5W4X|LBBcbNO?My0vVLe| zS=O121QszCUu)N!tMx6WbSa>Z!zQun-0q7t1V#~1Q9utAU2m2KkGpTJt(v|>_R|Wx zpZ>B|>#lBuZlR=WxdnQPJ%q!O$=_0*dzWYYl$JgI^mkOzQj?&XHZ<4UyEZmqW~ zoAD;nJzlGWoiXDYCVFf}>#1|6qqWXmj7yzbEn2BToP%*|&3^RToo+`rX~ip$dZ$)p)<95*;Tr|W=y?=i zV?^T#)R8r_VO|w24`|e@;2Ky4=t`BPi;$O_TdTHBq*9ZgL0@ElLS@@BMI6M5A; znz0l6JATRatx|U0_1vk?b*H#92o+DLaX&Pdf@5IPxp$J2W zF-Xm4+Q>M7tcOwUeW0cmPIN(SR}bD;NJR78?ueDc(GewWP;AyA(zMC`UiAp}IKVw zd$zjO)~CR0!25-oh}U+sv(egy<84$RyA_d#XG4K&wTy+YYw>%70fP_Q{XCUA9+04-N>YWzEh1AL_)_j_>awxeYvB82 zrry{l26}cpGRpB^UTL;&$Cd4FOJYk~c1IJ0-o>-mjLV)BnoCNeR+v@+7g}%CIuUw~ zga*jARbzg60V*jSMX2mwPatb!Xzw6CSEc>Fi||}(#ZK2S&JR0;d_qGQG8(=CW0+>u*Aj8Vw)ipt)Hnv z;%p}jm<1RnK~PSCG*todv{uchO?L-J4#O z>44JGG)-P$=3$jd0r9xs67{4LviT&@UaWU2iM=abq+@J1bYPa7Tb-GXX=fcNL|{nE z48_eFn#3I=Dn1^@&s+nQ zI(sla5iSCfgSD5|O0z1*g47qouypWXe@n;ltpYiK_TZK@1YynX9wBZX19&?w%PhJR9-xoX9FZv-78-AI-%!-<$9$;ii}l>w%!& z^G*b34O-nBR8rY zq_KQsj>rV}?{3$anuKE$sUSGAA*m&8Fmw`%$Ic#>`2jzgvn!rL1)x@U=Cx_Mij!T_8r@#U-Y zugki&zY8;Ox#2WRBdeGh;Oj*ljZ4i|bLe}ub_<6|TT}0#Q?(O*VLg~ubW*aP&7?3o zO_50bnc0zPNt%oUjhABUjn)e4K@b#9Q?cplZT3h`Ropif=^*kM+bR;!C2HC71U_?D z8;l#bD|fK9{WLX8H%TBF?1?2{?v>R%NIgVZKi2HBVO2W+)NG1o6o`nolMYPUFW;$F@5veJENbGctHb=PK-?9`N*@k$RH%<-oSwa5X|=uePVoJb9Ixfe_)iN z9yFm1#^VfQ>$*;imq(841mjxP~mVXaSKqCVN!H;YXDulk%nt^l1^QY zCnhh!23c;)$sOEY^vDFn`_bp{3IU}+xdD;Q#omj-1{<%B1OyS8m>T9M=m@{rN*sYP zNi(30rZ&(nY@$-WdpHoTEGAo0d~2)Q#J$vC_0C%Ky}=Mfa=@`j5uu_FaP7voiG0O< zo`!1G7him_&rIG{0=~PwJafkO@06M!l`brI6*LW}^6pi~uA=yE#d=Zo;j*sH}~_WE1W zDGiG`h}z7}67{-SYzXIM@x28fOQO&XugS?G9Zkd=oGd-4P_;my0Vp5g^o|tVEb~r- z?KMq0UJ5(afpNV24f^DEBI^#R8YyA>yfyT+2iqJ%rp}liZqW;@foi)&2-E!RsOF8< zomy>RP|D0cOd+bbz5#>ou`+teFtIZ)37i08~oW%VZ8p!|g~d~~b$=PRhvm$KmG zOtnhv6#SQqCOnQSw-Bd>CHRo1-H!R(fe?zsYi?-+A>imT2EsRyzRwp3FQi{xcWq2* zO%J;(Nr@x1#cU^V*O&qBf_n01!x%Odc|t8TfwW)0kIaBY(+cj@pwXI^Z^~p|w~rTV zwd09|GVux@xDpz6>~o5Zo$nH4w)6o2ACx$oL7ESuHT1geyqiussCV3T2)VMdy&+im zFH+ONR|Im-eGH=91KwqQpnwJv(P&vjOtUuoiKv2-JOnGLJl;hcc_YflSc8>pZIcd> z;b0x+jYFKp&Q||-vkOt+EoUK6pPLFW_b^Q~cRy=(IfSpw>6rf^v!;-Dtj$?n5*8MU z>Kr#?R{hp+)WYT)+naJwE;)b*fxIfqp1?FUtk9V8gT81GgzZXZxJXGPosWi&Wdx*8 zX@%~CUBM=zyJE_WmB%vkG^8@9kChru-MU=3=)ekAJB2lg{Nisb=RyWkHqGrOdugjZ z++?|3!Qt25R>0BNINz-ooH6pk8q(Vu!VIzZah_Rog|-tHHOwVCR2j@0=NRjLHrl>y z1;TfEjhX|vg`It*F@mL;3&I1UUP<79XqawXB-!W$Tn}93Qy{x*s*SVV=C43}fD54# z90(ci_iiZT=e$38$t+J>>O^GyDBh`Y+v6e0OP*4Xhr}UHa4a4~2~m=ff+pr+V7g|| zU`3uizhq95J+z<{IdoraG%1(+iJ@mJjA@hYCZ3~=udoe{nSY8+P{V__AR|_}O82v$ zbPKw766Km@0gHgfK^%o0_{;L5o*jq|*nz}3#~p)z@D4aAIVR2}D%TVqPsE#$Q~P_>1>bK?Nh@%=5uIrrYqAtQ z(U-S2_7Y+c(vM(WyG*{MztvoBwU^P<(BEcKA&%4~f~~wX2PC67Qbn2_dC8auBRlzS z+=lF`Y8|bdP&sBh?g(`H+m*W6&6=^vB^OEduMIkFI+5`%y+g5gS>yH@Z=QJ1F;=o1 z=1d~uAu{U_75ZTmY6@f$BAyj7z1px#&NDMVk2t}zmQ6+g@M^f9e~;fRTT1Yi#pflw zi5E8TxupFh77+ycY!$W)@=78i{kdyi9a(uWVsp44aGVZ#+&I3zrkal&a*;y!Atz9F z4{BGwKWH;;PyS9K*_rA=E{1eFs^XW_E{7#bbz_I5y}6jBvxRdlQe24Y87>S8!9xhq zGHaBqWXVjjf7N^9#jH}I;0Tg2QuRiid)C9U zl~3l=LD11)`mt>glfM<9Rpw>eIjD$OU z9}Q&D5pzoS(twhf!=4F+<&ZL zO1a}wL&zkC8!~;CDxa7F$OEUS`CnrnO@VZ9)^FV*Z+1iRbmrg_HQ@rQcqznDksQ)k z(>|jF4x9ghH|EG(2aiOHL(~!=!7vpm>m1OxUwKt_#>3WbDmx z?LG+wo6x)QFxx;`aUnZY`=8JJ^3p3FBHPFi%CB=kurh5I&g<84JPtr0Q(&t?b}YKo zty&`B1VJ_70j#iWTS)Tv2alZ9Z?GVBfLcNt6OPW%=?ITf2aBwnSRiHB|(gTu_j zASZxJN+AZjV@pCS-)=g-knS}HK}eS1{{SJE3~i%(Km{I_i{rY4af1M{4bsv;lQ0k( zj;2iy`@BSgSk6NP)vM(|C%$lc=+;>e$kakwqIH-;W^EYKNksrGq^Q;t#SLAwk7t%V zi+o`8ygOqwesgAFZsz>uS`(rqQr9dV~EsJP_m8CzC>k$ulXYN?aJaf*<8l*?waxq*mmXLJlDpt9`U zmZ=UdWZRdV62dAzD-hP4%a4jg>!yw}Zx{r-TW^B8WEzTVd;2>~#)VSM=*AsvWRoX% zWF;73c~M^TkzOgrk-9_ZutIdr@^+!5oP;p}CiTKeFt@a_PyPxLQP@&xD2j$TpeD9y zS_3D~%!*d-LvQMXu)lW!EK>PgPA%$n2bpu2l~uY@$`GEpEG{541Hw8aPQYS?n_!%s z4!JJkOcpv~g}Ln|>!AkkN0>QKqNX`+WuRoTE>GF`8i5?5bGerVEcC*4Fc)8S0DcF3 ztP>>$Rz-_=mzf3s#yqgNLpR>qx42YlOjXQ|zeD`brfA$*OkQcg zL40^kGKG%JmR02?izdTHWiBF@@emmn2v!1Lx{bjP=RGgD0*#)Hq$5CfKbj0Nl)*)7U(9>9a7Gzwj5%LYDH+uFR?(pxjpc&W$}In2nel@=!~syVo57 z5?-;-x&@Io+0cVE0Sn_tPOEVtedZ@M!tn%8sbS{$bUdo0OrcTf;DiWbAA_yo^gel} zB_icrak&ue7X}YW^c;_qG=s&H8X>(gm=`HVgU~X>IQFoI?`FKrh#Z!H8EWAm|K0nR zJc|2Rd%j={g1COz3N zE-S_JIXW{rt(+Fon*8upcWP7ApUe6%R0-)*tN7L;-T`&(jl{j80EZ>HrU^{FY>`Ew zo947W_aMbw?ZhEFzez}e{3Q%T4u^EMr0L80aS@T##2p#&T0vj|21D?!cM_%$=jLGF z519hL*?HV7-!Cw86b=9+J9#s{RZh0Hw#458^Ls>)Mcqi^XRK zpCwagjx4$lBZVHudkw_Vi7{^q&>$i9>`vf#2-*xBLmV&DG%i^}2oq9l1~p9#SP*0Z z(ORR0c;w4g3z~3ym*YF(F!|#3^NUM!OV@RFId94^QQYBJe%2}cZ*QKp7=hbZ({PC# z?MY5o{K7JplmiDr8jB?sX5L~iD$K3p_5r2o5-Ul)ew8?ZC+MJNs@o|;(`3_6c^w#rm2I_TeTK!%6AzFb_Ne)F*XqcL=yMSaIg)|-v>}8PK*t` z`s(1U8xi=7wfQzZHiVS22+5E{)nnFLCmP^M9`A@84c;P?Y%D-gHAJH|70VkrzSiR48nR4K$OiKeLMbHs;@Q!E=iXOH{k)x!DoU z(z5wE52q{5K_rF>9jO+d+5XPS5arz6%!5ABGXS0GbB=SqHM1}e-voFm!%R>^GB<6f zwblhiFzGk=znCTh0}CPraH!D{s&iOa0NAc<*E#8ET#3_vE=@zyP@dvR%Uzcumn*#y z5pCXv$dfcG<{ud6C;b|=qIRp*pwP#9IWApA5Aofuw+LhK#R3>C(KM+8mcXpUBBc!} zz^J1lI(e^$2t=jjDsIhjKy8;2{`bsK@o>#h;qV3;5Soh>2?5{eu8k8=2UGPj9x?R5 zb#J`MucAKd-e6k8G1Dm%YM(Q9jt2y}9sCmHrD2<>o(l@uiX!1cSXi^w5D4W9bjpg_ z9hoQDc!V7m_qKWFDL}wGrpY>ue93ukR+V`SBAh=x(`cNFKzZT9Ky~NHlRuN3TiaeIaS8h^ zhl-1{v+>O3#jE>_T!*yrMPD-pJsU?zByHp}^+$Fxlhv<_O&oOD%teYjIS|y#uCDoMnQ<)SjWuur8llFK${1Qe;N--qj3&}k&Mlb zK&gr}uGT_E=>&+{Y>R>HxK><8WH*y~MQuZIoj@^Tc1#_uwLKAN|8;UwTO0vbbML#O@!TD?GLHt;c?}^XIpoyZ`0?q4W7~ zA~s8?7Stsx4!K#|Pt=hohoIJ5EY!l;PZI$D5t?cSc9XCf?-% zZvsEP)~dBPHi^FO{FC2#`7Dp;>_~PzV2n4AtGujL{N~=@0LSRI3fw1d9I zokxH7*9yg*Kl|Oj=OpptxTfM$om^<&=O6s;)cvphqyN5m|5yItOOH|5 zD~=iU?YG~Kw>OW+w`FBXaCobX5!{L#M6Lsgc_8B= zMi{wP{i-OKsJ%Vz+>(*_IJ2`K@Bi?B`3FDs^~E>i_+{YKxs?an$&&)v&Tstj>Bswy zyDoPA^p7Ws=-owYyz`TP?`Pg%g?u?aGN{LNi=W3m>fFL7yt%d9>7ufy7TiIt`UbGC zc2542SHHA)>)M;@j(3}t!TZ1Rznv_U025oiY`!a7-9~NoCJYju?Q|xy6J8$P`Sbt1 z_Plmj)`S#Y9o$-$Q?N8x1PJ%v`IBFGbmw3G^KU+DRX1d#Nh%OLBUt0Khx;%7>Hqb_ zQxf?2`;W`x9lul^)Z*`t{`s#Lc7Fd~y>VGNVykgyWg>ogZF!ZbN#j&eqiQQ<@+hym zf(=$#s|oS~ycW+p*T=`u>D@ca^nEJYdFo%klFad#;g_ApVyA=<5r{4}ib{IcgOLA4 z|Eg8y%XLFD$}s}``P%IgL2Ca~`awe-*MtGRW^*^|QrolhSN`?iTsG~t^vWxBPhPG{ zie;F&h+u<5{{kXgyfPYV+3$=^PQ80dE4L$hN@WndTz+sYE!lhid28qGzc~H2)=-bn zo(U7wylgF+RDL}#pNYpK`ScWz5mf)JpSdMazyvRZuCTs z^zZ(1vG8k8m)f;Kp_J$iVsZLLJhOW)DomV97r~HkQR7X;YbwquYkTU``_hw8-U~}S z!$EX+=jAce~FO z`gTvU;@!XZeBsVxN7VSpp#$}4E)gZoPdOn6?b2Gr0~LS_k}{M(AoWy7YhIQG3$MF z_h+9kJhl6W-zfabCwISD*!=vxkCSJSojpZWos6&&p5K1VmGIns?`+|@XD69mDAzgV z#2)26A1d}Xp7~~|C3;A?&Ykc6;J0`F)yBVH7`^}f`X3h03+6c7+^M1tM-7XccQ~B5 zvLTc6+%hcZsBs)Q!oEw|d74Dn*GO-Uuu}eqZ@C%BLMn_@88nL|9 zuy2bndZ|h-2~~ET(-~bW(=$RQAe!sWU;p9p#6`OtlRVVv<9t4cczlAJC+F}BE85_Gv5R=FZgNtdUb%kx7J#lhhQfIkdBA=Z8Ojy0_|$?;>@4Kj?Mm z8)6PjLDq>)V&Ie<_rS1p`r^#e%-O*Rl3d+rZGnI8g}%6d8K+6nma;k6Y%_u zT&oz!-6ahOcV!+mcK_?~!cQj-5C<=_XXKt$l1{BvS~4oGeCs42xq~O7CHVLJWO}oE zOpmKpt|$RPekP#g1O3uC%eHy`#jA?cJM6M@ww%}>4S53u@UdHIZZG`*2CUaVJy@+} zMxD9iuC~Q_WZ2z!r4Xz1lm`rJPD?(IMdQ(AbRrrZjYh|#Q9hiE#>S(ulhM78|90O4 z*e8swy1lt2{(1gk{FD0G)F=1+bAkjS_~(hKhn5%r=+Y5o=*d%H9McaO80bZYHv~|W zkQ^1c!(f}im~?y!3R41@BH{e%<8GJ#_A1utrP@k+TPIMJp2|C)m4D;Zwqvu1S99(U zqJTwI0e7p~^H4KXjc?a7;{tAFasLPuhoZdTUhY|s;lGQvWJS3-l3=65C)F5XF@Uvp zU@$;jz0Wfw9}IAF>>E7rg}|}TnM2qQX?B3C)h!+_JO#98X5m>qfXb@pT@JFJrUIE9(*4sKBs0H-8gHhYp)3 z2^%$4pj0@JK@Qc442N?e^$tmF-O|AH0L3pMZci#s8(I%S+?0U5B$77ofe6c+2e;7l zU5zd+NecuJ(sU&GmH8tWVIt};daW49p=|LYCg+fx@)rt69kDq_)hDV|KHI5RmmHu5P5sz;)0yrBP@ zbSD@|u_lRhaa(9_SxwTkR)C+KK9ksy&%rA1RV1XH3j#m#P44?}mt%nClH>6JnxCly zJ3sp2H*S6gGXC_!SIE5|Gkc9O%e^z!@9^8Xr_7UmhLkw6Ob+bC3Bl57a(m|HdmIDC zc5^}yPr&{j5*1Mgb?4LUGRFfH>acpBc8Yz4sMSrKOaZVu{v+wuQy)=XyyZ`YvpvL= zY;>pY4tkfEOZ&_+CFHD6Hc4YnGZ~nQ`Jmk#4wi65NG&tp1vOKEi#XO5`HJlKJ$%Gm z7eX1LVa*n#6*}0SYTl$Yk28+x0$Q_)=P1ovo4oAd?(cj%2VB_SI_swu39A)|79t#L@50(+Bh$P1?beY4NvX-%;CEhOuKGDY=8?AUi32hd_3&r2V zKH#JwpVm}@@<4nFL!{pAGlW(g&6&lL5gg*^nFEdVFu%-D zDd9kL>YZ#~tCfefg2iI>Wh~vD&AeS3pnlI$D!I9h5SrPZzc~0AcqQ*^d>1a4DW;OJ zb~>mu5P&8P(iG1bO0QDv??EUAlexpZGS(sgMk$zq7J8Gw(3BB@*b3q+i5I`6V>$|j z6p*hW4qvDf;Z1TA3#U&HEb~wIg%SR_aD8EMc5!)e>H4Khcw=$Nsdd0YEd& z+OlNo@Drz?iVCZ&*xeqEQyrteDEEIUl2AN`yQW#ie)L}nuRso^zIhI)xopj##&JaX z{jT}+axW6gaxeDdd#sVmWpjh8xlyazTxdlat1-x9zVD9dL~EtKm&U4e{?gFsWap*v z4lEUg#C7w^E17OW*Blp-dB?%vfB}2P<0hmF&;JaH z^&^QN;jlOIL$T6B&;Vg!0>`;=4#1gfmuKeY4?>y5BI`wQnY~%L7Kddc<`uyX|JZ96 zlj4CC|L|O2WCZl~gcT5a$;<#=LG|}PkpJP8P1jRD+iLwB&GGR=vA73`iyy@OLm=9S z@=Xo7tJ}gdo~LQ3_Si6mr=v844stNffl2Z=n}d+T=qH%h@`Oa3)myR0(z$hfv=Jg5 zUP~8_iX>5j9ia(jM6lGmbZ)qvzy0GcCYR?Hm+BcD*ze_>&EW@(mn_4W9Q zy6rn?iX~HGl?_$mUWnreMhZqGRw2AJJ~)VrqJM6Fadu%z@8_L9?sez&iT!;M)?9m6 zq;ao1)-~_73+ekJw~j2$s=0S)n3A2i)_b&U&Be7})=utyY2Q0&$xR~u_S(YLYt}w1 z$7#*^4V(^O@s6UEN+MML^cKY4?X%r8B`9^r_)QQ_AK02%$S>(KO)F1ks-XF%o=Myu z==Fn)mHoc9&EZn{<-uwFkKFrWAc9i=DCHyK0l^QC&}%LYjNFla1ZB~qf2n_LZzBn3 zwNmnp$Kbs2(nH(?>-OcKKVaEZFrX%ka2E-}d3e1o#$t@&C=VqFzC`e34YgT9kE~6M zvu6^A3WtFN{%z;k-O5V?%j@#eOMz)r>=PzOqpDBuZF7qghTI2foHh&7YJGbL zN?h{ZLBZC;R=Wo!a=5&=^U$}D^APw@I?IsP0muNj$EZNNBBRr9Muv$Op#_b1ASU_N zd4uYZrpO5zqXMAE>HIYD=b&{twd-hF93Y4YpY3D`(_F%pI-JA2QzxVC#q<~_=HsO6 z#eV;URM&q~cu;T=$Er>tr@_SsT-O_qaW`*fKu%#y5?mag`mCN6KcrbrMIRFM&s_A( ztbq^)^q~etNiNp$qpK9ZfDHqpFo0|+>?C^-E(CCINFPs~3W>FF>1aZ9cgz7|M7%g- zBdgqr{pNeL_Ub37^}2BrO9{0=y1n(uT-Dsr-jxO*bJD(r;-mP8j(rgmW7(fn4-rb7 zLWD|FYlv*oH8=s~tElEs1vn;H9~`rB2`FM97}tUU`4U^(6kQ@3%Dty{32KL~LWncO zEsMvFQJ=A7AxC7M3uf|A&jk0q&)6MuKSIO7KvjKvqMirrTU;)?OaY*Xx$CON=^V4w zr__{P-+)jQVjyC|-ZYEzrWu?7hPO{)UCiS_rf;SP#q2}mBAQWjNwMES6!LIM7dU5MnavfcT;=ZBM5hWtPOA^jen4;|zdKWt*X)AZjM+PTU7 z2mJ{RiQw2jyvpG5JN@-{WhdFh{TIQ|e@wCNgZ}XJu4cDi?Dqzt4G9j4#l__>DQiS3 z1$EOABj!TfqXvbj^r0y-QL%JRvj?Mcl;X8$GO5FhLA8WR6>4^Fw$eGb+VFCt#@(*z zUDFSHS6~Ql>a)M1`hl;RdE*3aJuZ!a(sBP$%^!~_ASga+hQ@AXwD9yafGK)=B)V%S zc?e_paC)F0+BkNRi*cWd?j4zbP!8P!B)(a@cjUqsaOmx5s}b`y z%fkKCpw^BO-P}DePE43HC-V(*KFIQ4vQrXxs<2U@E9r~)NsGmcnJ3YO3~a+qo#d!7 z$#K2zX@9J*ScHGm$T>G{R^-#T$bn;%K7Qamt`Wr+e4b26E5K9z`qF<n;NYwd%A!NuaYCLWe~KXxzXmFL0AJ(IfUZPc6L>HX`f?Gg}n2 zg$+QKE|#;gGOrFI)cKATpX z;ptyO8+F_BMK5+G|H_uh@CSu&JRp++K;JuZ=^=>>qZ1QjnRPH_0%>A$^fOrp1Jydd z?ScCG$OwO>@-wvkU0iLWgK0y-chEVc9;OK4PsbZt^=Wb9x7l)3T z%3j0+nyU7O=`dXH&7#zcI1?wZ9G9&mUR9@u;t<|>yo~lf+|qKdShcvhg7>QJ9QV)8 zzxlyHcJuYXU3+uY9dTo1A*nkYmQ_zw-zqx6F>hJ~v^7ekIH{?{_9Lf-xqU4R#c2cU zdrcEUn!=M+Psyge6-PW5`Y`xs^|i*lZ|+W`055C8I z*+)9&LLDg%l0BF^i6uxKg}ZEaHFa31&PZms#q!v#^xBJ~xC=BgMwhwrI$bi#WxkOu zE24*#_*Gj;l{6T}uVm>phhx7Ai#_!k@coDMg2FdC01Cmn9$Tr6Mw*siEP%nEeg^x z`3z4JaRHC&3U3*FR)nhbFGbVAZiNGb8q^#Tp6fXOgX16m#npW;t|qxRa~vnK)!1lu zJ6F$WReQ$|=MPM#%Z&P|0^{b{*f(4w|E9@QRC!r{@^CAmXrH^ya3^ep#DBU&2U@|^ z6|8At4$jgCobkv)IXnOPkH7dh-feJ+X5f`&o}U1Zj?0yvPai!iPFH6f}YuhGJwZRcKo?abAq7=Lw~AcW#w zgA695QTUS{($q0!i$@cey5MR}I(|+xl`F(>UyD4Q@0AXyHzh>f?wYxzsdE+t zrI+ebm<@KcTtoD)8FdXH@r%WEC8^nyGSu+WP=E5l^4)Sj|Lc56MEDq*q=ZJ!;MZF^ zi4^NCeewN;z_Pyfc;qragKO=4N*d0CBVVQHMgo(;-q#$13xYA^62yG4j14Ee0^oA+ z$QJht6xkg9aCm5VHJhM+_KHFm%sHJ!Hk3Ke6tWM)g)y8NWpAL#$~T0U&F=&mBOdB| zh97!m`1FT8oj*Z0iBLnHA;o8mKKw+BJu68uK_Bii6l z;ZpU#TC3V;&xedhIc%`?yhX*FaMO>OW@P#z@x5Mx_Ywun?!Q&x&f05Q3#;GbgbBrp zi0d{O$%3QgG-SGY>paii%y znZ=@F?O>^Ofw1wZUn%)*c*hVqFV1-PdXQtu8PaG~hu_PkgoRU4;%TBYOpSv6;bG2R zILETa^;u;8i5?jJfNa9G2R9|w8lueS9GKv{$3$N}XG9VMt99#{xX$1qPhI+`vG^u2 zRo{mTl86VX07cP@W<}vj<|We^Zhzn}yy4)t@AQb!4TvUm!JI5_E(Dk@OpN%_jjAfy z)Wqt>^Aq{NPEYRK0l^-`yi2QD7G3)O(x^0VM&%|~iE#j;js!k zSa~G+bQjKJfmYV>so7gE#UpM+F#~t~m+K|}UQ}Ls!|ajEao;`_cdRceSE@{CBPuVx5$o8stor!I zP*AqT2)sJ(EpIBhTUM>hRAqO1^lWvr_?`Ky*B0j%qZ@1I>Fvhawdfr_-WXcpAie<*FRl#PfgRwJ+8XPrkLa&uO)o>(7M~mJ=Q369kk`#FHQH0Q=RQO?IbVl`T1e@ zbBK2FjcL!NT8h4FO&4buFD%Smqq1i*AC>3gMeJhyCrxt*pG}xW+wVr4ZwE#g}d!Z(B3-{u6EdJB$Yd%U&l7MAP;O%s)k1eXB>j;$VmFw z2Y9=|A=T#n?bSwc=1XysBrHSE!FL&hWfh#}Vo7X;l|8X;SeR63z%~FI*?@=yHo$3nJ{_9IJX=X zW^_KhJ*(;5Aq2RYngH2UctMq{9Z>fomYWWZ?Le5SZfl)#jcPs4H)_{yX=-e(BP+v& z8qTsoS9aLj)0TCuhTc&KGz}YM@vQSsIaiUNW-fcQQKK}Xai;v{uW1NjnW2J+#%8K| zDLo1Els~JlxlNN~m2#O)pd5wl?!?!*)O{+dfamp|AYv5^FkRcDwqLg%3(8xBBZNun z&C>?>nNI4stL6@yGslH-bbCW+sM&CxR9bJ&J3%6Oi1nM(2ZTA<9pjWKBZ+u@|Bwb1 zTZ1d<=FjYz2JW3Kaze>VZndxtByzXdO(r%Qn6^+X=mVxF^PQujW@rX+R*h_-s+F%cB1$`tc45!P+ ztMSgwEnJ;fl@Mbd2eBZ{^&u=sm151B_jaEbgGtKkGFBqDMGAmkDVK5uVSnHZZk`wC zW?rAaO2z04i%}V5du1{zckA)cr1*xp;JgdwhWEihDDfuzUko{Aw5&ZUue1$|vkmB_ zcl1Gvnu!WGx4RTMZTFs37i+#@dY`-Aq=&WkT4o9KFG<2VmiG zyH-wUY4MO+lOw!x@ z2=@Esxo|vdb^ovUsT#Yypd@u4KrjTOPf#Lpmo}NcWQ9qWgvH?u1|JPjI2-Uc0TijV zaEZg*<46=PjqleSduYd zq4t3Tz}(vF_C$3L)t4)F80Es#$3ZTrCN3khE<~r@fxvUx>9*C5Je&I+46nT(ea`;f z`^|rLSm{8{n_qU}`L!3GoT9$FN(7ERypYXrJ#%by#KQ5zqlXkr+FK*= z&wlIdqg42tjPBPzDHlH>u_93+Ohm_{>>~0$(I$cKO1!GiL`H&4Kvt{qwJ1d+ZC) z-p)r?el>aH+R*j4Rk==F3Wo}(7!lXap=)y&;?~N0Xt^+RT=M4M!|G7AScTX)7bdEe zp{7UWqGGoq|73qJOO&nr~BqCv7op2i7s7e0DM?vDRnAUc#Rb@6OT1-nKW{W z*nzWduG6Lae`o&jpL$Uk>~W3TP>t>QOadmT>F)fa>z4pA8SjKnKDc(}?$Fr}@@Y+X zF}nx)OLOyp=knb7!Qrg8`%k|4_>(`Kde+xqmmBh{?;KhAr{l{))Y#?z58yfn&eQQ~ zJ?<|Vq%Y21nz?>?iReBCp8s{{kE+i<(O+8R2+7>r{G#ur^gFMs9XS}Ju#}c&76$2y zKbJ1gyuLUX)A+f9{{OWv>36DGU0ax4^gleIM+;Y$7cN=DuRV#^e02kjE*`qAcb@-J zIt&%MZrLN=@H5$oYcK4q)?Pk)@%(E;FPDFgXu@ho=@rv-V~3vlEE&Q-jo&=eUwU(p zqfKINDm4->Tv!}_dFSt~zVao!h`0y5eNR%&g{SsV!Y~1Pt3`F~VF67ldZu(j4Jyh+ zjB=p#p(Ok_`U~Z+o;-+zcYp63#oucEg?~{v`J0O`6+ZtYP7X&Waoo4NI8b=)i-YDc zcHZK?-T!Q$@XOD-x`nPpIi-87-d<7ulHGHq!pl}m(|J#BG~ZD1Ju!5jM1P?96MMx& ze(t%8@oS8TtHyheQ(ue9ERBqwz~g>YFAR<7+cdz&_f@wmR4s@$oCMR=o$dHb&18{j zu$967I($ZBCq`7tq*QqSQL@D5rl*xpL3K~NUCrt_4V^`)g@bX5?31`$_}Zgq zk7f;By+CWn;dkoD+5w~k8n{a{_7J47q@|tDH7XG7ATw&V8W#LD<+EFuw+l zs=IfI1am0n13O~e2Lp5dx-*&Ut}nhD%VX&gd-i=y{czinSEhVy?3i8;ncSZ&PZa*! zFZ|@=3;WCUUbP@?Ig_~`l^=&bCm&kt=eKB|3~&C>Vt5jj zV<*G{ChvV*{USybvG4eE)Wce7-8=I9qkLamyZ7<$@0Gs0kIfgZBcn$qCU)!dh2xKp zPK=K{G*$1nt`+|N5lYzXnHfVZpMLzTugyaDxJ9N=B|crXXJsyD3D5B2 zl9G*{&h2>|xuy1Vy}R=pPhEfQ->r+Y_y5gP|M%znGgaBkU+D%Sb|^^UvKqzKcYgcW zVsZ)6MUC%DnY0S(Obs#G_*7F%TGSJc#A@=qT5DrcEisuZE7 zzOq6KC5nYoZ2J56s8s%Q`&6T)Ruw*WEv@-FU3mVP39EDtzrude@sH85i4zYmrg8q) zcmCP=e|zua<$bo&m6`duOS6kh*h)R)yLgqbHsVA0 z80-aI!wlj|Q^dNo3*9(gWfAGLgnTd-RSR_i&);S(&7$;@kMf&be2u@1kZjfAWoIWTqlT#!f(Xqmm-yW1nIVMxIMfD3x5 z(c;`DTps>$sI<8jufBr)eivCxOlHpy zceNx52fbasc3IQ5Y6~6pJv36D;+}Knqyq--@)haC>-<+~t6q_$n#Il)xDkXZaduUD z$x;I_|G3z6LpQ@JCZu>|Qw}CfbQ0K=pP~`WJC?cpgkB9L)m2FJq)#f05i1MgFyLx_ z$4kN(XlHsF+*4YhyQW1UFWiR?)xP2I$9F1TQ?XM7y4skVSax1K_4Q=xcsw>9Uq$P+ zvldJ(?6X4#uLaw|g+UiO@;CATNoCKud_|@x<+{~oM=semUz%OIKDTF0s(FTExw-3pF zgcrv1FX)c7(3(=+ng+ALix65*sI`^dR9SybJ@W$i_UC6VzB!Z5XHqY$pzD*P1Oo|? zVqWDyCa%RW$n`6{v>1k&;w>E}A(|D;1D4&}MJK#^Rh6^Dn&vrm&t70s zar~;~LWMYjOPRz)@0%?yEx=*aaGb5PxhpU>+@ydON6tw-Z#DhkTCjS)LgD+X>U(s| z_3h9>0ZHAtPT#|x{d$}ebCoN^7!WI(gMn%8Dv%}1gNa*~tvDgBPv?hPL;q8k;T~5c zWRxStGf@d|(CG2v0OAb(jWFfqcI6KK>0&&_b9bEDzK-*?Q(xElD~Vk=rahkEvE9IG z-%jw2yU%q6OSQIICmz%e$sV5RS+UUA|MppO4`HYsOyoR?>bE~Ee(5JdmlU*4>m%3!t z)Vm~F=-Utq1OWdyQxl{(Pxs|C-E`z;rP(-~Mmks{JyRAB@uDagG^r~F@G3QVrejuh z?Yq-x4b^C^C^dBP6zbS$MbXSDcGrChO*viLeF|01a7EWCRD~T?4B0p@O1hSX*-P1F z{Fr^_BP4-Nn}@!!Cm$iJTf&I$oX;Z6XQ5!E;9jyq zlcFA!PHT#yP08vcP+iw_BhGP(6o<563Q8P|>1;|li{F*FMZN9oDM#&g5M6#zPXXKpgpI-x*#ZdYWVh<2sk&D zk;M#}kvAwajeg9Hv#!P<*=De4KyxHnr=p3THZ-L`4UUPSV^Rvu`Z><$^V!RuBbSvP zeU|)k@!j=5CZtMkTrIiTyO)sGmRKxSlPV6qMZ4$dZIP?B)VJ96r=|sZg&|$FN*F`N z!nG=#YzuZrE7^9m-u2ai1T{@&y_N5Yg0AIpe#N|9gb{d|3w9wF#KN^)5JvaL zxry1>3dQUd$B4(?mLiuf(dphi0u1eGC2wT>Ii=mcH$@J+BJHISk!)?SkIUq? znS`v06fWMnZ33OAwwsWZ_kk}bi?AM4O?B?PexU01csKDvS67fgp7PzMUH!PK;kPym=_m zH#U&qJ2_62L zhWZCbhS=k#M5q69uDzE#z;T`XJtLRJ;|v!E5zhfEFgw;)#(L53I?W0QCNl$L2V<`$ z05~q09NIFNOmg;LCkf0_h1K-ZTo#QvSrn|H2`7sJ(O4ymj=bDL0xXBtT4w8`)<0hU z90?Q;z4DUVdghI*?X@adQ>CCkJL$OrU4s1;)Uj)%e1%}hdB&k&BpUr#)&@g!obozp zCEaYnKa}2ooxESaEIBbTk(4yAl*)8DDMGVYOYL26lGYiPG0vkC>jR^MLuHyD?hb*j zO&Psq((eS+0b(9WM`i3PXLHD?<%%pAK=)BGZ&ELM5*Y~z%*pM+3y1x=thrK+Q%$wNW*}?EM%w(FHV#aHjnGX9i?~#d)O~WH2L(ta;o05rv{>}Ykuzr2nl!4Ka zt^MO(^dQP*I!ga~k9>wSvdyIwEoC447y08!PhemF0a?)?QNz>=rTaf1->G-O{#ze+ zb*w0(l&FLdlCdgb0-a;nds|&A?X|?!Y>ULzLJrsk;tJRi6Kh1J7Tr-(i|)WZK{Ohx zCe1^~$nP6U3;#jZRSLA#)H0WKoa^l6CmlUlVU2}i)i(A>>lg_-Nmn#m=eewzR~A}_ zSFJ1FyJ|VHzP~!MqRqgT6}t<-C_t=z8?ii4T@@7Toz){vUVP2sV|JD`es;-fSrZ>@ zlk|*lqeN5rNpG8T!Kf_{?q{8^V2)@KWh4`WXe<({VOXb&ibVre zhCR5V?Cd|-NO;SNO*4jz$HRsWS!41FJWU36_BywLoqg>)0$3WDFIbi-5_Tc`-I%)8 zSFT#QlqH}W0|6AOVkN@i0qd=+I;|@X-?4&;)Nl?agP5E4;sRFq>ZtY4!=B>qtAF4= z|6?@U!PMx~%rrDg`}CDyQy@NIcbUvb5a&`^BBdU(Nb6_cKxowz@SK)K^gIt?YG zi-2SA6mq&Cnt7)wb9z!daBEWzJ`4!!OShlbc#hHT>B8b~y>xrH-nlvdx#o7av&A`h zkg&^Zl+S9&nGX8a-Y2@}A$r9}?&u*Mvt;DksA%eB($w>+nAG-Qx+DrnHWuv z)$qV3>&^$xX*N<}NGHWqKCN6an+b`X)?*K>A-z_l_>Erdw7ha(uoqfGYeY_N$QQY>Ua~D~kI1;k@PI!+z?;b<{)XI?FaU-w@$RA1%>U>= zrrU#U0m62&vl;qW5NBOoKK~Ug^5W8wkErcAm0D*Dr_@^$L>eZuwdj^9Yuoca>;7BL zC?0*@LoD<0rPkUPG$L3xzwoPtHH%s4-+sIHxp>x#S=Xw~mnAjTn@%DB8wCtvx3{3l z(x`K`wwn$+G|j$@MIsS$*<=X;peYaYKqlV&p3BJDviY~xxR~4-tMYp4>a6JX3(2; zb!2Ou>y;yQXVoph4q3sEB6T<>)sgR6buD#`{(bEGg)Y{ScfW|^CSJWbx1L1;-hUUz zZos);s#{gp* z=G-}Bt35JFa$0dbbUoHTa42LcskG*urQ|G7a2 z2qMJbf(s+JGg&5XH6&!EKv0y+W zDo~<=45kQz3@m1-010#4kp>-OpaDV;Atup+4<^3n#(5c{u%Q_s04XGqMsf(k2{h`U z0~vChkOBxlfN6VnX;68m9B3@LhZXP5 zk;WTt^x>lrMI4cY6CmtSrG!n*aipmr^r1i*cntYhhWC}>1{p3Wz}>WAg?8v#rn&V( z8)2;H8ntoBM%zfap`;RTeDTJT4L2B9Q)0x`P?t)3C5IDp;N~k)bdyO%Rdtv-rJ242 z7i_RZ-hnrVc;uOfo_g%L2cLZODZtczH2TZFvgfs=RgAs15$-w9d3+K2HN*! z@kSjWaGM7RWTes5e`3@jAqaevAs`)S>?ffdZ3z1Ym1PWBIaHMIcZ3sFfN+Gf@0|w% z6m^KfMjB(-%mnPtvIatoAcPJ=5Hc!0)fgbm?zbDP;k_CNbGSD~s%ex#1_LocivkrjS8jk!;V{22eiu{88_oFMF{ARJFx7;fY* ztg>Sm92=e|hW+TE1u3Wx%68Q&1tef&B%lcpf*^$>SfNf2Bvl;tz&>CtC=76b!|Tj5 z61v%u~ z9LQ$|I-mduyBY%CL@+}nD!^D4vt7pOb1~DEfeve##wS%w}QGJy%eUE=m5f-1}*3}+}qn<5B;EwtcyZszojf+<|7 zNDA%*@G>W^UvWF<3sf=sSzP;#(h zAIiW6)>JnE3SAXQht=6WIpt5JMK3T*o8Am%P?|*GFFyTrR{t@IRW$+@IFh=pZ(XR4QomM>7V&mg0Iq>ZZ9t0+ALu#wKGRVnpfbxW- zJYO@I)p>0?0SSO`0#QMbCPbiBYodDw@~9?0l3QFIe9J-*2+6JU{L?#AV4*r8OIb9l zj{@eZe?q+orDPx5H4Um=LYo>Q42L zHHrcmBze)Ug*U3juxcTwE(m7*Sool@QESl2q&y$*JGGI@DevClNX z=)F6Iq5gTPOI7ktQ4MQSA6VGulJ`<|0)^`?Xil?zNyzH0vL&5VTyfFgJ-pfdJ4uq#AGZe<#U_ z&5}EiFCi%KMD>?yTy=atUf`C}EfYjwcu6H65 zcz+=9fiKs3EP+M;HB%N61dd}*`~*9N^F?UDTxRkV6m~g~b4sb?ew8x@YoG)1=O|0o zD~tkLp4JAS=0qnz21(~jlu~60a0gG(KO!(@qSAp3l5z<$T)YKOT<}A+M|ogmXs^Zw zYUO^Wwjnsug>2`8taXAXf&zE2AI>6L`;k$3bq3~VLfwXj3lfGjZwYC`}%OIBFJMa}Yr8@jN`|bG{`kcNQN7G>D7y28;(wdsZh{ z)GW^uEeB%}*5XX1(H1X|781h-E&vB@Fpo+hE;KNZcVRAikuH8=6EYA3^dcBHfD$zj z12=#iJ0S!30+8ClFVpcammwC{fsr5?lAUoM`dB?<(*}gsf+my%5+w&-<~Jw?6;NQ3 zBXJg9axDXu1b|Z|M$;xG2_OB~22A5LGH@JqLp3oF16AV_MaeZZpaY7LI~+MSWpg$o zU^6D6Hf-ZIa1&i~vlmixH%FN_3?~G9<2O5L5`sfGhVxcwG<5qBIg>LzmycrE@yGWf1YfI<5mdSQ$LDLp*Dxm;1pxQ_&PIC_J@OVFs2wy~R8!6+OB$lM{12 z*|R;g1wK1T1!B`hlv6%U;*w?9Mca5>)01c9AtZB!Pj*lqDoH##kd`vhML)>~%yK(& zP?#~1LaK8Dx@i#mm_spOjLY;^`!QzFqbjoG14vQ>%pyM1!y3BvJo?0N=kc1FW1J@0 zjqyVvECvGScrnj&C1_wX>}Mn~0zxLqQf5Mv;e%B?h)Vmhn?AB39r7VL*_&N71Wy46 z8N#0)0wQDsBQo+HY-9yRAO%y91W&*#NJ400usA3X2PA+(DzsEBM3l!t0(c`ENd`qz z5Cp>#2X}x12^u4pQ=&zH1yJw=Qa}YMx}vh^fbaPQ20?P`@jO6U zq!?HvL>dNPfDmuM8abMzPTHfJLnTxiC}NYPQ$Ytk)}%b@EN4JD!osDNS0GcmqXA@u z%95o3^(U&qgJ2p4E4Zdd2&R$6LTOs08xjV71 zycwuLQgcQ2h|5}v*Emx(g(ZIFDm@i+L&riy<*aw$DoN#`eejIe8dY~SSbT*geZW=P zsva5gjv&C21m+*;^&^dd zU}$hotZGKqg(ujWtQrMz3>H;t(*{^Y2Tj0SWl*n35(EBKvU_j^QCP2jA*%T*XlN94 zzU3np3IbnX250#Ni=t?wb~q#eiWSO4Ym}qDR3&h*2E&CUKD3)&GOJ}UCS@W5G$I0Q z!XP%O12`FsCcyRGd^)Smk4P5F=!eKqHUqQd$@^PC5sESs{6Qd5V<+40-gH?XK{RFvF6iLh1&XO9o+3R87%|tyENcS2T5JLt&GzJS(REs4Cc=I4GpuQ%NrAvwi@2kCAP*jZCH|blLSxN?P@V(*dtaQ+c z_zR{`${PKfUiI;_LFyi#>$I-rx8l3N^YcT5nzh67XeRfx*$WlKoz&l{81yuyxLj*-&1VK;*OkktiLj_3i1Vpf}yh0;EX^kQU0#DF& zATR{dTm-jC$t7$)AkZ-9fj2E@XWwIv`|-djWkP>O2N=9|+Izy_o5BDWYr#whE({gB zEX6d;t=Wu|+B^hFpw4bZr(nb_ztf#MTz#vEF+{)w$m0}+>n!9MJt`b)DG&m!dceMN$HAAG&u>+RQS`e{Rg zz>mG7Z^{O7x(4!1z&onYQ$jbZ1N!YwPP~Z3c$edfG{4L=NlG*VE;BCaRo*k&Zyay@>MkjlOE{jeq zE6^e^$}K|OBkrUIe!=**PpL(sk_AS3|0ARATdYOY>BGFBq4J_S_$bgoyv=4Ku%Xzm8?nBF(T-g-{G z*!!r~7AJ+Nsg(LtLnG6sDJ*?jc=&|m@v#PYcUCz#bo7HfpH(0?Xns?%A1q}v60@EB z1C#nR-d_NzVpBf3WOyj+qWn|TXAHZ3u1jJwEL|A3I4Q^0mLV$O>XT}1izDk8C$VB{ zkG6hoHKX2pe(ZPK=LPO0ZxHA^`iL=sKZF)SF6umZ(?uizSdVyfcJ?{VX(Z*-x8UoW z^!%HNEvZg=zWc!v(q0GDzMx5b?wX3I!?k0qv2t@#q}_X3&OX|OZSR+s?@qe!nmgv; z2_JT}?65v8ColspP#lOv%wd=~jyYEzvP6@rDb%yAbun@p!{AkPL5p9l{}{@$oK3j)MU@2cE4=a^zHR`Pk|b~#~dEVAMW?A!*j8y05GcnU+@J*-~>d_ z`1R2PmE)%`;{>{0A5Y!_)H5*$;Wwokh6D}1xu+k(66)OtjzRxE<2eVDU-@M4GPdRf zPXGlGItAb-?tfdk#4EU?Te!G;y5hyVj?21_H_k}Hy%t={3QWHLyLKNuz>1y5N4nWn zGQaivAPfkm`zzSbKig+1{SHjX%s1JO$NR;5xw@~p)9<7P%>4Vz{$NVl1>)G}pWKaY z{_Stwk!}C`Z{qoF|A9CR7Xar}o$_z+k5+tv0eAlto`=ePgKF;_zu`4kCSc9$8y3(> zk-7{x>UbTYQ$&}F*+IZa#;Ftl<@0+l1DQ>MAs_{k02H7CTu$??zVg9890eYTdLF7g zX{Pw#e_)4^=uUPme~bapCoDuC#Ug!;#q@=b@v&^qQa>R_YBiKZMR@>K~y)0l21jVt%mG6LbN)1J5|YsrS$N2j%fH?d6Hlu=S8qPylAC9136u zB9F*4CYH=9D^EuXcJPyBV^&PfngIc8NgD;81wpLP%4niuH)hl6jw#{8`i7+weFhDm z2o&29XS$$jBOYjw3BElLf%U>rPUT5K z^`Vwlo_GlYCdz3+5aDXPNA)2fheHVP0GpH#U!UK53CLzW zEDx*_AB?~nq!q4D0WiVBu}20^-*|#C>HL&F+wu9fP5uB8=nu1`7BEHdSbzdxU)66W z>aPTJTJT1ea%VjeOufG`A)nCSl{ziqqX)c!T(To3-;mHSAV39(I?t8+{MPmwUOsA} z5H1Z9{Hnyo&?Tsg_^qzrrMXy=Z;~9KLu|CfQnemDos>I;>B)0Mj~Y1oCXeosOkrSD z5HEwka75bX(LCjhcooA^w;;@+!+0IBNq59V?=>b4SwD#u<3s=gJK2V&>g=IDkgzxh5}f_-zXrj$%Rn~-BA};qU8u;ap~R}kD$gHDb`m6MVqd1 zjYVi7)2!Ti_=9cmG6@UHd^7>VGZjS0e(+qvqAi^x<~S&j2UQ@C{G$vEjyaISLg7qnE8Z!8 zxJQ(g5E4pnSt-+K4ltZh7eKZn8JY@e4|Es=;(>syjrl=>=IM*Xp&^9?@8TQ~k5Ott z5Htj_7sHFNKmnnSr}0P0GzFpn6HozAfDJGOa#tcxq!EY_nPW_dNIED`j)fagAppe< zB*P*06w&}4(q>X12n+!xPz1g}gqmi!g9==MCqR0Fz!X>l<;kSH2T*g1dLWakkorLt ziVf(+V$h&jtbxt~N79NNX(f%s#VBGaBz3@d9^a#9)Iw4_r&PR%_DL-51v zJr2rKDEVTy^MMM$cfCV()_&SRj9_Usa2sJs+aW7Z(#wmF^RYhm#wl?s@y2da00zoG z6~XJY6&cQGEKlc1H)bqONrRNjdq9Io;GLvN`t_V@WN7r2(~L73OQ=8t`-g^+ABQ82 zB*x0oKi(5*KxpxSG~vNNQ}Kq2A6zR`f<_5RB55RlWs+QyP4Y<=!|A~kz@azfAAc!) zkd5$S9&gj}vx>*fh>^>$$KE((`WfBb$C{zF_#Gyq>QqPu-(18-{K{y#0i)uZ$MbNz8ZKQ#%4-90aQQ- z#Gp6^H;qx~=pT7ta1@U8fh;P2p==s>m%I6xF;OUZnUhR$N1#5&_MEge58XLYg< zJ+2wV7r#iXXcKv{I3g~LmK>uC&p9c)g&GEw#dunXB5j-={ZlJkG#mj&6u>!JX}obC zrnY{fI!e>;;-H-oDg?ylu`Bn3tk47K(i+wu1)%PLWo%3-p^oxQ0j^U7hJcNdp{`9q z*hk-}B5~&zkzr6&{oF+L$ryR3|D2)9FnN~H<>*`N9CoLc{6F^SG{IMVcr>Pk*2J5Gl#+tT3L!eS&Ar5ph zhRmR*shTM3{E^;q$i>dBc{UZqGxT74hn!)u^jlOv?RI*U61&DQJ8!dTI)s)GifNOo$cek#tB{ z1k;(QEY3qcxj~kWHLVp@q)=%E8sw-7V2Tn+D|$w=D1}&=K2>VsNlT}i{^(ligit|b zZnEf+QC(jc0)nV5keEt2a5zGp?(nBh6pDdS70PgiC!Ayr=Cg1`MN!wjzzFwNuCNrrb)|6UjZt8!?sd;qI z_{1I6z8q-zKu_gKbuCjN*c{n_0zj(-v8CBZ$#^ky$5b7TO?5|(P~^BgO{f?^p?pW< z&C?cYV1~r$1B}wrgEGr87>6LDfti{%qF4&o;aE1kXn(q+<_YXwC&8Kwv8gsyB}M11 zx~~$3H{?Yn=`i>y8Il($&?7$y#k`LhwdXa|gg`?f>hyR5AM=lZ2{#zj-T+bcsQ*wH z=BN1jETmX^HDHzwe*i&vaxE=qMax1(5H^~p!4Z!lsfh6%ZqC}FJ0tZ%eORv&Ln1`2 zT*1nDIT0+W{DJOquJlK~;x~|`vdkrkbWOp5&?4o+h!)f{o>Y324-17-6{{27Tp?sb z_!tRm9)e43(yk6P3^5yi)EjSyexSYj(39MrO4 zb*I`CSD|A1R8k3uo92_|k#^kY9pj1SPsacO2pKTJESB(ooGtumu93JC-)v)St)KPY zX+qtCJ|?IM!HiPWL>9B9N(BZDb$zH%>_4PQeBu`CjK-rp#M4nG)bv_GUEen9Fr+U= z9FE|6IT9&;#Sybrc{UH_ctZC`7_}#3^nEr^)Dk{S$rsd*-RL|>2a*c)3TPAbv;CtD z7SX#yDVGjyaXPLqcScuh*dgA-;gEEZ3PRGrHtHPr7bH!n>hW(}451Yt=AxVEkPJu4 z4p`Xw70c6W%c`-JW1c4V7$E9neb|>H(qHN>&U4ndADUfaNygPakGbdutqmz9tPH|e0|~0UTQqQXq{R5O10;OtP!~%pR0npV70-jy z3W#WHQbWk=;Etv4SqQ?%;eTMzT>2ZQ?WeI7%EJUE)Da+eE!PRW+#q=cAnv?Pun}@T zVGizD2jc|OL!tnspA}rGhZZl5wX|f)5$L`F*txI%X!+2%%(IX}Sxbrs&*fdx9c_l^ zs1C;3oOaY{BWIx1zWBXRSlCo9CzBJOLnZQ)>&83T02IP7_*PaF-IY_x0E!$Krn9ri zQe0{USurjUotEWkN8z#Zp*D4)u~GmiihVEz{8V>wM>)#5spKyW!g)(2D9^5q~x1 zw%8$K69O0_+#E@Ws4RDlown*^1$E#u!!s8$`LvY(r+h+(}wC_UIxkreA z-j2NV3b|gWTxS*MdxVel%fH6N;~lcB)EYVqaAZ~0F1dp)U=r!x4(_W|yrevPx=~72 zoS2DMH7y=BijZ_*LW04{VLPgf1mSYgKe#zm;q>6T6PDDiR&oS@&ymtii3|8H zDcr#GbKgU$<75%o?y8jIQ6A1Fv^clfG~E`R9_Ug6(5I3gaiXY@f!)=&%ELn;z>bXp zfiBP{g{VN;{VgFN497NA@#-Q~4|rK0!3J=v`yk2c3GOvNn9;2|1s!87>`WAj!4k7s zMod_DURf)yRj(dmW42do2wx>C9?Pg*7JZ63ca~iTS(GY&@Yb(ZUj8X)Kdqz;Jb{s# z`ZEr3pz2_VOv2{Tc(@fgoEK+}rFoe;wWjqC4oL(hEbfR@V-!7Ug-2Mj)S9%JHf zx?m%EXhE$St*y|sX`Z9$sULV_LM=qfu?j&4x@%VehPWBJS;pzH6eK85Gt;fT+ z-VTsMaG|a+^us0-5CaH@I*23c1SWq)^_nUW*+~R+0PVD$<<5-yPBGLbEul5E#4jM7 z5#DzKG@oY+I*k30{88R`j6HM7_9Tbh5-NO8&5_F33i)&o;ll);&$;^Snq32Qf51$| zSz^uQPCkfR39QwaJhedwoMH@a^q{dcwV#|;oa#Eg z3`aNk@+Qhu;G|(_x4KZ8S)_m>>=cRUwY65-+_6ES?kClcBJ>xJTBGTVEpb}Kq1IIi z>lm8M{E`qrse(W9T9OCG<4%*zq{Xv{Zm6MwXUK`iF?;Pp7Wo-NFmKvG>nRHh$zwuu zNo2YDWkp{4<75|^M-i{1xc=(H72uZE@PJ}sdM6+nA&4`$7Ju6>csa-|d&vW6a0=8kyrEBG#&zAdr({H4TSFOMkVhQgfl(0L z9afLqJmMndPykO(KD8xNx~o(%EX7#(4g|PTA^H@PV)ldzGQcVFWl=}}LZV3k0#(|~ zLYd1Z*&;FGozb4MElJ6pdy8}j=aEYDS#wNc8|cK6Sg|Fm!}c(mANd^EnC@Br!%Mjo z3m2CHbv-SJHjdYLDo4)SYHHc4eO`de54GTv#6dz-FbH_lW!3TKXlt0I%?++>%gwaN zR%#F-Y>x-sw6}-DA!ANMViUJfh$K{mRYkS|bu1FO^h>lHUl`6F++uU2;)>u-1-)^&agddI?5 z{xm-oMs}^w-Fb~VHbv{tGOe>}Py?`Yzzv*$1+jTuRE^ZWn^C!5j)*KtrZoOrZr}$9 z&}uTJr8jndPO~UVF^g&8N+lnw$G%Hmk4Xttn;UGu=)X0tlm}ABX=c1F_XDsFZuxmw zvk=Ibl=1Xyg|&M+Vt3F^3u{3%@(k1hVo>8&wn~>7x@4L;z9Mta>kdSt@SaC0?TQM9bkz%hgSO*b zQg23Wx`#{2%}e>ieot8ii@^&F3h=otK$&g-{&={SxNRx`S9*798XhI7Zz_m`Z~#4QtulyY+n_ih zd`7hhV@1rsL5a1vzNM7=21--eJ?$MJF|C@o-|}1vc;Xm@Ic!X@an1ZZrr_Xwd1ue1 z97deWLWeR?%^!oN+!%z%5tWfPR5;a4Dvb-8iaodA8-NCSPHF)1p!Qvq5ny2!fCriY z7G?#ovJ!_ttWA$u?cPO_cx>C50Doux%)$+F443w#_TL!L06IYjH8+*Zc~CSqnHSO| zFhPuZF^k|-1?93r#0u>onn+7|3pYE2I&|wIz-2rev`Ac#{~IMrSt1=X`^O@$gPjA2 z7tRUprH<{}b3fgQ#T;q?xWo_7;q2#`Q7v1;s`|nETQuK$UmSmk-;>IT(dOY0mExdQDtKmE|hpi*Ms+$a_-?88@D0T<}N?LmQIYrjiz%jj%j<^cPmmRfIXT%9Ffh z4vs$5F9atElV0&|m{v%h*l z<5Hb%Le9jly>f1#*Bb03=8f70Htb4m5k~$r-QqWNiTT-07PzhaRIl!g(JEVEo%4~f zqAV6mL1XU@btG{eVK2h4&CB@5;W(Fml4VBILds0Jg`z9z^VSXOMH<}(vU0x!KgYTS z_$nq#=a>rkImW_bH{p#dM^I-FAW8`3_Ai7FlMt`&kolp3?U@eA$-bc?<(@N_57W#H zkfAeR)c6A?eRM@1-3b zsu2Fk4%fhSe{vjml1A8XjTY}Qg~7M&ed-;L9cY?Ic=^yBZCMao=N%}Bh5!#}0d^ph z>2_2io857dMTq)Z%AE-YK4YmuXn_jIR`6hEhmjPuvk8QKFT)B@kR%WUgaDDmeMuE* z8q(#lby@P4+JYQXg;+iBo9;dskr&K!#U_^C!gl0IU6aql@<~%+syC1nVc$y_0+GR< zD2|_ISzBk1anK~#H;&#P49YG6@q2&(yf$BP@%1t)a-J84Y52Zv#@9)D}Dsb}v*@)Ga7rxxy*dhptb+ z3!O^3ZxQ{1u)30QP!w`bbZ_Z7D&@(SBjBy^Hh;0eGqFazur<1=4ijuVe9SU6KQ}lG z@%dz`W53A%V9jCB+dKC)Gp-6OrpupSWWqMluiD06+D~4=UX;+hJlAJ!xv+5Q@R_V5 zE9r#au;JbLp3?KKjMN8rvQG++t(<`^37|OqOX!C`%4?S-g)(sV-*a_wmpt{3oP3a|kpp)f>OU}1n4JI`VBOd*HaPyzZ=T-!55*Ajx- z-X*cBY4t0u+z@!9$=;P0^bOwp+Z=OWuHKH69on1$3u_o&7_4_&Do5WF_O#W9+G&rUTtpWN z>qmNT4fpPO2<6#H=4OKgWr7z^^t5SygAf#Caw#SNTWvCE=yU{xrUPRkbBbNl6y&7{ zn$FQ>clA+D7n&3RW?o0%j%S%rT@c@0vg9=?ibGCDwkcBNkqC#wygfYHB_uX9eic>Y zM{_w~#2aMvh1D4=m(9if@k9Gp+BLY*KyDW)6~GZ)KFrFY0ZL9Nz>TmGIY$LVk7YZ| zNeJNNM|o%zn$T`?l$k&--U-B=6%-cDiqz%hRDNC#=i^yAuUy71fLtF9!a%O%{4)F#}9`V5&IDx?%%~D>Zm;oIH7S1(I zb1-SKaeqP&Zuz6feOjLK`_h~xx z-v(uZsc9V4?~syYS?M0&!PYqmb6NptXQ^@BpUfro$y_(!nfBm$Yte;#Vt<(sMBr6FgBei?Ukz1$`2=A|`uA8JgVz)YaF`7# z&R_u6UOaiQ&j00Bh+o~H*l>f@U+miPpoF|e3RrzbB|u2HLl9PyNe<5im9R9~gMZLh z(^gZubWCaAv|~fg`+uTVN01;=On% zP(e`z2mw<73`7M~0Wi>n0s_c*El`bjq5mRPA&XP|nw z%^7o258%-QzHKH1aW%;Ob2ee6EPz z$CRyJ6o#+>P*qd|)$2AhnN$}_N>*oZUD;f3BnGusK-SYHESPy}k-c{YELOjf47dr2 zd4payhg6A3p_ny9T$MqWo}IDS!G_mi8wXFg2WtcQr|KyHyP+6C%Q-2XRdOf->_fZ- zIiy*L0E&SO&;sB9I6zNO9qvC3;u14O2mzPXg)l|r05iZ1&;rB&I6zTS9V!4@ob-UL zT_=;3jYS>~P9u$`;~tJ}x&?L;RFqo;R{`OpOd}6mHKcI-ZcGYDhDOzUU`l626y1pb zp6lb3%}dzR?{X}G0K!Kg@jO_Dl$8lFBi?aOT^?6qC;&PD=CeHrRJ#TfK>H9y+?q-^ zCGlKG7++}l@CQYJ5Ksji0V%@~P^{%$BhizisX#k0SP0nhu}vUAvJ{8p5`NrCQD8hG zKFV+*(%n!dMuCy|0f9pkJ2gNxW5K0?U_B4j%~PjLZm?N0q*x#Q9yim%-j z)F{3)^wp1G75z<<4h`gwH8hHjump~PL23~Y_k_IO-(!(w1)EE0yx;+4h&e2d^> zxEO-?0OVr1Xf7TZy#5ptL+>fB;fitLG?%F<%o z=wZf$6|j0734Q4NIlWb?4t8RJkHkVDjA zc9;~?5dIW;*d-`x7#n!Z8@NimI*Y>?_A$l@Un9#{l#xG<4aayx7#m;Q!sdRUV=YH8 zBFTtmip=`sHZms+Lfp6@^eC7|x@3jdX{@=ctX*VtdmMlj`VMj$Zy?D)9~08Q(`% z0Zp-;V*&IGTQ~{D2IHB76oeD7D;xnhUY@x6Bt!>Nol#FT5ul9`wNmI4LyA53G3 z2{z=@m{#3TTvt9c4&TF^Kr5OJD;qB|kFgK(i9y8FBoxdA;ZY#iYsp0bN#^ll09Xpq zee8F+y=qQAE;^XEJf^9($p4A6WOk0G9e<%k)O$t^r_BXJP zNkT>CKYmN5k`nTzFkyg4pP&%MCSTF%BSy(sS!*CuB0dTs;Q*XhLgV!S*RRduif=z`P|Lug%p16vB%I#HD6<;Zalo zRp0`cC6*8nfDO3-0fY-s2dD`0$q+CEBq6y__25Ue0H?`>00amvXTU0hNZJ$DV_!H$ zaSy@96z~L0K2KUxq~}3L62&;fctw7>*-J#JlWGEE*1+T^pqO?s100XV5l+LB?NHiVyqMEeK|5Cdo~ zdLf3hof(eH3^YTd;CSa`@bKN4g8>~6Pz3%7KtP1(o?S?5N<{>u#Zg2O^+>U(4RU~j zQk&on#bl}wBTOSF0W9SGnK!9zUAJj4{Z z2lfy?6h82eK@Etf5Sb7j+zQzrnL|84AX(WFl753B$=fB8i=+=Q`K%(+f=J?2K9x{q zROwXKBTNlja2og#i37@lNJ^C&fj~l#lnb~)On{Kc1U0}7U=zFyfx%6X6Nm&@19FfY zECzo8SGgHzB$NS1VjTz!*nwQBSMHS)!3&@Q$Rb5U=Ydte2#DlR@o7vdB9IAULhk4ej7il5Jk*xO!(?LKATjfjvuKiVCfWn9fl`DI zD!>acG-yP%9Vt;gq5(NZeLy1whPp#?9HN$LzxQG~H02y$&Oe0Q&tAa&sKPG{EDOf=nQIUN)2xSPF&2%{|=$8_LKoee) zJp0HOfLnY4bATO?S%f@D-Wi}-m=0FJ7mz(@56lb<#DACsUe~{aBovqjW`en3!gn;! zqEgss78ZnrNd!=s%}f#yV$=tIWp(884N<^D8Oc&0M!cN^kx+$SMwH>SAh; zx*)X>f`q0d0OuWSQBgGoTVa~Sk2nx&8h|$dIC8)k5cmOq^kqTu zU8(@pNKC*4fG=ObT|p(N0Dg-=GY5zPGC%@QX9_gY5LBQ7_#gZPf0?61J}<%-fCu0K z{7Y<+qm-8_z@THoBngPjg94#Y0aAb+gtAzgnC6AqETI6IORtasw3tyMd1DAJM=(}O zgv5DEF2x)8Iz>gwWdd+1uvh*?qggo20cXG#ARAx}U4VblViGj=6{}#Eh;)*S5@I-^ zHva@I1zm7SLzb|RTsjafW)kooo=RH+X4FPjLb@K}(tg~7xe!1BM(AzE$QdvMWsN}M z8IS;Mo1w&efCgj^tS0z^H`JMU0}3D^+(0To3XnOR0eHh8wK<>w11De-7JzZa02(L92?HP!2BTCIbTAyo zi-oYx_)MLqCLDljUY&K<;?Q+c2`GSkiLJOYNP@lLK$rn%f+9mBv|LAk5dZ~D z5hcJCB!QIx&x7>VGIk!NCyQVc)hb`-zG-I`6m|doX*LKfNdV|6dI~h0=bNC& zaGq0y@(BWY1bBCj zh1W7!G#3nL3E+U538*LXfO@)~90*G= ze>x(!)tS<7(mN@@2I@x)QXgm;5rVd#5GWG$dd37BsH-u1ZlJMNLZE62pb7#3Iz_Mq z;ZvK?L_B>6=%Qve^q}x(e9(i!2SdsbT2fx1B4P#_fVQ7IsC&SE0v1O~0opyZpF!vo zs@AYqR%qR$KCYN7-S4pIu$Ow<;W7s_n3ZP->K-7UID#Lcw@IHYLAUwu=|_zp-arG= zTykjChZqh4NB{-#3%*>4;SH#_{Q&c(av2k}m?(tUwmCLP(AD5pQidU21avXsz*h7Q z-XL`D2Mj?Vnxh~qYUtCqapC}bVoZ;oW1sMT1j zjH0y)&XCE(Xk~yU8WUimW~d;6B-jn2Xsyy>(tvkp9x4UAqN}LO)<56?!;CMg0>q+A z0@NpS*`h1~E;_hvoKr(DI*K}@d?*D$a}lGx=17J$B%`os-O`MnqN(V%854|Tfd&>a zUIGs$0vLLxh@lAPs8)vRZK7z4Nl4T{amXh(1=OD3Wf-Cxp)x(+4{!oNqb9+n(2BC5 zCP7ZYzqFzcOO9fKwFElAH5!ak5Q(Na$`U-Jrb0y8Vg`mS&@*b0ngkdr4xo{eqAr&z zDu`aB`axqkl7ax+C_xI)*$!C4N=lBpqz`EhU<0hAcqj#7k~*X*X%27$;H1K+7C@7x zq_V+HdW|*#Ou!Vt1k`w3hb5|L8l!u`&#B8mrRk`k(PCDMSZP+Om2Rb6X;R(2a%#ST@hCsR6vz$WOP(obtQcbept;FJMR92ufRJ_%ooCvaeLex9=jiD` zhyYRo@F0QaE_T36FqpDv3&LS)Xutu2=>$q3HlVqS8PJ&KE{_;wiil7a4g{-dg4U&K z&Fra}&J`&DXX*nKrbLTp3WAEJO+*O_nu-jaWn7bO6vnr)!8U3%j2c~|JH*i`B_N@6 z2}lW&;uzhnv~Q{HvJz7jqaZ-dch2=(85gz&p7ll+qaGh?&|Wg)1MB zZS9E2bPp(ilU9VPZoT+W7bMJH3m{ZJ+4Eqeaf}5`*>i~1RO3wJJPW!6(*Q$xY@*e= z+poE(jy^y$w=4<+pff+X9;zse&ua5I6z)E-3QOaU&>b9ek1 z`^&ft$RWs-gmXv0N$#{$;00AJ00SNnD$XrT>z|rb+sm1r80=RO?oNvxgX&3SL-^TT(p-{1F3+TK*F?tP=-$gB3%5$Fi<4@y`9t?Y3Tjfd z<2==ygaiRmHsxuxkA&hc_Xzo@`U0iuf?D$WgkIjF+V&dg>U2}B3nu6y2U#AaZ3qbD z_AwRu9$MA;Vq8c!xWuT&PT1T3g;{~uUb$zrwvn%XfoIJnAV0ZqudJj-b-GHw{6n3$ zr%qyd5&%`KG**7eB<7hWRclrk^1f`(&aLi_a1;Ik@x@*37fHpIJR5Zh!gX7MqWroW zw-Lw}w8z`e{q)l3LywA^a%E^=kn}Hs{34bBwV7TMXc{2@9+%%T~}9M zI?K-yY)hG36;0AH?RLs=M?RE852b48?1|XSd1hoKty+0h7pAbBlIQjEZ z_L_vJ{0h9haEe_=`PVt@$F=Y#m%SXxuB-x0+7>*ixrk&Gz7EvbG&HE{8D0(u@>){r zt}iI6?#*_fBEJ-%JC4X|{7aIBPtPi_z$_MYt+PRdzA1K>IJQNRl)GNjYhmaK-Oquc z1bUi{exUS+3<+<)+AmvOFmCT=Gt4&J7tZ9UP3@54k@RMQWu*0axWsG^nWmX!Kh5jJ z#yk@r%>CJw5b*%dEYIe8q`kqjiZRU=Qcqhr$gfs%pzyK``SMV>R_XPG-ih$VIw+<7 z<372=>w@~H!bHggeJv}@6=bE^UXMLm-@TTJs-OIhWUx_Z0voSIEfvJ}|i!&3L4SS7M7EJ3vh@E1ny zlyV^M3VNMLiYPwgJc|OMfR-3SPr5#^%e^8>zOm^pnicy&6aQ%6zSJ|#rKo{Ixy!FW z&MUwZJXaf1yExH1*wk5n1M~lE40qcId(oMfAzUk5cUgl5>L9yufar!`Bm-A-fynLN z-nJ$*VI!~VLyP#=Tv+Uq| zX>C~Ez*c^;wgBVaf_aZhP@n`=mN`Sk2T6`V>|LcSF7{`*FG@py)#f30eihBPQqPfAJAlh8!ZYP0o1{yUP4@o1+jV#pH*GUQ?o%{#~m(X_sgs$cp=+14X0PHghg2a1(!@d zP0cj(A6^ADr3!;pfJ>7Bn^SgzcZq4Zh31a$K-Uvi`cAW*ML*NJj=~fPuG|?s|J<9i zPawvihcz~D_$99S=ji+f0U;VO!ko*&t)hf{&{StvQ~C4%0$U2})miaAubK}1$Ug_X zN`+o7zLv2I004yPHXFjW-(0HBVJxj{AA_KkxnPWI3Z8yX#M}?0VB~*SE1T^2;miXT zL^K7W6=#rCxk6EzMxZ^UecLe~`AMsdlgxs$Am-IW7;}?}Q)p%vi)n(g1H(RW za&e`()A13{X`a)o4)4vF1@1cHA+BIasa6P(xKCo`^mnUFkE9YnQ$HdoT>!4i{7&10 z=vI03@ZHTzO7RgKu*u(9DrEELfwmS&4Z08jEhO1yM9K0NQfZ#9K2D(z-#k1X^PPH0}L+o3IlZP7<<)fW(& zdg1QyE-4@XrQMNg!TR;EaIxNA0ir1fKJ{gDz2sy^%?@+!kI?SQe?p~Ui;Vbls_}ud z)_XL&<0C`QX*SeY91#S%Cy3nR354R`N6FUvC355@)azc1YRV254rhx>+ar-BE4VQns@;KUlf0Wqd2G)-|T7VTn?R_oHgk zeB29!PIA6uIadBXl@y%cA!KrDZlx37ITX&d@wrz`uwNOSr_#_o@i0`=c;kK7=AmL0 ziEm%>!5&oHV32(3y+mj9;kS_sp_*Z%`WF4J;Mo7#IUuqQ76tPEB<;%5c$7~P{eUs= z&RZu0Y>%XgI?Z8n+WG@3k<{Lc!h%|h*6|{T~>BKtngz;*Zxs> zvNqSteX+=!TdkAskrsJJ8`x6qSCsLwpfQbu6ndxSuK99uxmicnz*Xsp5fnt}qYyWf z{Ejk*OWmp?P8?U)Wmo=&nFG5j*0J$OU|=bWYXJ8x2Z8E75seJ|G42G6-5Zr#=CfpR zBi_rqgCeROUp{T*GQ%+yMs$tqrT6gd0Q@iqf9`VODH{(7kI(Nt!II<0oBIrK7TT|l ziyj|YmO5fB*hOjfUVFQs2yi^pBxz~GGq1fnklL?q9m@$^k^1--kJW^nmxgj3e^YLY z+H7VeS#;|cEM6dsEzvxDoI+CDEl^3ihwWL~>&e$&HD*1`g)_|%igonIv>ttu1A_n+ z3i1Ho)-_cW?1@;y&;PDCC&{$l1(i39C4nM7QPJMVgaY*|YeIYz897m~NJ5wiutDz{ z(uM;m5KtJXgzgStM0XelN+#IiFiQMr0i;Au9lw7IdSG>lz7g<2JZlv&OSslrv$1L- zYe;$Kh~@>@0L`O$b?sLL+u_nt+(^@UZ4q$!4bI0!G7FSB#`}@90N5qI!7e(peeb{x zg${rdf>11ElZQUnvef8WjJi>;@CE6BK{OQer@W*9LYdON3gn8tC7dxqmOmM6`$yeq zQ%7pa3r@i54E<-+3<&fgi6!l8;cwa!(ZvF!vFZ3hCAb*6ty}>C)WbGoAQ6P?7T@sH z!8ariS?*_K0YeCQg7JOEDw_Fxl2O9UJ$e;g0+8k-U*i`s*b~2ia#%}&FWvw)uYfQX z!$b+VG74qc&|JfzN*Kr<)3^IYW;wVLf3uDXw-ZvjK|LOjH`#k&2ANjJ^4(Qd}H#5egqDXembG}NZH+Z3;va=672o2j6#HJ&5vOUoHA59 zoTk6@3Ftra{1{R?^txI`g)49HlV5QtWkV0Fj!OkS22hpYVLN_PE?P~@n1hn9G=1+? zk^qWh{^jsU2@7s;L}VTj9E(4B3@8oEFbxesii))G<}TXWo+iLLg?pI(9DywZE+~<~ z{jSOHID#%t|A6*g>4L&b;E=_~zr4OytAYj%y?09iwcF&_uxda~tjQ#3 zj2I_D9H4(oq;&sg3)%K1v`|mIi2xQ6t)qF(o9T`VmUcjl_xvqY(B52z2M^cmJKkPF z$!^HdVuk~f%!>fLZ9-{-!vy8FGvOhqbQn@o6YN($+~*GRBaT$mn01pgatc}bKe_li z0sULe{^z0+kh>i-1)><-bKkJt^=zG}HYdiqGCKM{v5MrNZLayp%d=Da&nN8^98N@? zbc$@ajj(XV*N41emk?!^hCoNCW7#WFl>l8VJ046A?22>f=Pez9;D~ymHYI7$TJGWl z=mUR1!HdX}h`Jp`Euu~C$eBr$kr|Tawbj?7!5eeBO~cs8)uiVERj{PJAu|bUL%|3x zw;mPKdQZ}4VR|CpO?@Sw!M)WM>NKjKDS{AXwWYjEmC_Pc#IE}0v=u(ZF&fW!XxA{^ z+_x>c+3Q~a%KOnrc(ZiYU$dFG3zFOdu+clDoMGS@hj;5I@v1TJnVx>ip$HP=HcOuA> z0b>tCy?HN)b0^O;_|GWQJ}7f>^N(4-i(dB09E5kqy$jHZwL86<#mssO0R1<;I>o)1z9QMk6Lqj-2=NiiqGpgp9ke7Z}RyJ z3^umSvL(`A9*mK-a^~xhF;+jWuIza=afD+JZVwTST4ox3YkLYb`{y>P)J~o9K1N=& zTHcV)yqS~-Y68KijvMwLw1m0HC0L7y{dsflmYi=AgVKSM%lz~qThq7v6JIPF2d`<%w9tL(cVoogf_&uFT8I9wZS@2TtKSijGnh-{ zI!s#WL)ZM~*+*(fExw?pYkc&l(ja%wZ2wZ6V z7f}iQuymxV#Qko(A>~te>fSraFD?n-0`>;uzbu>!K&{D-?y3kR1cb7Y9cnrC+Uw_w z(&VAv!3xN>^|2tiRlXTpF&av}Rj7K}u4*8>J>kYy8ZM^B#wIntFe=tOaq8mD)qZd4 zG=R=D0~i%hI`GKt-LaMGrA+YsUW8m2^IjRz_OCwA7USj7LJ{rLN2YX-$qEuF|9LRC z{lUTRMAuldTz2EyTl7NhK5D=ZJ9zbgiy8`);GBs~{F3vCd; z`M2gsQAcPLEtH-ih7mM)fLr8Kw6s}cBtM{!9B@c_qYe-N4=|il10z`}18GZ=Mr&w&*??;7OpCV)~o=jZZ6#yAb^?^!7U-+^t@uY@$<$ zaFn$HB2H`VBS^qSl7XrF8`S{*b2vQI1(h+`7Xtb zFf(`4Ew!0Trmy><2a8E9-#tOudrzwKn<9oa+gmP#EiTL3z>UJ+g*WuYo7G<5UuW!fI!~E5T*s9?6MH_hjJ-D;m2~!ha8~Y#_X3z#aal z`;ox;m6vGJehOj2pYb#Hj@!fE7UOGYdfB%ND|msm9e0>JRy~6$HybFvOfC699Y|Ma zyaDlHhVO2Uh)}A(MJGf(TLS}nfAS{B8QRWH%9Q&3Whlx!&-F&$8|JUHAlJv&&kJ5@ zffJoR*TWQdZ?5)0izV25nwcip7>^wzQD3yIXB;m`m}BdOD2YP)(VmkW%1<6Ye3Ew;C(KXo-CuuFUF;!N05N7-@KZbd z(FnYb)ycdg|5g`d^>jb!Q*;OMzD0XAL1VZ_$E!@@z!S1s-wz0Z){@mSV5b-hhlZ&aMpo07Z*zO5nJ4qo*C#1$OK-s1mB znX%^cf#tUCsVbE_^6Ed-dtghgfzq87U>E?7A<20n)qI+d)mHA7m3Y5HDmox=J9w? z=N0LqZqO@CHxB-;EkPhYsJK3|0KmNis>dmz6n}1X#k6%EyMvOPUoKb(imJGHDf4<< z&*1cZ-~GsBzfz*eO3Xea>HZ)DA_AR8$L{@XvJH67f;t(smZ77LL$t^yH6PL*L4&|*&gzrS*CUe*MV*+G{vs~^J>0U8E71s_KR6M`Lwff=hORmaM`<% zPFAJebDR!_eUE&mZ0k%@7;;dyeKwbv1S&r|vk&@{lxFCnpul~oJBn0Ph&e$qne}?f zuIM~UL^Q!(tEFk=eaU}CI`HaLKUABkY3G@>qzILZNBYxhK~I`9z9w4w{(KRhr!}2@ z{XdOgd!8vk_quM{HA@bll6-eipoDUFqEu z7#7uD>NI;oUmsaL-FJv=3O!pmtU3K-5&YHGqxmUI1$1QTg_n9x$s`Kzu%4grC{>H(}B5|BEqVziH3U)R}v zE)nh*zQ@xQ5tz1WeO4FM(I{e52#)Oti74W(Cq2}sL+Ny!OY*(vgf_8>X0iO`7U9CC zuo?xcFGw*F6sK2NwM0_%jDpF*YuzrJ~7vM;$}Tiy9L1?_h{IW7q zjs5*Da-rbI*?a44sOBeDtEXpDQT1P86;GOI`DZ*U7Y!|1FxgMZkqPr9)>C2hU($aU zkAMc&f}7!}!j;Z*6b?c)U?bI;6+^v12&CnBx+SPaDEVz|IR7Q(jYwPA3hBZLR^v|e zDbt$T`GfcMFFG#$qvm6H6ka&VYjY?#pI0*ypR|Cy5ClIyN6 zHE8%O_qp&;ScTJo+^&kYjiH=mhrdDZdqRUI-GpHG?g6x7H82SGmxkF~sLeG(WtBST z@%$ND=9U|V9RId|kiYxip_lEap$m8#cTB48iJY(cV)tP4Q=C|Ll7?)pdJMLw#FQ;U5RJs$qhJ}kNoJXWU`o?y+^ z=1xuEnH_v1@9`+XZ2jH^h=VSIQR@Reo|i3;uRI3LE7)%j z#X`_kT$r0*kFpgoM6S)u-ECl{bQfv%wxUDs_2b~jrRN^aUmA|c&e_TjNj^LtjXr_5 zs*&&dgb5$}sVum6{Q*bxW&2U3QHB$4+*;X^D}7Ig@}~GT`yWGcOc!|j*!E;EH)~7G z*3saGV!qpV&i!CNKhAr+)mN#InlSl0r81ptbv!Ym$}G7f^%@4Y-MG!t)fZw`>?r=Z zE+}d6TGUC^cY5OYu|--tiUo}86LPCcJ* zeL}dgH0Bie{lep;gx?N6IX!SR8o~YAMZZm3e)eGfN`?7L$WNK(Lg#PdKQM*oo$9TXmQ}>y=wF5t~zif>&*f;0? zvTgUUK|P}TmMB5P=GO_GvROeTO2X^!W1uobH`Cr_1Y)9)$;;kYE#!)3T)E$R*1Glg zw^(8FX2r@yl+U%l04#O)VK8u>5aK72qC9;T>Xtluv6&Su^?}yoOM-!XVTrxizT&~7 zH2D$wP$i%6+0sDlHVePNsB_!=3^wECS6P^v0q#v(NAz`otw|Q)*?1xzw^A_S-1~M{c!iGtf*wv z2NLh<))^)`_L_8+hrKM=hO1F~e=K@xv%`d9&1Uo{|M+ImTEV+F86dO7EKc>uJ1t9P zqv$JnMY9cha=X#oTsh{ybiq#wyjQxm)ds!kkzb4n3{yXkBeEsKUxChdyY&Y%>t;(T z!`{c@f%q)LLEtCL)!r}n%R;=S8_BnU+vU?wyPk^fHBY4UmTz6P?b#EHcF`fz8RutB z5k9~o9VX1br0Ji{OUJ6JeYx@B$M8acgyE%fP2q9PzGKuT}gk;{m^qd+<_GyQTQ|bIg=(lzA@RK~R=D+@X|Ncdg<%NqAJn2_5JD_)m*33F4fUcKo_qN4-H!PIa6~ z(ZVN15sj3}#W{COpT!RiHUIqfUX_$XsEsrbVK%J#Byn%}x4&Ir$zG&VfhyPJt_TJ& zgZC{m3a3QOtJptM?|KtH0v0ByUS1%8_m!9RkrhRULf?xVSKp`ej7rxn0YB4b`Zdta zIJa;;=tOq7z5i9rDX^j)QkoWHToqTl|30s?-Zo6<+JH>=Dj5;k&9vsY=P6Qa(52M6 z;%AhP#1yr=YLL>8n7msPJnWVlVE3W=%w?$MGrea-y*p{XYN^s_h9QRaRvdXNk9@@& zQCqb~2!HF~Lk;R{+(s}CP&xrtSiBxUL~h)&b>3q=7Jv1HI63CnYO`ao=2yL z&o!v6E)b=$8V)qe9d&4xCh9m6+2S6SdW{lQ_kOL0fl)Z&52M`oov)U!BJ@l~Y=^Oh zDGuM}e)LH5DWf9$l?C49 z?IrEgE7E&zmvZmBB2IZ|`Lgcl2}Vb8PThCtjxAbdV5W(tlm(J@VL7K!vg5OVw8DWs zoflNZQhG)LeMh|ygV;9Tw-``mD=$ceo;`HYU-+P8Wb`d^i~G@?v)t{Sr9M5ctC<>$ zSEu8FC8q_Z!kiKMpW^sM#3z^t$4#1c7H1=UTj2vlZ7m(|_`eYwr`K90*B7ci^Sf&k zy_Zb==LS_C>#p-uk;$UdIRyEkoN6CXGc*(&Iykmzw5{ByE%OEzTf#ip=)n zwr>pjpV*sV#czr|B>GQM~Q{MyWP_eK0`mq(&~ z10`dM-cqlI)~U3E;V@ztRK4-9+BnBP@7w~gMYveSj<-o1Z6ykR}_-q*K}9Q|I%|LNAeafi&UoQPS0S+i~} z+cBwk@#wLJv5CMK_%ZqmrAL4CCN zZRu!d&z_S^RC2Gr_sQAs?I)AN9V3pD2VtoteHD&y>y)Dnfz&SrfQ8fDVCDC=R0HywZ%JNMaJQlDeBg_ z)fy1E{J}h}`(xv}yxr}yqqWlwKvE3Xfkv(Kkqy z&zJO*XW-mKr(2$g^|k@st*DOI_J49mrmcR_l;gh+k6O3yFp*Dw7QVOP*P0?86#hc? zjZFH+-7Fc|^ndB%?NR<2)VE|lMu}yvXc{kgV6B=qx6Au#>L++x3OZlwXDqz~a;f@? z^D_diRkI()2LBGmBvWtkTuQ6vzXUB@To32BYE8MfP$bSoh9Zh**>5X< zN^r?|v}3s&ejT3qb+k?3)?~)|leViA#LTBI{uX9Q85v-^su|pRQTzhlZSTD+()#GB zyn)2f585~PZ+F|ZUp7AYZa=k?X|PE7A*mf{s@hlbVs`g{$>HM!bj@VHB+{yoEleo= z>1=z%(XIUhojvQY(y1wSJTi39NeSz_Ofct7fNoEPlnE*gu<1k-Zvy+sR4}Y@*?0 zEsK6`nCPrXqQYmI=#pP*#TPs78v1#d(q8Wi>N)T85y|bABOuS@;?sP zU48hBUZVu-@@{* zcRg(*m9SH-(pJe0c%+9LH@$MC2qk1=v@e7x^wXTmO9gdtNuV3D$&oOh&Zza47yF#9 zj5&^B!Y~)_A;>lXR}<+*&_BzSDEDYjR{GUS%PPR7uFQBKA)A$uIz5vlzt)m?P2H?4 zWI9Sy8&WVdNO5a&nJn?&i#}Jm>$$iZmRc}c>KUcRr1>@U9pWdtn;z-2rE|$}sFzY{ z=Yc|3tC|bj?>L6wo~d~{yfJ2h`Au{xP!SpE9%KO0(-}|}Aw~ygGVQl07+7_?o(j_l zvrHtdM+A0lrd|r)miV_ab9!6#4djEI=ZW31=<9#qsZAO62LJgu--!SkvdYHLa3|?s{@YSUJtSJkGB3L2Wy|0W zoilCd;AujOcND-%lilTdZp!EP$6qlo$QC4iHxFf=Ii42;Q1)d1M0yE9n83Of7JzcV zXY9D!f~6l|P=#i{$54g@>@9+?-ZKIlxA`UdH)SN&yyNdnZo@a&DUp@L8Wc4%Rs9N` z$pTFuUKv}J01!opj@nk(gCGYby=t~)S(L%4or4S> zUMcaRu6*!bWo_vcKnMlXWM0O{4aab0U>=~{&X2Uke!ciaKmx=xjV~mD)CmI1c=~xS zwTGq>VZa@L9iW(S)5&3Pt7`%qmp#k@HY%);^YVJ0ug4aNfu#X&lYU{sOM}%&0iY}O zP52Rg;L?M2k$}Qliwr=os2Elaln+$L!{!na<#hoS*&(nT-U$)_Me%B0DOsn;8xpz3 zTceabZoI%Jd|fPy@pPpS2}n0&3sh($!9WMP*>jir zwd6!g$H#+YuQ7&8Rlv}xr})-N%MvjGK!w`pE_|Z zeYR-qngM)Az$oF@OPEvqRLw$;H|##yRkSQtQhk6x$>YeZfj71TF_-=wP~o%313|zb ztR|+mGz18>g5;I!0voY*G@k+On_!2cLZw@(-sV9AWDvV!mRcrFP(856@mG|SSp>G! zG~whAz39vzVDR}Q@@`!fFI_y4RTE>}oq_QTsN$74M$@p0kSd!EdRwA{^ zrB-kh^#=zu*#j$Z4_uxa!et)dkjFEL?D_DVw^Z7c#VkhYzR)jnvcac-tz4D^M_?v_ z`vkaNvdAaX&BjZ4U-XKZtSLhKw?=m?dtm)4XS3^q#C$0iTyCsO;=uJaC@MB?dFVws z&5n(S%&JtD=`Y|@7HqACiTv+xwJxjVy5v7f`O5#sOwDMjFnc)WHrQzG5=ZXxvVeAw zb2mF7m@sul$?_>Sv~32KC|y7>OAfx)kuT@ruH2llCWs01BIDd4Ob~>HjRM2~zVkl; z$1)IIKnkpd3?U;#pauMze$)^LX3YcKq2+g6hz4Qd8_jh;(#qy zLS};^fSXw%g1?AXRS@rZnkcxI=QlMfs7Yr8m*#{4ZZnXR;8Fc|X-=gUoeBs4D=jUP z6a0});s)Hs-ii9+@G8N|`~fZf5wJ#UNX>4Nb4p?1pRf!s86BWp&3N|lv3{JERfNP< zWNZL1kh2rONpoABkpP)|8W@!U=)rttvUGx_L9S_gJ{JKM?8na^&!s_T7IgaHKXz; z+!X`Vnb(cXYiwH6IE}|jV6Kct(;O8L06lU!wH{U{8K%@=d$~=%m#L-o}EE^)a=;|*Z9a*W!@8^fXxynR5 z6fZJ!pi=77u{C8ox{Z%btfOcs-#v4wc!|5K<}%l@JAsaOu{YCj1O`G&&14TWLsO~| z)$NjpZ3}~IDv30wFYsCY8 z0%2x-YR^c<9K(;OBQUp)N#1s$EmhQk{*H^R*FT03Cf+wja(h>d$Nh)*$di+iPN9&Y z6rx*7^K#uK@gQH(^iZMEsjz^|`*oGesPtIFk6_4j{MwYCpNC8%-56!DgxOF{W+9&^ z*tdsueQJ))OoLSI!{CC6az7$4^^LekMU>GN;%l2C5y?UIDy}g$6}U4s=os1U>&-}@ zPpbbhO3xLPV3om7AAt@*aUIN`0n|@@_WP!^oy5hkN&_!=Qlc%_BxAW$B96HmSrmny zdTcA8+2YMb&*`%>6=LnqIkD`P8ZPlTjdjQE8{doaIoBrDD;edAuUvVaz6!BWjw1yQ zbkWdu+2V0XZL>ay6IGdHfkr{*naP7#1s73X$^jt<+^d0|4CC3`Xv8EHB!QNw6lJRU zH?s#Spi5^3PN5zp+tfIvsmccm0z3h5EGu@MhqUwp&!x{xH2U`*8$m~Z}GBn=;E zLp|u_P)39^I>I=wY89}jUTfBemm{E4nD$67LG(8qh|NubmNofv0GZH#bED(YnDU?` zR4!;J-o`o;W!BwLj@=SFL5dVJB$PuwV@89C3K3b%ZC4j0Ljp%Oj^8*>NoJ_i5c1KU zG+)w>NF{-vO8vCRk4UP)SDKnhX$ft9LSM9`SX2Nkjx2zz3&dRNMR$&VFp*h@LY)ec zX(MzJyv`*@vK%d3X30fD0CsSWP(x(>pheX_h^ij_2nu!_A*qxspxk9lUY$iu~U*42;RgA%?(oNY4EBc zF9jT0o_GhWl}g&0gN>G0Y^9A;oFeKweFp`snNP8_ncUPe8a)R`KLZqht%V07HLiXr zOnV+*!VU6cuTH7wq5&xp@m#=TBSTiVB!mMER4%#i+k0-=q{~!_H*x$pMiLnsrI@Yt z1}q?f<|{c3AXKd#@0PEU0-Hk7YVi&hN0Ya!b+F{73MR-^Y?hrOqM^QP0(O*ZiSY&V zDG@`JRtDz+a=CK}5?ZoOw34=XO|U*Q`6mDhEJLt+m~PPaX31(@8bKZqg$iv5Uv;^8CYqq_!aT*#9CrXzTxX~0IAd#N<~Mah(A{!2 znvGE<1DSxpz|tF^%-E{xdWMJe6z>RBDRDQ$cpbg1iqcQfEX(n1>bVu4$xR;e0&KJ0JweaA`}j<1^B@`yzD}Iue4Fs1`-@3jE!-t;P_uwb z^29B{3Y`YcUI;o({EosVi>bwru{?S8B#wsXrQ@)mhm|B8RYLI~iIWKV)HU|XO8Qg= zQkWO_j2Q1^B-y*VK`YINPVluZ6V$q++vse(7(PbDFN{T~m$SqEW|&mYMzJWth4&dL4I(KHZo})=Q@AIF9mD(wsUI3}}}B zD?%YDMq`MJjAk^Wy&I)2A(ilbSeZh9+O5>xphJclD~0H9oGM&>Rk0s+pTaic{uA5| z_jSf^wFd_R`iO0#KN>W&v)X+-B^k73A#$RF!?!#1>R^U0^!I z)txXY;XG;Uk)~l|HV#83kmBUD*h`GJWYk(N4VOBdP)fT71CKY2FYijNm@4x=Nosmm z@#c`HqsAs@>4UE%Bn%LOeiT`h%T>tcIzU)_xUM|Me?r%lo(T@tB(dNtDDS}wcu>=D z?c|0eK@#287)&2b(XMj8A@>8_C(_cq#jDGZSPAR16eqDK;t4wC6T0qbxH-d@gl(XL zlO>IPg$uJ0y#P|9ojAaaz)(9|P4eMlbx}E5)x+W^c^TG?ECG!BB>$B=O}CC|4^Kyf z0+X*m@41(YtEYL7(Kbx7D9hMF?VCV1eIPzvtpid3Sxqqo6Yi5 ziXcruAQm<~oIu9)=!%7kl?_TY^1D3#AX4G@q8eShmq;@b&b{m7T4~fHft!#amjjrn zcTQJW8MM=-SkniPXno~Mn2uGrd%?nDOW=zUE~k-5bsf4DNSWxHr|n2Xi)p5bDU-gG zsAh_YC#KYp^1z@mG9t+0IW}lq);$ep@01StQ!aBVGMEZ>B9|Ith`P!!gt8TDXTGV= zWZCfPkmD9AXYNXjtmrXyt@p{{LMdLlLZzGdb9nw?e837)b}6D#;2`au8N*B~=5s$F zGdYR7opv2<9!=x<-3Z2{T)D{Kssoq;|BZWYIY1QYa>`vTg^DhdwHJ>YmCV3LDdZZr zobOC`1n7X30@$1Aq#5z$ctGRAzp_ZM?2HH-)6WbRAAA;5k41+Zh(`#-k^P@W@t2go4l3RBq&pBR0-5hEp?RN$?1sRCLr zxVti4a&F%@iM=aFvnzS`jx0EehjB1$Zmh#LWAyoY`t%AEy9)G3egfIl>UX42_f4=% zu{WX8GTql+;&wWI`zh?Vf)7uL*te#!v{~@b+IJ!2{+cl1(gJmkISq9Ws#7)zzc%FG zeCgz3i2p{58oZUE*XwcVN02ku2y=La3JaoGn?oB{4w3}={f$OZu<>E3V)SxI)-K5; z^;mKAdhBKcslXbF?04lpbD?CjxqFUM2~Azv-@zFAJ0ui#Iq#(W-1~RTE z!$`~@HAto&NM(*PBq5k+_W@d~GOdM`w^I5nJq5W(;)O|W%dQpqEF4L4NEWP)#kL5_ z0@N2NVloI-iScnj-Ym-yHq`qM4_b-`(*N_PX7WW7WVrk@DmB?FGcj5`x2GhgW-pWE zNO%Aa#4HVu(tpr~Q@0}I8?}DDtL{ofRJM}+tXsgIrDT^n`e4!ib}CQB3+aki~7%@mHC0yEmg~2(J!|oHId)x z&osQAqrS+2<)YWMm}&23`3NFn0JP9-EkecHu@}tJVEzvjl<5jXE-r)HbTZC;bAFHD zkQ1I|6EukQp>J6=g3CbS{n#vpehde(R|&YeR<2W;_y-eZ;`}Q$x|+bxoO~bn9>NbF z{HB68A9z8enL$rS{O@1fCBE|#hAI4 zM3br4H^Qo?XAy>oD(7y;+sOh9QdxgITnyMT5-6%1a>+d4kpJp>gGC;|L4!Hz>h8~Y z{lL}#{4*(c06IK5n`G~VFvEm~QrN3mq*lj%5`5CW0KZQ)lCCY6>vB=a zr`IEq3x-BO4Y3c@Xi(nkHqt*?{(GJUOLmS<)3Ul@Xeji6A&`1$a3cS>acCBTO@a%qn{D^UWEjXzs5c=6SDr1p!XH&svV<8hjFD9 z6M8Xe_%*o0T1;=)B?>DE3%{#7f#Bh!9N$>hkm6R%)bvf@lx8K<x zfpq94Z6c4k^$dBW7+xo6)r`1gR!M%+)pCZpAmz2?^}Lw{oo#rfaSS-{oz(0RSJTHc zwsW3WjICgYRQ;;M$|G*{Iui;=!KsG(6_v_+TFbMme4%UE1E=I3x0##3p820$MEynQ zAgrNB6*Xc6urvV2fSkjvzcZH@sQ5(D zi-9?FpVZhQ9lq(n*6W2>=d3jD^s>FAf2VB}=w0Y&uExUf*19nlbtxLtpc&tvJXdC+m6!$30CWQu>E;!a^GMTn0#+lf<-9q*=k#)X+=wF61DKqcb4w@i_L1s-9Wpf66AG6Uwl>MV&E@kx zicIB~fS<+Zqf$V}1cKXY#Av)WMUIK8!x!+goTQ_duIE|GmR^R83yY@`@b?cO2C9 zE^$CnU>S$rPd*u?a}HZ`{;$2?hQsqKr-Fe= zmEpeQje;ne#t{s)QON%0F79gm;g}td9!BJjyL|JlE;oA|$c7gckvgVUaX56g9k062 z*1`5kTU>|H$u`OB;j5fmZK6yPc-Y6JdaQ!=hz2@{UsOy0uONh|v7UL?t_hS7|m{g=%L~FQ*Q= zdH4aeiFGjvbC&@n4kfyJLAK~bQf)may3=}09JUXu?dIwz2fIH*-Gqr(;GN;nvUDpb zOtYk3zG-DH)R z!Usa0r3nnb-VpUyaPwfhyO^0kk;ttG8)`1kc1#FnLw?~D8=6=zm&~&Ykzu}td_*dx zCd)U0J1+HMj&;dW74{%;ankohj(;q@Z$cOR>b1Y$1fqAwrA}F;4d5`F(mFFn7MABMaCxJ|@ z+!5DlrAh?Nux>d3*qe1R59|r=?&^eZo8o#=jctKU3-zf(ADvPX>RGA#|8+;8rwa+>&8z>R-VB6cAzgnMpGHSYm(-g&6ecU(5ijf2sU z1zDK?aZJ!FJN87G6CM;Nxo2WB2jOJXdWd4-hp@cmRsg z)2@h6PhblQ(t&`rfSV!#M_kzQeKDDGEYLqEFKUIf?u8n?C(5QVTz+7 zfdy3U@J;)Nv6!bYdC*L!NCVaZvnR)Naa}fugf{W`wo-GN|(E18o+p6hj{% zWVTWV?0{)=8>qOyf3prI=uPLZMrV*umwV~T@v8bYo(S*Vbm}r=LAoj~2^v34CNnjU z5v|c+4D8JA@gPyNT0%AxJ!wXqoLN$@#Y6`J2`XdE|6+XAX3fSnzyoODgB&WB_u0-z zx?H-`n4L~kCKEN#SM7*IJ&8I;+eZdnP&bvJX*8q3E#ZQ8pnPB9Yt$!@|MP!_&N3>h zE{wu=3Wgqr?jfZcq?w_+K|nw{Bm@CPFotdzx?$)>S|pT~mX?%}5)=>&Kt#WfpZDK; z*E;vyv-a7~-U5fItV|2;cX1C2cl#~Oni=;Dls9rMcvPa2G}ReYP8F5~Pe?PTM=)TW zN?f82m8HczMlR2GBp>XIs&Cn~cKDbws}a4%jC~h`uBFl-*MxTsinzK3w$~0UK64VV zlTTAOrj#Kz!T@u2D6++9y}?kE(252yqfK@k`4CMpPIMjv*{b4_^Ay%&C!PSqHd}ln zh`Hp(dV?d_B`C~NFHO=PD%QndIiK^0zq}p(wcM&y_>|C#NpJ`#sv-SJFh(#j?pZ5H z<~l=`7Q$*gwRv0ZmjzcuK0!!b8r4W}D&mshfS)M+(MIC7UDSf|Zz|asPba$(o#^~h zn0T9OwvNKT$K8f=RdoDa5aa$=OvpiERvii8p%h3Q>c~83B`D<%eutrksNHTNC!VH? z%KEQ(Yfc(0Vp@OdzfZM>?m;BmW66dDI2pCCqp)&;NR3$b`D@^FX|%GuKQV3PsEM<7 z+%iwy3|2^$Lyd!)Y%X?Doh;))lhl`jazpWowH?oMahFx-b9U|Hcpg)uiV3E{4K{km zLEWH(PrR8Uh@@Lydp^;2BZJhvx_kC}-+ zU+{e}Lt&{`vKdu$IiMsiXS@rec^q-zwDg5u7!F<9b6D#nvC_wtlgReTp2GEQ7I|s3 zp?y%Ont_4-dipCYQTVM@eRo6}CDp)WWcqMj-aWG?%Z1mIeXIYar!w{X^gmVLjh~B9 z{rn%nwS&FOQSgyM;ZNiiAA!p{w1`VdpnaFQ zFxrgzQ#6mEB)9r@S4^LU0v~Y*_$N3(Q@lR%28o+N2#FKxI;qMo;oe14FoF z2_OS*a_}se1x<$q2G5UMHfB&Khu!C@Nupkqq18Bb7~cKqud7h zg^3m$@Kd2|CU4J(i-_dT#pEhwLb;1i@ z#dU{M%w>5#Zr8A)0w?F`ym7HM&$)bDXsaXrIQPTY^!BGSZ4(A^@M1>{Y^#hsTnIz% z&ydF3g^WSXrP`=1m496&@_%u)eF?Nf|J)LUsgfs35`(?aU_fn(A^UitfY*@<_GS0!o`lZz?&xCQZj))jMEBVjQhjSzZ zh`37}Ki3O8z-3QpV#HI7MFXDdgLsvG#zV{R2rpoIxc3 zS$}MKL_RtkEBce)32(2!mKEZ19YMNrVL%l}5&(U)=n{}L46fvxqUbjjHE1hduX_Ij zrWtjgCZG4ktV#qb2$6ppu9A-#FE(UD0v(=IUrcK{h1Jw=C(oK4@MY#oj5_s(_>i(; zxhM8KX7{*D5Fh`FsY}Ma3wBrh++kvo8=k_@o;RXyTp7`_ZY_Bw>x@yP9wK7#6#scw zSJ08b_$bcd4^$vF(~YLueC`%3s*Fr!qR^D7wJ2{qR}>)yReWV4O zCi@!4ehX8^g;nIMG__fTSkvG!eq|h{MBz2)-T`Qy6IzYDnnUs-)$#2hQZ;SffE_=7G10f4=q3`>T905`FmO7wJd zB?mAQ{!kwAgi(!ghARV2MhSIF-Nu@Ky^b^Jw{_q9L7yeR%WZFMXoiJna{Fq81K3L9 z@PkGj+BCO=Wa1mj8G4X+{-peg~dO0)pV{NOVrRRFQrFU9>}-})GgUb^4v>sFrGMd2`hC9 z&<1$z{-cd}@a_daMb%&6v&7SENQ-n+ep;H5w0u;)0pO#d&%N1N11BNCPQm@E7G5Ul zMc_-%d@aEcj*$dE%^wo~OhqZMnHDJ2u>^dY75+;73KAgwhrfIytY7_Gd56xAdn2am z_ep;7OTRp&5`1Y@;=`TN@6(%7s{YI^3oNIxG$zI%OyD0l%@^%TIV={P^AL%uQp1jT_Dee_yuG&1)u#ha&Ge_nrET)9EW(@7cBp91TR`m@ zevVSQ5iQ1k)78Q~_JA*uP;-`R#;8=HA{yxB+@dWd|Af6k`jJRkaYO{3*NwDHKF_H2 zDkmi$Ay5W&Q7bmlRe|+WpO{z?>yJ6Di7w@i>i>eMEl|Ao58r8h^1F**N}EP=lOYfR zQ>GTVtcS{z36vH4z2Er0kf)?pw5#)o$BrTMuq%^Y2a3qwrd+JNGjJ<@R{H(Jkkx!q zgR@F*bIv7VZlCUTOgOXY23uiHn?T-t+#ps#5&n3Q%{IM|Y`y((Ua)&A9N4b9$aNqg zgLkRR`O>)Et0HDJk2{q2w-}Pst4%FNg7Pyfb<$8YE6C|KBB&rt&JwVR&$n93`D)EN5_={$&1S z!0)qb^jA~GPMjHxVxVYtV*i*)qzlZ*v579`Iu;P*tlWW^rM~f-fj%Yv9i`luA|09g zg57DV`j~ig;8%OFp8wT9R>{rk_w0YX-bIOWs18~SpU(pqyoq755-@##S^Z=uY^ z!n?G8L7@|>9r0t{tyTH7j}GehdROHfWB4IE#q5iV6R_yBJjuSfMP(uAiCF=>6}#0* zrh83bI#0ffi$c?II%OuZfb82GnBOLbrJ3x-LOJKwHOLl;{0rELR;XIX5l?8KO8hb~ ziy2UzyK_D#Dti~@i856bGPNDyL-UDbW>X_-YRO&T@AhT4sz~B z?Uck&omPuvuon+yhUP2N6|{Of)}X-4fLW|`zN)VzCP-<}ySV?B z4Hx*kV3&_RB^a1cRRQMu?o?+p_3p`tmPkZ)&$_1p&F} z97bpkU}T<4H5prfc$$BA*?E@c!>qbsk43Pcm~XkP(O-?`1$GMVth=NnQZMFJ!0NhK zPT*w7Xie1`L_pX>8f93^x-Fojm@*_!5}(BT$f&fh{Hgga3Kc&+t*T%$9#hO6q0Eab zCGN%-qP8rV8eY*NZ4b=T#z?_X>%~F%TIF*(Z8pb2-Ev|PfR)SShcj&W$?nsFxaXpZ ziEFcytY&I-<+e9yZDJ0qhE`3%rS947s)yL*QMd%OnYgG;*_rf-6^Tck1my}tf3i}NoC8%q(11hnK$+<}BOl(&q zU%v)j)Ndsdmc=21qR%&xT>PaCr^+VZq|I7F0(C3M^$_c7GnWt<65JhuG|`9-+KW69 z-e5uCpP)~nmc?t5Eh2CEX!5YKf*!{HaY5utF87zBc+TE}miS!?d-FzX<*~v?)ci`C z2xpzxPe(20WiRoIjLZo}WnbF*t0qJ$1sJ6s5$o38LZ^Tnx`nc0u<8#HZ54t@I8b%p zm{&&2{HyLog_+@Oc~_T+q0o6o8I#$KLS@nR)`g}eqe<&h@XatM7EGvI+ya4>EN(*! zDrB){<1P7$*alJfOeNcNQdRel)z@>Z!d_WH3FNA2?sO9CtJpZ511K}@T7{)QV7hS^ z$^Uqi_I=U4@SxA0GF1n6z{1Mc2K6Qy^5zSKXf%zSp51jeQm{6e!*x8zjV@QXh{Bbc zOZ6&6p!H4Q_X1|mz#HK4?QA;1wf$!{!KpACdb^f4)9}jTG496?{iACrO&f1EF#D}j zT6s)_`Y$=nP-OYNqp7^QpERPre2acYZ+DOpF4K$7YWLsxc^ba2JA&(T;;~loUOoj{ zz*AW`Gd*CEn;H6Cb8()fHp0OM&;MaobPh}lI)XfvnCsar}PMe^x;wlTfw~Jp#yD^%-jqule=gDpt3i2m5FB&4VGRT39 zFPB;IPM{ve=lg>*)M*N4GSR=l4>oiPsHgOf@xW?!!2!pR8Kt*~QB&hot!=c4-9Dvxz2rS1U?zkA2?gCC9>`k0k_ub>9CCOR|?LvHxIK`a$N-WiUyX9n;6z ze^#49DyK)tDGCuY=(N=#LtCOmjuqV-bWb*#yGsb%hJAnDv39@-V&$;L3X(c`hGha+ z5CN0`Q5q&8DwW}jbyf}_C~f%O=Ge-|qO<}+J;ULokrdB+m$KK%PJ&6yW%=Pr)K+Zx`?&VG(_S9Q$U2(E-3k7%jG>$f{O!6;gF9pXi zUp}sQk!0(ED)oL~YU_SB7~u$C5{)c)x+pYk%Pre4(pAym$=q7?Rfbfp?4f1K%IZ;Y z;QJ~NQUmnLMXvk4{Y%q)sr9*%j-Ox7oJra#n{%dKH+n+@V+1;N1yGp#FXbA`g_3R> zACnap{G)|mIH72ZW|n%SAEdjj+GscAF7wyBlAi@%>UBxhvl7jNTx`O%)jQqO-@F+y zV%?KI^49ZJpci6c8RKWCm8^T~*o?8z&NBD*wZU+2-Au-PA%n8DK4a%A(L@b@lbuXM>zv-@QrlPFO;}~*>9tTMh&`4on0?nhWskz&Wiy99g^V6tgE5Z!H>@0m`WydMA1_^cmB z({11gN;f%2jiPb^vYD?PFhe+&=ds+n9k92e)9`J?x(?_Uu|OLGzSwiF*F!7)>DH1c zQ3o#VsTXlO11kf+<@lzb*MtyL3Ju*4pC>4f@o-+&Jy$2cIl0pIoFxW>#}Mq$FGFb{ zQcQ!I@t>RUo?=eS)FEc!eOD#|4*JRRyJa8Mp#2+*Z&{JHQi6BE+s3GL7Z(0~0B8Y8 zAzEx{vM3a2{&Po1SGLM?Ot&BRNv)vQVZYtG6pPUSKVwHw&b@dZ^=s=Zn!JCP(SnIZk6aZg!b8}nKg--? z4-pA^VYHepY$5A`84Lke(8ZG&3dk`i*y26-?d{eNSd@zs;Awda_dHbtSN-@x; z`#3E)I;B%^Y!GYE5GBcmD`)=%fyvhdOtqfVC7W!d?HkWtu_DA7J_4xBx_79-2n-QI zBkE>RTVtC^eh;|MG82vqpN_F`D=GmW(K!`hMz9>|V3cH!a)D5VJ8=jqTiMyO{8Tev zQ~r>gkTDj82dvxFv4g44Mgj#@GbtCH^;&1ajLu;6#T{^wT9@1E3uoYJ z3f-ldUhNaMvif_QvB>8QDEEat>Hz6%%6E|FD&*t#B!ogNXK?wOx)~9psEHgCC9Tmm zMlv}b89COsD%#n~KF$dy0ZoQOS7z?JMN_U3lS7^_Klaza-&T;vvw+ul(!T-KI6Rwy zH0-K1fpi`%->E*Kx6UH(@u#hU@xUhxz@t;_A?4+8j4nz>v z{O{|v$w`GiO<6mQ& zyN9&_aZLN+HnB$wcHi+4)>BN-1b2gJ3wC3KAzy|Re-P@%Pbh*FM0b4s{o}SRm3VrH zxCp?H7X9^THV`GJ;e1#qOp~R)-ioI$mT;7Op%So~ zA#B&>FySW){StF)#SUV`B3O3aKN#=3Zt{MMh9A{$0X~e(!;Ax+m2`IU?VVoHP~(wk z?=YC$`Wxc;&K;aW)y5-z6h{}hhG;N=DGOY5nd<9JdLMKO@1t6JCphr#5tTTUb5-pu z21T9v2MEu&?aIvz8|B+DgiyoCJa~+-U5xH;?l*Qm91n%*Wcnq-LTtY{@x98rtBo1Y z#`P2RZy5dSX4=YL9S|8zyAet>yPa_DJGt+|xvkWIc)Be|^8(&c+;@;j2A@=K zdx5XUlCK*?fgeLb^;$>LZ0Rc}DS(x; zNm3Z2kcgV64^8J!lWe(3JiLe!SkRC4M^B~y@gc7Q`jAGLUsxzg9{?NpO+SAFeG`7r zHWNhzXtvV|I;q};h(r=xTby;_{z!EM#|GU<&-e)VzGnqFX1MBQ25l4C>fD^YW~WLGrmf!kApAP1x$CjYzT@LohMI@jBKZn z8-Uw8y0WL-vIwKU6b=GXfq)IM6V?x@>uKO!F8WA7g~%aUZ$JYjOn7>E$HO5yGKY6a zyU9exmyMkJL;m}6GEtFe&&g1x6oMQXskjKesNTR)zv`h%=AG7df0^$k@c!Qy^toW+ z=_bIc>6`Fyzc=+>-p0AlUHaB_5sY#;Q<+?iPAelD)zG>m`ivfsNHkpJW7=kV5=F`j zDsdvAx9;2ggZ^B%6{)vE;ZhIeuef6+#a#o5yVmWv(6?Vn1Wn5k6S1EFKR1ew z*&Uyg+05<_247Q?Vl{MZn(nI6w-!#PB|+tjMks5|n0YSqrsi`K(vs6Tp!DJCEzm~w zhcX`${>3Gbvi%5-EX;ZqPCZ3*clFiagNOwnXyryX%Lkreiv}@|ha4N}miHepbX-s5 ziAsl8el_<$91QAVxwZ>%HN5?aNY-gp*nZgp-aUvR+t*etowfSx7RH{yI6jef z9E}xSlz>s+yvnGDKYP}0Hp*rKZvb|+>*)%(`JHs~Mxl+Eb9lv#V}HGtv48N62l49H zIhqOC;|#rq_tLyPYjfOJ2$bR>r4&i*^UK#C2LjPuH`qsB&sal^o;a1oq#xB~7Smee zQA}qn8P><`$W`+ZPmj?`MeKu9D7>HsD(+sj@gKICP`o&ylV)Np&R-b!7pp<_B#Z;I zVvq_|EQ#nhZWZJObGDDH5nETzZXPrR-PTW#<)0)XzUcO{dEEfPiGBsgt=rzhsy`?l zhD-1;di5rxB)ra*ow1ekef&y=&``9{^w^h3--IZMf~T?Bc{Zft@i8?p_Dgi~LHFd= z@wZUj>Q3icwV{7y1_eZN3t-wPSm9>5CN5ixC4|; z>>-oq<02^@Pq&SQTpL|GLpX_}QR0i-1uF|Z;KbgC$bN3^on2Y1vemhI3(3xO48zkO z@>$iA5BZtQaXLrTw_NE6YG-P?2&=P2#5Cf8^YM$X`IS3Y_kWpKW_rf_&I-dd*e}=R7t`|skQru9DChnrg!M@*R3=3Y6q|{` znLlQJqI>Er8-BsH7Kmr)$EAXcad5iPp>)!C=&$WJ7&mKzvNWLOZh zAar>A{kxESU+a5gF*=HWXfOe60I~v90qq9?(nQVd1YS7oHNZ|e=Gmv#=`?A$lH?Qk z`urviQS8Hs$t2xDgx?ERmn3&h7AJ~+TKUFk(UoqewRdy3JL^l4EZ#<8J$EKk|8T_L zf%ZcV=FdHI`FJoJocgRc3y4GxHzQI0zNU zEr8yI^i&KB@Hjl$-ksfsA9Z~EVpP{Boqjh8nxv&gj+yKhMFN5?@tXs2Wd6j~Ab-$4 zAc(y~IPMHFt@@;5!J5naETL~`0>rs%>lJeu*5!1EoI?%2Z1jhH<-gbYesryhnOaqi zKk`rINwe6{eXLDT{r)B!OT*Wt@{-WUk?C{0is(!Irnq!{YLS+U)KF} z_s`*>e{6cbx08&sv)0MB+dRw2{m_l55xG`@-2>0UqQwT``-x!3-%Y?Jx%gHY|1rb& z$=`c1XRXlG)~%eEq>kUeP88`}1%FOo9b>cq^r~!7^GYJ~iT&HxvPiAuhEpM*Fy8!I z>x!=^j3OGbxtzUsHR36Tdo$J5KY^R!*j)g5=hD|MZ>k3m$2|3wAmN zhm>KK_LeE9$(>WgVHl`fj<`XHP5&;sKX60SmvcX%z&mVNFU-7u$d;`c!!4)3HUhlD zN|o)R1@o!8{)+41{f#^l`z^37qOY=ZOT`qyK}}VFQ-;za;^s(9y>NcaZ_kxWR^9X& ze@T2#SV?(}3;)3O`Xv2)g46x-&quEjXn&l}7Fe8|G<&oE$XugV@7D5^)x}U5{n7^; zY%B~hGNtB0zS9FWkr4^6rw&YP-DO2Q8{B;CxnK5cwCGH4B{|YMzF`vH86_w=q z`4FiTtSD1Q4^8-Dar%MpzS7FB(b}ane!!dMRicvti-zlYFLS{U!6gu?CXU7S^PJaBru$~ zho~65OW1z7{E79tBe$aBtbq)QA&qE}(d4tyoh19F#`v-A4yzQ|JWpe?rf zwl!*lk`Epzk0yC%tNZO2Kz2>FPedF=Ja{*SBwFrL085n(wqUy&pmPd7Rb%9~LlE%- zpaiH0PXb1Ig-Z$P2lt4g7~FAmYE)WzNv7usk)}Wn3V&JL!JgjYSIT(af7Fza{r)nVH~Xyd>7GgE+2Is@f4+kxT()- z2P|%YP!Vhl@O)0|K9Q}}6F50o->Aroa#l-$+=gatK&NGzM%9p}_3h2oXVyb_dQyk~ z-7Xl47$9cxRxAtoJXB!SJop?Okh`+6w4+bB&gda{C;*PmNOT!G#}E@v6zFa z9?d4AX^H&PADWeX=RF0mc$_ zOIvoEW~F9)b@{InZOGdde{!c7g2e$h>%TXpg``0TFdrM##{*MrG;8S)II-aI?Drok z1vOnN-7OcN*uderO=NVs@JtY%k0zoZjxSrygg@>bJB2v@BeAc$a;G0S1wX1l*ZM-_ zjuK}wwu<)_c$adxTZ<6Ifw4OeY~2)Dq(sKFp2Jh=IcJ6s<3Glkt_MoC9;-IyE}~=v>(U z#MMWiO}gO{vq(Hu@5DUQ!j=A_QNjMbzW+R)Dv{QZgV<2V^;9hgV#4fhIS3=qyw~rY z){;)f2f^?x;l6m1rc-joKXfY6#qz9ea*vat{B7Y5+cUJ}$SE*wTU^ob zLXuuxifb?zTW;;zq^P+HSajtXiUrf4XZ6?0kDM}!+-(c2Wy4%iZ2{p7uNz2vz#-0? z_?mxefWb}f`v{K9y)%zQ*#O{6-tYGVcz`L_bSe4d`*FH_BRPu_#?Q+@Z~;CVeh;d* z!X~?=EBGX02u|mqMh7X->mJZ{d5gDzfPh%`bA?0k0=sJ0EE&^u-xBVm^*QTGe5940 zxJ_4d9aqAWzC{KSG5CF#8>T6ODjB)g)E@CPTXgvL9=$%NFm!MGG0EX@kQoE>f4xai zs`aA7GzXl(ygbXp8M?)?ug>3VS{a2rSas^Cr51Swdt+LRoo_U#G?f^7=cEo&m&jO3k%P8)Ji&HM()AEA5PzK9^HJz0)Ap&Qn9z6tO(R&YElxquQ}0zmL4o_)hv8Oqx2u&aPEUrJ!y9P0nXNma#E zMgttfeIgTOPqx|N+>qh4mN zDJ6#Wou6j_wO9Kaz;Ez@ts!6dmoxBe>1py!V^6JP#B(FVsFCl2J>v&B zy#;bP2%~n<|G5Vm9N1z0g*PR?tYK)SE#op*x8isu=}B&^aeLImxb@Q{j)&B{?4AbX z-e@N`GJHBjEG{80mYe&26%m9*ONmd8ht~q&?$O8)^YucLeYIg?t<$F_rWfW|J@7*2 zh9iFzgH4EjnH!*V4-_IL9oOqP$6REw-&Z20l(aa?aXDoy5Ow#pPw@q`G;gbF@mf;- zA4{dS3z<%20`IFio3!2NkYZmcT*V&7J38^PcrY>p0wG6uCKnR?YeBL{rBh&DPV!Lw z;urp2t>Sgjl0))=F5*Umt2JzXmvnBXE4e z)%~H-VzGcs0^ci6E~*3KHm!{ntMGMr${fqe*n(2#APt7)O7DctY=>ZI^@g!B4ZR|% z?hmp{$9hRYvnhl%Ge@oPAQbRt4BHhZ*{li8wit@hWi>#Oa2=~(XDzqt8I8*5Lnpk5 z=a)8eHd|r2pv=P1us^prL{gEuOf;}6%S_cLdX)4QVCPnUI(8;>W&s)DT}Hrit8ay7 z$}JZG!<55l(eFf0vXde%`BKT(Zaqt2NxMbl?tLgu$TM)frM&v8>4e)g+^E<+lx2v4 zLQ7BbpGno!bVVs>fGa6St-7Sh|G&&zcH{%a&FrRbCj&;a*i*?dK0}gCrx97!vMB!= zAEQorJfGC~VA1!Z`#jZPId>E(D1~;H?oHe_6{o?)3Zyry1Qy^%HU9pb%&w0A)_T^b ziIH@9w8iq7ur&s(~@6xg7WU7{g+%<$2--(UtPYbe0I#UHE zAi&J;ReJ^|X+)K1`|{Jjg(q>W56BfJ3GWyM$XBNhR~!YsS>)**xcye7pL|A)&k}WT z%xL=pypoLs33{jYiP8(k5(&k6FwZg~Vcd1hIu39+VZ z3CX5C953JRs)jyCf}CqFbz?YQQtg2Y_O_(Um8`CI3q$o!{^Y&zMm0*;( zbCn}qi&(1h>EypX;xftG;ReJZB;vT2360ys7~EqA{tSL!*sfV{ z%7vx$@YTV7e}gu!u|d$n9d^lfZ6FY0x|h!VVO+w!hr{i;06Ljy|2=tgBU{(hL7j)L zdnv+(H%9>n=s4v<)|BK9T;$!8UXb=iLrGyi;S_NS>HglOr6SS;cVH;A)j#(|C%5PYI3f)O{rD)5|q^$^19s`SDU| zN$}-H5*xdt-d^WWQT&PcL$B#5r#)@6_|A}UzFA?7R!%bTEaw`rZLcEDYW%&&qy#V; zatU-h@^0?V2`pnR66YUn+T0_J&v*k`rI&9Nv5A@0!ISwE0!4e3Uq90xL@`BBvYMtr zfuF%oTMf=wla)lhR&cO53~+_;&>w5C=VF0<&Wwvc_acD(Lr#esp7|6$V10tkh{!ng zjHbHce4|_#`Ci2p6f28?jQ{>?L0gfXYpa{++CG}t% zurd8co3DleNvo96zLP${TQzB~UdmBf7x6MsFTY+qaQb5RK&!Q>sInJjbt{Pg-Ns{^k|t)JFvr{+TH= zMGS6gep3P?R27PU&xrEQ9WVnJ6aP`3lV5-ol}8@lW6`V zw-|LcUVpzQ?1+T^O=d*!K&NAeYebgPRwWt~+$Km@?fA^UGl(k{PXdT?@z*C zp}JHeOB&%!t!Gl4YHVlEtXvG4+TV{a@BLW)5<2^w$TaIGU}O54V%7M;g@wbQ(XV2L zr@uT-m;N&O@%H7a^yHA+E@FNJ7M%2T7L^6;mArI2{d|?aJJVQ-^NSR1m`IeOzyY!ydIeBKm1i)M z2+nScGWu*p{_&aB+hU{ipI!Y-)=rX7)OU6j)?OlSF9+Tu>-00a?ZN!Sv2=N4u~y2S zMq%_%hxx*p6xXbhXX@Z}UKk$RsrstLAe77VZ=jAbtcdeKwWlP07B~=X2d>DbJ12f9 z7djb5aF65D&?Jf8P3mDpviX@C12vuEHX+A91zN4#v@}MZZM8Sw!m}JWJdcS7i%+9g zv<8#--)L~Jm3BmjcxpAB4^X0r@gSWT_53yvw&dr$vlQAWj z?pEKUYsS+E5|1BvU&6yqM;A=&=M zKfFRRmBj_aY1&bE{}{h%XtuEZuKNORw(~k~A)ysdqCYW-e&#UnjcXONXj_dSgCS(dHd?Sc*DLa?rVk zJvW=)_L63&kF~xNl;wVP4lbD~?Ip4?G60 z2&l%&pMKoAWOFNOekM`@Yo=Re_VSlVJBbP0H$ntWgC{}hqxHld zn!Ze1`Ec@|j`Z2WaMQN5y`EYn25GcVW07Pe$YzUe=c$Ra(JP4_!jjMJ0xeeFOLmV=ZSM2-fby~KBuE8o+qPS>1}0hrf9W1Q0Y z{&dRNZb!0y-Spa}r$4EnPdL12=T3mr1C}b;A)cm!6*?H2PhIMG!ar-UVgc28;1DF* z{h~S1kCjkH#@Fu|7MBoxN@yz57s_&FG8A8FHyP&x7wj8&NU}@QQ%dUia8cQ}^Zvue zn%)n88$Yt}T2dqa4U2(488OagJxGz61B%+diivvub|P=f?}wFqV_~*BAM`2mJdOd) z9*VS&&t_b%a#|q8z&B;PSvG}!Yki&3DoU!zv>$L5dYa?nZKF2Za~_$mk@B9`H4xf--n{=k-0Bk{pwkV^kpQa z{xeMc2$6giEvseI^khn}jk~)A_wGMFu3CK4Upy0CQT}ORFq-|>#Cub5qGm|5!qGw) za2+HR&aR9$`Oi1{{UYSPU`|%3sc&Ty)hum=P7B4Gwr2b=UJly>CH4eo*7@_24_-H0 z#&Aj4pVO_ufo1;-W<8i1yes6f8Z8j4_=n-!^cVY!1-3C8mAs@1aFS3GaM4FYj@kS7>Yr2gJ4t9F4I zHmjO2>!?b{TClp3zh2A^|9PkS}q%{=NagVOscQ6yw z9v4~rXR#ue$R(-KOe#3v+jo)+J?Cs$EBIjnDM=?DV_c{h0!R*vq*c{!9pm_7H7dRW z5k#1e9#?5L`pl3OmRQ;}jnPPn(~B~9{`=CIJVKg>V@>9^0@Io9x=hC*3#Ny-&Hrk+ zDe~A&qbdXz_*K1vw7R{q>Ddg9b+LfRA#@M{KtgwD4a=)?i0clQsJ!!)YsIb+c!6LpDHmkYH@7$FKgo0KyEwQLHJ%+Zybd@IMf7 zFe(FL1M*+ROJMla1KCnxhBpbkb8kH7rNyqK|0ZfVkd^0r_{Ua(w6}e}3FUU&sftwZ z@zU~putxi?17yVQY6#c6zayw-p5OU7 zoJ-0};xiw{U$3@M{!K9Qo^xONXn5n?Ru`AxoDGz%_Hr^K9aT^pY*j}-VQLi|jEK~l z^p=Y3m#>a9Ev6^Sji8D0b8~4s_Turdz_oBP6~}^YWYj`E4E}~{Y#5HLKB%POJ7f$e zrDddyj}(|195n^|W(p&JUWY)a{8A`&?JB2tGGmSUiIEzwoF{qxv3Npk z3dzk!8bR@Cahimc*p#)Wvh@aj$RT(=9-NZ)H_WmHUCvtlTG4N{U~9XKoOt&QY|4eO zMF^LN5$Dl7k4s)yOK8*bqLJ}xgRmO9{YUVUpze+K2^U>;=D3NxrAxxz)#))|mu*G8 zS9?^WPW3$=+V68Qy!!a7IL%f_LZ64OE_Iya4dLrI)K0`8$zK}yMbqj&UDl7E{ufEU zt=awKiJTb9FTNCCXKE6pJR<^{F6xTETE+}`FL=t|l-)MHAg%m5Rfk>WnO${g^XD*7 z|CK)3QAfQH_eg+l&YPt2shbmsB~~p%ALpBmN%6E4vgF?AKln-d6cqCE?T3kI)^P^T zwkz-{B&f5;tupOk-`u_aPv&phnz}ynXOTJ8p22m{`!kZ;+_J4}gJx|U`7|Olr{wxP zGfDe7Wg0rD4JK15p=76}xQ_jb{zfKx%N z=I#XF;9Z}PkGmw{NCUtQ)T+H+Uc!e2?7CmV3!p5s3H+p{>C|Z5bo+^5v$=FYmK6Dz z7Bf#)FAQ#g(g5No$cr!dPL|T70zR$zHGMJpiQmzT`5h`XFcRjUuu3$ z2VICf)Ht0pE`K4gYk{05KHV44UfV8cNP`42dR&UV_y9_ zE;^m^C3o6UatQJmX2`%Q1%W%*Denu*wkTd6=VC(^76TqUrLIw!kT`)DJ#wwSC&6>- zxy!%5kxhFM{&aiB9>K}qj)UqXZay2~B`QDuTy+lW9%w4x@%HP8rgS{80>R1hkpmrzb^~>a-O4vu-G)G6A*6p3_iv8 z(-?uyUnv9pBFt#L0_J5E+V>NH-_DjsN|{K0t_Ycthjq24oi(FT zAmN3t*1Na$tfu#`>Nz06IJ4RGz|WMAO0#W=TBp|sZr=?|bC+XX<)6|?0rQA0kBk%C)Fgb4Hgmm`bSmA#`^NzJl_{trqhwbut* zfuJFu(1W;A+>x;nG?D_q<_y%tpl%MDfo)h{#V0m?TT;Fhd~Cf0z69MuLH4xZ-L*t> zPBYHPYQhSL;EDJd*=dJdVBfRSk|j)m!^`Sm37k%OG0YtLZb*ZKlE?|o2Aa@*YQOhD zpa4*S&Hkm4e-JYp0Sj_8w=>?iZ#BriIQF$U+BWOS& z;82?jHj%9Ku*~1uw7c2(I8+aDi&BQ}Q6>nMm90oCPrm zu7FF45stX{0<0_^;ckFPxEa70C@W|ItbE=s4uatJ+MxTOI2eRG5R?G#Rw@7~g**Ti z-~r$iGeYm+@m7pr2wH(DUSxPq;rEs$fNs}F;11b^0}_A$=dBz@gh-Lpjc9|P!n@%8 zgK5SQAPjy6-^`G~nc?M@Goi0C2(g14w{*C{xrLQSQ2sGj8+8T}wH%!P6@FXrJHNflO9WD1l;CrbdB47c5P9fejv%4o~8;%ZkYGf{9B>)^bg;ER=9j)6Ni6xHVjF z@FMAi@c`xtcmSDF#iLkS45yEXI8WCKfQ+rW78>0QBoJ7Wz~HJFG6Xz<2cQSAcmf5C zfoBhfbTPbPum-3c7%SG{<0N5$7e*Z+Ac!O)25ta2fHe#JB3YA9SY_}d*5M?dO38wN zAP$p>4>&yKA!m=3&n77?maa$$plBoq;mKuqdvARA#Nxw+(}5g-o<;`$FjPu_0EQ9u&qI4{B_{)!5t9z+DVoU9zZ7qI&KUc0~A}F1sZWKc$p1A!pNj- z#={X0zi0}>A8^&t`$CBWp28U{0VM!O{0-m{2Z@Ws5hNsWG@(g6F}|{3W|?yLsu&`1 zL3Cjo?eNeZI}qOBRg)UX92_@vIIx4`!S&#LaFm3691w0QFW7;Eqy5T+k39S0h=SZ6#9P zssXa587Ku%N2m^-%S%X?5@bQsf)oEs^v0J57m_@HL!}z79p@)-$DaVI7t*vEz$%a= ze@njy>Hxv4YYO~Ak>nIG->k?J0I+c{!ff0wZX16O;Ku7rJk9T2y4@*9;-F~4 zjV=xV%5^-*9mf)rslNi(e7SJQWe~gQGr%3d7-&{li@yiP07K8!K(Q1}=#@si_;o4d zQ5rP4kf)Z!CijuJ$;|_B@=-ZDwp1>Cgnvp%`yfIJ#C{`_r^B91g_d&H|aZOQ|M)mbL-l#G#0oFEk-f+$Rn#K#5N`VG48?r8ZOq zGa>?5^lpe>2iLi|P=UuG;-d;t(}_buIY9)G&|x}TEJcGnkOD>9@@f|ahm}+jO8Urw zuGXB{RR>{ZXA)Y(m;AG(EvcRwujJ)%P|cpz21ZtpTUmpEq9vQNPL+9`k32_02a&mS zg`aQ-B5xEocHgHZmAJxOK5Z2M5bC4%*<%O|%f2?7QY^KJoM&$|J@b9-dm?DQmF-jW zb`lub(mz6bK}NujxH{*FG9gU?$t=POXhPV%s03cZID6oAlyf9zUIozDZoCHvnC$a3 z{b)0Tkky(iI<~qbnvf931V?!F-fq^4G;F5 zBexw%t;x)Kc~ZZ@+8dRJS%|m?-~vbu^SA~j9)$JK%lbE$)OMcl&R?F32F0ePyFQQz zdAz99L<=t?8FpFjyO;fP#R7L0-KOrnckx{P-GE^qIOZ&jA}eLVdgN6UJ)ytwozoNC z5`VWMM0Ws>{pRc=wp$}W@2~^3_>#m{m);{1Elky7bfED z51}~Uc1{36XC&*;IfY`37;8E>NdpDvyLknDhTa0Wpt}@Kv^D1!z*C}|@iC^LFwe1d zLlYql2kunzL}UzoORzw+qc(xl(GdMIxRVcXFeR##82F7Obpk9djD)j?E^y-T;W^ep z;|f{sn$#i(#Ym0918VhR07O;;fn?yp;`)##WJ%*@vLJ0$F%!mgrm-P|UfouyLZLp&EP*U6WOPiFu#LtL2+9FMQB_Z$A(^v7fPw z=ORv`%v=K|^!dyB#88EvjT55II9zK`90_|+00D;H(hSVh3=Op)iUHX5@eUgFoRr3d z;8{}&*Lq_Fzvy=EYN(zC8N|L!+J=UzA&b>`Ncez;K0~*m?+0+`G=LX?PZLlaG1eOB zpoBXP<~@kr7%f5meTpz`RH}Ysg}`W}O~3<~0mK356ls7QfbGw-eK8n@SCoL`4RNYW zJv|N}2B-mW&lr|{10X;@eYpKkZ-ehyRzFI<-^_)iCP=^5LAh(o0BQg%&4t9ba=u!z zT&|-F+VPFbMZGMdJd(<>Vq7B6N4qUP#rzO7NzOXic=BsREmjOdg625`#%ktu35Lq47Pbo$k5w0D$#_RL! z!?6U402u9T1lc1*+C!qMH(aF<5MybvIb9O!tsb8gd;A7oi#Jg8)K-cR=oS>Ug;mMh zT}z1cE+MChO&sGA5Yg%@`jJb0rHYsyVHx(2>2$ufkR<_ey2}D2>p;~tnz}k&p+R^; z+i6KAEO5Pre$$L?_QbM~Mi52Z3JV-JkV5Ei?RLF+b{|qfy`_VOd~PMg3iqB{@)6x5o|UW?Q^Vx8gO z_73kkZqy#l1$Gp#N1>Jq@e81G+%_da?;4F4QscEo%qZ4x2gaK_llX?ltK$*@h)N=H zy&j`FK*y~xSr-pf*4G0nk4}jCs`U0;Pt|PHBHh1gHR(9@6|`?T_Snx#Z$xeIZNM3LEmkVb4hGU^TWpmb8j zSuiVr3QW^NFw0#GF6ly8umtr{)HI}BCV|~H9H6)T+wQ0X)Rhp$Z5KO6{VTl&>K_mY ziUe_j9>w86MZ-j+9S93z0uc#LltaKLfCETNo98YIeuEX5hgHjNR@xDmJfwUelCMt! zA*i-vAwviVpa9*6dmC%q1;MXK$uR!*0;MZo=^nGDF+UiJ9}b)VS%4A6Lc-)BL+7UF z%^ylZfQ5khB{9$@_&8Hwpeq*?=}o$!J<>lpz8de;PAV#k16HRpQUgh9P*k7`gko|= zEmG0}xc(S7b13PclhMdF-Ozq$UxNOMlOa!BnTi{rw(Akdpr2+j=njH=;W}i|GCN=( z!9z&X%cH#mF#L$-DNBqaRRt#jx;?P2DRJ(@YZH_hYLOR)m~}*3QVg_cDJ-`};C8$; z(?FYOO&(OMPP}gsk7tG$uy*-Z14!wbqx~k<^@;OO+x!FX9FkCVi3#&SXhyHQ1uP$c zh-Dwj?LvnEHJMZ@_wX*Xv)Zra=Ibf?-4vq{Yp3nnc5Ur`L>zj)4=&z6uwp04T}ma5 zCV685YOL7eN7%v%;ku-i+7tI!(?9AEx)cyFVF+S0N)JM}Pi3jsLPpe{17}R;98R;T zobc{ivgUIJzX2o#WCc$+XlR@n1d;P=AM*hz_7ggu;El37NE%jlNwA-An=p$!E%-mi zkai8rj=Ezn3#I2}HQn|ai|*&tAi)0QJ19yB)&T1qNX*ISo6;>1?gy{{NeL-HQH!^5 z0Lm~}ksC0#$K%PE!?arj&@)O};53wnwa^*Vq+=xi=yVP=-G0Pzw706{YIDQh<>g0q_Pz@@tK>^x^IbXOg3)B?eG(ABmLwLgF|G16aw8<<6uCdz-)v zJT~|{3Ch%x{U0LSG603$219LvyUPU32tCJx%MJ8vARGE6+ogxG-n{mIoRbk#!#Kcs(XWl(d_Kaj05cNjM1X~nnZU1?UNRh`YM zmOn#x7Q#;xPUFF$S*xlo*fWjE0{O(JfEvJtc*(^G(F|p*3q%K?=5_)M0SJ9}Yg}CV zpq`j8c?&R1I$KGRWw``?0)K9aM@+Zb+ZgyN<3_W31m8=oW}?4JSJ+c?7FH+lTE!P? zhLaM80eqjl02Q5cOm8Cv*4r8Qy^^k35y5K)5W@HDu)}7HUs3|O%7^9nMV9`sRS9Nu zRzklGndNUsoBi8XX#lrcV!QhCD-IL53p@tynjhyN!EHKNaKn}w-04+3E`*ypJmD_- z#aHnn^VK6pkLKO1;f^mWsF5;XGX`oy01yOG~Ni zLCv5EAkAQATz9K}2>>s~7TEmxhxfS06ee4UBlLJds&LV68L3g%GGxSwz<5f5>+-vb zLYN=6ULpeOQmk@U0OQ8O>C2M0RE{zP`^8z)Ccwle0q$BestRk`ifdtr550Q{3RIH^ z1e2#nvjA07TCobC3>sk8j)(vi4+T)g5BOT~qrq2vc`6n^NTJ2+#Tt5RDqQ?WYZqT} zowNSpPle1u9RT427Vi|0#UoLS@ko?|lg#xBEzp=f$2X=+(upP_JpfQ}=U?6izCt)6bV(z;^2zMM72ihv3mDMTE1i6}oVVd_`th9SpSw}P{ zYT`&CsjNU}A)+L(fX0&s0`WqUB>*8FTH%ntPRA}{&q)mObE@G_PquRt)VlJ1$UIC|HE?!5JE{|rh%zfG5dUoZJnmV7>o^|`XW zq33t=uKD7;Vt&E5pZ~~9=4tce`P=+RK8=;P63vUTGFb)s_WXCghW677$PMK3^KFg@ zy>9-Ypwb(?QlCwGX~lFlAzRwl=VAjuwP5oZd8$0rDmkBjX3i_=lj(dO$gLW< zibeuSVO7`kA~|L>)$(eVhFa!cW`9Li*yz6iOMuZxZ4F0XaZ)^exc`zJy!ir3K8$yx|^yc6i=4c4bWRiM`)iQ;ME}rvv2gMRT z?hXf^AInd#YS72YF!Xg^dKw(Jii1a}XMh>4XmG9iQ9Z2QBrmI%Ge;o?d~-_;p%0pl znntyO`0u9Y{s^c_{J7o z>tRpT%MxyZO=bl>Y01SNJ(jWG&^zcYWjXs|2}p01!Lxs8d9XzG*mKil=WU{F+G<(gUp?e&~Tw_I)+EB(9g)P$Fh4J z^hpvWfpPZA1UOA^u&J0Ggb{xtYOKZ9xMM*Q?^x9<*Cya2M6y1|>jehP$Y3gO|2!ZM z;SDNKm~WcdEsAk}-+9~v_r~-_SYg|a-Y||ECThVdCP-u0znTWt%1x*X1 zfxUs0YRC$_&^vi`-=lZkCo?Qw%loMP4}^Z6xZV)pAufvIN+Z244tS?Cw^n`Lpwspq@d_$meUtP;KLzR|a5 zdi1HFNA|q3O@{sc_r#2NC#>(3^9OsCy+fSXU+x9ywv=qdmGp>I;9c#`d1^{#tb zIbFe0Iyi_VI06_+fLe zHiJowPrpYPBohLaTRAe*&Gm8b|B`pD+tcG-l83q{Y31Toeb-rL*6Fk+=rSET;-_E-@Y$pK%yjS&D>Q-&Xs^L9NGS-2 zOt_jH1-&DbV1?G?ml06D>yvVPp3V;7$v=r9>*N_o`(oNCpJ{cb1Auk=sD1dXEd;?V z>h>(V;^U%-(1m=Cmv9S_Z-rLYHP%P@kbE$L71}~dEK1Ki>Q?yz4GdQMetSW|>Xl9K zlPd7}w3Tq{qsLvmVd?KH`7QbcJ#D@`pUN-b@5WKD|G_Q=gq5+oR|UnGpJS{=goCzl_@7XY);Z3;X<7gFZU%f+o=G z^MQKe{0aR)KS>~v^8p-~-1)+|##KK)J>Q{UdP(j8&?5Q-{ypnNU$a7JU+`P>{`?O9 z`%ZDk*vr&|s*Z1zHBh~>-UfH02UTJB#s=wAFp1~5bbPIrjUdCOkc)Pq&GeB5zjyRDFCvb@+62`=@a68`i4&-8+R|jS8#J1uNClG?*f&`tggqV^wda&mO_XruAw( z+Z((ov#<`~+}!Gg1-W`~ATuSU!1?gizrc4)Z~$Swl+OP~rF-#-ZKnE{_U_%XzNK%) zXIe?_Jo*HD87mRm2few&bHJhXg8{+|e7JCXOq2%gMX6JX)J3x)&D z;*{p~Qa7L&Xb#Mpr;IN6qW}y(1}|5dz+3l~pyU-$p} zL~u_xdm$H5KKRBp&rc0}mnR~(`s5CrHm1W3%=@#m=gt`YeibuN9_#}vX?1Mmq01{G0uWlMN0-2 z(N9HJv?H3j&sTz=mH1D`C=>25Uz&%6KZ#}%zrE?#3=X{OsyFwDT(iM_dj|x z{T_h?G5`0-OY|Y}MvUPfsADFkO*f4B7+Sd##7_NzWXN~(jV zCY@jQWiC|dJ{bBw+^}FjKp|`WHhW^Nz9*a}_%3Hq^-cmHs77H( zJsn?o4!{yOLlL^7;t)wGjAYIwxz1oekTs{hDYRF#pUlV;tK18&HHEbB&IywHT`fO` z$!!34D_c0JSKtrew*^^KEeW?)s|m^R9+z6(6Myh9Wz z$D@><8?M8hCdzUIRI_mc@4`VB6I7vA|=Dw{-%K%K;Yje zAd*fj*}9eB3~#beJA;R0>#qC{asZDSjf;xoa1JIEGZO&r(IOK6P2q0rWM)CbJLn)x zc#tgpNc>FaK?54xY?*SM(*J)0zy6<_$sUfh{+$c83eDDNi$@_1IbL)_7nz3P9RZJP zdt=23Lu_we07tFS4)Ki^rv5K*3Au=XGyyjRXeBWLas!@qLJw^c85hcbpefuiPXIt1 z3vaa;91<`BD<60id}9a;Q*iZu0#x}_Nff*YN_&qjUjQ38XjL8ptk7=1K3V&Nj1b<`)d1ZD9R9}Gz#Tl4;DFv8+kbAB%xqc!7xlUC8Z~%;1 z&jVUKENS^>183N84q=8NFLdAo=RtdaqJCF^6?v2>4FSe!CuzNZQv<($dO^W|NhHI6 ze1EoX;eR)Kej6|dG6+w9Jr`~qVO8Z49c-Wk|6cF}>;rj#gfVX$9y5G^v>~Drm_KWP zAVCd)X%`QGqFY}X#0x_&_A~8ND?qkxoDWj~>VE7qdtPA(TWIMRj~TTlSq=P7^eo9& z87S8#;ysuKfCb!ndJiB$oDc6|DFrKZYAGNBZcG_y%zGmokwOAgS0L1XhZ1ToxEC@A zp$;xcs{`sLasp2ul}St+z*RA4)_yQ_6j8H)=@5Dr!aKu&coba(-&4RPCx8bnMgr*- zn+}yvN`PJzZUlJ<&<&!xjP`iW@@^p%ycMu^|Ey0UcT)M@ZEW7jmruYjSM{rgC+1h9vm}vT_|I z$^tDKC|_j+9}=x7@F0~Ec0!VI_-mtS6LFStqiL9N zt7)2XR32VwBu;x&Y&c#JsDOqjj0*L5(;!3;3@Qp1RaJL8{0szve1B?yhk0y(PDjmX z3W2|V+%V%2QV`%K3=Ky~mJ_ob`*tWKTR+bOdjds&GyytqUVr-m0YVFG;tub0zwjWrhn3YLJ=5D ziyh|(-*vGG)_=4nBM+Dn;eSIBh^#P87T!Hs`UV--=zX4%^ z41o>=I8`EUGHxbryaG!z)Fn(pEGbkJz(FfP;!W#W+%@D67+FFu103uF3;{I&Qa*Bl z2>>Kj!hvRfA}iv7wj@O%S5?U>LTVR634Z7Yqc~0#hHhehVI0v?+6fhW@C5W6)>dH% zaZAlb&46e^bAhZ7Kp|TXXb;vyPk;vv85Z3VKpd(Ik!J%OOimy{O91RgOmCBK%|I<% z<_9e#gcK$O<`4oOKNWHwB@xFOpdd&|LNN<07#fy%7Hj$+s{zeGJu8128bWkY+j>44 z-FhBMX(l*s{sgHuxPYq<7=oQa zFC+jMjC92#yDJuJ6b~F6xlZ;Ad}EY=EiyhBOaa>h>j5n*QWG3-#}jCPxPAtKxPJ`+ zdU?o!zJCpYNE0aq1rl`#c|;XmW;0oB5lj9iOhY;u`Vo*a2>^FxqC=J!qZ-dHa|ss| z<#1q3a&|y8gkDh}K2#0_9C9NhH-J-T6JC*6l7Ap{F=z5}nF9_4z#1D^g3cBT?A$?q8ukl!GQ&Vw|{GZsvS`SfqyRp&`NS$T>Ftq2YTC~#uOGQiTp42m)_=Md zat(b_xC3#4K@iIkhfl@@K@a49zk;YZ`EsFuT_2-ZLppsaBoQ_-xla8>oMQMJJ$&J4 z$VGcR3LRDo5d+BvHyjN^uNk>cqk>z3VuGfE3;`%2wr<34Z35?7D{Jplz(Z0=Y1zSIz3hjjsuTTIem+Kd`xM7u7W0K#S15cQ9L?*voaJE zfNu~LKVu>UK!AHx5PYKt;rTSOcwoX(a;*`9e1U5j7ME>;kZUV??rkMFF&anS&t-bVY1`Iwj#F zMipKp_gbD)(-VsYrzGlsU>2XMU<5BN9;$D0SQz224+NR1jQ%<0m3acpD2* zDJh*gn^XU7B^HGabWA%5T^@NI6EUj}ts{<8Koxo)A9NfK|8=`hjsu%Sy-zG9Hb}{6 zq(r__PXKF8!BX}e%1?j?wSN&QzEVK|B?4U`!cuq+2oVw(<$VPwv~~Rh*&rYfK@z=q zv=7?@O#q@w;sUb)Z#Fj!4H;Ad9V>cT1B7=i3^%$|!zeEcws!N-*#tG;noes|=teI)qdQh#_r47KFtCY8b=}ixQZD z&PV$xAQMD{^&t?1AcV9Jq6a^OAOW{qRvE}$0Ao-oND%sis}H zdxXgW&QV(?F90?nuoqNMDs=&C2V!@GmT-4M@D&Jzr9{qAbU3>;EClF30|!|WHUq5@ zAat$|vOu9~awCgvl>^^qWlCERi&=JmZUt9g;RCZ+tAA$=P8=Kv0Tl@Vgaqd!VlG(~ zpc-gEI|3{KwuH1Jyo6XGwuCEmBpU5m?*Y7ocLTPBav=pbD=0SrzJw|l?jd= zyo5La&xAS;TPD1OIRMXu^9zk8Xh2B`&xG{{hzs9@1QoV~j9K4=x_`EW^9#Q&Xg~;o zwuJ12uP0ao*MuVv@PrNoHYv}9-h{6wMJX%*@L25y?iuU_KR`(azCy8s1ce2K289QO T2!#oS3WW=W422Da4uxI;c_9FE literal 0 HcmV?d00001 From 93677852f353cf771436d29a6cb3f58db54b0cb3 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Tue, 7 May 1996 14:42:00 -0500 Subject: [PATCH 009/637] import DBD-Oracle 0.29 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.29 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.29.tar.gz --- Changes | 156 +++++++ DBD-Oracle-0.27.tar | Bin 143360 -> 0 bytes DBD-Oracle-0.27.tar.Z | Bin 59715 -> 0 bytes MANIFEST | 26 ++ Makefile.PL | 268 +++++++++++++ Oracle.h | 70 ++++ Oracle.pm | 163 ++++++++ Oracle.xs | 315 +++++++++++++++ Oraperl.pm | 801 ++++++++++++++++++++++++++++++++++++ README | 277 +++++++++++++ Todo | 13 + dbdimp.c | 915 ++++++++++++++++++++++++++++++++++++++++++ dbdimp.h | 98 +++++ hints/svr4.pl | 114 ++++++ oraperl.ex/Readme | 38 ++ oraperl.ex/bind.pl | 37 ++ oraperl.ex/commit.pl | 59 +++ oraperl.ex/ex.pl | 35 ++ oraperl.ex/japh | 54 +++ oraperl.ex/mkdb.pl | 177 ++++++++ oraperl.ex/oradump.pl | 29 ++ oraperl.ex/sql | 225 +++++++++++ oraperl.ex/tabinfo.pl | 61 +++ oraperl.ph | 53 +++ t/base.t | 23 ++ t/main.t | 136 +++++++ temp_git_index.lock | 0 test.pl | 185 +++++++++ 28 files changed, 4328 insertions(+) create mode 100644 Changes delete mode 100644 DBD-Oracle-0.27.tar delete mode 100644 DBD-Oracle-0.27.tar.Z create mode 100644 MANIFEST create mode 100755 Makefile.PL create mode 100644 Oracle.h create mode 100644 Oracle.pm create mode 100644 Oracle.xs create mode 100644 Oraperl.pm create mode 100644 README create mode 100644 Todo create mode 100644 dbdimp.c create mode 100644 dbdimp.h create mode 100644 hints/svr4.pl create mode 100644 oraperl.ex/Readme create mode 100755 oraperl.ex/bind.pl create mode 100755 oraperl.ex/commit.pl create mode 100755 oraperl.ex/ex.pl create mode 100755 oraperl.ex/japh create mode 100755 oraperl.ex/mkdb.pl create mode 100755 oraperl.ex/oradump.pl create mode 100755 oraperl.ex/sql create mode 100644 oraperl.ex/tabinfo.pl create mode 100644 oraperl.ph create mode 100755 t/base.t create mode 100755 t/main.t delete mode 100644 temp_git_index.lock create mode 100755 test.pl diff --git a/Changes b/Changes new file mode 100644 index 00000000..42159eab --- /dev/null +++ b/Changes @@ -0,0 +1,156 @@ +Changes in DBD::Oracle 0.29, 2 March 1996 + + Fixed Makefile.PL to get DBIXS.h from right spot. + Changes to suit perl5.002 and site_lib directories. + Detects old versions ahead of new in @INC. + Random tidy-ups. + +Changes in DBD::Oracle 0.28, 29 Jan 1996: + + Minor release for Perl5.002 (beta2 or later). + Requires Perl5.002 and DBI 0.66; + + Only functional change is to suppress (rare) 'handle not setup' + warnings unless debugging. + +Changes in DBD::Oracle 0.27, 16 Nov 1995: + + Improved oraperl compatibility in assorted ways. + Added the original oraperl manual to Oraperl.pm as pod. + (perldoc Oraperl will display the manual). + The manual highlights remaining differences in the emulation. + Added original oraperl examples into oraperl.ex directory. + + Improved error reporting in test.pl. + Removed some internal limits. + Renamed readblob to blob_read and fixed return value. + Implemented $sth = $dbh->tables method (see DBI changes file). + Uses $Config{archlibexp} not $Config{archlib} in makefile.PL + Requires DBI-0.65. + + I've still not got around to implementing a row cache (array + fetch) but it's next on my list. + + This should be the last alpha release of the oraperl emulation. + (The DBD::Oracle module itself will remain alpha for awhile yet.) + + +Changes in DBD::Oracle 0.26, 23 Oct 1995: + + Removed error message (sql) size limits in parse and ora_error. + Fixed FETCH NUM_OF_PARAMS so it doesn't trigger a describe. + The ora_lengths and ora_types attributes work in non-oraperl mode. + + +Changes in DBD::Oracle 0.25, 26 Aug 1995: + + User visible changes: + + Fixed bug in parsing '?' style placeholders. + $sth->bind_param now checks for a too long LONG type string. + $sth->prepare now takes attributes: + ora_parse_lang => 0 | 1 | 2 (v6, auto v6/v7, v7) + ora_parse_defer => 0 | 1 (control defered parsing) + + Other changes to be propogated to other drivers: + + Added usage of new DBD_ATTRIB_* macros to XS and C code. + dbd_bind_ph return value inverted to make it consistent. + Added braces around XSRETURN_UNDEF in execute. + Checked for describe failure in FETCH. + Removed NumParams since it's now called NUM_OF_PARAMS in DBI. + Updated NEED_DBIXS_VERSION in Oracle.h + + +Changes in DBD::Oracle 0.24, 22 Aug 1995: + + User visible changes: + + $sth->bind_param method implemented (needs testing :-) + and new DBI $sth->bind_col* methods work for DBD::Oracle. + + Other changes to be propogated to other drivers: + + - Slight change to STORE functions to allow them to return status + if called as $h->STORE(...). + + - Revised signature of dbd_bind_ph function and added a bind_param + method for it. Prototype moved from dbdimp.h to Oracle.h + + - Revised execute method to use modified dbd_bind_ph function and + remove remaining oracle specifics. + + - imp_xxh_t structures first element now called 'com' not 'dbihcom' + and new DBI macros used to access fields. + + +Changes in DBD::Oracle 0.23, 18 Aug 1995: + + Fixed Oraperl.pm debug which was left on by default by accident. + Added small patches from Davide.Migliavacca@inferentia.it for + longs (dbtype_is_long, dbd_describe and dbd_st_readblob). + Added svr4 hints from Alan Burlison + Changed dbd_describe to return true for success (to be consistent). + + +Changes in DBD::Oracle 0.22, 17 Aug 1995: + + Much more maturity, in line with the required DBI-0.60 release. + The .xs file is now very 'clean'. It's an excellent base for + developing other drivers. See notes in the DBI Changes file. + + The oraperl &ora_do should be working now (along with $sth->do()). + It does not leak (as far as I can tell). + + This release is stable enough for general use again (like 0.20). + Please test heavily. + + +Changes in DBD::Oracle 0.21, 15 Aug 1995: + + NOTE: THIS IS AN UNSTABLE RELEASE! + It requires the closely related DBI 0.59 release. + See Changes file in that release. + Major reworking of internal data management! + + Only execute and fetchrow have yet to move into dbdimp.c. + These were kept back since I plan other associated changes. + + Known problems: + Warning mode is on by default so certain oraperl coding + styles cause warnings such as: + Statement handle ... destroyed without finish() at ... + disconnect(...) invalidates 1 associated cursor(s) at ... + In future oraperl mode handles will have those warnings disabled. + ...other changes to numerous/minor to mention + +Changes in DBD::Oracle 0.20, 1 Aug 1995: + + Fixed core dump when binding an undef (treated as a NULL) + Binding a string longer that 2000 bytes will use LONG type. + Workaround OSF makefile and oratype.h problems + PL/SQL := construct will no longer confuse dbd_preparse() + +Changes in DBD::Oracle 0.19, 21 June 1995: + + Added $VERSION + disconnect_all now gives error 'not implemented'. + Reworked memory management, imp_dbh's are cached. + imp_dbh_t now has an in_use flag and generation counter. + st::DESTROY now checks its imp_dbh for validity. + &ora_do() now returns "OK" for 0 rows (as per oraperl). + Reworked logging to use DBILOGFP macro. + Now test code added to loop through logon/prep/fin/logoff. + + +Changes in DBD::Oracle 0.18: + + Makefile.PL: HPUX now builds with LINKTYPE=static automatically. + Fixed errors on logout/global destruction. + Added logout/global destruction test to test.pl. + Changed Oraperl.pm default mode from safe to fast (see func_ref()). + Added platform who's-who list to README. + Added $sth->readblob($field, $offset, $length [, \$dest) method. + (You need to add the following after line 80 in DBI/DBI.pm: + 'readblob' => {'U'=>[4,5,'$field, $offset, $len [, \\$buf]']}, + in order to access the new readblob method.) diff --git a/DBD-Oracle-0.27.tar b/DBD-Oracle-0.27.tar deleted file mode 100644 index 8c42378cb348447b71f4a00e4ae755d70e330181..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143360 zcmeFadtY0}lJC9$MXzE7lSnw+4NihDF)=t{HU__Bk_?d}g-ATB~o>b+78`_3zeaclz~4r!~7UxAfKg-~NREvgL)ZR#vjV zWm&eovTXlmi%b45&-ia4%kD0$EPb_n_wJp$S+=;yUw_M1{)D+)>GFIqtoO6*Z^QQK zVeiV@`~jaG9p!)iPx-Yzvj4+B0Ruj6|5w=mrG@3M{@VY41&&?a|HJyAH8=c}V=pc& ztlUKZcNf|7y9*0nE#FyKSh&Of-&tB%{9Cs0DJOAVU;oSL|JG;o=Y#%yr`M==<`3K5 z`LkBPlg+-aRBmP8fe9H1lCAgK7p;D_-x>@nm9u`kJIp2*=jNt{JQ%#}PTs3j`mJBj z+kJh$c`ts_dzCHv+xF>MuRk1px#TaW2Cv)0#!2=-?`I#aHy3d=_SD@%XT|DU++sq5?M|J;ZlYL4hV zLh(7$2O__M;fnT&Pvvfn;F8D_P{v|23BWc%&Y?7Q=Bqh(+G)H|o!%dFWR4EycF z^I1p~!;@A9D>@xyy`!wv=1+h2{r2fs}HilS*y`LYPXtMyKB8a6R+LfSX+O(ksY-=tvRi8|D-+0_`iQ5nX=PM zF-4}q??I#AJ{!(t?O}D0iOta^dV9UAAMlYz@4VB@4qMsk>~!Kcm5H!VQw!OnwcYPu z7{>|^e|?)eub-Wa-`Ji2$$*L#*Pt(4A zFsM#fCfK58yOm8oAJmUqs~Ld#dA6B#f8n1K`^N=@I{(G_`{`v3hAtU6&2Uo!yZ4%Hew7_D`$3Oox4Zm2^$k1f z_f8F=w4HkM?lh5*M?3#K)?EKruZfZ!Rk8)W}(fxMqh6a&g#hj>N~-<2&M8wYz87l zWVndc8nwH}kv)|xYgq~L3J3^ zrl)6|Bn-^WLqSbcan$Y)pwQ!%sIl8^HHJX&e84Ot17ZF!66oNxH9YAx2dfpdh1$aO z+secg{lu*bt!q<(91MLyXQ4FzAF&boYIO!J8as-f6!yBL?Boq1Kk(&(M)n=kgo#LN zu}z9|(SzBC*G*<{IT*H1HKo&f7g|Cw6Tv%ibq%OO*U&s0_OjA)*dxHZy4vakwEkp8 zj)3!Sr!~+-4u$smXFQHpDy<9H@7t_@-aQa^gg|W%DGkE~_1PdWUq{q`Urk!&u?#Hpq6=>vVdrr(brhUDVksmBIO88vm_L-*$m{u#Jxn zSb&xkhIyRu!2o>-pnV$p#uwV?ou0PE2=z!^HO~8kUjLwOT*qK>)^DBF`>opKpw$7p zvb~@7*4Ort9^wG&&)2rZbJg57;hBFO)}GZ8yr;{sXCevmam@1ULr;z+@e`ZB217W< zXK}lhn8)Zk4&S?uFBi)znfRm2IDG#y4#zCx@X9if%aXyp!+#3w^}y^}gVG*vpPwG0 zBtYXx`3}Tggv;CN_VcF)J5LUtY;J6=?*%?2@C6L{_|^cvi(F{b8z-%1#R<=*Ded6s zywkbNu)I30(-t;WGrMdJWvvv3T(1x7+3@lVy+w0|4t?e$69>iC4)%X~wo!dI`w+>O zAQomGc!?zDXiEl=LqQGSR{cBwz0Jpw7u%EyDAan>YM_VJsU@1SRPF^z;&Q8Ll|-y58?*lT(juxFV>Wwgszh>vi@rEmRB}2GT+B z3v7LmsPNWDP7|)ZZehb3&o`aoSpA_(#)kCuT2kJ%*8+=$t%8)r4X$4yzI;mT!&p9e zir(LvF@4bX`rF6{Q_}+0%+1Zu&0UKy$byW`b(|?fB!{*mzUc|otU6N|CGC085JpyZ z)b6$il5GWaFzvpnachG{?+i+HHZ#af{Gibryn2_sf!-ZrAj_xl8jRZiI7Q?Enmap9 zCgLCdf&XuL+5P@w{Qq|smKL%3-T%L`viOzk|GRhpvj6`u+&`p)TUprgY~%F2+k~+UPiSZ&F@A=jmzno>1wX`Dz41y?CQY#H;k{+Ee_ZdM-AgZU zy5Qt(^gH8{@lG#rfW%z~Ly6Ml1`TEaBr#EPo8upHk{8h8({|?(jtPTI&X?2f> zC*coiM1#Do>*fAkA6wuM*!W*{gmm#O9s>DI@}~V(y?KaPVNa&C0#nv9``N(-;=iyr zx()w{HPppW(x+}1@V?}*hkI7wmuTFO%3Wt zt%-?Spv@55{=5ZdfI6+Lh;>yVTDR3|w(w1xotpYVq0x}Ir!eQ~bi}`)cf5##Ja6Wb zKB$caF9Ork~nWAmG(i?YIIblkAn^CH$K>deFdL ze(`p4>Mbqbt*%a~+es8h&EwX@?{?kBhGJ9`Q=Mj=S>>dRkII|~2kjVWzJ~n>qV1`ZH`b z(~`~o*6dWxMnWduU(q!NUb>BCk@uMWw9? zfcJe74hX@f?;#`hHa4>LjVEi*xAwEA8~Z=(tY?HWVIx=x4lcCFt@Z5j&ick`n3?S| zQ49+#&jhnO*)s+K%$zQp+8&0PeH>==EPZv z4NI(~i_69RXw#pC`TmGURsk0jqy`Q)IZrIcg3c824!NxI(nK@q* zX<@ex(p&xEuWI21a>XP7$btZ{hk?I;GHzuI$Q7#*76bT;TqY=7ft@7YWvbUGkMaI; zCIfN8U5s%>6c#$TheK@I8?1^Hx@g|$d9LS1_R;GeAP5V>A*#O43WHKSMo{{j#0%qyWp*fu8sC%{Vm^_i0L2-d zqEi*I!5P`xH8=uF7mjt0FY%S{wOFRGKWuD`ujBXpW!=#pmzjuPcHO`cd z-RJ5@u#v`eBIF4^)%(JD6Jc$#5##E8U){A@NTv zKVfbRX=4qUPda4yWUugM5o5&6l-weOJ*Zz`ka@sth^-3;r8!3Fkz$=h?9C$~f^#zo z{>dWE%Z=$-@4{zqhfN@GmOf(>UlRLB>aN9{5Za@kGTpJC@*KV36Oy38hnW|_WtM{2 zn4I^6^D{H1(Te2;m`Y)=rRnUoDL_-WQVEnH%%$ImZRL=68*{X){Jj~T8p?bDb;25e z%5+O7Xq%p~#cMvQRuZS^^Cs*S`rG?yd*|8S=AQIGL&lG=?iADcK-=a<%OC2dV(LUwS0u@dY_WkE4N(gn`@ zWCfW289Pi|Sqi_tvivX%3ZxT80VeAaCMnX%NeElShhSu%yXPd$$xjP`vn1o-bac|{ zoY4iIO29ybOstZ}wtm?TibS2mMCq9|@W#?;c}}_yQzBeA~Ev%dE z;qrWy-G4REzmMwYXt{6Zj`|PTgYG5C9;aqxRig5%iE5OB_>E5Gtd&9z0tz-&eS%J|Gu_Kd9KM*EBjJ&C*Qh@^y}!p@^8B<__3EL7)Cuks$(rf2*w7kD!j zdu2Y8_{KR&{L48<{0sgtExjc5C>AoUiS{6+Y>6Lj49)DeSf=}{KY%wPh{<^#@qSe{ zyL4iyh`qR$V%itjqYc{eGCq{8%$i5k0U>+yY9Dg2p_Uw)gM{ZAzupy=eD)U1JG2&Ds{N-`QPzytQ$# z$5zqZ{*OBc`)hlD7br*pB>Pp3owdgaRd|=@bj{&x7jTQ6`}gb}?u`~yp`@zzkuk|( zC3XX*fPug(sz)XQ>e(r3BZ`xw0*N-Q(=&Wpq#~R%4ot!@x`OLS82g&_D9=EQdaX0) z#XeztWa3z&q-M)D!_!l1Ur+@f^DD*J!QxZJK89?QMeyPj$LueR9+4r!F$l9=vlMMN2YArnb0?UFfD{M> z?h~0+&p5ga$W4~iG>Akbs)!|sxse@$>kcjodqK#E*g(G5o-qw}ykc5X*pXm(B+YJ# zs3y@G#F3N$Lz7{)zr6>cw@pWudTAFm(+!xFIAapTmPRGb<t(Qso9wY=wob!6CHolKW)Vd%`^(ltIhwU{v3#aBe?u-DB=IZ- zaso+Z4gy~wbf(1s7&Kr=+0S%@y^UYe%aH`QeB?78H9>S&bPlAzXo9B9hC-Ts)F#%~ zk?e-fq}Sw#0V2yRLp4muAfn7oG)1Xg;JPkUpuC)QcqmVl(LU}XWmv@i38M!V=$bp} z|Gh5F1J@>lymFl#T@6{nB<4xA9DpH)W-yPSSfT*hOE|h`V_e%6i*FIA;B=le14Odf zOoQ6$;!L)>#Q)!!HmAdfvVM`0^M243CKus0n9ERIDhZPi&}LW$6AZ;e1mkHX?IFey zdl6xaP84<}T85Q9rJuy_UW7duK=e{bO}=0uS~?Hx$Pun5c97=d(;1}+S6-~C)E4D(ATspC%~Xyq>_<~IXmrHR8_z;eEkbjOAWS+wwJ{tw9=POjQl#wBB*FsCt* zSiV39@CpvfaPC1OM=H@X(2EmBAEEyocALby#VH)=a;#_YeUQSmB>yTR5oSI3CN0AZ zjglr{4hW>fVGkFDI3PLU1rBKJ$b#7{)D>BlZyCO*;RTH%XvH#Ny2qF>9JXnoVkf<| zE<68>gEK~cA-HDKk)&b&OIT&RojA)G7QXah!oj!=q=V%^ofhKD=_0Ivl+K4|C;}1t zUDAwUvQZ2~F2T^+!v>m$#$j#)+Qo>5-SPuT~$Tx=>+BFx)?FzoD66#rejVr$dMnV#p;RM z?3n3EcADtCe(NFRw0MT?_nAp)@y5@zQ@%K@A$(T}{8dP<1#6AOBiI$q!IP_FOvo91l&9fX zRg^8R6s1rNnHaA1SQ33e78*WBx!*Y!(0P=!hQ906lAW%k8D z%;$>2a|NEPUbdjDeT-I=osLZi8`Tm?<7tovdjq34=oPtz8@z7HqX^7Cj16m3 z#^TTna9EP{$q&qN@vxU9DeBas{o^lxkr0#qUD%EWdMav<$q)bo;YPq%4rwo2Twb^f zM=CPGihUwk(ZQJn4qKopoJ=Zp&qgGKgiy5cc*7Mw^FB;8RGc?CcP0>Ohx3pbV)e8@ zl|_)c5@$>W?AKOBEbiG7z~W&=!}ZWjbnp}K6+@NL|3-(5FG+&BNc;{MMQV1s2SGJx z8Ltg8L9>bQ5%HLs7v|^8AQBx@G=tvqyG~F_Y?@O3OMD6~n7P)JQF=D);^>-c28S`~ zr1BmLaF>Qcu+UQ(JS!#;R;&5hXPkO>I zd45l_iAaEMVfK9L>mzg@C%`B_SZqJ7v8@YXhGZ<{upc`H6PMDf%*b4+1&U>bfB~;@z1eVSumbmVN03EkX2%r3@dgPRB4Y}?h~ zvT-vABH1+yW*3BUNh?K0xj~M>xoK|EMD3z#+Y*cQL<}t`BJR;e)OS!Tl`~LaOHHN4@WGf~+;( zJ|WC_e1Ze9ge+zHD=g1@CqXoBM8;N>HjZT=Nz&%|pCQy;`B8ps0XcfwAUC;bAzn|Z zWQ8$wmmLG#JQ(6irva(xalA@!NXE#m4JKg*xmx}aq~dLFpq1dx98W9a_R6KWvb7RI zzuQkbN;VI4D1|*xmd6r4!3MIij*k5#kCv`An{C-^@&d)Dq?;f=4MDJlSACB|`sQ>9 zjm9j87y=trNQgN2HRds}H&L0h38a)65q8;47~Fyk z87&?0hCbJUH+)^Dt+2IL6J)#aVojn^W@7M6*i* z!h&Ff88dIyZHv?gSbOLERPNAy2ZxX+Xsv7rj6}ma21nH}=)rW4??Wfnnic7Hd}pvq z=$@#A-lJ)OqJx^+$u5@WmU4qNrc|hp!xj$Yw%o;Ny9$rHZdwUTe~n>fCPzNWQ1gPd zUT?I#t`B73Da>gCp1-XZoH(ijVd!p4h!e#A$Kz(7TQFU-t`zbunv4~Ub!@FL8EsuY ze_^_OP2FnBN7N9}&@2S~0Z^Iydp5Koc>rg`@(A4zK=XXpY^Om1!Pgx%C67Wq`V(@j zzi~IqDpCmA1XtHJG*A>awdjg0#B8D~GFav%8X#Y(NCOcd!qlj%iY_CXn!=f{Z-fd| z9S=c?Atq|~SzbE%wku>4UmwXpAL z{FSx*B&!nXGiAv+&}{Q9O+^kgCdO1;!W-Km-K*I~5A0mdV5#f43vu;2iUzzyOEBT& z;q1_CI=ZyHUW9T>Wq?ZwY2xNn!!KCbL1Dtz2(D|?=l2n-sgE(hO8pb~>bxfknqgnW zqUd1D=c45Y4cy9IjJVJ8l|-Le_8qn5JV1$ppM#lxP?6aW@$-1N|Lf9Dn-++ciZ5w51@#OWZ|&KE|)tEaM-J&k6Nf? zn3z^Eit;`eneX+3sB$Lc4=Sk)mz2F5KZ<4vhjK|8BQzHmm^<1d#-{ZOXA9uTtqu23 zh2aVcZyGGOKrlST_E~t;#{dn%#A}%06_AV(Ljj`VManC4f{n3}LSWm@!-#xqp{`*e z<3tP{x0l={y^+tIL6|%erSxw;IjI6=_ zN%)!UA(J8w$Mh`W2Q~ph0xSXI;cXUTEpii3J0{e+EXIsr1`WIvVylP~lNWeEA$gq6 z-d}KIk^(K3WDZU88O5zrh|dzJTs@V)WN3<^I8l(5Y}lnou;Fo#b1=xY^CU8yf=vqI z2u;g$Ycryhzp=8I8eW563Y4 zyVXMF6bh!0e!>3&fG0An(g_W3%_AU8V<-=rbXAK9^Z9{M2)$Ro?zh4CEZogF_~J?KhtKgA*e;@XSLCLS4`W{@Xn1Cj6FfX{KV2&Cn?ZG4kK?WeaufJMgaC z(?r~#@|di=9*L>0nZ1af!>IC=XJSZ>P~{|n9ApN#+^Pa@0WK9gMvy_AmeG>$g2o+9 zCeIh;93uZa!2vA;1yTvSzF9%(fPGRb3~-bDWm5wO*-K~b!CM&xkRjleT$dO`30aB7 z4#}Akjhkx9v|$YFEG4dnZ4wbA&)LQQ-CPuQPWgrD}oXZ`|j=q{SA-pe7pCu}J z%ypu&FUUN?EW19GLWa03q>KTdH7G3MuR=?3OUsZEpRzC!>nm(6`4TPoJ>tvZh>GT! zZU#r@>gmyH%?HvG3ylRTRKjDB7XNgF`~Y2SfQrjIMTTg~yrO$!o4uq;pt-)xGs3%M zQCiocC8?~=(^DEW3kCPc%?9BE_C>cR(@2PEw2)*36hke5Ope2r(p(QFX4^Qv{gfPRHHjY72s9yxa zC)fyVvH^S{Cbc|vujMFH%{-o(z5}>^N|KLC^Z1{ z&~H&vjiSh)aRzSjWK#{4n6jw^M4fhn>4=Cmt?0bNh!HE#9ZBlQxLk}|#~FwzrTmTL zgQI*@9?lR+D1#0B4i6>gdNLA1R2%eCpx%4%=qVbsaY#$h>j3GEzHz!*D#RSJRZA$w6`Z;;jQ{e=|Z9-)wSoy0lP?=2Lc z%VR;`-lQM^k=It|$lN!VreH-=U6SRV)(!XTgpNGzz=UX2dyx-zuEhWv(t5$6Q#NzF zW)$kQ1T15uEMtr7p;gQE}QGY$xl#4!x{^@WrULz9?m(!hzPl4&rbLJNo%KBmJrwpDCFS-SERHMF4N`Gds3Z`k!yvKPo% z!U!avo|3po1J?>P%aCFolz>S3bZ$y+c@C!f7N%f-Uo!*VDeXNPp>!NMI0^;>%Mw1# zF6Pe8&cy5Br5EDOn$l_gpCHUg2f`73>)(*qK*d-y>MRR8Pv)TaI8f~2PT2@tTwV$) zzt7)=b|4y?fV06nb9|ZAEZc+msQNfMnYgaN$Mh>logM;_KhCHMADBad-K2x?&%fK- z-`sz$!_q~ICC=0OgzJqaVuN3CR;8rbWK$?}z%r4P@&+Y}nbHJBjOhjOfF6yiXIYo1 zNKaTuigG5^x#I3zFHz7(RP-rc#OOFc@%x>fD4u}Mj%c^*GQ@JVPx)bMF%23N4TqFx z7DEfBbt|$!@qG6diiHq`YjxmR2J(1hU|J=5wKh8^qgcIj#YV zInOGQrMZN)1o&|Y=svQR%bHkO4qZEKkf2pwaq=}HsZHqvcs^TBUZ1skaHr5^MUXRS z7;CY41Td^|bPjH>>jaj+TAKa(>pOS7IPsM)zat@~tM9(K^VRI)*GqQ{Lg?h$2@fM) z1B_I=%B=~222P=ea6AH!h%_}kA?5$a)vYp$%S{sf0b_BXb+cW{pe>kF@x=b}mgdZCK-jqjd+&y`8v=hlgE zC6bd#056#m_flK~6|P{s#DsOsCS;{>$y%6KNKQpqe2hUz^F~E6KNr;G@pPzOZk%HE z6;Re0nb%(l?$dfI#KJGI-<**7SWGOA1J%~M6*~Y2t`STzWmS&<{HRsW1oH#y{4cKHH+eN2VR7$82wZedqc9!T!#(>;X@;RoOGqI)6OiKl>lO zp_7qD*5J|o^k4SqVfv46Q?n{{CI`hUvZ|KcJ&_gkgFMTgo&xS;H!2kco3kr^$R z_gYzqh0P6hEiKD1-n;VPzq0xNcsYA(p3UH6W#5#lj#TY5h8HN%xs343YvQS*jsA<( zbeUZ`w@PP9R12LsFY`pIaFFVDIFVr7%#Y@SEaF{UEaUz9|Bmb3U}l<8ip07_ph4k< z=^}uCx9oURY&^F-KcC>u^Q$9LR;cEHFU#2Y*lbYl%Ft2E);%S0n(3dksBu}G;RXqJ zhMKZM!MGe&BPpb|5hRZ4gF?1u1o9-rMiPOi96B;ndW#{v1^Z4U%)>AvO?ZXCGqnO6 zltzg^Z13#LA&4dRs?|D^d^TfM4E&5#+1{Xcc7n;_UP`mj;5Eh}(2ZNO5%D^BA%{Aa zrH1*rh2p_}4@QaGmAPf~DaixG0R;tH%^;YBJ=w?>9*=4gs zX<+JJC4}$`#X^!+Ur#;&_cc@sj&7y_Ztj@z4sAxh`s3Q}He40Z71?R-q8;>(hB$^W z?N9h$aa3dp21SByEEf_Bg;+QMz#g8rJ7_0jTAVKQWDQj)k(XHI!#7Q|7s`NC2sEF= z1yUF+{B6tiT1l;oUWb|^$6U^`gL)ErJ?;^_;17#iut1~-3N>*Xch9C3Fex!m=}7W? z>iCF`{Oci{Ux~ODv9_%rGe0uWY<}9X4tf##j12**(Hk{KB};7%_{7i+kGYaTrB#A_ zY_)^=q)O@o3a|$6C@0|&=+Ql)fJ9SeWiZ$d6#^Hk!ndt-K`fe}$};UPQaq*>8E>$I z>cL3QJq8GVXQ`~x=+CZBFxWHX4$Tj?RxsW5Tp6;G_zSu5In@fTU%= zw_|U%9tzpm{^Bd*$kY~)KGzwI-B^4ld+I4qm1kZe;*|S{2HE%L1O*~JhVC9qk=>MK z>s!OHRn}g#iiH2s->^HS`@frqO=Qem<5MpB=KDWZzPh`xnBV`wWscncac7D9pZ~i5 z_fzh|_`c?Eqlfw3nsMv>cFp%+@07J(F=JP2KgK`Ur!i3c~| zu}L?d>XOad^HhTLL;&uAbg3|RGKrD|GuzweLbZeSjmKMSyBjE+asqG*)832BYA-4P zc5n2dIT)p!s(51sKprT-Qscq}b0N5G5dS(DX1C+-dzH6>kJO_*?2i1g9>TvVAchp; zjU>eZ_X-{iE^3;w{`L~5`U0mx_Wg^4we|I<6zSeHW5V0p%x-LNU(i9hy~@MR-_F)! z6fc!?8`UW$_T>pkURbh&$lAw)C$CRx6sy=(CggbF1}BrE0}3y>cds&GXCMdG+M22| z9^s?VPy$>I-k_j=5t6~@Dia%hTumf9VQP|2k^~|0{-U#rT;Hf`T(wEX7d)r* zY{tAfC~%5-aFo5oMXHMtgOfhE$ZdIpivtkq?4ss7#Owq;n_bu!naLT)weetF`PeWf zV1;$mzNkUMw!>+A>2veNbiYy9XSLIUe7`Fbbj&ssW-*!3&pMZL2r5_JhGDP1m^5dq z=IgU&E++>YFE+OKmxSry-Ola-@z^fMe8bPsyR&;)>?abtC*tWnx0J^_}0lc=jR!x?9(di@g{{9vz+>a7*1; zjUU)TPKF{7y?{~jkHcAL-j2lfWOHkScV|vmHXr{g&hqGt`O!A}oEcR=A5@tZPc*GI z$AEOLXoDmJw#a^WDfi!dWwr6QpKoo+4znv#+);~PEG*u-wE*Vla2ObwWz~G%;g4qi z^9*LQ4D)JJW`|bBYWc5ZQtOmfOhPs>MyjyE|q4)5X3E4v!gUM zjLI|Ct`wD{j{Oj6`42PauT0O{hJn;N{8an!Q$56=>LYApkdN#Sf=?4TXb((mA^!Ad z*iyF7|Bibo1|!ch0SJW+XY7A70?OeRSznKTSlgA`Meh|;QM6fIek=YWz|zOA-xmUy zVkId)aC-)!A^)RA;V=dLX#9+m^uk>1Lwv?(Cg$?BIiPIf`g3V{T3pm75GTScCXB%a z=UiCU!~|bXa8b@fohoaM@BSP5(|2h}S|U%xFGF`<-z)T_fv@RlWuzyYR>_5q`v}LYv!a!ZG zInYj?4{8n1bI&AGN!rQy`v8|`cAFoO03!=Y9KA9zS?f14V`mpj{_oMy|LvcJ7lggS zoA5xzi)o@;DPgb9-57<+6O#GH?Cj5rrGt?tM~H{Q2Mkf}fT2ns9F;qa_qzo?^yy&h ztgLy^JoNg#U@fxAuaKu6zpkp{#`|1jV5Q@@qDSm=j4~&5q(`Ks722$QApy&Pvky%rdU-r{2Ug>CvuALnjSNHC<9$Idxa=oWJIT0FxHxF-^18G(9J$5p|t3 zn8v~8(`S1d`v=t33w?4O5!)R8FpB_FgEQ35LDkx{o3+RLn=dx5v_pKV5N*7u3%@67 zwd=qzx=7z)Hc+vYlmaf`Y9m%)8)Yz%e$R?;+)BWt3j)g!r?lf+)Z>o?n-Bj!xRqvK zn0!1;@$u8A<)@f_oWMsdpa}ka<34H);0t#%AgtzL~BQ2D7Wr2l3TocU|DdH}G{oS3PV*Me-R(NW8Z^|4&6R4{5YRq~qG|w{_ z%o}3mui_2I@(LA4waf%dE`YQ?i=C9PI(M?bpjEo4-@E)Mlo0bO>{Qw%tQ@&+)N5iA z*0J+E0KrPEEDi|}kqNPIf=OC>GtSofj=Zac1tT0~Z+~ZZLnF)(#Jn6_aHK^S5ezQI z$QE%M`^YDwKf}j2F(CGAYhycm)hWs!xIAl~UhTNR;DRq?3I%qLNFuVQ zM*F+ZH)?U3K}HFnuR0GNEH22nWkWXpy++UQ`ZW?89vk1Bbgl;wgImG7iXH>3v)`oexP{0&;*1I~fZ+Ts`hR|L_bf^SN??B!eNXw6G zAolIr3gMM~pKr|<_y+79Zi07i(I8UPXZ}q9kUqU6fJkuY3K;V5DN*MJLhQ)IS5oA?josC!3%(4i+wLwmBmnf;aR{P<_?diRX z-4{k-MgaT|wr1#hhP&!~)G!Yrp37umsX1Ap)F&JJkAEnT(9M+d*7z`U9?`orH39E; zkPEXLAr^HXj%mOgv>ZheiKXl0g+WNLfyMZtHG`3_BQg+afCdJv;|G~9JV}s6c?zWl z5t%2AnDWLXq=qya&Tbg81dwgx))-uj-MhAQH}&GXXZ}Uq9bySkwTpJ$Hn1?aY3um? z+h_3b&6}vnI?*O?JbApmk59ZIr4jaKILP@!5ORssOXW(xF32Zag!ZFkL**aGUQ9## zltxulmp#RTwVTzsWmzX7=jV9#On{}SmR_O#KCZRiQi1V0(?QHhL0f3mV`RYusFV0#&2O(Ru9L4J%;^I1nl=JGWVZ=oh)L(+n{U2R@MaKv&b*$POrUn~yW5>r zi|3Gd23x@AjDo`dqMKIbiP3D*w9Nyu~ zR3ex*Dkxcj4>XjsAG=|G%5O@9l#wbB7L|YSUkrBg2H4yg(0Zn*jc`sJ<}))d!zx^94S;duXcR941WNW~qS+v}LYv^Oa(D21 zn7Pl##gJlbVGh@5F>mej!yffy+T8=f`*xqxgUl?PQX6^qZbSTi)TG-o%>C`z$$(Mp zf6sy)Dm_3CqH-#Qx7~arX<#x+KXhU({EvtVu&U2ngQN^arr1&eZRDGJiWSJe{Ct}wcE5c5hlFWA0C;n#>jjL zRsJjg3+|&9-sCfa`Kwj=46FzJ`E7Mt5xBg84I%MDuv1}2Go+_0Rr{^+coV|=r3Pz^^8k;W3$!R$0XZm8dt)z*`!Q8$p@$p_YrIl>?>eEOuVsiubUU6 zs`q!L=$1|D%p4NLHcuP_03my3e!ZLA9xls66YpG)V$=M|2e?7h(ES6NWAMfa9S_jP zy(jmw=$Zd*h-cbFkg%bZ%{y-<#fYu-r)PGbyM_?__b#?Kcm7^W%bu2}Scp@+z0p~l zk*m!BE8*vF7G$SsDr~knJ(AI;hd3aDJg^NhEj%AYyB}9()M#php2QtWZrw0~89%85 zHivJu!1#UczZip2W3Wk^PFfUv9xkO6spvUT4p#{0+Z4H6R0&*hM`tj-5<=jCx0liB z!aF?8lam>|w5|1^P^579D5|vq!?ySvH?N=8{3`QkXmP zTt#72m>~FpIcE`CVT?#V(QcD-w+XksA=-p@;^=jJV-m5JMu#pAcy(yl&Lj2gC>u=AW0K>0VCmI4(S`^iveoo8X1lFc1&x|r!8z< z6?~9_Z3~Ioi0{5G^AZZ1HLJWYIHL?}iY&pek)htNC5>6~U%=;_Aj97Kq)Ho+&jm^i z?zVTDl%<3M2!+Skhv(b)UmcPjW3?Jkg^e)_LJiG1MI{yVDbTVS~=Ou$&+f^7kVg23(JUOx)H;F}tZ1g|fc zoYzAlvoVMe z$qnpTD#`3aWmWPSUMHhRuXqI19BWiCBng>AeoSr^&&^dGg9qlcCW&N5=;%>lR*m50Mc5)$a>z*IIhkgI6uA3g{U+)WyzpB?z&c*iI6C zX6*H6VF1(H3xo05;u3vLY`0$5aFB;r>4zqSt$_bN;A*Z9BW$gr0Zbj5eVomVJK zq3oc(RN8Z3lvjJubi(>+|9yV!MF|Lggj|f%xtyPNF^*vGOy@~q9k+>bM+A-b5ct2c zt3yK3whqB2*ANDPT9E#EY31%OCi9IQs1U4Z+3#6!KZ>&+=Z=RNONWC0 zvqtHs93q^Y;G~BB%RBVfyg87sP4B?l)VFHOS@}sMhx}c7BmJ&O1Bt@M4ruI&z^1b) z9Kgk)Wj->h4I5b-%LS2;E(wB~oZkBMAf#IR0a5(6ymEPOau%f~5yfop@5u>i+pqVw zR69(=NO`QD$3M3@RR!vaU&f4mNJzQCp<`{ByNCG9UT9td+5=-4&YJT#9ea~g4XuDK z>4T4n^>b&5C@IQ zf&yAI;jMsJ%hXDP$u@N<++s8IDh9Gli*Y1Z>5vdoay#zh56ygAGy*-y5w8khYr}=4 zQH!?VoE`rs|E}?BkXw*uzsME{niY{|DjlA4`)Ru9P7^i3;D%ykbpf@~$)Li%qWmPb zFU>(aYN}p9I&#!eEkjh64HM$2^YGn$_fe--3PlRvMq-gzUD2$y>8Y163E>PI?mdJ7 z{FS{K`^t@VUImiTh#by!Ef}!qs3r!41mLNSm#eoLnXe@p#ZxTOdf1W`f~xP)R~1gZ z1Ouc|x85{#*}7mbm`+ot17+`+(TuV!Q>+SlhJE4K;Y_yu!s4B%?79Zb>d%y-54ObU zbXakqMHC?V)y!71Dy}rn-Q+HIh7CvFlyidbKizB@Z<;rom?O8uB7EK0IyREPD~^#v z_Dc`_ez~|RM<3&qNvxOC2?2c4lU4o|5GgVzvj*>^CmOzPY3bpyUD9hK+d#SFxfZ>} zX*N;^VuIT9XH+s>-|)kL>U!_R@Zi}CeWL8Owe_9tt)FzBAoN;n`)ud$yy;vP-^D># zuv-o8Xv$j~C4aZMy`H=(@I;bcN(uvFDx9|idigJ7c-EC|UobN4flN%X!%+((@;yJo z=M1rLXZRBBxtH8$5i%7Bfqy>08K{t!b?>}45oQoL0tWt(2~p)3&to99(kaiV)0hw( zt0!G6*#6~8P15E|9&<7TgTuwL_-rBaUSp13m*VA(FAnWC4ot6jKnAO`?-Aki6VzmZVZMR->KE^UU_C8>1^43;7XVl0r==OQ*Y3R5r)j5&HD9~c>diDNT|!}EBAuu9q4Y9WGC}Lvclm`%+VqRLT3xMXx8Iri#cs<-S8M={Z3#h zW5P+AlQ1h%OE4By0pNi|2x6(YQ2DE_-B2U4y3U}0J$thcRruuSuzryc$jKz9Aii9? zpeg{_zZcVJ7P*JUYlMcWf5^1)VY-*aBEu=`J1j649^>ut)wu1WzS`F&d2ju4s#Xq)=A_Cna@yXDC^VB}rdhpwVt zqk4nU0hfMk`EeURjUNiP<3A!&kuJ#&rh%on$&OP~aWe4P9Ppvc$w=lR3$qWA3Ccp$ zmpZtUvJ$OVMGX^rn8t69$)_~36Nc`DQDUhHTX(@)0TO|*sA_GrrdF&=u@0Q%gpt}q z>Hvr~iKQ@YmtUZmRjLVwjxtt>i;O3hSkXf};`5+SAIr8=)`v#bVD8t)|5d8jpO^ro z6}2YcFmg)YdTVW{Uz)RlYBo!2kdY;j%pP9O+6jH`-KY z{}hQK;2+)^cx#!JdnJ@fL=rX4efcKPG}buKCFCeEFnxUu6VoeIJ27@^k#IkeuYxDa z%(Uz^^Ya~uV$ikUtIC-9sYYQ?&;0(sm5fp*}rh*{KzUhN)`qy9NI+CeK znwYqRHFm~r(IWr2@W9YmUyBcVw}rQP|JNzlYO3Qe=m>>8Q-r?KOl`sT8?y0pXEt%L zRPCH_&MvxgEC8iRBG;Zs9{fMXI#fYd#bJW!t$kPHy^HU6cYX{l1(h%J$$q)$-S{^! z1;0=ip7iCS+FJ*%a&V?43b=Usz#~isIa2qXk=BYPrOg)A>~?$`WSf9#0Gwx!JZ@U3P#NJ3lFH8oJYoJes-&0qWr1ygrCh=1((48EGn z3(nAbM;dAUn8PXY1H0p7fEyz_?zdZ9E%F15NBkP*L-Bmh$Km5C%pD}t=>!J#8twY! zB=c<$c@9|sc?#Q8&3EK*sOLxBO%zE`Mzk-Wd`$=R zI?DO5P9^P`FA`plb#_EVb9?V%V|(3O%io{McUfGYTa;iKR(Z@+i$tFp{8Ov2K73~s zOc3XS$wYgN>-z>DY?x~{p{EfnKBL^*NY6T%H1MN)PWv|-{pyKK`NP49F*w- z5#|k0MIiow5a_ItNroaNrBt19Th*kTjI{r8=c7!cPD?N@wYxUE zu(+^{FSdHp8w}CWSQI2^x4T4{WpyFk8%%4r4V0UtV>o1iz@Ur+Qs{+MDr}}`zmzR# zpYZRoJWN5uqCLFNyD&Y@3Q34pb;J}|k+gJvRj-1u>iQjBPy;^O-q={*Sm)=D-x|(l zpN)yS!ilsxGl$y!;id2u$};`(fbtq`H#hZ{)tUFJNBc|K8u$PIB(Ga3CH13^+Bd`4+ z`D^&X2u(v-;AD#1o!ZnGDbB=jbm0{`k=P=q7d^fKq>B&fzps+q@IWv zng?yTAQyu_ z{u(~}xQZj@J{VhBM9>P1JsdT=)jkqqf-@W_LPb@JVdCkbY6Lr?ef6n)h-)I@YUtpT zRJ73Md~ijJTet|@N48Odc+_CLutmO8BjQWYDQwUu-H&$INoKBP1? z@48pQvp)IE)2~Sd_iO{y1Q>@IA%;sXHA5!ndYq~*ze6rJ&y{~oxNr8MBOWIJ%w_9d z1Nem{{lgAmWZEqFitQN$cde|-;cB~O;|jyEK%VTr zAc_ma#4DOO{_Jd9Nn|mTsvgVB)M5HKK4`V~0#}~=c1hUC6mI`AXBAszjrf96UbmGp z`eqchG+7zQfBICfOw+5VUNg_-(Ru2Etv?l-)Bp%axJGAc;bE%{P=x5)QF;sbW9WmD z5DMKOiDfAL;c_%1yw}htoCS++wm-cb&FqK$Cl&Pn_N5o2_do2Izhds}bo_Mzzw7DE z_dnnxSiF<&f4J-SKP)dV|8@Vv?*jHmHo65FPHo~gP8)C6KP)X~y2oLDadCd}ZbnVr zJIkxfUnyJZu$OJTIm@Ohw<>CT-31W)>HY`*?o-?Vq47S|6%ej4aZu!yYDcK%`l>@9 zh=XunwS?Q~lgn;>t5@gXiA%yqn|o_WtY2T(*3+BFtfyXV?C$A8P!f^P50QPfU#E6k z7j2o&|GV`emkhlG9RH=>~)a@Ha5q)m6T; z&eVX;Xu~mzkv2S+yf3!lkvD7hPiSMooxEAI&jIg#P^LVhp4TyG`s`U^=HKN!e@eY! z3+i8l_UUD9s=+B_lGdiAugLND=z!HvgbM*{Qybea-d6oSqk|uIo^Dj%P1BvE1+&$i zl{G*;e?I6_*vRUP%oEQ_zx7-ffQ1LsYCAEe&j(Wnb~IXZn{8&3QwQ_?=HcmJzSBOO zWTF}mTTTC*US?C&oMEOuxx(DuS;=^upmNICD8-jnLSB9hKKLwls$dg$j_j^I-rBJB zS?7dm7!;*y!oicxv1_ZV%|4GS?45e4XVue7id2wQ$`LWogj4zSL(WoZeDYmY;XgkS z=6k_4Qxmoerm3y29-tE)up4P30(7g}*yq*k0mTZO5~?BIP<=s;H3)0(B1Xq|8~uJ& zK%&{psR9`p8WuhRyR7}yk9ZTmTMLI7<6vPTA_iS;m3T^=**npVEv}@L26r&IM#Ooq z5V)XvFS~_zTK{G1yOavv4SyK{D7Y^AXv7lC!s|dwz-n}nd|G>Sz)S>&pcbnIZfv_! zgC@dyAP&yQBGOX~!U>`&DzcqSM-q_BBz!UbmQ63ZY87f2*kLu%Y`Rz_x(NY;hA;Gx z>6XmZdFyD?^MK^4-21h2dwXL)&JIY^l(FzG%L^M53#yvmyiAMN%}1vY9k+B+$5FRA ziz1(2HdX}plJ!#I&;?H5?=hi5U8ywoQL_$zIzr5OF+#rAzMCE1DaR* zavoa8E zW7ipqaENMkBsT1FU&+D9i!d1@^jo^ft`j3>3ba`{bGz1FzG7!vbC}CV07-09iD_rO zGhN#V#_7htF79~u2$+jq`&A<7<{=!?DwNl3dDqdb&kH07z62MS^k%IRGm!i3dOmbm z5^k$_}@B@GM;8xZs!@d_p8=w9((Sx@^Ygyx*S9Ml5t?8C5$ zwMoB<7}}OkZejwgL6La8wvP~=$ImxqvKm zZqxGDB1&H76Y?+ezqyA3dY=&VXCKDk&2Hk{oo z?}?6hN>19`IwYUL+V1x+eqP`>CZ^1P%-)*Um&z_69?LX?npPdE*zqfp4=FXD|FSZI z8f&s}ZM~V<*0$NR`{wyR=(nENN6lT;KC9Wk%I-dF^{2fg;n=<^Q;mT}>PSbRIH-Csvdd^k<~mEd^q3@Pai zCbOvnTm=(055>GpL4L^s<=5%LQNGSc4NGb8W~0GBaB= z``W)yDufMH7)DLqTsCl5!VF(_Uv_sfZqlmELQ{Op3n#&VTl$7&TnAKFeH@;iDnsAw z*9{vK;8vTmFQsAnQ2Bi@=yf`R!6B{*ZY1>i zM8a`ka|9+pA_5Q3NFn{lY(z`TJ3=iI2nSrhh*~8W&KU^9f_7xJI^yY8R*-RVF=j*K zUZ8>$pZ^bqx$RC)=goc(09f|!d$Gov+D$!2z9aYIMgXhI!2yYj2M3j<%ALwe<*Ul# zVrB78Wsx7>RF>{kmcIFKqzc|3|3P%!%=yO^fcMCMw7r!i|CjIZdyzZA7ypv~A0og1 z=r=dY{~QBM0ayncjN8QIZ21ClvF*4Y-f7Du9)2%;;!1LJF_>HcILK~g&j-X@R#n?b z_?6vPGWf&nzP0CHIfUHxNOh%$HZs=;o%H&v6MrXmf)7)oo_^Nx>a0#oEPahf;z{eU zf3B16gsqln^Czhvwc3=Wt|LcGO;L_z1+T5IedM8eN7I+Ng!J`iQwzud^doOuTD5WH zF}jWoj#SsjC>ho1iHWFD0nH$Fua%#{b&zqgMK=ceq$j7xb`cehMH)y4ltmd|_S!vB)jH^~3in?G*)85G|m{}*xlCi#Eo zEBSwyzgoKUm;C=%py0Lg|Kp^wv6T;U;2x>S^^lTZ>pRc)5B7JSWe+TK23tZ2NU|xe z`R~~Y$6DgImb-J!hdj32o(gX0(s21ukM5`c%AGuVnEs1HO)0-3)Q~KFJauL>Vifrb zYm>@x43!2j&~*4%?2;sOlDG5=_B~Br9r+u1rS`~z+f;BEWAIH5F_qj!|O*mkSqz>N~U4l_oPI?1g;qW*L&JddXE2#I6k8uP4 zm)iD8B*6Rl|DENK|E>7n9j-53Tv=LL_>2Gl@!frY57+X4rELccFk{YaLAV=N7RUgU z?kNh=CzgO^Np7m>KyDx0PZ!DRcxNasTBo;gB?Bd=UlEGXQK_@x{|kY_kK(1V(512d za9rE?sVBXNt-*x2jO#jf>IYTtBmXwHOMyINt_4$x(A`)jue_#hib1gj$Wdo*%6+t} zM(p~}L;SI?IJl=RIM%&f$`bDPRk&4EHQo%>#gA>3%&-&NTwh+`?9(BoO*xnQ$lMJgX5X_1cAyJqV(^~h9R|ZLf2?i?7i4-!7dr~{G|@U z#V)Z2*tku*z{G=PU1Zb$T^RBEN%c?p;s*YI`l@;Oui*b*EiB~uAIo=%5IqUl97J8`ekRGZnj$Z>X@yaiG|C>;nA0#za=1NdbIJxqm4s|7 z6mD#pgl?6{~#b@KBi?&ixrpIuxTe16AnG0Z|QUw)aJaVRc!?>KVb z7Ey4;C1a;InCW)WC&RXT3O6rG4jBHBv!&b<-j>))?rxzaE|&D7d4E9A#NiEpvq9xf}iQu^|mlxl5xA&;pF)Ajqd6{4hEaK`FQ(u~(^R3_VsV zo@GzQjJx335Vi`qcn+N6ggqkMvH61F>fS!l{IMFp7q^k7UFe&|76g^WNH961ZrfM9 zuHK)Oq~m(u5vP;)W0)(D-~6esV?yh28a65b$YZqjTGZkpe~RYV<%U;1Ev$0vG7VO? zKN`aJz)n_L@lOtPL3Hp_vuaF+X+JFdXodQe6K7V*)ME zL(*`fh}zU**7}u0X^;gmv2Xp5Gj$24kfIZT7HU&V*LcGm?egYypc3!T{*v$(}WNe1HUN2uJAs~qONj)OR|Tn8g~yv|O$Pc*Also6#V zPp3Lb%8|CysoSr9mm81t>!0VGqQr{96!r;|!zWJuo!Lf6>iq%|6JIV)(6>gw0 z&&{g7tf0>}>jZ8W?p8Q{&JOc)#XGV0qgLTxfB$cRzzzN%G@W+$sQ1TRK=}Wu=W^}& zucfIE3mLtQ+NZiC3@@@+T&P|k8($imOy}I8tq&~D=QmlpS3;G#smI`+A$<|bABPU@ zdvy~N)=nuRibn&MDl6Oul_k&TCUip4vEcR|wy7$qB)8!Du_|BkV0}~$G4Tx?49U4c z^)c0z{*^0;nKqq$K!n^+I7#Z`PSYwmfWz7Kfv#YoQvSKh+z;p~CLzak;|b3}w#^uM zX2sz~o*B^5Z#{u|I!eCDk+kG7dz*2ySIj|5B@5)HLA$UCd)I(jYMsH6>BdqzMMn#o zC~dAJ0_+u0B{v#VtloZ9Ji)k9d7{fuz1UsRroQI)Z`qdD%>FIg*Hz)+A1~Tx*AG-a ztZY~O>dTQI>F@Y_c3c9&b*n0`G5p0OJs~0d&_5#|5}(IJ|9PtY3!V~3?C^)+AAU;b zvF&&}6`#J-ULIJfI70NTbh0_ z#6!A)`M|8>Qltu?xyPdNPP!l`D@TtJKqS_zsDFOyaMlg-e-}1%+WG`S=sofuRWzOd zxwGK$|Ao8Df64z(0Q&cK@pE2Pi9%#|J&t0v-&T>Ph)l`RaIfU1Y73uI`AmWp`Ggxx zx3slMo93)tWHF8bJ;JIiphJA z7)VGeyp7~XmYcym@MzXfh@yDL!C=m>gi*AE8?MhWfjgHKgdLZsaS89Q`4l);1c*A9EBH)T8#WFfwTL>TzI$88ea zbnJ+tJu&fb3ciKh=IohP;OWgX=0v6(KBy4q zNb9I=Dx0p`nw5WsQ(1n`6q;ZPI7WO-TOLBL6BCb7^)$bFax9a%eop4b72g>5>)_2( zg)3d~M_xv|q0P50RRYd3IfSdyxycIwFimPZHRub+BAZKnES_?iNiifz50N^+`Nx5T zxvL&s*oj^v4&up*blHin8QdfmFmV;qG_~W+AiG=(uFF&I&#v+~ghE`#I$EoTsCEa$ zW;2*ZICwgtBZqE9eC(M+x-OnNtU%cXd=C+&6b9DOtvtWoW;f8WAu%??X**M!bm4G(aK?nPt*fKX>H zd+OK5oT(z^;d#3=oNadj2V@-V@QIJKt8x_m9R^WxZ%iYa`)`uc_+FX!*9SQSZqWar znEbmx^6TdO&&B2CrQH8>*Yv;TmBqjOKYs+|AKdm@|4+5qCextWK3-VhUpaNa2m5!= zGB>4%AxjVy@%(qy?GCS00gJM1btSKQ9Mu9Lyoly~M<_N-235<;#|!Is+?Z(^nOA&TI%UQf*4GH=WTLFnX` zF%=O-CIl0++Nnf7DXXr%L@x^+Ow5uhL8RB3hp4aCEFDRi9Ce~KUO6!qtECtvwQAL} z;bqJjSQ5Yln?FG_`%iLNCa5^e`r4;_5oLl)Irn_oJ6&*+k3@Ae>-tFZaaBj|FhBA* zBaM%wOq?)yyngMRq4{VORGQ2*?h{Noz@(!Hu`x=MKIx#)9=BA6pHD5qq@xPMU*y0itEuSWi!Z)FzSq5cWG$g_dDOUIOB zBnBu67@dfGIvAb~HE}c(eU_sYi({wab;W$CugqCy3L@7Qfh@S)blyUFuiOXPEuo-c z&5gAL7FA1NB$F)Ls)Hl04y{gn!w3I%-fhW7xzy@J^H@87HZ zJbNfq{3ZK&wqXVG^{Z)EqF+b9&7SDrPTWfUp=3Aq_!sk!8RWB{1zD`7xtNq8iD2O=T^r{V#It=;RmX<)pZi4YI zhZNOT{l>@(a-v1cHe;nS_0qm%y7r~Hio&h2%;OZZSu|{#F&t0S2Q-?8G&1NM3S=>9 z%%AAaAI3CSb6`r2RDN$lXh{9ck%nBgoEjGRQN`9`U6VOJ(xz!`!f2lT?OaQosWSB- zPLm54M_P7@Elr(uU!2kp6p6hO>@>8AyCA(gZO>RAW%CeUr?AFqU?h|o^(J2Dlr${i zC{}PLUMUd9Ed9W(tSTKolKL%YwTQ!2eFPh3n@Tu2B9c<$wj@9?v)!#3Ps_<3k_sbC z;qK27zWaWM`Sb#>pwEyC^;Q8O?XXm*NGR`kN`%?KOOgT*= zA1Z`O(r9rAcWGDyY)d)x39E!{knDAkkBmP1<^28M!dQa#e`SOD+JF4^^0(>x^Dh@4 z%^#0UqYR7e!F6zWBHx`tWo+(6osHG)wmAKJ4efDYPR6*xw6vTbPbj+(F0wT@iS8id z_Cn{-1gp^5?7WHW+?iq6O8-xpa;&TGXQu zIgDWgiz6oN)RgUr;$WW3PN(MQseI!NG;EMa;Ys=yJQJGT{3)q%F(vSk18E%B@pY6A zNpe6kos%@C-z5Vsbm3Vm63@Czd?IoolB8-D$Iu1sp;%yS!FNFKO6eYM#PCmgnEjxHk&DMZ~qtHqNuw_x|flUwRAm}?(b zvI>?Ky#D26eA?7a8@g~|c9z2q7i}T6m=qT~xUFJ!*ei2gZYS?#3$u&fSZVz#@dq6Y z@TSVcgtBjk6HEl#b;H)`^K8KfM9Na55^te>uvn?yBki2hzg5a5m;U1hOA1Dr*NcAb zDr~&W$``K__Yc<{TPMY4mAU;N%mUiVCa);gOOutkdXxE_ROa@6$W)kGKDzAXY}D|@ zMuH7ca-@wnFRhoopSE|N?QQN=ULJi%XD^SQRet8@%h^MIzC7BL7R|3;!qbL7HQlN3 zxap5gp({K-;`eXX+ezW62BBvyURG4$jehgS^>BO6Uy`%-{JVL79StA;V%B^e+=cpE zfZ<->$Ge-)_PIr-GPkKa2k_wA%@XJm#8VQCBv!OOVi|IXivYrSNsXpYubRUd8?wog zuhO*=H<<+L(Rpx7tCck_$51SHq50vf2HCE^=jr5evJ_7`%CNv>PW z@ElK(<5Zl;WDvXif$5j~S_z@|y%x%W62cQnC*3W{M6HJaeQFWGWWICtm zg0p=2-mHZnP?JGKzBsSxf=oPmq&dshf`LR6d@IWmv1-(ppw{u_5p7Rw2?ezcdrVvJ zMa&lGWP&60Dp;*HB&XLgvrbgT=v-XS!`@C~j%yN^#+;Z92NVxpTc87aJtK3ZSstdL ziiaR=OG4q>-5I!*O-lY!VU>a<$CRmdjge8cu(=`>xeYOXPH69b0kaAJY9HVnaZ|#? zYqxi4E~u2c{oY~RHr@(QfNS$$(BX8DsxBPP$2ir_9tevNp?TPa$aXcq=wTZjM#jH_ z7>D=S^=#;HMw+JtypS&pTqamgifnJh{!1D$Jv) zegg9pWUZ4*Ac%;8@TC|o!yr<8q|3iZ*KArk2El#A2qh;Y>nl&UwrhLqtF=N2IQwz2 zP#SfTnML6X)AI!#&g-DWd3}`@M>J`FVDOvm{>6LlIwT+g*gHNAMLK{_RFd#D4g|&> zy_F3uMcgn)%!=vk>265xXjck@d4obh0B>_Bb3O5Dx+noN8HKlzPL)zLL4?)6!)YZX z1NnwzEYK06GY($Qs7`wWr3)(JQsG(ut&G*vsup4pX|~LEkGyu$5*0jFFm~xo2d84J zW|1r|RN(1SNE{ks+Q)EUMGHoe4ASpSl?pWqfBRtt)SFZ-1aULW)R5#VIrN6X`e(pJ zpMV2l_L!!PIojT<*4)`4#^Z9xwo9l|P*<@fpbL?%tC=Gsp<1WjfRyUG8L}B3wLur| z8KGnC*=~e=gU=Xtl;&*Ejs|-AAdb}y0CW)cL-b8Oi{YJwnGjJK{tIA_2|m zeg(5YSlxK7TBVpsZF^h{kob=c5a_86bhmBZ66lrPHp=c80O}A(csDImarkT-weo!L z+4gQB=XNp;TybBL5@c$%@W3qE9cNBAM6+q+BTLIAWoH>ErQ~*>B zuPgtVd6ijdNQ-QT^+S+=!oog@PZDMkZWP@En;j&9&C_pBx1J|Y4c&K>ozwj;zG95_ zwTgeL?k=^483?2$LRD;Zk0COoJ^@o9>4rGJ?^K}|Dj?DmqpA(&o>E0k zPd%o$wck0SW@EFC9jbqf;)~gDKCkU%mP;~1ny>>>_D=A(SFLc$xoN3uzJ}I5#W-V9 z9#I)&#_WBqHa`QOUw#JrUoZn5T(Z$>)R{vwW!$I zpRpwUNGIz(#XYV$Y1irKcUaMZ{zXZc3jg={#{1HT6o;@7wlvgQQ)98!vlrGxt>j8o zH~oD!()Q`-ilLZuY}JC@vx4EzVQ!fMeANoq&|2m(u5x&9ii1gomk|A-H&~+Y)Nr5NU>J~khjm(` zY_Sfk3pXiP7kWOczXpxBNfF}z2;)oWf%>}L&;$3d*R1#7#7VGN`w1(Lxf7}f_!dtY zq4t1gLn)ZK*}9Pan~MDXK6CewzYNvf}Qs=MnF z8CEvp;&hX3-cM8>~I?Jn$AlE)c9QN`+m&b<4 z&dW`aTzs{<^t!_A{e9oBE|L=pcN1jlR({ZvHOCZ46Ve1&W&p&D6Utw|+7TpRRIv-Fd0V zs4rP7$=+wjFM>n{45-$DR3l_({Z30|E@TA(O6tX8?L~5jl9G`e-mzj)LdyeeK87Oi zyhVwlJSWyzIK+x%&^AM@LcMsV)2yR6{Z-hvx)RH182AOl7s4j-bK0j~%jKLURx|J^HptN-xT_W!1iKJx!G{npIzElw~d73KiK1jB{$rv*dlf~xOE z&qrvmDi!sh{|}OXy)FJjE}-^RP?k)*Xb<+OA(#9>4PuatTDs3!rBWNU{D;*(&H^|% z*i#A*-**$NY7nP3(JV$MhLqra3i~EMdg69eLcUP=0p+Cf7#EFDP0HpNi`P%`LZuS; zscC;sUHBSiH>+YiIaiv$N8Nc5ElIH|c>g|GBl$~xb?4!u$!>2l`7m7&HvT@@Ha|Mt zX&@SK2=cGUTq(uorv9inZ((siW=?p|$f|wPkd;C;1N+U=@f)cZAt3lc>Wgg|59RY% zCK#&;1rE$bfBN^3HkPo}6WnRwPVt2XcNVhZT*6V2tN8Ixh|e9Iwb z5F5o<(LV?6NwSMpnLKFDpKWheKTN&16L6n{*Rig=9+}P?2^&$pMTi%b?Nqe>&_n_s zBhFk$$RWsnQ3N8b{-y76GRtYG0;c>aJJjoXXiE6hX6E`qI}*n{~GoxRre>k<&C2iF~iJ9!^rVa71y_)0V-EKji>qC zY`^KAs)0E&3MzfuG2+C>@Vggw9mj@#t6vds)PV^!Ce`FZ9VKCYM;H}GNHAG5di5p> z>ua@7AomC(f^hEUt6G8ylvmoN!_ssd^mQ(IZCo6{+G1QGg%bzWWMHj}xW@6A7XCHJT`ahmc%~FHM z9F6qS@v$G9!nOnfV)urnBfmTb&(U9wE@Urf9|NEScUqj#+lR?a_n80phTW+GPHo30 z#R=@XG_lqXlmA3s(4k~NGMhdBPq0V0R^f=UXXGf#zJw!{zax+eVhDbp$8ztnwF-UM zf&(659pp7UabXg4WbtKTkb9+aX(1fRaUlQL=(h}fi=;47SgzOtnOTw!KOQ8<6*IKfL{bTm8a&&CIwY48k~(sAl4Wha{JUa11#m;v#j z``Xtz;`(u;Ip_~@V+wo3-X?K({g$MUGEBGm+xz1;;JpuVhk?2Et<{a^YjVY&;Bol& zK|3vnM?>Jl_Z#bvYae*!kNhzuD71v%hidhKlzBRvtizf03=jl%2|qY4elO$&&|t6n zFw0Hi^t_+eIYM-&S?8HXd!KCYJ*)0+tUcLSd0G=mnw;5~C^8vg#HnPWNNx6=?Z>~? zrjp50woeEr-XD*ut9$Bda-z6hf3i+(_bIK)vBfj)2bj=K0l%gu-X%k!5j}slGxPkF zNUUz5P5>fH(xI81_0^=m|4$+hom?R{Kp8N_p~q058_B6??@<@=;0chq>T zBJ8_|h#dMXs`paw^dNEwkp*=O8!dp^aTS=rXugD(P7}f#rdlbw%Xrvg%J$%j^TASm z9i5!MgM>P52{$lBJ7A=y)M1zU)w08JXpDGrp<9C=L2T$vAMK9}f;p;a_|8m*IUi&9 zRn+T#O60NpZSVJ;s-2TBi!;KR&L6K;pOEO%9?ra!0&NCWGhs3;e&%JbKO<|K{9tBY znhK#kn8D8zE@S2;2RfPo*&p^MJtJd@Lcsjo??u`_^AdlumbsGw0GE2W&}hHWnu&>e zXVh`*|6iw#E^k5~;~q7ezU_z2CQQ%wgj4Xg;y{LPM6vlf;By)Ad&tmm1Q(Zzvo8~U z)tD67z1(fH8~R;k)$PHCl=rKv(%8cmgtT)U%bAeSMQ)V43Tp&el!YDMg#RXw+mlIU zX3Aj)WB>b&?WbZKeF;`Ie$wcOQRP~FWq0*iz4j7LB>}J-;?;(IC;NvagBcngOW9t_ z4wjwt`WE~o*B4~LA23b;)geK;EDewC?ZK_sv8zTVw z7?P=f+_fDL#~gg3qp*KvF#gwRr}+jS%>c(Wb5g39!{x-E$#R$7?18)>;BOIUX2K3+&JLC{(6Fw*L8{U; zM?!j#86E%b(E6V;FfiZ$u%~)_I&FlKKgxCjUV?La0O}| zdIzE@;RKwtUbuKg6U-z#DYG?6T%|}Szv|}im5KtgO|R7fQTvAxQY(r|$leJhb)_DW+e^2ux;jl_t0flTJoD zxb6b;?~`iJ(voK**;)1D<{X&;H07M>6v&a!8;Aypa^Uz1>HPi9=7*U_?>%QvEU)&wy^&a zPqC&-+beoS&Iv%8U{KhQVosc#GFCce(P7ZT&VuqYacr*i&X!s`?QPeRyGb$JdBtV; zL4+%#AP-2x8vr_`kct8!P88jPVw=Duuw#8nHfaQ)Hm)}B75;^v3AM~EO&n|KBRRM< zDI&iIOL@@80A%Uc%^68oc)!h+!4Sjt33-~+7JUGDCfBGfUpIgAPO2QQToU~KtKKHW z_^2@UHRf3GX7o}p&#I&i|=3vw*^)LNWzW7VMen6;msUQ0w zbo4?W7oQI+uP0vDe*8sU|55Jr{(N2PzuvD@4i&wVXP@%|QA)MN!U7?Y+QFI!$pD5j z1x^#0*&OJ$Rwa0in3Z28C8s|l7ig1mKT`st7myZ!H~t_6W&$*YR}^QgcQPnvu_zP4 z+3FQUQzVzWo!|pU5Sza};s+_^!cbIF;@FTgpcM$SRG_t!0wusLV)i6ul!bD>C7jci z8-j6%6%>ATQI4!I86mJTg^m3Oy+2 zbPy8KX|V~^Z>NQY5k*1ZstfZtvIp~sYCOK%}v})>0(3tC7 zNsT0uMRw?*^eT##bX5j&Ev@aAdB7BuROBs+c%COX0@GfQdq(}!LmX&LMmJ?qc-PZpQ#VQ^zp;E_o?eQz_0MsDX&3WWugP031Qbgf>FwD@fu8 zg**Q7`nB!&Y+})l_B36k+C(^L@V?6~+!Uqq*hmL^gTgr)ak4(H`FeNS5E?5eJ@Tw^_1THa} z+A`#GfXY6;i}N8R|_cSn@<5^0J$*JG8fH|#4=-PlQQ_`R%z1TJJTv9j1kzL z0S-LEFJnbc8@9CBFgXpNA-42*2<{^aTnYla9qb)Cv5htHbsu!&i)?q%&vNSFL*EYV z@ZO%iBFnNC?OJuus2K0PCZuN{cWnE20V}~N#bHh3Wql?g6f`#l3SGbnY5QZZ8_a{Y ztJ$Gk>Nvh21)R@XBYnk?ud_$5UcE}5KCjkl$+MN!-?aTUNBcYA zi(=YKCgD_fcei)3BUuiI3~MIEc;P2A+%OsQ95_I{9%WkE%s?TB1Sw>=O>fL|JTGKu zO7sWp{}b$5R8mmm9>OW5^UGLUv^?yA+8v)$JC4A@6S&5Sz!0m9+_Elznxx`@$blnE zQ33Q}q#D@|MK2&bJsx_fBvwl0iWmNfUH{1|2Fqcnj4atbXW$2q7}zj*GGV{jJV;#( z_3?Lr&)A)>$P}fhM8Eh?j^USGu`b8-us=u%vNTqbW(UwPTO+!@mFF9KWZ(niho}BX zI;p9diDIzRO_g||G*NT`h4*js7DK5|Nqu9$;>xZ;@XD_7So*9vTs6=&kJO7eo?U?W zrsjHYceB3xz?0FPTsceCvdLh&{=!@%gmk9e~?A7>8x6=`}8{7v~=PHF@!n^O?f*B)TUv zS^~kGy>nj%u=vi*K<_Xv?vZlROy(c`qfFjk*#(hM4C-QOfSU~aw|s`8WX6f{j4a%< zGQx4$ZrS>FuYJP*V_`n?|5%!vpOgQ`{K7Z?|J!ZuUwrEt|Bts4q|N^$0E7nx{QODZ z59Q_hC@5fYI@#+Sle7ejkL6&Ju1i6H!Zu$T5Ac2RwZZ{XQUhBobDa~L!o+_=65z31 zZ~3qHToZGSF*`Ln9)c2FQ#i3pl)eJ?D@nOj{yCZWPzuShrJ}F5=tgn>QZVhG9-1km z-c5f*CGS5q`DxMKvk)}Xp^&`wWay9OB;wsQmimlYNHSCVe~{S5DR4dO@hV| zzG*V-!eml3rIYM&5~?Mgpr{c~$jXq3c2`z6s>G74&Bk4k;X48#I(E!aVH@b{tkZ~1 zd>1YUy_@*#YDVv;AVJWe7pV zTb>SN?D|~!9vP_c!`fY$nJe?H0;h&F{{_ zU0iDn^sIeW-kF+jQog+Ity*4Nsjnj30M+smm)e zG~ovxKqUO0!Nyf^@}V$+0-Q7@4-<@pIQf&lP6t>VH_Al!9&w7J?UkyP-Ydf8m+TyTS>5geXZx~pQFEvdky{16oLH{k* zCL#Q>?={5CqYNZGVO??Af~n+#e|Zm#g%o6GaO&Hc#-)|UOQCs5xzcnz>@`V~1nLLL z-S5Qks0S%(!<*kdgx7IMGiGK7Jr9ica5Q_>5t*txv_$nB8cz6Fe=PhdhC#5F9;BH) zvBG4pgf`(UH5*$6>PZwv(q1OxVF2GK>C|m2GD32RF618Ed~G8TSjXwfa1Q2!HpI)1 znHCS^&S(Ln7Kx73Iu#w`b!>LSbH}E0jHi{|-3Jdc$?|q|l;Q_?uE67v$QmI>N<^p1 zD;pbi`>n?5;nsroGxv(JtRxjT0_<+T+&FirH0;zAdmS=9PX1u!m96Gl0L#f`xjt@!C1-@A?4}uo!9I^r zfjXJz*f=5V*H9;yOLa?Ru(EPJ_!gQ8^}U1Qd-p*e3_pAz%Q-$_?}JG=&hBAG$;Oip ziEewCY+yHC<_g?%Ku>mdx2B$&-v##IlLRzQL6?U_UqVmt{iN3l_4CvtH(&pR$p&sn zc_MS~*gSKLA>8N1ndG0{bfSS&hrxivE2qVj%=<_T-uxv7FQwoNc^xyZ)Ba5MPFoOo zNTicM76PKlv+&b*=P&)2XX-BxtPXD8j%?gz$QDqeAM`QKAzqd6$W9`n;!C1z`m@|V zb&%JnJT%0`6TQ??dYV%=Pds(N^?O-D`SjH%z;@8QQECpyUkbZ}uD5D{T1@TJ9Zvv*8%aJ@JgPE5EU zPNm9D@&g%D=!vd$Ia7(#dUc!T=XJsA!4?$F`W9CF7nT1szij{6Hg~xHr}>{278Wf2 zw|sADaj85ve!7R*JGzHv>4`^grkr`10^6gxihAqL#Bn>mGSD9f`$Yqox?g*1=M^;vLzowaH3g={L~T);wvTY zqp3km%hn|jBKTT;NAp>wR*DM`gJ?7O^_hI%Q0pFa-X;5k{u>)e6PI_C#BaCQKSlQ@gmWFXUykBs}RH$6Fz5-ni%DAhFJ;b8#r4Mq+Qa_T69-GitPy z-NTcCxcw}CJMFaMN1P8rQjW9_lt&@M$nY$_mMV=dzwC;t*nkl)zYtYmH@uQ5voF1* z)Fp9cqzfVH{QS}z`L);fws)(!=hKO@q!6W~W$2^1-VDz)L%u4b30X+?>rbkCtIw`( zr&kNv2IE%a2~RBFiMk}y(nnk5gAuTRMS6H)J7_Q6MjXqhk}g3qVEyDMKBZ%gpxCwJ z-289sJv!^9=cnOU;#wKrxY0PmrSbLH^U25NBRkFX6nNp%DX{#H7Kj>UzuVtW2hk2` zji&vWwzONwF$c(U;S1U%lkc=z>!0H?l%+5J=H)@Y=%|_gCy$y-3;vLtys;uCfZ?I4p1f%nCKN*G-r>rxFgequIMEweXiKxf-%7aA zA~?OVjyKnbG~|1`*GIck^Mt92& z(;F3heNP4**7uXWVuDS1v9hpGp&e^QBwv9L5t_@6GH|g7JJt z?>_jMDw<{fx42Mh?3d?}u$L7_Te70mvB@Ux6f-Zp)QmjW=E(hzy{b2wktK)`iJqL@ z*;rZMx^LVll>g!L+RRFg6c&ZTb`Qw8xH~y7KQHuMDHI+h{P*aKfK2VIG3%YS5B}{! z;8||N2sH?ve4Y&*)D|;3DKt_zEhKxl)F#%M*%tst<*&h?flu;2vXGns_6kJ`EBHU1 z$`eiocNtTX%wE8i**jkg@HOb?0)Lq3^J7@gNyY8pVKIrPrT#$wQK8%SAl?Tep>s0OI>70x6{e5QNa+}Ay&i#|!8N{OR9dA3?HfzL&Cs5P5sqtYdm z2galGFq*I&NbcIz-2OqKFfIg*&C??~hskpaa}oQrL@L{)2=)>D7|<9Z<{(H+$r{(? zmrfwG1p+HC1{WvogK8SyM3S~%CQC}F6c^=jhIxmP7ti)mnb2j-BXm&kd_(b_>JYM{ z*2Ie40i;Nwc1KvW=;@8CV*2UaEoIL$0$p0c5!rYo^i+aL&O}+pHRe!spGST_nzG} z4^}^B&Dx*gIr_dXa-hz^zyX>u^n)mB^@Z$5OD-d)l_{YW*Kvt)Ft4K29_!NI&2Rb0$!lPm-`v3=8)^`*5x!}{6y;b{5HdBf?%R;y4K z{eQ50fG5&_mEOKBjZSCw@wn*p;5-V2DpiUG%D{La#!Opj+Z#-?!u2VWQz=Y+A=jXG z)_9NpvoruYG;9d6VkzN;1kk!z80UL4nLPqm|}~*gh`mv-hMSEVG7W@ z4U=G_u9HxscOI`Pj@&{}mv}soujqZi5|(Lz%WWxalKCl83SQa^enG$|4Oz{ZWo#H=)Tk{qTb#$gb1hI+b`z)~r%j(MQ(w{;!|lwtBB zg=}z7gzXRqbP#sXb+V|T@_XSftuq6iC_I(JQ8#rbhityE0QyL)Sj5t_XKea8`JzNs zKE8BF}ysdp|imT4v`1)ggs3>s*IS(s$*6BL|DjWUudv64%3`E z)yV-fb#{h%GJ9u`nU5{(kfI$L3*yF_9-od1d?BnF$=RO2Go*RYersHZf~gG}ojgI8 z1vfS$`RY@_ZO|%kO7wAbN?r*zl?$YOI<%S&M!?r6u@K4MgQ;lbp3*mvG=#U>xc?Rk z>yyW#k#5QAL)Ia>FzKGdu4K1Ox56CjjI3KlLEmz+M+$6=lp0xfPj;JvkyB+9gsSvm z5{!7m(^rWQXBKBqsap`mIjsHGgv@6`sO-N3)`L!N+=+EXcUqv7|S?q7Rw5X)uQ z6<>7L_J610e{AgK%I=n>+S_}!UQ76IWn<^rN>bZ?vd5!p2}d&B?)5!ABWo+c>l@X* z>UaF^zwK<-YU__Teovln?N&F|<;?n>QyHV`S(zY}U-UG6*)EFsC~7a}UPDPE?xFAB z3+-bHe_G{cNC!9v^(rm+k8~UZ=ya5(ID*3C>JwQ_A3rB`1`9&| zIwQ8?rjE7P%wysU2Pnif`&jD-Hs3|mv(7<9M{BPT++($bnd73=lu2soyl92D@fL$a* zysHdGm@>7wcIsr24sGMv=xuGIzar9NTpI7K^%JcI1%#{5?6ourSGo<+tvOPt2voqA z@&p$2doIPD#`2&pgG|!+tayf;kuxpEE_rrD2W}b^a$7E-h4g#0tDuGC+NpL=o#);K zu779rkm;~z+;OD$HjcI_j8#${Wz7{W&mGtY7>PSD<;qZ3Fx~*!+}IKLPEcBYwt`wh zb(Hk9$>GDyaO+@dg2Gp~YyC;``}TA4uDqxwxRh|oH*1{hj%$Qn{UwEZ#)okww3C<@ z(BTN~O6X9?Z0fb?7iSC?3{c(JomN_TQ-J}r8KMww(3YrqPRuqbSqy}fC}|~6aTgYn znHDC)J6bG*)$VdVc3#&CKdMbCm|_zCRz(p)3(I=T@(DgYc_;o7P7jrA?ONd0f$KRz(=N! zY$`!_$T^iu$x4bX5pPV7+_2(eFuHiUhP!5oq6xt!KmAqcLZ~eKDN31Wvo`jf{2&08 z>Bus;b1m>A3+ zEQne_O1$n{Ul~ZWwaE-=#)x?)Cxg|{;A|jA;ajD0d`^fGwKa-UWIw!{-l?d(qkqMJ zK_dLJN9`<-GctcM^lB(sq|NC7nd}vpQV^VfY;JH8D)F#eBY*jZq|HIS)y3(l(ZY2F z-k&x-HWr>=o!DJB0@FCq#l-OB;s-rn85r&<49H@j36oL>EHy(=fR--^TJQf<<9W>s}|*`wsa8~uYmb(z{*-E-+MPlrtjQhM#S zEC03MPM*Q4w84{l zw-!prK8d%Wy72lA{dG=~-^eb^nogQ;^kI3_I5vroiJEO(vvt!rD8BSh|F(SC?#4k$ zaPp-8E_ra!f45A=Ga$CqV6DUMzQ0lMjQKxvB6|b~oO9%8c)JuSeDGf~*Dfs|cSJvE zgU|k(BQ)co>kVx=K6IMiXnyYAPs^?5aK6+#I88_2>JN}oM=XM5*xlqo@6B@OM8`-M z-O}*wOt*c`F0mL!J(ObFl}Z3x`*8VSbW&nl?0x?AvmvuTQ>4Ek8M_6Q`nXJVIbD_- zdI{iZCokH)(;pa49>Z~h>_U)2hwKfi>yG zrr%rUQVcL=^hRf4AGY=?#uoqjNf6oWlZq8Ak!=3-6H+s&L|^PKl;)?H*k@h;wdyJY z%KEE>#}eD1z+-c$$nVNFjvCq(EJ%D&ZG8 ziAqSMSHO`SAC5Ww@-A5{3C_3|)H+X|CNKLW8+*_=e7h_jipw!*&XDb*)M%RjOJT+L z){gbBOi7SEI817kI(|dG;?a<*^@8ld;W8f6B<63jibw*!J`Ic1NqlNxFkS?fBQ;UN zWD*u!K!x^I|2R6t%jC0gVF5+2m=1BTQ7vf7RiY~^9IGdJF@-i6);jM_PXg0vnRvvS zh~FrX+gu43OL(zw$NC_M1&Y@u8SGGLRxGtPW=A5)R7`_sBs~`S2_;YV+bTyE?9spn zxHhc^qVeI@Rq6z!88|a3{V!HQf$eFG3Sr+#>kMORl2<5L0-S1|=4%2O2`nMD+AbSl z&)#u+r?nUg1@kGq9zHeC4)sY>=8YcJ7)HG0lOcU2Jeo>5L8r((9y6B1I++?n8b>j4 zNJwTO2-A8_$rm^&gfy8*qG;yjR`Lu`uB928rCOkCZND+4cuZRn7!^Ya?4o2by(>A# zAP(I;8N3cEnuF$p&(Mha$vEuv#oB6 z|WFR*eML#Z52vM7l5$0X>(XfCdyKW7&47gzJ}A(g zL9!ccfENTlPiH3VsnI;X$C0s>?vOTwG4x!`<8#g4J#b?A#%M?Ng^?;3B0_+QISQF7 z=@?DK5J#clP-CFa5&>E(`w<_YbnBgUa3ir&P}v%?JY#013tz3EqBKm}0Irvocb;EZ z3|KM6Wl&%H@@0%QopE|AP2&VbRpK)6J?f=~tfeef3Do>Jd;>6F7qFaLyu6;rWNntU zA|?n>!n3ep#c{Htj3XrM?al73KdtUAqpVva>%jOp=}pl0P)Sf}%-1uksPK$HhLaAu zH~~O7f1N%$G8x~w5)#`@>FFAd-$?R^U{8*pH-GQ7zB{{U8QGM&Zf?Hf2}GioT1*jE zQ1WhOYRZ>QBr{5z&#bTE`@8V3#%bs0iAH;w?US%OIO!O#t-Dp=@&01#WMaP8{OCE$ zGaV+LaF*I_SYoG9bp^j94DWB+|6C?NCVXn_H7WkeW-fc`r2dw+(1@;=1UB)@JwOgG3XW?; z2`bzk&ZonP7cwJqLb*3#2Sy6eurL2A8U&y;5^vUebyuZxjPlZlN+}f*AZcm5=L_j2 za4a zoQfI@k(Sd##ywkpd4@iQr{-00aN1?)LSYLjL=3)d)woBfj%VZe5>r)p+`)be9Xy97 z3Ikj@DDQd{Q$^GIj5`-6;GkAjS4@+mqS-%Z@I&6k-#uw%$;C3+3CRHeKC}4ZY2I`hUb!EHe{eX^9hT}hiJT15dupX;L*lx}T zlufuq8#*Dl&<5MG(p-4LsMCazI^M91cm|!oApbSYr?;p6=-qB|cFD>m+~>o28r#K5 zB4KfV*+8))OG2pl)Ig|%Ln&Q;KfmyEdH$!8d0?cd!VlugzXO&DNUMNk+~K^o+9M;> zwc!3)?U96}4U?unIX{ZfZ1#V=o5Feyi|n1=bIDJfNo|CB zkIN^;U9$B%VI=eApXUAs?n*dlZfOq2$}VcsmuIwUZGvCmzfZ9spr)(+`v&GQFfIm1 ziE3O3b}$rr0CO8JAxqhj?kbl8XUvz|WM-=UCdde(+#Ig^?FN3z%@4UGrhfxvtY&-* z`Bg%dDwV9wl@tc}cqD&1^uCbkLjq7yJstN?snvn*8TXq0+n~0~%XB6k*|vG~0o#Ha z;W^q-;D;@A|7ZD=`6Lp|7Q&zU*RsAOWa}};NmtE!gMw!E&LAm}w|8d4GHj0>b5RWT+6 zV4|odugc}!C72-ak6MSsc3PJlE<3$KzTmm)E@~)t0n4N$jxI$s#S>Z$dF}21PfD9o zRPI^0-QRvkFY1t|fsddkzm-NfgA}i1QpK{cSCME=R<*&yXDhX5#kqIoyL098LA(9a z)XXD)6bkCe|3M{21BF&>v9W1rdgm$#b@22AG-TX`vAj4A$jo{rX2fde;E<>wVJbgc z){05N>$Xdi6jGGP&l}N9`T)2HsX886`6t9s;vvv5X3f+HoC?u2d6Kj43}Oi--D~5C zm+qpofkk%W$N8m~DXZ5KFmeuj4K!S%lDZxOBWNfD%cOiFCD~{+JL+I3SsqoMZBu)8 zeWzm1LtCrWal>npf-RLu{_Sz5@O7=J4~Y)=meJ{N^z*x}YY^~-`X2$9-wm&8@CCo$ z?EhK5yL1=o9peAXWwHmA7Z$(8e}BP7e?gPkJ3^HC{7>(OmH>)842pQ3EthA@OUe8~ zg*@?h?}ZFdq*nZ2p8+aG)8i3=lf6gTe=s;CFRlZE`V~oSdpp>HA<`%SteOYIH7rldyO zm(r&`#PtD{n*Qk@6z%81QGKK|E@2MWc0)AQDF4B{J8+bb%?A;Cv=I5C*OCdHdIuVx)4hD`Xjm$cAMeh%2^d_1R= zYJmkBPdcq`u{FrAkZ+gPhyYjo4hszIDXF-=tDWubKCc$Vc-K*3)rV(-1J-T6Q`Idw z5sy#LO-)%I<~3U(o!T&DZDe7nf;(sFnj&zZW-YG2m{O|q@X|^4Qe3#^s#HNmz;bYB zYW(6-Ow-PeqH$0_Ps@_zGPk3;v3~QK!*pWIU>ymsXZgY7-sa{Jf69-lX}zlLR`;Io zZgE6@TAp}s_Wg`4F!;;V4-|| zw0wuTRi%42mNoMQ2svC@K)5z>+M&h$G0ou-t(MIj zlxz#Ve*5O|FudpHs|7SN*T8e#LjkJ*wObI z!q9LBQ`b)B0#=NN91b?OYdVjcE@r6s@;yXgABIU-OhO_~8KNnh;^7EBhUGP{<+hkD zq+qEEh34V!5(wny|5vAobpbQXIWtSGH19&?o$SbrkY0U|`Dw;CyvuO!KA#*?LM+n5 zkZiGNSr+AKVU!)~f#+6yxW#!5&vJNx7Y!i?(wH{M&~|8g32np4)>roScF~j8SD#f^ ze=Cm1Opjt?mBKJIyoAHFX7UPtVxl*~yD~y*g;y*iLuWZABMg}~V@6@WJb|S0Mf#2@ zcpTfA;n{Qn*Ke9p1#6RSm$l8l-g@`4seF3>{N1A)=6vJ+1s4KujvD>OeRQ(GZrhG$ zWWhzLN1;M9NC6*J)PHhuYDsufa80*ka#fe;7U|v0eGYeYc|bd|z`Kt`R&G79gy+Jb z`lFrgwBB*Kb(L+bnR4=-#638Bic!>eR(4l59j^-%3~#GtbI@ zov|N(w0*UC*)H1Gbcjo{k1R##88ft{lY%xMLVQU<KAy&>z^j zBtzR)E|D1nt@IS(o-Jiv+Hd1nL})&t|1IT;FfUOq6RK{Rqs@&owx%aQ3nQ2pvNQ8V zF!@}Ha7~I~;L^$Qlr>M`0l_T2WKY(s8-aP!Vgf4nBju+>^mVp z8Ekp)*+YHLHOK%?Tlk&7&29D%AK?^0+%SvqN;n*~3wKdTg>SXk{3@p;D#d$MJ7a_} z35Rnlni?OAX}ox&Tv!8Erju)BM4o2*@fBo5@WS=OvKre-KsqlYUNu84oIm-+$!z`|z;i7~UXgQ0Cg?)<(Bf*vyppE!A6K`JEXX5uFk=N($4LSh{1dLa>uJF#Nd zAi)eGuR?*T&{&t37>wOfh7PZk8x1Fb=&BH8V*}4 zwy39ert>uIXSh#6)T>2dR|3tU0~K zG7zPp*%P)67h<|bcRRI7+uF+XgK{hAzDK zF!N0PjaT1bgrSeRK19vLP@OtVr55gBDm4X)5(w3+$R-Kl&x(nM(T;dzOk-4J%^$M(BR zKm3#AkNH-|Z(948UZGDRk4wK2%b9OSD275&^wQsf3ohUPaQ=TCuyQ@zeE-Yyb5v-L z{y%riUjOae{m*US-}o_{Hx~@iF3XocSDL?vU3>}A;>`Sj6fL@bOkjYLFo(-v7qKzw z?2|tOHv_sLunYGG-XMDj@l|7ZO!CDwKpp(eA(ydjh=y_h$$&gW_)q%y;EtK2LaX15 znkmd21XUnyp}i$82La35Px0Ggn$tV!$!W zCh8oSm^o!^jiHt33gdjWKUOUqy*U2)DCq_Ra;1)$A{65+{;-yC+%oCnmWvOzr@qoz zi{&FMNlJ7N9w&W;SS8XWuz{YS3!30C=Z@z2(=G~H@{sP;`xsF9cpS_ebV8pZI1P{e zAvj4D3nGowmgIZl&MZyiDVJJk)sh$Al>i$G~ZbZP#o$F%Uxu-OKEWwEf<&?kmJxpJ)OWRcSKl)LW9CW1p|}6 zOu_`8W3I{DWSF*~dFGKD0b~nfT5kbgO!;V7bRK9oh!a4~nQUw;$szSh#7@&`+Bz0| zQ_~P;Y}Q9DmrNgH+7{dKx>B|!$-_r@ivM>~=KoNm;u%M&sPE)#Y4!|McyYq6QGh^ETB%F(LS5nRZyUUyh4;7JZRigm8ueyU_gk3HmgK+4{IxC+}POHQ z5NV3Pm%DTXg|K61@Nn(h{ByrD#UA7;KY}-U%+9>#${x)wE_1xVgQ#cMs}XL2}DzB z=#1C!msRam(yTGR>!zgf!RHFhaI~)D;_egHoL1q025YIDubevT1X@JN9CXvco0P&3 z=E0DM)JepENq!h5ldb*Ek-llHJP?En$~^6YldMPri<_WsMy$lP<*H6)2$Y?PtP&Z} zfMrh;C{LJf`@qt76PE<~QCw1@5Tzz%Qu9}PNcc-v5kjETpsx1(MWtLyrR58WlXSTY zW5TvbPpy5OT)i{I>9MCo380$v;%o8x0cC&WWyEMWBC}NCCh@tJ{PR+QfoUX|hO(l8 z!UU%2Mu3cM;LraPl zj0D>>r@=x(QK3`?K%I5E=Qp1i#e)bI$zyc#-&V;e6;nHJkpm5veX_SEOeUheoGUH7)`e(`T%&M3Pr&KzJ|3-{0P{w=|Ba9SZez>?GphE4vtPt*TqMX zy~dzLq8N3LMKuH0AuRVBFqp=7iw}B<@kt;CA~hI=-OgbUSWHT`C?{5wfW%_(KF;1^ z+(I;@8CUofs;)cJP{(43KC-qzSHvb=Odg420?=*O5)BS@u9E1^er%Bo`6>JCqw!+hP~5qVD)dK z;~mbD_>RNY0dbtf4c>%SSzsCw@vU$v2TtjHSkR{>>*Z4RCx)>~A&fT_xL_t+B!8Z{`>EdsF~uT7S*0q^d2C$9PjezQ95;F4 z)>)XN)yX*Qq~y;ec|ZAl^5LUD?oKaGPhL3@o5kyi{nLX#C;$9_hoPZ!OK~R00pm(F z2MI5+?>ODR-2nAB>NdZ1{plS*4!scn3$Ahr;ZR`v~G#1ZY7pnYpsLv zEzu<8;5rR@ogYLZ#e$efql6o-8ItHs#!~VoTfJjASSqci5L)=2uZq-#DRVA`X+e{Y zIuhKl6CnT51JNNuqoG}zEXi80oWcVRDr33iZuGeZ>s1*Wn^ztml({MZC4QyMqYV)d zCpncdJzpWCepgTD5ih@wR48yOqQ{v26*a;PCbUY(V6R`WOddP+t?kX~=Geo88!|Un zzCXt5P<|skI42X{THkuHTHB4U&Fi(m4J*|q7MIk`J!`PBwh|jGAvE}yK%3ivdduk~Cl`CYV{e~YARKoC6eg#?U!a10l#F!^L z3*)%#9P9xH_C(bSq;eIThY~=U8C_2HQgx_HNTUfrLLsqU>*UrRKdo0^RaaR|lKgak zj2Xc8eW%K;*hh|?F_$uun{I^72Y!LSIU4A|w5%S2s-Q(K{k}5B?+RYA1 zDEs**em3QU3pDoI&-?}yX=HsbYZ`FKotAym;1UAu%c8$JXuQ?edCeq#*6`MI_~GXz wen|VATbiCc?hd;Rk_^)nm%ajC;C}^=erx+}2fppVw;lMl1K)Pwf71^9U-Vch#{d8T diff --git a/DBD-Oracle-0.27.tar.Z b/DBD-Oracle-0.27.tar.Z deleted file mode 100644 index dd391d5a6b1a0083aee3117bf9bda1caf8684de9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59715 zcmV(pK=8jGosdL?5NYv5PM9%l%CvytLdK0303u49NU@^Dix@L%+*lC=4H!3S)Bphh zgh?7TXpl5%GKP$mEMuC4VbTVS8V+gLurb3%%NRCmloZObsL`WHlUA%VhfWwdCIQe% z(?-l2r5BrqF=Ga+*RNp1iXBV#Yrug84<=mL@F5+DW#fkR2vQ_Wk16khaH&@&2$~>* z=G-}Bt35JFa$0dbbUoHTa42LcskG*urQ|G7a2 z2qMJbf(s+JGg&5XH6&!EKv0y+W zDo~<=45kQz3@m1-010#4kp>-OpaDV;Atup+4<^3n#(5c{u%Q_s04XGqMsf(k2{h`U z0~vChkOBxlfN6VnX;68m9B3@LhZXP5 zk;WTt^x>lrMI4cY6CmtSrG!n*aipmr^r1i*cntYhhWC}>1{p3Wz}>WAg?8v#rn&V( z8)2;H8ntoBM%zfap`;RTeDTJT4L2B9Q)0x`P?t)3C5IDp;N~k)bdyO%Rdtv-rJ242 z7i_RZ-hnrVc;uOfo_g%L2cLZODZtczH2TZFvgfs=RgAs15$-w9d3+K2HN*! z@kSjWaGM7RWTes5e`3@jAqaevAs`)S>?ffdZ3z1Ym1PWBIaHMIcZ3sFfN+Gf@0|w% z6m^KfMjB(-%mnPtvIatoAcPJ=5Hc!0)fgbm?zbDP;k_CNbGSD~s%ex#1_LocivkrjS8jk!;V{22eiu{88_oFMF{ARJFx7;fY* ztg>Sm92=e|hW+TE1u3Wx%68Q&1tef&B%lcpf*^$>SfNf2Bvl;tz&>CtC=76b!|Tj5 z61v%u~ z9LQ$|I-mduyBY%CL@+}nD!^D4vt7pOb1~DEfeve##wS%w}QGJy%eUE=m5f-1}*3}+}qn<5B;EwtcyZszojf+<|7 zNDA%*@G>W^UvWF<3sf=sSzP;#(h zAIiW6)>JnE3SAXQht=6WIpt5JMK3T*o8Am%P?|*GFFyTrR{t@IRW$+@IFh=pZ(XR4QomM>7V&mg0Iq>ZZ9t0+ALu#wKGRVnpfbxW- zJYO@I)p>0?0SSO`0#QMbCPbiBYodDw@~9?0l3QFIe9J-*2+6JU{L?#AV4*r8OIb9l zj{@eZe?q+orDPx5H4Um=LYo>Q42L zHHrcmBze)Ug*U3juxcTwE(m7*Sool@QESl2q&y$*JGGI@DevClNX z=)F6Iq5gTPOI7ktQ4MQSA6VGulJ`<|0)^`?Xil?zNyzH0vL&5VTyfFgJ-pfdJ4uq#AGZe<#U_ z&5}EiFCi%KMD>?yTy=atUf`C}EfYjwcu6H65 zcz+=9fiKs3EP+M;HB%N61dd}*`~*9N^F?UDTxRkV6m~g~b4sb?ew8x@YoG)1=O|0o zD~tkLp4JAS=0qnz21(~jlu~60a0gG(KO!(@qSAp3l5z<$T)YKOT<}A+M|ogmXs^Zw zYUO^Wwjnsug>2`8taXAXf&zE2AI>6L`;k$3bq3~VLfwXj3lfGjZwYC`}%OIBFJMa}Yr8@jN`|bG{`kcNQN7G>D7y28;(wdsZh{ z)GW^uEeB%}*5XX1(H1X|781h-E&vB@Fpo+hE;KNZcVRAikuH8=6EYA3^dcBHfD$zj z12=#iJ0S!30+8ClFVpcammwC{fsr5?lAUoM`dB?<(*}gsf+my%5+w&-<~Jw?6;NQ3 zBXJg9axDXu1b|Z|M$;xG2_OB~22A5LGH@JqLp3oF16AV_MaeZZpaY7LI~+MSWpg$o zU^6D6Hf-ZIa1&i~vlmixH%FN_3?~G9<2O5L5`sfGhVxcwG<5qBIg>LzmycrE@yGWf1YfI<5mdSQ$LDLp*Dxm;1pxQ_&PIC_J@OVFs2wy~R8!6+OB$lM{12 z*|R;g1wK1T1!B`hlv6%U;*w?9Mca5>)01c9AtZB!Pj*lqDoH##kd`vhML)>~%yK(& zP?#~1LaK8Dx@i#mm_spOjLY;^`!QzFqbjoG14vQ>%pyM1!y3BvJo?0N=kc1FW1J@0 zjqyVvECvGScrnj&C1_wX>}Mn~0zxLqQf5Mv;e%B?h)Vmhn?AB39r7VL*_&N71Wy46 z8N#0)0wQDsBQo+HY-9yRAO%y91W&*#NJ400usA3X2PA+(DzsEBM3l!t0(c`ENd`qz z5Cp>#2X}x12^u4pQ=&zH1yJw=Qa}YMx}vh^fbaPQ20?P`@jO6U zq!?HvL>dNPfDmuM8abMzPTHfJLnTxiC}NYPQ$Ytk)}%b@EN4JD!osDNS0GcmqXA@u z%95o3^(U&qgJ2p4E4Zdd2&R$6LTOs08xjV71 zycwuLQgcQ2h|5}v*Emx(g(ZIFDm@i+L&riy<*aw$DoN#`eejIe8dY~SSbT*geZW=P zsva5gjv&C21m+*;^&^dd zU}$hotZGKqg(ujWtQrMz3>H;t(*{^Y2Tj0SWl*n35(EBKvU_j^QCP2jA*%T*XlN94 zzU3np3IbnX250#Ni=t?wb~q#eiWSO4Ym}qDR3&h*2E&CUKD3)&GOJ}UCS@W5G$I0Q z!XP%O12`FsCcyRGd^)Smk4P5F=!eKqHUqQd$@^PC5sESs{6Qd5V<+40-gH?XK{RFvF6iLh1&XO9o+3R87%|tyENcS2T5JLt&GzJS(REs4Cc=I4GpuQ%NrAvwi@2kCAP*jZCH|blLSxN?P@V(*dtaQ+c z_zR{`${PKfUiI;_LFyi#>$I-rx8l3N^YcT5nzh67XeRfx*$WlKoz&l{81yuyxLj*-&1VK;*OkktiLj_3i1Vpf}yh0;EX^kQU0#DF& zATR{dTm-jC$t7$)AkZ-9fj2E@XWwIv`|-djWkP>O2N=9|+Izy_o5BDWYr#whE({gB zEX6d;t=Wu|+B^hFpw4bZr(nb_ztf#MTz#vEF+{)w$m0}+>n!9MJt`b)DG&m!dceMN$HAAG&u>+RQS`e{Rg zz>mG7Z^{O7x(4!1z&onYQ$jbZ1N!YwPP~Z3c$edfG{4L=NlG*VE;BCaRo*k&Zyay@>MkjlOE{jeq zE6^e^$}K|OBkrUIe!=**PpL(sk_AS3|0ARATdYOY>BGFBq4J_S_$bgoyv=4Ku%Xzm8?nBF(T-g-{G z*!!r~7AJ+Nsg(LtLnG6sDJ*?jc=&|m@v#PYcUCz#bo7HfpH(0?Xns?%A1q}v60@EB z1C#nR-d_NzVpBf3WOyj+qWn|TXAHZ3u1jJwEL|A3I4Q^0mLV$O>XT}1izDk8C$VB{ zkG6hoHKX2pe(ZPK=LPO0ZxHA^`iL=sKZF)SF6umZ(?uizSdVyfcJ?{VX(Z*-x8UoW z^!%HNEvZg=zWc!v(q0GDzMx5b?wX3I!?k0qv2t@#q}_X3&OX|OZSR+s?@qe!nmgv; z2_JT}?65v8ColspP#lOv%wd=~jyYEzvP6@rDb%yAbun@p!{AkPL5p9l{}{@$oK3j)MU@2cE4=a^zHR`Pk|b~#~dEVAMW?A!*j8y05GcnU+@J*-~>d_ z`1R2PmE)%`;{>{0A5Y!_)H5*$;Wwokh6D}1xu+k(66)OtjzRxE<2eVDU-@M4GPdRf zPXGlGItAb-?tfdk#4EU?Te!G;y5hyVj?21_H_k}Hy%t={3QWHLyLKNuz>1y5N4nWn zGQaivAPfkm`zzSbKig+1{SHjX%s1JO$NR;5xw@~p)9<7P%>4Vz{$NVl1>)G}pWKaY z{_Stwk!}C`Z{qoF|A9CR7Xar}o$_z+k5+tv0eAlto`=ePgKF;_zu`4kCSc9$8y3(> zk-7{x>UbTYQ$&}F*+IZa#;Ftl<@0+l1DQ>MAs_{k02H7CTu$??zVg9890eYTdLF7g zX{Pw#e_)4^=uUPme~bapCoDuC#Ug!;#q@=b@v&^qQa>R_YBiKZMR@>K~y)0l21jVt%mG6LbN)1J5|YsrS$N2j%fH?d6Hlu=S8qPylAC9136u zB9F*4CYH=9D^EuXcJPyBV^&PfngIc8NgD;81wpLP%4niuH)hl6jw#{8`i7+weFhDm z2o&29XS$$jBOYjw3BElLf%U>rPUT5K z^`Vwlo_GlYCdz3+5aDXPNA)2fheHVP0GpH#U!UK53CLzW zEDx*_AB?~nq!q4D0WiVBu}20^-*|#C>HL&F+wu9fP5uB8=nu1`7BEHdSbzdxU)66W z>aPTJTJT1ea%VjeOufG`A)nCSl{ziqqX)c!T(To3-;mHSAV39(I?t8+{MPmwUOsA} z5H1Z9{Hnyo&?Tsg_^qzrrMXy=Z;~9KLu|CfQnemDos>I;>B)0Mj~Y1oCXeosOkrSD z5HEwka75bX(LCjhcooA^w;;@+!+0IBNq59V?=>b4SwD#u<3s=gJK2V&>g=IDkgzxh5}f_-zXrj$%Rn~-BA};qU8u;ap~R}kD$gHDb`m6MVqd1 zjYVi7)2!Ti_=9cmG6@UHd^7>VGZjS0e(+qvqAi^x<~S&j2UQ@C{G$vEjyaISLg7qnE8Z!8 zxJQ(g5E4pnSt-+K4ltZh7eKZn8JY@e4|Es=;(>syjrl=>=IM*Xp&^9?@8TQ~k5Ott z5Htj_7sHFNKmnnSr}0P0GzFpn6HozAfDJGOa#tcxq!EY_nPW_dNIED`j)fagAppe< zB*P*06w&}4(q>X12n+!xPz1g}gqmi!g9==MCqR0Fz!X>l<;kSH2T*g1dLWakkorLt ziVf(+V$h&jtbxt~N79NNX(f%s#VBGaBz3@d9^a#9)Iw4_r&PR%_DL-51v zJr2rKDEVTy^MMM$cfCV()_&SRj9_Usa2sJs+aW7Z(#wmF^RYhm#wl?s@y2da00zoG z6~XJY6&cQGEKlc1H)bqONrRNjdq9Io;GLvN`t_V@WN7r2(~L73OQ=8t`-g^+ABQ82 zB*x0oKi(5*KxpxSG~vNNQ}Kq2A6zR`f<_5RB55RlWs+QyP4Y<=!|A~kz@azfAAc!) zkd5$S9&gj}vx>*fh>^>$$KE((`WfBb$C{zF_#Gyq>QqPu-(18-{K{y#0i)uZ$MbNz8ZKQ#%4-90aQQ- z#Gp6^H;qx~=pT7ta1@U8fh;P2p==s>m%I6xF;OUZnUhR$N1#5&_MEge58XLYg< zJ+2wV7r#iXXcKv{I3g~LmK>uC&p9c)g&GEw#dunXB5j-={ZlJkG#mj&6u>!JX}obC zrnY{fI!e>;;-H-oDg?ylu`Bn3tk47K(i+wu1)%PLWo%3-p^oxQ0j^U7hJcNdp{`9q z*hk-}B5~&zkzr6&{oF+L$ryR3|D2)9FnN~H<>*`N9CoLc{6F^SG{IMVcr>Pk*2J5Gl#+tT3L!eS&Ar5ph zhRmR*shTM3{E^;q$i>dBc{UZqGxT74hn!)u^jlOv?RI*U61&DQJ8!dTI)s)GifNOo$cek#tB{ z1k;(QEY3qcxj~kWHLVp@q)=%E8sw-7V2Tn+D|$w=D1}&=K2>VsNlT}i{^(ligit|b zZnEf+QC(jc0)nV5keEt2a5zGp?(nBh6pDdS70PgiC!Ayr=Cg1`MN!wjzzFwNuCNrrb)|6UjZt8!?sd;qI z_{1I6z8q-zKu_gKbuCjN*c{n_0zj(-v8CBZ$#^ky$5b7TO?5|(P~^BgO{f?^p?pW< z&C?cYV1~r$1B}wrgEGr87>6LDfti{%qF4&o;aE1kXn(q+<_YXwC&8Kwv8gsyB}M11 zx~~$3H{?Yn=`i>y8Il($&?7$y#k`LhwdXa|gg`?f>hyR5AM=lZ2{#zj-T+bcsQ*wH z=BN1jETmX^HDHzwe*i&vaxE=qMax1(5H^~p!4Z!lsfh6%ZqC}FJ0tZ%eORv&Ln1`2 zT*1nDIT0+W{DJOquJlK~;x~|`vdkrkbWOp5&?4o+h!)f{o>Y324-17-6{{27Tp?sb z_!tRm9)e43(yk6P3^5yi)EjSyexSYj(39MrO4 zb*I`CSD|A1R8k3uo92_|k#^kY9pj1SPsacO2pKTJESB(ooGtumu93JC-)v)St)KPY zX+qtCJ|?IM!HiPWL>9B9N(BZDb$zH%>_4PQeBu`CjK-rp#M4nG)bv_GUEen9Fr+U= z9FE|6IT9&;#Sybrc{UH_ctZC`7_}#3^nEr^)Dk{S$rsd*-RL|>2a*c)3TPAbv;CtD z7SX#yDVGjyaXPLqcScuh*dgA-;gEEZ3PRGrHtHPr7bH!n>hW(}451Yt=AxVEkPJu4 z4p`Xw70c6W%c`-JW1c4V7$E9neb|>H(qHN>&U4ndADUfaNygPakGbdutqmz9tPH|e0|~0UTQqQXq{R5O10;OtP!~%pR0npV70-jy z3W#WHQbWk=;Etv4SqQ?%;eTMzT>2ZQ?WeI7%EJUE)Da+eE!PRW+#q=cAnv?Pun}@T zVGizD2jc|OL!tnspA}rGhZZl5wX|f)5$L`F*txI%X!+2%%(IX}Sxbrs&*fdx9c_l^ zs1C;3oOaY{BWIx1zWBXRSlCo9CzBJOLnZQ)>&83T02IP7_*PaF-IY_x0E!$Krn9ri zQe0{USurjUotEWkN8z#Zp*D4)u~GmiihVEz{8V>wM>)#5spKyW!g)(2D9^5q~x1 zw%8$K69O0_+#E@Ws4RDlown*^1$E#u!!s8$`LvY(r+h+(}wC_UIxkreA z-j2NV3b|gWTxS*MdxVel%fH6N;~lcB)EYVqaAZ~0F1dp)U=r!x4(_W|yrevPx=~72 zoS2DMH7y=BijZ_*LW04{VLPgf1mSYgKe#zm;q>6T6PDDiR&oS@&ymtii3|8H zDcr#GbKgU$<75%o?y8jIQ6A1Fv^clfG~E`R9_Ug6(5I3gaiXY@f!)=&%ELn;z>bXp zfiBP{g{VN;{VgFN497NA@#-Q~4|rK0!3J=v`yk2c3GOvNn9;2|1s!87>`WAj!4k7s zMod_DURf)yRj(dmW42do2wx>C9?Pg*7JZ63ca~iTS(GY&@Yb(ZUj8X)Kdqz;Jb{s# z`ZEr3pz2_VOv2{Tc(@fgoEK+}rFoe;wWjqC4oL(hEbfR@V-!7Ug-2Mj)S9%JHf zx?m%EXhE$St*y|sX`Z9$sULV_LM=qfu?j&4x@%VehPWBJS;pzH6eK85Gt;fT+ z-VTsMaG|a+^us0-5CaH@I*23c1SWq)^_nUW*+~R+0PVD$<<5-yPBGLbEul5E#4jM7 z5#DzKG@oY+I*k30{88R`j6HM7_9Tbh5-NO8&5_F33i)&o;ll);&$;^Snq32Qf51$| zSz^uQPCkfR39QwaJhedwoMH@a^q{dcwV#|;oa#Eg z3`aNk@+Qhu;G|(_x4KZ8S)_m>>=cRUwY65-+_6ES?kClcBJ>xJTBGTVEpb}Kq1IIi z>lm8M{E`qrse(W9T9OCG<4%*zq{Xv{Zm6MwXUK`iF?;Pp7Wo-NFmKvG>nRHh$zwuu zNo2YDWkp{4<75|^M-i{1xc=(H72uZE@PJ}sdM6+nA&4`$7Ju6>csa-|d&vW6a0=8kyrEBG#&zAdr({H4TSFOMkVhQgfl(0L z9afLqJmMndPykO(KD8xNx~o(%EX7#(4g|PTA^H@PV)ldzGQcVFWl=}}LZV3k0#(|~ zLYd1Z*&;FGozb4MElJ6pdy8}j=aEYDS#wNc8|cK6Sg|Fm!}c(mANd^EnC@Br!%Mjo z3m2CHbv-SJHjdYLDo4)SYHHc4eO`de54GTv#6dz-FbH_lW!3TKXlt0I%?++>%gwaN zR%#F-Y>x-sw6}-DA!ANMViUJfh$K{mRYkS|bu1FO^h>lHUl`6F++uU2;)>u-1-)^&agddI?5 z{xm-oMs}^w-Fb~VHbv{tGOe>}Py?`Yzzv*$1+jTuRE^ZWn^C!5j)*KtrZoOrZr}$9 z&}uTJr8jndPO~UVF^g&8N+lnw$G%Hmk4Xttn;UGu=)X0tlm}ABX=c1F_XDsFZuxmw zvk=Ibl=1Xyg|&M+Vt3F^3u{3%@(k1hVo>8&wn~>7x@4L;z9Mta>kdSt@SaC0?TQM9bkz%hgSO*b zQg23Wx`#{2%}e>ieot8ii@^&F3h=otK$&g-{&={SxNRx`S9*798XhI7Zz_m`Z~#4QtulyY+n_ih zd`7hhV@1rsL5a1vzNM7=21--eJ?$MJF|C@o-|}1vc;Xm@Ic!X@an1ZZrr_Xwd1ue1 z97deWLWeR?%^!oN+!%z%5tWfPR5;a4Dvb-8iaodA8-NCSPHF)1p!Qvq5ny2!fCriY z7G?#ovJ!_ttWA$u?cPO_cx>C50Doux%)$+F443w#_TL!L06IYjH8+*Zc~CSqnHSO| zFhPuZF^k|-1?93r#0u>onn+7|3pYE2I&|wIz-2rev`Ac#{~IMrSt1=X`^O@$gPjA2 z7tRUprH<{}b3fgQ#T;q?xWo_7;q2#`Q7v1;s`|nETQuK$UmSmk-;>IT(dOY0mExdQDtKmE|hpi*Ms+$a_-?88@D0T<}N?LmQIYrjiz%jj%j<^cPmmRfIXT%9Ffh z4vs$5F9atElV0&|m{v%h*l z<5Hb%Le9jly>f1#*Bb03=8f70Htb4m5k~$r-QqWNiTT-07PzhaRIl!g(JEVEo%4~f zqAV6mL1XU@btG{eVK2h4&CB@5;W(Fml4VBILds0Jg`z9z^VSXOMH<}(vU0x!KgYTS z_$nq#=a>rkImW_bH{p#dM^I-FAW8`3_Ai7FlMt`&kolp3?U@eA$-bc?<(@N_57W#H zkfAeR)c6A?eRM@1-3b zsu2Fk4%fhSe{vjml1A8XjTY}Qg~7M&ed-;L9cY?Ic=^yBZCMao=N%}Bh5!#}0d^ph z>2_2io857dMTq)Z%AE-YK4YmuXn_jIR`6hEhmjPuvk8QKFT)B@kR%WUgaDDmeMuE* z8q(#lby@P4+JYQXg;+iBo9;dskr&K!#U_^C!gl0IU6aql@<~%+syC1nVc$y_0+GR< zD2|_ISzBk1anK~#H;&#P49YG6@q2&(yf$BP@%1t)a-J84Y52Zv#@9)D}Dsb}v*@)Ga7rxxy*dhptb+ z3!O^3ZxQ{1u)30QP!w`bbZ_Z7D&@(SBjBy^Hh;0eGqFazur<1=4ijuVe9SU6KQ}lG z@%dz`W53A%V9jCB+dKC)Gp-6OrpupSWWqMluiD06+D~4=UX;+hJlAJ!xv+5Q@R_V5 zE9r#au;JbLp3?KKjMN8rvQG++t(<`^37|OqOX!C`%4?S-g)(sV-*a_wmpt{3oP3a|kpp)f>OU}1n4JI`VBOd*HaPyzZ=T-!55*Ajx- z-X*cBY4t0u+z@!9$=;P0^bOwp+Z=OWuHKH69on1$3u_o&7_4_&Do5WF_O#W9+G&rUTtpWN z>qmNT4fpPO2<6#H=4OKgWr7z^^t5SygAf#Caw#SNTWvCE=yU{xrUPRkbBbNl6y&7{ zn$FQ>clA+D7n&3RW?o0%j%S%rT@c@0vg9=?ibGCDwkcBNkqC#wygfYHB_uX9eic>Y zM{_w~#2aMvh1D4=m(9if@k9Gp+BLY*KyDW)6~GZ)KFrFY0ZL9Nz>TmGIY$LVk7YZ| zNeJNNM|o%zn$T`?l$k&--U-B=6%-cDiqz%hRDNC#=i^yAuUy71fLtF9!a%O%{4)F#}9`V5&IDx?%%~D>Zm;oIH7S1(I zb1-SKaeqP&Zuz6feOjLK`_h~xx z-v(uZsc9V4?~syYS?M0&!PYqmb6NptXQ^@BpUfro$y_(!nfBm$Yte;#Vt<(sMBr6FgBei?Ukz1$`2=A|`uA8JgVz)YaF`7# z&R_u6UOaiQ&j00Bh+o~H*l>f@U+miPpoF|e3RrzbB|u2HLl9PyNe<5im9R9~gMZLh z(^gZubWCaAv|~fg`+uTVN01;=On% zP(e`z2mw<73`7M~0Wi>n0s_c*El`bjq5mRPA&XP|nw z%^7o258%-QzHKH1aW%;Ob2ee6EPz z$CRyJ6o#+>P*qd|)$2AhnN$}_N>*oZUD;f3BnGusK-SYHESPy}k-c{YELOjf47dr2 zd4payhg6A3p_ny9T$MqWo}IDS!G_mi8wXFg2WtcQr|KyHyP+6C%Q-2XRdOf->_fZ- zIiy*L0E&SO&;sB9I6zNO9qvC3;u14O2mzPXg)l|r05iZ1&;rB&I6zTS9V!4@ob-UL zT_=;3jYS>~P9u$`;~tJ}x&?L;RFqo;R{`OpOd}6mHKcI-ZcGYDhDOzUU`l626y1pb zp6lb3%}dzR?{X}G0K!Kg@jO_Dl$8lFBi?aOT^?6qC;&PD=CeHrRJ#TfK>H9y+?q-^ zCGlKG7++}l@CQYJ5Ksji0V%@~P^{%$BhizisX#k0SP0nhu}vUAvJ{8p5`NrCQD8hG zKFV+*(%n!dMuCy|0f9pkJ2gNxW5K0?U_B4j%~PjLZm?N0q*x#Q9yim%-j z)F{3)^wp1G75z<<4h`gwH8hHjump~PL23~Y_k_IO-(!(w1)EE0yx;+4h&e2d^> zxEO-?0OVr1Xf7TZy#5ptL+>fB;fitLG?%F<%o z=wZf$6|j0734Q4NIlWb?4t8RJkHkVDjA zc9;~?5dIW;*d-`x7#n!Z8@NimI*Y>?_A$l@Un9#{l#xG<4aayx7#m;Q!sdRUV=YH8 zBFTtmip=`sHZms+Lfp6@^eC7|x@3jdX{@=ctX*VtdmMlj`VMj$Zy?D)9~08Q(`% z0Zp-;V*&IGTQ~{D2IHB76oeD7D;xnhUY@x6Bt!>Nol#FT5ul9`wNmI4LyA53G3 z2{z=@m{#3TTvt9c4&TF^Kr5OJD;qB|kFgK(i9y8FBoxdA;ZY#iYsp0bN#^ll09Xpq zee8F+y=qQAE;^XEJf^9($p4A6WOk0G9e<%k)O$t^r_BXJP zNkT>CKYmN5k`nTzFkyg4pP&%MCSTF%BSy(sS!*CuB0dTs;Q*XhLgV!S*RRduif=z`P|Lug%p16vB%I#HD6<;Zalo zRp0`cC6*8nfDO3-0fY-s2dD`0$q+CEBq6y__25Ue0H?`>00amvXTU0hNZJ$DV_!H$ zaSy@96z~L0K2KUxq~}3L62&;fctw7>*-J#JlWGEE*1+T^pqO?s100XV5l+LB?NHiVyqMEeK|5Cdo~ zdLf3hof(eH3^YTd;CSa`@bKN4g8>~6Pz3%7KtP1(o?S?5N<{>u#Zg2O^+>U(4RU~j zQk&on#bl}wBTOSF0W9SGnK!9zUAJj4{Z z2lfy?6h82eK@Etf5Sb7j+zQzrnL|84AX(WFl753B$=fB8i=+=Q`K%(+f=J?2K9x{q zROwXKBTNlja2og#i37@lNJ^C&fj~l#lnb~)On{Kc1U0}7U=zFyfx%6X6Nm&@19FfY zECzo8SGgHzB$NS1VjTz!*nwQBSMHS)!3&@Q$Rb5U=Ydte2#DlR@o7vdB9IAULhk4ej7il5Jk*xO!(?LKATjfjvuKiVCfWn9fl`DI zD!>acG-yP%9Vt;gq5(NZeLy1whPp#?9HN$LzxQG~H02y$&Oe0Q&tAa&sKPG{EDOf=nQIUN)2xSPF&2%{|=$8_LKoee) zJp0HOfLnY4bATO?S%f@D-Wi}-m=0FJ7mz(@56lb<#DACsUe~{aBovqjW`en3!gn;! zqEgss78ZnrNd!=s%}f#yV$=tIWp(884N<^D8Oc&0M!cN^kx+$SMwH>SAh; zx*)X>f`q0d0OuWSQBgGoTVa~Sk2nx&8h|$dIC8)k5cmOq^kqTu zU8(@pNKC*4fG=ObT|p(N0Dg-=GY5zPGC%@QX9_gY5LBQ7_#gZPf0?61J}<%-fCu0K z{7Y<+qm-8_z@THoBngPjg94#Y0aAb+gtAzgnC6AqETI6IORtasw3tyMd1DAJM=(}O zgv5DEF2x)8Iz>gwWdd+1uvh*?qggo20cXG#ARAx}U4VblViGj=6{}#Eh;)*S5@I-^ zHva@I1zm7SLzb|RTsjafW)kooo=RH+X4FPjLb@K}(tg~7xe!1BM(AzE$QdvMWsN}M z8IS;Mo1w&efCgj^tS0z^H`JMU0}3D^+(0To3XnOR0eHh8wK<>w11De-7JzZa02(L92?HP!2BTCIbTAyo zi-oYx_)MLqCLDljUY&K<;?Q+c2`GSkiLJOYNP@lLK$rn%f+9mBv|LAk5dZ~D z5hcJCB!QIx&x7>VGIk!NCyQVc)hb`-zG-I`6m|doX*LKfNdV|6dI~h0=bNC& zaGq0y@(BWY1bBCj zh1W7!G#3nL3E+U538*LXfO@)~90*G= ze>x(!)tS<7(mN@@2I@x)QXgm;5rVd#5GWG$dd37BsH-u1ZlJMNLZE62pb7#3Iz_Mq z;ZvK?L_B>6=%Qve^q}x(e9(i!2SdsbT2fx1B4P#_fVQ7IsC&SE0v1O~0opyZpF!vo zs@AYqR%qR$KCYN7-S4pIu$Ow<;W7s_n3ZP->K-7UID#Lcw@IHYLAUwu=|_zp-arG= zTykjChZqh4NB{-#3%*>4;SH#_{Q&c(av2k}m?(tUwmCLP(AD5pQidU21avXsz*h7Q z-XL`D2Mj?Vnxh~qYUtCqapC}bVoZ;oW1sMT1j zjH0y)&XCE(Xk~yU8WUimW~d;6B-jn2Xsyy>(tvkp9x4UAqN}LO)<56?!;CMg0>q+A z0@NpS*`h1~E;_hvoKr(DI*K}@d?*D$a}lGx=17J$B%`os-O`MnqN(V%854|Tfd&>a zUIGs$0vLLxh@lAPs8)vRZK7z4Nl4T{amXh(1=OD3Wf-Cxp)x(+4{!oNqb9+n(2BC5 zCP7ZYzqFzcOO9fKwFElAH5!ak5Q(Na$`U-Jrb0y8Vg`mS&@*b0ngkdr4xo{eqAr&z zDu`aB`axqkl7ax+C_xI)*$!C4N=lBpqz`EhU<0hAcqj#7k~*X*X%27$;H1K+7C@7x zq_V+HdW|*#Ou!Vt1k`w3hb5|L8l!u`&#B8mrRk`k(PCDMSZP+Om2Rb6X;R(2a%#ST@hCsR6vz$WOP(obtQcbept;FJMR92ufRJ_%ooCvaeLex9=jiD` zhyYRo@F0QaE_T36FqpDv3&LS)Xutu2=>$q3HlVqS8PJ&KE{_;wiil7a4g{-dg4U&K z&Fra}&J`&DXX*nKrbLTp3WAEJO+*O_nu-jaWn7bO6vnr)!8U3%j2c~|JH*i`B_N@6 z2}lW&;uzhnv~Q{HvJz7jqaZ-dch2=(85gz&p7ll+qaGh?&|Wg)1MB zZS9E2bPp(ilU9VPZoT+W7bMJH3m{ZJ+4Eqeaf}5`*>i~1RO3wJJPW!6(*Q$xY@*e= z+poE(jy^y$w=4<+pff+X9;zse&ua5I6z)E-3QOaU&>b9ek1 z`^&ft$RWs-gmXv0N$#{$;00AJ00SNnD$XrT>z|rb+sm1r80=RO?oNvxgX&3SL-^TT(p-{1F3+TK*F?tP=-$gB3%5$Fi<4@y`9t?Y3Tjfd z<2==ygaiRmHsxuxkA&hc_Xzo@`U0iuf?D$WgkIjF+V&dg>U2}B3nu6y2U#AaZ3qbD z_AwRu9$MA;Vq8c!xWuT&PT1T3g;{~uUb$zrwvn%XfoIJnAV0ZqudJj-b-GHw{6n3$ zr%qyd5&%`KG**7eB<7hWRclrk^1f`(&aLi_a1;Ik@x@*37fHpIJR5Zh!gX7MqWroW zw-Lw}w8z`e{q)l3LywA^a%E^=kn}Hs{34bBwV7TMXc{2@9+%%T~}9M zI?K-yY)hG36;0AH?RLs=M?RE852b48?1|XSd1hoKty+0h7pAbBlIQjEZ z_L_vJ{0h9haEe_=`PVt@$F=Y#m%SXxuB-x0+7>*ixrk&Gz7EvbG&HE{8D0(u@>){r zt}iI6?#*_fBEJ-%JC4X|{7aIBPtPi_z$_MYt+PRdzA1K>IJQNRl)GNjYhmaK-Oquc z1bUi{exUS+3<+<)+AmvOFmCT=Gt4&J7tZ9UP3@54k@RMQWu*0axWsG^nWmX!Kh5jJ z#yk@r%>CJw5b*%dEYIe8q`kqjiZRU=Qcqhr$gfs%pzyK``SMV>R_XPG-ih$VIw+<7 z<372=>w@~H!bHggeJv}@6=bE^UXMLm-@TTJs-OIhWUx_Z0voSIEfvJ}|i!&3L4SS7M7EJ3vh@E1ny zlyV^M3VNMLiYPwgJc|OMfR-3SPr5#^%e^8>zOm^pnicy&6aQ%6zSJ|#rKo{Ixy!FW z&MUwZJXaf1yExH1*wk5n1M~lE40qcId(oMfAzUk5cUgl5>L9yufar!`Bm-A-fynLN z-nJ$*VI!~VLyP#=Tv+Uq| zX>C~Ez*c^;wgBVaf_aZhP@n`=mN`Sk2T6`V>|LcSF7{`*FG@py)#f30eihBPQqPfAJAlh8!ZYP0o1{yUP4@o1+jV#pH*GUQ?o%{#~m(X_sgs$cp=+14X0PHghg2a1(!@d zP0cj(A6^ADr3!;pfJ>7Bn^SgzcZq4Zh31a$K-Uvi`cAW*ML*NJj=~fPuG|?s|J<9i zPawvihcz~D_$99S=ji+f0U;VO!ko*&t)hf{&{StvQ~C4%0$U2})miaAubK}1$Ug_X zN`+o7zLv2I004yPHXFjW-(0HBVJxj{AA_KkxnPWI3Z8yX#M}?0VB~*SE1T^2;miXT zL^K7W6=#rCxk6EzMxZ^UecLe~`AMsdlgxs$Am-IW7;}?}Q)p%vi)n(g1H(RW za&e`()A13{X`a)o4)4vF1@1cHA+BIasa6P(xKCo`^mnUFkE9YnQ$HdoT>!4i{7&10 z=vI03@ZHTzO7RgKu*u(9DrEELfwmS&4Z08jEhO1yM9K0NQfZ#9K2D(z-#k1X^PPH0}L+o3IlZP7<<)fW(& zdg1QyE-4@XrQMNg!TR;EaIxNA0ir1fKJ{gDz2sy^%?@+!kI?SQe?p~Ui;Vbls_}ud z)_XL&<0C`QX*SeY91#S%Cy3nR354R`N6FUvC355@)azc1YRV254rhx>+ar-BE4VQns@;KUlf0Wqd2G)-|T7VTn?R_oHgk zeB29!PIA6uIadBXl@y%cA!KrDZlx37ITX&d@wrz`uwNOSr_#_o@i0`=c;kK7=AmL0 ziEm%>!5&oHV32(3y+mj9;kS_sp_*Z%`WF4J;Mo7#IUuqQ76tPEB<;%5c$7~P{eUs= z&RZu0Y>%XgI?Z8n+WG@3k<{Lc!h%|h*6|{T~>BKtngz;*Zxs> zvNqSteX+=!TdkAskrsJJ8`x6qSCsLwpfQbu6ndxSuK99uxmicnz*Xsp5fnt}qYyWf z{Ejk*OWmp?P8?U)Wmo=&nFG5j*0J$OU|=bWYXJ8x2Z8E75seJ|G42G6-5Zr#=CfpR zBi_rqgCeROUp{T*GQ%+yMs$tqrT6gd0Q@iqf9`VODH{(7kI(Nt!II<0oBIrK7TT|l ziyj|YmO5fB*hOjfUVFQs2yi^pBxz~GGq1fnklL?q9m@$^k^1--kJW^nmxgj3e^YLY z+H7VeS#;|cEM6dsEzvxDoI+CDEl^3ihwWL~>&e$&HD*1`g)_|%igonIv>ttu1A_n+ z3i1Ho)-_cW?1@;y&;PDCC&{$l1(i39C4nM7QPJMVgaY*|YeIYz897m~NJ5wiutDz{ z(uM;m5KtJXgzgStM0XelN+#IiFiQMr0i;Au9lw7IdSG>lz7g<2JZlv&OSslrv$1L- zYe;$Kh~@>@0L`O$b?sLL+u_nt+(^@UZ4q$!4bI0!G7FSB#`}@90N5qI!7e(peeb{x zg${rdf>11ElZQUnvef8WjJi>;@CE6BK{OQer@W*9LYdON3gn8tC7dxqmOmM6`$yeq zQ%7pa3r@i54E<-+3<&fgi6!l8;cwa!(ZvF!vFZ3hCAb*6ty}>C)WbGoAQ6P?7T@sH z!8ariS?*_K0YeCQg7JOEDw_Fxl2O9UJ$e;g0+8k-U*i`s*b~2ia#%}&FWvw)uYfQX z!$b+VG74qc&|JfzN*Kr<)3^IYW;wVLf3uDXw-ZvjK|LOjH`#k&2ANjJ^4(Qd}H#5egqDXembG}NZH+Z3;va=672o2j6#HJ&5vOUoHA59 zoTk6@3Ftra{1{R?^txI`g)49HlV5QtWkV0Fj!OkS22hpYVLN_PE?P~@n1hn9G=1+? zk^qWh{^jsU2@7s;L}VTj9E(4B3@8oEFbxesii))G<}TXWo+iLLg?pI(9DywZE+~<~ z{jSOHID#%t|A6*g>4L&b;E=_~zr4OytAYj%y?09iwcF&_uxda~tjQ#3 zj2I_D9H4(oq;&sg3)%K1v`|mIi2xQ6t)qF(o9T`VmUcjl_xvqY(B52z2M^cmJKkPF z$!^HdVuk~f%!>fLZ9-{-!vy8FGvOhqbQn@o6YN($+~*GRBaT$mn01pgatc}bKe_li z0sULe{^z0+kh>i-1)><-bKkJt^=zG}HYdiqGCKM{v5MrNZLayp%d=Da&nN8^98N@? zbc$@ajj(XV*N41emk?!^hCoNCW7#WFl>l8VJ046A?22>f=Pez9;D~ymHYI7$TJGWl z=mUR1!HdX}h`Jp`Euu~C$eBr$kr|Tawbj?7!5eeBO~cs8)uiVERj{PJAu|bUL%|3x zw;mPKdQZ}4VR|CpO?@Sw!M)WM>NKjKDS{AXwWYjEmC_Pc#IE}0v=u(ZF&fW!XxA{^ z+_x>c+3Q~a%KOnrc(ZiYU$dFG3zFOdu+clDoMGS@hj;5I@v1TJnVx>ip$HP=HcOuA> z0b>tCy?HN)b0^O;_|GWQJ}7f>^N(4-i(dB09E5kqy$jHZwL86<#mssO0R1<;I>o)1z9QMk6Lqj-2=NiiqGpgp9ke7Z}RyJ z3^umSvL(`A9*mK-a^~xhF;+jWuIza=afD+JZVwTST4ox3YkLYb`{y>P)J~o9K1N=& zTHcV)yqS~-Y68KijvMwLw1m0HC0L7y{dsflmYi=AgVKSM%lz~qThq7v6JIPF2d`<%w9tL(cVoogf_&uFT8I9wZS@2TtKSijGnh-{ zI!s#WL)ZM~*+*(fExw?pYkc&l(ja%wZ2wZ6V z7f}iQuymxV#Qko(A>~te>fSraFD?n-0`>;uzbu>!K&{D-?y3kR1cb7Y9cnrC+Uw_w z(&VAv!3xN>^|2tiRlXTpF&av}Rj7K}u4*8>J>kYy8ZM^B#wIntFe=tOaq8mD)qZd4 zG=R=D0~i%hI`GKt-LaMGrA+YsUW8m2^IjRz_OCwA7USj7LJ{rLN2YX-$qEuF|9LRC z{lUTRMAuldTz2EyTl7NhK5D=ZJ9zbgiy8`);GBs~{F3vCd; z`M2gsQAcPLEtH-ih7mM)fLr8Kw6s}cBtM{!9B@c_qYe-N4=|il10z`}18GZ=Mr&w&*??;7OpCV)~o=jZZ6#yAb^?^!7U-+^t@uY@$<$ zaFn$HB2H`VBS^qSl7XrF8`S{*b2vQI1(h+`7Xtb zFf(`4Ew!0Trmy><2a8E9-#tOudrzwKn<9oa+gmP#EiTL3z>UJ+g*WuYo7G<5UuW!fI!~E5T*s9?6MH_hjJ-D;m2~!ha8~Y#_X3z#aal z`;ox;m6vGJehOj2pYb#Hj@!fE7UOGYdfB%ND|msm9e0>JRy~6$HybFvOfC699Y|Ma zyaDlHhVO2Uh)}A(MJGf(TLS}nfAS{B8QRWH%9Q&3Whlx!&-F&$8|JUHAlJv&&kJ5@ zffJoR*TWQdZ?5)0izV25nwcip7>^wzQD3yIXB;m`m}BdOD2YP)(VmkW%1<6Ye3Ew;C(KXo-CuuFUF;!N05N7-@KZbd z(FnYb)ycdg|5g`d^>jb!Q*;OMzD0XAL1VZ_$E!@@z!S1s-wz0Z){@mSV5b-hhlZ&aMpo07Z*zO5nJ4qo*C#1$OK-s1mB znX%^cf#tUCsVbE_^6Ed-dtghgfzq87U>E?7A<20n)qI+d)mHA7m3Y5HDmox=J9w? z=N0LqZqO@CHxB-;EkPhYsJK3|0KmNis>dmz6n}1X#k6%EyMvOPUoKb(imJGHDf4<< z&*1cZ-~GsBzfz*eO3Xea>HZ)DA_AR8$L{@XvJH67f;t(smZ77LL$t^yH6PL*L4&|*&gzrS*CUe*MV*+G{vs~^J>0U8E71s_KR6M`Lwff=hORmaM`<% zPFAJebDR!_eUE&mZ0k%@7;;dyeKwbv1S&r|vk&@{lxFCnpul~oJBn0Ph&e$qne}?f zuIM~UL^Q!(tEFk=eaU}CI`HaLKUABkY3G@>qzILZNBYxhK~I`9z9w4w{(KRhr!}2@ z{XdOgd!8vk_quM{HA@bll6-eipoDUFqEu z7#7uD>NI;oUmsaL-FJv=3O!pmtU3K-5&YHGqxmUI1$1QTg_n9x$s`Kzu%4grC{>H(}B5|BEqVziH3U)R}v zE)nh*zQ@xQ5tz1WeO4FM(I{e52#)Oti74W(Cq2}sL+Ny!OY*(vgf_8>X0iO`7U9CC zuo?xcFGw*F6sK2NwM0_%jDpF*YuzrJ~7vM;$}Tiy9L1?_h{IW7q zjs5*Da-rbI*?a44sOBeDtEXpDQT1P86;GOI`DZ*U7Y!|1FxgMZkqPr9)>C2hU($aU zkAMc&f}7!}!j;Z*6b?c)U?bI;6+^v12&CnBx+SPaDEVz|IR7Q(jYwPA3hBZLR^v|e zDbt$T`GfcMFFG#$qvm6H6ka&VYjY?#pI0*ypR|Cy5ClIyN6 zHE8%O_qp&;ScTJo+^&kYjiH=mhrdDZdqRUI-GpHG?g6x7H82SGmxkF~sLeG(WtBST z@%$ND=9U|V9RId|kiYxip_lEap$m8#cTB48iJY(cV)tP4Q=C|Ll7?)pdJMLw#FQ;U5RJs$qhJ}kNoJXWU`o?y+^ z=1xuEnH_v1@9`+XZ2jH^h=VSIQR@Reo|i3;uRI3LE7)%j z#X`_kT$r0*kFpgoM6S)u-ECl{bQfv%wxUDs_2b~jrRN^aUmA|c&e_TjNj^LtjXr_5 zs*&&dgb5$}sVum6{Q*bxW&2U3QHB$4+*;X^D}7Ig@}~GT`yWGcOc!|j*!E;EH)~7G z*3saGV!qpV&i!CNKhAr+)mN#InlSl0r81ptbv!Ym$}G7f^%@4Y-MG!t)fZw`>?r=Z zE+}d6TGUC^cY5OYu|--tiUo}86LPCcJ* zeL}dgH0Bie{lep;gx?N6IX!SR8o~YAMZZm3e)eGfN`?7L$WNK(Lg#PdKQM*oo$9TXmQ}>y=wF5t~zif>&*f;0? zvTgUUK|P}TmMB5P=GO_GvROeTO2X^!W1uobH`Cr_1Y)9)$;;kYE#!)3T)E$R*1Glg zw^(8FX2r@yl+U%l04#O)VK8u>5aK72qC9;T>Xtluv6&Su^?}yoOM-!XVTrxizT&~7 zH2D$wP$i%6+0sDlHVePNsB_!=3^wECS6P^v0q#v(NAz`otw|Q)*?1xzw^A_S-1~M{c!iGtf*wv z2NLh<))^)`_L_8+hrKM=hO1F~e=K@xv%`d9&1Uo{|M+ImTEV+F86dO7EKc>uJ1t9P zqv$JnMY9cha=X#oTsh{ybiq#wyjQxm)ds!kkzb4n3{yXkBeEsKUxChdyY&Y%>t;(T z!`{c@f%q)LLEtCL)!r}n%R;=S8_BnU+vU?wyPk^fHBY4UmTz6P?b#EHcF`fz8RutB z5k9~o9VX1br0Ji{OUJ6JeYx@B$M8acgyE%fP2q9PzGKuT}gk;{m^qd+<_GyQTQ|bIg=(lzA@RK~R=D+@X|Ncdg<%NqAJn2_5JD_)m*33F4fUcKo_qN4-H!PIa6~ z(ZVN15sj3}#W{COpT!RiHUIqfUX_$XsEsrbVK%J#Byn%}x4&Ir$zG&VfhyPJt_TJ& zgZC{m3a3QOtJptM?|KtH0v0ByUS1%8_m!9RkrhRULf?xVSKp`ej7rxn0YB4b`Zdta zIJa;;=tOq7z5i9rDX^j)QkoWHToqTl|30s?-Zo6<+JH>=Dj5;k&9vsY=P6Qa(52M6 z;%AhP#1yr=YLL>8n7msPJnWVlVE3W=%w?$MGrea-y*p{XYN^s_h9QRaRvdXNk9@@& zQCqb~2!HF~Lk;R{+(s}CP&xrtSiBxUL~h)&b>3q=7Jv1HI63CnYO`ao=2yL z&o!v6E)b=$8V)qe9d&4xCh9m6+2S6SdW{lQ_kOL0fl)Z&52M`oov)U!BJ@l~Y=^Oh zDGuM}e)LH5DWf9$l?C49 z?IrEgE7E&zmvZmBB2IZ|`Lgcl2}Vb8PThCtjxAbdV5W(tlm(J@VL7K!vg5OVw8DWs zoflNZQhG)LeMh|ygV;9Tw-``mD=$ceo;`HYU-+P8Wb`d^i~G@?v)t{Sr9M5ctC<>$ zSEu8FC8q_Z!kiKMpW^sM#3z^t$4#1c7H1=UTj2vlZ7m(|_`eYwr`K90*B7ci^Sf&k zy_Zb==LS_C>#p-uk;$UdIRyEkoN6CXGc*(&Iykmzw5{ByE%OEzTf#ip=)n zwr>pjpV*sV#czr|B>GQM~Q{MyWP_eK0`mq(&~ z10`dM-cqlI)~U3E;V@ztRK4-9+BnBP@7w~gMYveSj<-o1Z6ykR}_-q*K}9Q|I%|LNAeafi&UoQPS0S+i~} z+cBwk@#wLJv5CMK_%ZqmrAL4CCN zZRu!d&z_S^RC2Gr_sQAs?I)AN9V3pD2VtoteHD&y>y)Dnfz&SrfQ8fDVCDC=R0HywZ%JNMaJQlDeBg_ z)fy1E{J}h}`(xv}yxr}yqqWlwKvE3Xfkv(Kkqy z&zJO*XW-mKr(2$g^|k@st*DOI_J49mrmcR_l;gh+k6O3yFp*Dw7QVOP*P0?86#hc? zjZFH+-7Fc|^ndB%?NR<2)VE|lMu}yvXc{kgV6B=qx6Au#>L++x3OZlwXDqz~a;f@? z^D_diRkI()2LBGmBvWtkTuQ6vzXUB@To32BYE8MfP$bSoh9Zh**>5X< zN^r?|v}3s&ejT3qb+k?3)?~)|leViA#LTBI{uX9Q85v-^su|pRQTzhlZSTD+()#GB zyn)2f585~PZ+F|ZUp7AYZa=k?X|PE7A*mf{s@hlbVs`g{$>HM!bj@VHB+{yoEleo= z>1=z%(XIUhojvQY(y1wSJTi39NeSz_Ofct7fNoEPlnE*gu<1k-Zvy+sR4}Y@*?0 zEsK6`nCPrXqQYmI=#pP*#TPs78v1#d(q8Wi>N)T85y|bABOuS@;?sP zU48hBUZVu-@@{* zcRg(*m9SH-(pJe0c%+9LH@$MC2qk1=v@e7x^wXTmO9gdtNuV3D$&oOh&Zza47yF#9 zj5&^B!Y~)_A;>lXR}<+*&_BzSDEDYjR{GUS%PPR7uFQBKA)A$uIz5vlzt)m?P2H?4 zWI9Sy8&WVdNO5a&nJn?&i#}Jm>$$iZmRc}c>KUcRr1>@U9pWdtn;z-2rE|$}sFzY{ z=Yc|3tC|bj?>L6wo~d~{yfJ2h`Au{xP!SpE9%KO0(-}|}Aw~ygGVQl07+7_?o(j_l zvrHtdM+A0lrd|r)miV_ab9!6#4djEI=ZW31=<9#qsZAO62LJgu--!SkvdYHLa3|?s{@YSUJtSJkGB3L2Wy|0W zoilCd;AujOcND-%lilTdZp!EP$6qlo$QC4iHxFf=Ii42;Q1)d1M0yE9n83Of7JzcV zXY9D!f~6l|P=#i{$54g@>@9+?-ZKIlxA`UdH)SN&yyNdnZo@a&DUp@L8Wc4%Rs9N` z$pTFuUKv}J01!opj@nk(gCGYby=t~)S(L%4or4S> zUMcaRu6*!bWo_vcKnMlXWM0O{4aab0U>=~{&X2Uke!ciaKmx=xjV~mD)CmI1c=~xS zwTGq>VZa@L9iW(S)5&3Pt7`%qmp#k@HY%);^YVJ0ug4aNfu#X&lYU{sOM}%&0iY}O zP52Rg;L?M2k$}Qliwr=os2Elaln+$L!{!na<#hoS*&(nT-U$)_Me%B0DOsn;8xpz3 zTceabZoI%Jd|fPy@pPpS2}n0&3sh($!9WMP*>jir zwd6!g$H#+YuQ7&8Rlv}xr})-N%MvjGK!w`pE_|Z zeYR-qngM)Az$oF@OPEvqRLw$;H|##yRkSQtQhk6x$>YeZfj71TF_-=wP~o%313|zb ztR|+mGz18>g5;I!0voY*G@k+On_!2cLZw@(-sV9AWDvV!mRcrFP(856@mG|SSp>G! zG~whAz39vzVDR}Q@@`!fFI_y4RTE>}oq_QTsN$74M$@p0kSd!EdRwA{^ zrB-kh^#=zu*#j$Z4_uxa!et)dkjFEL?D_DVw^Z7c#VkhYzR)jnvcac-tz4D^M_?v_ z`vkaNvdAaX&BjZ4U-XKZtSLhKw?=m?dtm)4XS3^q#C$0iTyCsO;=uJaC@MB?dFVws z&5n(S%&JtD=`Y|@7HqACiTv+xwJxjVy5v7f`O5#sOwDMjFnc)WHrQzG5=ZXxvVeAw zb2mF7m@sul$?_>Sv~32KC|y7>OAfx)kuT@ruH2llCWs01BIDd4Ob~>HjRM2~zVkl; z$1)IIKnkpd3?U;#pauMze$)^LX3YcKq2+g6hz4Qd8_jh;(#qy zLS};^fSXw%g1?AXRS@rZnkcxI=QlMfs7Yr8m*#{4ZZnXR;8Fc|X-=gUoeBs4D=jUP z6a0});s)Hs-ii9+@G8N|`~fZf5wJ#UNX>4Nb4p?1pRf!s86BWp&3N|lv3{JERfNP< zWNZL1kh2rONpoABkpP)|8W@!U=)rttvUGx_L9S_gJ{JKM?8na^&!s_T7IgaHKXz; z+!X`Vnb(cXYiwH6IE}|jV6Kct(;O8L06lU!wH{U{8K%@=d$~=%m#L-o}EE^)a=;|*Z9a*W!@8^fXxynR5 z6fZJ!pi=77u{C8ox{Z%btfOcs-#v4wc!|5K<}%l@JAsaOu{YCj1O`G&&14TWLsO~| z)$NjpZ3}~IDv30wFYsCY8 z0%2x-YR^c<9K(;OBQUp)N#1s$EmhQk{*H^R*FT03Cf+wja(h>d$Nh)*$di+iPN9&Y z6rx*7^K#uK@gQH(^iZMEsjz^|`*oGesPtIFk6_4j{MwYCpNC8%-56!DgxOF{W+9&^ z*tdsueQJ))OoLSI!{CC6az7$4^^LekMU>GN;%l2C5y?UIDy}g$6}U4s=os1U>&-}@ zPpbbhO3xLPV3om7AAt@*aUIN`0n|@@_WP!^oy5hkN&_!=Qlc%_BxAW$B96HmSrmny zdTcA8+2YMb&*`%>6=LnqIkD`P8ZPlTjdjQE8{doaIoBrDD;edAuUvVaz6!BWjw1yQ zbkWdu+2V0XZL>ay6IGdHfkr{*naP7#1s73X$^jt<+^d0|4CC3`Xv8EHB!QNw6lJRU zH?s#Spi5^3PN5zp+tfIvsmccm0z3h5EGu@MhqUwp&!x{xH2U`*8$m~Z}GBn=;E zLp|u_P)39^I>I=wY89}jUTfBemm{E4nD$67LG(8qh|NubmNofv0GZH#bED(YnDU?` zR4!;J-o`o;W!BwLj@=SFL5dVJB$PuwV@89C3K3b%ZC4j0Ljp%Oj^8*>NoJ_i5c1KU zG+)w>NF{-vO8vCRk4UP)SDKnhX$ft9LSM9`SX2Nkjx2zz3&dRNMR$&VFp*h@LY)ec zX(MzJyv`*@vK%d3X30fD0CsSWP(x(>pheX_h^ij_2nu!_A*qxspxk9lUY$iu~U*42;RgA%?(oNY4EBc zF9jT0o_GhWl}g&0gN>G0Y^9A;oFeKweFp`snNP8_ncUPe8a)R`KLZqht%V07HLiXr zOnV+*!VU6cuTH7wq5&xp@m#=TBSTiVB!mMER4%#i+k0-=q{~!_H*x$pMiLnsrI@Yt z1}q?f<|{c3AXKd#@0PEU0-Hk7YVi&hN0Ya!b+F{73MR-^Y?hrOqM^QP0(O*ZiSY&V zDG@`JRtDz+a=CK}5?ZoOw34=XO|U*Q`6mDhEJLt+m~PPaX31(@8bKZqg$iv5Uv;^8CYqq_!aT*#9CrXzTxX~0IAd#N<~Mah(A{!2 znvGE<1DSxpz|tF^%-E{xdWMJe6z>RBDRDQ$cpbg1iqcQfEX(n1>bVu4$xR;e0&KJ0JweaA`}j<1^B@`yzD}Iue4Fs1`-@3jE!-t;P_uwb z^29B{3Y`YcUI;o({EosVi>bwru{?S8B#wsXrQ@)mhm|B8RYLI~iIWKV)HU|XO8Qg= zQkWO_j2Q1^B-y*VK`YINPVluZ6V$q++vse(7(PbDFN{T~m$SqEW|&mYMzJWth4&dL4I(KHZo})=Q@AIF9mD(wsUI3}}}B zD?%YDMq`MJjAk^Wy&I)2A(ilbSeZh9+O5>xphJclD~0H9oGM&>Rk0s+pTaic{uA5| z_jSf^wFd_R`iO0#KN>W&v)X+-B^k73A#$RF!?!#1>R^U0^!I z)txXY;XG;Uk)~l|HV#83kmBUD*h`GJWYk(N4VOBdP)fT71CKY2FYijNm@4x=Nosmm z@#c`HqsAs@>4UE%Bn%LOeiT`h%T>tcIzU)_xUM|Me?r%lo(T@tB(dNtDDS}wcu>=D z?c|0eK@#287)&2b(XMj8A@>8_C(_cq#jDGZSPAR16eqDK;t4wC6T0qbxH-d@gl(XL zlO>IPg$uJ0y#P|9ojAaaz)(9|P4eMlbx}E5)x+W^c^TG?ECG!BB>$B=O}CC|4^Kyf z0+X*m@41(YtEYL7(Kbx7D9hMF?VCV1eIPzvtpid3Sxqqo6Yi5 ziXcruAQm<~oIu9)=!%7kl?_TY^1D3#AX4G@q8eShmq;@b&b{m7T4~fHft!#amjjrn zcTQJW8MM=-SkniPXno~Mn2uGrd%?nDOW=zUE~k-5bsf4DNSWxHr|n2Xi)p5bDU-gG zsAh_YC#KYp^1z@mG9t+0IW}lq);$ep@01StQ!aBVGMEZ>B9|Ith`P!!gt8TDXTGV= zWZCfPkmD9AXYNXjtmrXyt@p{{LMdLlLZzGdb9nw?e837)b}6D#;2`au8N*B~=5s$F zGdYR7opv2<9!=x<-3Z2{T)D{Kssoq;|BZWYIY1QYa>`vTg^DhdwHJ>YmCV3LDdZZr zobOC`1n7X30@$1Aq#5z$ctGRAzp_ZM?2HH-)6WbRAAA;5k41+Zh(`#-k^P@W@t2go4l3RBq&pBR0-5hEp?RN$?1sRCLr zxVti4a&F%@iM=aFvnzS`jx0EehjB1$Zmh#LWAyoY`t%AEy9)G3egfIl>UX42_f4=% zu{WX8GTql+;&wWI`zh?Vf)7uL*te#!v{~@b+IJ!2{+cl1(gJmkISq9Ws#7)zzc%FG zeCgz3i2p{58oZUE*XwcVN02ku2y=La3JaoGn?oB{4w3}={f$OZu<>E3V)SxI)-K5; z^;mKAdhBKcslXbF?04lpbD?CjxqFUM2~Azv-@zFAJ0ui#Iq#(W-1~RTE z!$`~@HAto&NM(*PBq5k+_W@d~GOdM`w^I5nJq5W(;)O|W%dQpqEF4L4NEWP)#kL5_ z0@N2NVloI-iScnj-Ym-yHq`qM4_b-`(*N_PX7WW7WVrk@DmB?FGcj5`x2GhgW-pWE zNO%Aa#4HVu(tpr~Q@0}I8?}DDtL{ofRJM}+tXsgIrDT^n`e4!ib}CQB3+aki~7%@mHC0yEmg~2(J!|oHId)x z&osQAqrS+2<)YWMm}&23`3NFn0JP9-EkecHu@}tJVEzvjl<5jXE-r)HbTZC;bAFHD zkQ1I|6EukQp>J6=g3CbS{n#vpehde(R|&YeR<2W;_y-eZ;`}Q$x|+bxoO~bn9>NbF z{HB68A9z8enL$rS{O@1fCBE|#hAI4 zM3br4H^Qo?XAy>oD(7y;+sOh9QdxgITnyMT5-6%1a>+d4kpJp>gGC;|L4!Hz>h8~Y z{lL}#{4*(c06IK5n`G~VFvEm~QrN3mq*lj%5`5CW0KZQ)lCCY6>vB=a zr`IEq3x-BO4Y3c@Xi(nkHqt*?{(GJUOLmS<)3Ul@Xeji6A&`1$a3cS>acCBTO@a%qn{D^UWEjXzs5c=6SDr1p!XH&svV<8hjFD9 z6M8Xe_%*o0T1;=)B?>DE3%{#7f#Bh!9N$>hkm6R%)bvf@lx8K<x zfpq94Z6c4k^$dBW7+xo6)r`1gR!M%+)pCZpAmz2?^}Lw{oo#rfaSS-{oz(0RSJTHc zwsW3WjICgYRQ;;M$|G*{Iui;=!KsG(6_v_+TFbMme4%UE1E=I3x0##3p820$MEynQ zAgrNB6*Xc6urvV2fSkjvzcZH@sQ5(D zi-9?FpVZhQ9lq(n*6W2>=d3jD^s>FAf2VB}=w0Y&uExUf*19nlbtxLtpc&tvJXdC+m6!$30CWQu>E;!a^GMTn0#+lf<-9q*=k#)X+=wF61DKqcb4w@i_L1s-9Wpf66AG6Uwl>MV&E@kx zicIB~fS<+Zqf$V}1cKXY#Av)WMUIK8!x!+goTQ_duIE|GmR^R83yY@`@b?cO2C9 zE^$CnU>S$rPd*u?a}HZ`{;$2?hQsqKr-Fe= zmEpeQje;ne#t{s)QON%0F79gm;g}td9!BJjyL|JlE;oA|$c7gckvgVUaX56g9k062 z*1`5kTU>|H$u`OB;j5fmZK6yPc-Y6JdaQ!=hz2@{UsOy0uONh|v7UL?t_hS7|m{g=%L~FQ*Q= zdH4aeiFGjvbC&@n4kfyJLAK~bQf)may3=}09JUXu?dIwz2fIH*-Gqr(;GN;nvUDpb zOtYk3zG-DH)R z!Usa0r3nnb-VpUyaPwfhyO^0kk;ttG8)`1kc1#FnLw?~D8=6=zm&~&Ykzu}td_*dx zCd)U0J1+HMj&;dW74{%;ankohj(;q@Z$cOR>b1Y$1fqAwrA}F;4d5`F(mFFn7MABMaCxJ|@ z+!5DlrAh?Nux>d3*qe1R59|r=?&^eZo8o#=jctKU3-zf(ADvPX>RGA#|8+;8rwa+>&8z>R-VB6cAzgnMpGHSYm(-g&6ecU(5ijf2sU z1zDK?aZJ!FJN87G6CM;Nxo2WB2jOJXdWd4-hp@cmRsg z)2@h6PhblQ(t&`rfSV!#M_kzQeKDDGEYLqEFKUIf?u8n?C(5QVTz+7 zfdy3U@J;)Nv6!bYdC*L!NCVaZvnR)Naa}fugf{W`wo-GN|(E18o+p6hj{% zWVTWV?0{)=8>qOyf3prI=uPLZMrV*umwV~T@v8bYo(S*Vbm}r=LAoj~2^v34CNnjU z5v|c+4D8JA@gPyNT0%AxJ!wXqoLN$@#Y6`J2`XdE|6+XAX3fSnzyoODgB&WB_u0-z zx?H-`n4L~kCKEN#SM7*IJ&8I;+eZdnP&bvJX*8q3E#ZQ8pnPB9Yt$!@|MP!_&N3>h zE{wu=3Wgqr?jfZcq?w_+K|nw{Bm@CPFotdzx?$)>S|pT~mX?%}5)=>&Kt#WfpZDK; z*E;vyv-a7~-U5fItV|2;cX1C2cl#~Oni=;Dls9rMcvPa2G}ReYP8F5~Pe?PTM=)TW zN?f82m8HczMlR2GBp>XIs&Cn~cKDbws}a4%jC~h`uBFl-*MxTsinzK3w$~0UK64VV zlTTAOrj#Kz!T@u2D6++9y}?kE(252yqfK@k`4CMpPIMjv*{b4_^Ay%&C!PSqHd}ln zh`Hp(dV?d_B`C~NFHO=PD%QndIiK^0zq}p(wcM&y_>|C#NpJ`#sv-SJFh(#j?pZ5H z<~l=`7Q$*gwRv0ZmjzcuK0!!b8r4W}D&mshfS)M+(MIC7UDSf|Zz|asPba$(o#^~h zn0T9OwvNKT$K8f=RdoDa5aa$=OvpiERvii8p%h3Q>c~83B`D<%eutrksNHTNC!VH? z%KEQ(Yfc(0Vp@OdzfZM>?m;BmW66dDI2pCCqp)&;NR3$b`D@^FX|%GuKQV3PsEM<7 z+%iwy3|2^$Lyd!)Y%X?Doh;))lhl`jazpWowH?oMahFx-b9U|Hcpg)uiV3E{4K{km zLEWH(PrR8Uh@@Lydp^;2BZJhvx_kC}-+ zU+{e}Lt&{`vKdu$IiMsiXS@rec^q-zwDg5u7!F<9b6D#nvC_wtlgReTp2GEQ7I|s3 zp?y%Ont_4-dipCYQTVM@eRo6}CDp)WWcqMj-aWG?%Z1mIeXIYar!w{X^gmVLjh~B9 z{rn%nwS&FOQSgyM;ZNiiAA!p{w1`VdpnaFQ zFxrgzQ#6mEB)9r@S4^LU0v~Y*_$N3(Q@lR%28o+N2#FKxI;qMo;oe14FoF z2_OS*a_}se1x<$q2G5UMHfB&Khu!C@Nupkqq18Bb7~cKqud7h zg^3m$@Kd2|CU4J(i-_dT#pEhwLb;1i@ z#dU{M%w>5#Zr8A)0w?F`ym7HM&$)bDXsaXrIQPTY^!BGSZ4(A^@M1>{Y^#hsTnIz% z&ydF3g^WSXrP`=1m496&@_%u)eF?Nf|J)LUsgfs35`(?aU_fn(A^UitfY*@<_GS0!o`lZz?&xCQZj))jMEBVjQhjSzZ zh`37}Ki3O8z-3QpV#HI7MFXDdgLsvG#zV{R2rpoIxc3 zS$}MKL_RtkEBce)32(2!mKEZ19YMNrVL%l}5&(U)=n{}L46fvxqUbjjHE1hduX_Ij zrWtjgCZG4ktV#qb2$6ppu9A-#FE(UD0v(=IUrcK{h1Jw=C(oK4@MY#oj5_s(_>i(; zxhM8KX7{*D5Fh`FsY}Ma3wBrh++kvo8=k_@o;RXyTp7`_ZY_Bw>x@yP9wK7#6#scw zSJ08b_$bcd4^$vF(~YLueC`%3s*Fr!qR^D7wJ2{qR}>)yReWV4O zCi@!4ehX8^g;nIMG__fTSkvG!eq|h{MBz2)-T`Qy6IzYDnnUs-)$#2hQZ;SffE_=7G10f4=q3`>T905`FmO7wJd zB?mAQ{!kwAgi(!ghARV2MhSIF-Nu@Ky^b^Jw{_q9L7yeR%WZFMXoiJna{Fq81K3L9 z@PkGj+BCO=Wa1mj8G4X+{-peg~dO0)pV{NOVrRRFQrFU9>}-})GgUb^4v>sFrGMd2`hC9 z&<1$z{-cd}@a_daMb%&6v&7SENQ-n+ep;H5w0u;)0pO#d&%N1N11BNCPQm@E7G5Ul zMc_-%d@aEcj*$dE%^wo~OhqZMnHDJ2u>^dY75+;73KAgwhrfIytY7_Gd56xAdn2am z_ep;7OTRp&5`1Y@;=`TN@6(%7s{YI^3oNIxG$zI%OyD0l%@^%TIV={P^AL%uQp1jT_Dee_yuG&1)u#ha&Ge_nrET)9EW(@7cBp91TR`m@ zevVSQ5iQ1k)78Q~_JA*uP;-`R#;8=HA{yxB+@dWd|Af6k`jJRkaYO{3*NwDHKF_H2 zDkmi$Ay5W&Q7bmlRe|+WpO{z?>yJ6Di7w@i>i>eMEl|Ao58r8h^1F**N}EP=lOYfR zQ>GTVtcS{z36vH4z2Er0kf)?pw5#)o$BrTMuq%^Y2a3qwrd+JNGjJ<@R{H(Jkkx!q zgR@F*bIv7VZlCUTOgOXY23uiHn?T-t+#ps#5&n3Q%{IM|Y`y((Ua)&A9N4b9$aNqg zgLkRR`O>)Et0HDJk2{q2w-}Pst4%FNg7Pyfb<$8YE6C|KBB&rt&JwVR&$n93`D)EN5_={$&1S z!0)qb^jA~GPMjHxVxVYtV*i*)qzlZ*v579`Iu;P*tlWW^rM~f-fj%Yv9i`luA|09g zg57DV`j~ig;8%OFp8wT9R>{rk_w0YX-bIOWs18~SpU(pqyoq755-@##S^Z=uY^ z!n?G8L7@|>9r0t{tyTH7j}GehdROHfWB4IE#q5iV6R_yBJjuSfMP(uAiCF=>6}#0* zrh83bI#0ffi$c?II%OuZfb82GnBOLbrJ3x-LOJKwHOLl;{0rELR;XIX5l?8KO8hb~ ziy2UzyK_D#Dti~@i856bGPNDyL-UDbW>X_-YRO&T@AhT4sz~B z?Uck&omPuvuon+yhUP2N6|{Of)}X-4fLW|`zN)VzCP-<}ySV?B z4Hx*kV3&_RB^a1cRRQMu?o?+p_3p`tmPkZ)&$_1p&F} z97bpkU}T<4H5prfc$$BA*?E@c!>qbsk43Pcm~XkP(O-?`1$GMVth=NnQZMFJ!0NhK zPT*w7Xie1`L_pX>8f93^x-Fojm@*_!5}(BT$f&fh{Hgga3Kc&+t*T%$9#hO6q0Eab zCGN%-qP8rV8eY*NZ4b=T#z?_X>%~F%TIF*(Z8pb2-Ev|PfR)SShcj&W$?nsFxaXpZ ziEFcytY&I-<+e9yZDJ0qhE`3%rS947s)yL*QMd%OnYgG;*_rf-6^Tck1my}tf3i}NoC8%q(11hnK$+<}BOl(&q zU%v)j)Ndsdmc=21qR%&xT>PaCr^+VZq|I7F0(C3M^$_c7GnWt<65JhuG|`9-+KW69 z-e5uCpP)~nmc?t5Eh2CEX!5YKf*!{HaY5utF87zBc+TE}miS!?d-FzX<*~v?)ci`C z2xpzxPe(20WiRoIjLZo}WnbF*t0qJ$1sJ6s5$o38LZ^Tnx`nc0u<8#HZ54t@I8b%p zm{&&2{HyLog_+@Oc~_T+q0o6o8I#$KLS@nR)`g}eqe<&h@XatM7EGvI+ya4>EN(*! zDrB){<1P7$*alJfOeNcNQdRel)z@>Z!d_WH3FNA2?sO9CtJpZ511K}@T7{)QV7hS^ z$^Uqi_I=U4@SxA0GF1n6z{1Mc2K6Qy^5zSKXf%zSp51jeQm{6e!*x8zjV@QXh{Bbc zOZ6&6p!H4Q_X1|mz#HK4?QA;1wf$!{!KpACdb^f4)9}jTG496?{iACrO&f1EF#D}j zT6s)_`Y$=nP-OYNqp7^QpERPre2acYZ+DOpF4K$7YWLsxc^ba2JA&(T;;~loUOoj{ zz*AW`Gd*CEn;H6Cb8()fHp0OM&;MaobPh}lI)XfvnCsar}PMe^x;wlTfw~Jp#yD^%-jqule=gDpt3i2m5FB&4VGRT39 zFPB;IPM{ve=lg>*)M*N4GSR=l4>oiPsHgOf@xW?!!2!pR8Kt*~QB&hot!=c4-9Dvxz2rS1U?zkA2?gCC9>`k0k_ub>9CCOR|?LvHxIK`a$N-WiUyX9n;6z ze^#49DyK)tDGCuY=(N=#LtCOmjuqV-bWb*#yGsb%hJAnDv39@-V&$;L3X(c`hGha+ z5CN0`Q5q&8DwW}jbyf}_C~f%O=Ge-|qO<}+J;ULokrdB+m$KK%PJ&6yW%=Pr)K+Zx`?&VG(_S9Q$U2(E-3k7%jG>$f{O!6;gF9pXi zUp}sQk!0(ED)oL~YU_SB7~u$C5{)c)x+pYk%Pre4(pAym$=q7?Rfbfp?4f1K%IZ;Y z;QJ~NQUmnLMXvk4{Y%q)sr9*%j-Ox7oJra#n{%dKH+n+@V+1;N1yGp#FXbA`g_3R> zACnap{G)|mIH72ZW|n%SAEdjj+GscAF7wyBlAi@%>UBxhvl7jNTx`O%)jQqO-@F+y zV%?KI^49ZJpci6c8RKWCm8^T~*o?8z&NBD*wZU+2-Au-PA%n8DK4a%A(L@b@lbuXM>zv-@QrlPFO;}~*>9tTMh&`4on0?nhWskz&Wiy99g^V6tgE5Z!H>@0m`WydMA1_^cmB z({11gN;f%2jiPb^vYD?PFhe+&=ds+n9k92e)9`J?x(?_Uu|OLGzSwiF*F!7)>DH1c zQ3o#VsTXlO11kf+<@lzb*MtyL3Ju*4pC>4f@o-+&Jy$2cIl0pIoFxW>#}Mq$FGFb{ zQcQ!I@t>RUo?=eS)FEc!eOD#|4*JRRyJa8Mp#2+*Z&{JHQi6BE+s3GL7Z(0~0B8Y8 zAzEx{vM3a2{&Po1SGLM?Ot&BRNv)vQVZYtG6pPUSKVwHw&b@dZ^=s=Zn!JCP(SnIZk6aZg!b8}nKg--? z4-pA^VYHepY$5A`84Lke(8ZG&3dk`i*y26-?d{eNSd@zs;Awda_dHbtSN-@x; z`#3E)I;B%^Y!GYE5GBcmD`)=%fyvhdOtqfVC7W!d?HkWtu_DA7J_4xBx_79-2n-QI zBkE>RTVtC^eh;|MG82vqpN_F`D=GmW(K!`hMz9>|V3cH!a)D5VJ8=jqTiMyO{8Tev zQ~r>gkTDj82dvxFv4g44Mgj#@GbtCH^;&1ajLu;6#T{^wT9@1E3uoYJ z3f-ldUhNaMvif_QvB>8QDEEat>Hz6%%6E|FD&*t#B!ogNXK?wOx)~9psEHgCC9Tmm zMlv}b89COsD%#n~KF$dy0ZoQOS7z?JMN_U3lS7^_Klaza-&T;vvw+ul(!T-KI6Rwy zH0-K1fpi`%->E*Kx6UH(@u#hU@xUhxz@t;_A?4+8j4nz>v z{O{|v$w`GiO<6mQ& zyN9&_aZLN+HnB$wcHi+4)>BN-1b2gJ3wC3KAzy|Re-P@%Pbh*FM0b4s{o}SRm3VrH zxCp?H7X9^THV`GJ;e1#qOp~R)-ioI$mT;7Op%So~ zA#B&>FySW){StF)#SUV`B3O3aKN#=3Zt{MMh9A{$0X~e(!;Ax+m2`IU?VVoHP~(wk z?=YC$`Wxc;&K;aW)y5-z6h{}hhG;N=DGOY5nd<9JdLMKO@1t6JCphr#5tTTUb5-pu z21T9v2MEu&?aIvz8|B+DgiyoCJa~+-U5xH;?l*Qm91n%*Wcnq-LTtY{@x98rtBo1Y z#`P2RZy5dSX4=YL9S|8zyAet>yPa_DJGt+|xvkWIc)Be|^8(&c+;@;j2A@=K zdx5XUlCK*?fgeLb^;$>LZ0Rc}DS(x; zNm3Z2kcgV64^8J!lWe(3JiLe!SkRC4M^B~y@gc7Q`jAGLUsxzg9{?NpO+SAFeG`7r zHWNhzXtvV|I;q};h(r=xTby;_{z!EM#|GU<&-e)VzGnqFX1MBQ25l4C>fD^YW~WLGrmf!kApAP1x$CjYzT@LohMI@jBKZn z8-Uw8y0WL-vIwKU6b=GXfq)IM6V?x@>uKO!F8WA7g~%aUZ$JYjOn7>E$HO5yGKY6a zyU9exmyMkJL;m}6GEtFe&&g1x6oMQXskjKesNTR)zv`h%=AG7df0^$k@c!Qy^toW+ z=_bIc>6`Fyzc=+>-p0AlUHaB_5sY#;Q<+?iPAelD)zG>m`ivfsNHkpJW7=kV5=F`j zDsdvAx9;2ggZ^B%6{)vE;ZhIeuef6+#a#o5yVmWv(6?Vn1Wn5k6S1EFKR1ew z*&Uyg+05<_247Q?Vl{MZn(nI6w-!#PB|+tjMks5|n0YSqrsi`K(vs6Tp!DJCEzm~w zhcX`${>3Gbvi%5-EX;ZqPCZ3*clFiagNOwnXyryX%Lkreiv}@|ha4N}miHepbX-s5 ziAsl8el_<$91QAVxwZ>%HN5?aNY-gp*nZgp-aUvR+t*etowfSx7RH{yI6jef z9E}xSlz>s+yvnGDKYP}0Hp*rKZvb|+>*)%(`JHs~Mxl+Eb9lv#V}HGtv48N62l49H zIhqOC;|#rq_tLyPYjfOJ2$bR>r4&i*^UK#C2LjPuH`qsB&sal^o;a1oq#xB~7Smee zQA}qn8P><`$W`+ZPmj?`MeKu9D7>HsD(+sj@gKICP`o&ylV)Np&R-b!7pp<_B#Z;I zVvq_|EQ#nhZWZJObGDDH5nETzZXPrR-PTW#<)0)XzUcO{dEEfPiGBsgt=rzhsy`?l zhD-1;di5rxB)ra*ow1ekef&y=&``9{^w^h3--IZMf~T?Bc{Zft@i8?p_Dgi~LHFd= z@wZUj>Q3icwV{7y1_eZN3t-wPSm9>5CN5ixC4|; z>>-oq<02^@Pq&SQTpL|GLpX_}QR0i-1uF|Z;KbgC$bN3^on2Y1vemhI3(3xO48zkO z@>$iA5BZtQaXLrTw_NE6YG-P?2&=P2#5Cf8^YM$X`IS3Y_kWpKW_rf_&I-dd*e}=R7t`|skQru9DChnrg!M@*R3=3Y6q|{` znLlQJqI>Er8-BsH7Kmr)$EAXcad5iPp>)!C=&$WJ7&mKzvNWLOZh zAar>A{kxESU+a5gF*=HWXfOe60I~v90qq9?(nQVd1YS7oHNZ|e=Gmv#=`?A$lH?Qk z`urviQS8Hs$t2xDgx?ERmn3&h7AJ~+TKUFk(UoqewRdy3JL^l4EZ#<8J$EKk|8T_L zf%ZcV=FdHI`FJoJocgRc3y4GxHzQI0zNU zEr8yI^i&KB@Hjl$-ksfsA9Z~EVpP{Boqjh8nxv&gj+yKhMFN5?@tXs2Wd6j~Ab-$4 zAc(y~IPMHFt@@;5!J5naETL~`0>rs%>lJeu*5!1EoI?%2Z1jhH<-gbYesryhnOaqi zKk`rINwe6{eXLDT{r)B!OT*Wt@{-WUk?C{0is(!Irnq!{YLS+U)KF} z_s`*>e{6cbx08&sv)0MB+dRw2{m_l55xG`@-2>0UqQwT``-x!3-%Y?Jx%gHY|1rb& z$=`c1XRXlG)~%eEq>kUeP88`}1%FOo9b>cq^r~!7^GYJ~iT&HxvPiAuhEpM*Fy8!I z>x!=^j3OGbxtzUsHR36Tdo$J5KY^R!*j)g5=hD|MZ>k3m$2|3wAmN zhm>KK_LeE9$(>WgVHl`fj<`XHP5&;sKX60SmvcX%z&mVNFU-7u$d;`c!!4)3HUhlD zN|o)R1@o!8{)+41{f#^l`z^37qOY=ZOT`qyK}}VFQ-;za;^s(9y>NcaZ_kxWR^9X& ze@T2#SV?(}3;)3O`Xv2)g46x-&quEjXn&l}7Fe8|G<&oE$XugV@7D5^)x}U5{n7^; zY%B~hGNtB0zS9FWkr4^6rw&YP-DO2Q8{B;CxnK5cwCGH4B{|YMzF`vH86_w=q z`4FiTtSD1Q4^8-Dar%MpzS7FB(b}ane!!dMRicvti-zlYFLS{U!6gu?CXU7S^PJaBru$~ zho~65OW1z7{E79tBe$aBtbq)QA&qE}(d4tyoh19F#`v-A4yzQ|JWpe?rf zwl!*lk`Epzk0yC%tNZO2Kz2>FPedF=Ja{*SBwFrL085n(wqUy&pmPd7Rb%9~LlE%- zpaiH0PXb1Ig-Z$P2lt4g7~FAmYE)WzNv7usk)}Wn3V&JL!JgjYSIT(af7Fza{r)nVH~Xyd>7GgE+2Is@f4+kxT()- z2P|%YP!Vhl@O)0|K9Q}}6F50o->Aroa#l-$+=gatK&NGzM%9p}_3h2oXVyb_dQyk~ z-7Xl47$9cxRxAtoJXB!SJop?Okh`+6w4+bB&gda{C;*PmNOT!G#}E@v6zFa z9?d4AX^H&PADWeX=RF0mc$_ zOIvoEW~F9)b@{InZOGdde{!c7g2e$h>%TXpg``0TFdrM##{*MrG;8S)II-aI?Drok z1vOnN-7OcN*uderO=NVs@JtY%k0zoZjxSrygg@>bJB2v@BeAc$a;G0S1wX1l*ZM-_ zjuK}wwu<)_c$adxTZ<6Ifw4OeY~2)Dq(sKFp2Jh=IcJ6s<3Glkt_MoC9;-IyE}~=v>(U z#MMWiO}gO{vq(Hu@5DUQ!j=A_QNjMbzW+R)Dv{QZgV<2V^;9hgV#4fhIS3=qyw~rY z){;)f2f^?x;l6m1rc-joKXfY6#qz9ea*vat{B7Y5+cUJ}$SE*wTU^ob zLXuuxifb?zTW;;zq^P+HSajtXiUrf4XZ6?0kDM}!+-(c2Wy4%iZ2{p7uNz2vz#-0? z_?mxefWb}f`v{K9y)%zQ*#O{6-tYGVcz`L_bSe4d`*FH_BRPu_#?Q+@Z~;CVeh;d* z!X~?=EBGX02u|mqMh7X->mJZ{d5gDzfPh%`bA?0k0=sJ0EE&^u-xBVm^*QTGe5940 zxJ_4d9aqAWzC{KSG5CF#8>T6ODjB)g)E@CPTXgvL9=$%NFm!MGG0EX@kQoE>f4xai zs`aA7GzXl(ygbXp8M?)?ug>3VS{a2rSas^Cr51Swdt+LRoo_U#G?f^7=cEo&m&jO3k%P8)Ji&HM()AEA5PzK9^HJz0)Ap&Qn9z6tO(R&YElxquQ}0zmL4o_)hv8Oqx2u&aPEUrJ!y9P0nXNma#E zMgttfeIgTOPqx|N+>qh4mN zDJ6#Wou6j_wO9Kaz;Ez@ts!6dmoxBe>1py!V^6JP#B(FVsFCl2J>v&B zy#;bP2%~n<|G5Vm9N1z0g*PR?tYK)SE#op*x8isu=}B&^aeLImxb@Q{j)&B{?4AbX z-e@N`GJHBjEG{80mYe&26%m9*ONmd8ht~q&?$O8)^YucLeYIg?t<$F_rWfW|J@7*2 zh9iFzgH4EjnH!*V4-_IL9oOqP$6REw-&Z20l(aa?aXDoy5Ow#pPw@q`G;gbF@mf;- zA4{dS3z<%20`IFio3!2NkYZmcT*V&7J38^PcrY>p0wG6uCKnR?YeBL{rBh&DPV!Lw z;urp2t>Sgjl0))=F5*Umt2JzXmvnBXE4e z)%~H-VzGcs0^ci6E~*3KHm!{ntMGMr${fqe*n(2#APt7)O7DctY=>ZI^@g!B4ZR|% z?hmp{$9hRYvnhl%Ge@oPAQbRt4BHhZ*{li8wit@hWi>#Oa2=~(XDzqt8I8*5Lnpk5 z=a)8eHd|r2pv=P1us^prL{gEuOf;}6%S_cLdX)4QVCPnUI(8;>W&s)DT}Hrit8ay7 z$}JZG!<55l(eFf0vXde%`BKT(Zaqt2NxMbl?tLgu$TM)frM&v8>4e)g+^E<+lx2v4 zLQ7BbpGno!bVVs>fGa6St-7Sh|G&&zcH{%a&FrRbCj&;a*i*?dK0}gCrx97!vMB!= zAEQorJfGC~VA1!Z`#jZPId>E(D1~;H?oHe_6{o?)3Zyry1Qy^%HU9pb%&w0A)_T^b ziIH@9w8iq7ur&s(~@6xg7WU7{g+%<$2--(UtPYbe0I#UHE zAi&J;ReJ^|X+)K1`|{Jjg(q>W56BfJ3GWyM$XBNhR~!YsS>)**xcye7pL|A)&k}WT z%xL=pypoLs33{jYiP8(k5(&k6FwZg~Vcd1hIu39+VZ z3CX5C953JRs)jyCf}CqFbz?YQQtg2Y_O_(Um8`CI3q$o!{^Y&zMm0*;( zbCn}qi&(1h>EypX;xftG;ReJZB;vT2360ys7~EqA{tSL!*sfV{ z%7vx$@YTV7e}gu!u|d$n9d^lfZ6FY0x|h!VVO+w!hr{i;06Ljy|2=tgBU{(hL7j)L zdnv+(H%9>n=s4v<)|BK9T;$!8UXb=iLrGyi;S_NS>HglOr6SS;cVH;A)j#(|C%5PYI3f)O{rD)5|q^$^19s`SDU| zN$}-H5*xdt-d^WWQT&PcL$B#5r#)@6_|A}UzFA?7R!%bTEaw`rZLcEDYW%&&qy#V; zatU-h@^0?V2`pnR66YUn+T0_J&v*k`rI&9Nv5A@0!ISwE0!4e3Uq90xL@`BBvYMtr zfuF%oTMf=wla)lhR&cO53~+_;&>w5C=VF0<&Wwvc_acD(Lr#esp7|6$V10tkh{!ng zjHbHce4|_#`Ci2p6f28?jQ{>?L0gfXYpa{++CG}t% zurd8co3DleNvo96zLP${TQzB~UdmBf7x6MsFTY+qaQb5RK&!Q>sInJjbt{Pg-Ns{^k|t)JFvr{+TH= zMGS6gep3P?R27PU&xrEQ9WVnJ6aP`3lV5-ol}8@lW6`V zw-|LcUVpzQ?1+T^O=d*!K&NAeYebgPRwWt~+$Km@?fA^UGl(k{PXdT?@z*C zp}JHeOB&%!t!Gl4YHVlEtXvG4+TV{a@BLW)5<2^w$TaIGU}O54V%7M;g@wbQ(XV2L zr@uT-m;N&O@%H7a^yHA+E@FNJ7M%2T7L^6;mArI2{d|?aJJVQ-^NSR1m`IeOzyY!ydIeBKm1i)M z2+nScGWu*p{_&aB+hU{ipI!Y-)=rX7)OU6j)?OlSF9+Tu>-00a?ZN!Sv2=N4u~y2S zMq%_%hxx*p6xXbhXX@Z}UKk$RsrstLAe77VZ=jAbtcdeKwWlP07B~=X2d>DbJ12f9 z7djb5aF65D&?Jf8P3mDpviX@C12vuEHX+A91zN4#v@}MZZM8Sw!m}JWJdcS7i%+9g zv<8#--)L~Jm3BmjcxpAB4^X0r@gSWT_53yvw&dr$vlQAWj z?pEKUYsS+E5|1BvU&6yqM;A=&=M zKfFRRmBj_aY1&bE{}{h%XtuEZuKNORw(~k~A)ysdqCYW-e&#UnjcXONXj_dSgCS(dHd?Sc*DLa?rVk zJvW=)_L63&kF~xNl;wVP4lbD~?Ip4?G60 z2&l%&pMKoAWOFNOekM`@Yo=Re_VSlVJBbP0H$ntWgC{}hqxHld zn!Ze1`Ec@|j`Z2WaMQN5y`EYn25GcVW07Pe$YzUe=c$Ra(JP4_!jjMJ0xeeFOLmV=ZSM2-fby~KBuE8o+qPS>1}0hrf9W1Q0Y z{&dRNZb!0y-Spa}r$4EnPdL12=T3mr1C}b;A)cm!6*?H2PhIMG!ar-UVgc28;1DF* z{h~S1kCjkH#@Fu|7MBoxN@yz57s_&FG8A8FHyP&x7wj8&NU}@QQ%dUia8cQ}^Zvue zn%)n88$Yt}T2dqa4U2(488OagJxGz61B%+diivvub|P=f?}wFqV_~*BAM`2mJdOd) z9*VS&&t_b%a#|q8z&B;PSvG}!Yki&3DoU!zv>$L5dYa?nZKF2Za~_$mk@B9`H4xf--n{=k-0Bk{pwkV^kpQa z{xeMc2$6giEvseI^khn}jk~)A_wGMFu3CK4Upy0CQT}ORFq-|>#Cub5qGm|5!qGw) za2+HR&aR9$`Oi1{{UYSPU`|%3sc&Ty)hum=P7B4Gwr2b=UJly>CH4eo*7@_24_-H0 z#&Aj4pVO_ufo1;-W<8i1yes6f8Z8j4_=n-!^cVY!1-3C8mAs@1aFS3GaM4FYj@kS7>Yr2gJ4t9F4I zHmjO2>!?b{TClp3zh2A^|9PkS}q%{=NagVOscQ6yw z9v4~rXR#ue$R(-KOe#3v+jo)+J?Cs$EBIjnDM=?DV_c{h0!R*vq*c{!9pm_7H7dRW z5k#1e9#?5L`pl3OmRQ;}jnPPn(~B~9{`=CIJVKg>V@>9^0@Io9x=hC*3#Ny-&Hrk+ zDe~A&qbdXz_*K1vw7R{q>Ddg9b+LfRA#@M{KtgwD4a=)?i0clQsJ!!)YsIb+c!6LpDHmkYH@7$FKgo0KyEwQLHJ%+Zybd@IMf7 zFe(FL1M*+ROJMla1KCnxhBpbkb8kH7rNyqK|0ZfVkd^0r_{Ua(w6}e}3FUU&sftwZ z@zU~putxi?17yVQY6#c6zayw-p5OU7 zoJ-0};xiw{U$3@M{!K9Qo^xONXn5n?Ru`AxoDGz%_Hr^K9aT^pY*j}-VQLi|jEK~l z^p=Y3m#>a9Ev6^Sji8D0b8~4s_Turdz_oBP6~}^YWYj`E4E}~{Y#5HLKB%POJ7f$e zrDddyj}(|195n^|W(p&JUWY)a{8A`&?JB2tGGmSUiIEzwoF{qxv3Npk z3dzk!8bR@Cahimc*p#)Wvh@aj$RT(=9-NZ)H_WmHUCvtlTG4N{U~9XKoOt&QY|4eO zMF^LN5$Dl7k4s)yOK8*bqLJ}xgRmO9{YUVUpze+K2^U>;=D3NxrAxxz)#))|mu*G8 zS9?^WPW3$=+V68Qy!!a7IL%f_LZ64OE_Iya4dLrI)K0`8$zK}yMbqj&UDl7E{ufEU zt=awKiJTb9FTNCCXKE6pJR<^{F6xTETE+}`FL=t|l-)MHAg%m5Rfk>WnO${g^XD*7 z|CK)3QAfQH_eg+l&YPt2shbmsB~~p%ALpBmN%6E4vgF?AKln-d6cqCE?T3kI)^P^T zwkz-{B&f5;tupOk-`u_aPv&phnz}ynXOTJ8p22m{`!kZ;+_J4}gJx|U`7|Olr{wxP zGfDe7Wg0rD4JK15p=76}xQ_jb{zfKx%N z=I#XF;9Z}PkGmw{NCUtQ)T+H+Uc!e2?7CmV3!p5s3H+p{>C|Z5bo+^5v$=FYmK6Dz z7Bf#)FAQ#g(g5No$cr!dPL|T70zR$zHGMJpiQmzT`5h`XFcRjUuu3$ z2VICf)Ht0pE`K4gYk{05KHV44UfV8cNP`42dR&UV_y9_ zE;^m^C3o6UatQJmX2`%Q1%W%*Denu*wkTd6=VC(^76TqUrLIw!kT`)DJ#wwSC&6>- zxy!%5kxhFM{&aiB9>K}qj)UqXZay2~B`QDuTy+lW9%w4x@%HP8rgS{80>R1hkpmrzb^~>a-O4vu-G)G6A*6p3_iv8 z(-?uyUnv9pBFt#L0_J5E+V>NH-_DjsN|{K0t_Ycthjq24oi(FT zAmN3t*1Na$tfu#`>Nz06IJ4RGz|WMAO0#W=TBp|sZr=?|bC+XX<)6|?0rQA0kBk%C)Fgb4Hgmm`bSmA#`^NzJl_{trqhwbut* zfuJFu(1W;A+>x;nG?D_q<_y%tpl%MDfo)h{#V0m?TT;Fhd~Cf0z69MuLH4xZ-L*t> zPBYHPYQhSL;EDJd*=dJdVBfRSk|j)m!^`Sm37k%OG0YtLZb*ZKlE?|o2Aa@*YQOhD zpa4*S&Hkm4e-JYp0Sj_8w=>?iZ#BriIQF$U+BWOS& z;82?jHj%9Ku*~1uw7c2(I8+aDi&BQ}Q6>nMm90oCPrm zu7FF45stX{0<0_^;ckFPxEa70C@W|ItbE=s4uatJ+MxTOI2eRG5R?G#Rw@7~g**Ti z-~r$iGeYm+@m7pr2wH(DUSxPq;rEs$fNs}F;11b^0}_A$=dBz@gh-Lpjc9|P!n@%8 zgK5SQAPjy6-^`G~nc?M@Goi0C2(g14w{*C{xrLQSQ2sGj8+8T}wH%!P6@FXrJHNflO9WD1l;CrbdB47c5P9fejv%4o~8;%ZkYGf{9B>)^bg;ER=9j)6Ni6xHVjF z@FMAi@c`xtcmSDF#iLkS45yEXI8WCKfQ+rW78>0QBoJ7Wz~HJFG6Xz<2cQSAcmf5C zfoBhfbTPbPum-3c7%SG{<0N5$7e*Z+Ac!O)25ta2fHe#JB3YA9SY_}d*5M?dO38wN zAP$p>4>&yKA!m=3&n77?maa$$plBoq;mKuqdvARA#Nxw+(}5g-o<;`$FjPu_0EQ9u&qI4{B_{)!5t9z+DVoU9zZ7qI&KUc0~A}F1sZWKc$p1A!pNj- z#={X0zi0}>A8^&t`$CBWp28U{0VM!O{0-m{2Z@Ws5hNsWG@(g6F}|{3W|?yLsu&`1 zL3Cjo?eNeZI}qOBRg)UX92_@vIIx4`!S&#LaFm3691w0QFW7;Eqy5T+k39S0h=SZ6#9P zssXa587Ku%N2m^-%S%X?5@bQsf)oEs^v0J57m_@HL!}z79p@)-$DaVI7t*vEz$%a= ze@njy>Hxv4YYO~Ak>nIG->k?J0I+c{!ff0wZX16O;Ku7rJk9T2y4@*9;-F~4 zjV=xV%5^-*9mf)rslNi(e7SJQWe~gQGr%3d7-&{li@yiP07K8!K(Q1}=#@si_;o4d zQ5rP4kf)Z!CijuJ$;|_B@=-ZDwp1>Cgnvp%`yfIJ#C{`_r^B91g_d&H|aZOQ|M)mbL-l#G#0oFEk-f+$Rn#K#5N`VG48?r8ZOq zGa>?5^lpe>2iLi|P=UuG;-d;t(}_buIY9)G&|x}TEJcGnkOD>9@@f|ahm}+jO8Urw zuGXB{RR>{ZXA)Y(m;AG(EvcRwujJ)%P|cpz21ZtpTUmpEq9vQNPL+9`k32_02a&mS zg`aQ-B5xEocHgHZmAJxOK5Z2M5bC4%*<%O|%f2?7QY^KJoM&$|J@b9-dm?DQmF-jW zb`lub(mz6bK}NujxH{*FG9gU?$t=POXhPV%s03cZID6oAlyf9zUIozDZoCHvnC$a3 z{b)0Tkky(iI<~qbnvf931V?!F-fq^4G;F5 zBexw%t;x)Kc~ZZ@+8dRJS%|m?-~vbu^SA~j9)$JK%lbE$)OMcl&R?F32F0ePyFQQz zdAz99L<=t?8FpFjyO;fP#R7L0-KOrnckx{P-GE^qIOZ&jA}eLVdgN6UJ)ytwozoNC z5`VWMM0Ws>{pRc=wp$}W@2~^3_>#m{m);{1Elky7bfED z51}~Uc1{36XC&*;IfY`37;8E>NdpDvyLknDhTa0Wpt}@Kv^D1!z*C}|@iC^LFwe1d zLlYql2kunzL}UzoORzw+qc(xl(GdMIxRVcXFeR##82F7Obpk9djD)j?E^y-T;W^ep z;|f{sn$#i(#Ym0918VhR07O;;fn?yp;`)##WJ%*@vLJ0$F%!mgrm-P|UfouyLZLp&EP*U6WOPiFu#LtL2+9FMQB_Z$A(^v7fPw z=ORv`%v=K|^!dyB#88EvjT55II9zK`90_|+00D;H(hSVh3=Op)iUHX5@eUgFoRr3d z;8{}&*Lq_Fzvy=EYN(zC8N|L!+J=UzA&b>`Ncez;K0~*m?+0+`G=LX?PZLlaG1eOB zpoBXP<~@kr7%f5meTpz`RH}Ysg}`W}O~3<~0mK356ls7QfbGw-eK8n@SCoL`4RNYW zJv|N}2B-mW&lr|{10X;@eYpKkZ-ehyRzFI<-^_)iCP=^5LAh(o0BQg%&4t9ba=u!z zT&|-F+VPFbMZGMdJd(<>Vq7B6N4qUP#rzO7NzOXic=BsREmjOdg625`#%ktu35Lq47Pbo$k5w0D$#_RL! z!?6U402u9T1lc1*+C!qMH(aF<5MybvIb9O!tsb8gd;A7oi#Jg8)K-cR=oS>Ug;mMh zT}z1cE+MChO&sGA5Yg%@`jJb0rHYsyVHx(2>2$ufkR<_ey2}D2>p;~tnz}k&p+R^; z+i6KAEO5Pre$$L?_QbM~Mi52Z3JV-JkV5Ei?RLF+b{|qfy`_VOd~PMg3iqB{@)6x5o|UW?Q^Vx8gO z_73kkZqy#l1$Gp#N1>Jq@e81G+%_da?;4F4QscEo%qZ4x2gaK_llX?ltK$*@h)N=H zy&j`FK*y~xSr-pf*4G0nk4}jCs`U0;Pt|PHBHh1gHR(9@6|`?T_Snx#Z$xeIZNM3LEmkVb4hGU^TWpmb8j zSuiVr3QW^NFw0#GF6ly8umtr{)HI}BCV|~H9H6)T+wQ0X)Rhp$Z5KO6{VTl&>K_mY ziUe_j9>w86MZ-j+9S93z0uc#LltaKLfCETNo98YIeuEX5hgHjNR@xDmJfwUelCMt! zA*i-vAwviVpa9*6dmC%q1;MXK$uR!*0;MZo=^nGDF+UiJ9}b)VS%4A6Lc-)BL+7UF z%^ylZfQ5khB{9$@_&8Hwpeq*?=}o$!J<>lpz8de;PAV#k16HRpQUgh9P*k7`gko|= zEmG0}xc(S7b13PclhMdF-Ozq$UxNOMlOa!BnTi{rw(Akdpr2+j=njH=;W}i|GCN=( z!9z&X%cH#mF#L$-DNBqaRRt#jx;?P2DRJ(@YZH_hYLOR)m~}*3QVg_cDJ-`};C8$; z(?FYOO&(OMPP}gsk7tG$uy*-Z14!wbqx~k<^@;OO+x!FX9FkCVi3#&SXhyHQ1uP$c zh-Dwj?LvnEHJMZ@_wX*Xv)Zra=Ibf?-4vq{Yp3nnc5Ur`L>zj)4=&z6uwp04T}ma5 zCV685YOL7eN7%v%;ku-i+7tI!(?9AEx)cyFVF+S0N)JM}Pi3jsLPpe{17}R;98R;T zobc{ivgUIJzX2o#WCc$+XlR@n1d;P=AM*hz_7ggu;El37NE%jlNwA-An=p$!E%-mi zkai8rj=Ezn3#I2}HQn|ai|*&tAi)0QJ19yB)&T1qNX*ISo6;>1?gy{{NeL-HQH!^5 z0Lm~}ksC0#$K%PE!?arj&@)O};53wnwa^*Vq+=xi=yVP=-G0Pzw706{YIDQh<>g0q_Pz@@tK>^x^IbXOg3)B?eG(ABmLwLgF|G16aw8<<6uCdz-)v zJT~|{3Ch%x{U0LSG603$219LvyUPU32tCJx%MJ8vARGE6+ogxG-n{mIoRbk#!#Kcs(XWl(d_Kaj05cNjM1X~nnZU1?UNRh`YM zmOn#x7Q#;xPUFF$S*xlo*fWjE0{O(JfEvJtc*(^G(F|p*3q%K?=5_)M0SJ9}Yg}CV zpq`j8c?&R1I$KGRWw``?0)K9aM@+Zb+ZgyN<3_W31m8=oW}?4JSJ+c?7FH+lTE!P? zhLaM80eqjl02Q5cOm8Cv*4r8Qy^^k35y5K)5W@HDu)}7HUs3|O%7^9nMV9`sRS9Nu zRzklGndNUsoBi8XX#lrcV!QhCD-IL53p@tynjhyN!EHKNaKn}w-04+3E`*ypJmD_- z#aHnn^VK6pkLKO1;f^mWsF5;XGX`oy01yOG~Ni zLCv5EAkAQATz9K}2>>s~7TEmxhxfS06ee4UBlLJds&LV68L3g%GGxSwz<5f5>+-vb zLYN=6ULpeOQmk@U0OQ8O>C2M0RE{zP`^8z)Ccwle0q$BestRk`ifdtr550Q{3RIH^ z1e2#nvjA07TCobC3>sk8j)(vi4+T)g5BOT~qrq2vc`6n^NTJ2+#Tt5RDqQ?WYZqT} zowNSpPle1u9RT427Vi|0#UoLS@ko?|lg#xBEzp=f$2X=+(upP_JpfQ}=U?6izCt)6bV(z;^2zMM72ihv3mDMTE1i6}oVVd_`th9SpSw}P{ zYT`&CsjNU}A)+L(fX0&s0`WqUB>*8FTH%ntPRA}{&q)mObE@G_PquRt)VlJ1$UIC|HE?!5JE{|rh%zfG5dUoZJnmV7>o^|`XW zq33t=uKD7;Vt&E5pZ~~9=4tce`P=+RK8=;P63vUTGFb)s_WXCghW677$PMK3^KFg@ zy>9-Ypwb(?QlCwGX~lFlAzRwl=VAjuwP5oZd8$0rDmkBjX3i_=lj(dO$gLW< zibeuSVO7`kA~|L>)$(eVhFa!cW`9Li*yz6iOMuZxZ4F0XaZ)^exc`zJy!ir3K8$yx|^yc6i=4c4bWRiM`)iQ;ME}rvv2gMRT z?hXf^AInd#YS72YF!Xg^dKw(Jii1a}XMh>4XmG9iQ9Z2QBrmI%Ge;o?d~-_;p%0pl znntyO`0u9Y{s^c_{J7o z>tRpT%MxyZO=bl>Y01SNJ(jWG&^zcYWjXs|2}p01!Lxs8d9XzG*mKil=WU{F+G<(gUp?e&~Tw_I)+EB(9g)P$Fh4J z^hpvWfpPZA1UOA^u&J0Ggb{xtYOKZ9xMM*Q?^x9<*Cya2M6y1|>jehP$Y3gO|2!ZM z;SDNKm~WcdEsAk}-+9~v_r~-_SYg|a-Y||ECThVdCP-u0znTWt%1x*X1 zfxUs0YRC$_&^vi`-=lZkCo?Qw%loMP4}^Z6xZV)pAufvIN+Z244tS?Cw^n`Lpwspq@d_$meUtP;KLzR|a5 zdi1HFNA|q3O@{sc_r#2NC#>(3^9OsCy+fSXU+x9ywv=qdmGp>I;9c#`d1^{#tb zIbFe0Iyi_VI06_+fLe zHiJowPrpYPBohLaTRAe*&Gm8b|B`pD+tcG-l83q{Y31Toeb-rL*6Fk+=rSET;-_E-@Y$pK%yjS&D>Q-&Xs^L9NGS-2 zOt_jH1-&DbV1?G?ml06D>yvVPp3V;7$v=r9>*N_o`(oNCpJ{cb1Auk=sD1dXEd;?V z>h>(V;^U%-(1m=Cmv9S_Z-rLYHP%P@kbE$L71}~dEK1Ki>Q?yz4GdQMetSW|>Xl9K zlPd7}w3Tq{qsLvmVd?KH`7QbcJ#D@`pUN-b@5WKD|G_Q=gq5+oR|UnGpJS{=goCzl_@7XY);Z3;X<7gFZU%f+o=G z^MQKe{0aR)KS>~v^8p-~-1)+|##KK)J>Q{UdP(j8&?5Q-{ypnNU$a7JU+`P>{`?O9 z`%ZDk*vr&|s*Z1zHBh~>-UfH02UTJB#s=wAFp1~5bbPIrjUdCOkc)Pq&GeB5zjyRDFCvb@+62`=@a68`i4&-8+R|jS8#J1uNClG?*f&`tggqV^wda&mO_XruAw( z+Z((ov#<`~+}!Gg1-W`~ATuSU!1?gizrc4)Z~$Swl+OP~rF-#-ZKnE{_U_%XzNK%) zXIe?_Jo*HD87mRm2few&bHJhXg8{+|e7JCXOq2%gMX6JX)J3x)&D z;*{p~Qa7L&Xb#Mpr;IN6qW}y(1}|5dz+3l~pyU-$p} zL~u_xdm$H5KKRBp&rc0}mnR~(`s5CrHm1W3%=@#m=gt`YeibuN9_#}vX?1Mmq01{G0uWlMN0-2 z(N9HJv?H3j&sTz=mH1D`C=>25Uz&%6KZ#}%zrE?#3=X{OsyFwDT(iM_dj|x z{T_h?G5`0-OY|Y}MvUPfsADFkO*f4B7+Sd##7_NzWXN~(jV zCY@jQWiC|dJ{bBw+^}FjKp|`WHhW^Nz9*a}_%3Hq^-cmHs77H( zJsn?o4!{yOLlL^7;t)wGjAYIwxz1oekTs{hDYRF#pUlV;tK18&HHEbB&IywHT`fO` z$!!34D_c0JSKtrew*^^KEeW?)s|m^R9+z6(6Myh9Wz z$D@><8?M8hCdzUIRI_mc@4`VB6I7vA|=Dw{-%K%K;Yje zAd*fj*}9eB3~#beJA;R0>#qC{asZDSjf;xoa1JIEGZO&r(IOK6P2q0rWM)CbJLn)x zc#tgpNc>FaK?54xY?*SM(*J)0zy6<_$sUfh{+$c83eDDNi$@_1IbL)_7nz3P9RZJP zdt=23Lu_we07tFS4)Ki^rv5K*3Au=XGyyjRXeBWLas!@qLJw^c85hcbpefuiPXIt1 z3vaa;91<`BD<60id}9a;Q*iZu0#x}_Nff*YN_&qjUjQ38XjL8ptk7=1K3V&Nj1b<`)d1ZD9R9}Gz#Tl4;DFv8+kbAB%xqc!7xlUC8Z~%;1 z&jVUKENS^>183N84q=8NFLdAo=RtdaqJCF^6?v2>4FSe!CuzNZQv<($dO^W|NhHI6 ze1EoX;eR)Kej6|dG6+w9Jr`~qVO8Z49c-Wk|6cF}>;rj#gfVX$9y5G^v>~Drm_KWP zAVCd)X%`QGqFY}X#0x_&_A~8ND?qkxoDWj~>VE7qdtPA(TWIMRj~TTlSq=P7^eo9& z87S8#;ysuKfCb!ndJiB$oDc6|DFrKZYAGNBZcG_y%zGmokwOAgS0L1XhZ1ToxEC@A zp$;xcs{`sLasp2ul}St+z*RA4)_yQ_6j8H)=@5Dr!aKu&coba(-&4RPCx8bnMgr*- zn+}yvN`PJzZUlJ<&<&!xjP`iW@@^p%ycMu^|Ey0UcT)M@ZEW7jmruYjSM{rgC+1h9vm}vT_|I z$^tDKC|_j+9}=x7@F0~Ec0!VI_-mtS6LFStqiL9N zt7)2XR32VwBu;x&Y&c#JsDOqjj0*L5(;!3;3@Qp1RaJL8{0szve1B?yhk0y(PDjmX z3W2|V+%V%2QV`%K3=Ky~mJ_ob`*tWKTR+bOdjds&GyytqUVr-m0YVFG;tub0zwjWrhn3YLJ=5D ziyh|(-*vGG)_=4nBM+Dn;eSIBh^#P87T!Hs`UV--=zX4%^ z41o>=I8`EUGHxbryaG!z)Fn(pEGbkJz(FfP;!W#W+%@D67+FFu103uF3;{I&Qa*Bl z2>>Kj!hvRfA}iv7wj@O%S5?U>LTVR634Z7Yqc~0#hHhehVI0v?+6fhW@C5W6)>dH% zaZAlb&46e^bAhZ7Kp|TXXb;vyPk;vv85Z3VKpd(Ik!J%OOimy{O91RgOmCBK%|I<% z<_9e#gcK$O<`4oOKNWHwB@xFOpdd&|LNN<07#fy%7Hj$+s{zeGJu8128bWkY+j>44 z-FhBMX(l*s{sgHuxPYq<7=oQa zFC+jMjC92#yDJuJ6b~F6xlZ;Ad}EY=EiyhBOaa>h>j5n*QWG3-#}jCPxPAtKxPJ`+ zdU?o!zJCpYNE0aq1rl`#c|;XmW;0oB5lj9iOhY;u`Vo*a2>^FxqC=J!qZ-dHa|ss| z<#1q3a&|y8gkDh}K2#0_9C9NhH-J-T6JC*6l7Ap{F=z5}nF9_4z#1D^g3cBT?A$?q8ukl!GQ&Vw|{GZsvS`SfqyRp&`NS$T>Ftq2YTC~#uOGQiTp42m)_=Md zat(b_xC3#4K@iIkhfl@@K@a49zk;YZ`EsFuT_2-ZLppsaBoQ_-xla8>oMQMJJ$&J4 z$VGcR3LRDo5d+BvHyjN^uNk>cqk>z3VuGfE3;`%2wr<34Z35?7D{Jplz(Z0=Y1zSIz3hjjsuTTIem+Kd`xM7u7W0K#S15cQ9L?*voaJE zfNu~LKVu>UK!AHx5PYKt;rTSOcwoX(a;*`9e1U5j7ME>;kZUV??rkMFF&anS&t-bVY1`Iwj#F zMipKp_gbD)(-VsYrzGlsU>2XMU<5BN9;$D0SQz224+NR1jQ%<0m3acpD2* zDJh*gn^XU7B^HGabWA%5T^@NI6EUj}ts{<8Koxo)A9NfK|8=`hjsu%Sy-zG9Hb}{6 zq(r__PXKF8!BX}e%1?j?wSN&QzEVK|B?4U`!cuq+2oVw(<$VPwv~~Rh*&rYfK@z=q zv=7?@O#q@w;sUb)Z#Fj!4H;Ad9V>cT1B7=i3^%$|!zeEcws!N-*#tG;noes|=teI)qdQh#_r47KFtCY8b=}ixQZD z&PV$xAQMD{^&t?1AcV9Jq6a^OAOW{qRvE}$0Ao-oND%sis}H zdxXgW&QV(?F90?nuoqNMDs=&C2V!@GmT-4M@D&Jzr9{qAbU3>;EClF30|!|WHUq5@ zAat$|vOu9~awCgvl>^^qWlCERi&=JmZUt9g;RCZ+tAA$=P8=Kv0Tl@Vgaqd!VlG(~ zpc-gEI|3{KwuH1Jyo6XGwuCEmBpU5m?*Y7ocLTPBav=pbD=0SrzJw|l?jd= zyo5La&xAS;TPD1OIRMXu^9zk8Xh2B`&xG{{hzs9@1QoV~j9K4=x_`EW^9#Q&Xg~;o zwuJ12uP0ao*MuVv@PrNoHYv}9-h{6wMJX%*@L25y?iuU_KR`(azCy8s1ce2K289QO T2!#oS3WW=W422Da4uxI;c_9FE diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 00000000..3ed70b5e --- /dev/null +++ b/MANIFEST @@ -0,0 +1,26 @@ +MANIFEST +README +Changes +Todo +Makefile.PL +Oracle.pm +Oracle.xs +Oracle.h +Oraperl.pm +dbdimp.h +dbdimp.c +test.pl +t/base.t +t/main.t +hints/svr4.pl +oraperl.ph Old oraperl file included for completeness of emulation +oraperl.ex/Readme Oraperl examples (copied unchanged from oraperl-2.4) +oraperl.ex/bind.pl +oraperl.ex/commit.pl +oraperl.ex/ex.pl +oraperl.ex/japh +oraperl.ex/mkdb.pl +oraperl.ex/oradump.pl +oraperl.ex/sql +oraperl.ex/tabinfo.pl + diff --git a/Makefile.PL b/Makefile.PL new file mode 100755 index 00000000..4c61c16f --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,268 @@ +#!/usr/local/bin/perl -sw +# $Id: Makefile.PL,v 1.33 1996/03/05 02:04:42 timbo Exp $ + +require 5.002; + +use ExtUtils::MakeMaker 5.16, qw(&WriteMakefile $Verbose); +use Getopt::Std; +use Config; +use strict; + +use DBI 0.68; # This DBI must be installed before we can build a DBD + +my %opts = ( + NAME => 'DBD::Oracle', + VERSION_FROM => 'Oracle.pm', + dist => { DIST_DEFAULT=> 'clean distcheck disttest ci tardist', + PREOP => '$(MAKE) -f Makefile.old distdir' }, +); +my(@MK, %MK, $MK); # parsed macros from Oracle proc.mk file + +# Options, typically only used for debugging +$::opt_m = ''; # path to proc.mk or oracle.mk file to read + +getopts('m:') or die "Invalid arguments"; + +# --- Introduction + +print "\nConfiguring DBD::Oracle ...\n"; +print "\n\tRemember to actually read the README file!\n\n"; + +# --- Where is Oracle installed... + +unless ($ENV{ORACLE_HOME}){ + warn "\$ORACLE_HOME not defined. Searching for Oracle...\n"; + foreach(qw(/usr/oracle /opt/oracle /usr/soft/oracle)){ + $ENV{ORACLE_HOME}=$_,last if -d "$_/rdbms/lib"; + } + die "Unable to determine ORACLE_HOME" unless $ENV{ORACLE_HOME}; +} +my $OH = $ENV{ORACLE_HOME}; + +print "Using Oracle in $OH\n"; + + +# --- What Oracle is installed... + +# Todo: validate we have the right stuff installed +# Todo: add depend's for DBIXS etc +# e.g., Oracle 7.x, Pro*C etc. How do we test for those? + +warn "Warning: OCI (Pro*C) does not appear to be installed.\n" + unless -f "$OH/lib/libocic.a" + and -f "$OH/rdbms/demo/oratypes.h"; + +# read list of libs that oracle requires (eg -lm -lnsl) +my $sysliblist = `cat $OH/rdbms/lib/sysliblist`; +chomp $sysliblist; +print "Oracle sysliblist: $sysliblist\n"; + + +my $oraclemk = $::opt_m || "$OH/proc/lib/proc.mk"; +# Apparently some Oracle 7.1.3 Pro*C makefiles might be here: +$oraclemk = "$OH/proc16/lib/proc16.mk" unless -f $oraclemk; +die "Unable to locate proc.mk (use -m /path/to/proc.mk to specify)\n" + unless -f $oraclemk; +my $linkwith = fetch_oci_macros(); + +print "Using $oraclemk version $MK{mkver}\n"; + + +my $OCIINCLUDE = $MK{INCLUDE} || ''; + +$opts{LIBS} = [ $sysliblist ]; +# INSTALLARCHLIB included _after_ INSTALLSITEARCH for transition period +$opts{INC} = "$OCIINCLUDE -I$OH/rdbms/demo -I\$(INSTALLSITEARCH)/DBI -I\$(INSTALLARCHLIB)/DBI"; +$opts{dynamic_lib} = { OTHERLDFLAGS => '-L$(LIBHOME) $(COMPOBJS) '.$linkwith }; +$opts{OBJECT} = '$(O_FILES)'; + +# --- Handle special cases --- + +# HP-UX cannot link a non-PIC object file into a shared library. +# Since the # .a libs that Oracle supplies contain non-PIC object +# files, we sadly have to build static on HP-UX :( +# XXX Fixed for HP-UX 10 and Oracle 7.2 +if ($Config{osname} eq 'hpux') { + print "Warning: forced to build static not dynamic on $Config{osname}\n"; + print " See README and Makefile.PL for more information.\n"; + $opts{LINKTYPE} = 'static'; +} + +$opts{DEFINE} = '-Wall -pedantic -Wno-comment -Wtraditional' + if $Config{cc} eq 'gcc'; + +$opts{DEFINE} .= '-Xa' if $Config{cc} eq 'clcc'; # CenterLine CC + + +# Set some private WriteMakefile options if this is 'me' :-) +if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess + $Verbose = 1; + $opts{INST_LIB} = '$(INSTALLSITELIB)'; + $opts{INST_ARCHLIB} = '$(INSTALLSITEARCH)'; + $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith' + . ' -Wbad-function-cast -Wcast-qual' if $Config{cc} eq 'gcc'; +} + +# log key platform information to help me help you quickly +print "System: perl$] @Config{qw(myuname archname dlsrc)}\n"; +print "Compiler: @Config{qw(cc optimize ccflags)}\n"; +print "Oracle proc.mk would have used these values but we override them:\n"; +print " CC: $MK{CC}\n" if $MK{CC}; +print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; +print " LDFLAGS: $MK{LDFLAGS}\n" if $MK{LDFLAGS}; +print " LDSTRING: $MK{LDSTRING}\n" if $MK{LDSTRING}; + +# Assorted hints - these should be move to a hints subdirectory +print "See README notes about SPARCompiler on Solaris\n" + if -d "/opt/SUNWspro/bin" and $Config{osname} eq 'solaris'; + +print "\n"; + +WriteMakefile(%opts); + +exit 0; + + +sub MY::post_initialize { + my $self = shift; + + if (-f "$Config{installprivlib}/DBD/Oraperl.pm"){ # very old now + warn " +Please note: the Oraperl.pm installation location has changed. +It was: $Config{installprivlib}/DBD/Oraperl.pm +Is now: $Config{installprivlib}/Oraperl.pm +You have an old copy which you should delete when installing this one.\n"; + } + + if ($Config{privlibexp} ne $Config{sitelibexp}) { + warn " +Warning: By default new modules are installed into your 'site_lib' +directories. Since site_lib directories come after the normal library +directories you must delete any old DBD::Oracle files and directories from +your 'privlib' and 'archlib' directories and their auto subdirectories. +"; + my $find = "find $Config{privlibexp} $Config{archlibexp} "; + $find .= "-name 'Oracle*' -print | sort | uniq"; + if (open(FIND, "$find |")) { + my @old; + while() { + next if m:^$Config{sitelibexp}/:; + next if m:^$Config{sitearchexp}/:; + chop; + push @old, $_; + } + close(FIND); + warn "Here's a list of probable old files and directories:\n ", + join("\n ",@old),"\n" if @old; + warn "\n"; + } + } + + # Ensure Oraperl.pm and oraperl.ph are installed into top lib dir + $self->{PM}->{'Oraperl.pm'} = '$(INST_LIB)/Oraperl.pm'; + $self->{PM}->{'oraperl.ph'} = '$(INST_LIB)/oraperl.ph'; + + # Add $linkwith to EXTRALIBS for those doing static linking + $self->{EXTRALIBS} .= " -L\$(LIBHOME) $linkwith"; + + ''; +} + + +sub MY::post_constants { + my $self = shift; + + # Oracle Definitions, based on $(ORACLE_HOME)/proc/lib/proc.mk + # Please let me know if this does, or does not, work for you. + ' +################################################################### +# +ORACLE_HOME = '.$ENV{ORACLE_HOME}.' + +# The following text has been extracted from '.$oraclemk.' + +'.$MK.' + +# End of extract from '.$oraclemk.' +# +################################################################### +'; +} + + +sub fetch_oci_macros { + + # Read $oraclemk makefile, extract macro definitions from it + # and store them in $MK, @MK and %MK. + + # Don't include the following definitions in the generated + # makefile (note that %MK stills gets these values). + my @edit = qw(SHELL CC CFLAGS ASFLAGS RCC LDFLAGS AR ECHO EXE OBJS); + my %edit; @edit{@edit} = ('$_ = ""') x @edit; + + $edit{COMPOBJS} = q{ + # Change the COMPOBJS line. (Some files use LIBHOME not COMPOBJ) + # old: $(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/__fstd.o + # new: $(COMPOBJ)/__fstd.o + s:\$\S+?/crt[1in]\.o\b::g; + } if $Config{osname} eq 'solaris'; # and $Config{gccversion}; + + my $mkver = 0; + my $linkwith = ''; + my $lastline = ''; + open(ORACLEMK,"<$oraclemk") or die "open $oraclemk: $!\n"; + for(1; $_ = ; $lastline = $_){ + # Join split lines but retain backwack and newlines: + $_ .= while(m/\\[\r\n]+$/); + chomp; + push(@MK, '') if ($_ eq '' and $lastline ne ''); + next unless $_; + last if m/^\w+\s*:/; # gone too far, reached actual targets + + unless($MK{mkver}) { # still need to get version number + # This is tough since some versions of proc.mk split the + # RCS header over three lines! Well that's Oracle for you. + my $line = $_; + $line =~ s/[\\\r\n]/ /g; + $MK{mkver} = $mkver = $1 + if $line =~ m/\$Header:.*?\.mk.+(\d+\.\d+)/; + } + + # We always store values into %MK before checking %edit + $MK{$1} = $2 if m/^\s*(\w+)\s*=\s*(.*)/; + + next if m/^\s*\.SUFFIXES/; + + if ($1 and exists $edit{$1}) { + my $name = $1; + eval $edit{$name}; # execute code to edit $_ + warn "Edit $name ($edit{$name}) failed: $@\n" if $@; + } + + push(@MK, $_); + + # have we seen enough now? ( this caused problems) + # last if ($MK{OCILDLIBS} or (int($mkver)==1 and $MK{TTLIBS})); + } + close(ORACLEMK); + + if ($MK{OCILDLIBS}) { + $linkwith = '$(OCILDLIBS)'; + + } elsif (int($mkver) == 1) { + if ($MK{LLIBOCIC}) { + $linkwith = '$(LLIBOCIC) $(TTLIBS)'; + } else { + $linkwith = '-locic $(TTLIBS)'; # XXX GUESS HACK + } + } + unless ($linkwith){ + warn "ERROR parsing $oraclemk (version '$MK{mkver}'):\n"; + warn "\tUnable to determine what to link with.\n"; + } + $MK = join("\n", @MK); + $linkwith; +} + + +__END__ diff --git a/Oracle.h b/Oracle.h new file mode 100644 index 00000000..25518f79 --- /dev/null +++ b/Oracle.h @@ -0,0 +1,70 @@ +/* + $Id: Oracle.h,v 1.8 1995/08/26 17:39:01 timbo Rel $ + + Copyright (c) 1994,1995 Tim Bunce + + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the Perl README file. + +*/ + + +#define NEED_DBIXS_VERSION 7 + +#include /* installed by the DBI module */ + + +/* try uncommenting this line if you get a syntax error on + * typedef signed long sbig_ora; + * in oratypes.h for Oracle 7.1.3. Don't you just love Oracle! + */ +/* #define signed */ + +/* Hack to fix broken Oracle oratypes.h on OSF Alpha. Sigh. */ +#if defined(__osf__) && defined(__alpha) +#ifndef A_OSF +#define A_OSF +#endif +#endif + +#include + +#include + +#ifdef CAN_PROTOTYPE +# include +#else +# include +#endif + + +/* read in our implementation details */ + +#include "dbdimp.h" + +void dbd_init _((dbistate_t *dbistate)); + +int dbd_db_login _((SV *dbh, char *dbname, char *uid, char *pwd)); +int dbd_db_do _((SV *sv, char *statement)); +int dbd_db_commit _((SV *dbh)); +int dbd_db_rollback _((SV *dbh)); +int dbd_db_disconnect _((SV *dbh)); +void dbd_db_destroy _((SV *dbh)); +int dbd_db_STORE _((SV *dbh, SV *keysv, SV *valuesv)); +SV *dbd_db_FETCH _((SV *dbh, SV *keysv)); + + +int dbd_st_prepare _((SV *sth, char *statement, SV *attribs)); +int dbd_st_rows _((SV *sv)); +int dbd_bind_ph _((SV *h, SV *param, SV *value, SV *attribs)); +int dbd_st_execute _((SV *sv)); +AV *dbd_st_fetch _((SV *sv)); +int dbd_st_finish _((SV *sth)); +void dbd_st_destroy _((SV *sth)); +int dbd_st_readblob _((SV *sth, int field, long offset, long len, + SV *destrv, long destoffset)); +int dbd_st_STORE _((SV *dbh, SV *keysv, SV *valuesv)); +SV *dbd_st_FETCH _((SV *dbh, SV *keysv)); + + +/* end of Oracle.h */ diff --git a/Oracle.pm b/Oracle.pm new file mode 100644 index 00000000..5a413cd2 --- /dev/null +++ b/Oracle.pm @@ -0,0 +1,163 @@ +# $Id: Oracle.pm,v 1.23 1996/03/05 02:27:25 timbo Exp $ +# +# Copyright (c) 1994,1995 Tim Bunce +# +# You may distribute under the terms of either the GNU General Public +# License or the Artistic License, as specified in the Perl README file. + +{ + package DBD::Oracle; + + use DBI (); + use DynaLoader (); + @ISA = qw(DynaLoader); + + $VERSION = '0.29'; + my $Revision = substr(q$Revision: 1.23 $, 10); + + require_version DBI 0.68; + + bootstrap DBD::Oracle $VERSION; + + $err = 0; # holds error code for DBI::err + $errstr = ""; # holds error string for DBI::errstr + $drh = undef; # holds driver handle once initialised + + sub driver{ + return $drh if $drh; + my($class, $attr) = @_; + + unless ($ENV{'ORACLE_HOME'}){ + foreach(qw(/usr/oracle /opt/oracle /home/oracle /usr/soft/oracle)){ + $ENV{'ORACLE_HOME'}=$_,last if -d "$_/rdbms/lib"; + } + my $msg = ($ENV{ORACLE_HOME}) ? "set to $ENV{ORACLE_HOME}" : "not set!"; + warn "ORACLE_HOME $msg\n"; + } + + $class .= "::dr"; + + # not a 'my' since we use it above to prevent multiple drivers + + $drh = DBI::_new_drh($class, { + 'Name' => 'Oracle', + 'Version' => $VERSION, + 'Err' => \$DBD::Oracle::err, + 'Errstr' => \$DBD::Oracle::errstr, + 'Attribution' => 'Oracle DBD by Tim Bunce', + }); + + $drh; + } + + 1; +} + + +{ package DBD::Oracle::dr; # ====== DRIVER ====== + use strict; + + sub errstr { + DBD::Oracle::errstr(@_); + } + + sub connect { + my($drh, $dbname, $user, $auth)= @_; + + if ($dbname){ # application is asking for specific database + + if ($dbname =~ /:/){ # Implies an Sql*NET connection + + # We can use the 'user/passwd@machine' form of user: + $user .= '@'.$dbname; + # $TWO_TASK and $ORACLE_SID will be ignored + + } else { + + # Is this a NON-Sql*NET connection (ORACLE_SID)? + # Or is it an alias for an Sql*NET connection (TWO_TASK)? + # Sadly the 'user/passwd@machine' form only works + # for Sql*NET connections. + + # We need a solution to this problem! + # Perhaps we need to read and parse oracle + # alias files like /etc/tnsnames.ora (/etc/sqlnet) + + $ENV{ORACLE_SID} = $dbname; + delete $ENV{TWO_TASK}; + } + } + + # create a 'blank' dbh + + my $this = DBI::_new_dbh($drh, { + 'Name' => $dbname, + 'USER' => $user, 'CURRENT_USER' => $user, + }); + + # Call Oracle OCI orlon func in Oracle.xs file + # and populate internal handle data. + + DBD::Oracle::db::_login($this, $dbname, $user, $auth) + or return undef; + + $this; + } + +} + + +{ package DBD::Oracle::db; # ====== DATABASE ====== + use strict; + + sub errstr { + DBD::Oracle::errstr(@_); + } + + sub prepare { + my($dbh, $statement, @attribs)= @_; + + # create a 'blank' dbh + + my $sth = DBI::_new_sth($dbh, { + 'Statement' => $statement, + }); + + # Call Oracle OCI oparse func in Oracle.xs file. + # (This will actually also call oopen for you.) + # and populate internal handle data. + + DBD::Oracle::st::_prepare($sth, $statement, @attribs) + or return undef; + + $sth; + } + + sub tables { + my($dbh) = @_; # XXX add qualification + my $sth = $dbh->prepare("select + NULL TABLE_CAT, + at.OWNER TABLE_SCHEM, + at.TABLE_NAME, + tc.TABLE_TYPE, + tc.COMMENTS TABLE_REMARKS + from ALL_TABLES at, ALL_TAB_COMMENTS tc + where at.OWNER = tc.OWNER + and at.TABLE_NAME = tc.TABLE_NAME + "); + $sth->execute or return undef; + $sth; + } + +} + + +{ package DBD::Oracle::st; # ====== STATEMENT ====== + use strict; + + sub errstr { + DBD::Oracle::errstr(@_); + } +} + +1; diff --git a/Oracle.xs b/Oracle.xs new file mode 100644 index 00000000..adea7965 --- /dev/null +++ b/Oracle.xs @@ -0,0 +1,315 @@ +/* + $Id: Oracle.xs,v 1.39 1996/03/05 02:04:42 timbo Exp $ + + Copyright (c) 1994,1995 Tim Bunce + + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the Perl README file. + +*/ + +#include "Oracle.h" + + +/* --- Variables --- */ + + +DBISTATE_DECLARE; + + +MODULE = DBD::Oracle PACKAGE = DBD::Oracle + +REQUIRE: 1.929 +PROTOTYPES: DISABLE + +BOOT: + items = 0; /* avoid 'unused variable' warning */ + DBISTATE_INIT; + /* XXX this interface will change: */ + DBI_IMP_SIZE("DBD::Oracle::dr::imp_data_size", sizeof(imp_drh_t)); + DBI_IMP_SIZE("DBD::Oracle::db::imp_data_size", sizeof(imp_dbh_t)); + DBI_IMP_SIZE("DBD::Oracle::st::imp_data_size", sizeof(imp_sth_t)); + dbd_init(DBIS); + + +void +errstr(h) + SV * h + CODE: + /* called from DBI::var TIESCALAR code for $DBI::errstr */ + D_imp_xxh(h); + ST(0) = sv_mortalcopy(DBIc_ERRSTR(imp_xxh)); + + +MODULE = DBD::Oracle PACKAGE = DBD::Oracle::dr + +void +disconnect_all(drh) + SV * drh + CODE: + if (!dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { + D_imp_drh(drh); + sv_setiv(DBIc_ERR(imp_drh), (IV)1); + sv_setpv(DBIc_ERRSTR(imp_drh), + (char*)"disconnect_all not implemented"); + DBIh_EVENT2(drh, ERROR_event, + DBIc_ERR(imp_drh), DBIc_ERRSTR(imp_drh)); + XSRETURN(0); + } + XST_mIV(0, 1); + + + +MODULE = DBD::Oracle PACKAGE = DBD::Oracle::db + +void +_login(dbh, dbname, uid, pwd) + SV * dbh + char * dbname + char * uid + char * pwd + CODE: + ST(0) = dbd_db_login(dbh, dbname, uid, pwd) ? &sv_yes : &sv_no; + + +void +commit(dbh) + SV * dbh + CODE: + ST(0) = dbd_db_commit(dbh) ? &sv_yes : &sv_no; + +void +rollback(dbh) + SV * dbh + CODE: + ST(0) = dbd_db_rollback(dbh) ? &sv_yes : &sv_no; + + +void +STORE(dbh, keysv, valuesv) + SV * dbh + SV * keysv + SV * valuesv + CODE: + ST(0) = &sv_yes; + if (!dbd_db_STORE(dbh, keysv, valuesv)) + if (!DBIS->set_attr(dbh, keysv, valuesv)) + ST(0) = &sv_no; + +void +FETCH(dbh, keysv) + SV * dbh + SV * keysv + CODE: + SV *valuesv = dbd_db_FETCH(dbh, keysv); + if (!valuesv) + valuesv = DBIS->get_attr(dbh, keysv); + ST(0) = valuesv; /* dbd_db_FETCH did sv_2mortal */ + + +void +disconnect(dbh) + SV * dbh + CODE: + D_imp_dbh(dbh); + if ( !DBIc_ACTIVE(imp_dbh) ) { + XSRETURN_YES; + } + /* Check for disconnect() being called whilst refs to cursors */ + /* still exists. This needs some more thought. */ + if (DBIc_ACTIVE_KIDS(imp_dbh) && DBIc_WARN(imp_dbh) && !dirty) { + warn("disconnect(%s) invalidates %d active cursor(s)", + SvPV(dbh,na), (int)DBIc_ACTIVE_KIDS(imp_dbh)); + } + ST(0) = dbd_db_disconnect(dbh) ? &sv_yes : &sv_no; + + +void +DESTROY(dbh) + SV * dbh + PPCODE: + D_imp_dbh(dbh); + ST(0) = &sv_yes; + if (!DBIc_IMPSET(imp_dbh)) { /* was never fully set up */ + if (DBIc_WARN(imp_dbh) && !dirty && dbis->debug >= 2) + warn("Database handle %s DESTROY ignored - never set up", + SvPV(dbh,na)); + } + else { + if (DBIc_ACTIVE(imp_dbh)) { + if (DBIc_WARN(imp_dbh) && !dirty) + warn("Database handle destroyed without explicit disconnect"); + dbd_db_disconnect(dbh); + } + dbd_db_destroy(dbh); + } + + + +MODULE = DBD::Oracle PACKAGE = DBD::Oracle::st + + +void +_prepare(sth, statement, attribs=Nullsv) + SV * sth + char * statement + SV * attribs + CODE: + DBD_ATTRIBS_CHECK("_prepare", sth, attribs); + ST(0) = dbd_st_prepare(sth, statement, attribs) ? &sv_yes : &sv_no; + + +void +rows(sth) + SV * sth + CODE: + XST_mIV(0, dbd_st_rows(sth)); + + +void +bind_param(sth, param, value, attribs=Nullsv) + SV * sth + SV * param + SV * value + SV * attribs + CODE: + DBD_ATTRIBS_CHECK("bind_param", sth, attribs); + ST(0) = dbd_bind_ph(sth, param, value, attribs) ? &sv_yes : &sv_no; + + +void +execute(sth, ...) + SV * sth + CODE: + D_imp_sth(sth); + if (items > 1) { + /* Handle binding supplied values to placeholders */ + int i, error = 0; + SV *idx; + if (items-1 != DBIc_NUM_PARAMS(imp_sth)) { + croak("execute called with %ld bind variables, %d needed", + items-1, DBIc_NUM_PARAMS(imp_sth)); + XSRETURN_UNDEF; + } + idx = sv_2mortal(newSViv(0)); + for(i=1; i < items ; ++i) { + sv_setiv(idx, i); + if (!dbd_bind_ph(sth, idx, ST(i), Nullsv)) + ++error; + } + if (error) { + XSRETURN_UNDEF; /* dbd_bind_ph already registered error */ + } + } + ST(0) = dbd_st_execute(sth) ? &sv_yes : &sv_no; + + +void +fetch(sth) + SV * sth + CODE: + AV *av = dbd_st_fetch(sth); + ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &sv_undef; + + +void +fetchrow(sth) + SV * sth + PPCODE: + D_imp_sth(sth); + AV *av; + if (DBIc_COMPAT(imp_sth) && GIMME == G_SCALAR) { /* XXX Oraperl */ + /* This non-standard behaviour added only to increase the */ + /* performance of the oraperl emulation layer (Oraperl.pm) */ + XSRETURN_IV(DBIc_NUM_FIELDS(imp_sth)); + } + av = dbd_st_fetch(sth); + if (av) { + int num_fields = AvFILL(av)+1; + int i; + EXTEND(sp, num_fields); + for(i=0; i < num_fields; ++i) { + PUSHs(AvARRAY(av)[i]); + } + } + + + +void +blob_read(sth, field, offset, len, destrv=Nullsv, destoffset=0) + SV * sth + int field + long offset + long len + SV * destrv + long destoffset + CODE: + if (!destrv) + destrv = sv_2mortal(newRV(newSV(0))); + if (dbd_st_blob_read(sth, field, offset, len, destrv, destoffset)) + ST(0) = SvRV(destrv); + else ST(0) = &sv_undef; + + +void +STORE(sth, keysv, valuesv) + SV * sth + SV * keysv + SV * valuesv + CODE: + ST(0) = &sv_yes; + if (!dbd_st_STORE(sth, keysv, valuesv)) + if (!DBIS->set_attr(sth, keysv, valuesv)) + ST(0) = &sv_no; + + +void +FETCH(sth, keysv) + SV * sth + SV * keysv + CODE: + SV *valuesv = dbd_st_FETCH(sth, keysv); + if (!valuesv) + valuesv = DBIS->get_attr(sth, keysv); + ST(0) = valuesv; /* dbd_st_FETCH did sv_2mortal */ + + +void +finish(sth) + SV * sth + CODE: + D_imp_sth(sth); + D_imp_dbh_from_sth; + if (!DBIc_ACTIVE(imp_dbh)) { + /* Either an explicit disconnect() or global destruction */ + /* has disconnected us from the database. Finish is meaningless */ + /* XXX warn */ + XSRETURN_YES; + } + if (!DBIc_ACTIVE(imp_sth)) { + /* No active statement to finish */ + XSRETURN_YES; + } + ST(0) = dbd_st_finish(sth) ? &sv_yes : &sv_no; + + +void +DESTROY(sth) + SV * sth + PPCODE: + D_imp_sth(sth); + ST(0) = &sv_yes; + if (!DBIc_IMPSET(imp_sth)) { /* was never fully set up */ + if (DBIc_WARN(imp_sth) && !dirty && dbis->debug >= 2) + warn("Statement handle %s DESTROY ignored - never set up", + SvPV(sth,na)); + } + else { + if (DBIc_ACTIVE(imp_sth)) + dbd_st_finish(sth); + dbd_st_destroy(sth); + } + + + +# end of Oracle.xs diff --git a/Oraperl.pm b/Oraperl.pm new file mode 100644 index 00000000..74545b70 --- /dev/null +++ b/Oraperl.pm @@ -0,0 +1,801 @@ +# Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI +# +# $Id: Oraperl.pm,v 1.23 1995/11/16 23:34:47 timbo Exp $ +# +# Copyright (c) 1994,1995 Tim Bunce +# +# You may distribute under the terms of either the GNU General Public +# License or the Artistic License, as specified in the Perl README file. +# +# To use this interface use one of the following invocations: +# +# use Oraperl; +# or +# eval 'use Oraperl; 1' || die $@ if $] >= 5; +# +# The second form allows oraperl scripts to be used with +# both oraperl and perl 5. + +package Oraperl; + +require DBI; +# use Carp; +require Exporter; + +$VERSION = substr(q$Revision: 1.23 $, 10); + +@ISA = qw(Exporter); + +@EXPORT = qw( + &ora_login &ora_open &ora_bind &ora_fetch &ora_close + &ora_logoff &ora_do &ora_titles &ora_lengths &ora_types + &ora_commit &ora_rollback &ora_autocommit &ora_version + &ora_readblob + $ora_cache $ora_long $ora_trunc $ora_errno $ora_errstr + $ora_verno $ora_debug +); + +$debug = 0 unless defined $debug; +$debugdbi = 0; +# $safe # set true before 'use Oraperl' if needed. + +if ($debugdbi){ + my $sw = DBI->internal; + $sw->debug($debugdbi); + print "Switch: $sw->{Attribution}, $sw->{Version}\n"; + $sw->{DebugDispatch} = $debugdbi; +} + +# Install Driver +$drh = DBI->install_driver('Oracle'); +if ($drh) { + print "DBD::Oracle driver installed as $drh\n" if $debug; + $drh->debug($debug); + $drh->{CompatMode} = 1; + $drh->{Warn} = 0; +} + + +use strict; + +sub _func_ref { + my $name = shift; + my $pkg = ($Oraperl::safe) ? "DBI" : "DBD::Oracle"; + \&{"${pkg}::$name"}; +} + + +# ----------------------------------------------------------------- +# +# $lda = &ora_login($system_id, $name, $password) +# &ora_logoff($lda) + +sub ora_login { + my($system_id, $name, $password) = @_; + $Oraperl::drh->connect($system_id, $name, $password); +} +*ora_logoff = _func_ref('db::disconnect'); + + +# ----------------------------------------------------------------- +# +# $csr = &ora_open($lda, $stmt [, $cache]) +# &ora_bind($csr, $var, ...) +# &ora_fetch($csr [, $trunc]) +# &ora_do($lda, $stmt) +# &ora_close($csr) + +sub ora_open { + my($lda, $stmt, $cache) = @_; + + my $csr = $lda->prepare($stmt) or return undef; + + # only execute here if no bind vars specified + $csr->execute or return undef unless $csr->{NUM_OF_PARAMS}; + + $csr; +} + +*ora_bind = _func_ref('st::execute'); +*ora_fetch = _func_ref('st::fetchrow'); +*ora_close = _func_ref('st::finish'); + +sub ora_do { + # error => undef + # 0 => "OK" (0 but true) + # >0 => >0 + my($lda, $stmt) = @_; + + return $lda->do($stmt); # SEE DEFAULT METHOD IN DBI.pm + + # OLD CODE: + # $csr is local, cursor will be closed on exit + my $csr = $lda->prepare($stmt) or return undef; + # Oracle OCI will automatically execute DDL statements in prepare()! + # We must be carefull not to execute them again! This needs careful + # examination and thought. + # Perhaps oracle is smart enough not to execute them again? + my $ret = $csr->execute; + my $rows = $csr->rows; + ($rows == 0) ? "OK" : $rows; +} + + +# ----------------------------------------------------------------- +# +# &ora_titles($csr [, $truncate]) +# &ora_lengths($csr) +# &ora_types($csr) + +sub ora_titles{ + my($csr, $trunc) = @_; + warn "ora_titles: truncate option not implemented" if $trunc; + @{$csr->{'NAME'}}; +} +sub ora_lengths{ + @{shift->{'ora_lengths'}} # oracle specific +} +sub ora_types{ + @{shift->{'ora_types'}} # oracle specific +} + + +# ----------------------------------------------------------------- +# +# &ora_commit($lda) +# &ora_rollback($lda) +# &ora_autocommit($lda, $on_off) +# &ora_version + +*ora_commit = _func_ref('db::commit'); +*ora_rollback = _func_ref('db::rollback'); + +sub ora_autocommit { + my($lda, $mode) = @_; + $lda->{AutoCommit} = $mode; + "OK"; +} +sub ora_version { + my($sw) = DBI->internal; + print "\n"; + print "Oraperl Emulation Interface version $Oraperl::VERSION\n"; + print "Oracle Driver $Oraperl::drh->{Version}\n"; + print "$sw->{Attribution}, version $sw->{Version}\n\n"; +} + + +# ----------------------------------------------------------------- +# +# $ora_errno +# $ora_errstr + +# This is really internal knowledge but it saves using tie and +# performance for ora_errno is very important. +*Oraperl::ora_errno = \$DBD::Oracle::err; +*Oraperl::ora_errstr = \$DBD::Oracle::errstr; + + +# ----------------------------------------------------------------- +# +# $ora_verno +# $ora_debug not supported, use $h->debug(2) where $h is $lda or $csr +# $ora_cache not supported +# $ora_long used at ora_open() +# $ora_trunc used at ora_open() + +$Oraperl::ora_verno = '3.000'; # to distinguish it from oraperl 2.4 + +$Oraperl::ora_long = 80; # 80, oraperl default +$Oraperl::ora_trunc = 0; # long trunc is error, oraperl default + + +# ----------------------------------------------------------------- +# +# Non-oraperl extensions added here to make it easy to still run +# script using oraperl (by avoiding $csr->readblob(...)) + +*ora_readblob = _func_ref('st::readblob'); + + +1; +__END__ + +=head1 NAME + +Oraperl - Perl access to Oracle databases for old oraperl scripts + +=head1 SYNOPSIS + + $lda = &ora_login($system_id, $name, $password) + $csr = &ora_open($lda, $stmt [, $cache]) + &ora_bind($csr, $var, ...) + &ora_fetch($csr [, $trunc]) + &ora_close($csr) + &ora_logoff($lda) + + &ora_do($lda, $stmt) + + &ora_titles($csr) + &ora_lengths($csr) + &ora_types($csr) + &ora_commit($lda) + &ora_rollback($lda) + &ora_autocommit($lda, $on_off) + &ora_version + + $ora_cache + $ora_long + $ora_trunc + $ora_errno + $ora_errstr + $ora_verno + + $ora_debug + +=head1 DESCRIPTION + +Oraperl is an extension to Perl which allows access to Oracle databases. + +The functions which make up this extension are described in the +following sections. All functions return a false or undefined (in the +Perl sense) value to indicate failure. You do not need to understand +the references to OCI in these descriptions. They are here to help +those who wish to extend the routines or to port them to new machines. + +The text in this document is largely unchanged from the original Perl4 +oraperl manual written by Kevin Stock . Any comments +specific to the DBD::Oracle Oraperl emulation are prefixed by B. + +=head2 Principal Functions + +The main functions for database access are &ora_login(), &ora_open(), +&ora_bind(), &ora_fetch(), &ora_close(), &ora_do() and &ora_logoff(). + +=over 2 + +=item * ora_login + + $lda = &ora_login($system_id, $username, $password) + +In order to access information held within an Oracle database, a +program must first log in to it by calling the &ora_login() function. +This function is called with three parameters, the system ID (see +below) of the Oracle database to be used, and the Oracle username and +password. The value returned is a login identifier (actually an Oracle +Login Data Area) referred to below as $lda. + +Multiple logins may be active simultaneously. This allows a simple +mechanism for correlating or transferring data between databases. + +Most Oracle programs (for example, SQL*Plus or SQL*Forms) examine the +environment variable ORACLE_SID or TWO_TASK to determine which database +to connect to. In an environment which uses several different +databases, it is easy to make a mistake, and attempt to run a program +on the wrong one. Also, it is cumbersome to create a program which +works with more than one database simultaneously. Therefore, Oraperl +requires the system ID to be passed as a parameter. However, if the +system ID parameter is an empty string then oracle will use the +existing value of ORACLE_SID or TWO_TASK in the usual manner. + +Example: + + $lda = &ora_login('personnel', 'scott', 'tiger') || die $ora_errstr; + +This function is equivalent to the OCI olon and orlon functions. +Really, it should have been called &ora_logon(), but I made the mistake +a long time ago and fixing it would break too many existing programs. + +B note that TNS aliases are currently not supported. If 'foo' is +an alias for 'T:host:foo' then you must explicitly use 'T:host:foo' (or +an empty string and rely on ORACLE_SID or TWO_TASK environment variables). + +B Since the returned $lda is a Perl5 reference the database login +identifier is now automatically released if $lda is overwritten or goes +out of scope. + +=item * ora_open + + $csr = &ora_open($lda, $statement [, $cache]) + +To specify an SQL statement to be executed, the program must call the +&ora_open() function. This function takes at least two parameters: a +login identifier (obtained from &ora_login()) and the SQL statement to +be executed. An optional third parameter specifies the size of the row +cache to be used for a SELECT statement. The value returned from +&ora_open() is a statement identifier (actually an ORACLE Cursor) +referred to below as $csr. + +If the row cache size is not specified, a default size is +used. As distributed, the default is five rows, but this +may have been changed at your installation (see the +&ora_version() function and $ora_cache variable below). + +B currently $cache is ignored. That should change soon. + +Examples: + + $csr = &ora_open($lda, 'select ename, sal from emp order by ename', 10); + + $csr = &ora_open($lda, 'insert into dept values(:1, :2, :3)'); + +This function is equivalent to the OCI oopen and oparse functions. For +statements which do not contain substitution variables (see the section +Substitution Variables below), it also uses of the oexec function. For +SELECT statements, it also makes use of the odescr and odefin functions +to allocate memory for the values to be returned from the database. + +=item * ora_bind + + &ora_bind($csr, $var, ...) + +If an SQL statement contains substitution variables (see the section +Substitution Variables below), &ora_bind() is used to assign actual +values to them. This function takes a statement identifier (obtained +from &ora_open()) as its first parameter, followed by as many +parameters as are required by the statement. + +Example: + + &ora_bind($csr, 50, 'management', 'Paris'); + +This function is equivalent to the OCI obndrn and oexec statements. + +The OCI obndrn function does not allow empty strings to be bound. As +distributed, $ora_bind therefore replaces empty strings with a single +space. However, a compilation option allows this substitution to be +suppressed, causing &ora_bind() to fail. The output from the +&ora_version() function specifies which is the case at your installation. + +=item * ora_fetch + + $nfields = &ora_fetch($csr) + + @data = &ora_fetch($csr [, $trunc]) + +The &ora_fetch() function is used in conjunction with a SQL SELECT +statement to retrieve information from a database. This function takes +one mandatory parameter, a statement identifier (obtained from +&ora_open()). + +Used in a scalar context, the function returns the number of fields +returned by the query but no data is actually fetched. This may be +useful in a program which allows a user to enter a statement interactively. + +Example: + + $nfields = &ora_fetch($csr); + +Used in an array context, the value returned is an array +containing the data, one element per field. + +An optional second parameter may be supplied to indicate whether the +truncation of a LONG or LONG RAW field is to be permitted (non-zero) or +considered an error (zero). If this parameter is not specified, the +value of the global variable $ora_trunc is used instead. Truncation of +other datatypes is always considered a error. + +B The optional second parameter to ora_fetch is not supported. +A DBI usage error will be generated if a second parameter is supplied. +Use the global variable $ora_trunc instead. Also note that the +experimental DBI readblob method can be used to retrieve a long: + + $csr->readblob($field, $offset, $len [, \$dest, $destoffset]); + +If truncation occurs, $ora_errno will be set to 1406. &ora_fetch() +will complete successfully if truncation is permitted, otherwise it +will fail. + +&ora_fetch() will fail at the end of the data or if an error occurs. It +is possible to distinguish between these cases by testing the value of +the variable $ora_errno. This will be zero for end of data, non-zero if +an error has occurred. + +Example: + + while (($deptno, $dname, $loc) = &ora_fetch($csr)) + { + warn "Truncated!!!" if $ora_errno == 1406; + # do something with the data + } + warn $ora_errstr if $ora_errno; + +This function is equivalent to the OCI ofetch function. + +=item * ora_close + + &ora_close($csr) + +If an SQL statement is no longer required (for example, all the data +selected has been processed, or no more rows are to be inserted) then +the statement identifier should be released. This is done by calling +the &ora_close() function with the statement identifier as its only +parameter. + +This function is equivalent to the OCI oclose function. + +B Since $csr is a Perl5 reference the statement/cursor is now +automatically closed if $csr is overwritten or goes out of scope. + + +=item * ora_do + + &ora_do($lda, $statement) + +Not all SQL statements return data or contain substitution +variables. In these cases the &ora_do() function may be +used as an alternative to &ora_open() and &ora_close(). +This function takes two parameters, a login identifier and +the statement to be executed. + +Example: + + &ora_do($lda, 'drop table employee'); + +This function is roughly equivalent to + + &ora_close( &ora_open($lda, $statement) ) + + +=item * ora_logoff + + &ora_logoff($lda) + +When the program no longer needs to access a given database, the login +identifier should be released using the &ora_logoff() function. + +This function is equivalent to the OCI ologoff function. + +B Since $lda is a Perl5 reference the database login identifier +is now automatically released if $lda is overwritten or goes out of scope. + +=back + +=head2 Ancillary Functions + +Additional functions available are: &ora_titles(), +&ora_lengths(), &ora_types(), &ora_autocommit(), +&ora_commit(), &ora_rollback() and &ora_version(). + +The first three are of most use within a program which +allows statements to be entered interactively. See, for +example, the sample program sql which is supplied with +Oraperl and may have been installed at your site. + +=over 2 + +=item * ora_titles + + @titles = &ora_titles($csr) + +A program may determine the field titles of an executed +query by calling &ora_titles(). This function takes a +single parameter, a statement identifier (obtained from +&ora_open()) indicating the query for which the titles are +required. The titles are returned as an array of strings, +one for each column. + +Titles are truncated to the length of the field, as reported +by the &ora_lengths() function. + +B oraperl v2.2 actually changed the behaviour such that the +titles were not truncated unless an optional second parameter was +true. This was not reflected in the oraperl manual. The Oraperl +emulation adopts the non truncating behaviour and doesn't support the +truncate parameter. + + +=item * ora_lengths + + @lengths = &ora_lengths($csr) + +A program may determine the length of each of the fields +returned by a query by calling the &ora_lengths() function. +This function takes a single parameter, a statement +identifier (obtained from &ora_open()) indicating the query +for which the lengths are required. The lengths are +returned as an array of integers, one for each column. + + +=item * ora_types + + @types = &ora_types($csr) + +A program may determine the type of each of the fields returned by a +query by calling the &ora_types() function. This function takes a +single parameter, a statement identifier (obtained from &ora_open()) +indicating the query for which the lengths are required. The types are +returned as an array of integers, one for each field. + +These types are defined in your OCI documentation. The correct +interpretation for Oracle v6 is given in the file oraperl.ph. + + +=item * ora_autocommit + + &ora_autocommit($lda, $on_or_off) + +Autocommit mode (in which each transaction is committed immediately, +without waiting for an explicit commit) may be enabled or disabled +using &ora_autocommit(). This function takes two parameters, a login +identifier (obtained from &ora_login()) and a true/false value +indicating whether autocommit is to be enabled (non-zero) or disabled +(zero). By default, autocommit is off. + +Note that autocommit can only be set per login, not per statement. If +you need to control autocommit by statement (for example, to allow +deletions to be rolled back, but insertions to be committed +immediately) you should make multiple calls to &ora_login() and use a +separate login identifier for each statement. + + +=item * ora_commit, ora_rollback + + &ora_commit($lda) + &ora_rollback($lda) + +Modifications to a database may be committed or rolled back using the +&ora_commit() and &ora_rollback() functions. These functions take a +single parameter, a login identifier obtained from &ora_login(). + +Transactions which have been committed (either explicitly by a call to +&ora_commit() or implicitly through the use of &ora_autocommit()) +cannot be subsequently rolled back. + +Note that commit and rollback can only be used per login, not per +statement. If you need to commit or rollback by statement you should +make multiple calls to &ora_login() and use a separate login identifier +for each statement. + + +=item * ora_version + + &ora_version() + +The &ora_version() function prints the version number and +copyright information concerning Oraperl. It also prints +the values of various compilation time options. It does not +return any value, and should not normally be used in a +program. + +Example: + + oraperl -e '&ora_version' + + This is Oraperl, version 2, patch level 0. + + Debugging is available, including the -D flag. + Default fetch row cache size is 5. + Empty bind values are replaced by a space. + + Perl is copyright by Larry Wall; type oraperl -v for details. + Additions for oraperl: Copyright 1991, 1992, Kevin Stock. + + Oraperl may be distributed under the same conditions as Perl. + +This function is the equivalent of Perl's C<-v> flag. + +B The Oraperl emulation printout is similar but not identical. + +=back + +=head1 VARIABLES + +Six special variables are provided, $ora_cache, $ora_long, +$ora_trunc, $ora_errno, $ora_errstr and $ora_verno. + +=head2 Customisation Variables + +These variables are used to dictate the behaviour of Oraperl +under certain conditions. + +=over 2 + +=item * $ora_cache + +The $ora_cache variable determines the default cache size used by the +&ora_open() function for SELECT statements if an explicit cache size is +not given. + +It is initialised to the default value reported by &ora_version() but +may be set within a program to apply to all subsequent calls to +&ora_open(). Cursors which are already open are not affected. As +distributed, the default value is five, but may have been altered at +your installation. + +As a special case, assigning zero to $ora_cache resets it to the +default value. Attempting to set $ora_cache to a negative value results +in a warning. + +B Not yet supported. + + +=item * $ora_long + +Normally, Oraperl interrogates the database to determine the length of +each field and allocates buffer space accordingly. This is not +possible for fields of type LONG or LONGRAW. To allocate space +according to the maximum possible length (65535 bytes) would obviously +be extremely wasteful of memory. + +Therefore, when &ora_open() determines that a field is a LONG type, it +allocates the amount of space indicated by the $ora_long variable. This +is initially set to 80 (for compatibility with Oracle products) but may +be set within a program to whatever size is required. + + +=item * $ora_trunc + +Since Oraperl cannot determine exactly the maximum length of a LONG +field, it is possible that the length indicated by $ora_long is not +sufficient to store the data fetched. In such a case, the optional +second parameter to &ora_fetch() indicates whether the truncation +should be allowed or should provoke an error. + +If this second parameter is not specified, the value of $ora_trunc is +used as a default. This only applies to LONG and LONGRAW data types. +Truncation of a field of any other type is always considered an error +(principally because it indicates a bug in Oraperl). + +=back + +=head2 Status Variables + +These variables report information about error conditions or about +Oraperl itself. They may only be read; a fatal error occurs if a +program attempts to change them. + +=over 2 + +=item * $ora_errno + +$ora_errno contains the Oracle error code provoked by the last function +call. + +There are two cases of particular interest concerning &ora_fetch(). If +a LONG or LONGRAW field is truncated (and truncation is allowed) then +&ora_fetch() will complete successfully but $ora_errno will be set to +1406 to indicate the truncation. When &ora_fetch() fails, $ora_errno +will be set to zero if this was due to the end of data or an error code +if it was due to an actual error. + + +=item * $ora_errstr + +The $ora_errstr variable contains the Oracle error message +corresponding to the current value of $ora_errno. + + +=item * $ora_verno + +The $ora_verno variable contains the version number of Oraperl in the +form v.ppp where v is the major version number and ppp is the +patchlevel. For example, in Oraperl version 3, patch level 142, +$ora_verno would contain the value 3.142 (more or less, allowing for +floating point error). + +=back + + +=head1 SUBSTITUTION VARIABLES + +Oraperl allows an SQL statement to contain substitution variables. +These consist of a colon followed by a number. For example, a program +which added records to a telephone list might use the following call to +&ora_open(): + + $csr = &ora_open($csr, "insert into telno values(:1, :2)"); + +The two names :1 and :2 are called substitution variables. The +function &ora_bind() is used to assign values to these variables. For +example, the following statements would add two new people to the +list: + + &ora_bind($csr, "Annette", "472-8836"); + &ora_bind($csr, "Brian", "937-1823"); + +Note that the substitution variables must be assigned consecutively +beginning from 1 for each SQL statement, as &ora_bind() assigns its +parameters in this order. Named substitution variables (for example, +:NAME, :TELNO) are not permitted. + +=head1 DEBUGGING + +B The Oraperl $ora_debug variable is not supported. However +detailed debugging can be enabled at any time by executing + + $h->debug(2); + +where $h is either a $lda or a $csr. If debugging is enabled on an +$lda then it is automatically passed on to any cursors returned by +&ora_open(). + +=head1 EXAMPLE + + format STDOUT_TOP = + Name Phone + ==== ===== + . + + format STDOUT = + @<<<<<<<<<< @>>>>>>>>>> + $name, $phone + . + + die "You should use oraperl, not perl\n" unless defined &ora_login; + $ora_debug = shift if $ARGV[0] =~ /^\-#/; + + $lda = &ora_login('t', 'kstock', 'kstock') + || die $ora_errstr; + $csr = &ora_open($lda, 'select * from telno order by name') + || die $ora_errstr; + + $nfields = &ora_fetch($csr); + print "Query will return $nfields fields\n\n"; + + while (($name, $phone) = &ora_fetch($csr)) { write; } + warn $ora_errstr if $ora_errno; + + die "fetch error: $ora_errstr" if $ora_errno; + + do ora_close($csr) || die "can't close cursor"; + do ora_logoff($lda) || die "can't log off Oracle"; + + +=head1 NOTES + +In keeping with the philosophy of Perl, there is no pre-defined limit +to the number of simultaneous logins or SQL statements which may be +active, nor to the number of data fields which may be returned by a +query. The only limits are those imposed by the amount of memory +available, or by Oracle. + + +=head1 WARNINGS + +The Oraperl emulation software shares no code with the original +oraperl. It is built on top of the new Perl5 DBI and DBD::Oracle +modules. These modules are still evolving. (One of the goals of +the Oraperl emulation software is to allow useful work to be done +with the DBI and DBD::Oracle modules whilst insulating users from +the ongoing changes in their interfaces.) + +It is quite possible, indeed probable, that some differences in +behaviour will exist. This should be confined to error handling. + +B differences in behaviour which are not documented here should be +reported to Tim.Bunce@ig.co.uk and CC'd to perldb-interest@fugue.com. + + +=head1 SEE ALSO + +=over 2 + +=item Oracle Documentation + +SQL Language Reference Manual. +Programmer's Guide to the Oracle Call Interfaces. + +=item Books + +Programming Perl by Larry Wall and Randal Schwartz. +Learning Perl by Randal Schwartz. + +=item Manual Pages + +perl(1) + +=back + +=head1 AUTHORS + +Perl by Larry Wall . + +ORACLE by Oracle Corporation, California. + +Original Oraperl 2.4 code and documentation +by Kevin Stock . + +DBI and Oraperl emulation using DBD::Oracle +by + +=cut diff --git a/README b/README new file mode 100644 index 00000000..6da696e7 --- /dev/null +++ b/README @@ -0,0 +1,277 @@ +DBD::Oracle -- an Oracle 7 interface for Perl 5. + + Copyright (c) 1994,1995,1996 Tim Bunce + + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the Perl README file. + + WARNING: THIS IS ALPHA SOFTWARE. + IT IS INCOMPLETE! + IT IS POSSIBLY UNRELIABLE! + +The only currently supported interface is via Oraperl.pm, the oraperl +emulation layer. This is fairly complete. Execute "perldoc Oraperl" for info. + + +BEFORE BUILDING, TESTING AND INSTALLING this you will need to: + + Build, test and install Perl 5 (at least 5.002beta2). + It is very important to test it and install it! + + Build, test and install the DBI module (at least DBI 0.68). + It is very important to test it and install it! + + Remember to *read* the DBI README file! + + +BUILDING + + perl Makefile.PL + make + make test + make test TEST_VERBOSE=1 (if any of the t/* tests fail) + + make install (if the tests look okay) + +Do NOT hand edit the generated Makefile unless you are completely sure +you understand the implications! Always try to make changes via the +Makefile.PL command line and/or editing the Makefile.PL. + +You should never need to make any changes. If you do *please* let me +know so that I can try to make it automatic in a later release. + + +IF YOU HAVE PROBLEMS: + +Please don't post problems to comp.lang.perl.misc or perl5-porters. +This software is supported via the dbi-users mailing list. For more +information and to keep informed about progress you can join the a +mailing list via http://www.fugue.com/dbi (if you are unable to use the +web you can subscribe by sending a message to dbi-request@fugue.com, it +may take a few days to be processed). + +Please post details of any problems (or changes you needed to make) to +dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. + +Please include: + +1. A complete log of a all steps of the build, e.g.: + + perl Makefile.PL (do a make realclean first) + make + make test + make test TEST_VERBOSE=1 (if any tests fail) + +2. Full details of which version of Oracle and Perl you're using. + +3. The output of perl -V + +4. If you get a core dump, try to include a stack trace from it. + If the stack trace mentions XS_DynaLoader_dl_load_file then rerun + make test after setting the environment variable PERL_DL_DEBUG to 2. + + +Regards, +Tim. + +=============================================================================== +Some Users of DBD::Oracle on Specific Platforms: +(this is out of date now, there are many users on many platforms) + +Solaris 1: + Myself. + John D Groenveld + Christian Murphy + +Solaris 2: + Myself. + David Moellenhoff + James Taylor + Jay Krish + John D Groenveld + Joe Hildebrand + John Liptak + Philip Kizer + Alan Johnson + Jim Fox + +HP-UX 9: + Terry Greenlaw + Les Troyer + Norbert Kiesel + Greg Anderson + Johann Griessler + Dave Venus + +Unisys U6000/300: + Alan Burlison + +SCO 3: + Joel Rosi-Schwartz + Greg Gerber + +Sequent DYNIX/ptx 2: + Alligator Descartes + Jonathan Lemon + +NT: + Jim Fox + +Motorola M88100 (SVR3.2): + Christian Murphy + +DEC UNIX 3.2: + David J. DeWolfe + + +DEC Alpha, OSF/1 v2: + Royal Hansen + Jonathan Olson + Greg Gerber + Davide Migliavacca + +SGI Iris Indigo R4000 Irix 5.3: + Andrew G Wood + +AIX 3.2 + Davide Migliavacca + Joerg Senekowitsch + + +=============================================================================== +Platform or Oracle Version specific notes: + +------------------------------------------------------------------------------- +HP-UX: Terry Greenlaw + +I traced a problem with "ld: Invalid loader fixup needed" to the file +libocic.a. On HP-UX it contains position-dependant code and cannot be +used to generate dynamic load libraries. The only shared library that +Oracle ships under HP-UX is liboracle.sl which replaces libxa.a, +libsql.a, libora.a, libcvg.a, and libnlsrtl.a. The OCI stuff still +appears to only link statically under HU-UX. + +You'll need to build DBD::Oracle statically linked into the perl binary. +See the static linking notes below. + +------------------------------------------------------------------------------- +For platforms which require static linking. + +If you get an error like: + +/usr/lib/dld.sl: Bad magic number for shared library: +/usr/local/lib/perl5/hpux/auto/DBD/Oracle/Oracle.a + +You'll need to build DBD::Oracle statically linked and then link it +into a perl binary: + + perl Makefile.PL LINKTYPE=static + make + make perl (makes a perl binary in current directory) + make test FULLPERL=./perl (run tests using the new perl binary) + make install + +You will probably need to have already built and installed a static +version of the DBI in order that it be automatically included when +you do the 'make perl' above. + +------------------------------------------------------------------------------- +Oracle 7.1.3: Syntax error in oratypes.h + +Try uncommenting the '#define signed' line in Oracle.h + +------------------------------------------------------------------------------- +Oracle 7.1.3/4: Connection takes a long time and may coredump + +Oracle bug number: 227321 related to changing the environment before +connecting to oracle. + +To work around this bug, do not set any environment variables in your +oraperl script before you call ora_login, and when you do call +ora_login, the first argument must be the empty string. This means +that you have to be sure that your environment variables ORACLE_SID +and ORACLE_HOME are set properly before you execute any oraperl +script. It is probably also possible to pass the SID to ora_login as +part of the username (for example, ora_login("", "SCOTT/TIGER@PROD", +"")), although I have not tested this. +This workaround is based on information from Kevin Stock. + +------------------------------------------------------------------------------- +Oracle 7.1.4/5: ORA-01002: fetch out of sequence +Edited from Message-ID: <3qaui9$ae@usenet.rpi.edu> and +<3qb5dp$2nc@usenet.rpi.edu> in comp.databases.oracle +From: finkej@ts.its.rpi.edu (Jon Finke) + +I am in the process of converting a locally developed that sits on top +of the OCI routines from version 6 to version 7. Unfortunately, I have +run into a snag that I have been unable to get around. Every test run +results in getting an "ORA-01002: fetch out of sequence" error. + +The manual claims that this is the result of calling "ofetch" before +oparse/oexec, or running out of things to fetch. Yet, I am calling +oopen, oparse, oexec, (odesc, odefin) all without error. As a control +case, I also built the cdemo2 program, and it appears to be calling +the same routines, yet it is successful. + +Note: In the "broken" program, I am currently calling odsc in a loop + for each column in the query, and then calling odefin, while in the + "working" program, I call odescr/odefin, odesc/odefin for each column. + In both cases, the calls to odefin seem reasonable. + +Both programs are attempting the query "select user,uid from dual". + +This is a known problem in version 7.1.4, and it will be fixed in 7.1.6. +The bug report is #239128. +-- +Jon Finke finkej@rpi.edu +Senior Network Systems Engineer http://www.rpi.edu/~finkej +Information Technology Services 518 276 8185 (voice) | 518 276 2809 (fax) +Rensselaer Polytechnic Institute 110 8th Street, Troy NY, 12180 + +------------------------------------------------------------------------------- +ORA-00604: error occurred at recursive SQL level (DBD: login failed) + +This can happen if TWO_TASK is defined but you connect using ORACLE_SID. + +------------------------------------------------------------------------------- +Environment: SunOS 4.1.3, Oracle 7.1.6 Steve Livingston + +If you get link errors like: ld: Undefined symbols _environ _dlopen _dlclose ... +and the link command line includes '-L/usr/5lib -lc' then comment out the +'CLIBS= $(OTHERLIBS) -L/usr/5lib -lc' line in the Makefile. + +------------------------------------------------------------------------------- +Environment: Solaris, GCC, Sanford Dickert + +Error: gcc: unrecognized option `-Y' +Fix: Edit the Makefile to remove the space from '-Y P'. + +------------------------------------------------------------------------------- +Environment: SunOS 4.1.3, Oracle 7.1.3 John Carlson + +Problem: oraperl and DBD::Oracle fail to link. Some messing around with +the library order makes the link succeed. Now I get a "Bad free()" when +ora_logoff is called. + +Solution: +In my case, this was caused by a faulty oracle install. The install grabbed +the wrong version of mergelib (The X11R6 one) instead of the one in +$ORACLE_HOME/bin. Try a more limited path and reinstall Oracle again. + +------------------------------------------------------------------------------- +Environment: DEC Alpha, OSF, Jonathan Olson + +Problem: ERROR EVENT: DBI::dr=HASH(0x14011fee8)->DBI::default_handler: + 0 ORA-00000: normal, successful completion (DBD: login failed) + +Solution: Add '#define A_OSF' to Oracle.h above '#include ' and +complain to Oracle about bugs in their header files on 64 bit systems. + +Problem: Unable to connect + +Solution: Try using something like this: "scott/tiger@t:HOST_IP:INSTANCE" +and not just "scott/tiger". + +=============================================================================== + +End. diff --git a/Todo b/Todo new file mode 100644 index 00000000..1727a037 --- /dev/null +++ b/Todo @@ -0,0 +1,13 @@ +=============================================================================== +General Outstanding Issues + +Return codes and error handling not quite same as oraperl? + +Many others. Remember, this is still alpha software! + + +=============================================================================== +Below is just a personal dumping ground for thoughts and issues, don't +expect any structure: + +(or even anything at all) diff --git a/dbdimp.c b/dbdimp.c new file mode 100644 index 00000000..26614626 --- /dev/null +++ b/dbdimp.c @@ -0,0 +1,915 @@ +/* + $Id: dbdimp.c,v 1.14 1996/03/05 02:27:25 timbo Exp $ + + Copyright (c) 1994,1995 Tim Bunce + + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the Perl README file. + +*/ + +#include "Oracle.h" + + +DBISTATE_DECLARE; + +static SV *ora_long; +static SV *ora_trunc; + + +void +dbd_init(dbistate) + dbistate_t *dbistate; +{ + DBIS = dbistate; + ora_long = perl_get_sv("Oraperl::ora_long", GV_ADDMULTI); + ora_trunc = perl_get_sv("Oraperl::ora_trunc", GV_ADDMULTI); +} + + +/* Database specific error handling. + This will be split up into specific routines + for dbh and sth level. + Also split into helper routine to set number & string. + Err, many changes needed, ramble ... +*/ + +void +ora_error(h, lda, rc, what) + SV *h; + Lda_Def *lda; + sb2 rc; + char *what; +{ + D_imp_xxh(h); + SV *errstr = DBIc_ERRSTR(imp_xxh); + if (lda) { /* is oracle error (allow for non-oracle errors) */ + int len; + char msg[1024]; + /* Oracle oerhms can do duplicate free if connect fails */ + /* Ignore 'with different width due to prototype' gcc warning */ + oerhms(lda, rc, (text*)msg, sizeof(msg)); + len = strlen(msg); + if (len && msg[len-1] == '\n') + msg[len-1] = '\0'; /* trim off \n from end of message */ + sv_setpv(errstr, (char*)msg); + } + else sv_setpv(errstr, what); + sv_setiv(DBIc_ERR(imp_xxh), (IV)rc); + if (what && lda) { + sv_catpv(errstr, " (DBD: "); + sv_catpv(errstr, what); + sv_catpv(errstr, ")"); + } + DBIh_EVENT2(h, ERROR_event, DBIc_ERR(imp_xxh), errstr); + if (dbis->debug >= 2) + fprintf(DBILOGFP, "%s error %d recorded: %s\n", + what, rc, SvPV(errstr,na)); +} + + +void +fbh_dump(fbh, i) + imp_fbh_t *fbh; + int i; +{ + FILE *fp = DBILOGFP; + fprintf(fp, "fbh %d: '%s' %s, ", + i, fbh->cbuf, (fbh->nullok) ? "NULLable" : ""); + fprintf(fp, "type %d, dbsize %ld, dsize %ld, p%d s%d\n", + fbh->dbtype, (long)fbh->dbsize, (long)fbh->dsize, + fbh->prec, fbh->scale); + fprintf(fp, " out: ftype %d, indp %d, bufl %d, rlen %d, rcode %d\n", + fbh->ftype, fbh->indp, fbh->bufl, fbh->rlen, fbh->rcode); +} + + +static int +dbtype_is_long(dbtype) + int dbtype; +{ + /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW type? */ + /* Return preferred type code to use if it's a long, else 0. */ + if (dbtype == 8 || dbtype == 24) /* LONG or LONG RAW */ + return dbtype; /* --> same */ + if (dbtype == 94) /* LONG VARCHAR */ + return 8; /* --> LONG */ + if (dbtype == 95) /* LONG VARRAW */ + return 24; /* --> LONG RAW */ + return 0; +} + +static int +dbtype_is_string(dbtype) /* 'can we use SvPV to pass buffer?' */ + int dbtype; +{ + switch(dbtype) { + case 1: /* VARCHAR2 */ + case 5: /* STRING */ + case 8: /* LONG */ + case 23: /* RAW */ + case 24: /* LONG RAW */ + case 96: /* CHAR */ + case 97: /* CHARZ */ + case 106: /* MLSLABEL */ + return 1; + } + return 0; +} + + +/* ================================================================== */ + + +static void +dump_error_status(cda) + struct cda_def *cda; +{ + fprintf(DBILOGFP, + "(rc %ld, v2 %ld, ft %ld, rpc %ld, peo %ld, fc %ld, ose %ld)\n", + (long)cda->rc, (long)cda->v2_rc, (long)cda->ft, (long)cda->rpc, + (long)cda->peo, (long)cda->fc, (long)cda->ose + ); +} + + +/* ================================================================== */ + +int +dbd_db_login(dbh, dbname, uid, pwd) + SV *dbh; + char *dbname; + char *uid; + char *pwd; +{ + D_imp_dbh(dbh); + int ret; + + /* can give duplicate free errors (from Oracle) if connect fails */ + ret = orlon(&imp_dbh->lda, imp_dbh->hda, (text*)uid,-1, (text*)pwd,-1,0); + if (ret) { + ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "login failed"); + return 0; + } + DBIc_IMPSET_on(imp_dbh); /* imp_dbh set up now */ + DBIc_ACTIVE_on(imp_dbh); /* call disconnect before freeing */ + return 1; +} + + +int +dbd_db_commit(dbh) + SV *dbh; +{ + D_imp_dbh(dbh); + if (ocom(&imp_dbh->lda)) { + ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "commit failed"); + return 0; + } + return 1; +} + +int +dbd_db_rollback(dbh) + SV *dbh; +{ + D_imp_dbh(dbh); + if (orol(&imp_dbh->lda)) { + ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "rollback failed"); + return 0; + } + return 1; +} + + +int +dbd_db_disconnect(dbh) + SV *dbh; +{ + D_imp_dbh(dbh); + /* We assume that disconnect will always work */ + /* since most errors imply already disconnected. */ + DBIc_ACTIVE_off(imp_dbh); + if (ologof(&imp_dbh->lda)) { + ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "disconnect error"); + return 0; + } + /* We don't free imp_dbh since a reference still exists */ + /* The DESTROY method is the only one to 'free' memory. */ + /* Note that statement objects may still exists for this dbh! */ + return 1; +} + + +void +dbd_db_destroy(dbh) + SV *dbh; +{ + D_imp_dbh(dbh); + if (DBIc_ACTIVE(imp_dbh)) + dbd_db_disconnect(dbh); + /* Nothing in imp_dbh to be freed */ + DBIc_IMPSET_off(imp_dbh); +} + + +int +dbd_db_STORE(dbh, keysv, valuesv) + SV *dbh; + SV *keysv; + SV *valuesv; +{ + D_imp_dbh(dbh); + STRLEN kl; + char *key = SvPV(keysv,kl); + SV *cachesv = NULL; + int on = SvTRUE(valuesv); + + if (kl==10 && strEQ(key, "AutoCommit")) { + /* Ignore SvTRUE warning: '=' where '==' may have been intended. */ + if ( (on) ? ocon(&imp_dbh->lda) : ocof(&imp_dbh->lda) ) { + ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "ocon/ocof failed"); + /* XXX um, we can't return FALSE and true isn't acurate */ + /* the best we can do is cache an undef */ + cachesv = &sv_undef; + } else { + cachesv = (on) ? &sv_yes : &sv_no; /* cache new state */ + } + } else { + return FALSE; + } + if (cachesv) /* cache value for later DBI 'quick' fetch? */ + hv_store((HV*)SvRV(dbh), key, kl, cachesv, 0); + return TRUE; +} + + +SV * +dbd_db_FETCH(dbh, keysv) + SV *dbh; + SV *keysv; +{ + /* D_imp_dbh(dbh); */ + STRLEN kl; + char *key = SvPV(keysv,kl); + SV *retsv = NULL; + /* Default to caching results for DBI dispatch quick_FETCH */ + int cacheit = TRUE; + + if (1) { /* no attribs defined yet */ + return Nullsv; + } + if (cacheit) { /* cache for next time (via DBI quick_FETCH) */ + hv_store((HV*)SvRV(dbh), key, kl, retsv, 0); + (void)SvREFCNT_inc(retsv); /* so sv_2mortal won't free it */ + } + return sv_2mortal(retsv); +} + + + +/* ================================================================== */ + + +int +dbd_st_prepare(sth, statement, attribs) + SV *sth; + char *statement; + SV *attribs; +{ + D_imp_sth(sth); + D_imp_dbh_from_sth; + sword oparse_defer = 0; /* PARSE_NO_DEFER */ + ub4 oparse_lng = 1; /* auto v6 or v7 as suits db connected to */ + + imp_sth->done_desc = 0; + imp_sth->cda = &imp_sth->cdabuf; + + if (attribs) { + SV **svp; + DBD_ATTRIB_GET_IV( attribs, "ora_parse_lang", 14, svp, oparse_lng); + DBD_ATTRIB_GET_BOOL(attribs, "ora_parse_defer",15, svp, oparse_defer); + } + + if (oopen(imp_sth->cda, &imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oopen error"); + return 0; + } + + /* scan statement for '?', ':1' and/or ':foo' style placeholders */ + dbd_preparse(imp_sth, statement); + + /* parse the (possibly edited) SQL statement */ + /* Note that (if oparse_defer=0, the default) Data Definition */ + /* statements will be executed at once. This is a major pain! */ + imp_sth->cda->peo = 0; + if (oparse(imp_sth->cda, (text*)imp_sth->statement, (sb4)-1, + (sword)oparse_defer, (ub4)oparse_lng)) { + SV *msgsv; + char msg[99]; + sprintf(msg,"possibly parse error at character %d of %d in '", + imp_sth->cda->peo+1, (int)strlen(imp_sth->statement)); + msgsv = sv_2mortal(newSVpv(msg,0)); + sv_catpv(msgsv, imp_sth->statement); + sv_catpv(msgsv, "'"); + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, SvPV(msgsv,na)); + oclose(imp_sth->cda); /* close the cursor */ + return 0; + } + + /* long_buflen: length for long/longraw (if >0) */ + /* long_trunc_ok: is truncating a long an error XXX not implemented */ + + if (DBIc_COMPAT(imp_sth)) { /* is an Oraperl handle */ + imp_sth->long_buflen = SvIV(ora_long); + /* ora_trunc is checked at fetch time */ + } else { + imp_sth->long_buflen = 80; /* typical oracle default */ + imp_sth->long_trunc_ok = 1; /* can use blob_read() */ + } + + /* Describe and allocate storage for results. This could */ + /* and possibly should be deferred until execution or some */ + /* output related information is fetched. */ +/* defered + if (!dbd_describe(dbh, imp_sth)) { + return 0; + } +*/ + DBIc_IMPSET_on(imp_sth); + return 1; +} + + +void +dbd_preparse(imp_sth, statement) + imp_sth_t *imp_sth; + char *statement; +{ + bool in_literal = FALSE; + char *src, *start, *dest; + phs_t phs_tpl; + SV *phs_sv; + int idx=0, style=0, laststyle=0; + + /* allocate room for copy of statement with spare capacity */ + /* for editing ':1' into ':p1' so we can use obndrv. */ + imp_sth->statement = (char*)safemalloc(strlen(statement) + 100); + + /* initialise phs ready to be cloned per placeholder */ + memset(&phs_tpl, sizeof(phs_tpl), 0); + phs_tpl.ftype = 1; /* VARCHAR2 */ + + src = statement; + dest = imp_sth->statement; + while(*src) { + if (*src == '\'') + in_literal = ~in_literal; + if ((*src != ':' && *src != '?') || in_literal) { + *dest++ = *src++; + continue; + } + start = dest; /* save name inc colon */ + *dest++ = *src++; + if (*start == '?') { /* X/Open standard */ + sprintf(start,":p%d", ++idx); /* '?' -> ':p1' (etc) */ + dest = start+strlen(start); + style = 3; + + } else if (isDIGIT(*src)) { /* ':1' */ + idx = atoi(src); + *dest++ = 'p'; /* ':1'->':p1' */ + if (idx <= 0) + croak("Placeholder :%d must be a positive number", idx); + while(isDIGIT(*src)) + *dest++ = *src++; + style = 1; + + } else if (isALNUM(*src)) { /* ':foo' */ + while(isALNUM(*src)) /* includes '_' */ + *dest++ = *src++; + style = 2; + } else { /* perhaps ':=' PL/SQL construct */ + continue; + } + *dest = '\0'; /* handy for debugging */ + if (laststyle && style != laststyle) + croak("Can't mix placeholder styles (%d/%d)",style,laststyle); + laststyle = style; + if (imp_sth->bind_names == NULL) + imp_sth->bind_names = newHV(); + phs_tpl.sv = &sv_undef; + phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)); + hv_store(imp_sth->bind_names, start, (STRLEN)(dest-start), + phs_sv, 0); + /* warn("bind_names: '%s'\n", start); */ + } + *dest = '\0'; + if (imp_sth->bind_names) { + DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->bind_names); + if (dbis->debug >= 2) + fprintf(DBILOGFP, "scanned %d distinct placeholders\n", + (int)DBIc_NUM_PARAMS(imp_sth)); + } +} + + +int +dbd_bind_ph(sth, ph_namesv, newvalue, attribs) + SV *sth; + SV *ph_namesv; + SV *newvalue; + SV *attribs; +{ + D_imp_sth(sth); + SV **svp; + STRLEN name_len; + char *name; + phs_t *phs; + + STRLEN value_len; + void *value_ptr; + + if (SvNIOK(ph_namesv) ) { /* passed as a number */ + char buf[90]; + name = buf; + sprintf(name, ":p%d", (int)SvIV(ph_namesv)); + name_len = strlen(name); + } else { + name = SvPV(ph_namesv, name_len); + } + + if (dbis->debug >= 2) + fprintf(DBILOGFP, "bind %s <== '%s' (attribs: %s)\n", + name, SvPV(newvalue,na), attribs ? SvPV(attribs,na) : "" ); + + svp = hv_fetch(imp_sth->bind_names, name, name_len, 0); + if (svp == NULL) + croak("dbd_bind_ph placeholder '%s' unknown", name); + phs = (phs_t*)((void*)SvPVX(*svp)); /* placeholder struct */ + + if (phs->sv == &sv_undef) { /* first bind for this placeholder */ + phs->sv = newSV(0); + phs->ftype = 1; + } + + if (attribs) { + /* Setup / Clear attributes as defined by attribs. */ + /* If attribs is EMPTY then reset attribs to default. */ + ; /* XXX */ + if ( (svp=hv_fetch((HV*)SvRV(attribs), "ora_type",0, 0)) == NULL) { + if (!dbtype_is_string(SvIV(*svp))) /* mean but safe */ + croak("bind_param %s ora_type %d not a simple string type", + name, (int)SvIV(*svp)); + phs->ftype = SvIV(*svp); + } + + } /* else if NULL / UNDEF then don't alter attributes. */ + /* This approach allows maximum performance when */ + /* rebinding parameters often (for multiple executes). */ + + /* At the moment we always do sv_setsv() and rebind. */ + /* Later we may optimise this so that more often we can */ + /* just copy the value & length over and not rebind. */ + + if (SvOK(newvalue)) { + /* XXX need to consider oraperl null vs space issues? */ + /* XXX need to consider taking reference to source var */ + sv_setsv(phs->sv, newvalue); + value_ptr = SvPV(phs->sv, value_len); + phs->indp = 0; + + /* Since we don't support LONG VAR types we must check */ + /* for lengths too big to pass to obndrv as an sword. */ + if (value_len > SWORDMAXVAL) /* generally INT_MAX */ + croak("bind_param %s value is too long (%d bytes, max %d)", + name, value_len, SWORDMAXVAL); + } else { + value_ptr = ""; + value_len = 0; + phs->indp = -1; + } + + /* this will change to odndra sometime */ + if (obndrv(imp_sth->cda, (text*)name, -1, + (ub1*)value_ptr, (sword)value_len, + phs->ftype, -1, &phs->indp, + (text*)0, -1, -1)) { + D_imp_dbh_from_sth; + ora_error(sth, &imp_dbh->lda, imp_sth->cda->rc, "obndrv failed"); + return 0; + } + return 1; +} + + + + +int +dbd_describe(h, imp_sth) + SV *h; + imp_sth_t *imp_sth; +{ + static sb4 *f_cbufl; /* XXX not thread safe */ + static U32 f_cbufl_max; + + sb1 *cbuf_ptr; + int t_cbufl=0; + I32 num_fields; + int i = 0; + + if (!f_cbufl) { + f_cbufl_max = 120; + New(1, f_cbufl, f_cbufl_max, sb4); + } + + if (imp_sth->done_desc) + return 1; /* success, already done it */ + imp_sth->done_desc = 1; + + /* Get number of fields and space needed for field names */ + while(++i) { /* break out within loop */ + sb1 cbuf[256]; /* generous max column name length */ + sb2 dbtype = 0; /* workaround for problem log #405032 */ + if (i >= f_cbufl_max) { + f_cbufl_max *= 2; + Renew(f_cbufl, f_cbufl_max, sb4); + } + f_cbufl[i] = sizeof(cbuf); + odescr(imp_sth->cda, i, (sb4*)0, &dbtype, + cbuf, &f_cbufl[i], (sb4*)0, (sb2*)0, (sb2*)0, (sb2*)0); + if (imp_sth->cda->rc || dbtype == 0) + break; + t_cbufl += f_cbufl[i]; + } + if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { + D_imp_dbh_from_sth; + ora_error(h, &imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); + return 0; + } + imp_sth->cda->rc = 0; + num_fields = i - 1; + DBIc_NUM_FIELDS(imp_sth) = num_fields; + + /* allocate field buffers */ + Newz(42, imp_sth->fbh, num_fields, imp_fbh_t); + /* allocate a buffer to hold all the column names */ + Newz(42, imp_sth->fbh_cbuf, t_cbufl + num_fields, char); + + cbuf_ptr = (sb1*)imp_sth->fbh_cbuf; + for(i=1; i <= num_fields && imp_sth->cda->rc != 10; ++i) { + imp_fbh_t *fbh = &imp_sth->fbh[i-1]; + int dbtype; + + fbh->imp_sth = imp_sth; + fbh->cbuf = cbuf_ptr; + fbh->cbufl = f_cbufl[i]; + /* DESCRIBE */ + odescr(imp_sth->cda, i, + &fbh->dbsize, &fbh->dbtype, fbh->cbuf, &fbh->cbufl, + &fbh->dsize, &fbh->prec, &fbh->scale, &fbh->nullok); + fbh->cbuf[fbh->cbufl] = '\0'; /* ensure null terminated */ + cbuf_ptr += fbh->cbufl + 1; /* increment name pointer */ + + /* Now define the storage for this field data. */ + + /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW? */ + /* If so we need to implement oraperl truncation hacks. */ + /* This may change in a future release. */ + if ( (dbtype = dbtype_is_long(fbh->dbtype)) ) { + sb4 buflen = imp_sth->long_buflen; + if (buflen < 0) + buflen = 80; /* typical oracle app default */ + fbh->dbsize = buflen; + fbh->dsize = buflen; + fbh->ftype = dbtype; /* get long in non-var form */ + } else { + /* for the time being we fetch everything (except longs) */ + /* as strings, that'll change (IV, NV and binary data etc) */ + fbh->ftype = 5; /* oraperl used 5 'STRING' */ + /* dbsize can be zero for 'select NULL ...' */ + } + + fbh->bufl = fbh->dsize+1; /* +1: STRING null terminator */ + + /* currently we use an sv, later we'll use an array */ + fbh->sv = newSV((STRLEN)fbh->bufl); + (void)SvUPGRADE(fbh->sv, SVt_PV); + SvREADONLY_on(fbh->sv); + (void)SvPOK_only(fbh->sv); + fbh->buf = (ub1*)SvPVX(fbh->sv); + + /* BIND */ + if (odefin(imp_sth->cda, i, fbh->buf, fbh->bufl, + fbh->ftype, -1, &fbh->indp, + (text*)0, -1, -1, &fbh->rlen, &fbh->rcode)) { + warn("odefin error on %s: %d", fbh->cbuf, imp_sth->cda->rc); + } + + if (dbis->debug >= 2) + fbh_dump(fbh, i); + } + + if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { + D_imp_dbh_from_sth; + ora_error(h, &imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); + return 0; + } + return 1; +} + + +int +dbd_st_execute(sth) + SV *sth; +{ + D_imp_sth(sth); + + if (!imp_sth->done_desc) { + /* describe and allocate storage for results */ + if (!dbd_describe(sth, imp_sth)) + return 0; /* dbd_describe already called ora_error() */ + } + + /* Trigger execution of the statement */ + if (oexec(imp_sth->cda)) { /* may change to oexfet later */ + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexec error"); + return 0; + } + DBIc_ACTIVE_on(imp_sth); + return 1; +} + + + +AV * +dbd_st_fetch(sth) + SV * sth; +{ + D_imp_sth(sth); + int debug = dbis->debug; + int num_fields; + int i; + AV *av; + /* Check that execute() was executed sucessfuly. This also implies */ + /* that dbd_describe() executed sucessfuly so the memory buffers */ + /* are allocated and bound. */ + if ( !DBIc_ACTIVE(imp_sth) ) { + ora_error(sth, NULL, 1, "no statement executing"); + return Nullav; + } + /* This will become ofen() once the buffer management is reworked. */ + if (ofetch(imp_sth->cda)) { + if (imp_sth->cda->rc != 1403) { /* was not just end-of-fetch */ + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "ofetch error"); + /* should we ocan() here? */ + } else { + sv_setiv(DBIc_ERR(imp_sth), 0); /* just end-of-fetch */ + } + if (debug >= 3) + fprintf(DBILOGFP, " dbd_st_fetch failed, rc=%d", + imp_sth->cda->rc); + return Nullav; + } + + av = DBIS->get_fbav(imp_sth); + num_fields = AvFILL(av)+1; + + if (debug >= 3) + fprintf(DBILOGFP, " dbd_st_fetch %d fields\n", num_fields); + + for(i=0; i < num_fields; ++i) { + imp_fbh_t *fbh = &imp_sth->fbh[i]; + int rc = fbh->rcode; + SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */ + + if (rc == 1406 && dbtype_is_long(fbh->dbtype)) { + /* We have a LONG field which has been truncated. */ + int oraperl = DBIc_COMPAT(imp_sth); + if ((oraperl) ? SvIV(ora_trunc) : imp_sth->long_trunc_ok) { + /* Oraperl recorded the truncation in ora_errno. */ + /* We do so but it's not part of the DBI spec. */ + sv_setiv(DBIc_ERR(imp_sth), (IV)rc); /* record it */ + rc = 0; /* but don't provoke an error */ + } + } + + if (rc == 0) { /* the normal case */ + SvCUR(fbh->sv) = fbh->rlen; + sv_setsv(sv, fbh->sv); /* XXX can be optimised later */ + + } else if (rc == 1405) { /* field is null - return undef */ + (void)SvOK_off(sv); + + } else { /* See odefin rcode arg description in OCI docs */ + /* These may get case-by-case treatment eventually. */ + /* Some should probably be treated as warnings but */ + /* for now we just treat them all as errors */ + ora_error(sth, imp_sth->cda, rc, "ofetch rcode"); + (void)SvOK_off(sv); + } + + if (debug >= 3) + fprintf(DBILOGFP, " %d: rc=%d '%s'\n", + i, rc, SvPV(sv,na)); + + } + return av; +} + + + + +int +dbd_st_blob_read(sth, field, offset, len, destrv, destoffset) + SV *sth; + int field; + long offset; + long len; + SV *destrv; + long destoffset; +{ + D_imp_sth(sth); + ub4 retl; + SV *bufsv; + + bufsv = SvRV(destrv); + sv_setpvn(bufsv,"",0); /* ensure it's writable string */ + SvGROW(bufsv, len+destoffset+1); /* SvGROW doesn't do +1 */ + + if (oflng(imp_sth->cda, (sword)field+1, + ((ub1*)SvPVX(bufsv)) + destoffset, len, + imp_sth->fbh[field].ftype, /* original long type */ + &retl, offset)) { + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oflng error"); + /* XXX database may have altered the buffer contents */ + return 0; + } + /* Sadly, even though retl is a ub4, oracle will cap the */ + /* value of retl at 65535 even if more was returned! */ + /* This is according to the OCI manual for Oracle 7.0. */ + /* Once again Oracle causes us grief. How can we tell what */ + /* length to assign to destrv? We do have a compromise: if */ + /* retl is exactly 65535 we assume that all data was read. */ + SvCUR_set(bufsv, destoffset+((retl == 65535) ? len : retl)); + *SvEND(bufsv) = '\0'; /* consistent with perl sv_setpvn etc */ + + return 1; +} + + +int +dbd_st_rows(sth) + SV *sth; +{ + D_imp_sth(sth); + return imp_sth->cda->rpc; +} + + +int +dbd_st_finish(sth) + SV *sth; +{ + D_imp_sth(sth); + /* Cancel further fetches from this cursor. */ + /* We don't close the cursor till DESTROY. */ + /* The application may re execute it. */ + if (DBIc_ACTIVE(imp_sth) && ocan(imp_sth->cda) ) { + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "ocan error"); + return 0; + } + DBIc_ACTIVE_off(imp_sth); + return 1; +} + + +void +dbd_st_destroy(sth) + SV *sth; +{ + D_imp_sth(sth); + D_imp_dbh_from_sth; + int i; + /* Check if an explicit disconnect() or global destruction has */ + /* disconnected us from the database before attempting to close. */ + if (DBIc_ACTIVE(imp_dbh) && oclose(imp_sth->cda)) { + /* Check for ORA-01041: 'hostdef extension doesn't exist' */ + /* which indicates that the lda had already been logged out */ + /* in which case only complain if not in 'global destruction'. */ + /* NOT NEEDED NOW? if ( ! (imp_sth->cda->rc == 1041 && dirty) ) */ + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oclose error"); + /* fall through */ + } + + /* Free off contents of imp_sth */ + + for(i=0; i < DBIc_NUM_FIELDS(imp_sth); ++i) { + imp_fbh_t *fbh = &imp_sth->fbh[i]; + sv_free(fbh->sv); + } + safefree(imp_sth->fbh); + safefree(imp_sth->fbh_cbuf); + safefree(imp_sth->statement); + + if (imp_sth->bind_names) { + HV *hv = imp_sth->bind_names; + SV *sv; + char *key; + I32 retlen; + hv_iterinit(hv); + while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) { + phs_t *phs_tpl; + if (sv != &sv_undef) { + phs_tpl = (phs_t*)SvPVX(sv); + sv_free(phs_tpl->sv); + } + } + sv_free((SV*)imp_sth->bind_names); + } + + DBIc_IMPSET_off(imp_sth); /* let DBI know we've done it */ +} + + +int +dbd_st_STORE(sth, keysv, valuesv) + SV *sth; + SV *keysv; + SV *valuesv; +{ + return FALSE; +#ifdef not_used_yet + D_imp_sth(sth); + STRLEN kl; + char *key = SvPV(keysv,kl); + int on = SvTRUE(valuesv); + SV *cachesv = NULL; + int oraperl = DBIc_COMPAT(imp_sth); + + if (cachesv) /* cache value for later DBI 'quick' fetch? */ + hv_store((HV*)SvRV(sth), key, kl, cachesv, 0); + return TRUE; +#endif +} + + +SV * +dbd_st_FETCH(sth, keysv) + SV *sth; + SV *keysv; +{ + D_imp_sth(sth); + STRLEN kl; + char *key = SvPV(keysv,kl); + int i; + SV *retsv = NULL; + /* Default to caching results for DBI dispatch quick_FETCH */ + int cacheit = TRUE; + /* int oraperl = DBIc_COMPAT(imp_sth); */ + + if (kl==13 && strEQ(key, "NUM_OF_PARAMS")) /* handled by DBI */ + return Nullsv; + + if (!imp_sth->done_desc && !dbd_describe(sth, imp_sth)) { + /* dbd_describe has already called ora_error() */ + /* we can't return Nullsv here because the xs code will */ + /* then just pass the attribute name to DBI for FETCH. */ + croak("Describe failed during %s->FETCH(%s)", + SvPV(sth,na), key); + } + + i = DBIc_NUM_FIELDS(imp_sth); + + if (kl==11 && strEQ(key, "ora_lengths")) { + AV *av = newAV(); + retsv = newRV((SV*)av); + while(--i >= 0) + av_store(av, i, newSViv((IV)imp_sth->fbh[i].dsize)); + + } else if (kl==9 && strEQ(key, "ora_types")) { + AV *av = newAV(); + retsv = newRV((SV*)av); + while(--i >= 0) + av_store(av, i, newSViv(imp_sth->fbh[i].dbtype)); + + } else if (kl==4 && strEQ(key, "NAME")) { + AV *av = newAV(); + retsv = newRV((SV*)av); + while(--i >= 0) + av_store(av, i, newSVpv((char*)imp_sth->fbh[i].cbuf,0)); + + } else { + return Nullsv; + } + if (cacheit) { /* cache for next time (via DBI quick_FETCH) */ + hv_store((HV*)SvRV(sth), key, kl, retsv, 0); + (void)SvREFCNT_inc(retsv); /* so sv_2mortal won't free it */ + } + return sv_2mortal(retsv); +} + + + +/* --------------------------------------- */ + diff --git a/dbdimp.h b/dbdimp.h new file mode 100644 index 00000000..4adb5389 --- /dev/null +++ b/dbdimp.h @@ -0,0 +1,98 @@ +/* + $Id: dbdimp.h,v 1.11 1996/03/05 02:27:25 timbo Exp $ + + Copyright (c) 1994,1995 Tim Bunce + + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the Perl README file. + +*/ + +/* these are (almost) random values ! */ +#define MAX_COLS 1025 + + +#ifndef HDA_SIZE +#define HDA_SIZE 512 +#endif + +typedef struct imp_fbh_st imp_fbh_t; + +struct imp_drh_st { + dbih_drc_t com; /* MUST be first element in structure */ +}; + +/* Define dbh implementor data structure */ +struct imp_dbh_st { + dbih_dbc_t com; /* MUST be first element in structure */ + + Lda_Def lda; + ub1 hda[HDA_SIZE]; +}; + + +/* Define sth implementor data structure */ +struct imp_sth_st { + dbih_stc_t com; /* MUST be first element in structure */ + + Cda_Def *cda; /* currently just points to cdabuf below */ + Cda_Def cdabuf; + + /* Input Details */ + char *statement; /* sql (see sth_scan) */ + HV *bind_names; + + /* Output Details */ + int done_desc; /* have we described this sth yet ? */ + imp_fbh_t *fbh; /* array of imp_fbh_t structs */ + char *fbh_cbuf; /* memory for all field names */ + sb4 long_buflen; /* length for long/longraw (if >0) */ + bool long_trunc_ok; /* is truncating a long an error */ +}; +#define IMP_STH_EXECUTING 0x0001 + + +struct imp_fbh_st { /* field buffer EXPERIMENTAL */ + imp_sth_t *imp_sth; /* 'parent' statement */ + + /* Oracle's description of the field */ + sb4 dbsize; + sb2 dbtype; + sb1 *cbuf; /* ptr to name of select-list item */ + sb4 cbufl; /* length of select-list item name */ + sb4 dsize; /* max display size if field is a char */ + sb2 prec; + sb2 scale; + sb2 nullok; + + /* Our storage space for the field data as it's fetched */ + sb2 indp; /* null/trunc indicator variable */ + sword ftype; /* external datatype we wish to get */ + ub1 *buf; /* data buffer (points to sv data) */ + ub2 bufl; /* length of data buffer */ + ub2 rlen; /* length of returned data */ + ub2 rcode; /* field level error status */ + + SV *sv; +}; + + +typedef struct phs_st phs_t; /* scalar placeholder */ + +struct phs_st { /* scalar placeholder EXPERIMENTAL */ + SV *sv; /* the scalar holding the value */ + sword ftype; /* external OCI field type */ + sb2 indp; /* null indicator */ +}; + + +void ora_error _((SV *h, Lda_Def *lda, int rc, char *what)); +void fbh_dump _((imp_fbh_t *fbh, int i)); + +void dbd_init _((dbistate_t *dbistate)); +void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); +int dbd_describe _((SV *h, imp_sth_t *imp_sth)); +int dbd_st_blob_read _((SV *sth, int field, long offset, long len, + SV *destrv, long destoffset)); + +/* end */ diff --git a/hints/svr4.pl b/hints/svr4.pl new file mode 100644 index 00000000..9b42dd06 --- /dev/null +++ b/hints/svr4.pl @@ -0,0 +1,114 @@ +# From: Alan Burlison +# Date: Thu, 17 Aug 95 16:54 BST-1 + +# Some SVR4 systems may need to link against -lc to pick up things like +$att{LIBS} = [ '-lsocket -lnsl -lm -ldl -lc' ]; + +__END__ + +From doughera@lafcol.lafayette.edu Mon Aug 21 07:01:51 1995 +Date: Fri, 18 Aug 1995 15:33:22 -0400 (EDT) +From: Andy Dougherty +Subject: Re: [MM] Re: hints file for Oracle +To: Tim Bunce +In-Reply-To: <9508181853.ab12333@post.demon.co.uk> +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII + +On Fri, 18 Aug 1995, Tim Bunce wrote: + +> +> > From: Alan Burlison +> > +> > Tim, +> > +> > The following hints file is required for DBD::Oracle on svr4, you might +> > like to add it to the next release :-) +> > +> > File: Oracle/hints/svr4.pl +> > +> > # Some SVR4 systems may need to link against -lc to pick up things like +> > $att{LIBS} = [ '-lsocket -lnsl -lm -ldl -lc' ]; +> > +> Umm, 'some', 'may', 'things like'. Care to clarify? +> +> Why _exactly_ is this needed, and why doesn't MakeMaker do this already? +> (CC'd to the MakeMaker mailing list.) + +That looks like a bad editing of the ODBM_File/hints/svr4.pl: + +########################## hints/svr4.pl ######################### +# Some SVR4 systems may need to link against routines in -lucb for +# odbm. Some may also need to link against -lc to pick up things like +# ecvt. +$att{LIBS} = ['-ldbm -lucb -lc']; +################################################################### + +"Some" includes Unisys 6000 (or something like that). I don't know +if it includes anything else. It doesn't include Unixware 2.1, but it +might include Esix. It's *really* hard to get accurate info. + +"May" because some do and some don't, and any listing gets out of date +quickly as vendors issue different versions, and probably more than +half the info you *do* get about specific versions is wrong. Hence all +the vague weasel-words. + +"Things like" is ecvt() for Unisys (for ODBM_File). Since some linkers +only report the first missing symbol, it's sometimes hard (and +sometimes pointless) to get a complete list of things that you need). + +Basically, there are *many* SVR4-derived systems out there, and there are +many little idiosyncracies; the best bet is to put someone else's name +and email address in the hint file so you can blame them :-). + + Andy Dougherty doughera@lafcol.lafayette.edu + + +From: Tye McQueen +Subject: Re: [MM] Re: hints file for Oracle +Date: Fri, 18 Aug 1995 16:01:39 -0500 (CDT) +Cc: aburlison@cix.compulink.co.uk, perldb-interest@vix.com, + makemaker@franz.ww.tu-berlin.de + +Excerpts from the mail message of Tim Bunce: +) > From: Alan Burlison +) > +) > The following hints file is required for DBD::Oracle on svr4, you might +) > like to add it to the next release :-) +) > +) > File: Oracle/hints/svr4.pl +) > +) > # Some SVR4 systems may need to link against -lc to pick up things like +) > $att{LIBS} = [ '-lsocket -lnsl -lm -ldl -lc' ]; +) +) Umm, 'some', 'may', 'things like'. Care to clarify? +) +) Why _exactly_ is this needed, and why doesn't MakeMaker do this already? +) (CC'd to the MakeMaker mailing list.) +) +) Is anyone else using DBD::Oracle on an svr4 system (not solaris 2)? + +That looks like something I wrote. I'll take credit and blame +for it at least for the sake of the next paragraph. + +So far "some" is only whatever Unisys system Alan and one other +person have used. "may" is because, as far as I could tell from +my end, some of the dynamically loaded extensions worked okay +before this fix but one of them didn't. "thinks like" must be +because I couldn't remember which routine was not being found +and then forgot to finish my sentence. I think it was _ecvt(). + +The description is very vague because it doesn't make sense to +me why it is needed and I don't have access to a system to play +around with it if I really wanted to try to figure it out. But +it seems to fix the few problems it addresses and have not heard +of it hurting anything yet (and I've tested it on my machines). + +I'm putting together a README.svr4 for Perl that will describe this +and many other things in case people are curious or run into a +problem and need to know why some of the strange things were done. +-- +Tye McQueen tye@metronet.com || tye@doober.usu.edu + Nothing is obvious unless you are overlooking something + http://www.metronet.com/~tye/ (scripts, links, nothing fancy) + diff --git a/oraperl.ex/Readme b/oraperl.ex/Readme new file mode 100644 index 00000000..2246da37 --- /dev/null +++ b/oraperl.ex/Readme @@ -0,0 +1,38 @@ +[ Tim Bunce, 16th Nov 1995: The only change I've made to these + original oraperl examples by Kevin Stock is to add the magic + eval 'use Oraperl; 1' || die $@ if $] >= 5; + line to each. ] + +This directory contains a few sample Oraperl scripts. Some are genuinely +useful (sql, for example, is installed as part of make install) while +others are just demonstrations of different things. + +bind.pl Demonstrates how &ora_bind() and &ora_fetch() may be + combined to make a simple table lookup program + +commit.pl Demonstrates the use of &ora_commit() and &ora_rollback() + +ex.pl This was my first ever Oraperl script. I think I wrote it even + before writing Oraperl! It reads data from a table and prints + it using a format. It also illustrates how to recognise NULL + fields. + +japh Just another Perl hacker, written in Oraperl + This is no one-liner, but it demonstrates a few things. + +mkdb.pl Creates a database, puts some data into it, drops it. The nice + thing about this is that it detects whether it is running under + Oraperl or Coraperl, and changes its output accordingly. It + also illustrates handling of NULL fields, with both &ora_bind() + and &ora_fetch(). + +oradump.pl Dumps the contents of an Oracle table into a set of insert + statements. + +sql This was written in response to a posting on the net, asking + whether there was a tool which would execute an SQL statement + specified on the command line. Manual page built-in. + +tabinfo.pl Displays the structure of the specified table. + This is mainly to show the use of &ora_lengths, &ora_titles + and &ora_types. diff --git a/oraperl.ex/bind.pl b/oraperl.ex/bind.pl new file mode 100755 index 00000000..8507ecfc --- /dev/null +++ b/oraperl.ex/bind.pl @@ -0,0 +1,37 @@ +#!/usr/local/bin/oraperl +# +# bind.pl +# +# This shows how the ora_bind function may be used to implement a +# simple lookup script. + +eval 'use Oraperl; 1' || die $@ if $] >= 5; + +$ora_debug = shift if $ARGV[0] =~ /^-#/; + +$lda = &ora_login('t', 'kstock', 'kstock') + || die $ora_errstr; +$csr = &ora_open($lda, 'select phone from telno where name = :1') + || die $ora_errstr; + +while() +{ + chop; + &ora_bind($csr, $_) || die $ora_errstr; + + # Note that $phone is placed in brackets to give it array context + # Without them, &ora_fetch() returns the number of columns available + + if (($phone) = &ora_fetch($csr)) + { + print "$phone\n"; + } + else + { + die $ora_errstr if $ora_errno; + print "unknown\n"; + } +} + +&ora_close($csr); +&ora_logoff($lda); diff --git a/oraperl.ex/commit.pl b/oraperl.ex/commit.pl new file mode 100755 index 00000000..24754631 --- /dev/null +++ b/oraperl.ex/commit.pl @@ -0,0 +1,59 @@ +#!/usr/local/bin/oraperl +# +# commit.pl +# +# Simple example of using commit and rollback. + +eval 'use Oraperl; 1' || die $@ if $] >= 5; + +$ora_debug = shift if $ARGV[0] =~ /^-#/; + +$lda = &ora_login('t', 'kstock', 'kstock') || die "$ora_errstr\n"; +&ora_do($lda, 'create table primes (prime number)') || die "$ora_errstr\n"; + +$csr = &ora_open($lda, 'insert into primes values(:1)') || die "$ora_errstr\n"; +print 'creating table'; +while () +{ + chop; + print " $_"; + &ora_bind($csr, $_) || die "$_: $ora_errstr\n"; + (print ' committing ', &ora_commit($lda)) if $_ == 11; +} +&ora_close($csr) || die "$ora_errstr\n"; + +print "\n\nReading table for the first time\n\n"; +$csr = &ora_open($lda, 'select prime from primes') || die "$ora_errstr\n"; +while (($prime) = &ora_fetch($csr)) +{ + print "$prime "; +} +die "$ora_errstr\n" if $ora_errno; +&ora_close($csr) || die "$ora_errstr\n"; + +print "\n\nRolling back ", &ora_rollback($lda), "\n\n"; + +print "Attempting to read data for the second time.\n"; +print "Only values up to 11 should appear.\n\n"; +$csr = &ora_open($lda, 'select prime from primes') || die "$ora_errstr\n"; +while (($prime) = &ora_fetch($csr)) +{ + print "$prime "; +} +die "$ora_errstr\n" if $ora_errno; +&ora_close($csr) || die "$ora_errstr\n"; + +&ora_do($lda, 'drop table primes') || die "$ora_errstr\n"; +&ora_logoff($lda); +print "\n" +__END__ +2 +3 +5 +7 +11 +13 +17 +19 +23 +29 diff --git a/oraperl.ex/ex.pl b/oraperl.ex/ex.pl new file mode 100755 index 00000000..1a23a59d --- /dev/null +++ b/oraperl.ex/ex.pl @@ -0,0 +1,35 @@ +#!/usr/local/bin/oraperl + +eval 'use Oraperl; 1' || die $@ if $] >= 5; + +$ora_debug = shift if $ARGV[0] =~ /^-#/; + +format STDOUT_TOP = + Name Phone + ==== ===== +. + +format STDOUT = + @<<<<<<<<<< @>>>>>>>>>> + $name, $phone +. + +die ("You should use oraperl, not perl\n") unless defined &ora_login; + +$lda = &ora_login("t", "kstock", "kstock") + || die $ora_errstr; +$csr = &ora_open($lda, "select * from telno order by name", 6) + || die $ora_errstr; + +$nfields = &ora_fetch($csr); +print "Query will return $nfields fields\n\n"; + +while (($name, $phone) = &ora_fetch($csr)) +{ + # mark any NULL fields found + grep(defined || ($_ = ''), $name, $phone); + write; +} + +do ora_close($csr) || die "can't close cursor"; +do ora_logoff($lda) || die "can't log off Oracle"; diff --git a/oraperl.ex/japh b/oraperl.ex/japh new file mode 100755 index 00000000..06d9df0e --- /dev/null +++ b/oraperl.ex/japh @@ -0,0 +1,54 @@ +#!/usr/local/bin/oraperl +# +# This is an example of how we could code a JAPH in Oraperl. +# +# Author: Kevin Stock +# Date: 1st December 1992 + +eval 'use Oraperl; 1' || die $@ if $] >= 5; + +# supply debugging output if desired + +$ora_debug = shift if $ARGV[0] =~ /^-#/; + +# login to the database and create the table + +$lda = &ora_login('t', 'kstock', 'kstock') || die $ora_errstr; +&ora_do($lda, <<) || die $ora_errstr; + create table japh (word char(7), posn number(1)) + +# Loop to insert data into the table + +$csr = &ora_open($lda, <<) || die $ora_errstr; + insert into japh values(:1, :2) + +while () +{ + chop; + &ora_bind($csr, split(':')) || warn "$_: $ora_errstr"; +} +&ora_close($csr) || warn $ora_errstr; + +# Now retrieve the data, printing it word by word + +$csr = &ora_open($lda, <<) || die $ora_errstr; + select word from japh order by posn + +while (($word) = &ora_fetch($csr)) +{ + print "$word "; +} +&ora_close($csr) || warn $ora_errstr; + +print "\n"; + +# delete the table + +&ora_do($lda, 'drop table japh') || warn $ora_errstr; +&ora_logoff($lda) || die $ora_errstr; + +__END__ +Oraperl:3 +another:2 +hacker:4 +just:1 diff --git a/oraperl.ex/mkdb.pl b/oraperl.ex/mkdb.pl new file mode 100755 index 00000000..fece2134 --- /dev/null +++ b/oraperl.ex/mkdb.pl @@ -0,0 +1,177 @@ +# mkdb.pl +# +# Sample (c)oraperl program to create a new database and load data into it. +# +# Author: Kevin Stock +# Date: 5th August 1991 +# +# Modified to use curses functions if present. +# +# Date: 15th November 1991 +# +# Modified to demonstrate NULL handling in &ora_bind and &ora_fetch() +# +# Date: 25th September 1992 + +# First make sure that we are running under some form of perl. + +eval "echo 'You must specify oraperl or coraperl.' ; exit" + if 0; + +eval 'use Oraperl; 1' || die $@ if $] >= 5; + +# make sure that we really are running (c)oraperl +die ("You should use oraperl, not perl\n") unless defined &ora_login; + +# Set up debugging (hope the user has redirected this if we're +# going into curses!) +$ora_debug = shift if $ARGV[0] =~ /^-#/; + +# get error codes +require('oraperl.ph'); + +# Arrange to use curses functions if they're available. +# (This is just showing off) + +if (defined(&initscr) && &initscr()) +{ + eval <<'____END_OF_CURSES_STUFF'; + + $curses = 1; + + # functions used by the list function + + sub before + { + &erase(); + &standout(); + &addstr("Num Name Ext\n\n"); + &standend(); + $lineno = 1; + } + + sub during + { + &addstr(sprintf("%2d %-15s%3s\n", $lineno++, $name, $ext)); + } + + sub after + { + &standout(); + &move($LINES - 1, 0); + &addstr("Press RETURN to continue."); + &standend(); + &refresh(); + &getstr($dummy); + &move($LINES - 1, 0); + &addstr(" "); + &move($LINES - 1, 0); + &refresh(); + } + +____END_OF_CURSES_STUFF +} +else +{ + eval <<'____END_OF_PLAIN_STUFF'; + + $curses = 0; + + format STDOUT_TOP = + Name Ext + ==== === +. + + format STDOUT = + @<<<<<<<<< @>> + $name, $ext +. + + # functions used by the list function + + sub before { $- = 0; } + sub during { write; } + sub after { 1; } + +____END_OF_PLAIN_STUFF +} + +# function to list the database + +sub list +{ + local($csr, $name, $ext); + + do before(); + + $csr = &ora_open($lda, $LIST) || die $ora_errstr; + while (($name, $ext) = &ora_fetch($csr)) + { + $name = '<-NULL->' unless defined($name); + $ext = '<-NULL->' unless defined($ext); + do during(); + } + die $ora_errstr if ($ora_errno != 0); + do ora_close($csr) || die $ora_errstr; + + do after(); +} + +# set these as strings to make the code more readable +$CREATE = "create table tryit (name char(10), ext number(3))"; +$INSERT = "insert into tryit values (:1, :2)"; +$LIST = "select * from tryit order by name"; +$DELETE = "delete from tryit where name = :1"; +$DELETE_NULL = "delete from tryit where name is null"; +$DROP = "drop table tryit"; + +# create the database + +$lda = &ora_login('t', 'kstock', 'kstock') || die $ora_errstr; +&ora_do($lda, $CREATE) || die $ora_errstr; + +# put some data into it + +$csr = &ora_open($lda, $INSERT) || die $ora_errstr; +while () +{ + m/(.*):(.*)/; + $name = ($1 eq 'NULL') ? undef : $1; + $ext = ($2 eq 'NULL') ? undef : $2; + do ora_bind($csr, $name, $ext); +} +do ora_close($csr) || die $ora_errstr; + +# check the result +do list(); + +# remove a few lines + +$csr = &ora_open($lda, $DELETE) || die $ora_errstr; +foreach $name ('catherine', 'angela', 'arnold', 'julia') +{ + &ora_bind($csr, $name) || die $ora_errstr; +} +&ora_close($csr) || die $ora_errstr; +&ora_do($lda, $DELETE_NULL) || die $ora_errstr; + +# check the result +do list(); + +# remove the database and log out +do ora_do($lda, $DROP) || die $ora_errstr; +do ora_logoff($lda) || die $ora_errstr; + +do endwin() if $curses == 1; + +# This is the data which will go into the database +__END__ +julia:292 +angela:208 +NULL:999 +larry:424 +catherine:201 +nonumber:NULL +randal:306 +arnold:305 +NULL:NULL diff --git a/oraperl.ex/oradump.pl b/oraperl.ex/oradump.pl new file mode 100755 index 00000000..170ac3f7 --- /dev/null +++ b/oraperl.ex/oradump.pl @@ -0,0 +1,29 @@ +#!/usr/local/bin/oraperl +# +# oradump.pl +# +# Dump the contents of an Oracle table into a set of insert statements. +# Usage: oradump +# +# Author: Kevin Stock +# Date: 28th February 1992 +# +eval 'use Oraperl; 1' || die $@ if $] >= 5; + +$ora_debug = shift if $ARGV[0] =~ /^-#/; + +(($base = shift) && + ($table = shift) && + ($user = shift)) || die "Usage: $0 base table user/password\n"; + +$lda = &ora_login($base, $user, '') || die $ora_errstr; +$csr = &ora_open($lda, "select * from $table") || die $ora_errstr; + +while (@data = &ora_fetch($csr)) +{ + print "insert into $table values('" . join("', '", @data) . "');\n"; +} +warn "$ora_errstr" if $ora_errno; + +&ora_close($csr) || die $ora_errstr; +&ora_logoff($lda) || die $ora_errstr; diff --git a/oraperl.ex/sql b/oraperl.ex/sql new file mode 100755 index 00000000..c4aaab0a --- /dev/null +++ b/oraperl.ex/sql @@ -0,0 +1,225 @@ +#!/usr/local/bin/oraperl +'di'; +'ig00'; +# +# sql +# +# Script to run an Oracle statement from the command line. +# Written in response to in alt.sources.wanted. +# +# Parameters (* = mandatory) +# +# -#debug debugging control string (must be first argument) +# -b base database to use (default $ENV{'ORACLE_SID'}) +# -c cache SQL fetch cache size +# -d delim specifies the field delimiter (default TAB) +# -f formatted output, similar to sqlplus +# -h add headers, no formatting +# -l page_len lines per page, only used by -f (default 60) +# -n string replace NULL fields by string +# name/pass * Oracle username and password +# stmt Oracle statement to be executed +# read from stdin if not given on command line +# +# Author: Kevin Stock +# Date: 18th November 1991 +# Last change: 9th June 1993 +# +eval 'use Oraperl; 1' || die $@ if $] >= 5; + +$ora_debug = shift if $ARGV[0] =~ /^-#/; + +$USAGE = <<; +[-bbase] [-ccache] [-ddelim] [-f|-h] [-lpage_len] [-nstring] name/pass [stmt] + +require 'getopts.pl'; # option parsing +do Getopts('b:c:d:fhl:n:'); +die "$0: only one of -f and -h may be specified\n" if ($opt_f && $opt_h); + +$USER = shift || die "user/password not specified\n"; + +if ($#ARGV >= 0) +{ + @stmt = @ARGV; +} +else +{ + print "Enter the statement to execute (^D to end):\n"; + @stmt = ; +} + +$, = "\t"; # default delimiter is a tab +$\ = "\n"; # each record terminated with newline + +$db = $opt_b if defined($opt_b); # set database +$ora_cache = $opt_c if defined($opt_c); # set fetch cache +$, = $opt_d if defined($opt_d); # set column delimiter +$= = $opt_l if defined($opt_l); # set page length + +# log into the database and execute the statement + +$lda = &ora_login($db, $USER, '') || die "$ora_errstr\n"; +$csr = &ora_open($lda, "@stmt") || die "$ora_errstr\n"; + +# print out any information which comes back + +if (($nfields = &ora_fetch($csr)) > 0) # does the statement return data? +{ + if ($opt_f) # formatted output + { + # Build up format statements for the data + + # First, the header - a list of field names, formatted + # in columns of the appropriate width + + $fmt = ''; + grep($fmt .= "%-${_}.${_}s|", &ora_lengths($csr)); + chop $fmt; + $fmt = sprintf($fmt, &ora_titles($csr, 0)); + $format .= "format STDOUT_TOP =\n" . $fmt . "\n"; + + # Then underlines for the field names + + $fmt =~ tr/|/-/c; + $fmt =~ tr/|/+/; + $format .= $fmt . "\n.\n"; + + # Then for the data format, a @<<... field per column + + $fmt =~ tr/-+/<|/; + $fmt =~ s/(^|\|) +.if t .ft P +.ex diff --git a/oraperl.ex/tabinfo.pl b/oraperl.ex/tabinfo.pl new file mode 100644 index 00000000..669219b9 --- /dev/null +++ b/oraperl.ex/tabinfo.pl @@ -0,0 +1,61 @@ +#!/usr/local/bin/oraperl +# +# tabinfo +# +# Usage: tabinfo base user password table +# +# Displays the structure of the specified table. +# Note that the field names are restricted to the length of the field. +# This is mainly to show the use of &ora_lengths, &ora_titles and &ora_types. +# +eval 'use Oraperl; 1' || die $@ if $] >= 5; + +# set debugging, if requested +# +$ora_debug = shift if $ARGV[0] =~ /-#/; + +# read the compulsory arguments +# +(($base = shift) && + ($user = shift) && + ($pass = shift) && + ($table = shift)) || die "Usage: $0 base user password table ...\n"; + +# we need this for the table of datatypes +# +require 'oraperl.ph'; + +format STDOUT_TOP = +Structure of @<<<<<<<<<<<<<<<<<<<<<<< +$table + +Field name | Length | Type | Type description +----------------------------------------------+--------+------+----------------- +. + +format STDOUT = +@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | @>>>>> | @>>> | @<<<<<<<<<<<<<<< +$name[$i], $length[$i], $type[$i], $ora_types{$type[$i]} +. + +$lda = &ora_login($base, $user, $pass) || die $ora_errstr . "\n"; + +do +{ + $csr = &ora_open($lda, "select * from $table") || die "$ora_errstr\n"; + + (@name = &ora_titles($csr, 0)) || die $ora_errstr . "\n"; + (@length = &ora_lengths($csr)) || die $ora_errstr . "\n"; + (@type = &ora_types($csr)) || die $ora_errstr . "\n"; + + foreach $i (0 .. $#name) + { + write; + } + + &ora_close($csr); + + $- = 0; +} while ($table = shift); + +&ora_logoff($lda); diff --git a/oraperl.ph b/oraperl.ph new file mode 100644 index 00000000..99f62994 --- /dev/null +++ b/oraperl.ph @@ -0,0 +1,53 @@ +# DBD::Oracle Oraperl emulation. This file is not relevant to the +# emulation but is included for completeness only. +# I have updated %ora_types in case it's used. Tim Bunce. + +# oraperl.ph +# +# Various constants which may be useful in oraperl programs +# +# Author: Kevin Stock +# Date: 28th October 1991 +# Last Change: 8th April 1992 + + +# Oraperl error codes, set in $ora_errno + +$ORAP_NOMEM = 100001; # out of memory +$ORAP_INVCSR = 100002; # invalid cursor supplied +$ORAP_INVLDA = 100003; # invalid lda supplied +$ORAP_NOSID = 100004; # couldn't set ORACLE_SID +$ORAP_BADVAR = 100005; # bad colon variable sequence +$ORAP_NUMVARS = 100006; # wrong number of colon variables +$ORAP_NODATA = 100007; # statement does not return data + + +# Oraperl debugging codes for $ora_debug +# From version 2, you shouldn't really use these. + +$ODBG_EXEC = 8; # program execution +$ODBG_STRNUM = 32; # string/numeric conversions +$ODBG_MALLOC = 128; # memory allocation/release + +# Oracle datatypes +# I don't know whether these are valid for all versions. + +%ora_types = +( + 1, 'character array', + 2, 'number', + 3, 'signed integer', + 4, 'float', + 7, 'packed decimal', + 8, 'long string', + 9, 'varchar', + 11, 'rowid', + 12, 'date', + 15, 'varraw', + 23, 'raw', + 24, 'long raw', + 96, 'char', + 106,'mlslabel', +); + +1; diff --git a/t/base.t b/t/base.t new file mode 100755 index 00000000..24e16768 --- /dev/null +++ b/t/base.t @@ -0,0 +1,23 @@ +#!/usr/local/bin/perl -w + +# Base DBD Driver Test + +print "1..$tests\n"; + +require DBI; +print "ok 1\n"; + +import DBI; +print "ok 2\n"; + +$switch = DBI->internal; +(ref $switch eq 'DBI::dr') ? print "ok 3\n" : print "not ok 3\n"; + +$drh = DBI->install_driver('Oracle'); +(ref $drh eq 'DBI::dr') ? print "ok 4\n" : print "not ok 4\n"; + +print "ok 5\n" if $drh->{Version}; + +BEGIN { $tests = 5 } +exit 0; +# end. diff --git a/t/main.t b/t/main.t new file mode 100755 index 00000000..901e21af --- /dev/null +++ b/t/main.t @@ -0,0 +1,136 @@ +#!/usr/local/bin/perl -w + +use DBI; + +print "1..$tests\n"; + +print "ok 1\n"; + +BEGIN { $tests = 1 } +exit 0; + + +# ---------------------------------------------------------- + +# $Id: main.t,v 1.1 1995/10/24 02:39:35 timbo Exp $ +# +# Copyright (c) 1994, Tim Bunce +# +# You may distribute under the terms of either the GNU General Public +# License or the Artistic License, as specified in the Perl README file. + +# This is just my DBI test script, it's not as clean as it could be :-) + +BEGIN { + print "$0 @ARGV\n"; + print q{DBI test application $Revision: 1.1 $}."\n"; + $| = 1; # chop($cwd = `pwd`); unshift(@INC, "."); +} + +use DBI; + +use Getopt::Long; +use strict; + +$main::opt_d = 1; +$main::opt_h = 0; +$main::opt_dbname = 'crgs'; + +GetOptions('d=i', 'h=i', 'dbname=s') + or die "Usage: $0 [-d n] [-h n] [drivername]\n"; + +my($driver) = $ARGV[0] || 'Oracle'; +print "opt_d=$main::opt_d\n" if $main::opt_d; +print "opt_h=$main::opt_h\n" if $main::opt_h; + +# Now ask for some information from the DBI Switch +my($switch) = DBI->internal; +$switch->debug($main::opt_h); # 2=detailed handle trace + +print "Switch: $switch->{'Attribution'}, $switch->{'Version'}\n"; + +$switch->{'DebugDispatch'} = $main::opt_d; # 2=detailed trace of all dispatching +print "DebugDispatch: $switch->{'DebugDispatch'}\n"; + +print "Available Drivers: ",join(", ",DBI->available_drivers()),"\n"; + +my($dbh); # first, get connected using either of these methods: +if (0){ + $dbh = DBI->connect($::opt_dbname, '', '', $driver); +}else{ + my($drh) = DBI->install_driver($driver); + print "Driver installed as $drh\n"; + $dbh = $drh->connect($::opt_dbname, 'system', 'manager'); +} +die "Unable for connect to $::opt_dbname: $DBI::errstr" + unless $dbh; + +$dbh->debug($main::opt_h); + +eval { run_test($dbh); }; +print "run_test($dbh) failed: '$@'\n"; + +print "$0 Done. (global destruction will follow)\n\n"; +exit 0; + + +sub run_test{ + my($dbh) = @_; + + print "Connected as $dbh\n\n"; + + $dbh->commit; + + my($cursor_a) = $dbh->prepare("select SYSDATE from DUAL"); + die "Prepare failed ($DBI::err): $DBI::errstr\n" unless $cursor_a; + + print "Prepared as $cursor_a\n"; + # $cursor_a->debug(2); + + my($cursor_b) = $dbh->prepare("select SYSDATE+1 from DUAL"); + die "Prepare failed ($DBI::err): $DBI::errstr\n" unless $cursor_b; + + print "Prepared as $cursor_b\n"; + # $cursor_b->debug(2); + + # Test object attributes + + print "Number of fields: $cursor_a->{'NUM_OF_FIELDS'}\n"; + print "Number of fields: $cursor_a->{'NUM_OF_FIELDS'}\n"; # now cached + +die "Test not fully implemented yet"; + + print "Data type of first field: $cursor_a->{'DATA_TYPE'}->[0]\n"; + print "Driver name: $cursor_a->{'Database'}->{'Driver'}->{'Name'}\n"; + + + $cursor_a->execute('/usr'); + $cursor_b->execute('/usr/spool'); + + print "Fetching data from both cursors:\n"; + my(@row_a, @row_b); + while((@row_a = $cursor_a->fetchrow) + && (@row_b = $cursor_b->fetchrow)){ + print "@row_a, @row_b\n"; + } + + print "\nAutomatic method parameter usage check:\n"; + eval { $dbh->commit('dummy') }; + warn "$@\n"; + + print "Preparing new \$cursor_a to replace current \$cursor_a:\n"; + + print "(we enable debugging on current to watch it's destruction)\n"; + $cursor_a->debug(2); + + $cursor_a = $dbh->prepare("select mtime,name from ?"); + $cursor_a->execute('../..'); + + print "Fetching one row from new \$cursor_a:\n"; + print join(' ',$cursor_a->fetchrow),"\n"; + $cursor_a->finish; + + print "test done (scoped objects will be destroyed now)\n"; +} + +# end. diff --git a/temp_git_index.lock b/temp_git_index.lock deleted file mode 100644 index e69de29b..00000000 diff --git a/test.pl b/test.pl new file mode 100755 index 00000000..1a56b5ff --- /dev/null +++ b/test.pl @@ -0,0 +1,185 @@ +#!/usr/local/bin/perl -w + +# $Id: test.pl,v 1.20 1996/01/29 22:33:23 timbo Exp $ +# +# Copyright (c) 1995, Tim Bunce +# +# You may distribute under the terms of either the GNU General Public +# License or the Artistic License, as specified in the Perl README file. + +require 'getopts.pl'; + +$| = 1; +print q{Oraperl test application $Revision: 1.20 $}."\n"; + +$opt_d = 0; # debug +$opt_l = 0; # log +$opt_c = 5; # count for loops +$opt_m = 0; # count for mem leek test +&Getopts('m:d:c:l') || die "Invalid options\n"; + +$ENV{PERL_DBI_DEBUG} = 2 if $opt_d; +$ENV{ORACLE_HOME} = '/usr/oracle' unless $ENV{ORACLE_HOME}; + +$dbname = $ARGV[0] || ''; # $ENV{TWO_TASK} || $ENV{ORACLE_SID} || 'crgs'; +$dbuser = $ENV{ORACLE_USERID} || 'crgs/crgs'; + +eval '$Oraperl::safe = 1' if $] >= 5; +eval 'use Oraperl; 1' || die $@ if $] >= 5; + +&ora_version; + +print "\nConnecting\n", + " to '$dbname' (from command line, else uses ORACLE_SID/TWO_TASK)\n"; +print " as '$dbuser' (via ORACLE_USERID environment var or default)\n"; + +{ # test connect works first + local($l) = &ora_login($dbname, $dbuser, ''); + unless($l) { + warn "ora_login: $ora_errno: $ora_errstr\n"; + warn "\nHave you set the environment variable ORACLE_USERID ?\n" + if ($ora_errno == 1017); # ORA-01017: invalid username/password + warn "\nHave you set the environment variable ORACLE_SID or TWO_TASK?\n" + if ($ora_errno == 2700); # error translating ORACLE_SID + warn "\nORACLE_SID or TWO_TASK possibly not right, or server not running.\n" + if ($ora_errno == 1034); # ORA-01034: ORACLE not available + die "\nCould not connect to database. Test aborted.\n"; + } + &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; +} +$start = time; + +rename("test.log","test.olog") if $opt_l; +eval 'DBI->internal->{DebugLog} = "test.log";' if $opt_l; + +&test3($opt_m) if ($opt_m); +&test1(); + +print "\nTesting repetitive connect/open/close/disconnect:\n"; +print "Expect sequence of digits, no other messages:\n"; +#DBI->internal->{DebugDispatch} = 2; +foreach(1..$opt_c) { print "$_ "; &test2(); } +print "\n"; + +print "\nTest interaction of explicit close/logoff and implicit DESTROYs\n"; +print "Expect just 'done.', no other messages:\n"; +$lda2 = &ora_login($dbname, $dbuser, ''); +$csr2 = &ora_open($lda2, "select 42 from dual") || die "ora_open: $ora_errno: $ora_errstr\n"; +&ora_close($csr2) || warn "ora_close($csr2): $ora_errno: $ora_errstr\n"; +&ora_logoff($lda2) || warn "ora_logoff($lda2): $ora_errno: $ora_errstr\n"; +print "done.\n"; + +&test3($opt_m) if ($opt_m); + +$dur = time - $start; +print "\nTest complete ($dur seconds).\n"; + +exit 0; + + +sub test1 { + local($lda) = &ora_login($dbname, $dbuser, '') + || die "ora_login: $ora_errno: $ora_errstr\n"; + + &ora_commit($lda) || warn "ora_commit($lda): $ora_errno: $ora_errstr\n"; + &ora_rollback($lda) || warn "ora_rollback($lda): $ora_errno: $ora_errstr\n"; + &ora_autocommit($lda, 1); + &ora_autocommit($lda, 0); + + # Test ora_do with harmless non-select statement + &ora_do($lda, "set transaction read only ") + || warn "ora_do: $ora_errno: $ora_errstr\n"; + + # DBI::dump_results($lda->tables()); + + # $lda->debug(2); + + { + local($csr) = &ora_open($lda, + "select 11*7.2 num_t, + SYSDATE date_t, + USER char_t, + NULL null_t + from dual") || die "ora_open: $ora_errno: $ora_errstr\n"; + + print "Fields: ",scalar(&ora_fetch($csr)),"\n"; + die "ora_fetch in scalar context error\n" unless &ora_fetch($csr)==4; + print "Names: '",join("',\t'", &ora_titles($csr)),"'\n"; + print "Lengths: '",join("',\t'", &ora_lengths($csr)),"'\n"; + print "Types: '",join("',\t'", &ora_types($csr)),"'\n"; + + print "Data rows:\n"; + #$csr->debug(2); + while(@fields = &ora_fetch($csr)) { + warn "ora_fetch returned .".@fields." fields instead of 4!" + if (@fields!=4); + die "Perl list/scalar context error" if @fields==1; + $fields[3] = "NULL" unless defined $fields[3]; + print " fetch: "; print "@fields\n"; + } + + &ora_close($csr) || warn "ora_close($csr): $ora_errno: $ora_errstr\n"; + print "\n"; + + print "csr reassigned (forces destruction)...\n"; + + #$lda->debug(2); + $csr = &ora_open($lda,<<"") || die "ora_open: $ora_errno: $ora_errstr\n"; + select TABLE_NAME from ALL_TABLES + where TABLE_NAME like :1 and ROWNUM < 5 + + #$lda->debug(0); + print "Fetch list of tables:\n"; +# print "BindParams error $csr->{BindParams}\n" unless $csr->{BindParams}==1; + &ora_bind($csr, '%'); + + #DBI::dump_handle($lda, "lda"); + #DBI::dump_handle($csr, "csr"); + + while(@fields = &ora_fetch($csr)){ + print "Fetched: "; print "@fields\n"; + } + warn "ora_fetch($csr): $ora_errno: $ora_errstr\n" if $ora_errno; + + print "Test ora_do with harmless non-select statement ", + "(set transaction read only)\n"; + # example: push(@{$lda->{Handlers}}, sub { die "ora_errno=$ora_errno" } ); + print "Expect error message:\n"; + &ora_do($lda, "set transaction read only ") + || warn "ora_do: $ora_errno: $ora_errstr\n"; + + print "csr out of scope...\n"; + } + + print "ora_logoff...\n"; + &ora_logoff($lda) || warn "ora_logoff($lda): $ora_errno: $ora_errstr\n"; + + print "lda out of scope...\n"; +} + + +sub test2 { + local($l) = &ora_login($dbname, $dbuser, '') + || die "ora_login: $ora_errno: $ora_errstr\n"; + local($c) = &ora_open($l, "select 42,42,42,42,42,42,42 from dual") + || die "ora_open: $ora_errno: $ora_errstr\n"; + local(@row); + @row = &ora_fetch($c); + &ora_close($c) || warn "ora_close($c): $ora_errno: $ora_errstr\n"; + &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; +} + + +sub test3 { + local($count) = @_; + local($ps) = (-d '/proc') ? "ps -p " : "ps -l"; + local($i) = 0; + + while(++$i <= $count) { + system("echo $i; $ps$$") if (($i % 10) == 0); + &test2(); + } + system("echo $i; $ps$$") if (($i % 10) == 0); +} + +# end. From 239214bebac979123f4bab4e6ea628c77dde49ab Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Tue, 7 May 1996 14:42:00 -0500 Subject: [PATCH 010/637] import DBD-Oracle 0.30 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.30 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.30.tar.gz --- Changes | 18 +++++++ MANIFEST | 1 - Makefile.PL | 8 +++- Oracle.pm | 72 +++++++++++++++++++++------- Oraperl.pm | 16 ++++--- README | 39 ++++++++++++--- dbdimp.c | 8 ++-- t/main.t | 136 ---------------------------------------------------- 8 files changed, 125 insertions(+), 173 deletions(-) delete mode 100755 t/main.t diff --git a/Changes b/Changes index 42159eab..85f797d3 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,21 @@ +Changes in DBD::Oracle 0.30, 7th May 1996 + + THE ORAPERL EMULATION LAYER IS NOW FORMALLY RELEASED (NO LONGER ALPHA). + + Note that the underlying DBI and DBD::Oracle interfaces remain alpha + because they are still subject to, possibly significant, change. + + Oraperl v2 used to return the string 'OK' to indicate success + with a zero numeric value. The Oraperl emulation now uses the + string '0E0' to achieve the same effect since it does not cause + any -w warnings when used in a numeric context. + + Fixed typecast warning (s/safefree/Safefree). + Automatically sets/resets ORACLE_HOME from oratab value for sid. + + TO DO: Automatic configuration from Oracle 7.3 is not yet working + (Oracle have reorganised the makefiles yet again!). + Changes in DBD::Oracle 0.29, 2 March 1996 Fixed Makefile.PL to get DBIXS.h from right spot. diff --git a/MANIFEST b/MANIFEST index 3ed70b5e..d611aa0c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -11,7 +11,6 @@ dbdimp.h dbdimp.c test.pl t/base.t -t/main.t hints/svr4.pl oraperl.ph Old oraperl file included for completeness of emulation oraperl.ex/Readme Oraperl examples (copied unchanged from oraperl-2.4) diff --git a/Makefile.PL b/Makefile.PL index 4c61c16f..8900b163 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,5 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.33 1996/03/05 02:04:42 timbo Exp $ +# $Id: Makefile.PL,v 1.35 1996/05/07 20:47:15 timbo Exp $ require 5.002; @@ -8,7 +8,7 @@ use Getopt::Std; use Config; use strict; -use DBI 0.68; # This DBI must be installed before we can build a DBD +use DBI 0.69; # This DBI must be installed before we can build a DBD my %opts = ( NAME => 'DBD::Oracle', @@ -64,6 +64,7 @@ $oraclemk = "$OH/proc16/lib/proc16.mk" unless -f $oraclemk; die "Unable to locate proc.mk (use -m /path/to/proc.mk to specify)\n" unless -f $oraclemk; my $linkwith = fetch_oci_macros(); +$linkwith =~ s/-Y P,/-YP,/ if $Config{'cc'} =~ /gcc/; print "Using $oraclemk version $MK{mkver}\n"; @@ -219,6 +220,9 @@ sub fetch_oci_macros { next unless $_; last if m/^\w+\s*:/; # gone too far, reached actual targets + # XXX temporary warning (for Oracle 7.3) till includes are supported + warn "$_ not processed\n" if m/^\s*include/i; + unless($MK{mkver}) { # still need to get version number # This is tough since some versions of proc.mk split the # RCS header over three lines! Well that's Oracle for you. diff --git a/Oracle.pm b/Oracle.pm index 5a413cd2..3024a738 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,10 +1,12 @@ -# $Id: Oracle.pm,v 1.23 1996/03/05 02:27:25 timbo Exp $ +# $Id: Oracle.pm,v 1.27 1996/05/07 21:38:04 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # # You may distribute under the terms of either the GNU General Public # License or the Artistic License, as specified in the Perl README file. +my $oracle_home; + { package DBD::Oracle; @@ -12,16 +14,17 @@ use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.29'; - my $Revision = substr(q$Revision: 1.23 $, 10); + $VERSION = '0.30'; + my $Revision = substr(q$Revision: 1.27 $, 10); - require_version DBI 0.68; + require_version DBI 0.69; bootstrap DBD::Oracle $VERSION; $err = 0; # holds error code for DBI::err $errstr = ""; # holds error string for DBI::errstr $drh = undef; # holds driver handle once initialised + %oratab = (); # holds list of oratab databases (e.g., local) sub driver{ return $drh if $drh; @@ -29,10 +32,8 @@ unless ($ENV{'ORACLE_HOME'}){ foreach(qw(/usr/oracle /opt/oracle /home/oracle /usr/soft/oracle)){ - $ENV{'ORACLE_HOME'}=$_,last if -d "$_/rdbms/lib"; + $oracle_home = $_,last if -d "$_/rdbms/lib"; } - my $msg = ($ENV{ORACLE_HOME}) ? "set to $ENV{ORACLE_HOME}" : "not set!"; - warn "ORACLE_HOME $msg\n"; } $class .= "::dr"; @@ -61,33 +62,68 @@ DBD::Oracle::errstr(@_); } + sub load_oratab { # get list of 'local' databases + my($drh) = @_; + my $debug = $drh->debug; + foreach(qw(/etc /var/opt/oracle), $ENV{TNS_ADMIN}) { + warn "Checking for $_/oratab\n" if $debug; + next unless open(ORATAB, "<$_/oratab"); + while() { + next unless m/^(\w+)\s*:\s*(.*?)\s*:/; + warn "Duplicate SID $1 in $_/oratab" if $DBD::Oracle::oratab{$1}; + $DBD::Oracle::oratab{$1} = $2; # store ORACLE_HOME value + warn "$DBD::Oracle::oratab{$1} = $_" if $debug; + } + close(ORATAB); + last; + } + } + sub connect { my($drh, $dbname, $user, $auth)= @_; if ($dbname){ # application is asking for specific database - if ($dbname =~ /:/){ # Implies an Sql*NET connection + # We can use the 'user/passwd@machine' form of user. + # $TWO_TASK and $ORACLE_SID will be ignored in that case. - # We can use the 'user/passwd@machine' form of user: - $user .= '@'.$dbname; - # $TWO_TASK and $ORACLE_SID will be ignored + if ($dbname =~ /@/){ # Implies an Sql*NET connection + + $user .= $dbname; + } + elsif ($dbname =~ /:/){ # Implies an Sql*NET connection - } else { + $user .= '@'.$dbname; + } + else { # Is this a NON-Sql*NET connection (ORACLE_SID)? # Or is it an alias for an Sql*NET connection (TWO_TASK)? # Sadly the 'user/passwd@machine' form only works # for Sql*NET connections. - # We need a solution to this problem! - # Perhaps we need to read and parse oracle - # alias files like /etc/tnsnames.ora (/etc/sqlnet) - - $ENV{ORACLE_SID} = $dbname; - delete $ENV{TWO_TASK}; + load_oratab($drh) unless %DBD::Oracle::oratab; + + my $orahome = $DBD::Oracle::oratab{$dbname}; + if ($orahome) { # is in oratab == is local + warn "Changing ORACLE_HOME for $dbname" + if ($ENV{ORACLE_HOME} and $orahome ne $ENV{ORACLE_HOME}); + $ENV{ORACLE_HOME} = $orahome; + $ENV{ORACLE_SID} = $dbname; + delete $ENV{TWO_TASK}; + } + else { + $user .= '@'.$dbname; # assume it's an alias + } } } + unless($ENV{ORACLE_HOME}) { # last chance... + $ENV{ORACLE_HOME} = $oracle_home if $oracle_home; + my $msg = ($oracle_home) ? "set to $oracle_home" : "not set!"; + warn "ORACLE_HOME $msg\n"; + } + # create a 'blank' dbh my $this = DBI::_new_dbh($drh, { diff --git a/Oraperl.pm b/Oraperl.pm index 74545b70..29d5dc5f 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.23 1995/11/16 23:34:47 timbo Exp $ +# $Id: Oraperl.pm,v 1.25 1996/05/07 20:47:15 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -22,7 +22,7 @@ require DBI; # use Carp; require Exporter; -$VERSION = substr(q$Revision: 1.23 $, 10); +$VERSION = substr(q$Revision: 1.25 $, 10); @ISA = qw(Exporter); @@ -102,7 +102,7 @@ sub ora_open { sub ora_do { # error => undef - # 0 => "OK" (0 but true) + # 0 => "0E0" (0 but true) # >0 => >0 my($lda, $stmt) = @_; @@ -117,7 +117,7 @@ sub ora_do { # Perhaps oracle is smart enough not to execute them again? my $ret = $csr->execute; my $rows = $csr->rows; - ($rows == 0) ? "OK" : $rows; + ($rows == 0) ? "0E0" : $rows; } @@ -153,7 +153,7 @@ sub ora_types{ sub ora_autocommit { my($lda, $mode) = @_; $lda->{AutoCommit} = $mode; - "OK"; + "0E0"; } sub ora_version { my($sw) = DBI->internal; @@ -435,6 +435,10 @@ This function is roughly equivalent to &ora_close( &ora_open($lda, $statement) ) +B oraperl v2 used to return the string 'OK' to indicate +success with a zero numeric value. The Oraperl emulation now +uses the string '0E0' to achieve the same effect since it does +not cause any C<-w> warnings when used in a numeric context. =item * ora_logoff @@ -763,7 +767,7 @@ It is quite possible, indeed probable, that some differences in behaviour will exist. This should be confined to error handling. B differences in behaviour which are not documented here should be -reported to Tim.Bunce@ig.co.uk and CC'd to perldb-interest@fugue.com. +reported to Tim.Bunce@ig.co.uk and CC'd to dbi-users@fugue.com. =head1 SEE ALSO diff --git a/README b/README index 6da696e7..56556623 100644 --- a/README +++ b/README @@ -5,12 +5,16 @@ DBD::Oracle -- an Oracle 7 interface for Perl 5. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. - WARNING: THIS IS ALPHA SOFTWARE. - IT IS INCOMPLETE! - IT IS POSSIBLY UNRELIABLE! +* WARNING: THIS IS MOSTLY ALPHA SOFTWARE. Your mileage may vary. -The only currently supported interface is via Oraperl.pm, the oraperl -emulation layer. This is fairly complete. Execute "perldoc Oraperl" for info. + The only currently supported interface is via Oraperl.pm, the + oraperl emulation layer. This is fairly complete and stable. + Execute "perldoc Oraperl" for info. + +* THE ORAPERL EMULATION IS NO LONGER ALPHA. IT IS NOW FULLY RELEASED. + +NOTE: Automatic configuration from Oracle 7.3 is not yet working + (Oracle have reorganised the makefiles yet again!). BEFORE BUILDING, TESTING AND INSTALLING this you will need to: @@ -18,7 +22,7 @@ BEFORE BUILDING, TESTING AND INSTALLING this you will need to: Build, test and install Perl 5 (at least 5.002beta2). It is very important to test it and install it! - Build, test and install the DBI module (at least DBI 0.68). + Build, test and install the DBI module (at least DBI 0.69). It is very important to test it and install it! Remember to *read* the DBI README file! @@ -67,6 +71,7 @@ Please include: 3. The output of perl -V 4. If you get a core dump, try to include a stack trace from it. + I may not be able to help you much without it. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun make test after setting the environment variable PERL_DL_DEBUG to 2. @@ -137,6 +142,9 @@ AIX 3.2 Davide Migliavacca Joerg Senekowitsch +AIX 4.1 + Ken P. Nikolai + =============================================================================== Platform or Oracle Version specific notes: @@ -246,6 +254,25 @@ Environment: Solaris, GCC, Sanford Dickert Error: gcc: unrecognized option `-Y' Fix: Edit the Makefile to remove the space from '-Y P'. +------------------------------------------------------------------------------- +Environment: SVR4, stephen.zander@mckesson.com + +Error: can't load ./blib/arch/auto/DBD/Oracle/Oracle.so for module DBD::Oracle: +DynamicLinker:/usr/local/bin/perl:relocation error:symbol not found:setitimer +Fix: Try adding the '-lc' to $ORACLE_HOME/rdbms/lib/sysliblist (just +make sure it's not on a new line). + +------------------------------------------------------------------------------- +Environment: Solaris, GCC + +Error: Undefined symbols __cg92_used at link time. +Fix: If you're compiling Oracle applications with gcc on Solaris you need to +link with a file called $ORACLE_HOME/lib/__fstd.o. If you compile with the +SparcWorks compiler you need to add the command line option on -xcg92 +to resolve these symbol problems cleanly. + +Alligator Descartes + ------------------------------------------------------------------------------- Environment: SunOS 4.1.3, Oracle 7.1.3 John Carlson diff --git a/dbdimp.c b/dbdimp.c index 26614626..449489f8 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.14 1996/03/05 02:27:25 timbo Exp $ + $Id: dbdimp.c,v 1.15 1996/05/07 20:28:50 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -808,9 +808,9 @@ dbd_st_destroy(sth) imp_fbh_t *fbh = &imp_sth->fbh[i]; sv_free(fbh->sv); } - safefree(imp_sth->fbh); - safefree(imp_sth->fbh_cbuf); - safefree(imp_sth->statement); + Safefree(imp_sth->fbh); + Safefree(imp_sth->fbh_cbuf); + Safefree(imp_sth->statement); if (imp_sth->bind_names) { HV *hv = imp_sth->bind_names; diff --git a/t/main.t b/t/main.t deleted file mode 100755 index 901e21af..00000000 --- a/t/main.t +++ /dev/null @@ -1,136 +0,0 @@ -#!/usr/local/bin/perl -w - -use DBI; - -print "1..$tests\n"; - -print "ok 1\n"; - -BEGIN { $tests = 1 } -exit 0; - - -# ---------------------------------------------------------- - -# $Id: main.t,v 1.1 1995/10/24 02:39:35 timbo Exp $ -# -# Copyright (c) 1994, Tim Bunce -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -# This is just my DBI test script, it's not as clean as it could be :-) - -BEGIN { - print "$0 @ARGV\n"; - print q{DBI test application $Revision: 1.1 $}."\n"; - $| = 1; # chop($cwd = `pwd`); unshift(@INC, "."); -} - -use DBI; - -use Getopt::Long; -use strict; - -$main::opt_d = 1; -$main::opt_h = 0; -$main::opt_dbname = 'crgs'; - -GetOptions('d=i', 'h=i', 'dbname=s') - or die "Usage: $0 [-d n] [-h n] [drivername]\n"; - -my($driver) = $ARGV[0] || 'Oracle'; -print "opt_d=$main::opt_d\n" if $main::opt_d; -print "opt_h=$main::opt_h\n" if $main::opt_h; - -# Now ask for some information from the DBI Switch -my($switch) = DBI->internal; -$switch->debug($main::opt_h); # 2=detailed handle trace - -print "Switch: $switch->{'Attribution'}, $switch->{'Version'}\n"; - -$switch->{'DebugDispatch'} = $main::opt_d; # 2=detailed trace of all dispatching -print "DebugDispatch: $switch->{'DebugDispatch'}\n"; - -print "Available Drivers: ",join(", ",DBI->available_drivers()),"\n"; - -my($dbh); # first, get connected using either of these methods: -if (0){ - $dbh = DBI->connect($::opt_dbname, '', '', $driver); -}else{ - my($drh) = DBI->install_driver($driver); - print "Driver installed as $drh\n"; - $dbh = $drh->connect($::opt_dbname, 'system', 'manager'); -} -die "Unable for connect to $::opt_dbname: $DBI::errstr" - unless $dbh; - -$dbh->debug($main::opt_h); - -eval { run_test($dbh); }; -print "run_test($dbh) failed: '$@'\n"; - -print "$0 Done. (global destruction will follow)\n\n"; -exit 0; - - -sub run_test{ - my($dbh) = @_; - - print "Connected as $dbh\n\n"; - - $dbh->commit; - - my($cursor_a) = $dbh->prepare("select SYSDATE from DUAL"); - die "Prepare failed ($DBI::err): $DBI::errstr\n" unless $cursor_a; - - print "Prepared as $cursor_a\n"; - # $cursor_a->debug(2); - - my($cursor_b) = $dbh->prepare("select SYSDATE+1 from DUAL"); - die "Prepare failed ($DBI::err): $DBI::errstr\n" unless $cursor_b; - - print "Prepared as $cursor_b\n"; - # $cursor_b->debug(2); - - # Test object attributes - - print "Number of fields: $cursor_a->{'NUM_OF_FIELDS'}\n"; - print "Number of fields: $cursor_a->{'NUM_OF_FIELDS'}\n"; # now cached - -die "Test not fully implemented yet"; - - print "Data type of first field: $cursor_a->{'DATA_TYPE'}->[0]\n"; - print "Driver name: $cursor_a->{'Database'}->{'Driver'}->{'Name'}\n"; - - - $cursor_a->execute('/usr'); - $cursor_b->execute('/usr/spool'); - - print "Fetching data from both cursors:\n"; - my(@row_a, @row_b); - while((@row_a = $cursor_a->fetchrow) - && (@row_b = $cursor_b->fetchrow)){ - print "@row_a, @row_b\n"; - } - - print "\nAutomatic method parameter usage check:\n"; - eval { $dbh->commit('dummy') }; - warn "$@\n"; - - print "Preparing new \$cursor_a to replace current \$cursor_a:\n"; - - print "(we enable debugging on current to watch it's destruction)\n"; - $cursor_a->debug(2); - - $cursor_a = $dbh->prepare("select mtime,name from ?"); - $cursor_a->execute('../..'); - - print "Fetching one row from new \$cursor_a:\n"; - print join(' ',$cursor_a->fetchrow),"\n"; - $cursor_a->finish; - - print "test done (scoped objects will be destroyed now)\n"; -} - -# end. From 8f54744ff0487c677bb53941954d15f47b852cbd Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Mon, 20 May 1996 16:55:00 -0500 Subject: [PATCH 011/637] import DBD-Oracle 0.31 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.31 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.31.tar.gz --- Changes | 14 ++++++++++++++ Makefile.PL | 37 ++++++++++++++++++++++++++----------- Oracle.pm | 6 +++--- Oracle.xs | 11 +++++++++-- README | 13 +++++-------- Todo | 2 ++ dbdimp.c | 14 ++++++++------ 7 files changed, 67 insertions(+), 30 deletions(-) diff --git a/Changes b/Changes index 85f797d3..05e7e6b3 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,17 @@ +Changes in DBD::Oracle 0.31 (Oraperl 1.25), 20th May 1996 + + Makefile.PL for HP-UX now defaults to dynamic for hpux >= 10. + + execute (ora_bind/ora_do) now returns undef on error or the + number of rows affected (0 is returned as 0E0, hence true, for + okay but no rows affected or no row count available/applicable). + This matches the oraperl version 2.4 behaviour. + + Made an attempt at supporting Oracle 7.3 (e.g. include's in proc.mk) + Please let me know if it works (else supply patches to fix it :-) + + Fixed small memory leak in ora_titles etc functions. + Changes in DBD::Oracle 0.30, 7th May 1996 THE ORAPERL EMULATION LAYER IS NOW FORMALLY RELEASED (NO LONGER ALPHA). diff --git a/Makefile.PL b/Makefile.PL index 8900b163..51919cfb 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,5 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.35 1996/05/07 20:47:15 timbo Exp $ +# $Id: Makefile.PL,v 1.36 1996/05/20 21:53:26 timbo Exp $ require 5.002; @@ -63,10 +63,11 @@ my $oraclemk = $::opt_m || "$OH/proc/lib/proc.mk"; $oraclemk = "$OH/proc16/lib/proc16.mk" unless -f $oraclemk; die "Unable to locate proc.mk (use -m /path/to/proc.mk to specify)\n" unless -f $oraclemk; + my $linkwith = fetch_oci_macros(); $linkwith =~ s/-Y P,/-YP,/ if $Config{'cc'} =~ /gcc/; -print "Using $oraclemk version $MK{mkver}\n"; +print "Using $oraclemk (version ".($MK{mkver}||'unknown').")\n"; my $OCIINCLUDE = $MK{INCLUDE} || ''; @@ -79,11 +80,10 @@ $opts{OBJECT} = '$(O_FILES)'; # --- Handle special cases --- -# HP-UX cannot link a non-PIC object file into a shared library. +# HP-UX 9 cannot link a non-PIC object file into a shared library. # Since the # .a libs that Oracle supplies contain non-PIC object -# files, we sadly have to build static on HP-UX :( -# XXX Fixed for HP-UX 10 and Oracle 7.2 -if ($Config{osname} eq 'hpux') { +# files, we sadly have to build static on HP-UX 9 :( +if ($Config{osname} eq 'hpux' and $Config{osver} < 10) { print "Warning: forced to build static not dynamic on $Config{osname}\n"; print " See README and Makefile.PL for more information.\n"; $opts{LINKTYPE} = 'static'; @@ -105,7 +105,7 @@ if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess } # log key platform information to help me help you quickly -print "System: perl$] @Config{qw(myuname archname dlsrc)}\n"; +print "System: perl$] @Config{qw(myuname)}\n"; print "Compiler: @Config{qw(cc optimize ccflags)}\n"; print "Oracle proc.mk would have used these values but we override them:\n"; print " CC: $MK{CC}\n" if $MK{CC}; @@ -211,10 +211,10 @@ sub fetch_oci_macros { my $mkver = 0; my $linkwith = ''; my $lastline = ''; - open(ORACLEMK,"<$oraclemk") or die "open $oraclemk: $!\n"; - for(1; $_ = ; $lastline = $_){ + my @lines = read_inc_file($oraclemk); + for(1; $_ = shift(@lines); $lastline = $_){ # Join split lines but retain backwack and newlines: - $_ .= while(m/\\[\r\n]+$/); + $_ .= shift(@lines) while(m/\\[\r\n]+$/); chomp; push(@MK, '') if ($_ eq '' and $lastline ne ''); next unless $_; @@ -248,7 +248,6 @@ sub fetch_oci_macros { # have we seen enough now? ( this caused problems) # last if ($MK{OCILDLIBS} or (int($mkver)==1 and $MK{TTLIBS})); } - close(ORACLEMK); if ($MK{OCILDLIBS}) { $linkwith = '$(OCILDLIBS)'; @@ -268,5 +267,21 @@ sub fetch_oci_macros { $linkwith; } +sub read_inc_file { + my $file = shift; + my $fh = new FileHandle "<$file" or die "Unable to read $file: $!"; + my @lines; + while(<$fh>) { + # soak up while looking for include directives + push(@lines, $_), next + unless /^\s*include\s+(.*?)\s*$/m; + $file = $1; + # deal with "include $(ORACLE_HOME)/..." + $file =~ s/\$\((\w+)\)/$ENV{$1}/g; + push(@lines, read_inc_file($file)); + } + return @lines; +} + __END__ diff --git a/Oracle.pm b/Oracle.pm index 3024a738..0653a17c 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.27 1996/05/07 21:38:04 timbo Exp $ +# $Id: Oracle.pm,v 1.28 1996/05/20 21:53:26 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -14,8 +14,8 @@ my $oracle_home; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.30'; - my $Revision = substr(q$Revision: 1.27 $, 10); + $VERSION = '0.31'; + my $Revision = substr(q$Revision: 1.28 $, 10); require_version DBI 0.69; diff --git a/Oracle.xs b/Oracle.xs index adea7965..b63c962d 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -1,5 +1,5 @@ /* - $Id: Oracle.xs,v 1.39 1996/03/05 02:04:42 timbo Exp $ + $Id: Oracle.xs,v 1.40 1996/05/20 21:30:26 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -182,6 +182,7 @@ execute(sth, ...) SV * sth CODE: D_imp_sth(sth); + int retval; if (items > 1) { /* Handle binding supplied values to placeholders */ int i, error = 0; @@ -201,7 +202,13 @@ execute(sth, ...) XSRETURN_UNDEF; /* dbd_bind_ph already registered error */ } } - ST(0) = dbd_st_execute(sth) ? &sv_yes : &sv_no; + retval = dbd_st_execute(sth); + if (retval < 0) + XST_mUNDEF(0); /* error */ + else if (retval == 0) + XST_mPV(0, "0E0"); /* true but zero */ + else + XST_mIV(0, retval); /* typically 1 or rowcount */ void diff --git a/README b/README index 56556623..dec13ee6 100644 --- a/README +++ b/README @@ -5,19 +5,16 @@ DBD::Oracle -- an Oracle 7 interface for Perl 5. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. -* WARNING: THIS IS MOSTLY ALPHA SOFTWARE. Your mileage may vary. + +** WARNING: THIS IS MOSTLY ALPHA SOFTWARE. Your mileage may vary. ** +** THE ORAPERL EMULATION IS NO LONGER ALPHA. IT IS NOW FULLY RELEASED. ** The only currently supported interface is via Oraperl.pm, the oraperl emulation layer. This is fairly complete and stable. Execute "perldoc Oraperl" for info. -* THE ORAPERL EMULATION IS NO LONGER ALPHA. IT IS NOW FULLY RELEASED. - -NOTE: Automatic configuration from Oracle 7.3 is not yet working - (Oracle have reorganised the makefiles yet again!). - -BEFORE BUILDING, TESTING AND INSTALLING this you will need to: +*BEFORE* BUILDING, TESTING AND INSTALLING this you will need to: Build, test and install Perl 5 (at least 5.002beta2). It is very important to test it and install it! @@ -81,7 +78,7 @@ Tim. =============================================================================== Some Users of DBD::Oracle on Specific Platforms: -(this is out of date now, there are many users on many platforms) +(this is VERY out of date now, there are MANY users on many platforms) Solaris 1: Myself. diff --git a/Todo b/Todo index 1727a037..5af2ed9e 100644 --- a/Todo +++ b/Todo @@ -5,6 +5,8 @@ Return codes and error handling not quite same as oraperl? Many others. Remember, this is still alpha software! +Support shared libraries with Oracle 7.3 + =============================================================================== Below is just a personal dumping ground for thoughts and issues, don't diff --git a/dbdimp.c b/dbdimp.c index 449489f8..f4650f6d 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.15 1996/05/07 20:28:50 timbo Exp $ + $Id: dbdimp.c,v 1.17 1996/05/20 23:52:00 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -620,7 +620,7 @@ dbd_describe(h, imp_sth) int -dbd_st_execute(sth) +dbd_st_execute(sth) /* <0 is error, >=0 is ok (row count) */ SV *sth; { D_imp_sth(sth); @@ -628,16 +628,16 @@ dbd_st_execute(sth) if (!imp_sth->done_desc) { /* describe and allocate storage for results */ if (!dbd_describe(sth, imp_sth)) - return 0; /* dbd_describe already called ora_error() */ + return -1; /* dbd_describe already called ora_error() */ } /* Trigger execution of the statement */ if (oexec(imp_sth->cda)) { /* may change to oexfet later */ ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexec error"); - return 0; + return -1; } DBIc_ACTIVE_on(imp_sth); - return 1; + return imp_sth->cda->rpc; /* row count */ } @@ -903,7 +903,9 @@ dbd_st_FETCH(sth, keysv) return Nullsv; } if (cacheit) { /* cache for next time (via DBI quick_FETCH) */ - hv_store((HV*)SvRV(sth), key, kl, retsv, 0); + SV **svp = hv_fetch((HV*)SvRV(sth), key, kl, 1); + sv_free(*svp); + *svp = retsv; (void)SvREFCNT_inc(retsv); /* so sv_2mortal won't free it */ } return sv_2mortal(retsv); From 9476444cc10e2a324824cdd90b4de811bfae6657 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Wed, 5 Jun 1996 09:56:00 -0500 Subject: [PATCH 012/637] import DBD-Oracle 0.32 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.32 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.32.tar.gz --- Changes | 6 +++++ Makefile.PL | 69 +++++++++++++++++++++++++++++++++++++---------------- Oracle.pm | 8 ++++--- Oraperl.pm | 6 +++-- README | 6 ----- dbdimp.c | 12 ++++++---- 6 files changed, 70 insertions(+), 37 deletions(-) diff --git a/Changes b/Changes index 05e7e6b3..76428491 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,9 @@ +Changes in DBD::Oracle 0.32 (Oraperl 1.25), 30th May 1996 + + Fixed memory leak when FETCH'ing attributes. + Fixed Makefile.PL FileHandle problem (forgot 'use FileHandle;'). + Enhanced Makefile.PL support for Oracle 7.3. + Changes in DBD::Oracle 0.31 (Oraperl 1.25), 20th May 1996 Makefile.PL for HP-UX now defaults to dynamic for hpux >= 10. diff --git a/Makefile.PL b/Makefile.PL index 51919cfb..f1f2e345 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,5 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.36 1996/05/20 21:53:26 timbo Exp $ +# $Id: Makefile.PL,v 1.39 1996/05/30 13:49:31 timbo Exp $ require 5.002; @@ -8,6 +8,9 @@ use Getopt::Std; use Config; use strict; +# Some MakeMaker's forged some FileHandle methods +require FileHandle unless defined(&FileHandle::new); + use DBI 0.69; # This DBI must be installed before we can build a DBD my %opts = ( @@ -26,7 +29,7 @@ getopts('m:') or die "Invalid arguments"; # --- Introduction print "\nConfiguring DBD::Oracle ...\n"; -print "\n\tRemember to actually read the README file!\n\n"; +print "\n>>>\tRemember to actually *READ* the README file!\n\n"; # --- Where is Oracle installed... @@ -48,6 +51,7 @@ print "Using Oracle in $OH\n"; # Todo: add depend's for DBIXS etc # e.g., Oracle 7.x, Pro*C etc. How do we test for those? +# XXX out of date for Oracle 7.3.2. Sigh. warn "Warning: OCI (Pro*C) does not appear to be installed.\n" unless -f "$OH/lib/libocic.a" and -f "$OH/rdbms/demo/oratypes.h"; @@ -58,17 +62,19 @@ chomp $sysliblist; print "Oracle sysliblist: $sysliblist\n"; +my @mkfiles; my $oraclemk = $::opt_m || "$OH/proc/lib/proc.mk"; -# Apparently some Oracle 7.1.3 Pro*C makefiles might be here: +$oraclemk = "$OH/precomp/demo/proc/proc.mk" unless -f $oraclemk; # 7.3.x $oraclemk = "$OH/proc16/lib/proc16.mk" unless -f $oraclemk; die "Unable to locate proc.mk (use -m /path/to/proc.mk to specify)\n" unless -f $oraclemk; my $linkwith = fetch_oci_macros(); -$linkwith =~ s/-Y P,/-YP,/ if $Config{'cc'} =~ /gcc/; -print "Using $oraclemk (version ".($MK{mkver}||'unknown').")\n"; +print "Using @mkfiles ".($MK{mkver} ? "(version $MK{mkver})" : '')."\n"; +$linkwith = expand_mkvars($linkwith, 0); +$linkwith =~ s/-Y P,/-YP,/ if $Config{'cc'} =~ /gcc/; my $OCIINCLUDE = $MK{INCLUDE} || ''; @@ -78,13 +84,15 @@ $opts{INC} = "$OCIINCLUDE -I$OH/rdbms/demo -I\$(INSTALLSITEARCH)/DBI -I\$(INSTA $opts{dynamic_lib} = { OTHERLDFLAGS => '-L$(LIBHOME) $(COMPOBJS) '.$linkwith }; $opts{OBJECT} = '$(O_FILES)'; + + # --- Handle special cases --- # HP-UX 9 cannot link a non-PIC object file into a shared library. # Since the # .a libs that Oracle supplies contain non-PIC object # files, we sadly have to build static on HP-UX 9 :( if ($Config{osname} eq 'hpux' and $Config{osver} < 10) { - print "Warning: forced to build static not dynamic on $Config{osname}\n"; + print "Warning: forced to build static not dynamic on $Config{osname} $Config{osver}\n"; print " See README and Makefile.PL for more information.\n"; $opts{LINKTYPE} = 'static'; } @@ -112,10 +120,11 @@ print " CC: $MK{CC}\n" if $MK{CC}; print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; print " LDFLAGS: $MK{LDFLAGS}\n" if $MK{LDFLAGS}; print " LDSTRING: $MK{LDSTRING}\n" if $MK{LDSTRING}; +print "Linking with $linkwith\n"; # Assorted hints - these should be move to a hints subdirectory -print "See README notes about SPARCompiler on Solaris\n" - if -d "/opt/SUNWspro/bin" and $Config{osname} eq 'solaris'; +#print "See README notes about SPARCompiler on Solaris\n" +# if -d "/opt/SUNWspro/bin" and $Config{osname} eq 'solaris'; print "\n"; @@ -180,11 +189,11 @@ sub MY::post_constants { # ORACLE_HOME = '.$ENV{ORACLE_HOME}.' -# The following text has been extracted from '.$oraclemk.' +# The following text has been extracted from '."@mkfiles".' '.$MK.' -# End of extract from '.$oraclemk.' +# End of extract from '."@mkfiles".' # ################################################################### '; @@ -220,12 +229,10 @@ sub fetch_oci_macros { next unless $_; last if m/^\w+\s*:/; # gone too far, reached actual targets - # XXX temporary warning (for Oracle 7.3) till includes are supported - warn "$_ not processed\n" if m/^\s*include/i; - unless($MK{mkver}) { # still need to get version number # This is tough since some versions of proc.mk split the - # RCS header over three lines! Well that's Oracle for you. + # RCS header over three lines! Later versions don't even + # have one. That's Oracle for you. my $line = $_; $line =~ s/[\\\r\n]/ /g; $MK{mkver} = $mkver = $1 @@ -233,7 +240,7 @@ sub fetch_oci_macros { } # We always store values into %MK before checking %edit - $MK{$1} = $2 if m/^\s*(\w+)\s*=\s*(.*)/; + $MK{$1} = $2 if m/^\s*(\w+)\s*=\s*([\s\S]*)/; next if m/^\s*\.SUFFIXES/; @@ -244,9 +251,6 @@ sub fetch_oci_macros { } push(@MK, $_); - - # have we seen enough now? ( this caused problems) - # last if ($MK{OCILDLIBS} or (int($mkver)==1 and $MK{TTLIBS})); } if ($MK{OCILDLIBS}) { @@ -256,12 +260,15 @@ sub fetch_oci_macros { if ($MK{LLIBOCIC}) { $linkwith = '$(LLIBOCIC) $(TTLIBS)'; } else { + warn "Warning: Guessing what to link with.\n"; $linkwith = '-locic $(TTLIBS)'; # XXX GUESS HACK } } + elsif ($MK{PROLDLIBS}) { # Oracle 7.3.x + $linkwith = '$(PROLDLIBS)'; + } unless ($linkwith){ - warn "ERROR parsing $oraclemk (version '$MK{mkver}'):\n"; - warn "\tUnable to determine what to link with.\n"; + die "ERROR parsing $oraclemk: Unable to determine what to link with.\n"; } $MK = join("\n", @MK); $linkwith; @@ -271,17 +278,37 @@ sub read_inc_file { my $file = shift; my $fh = new FileHandle "<$file" or die "Unable to read $file: $!"; my @lines; + push(@mkfiles, $file); while(<$fh>) { # soak up while looking for include directives push(@lines, $_), next unless /^\s*include\s+(.*?)\s*$/m; $file = $1; # deal with "include $(ORACLE_HOME)/..." - $file =~ s/\$\((\w+)\)/$ENV{$1}/g; + # (can't use expand_mkvars() here) + $file =~ s/\$\(ORACLE_HOME\)/$ENV{ORACLE_HOME}/g; push(@lines, read_inc_file($file)); } return @lines; } +sub expand_mkvars { + my $string = shift; + my $strip = shift; + # warn "Expanding: $string\n"; + $string =~ s/\$\((\w+)\)/mkvar($1, $strip)/ge; + $string =~ s/\s*\\\n\s*/ /g; # merge continuations + $string =~ s/\s+/ /g; # shrink whitespace + $string; +} +sub mkvar { + my $var = shift; + my $strip = shift; + my $default = $strip ? '' : "\$($var)"; + # warn "Expand var: $var\n"; + return $default if $var eq 'LIBHOME'; + return $ENV{ORACLE_HOME} if $var eq 'ORACLE_HOME'; + $MK{$var} ? expand_mkvars($MK{$var}, $strip) : $default; +} __END__ diff --git a/Oracle.pm b/Oracle.pm index 0653a17c..94e4164f 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.28 1996/05/20 21:53:26 timbo Exp $ +# $Id: Oracle.pm,v 1.30 1996/05/30 13:23:39 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -7,6 +7,8 @@ my $oracle_home; +require 5.002; + { package DBD::Oracle; @@ -14,8 +16,8 @@ my $oracle_home; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.31'; - my $Revision = substr(q$Revision: 1.28 $, 10); + $VERSION = '0.32'; + my $Revision = substr(q$Revision: 1.30 $, 10); require_version DBI 0.69; diff --git a/Oraperl.pm b/Oraperl.pm index 29d5dc5f..975c2fd8 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.25 1996/05/07 20:47:15 timbo Exp $ +# $Id: Oraperl.pm,v 1.26 1996/05/30 13:24:24 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -18,11 +18,13 @@ package Oraperl; +require 5.002; + require DBI; # use Carp; require Exporter; -$VERSION = substr(q$Revision: 1.25 $, 10); +$VERSION = substr(q$Revision: 1.26 $, 10); @ISA = qw(Exporter); diff --git a/README b/README index dec13ee6..f7050ca0 100644 --- a/README +++ b/README @@ -245,12 +245,6 @@ If you get link errors like: ld: Undefined symbols _environ _dlopen _dlclose ... and the link command line includes '-L/usr/5lib -lc' then comment out the 'CLIBS= $(OTHERLIBS) -L/usr/5lib -lc' line in the Makefile. -------------------------------------------------------------------------------- -Environment: Solaris, GCC, Sanford Dickert - -Error: gcc: unrecognized option `-Y' -Fix: Edit the Makefile to remove the space from '-Y P'. - ------------------------------------------------------------------------------- Environment: SVR4, stephen.zander@mckesson.com diff --git a/dbdimp.c b/dbdimp.c index f4650f6d..941a7128 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.17 1996/05/20 23:52:00 timbo Exp $ + $Id: dbdimp.c,v 1.18 1996/05/30 13:42:11 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -260,7 +260,9 @@ dbd_db_FETCH(dbh, keysv) return Nullsv; } if (cacheit) { /* cache for next time (via DBI quick_FETCH) */ - hv_store((HV*)SvRV(dbh), key, kl, retsv, 0); + SV **svp = hv_fetch((HV*)SvRV(dbh), key, kl, 1); + sv_free(*svp); + *svp = retsv; (void)SvREFCNT_inc(retsv); /* so sv_2mortal won't free it */ } return sv_2mortal(retsv); @@ -883,19 +885,19 @@ dbd_st_FETCH(sth, keysv) if (kl==11 && strEQ(key, "ora_lengths")) { AV *av = newAV(); - retsv = newRV((SV*)av); + retsv = newRV(sv_2mortal((SV*)av)); while(--i >= 0) av_store(av, i, newSViv((IV)imp_sth->fbh[i].dsize)); } else if (kl==9 && strEQ(key, "ora_types")) { AV *av = newAV(); - retsv = newRV((SV*)av); + retsv = newRV(sv_2mortal((SV*)av)); while(--i >= 0) av_store(av, i, newSViv(imp_sth->fbh[i].dbtype)); } else if (kl==4 && strEQ(key, "NAME")) { AV *av = newAV(); - retsv = newRV((SV*)av); + retsv = newRV(sv_2mortal((SV*)av)); while(--i >= 0) av_store(av, i, newSVpv((char*)imp_sth->fbh[i].cbuf,0)); From f34a720d21b405b26846489bd1f0fe78da757d40 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Tue, 18 Jun 1996 18:17:00 -0500 Subject: [PATCH 013/637] import DBD-Oracle 0.33 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.33 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.33.tar.gz --- Changes | 10 ++++++ Makefile.PL | 92 +++++++++++++++++++++++++++++++++----------------- Oracle.pm | 12 ++++--- Oraperl.pm | 29 ++++++++++------ README | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++-- Todo | 3 ++ dbdimp.c | 4 +-- test.pl | 6 ++-- 8 files changed, 198 insertions(+), 54 deletions(-) diff --git a/Changes b/Changes index 76428491..bf931998 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,13 @@ +Changes in DBD::Oracle 0.33 (Oraperl 1.27), 19th June 1996 + + Added Makefile.PL -g option to enable debugging. + Added Makefile.PL -s symbol_name option to search for symbols. + Reorganised the way Makefile.PL uses MakeMaker liblist code. + Oraperl defaults to the 'safe' (normal) mode of using the DBI. + Oraperl uses sigtrap on SEGV & BUS to give a perl stack trace. + Added README notes about -g option, core files and stack traces. + Small change to $dbname/$user/$passwd logic in connect. + Changes in DBD::Oracle 0.32 (Oraperl 1.25), 30th May 1996 Fixed memory leak when FETCH'ing attributes. diff --git a/Makefile.PL b/Makefile.PL index f1f2e345..8cb0ded2 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,5 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.39 1996/05/30 13:49:31 timbo Exp $ +# $Id: Makefile.PL,v 1.41 1996/06/19 00:48:09 timbo Exp $ require 5.002; @@ -11,7 +11,11 @@ use strict; # Some MakeMaker's forged some FileHandle methods require FileHandle unless defined(&FileHandle::new); -use DBI 0.69; # This DBI must be installed before we can build a DBD +# This DBI must be installed before we can build a DBD. +# For those not using Dynamic loading this means building a +# new static perl in the DBI directory by saying 'make perl' +# and then using _that_ perl to make this one. +use DBI 0.70; my %opts = ( NAME => 'DBD::Oracle', @@ -23,13 +27,19 @@ my(@MK, %MK, $MK); # parsed macros from Oracle proc.mk file # Options, typically only used for debugging $::opt_m = ''; # path to proc.mk or oracle.mk file to read +$::opt_g = ''; # enable debugging (s/-O/-g/g) +$::opt_s = ''; # Find a symbol, Don't build a Makefile -getopts('m:') or die "Invalid arguments"; +getopts('gm:s:') or die "Invalid arguments"; + +$::opt_g &&= '-g'; # convert to actual string # --- Introduction -print "\nConfiguring DBD::Oracle ...\n"; -print "\n>>>\tRemember to actually *READ* the README file!\n\n"; + +print "\n Configuring DBD::Oracle ...\n +>>>\tRemember to actually *READ* the README file!\n +" unless $::opt_s; # --- Where is Oracle installed... @@ -48,40 +58,43 @@ print "Using Oracle in $OH\n"; # --- What Oracle is installed... # Todo: validate we have the right stuff installed -# Todo: add depend's for DBIXS etc -# e.g., Oracle 7.x, Pro*C etc. How do we test for those? - -# XXX out of date for Oracle 7.3.2. Sigh. warn "Warning: OCI (Pro*C) does not appear to be installed.\n" - unless -f "$OH/lib/libocic.a" - and -f "$OH/rdbms/demo/oratypes.h"; - -# read list of libs that oracle requires (eg -lm -lnsl) -my $sysliblist = `cat $OH/rdbms/lib/sysliblist`; -chomp $sysliblist; -print "Oracle sysliblist: $sysliblist\n"; - + unless (-f "$OH/lib/libocic.a" and -f "$OH/rdbms/demo/oratypes.h") + or (-f "$OH/precomp/demo/proc/proc.mk"); # 7.3.x my @mkfiles; my $oraclemk = $::opt_m || "$OH/proc/lib/proc.mk"; $oraclemk = "$OH/precomp/demo/proc/proc.mk" unless -f $oraclemk; # 7.3.x -$oraclemk = "$OH/proc16/lib/proc16.mk" unless -f $oraclemk; +$oraclemk = "$OH/proc16/lib/proc16.mk" unless -f $oraclemk; die "Unable to locate proc.mk (use -m /path/to/proc.mk to specify)\n" unless -f $oraclemk; my $linkwith = fetch_oci_macros(); - -print "Using @mkfiles ".($MK{mkver} ? "(version $MK{mkver})" : '')."\n"; - -$linkwith = expand_mkvars($linkwith, 0); +my $libhome = expand_mkvars($MK{LIBHOME}, 0, 0); +$linkwith = expand_mkvars($linkwith, 0, 0); $linkwith =~ s/-Y P,/-YP,/ if $Config{'cc'} =~ /gcc/; -my $OCIINCLUDE = $MK{INCLUDE} || ''; +# get a cut down $linkwith to pass to MakeMaker liblist +my $linkwith_s = expand_mkvars($linkwith, 1, 1); +# extract object files, keep for use later +my @linkwith_o; +push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.o)\b//; + +if ($::opt_s) { + warn "Searching for symbol '$::opt_s' in $libhome ...\n"; + system(qq{ cd $libhome; for i in lib*.[as]* *.o; + do echo " searching \$i ..."; nm \$i | grep $::opt_s; + done + }); + warn "Search done.\n"; + exit; +} -$opts{LIBS} = [ $sysliblist ]; +my $OCIINCLUDE = $MK{INCLUDE} || ''; +$opts{LIBS} = [ "-L$libhome $linkwith_s" ]; # INSTALLARCHLIB included _after_ INSTALLSITEARCH for transition period $opts{INC} = "$OCIINCLUDE -I$OH/rdbms/demo -I\$(INSTALLSITEARCH)/DBI -I\$(INSTALLARCHLIB)/DBI"; -$opts{dynamic_lib} = { OTHERLDFLAGS => '-L$(LIBHOME) $(COMPOBJS) '.$linkwith }; +$opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o \$(COMPOBJS)" }; $opts{OBJECT} = '$(O_FILES)'; @@ -101,7 +114,8 @@ $opts{DEFINE} = '-Wall -pedantic -Wno-comment -Wtraditional' if $Config{cc} eq 'gcc'; $opts{DEFINE} .= '-Xa' if $Config{cc} eq 'clcc'; # CenterLine CC - +warn "WARNING: Your GNU C compiler is very old. Please upgrade.\n" + if ($Config{gccversion} and $Config{gccversion} =~ m/^(1|2\.[1-5])/); # Set some private WriteMakefile options if this is 'me' :-) if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess @@ -120,7 +134,7 @@ print " CC: $MK{CC}\n" if $MK{CC}; print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; print " LDFLAGS: $MK{LDFLAGS}\n" if $MK{LDFLAGS}; print " LDSTRING: $MK{LDSTRING}\n" if $MK{LDSTRING}; -print "Linking with $linkwith\n"; +print "Linking with @linkwith_o $linkwith_s\n"; # Assorted hints - these should be move to a hints subdirectory #print "See README notes about SPARCompiler on Solaris\n" @@ -271,7 +285,8 @@ sub fetch_oci_macros { die "ERROR parsing $oraclemk: Unable to determine what to link with.\n"; } $MK = join("\n", @MK); - $linkwith; + print "Using @mkfiles ".($MK{mkver} ? "(version $MK{mkver})" : '')."\n"; + return $linkwith; } sub read_inc_file { @@ -295,20 +310,35 @@ sub read_inc_file { sub expand_mkvars { my $string = shift; my $strip = shift; + my $backtick = shift; # warn "Expanding: $string\n"; - $string =~ s/\$\((\w+)\)/mkvar($1, $strip)/ge; + $string =~ s/\$\((\w+)\)/mkvar($1, $strip, $backtick)/ge; $string =~ s/\s*\\\n\s*/ /g; # merge continuations + $string =~ s/`(.*?)`/`$1`/eg if $backtick; $string =~ s/\s+/ /g; # shrink whitespace $string; } sub mkvar { my $var = shift; my $strip = shift; + my $backtick = shift; my $default = $strip ? '' : "\$($var)"; # warn "Expand var: $var\n"; - return $default if $var eq 'LIBHOME'; + return '$(LIBHOME)' if $var eq 'LIBHOME'; # gets too noisy return $ENV{ORACLE_HOME} if $var eq 'ORACLE_HOME'; - $MK{$var} ? expand_mkvars($MK{$var}, $strip) : $default; + $MK{$var} ? expand_mkvars($MK{$var}, $strip, $backtick) : $default; +} + + +{ # If perl Makefile.PL *-g* then switch on debugging + package MY; # SUPER needs package context, $self is not sufficient + sub const_cccmd { + my($self) = shift; + local($_) = $self->SUPER::const_cccmd(@_); + s/\s-O\d?\b/ -g/g if $::opt_g; + $_; + } + } __END__ diff --git a/Oracle.pm b/Oracle.pm index 94e4164f..ce994d5b 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.30 1996/05/30 13:23:39 timbo Exp $ +# $Id: Oracle.pm,v 1.31 1996/06/19 00:48:09 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -16,8 +16,8 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.32'; - my $Revision = substr(q$Revision: 1.30 $, 10); + $VERSION = '0.33'; + my $Revision = substr(q$Revision: 1.31 $, 10); require_version DBI 0.69; @@ -91,11 +91,13 @@ require 5.002; if ($dbname =~ /@/){ # Implies an Sql*NET connection - $user .= $dbname; + $user = "$user/$auth$dbname"; + $auth = ""; } elsif ($dbname =~ /:/){ # Implies an Sql*NET connection - $user .= '@'.$dbname; + $user = "$user/$auth".'@'.$dbname; + $auth = ""; } else { diff --git a/Oraperl.pm b/Oraperl.pm index 975c2fd8..46b1844f 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.26 1996/05/30 13:24:24 timbo Exp $ +# $Id: Oraperl.pm,v 1.27 1996/06/19 00:48:09 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -20,11 +20,10 @@ package Oraperl; require 5.002; -require DBI; -# use Carp; -require Exporter; +use DBI 0.69; +use Exporter; -$VERSION = substr(q$Revision: 1.26 $, 10); +$VERSION = substr(q$Revision: 1.27 $, 10); @ISA = qw(Exporter); @@ -39,7 +38,17 @@ $VERSION = substr(q$Revision: 1.26 $, 10); $debug = 0 unless defined $debug; $debugdbi = 0; -# $safe # set true before 'use Oraperl' if needed. +# $safe # set true/false before 'use Oraperl' if needed. +$safe = 1 unless defined $safe; + +# Help those who get core dumps from non-'safe' Oraperl (bad cursors) +use sigtrap qw(ILL); +$SIG{BUS} = $SIG{SEGV} = sub { + print STDERR "Add BEGIN { \$Oraperl::safe=1 } above 'use Oraperl'.\n" + unless $safe; + goto &sigtrap::trap; +}; + if ($debugdbi){ my $sw = DBI->internal; @@ -284,12 +293,10 @@ Example: $lda = &ora_login('personnel', 'scott', 'tiger') || die $ora_errstr; This function is equivalent to the OCI olon and orlon functions. -Really, it should have been called &ora_logon(), but I made the mistake -a long time ago and fixing it would break too many existing programs. -B note that TNS aliases are currently not supported. If 'foo' is -an alias for 'T:host:foo' then you must explicitly use 'T:host:foo' (or -an empty string and rely on ORACLE_SID or TWO_TASK environment variables). +B note that a name is assumed to be a TNS alias if it does not +appear as the name of a SID in /etc/oratab or /var/opt/oracle/oratab. +See the code in Oracle.pm for the full logic of database name handling. B Since the returned $lda is a Perl5 reference the database login identifier is now automatically released if $lda is overwritten or goes diff --git a/README b/README index f7050ca0..0683b895 100644 --- a/README +++ b/README @@ -67,15 +67,84 @@ Please include: 3. The output of perl -V -4. If you get a core dump, try to include a stack trace from it. - I may not be able to help you much without it. - If the stack trace mentions XS_DynaLoader_dl_load_file then rerun +4. If you get a core dump when using Oraperl try adding this *before* + your 'use Oraperl' line: BEGIN { $Oraperl::safe = 1 } + (unless your version of Oraperl.pm already has $safe=1 in it). + +5. If you still get a core dump rebuild DBD::Oracle with debugging + enabled by executing: perl Makefile.PL -g (note the -g option) + then rerun the code to get a new core dump file, finally use a + debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. + NOTE: I may not be able to help you much without a stack trace! + It is worth fetching and building the GNU GDB debugger (4.15) if + you don't have a good debugger on your system. If desparate try: + make perl; ./perl script; echo '$c' | adb ./perl core + +6. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun make test after setting the environment variable PERL_DL_DEBUG to 2. Regards, Tim. +=============================================================================== +Examples and other info: + +ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources/...... + +Jeff Stander's stuff stands out for Oraperl. +Directories of interest might be + /pub/Oracle/sources + /pub/Oracle/sources/jstander + /pub/Oracle/sources/jstander/distrib + /pub/Oracle/sources/jstander/tsmlib + /pub/Oracle/sources/jstander/wdbex + /pub/Oracle/sources/web/scripts + /pub/Oracle/sources/dba + /pub/Oracle/sources/dba/imp2sql7 + /pub/Oracle/sources/Lonnroth + /pub/Oracle/sources/harrison + +Send stuff for the archive in + [.{cpio|tar|zip}][.{gz|Z|zip}].uu + format if by mail to me (orafaq@bf.rmit.edu.au) + And drop the .uu if using ftp, putting file(s) in + ftp://ftp.bf.rmit.edu.au/incoming/Oracle + +http://www.bf.rmit.edu.au/~orafaq/perlish.html +ftp://ftp.bf.rmit.edu.au/pub/perl/db +ftp://ftp.bf.rmit.edu.au/pub/Oracle +ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources +ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip + +ftp://ftp.demon.co.uk/pub/perl/db/perl4/oraperl/ + +=============================================================================== +Example for reading LONG fields via blob_read: + +my $sql = "SELECT long_field FROM table_name WHERE id = :1"; +my $csr = ora_open($lda, $sql) or die $ora_errstr; +ora_bind($csr, $id) or die $ora_errstr; +# ora_fetch() needs to be called in an array context +my (@data) = ora_fetch($csr); +my ($frag, $blob, $length, $ll, $offset); +$blob = ''; +$length = 4096; # use benchmarks to get best value for you +$offset = 0; +while (1) +{ + $frag = $csr->blob_read(0, $offset, $length); + last unless defined $frag; + $ll = length $frag; + last unless $ll; + $blob .= $frag; + $offset += $ll; +} +print $blob; + +With thanks to james.taylor@srs.gov and desilva@ind70.industry.net. + + =============================================================================== Some Users of DBD::Oracle on Specific Platforms: (this is VERY out of date now, there are MANY users on many platforms) @@ -146,6 +215,27 @@ AIX 4.1 =============================================================================== Platform or Oracle Version specific notes: +------------------------------------------------------------------------------- +Oracle 7.3 on Solaris 2.5 (maybe others): + + libc internal error: _rmutex_unlock: rmutex not held. + +- Try passing explicit db sid name to ora_login or connect. +- Try removing clntsh from the list of libraries to link to (edit Makefile). +- Try adding -lthread to the list of libraries to link to (edit Makefile). + +If any of these work please let me know (include full version info). + +------------------------------------------------------------------------------- +Bad free() warnings: + +These are generally cause by problems in oracle own library code. +You can use this code to hide them: + + $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Bad free/ } + +But please let me know if you have this problem (include full version info) . + ------------------------------------------------------------------------------- HP-UX: Terry Greenlaw diff --git a/Todo b/Todo index 5af2ed9e..7fe2878e 100644 --- a/Todo +++ b/Todo @@ -7,6 +7,9 @@ Many others. Remember, this is still alpha software! Support shared libraries with Oracle 7.3 +Add a mechanism for fork style tasks so dbh of parent +doesn't get freed by child. + =============================================================================== Below is just a personal dumping ground for thoughts and issues, don't diff --git a/dbdimp.c b/dbdimp.c index 941a7128..701bae96 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.18 1996/05/30 13:42:11 timbo Exp $ + $Id: dbdimp.c,v 1.19 1996/06/19 00:48:09 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -359,7 +359,7 @@ dbd_preparse(imp_sth, statement) imp_sth->statement = (char*)safemalloc(strlen(statement) + 100); /* initialise phs ready to be cloned per placeholder */ - memset(&phs_tpl, sizeof(phs_tpl), 0); + memset(&phs_tpl, 0, sizeof(phs_tpl)); phs_tpl.ftype = 1; /* VARCHAR2 */ src = statement; diff --git a/test.pl b/test.pl index 1a56b5ff..bdeee971 100755 --- a/test.pl +++ b/test.pl @@ -1,6 +1,6 @@ #!/usr/local/bin/perl -w -# $Id: test.pl,v 1.20 1996/01/29 22:33:23 timbo Exp $ +# $Id: test.pl,v 1.21 1996/06/19 00:48:09 timbo Exp $ # # Copyright (c) 1995, Tim Bunce # @@ -10,7 +10,7 @@ require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.20 $}."\n"; +print q{Oraperl test application $Revision: 1.21 $}."\n"; $opt_d = 0; # debug $opt_l = 0; # log @@ -39,6 +39,8 @@ warn "ora_login: $ora_errno: $ora_errstr\n"; warn "\nHave you set the environment variable ORACLE_USERID ?\n" if ($ora_errno == 1017); # ORA-01017: invalid username/password + warn "\nHave you included your password in ORACLE_USERID ? (e.g., 'user/passwd')\n" + if ($ora_errno == 1017 and $dbuser !~ m:/:); warn "\nHave you set the environment variable ORACLE_SID or TWO_TASK?\n" if ($ora_errno == 2700); # error translating ORACLE_SID warn "\nORACLE_SID or TWO_TASK possibly not right, or server not running.\n" From bbfd8de8e97e9e2bce3a207532718915d046dfa0 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Fri, 21 Jun 1996 19:14:00 -0500 Subject: [PATCH 014/637] import DBD-Oracle 0.34 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.34 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.34.tar.gz --- Changes | 12 ++++++++++ Makefile.PL | 10 +++++++- Oracle.pm | 6 ++--- Oraperl.pm | 24 ++++++++++++++++--- README | 69 +++++++++++++++++++++++++++++++++-------------------- 5 files changed, 88 insertions(+), 33 deletions(-) diff --git a/Changes b/Changes index bf931998..10ef1b9b 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,15 @@ +Changes in DBD::Oracle 0.34 (Oraperl 1.28), 21st June 1996 + + Workaround Solaris 2 bug #1224467 (_rmutex_unlock). + With many thanks to James Taylor. + + Added 'Bad free()' warning suppression to ora_logon and + ora_logoff(). Setting the DBD_DUMP environment variable + will trigger a (handy for me) core dump if a Bad free + warning is detected. + + Further additions to the README about Bad free()'s. + Changes in DBD::Oracle 0.33 (Oraperl 1.27), 19th June 1996 Added Makefile.PL -g option to enable debugging. diff --git a/Makefile.PL b/Makefile.PL index 8cb0ded2..248f703f 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,5 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.41 1996/06/19 00:48:09 timbo Exp $ +# $Id: Makefile.PL,v 1.44 1996/06/21 21:19:48 timbo Exp $ require 5.002; @@ -90,6 +90,13 @@ if ($::opt_s) { exit; } +if ($Config{osname} eq 'solaris' and $Config{osver} == 2.5 + and $linkwith_s =~ /-lthread/) { + warn "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; + warn "Deleting -lthread from link list as a possible workround.\n"; + $linkwith_s =~ s/\s*-lthread\b/ /g; +} + my $OCIINCLUDE = $MK{INCLUDE} || ''; $opts{LIBS} = [ "-L$libhome $linkwith_s" ]; # INSTALLARCHLIB included _after_ INSTALLSITEARCH for transition period @@ -114,6 +121,7 @@ $opts{DEFINE} = '-Wall -pedantic -Wno-comment -Wtraditional' if $Config{cc} eq 'gcc'; $opts{DEFINE} .= '-Xa' if $Config{cc} eq 'clcc'; # CenterLine CC + warn "WARNING: Your GNU C compiler is very old. Please upgrade.\n" if ($Config{gccversion} and $Config{gccversion} =~ m/^(1|2\.[1-5])/); diff --git a/Oracle.pm b/Oracle.pm index ce994d5b..ea17f4a1 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.31 1996/06/19 00:48:09 timbo Exp $ +# $Id: Oracle.pm,v 1.32 1996/06/21 18:25:00 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -16,8 +16,8 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.33'; - my $Revision = substr(q$Revision: 1.31 $, 10); + $VERSION = '0.34'; + my $Revision = substr(q$Revision: 1.32 $, 10); require_version DBI 0.69; diff --git a/Oraperl.pm b/Oraperl.pm index 46b1844f..eb26f2ee 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.27 1996/06/19 00:48:09 timbo Exp $ +# $Id: Oraperl.pm,v 1.28 1996/06/21 18:25:00 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -23,7 +23,7 @@ require 5.002; use DBI 0.69; use Exporter; -$VERSION = substr(q$Revision: 1.27 $, 10); +$VERSION = substr(q$Revision: 1.28 $, 10); @ISA = qw(Exporter); @@ -38,6 +38,7 @@ $VERSION = substr(q$Revision: 1.27 $, 10); $debug = 0 unless defined $debug; $debugdbi = 0; +my $bad_free_dump = $ENV{DBD_DUMP}; # $safe # set true/false before 'use Oraperl' if needed. $safe = 1 unless defined $safe; @@ -75,6 +76,15 @@ sub _func_ref { \&{"${pkg}::$name"}; } +sub _warn { + my $prev_warn = shift; + if ($_[0] =~ /free\(\) ignored/) { + dump if $bad_free_dump; + return; + } + $prev_warn ? &$prev_warn(@_) : warn @_; +} + # ----------------------------------------------------------------- # @@ -83,9 +93,17 @@ sub _func_ref { sub ora_login { my($system_id, $name, $password) = @_; + local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local + local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; $Oraperl::drh->connect($system_id, $name, $password); } -*ora_logoff = _func_ref('db::disconnect'); +sub ora_logoff { + my($dbh) = @_; + local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local + local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; + $dbh->disconnect(); +} + # ----------------------------------------------------------------- diff --git a/README b/README index 0683b895..dc416ebc 100644 --- a/README +++ b/README @@ -5,8 +5,8 @@ DBD::Oracle -- an Oracle 7 interface for Perl 5. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. - ** WARNING: THIS IS MOSTLY ALPHA SOFTWARE. Your mileage may vary. ** + ** THE ORAPERL EMULATION IS NO LONGER ALPHA. IT IS NOW FULLY RELEASED. ** The only currently supported interface is via Oraperl.pm, the @@ -90,9 +90,16 @@ Tim. =============================================================================== Examples and other info: -ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources/...... +DBI 'home page': http://www.hermetica.com/technologia/DBI + +Master archive site for Perl DB information: + ftp://ftp.demon.co.uk/pub/perl/db/ +Mailing list archive: /DBI/perldb-interest/ +Perl 4 Oraperl (v2.4) /perl4/oraperl/ -Jeff Stander's stuff stands out for Oraperl. +ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources/... + +Jeff Stander's stuff stands out for Oraperl: Directories of interest might be /pub/Oracle/sources /pub/Oracle/sources/jstander @@ -117,30 +124,29 @@ ftp://ftp.bf.rmit.edu.au/pub/Oracle ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip -ftp://ftp.demon.co.uk/pub/perl/db/perl4/oraperl/ =============================================================================== Example for reading LONG fields via blob_read: -my $sql = "SELECT long_field FROM table_name WHERE id = :1"; -my $csr = ora_open($lda, $sql) or die $ora_errstr; -ora_bind($csr, $id) or die $ora_errstr; -# ora_fetch() needs to be called in an array context -my (@data) = ora_fetch($csr); -my ($frag, $blob, $length, $ll, $offset); -$blob = ''; -$length = 4096; # use benchmarks to get best value for you -$offset = 0; -while (1) -{ - $frag = $csr->blob_read(0, $offset, $length); - last unless defined $frag; - $ll = length $frag; - last unless $ll; - $blob .= $frag; - $offset += $ll; -} -print $blob; + my $sql = "SELECT long_field FROM table_name WHERE id = :1"; + my $csr = ora_open($lda, $sql) or die $ora_errstr; + ora_bind($csr, $id) or die $ora_errstr; + # ora_fetch() needs to be called in an array context + my (@data) = ora_fetch($csr); + my ($frag, $blob, $length, $ll, $offset); + $blob = ''; + $length = 4096; # use benchmarks to get best value for you + $offset = 0; + while (1) + { + $frag = $csr->blob_read(0, $offset, $length); + last unless defined $frag; + $ll = length $frag; + last unless $ll; + $blob .= $frag; + $offset += $ll; + } + print $blob; With thanks to james.taylor@srs.gov and desilva@ind70.industry.net. @@ -220,21 +226,32 @@ Oracle 7.3 on Solaris 2.5 (maybe others): libc internal error: _rmutex_unlock: rmutex not held. +Try each of these in turn: +- Try removing -lthread from the list of libraries to link with (edit Makefile). - Try passing explicit db sid name to ora_login or connect. - Try removing clntsh from the list of libraries to link to (edit Makefile). -- Try adding -lthread to the list of libraries to link to (edit Makefile). If any of these work please let me know (include full version info). ------------------------------------------------------------------------------- Bad free() warnings: -These are generally cause by problems in oracle own library code. +These are generally cause by problems in Oracle's own library code. You can use this code to hide them: $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Bad free/ } -But please let me know if you have this problem (include full version info) . +But please let me know if you have this problem (include full version info). +Rather than simply hiding it it would be much better to help me fix it! +Follow the instructions in step 5 above (for generating a version of +DBD::Oracle with debugging enabled) and then use the following code +to generate a core dump at the point the bad free happens. + + $SIG{__WARN__} = sub { $_[0] =~ /^Bad free/ ? dump : warn $_[0] } + +Follow the instructions in step 5 above for getting a stack trace from +the core file and then send it to me along with the other information +requested in the 'If you have problems' section. ------------------------------------------------------------------------------- HP-UX: Terry Greenlaw From df81ef4f706e306facbac890d516e8bebcb61e6d Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Fri, 21 Jun 1996 19:15:00 -0500 Subject: [PATCH 015/637] import DBD-Oracle 0.35 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.35 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.35.tar.gz --- Changes | 5 +++++ Makefile.PL | 12 ++++++++++-- Oracle.pm | 6 +++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index 10ef1b9b..24dc8800 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,8 @@ +Changes in DBD::Oracle 0.35 (Oraperl 1.28), 21st June 1996 + + Fixed broken Solaris 2.5 check in Makefile.PL. + Added ld path to the log. + Changes in DBD::Oracle 0.34 (Oraperl 1.28), 21st June 1996 Workaround Solaris 2 bug #1224467 (_rmutex_unlock). diff --git a/Makefile.PL b/Makefile.PL index 248f703f..9dd6d505 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,5 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.44 1996/06/21 21:19:48 timbo Exp $ +# $Id: Makefile.PL,v 1.45 1996/06/22 02:09:29 timbo Exp $ require 5.002; @@ -90,7 +90,7 @@ if ($::opt_s) { exit; } -if ($Config{osname} eq 'solaris' and $Config{osver} == 2.5 +if ($Config{osname} eq 'solaris' and $Config{osvers} == 2.5 and $linkwith_s =~ /-lthread/) { warn "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; warn "Deleting -lthread from link list as a possible workround.\n"; @@ -137,6 +137,7 @@ if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess # log key platform information to help me help you quickly print "System: perl$] @Config{qw(myuname)}\n"; print "Compiler: @Config{qw(cc optimize ccflags)}\n"; +print "Linker: ". find_bin('ld') ."\n"; print "Oracle proc.mk would have used these values but we override them:\n"; print " CC: $MK{CC}\n" if $MK{CC}; print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; @@ -337,6 +338,13 @@ sub mkvar { $MK{$var} ? expand_mkvars($MK{$var}, $strip, $backtick) : $default; } +sub find_bin{ + my $bin = shift; + foreach(split(/:/, $ENV{PATH})){ + return "$_/$bin" if -x "$_/$bin"; + } + return "<$bin not found>"; +} { # If perl Makefile.PL *-g* then switch on debugging package MY; # SUPER needs package context, $self is not sufficient diff --git a/Oracle.pm b/Oracle.pm index ea17f4a1..d6215ce7 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.32 1996/06/21 18:25:00 timbo Exp $ +# $Id: Oracle.pm,v 1.33 1996/06/22 02:11:52 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -16,8 +16,8 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.34'; - my $Revision = substr(q$Revision: 1.32 $, 10); + $VERSION = '0.35'; + my $Revision = substr(q$Revision: 1.33 $, 10); require_version DBI 0.69; From fc42031a189e32d4a1d9f5b8307b8e20455468f9 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Tue, 9 Jul 1996 19:45:00 -0500 Subject: [PATCH 016/637] import DBD-Oracle 0.36 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.36 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.36.tar.gz --- Changes | 8 ++++++++ Makefile.PL | 19 +++++++++++-------- Oracle.pm | 6 +++--- README | 15 +++++++++------ dbdimp.c | 10 +++++----- 5 files changed, 36 insertions(+), 22 deletions(-) diff --git a/Changes b/Changes index 24dc8800..c78b003b 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,11 @@ +Changes in DBD::Oracle 0.36 (Oraperl 1.28), 10th July 1996 + + Fixed bind_param ora_type attribute. + Fixed preparse to allocate enough memory for worst case. + Fixed broken HP-UX 10 check in Makefile.PL. + Other assorted Makefile.PL improvements. + (Many thanks to those who sent in fixes.) + Changes in DBD::Oracle 0.35 (Oraperl 1.28), 21st June 1996 Fixed broken Solaris 2.5 check in Makefile.PL. diff --git a/Makefile.PL b/Makefile.PL index 9dd6d505..9eb61926 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,7 +1,7 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.45 1996/06/22 02:09:29 timbo Exp $ +# $Id: Makefile.PL,v 1.46 1996/07/10 02:27:52 timbo Exp $ -require 5.002; +BEGIN { require 5.003 } # 5.003 fixes very important bugs use ExtUtils::MakeMaker 5.16, qw(&WriteMakefile $Verbose); use Getopt::Std; @@ -15,7 +15,7 @@ require FileHandle unless defined(&FileHandle::new); # For those not using Dynamic loading this means building a # new static perl in the DBI directory by saying 'make perl' # and then using _that_ perl to make this one. -use DBI 0.70; +use DBI 0.71; my %opts = ( NAME => 'DBD::Oracle', @@ -72,13 +72,16 @@ die "Unable to locate proc.mk (use -m /path/to/proc.mk to specify)\n" my $linkwith = fetch_oci_macros(); my $libhome = expand_mkvars($MK{LIBHOME}, 0, 0); $linkwith = expand_mkvars($linkwith, 0, 0); -$linkwith =~ s/-Y P,/-YP,/ if $Config{'cc'} =~ /gcc/; +$linkwith =~ s/-Y P,/-YP,/g if $Config{'cc'} =~ /gcc/; +$linkwith =~ s:-R /:-R/:g if $Config{osname} eq 'solaris'; # get a cut down $linkwith to pass to MakeMaker liblist my $linkwith_s = expand_mkvars($linkwith, 1, 1); +# convert "/full/path/libFOO.a" into "-L/full/path -lFOO" +$linkwith_s =~ s!([/\w.]+)/lib(\w+).a!-L$1 -l$2!g; # extract object files, keep for use later my @linkwith_o; -push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.o)\b//; +push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; if ($::opt_s) { warn "Searching for symbol '$::opt_s' in $libhome ...\n"; @@ -111,8 +114,8 @@ $opts{OBJECT} = '$(O_FILES)'; # HP-UX 9 cannot link a non-PIC object file into a shared library. # Since the # .a libs that Oracle supplies contain non-PIC object # files, we sadly have to build static on HP-UX 9 :( -if ($Config{osname} eq 'hpux' and $Config{osver} < 10) { - print "Warning: forced to build static not dynamic on $Config{osname} $Config{osver}\n"; +if ($Config{osname} eq 'hpux' and $Config{osvers} < 10) { + print "Warning: forced to build static not dynamic on $Config{osname} $Config{osvers}\n"; print " See README and Makefile.PL for more information.\n"; $opts{LINKTYPE} = 'static'; } @@ -333,7 +336,7 @@ sub mkvar { my $backtick = shift; my $default = $strip ? '' : "\$($var)"; # warn "Expand var: $var\n"; - return '$(LIBHOME)' if $var eq 'LIBHOME'; # gets too noisy + return '$(LIBHOME)' if $var eq 'LIBHOME' && !$strip; # gets noisy return $ENV{ORACLE_HOME} if $var eq 'ORACLE_HOME'; $MK{$var} ? expand_mkvars($MK{$var}, $strip, $backtick) : $default; } diff --git a/Oracle.pm b/Oracle.pm index d6215ce7..f8392f82 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.33 1996/06/22 02:11:52 timbo Exp $ +# $Id: Oracle.pm,v 1.34 1996/07/10 02:27:52 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -16,8 +16,8 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.35'; - my $Revision = substr(q$Revision: 1.33 $, 10); + $VERSION = '0.36'; + my $Revision = substr(q$Revision: 1.34 $, 10); require_version DBI 0.69; diff --git a/README b/README index dc416ebc..ce4528e0 100644 --- a/README +++ b/README @@ -13,6 +13,8 @@ DBD::Oracle -- an Oracle 7 interface for Perl 5. oraperl emulation layer. This is fairly complete and stable. Execute "perldoc Oraperl" for info. + PLEASE READ THE ENTIRE README FILE! + *BEFORE* BUILDING, TESTING AND INSTALLING this you will need to: @@ -97,6 +99,10 @@ Master archive site for Perl DB information: Mailing list archive: /DBI/perldb-interest/ Perl 4 Oraperl (v2.4) /perl4/oraperl/ +Searchable index of the dbi-users mailing list: +http://www.coe.missouri.edu/~faq/lists/dbiusers/ + + ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources/... Jeff Stander's stuff stands out for Oraperl: @@ -288,12 +294,12 @@ version of the DBI in order that it be automatically included when you do the 'make perl' above. ------------------------------------------------------------------------------- -Oracle 7.1.3: Syntax error in oratypes.h +Oracle 7.1: Syntax error in oratypes.h Try uncommenting the '#define signed' line in Oracle.h ------------------------------------------------------------------------------- -Oracle 7.1.3/4: Connection takes a long time and may coredump +Oracle 7.1 and 7.2: Connection takes a long time and may coredump Oracle bug number: 227321 related to changing the environment before connecting to oracle. @@ -314,10 +320,7 @@ Edited from Message-ID: <3qaui9$ae@usenet.rpi.edu> and <3qb5dp$2nc@usenet.rpi.edu> in comp.databases.oracle From: finkej@ts.its.rpi.edu (Jon Finke) -I am in the process of converting a locally developed that sits on top -of the OCI routines from version 6 to version 7. Unfortunately, I have -run into a snag that I have been unable to get around. Every test run -results in getting an "ORA-01002: fetch out of sequence" error. +Every test run results in an "ORA-01002: fetch out of sequence" error. The manual claims that this is the result of calling "ofetch" before oparse/oexec, or running out of things to fetch. Yet, I am calling diff --git a/dbdimp.c b/dbdimp.c index 701bae96..a8e90830 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.19 1996/06/19 00:48:09 timbo Exp $ + $Id: dbdimp.c,v 1.20 1996/07/10 02:27:52 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -309,7 +309,7 @@ dbd_st_prepare(sth, statement, attribs) (sword)oparse_defer, (ub4)oparse_lng)) { SV *msgsv; char msg[99]; - sprintf(msg,"possibly parse error at character %d of %d in '", + sprintf(msg,"possibly parse error near character %d of %d in '", imp_sth->cda->peo+1, (int)strlen(imp_sth->statement)); msgsv = sv_2mortal(newSVpv(msg,0)); sv_catpv(msgsv, imp_sth->statement); @@ -355,8 +355,8 @@ dbd_preparse(imp_sth, statement) int idx=0, style=0, laststyle=0; /* allocate room for copy of statement with spare capacity */ - /* for editing ':1' into ':p1' so we can use obndrv. */ - imp_sth->statement = (char*)safemalloc(strlen(statement) + 100); + /* for editing '?' or ':1' into ':p1' so we can use obndrv. */ + imp_sth->statement = (char*)safemalloc(strlen(statement) * 3); /* initialise phs ready to be cloned per placeholder */ memset(&phs_tpl, 0, sizeof(phs_tpl)); @@ -459,7 +459,7 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs) /* Setup / Clear attributes as defined by attribs. */ /* If attribs is EMPTY then reset attribs to default. */ ; /* XXX */ - if ( (svp=hv_fetch((HV*)SvRV(attribs), "ora_type",0, 0)) == NULL) { + if ( (svp=hv_fetch((HV*)SvRV(attribs), "ora_type",8, 0)) == NULL) { if (!dbtype_is_string(SvIV(*svp))) /* mean but safe */ croak("bind_param %s ora_type %d not a simple string type", name, (int)SvIV(*svp)); From 773a83f7c866e3fbd15974472fbfc2b9373afc0b Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Fri, 26 Jul 1996 14:19:00 -0500 Subject: [PATCH 017/637] import DBD-Oracle 0.37 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.37 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.37.tar.gz --- Changes | 7 +++++++ Makefile.PL | 41 +++++++++++++++++++++++------------------ Oracle.pm | 6 +++--- Oracle.xs | 4 +++- README | 8 ++++---- dbdimp.c | 23 +++++++++++++++-------- 6 files changed, 55 insertions(+), 34 deletions(-) diff --git a/Changes b/Changes index c78b003b..995adb01 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,10 @@ +Changes in DBD::Oracle 0.37 (Oraperl 1.28), 25th July 1996 + + Fixed Makefile.PL for Oracle 7.3.2. + Fixed $num_fields = ora_fetch($csr) before first fetch for + queries with bind vars. + Fixed occasional core dump on global destruct. + Changes in DBD::Oracle 0.36 (Oraperl 1.28), 10th July 1996 Fixed bind_param ora_type attribute. diff --git a/Makefile.PL b/Makefile.PL index 9eb61926..8f370a30 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,5 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.46 1996/07/10 02:27:52 timbo Exp $ +# $Id: Makefile.PL,v 1.47 1996/07/26 21:09:53 timbo Exp $ BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -57,20 +57,22 @@ print "Using Oracle in $OH\n"; # --- What Oracle is installed... -# Todo: validate we have the right stuff installed -warn "Warning: OCI (Pro*C) does not appear to be installed.\n" +warn "\nWARNING: Oracle OCI (Pro*C) does not appear to be installed.\n" + ."You must install Pro*C before you can build DBD::Oracle properly.\n\n" unless (-f "$OH/lib/libocic.a" and -f "$OH/rdbms/demo/oratypes.h") or (-f "$OH/precomp/demo/proc/proc.mk"); # 7.3.x +# Todo: validate we have all the right stuff installed -my @mkfiles; -my $oraclemk = $::opt_m || "$OH/proc/lib/proc.mk"; -$oraclemk = "$OH/precomp/demo/proc/proc.mk" unless -f $oraclemk; # 7.3.x -$oraclemk = "$OH/proc16/lib/proc16.mk" unless -f $oraclemk; +# Using -m to specify oracle.mk might work but is NOT supported. +my $procmk = $::opt_m || "$OH/proc/lib/proc.mk"; +$procmk = "$OH/precomp/demo/proc/proc.mk" unless -f $procmk; # 7.3.x +$procmk = "$OH/proc16/lib/proc16.mk" unless -f $procmk; die "Unable to locate proc.mk (use -m /path/to/proc.mk to specify)\n" - unless -f $oraclemk; + unless -f $procmk; +my @mkfiles; my $linkwith = fetch_oci_macros(); -my $libhome = expand_mkvars($MK{LIBHOME}, 0, 0); +my $libhome = expand_mkvars($MK{LIBHOME}, 0, 0) || "$OH/lib"; $linkwith = expand_mkvars($linkwith, 0, 0); $linkwith =~ s/-Y P,/-YP,/g if $Config{'cc'} =~ /gcc/; $linkwith =~ s:-R /:-R/:g if $Config{osname} eq 'solaris'; @@ -82,10 +84,13 @@ $linkwith_s =~ s!([/\w.]+)/lib(\w+).a!-L$1 -l$2!g; # extract object files, keep for use later my @linkwith_o; push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; +# also extract AIX .exp files since they confuse MakeMaker +push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; if ($::opt_s) { - warn "Searching for symbol '$::opt_s' in $libhome ...\n"; - system(qq{ cd $libhome; for i in lib*.[as]* *.o; + warn "Searching for symbol '$::opt_s' in $OH ...\n"; + my $dlext = $Config{dlext}; + system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; do echo " searching \$i ..."; nm \$i | grep $::opt_s; done }); @@ -93,7 +98,7 @@ if ($::opt_s) { exit; } -if ($Config{osname} eq 'solaris' and $Config{osvers} == 2.5 +if ($Config{osname} eq 'solaris' and $Config{osvers} >= 2.3 and $linkwith_s =~ /-lthread/) { warn "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; warn "Deleting -lthread from link list as a possible workround.\n"; @@ -131,8 +136,8 @@ warn "WARNING: Your GNU C compiler is very old. Please upgrade.\n" # Set some private WriteMakefile options if this is 'me' :-) if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess $Verbose = 1; - $opts{INST_LIB} = '$(INSTALLSITELIB)'; - $opts{INST_ARCHLIB} = '$(INSTALLSITEARCH)'; + # $opts{INST_LIB} = '$(INSTALLSITELIB)'; + # $opts{INST_ARCHLIB} = '$(INSTALLSITEARCH)'; $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith' . ' -Wbad-function-cast -Wcast-qual' if $Config{cc} eq 'gcc'; } @@ -228,12 +233,12 @@ ORACLE_HOME = '.$ENV{ORACLE_HOME}.' sub fetch_oci_macros { - # Read $oraclemk makefile, extract macro definitions from it + # Read $procmk makefile, extract macro definitions from it # and store them in $MK, @MK and %MK. # Don't include the following definitions in the generated # makefile (note that %MK stills gets these values). - my @edit = qw(SHELL CC CFLAGS ASFLAGS RCC LDFLAGS AR ECHO EXE OBJS); + my @edit = qw(SHELL CC CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS AR ECHO EXE OBJS); my %edit; @edit{@edit} = ('$_ = ""') x @edit; $edit{COMPOBJS} = q{ @@ -246,7 +251,7 @@ sub fetch_oci_macros { my $mkver = 0; my $linkwith = ''; my $lastline = ''; - my @lines = read_inc_file($oraclemk); + my @lines = read_inc_file($procmk); for(1; $_ = shift(@lines); $lastline = $_){ # Join split lines but retain backwack and newlines: $_ .= shift(@lines) while(m/\\[\r\n]+$/); @@ -294,7 +299,7 @@ sub fetch_oci_macros { $linkwith = '$(PROLDLIBS)'; } unless ($linkwith){ - die "ERROR parsing $oraclemk: Unable to determine what to link with.\n"; + die "ERROR parsing $procmk: Unable to determine what to link with.\n"; } $MK = join("\n", @MK); print "Using @mkfiles ".($MK{mkver} ? "(version $MK{mkver})" : '')."\n"; diff --git a/Oracle.pm b/Oracle.pm index f8392f82..c0f6f391 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.34 1996/07/10 02:27:52 timbo Exp $ +# $Id: Oracle.pm,v 1.35 1996/07/26 21:08:47 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -16,8 +16,8 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.36'; - my $Revision = substr(q$Revision: 1.34 $, 10); + $VERSION = '0.37'; + my $Revision = substr(q$Revision: 1.35 $, 10); require_version DBI 0.69; diff --git a/Oracle.xs b/Oracle.xs index b63c962d..d5d474b0 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -1,5 +1,5 @@ /* - $Id: Oracle.xs,v 1.40 1996/05/20 21:30:26 timbo Exp $ + $Id: Oracle.xs,v 1.41 1996/07/26 21:08:14 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -228,6 +228,8 @@ fetchrow(sth) if (DBIc_COMPAT(imp_sth) && GIMME == G_SCALAR) { /* XXX Oraperl */ /* This non-standard behaviour added only to increase the */ /* performance of the oraperl emulation layer (Oraperl.pm) */ + if (!imp_sth->done_desc && !dbd_describe(sth, imp_sth)) + XSRETURN_UNDEF; XSRETURN_IV(DBIc_NUM_FIELDS(imp_sth)); } av = dbd_st_fetch(sth); diff --git a/README b/README index ce4528e0..700a71e7 100644 --- a/README +++ b/README @@ -19,10 +19,10 @@ DBD::Oracle -- an Oracle 7 interface for Perl 5. *BEFORE* BUILDING, TESTING AND INSTALLING this you will need to: Build, test and install Perl 5 (at least 5.002beta2). - It is very important to test it and install it! + It is very important to TEST it and INSTALL it! Build, test and install the DBI module (at least DBI 0.69). - It is very important to test it and install it! + It is very important to TEST it and INSTALL it! Remember to *read* the DBI README file! @@ -260,14 +260,14 @@ the core file and then send it to me along with the other information requested in the 'If you have problems' section. ------------------------------------------------------------------------------- -HP-UX: Terry Greenlaw +HP-UX 9.x: Terry Greenlaw I traced a problem with "ld: Invalid loader fixup needed" to the file libocic.a. On HP-UX it contains position-dependant code and cannot be used to generate dynamic load libraries. The only shared library that Oracle ships under HP-UX is liboracle.sl which replaces libxa.a, libsql.a, libora.a, libcvg.a, and libnlsrtl.a. The OCI stuff still -appears to only link statically under HU-UX. +appears to only link statically under HU-UX 9.x [10.x is okay]. You'll need to build DBD::Oracle statically linked into the perl binary. See the static linking notes below. diff --git a/dbdimp.c b/dbdimp.c index a8e90830..0dc140a3 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.20 1996/07/10 02:27:52 timbo Exp $ + $Id: dbdimp.c,v 1.21 1996/07/26 21:05:34 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -520,15 +520,15 @@ dbd_describe(h, imp_sth) I32 num_fields; int i = 0; + if (imp_sth->done_desc) + return 1; /* success, already done it */ + imp_sth->done_desc = 1; + if (!f_cbufl) { f_cbufl_max = 120; New(1, f_cbufl, f_cbufl_max, sb4); } - if (imp_sth->done_desc) - return 1; /* success, already done it */ - imp_sth->done_desc = 1; - /* Get number of fields and space needed for field names */ while(++i) { /* break out within loop */ sb1 cbuf[256]; /* generous max column name length */ @@ -775,10 +775,17 @@ dbd_st_finish(sth) { D_imp_sth(sth); /* Cancel further fetches from this cursor. */ - /* We don't close the cursor till DESTROY. */ - /* The application may re execute it. */ + /* We don't close the cursor till DESTROY (dbd_st_destroy). */ + /* The application may re execute(...) it. */ if (DBIc_ACTIVE(imp_sth) && ocan(imp_sth->cda) ) { - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "ocan error"); + /* oracle 7.3 code can core dump looking up an error message */ + /* if we have logged out of the database. This typically */ + /* happens during global destruction. This should catch most: */ + if (dirty && imp_sth->cda->rc == 3114) + ora_error(sth, NULL, imp_sth->cda->rc, + "ORA-03114: not connected to ORACLE (ocan)"); + else + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "ocan error"); return 0; } DBIc_ACTIVE_off(imp_sth); From 370dbd763dd692b37b2e9425fd9e9bf89d2b7659 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Mon, 23 Sep 1996 11:26:00 -0500 Subject: [PATCH 018/637] import DBD-Oracle 0.38 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.38 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.38.tar.gz --- Changes | 17 +++++++-- Makefile.PL | 88 ++++++++++++++++++++++++++----------------- Oracle.pm | 6 +-- README | 74 +++++++++++++++++++++++++++--------- dbdimp.c | 4 +- oraperl.ex/commit.pl | 1 - oraperl.ex/ex.pl | 2 +- oraperl.ex/japh | 2 +- oraperl.ex/mkdb.pl | 5 --- oraperl.ex/oradump.pl | 1 - oraperl.ex/sql | 2 +- oraperl.ex/tabinfo.pl | 1 - test.pl | 26 +++++++++---- 13 files changed, 150 insertions(+), 79 deletions(-) diff --git a/Changes b/Changes index 995adb01..77905598 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,11 @@ +Changes in DBD::Oracle 0.38 (Oraperl 1.28), 22th Aug 1996 + + Overhaul of Makefile variable parsing. Should now cope with + complex variables which expand to nested shell escapes. + Try perl Makefile.PL -v to watch the fun. + Updated README, Makefile.PL and test.pl messages for clarity. + Fixed possible memory corruption in dbd_bind_ph(). + Changes in DBD::Oracle 0.37 (Oraperl 1.28), 25th July 1996 Fixed Makefile.PL for Oracle 7.3.2. @@ -65,7 +73,7 @@ Changes in DBD::Oracle 0.30, 7th May 1996 THE ORAPERL EMULATION LAYER IS NOW FORMALLY RELEASED (NO LONGER ALPHA). Note that the underlying DBI and DBD::Oracle interfaces remain alpha - because they are still subject to, possibly significant, change. + because they are still subject to (possibly significant) change. Oraperl v2 used to return the string 'OK' to indicate success with a zero numeric value. The Oraperl emulation now uses the @@ -75,13 +83,13 @@ Changes in DBD::Oracle 0.30, 7th May 1996 Fixed typecast warning (s/safefree/Safefree). Automatically sets/resets ORACLE_HOME from oratab value for sid. - TO DO: Automatic configuration from Oracle 7.3 is not yet working - (Oracle have reorganised the makefiles yet again!). + TO DO: Automatic configuration from Oracle 7.3 is not yet working + (Oracle have reorganised the makefiles yet again!). Changes in DBD::Oracle 0.29, 2 March 1996 Fixed Makefile.PL to get DBIXS.h from right spot. - Changes to suit perl5.002 and site_lib directories. + Changes to suit perl5.002 and site_lib directories. Detects old versions ahead of new in @INC. Random tidy-ups. @@ -234,3 +242,4 @@ Changes in DBD::Oracle 0.18: (You need to add the following after line 80 in DBI/DBI.pm: 'readblob' => {'U'=>[4,5,'$field, $offset, $len [, \\$buf]']}, in order to access the new readblob method.) + diff --git a/Makefile.PL b/Makefile.PL index 8f370a30..cd8629df 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,5 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.47 1996/07/26 21:09:53 timbo Exp $ +# $Id: Makefile.PL,v 1.49 1996/08/22 23:41:31 timbo Exp $ BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -29,8 +29,9 @@ my(@MK, %MK, $MK); # parsed macros from Oracle proc.mk file $::opt_m = ''; # path to proc.mk or oracle.mk file to read $::opt_g = ''; # enable debugging (s/-O/-g/g) $::opt_s = ''; # Find a symbol, Don't build a Makefile +$::opt_v = 0; # be verbose -getopts('gm:s:') or die "Invalid arguments"; +getopts('gm:s:v') or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string @@ -38,14 +39,15 @@ $::opt_g &&= '-g'; # convert to actual string print "\n Configuring DBD::Oracle ...\n ->>>\tRemember to actually *READ* the README file!\n +>>>\tRemember to actually *READ* the README file! + \tEspecially if you have any problems.\n " unless $::opt_s; # --- Where is Oracle installed... unless ($ENV{ORACLE_HOME}){ warn "\$ORACLE_HOME not defined. Searching for Oracle...\n"; - foreach(qw(/usr/oracle /opt/oracle /usr/soft/oracle)){ + foreach(qw(/usr/oracle /home/oracle /opt/oracle)){ $ENV{ORACLE_HOME}=$_,last if -d "$_/rdbms/lib"; } die "Unable to determine ORACLE_HOME" unless $ENV{ORACLE_HOME}; @@ -61,24 +63,32 @@ warn "\nWARNING: Oracle OCI (Pro*C) does not appear to be installed.\n" ."You must install Pro*C before you can build DBD::Oracle properly.\n\n" unless (-f "$OH/lib/libocic.a" and -f "$OH/rdbms/demo/oratypes.h") or (-f "$OH/precomp/demo/proc/proc.mk"); # 7.3.x -# Todo: validate we have all the right stuff installed +# XXX Todo: validate user has all the right Oracle stuff installed. # Using -m to specify oracle.mk might work but is NOT supported. my $procmk = $::opt_m || "$OH/proc/lib/proc.mk"; $procmk = "$OH/precomp/demo/proc/proc.mk" unless -f $procmk; # 7.3.x $procmk = "$OH/proc16/lib/proc16.mk" unless -f $procmk; -die "Unable to locate proc.mk (use -m /path/to/proc.mk to specify)\n" - unless -f $procmk; +die q{ + Unable to locate proc.mk in your Oracle installation. + + proc.mk is part of the Oracle Pro*C product. You need to build + DBD::Oracle on a system which has Oracle Pro*C installed. + + If proc.mk is installed somewhere non-standard you can use + perl Makefile.PL -m /path/to/proc.mk + to specify where it is. +} unless -f $procmk; my @mkfiles; my $linkwith = fetch_oci_macros(); -my $libhome = expand_mkvars($MK{LIBHOME}, 0, 0) || "$OH/lib"; -$linkwith = expand_mkvars($linkwith, 0, 0); +my $libhome = expand_mkvars($MK{LIBHOME}, 0, 1, 0) || "$OH/lib"; +$linkwith = expand_mkvars($linkwith, 0, 1, 0); $linkwith =~ s/-Y P,/-YP,/g if $Config{'cc'} =~ /gcc/; $linkwith =~ s:-R /:-R/:g if $Config{osname} eq 'solaris'; # get a cut down $linkwith to pass to MakeMaker liblist -my $linkwith_s = expand_mkvars($linkwith, 1, 1); +my $linkwith_s = expand_mkvars($linkwith, 1, 1, 0); # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" $linkwith_s =~ s!([/\w.]+)/lib(\w+).a!-L$1 -l$2!g; # extract object files, keep for use later @@ -141,6 +151,7 @@ if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith' . ' -Wbad-function-cast -Wcast-qual' if $Config{cc} eq 'gcc'; } +$Verbose = 1 if $::opt_v; # log key platform information to help me help you quickly print "System: perl$] @Config{qw(myuname)}\n"; @@ -302,13 +313,13 @@ sub fetch_oci_macros { die "ERROR parsing $procmk: Unable to determine what to link with.\n"; } $MK = join("\n", @MK); - print "Using @mkfiles ".($MK{mkver} ? "(version $MK{mkver})" : '')."\n"; return $linkwith; } sub read_inc_file { my $file = shift; my $fh = new FileHandle "<$file" or die "Unable to read $file: $!"; + print "Reading $file.\n"; my @lines; push(@mkfiles, $file); while(<$fh>) { @@ -324,43 +335,52 @@ sub read_inc_file { return @lines; } +sub expand_shellescape { + my($orig, $level) = @_; + my $cmd = $orig; + warn "\n$level * Evaluating \`$orig\`\n" if $::opt_v; + # ensure we have no $(...) vars left - strip out undefined ones: + $cmd =~ s/\$\((\w+)\)/mkvar($1, 1, 0, $level+1)/ge; + warn "\n$level * After reducing to \`$cmd\`\n" if $::opt_v and $cmd ne $orig; + my $result = `$cmd`; + warn "$level * Returned $result\n\n" if $::opt_v; + $result; +} sub expand_mkvars { - my $string = shift; - my $strip = shift; - my $backtick = shift; - # warn "Expanding: $string\n"; - $string =~ s/\$\((\w+)\)/mkvar($1, $strip, $backtick)/ge; - $string =~ s/\s*\\\n\s*/ /g; # merge continuations - $string =~ s/`(.*?)`/`$1`/eg if $backtick; - $string =~ s/\s+/ /g; # shrink whitespace - $string; + my($string, $strip, $backtick, $level) = @_; + local($_) = $string; + warn "$level Expanding $_\n" if $::opt_v; + s/\$\((\w+)\)/mkvar($1, $strip, $backtick, $level+1)/ge; + s/`(.*?[^\\])`/expand_shellescape($1, $level+1)/esg if $backtick; + s/\s*\\\n\s*/ /g; # merge continuations + s/\s+/ /g; # shrink whitespace + warn "$level Expanded $string\n to $_\n\n" if $::opt_v and $_ ne $string; + $_; } sub mkvar { - my $var = shift; - my $strip = shift; - my $backtick = shift; + my($var, $strip, $backtick, $level) = @_; my $default = $strip ? '' : "\$($var)"; - # warn "Expand var: $var\n"; + warn "$level Variable: $var\n" if $::opt_v; return '$(LIBHOME)' if $var eq 'LIBHOME' && !$strip; # gets noisy return $ENV{ORACLE_HOME} if $var eq 'ORACLE_HOME'; - $MK{$var} ? expand_mkvars($MK{$var}, $strip, $backtick) : $default; + $MK{$var} ? expand_mkvars($MK{$var}, $strip, $backtick, $level+1) : $default; } sub find_bin{ - my $bin = shift; - foreach(split(/:/, $ENV{PATH})){ - return "$_/$bin" if -x "$_/$bin"; - } - return "<$bin not found>"; + my $bin = shift; + foreach(split(/:/, $ENV{PATH})){ + return "$_/$bin" if -x "$_/$bin"; + } + return "<$bin not found>"; } { # If perl Makefile.PL *-g* then switch on debugging package MY; # SUPER needs package context, $self is not sufficient sub const_cccmd { - my($self) = shift; - local($_) = $self->SUPER::const_cccmd(@_); - s/\s-O\d?\b/ -g/g if $::opt_g; - $_; + my($self) = shift; + local($_) = $self->SUPER::const_cccmd(@_); + s/\s-O\d?\b/ -g/g if $::opt_g; + $_; } } diff --git a/Oracle.pm b/Oracle.pm index c0f6f391..4d25d13e 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.35 1996/07/26 21:08:47 timbo Exp $ +# $Id: Oracle.pm,v 1.36 1996/08/22 23:20:19 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -16,8 +16,8 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.37'; - my $Revision = substr(q$Revision: 1.35 $, 10); + $VERSION = '0.38'; + my $Revision = substr(q$Revision: 1.36 $, 10); require_version DBI 0.69; diff --git a/README b/README index 700a71e7..4062083f 100644 --- a/README +++ b/README @@ -5,15 +5,17 @@ DBD::Oracle -- an Oracle 7 interface for Perl 5. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. -** WARNING: THIS IS MOSTLY ALPHA SOFTWARE. Your mileage may vary. ** + PLEASE READ THE ENTIRE README FILE CAREFULLY ! -** THE ORAPERL EMULATION IS NO LONGER ALPHA. IT IS NOW FULLY RELEASED. ** - The only currently supported interface is via Oraperl.pm, the - oraperl emulation layer. This is fairly complete and stable. - Execute "perldoc Oraperl" for info. +* WARNING: THIS IS MOSTLY ALPHA SOFTWARE. Your mileage may vary. * + +* THE ORAPERL EMULATION IS NO LONGER ALPHA. IT IS NOW FULLY RELEASED. * + +* The only currently supported interface is via Oraperl.pm, the * +* oraperl emulation layer. This is fairly complete and stable. * +* Execute "perldoc Oraperl" after installing for full information. * - PLEASE READ THE ENTIRE README FILE! *BEFORE* BUILDING, TESTING AND INSTALLING this you will need to: @@ -21,31 +23,54 @@ DBD::Oracle -- an Oracle 7 interface for Perl 5. Build, test and install Perl 5 (at least 5.002beta2). It is very important to TEST it and INSTALL it! - Build, test and install the DBI module (at least DBI 0.69). + Build, test and install the DBI module (at least DBI 0.71). It is very important to TEST it and INSTALL it! Remember to *read* the DBI README file! + Install enough Oracle software to enable DBD::Oracle to build. + That includes Pro*C. -BUILDING + +BUILDING: perl Makefile.PL make + +If you have problems see the 'IF YOU HAVE PROBLEMS' section below. +If it's builds without error you can then run the tests. For the +main test to work it must be able to connect to an Oracle database. + +Don't worry about most warnings, specifically "end-of-loop code not +reached", "ANSI C forbids braced-groups within expressions", "cast +increases required alignment of target type" and "passing arg 2 of +`oerhms' with different width due to prototype". + +You will need to set either the TWO_TASK or ORACLE_SID environment +variables to the correct values for your database. Consult Oracle +documentation for more details. Test your setting by connecting to +the database using an Oracle tool such as sqlplus. Once you can do +that then you can test DBD::Oracle knowing that it should work. + +The test will connect to the database using the value of the +ORACLE_USER environment variable so you should set that to the +correct value before starting the test. + make test make test TEST_VERBOSE=1 (if any of the t/* tests fail) make install (if the tests look okay) -Do NOT hand edit the generated Makefile unless you are completely sure + +IF YOU HAVE PROBLEMS: + +Do not hand edit the generated Makefile unless you are completely sure you understand the implications! Always try to make changes via the Makefile.PL command line and/or editing the Makefile.PL. -You should never need to make any changes. If you do *please* let me +You should not need to make any changes. If you do *please* let me know so that I can try to make it automatic in a later release. - -IF YOU HAVE PROBLEMS: - Please don't post problems to comp.lang.perl.misc or perl5-porters. This software is supported via the dbi-users mailing list. For more information and to keep informed about progress you can join the a @@ -56,7 +81,7 @@ may take a few days to be processed). Please post details of any problems (or changes you needed to make) to dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. -Please include: +** IT IS IMPORTANT TO INCLUDE THE FOLLOWING INFORMATION: 1. A complete log of a all steps of the build, e.g.: @@ -69,11 +94,18 @@ Please include: 3. The output of perl -V -4. If you get a core dump when using Oraperl try adding this *before* +4. If you get errors like "undefined symbol", "symbol not found" + or "Text relocation remains" then include the output of + "perl Makefile.PL -s XXX" where XXX is the name of one of the + symbols. Please don't send the entire output of this command, + just any obviously 'interesting' parts (if there are any). + +5. If you get a core dump when using Oraperl try adding this *before* your 'use Oraperl' line: BEGIN { $Oraperl::safe = 1 } - (unless your version of Oraperl.pm already has $safe=1 in it). + unless your version of Oraperl.pm already has $safe=1 in it + (it does by default now). -5. If you still get a core dump rebuild DBD::Oracle with debugging +6. If you still get a core dump rebuild DBD::Oracle with debugging enabled by executing: perl Makefile.PL -g (note the -g option) then rerun the code to get a new core dump file, finally use a debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. @@ -82,9 +114,15 @@ Please include: you don't have a good debugger on your system. If desparate try: make perl; ./perl script; echo '$c' | adb ./perl core -6. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun +7. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun make test after setting the environment variable PERL_DL_DEBUG to 2. +It is important to check that you are using the latest version before +posting. If you're not then I'm *very* likely to simply say "upgrade to +the latest". You would do yourself a favour by upgrading beforehand. + +Please remember that I'm _very_ busy. Try to help yourself first, +then try to help me help you by following these guidelines. Regards, Tim. diff --git a/dbdimp.c b/dbdimp.c index 0dc140a3..ab363cac 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.21 1996/07/26 21:05:34 timbo Exp $ + $Id: dbdimp.c,v 1.22 1996/08/22 23:20:19 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -427,13 +427,13 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs) SV **svp; STRLEN name_len; char *name; + char buf[90]; phs_t *phs; STRLEN value_len; void *value_ptr; if (SvNIOK(ph_namesv) ) { /* passed as a number */ - char buf[90]; name = buf; sprintf(name, ":p%d", (int)SvIV(ph_namesv)); name_len = strlen(name); diff --git a/oraperl.ex/commit.pl b/oraperl.ex/commit.pl index 24754631..d9af8330 100755 --- a/oraperl.ex/commit.pl +++ b/oraperl.ex/commit.pl @@ -1,4 +1,3 @@ -#!/usr/local/bin/oraperl # # commit.pl # diff --git a/oraperl.ex/ex.pl b/oraperl.ex/ex.pl index 1a23a59d..6f361802 100755 --- a/oraperl.ex/ex.pl +++ b/oraperl.ex/ex.pl @@ -1,4 +1,4 @@ -#!/usr/local/bin/oraperl +# eval 'use Oraperl; 1' || die $@ if $] >= 5; diff --git a/oraperl.ex/japh b/oraperl.ex/japh index 06d9df0e..c103c7e4 100755 --- a/oraperl.ex/japh +++ b/oraperl.ex/japh @@ -1,4 +1,4 @@ -#!/usr/local/bin/oraperl +# # # This is an example of how we could code a JAPH in Oraperl. # diff --git a/oraperl.ex/mkdb.pl b/oraperl.ex/mkdb.pl index fece2134..cd3fefb3 100755 --- a/oraperl.ex/mkdb.pl +++ b/oraperl.ex/mkdb.pl @@ -13,11 +13,6 @@ # # Date: 25th September 1992 -# First make sure that we are running under some form of perl. - -eval "echo 'You must specify oraperl or coraperl.' ; exit" - if 0; - eval 'use Oraperl; 1' || die $@ if $] >= 5; # make sure that we really are running (c)oraperl diff --git a/oraperl.ex/oradump.pl b/oraperl.ex/oradump.pl index 170ac3f7..836157f7 100755 --- a/oraperl.ex/oradump.pl +++ b/oraperl.ex/oradump.pl @@ -1,4 +1,3 @@ -#!/usr/local/bin/oraperl # # oradump.pl # diff --git a/oraperl.ex/sql b/oraperl.ex/sql index c4aaab0a..7e8e0f1b 100755 --- a/oraperl.ex/sql +++ b/oraperl.ex/sql @@ -1,4 +1,4 @@ -#!/usr/local/bin/oraperl +# 'di'; 'ig00'; # diff --git a/oraperl.ex/tabinfo.pl b/oraperl.ex/tabinfo.pl index 669219b9..1c6f7b25 100644 --- a/oraperl.ex/tabinfo.pl +++ b/oraperl.ex/tabinfo.pl @@ -1,4 +1,3 @@ -#!/usr/local/bin/oraperl # # tabinfo # diff --git a/test.pl b/test.pl index bdeee971..54de18f9 100755 --- a/test.pl +++ b/test.pl @@ -1,6 +1,6 @@ #!/usr/local/bin/perl -w -# $Id: test.pl,v 1.21 1996/06/19 00:48:09 timbo Exp $ +# $Id: test.pl,v 1.23 1996/08/22 23:41:31 timbo Exp $ # # Copyright (c) 1995, Tim Bunce # @@ -10,7 +10,11 @@ require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.21 $}."\n"; +print q{Oraperl test application $Revision: 1.23 $}."\n"; + +$SIG{__WARN__} = sub { + ($_[0] =~ /^Bad free/) ? warn "See README about Bad free() warnings!\n": warn @_; +}; $opt_d = 0; # debug $opt_l = 0; # log @@ -21,8 +25,8 @@ $ENV{PERL_DBI_DEBUG} = 2 if $opt_d; $ENV{ORACLE_HOME} = '/usr/oracle' unless $ENV{ORACLE_HOME}; -$dbname = $ARGV[0] || ''; # $ENV{TWO_TASK} || $ENV{ORACLE_SID} || 'crgs'; -$dbuser = $ENV{ORACLE_USERID} || 'crgs/crgs'; +$dbname = $ARGV[0] || ''; # $ENV{TWO_TASK} || $ENV{ORACLE_SID} || 'crgs'; +$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; eval '$Oraperl::safe = 1' if $] >= 5; eval 'use Oraperl; 1' || die $@ if $] >= 5; @@ -30,13 +34,15 @@ &ora_version; print "\nConnecting\n", - " to '$dbname' (from command line, else uses ORACLE_SID/TWO_TASK)\n"; -print " as '$dbuser' (via ORACLE_USERID environment var or default)\n"; + " to '$dbname' (from command line, else uses ORACLE_SID or TWO_TASK - recommended)\n"; +print " as '$dbuser' (via ORACLE_USERID env var or default - recommend name/passwd\@dbname)\n"; +printf("(ORACLE_SID='%s', TWO_TASK='%s')\n", $ENV{ORACLE_SID}||'', $ENV{TWO_TASK}||''); { # test connect works first local($l) = &ora_login($dbname, $dbuser, ''); unless($l) { warn "ora_login: $ora_errno: $ora_errstr\n"; + # Try to help dumb users who don't know how to connect to oracle... warn "\nHave you set the environment variable ORACLE_USERID ?\n" if ($ora_errno == 1017); # ORA-01017: invalid username/password warn "\nHave you included your password in ORACLE_USERID ? (e.g., 'user/passwd')\n" @@ -45,7 +51,13 @@ if ($ora_errno == 2700); # error translating ORACLE_SID warn "\nORACLE_SID or TWO_TASK possibly not right, or server not running.\n" if ($ora_errno == 1034); # ORA-01034: ORACLE not available - die "\nCould not connect to database. Test aborted.\n"; + warn "\nTWO_TASK possibly not set correctly right.\n" + if ($ora_errno == 12545); + warn "\n"; + warn "Try to connect to the database using an oracle tool like sqlplus\n"; + warn "only if that works should you suspect problems with DBD::Oracle.\n"; + warn "Try leaving dbname value empty and set dbuser to name/passwd\@dbname.\n"; + die "\nTest aborted.\n"; } &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; } From 9a771951fa12d8d4ad46057d649ecb20c251a7b9 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Mon, 23 Sep 1996 13:07:00 -0500 Subject: [PATCH 019/637] import DBD-Oracle 0.39 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.39 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.39.tar.gz --- Changes | 10 ++++ MANIFEST | 2 + Makefile.PL | 24 +++++---- Oracle.pm | 7 +-- Oraperl.pm | 28 +++++++--- README | 130 ++++++++++++++++++++++++++++----------------- README.clients | 65 +++++++++++++++++++++++ README.login | 76 ++++++++++++++++++++++++++ oraperl.ex/bind.pl | 1 - test.pl | 5 +- 10 files changed, 276 insertions(+), 72 deletions(-) create mode 100644 README.clients create mode 100644 README.login diff --git a/Changes b/Changes index 77905598..6d31cd8e 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,13 @@ +Changes in DBD::Oracle 0.39 (Oraperl 1.28), ??th Aug 1996 + + Fix for DEC "target := MACRO = string" Makefile syntax. + Added README notes from Dave Moellenhoff, Lou Henefeld and others. + Added README.login from James Taylor. + Added README.client with various notes about building DBD::Oracle + on minimaly configured client systems. + Extra parameters to ora_do are now passed to DBI's do(). + (This is an extension to the original oraperl ora_do.) + Changes in DBD::Oracle 0.38 (Oraperl 1.28), 22th Aug 1996 Overhaul of Makefile variable parsing. Should now cope with diff --git a/MANIFEST b/MANIFEST index d611aa0c..6ffa1d9a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,5 +1,7 @@ MANIFEST README +README.login +README.clients Changes Todo Makefile.PL diff --git a/Makefile.PL b/Makefile.PL index cd8629df..f504c63e 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,10 +1,10 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.49 1996/08/22 23:41:31 timbo Exp $ +# $Id: Makefile.PL,v 1.50 1996/09/23 19:30:58 timbo Exp $ BEGIN { require 5.003 } # 5.003 fixes very important bugs use ExtUtils::MakeMaker 5.16, qw(&WriteMakefile $Verbose); -use Getopt::Std; +use Getopt::Long; use Config; use strict; @@ -25,13 +25,13 @@ my %opts = ( ); my(@MK, %MK, $MK); # parsed macros from Oracle proc.mk file -# Options, typically only used for debugging +# Options (rarely needed) $::opt_m = ''; # path to proc.mk or oracle.mk file to read $::opt_g = ''; # enable debugging (s/-O/-g/g) $::opt_s = ''; # Find a symbol, Don't build a Makefile $::opt_v = 0; # be verbose -getopts('gm:s:v') or die "Invalid arguments"; +GetOptions('v!', 'g!', 'm=s', 's=s') or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string @@ -47,8 +47,9 @@ print "\n Configuring DBD::Oracle ...\n unless ($ENV{ORACLE_HOME}){ warn "\$ORACLE_HOME not defined. Searching for Oracle...\n"; - foreach(qw(/usr/oracle /home/oracle /opt/oracle)){ - $ENV{ORACLE_HOME}=$_,last if -d "$_/rdbms/lib"; + foreach(qw(/usr/oracle /home/oracle /opt/oracle /home/oracle/home)){ + $ENV{ORACLE_HOME}=$_,last + if -d "$_/rdbms" or -d "$_/precomp" or -d "$_/ocommon"; } die "Unable to determine ORACLE_HOME" unless $ENV{ORACLE_HOME}; } @@ -61,8 +62,9 @@ print "Using Oracle in $OH\n"; warn "\nWARNING: Oracle OCI (Pro*C) does not appear to be installed.\n" ."You must install Pro*C before you can build DBD::Oracle properly.\n\n" - unless (-f "$OH/lib/libocic.a" and -f "$OH/rdbms/demo/oratypes.h") - or (-f "$OH/precomp/demo/proc/proc.mk"); # 7.3.x + unless (-f "$OH/lib/libocic.a" + and (-f "$OH/rdbms/demo/oratypes.h" or -f "$OH/rdbms/public/oratypes.h")) + or (-f "$OH/precomp/demo/proc/proc.mk"); # 7.3.x # XXX Todo: validate user has all the right Oracle stuff installed. # Using -m to specify oracle.mk might work but is NOT supported. @@ -269,7 +271,7 @@ sub fetch_oci_macros { chomp; push(@MK, '') if ($_ eq '' and $lastline ne ''); next unless $_; - last if m/^\w+\s*:/; # gone too far, reached actual targets + last if m/^\w+\s*:[^=]/; # gone too far, reached actual targets unless($MK{mkver}) { # still need to get version number # This is tough since some versions of proc.mk split the @@ -310,7 +312,8 @@ sub fetch_oci_macros { $linkwith = '$(PROLDLIBS)'; } unless ($linkwith){ - die "ERROR parsing $procmk: Unable to determine what to link with.\n"; + die "ERROR parsing $procmk: Unable to determine what to link with.\n" + ."Please send me copies of these files (one per mail message):\n@mkfiles\n"; } $MK = join("\n", @MK); return $linkwith; @@ -332,6 +335,7 @@ sub read_inc_file { $file =~ s/\$\(ORACLE_HOME\)/$ENV{ORACLE_HOME}/g; push(@lines, read_inc_file($file)); } + print "Read a total of ".@lines." lines from $file (including inclusions)\n" if $::opt_v; return @lines; } diff --git a/Oracle.pm b/Oracle.pm index 4d25d13e..3a0251d9 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.36 1996/08/22 23:20:19 timbo Exp $ +# $Id: Oracle.pm,v 1.37 1996/09/23 19:30:58 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -16,8 +16,8 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.38'; - my $Revision = substr(q$Revision: 1.36 $, 10); + $VERSION = '0.39'; + my $Revision = substr(q$Revision: 1.37 $, 10); require_version DBI 0.69; @@ -68,6 +68,7 @@ require 5.002; my($drh) = @_; my $debug = $drh->debug; foreach(qw(/etc /var/opt/oracle), $ENV{TNS_ADMIN}) { + next unless defined $_; warn "Checking for $_/oratab\n" if $debug; next unless open(ORATAB, "<$_/oratab"); while() { diff --git a/Oraperl.pm b/Oraperl.pm index eb26f2ee..b1d52b5d 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.28 1996/06/21 18:25:00 timbo Exp $ +# $Id: Oraperl.pm,v 1.29 1996/09/23 19:30:58 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -20,10 +20,10 @@ package Oraperl; require 5.002; -use DBI 0.69; +use DBI 0.70; use Exporter; -$VERSION = substr(q$Revision: 1.28 $, 10); +$VERSION = substr(q$Revision: 1.29 $, 10); @ISA = qw(Exporter); @@ -133,9 +133,9 @@ sub ora_do { # error => undef # 0 => "0E0" (0 but true) # >0 => >0 - my($lda, $stmt) = @_; + my($lda, $stmt, @params) = @_; # @params are an extension to the original Oraperl. - return $lda->do($stmt); # SEE DEFAULT METHOD IN DBI.pm + return $lda->do($stmt, undef, @params); # SEE DEFAULT METHOD IN DBI.pm # OLD CODE: # $csr is local, cursor will be closed on exit @@ -144,7 +144,7 @@ sub ora_do { # We must be carefull not to execute them again! This needs careful # examination and thought. # Perhaps oracle is smart enough not to execute them again? - my $ret = $csr->execute; + my $ret = $csr->execute(@params); my $rows = $csr->rows; ($rows == 0) ? "0E0" : $rows; } @@ -729,6 +729,22 @@ beginning from 1 for each SQL statement, as &ora_bind() assigns its parameters in this order. Named substitution variables (for example, :NAME, :TELNO) are not permitted. +B Substitution variables are now bound as type 1 (VARCHAR2) +and not type 5 (STRING) by default. This can alter the behaviour of +SQL code which compares a char field with a substitution variable. +See the String Comparison section in the Datatypes chapter of the +Oracle OCI manual for more details. + +You can work around this by using DBD::Oracle's ability to specify +the Oracle type to be used on a per field basis: + + $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) + $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); + $csr->bind_param(1, $value_x, $char_attrib); + $csr->bind_param(2, $value_y, $char_attrib); + ora_bind($csr); # bind with no parameters since we've done bind_param()'s + + =head1 DEBUGGING B The Oraperl $ora_debug variable is not supported. However diff --git a/README b/README index 4062083f..680a4e32 100644 --- a/README +++ b/README @@ -54,7 +54,7 @@ that then you can test DBD::Oracle knowing that it should work. The test will connect to the database using the value of the ORACLE_USER environment variable so you should set that to the -correct value before starting the test. +correct value before starting the test. Please read README.login. make test make test TEST_VERBOSE=1 (if any of the t/* tests fail) @@ -71,6 +71,12 @@ Makefile.PL command line and/or editing the Makefile.PL. You should not need to make any changes. If you do *please* let me know so that I can try to make it automatic in a later release. +If you just can't login then read README.login and edit test.pl to suit. + +If you can't get it to build on a minimally configured client system +then read README.client, it might help but basically I can't help much. +Others on the dbi-users mailing list probably can. + Please don't post problems to comp.lang.perl.misc or perl5-porters. This software is supported via the dbi-users mailing list. For more information and to keep informed about progress you can join the a @@ -196,75 +202,84 @@ With thanks to james.taylor@srs.gov and desilva@ind70.industry.net. =============================================================================== -Some Users of DBD::Oracle on Specific Platforms: +Some users of DBD::Oracle on non-sun platforms: (this is VERY out of date now, there are MANY users on many platforms) -Solaris 1: - Myself. - John D Groenveld - Christian Murphy - -Solaris 2: - Myself. - David Moellenhoff - James Taylor - Jay Krish - John D Groenveld - Joe Hildebrand - John Liptak - Philip Kizer - Alan Johnson - Jim Fox - HP-UX 9: - Terry Greenlaw - Les Troyer - Norbert Kiesel - Greg Anderson - Johann Griessler - Dave Venus + Terry Greenlaw + Les Troyer + Norbert Kiesel + Greg Anderson + Johann Griessler + Dave Venus Unisys U6000/300: - Alan Burlison + Alan Burlison SCO 3: - Joel Rosi-Schwartz - Greg Gerber + Greg Gerber Sequent DYNIX/ptx 2: - Alligator Descartes - Jonathan Lemon - -NT: - Jim Fox + Alligator Descartes + Jonathan Lemon Motorola M88100 (SVR3.2): - Christian Murphy + Christian Murphy DEC UNIX 3.2: - David J. DeWolfe + David J. DeWolfe DEC Alpha, OSF/1 v2: - Royal Hansen - Jonathan Olson - Greg Gerber + Royal Hansen + Jonathan Olson + Greg Gerber Davide Migliavacca SGI Iris Indigo R4000 Irix 5.3: - Andrew G Wood + Andrew G Wood AIX 3.2 Davide Migliavacca - Joerg Senekowitsch + Joerg Senekowitsch AIX 4.1 - Ken P. Nikolai + Ken P. Nikolai + +NT: + Jim Fox =============================================================================== Platform or Oracle Version specific notes: +Note that although some of these refer to specific systems and versions the +same or similar problems may exist on other systems or versions. + +------------------------------------------------------------------------------- +Can't find libclntsh.so at run time: + +Dave Moellenhoff : libclntsh.so is the shared +library composed of all the other Oracle libs you used to have to +statically link. Oracle didn't start providing it until 7.2 and later. +libclntsh.so should be in $ORACLE_HOME/lib. If it's missing, try +running $ORACLE_HOME/rdbms/lib/genclntsh.sh and it should create it. + +Also: Never copy libclntsh.so to a different machine or Oracle version. +If DBD::Oracle was built on a machine with a different path to libclntsh.so +then you'll need to set set an environment variable, typically +LD_LIBRARY_PATH, to include the directory containing libclntsh.so. + +------------------------------------------------------------------------------- +Error while trying to retrieve text for error ...: + +From Lou Henefeld : We discovered that we needed +some files from the $ORACLE_HOME/ocommon/nls/admin/data directory: + lx00001.nlb, lx10001.nlb, lx1boot.nlb, lx20001.nlb +If your national language is different from ours (American English), +you will probably need different nls data files. + + ------------------------------------------------------------------------------- Oracle 7.3 on Solaris 2.5 (maybe others): @@ -280,7 +295,7 @@ If any of these work please let me know (include full version info). ------------------------------------------------------------------------------- Bad free() warnings: -These are generally cause by problems in Oracle's own library code. +These are generally caused by problems in Oracle's own library code. You can use this code to hide them: $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Bad free/ } @@ -297,6 +312,17 @@ Follow the instructions in step 5 above for getting a stack trace from the core file and then send it to me along with the other information requested in the 'If you have problems' section. +------------------------------------------------------------------------------- +8-bit text is returned as '?' characters. + +Make sure the following environment vaiables are set: + NLS_LANG, ORA_NLS, ORA_NLS32 +Thanks to Robin Langdon for this information. +Example: + $ENV{NLS_LANG} = "american_america.we8iso8859p1"; + $ENV{ORA_NLS} = "/home/oracle/ocommon/nls/admin/data"; + $ENV{ORA_NLS32} = "/home/oracle/ocommon/nls/admin/data"; + ------------------------------------------------------------------------------- HP-UX 9.x: Terry Greenlaw @@ -310,6 +336,13 @@ appears to only link statically under HU-UX 9.x [10.x is okay]. You'll need to build DBD::Oracle statically linked into the perl binary. See the static linking notes below. +HP-UX 10 and Oracle 7.2.x do work together when creating dynamic libraries. +The problem was older Oracle libraries were built without the +z flag to cc, +and were therefore position-dependent libraries that can't be linked +dynamically. Newer Oracle releases don't have this problem and it may be +possible to even use the newer Oracle libraries under HP-UX 9. Oracle 7.3 +will ONLY work under HP-UX 10, however. + ------------------------------------------------------------------------------- For platforms which require static linking. @@ -332,7 +365,7 @@ version of the DBI in order that it be automatically included when you do the 'make perl' above. ------------------------------------------------------------------------------- -Oracle 7.1: Syntax error in oratypes.h +Error: Syntax error in oratypes.h Try uncommenting the '#define signed' line in Oracle.h @@ -354,6 +387,7 @@ This workaround is based on information from Kevin Stock. ------------------------------------------------------------------------------- Oracle 7.1.4/5: ORA-01002: fetch out of sequence + Edited from Message-ID: <3qaui9$ae@usenet.rpi.edu> and <3qb5dp$2nc@usenet.rpi.edu> in comp.databases.oracle From: finkej@ts.its.rpi.edu (Jon Finke) @@ -382,11 +416,12 @@ Information Technology Services 518 276 8185 (voice) | 518 276 2809 (fax) Rensselaer Polytechnic Institute 110 8th Street, Troy NY, 12180 ------------------------------------------------------------------------------- -ORA-00604: error occurred at recursive SQL level (DBD: login failed) +Error: ORA-00604: error occurred at recursive SQL level (DBD: login failed) This can happen if TWO_TASK is defined but you connect using ORACLE_SID. ------------------------------------------------------------------------------- +Error: ld: Undefined symbols _environ _dlopen _dlclose ... Environment: SunOS 4.1.3, Oracle 7.1.6 Steve Livingston If you get link errors like: ld: Undefined symbols _environ _dlopen _dlclose ... @@ -402,9 +437,9 @@ Fix: Try adding the '-lc' to $ORACLE_HOME/rdbms/lib/sysliblist (just make sure it's not on a new line). ------------------------------------------------------------------------------- +Error: Undefined symbols __cg92_used at link time. Environment: Solaris, GCC -Error: Undefined symbols __cg92_used at link time. Fix: If you're compiling Oracle applications with gcc on Solaris you need to link with a file called $ORACLE_HOME/lib/__fstd.o. If you compile with the SparcWorks compiler you need to add the command line option on -xcg92 @@ -433,11 +468,6 @@ Problem: ERROR EVENT: DBI::dr=HASH(0x14011fee8)->DBI::default_handler: Solution: Add '#define A_OSF' to Oracle.h above '#include ' and complain to Oracle about bugs in their header files on 64 bit systems. -Problem: Unable to connect - -Solution: Try using something like this: "scott/tiger@t:HOST_IP:INSTANCE" -and not just "scott/tiger". - =============================================================================== End. diff --git a/README.clients b/README.clients new file mode 100644 index 00000000..5d032310 --- /dev/null +++ b/README.clients @@ -0,0 +1,65 @@ +This file contains some random notes relating to minimal Oracle +configurations for building and/or using DBD::Oracle / Oraperl. + +------------------------------------------------------------------------------- +From: James Cooper + +> [...], what do I need in addition to perl5 to access an Oracle database +> on another system from a unix box (Solaris 2.5) that doesn't have an +> oracle database running on it ? +> +> In other words are their some oracle shared objects, etc. I need ? + +I don't have experience with Solaris, but on IRIX 5.3, I simply installed +SQL*Net (ORACLE_HOME/network/admin/*) and the OCI libraries which are in +ORACLE_HOME/lib. You'll also need the header files from +ORACLE_HOME/sqllib/public/*.h and ORACLE_HOME/rdbms/demo/*.h (you won't +need them all, but you can get rid of them after DBD::Oracle compiles). + +So just put that stuff on your client box and install DBI and DBD::Oracle +there. Once DBD::Oracle is installed you can remove the OCI libraries and +headers (make sure to keep SQL*Net!) + +Other than that, getting it working isn't too hard. If you're not +familiar with SQL*Net, let me know. I'm no expert, but I know the basics. +The main thing is to have a good tnsnames.ora file in +ORACLE_HOME/network/admin + +------------------------------------------------------------------------------- +From: Jon Meek + +For my compilation of DBD-Oracle/Solaris2.5/Oracle7.2.x(x=2, I think), I +just pulled the required files in the rdbms directory from the Oracle CD. +The files I needed were: + +$ ls -lR +drwxr-xr-x 2 oracle apbr 512 May 15 17:43 demo/ +drwxr-xr-x 2 oracle apbr 512 May 15 16:20 lib/ +drwxr-xr-x 2 oracle apbr 512 May 15 16:18 mesg/ +drwxr-xr-x 2 oracle apbr 512 May 15 17:38 public/ + +./demo: +-r--r--r-- 1 oracle apbr 4509 Jun 29 1995 ociapr.h +-r--r--r-- 1 oracle apbr 5187 Jun 29 1995 ocidfn.h +-rw-rw-r-- 1 oracle apbr 6659 Jun 29 1995 oratypes.h + +./lib: +-rw-r--r-- 1 oracle apbr 1132 Jul 6 1995 clntsh.mk +-rwxr-xr-x 1 oracle apbr 5623 Jul 17 1995 genclntsh.sh* +-rw-r--r-- 1 oracle apbr 15211 Jul 5 1995 oracle.mk +-rw-r--r-- 2 oracle apbr 3137 May 15 16:20 osntab.s +-rw-r--r-- 2 oracle apbr 3137 May 15 16:20 osntabst.s +-rw-r--r-- 1 oracle apbr 9 May 15 16:19 psoliblist +-rw-r--r-- 1 oracle apbr 39 May 15 16:21 sysliblist + +./mesg: +-r--r--r-- 1 oracle apbr 183296 Jul 11 1995 oraus.msb +-r--r--r-- 1 oracle apbr 878114 Jul 11 1995 oraus.msg + +./public: +-r--r--r-- 1 oracle apbr 5187 Jun 29 1995 ocidfn.h + +Jon + +------------------------------------------------------------------------------- + diff --git a/README.login b/README.login new file mode 100644 index 00000000..db6a062f --- /dev/null +++ b/README.login @@ -0,0 +1,76 @@ +Using Oracle environment variables with sqlplus and Perl. +--------------------------------------------------------- + +sqlplus +------- + +ORACLE_SID is really unnecessary to set since TWO_TASK provides the +same functionality in addition to allowing remote connections. + +% setenv TWO_TASK T:hostname:ORACLE_SID +% sqlplus username/password + +Note that if you have *both* local and remote databases, and you +have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO_TASK takes precedence +over ORACLE_SID (i.e. you get connected to remote system). + +TWO_TASK = P:sid will use the pipe driver for local connections +SQL*Net 1.x + +TWO_TASK = T:machine:sid will use TCP/IP (or D for DECNET, etc.) for +remote SQL*Net 1.x conn. + +TWO_TASK = dbname will use the info stored in the SQL*Net 2.x +configuration file for local or remote connections. + +ORACLE_HOME can also be left unset if you aren't using any of Oracle's +executables, but error messages may not display. + +Discouraging the use of ORACLE_SID makes it easier on the users to see +what is going on. I just wish that TWO_TASK could be renamed, since it +makes no sense to the end user, and doesn't have the ORACLE prefix on +it. + +Perl with DBI/DBD +----------------- + +Below are various ways of connecting to an oracle database using +SQL*Net 1.x and SQL*Net 2.x. "Machine" is the computer the database is +running on, "SID" is the SID of the database, "MS2" is the SQL*Net 2.x +connection descriptor for the database. + + BEGIN { + $ENV{TWO_TASK}='MS2'; + $ENV{ORACLE_HOME} = '/home/oracle/product/7.x.x'; + } + ora_login('','scott/tiger'); + +works here for SQL*Net 2.x, as does + + BEGIN { + $ENV{TWO_TASK}='T:Machine:SID'; + $ENV{ORACLE_HOME} = '/home/oracle/product/7.x.x'; + } + ora_login('','scott/tiger'); + +for SQL*Net 1.x connections. + +For local connections use 'P:SID'. + +login variations (not setting TWO_TASK) +---------------------------------------- + +$lda = ora_login('T:Machine:SID','username','password'); + +$lda = ora_login('','username@T:Machine:SID','password'); + +$lda = ora_login('','username@MS2','password'); + +$lda = ora_login('MS2','username','password'); + +$lda = ora_login('MS2','username/password',''); + + + +With thanks to James Taylor . diff --git a/oraperl.ex/bind.pl b/oraperl.ex/bind.pl index 8507ecfc..06df6ec1 100755 --- a/oraperl.ex/bind.pl +++ b/oraperl.ex/bind.pl @@ -1,4 +1,3 @@ -#!/usr/local/bin/oraperl # # bind.pl # diff --git a/test.pl b/test.pl index 54de18f9..405a42ce 100755 --- a/test.pl +++ b/test.pl @@ -1,6 +1,6 @@ #!/usr/local/bin/perl -w -# $Id: test.pl,v 1.23 1996/08/22 23:41:31 timbo Exp $ +# $Id: test.pl,v 1.24 1996/09/23 19:30:58 timbo Exp $ # # Copyright (c) 1995, Tim Bunce # @@ -10,7 +10,7 @@ require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.23 $}."\n"; +print q{Oraperl test application $Revision: 1.24 $}."\n"; $SIG{__WARN__} = sub { ($_[0] =~ /^Bad free/) ? warn "See README about Bad free() warnings!\n": warn @_; @@ -87,6 +87,7 @@ $dur = time - $start; print "\nTest complete ($dur seconds).\n"; +print "If the tests above have produced the 'expected' output then they have passed.\n"; exit 0; From cf8dc3acbf26c978fa4d3cbf328ef354639933c4 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Mon, 14 Oct 1996 19:55:00 -0500 Subject: [PATCH 020/637] import DBD-Oracle 0.40 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.40 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.40.tar.gz --- Changes | 18 ++- MANIFEST | 3 +- Makefile.PL | 17 ++- Oracle.h | 4 +- Oracle.pm | 6 +- Oracle.xs | 24 +++- README | 60 ++++---- README.clients | 9 ++ README.longs | 58 ++++++++ dbdimp.c | 378 +++++++++++++++++++++++++++++++++++-------------- dbdimp.h | 25 +++- test.pl | 83 ++++++++++- 12 files changed, 519 insertions(+), 166 deletions(-) create mode 100644 README.longs diff --git a/Changes b/Changes index 6d31cd8e..1ee4bf4b 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,20 @@ -Changes in DBD::Oracle 0.39 (Oraperl 1.28), ??th Aug 1996 +Changes in DBD::Oracle 0.40 (Oraperl 1.29), 14th Oct 1996 + + WARNING - This release contains significant changes to the + placeholding binding code. You should test it carefully + before using in live systems. + + Implemented PL/SQL output values via $sth->bind_param_inout. + See the code at the end of test.pl for example usage. + + Binding is now implemented using obndra rather than obndrv. + This may have a subtle effect when matching char fields + against placeholders with trailing spaces. + + Fixed bind_param ora_type attribute. Thanks to Stephen Zander + for the patch. Updated README's. Added README.longs. + +Changes in DBD::Oracle 0.39 (Oraperl 1.29), 23rd Sep 1996 Fix for DEC "target := MACRO = string" Makefile syntax. Added README notes from Dave Moellenhoff, Lou Henefeld and others. diff --git a/MANIFEST b/MANIFEST index 6ffa1d9a..d06cc64f 100644 --- a/MANIFEST +++ b/MANIFEST @@ -2,6 +2,7 @@ MANIFEST README README.login README.clients +README.longs Changes Todo Makefile.PL @@ -15,7 +16,7 @@ test.pl t/base.t hints/svr4.pl oraperl.ph Old oraperl file included for completeness of emulation -oraperl.ex/Readme Oraperl examples (copied unchanged from oraperl-2.4) +oraperl.ex/Readme Oraperl examples (copied mostly unchanged from oraperl-2.4) oraperl.ex/bind.pl oraperl.ex/commit.pl oraperl.ex/ex.pl diff --git a/Makefile.PL b/Makefile.PL index f504c63e..fd5771d7 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,5 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.50 1996/09/23 19:30:58 timbo Exp $ +# $Id: Makefile.PL,v 1.51 1996/10/15 02:19:14 timbo Exp $ BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -61,7 +61,7 @@ print "Using Oracle in $OH\n"; # --- What Oracle is installed... warn "\nWARNING: Oracle OCI (Pro*C) does not appear to be installed.\n" - ."You must install Pro*C before you can build DBD::Oracle properly.\n\n" + ."You should install Pro*C before you can build DBD::Oracle properly.\n\n" unless (-f "$OH/lib/libocic.a" and (-f "$OH/rdbms/demo/oratypes.h" or -f "$OH/rdbms/public/oratypes.h")) or (-f "$OH/precomp/demo/proc/proc.mk"); # 7.3.x @@ -74,12 +74,15 @@ $procmk = "$OH/proc16/lib/proc16.mk" unless -f $procmk; die q{ Unable to locate proc.mk in your Oracle installation. - proc.mk is part of the Oracle Pro*C product. You need to build + proc.mk is part of the Oracle Pro*C product. You should build DBD::Oracle on a system which has Oracle Pro*C installed. If proc.mk is installed somewhere non-standard you can use perl Makefile.PL -m /path/to/proc.mk to specify where it is. + + See README.clients for more information and some alternatives. + } unless -f $procmk; my @mkfiles; @@ -321,7 +324,13 @@ sub fetch_oci_macros { sub read_inc_file { my $file = shift; - my $fh = new FileHandle "<$file" or die "Unable to read $file: $!"; + my $fh; + unless ($fh = new FileHandle "<$file") { + # Workaround more oracle bungling (Oracle 7.3.2/Solaris x86) + my $alt; ($alt = $file) =~ s/\.dk\.mk$/\.mk/; + $fh = new FileHandle "<$alt"; + die "Unable to read $file: $!" unless $fh; + } print "Reading $file.\n"; my @lines; push(@mkfiles, $file); diff --git a/Oracle.h b/Oracle.h index 25518f79..f0591906 100644 --- a/Oracle.h +++ b/Oracle.h @@ -1,5 +1,5 @@ /* - $Id: Oracle.h,v 1.8 1995/08/26 17:39:01 timbo Rel $ + $Id: Oracle.h,v 1.9 1996/10/15 02:19:14 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -56,7 +56,7 @@ SV *dbd_db_FETCH _((SV *dbh, SV *keysv)); int dbd_st_prepare _((SV *sth, char *statement, SV *attribs)); int dbd_st_rows _((SV *sv)); -int dbd_bind_ph _((SV *h, SV *param, SV *value, SV *attribs)); +int dbd_bind_ph _((SV *h, SV *param, SV *value, SV *attribs, int is_inout, IV maxlen)); int dbd_st_execute _((SV *sv)); AV *dbd_st_fetch _((SV *sv)); int dbd_st_finish _((SV *sth)); diff --git a/Oracle.pm b/Oracle.pm index 3a0251d9..88169bc4 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.37 1996/09/23 19:30:58 timbo Exp $ +# $Id: Oracle.pm,v 1.38 1996/10/15 02:19:14 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -16,8 +16,8 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.39'; - my $Revision = substr(q$Revision: 1.37 $, 10); + $VERSION = '0.40'; + my $Revision = substr(q$Revision: 1.38 $, 10); require_version DBI 0.69; diff --git a/Oracle.xs b/Oracle.xs index d5d474b0..8b977da5 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -1,5 +1,5 @@ /* - $Id: Oracle.xs,v 1.41 1996/07/26 21:08:14 timbo Exp $ + $Id: Oracle.xs,v 1.42 1996/10/15 02:19:14 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -56,6 +56,10 @@ disconnect_all(drh) DBIc_ERR(imp_drh), DBIc_ERRSTR(imp_drh)); XSRETURN(0); } + /* perl_destruct with perl_destruct_level and $SIG{__WARN__} set */ + /* to a code ref core dumps when sv_2cv triggers warn loop. */ + if (perl_destruct_level) + perl_destruct_level = 0; XST_mIV(0, 1); @@ -174,7 +178,21 @@ bind_param(sth, param, value, attribs=Nullsv) SV * attribs CODE: DBD_ATTRIBS_CHECK("bind_param", sth, attribs); - ST(0) = dbd_bind_ph(sth, param, value, attribs) ? &sv_yes : &sv_no; + ST(0) = dbd_bind_ph(sth, param, value, attribs, FALSE, 0) ? &sv_yes : &sv_no; + + +void +bind_param_inout(sth, param, value_ref, maxlen, attribs=Nullsv) + SV * sth + SV * param + SV * value_ref + IV maxlen + SV * attribs + CODE: + DBD_ATTRIBS_CHECK("bind_param_inout", sth, attribs); + if (!SvROK(value_ref)) /* XXX needs better message */ + croak("bind_param_inout needs a reference to the value"); + ST(0) = dbd_bind_ph(sth, param, SvRV(value_ref), attribs, TRUE, maxlen) ? &sv_yes : &sv_no; void @@ -195,7 +213,7 @@ execute(sth, ...) idx = sv_2mortal(newSViv(0)); for(i=1; i < items ; ++i) { sv_setiv(idx, i); - if (!dbd_bind_ph(sth, idx, ST(i), Nullsv)) + if (!dbd_bind_ph(sth, idx, ST(i), Nullsv, FALSE, 0)) ++error; } if (error) { diff --git a/README b/README index 680a4e32..79de986f 100644 --- a/README +++ b/README @@ -52,9 +52,9 @@ documentation for more details. Test your setting by connecting to the database using an Oracle tool such as sqlplus. Once you can do that then you can test DBD::Oracle knowing that it should work. -The test will connect to the database using the value of the -ORACLE_USER environment variable so you should set that to the -correct value before starting the test. Please read README.login. +The supplied test will connect to the database using the value of the +ORACLE_USER environment variable so you should set that to the correct +value before starting the test. Please read README.login. make test make test TEST_VERBOSE=1 (if any of the t/* tests fail) @@ -85,7 +85,7 @@ web you can subscribe by sending a message to dbi-request@fugue.com, it may take a few days to be processed). Please post details of any problems (or changes you needed to make) to -dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. +dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. But note... ** IT IS IMPORTANT TO INCLUDE THE FOLLOWING INFORMATION: @@ -109,7 +109,7 @@ dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. 5. If you get a core dump when using Oraperl try adding this *before* your 'use Oraperl' line: BEGIN { $Oraperl::safe = 1 } unless your version of Oraperl.pm already has $safe=1 in it - (it does by default now). + (it does by default now so you can probably ignore this step). 6. If you still get a core dump rebuild DBD::Oracle with debugging enabled by executing: perl Makefile.PL -g (note the -g option) @@ -128,7 +128,7 @@ posting. If you're not then I'm *very* likely to simply say "upgrade to the latest". You would do yourself a favour by upgrading beforehand. Please remember that I'm _very_ busy. Try to help yourself first, -then try to help me help you by following these guidelines. +then try to help me help you by following these guidelines carefully. Regards, Tim. @@ -136,6 +136,10 @@ Tim. =============================================================================== Examples and other info: +README.clients -- building/using DBD::Oracle on minimally configured systems +README.login -- help for login problems +README.longs -- examples dealing with LONG types (blobs) + DBI 'home page': http://www.hermetica.com/technologia/DBI Master archive site for Perl DB information: @@ -175,32 +179,6 @@ ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip -=============================================================================== -Example for reading LONG fields via blob_read: - - my $sql = "SELECT long_field FROM table_name WHERE id = :1"; - my $csr = ora_open($lda, $sql) or die $ora_errstr; - ora_bind($csr, $id) or die $ora_errstr; - # ora_fetch() needs to be called in an array context - my (@data) = ora_fetch($csr); - my ($frag, $blob, $length, $ll, $offset); - $blob = ''; - $length = 4096; # use benchmarks to get best value for you - $offset = 0; - while (1) - { - $frag = $csr->blob_read(0, $offset, $length); - last unless defined $frag; - $ll = length $frag; - last unless $ll; - $blob .= $frag; - $offset += $ll; - } - print $blob; - -With thanks to james.taylor@srs.gov and desilva@ind70.industry.net. - - =============================================================================== Some users of DBD::Oracle on non-sun platforms: (this is VERY out of date now, there are MANY users on many platforms) @@ -323,6 +301,24 @@ Example: $ENV{ORA_NLS} = "/home/oracle/ocommon/nls/admin/data"; $ENV{ORA_NLS32} = "/home/oracle/ocommon/nls/admin/data"; +Also From: Yngvi Thor Sigurjonsson +I would like all of you who are using 8-bit characters and "export" for +backups to make sure that you have NLS_LANG set when export is run. +Otherwise you might get unusable backups with ? replacing all your +beloved characters. We were lucky once when we noticed that our exports +were damaged before disaster struck. + +------------------------------------------------------------------------------- +AIX - warnings like these when building perl are not usually a problem: + +ld: 0711-415 WARNING: Symbol Perl_sighandler is already exported. +ld: 0711-319 WARNING: Exported symbol not defined: Perl_abs_amg + +When building on AIX check to make sure that all of bos.adt (13 pieces) +and all of bos.compat (11 pieces) are installed. + +Thanks to Mike Moran for this information. + ------------------------------------------------------------------------------- HP-UX 9.x: Terry Greenlaw diff --git a/README.clients b/README.clients index 5d032310..cbadd3e1 100644 --- a/README.clients +++ b/README.clients @@ -1,6 +1,15 @@ This file contains some random notes relating to minimal Oracle configurations for building and/or using DBD::Oracle / Oraperl. +------------------------------------------------------------------------------- +With recent versions of Oracle (specifically around 7.3) you may be +able to build DBD::Oracle without Pro*C installed by using the Oracle +supplied oracle.mk file: + + perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/oracle.mk + +(The oracle.mk file might also be found in $ORACLE_HOME/rdbms/public/) + ------------------------------------------------------------------------------- From: James Cooper diff --git a/README.longs b/README.longs new file mode 100644 index 00000000..e56e0c1c --- /dev/null +++ b/README.longs @@ -0,0 +1,58 @@ +Some examples related to the use of LONG types. + +---------------------------------------------------------------------- +Example for reading LONG fields via blob_read: + + my $sql = "SELECT long_field FROM table_name WHERE id = :1"; + my $csr = ora_open($lda, $sql) or die $ora_errstr; + ora_bind($csr, $id) or die $ora_errstr; + # ora_fetch() needs to be called in an array context + my (@data) = ora_fetch($csr); + my ($frag, $blob, $length, $ll, $offset); + $blob = ''; + $length = 4096; # use benchmarks to get best value for you + $offset = 0; + while (1) + { + $frag = $csr->blob_read(0, $offset, $length); + last unless defined $frag; + $ll = length $frag; + last unless $ll; + $blob .= $frag; + $offset += $ll; + } + print $blob; + +With thanks to james.taylor@srs.gov and desilva@ind70.industry.net. + +---------------------------------------------------------------------- + +Example for inserting LONGS From: Andrew Berry + +# Assuming the existence of @row and an associative array (%clauses) containing the +# column names and placeholders, and an array @types containing column types ... + + $ih = $db->prepare("INSERT INTO $table ($clauses{names}) + VALUES ($clauses{places})") + || die "prepare insert into $table: " . $db->errstr; + + $attrib{'ora_type'} = $longrawtype; # $longrawtype == 24 + + ##-- bind the parameter for each of the columns + for ($i = 0; $i < @types; $i++) { + + ##-- long raw values must have their type attribute explicitly specified + if ($types[$i] == $longrawtype) { + $ih->bind_param($i+1, $row[$i], \%attrib) + || die "binding placeholder for LONG RAW " . $db->errstr; + } + ##-- other values work OK with the default attributes + else { + $ih->bind_param($i+1, $row[$i]) + || die "binding placeholder" . $db->errstr; + } + } + + $ih->execute || die "execute INSERT into $table: " . $db->errstr; + +---------------------------------------------------------------------- diff --git a/dbdimp.c b/dbdimp.c index ab363cac..8036b6fe 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.22 1996/08/22 23:20:19 timbo Exp $ + $Id: dbdimp.c,v 1.23 1996/10/15 02:19:14 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -226,7 +226,6 @@ dbd_db_STORE(dbh, keysv, valuesv) int on = SvTRUE(valuesv); if (kl==10 && strEQ(key, "AutoCommit")) { - /* Ignore SvTRUE warning: '=' where '==' may have been intended. */ if ( (on) ? ocon(&imp_dbh->lda) : ocof(&imp_dbh->lda) ) { ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "ocon/ocof failed"); /* XXX um, we can't return FALSE and true isn't acurate */ @@ -353,6 +352,7 @@ dbd_preparse(imp_sth, statement) phs_t phs_tpl; SV *phs_sv; int idx=0, style=0, laststyle=0; + STRLEN namelen; /* allocate room for copy of statement with spare capacity */ /* for editing '?' or ':1' into ':p1' so we can use obndrv. */ @@ -395,20 +395,21 @@ dbd_preparse(imp_sth, statement) continue; } *dest = '\0'; /* handy for debugging */ + namelen = (dest-start); if (laststyle && style != laststyle) croak("Can't mix placeholder styles (%d/%d)",style,laststyle); laststyle = style; - if (imp_sth->bind_names == NULL) - imp_sth->bind_names = newHV(); + if (imp_sth->all_params_hv == NULL) + imp_sth->all_params_hv = newHV(); phs_tpl.sv = &sv_undef; - phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)); - hv_store(imp_sth->bind_names, start, (STRLEN)(dest-start), - phs_sv, 0); - /* warn("bind_names: '%s'\n", start); */ + phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)+namelen+1); + hv_store(imp_sth->all_params_hv, start, namelen, phs_sv, 0); + strcpy( ((phs_t*)SvPVX(phs_sv))->name, start); + /* warn("params_hv: '%s'\n", start); */ } *dest = '\0'; - if (imp_sth->bind_names) { - DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->bind_names); + if (imp_sth->all_params_hv) { + DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv); if (dbis->debug >= 2) fprintf(DBILOGFP, "scanned %d distinct placeholders\n", (int)DBIc_NUM_PARAMS(imp_sth)); @@ -416,96 +417,6 @@ dbd_preparse(imp_sth, statement) } -int -dbd_bind_ph(sth, ph_namesv, newvalue, attribs) - SV *sth; - SV *ph_namesv; - SV *newvalue; - SV *attribs; -{ - D_imp_sth(sth); - SV **svp; - STRLEN name_len; - char *name; - char buf[90]; - phs_t *phs; - - STRLEN value_len; - void *value_ptr; - - if (SvNIOK(ph_namesv) ) { /* passed as a number */ - name = buf; - sprintf(name, ":p%d", (int)SvIV(ph_namesv)); - name_len = strlen(name); - } else { - name = SvPV(ph_namesv, name_len); - } - - if (dbis->debug >= 2) - fprintf(DBILOGFP, "bind %s <== '%s' (attribs: %s)\n", - name, SvPV(newvalue,na), attribs ? SvPV(attribs,na) : "" ); - - svp = hv_fetch(imp_sth->bind_names, name, name_len, 0); - if (svp == NULL) - croak("dbd_bind_ph placeholder '%s' unknown", name); - phs = (phs_t*)((void*)SvPVX(*svp)); /* placeholder struct */ - - if (phs->sv == &sv_undef) { /* first bind for this placeholder */ - phs->sv = newSV(0); - phs->ftype = 1; - } - - if (attribs) { - /* Setup / Clear attributes as defined by attribs. */ - /* If attribs is EMPTY then reset attribs to default. */ - ; /* XXX */ - if ( (svp=hv_fetch((HV*)SvRV(attribs), "ora_type",8, 0)) == NULL) { - if (!dbtype_is_string(SvIV(*svp))) /* mean but safe */ - croak("bind_param %s ora_type %d not a simple string type", - name, (int)SvIV(*svp)); - phs->ftype = SvIV(*svp); - } - - } /* else if NULL / UNDEF then don't alter attributes. */ - /* This approach allows maximum performance when */ - /* rebinding parameters often (for multiple executes). */ - - /* At the moment we always do sv_setsv() and rebind. */ - /* Later we may optimise this so that more often we can */ - /* just copy the value & length over and not rebind. */ - - if (SvOK(newvalue)) { - /* XXX need to consider oraperl null vs space issues? */ - /* XXX need to consider taking reference to source var */ - sv_setsv(phs->sv, newvalue); - value_ptr = SvPV(phs->sv, value_len); - phs->indp = 0; - - /* Since we don't support LONG VAR types we must check */ - /* for lengths too big to pass to obndrv as an sword. */ - if (value_len > SWORDMAXVAL) /* generally INT_MAX */ - croak("bind_param %s value is too long (%d bytes, max %d)", - name, value_len, SWORDMAXVAL); - } else { - value_ptr = ""; - value_len = 0; - phs->indp = -1; - } - - /* this will change to odndra sometime */ - if (obndrv(imp_sth->cda, (text*)name, -1, - (ub1*)value_ptr, (sword)value_len, - phs->ftype, -1, &phs->indp, - (text*)0, -1, -1)) { - D_imp_dbh_from_sth; - ora_error(sth, &imp_dbh->lda, imp_sth->cda->rc, "obndrv failed"); - return 0; - } - return 1; -} - - - int dbd_describe(h, imp_sth) @@ -524,6 +435,16 @@ dbd_describe(h, imp_sth) return 1; /* success, already done it */ imp_sth->done_desc = 1; + if (imp_sth->cda->ft == 34) { /* SQL function "PL/SQL EXECUTE" */ + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_describe skipped for pl/sql\n"); + return 1; + } + + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_describe (for sql func %d after oci func %d)...\n", + imp_sth->cda->ft, imp_sth->cda->fc); + if (!f_cbufl) { f_cbufl_max = 120; New(1, f_cbufl, f_cbufl_max, sb4); @@ -531,7 +452,7 @@ dbd_describe(h, imp_sth) /* Get number of fields and space needed for field names */ while(++i) { /* break out within loop */ - sb1 cbuf[256]; /* generous max column name length */ + sb1 cbuf[257]; /* generous max column name length */ sb2 dbtype = 0; /* workaround for problem log #405032 */ if (i >= f_cbufl_max) { f_cbufl_max *= 2; @@ -601,7 +522,7 @@ dbd_describe(h, imp_sth) (void)SvPOK_only(fbh->sv); fbh->buf = (ub1*)SvPVX(fbh->sv); - /* BIND */ + /* DEFINE output column variable storage */ if (odefin(imp_sth->cda, i, fbh->buf, fbh->bufl, fbh->ftype, -1, &fbh->indp, (text*)0, -1, -1, &fbh->rlen, &fbh->rcode)) { @@ -617,28 +538,265 @@ dbd_describe(h, imp_sth) ora_error(h, &imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); return 0; } + + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_describe completed for %d columns\n", (int)num_fields); + + return 1; +} + + + +static int +_dbd_rebind_ph(sth, imp_sth, phs, maxlen) + SV *sth; + imp_sth_t *imp_sth; + phs_t *phs; + int maxlen; +{ + maxlen = (maxlen < phs->alen) ? phs->alen : maxlen; + + if (dbis->debug >= 2) + fprintf(DBILOGFP, "bind %s <== '%.200s' (size %d/%d, ora_type %d)\n", + phs->name, (char*)phs->progv, phs->alen,maxlen, phs->ftype); + + if (phs->alen_incnull) + ++phs->alen; + + /* Since we don't support LONG VAR types we must check */ + /* for lengths too big to pass to obndrv as an sword. */ + if (maxlen > SWORDMAXVAL) /* generally 64K */ + croak("Can't bind %s, value is too long (%d bytes, max %d)", + phs->name, maxlen, SWORDMAXVAL); + + if (0) { /* old code */ + if (obndrv(imp_sth->cda, (text*)phs->name, -1, + (ub1*)phs->progv, (sword)phs->alen, + phs->ftype, -1, &phs->indp, + (text*)0, -1, -1)) { + D_imp_dbh_from_sth; + ora_error(sth, &imp_dbh->lda, imp_sth->cda->rc, "obndrv failed"); + return 0; + } + } + else { + if (obndra(imp_sth->cda, (text *)phs->name, -1, + (ub1*)phs->progv, maxlen, (sword)phs->ftype, -1, + &phs->indp, &phs->alen, &phs->arcode, 0, (ub4 *)0, + (text *)0, -1, -1)) { + D_imp_dbh_from_sth; + ora_error(sth, &imp_dbh->lda, imp_sth->cda->rc, "obndra failed"); + return 0; + } + } return 1; } +int +dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) + SV *sth; + SV *ph_namesv; + SV *newvalue; + SV *attribs; + int is_inout; + IV maxlen; +{ + D_imp_sth(sth); + SV **phs_svp; + STRLEN name_len; + char *name; + char namebuf[30]; + phs_t *phs; + + if (SvNIOK(ph_namesv) ) { /* passed as a number */ + name = namebuf; + sprintf(name, ":p%d", (int)SvIV(ph_namesv)); + name_len = strlen(name); + } else { + name = SvPV(ph_namesv, name_len); + } + + if (dbis->debug >= 2) + fprintf(DBILOGFP, "bind %s <== '%.200s' (attribs: %s)\n", + name, SvPV(newvalue,na), attribs ? SvPV(attribs,na) : "" ); + + phs_svp = hv_fetch(imp_sth->all_params_hv, name, name_len, 0); + if (phs_svp == NULL) + croak("Can't bind unknown placeholder '%s'", name); + phs = (phs_t*)SvPVX(*phs_svp); /* placeholder struct */ + + if (phs->sv == &sv_undef) { /* first bind for this placeholder */ + phs->ftype = 1; /* our default type VARCHAR2 */ + if (is_inout) { + /* ensure room for result, 28 is magic number (see sv_2pv) */ + I32 grow_len = (maxlen < 28) ? 28 : maxlen+1; + ++imp_sth->has_inout_params; + phs->is_inout = 1; + phs->sv = SvREFCNT_inc(newvalue); + if (SvOOK(phs->sv)) + sv_backoff(phs->sv); + /* pre-upgrade to cut down risks of SvPVX realloc/move */ + (void)SvUPGRADE(phs->sv, SVt_PVNV); + /* ensure we have a string to point oracle at */ + (void)SvPV(phs->sv, na); + SvGROW(phs->sv, grow_len); + phs->progv = SvPVX(phs->sv); + /* build array of phs's so we can deal with out vars fast */ + if (!imp_sth->out_params_av) + imp_sth->out_params_av = newAV(); + av_push(imp_sth->out_params_av, SvREFCNT_inc(*phs_svp)); + } + else { + phs->sv = newSV(0); + phs->is_inout = 0; + } + + if (attribs) { /* only look for ora_type on first bind of var */ + SV **svp; + /* Setup / Clear attributes as defined by attribs. */ + /* XXX If attribs is EMPTY then reset attribs to default? */ + if ( (svp=hv_fetch((HV*)SvRV(attribs), "ora_type",8, 0)) != NULL) { + int ora_type = SvIV(*svp); + if (!dbtype_is_string(ora_type)) /* mean but safe */ + croak("Can't bind %s, ora_type %d not a simple string type", + phs->name, ora_type); + phs->ftype = ora_type; + } + } + + /* some types require the trailing null included in the length. */ + phs->alen_incnull = (phs->ftype==SQLT_STR || phs->ftype==SQLT_AVC); + + } + else if (is_inout != phs->is_inout) { + croak("Can't change param %s in/out mode", phs->name); + } + + + /* At the moment we always do sv_setsv() and rebind. */ + /* Later we may optimise this so that more often we can */ + /* just copy the value & length over and not rebind. */ + + if (!SvOK(newvalue)) { /* undef == NULL */ + phs->indp = -1; + phs->progv = ""; + phs->alen = 0; + } + else { + STRLEN value_len; + + phs->indp = 0; + + /* XXX need to consider oraperl null vs space issues? */ + + if (is_inout) { /* XXX */ + phs->progv = SvPV(phs->sv, value_len); + } + else { + sv_setsv(phs->sv, newvalue); + phs->progv = SvPV(phs->sv, value_len); + } + phs->alen = value_len + phs->alen_incnull; + } + + + return _dbd_rebind_ph(sth, imp_sth, phs, maxlen); +} + + + int dbd_st_execute(sth) /* <0 is error, >=0 is ok (row count) */ SV *sth; { D_imp_sth(sth); + int debug = dbis->debug; + int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0; if (!imp_sth->done_desc) { - /* describe and allocate storage for results */ + /* describe and allocate storage for results (if any needed) */ if (!dbd_describe(sth, imp_sth)) return -1; /* dbd_describe already called ora_error() */ } + if (debug >= 2) + fprintf(DBILOGFP, + " dbd_st_execute (for sql func %d after oci func %d)...\n", + imp_sth->cda->ft, imp_sth->cda->fc); + + if (outparams) { /* check validity of bound SV's */ + int i = outparams; + STRLEN phs_len; + while(--i >= 0) { + phs_t *phs = (phs_t*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); + /* Make sure we have the value in string format. Typically a number */ + /* will be converted back into a string using the same bound buffer */ + /* so the progv test below will not trip. */ + if (!SvPOK(phs->sv)) { /* ooops, no string ($var = 42) */ + SvPV(phs->sv, phs_len); /* get a string ("42") */ + phs->alen = phs_len + phs->alen_incnull; + } + else { + if (SvOOK(phs->sv)) + sv_backoff(phs->sv); + phs->alen = SvCUR(phs->sv) + phs->alen_incnull; + } + /* Some checks for mutated storage since we pointed oracle at it. */ + /* XXX Instead of croaking we could rebind (probably will later). */ + if (SvTYPE(phs->sv) != SVt_PVNV) + croak("Placeholder %s value mutated type after bind.\n", phs->name); + if (SvPVX(phs->sv) != phs->progv) + croak("Placeholder %s value mutated location after bind.\n", phs->name); + if (debug >= 2) + warn("pre %s = '%s' (len %d)\n", phs->name, SvPVX(phs->sv), phs->alen); + } + } + /* Trigger execution of the statement */ if (oexec(imp_sth->cda)) { /* may change to oexfet later */ ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexec error"); return -1; } - DBIc_ACTIVE_on(imp_sth); + + if (debug >= 2) + fprintf(DBILOGFP, " dbd_st_execute complete (rc %d, w %02x, rpc %ld, op%d)\n", + imp_sth->cda->rc, imp_sth->cda->wrn, + imp_sth->cda->rpc, imp_sth->has_inout_params); + + if (outparams) { /* check validity of bound SV's */ + int i = outparams; + STRLEN retlen; + while(--i >= 0) { + phs_t *phs = (phs_t*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); + SV *sv = phs->sv; + if (phs->indp == 0) { /* is okay */ + SvPOK_only(sv); + SvCUR(sv) = phs->alen; + *SvEND(sv) = '\0'; + if (debug >= 2) + warn(" %s = '%s' (len %d)\n", phs->name, SvPV(sv,retlen),retlen); + } + else + if (phs->indp > 0 || phs->indp == -2) { /* truncated */ + SvPOK_only(sv); + SvCUR(sv) = phs->alen; + *SvEND(sv) = '\0'; + if (debug >= 2) + warn(" %s = '%s' (TRUNCATED from %d to %d)\n", phs->name, + SvPV(sv,retlen), phs->indp, retlen); + } + else + if (phs->indp == -1) { /* is NULL */ + (void)SvOK_off(phs->sv); + if (debug >= 2) + warn(" %s = undef (NULL)\n", phs->name); + } + else croak("%s bad indp %d", phs->name, phs->indp); + } + } + + DBIc_ACTIVE_on(imp_sth); /* XXX should only set for select ? */ return imp_sth->cda->rpc; /* row count */ } @@ -821,20 +979,22 @@ dbd_st_destroy(sth) Safefree(imp_sth->fbh_cbuf); Safefree(imp_sth->statement); - if (imp_sth->bind_names) { - HV *hv = imp_sth->bind_names; + if (imp_sth->out_params_av) + sv_free((SV*)imp_sth->out_params_av); + + if (imp_sth->all_params_hv) { + HV *hv = imp_sth->all_params_hv; SV *sv; char *key; I32 retlen; hv_iterinit(hv); while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) { - phs_t *phs_tpl; if (sv != &sv_undef) { - phs_tpl = (phs_t*)SvPVX(sv); + phs_t *phs_tpl = (phs_t*)SvPVX(sv); sv_free(phs_tpl->sv); } } - sv_free((SV*)imp_sth->bind_names); + sv_free((SV*)imp_sth->all_params_hv); } DBIc_IMPSET_off(imp_sth); /* let DBI know we've done it */ diff --git a/dbdimp.h b/dbdimp.h index 4adb5389..3c9968ae 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.11 1996/03/05 02:27:25 timbo Exp $ + $Id: dbdimp.h,v 1.12 1996/10/15 02:19:14 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -39,15 +39,19 @@ struct imp_sth_st { Cda_Def cdabuf; /* Input Details */ - char *statement; /* sql (see sth_scan) */ - HV *bind_names; + char *statement; /* sql (see sth_scan) */ + HV *all_params_hv; /* all params, keyed by name */ + AV *out_params_av; /* quick access to inout params */ - /* Output Details */ + /* Select Column Output Details */ int done_desc; /* have we described this sth yet ? */ imp_fbh_t *fbh; /* array of imp_fbh_t structs */ char *fbh_cbuf; /* memory for all field names */ sb4 long_buflen; /* length for long/longraw (if >0) */ bool long_trunc_ok; /* is truncating a long an error */ + + /* (In/)Out Parameter Details */ + bool has_inout_params; }; #define IMP_STH_EXECUTING 0x0001 @@ -83,6 +87,15 @@ struct phs_st { /* scalar placeholder EXPERIMENTAL */ SV *sv; /* the scalar holding the value */ sword ftype; /* external OCI field type */ sb2 indp; /* null indicator */ + + /* fields for inout params */ + bool is_inout; + char *progv; + ub2 alen; + ub2 arcode; + int alen_incnull; /* 0 or 1 if alen should include null */ + + char name[1]; /* struct is malloc'd bigger as needed */ }; @@ -91,8 +104,8 @@ void fbh_dump _((imp_fbh_t *fbh, int i)); void dbd_init _((dbistate_t *dbistate)); void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); -int dbd_describe _((SV *h, imp_sth_t *imp_sth)); -int dbd_st_blob_read _((SV *sth, int field, long offset, long len, +int dbd_describe _((SV *h, imp_sth_t *imp_sth)); +int dbd_st_blob_read _((SV *sth, int field, long offset, long len, SV *destrv, long destoffset)); /* end */ diff --git a/test.pl b/test.pl index 405a42ce..adff977e 100755 --- a/test.pl +++ b/test.pl @@ -1,6 +1,6 @@ #!/usr/local/bin/perl -w -# $Id: test.pl,v 1.24 1996/09/23 19:30:58 timbo Exp $ +# $Id: test.pl,v 1.25 1996/10/15 02:19:14 timbo Exp $ # # Copyright (c) 1995, Tim Bunce # @@ -10,7 +10,7 @@ require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.24 $}."\n"; +print q{Oraperl test application $Revision: 1.25 $}."\n"; $SIG{__WARN__} = sub { ($_[0] =~ /^Bad free/) ? warn "See README about Bad free() warnings!\n": warn @_; @@ -20,7 +20,8 @@ $opt_l = 0; # log $opt_c = 5; # count for loops $opt_m = 0; # count for mem leek test -&Getopts('m:d:c:l') || die "Invalid options\n"; +$opt_p = 1; # test pl/sql code +&Getopts('m:d:c:lp ') || die "Invalid options\n"; $ENV{PERL_DBI_DEBUG} = 2 if $opt_d; $ENV{ORACLE_HOME} = '/usr/oracle' unless $ENV{ORACLE_HOME}; @@ -66,7 +67,8 @@ rename("test.log","test.olog") if $opt_l; eval 'DBI->internal->{DebugLog} = "test.log";' if $opt_l; -&test3($opt_m) if ($opt_m); +&test3($opt_m) if $opt_m; + &test1(); print "\nTesting repetitive connect/open/close/disconnect:\n"; @@ -83,7 +85,9 @@ &ora_logoff($lda2) || warn "ora_logoff($lda2): $ora_errno: $ora_errstr\n"; print "done.\n"; -&test3($opt_m) if ($opt_m); +&test3($opt_m) if $opt_m; + +&test_plsql() if $opt_p; $dur = time - $start; print "\nTest complete ($dur seconds).\n"; @@ -197,4 +201,73 @@ sub test3 { system("echo $i; $ps$$") if (($i % 10) == 0); } + +sub test_plsql { + + print "\nTesting PL/SQL interaction.\n"; + + local($l) = &ora_login($dbname, $dbuser, '') + || die "ora_login: $ora_errno: $ora_errstr\n"; + my $c; + + $c = &ora_open($l, q{ + begin RAISE invalid_number; end; + }); + # Expect ORA-01722: invalid number + die "ora_open: $ora_errstr" unless $ora_errno == 1722; + + $c = &ora_open($l, q{ + DECLARE FOO EXCEPTION; + begin raise foo; end; + }); + # Expect ORA-06510: PL/SQL: unhandled user-defined exception + die "ora_open: $ora_errstr" unless $ora_errno == 6510; + + $c = &ora_open($l, q{ + begin raise_application_error(-20101,'app error'); end; + }); + # Expect our exception number and error text + die "ora_open: $ora_errno $ora_errstr" + unless $ora_errno == 20101; # our exception number + die "ora_open: $ora_errstr" + unless $ora_errstr =~ m/app error/; # our exception text + + $c = &ora_open($l, q{ + declare err_num number; err_msg char(510); + begin + err_num := :1; + err_msg := :2; + raise_application_error(-20000-err_num, 'plus '||err_msg); + end; + }) || die "ora_open: $ora_errstr"; + $c->execute(42,"my msg"); + # Expect our exception number and error text + die "ora_open: $ora_errno $ora_errstr" + unless $ora_errno == 20042; # our exception number + die "ora_open: $ora_errstr" + unless $ora_errstr =~ m/plus my msg/; # our exception text + + print "Testing bind_param_inout. Expect '200', '3800', '75800':\n"; + #$l->debug(2); + #DBI->internal->{DebugDispatch} = 2; + $c = &ora_open($l, q{ + declare bar number; + begin bar := :1; bar := bar * 20; :1 := bar; end; + }) || die "ora_open: $ora_errstr"; + $param = 10; + $c->bind_param_inout(1, \$param, 100) || die "bind_param_inout $ora_errstr"; + do { + $c->execute || die "execute $ora_errstr"; + print "param='$param'\n"; + $param -= 10; + } while ($param < 70000); + + # To do + # test NULLs at first bind + # NULLS later binds. + # returning NULLS + # multiple params, mixed types and in only vs inout + # automatic rebind if location changes +} + # end. From ab9bf2f3151539686b6a06dca095813538f23201 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Tue, 29 Oct 1996 12:32:00 -0500 Subject: [PATCH 021/637] import DBD-Oracle 0.43 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.43 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.43.tar.gz --- .purify | 11 +++ Changes | 32 +++++++ MANIFEST | 1 + Oracle.pm | 6 +- Oraperl.pm | 42 ++++----- README | 26 +++++- README.login | 17 ++-- dbdimp.c | 254 +++++++++++++++++++++++++++++++++++++-------------- dbdimp.h | 53 +++++++---- test.pl | 62 ++++++++++--- 10 files changed, 366 insertions(+), 138 deletions(-) create mode 100644 .purify diff --git a/.purify b/.purify new file mode 100644 index 00000000..ef7a6ae0 --- /dev/null +++ b/.purify @@ -0,0 +1,11 @@ +suppress umr strlen; sosngun +suppress umr "libclntsh.so.1.0" +suppress umr _nsc_trydoorcall; _door_gethostbyname_r; _get_hostserv_inetnetdir_byname; gethostbyname_r; nttbnd2addr +suppress umr process_gethost +suppress umr _get_hostserv_inetnetdir_byname +suppress umr _s_cpaddr; __getsockname; getsockname; nttcni +suppress umr _libc_write; write; nttwr +suppress umr _nsc_trydoorcall; getpwuid_r; sigunmu +suppress umr strlen; sigunmu +suppress umr _nsc_trydoorcall; getpwuid_r; sosngun + diff --git a/Changes b/Changes index 1ee4bf4b..effa29c9 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,35 @@ + +Changes in DBD::Oracle 0.43 (Oraperl 1.30), 29nd Oct 1996 + + Fixed serious 'false ora_errno 1 after short select' bug. + Worked around oracle bug that makes cda->ft unreliable. + Do not use DBD::Oracle 0.41 or 0.42. + Cursors are now 'describe'd at prepare time thus making + NUM_OF_FIELDS always available. Describe does nothing for + non-select operations. NUM_OF_FIELDS > 0 is now used to + select between oexec() and oexfet() in execute(). + Added a more internal debugging. Improved test.pl. + +Changes in DBD::Oracle 0.42 (Oraperl 1.30), 28nd Oct 1996 + + Fixed serious 'cache empty after re-bind' bug. + Do not use DBD::Oracle 0.41. + Implemented oexfet (combined execute and cache fetch) for + select operations. This is a further significant speed up. + Many selects now make only one trip to Oracle (after prepare) + which combines the execute and fetching multiple rows. + +Changes in DBD::Oracle 0.41 (Oraperl 1.30), 22nd Oct 1996 + + Added the long overdue row cache to DBD::Oracle. + (Thanks to Reetnem@aol.com for providing a patch that prompted + me to complete the work.) + Oraperl $ora_cache and cache parameter to ora_open now work. + Default cache size is adjusted automatically for row width. + Major reworking of field buffer memory management. + Added a more internal debugging. + Further updates to the README files. + Changes in DBD::Oracle 0.40 (Oraperl 1.29), 14th Oct 1996 WARNING - This release contains significant changes to the diff --git a/MANIFEST b/MANIFEST index d06cc64f..9b189d04 100644 --- a/MANIFEST +++ b/MANIFEST @@ -15,6 +15,7 @@ dbdimp.c test.pl t/base.t hints/svr4.pl +.purify Ignore most of the (many) problems in Oracle's libraries. Very sad. oraperl.ph Old oraperl file included for completeness of emulation oraperl.ex/Readme Oraperl examples (copied mostly unchanged from oraperl-2.4) oraperl.ex/bind.pl diff --git a/Oracle.pm b/Oracle.pm index 88169bc4..2ff11974 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.38 1996/10/15 02:19:14 timbo Exp $ +# $Id: Oracle.pm,v 1.41 1996/10/29 13:20:39 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -16,8 +16,8 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.40'; - my $Revision = substr(q$Revision: 1.38 $, 10); + $VERSION = '0.43'; + my $Revision = substr(q$Revision: 1.41 $, 10); require_version DBI 0.69; diff --git a/Oraperl.pm b/Oraperl.pm index b1d52b5d..59e55e29 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.29 1996/09/23 19:30:58 timbo Exp $ +# $Id: Oraperl.pm,v 1.31 1996/10/29 18:17:23 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -23,7 +23,7 @@ require 5.002; use DBI 0.70; use Exporter; -$VERSION = substr(q$Revision: 1.29 $, 10); +$VERSION = substr(q$Revision: 1.31 $, 10); @ISA = qw(Exporter); @@ -44,27 +44,22 @@ $safe = 1 unless defined $safe; # Help those who get core dumps from non-'safe' Oraperl (bad cursors) use sigtrap qw(ILL); -$SIG{BUS} = $SIG{SEGV} = sub { +if (!$safe) { + $SIG{BUS} = $SIG{SEGV} = sub { print STDERR "Add BEGIN { \$Oraperl::safe=1 } above 'use Oraperl'.\n" unless $safe; goto &sigtrap::trap; -}; - - -if ($debugdbi){ - my $sw = DBI->internal; - $sw->debug($debugdbi); - print "Switch: $sw->{Attribution}, $sw->{Version}\n"; - $sw->{DebugDispatch} = $debugdbi; + }; } -# Install Driver + +# Install Driver (use of install_driver is a special case here) $drh = DBI->install_driver('Oracle'); if ($drh) { - print "DBD::Oracle driver installed as $drh\n" if $debug; - $drh->debug($debug); - $drh->{CompatMode} = 1; - $drh->{Warn} = 0; + print "DBD::Oracle driver installed as $drh\n" if $debug; + $drh->debug($debug); + $drh->{CompatMode} = 1; + $drh->{Warn} = 0; } @@ -115,7 +110,8 @@ sub ora_logoff { # &ora_close($csr) sub ora_open { - my($lda, $stmt, $cache) = @_; + my($lda, $stmt) = @_; + $Oraperl::ora_cache_o = $_[2]; # temp hack to pass cache through my $csr = $lda->prepare($stmt) or return undef; @@ -250,7 +246,7 @@ Oraperl - Perl access to Oracle databases for old oraperl scripts &ora_commit($lda) &ora_rollback($lda) &ora_autocommit($lda, $on_off) - &ora_version + &ora_version() $ora_cache $ora_long @@ -337,8 +333,6 @@ used. As distributed, the default is five rows, but this may have been changed at your installation (see the &ora_version() function and $ora_cache variable below). -B currently $cache is ignored. That should change soon. - Examples: $csr = &ora_open($lda, 'select ename, sal from emp order by ename', 10); @@ -590,7 +584,7 @@ program. Example: - oraperl -e '&ora_version' + perl -MOraperl -e 'ora_version()' This is Oraperl, version 2, patch level 0. @@ -637,8 +631,6 @@ As a special case, assigning zero to $ora_cache resets it to the default value. Attempting to set $ora_cache to a negative value results in a warning. -B Not yet supported. - =item * $ora_long @@ -807,10 +799,10 @@ with the DBI and DBD::Oracle modules whilst insulating users from the ongoing changes in their interfaces.) It is quite possible, indeed probable, that some differences in -behaviour will exist. This should be confined to error handling. +behaviour will exist. These are probably confined to error handling. B differences in behaviour which are not documented here should be -reported to Tim.Bunce@ig.co.uk and CC'd to dbi-users@fugue.com. +reported to Tim.Bunce@ig.co.uk B CC'd to dbi-users@fugue.com. =head1 SEE ALSO diff --git a/README b/README index 79de986f..35af93dd 100644 --- a/README +++ b/README @@ -12,9 +12,11 @@ DBD::Oracle -- an Oracle 7 interface for Perl 5. * THE ORAPERL EMULATION IS NO LONGER ALPHA. IT IS NOW FULLY RELEASED. * -* The only currently supported interface is via Oraperl.pm, the * -* oraperl emulation layer. This is fairly complete and stable. * -* Execute "perldoc Oraperl" after installing for full information. * + +| NOTE: +| The only currently supported interface is via Oraperl.pm, the | +| oraperl emulation layer. This is fairly complete and stable. | +| Execute "perldoc Oraperl" after installing for full information. | @@ -71,7 +73,8 @@ Makefile.PL command line and/or editing the Makefile.PL. You should not need to make any changes. If you do *please* let me know so that I can try to make it automatic in a later release. -If you just can't login then read README.login and edit test.pl to suit. +If you just can't login or login takes a long time then read +README.login and edit test.pl to suit. If you can't get it to build on a minimally configured client system then read README.client, it might help but basically I can't help much. @@ -150,6 +153,8 @@ Perl 4 Oraperl (v2.4) /perl4/oraperl/ Searchable index of the dbi-users mailing list: http://www.coe.missouri.edu/~faq/lists/dbiusers/ +IOUW 1996 Paper on connecting Oracle to the Web: +http://www.cse.psu.edu/~groenvel/IOUW96/paper/. ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources/... @@ -248,6 +253,14 @@ If DBD::Oracle was built on a machine with a different path to libclntsh.so then you'll need to set set an environment variable, typically LD_LIBRARY_PATH, to include the directory containing libclntsh.so. +But: LD_LIBRARY_PATH is typically ignored if the script is running set-uid +(which is common in some httpd/CGI configurations). In this case +either rebuild with LD_RUN_PATH set to include the path to libclntsh +or create a symbolic link so that libclntsh is available via the same +path as it was when the module was built. (On Solaris the command +"ldd -s Oracle.so" can be used to see how the linker is searching for it.) + + ------------------------------------------------------------------------------- Error while trying to retrieve text for error ...: @@ -258,6 +271,11 @@ If your national language is different from ours (American English), you will probably need different nls data files. +------------------------------------------------------------------------------- +Login takes a long time + +Use connect('', 'user/passwd@tnsname', ''). See README.login. + ------------------------------------------------------------------------------- Oracle 7.3 on Solaris 2.5 (maybe others): diff --git a/README.login b/README.login index db6a062f..a24d30ce 100644 --- a/README.login +++ b/README.login @@ -37,11 +37,11 @@ Perl with DBI/DBD Below are various ways of connecting to an oracle database using SQL*Net 1.x and SQL*Net 2.x. "Machine" is the computer the database is -running on, "SID" is the SID of the database, "MS2" is the SQL*Net 2.x +running on, "SID" is the SID of the database, "DB" is the SQL*Net 2.x connection descriptor for the database. BEGIN { - $ENV{TWO_TASK}='MS2'; + $ENV{TWO_TASK}='DB'; $ENV{ORACLE_HOME} = '/home/oracle/product/7.x.x'; } ora_login('','scott/tiger'); @@ -65,12 +65,17 @@ $lda = ora_login('T:Machine:SID','username','password'); $lda = ora_login('','username@T:Machine:SID','password'); -$lda = ora_login('','username@MS2','password'); +$lda = ora_login('','username@DB','password'); -$lda = ora_login('MS2','username','password'); +$lda = ora_login('DB','username','password'); -$lda = ora_login('MS2','username/password',''); +$lda = ora_login('DB','username/password',''); +With thanks to James Taylor . +If you are having problems with login taking a long time (>10 secs say) +then try using one of the ...@DB variants. E.g., -With thanks to James Taylor . + $lda = ora_login('','username/password@DB',''); + +Tim. diff --git a/dbdimp.c b/dbdimp.c index 8036b6fe..062d04d1 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.23 1996/10/15 02:19:14 timbo Exp $ + $Id: dbdimp.c,v 1.28 1996/10/29 18:17:23 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -15,6 +15,8 @@ DBISTATE_DECLARE; static SV *ora_long; static SV *ora_trunc; +static SV *ora_cache; +static SV *ora_cache_o; /* temp hack for ora_open() cache override */ void @@ -22,8 +24,10 @@ dbd_init(dbistate) dbistate_t *dbistate; { DBIS = dbistate; - ora_long = perl_get_sv("Oraperl::ora_long", GV_ADDMULTI); - ora_trunc = perl_get_sv("Oraperl::ora_trunc", GV_ADDMULTI); + ora_long = perl_get_sv("Oraperl::ora_long", GV_ADDMULTI); + ora_trunc = perl_get_sv("Oraperl::ora_trunc", GV_ADDMULTI); + ora_cache = perl_get_sv("Oraperl::ora_cache", GV_ADDMULTI); + ora_cache_o = perl_get_sv("Oraperl::ora_cache_o", GV_ADDMULTI); } @@ -69,9 +73,10 @@ ora_error(h, lda, rc, what) void -fbh_dump(fbh, i) +fbh_dump(fbh, i, aidx) imp_fbh_t *fbh; int i; + int aidx; /* array index */ { FILE *fp = DBILOGFP; fprintf(fp, "fbh %d: '%s' %s, ", @@ -79,8 +84,9 @@ fbh_dump(fbh, i) fprintf(fp, "type %d, dbsize %ld, dsize %ld, p%d s%d\n", fbh->dbtype, (long)fbh->dbsize, (long)fbh->dsize, fbh->prec, fbh->scale); - fprintf(fp, " out: ftype %d, indp %d, bufl %d, rlen %d, rcode %d\n", - fbh->ftype, fbh->indp, fbh->bufl, fbh->rlen, fbh->rcode); + fprintf(fp, " out: ftype %d, bufl %d. cache@%d: indp %d, rlen %d, rcode %d\n", + fbh->ftype, fbh->fb_ary->bufl, aidx, fbh->fb_ary->aindp[aidx], + fbh->fb_ary->arlen[aidx], fbh->fb_ary->arcode[aidx]); } @@ -118,7 +124,36 @@ dbtype_is_string(dbtype) /* 'can we use SvPV to pass buffer?' */ } -/* ================================================================== */ +/* --- allocate and free oracle oci 'array' buffers --- */ + +fb_ary_t * +fb_ary_alloc(bufl, size) +int bufl; +int size; +{ + fb_ary_t *fb_ary; + /* these should be reworked to only to one Newz() */ + /* and setup the pointers in the head fb_ary struct */ + Newz(42, fb_ary, sizeof(fb_ary_t), fb_ary_t); + Newz(42, fb_ary->abuf, size * bufl, ub1); + Newz(42, fb_ary->aindp, size, sb2); + Newz(42, fb_ary->arlen, size, ub2); + Newz(42, fb_ary->arcode, size, ub2); + fb_ary->bufl = bufl; + return fb_ary; +} + +void +fb_ary_free(fb_ary) +fb_ary_t *fb_ary; +{ + Safefree(fb_ary->abuf); + Safefree(fb_ary->aindp); + Safefree(fb_ary->arlen); + Safefree(fb_ary->arcode); + Safefree(fb_ary); +} + static void @@ -306,16 +341,18 @@ dbd_st_prepare(sth, statement, attribs) imp_sth->cda->peo = 0; if (oparse(imp_sth->cda, (text*)imp_sth->statement, (sb4)-1, (sword)oparse_defer, (ub4)oparse_lng)) { - SV *msgsv; + SV *msgsv, *sqlsv; char msg[99]; - sprintf(msg,"possibly parse error near character %d of %d in '", - imp_sth->cda->peo+1, (int)strlen(imp_sth->statement)); + sqlsv = sv_2mortal(newSVpv(imp_sth->statement,0)); + sv_insert(sqlsv, imp_sth->cda->peo, 0, "<*>",3); + sprintf(msg,"error possibly near <*> indicator at char %d in '", + imp_sth->cda->peo+1); msgsv = sv_2mortal(newSVpv(msg,0)); - sv_catpv(msgsv, imp_sth->statement); + sv_catsv(msgsv, sqlsv); sv_catpv(msgsv, "'"); - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, SvPV(msgsv,na)); + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, SvPV(msgsv,na)); oclose(imp_sth->cda); /* close the cursor */ - return 0; + return 0; } /* long_buflen: length for long/longraw (if >0) */ @@ -329,14 +366,17 @@ dbd_st_prepare(sth, statement, attribs) imp_sth->long_trunc_ok = 1; /* can use blob_read() */ } + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_st_prepare'd sql f%d (lb %ld, lt %d)\n", + imp_sth->cda->ft, (long)imp_sth->long_buflen, imp_sth->long_trunc_ok); + /* Describe and allocate storage for results. This could */ /* and possibly should be deferred until execution or some */ /* output related information is fetched. */ -/* defered - if (!dbd_describe(dbh, imp_sth)) { +/* was defered prior to 0.43 */ + if (!dbd_describe(sth, imp_sth)) { return 0; } -*/ DBIc_IMPSET_on(imp_sth); return 1; } @@ -411,7 +451,7 @@ dbd_preparse(imp_sth, statement) if (imp_sth->all_params_hv) { DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv); if (dbis->debug >= 2) - fprintf(DBILOGFP, "scanned %d distinct placeholders\n", + fprintf(DBILOGFP, " dbd_preparse scanned %d distinct placeholders\n", (int)DBIc_NUM_PARAMS(imp_sth)); } } @@ -429,20 +469,23 @@ dbd_describe(h, imp_sth) sb1 *cbuf_ptr; int t_cbufl=0; I32 num_fields; + int has_longs = 0; int i = 0; if (imp_sth->done_desc) return 1; /* success, already done it */ imp_sth->done_desc = 1; - if (imp_sth->cda->ft == 34) { /* SQL function "PL/SQL EXECUTE" */ + if (imp_sth->cda->ft != FT_SELECT) { if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_describe skipped for pl/sql\n"); + fprintf(DBILOGFP, " dbd_describe skipped for non-select (sql f%d)\n", + imp_sth->cda->ft); + /* imp_sth memory was cleared when created so no setup required here */ return 1; } if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_describe (for sql func %d after oci func %d)...\n", + fprintf(DBILOGFP, " dbd_describe (for sql f%d after oci f%d)...\n", imp_sth->cda->ft, imp_sth->cda->fc); if (!f_cbufl) { @@ -453,17 +496,22 @@ dbd_describe(h, imp_sth) /* Get number of fields and space needed for field names */ while(++i) { /* break out within loop */ sb1 cbuf[257]; /* generous max column name length */ - sb2 dbtype = 0; /* workaround for problem log #405032 */ + sb2 dbtype = 0; /* workaround for Oracle bug #405032 */ + sb4 dbsize; if (i >= f_cbufl_max) { f_cbufl_max *= 2; Renew(f_cbufl, f_cbufl_max, sb4); } f_cbufl[i] = sizeof(cbuf); - odescr(imp_sth->cda, i, (sb4*)0, &dbtype, + odescr(imp_sth->cda, i, &dbsize, &dbtype, cbuf, &f_cbufl[i], (sb4*)0, (sb2*)0, (sb2*)0, (sb2*)0); if (imp_sth->cda->rc || dbtype == 0) break; - t_cbufl += f_cbufl[i]; + t_cbufl += f_cbufl[i]; + if (dbsize) + imp_sth->t_dbsize += dbsize; + else if (dbtype_is_long(dbtype)) + ++has_longs; /* hint to auto cache sizing code */ } if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { D_imp_dbh_from_sth; @@ -474,6 +522,30 @@ dbd_describe(h, imp_sth) num_fields = i - 1; DBIc_NUM_FIELDS(imp_sth) = num_fields; + /* --- Setup the row cache for this query --- */ + if (SvOK(ora_cache_o)) imp_sth->cache_size = SvIV(ora_cache_o); + else if (SvOK(ora_cache)) imp_sth->cache_size = SvIV(ora_cache); + else imp_sth->cache_size = 0; /* auto size */ + /* deal with default (auto-size) and out of range cases */ + if (imp_sth->cache_size < 1) { /* 0 == try to pick 'optimal' */ + /* Guess a maximum on-the-wire row width (but note t_dbsize */ + /* doesn't include longs yet so this could be suboptimal) */ + int width = 8 + imp_sth->t_dbsize + num_fields*5; + /* How many rows fit in 2Kb? (2Kb is a reasonable compromise) */ + imp_sth->cache_size = 2048 / width; + if (imp_sth->cache_size < 5) /* cache at least 5 */ + imp_sth->cache_size = 5; + else /* if query includes longs, limit auto-size to 10 rows */ + if (has_longs && imp_sth->cache_size > 10) + imp_sth->cache_size = 10; + } + if (imp_sth->cache_size > 32767) /* keep within Oracle's limits */ + imp_sth->cache_size = 32767; + /* Initialise cache counters */ + imp_sth->in_cache = 0; + imp_sth->eod_errno = 0; + + /* allocate field buffers */ Newz(42, imp_sth->fbh, num_fields, imp_fbh_t); /* allocate a buffer to hold all the column names */ @@ -482,6 +554,7 @@ dbd_describe(h, imp_sth) cbuf_ptr = (sb1*)imp_sth->fbh_cbuf; for(i=1; i <= num_fields && imp_sth->cda->rc != 10; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i-1]; + fb_ary_t *fb_ary; int dbtype; fbh->imp_sth = imp_sth; @@ -506,6 +579,7 @@ dbd_describe(h, imp_sth) fbh->dbsize = buflen; fbh->dsize = buflen; fbh->ftype = dbtype; /* get long in non-var form */ + imp_sth->t_dbsize += buflen; } else { /* for the time being we fetch everything (except longs) */ /* as strings, that'll change (IV, NV and binary data etc) */ @@ -513,35 +587,33 @@ dbd_describe(h, imp_sth) /* dbsize can be zero for 'select NULL ...' */ } - fbh->bufl = fbh->dsize+1; /* +1: STRING null terminator */ - - /* currently we use an sv, later we'll use an array */ - fbh->sv = newSV((STRLEN)fbh->bufl); - (void)SvUPGRADE(fbh->sv, SVt_PV); - SvREADONLY_on(fbh->sv); - (void)SvPOK_only(fbh->sv); - fbh->buf = (ub1*)SvPVX(fbh->sv); + fbh->fb_ary = fb_ary = fb_ary_alloc( + fbh->dsize+1, /* +1: STRING null terminator */ + imp_sth->cache_size + ); /* DEFINE output column variable storage */ - if (odefin(imp_sth->cda, i, fbh->buf, fbh->bufl, - fbh->ftype, -1, &fbh->indp, - (text*)0, -1, -1, &fbh->rlen, &fbh->rcode)) { + if (odefin(imp_sth->cda, i, fb_ary->abuf, fb_ary->bufl, + fbh->ftype, -1, fb_ary->aindp, (text*)0, -1, -1, + fb_ary->arlen, fb_ary->arcode)) { warn("odefin error on %s: %d", fbh->cbuf, imp_sth->cda->rc); } if (dbis->debug >= 2) - fbh_dump(fbh, i); + fbh_dump(fbh, i, 0); } + if (dbis->debug >= 2) + fprintf(DBILOGFP, + " dbd_describe'd %d columns (~%d data bytes, %d cache rows)\n", + (int)num_fields, imp_sth->t_dbsize, imp_sth->cache_size); + if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { D_imp_dbh_from_sth; ora_error(h, &imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); return 0; } - if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_describe completed for %d columns\n", (int)num_fields); - return 1; } @@ -685,11 +757,8 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) } else { STRLEN value_len; - phs->indp = 0; - /* XXX need to consider oraperl null vs space issues? */ - if (is_inout) { /* XXX */ phs->progv = SvPV(phs->sv, value_len); } @@ -700,7 +769,6 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) phs->alen = value_len + phs->alen_incnull; } - return _dbd_rebind_ph(sth, imp_sth, phs, maxlen); } @@ -722,7 +790,7 @@ dbd_st_execute(sth) /* <0 is error, >=0 is ok (row count) */ if (debug >= 2) fprintf(DBILOGFP, - " dbd_st_execute (for sql func %d after oci func %d)...\n", + " dbd_st_execute (for sql f%d after oci f%d)...\n", imp_sth->cda->ft, imp_sth->cda->fc); if (outparams) { /* check validity of bound SV's */ @@ -753,16 +821,36 @@ dbd_st_execute(sth) /* <0 is error, >=0 is ok (row count) */ } } - /* Trigger execution of the statement */ - if (oexec(imp_sth->cda)) { /* may change to oexfet later */ - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexec error"); - return -1; + /* reset cache counters */ + imp_sth->in_cache = 0; + imp_sth->next_entry = 0; + imp_sth->eod_errno = 0; + + /* Trigger execution of the statement */ + if (DBIc_NUM_FIELDS(imp_sth) > 0) { /* is a SELECT */ + /* The number of fields is used because imp_sth->cda->ft is unreliable. */ + /* Specifically an update (5) may change to select (4) after odesc(). */ + if (oexfet(imp_sth->cda, (ub4)imp_sth->cache_size, 0, 0) + && imp_sth->cda->rc != 1403 /* other than no more data */ ) { + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexfet error"); + return -1; + } + imp_sth->in_cache = imp_sth->cda->rpc; /* cache loaded */ + if (imp_sth->cda->rc == 1403) + imp_sth->eod_errno = 1403; + } + else { /* NOT a select */ + if (oexec(imp_sth->cda)) { + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexec error"); + return -1; + } } if (debug >= 2) - fprintf(DBILOGFP, " dbd_st_execute complete (rc %d, w %02x, rpc %ld, op%d)\n", + fprintf(DBILOGFP, " dbd_st_execute complete (rc%d, w%02x, rpc%ld, eod%d, out%d)\n", imp_sth->cda->rc, imp_sth->cda->wrn, - imp_sth->cda->rpc, imp_sth->has_inout_params); + imp_sth->cda->rpc, imp_sth->eod_errno, + imp_sth->has_inout_params); if (outparams) { /* check validity of bound SV's */ int i = outparams; @@ -811,36 +899,59 @@ dbd_st_fetch(sth) int num_fields; int i; AV *av; - /* Check that execute() was executed sucessfuly. This also implies */ + + /* Check that execute() was executed sucessfully. This also implies */ /* that dbd_describe() executed sucessfuly so the memory buffers */ /* are allocated and bound. */ if ( !DBIc_ACTIVE(imp_sth) ) { ora_error(sth, NULL, 1, "no statement executing"); return Nullav; } - /* This will become ofen() once the buffer management is reworked. */ - if (ofetch(imp_sth->cda)) { - if (imp_sth->cda->rc != 1403) { /* was not just end-of-fetch */ - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "ofetch error"); - /* should we ocan() here? */ - } else { - sv_setiv(DBIc_ERR(imp_sth), 0); /* just end-of-fetch */ + + if (!imp_sth->in_cache) { /* refill cache if empty */ + int rows_returned; + + if (imp_sth->eod_errno) { + end_of_data: + if (imp_sth->eod_errno != 1403) { /* was not just end-of-fetch */ + ora_error(sth, imp_sth->cda, imp_sth->eod_errno, "ofetch error"); + } else { /* is simply no more data */ + sv_setiv(DBIc_ERR(imp_sth), 0); /* ensure errno set to 0 here */ + if (debug >= 2) + fprintf(DBILOGFP, " dbd_st_fetch no-more-data, rc=%d, rpc=%ld\n", + imp_sth->cda->rc, imp_sth->cda->rpc); + } + imp_sth->eod_errno = 0; /* let user retry if they want */ + return Nullav; } - if (debug >= 3) - fprintf(DBILOGFP, " dbd_st_fetch failed, rc=%d", - imp_sth->cda->rc); - return Nullav; + + rows_returned = imp_sth->cda->rpc; /* remember rpc before re-fetch */ + if (ofen(imp_sth->cda, imp_sth->cache_size)) { + /* Note that errors may happen after one or more rows have been */ + /* added to the cache. We record the error but don't handle it till */ + /* the cache is empty (which may be at once if no rows returned). */ + imp_sth->eod_errno = imp_sth->cda->rc; /* store rc for later */ + if (imp_sth->cda->rpc == rows_returned) /* no more rows fetched */ + goto end_of_data; + /* else fall through and return the first of the fetched rows */ + } + imp_sth->in_cache = imp_sth->cda->rpc - rows_returned; + imp_sth->next_entry = 0; } av = DBIS->get_fbav(imp_sth); num_fields = AvFILL(av)+1; if (debug >= 3) - fprintf(DBILOGFP, " dbd_st_fetch %d fields\n", num_fields); + fprintf(DBILOGFP, " dbd_st_fetch %d fields (cache: %d/%d/%d)\n", + num_fields, imp_sth->next_entry, imp_sth->in_cache, + imp_sth->cache_size); for(i=0; i < num_fields; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i]; - int rc = fbh->rcode; + int cache_entry = imp_sth->next_entry; + fb_ary_t *fb_ary = fbh->fb_ary; + int rc = fb_ary->arcode[cache_entry]; SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */ if (rc == 1406 && dbtype_is_long(fbh->dbtype)) { @@ -855,8 +966,8 @@ dbd_st_fetch(sth) } if (rc == 0) { /* the normal case */ - SvCUR(fbh->sv) = fbh->rlen; - sv_setsv(sv, fbh->sv); /* XXX can be optimised later */ + sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], + fb_ary->arlen[cache_entry]); } else if (rc == 1405) { /* field is null - return undef */ (void)SvOK_off(sv); @@ -874,6 +985,11 @@ dbd_st_fetch(sth) i, rc, SvPV(sv,na)); } + + /* update cache counters */ + --imp_sth->in_cache; + ++imp_sth->next_entry; + return av; } @@ -957,6 +1073,7 @@ dbd_st_destroy(sth) { D_imp_sth(sth); D_imp_dbh_from_sth; + int fields; int i; /* Check if an explicit disconnect() or global destruction has */ /* disconnected us from the database before attempting to close. */ @@ -971,9 +1088,12 @@ dbd_st_destroy(sth) /* Free off contents of imp_sth */ - for(i=0; i < DBIc_NUM_FIELDS(imp_sth); ++i) { + fields = DBIc_NUM_FIELDS(imp_sth); + imp_sth->in_cache = 0; + imp_sth->eod_errno = 1403; + for(i=0; i < fields; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i]; - sv_free(fbh->sv); + fb_ary_free(fbh->fb_ary); } Safefree(imp_sth->fbh); Safefree(imp_sth->fbh_cbuf); diff --git a/dbdimp.h b/dbdimp.h index 3c9968ae..b55e74c6 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.12 1996/10/15 02:19:14 timbo Exp $ + $Id: dbdimp.h,v 1.16 1996/10/29 18:17:23 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -8,14 +8,17 @@ */ -/* these are (almost) random values ! */ -#define MAX_COLS 1025 - +/* #define MAX_COLS 1025 */ #ifndef HDA_SIZE #define HDA_SIZE 512 #endif +#ifndef FT_SELECT +#define FT_SELECT 4 /* from rdbms/demo/ocidem.h */ +#endif + + typedef struct imp_fbh_st imp_fbh_t; struct imp_drh_st { @@ -47,15 +50,31 @@ struct imp_sth_st { int done_desc; /* have we described this sth yet ? */ imp_fbh_t *fbh; /* array of imp_fbh_t structs */ char *fbh_cbuf; /* memory for all field names */ + int t_dbsize; /* raw data width of a row */ sb4 long_buflen; /* length for long/longraw (if >0) */ bool long_trunc_ok; /* is truncating a long an error */ - /* (In/)Out Parameter Details */ + /* Select Row Cache Details */ + int cache_size; + int in_cache; + int next_entry; + int eod_errno; + + /* (In/)Out Parameter Details */ bool has_inout_params; }; #define IMP_STH_EXECUTING 0x0001 +typedef struct fb_ary_st fb_ary_t; /* field buffer array */ +struct fb_ary_st { /* field buffer array EXPERIMENTAL */ + ub2 bufl; /* length of data buffer */ + sb2 *aindp; /* null/trunc indicator variable */ + ub1 *abuf; /* data buffer (points to sv data) */ + ub2 *arlen; /* length of returned data */ + ub2 *arcode; /* field level error status */ +}; + struct imp_fbh_st { /* field buffer EXPERIMENTAL */ imp_sth_t *imp_sth; /* 'parent' statement */ @@ -70,37 +89,31 @@ struct imp_fbh_st { /* field buffer EXPERIMENTAL */ sb2 nullok; /* Our storage space for the field data as it's fetched */ - sb2 indp; /* null/trunc indicator variable */ sword ftype; /* external datatype we wish to get */ - ub1 *buf; /* data buffer (points to sv data) */ - ub2 bufl; /* length of data buffer */ - ub2 rlen; /* length of returned data */ - ub2 rcode; /* field level error status */ - - SV *sv; + fb_ary_t *fb_ary; /* field buffer array */ }; typedef struct phs_st phs_t; /* scalar placeholder */ -struct phs_st { /* scalar placeholder EXPERIMENTAL */ - SV *sv; /* the scalar holding the value */ +struct phs_st { /* scalar placeholder EXPERIMENTAL */ sword ftype; /* external OCI field type */ - sb2 indp; /* null indicator */ - /* fields for inout params */ - bool is_inout; + SV *sv; /* the scalar holding the value */ + + sb2 indp; /* null indicator */ char *progv; - ub2 alen; ub2 arcode; - int alen_incnull; /* 0 or 1 if alen should include null */ + ub2 alen; + bool is_inout; + int alen_incnull; /* 0 or 1 if alen should include null */ char name[1]; /* struct is malloc'd bigger as needed */ }; void ora_error _((SV *h, Lda_Def *lda, int rc, char *what)); -void fbh_dump _((imp_fbh_t *fbh, int i)); +void fbh_dump _((imp_fbh_t *fbh, int i, int cacheidx)); void dbd_init _((dbistate_t *dbistate)); void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); diff --git a/test.pl b/test.pl index adff977e..73d989ab 100755 --- a/test.pl +++ b/test.pl @@ -1,6 +1,6 @@ #!/usr/local/bin/perl -w -# $Id: test.pl,v 1.25 1996/10/15 02:19:14 timbo Exp $ +# $Id: test.pl,v 1.28 1996/10/29 18:17:23 timbo Exp $ # # Copyright (c) 1995, Tim Bunce # @@ -10,7 +10,7 @@ require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.25 $}."\n"; +print q{Oraperl test application $Revision: 1.28 $}."\n"; $SIG{__WARN__} = sub { ($_[0] =~ /^Bad free/) ? warn "See README about Bad free() warnings!\n": warn @_; @@ -18,10 +18,11 @@ $opt_d = 0; # debug $opt_l = 0; # log -$opt_c = 5; # count for loops +$opt_n = 5; # num of loops $opt_m = 0; # count for mem leek test +$opt_c = 1; # do cache test $opt_p = 1; # test pl/sql code -&Getopts('m:d:c:lp ') || die "Invalid options\n"; +&Getopts('m:d:n:clp ') || die "Invalid options\n"; $ENV{PERL_DBI_DEBUG} = 2 if $opt_d; $ENV{ORACLE_HOME} = '/usr/oracle' unless $ENV{ORACLE_HOME}; @@ -74,7 +75,7 @@ print "\nTesting repetitive connect/open/close/disconnect:\n"; print "Expect sequence of digits, no other messages:\n"; #DBI->internal->{DebugDispatch} = 2; -foreach(1..$opt_c) { print "$_ "; &test2(); } +foreach(1..$opt_n) { print "$_ "; &test2(); } print "\n"; print "\nTest interaction of explicit close/logoff and implicit DESTROYs\n"; @@ -87,6 +88,8 @@ &test3($opt_m) if $opt_m; +&test_cache() if $opt_c; + &test_plsql() if $opt_p; $dur = time - $start; @@ -107,7 +110,7 @@ sub test1 { # Test ora_do with harmless non-select statement &ora_do($lda, "set transaction read only ") - || warn "ora_do: $ora_errno: $ora_errstr\n"; + || warn "ora_do: $ora_errno: $ora_errstr"; # DBI::dump_results($lda->tables()); @@ -202,29 +205,62 @@ sub test3 { } -sub test_plsql { +sub test_cache { + local($cache) = 5; + print "\nTesting row cache ($cache).\n"; + local($l) = &ora_login($dbname, $dbuser, '') + || die "ora_login: $ora_errno: $ora_errstr\n"; + local($csr, $rows, $max); + local($start) = time; + foreach $max (1, 0, $cache-1, $cache, $cache+1) { + $csr = &ora_open($l, q{ + select object_name from all_objects where rownum <= :1 + }, $cache); + &ora_bind($csr, $max) || die $ora_errstr; + $rows = count_fetch($csr); + die "test_cache $rows/$max" if $rows != $max; + &ora_bind($csr, $max+1) || die $ora_errstr; + $rows = count_fetch($csr); + die "test_cache $rows/$max+1" if $rows != $max+1; + } + # this test will only show timing improvements when + # run over a modem link. It's primarily designed to + # test boundary cases in the cache code. + print "Test completed in ".(time-$start)." seconds.\n"; +} +sub count_fetch { + local($csr) = @_; + local($rows) = 0; + while((@row) = &ora_fetch($csr)) { + ++$rows; + } + die "count_fetch $ora_errstr" if $ora_errno; + return $rows; +} - print "\nTesting PL/SQL interaction.\n"; +sub test_plsql { + print "\nTesting PL/SQL interaction.\n"; local($l) = &ora_login($dbname, $dbuser, '') - || die "ora_login: $ora_errno: $ora_errstr\n"; + || die "ora_login: $ora_errno: $ora_errstr\n"; my $c; + # $l->debug(2); $c = &ora_open($l, q{ - begin RAISE invalid_number; end; + begin RAISE invalid_number; end; }); # Expect ORA-01722: invalid number die "ora_open: $ora_errstr" unless $ora_errno == 1722; $c = &ora_open($l, q{ - DECLARE FOO EXCEPTION; - begin raise foo; end; + DECLARE FOO EXCEPTION; + begin raise foo; end; }); # Expect ORA-06510: PL/SQL: unhandled user-defined exception die "ora_open: $ora_errstr" unless $ora_errno == 6510; $c = &ora_open($l, q{ - begin raise_application_error(-20101,'app error'); end; + begin raise_application_error(-20101,'app error'); end; }); # Expect our exception number and error text die "ora_open: $ora_errno $ora_errstr" From 563f98a63cfa8a50ab47a477917f30205da80633 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Tue, 14 Jan 1997 15:55:00 -0500 Subject: [PATCH 022/637] import DBD-Oracle 0.44 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.44 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.44.tar.gz --- Changes | 16 +++++- Makefile.PL | 18 +++++- Oracle.pm | 6 +- Oracle.xs | 14 +++-- README | 28 +++++---- README.clients | 2 +- README.longs | 11 ++-- dbdimp.c | 152 ++++++++++++++++++++++++++++++++----------------- dbdimp.h | 8 ++- test.pl | 22 ++++++- 10 files changed, 194 insertions(+), 83 deletions(-) diff --git a/Changes b/Changes index effa29c9..e449f3ea 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,17 @@ +Changes in DBD::Oracle 0.44 (Oraperl 1.30), 14th Jan 1997 + + Fixed leak in read_blob (thanks to Jurgen Botz for the patch). + Improved automatic cache sizing (so better default caching). + Negative cache size specifies desired cache/transfer size in bytes. + Added $rowid = $csr->{ora_rowid} attribute (untested, please test). + (Use via $csr->bind_param(1, $rowid, { ora_type => 11 });) + Queries returning LONG's are no longer cached (so there's no + need to set the cache to 1 explicitly to get read_blob to work). + Added a test using string type with bind_param_inout in test.pl. + Worked around the rather sad VMS linker case insensitivity. + Worked around VMS linker length warning on XS...disconnect_all. + Makefile.PL deletes non-existant files from $(COMPOBJS) + (thanks to aburlison@cix.compulink.co.uk for the original patch) Changes in DBD::Oracle 0.43 (Oraperl 1.30), 29nd Oct 1996 @@ -8,7 +22,7 @@ Changes in DBD::Oracle 0.43 (Oraperl 1.30), 29nd Oct 1996 NUM_OF_FIELDS always available. Describe does nothing for non-select operations. NUM_OF_FIELDS > 0 is now used to select between oexec() and oexfet() in execute(). - Added a more internal debugging. Improved test.pl. + Added more internal debugging. Improved test.pl. Changes in DBD::Oracle 0.42 (Oraperl 1.30), 28nd Oct 1996 diff --git a/Makefile.PL b/Makefile.PL index fd5771d7..a422a4b4 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,5 @@ #!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.51 1996/10/15 02:19:14 timbo Exp $ +# $Id: Makefile.PL,v 1.52 1997/01/14 21:48:19 timbo Exp $ BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -258,11 +258,24 @@ sub fetch_oci_macros { my %edit; @edit{@edit} = ('$_ = ""') x @edit; $edit{COMPOBJS} = q{ + # Firstly a Solaris specific edit: + if ($Config{osname} eq 'solaris') { # and $Config{gccversion}? # Change the COMPOBJS line. (Some files use LIBHOME not COMPOBJ) # old: $(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/__fstd.o # new: $(COMPOBJ)/__fstd.o s:\$\S+?/crt[1in]\.o\b::g; - } if $Config{osname} eq 'solaris'; # and $Config{gccversion}; + } + + # Delete any object files in COMPOBJS that don't actually exist + my $of; + foreach $of (split(/=|\s+/)) { + next if !$of or $of eq "COMPOBJS"; + my $obj = expand_mkvars($of,0,0,0); + next if -e $obj; + print "Deleting $of from COMPOBJS because $obj doesn't exist.\n"; + s:\Q$of::; + } + }; my $mkver = 0; my $linkwith = ''; @@ -287,6 +300,7 @@ sub fetch_oci_macros { } # We always store values into %MK before checking %edit + # %edit can edit this in addition to $_ if needed. $MK{$1} = $2 if m/^\s*(\w+)\s*=\s*([\s\S]*)/; next if m/^\s*\.SUFFIXES/; diff --git a/Oracle.pm b/Oracle.pm index 2ff11974..050260b9 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.41 1996/10/29 13:20:39 timbo Exp $ +# $Id: Oracle.pm,v 1.42 1997/01/14 21:51:50 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -16,8 +16,8 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.43'; - my $Revision = substr(q$Revision: 1.41 $, 10); + $VERSION = '0.44'; + my $Revision = substr(q$Revision: 1.42 $, 10); require_version DBI 0.69; diff --git a/Oracle.xs b/Oracle.xs index 8b977da5..e7544dac 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -1,5 +1,5 @@ /* - $Id: Oracle.xs,v 1.42 1996/10/15 02:19:14 timbo Exp $ + $Id: Oracle.xs,v 1.43 1997/01/14 21:48:19 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -43,9 +43,12 @@ errstr(h) MODULE = DBD::Oracle PACKAGE = DBD::Oracle::dr +# disconnect_all renamed and ALIAS'd to avoid length clash on VMS :-( void -disconnect_all(drh) +discon_all_(drh) SV * drh + ALIAS: + disconnect_all = 1 CODE: if (!dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { D_imp_drh(drh); @@ -272,7 +275,7 @@ blob_read(sth, field, offset, len, destrv=Nullsv, destoffset=0) long destoffset CODE: if (!destrv) - destrv = sv_2mortal(newRV(newSV(0))); + destrv = sv_2mortal(newRV(sv_2mortal(newSV(0)))); if (dbd_st_blob_read(sth, field, offset, len, destrv, destoffset)) ST(0) = SvRV(destrv); else ST(0) = &sv_undef; @@ -290,10 +293,13 @@ STORE(sth, keysv, valuesv) ST(0) = &sv_no; +# FETCH renamed and ALIAS'd to avoid case clash on VMS :-( void -FETCH(sth, keysv) +FETCH_attrib_(sth, keysv) SV * sth SV * keysv + ALIAS: + FETCH = 1 CODE: SV *valuesv = dbd_st_FETCH(sth, keysv); if (!valuesv) diff --git a/README b/README index 35af93dd..3039e698 100644 --- a/README +++ b/README @@ -59,7 +59,6 @@ ORACLE_USER environment variable so you should set that to the correct value before starting the test. Please read README.login. make test - make test TEST_VERBOSE=1 (if any of the t/* tests fail) make install (if the tests look okay) @@ -80,6 +79,14 @@ If you can't get it to build on a minimally configured client system then read README.client, it might help but basically I can't help much. Others on the dbi-users mailing list probably can. +If you have linking problems (errors related to libraries or functions) +then you could try foring a 'static' build using: + + make clean + perl Makefile.PL LINKTYPE=static + make + make perl (you'll need to use and install _this_ new perl binary) + Please don't post problems to comp.lang.perl.misc or perl5-porters. This software is supported via the dbi-users mailing list. For more information and to keep informed about progress you can join the a @@ -97,7 +104,7 @@ dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. But note... perl Makefile.PL (do a make realclean first) make make test - make test TEST_VERBOSE=1 (if any tests fail) + make test TEST_VERBOSE=1 (only if any of the t/* tests fail) 2. Full details of which version of Oracle and Perl you're using. @@ -108,13 +115,9 @@ dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. But note... "perl Makefile.PL -s XXX" where XXX is the name of one of the symbols. Please don't send the entire output of this command, just any obviously 'interesting' parts (if there are any). + See also the LINKTYPE=static notes above. -5. If you get a core dump when using Oraperl try adding this *before* - your 'use Oraperl' line: BEGIN { $Oraperl::safe = 1 } - unless your version of Oraperl.pm already has $safe=1 in it - (it does by default now so you can probably ignore this step). - -6. If you still get a core dump rebuild DBD::Oracle with debugging +5. If you get a core dump, rebuild DBD::Oracle with debugging enabled by executing: perl Makefile.PL -g (note the -g option) then rerun the code to get a new core dump file, finally use a debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. @@ -123,7 +126,7 @@ dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. But note... you don't have a good debugger on your system. If desparate try: make perl; ./perl script; echo '$c' | adb ./perl core -7. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun +6. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun make test after setting the environment variable PERL_DL_DEBUG to 2. It is important to check that you are using the latest version before @@ -309,7 +312,7 @@ the core file and then send it to me along with the other information requested in the 'If you have problems' section. ------------------------------------------------------------------------------- -8-bit text is returned as '?' characters. +8-bit text is returned as '?' characters or can't be inserted. Make sure the following environment vaiables are set: NLS_LANG, ORA_NLS, ORA_NLS32 @@ -326,6 +329,11 @@ Otherwise you might get unusable backups with ? replacing all your beloved characters. We were lucky once when we noticed that our exports were damaged before disaster struck. +Remember that the database has to be created with an 8-bit character set. + +Also note that the NLS files $ORACLE_HOME/ocommon/nls/admin/data +changed extension (from .d to .nlb) between 7.2.3 and 7.3.2. + ------------------------------------------------------------------------------- AIX - warnings like these when building perl are not usually a problem: diff --git a/README.clients b/README.clients index cbadd3e1..d6827e5d 100644 --- a/README.clients +++ b/README.clients @@ -2,7 +2,7 @@ This file contains some random notes relating to minimal Oracle configurations for building and/or using DBD::Oracle / Oraperl. ------------------------------------------------------------------------------- -With recent versions of Oracle (specifically around 7.3) you may be +With recent versions of Oracle (specifically >= 7.3) you may be able to build DBD::Oracle without Pro*C installed by using the Oracle supplied oracle.mk file: diff --git a/README.longs b/README.longs index e56e0c1c..10f70568 100644 --- a/README.longs +++ b/README.longs @@ -8,15 +8,14 @@ Example for reading LONG fields via blob_read: ora_bind($csr, $id) or die $ora_errstr; # ora_fetch() needs to be called in an array context my (@data) = ora_fetch($csr); - my ($frag, $blob, $length, $ll, $offset); - $blob = ''; - $length = 4096; # use benchmarks to get best value for you - $offset = 0; + my $blob = ''; + my $lump = 4096; # use benchmarks to get best value for you + my $offset = 0; while (1) { - $frag = $csr->blob_read(0, $offset, $length); + my $frag = $csr->blob_read(0, $offset, $lump); last unless defined $frag; - $ll = length $frag; + my $ll = length $frag; last unless $ll; $blob .= $frag; $offset += $ll; diff --git a/dbdimp.c b/dbdimp.c index 062d04d1..b5f1759e 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.28 1996/10/29 18:17:23 timbo Exp $ + $Id: dbdimp.c,v 1.29 1997/01/14 21:48:19 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -340,7 +340,8 @@ dbd_st_prepare(sth, statement, attribs) /* statements will be executed at once. This is a major pain! */ imp_sth->cda->peo = 0; if (oparse(imp_sth->cda, (text*)imp_sth->statement, (sb4)-1, - (sword)oparse_defer, (ub4)oparse_lng)) { + (sword)oparse_defer, (ub4)oparse_lng) + ) { SV *msgsv, *sqlsv; char msg[99]; sqlsv = sv_2mortal(newSVpv(imp_sth->statement,0)); @@ -355,6 +356,11 @@ dbd_st_prepare(sth, statement, attribs) return 0; } + /* detect warning for pl/sql create errors */ + if (imp_sth->cda->wrn & 32) { + ; /* XXX perl_call_method to get error text ? */ + } + /* long_buflen: length for long/longraw (if >0) */ /* long_trunc_ok: is truncating a long an error XXX not implemented */ @@ -370,10 +376,7 @@ dbd_st_prepare(sth, statement, attribs) fprintf(DBILOGFP, " dbd_st_prepare'd sql f%d (lb %ld, lt %d)\n", imp_sth->cda->ft, (long)imp_sth->long_buflen, imp_sth->long_trunc_ok); - /* Describe and allocate storage for results. This could */ - /* and possibly should be deferred until execution or some */ - /* output related information is fetched. */ -/* was defered prior to 0.43 */ + /* Describe and allocate storage for results. */ if (!dbd_describe(sth, imp_sth)) { return 0; } @@ -470,8 +473,13 @@ dbd_describe(h, imp_sth) int t_cbufl=0; I32 num_fields; int has_longs = 0; + int est_width = 0; /* estimated avg row width (for cache) */ int i = 0; + I32 long_buflen = imp_sth->long_buflen; + if (long_buflen < 0) + long_buflen = 80; /* typical oracle app default */ + if (imp_sth->done_desc) return 1; /* success, already done it */ imp_sth->done_desc = 1; @@ -493,6 +501,11 @@ dbd_describe(h, imp_sth) New(1, f_cbufl, f_cbufl_max, sb4); } + /* number of rows to cache */ + if (SvOK(ora_cache_o)) imp_sth->cache_size = SvIV(ora_cache_o); + else if (SvOK(ora_cache)) imp_sth->cache_size = SvIV(ora_cache); + else imp_sth->cache_size = 0; /* auto size */ + /* Get number of fields and space needed for field names */ while(++i) { /* break out within loop */ sb1 cbuf[257]; /* generous max column name length */ @@ -508,10 +521,30 @@ dbd_describe(h, imp_sth) if (imp_sth->cda->rc || dbtype == 0) break; t_cbufl += f_cbufl[i]; - if (dbsize) - imp_sth->t_dbsize += dbsize; - else if (dbtype_is_long(dbtype)) - ++has_longs; /* hint to auto cache sizing code */ + + /* now we calculate the approx average on-the-wire width of */ + /* each field (and thus row) to determine a 'good' cache size. */ + if (imp_sth->cache_size > 0) + continue; /* no need, user specified a size */ + if (dbsize==0) { /* is a LONG type or 'select NULL' */ + if (dbtype_is_long(dbtype)) { + est_width += long_buflen; + ++has_longs; /* hint to auto cache sizing code */ + } + } + else /* deal with dbtypes with overblown dbsizes */ + switch(dbtype) { + case 1: /* VARCHAR2 - result of to_char() has dbsize==75 */ + /* for all but small strings we take off 25% */ + est_width += (dbsize < 32) ? dbsize : dbsize-(dbsize>>2); + break; + case 2: /* NUMBER - e.g., from a sum() or max(), dbsize==22 */ + /* Most numbers are _much_ smaller than 22 bytes */ + est_width += 4; /* > approx +/- 1_000_000 ? */ + break; + default: est_width += dbsize; + break; + } } if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { D_imp_dbh_from_sth; @@ -523,26 +556,28 @@ dbd_describe(h, imp_sth) DBIc_NUM_FIELDS(imp_sth) = num_fields; /* --- Setup the row cache for this query --- */ - if (SvOK(ora_cache_o)) imp_sth->cache_size = SvIV(ora_cache_o); - else if (SvOK(ora_cache)) imp_sth->cache_size = SvIV(ora_cache); - else imp_sth->cache_size = 0; /* auto size */ - /* deal with default (auto-size) and out of range cases */ - if (imp_sth->cache_size < 1) { /* 0 == try to pick 'optimal' */ - /* Guess a maximum on-the-wire row width (but note t_dbsize */ - /* doesn't include longs yet so this could be suboptimal) */ - int width = 8 + imp_sth->t_dbsize + num_fields*5; + + if (has_longs) /* override/disable caching */ + imp_sth->cache_size = 1; /* else read_blob can't work */ + + else if (imp_sth->cache_size < 1) { /* automaticaly size the cache */ + /* 0 == try to pick 'optimal' cache for this query. */ + /* <0 == base cache on transfer size of -n bytes (default 2048) */ + /* Use guessed average on-the-wire row width calculated above */ + /* + overhead of 5 bytes per field plus 8 bytes per row. */ + int width = est_width + num_fields*5 + 8; /* How many rows fit in 2Kb? (2Kb is a reasonable compromise) */ - imp_sth->cache_size = 2048 / width; - if (imp_sth->cache_size < 5) /* cache at least 5 */ + int hunk = 2048; /* default cache size */ + if (imp_sth->cache_size < 0) /* user is specifying txfr size */ + hunk = -imp_sth->cache_size;/* is also approx cache size */ + imp_sth->cache_size = hunk / width; + if (imp_sth->cache_size < 5) /* always cache at least 5 */ imp_sth->cache_size = 5; - else /* if query includes longs, limit auto-size to 10 rows */ - if (has_longs && imp_sth->cache_size > 10) - imp_sth->cache_size = 10; } if (imp_sth->cache_size > 32767) /* keep within Oracle's limits */ imp_sth->cache_size = 32767; /* Initialise cache counters */ - imp_sth->in_cache = 0; + imp_sth->in_cache = 0; imp_sth->eod_errno = 0; @@ -572,19 +607,19 @@ dbd_describe(h, imp_sth) /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW? */ /* If so we need to implement oraperl truncation hacks. */ /* This may change in a future release. */ + /* Note that dbtype_is_long() returns alternale dbtype to use */ if ( (dbtype = dbtype_is_long(fbh->dbtype)) ) { - sb4 buflen = imp_sth->long_buflen; - if (buflen < 0) - buflen = 80; /* typical oracle app default */ - fbh->dbsize = buflen; - fbh->dsize = buflen; + fbh->dbsize = long_buflen; + fbh->dsize = long_buflen; fbh->ftype = dbtype; /* get long in non-var form */ - imp_sth->t_dbsize += buflen; + imp_sth->t_dbsize += long_buflen; + } else { /* for the time being we fetch everything (except longs) */ /* as strings, that'll change (IV, NV and binary data etc) */ fbh->ftype = 5; /* oraperl used 5 'STRING' */ /* dbsize can be zero for 'select NULL ...' */ + imp_sth->t_dbsize += fbh->dbsize; } fbh->fb_ary = fb_ary = fb_ary_alloc( @@ -605,8 +640,8 @@ dbd_describe(h, imp_sth) if (dbis->debug >= 2) fprintf(DBILOGFP, - " dbd_describe'd %d columns (~%d data bytes, %d cache rows)\n", - (int)num_fields, imp_sth->t_dbsize, imp_sth->cache_size); + " dbd_describe'd %d columns (~%d data bytes, %d cache rows @%db)\n", + (int)num_fields, imp_sth->t_dbsize, imp_sth->cache_size, est_width); if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { D_imp_dbh_from_sth; @@ -620,26 +655,26 @@ dbd_describe(h, imp_sth) static int -_dbd_rebind_ph(sth, imp_sth, phs, maxlen) +_dbd_rebind_ph(sth, imp_sth, phs) SV *sth; imp_sth_t *imp_sth; phs_t *phs; - int maxlen; { - maxlen = (maxlen < phs->alen) ? phs->alen : maxlen; - if (dbis->debug >= 2) - fprintf(DBILOGFP, "bind %s <== '%.200s' (size %d/%d, ora_type %d)\n", - phs->name, (char*)phs->progv, phs->alen,maxlen, phs->ftype); + fprintf(DBILOGFP, "bind %s <== '%.300s' (size %d/%d, ora_type %d)\n", + phs->name, (char*)phs->progv, phs->alen,phs->maxlen, phs->ftype); if (phs->alen_incnull) ++phs->alen; /* Since we don't support LONG VAR types we must check */ /* for lengths too big to pass to obndrv as an sword. */ - if (maxlen > SWORDMAXVAL) /* generally 64K */ + if (phs->maxlen > SWORDMAXVAL) /* generally 64K */ croak("Can't bind %s, value is too long (%d bytes, max %d)", - phs->name, maxlen, SWORDMAXVAL); + phs->name, phs->maxlen, SWORDMAXVAL); + + if (phs->alen > phs->maxlen) + croak("panic: _dbd_rebind_ph alen %d > maxlen %d", phs->alen,phs->maxlen); if (0) { /* old code */ if (obndrv(imp_sth->cda, (text*)phs->name, -1, @@ -653,7 +688,7 @@ _dbd_rebind_ph(sth, imp_sth, phs, maxlen) } else { if (obndra(imp_sth->cda, (text *)phs->name, -1, - (ub1*)phs->progv, maxlen, (sword)phs->ftype, -1, + (ub1*)phs->progv, phs->maxlen, (sword)phs->ftype, -1, &phs->indp, &phs->alen, &phs->arcode, 0, (ub4 *)0, (text *)0, -1, -1)) { D_imp_dbh_from_sth; @@ -689,6 +724,9 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) name = SvPV(ph_namesv, name_len); } + if (SvTYPE(newvalue) > SVt_PVMG) /* hook for later array logic */ + croak("Can't bind non-scalar value (currently)"); + if (dbis->debug >= 2) fprintf(DBILOGFP, "bind %s <== '%.200s' (attribs: %s)\n", name, SvPV(newvalue,na), attribs ? SvPV(attribs,na) : "" ); @@ -706,8 +744,6 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) ++imp_sth->has_inout_params; phs->is_inout = 1; phs->sv = SvREFCNT_inc(newvalue); - if (SvOOK(phs->sv)) - sv_backoff(phs->sv); /* pre-upgrade to cut down risks of SvPVX realloc/move */ (void)SvUPGRADE(phs->sv, SVt_PVNV); /* ensure we have a string to point oracle at */ @@ -741,8 +777,13 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) phs->alen_incnull = (phs->ftype==SQLT_STR || phs->ftype==SQLT_AVC); } + /* check later rebinds for any changes */ else if (is_inout != phs->is_inout) { - croak("Can't change param %s in/out mode", phs->name); + croak("Can't change param %s in/out mode after first bind", phs->name); + } + else if (maxlen && maxlen != phs->maxlen) { + croak("Can't change param %s maxlen (%d->%d) after first bind", + phs->name, phs->maxlen, (int)maxlen); } @@ -751,25 +792,29 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) /* just copy the value & length over and not rebind. */ if (!SvOK(newvalue)) { /* undef == NULL */ - phs->indp = -1; - phs->progv = ""; - phs->alen = 0; + phs->indp = -1; + phs->progv = ""; + phs->alen = 0; + phs->maxlen = 0; } else { STRLEN value_len; phs->indp = 0; /* XXX need to consider oraperl null vs space issues? */ if (is_inout) { /* XXX */ + /* point Oracle at the real live variable memory */ phs->progv = SvPV(phs->sv, value_len); } else { + /* point Oracle at the real live variable memory */ sv_setsv(phs->sv, newvalue); phs->progv = SvPV(phs->sv, value_len); } phs->alen = value_len + phs->alen_incnull; + phs->maxlen = SvLEN(phs->sv); /* avail buffer space */ } - return _dbd_rebind_ph(sth, imp_sth, phs, maxlen); + return _dbd_rebind_ph(sth, imp_sth, phs); } @@ -806,14 +851,13 @@ dbd_st_execute(sth) /* <0 is error, >=0 is ok (row count) */ phs->alen = phs_len + phs->alen_incnull; } else { - if (SvOOK(phs->sv)) - sv_backoff(phs->sv); phs->alen = SvCUR(phs->sv) + phs->alen_incnull; } /* Some checks for mutated storage since we pointed oracle at it. */ /* XXX Instead of croaking we could rebind (probably will later). */ if (SvTYPE(phs->sv) != SVt_PVNV) - croak("Placeholder %s value mutated type after bind.\n", phs->name); + croak("Placeholder %s value mutated type after bind (now %ld).\n", + phs->name, SvTYPE(phs->sv)); if (SvPVX(phs->sv) != phs->progv) croak("Placeholder %s value mutated location after bind.\n", phs->name); if (debug >= 2) @@ -1182,6 +1226,12 @@ dbd_st_FETCH(sth, keysv) while(--i >= 0) av_store(av, i, newSViv(imp_sth->fbh[i].dbtype)); + } else if (kl==9 && strEQ(key, "ora_rowid")) { + /* return current _binary_ ROWID (oratype 11) uncached */ + /* Use { ora_type => 11 } when binding to a placeholder */ + retsv = newSVpv((char*)&imp_sth->cda->rid, sizeof(imp_sth->cda->rid)); + cacheit = FALSE; + } else if (kl==4 && strEQ(key, "NAME")) { AV *av = newAV(); retsv = newRV(sv_2mortal((SV*)av)); diff --git a/dbdimp.h b/dbdimp.h index b55e74c6..fed0461b 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.16 1996/10/29 18:17:23 timbo Exp $ + $Id: dbdimp.h,v 1.17 1997/01/14 21:48:19 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -104,7 +104,8 @@ struct phs_st { /* scalar placeholder EXPERIMENTAL */ sb2 indp; /* null indicator */ char *progv; ub2 arcode; - ub2 alen; + ub2 alen; /* effective length ( <= maxlen ) */ + ub2 maxlen; /* max possible len (=allocated buffer) */ bool is_inout; int alen_incnull; /* 0 or 1 if alen should include null */ @@ -120,5 +121,8 @@ void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); int dbd_describe _((SV *h, imp_sth_t *imp_sth)); int dbd_st_blob_read _((SV *sth, int field, long offset, long len, SV *destrv, long destoffset)); +SV *dbd_st_FETCH _((SV *sth, SV *keysv)); +SV *dbd_db_FETCH _((SV *dbh, SV *keysv)); + /* end */ diff --git a/test.pl b/test.pl index 73d989ab..d969d1b9 100755 --- a/test.pl +++ b/test.pl @@ -1,6 +1,8 @@ #!/usr/local/bin/perl -w -# $Id: test.pl,v 1.28 1996/10/29 18:17:23 timbo Exp $ +die "Use 'make test' to run test.pl\n" unless "@INC" =~ /\bblib\b/; + +# $Id: test.pl,v 1.29 1997/01/14 21:48:19 timbo Exp $ # # Copyright (c) 1995, Tim Bunce # @@ -10,7 +12,7 @@ require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.28 $}."\n"; +print q{Oraperl test application $Revision: 1.29 $}."\n"; $SIG{__WARN__} = sub { ($_[0] =~ /^Bad free/) ? warn "See README about Bad free() warnings!\n": warn @_; @@ -283,7 +285,7 @@ sub test_plsql { die "ora_open: $ora_errstr" unless $ora_errstr =~ m/plus my msg/; # our exception text - print "Testing bind_param_inout. Expect '200', '3800', '75800':\n"; + print "Testing numeric bind_param_inout. Expect '200', '3800', '75800':\n"; #$l->debug(2); #DBI->internal->{DebugDispatch} = 2; $c = &ora_open($l, q{ @@ -298,6 +300,20 @@ sub test_plsql { $param -= 10; } while ($param < 70000); + print "Testing string bind_param_inout. Expect '**foo**':\n"; + #$l->debug(2); + #DBI->internal->{DebugDispatch} = 2; + $c = &ora_open($l, q{ + declare bar varchar2(200); + begin bar := :1; bar := '**'||bar||'**'; :1 := bar; end; + }) || die "ora_open: $ora_errstr"; + $param = "foo"; + $c->bind_param_inout(1, \$param, 100) || die "bind_param_inout $ora_errstr"; + # can be used for force realloc and thus a 'mutated location' error: + # $param = "ffffffffffffffffffffffffffffffffffffffffffffffffoo" x 3; + $c->execute || die "execute $ora_errstr"; + print "param='$param'\n"; + # To do # test NULLs at first bind # NULLS later binds. From f8379daf799ff0a51c726d9c189ca09cbb773ba9 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Sat, 14 Jun 1997 10:47:00 -0500 Subject: [PATCH 023/637] import DBD-Oracle 0.45 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.45 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.45.tar.gz --- Changes | 41 ++++++ MANIFEST | 4 + Makefile.PL | 268 ++++++++++++++++++++--------------- Oracle.h | 8 +- Oracle.pm | 288 ++++++++++++++++++++++++++++++++++++-- Oracle.xs | 49 ++++--- Oraperl.pm | 28 ++-- README | 368 ++++++++----------------------------------------- README.clients | 120 ++++++++++++++++ README.help | 307 +++++++++++++++++++++++++++++++++++++++++ README.login | 83 +---------- README.longs | 23 ++++ README.plsql | 6 + README.win32 | 25 ++++ Todo | 6 + dbdimp.c | 330 +++++++++++++++++++++++++++----------------- dbdimp.h | 26 ++-- t/base.t | 1 + t/plsql.t | 145 +++++++++++++++++++ test.pl | 97 ++----------- 20 files changed, 1449 insertions(+), 774 deletions(-) create mode 100644 README.help create mode 100644 README.plsql create mode 100644 README.win32 create mode 100644 t/plsql.t diff --git a/Changes b/Changes index e449f3ea..2d96c4de 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,44 @@ +Changes in DBD::Oracle 0.45 (Oraperl 1.32), 16th June 1997 + + A $dbh DESTROY without an explicit disconnect does a rollback. + Note that this may 'break' existing 'lazy' code but is completely + essential for robust applications. See comments in Oracle.xs. + + Added Makefile.PL changes from Eric Bartley and others. + The changes should fix build problems for Oracle 7.3.x. + + Requires DBI 0.83. + + Oraperl now uses DBI->connect and thus works with DBI 0.81 to + automatically support Apache without requiring script changes. + + Reworked parameter binding in preparation for future changes. + - mutated placeholder values are now automatically rebound. + - in/out vars that become undef/null after binding now work. + - transparent support for longs should be easier to implement. + + Added Win32 support from Jeff Urlwin. + + Added some documentation to DBD::Oracle for 'perldoc DBD::Oracle'. + + Added $sth->{NULLABLE}->[$field]. + Added private plsql_errstr method: $txt=$dbh->func('plsql_errstr') + to fetch PL/SQL error messages. Thanks to Bob Menteer. + Added $sth->{ora_pad_empty} and ORAPERL_PAD_EMPTY env var + for better compatibility with old oraperl. + Added $sth->{AutoCommit} FETCH. + Added $sth->{ChopBlanks} (but not yet tested). + No longer asks Oracle for text of login failure message since + that can cause oracle's code to hang (sigh). We provide fake text + for the most common errors and a useful default for the rest. + You can set DBD_ORACLE_LOGIN_ERR env var to revert to old behaviour. + + The Copyright terms for DBD::Oracle have changed and now read as follows: + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the Perl README file, + with the exception that it cannot be placed on a CD-ROM or similar media + for commercial distribution without the prior approval of the author. + Changes in DBD::Oracle 0.44 (Oraperl 1.30), 14th Jan 1997 Fixed leak in read_blob (thanks to Jurgen Botz for the patch). diff --git a/MANIFEST b/MANIFEST index 9b189d04..db9898a4 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,7 +1,10 @@ MANIFEST README README.login +README.win32 +README.plsql README.clients +README.help README.longs Changes Todo @@ -14,6 +17,7 @@ dbdimp.h dbdimp.c test.pl t/base.t +t/plsql.t hints/svr4.pl .purify Ignore most of the (many) problems in Oracle's libraries. Very sad. oraperl.ph Old oraperl file included for completeness of emulation diff --git a/Makefile.PL b/Makefile.PL index a422a4b4..5eb58fbe 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,4 @@ -#!/usr/local/bin/perl -sw -# $Id: Makefile.PL,v 1.52 1997/01/14 21:48:19 timbo Exp $ +# $Id: Makefile.PL,v 1.53 1997/06/14 17:42:12 timbo Exp $ BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -15,7 +14,11 @@ require FileHandle unless defined(&FileHandle::new); # For those not using Dynamic loading this means building a # new static perl in the DBI directory by saying 'make perl' # and then using _that_ perl to make this one. -use DBI 0.71; +use DBI 0.82; + +my $osname = $^O; +my $osvers = $Config{osvers}; +$osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 my %opts = ( NAME => 'DBD::Oracle', @@ -23,17 +26,20 @@ my %opts = ( dist => { DIST_DEFAULT=> 'clean distcheck disttest ci tardist', PREOP => '$(MAKE) -f Makefile.old distdir' }, ); -my(@MK, %MK, $MK); # parsed macros from Oracle proc.mk file +my(@MK, %MK, $MK); # parsed macros from Oracle's makefiles # Options (rarely needed) $::opt_m = ''; # path to proc.mk or oracle.mk file to read +$::opt_p = ''; # prefer oracle.mk over proc $::opt_g = ''; # enable debugging (s/-O/-g/g) $::opt_s = ''; # Find a symbol, Don't build a Makefile -$::opt_v = 0; # be verbose +$::opt_v = 0; # be more verbose +$::opt_old = 0; # old style .mk file parsing -GetOptions('v!', 'g!', 'm=s', 's=s') or die "Invalid arguments"; +GetOptions(qw(v! g! old! p! m=s s=s)) or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string +$Verbose = 1 if $::opt_v; # --- Introduction @@ -45,99 +51,122 @@ print "\n Configuring DBD::Oracle ...\n # --- Where is Oracle installed... -unless ($ENV{ORACLE_HOME}){ - warn "\$ORACLE_HOME not defined. Searching for Oracle...\n"; - foreach(qw(/usr/oracle /home/oracle /opt/oracle /home/oracle/home)){ - $ENV{ORACLE_HOME}=$_,last - if -d "$_/rdbms" or -d "$_/precomp" or -d "$_/ocommon"; - } - die "Unable to determine ORACLE_HOME" unless $ENV{ORACLE_HOME}; -} +die "ORACLE_HOME environment variable must be set.\n" + unless $ENV{ORACLE_HOME}; my $OH = $ENV{ORACLE_HOME}; +die "ORACLE_HOME environment variable ($OH) not value.\n" + unless -d $OH; +my $OCIDIR = "OCI73"; # For MSWin32. XXX what about 7.4 etc? print "Using Oracle in $OH\n"; -# --- What Oracle is installed... - -warn "\nWARNING: Oracle OCI (Pro*C) does not appear to be installed.\n" - ."You should install Pro*C before you can build DBD::Oracle properly.\n\n" - unless (-f "$OH/lib/libocic.a" - and (-f "$OH/rdbms/demo/oratypes.h" or -f "$OH/rdbms/public/oratypes.h")) - or (-f "$OH/precomp/demo/proc/proc.mk"); # 7.3.x -# XXX Todo: validate user has all the right Oracle stuff installed. +my @mkplaces = qw( + rdbms/demo/oracle.mk + proc/lib/proc.mk + precomp/demo/proc/proc.mk + proc16/lib/proc16.mk +); +# if -p then remove oracle.mk from search list, prefer Pro*C +@mkplaces = grep { !m/oracle\.mk\b/ } @mkplaces if $::opt_p; +unshift @mkplaces, $::opt_m if $::opt_m; +my($mkfile, $place); +foreach $place (@mkplaces) { + $place = "$OH/$place" unless $place =~ m:^[./]:; + $mkfile = $place if -f $place; + last if $mkfile; +} +if (!$mkfile and "@mkplaces" !~ m/oracle\.mk/) { + warn "Unable to locate a Pro*C *.mk. Falling back to oracle.mk.\n"; + $mkfile = "$OH/oracle.mk"; + push @mkplaces, $mkfile; # just for error message below +} +die qq{ + Unable to locate an oracle.mk or proc.mk file in your Oracle installation. + (Looked in @mkplaces) -# Using -m to specify oracle.mk might work but is NOT supported. -my $procmk = $::opt_m || "$OH/proc/lib/proc.mk"; -$procmk = "$OH/precomp/demo/proc/proc.mk" unless -f $procmk; # 7.3.x -$procmk = "$OH/proc16/lib/proc16.mk" unless -f $procmk; -die q{ - Unable to locate proc.mk in your Oracle installation. + The oracle.mk file is part of the Oracle RDBMS product. The + proc.mk file is part of the Oracle Pro*C product. You need to + build DBD::Oracle on a system which has one of these installed. - proc.mk is part of the Oracle Pro*C product. You should build - DBD::Oracle on a system which has Oracle Pro*C installed. + If your oracle.mk or proc.mk file is installed somewhere + non-standard you can specify where it is using the -m option: + perl Makefile.PL -m /path/to/your.mk - If proc.mk is installed somewhere non-standard you can use - perl Makefile.PL -m /path/to/proc.mk - to specify where it is. + See README.clients for more information and some alternatives. - See README.clients for more information and some alternatives. +} unless ($osname eq 'MSWin32') || ($mkfile && -f $mkfile); -} unless -f $procmk; +my(@mkfiles, $linkvia, $libhome, $linkwith, $linkwith_s, @linkwith_o, $OCIINCLUDE); -my @mkfiles; -my $linkwith = fetch_oci_macros(); -my $libhome = expand_mkvars($MK{LIBHOME}, 0, 1, 0) || "$OH/lib"; -$linkwith = expand_mkvars($linkwith, 0, 1, 0); -$linkwith =~ s/-Y P,/-YP,/g if $Config{'cc'} =~ /gcc/; -$linkwith =~ s:-R /:-R/:g if $Config{osname} eq 'solaris'; +if ($osname ne 'MSWin32') { + $linkvia = fetch_oci_macros($mkfile); + $libhome = expand_mkvars($MK{LIBHOME}, 0, 1, 0) || "$OH/lib"; + $linkwith = expand_mkvars($linkvia, 0, 1, 0); + $linkwith =~ s/-Y P,/-YP,/g if $Config{'cc'} =~ /gcc/; + $linkwith =~ s:-R /:-R/:g if $osname eq 'solaris'; -# get a cut down $linkwith to pass to MakeMaker liblist -my $linkwith_s = expand_mkvars($linkwith, 1, 1, 0); -# convert "/full/path/libFOO.a" into "-L/full/path -lFOO" -$linkwith_s =~ s!([/\w.]+)/lib(\w+).a!-L$1 -l$2!g; -# extract object files, keep for use later -my @linkwith_o; -push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; -# also extract AIX .exp files since they confuse MakeMaker -push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; + # get a cut down $linkwith to pass to MakeMaker liblist + $linkwith_s = expand_mkvars($linkwith, 1, 1, 0); + # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" + $linkwith_s =~ s!([/\w.]+)/lib(\w+).a!-L$1 -l$2!g; + # extract object files, keep for use later + push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; + # also extract AIX .exp files since they confuse MakeMaker + push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; -if ($::opt_s) { + if ($::opt_s) { warn "Searching for symbol '$::opt_s' in $OH ...\n"; my $dlext = $Config{dlext}; system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; - do echo " searching \$i ..."; nm \$i | grep $::opt_s; - done - }); + do echo " searching \$i ..."; nm \$i | grep $::opt_s; + done + }); warn "Search done.\n"; exit; -} + } -if ($Config{osname} eq 'solaris' and $Config{osvers} >= 2.3 - and $linkwith_s =~ /-lthread/) { + if ($osname eq 'solaris' and $osvers >= 2.3 + and $linkwith_s =~ /-lthread/) { warn "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; warn "Deleting -lthread from link list as a possible workround.\n"; $linkwith_s =~ s/\s*-lthread\b/ /g; -} - -my $OCIINCLUDE = $MK{INCLUDE} || ''; -$opts{LIBS} = [ "-L$libhome $linkwith_s" ]; -# INSTALLARCHLIB included _after_ INSTALLSITEARCH for transition period -$opts{INC} = "$OCIINCLUDE -I$OH/rdbms/demo -I\$(INSTALLSITEARCH)/DBI -I\$(INSTALLARCHLIB)/DBI"; -$opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o \$(COMPOBJS)" }; -$opts{OBJECT} = '$(O_FILES)'; + } + $OCIINCLUDE = $MK{INCLUDE} || ''; + $opts{LIBS} = [ "-L$libhome $linkwith_s" ]; + $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o \$(COMPOBJS)" }; + $opts{OBJECT} = '$(O_FILES)'; +} +else { # MSWin32 + # this assumes MSVC... + $OCIINCLUDE = "-I$OH/$OCIDIR/include"; + $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/MSVC/OCIW32.LIB"]; + $opts{dynamic_lib} = { OTHERLDFLAGS => " $OH/$OCIDIR/LIB/MSVC/OCIW32.LIB" }; + $opts{OBJECT} = '$(O_FILES)'; + $opts{SKIP} = ['processPL']; # XXX caused problems with Nmake... +} +$opts{INC} = "$OCIINCLUDE -I$OH/rdbms/demo -I\$(INSTALLSITEARCH)/auto/DBI"; # --- Handle special cases --- # HP-UX 9 cannot link a non-PIC object file into a shared library. # Since the # .a libs that Oracle supplies contain non-PIC object # files, we sadly have to build static on HP-UX 9 :( -if ($Config{osname} eq 'hpux' and $Config{osvers} < 10) { - print "Warning: forced to build static not dynamic on $Config{osname} $Config{osvers}\n"; - print " See README and Makefile.PL for more information.\n"; +if ($osname eq 'hpux' and $osvers < 10) { $opts{LINKTYPE} = 'static'; + print "Warning: Forced to build static not dynamic on $osname $osvers.\a\n"; + print "** Note: DBD::Oracle will be built *into* a NEW perl binary. You MUST use that new perl.\n"; + print " See README and Makefile.PL for more information.\a\n"; +} +if ($osname eq 'hpux' and $osvers >= 10) { + print "Warning: You may need to build using static linking. See the README file.\n\a"; +} + +if ($osname eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { + print "Warning: You may need to rebuild perl using the xlc_r compiler.\a\n"; + print " You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV\n"; } $opts{DEFINE} = '-Wall -pedantic -Wno-comment -Wtraditional' @@ -151,28 +180,23 @@ warn "WARNING: Your GNU C compiler is very old. Please upgrade.\n" # Set some private WriteMakefile options if this is 'me' :-) if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess $Verbose = 1; - # $opts{INST_LIB} = '$(INSTALLSITELIB)'; - # $opts{INST_ARCHLIB} = '$(INSTALLSITEARCH)'; - $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith' - . ' -Wbad-function-cast -Wcast-qual' if $Config{cc} eq 'gcc'; + $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith' + . ' -Wbad-function-cast -Wcast-qual' if $Config{cc} eq 'gcc'; } -$Verbose = 1 if $::opt_v; # log key platform information to help me help you quickly print "System: perl$] @Config{qw(myuname)}\n"; print "Compiler: @Config{qw(cc optimize ccflags)}\n"; -print "Linker: ". find_bin('ld') ."\n"; +print "Linker: ". (find_bin('ld')||"not found") ."\n"; print "Oracle proc.mk would have used these values but we override them:\n"; -print " CC: $MK{CC}\n" if $MK{CC}; -print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; -print " LDFLAGS: $MK{LDFLAGS}\n" if $MK{LDFLAGS}; -print " LDSTRING: $MK{LDSTRING}\n" if $MK{LDSTRING}; -print "Linking with @linkwith_o $linkwith_s\n"; - -# Assorted hints - these should be move to a hints subdirectory -#print "See README notes about SPARCompiler on Solaris\n" -# if -d "/opt/SUNWspro/bin" and $Config{osname} eq 'solaris'; - +print " CC: $MK{CC}\n" if $MK{CC}; +print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; +print " [".mkvar('CFLAGS',1,0,0). "]\n" if $MK{CFLAGS}; +print " LDFLAGS: $MK{LDFLAGS}\n" if $MK{LDFLAGS}; +print " [".mkvar('LDFLAGS',1,0,0). "]\n" if $MK{LDFLAGS}; +print " LDSTRING: $MK{LDSTRING}\n" if $MK{LDSTRING}; +print " [".mkvar('LDSTRING',1,0,0)."]\n" if $MK{LDSTRING}; +print "\nLinking with @linkwith_o $linkwith_s [from $linkvia]\n"; print "\n"; WriteMakefile(%opts); @@ -247,24 +271,31 @@ ORACLE_HOME = '.$ENV{ORACLE_HOME}.' } +sub del_crtobj { + # E.g. for changing the COMPOBJS line + # old: $(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/__fstd.o + # new: $(COMPOBJ)/__fstd.o + s:\$\S+?/crt[1in]\.o\b::g; +} + + sub fetch_oci_macros { + my $file = shift; - # Read $procmk makefile, extract macro definitions from it + # Read $file makefile, extract macro definitions from it # and store them in $MK, @MK and %MK. # Don't include the following definitions in the generated # makefile (note that %MK stills gets these values). - my @edit = qw(SHELL CC CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS AR ECHO EXE OBJS); + my @edit = qw( + SHELL CC CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS + AR ECHO EXE OBJS PERL + ); my %edit; @edit{@edit} = ('$_ = ""') x @edit; $edit{COMPOBJS} = q{ # Firstly a Solaris specific edit: - if ($Config{osname} eq 'solaris') { # and $Config{gccversion}? - # Change the COMPOBJS line. (Some files use LIBHOME not COMPOBJ) - # old: $(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/__fstd.o - # new: $(COMPOBJ)/__fstd.o - s:\$\S+?/crt[1in]\.o\b::g; - } + del_crtobj() if $osname eq 'solaris'; # Delete any object files in COMPOBJS that don't actually exist my $of; @@ -280,14 +311,22 @@ sub fetch_oci_macros { my $mkver = 0; my $linkwith = ''; my $lastline = ''; - my @lines = read_inc_file($procmk); + my @lines = read_inc_file($file); for(1; $_ = shift(@lines); $lastline = $_){ # Join split lines but retain backwack and newlines: - $_ .= shift(@lines) while(m/\\[\r\n]+$/); + $_ .= shift @lines while(m/\\[\r\n]+$/); chomp; - push(@MK, '') if ($_ eq '' and $lastline ne ''); + push @MK, '' if $_ eq '' and $lastline ne ''; # squeeze multiple blank lines next unless $_; - last if m/^\w+\s*:[^=]/; # gone too far, reached actual targets + + if ($::opt_old) { + last if m/^\w+\s*:[^=]/; # gone too far, reached actual targets + } + else { + next if m!^[-\w/+.\$()]+\s*:+[^=]*!; # skip targets + next if m!^\t!; # skip target build rules + } + next if m/^\s*\.SUFFIXES/; unless($MK{mkver}) { # still need to get version number # This is tough since some versions of proc.mk split the @@ -301,9 +340,12 @@ sub fetch_oci_macros { # We always store values into %MK before checking %edit # %edit can edit this in addition to $_ if needed. - $MK{$1} = $2 if m/^\s*(\w+)\s*=\s*([\s\S]*)/; - - next if m/^\s*\.SUFFIXES/; + if ($::opt_old) { + $MK{$1} = $2 if m/^\s*(\w+)\s*=\s*([\s\S]*)/; + } + else { + $MK{$1}= $' if m/^\s*(\w+)\s*=\s*/; + } if ($1 and exists $edit{$1}) { my $name = $1; @@ -329,22 +371,23 @@ sub fetch_oci_macros { $linkwith = '$(PROLDLIBS)'; } unless ($linkwith){ - die "ERROR parsing $procmk: Unable to determine what to link with.\n" + die "ERROR parsing $file: Unable to determine what to link with.\n" ."Please send me copies of these files (one per mail message):\n@mkfiles\n"; } $MK = join("\n", @MK); return $linkwith; } + sub read_inc_file { my $file = shift; my $fh; unless ($fh = new FileHandle "<$file") { - # Workaround more oracle bungling (Oracle 7.3.2/Solaris x86) - my $alt; ($alt = $file) =~ s/\.dk\.mk$/\.mk/; - $fh = new FileHandle "<$alt"; - die "Unable to read $file: $!" unless $fh; - } + # Workaround more oracle bungling (Oracle 7.3.2/Solaris x86) + my $alt; ($alt = $file) =~ s/\.dk\.mk$/\.mk/; + $fh = new FileHandle "<$alt"; + die "Unable to read $file: $!" unless $fh; + } print "Reading $file.\n"; my @lines; push(@mkfiles, $file); @@ -362,12 +405,13 @@ sub read_inc_file { return @lines; } + sub expand_shellescape { my($orig, $level) = @_; my $cmd = $orig; warn "\n$level * Evaluating \`$orig\`\n" if $::opt_v; # ensure we have no $(...) vars left - strip out undefined ones: - $cmd =~ s/\$\((\w+)\)/mkvar($1, 1, 0, $level+1)/ge; + $cmd =~ s/\$\((\w+)\)/mkvar("$1", 1, 0, $level+1)/ge; warn "\n$level * After reducing to \`$cmd\`\n" if $::opt_v and $cmd ne $orig; my $result = `$cmd`; warn "$level * Returned $result\n\n" if $::opt_v; @@ -377,8 +421,8 @@ sub expand_mkvars { my($string, $strip, $backtick, $level) = @_; local($_) = $string; warn "$level Expanding $_\n" if $::opt_v; - s/\$\((\w+)\)/mkvar($1, $strip, $backtick, $level+1)/ge; - s/`(.*?[^\\])`/expand_shellescape($1, $level+1)/esg if $backtick; + s/\$\((\w+)\)/mkvar("$1", $strip, $backtick, $level+1)/ge; # can recurse + s/`(.*?[^\\])`/expand_shellescape("$1", $level+1)/esg if $backtick; # can recurse s/\s*\\\n\s*/ /g; # merge continuations s/\s+/ /g; # shrink whitespace warn "$level Expanded $string\n to $_\n\n" if $::opt_v and $_ ne $string; @@ -390,7 +434,8 @@ sub mkvar { warn "$level Variable: $var\n" if $::opt_v; return '$(LIBHOME)' if $var eq 'LIBHOME' && !$strip; # gets noisy return $ENV{ORACLE_HOME} if $var eq 'ORACLE_HOME'; - $MK{$var} ? expand_mkvars($MK{$var}, $strip, $backtick, $level+1) : $default; + return $default unless exists $MK{$var}; + return expand_mkvars($MK{$var}, $strip, $backtick, $level+1); # can recurse } sub find_bin{ @@ -406,7 +451,10 @@ sub find_bin{ sub const_cccmd { my($self) = shift; local($_) = $self->SUPER::const_cccmd(@_); - s/\s-O\d?\b/ -g/g if $::opt_g; + if ($::opt_g) { + s/\s-O\d?\b//; # delete optimise option + s/\s-/ -g -/; # add -g option + } $_; } diff --git a/Oracle.h b/Oracle.h index f0591906..f6604b81 100644 --- a/Oracle.h +++ b/Oracle.h @@ -1,15 +1,17 @@ /* - $Id: Oracle.h,v 1.9 1996/10/15 02:19:14 timbo Exp $ + $Id: Oracle.h,v 1.10 1997/06/14 17:42:12 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce You may distribute under the terms of either the GNU General Public - License or the Artistic License, as specified in the Perl README file. + License or the Artistic License, as specified in the Perl README file, + with the exception that it cannot be placed on a CD-ROM or similar media + for commercial distribution without the prior approval of the author. */ -#define NEED_DBIXS_VERSION 7 +#define NEED_DBIXS_VERSION 8 #include /* installed by the DBI module */ diff --git a/Oracle.pm b/Oracle.pm index 050260b9..5a354425 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,9 +1,11 @@ -# $Id: Oracle.pm,v 1.42 1997/01/14 21:51:50 timbo Exp $ +# $Id: Oracle.pm,v 1.44 1997/06/14 17:42:12 timbo Exp $ # -# Copyright (c) 1994,1995 Tim Bunce +# Copyright (c) 1994,1995,1996,1997 Tim Bunce # # You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. +# License or the Artistic License, as specified in the Perl README file, +# with the exception that it cannot be placed on a CD-ROM or similar media +# for commercial distribution without the prior approval of the author. my $oracle_home; @@ -16,10 +18,10 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.44'; - my $Revision = substr(q$Revision: 1.42 $, 10); + $VERSION = '0.45'; + my $Revision = substr(q$Revision: 1.44 $, 10); - require_version DBI 0.69; + require_version DBI 0.83; bootstrap DBD::Oracle $VERSION; @@ -53,6 +55,13 @@ require 5.002; $drh; } + + END { + # Used to silence 'Bad free() ...' warnings caused by bugs in Oracle's code + # being detected by Perl's malloc. + $ENV{PERL_BADFREE} = 0; + } + 1; } @@ -61,7 +70,7 @@ require 5.002; use strict; sub errstr { - DBD::Oracle::errstr(@_); + return $DBD::Oracle::errstr; } sub load_oratab { # get list of 'local' databases @@ -138,7 +147,6 @@ require 5.002; # Call Oracle OCI orlon func in Oracle.xs file # and populate internal handle data. - DBD::Oracle::db::_login($this, $dbname, $user, $auth) or return undef; @@ -152,7 +160,7 @@ require 5.002; use strict; sub errstr { - DBD::Oracle::errstr(@_); + return $DBD::Oracle::errstr; } sub prepare { @@ -190,6 +198,21 @@ require 5.002; $sth; } + sub plsql_errstr { + my ($dbh) = @_; + # with thanks to Bob Menteer + my (@msg, $line,$pos,$text); + my $sth = $dbh->prepare(q{ + select line,position,text from user_errors order by sequence + }); + return undef unless $sth; + $sth->execute or return undef; + while(($line,$pos,$text) = $sth->fetchrow){ + push @msg, "Error in PL/SQL block" unless @msg; + push @msg, "$line.$pos: $text"; + } + join("\n", @msg); + } } @@ -197,8 +220,253 @@ require 5.002; use strict; sub errstr { - DBD::Oracle::errstr(@_); + return $DBD::Oracle::errstr; } } 1; + +__END__ + +=head1 NAME + +DBD::Oracle - Oracle database driver for the DBI module + +=head1 SYNOPSIS + + use DBI; + + $dbh = DBI->connect("dbi:Oracle:", $user, $passwd); + + # See the DBI module documentation for full details + +=head1 DESCRIPTION + +DBD::Oracle is a Perl module which works with the DBI module to provide +access to Oracle databases. + +=head1 CONNECTING TO ORACLE + +This is a topic which often causes problems. Mainly due to Oracle's many +and sometimes complex ways of specifying and connecting to databases. +(James Taylor and Lane Sharman have contributed much of the text in +this section.) + +=head2 Oracle environment variables + +Oracle typically uses two environment variables to specify default +connections: ORACLE_SID and TWO_TASK. + +ORACLE_SID is really unnecessary to set since TWO_TASK provides the +same functionality in addition to allowing remote connections. + + % setenv TWO_TASK T:hostname:ORACLE_SID # for csh shell + $ TWO_TASK=T:hostname:ORACLE_SID export TWO_TASK # for sh shell + + % sqlplus username/password + +Note that if you have *both* local and remote databases, and you +have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO_TASK takes precedence +over ORACLE_SID (i.e. you get connected to remote system). + + TWO_TASK=P:sid + +will use the pipe driver for local connections using SQL*Net v1. + + TWO_TASK=T:machine:sid + +will use TCP/IP (or D for DECNET, etc.) for remote SQL*Net v1 connection. + + TWO_TASK=dbname + +will use the info stored in the SQL*Net v2 F +configuration file for local or remote connections. + +The ORACLE_HOME environment variable should be set correctly. It can be +left unset if you aren't using any of Oracle's executables, but it is +not recommended and error messages may not display. + +Discouraging the use of ORACLE_SID makes it easier on the users to see +what is going on. (It's unfortunate that TWO_TASK couldn't be renamed, +since it makes no sense to the end user, and doesn't have the ORACLE +prefix). + +=head2 Using DBD::Oracle + +Below are various ways of connecting to an oracle database using +SQL*Net 1.x and SQL*Net 2.x. "Machine" is the computer the database is +running on, "SID" is the SID of the database, "DB" is the SQL*Net 2.x +connection descriptor for the database. + + BEGIN { + $ENV{ORACLE_HOME} = '/home/oracle/product/7.x.x'; + $ENV{TWO_TASK} = 'DB'; + } + $dbh = DBI->connect('dbi:Oracle:','scott', 'tiger'); + # - or - + $dbh = DBI->connect('dbi:Oracle:','scott/tiger'); + +works for SQL*Net 2.x, so does + + $ENV{TWO_TASK} = 'T:Machine:SID'; + +for SQL*Net 1.x connections. For local connections you can use the +pipe driver: + + $ENV{TWO_TASK} = 'P:SID'; + +Here are some variations (not setting TWO_TASK) + + $dbh = DBI->connect('dbi:Oracle:T:Machine:SID','username','password') + + $dbh = DBI->connect('dbi:Oracle:','username@T:Machine:SID','password') + + $dbh = DBI->connect('dbi:Oracle:','username@DB','password') + + $dbh = DBI->connect('dbi:Oracle:DB','username','password') + + $dbh = DBI->connect('dbi:Oracle:DB','username/password','') + + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=foobarSID)))}, "") + +If you are having problems with login taking a long time (>10 secs say) +then you might have tripped up on an Oracle bug. Yoy can try using one +of the ...@DB variants as a workaround. E.g., + + $dbh = DBI->connect('','username/password@DB',''); + +On the other hand, that may cause you to trip up on another Oracle bug +that causes alternating connection attempts to fail! (In reality only +a small proportion of people experience these problems.) + + +=head2 Optimizing Oracle's listner + +[By Lane Sharman ] I spent a LOT of time optimizing +listener.ora and I am including it here for anyone to benefit from. My +connections over tnslistener on the same humble Netra 1 take an average +of 10-20 millies according to tnsping. If anyone knows how to make it +better, please let me know! + + LISTENER = + (ADDRESS_LIST = + (ADDRESS = + (PROTOCOL = TCP) + (Host = aa.bbb.cc.d) + (Port = 1521) + (QUEUESIZE=10) + ) + ) + + STARTUP_WAIT_TIME_LISTENER = 0 + CONNECT_TIMEOUT_LISTENER = 10 + TRACE_LEVEL_LISTENER = OFF + SID_LIST_LISTENER = + (SID_LIST = + (SID_DESC = + (SID_NAME = xxxx) + (ORACLE_HOME = /xxx/local/oracle7-3) + (PRESPAWN_MAX = 40) + (PRESPAWN_LIST= + (PRESPAWN_DESC=(PROTOCOL=tcp) (POOL_SIZE=40) (TIMEOUT=120)) + ) + ) + ) + +1) When the application is co-located on the host AND there is no need for +outside SQLNet connectivity, stop the listener. You do not need it. Get +your application/cgi/whatever working using pipes and shared memory. I am +convinced that this is one of the connection bugs (sockets over the same +machine). Note the $ENV{ORAPIPES} env var. The essential code to do +this at the end of this section. + +2) Be careful in how you implement the multi-threaded server. Currently I +am not using it in the initxxxx.ora file but will be doing some more testing. + +3) Be sure to create user rollback segments and use them; do not use the +system rollback segments; however, you must also create a small rollback +space for the system as well. + +5) Use large tuning settings and get lots of RAM. Check out all the +parameters you can set in v$parameters because there are quite a few not +documented you may to set in your initxxx.ora file. + +6) Use svrmgrl to control oracle from the command line. Write lots of small +SQL scripts to get at V$ info. + + use DBI; + # Environmental variables used by Oracle + $ENV{ORACLE_SID} = "xxx"; + $ENV{ORACLE_HOME} = "/opt/oracle7"; + $ENV{EPC_DISABLED} = "TRUE"; + $ENV{ORAPIPES} = "V2"; + my $dbname = "xxx"; + my $dbuser = "xxx"; + my $dbpass = "xxx"; + my $dbh = DBI->connect("dbi:Oracle:$dbname", $dbuser, $dbpass) + || die "Unale to connect to $dbname: $DBI::errstr\n"; + +=head2 Oracle utilities + +If you are still having problems connecting then the Oracle adapters +utility may offer some help. Run these two commands: + + $ORACLE_HOME/bin/adapters + $ORACLE_HOME/bin/adapters $ORACLE_HOME/bin/sqlplus + +and check the output. The "Protocol Adapters" section should be the +same. It should include at least "IPC Protocol Adapter" and "TCP/IP +Protocol Adapter". + +If it generates any errors which look relevant then please talk to yor +Oracle technical support (and not the dbi-users mailing list). Thanks. +Thanks to Mark Dedlow for this information. + +=head2 International NLS / 8-bit text issues + +If 8-bit text is returned as '?' characters or can't be inserted +make sure the following environment vaiables are set correctly: + NLS_LANG, ORA_NLS, ORA_NLS32 +Thanks to Robin Langdon for this information. +Example: + $ENV{NLS_LANG} = "american_america.we8iso8859p1"; + $ENV{ORA_NLS} = "/home/oracle/ocommon/nls/admin/data"; + $ENV{ORA_NLS32} = "/home/oracle/ocommon/nls/admin/data"; + +Also From: Yngvi Thor Sigurjonsson +If you are using 8-bit characters and "export" for backups make sure +that you have NLS_LANG set when export is run. Otherwise you might get +unusable backups with ? replacing all your beloved characters. We were +lucky once when we noticed that our exports were damaged before +disaster struck. + +Remember that the database has to be created with an 8-bit character set. + +Also note that the NLS files $ORACLE_HOME/ocommon/nls/admin/data +changed extension (from .d to .nlb) between 7.2.3 and 7.3.2. + + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +DBD::Oracle by Tim Bunce. + +=head1 COPYRIGHT + +The DBD::Oracle module is Copyright (c) 1995,1996,1997 Tim Bunce. England. +The DBD::Oracle module is free software; you can redistribute it and/or +modify it under the same terms as Perl itself with the exception that it +cannot be placed on a CD-ROM or similar media for commercial distribution +without the prior approval of the author. + +=head1 ACKNOWLEDGEMENTS + +See also L. + +=cut diff --git a/Oracle.xs b/Oracle.xs index e7544dac..79c0e29c 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -1,10 +1,12 @@ /* - $Id: Oracle.xs,v 1.43 1997/01/14 21:48:19 timbo Exp $ + $Id: Oracle.xs,v 1.44 1997/06/14 17:42:12 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce You may distribute under the terms of either the GNU General Public - License or the Artistic License, as specified in the Perl README file. + License or the Artistic License, as specified in the Perl README file, + with the exception that it cannot be placed on a CD-ROM or similar media + for commercial distribution without the prior approval of the author. */ @@ -32,15 +34,6 @@ BOOT: dbd_init(DBIS); -void -errstr(h) - SV * h - CODE: - /* called from DBI::var TIESCALAR code for $DBI::errstr */ - D_imp_xxh(h); - ST(0) = sv_mortalcopy(DBIc_ERRSTR(imp_xxh)); - - MODULE = DBD::Oracle PACKAGE = DBD::Oracle::dr # disconnect_all renamed and ALIAS'd to avoid length clash on VMS :-( @@ -99,7 +92,7 @@ STORE(dbh, keysv, valuesv) SV * valuesv CODE: ST(0) = &sv_yes; - if (!dbd_db_STORE(dbh, keysv, valuesv)) + if (!dbd_db_STORE_attrib(dbh, keysv, valuesv)) if (!DBIS->set_attr(dbh, keysv, valuesv)) ST(0) = &sv_no; @@ -108,10 +101,10 @@ FETCH(dbh, keysv) SV * dbh SV * keysv CODE: - SV *valuesv = dbd_db_FETCH(dbh, keysv); + SV *valuesv = dbd_db_FETCH_attrib(dbh, keysv); if (!valuesv) valuesv = DBIS->get_attr(dbh, keysv); - ST(0) = valuesv; /* dbd_db_FETCH did sv_2mortal */ + ST(0) = valuesv; /* dbd_db_FETCH_attrib did sv_2mortal */ void @@ -123,7 +116,7 @@ disconnect(dbh) XSRETURN_YES; } /* Check for disconnect() being called whilst refs to cursors */ - /* still exists. This needs some more thought. */ + /* still exists. This possibly needs some more thought. */ if (DBIc_ACTIVE_KIDS(imp_dbh) && DBIc_WARN(imp_dbh) && !dirty) { warn("disconnect(%s) invalidates %d active cursor(s)", SvPV(dbh,na), (int)DBIc_ACTIVE_KIDS(imp_dbh)); @@ -144,8 +137,24 @@ DESTROY(dbh) } else { if (DBIc_ACTIVE(imp_dbh)) { - if (DBIc_WARN(imp_dbh) && !dirty) + static int auto_rollback = -1; + if (DBIc_WARN(imp_dbh) && (!dirty || dbis->debug >= 3)) warn("Database handle destroyed without explicit disconnect"); + /* The application has not explicitly disconnected. That's bad. */ + /* To ensure integrity we *must* issue a rollback. This will be */ + /* harmless if the application has issued a commit. If it hasn't */ + /* then it'll ensure integrity. Consider a Ctrl-C killing perl */ + /* between two statements that must be executed as a transaction. */ + /* Perl will call DESTROY on the dbh and, if we don't rollback, */ + /* the server will automatically commit! Bham! Corrupt database! */ + if (auto_rollback == -1) { /* need to determine behaviour */ + /* DBD_ORACLE_AUTO_ROLLBACK is offered as a _temporary_ sop to */ + /* those who can't fix their code in a short timescale. */ + char *p = getenv("DBD_ORACLE_AUTO_ROLLBACK"); + auto_rollback = (p) ? atoi(p) : 1; + } + if (auto_rollback) + dbd_db_rollback(dbh); /* ROLLBACK! */ dbd_db_disconnect(dbh); } dbd_db_destroy(dbh); @@ -288,23 +297,23 @@ STORE(sth, keysv, valuesv) SV * valuesv CODE: ST(0) = &sv_yes; - if (!dbd_st_STORE(sth, keysv, valuesv)) + if (!dbd_st_STORE_attrib(sth, keysv, valuesv)) if (!DBIS->set_attr(sth, keysv, valuesv)) ST(0) = &sv_no; # FETCH renamed and ALIAS'd to avoid case clash on VMS :-( void -FETCH_attrib_(sth, keysv) +FETCH_attrib(sth, keysv) SV * sth SV * keysv ALIAS: FETCH = 1 CODE: - SV *valuesv = dbd_st_FETCH(sth, keysv); + SV *valuesv = dbd_st_FETCH_attrib(sth, keysv); if (!valuesv) valuesv = DBIS->get_attr(sth, keysv); - ST(0) = valuesv; /* dbd_st_FETCH did sv_2mortal */ + ST(0) = valuesv; /* dbd_st_FETCH_attrib did sv_2mortal */ void diff --git a/Oraperl.pm b/Oraperl.pm index 59e55e29..535c5229 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,11 +1,13 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.31 1996/10/29 18:17:23 timbo Exp $ +# $Id: Oraperl.pm,v 1.33 1997/06/14 17:42:12 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # # You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. +# License or the Artistic License, as specified in the Perl README file, +# with the exception that it cannot be placed on a CD-ROM or similar media +# for commercial distribution without the prior approval of the author. # # To use this interface use one of the following invocations: # @@ -23,7 +25,7 @@ require 5.002; use DBI 0.70; use Exporter; -$VERSION = substr(q$Revision: 1.31 $, 10); +$VERSION = substr(q$Revision: 1.33 $, 10); @ISA = qw(Exporter); @@ -38,7 +40,6 @@ $VERSION = substr(q$Revision: 1.31 $, 10); $debug = 0 unless defined $debug; $debugdbi = 0; -my $bad_free_dump = $ENV{DBD_DUMP}; # $safe # set true/false before 'use Oraperl' if needed. $safe = 1 unless defined $safe; @@ -73,8 +74,11 @@ sub _func_ref { sub _warn { my $prev_warn = shift; - if ($_[0] =~ /free\(\) ignored/) { - dump if $bad_free_dump; + if ($_[0] =~ /^(Bad|Duplicate) free/) { + if ($ENV{PERL_DBD_DUMP} eq 'dump') { + print STDERR "Aborting with a core dump for diagnostics (PERL_DBD_DUMP)\n"; + dump; + } return; } $prev_warn ? &$prev_warn(@_) : warn @_; @@ -90,7 +94,7 @@ sub ora_login { my($system_id, $name, $password) = @_; local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; - $Oraperl::drh->connect($system_id, $name, $password); + DBI->connect($system_id, $name, $password, 'Oracle'); } sub ora_logoff { my($dbh) = @_; @@ -386,8 +390,12 @@ Example: $nfields = &ora_fetch($csr); -Used in an array context, the value returned is an array -containing the data, one element per field. +Used in an array context, the value returned is an array containing the +data, one element per field. Note that this will not work as expected: + + @data = &ora_fetch($csr) || die "..."; # WRONG + +The || forces a scalar context so ora_fetch returns the number of fields. An optional second parameter may be supplied to indicate whether the truncation of a LONG or LONG RAW field is to be permitted (non-zero) or @@ -645,6 +653,8 @@ allocates the amount of space indicated by the $ora_long variable. This is initially set to 80 (for compatibility with Oracle products) but may be set within a program to whatever size is required. +$ora_long is only used when fetching data, not when inserting it. + =item * $ora_trunc diff --git a/README b/README index 3039e698..70c8582a 100644 --- a/README +++ b/README @@ -1,17 +1,21 @@ + DBD::Oracle -- an Oracle 7 interface for Perl 5. - Copyright (c) 1994,1995,1996 Tim Bunce + Copyright (c) 1994,1995,1996,1997 Tim Bunce You may distribute under the terms of either the GNU General Public - License or the Artistic License, as specified in the Perl README file. + License or the Artistic License, as specified in the Perl README file, + with the exception that it cannot be placed on a CD-ROM or similar media + for commercial distribution without the prior approval of the author. PLEASE READ THE ENTIRE README FILE CAREFULLY ! -* WARNING: THIS IS MOSTLY ALPHA SOFTWARE. Your mileage may vary. * - -* THE ORAPERL EMULATION IS NO LONGER ALPHA. IT IS NOW FULLY RELEASED. * +WARNING: + THE DBD::Oracle MODULE IS ALPHA SOFTWARE. It is *only* 'Alpha' + because the interface (api) is not finalised. The Alpha status does + not reflect code quality or stability. | NOTE: | The only currently supported interface is via Oraperl.pm, the | @@ -19,16 +23,25 @@ DBD::Oracle -- an Oracle 7 interface for Perl 5. | Execute "perldoc Oraperl" after installing for full information. | +QUICK START GUIDE: + + The DBI requires one or more 'driver' modules to talk to databases. + Fetch, build and install the DBI module as per it's README file. + Then delete its source directory tree since it's no longer needed. + Use the 'perldoc DBI' command to read the DBI documentation. + Fetch the DBD::Oracle driver module and unpack it. + Follow the guidelines in this README file caefully. + *BEFORE* BUILDING, TESTING AND INSTALLING this you will need to: - Build, test and install Perl 5 (at least 5.002beta2). + Build, test and install Perl 5 (at least 5.003). It is very important to TEST it and INSTALL it! Build, test and install the DBI module (at least DBI 0.71). It is very important to TEST it and INSTALL it! - Remember to *read* the DBI README file! + Remember to *read* the DBI README file and this one fully! Install enough Oracle software to enable DBD::Oracle to build. That includes Pro*C. @@ -36,8 +49,8 @@ DBD::Oracle -- an Oracle 7 interface for Perl 5. BUILDING: - perl Makefile.PL - make + perl Makefile.PL # use a perl that's in your PATH + make If you have problems see the 'IF YOU HAVE PROBLEMS' section below. If it's builds without error you can then run the tests. For the @@ -58,13 +71,17 @@ The supplied test will connect to the database using the value of the ORACLE_USER environment variable so you should set that to the correct value before starting the test. Please read README.login. - make test + make test - make install (if the tests look okay) + make install (if the tests look okay) IF YOU HAVE PROBLEMS: +Make sure you are using a recent perl 5.003 or preferably 5.004 and +make sure it's on your path so you can say 'perl Makefile.PL' and +not '/path/to/perl Makefile.PL'. + Do not hand edit the generated Makefile unless you are completely sure you understand the implications! Always try to make changes via the Makefile.PL command line and/or editing the Makefile.PL. @@ -80,12 +97,18 @@ then read README.client, it might help but basically I can't help much. Others on the dbi-users mailing list probably can. If you have linking problems (errors related to libraries or functions) -then you could try foring a 'static' build using: +then you could try forcing a 'static' build using: make clean perl Makefile.PL LINKTYPE=static make make perl (you'll need to use and install _this_ new perl binary) + make test + make -f Makefile.aperl inst_perl MAP_TARGET=perl + make install + +Also read the README.help file which is full of useful tips and +workarounds for various problems of various systems. Please don't post problems to comp.lang.perl.misc or perl5-porters. This software is supported via the dbi-users mailing list. For more @@ -106,7 +129,7 @@ dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. But note... make test make test TEST_VERBOSE=1 (only if any of the t/* tests fail) -2. Full details of which version of Oracle and Perl you're using. +2. Full details of which version of Oracle you're using. 3. The output of perl -V @@ -142,6 +165,7 @@ Tim. =============================================================================== Examples and other info: +README.help -- Read it first if you have any problems at all README.clients -- building/using DBD::Oracle on minimally configured systems README.login -- help for login problems README.longs -- examples dealing with LONG types (blobs) @@ -188,308 +212,26 @@ ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip =============================================================================== -Some users of DBD::Oracle on non-sun platforms: -(this is VERY out of date now, there are MANY users on many platforms) - -HP-UX 9: - Terry Greenlaw - Les Troyer - Norbert Kiesel - Greg Anderson - Johann Griessler - Dave Venus - -Unisys U6000/300: - Alan Burlison - -SCO 3: - Greg Gerber - -Sequent DYNIX/ptx 2: - Alligator Descartes - Jonathan Lemon - -Motorola M88100 (SVR3.2): - Christian Murphy - -DEC UNIX 3.2: - David J. DeWolfe - - -DEC Alpha, OSF/1 v2: - Royal Hansen - Jonathan Olson - Greg Gerber - Davide Migliavacca - -SGI Iris Indigo R4000 Irix 5.3: - Andrew G Wood - -AIX 3.2 - Davide Migliavacca - Joerg Senekowitsch - -AIX 4.1 - Ken P. Nikolai - -NT: - Jim Fox - +Some platforms on which the DBI and DBD::Oracle modules run: + + Solaris 1 and 2 + Windows NT (using Perl5.004) + HP-UX 9 and 10 + Unisys U6000/300 + SCO 3 + Sequent DYNIX/ptx 2 + Motorola M88100 (SVR3.2) + DEC UNIX 3.2 + DEC Alpha + OSF/1 v2 + SGI IRIX 5 & 6 + AIX 3 & 4 and others + +(please let me know if you system is not listed). =============================================================================== -Platform or Oracle Version specific notes: - -Note that although some of these refer to specific systems and versions the -same or similar problems may exist on other systems or versions. - -------------------------------------------------------------------------------- -Can't find libclntsh.so at run time: - -Dave Moellenhoff : libclntsh.so is the shared -library composed of all the other Oracle libs you used to have to -statically link. Oracle didn't start providing it until 7.2 and later. -libclntsh.so should be in $ORACLE_HOME/lib. If it's missing, try -running $ORACLE_HOME/rdbms/lib/genclntsh.sh and it should create it. - -Also: Never copy libclntsh.so to a different machine or Oracle version. -If DBD::Oracle was built on a machine with a different path to libclntsh.so -then you'll need to set set an environment variable, typically -LD_LIBRARY_PATH, to include the directory containing libclntsh.so. - -But: LD_LIBRARY_PATH is typically ignored if the script is running set-uid -(which is common in some httpd/CGI configurations). In this case -either rebuild with LD_RUN_PATH set to include the path to libclntsh -or create a symbolic link so that libclntsh is available via the same -path as it was when the module was built. (On Solaris the command -"ldd -s Oracle.so" can be used to see how the linker is searching for it.) - - -------------------------------------------------------------------------------- -Error while trying to retrieve text for error ...: - -From Lou Henefeld : We discovered that we needed -some files from the $ORACLE_HOME/ocommon/nls/admin/data directory: - lx00001.nlb, lx10001.nlb, lx1boot.nlb, lx20001.nlb -If your national language is different from ours (American English), -you will probably need different nls data files. - - -------------------------------------------------------------------------------- -Login takes a long time - -Use connect('', 'user/passwd@tnsname', ''). See README.login. - -------------------------------------------------------------------------------- -Oracle 7.3 on Solaris 2.5 (maybe others): - - libc internal error: _rmutex_unlock: rmutex not held. - -Try each of these in turn: -- Try removing -lthread from the list of libraries to link with (edit Makefile). -- Try passing explicit db sid name to ora_login or connect. -- Try removing clntsh from the list of libraries to link to (edit Makefile). - -If any of these work please let me know (include full version info). - -------------------------------------------------------------------------------- -Bad free() warnings: - -These are generally caused by problems in Oracle's own library code. -You can use this code to hide them: - - $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Bad free/ } - -But please let me know if you have this problem (include full version info). -Rather than simply hiding it it would be much better to help me fix it! -Follow the instructions in step 5 above (for generating a version of -DBD::Oracle with debugging enabled) and then use the following code -to generate a core dump at the point the bad free happens. - - $SIG{__WARN__} = sub { $_[0] =~ /^Bad free/ ? dump : warn $_[0] } - -Follow the instructions in step 5 above for getting a stack trace from -the core file and then send it to me along with the other information -requested in the 'If you have problems' section. - -------------------------------------------------------------------------------- -8-bit text is returned as '?' characters or can't be inserted. - -Make sure the following environment vaiables are set: - NLS_LANG, ORA_NLS, ORA_NLS32 -Thanks to Robin Langdon for this information. -Example: - $ENV{NLS_LANG} = "american_america.we8iso8859p1"; - $ENV{ORA_NLS} = "/home/oracle/ocommon/nls/admin/data"; - $ENV{ORA_NLS32} = "/home/oracle/ocommon/nls/admin/data"; - -Also From: Yngvi Thor Sigurjonsson -I would like all of you who are using 8-bit characters and "export" for -backups to make sure that you have NLS_LANG set when export is run. -Otherwise you might get unusable backups with ? replacing all your -beloved characters. We were lucky once when we noticed that our exports -were damaged before disaster struck. -Remember that the database has to be created with an 8-bit character set. - -Also note that the NLS files $ORACLE_HOME/ocommon/nls/admin/data -changed extension (from .d to .nlb) between 7.2.3 and 7.3.2. - -------------------------------------------------------------------------------- -AIX - warnings like these when building perl are not usually a problem: - -ld: 0711-415 WARNING: Symbol Perl_sighandler is already exported. -ld: 0711-319 WARNING: Exported symbol not defined: Perl_abs_amg - -When building on AIX check to make sure that all of bos.adt (13 pieces) -and all of bos.compat (11 pieces) are installed. - -Thanks to Mike Moran for this information. - -------------------------------------------------------------------------------- -HP-UX 9.x: Terry Greenlaw - -I traced a problem with "ld: Invalid loader fixup needed" to the file -libocic.a. On HP-UX it contains position-dependant code and cannot be -used to generate dynamic load libraries. The only shared library that -Oracle ships under HP-UX is liboracle.sl which replaces libxa.a, -libsql.a, libora.a, libcvg.a, and libnlsrtl.a. The OCI stuff still -appears to only link statically under HU-UX 9.x [10.x is okay]. - -You'll need to build DBD::Oracle statically linked into the perl binary. -See the static linking notes below. - -HP-UX 10 and Oracle 7.2.x do work together when creating dynamic libraries. -The problem was older Oracle libraries were built without the +z flag to cc, -and were therefore position-dependent libraries that can't be linked -dynamically. Newer Oracle releases don't have this problem and it may be -possible to even use the newer Oracle libraries under HP-UX 9. Oracle 7.3 -will ONLY work under HP-UX 10, however. - -------------------------------------------------------------------------------- -For platforms which require static linking. - -If you get an error like: - -/usr/lib/dld.sl: Bad magic number for shared library: -/usr/local/lib/perl5/hpux/auto/DBD/Oracle/Oracle.a - -You'll need to build DBD::Oracle statically linked and then link it -into a perl binary: - - perl Makefile.PL LINKTYPE=static - make - make perl (makes a perl binary in current directory) - make test FULLPERL=./perl (run tests using the new perl binary) - make install - -You will probably need to have already built and installed a static -version of the DBI in order that it be automatically included when -you do the 'make perl' above. - -------------------------------------------------------------------------------- -Error: Syntax error in oratypes.h - -Try uncommenting the '#define signed' line in Oracle.h - -------------------------------------------------------------------------------- -Oracle 7.1 and 7.2: Connection takes a long time and may coredump - -Oracle bug number: 227321 related to changing the environment before -connecting to oracle. - -To work around this bug, do not set any environment variables in your -oraperl script before you call ora_login, and when you do call -ora_login, the first argument must be the empty string. This means -that you have to be sure that your environment variables ORACLE_SID -and ORACLE_HOME are set properly before you execute any oraperl -script. It is probably also possible to pass the SID to ora_login as -part of the username (for example, ora_login("", "SCOTT/TIGER@PROD", -"")), although I have not tested this. -This workaround is based on information from Kevin Stock. - -------------------------------------------------------------------------------- -Oracle 7.1.4/5: ORA-01002: fetch out of sequence - -Edited from Message-ID: <3qaui9$ae@usenet.rpi.edu> and -<3qb5dp$2nc@usenet.rpi.edu> in comp.databases.oracle -From: finkej@ts.its.rpi.edu (Jon Finke) - -Every test run results in an "ORA-01002: fetch out of sequence" error. - -The manual claims that this is the result of calling "ofetch" before -oparse/oexec, or running out of things to fetch. Yet, I am calling -oopen, oparse, oexec, (odesc, odefin) all without error. As a control -case, I also built the cdemo2 program, and it appears to be calling -the same routines, yet it is successful. - -Note: In the "broken" program, I am currently calling odsc in a loop - for each column in the query, and then calling odefin, while in the - "working" program, I call odescr/odefin, odesc/odefin for each column. - In both cases, the calls to odefin seem reasonable. - -Both programs are attempting the query "select user,uid from dual". - -This is a known problem in version 7.1.4, and it will be fixed in 7.1.6. -The bug report is #239128. --- -Jon Finke finkej@rpi.edu -Senior Network Systems Engineer http://www.rpi.edu/~finkej -Information Technology Services 518 276 8185 (voice) | 518 276 2809 (fax) -Rensselaer Polytechnic Institute 110 8th Street, Troy NY, 12180 - -------------------------------------------------------------------------------- -Error: ORA-00604: error occurred at recursive SQL level (DBD: login failed) - -This can happen if TWO_TASK is defined but you connect using ORACLE_SID. - -------------------------------------------------------------------------------- -Error: ld: Undefined symbols _environ _dlopen _dlclose ... -Environment: SunOS 4.1.3, Oracle 7.1.6 Steve Livingston - -If you get link errors like: ld: Undefined symbols _environ _dlopen _dlclose ... -and the link command line includes '-L/usr/5lib -lc' then comment out the -'CLIBS= $(OTHERLIBS) -L/usr/5lib -lc' line in the Makefile. - -------------------------------------------------------------------------------- -Environment: SVR4, stephen.zander@mckesson.com - -Error: can't load ./blib/arch/auto/DBD/Oracle/Oracle.so for module DBD::Oracle: -DynamicLinker:/usr/local/bin/perl:relocation error:symbol not found:setitimer -Fix: Try adding the '-lc' to $ORACLE_HOME/rdbms/lib/sysliblist (just -make sure it's not on a new line). - -------------------------------------------------------------------------------- -Error: Undefined symbols __cg92_used at link time. -Environment: Solaris, GCC - -Fix: If you're compiling Oracle applications with gcc on Solaris you need to -link with a file called $ORACLE_HOME/lib/__fstd.o. If you compile with the -SparcWorks compiler you need to add the command line option on -xcg92 -to resolve these symbol problems cleanly. - -Alligator Descartes - -------------------------------------------------------------------------------- -Environment: SunOS 4.1.3, Oracle 7.1.3 John Carlson - -Problem: oraperl and DBD::Oracle fail to link. Some messing around with -the library order makes the link succeed. Now I get a "Bad free()" when -ora_logoff is called. - -Solution: -In my case, this was caused by a faulty oracle install. The install grabbed -the wrong version of mergelib (The X11R6 one) instead of the one in -$ORACLE_HOME/bin. Try a more limited path and reinstall Oracle again. - -------------------------------------------------------------------------------- -Environment: DEC Alpha, OSF, Jonathan Olson - -Problem: ERROR EVENT: DBI::dr=HASH(0x14011fee8)->DBI::default_handler: - 0 ORA-00000: normal, successful completion (DBD: login failed) - -Solution: Add '#define A_OSF' to Oracle.h above '#include ' and -complain to Oracle about bugs in their header files on 64 bit systems. - -=============================================================================== +See the large README.help file for lots of hints and advice about build and +runtime issues. End. diff --git a/README.clients b/README.clients index d6827e5d..2151ffd5 100644 --- a/README.clients +++ b/README.clients @@ -25,6 +25,10 @@ ORACLE_HOME/lib. You'll also need the header files from ORACLE_HOME/sqllib/public/*.h and ORACLE_HOME/rdbms/demo/*.h (you won't need them all, but you can get rid of them after DBD::Oracle compiles). +[You'll probably need at least ocommon in addition to network. But if you +use the Oracle installer (as you always should) it'll probably install +ocommon for you.] + So just put that stuff on your client box and install DBI and DBD::Oracle there. Once DBD::Oracle is installed you can remove the OCI libraries and headers (make sure to keep SQL*Net!) @@ -71,4 +75,120 @@ drwxr-xr-x 2 oracle apbr 512 May 15 17:38 public/ Jon ------------------------------------------------------------------------------- +Jon Meek Tue, 18 Feb 1997 + +This was for Oracle 7.2.2.3.0 (client side for DBD:Oracle build) and +SQL*net v2. I have heard that sqlnet.ora might not be needed. + +ls -lR oracle +oracle: +total 2 +drwxr-xr-x 3 meekj apbr 512 Nov 3 11:46 network/ + +oracle/network: +total 2 +drwxr-xr-x 2 meekj apbr 512 Nov 3 11:46 admin/ + +oracle/network/admin: +total 6 +-rw-r--r-- 1 meekj apbr 309 Nov 3 11:46 sqlnet.ora +-rw-r--r-- 1 meekj apbr 1989 Nov 3 11:46 tnsnames.ora + +------------------------------------------------------------------------------- + +From: Lack Mr G M +Date: Thu, 23 Jan 1997 18:24:03 +0000 + + I noticed the appended in the README.clients file of the DBD-Oracle +distribution. My experience is somewhat different (and simpler). + On Irix5.3 (ie. what this user was using) I built DBI and DBD-Oracle +on a system with Oracle and Pro*C installed. I tested it on another +system (where I knew an oracle id). I installed it from a third (which +had write rights to the master copies of the NFS mounted directories), +but this didn't have Oracle installed. + + Having done this all of my systems (even those without a hint of +oracle on them) could access remote Oracle servers by setting TWO_TASK +appropriately. SQL*Net didn't seem to come into it. + + The dynamically-loadable library created (auto/DBD/Oracle/Oracle.so) +contains no reference to any dynamic Oracle library. + + Exactly the same happened for my Solaris systems. + + From: James Cooper + > [...], what do I need in addition to perl5 to access an Oracle database + > on another system from a unix box (Solaris 2.5) that doesn't have an + > oracle database running on it ? + > + > In other words are their some oracle shared objects, etc. I need ? + +I don't have experience with Solaris, but on IRIX 5.3, I simply installed +SQL*Net (ORACLE_HOME/network/admin/*) and the OCI libraries which are in +ORACLE_HOME/lib. You'll also need the header files from +ORACLE_HOME/sqllib/public/*.h and ORACLE_HOME/rdbms/demo/*.h (you won't +need them all, but you can get rid of them after DBD::Oracle compiles). + +So just put that stuff on your client box and install DBI and DBD::Oracle +there. Once DBD::Oracle is installed you can remove the OCI libraries and +headers (make sure to keep SQL*Net!) + +------------------------------------------------------------------------------- +OS/Oracle version: Solaris 2 and Oracle 7.3 + +Problem: DBD::Oracle works on the database machine, but not from remote +machines (via TCP). SQL*Plus, however, does work from the remote machines. + +Cause: $ORACLE_HOME/ocommon/nls/admin/data/lx1boot.nlb is missing + +Solution: Make sure $ORACLE_HOME/ocommon is available on the remote machine. + +This was the first time I had used DBD::Oracle with Oracle 7.3.2. Oracle +7.1 has a somewhat different directory structure, and seems to store files +in different places relative to $ORACLE_HOME. So I just hadn't NFS +exported all the files I needed to. I figured that as long as SQL*Plus +was happy, I had all the necessary files to run DBD::Oracle (since that +was always the case with 7.1). But I was wrong. + +James Cooper + +------------------------------------------------------------------------------- +To: dbi-users@fugue.com +Subject: Re: Oracle Licencing... +Date: Thu, 15 May 1997 11:54:09 -0700 +From: Mark Dedlow + +Please forgive the continuation of this somewhat off-topic issue, +but I wanted to correct/update my previous statement, and it's +probably of interest to many DBD-Oracle users. + +> > In general, as I understand it, Oracle doesn't license the client runtime +> > libraries directly, rather they get you for SQL*NET. It is typically +> > about $100 per node. You have to have that licensed on any machine +> > that runs DBD-Oracle. + +Oracle recently changed policy. sqlnet now comes with RDBMS licenses. +If you have named RDBMS licenses, you can install sqlnet on as many +client machines as you have named licenses for the server. If you +have concurrent RDBMS licenses, you can install sqlnet on as many +client machines as you like, and only use concurrently as many +as you have concurrent server RDBMS licenses. + +OCI, Pro*C, et. al. only requires you to have a development license, +per developer. The compiled apps can be distributed unlimited. +The client where the client app resides must be licensed to use +sqlnet, by the above terms, i.e. by virtue of what the licenses on +the server are that the client is connecting to. + +This means one could legitimately distribute DBD-Oracle in compiled form. +Probably not recommended :-) + +But is does mean one can compile DBD-Oracle and distribute it internally +to your org without more licensing, as long as the targets have sqlnet. + +Obviously, this is not a legal ruling. I don't work for Oracle. +But this is what my sales rep tells me as of today. + +Mark +------------------------------------------------------------------------------- diff --git a/README.help b/README.help new file mode 100644 index 00000000..49981d0f --- /dev/null +++ b/README.help @@ -0,0 +1,307 @@ +=============================================================================== +Platform or Oracle Version specific notes, hints, tips etc: + +Note that although some of these refer to specific systems and versions the +same or similar problems may exist on other systems or versions. + +------------------------------------------------------------------------------- +Assorted runtime problems are caused by Oracle version mismatches: + +If you have problems then ensure that the version of Oracle you are +talking to is the same one you used to build your DBD::Oracle module. + +------------------------------------------------------------------------------- +Can't find libclntsh.so at run time: + +Dave Moellenhoff : libclntsh.so is the shared +library composed of all the other Oracle libs you used to have to +statically link. Oracle didn't start providing it until 7.2 and later. +libclntsh.so should be in $ORACLE_HOME/lib. If it's missing, try +running $ORACLE_HOME/rdbms/lib/genclntsh.sh and it should create it. + +Also: Never copy libclntsh.so to a different machine or Oracle version. +If DBD::Oracle was built on a machine with a different path to libclntsh.so +then you'll need to set set an environment variable, typically +LD_LIBRARY_PATH, to include the directory containing libclntsh.so. + +But: LD_LIBRARY_PATH is typically ignored if the script is running set-uid +(which is common in some httpd/CGI configurations). In this case +either rebuild with LD_RUN_PATH set to include the path to libclntsh +or create a symbolic link so that libclntsh is available via the same +path as it was when the module was built. (On Solaris the command +"ldd -s Oracle.so" can be used to see how the linker is searching for it.) + + +------------------------------------------------------------------------------- +Error while trying to retrieve text for error ...: + +From Lou Henefeld : We discovered that we needed +some files from the $ORACLE_HOME/ocommon/nls/admin/data directory: + lx00001.nlb, lx10001.nlb, lx1boot.nlb, lx20001.nlb +If your national language is different from ours (American English), +you will probably need different nls data files. + + +------------------------------------------------------------------------------- +ORA-01019: unable to allocate memory in the user side + +From Ethan Tuttle : My experience: ORA-01019 errors +occur when using Oracle 7.3.x shared libraries on a machine that +doesn't have all necessary Oracle files in $ORACLE_HOME. + +It used to be with 7.2 libraries that all one needed was the tnsnames.ora +file for a DBD-Oracle client to connect. Not so with 7.3.x. I'm not sure +exactly which additional files are needed on the client machine. + +Furthermore, from what I can tell, the path to ORACLE_HOME is resolved and +compiled into either libclntsh.so or the DBD-Oracle. Thus, copying a +minimal ORACLE_HOME onto a client machine won't work unless the path to +ORACLE_HOME is the same on the client machine as it is on the machine +where DBD-Oracle was compiled. + +ORA-01019 can also be caused by corrupt Oracle config files such as +/etc/oratab. + +Also try building with oracle.mk if your DBD::Oracle defaulted to proc.mk. + +------------------------------------------------------------------------------- +Login takes a long time + +Try connect('', 'user/passwd@tnsname', ''). See README.login. + +------------------------------------------------------------------------------- +AIX - warnings like these when building perl are not usually a problem: + +ld: 0711-415 WARNING: Symbol Perl_sighandler is already exported. +ld: 0711-319 WARNING: Exported symbol not defined: Perl_abs_amg + +When building on AIX check to make sure that all of bos.adt (13 pieces) +and all of bos.compat (11 pieces) are installed. + +Thanks to Mike Moran for this information. + +------------------------------------------------------------------------------- +AIX 4 - core dump on login and similar problems + +set + cc='xlc_r' +in config.sh. Rebuild everything, and make sure xlc_r is used everywhere. +set environment + ORACCENV='cc=xlc_r'; export ORACCENV +to enforce this in oraxlc + +Thanks to Goran Thyni for this information. + +------------------------------------------------------------------------------- +HP-UX: General + +HP's bundled C compiler is dumb. Very dumb. You're almost bound to have +problems if you use it - you'll certainly need to do a 'static link' +(see elsewhere). It is recommended that you use HP's ANSI C compiler +(which costs) fetch and build the free GNU GCC compiler (v2.7.2.2 or later). + +Note that using shared libraries on HP-UX 10.10 (and others?) requires +patch 441647. With thanks to John Liptak . + +------------------------------------------------------------------------------- +HP-UX: Terry Greenlaw + +I traced a problem with "ld: Invalid loader fixup needed" to the file +libocic.a. On HP-UX 9 it contains position-dependant code and cannot be +used to generate dynamic load libraries. The only shared library that +Oracle ships under HP-UX is liboracle.sl which replaces libxa.a, +libsql.a, libora.a, libcvg.a, and libnlsrtl.a. The OCI stuff still +appears to only link statically under HU-UX 9.x [10.x seems okay]. + +You'll need to build DBD::Oracle statically linked into the perl binary. +See the static linking notes below. + +If you get an error like: Bad magic number for shared library: Oracle.a +You'll need to build DBD::Oracle statically linked into the perl binary. + +HP-UX 10 and Oracle 7.2.x do work together when creating dynamic libraries. +The problem was older Oracle libraries were built without the +z flag to cc, +and were therefore position-dependent libraries that can't be linked +dynamically. Newer Oracle releases don't have this problem and it may be +possible to even use the newer Oracle libraries under HP-UX 9. Oracle 7.3 +will ONLY work under HP-UX 10, however. + +HP-UX 10 and Oracle 7.3.x seem to have problems. You'll probably need +to build DBD::Oracle statically linked (see below). The problem seems +to be related to Oracle's own shared library code trying to do a +dynamic load (from lxfgno() in libnlsrtl3.a or libclntsh.sl). If you +get core dumps on login try uncommenting the /* #define signed */ line +in Oracle.h as a long-shot. Please let me know if this fixes it for you +(but I doubt it will). + +------------------------------------------------------------------------------- +For platforms which require static linking. + +You'll need to build DBD::Oracle statically linked and then link it +into a perl binary: + + perl Makefile.PL LINKTYPE=static + make + make perl (makes a perl binary in current directory) + make test FULLPERL=./perl (run tests using the new perl binary) + make install + +You will probably need to have already built and installed a static +version of the DBI in order that it be automatically included when +you do the 'make perl' above. + +Remember that you must use this new perl binary to access Oracle. + +------------------------------------------------------------------------------- +Error: Can't find loadable object for module DBD::Oracle in @INC ... + +You probably built DBD::Oracle for static linking rather than dynamic +linking. See 'For platforms which require static linking' above for +more info. If your platform supports dynamic linking then try to work +out why DBD::Oracle got built for static linking. + +------------------------------------------------------------------------------- +Error: Syntax error in oratypes.h + +Try uncommenting the '#define signed' line in Oracle.h + +------------------------------------------------------------------------------- +ORA-00900: invalid SQL statement "begin ... end" + +You probably don't have PL/SQL Oracle properly/fully installed. + +------------------------------------------------------------------------------- +Oracle 7.1 and 7.2: Connection takes a long time and may coredump + +Oracle bug number: 227321 related to changing the environment before +connecting to oracle. + +To work around this bug, do not set any environment variables in your +oraperl script before you call ora_login, and when you do call +ora_login, the first argument must be the empty string. This means +that you have to be sure that your environment variables ORACLE_SID +and ORACLE_HOME are set properly before you execute any oraperl +script. It is probably also possible to pass the SID to ora_login as +part of the username (for example, ora_login("", "SCOTT/TIGER@PROD", +"")), although I have not tested this. +This workaround is based on information from Kevin Stock. + +------------------------------------------------------------------------------- +Oracle 7.1.4/5: ORA-01002: fetch out of sequence + +Edited from Message-ID: <3qaui9$ae@usenet.rpi.edu> and +<3qb5dp$2nc@usenet.rpi.edu> in comp.databases.oracle +From: finkej@ts.its.rpi.edu (Jon Finke) + +Every test run results in an "ORA-01002: fetch out of sequence" error. + +The manual claims that this is the result of calling "ofetch" before +oparse/oexec, or running out of things to fetch. Yet, I am calling +oopen, oparse, oexec, (odesc, odefin) all without error. As a control +case, I also built the cdemo2 program, and it appears to be calling +the same routines, yet it is successful. + +Note: In the "broken" program, I am currently calling odsc in a loop + for each column in the query, and then calling odefin, while in the + "working" program, I call odescr/odefin, odesc/odefin for each column. + In both cases, the calls to odefin seem reasonable. + +Both programs are attempting the query "select user,uid from dual". + +This is a known problem in version 7.1.4, and it will be fixed in 7.1.6. +The Oracle bug report is #239128. + +------------------------------------------------------------------------------- +Error: ORA-00604: error occurred at recursive SQL level (DBD: login failed) + +This can happen if TWO_TASK is defined but you connect using ORACLE_SID. + +------------------------------------------------------------------------------- +Error: ld: Undefined symbols _environ _dlopen _dlclose ... +Environment: SunOS 4.1.3, Oracle 7.1.6 Steve Livingston + +If you get link errors like: ld: Undefined symbols _environ _dlopen _dlclose ... +and the link command line includes '-L/usr/5lib -lc' then comment out the +'CLIBS= $(OTHERLIBS) -L/usr/5lib -lc' line in the Makefile. + +------------------------------------------------------------------------------- +Error: fatal: relocation error: symbol not found: main +Environment: Solaris, GCC + +Do not use GNU as or GNU ld on Solaris. Delete or rename them, they are +just bad news. In the words of John D Groenveld : +Run, dont walk, to your console and 'mv /opt/gnu/bin/as /opt/gnu/bin/gas; +mv /opt/gnu/bin/ld /opt/gnu/bin/gld'. You can add -v to the gcc command +in the Makefile to see what GCC is using. + +------------------------------------------------------------------------------- +Error: relocation error:symbol not found:setitimer +Environment: SVR4, stephen.zander@mckesson.com + +Error: can't load ./blib/arch/auto/DBD/Oracle/Oracle.so for module DBD::Oracle: +DynamicLinker:/usr/local/bin/perl:relocation error:symbol not found:setitimer +Fix: Try adding the '-lc' to $ORACLE_HOME/rdbms/lib/sysliblist (just +make sure it's not on a new line). + +------------------------------------------------------------------------------- +Error: Undefined symbols __cg92_used at link time. +Environment: Solaris, GCC + +Fix: If you're compiling Oracle applications with gcc on Solaris you need to +link with a file called $ORACLE_HOME/lib/__fstd.o. If you compile with the +SparcWorks compiler you need to add the command line option on -xcg92 +to resolve these symbol problems cleanly. + +Alligator Descartes + +------------------------------------------------------------------------------- +Environment: SunOS 4.1.3, Oracle 7.1.3 John Carlson + +Problem: oraperl and DBD::Oracle fail to link. Some messing around with +the library order makes the link succeed. Now I get a "Bad free()" when +ora_logoff is called. + +Solution: +In my case, this was caused by a faulty oracle install. The install grabbed +the wrong version of mergelib (The X11R6 one) instead of the one in +$ORACLE_HOME/bin. Try a more limited path and reinstall Oracle again. + +------------------------------------------------------------------------------- +Environment: SGI IRIX 6 - Mark Duffield + +Oracle only supports "-32" and "-mips2" compilation flags, not "-n32". +Configure and build perl with -32 flag (see hints/irix_6.sh file). +Rebuild DBI (which will now use the -32 flag). +Rebuild DBD::Oracle (which will now use the -32 flag). + +Since IRIX depends on the perl executable in /usr/sbin, you'll have to +keep it around along with the one you just built. Some care will need +to be taken to make sure that you are getting the right perl, either +through explicitly running the perl you want, or with a file header in +your perl file. The file header is probably the better solution of the two. + +In summary, until Oracle provides support for either the "-n32" or the "-64" +compiler switches, you'll have to have a perl, DBI, and DBD-Oracle which are +compiled and linked "-32". I understand that Oracle is working on a 64bit +versions of V7.3.3 for SGI (or MIPS ABI as they call it), but I don't have +any firm dates. + +------------------------------------------------------------------------------- +Environment: DEC Alpha, OSF, Jonathan Olson + +Problem: ERROR EVENT: DBI::dr=HASH(0x14011fee8)->DBI::default_handler: + 0 ORA-00000: normal, successful completion (DBD: login failed) + +Solution: Add '#define A_OSF' to Oracle.h above '#include ' and +complain to Oracle about bugs in their header files on 64 bit systems. + +------------------------------------------------------------------------------- +Some runtime problems might be related to perl's malloc. + +This is a long shot. If all else fails and perl -V:usemymalloc says +usemymalloc='y' then try rebuilding perl using Configure -Uusemymalloc. +If this does fix it for you then please let me know. + +=============================================================================== + +End. diff --git a/README.login b/README.login index a24d30ce..33c2d56b 100644 --- a/README.login +++ b/README.login @@ -1,81 +1,2 @@ -Using Oracle environment variables with sqlplus and Perl. ---------------------------------------------------------- - -sqlplus -------- - -ORACLE_SID is really unnecessary to set since TWO_TASK provides the -same functionality in addition to allowing remote connections. - -% setenv TWO_TASK T:hostname:ORACLE_SID -% sqlplus username/password - -Note that if you have *both* local and remote databases, and you -have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully -qualified connect string on the command line, TWO_TASK takes precedence -over ORACLE_SID (i.e. you get connected to remote system). - -TWO_TASK = P:sid will use the pipe driver for local connections -SQL*Net 1.x - -TWO_TASK = T:machine:sid will use TCP/IP (or D for DECNET, etc.) for -remote SQL*Net 1.x conn. - -TWO_TASK = dbname will use the info stored in the SQL*Net 2.x -configuration file for local or remote connections. - -ORACLE_HOME can also be left unset if you aren't using any of Oracle's -executables, but error messages may not display. - -Discouraging the use of ORACLE_SID makes it easier on the users to see -what is going on. I just wish that TWO_TASK could be renamed, since it -makes no sense to the end user, and doesn't have the ORACLE prefix on -it. - -Perl with DBI/DBD ------------------ - -Below are various ways of connecting to an oracle database using -SQL*Net 1.x and SQL*Net 2.x. "Machine" is the computer the database is -running on, "SID" is the SID of the database, "DB" is the SQL*Net 2.x -connection descriptor for the database. - - BEGIN { - $ENV{TWO_TASK}='DB'; - $ENV{ORACLE_HOME} = '/home/oracle/product/7.x.x'; - } - ora_login('','scott/tiger'); - -works here for SQL*Net 2.x, as does - - BEGIN { - $ENV{TWO_TASK}='T:Machine:SID'; - $ENV{ORACLE_HOME} = '/home/oracle/product/7.x.x'; - } - ora_login('','scott/tiger'); - -for SQL*Net 1.x connections. - -For local connections use 'P:SID'. - -login variations (not setting TWO_TASK) ----------------------------------------- - -$lda = ora_login('T:Machine:SID','username','password'); - -$lda = ora_login('','username@T:Machine:SID','password'); - -$lda = ora_login('','username@DB','password'); - -$lda = ora_login('DB','username','password'); - -$lda = ora_login('DB','username/password',''); - -With thanks to James Taylor . - -If you are having problems with login taking a long time (>10 secs say) -then try using one of the ...@DB variants. E.g., - - $lda = ora_login('','username/password@DB',''); - -Tim. +This information is now in the DBD::Oracle module pod documentation. +Use the 'perldoc DBD::Oracle' command to read it. diff --git a/README.longs b/README.longs index 10f70568..96e92bab 100644 --- a/README.longs +++ b/README.longs @@ -1,5 +1,26 @@ Some examples related to the use of LONG types. +---------------------------------------------------------------------- + +You must fetch the row before you can fetch the longs associated with +that row. In other words, use the following alorithm... + + 1) login + 2) prepare( select ... ) + 3) execute + 4) while rows to fetch do + 5) fetch row + 6) repeat + 7) fetch chunk of long + 8) until have all of it + 9) done + +If your select selects more than one row the need for step 4 may +become a bit clearer... the blob_read always applies to the row +that was last fetched. + +Thanks to Jurgen Botz + ---------------------------------------------------------------------- Example for reading LONG fields via blob_read: @@ -8,12 +29,14 @@ Example for reading LONG fields via blob_read: ora_bind($csr, $id) or die $ora_errstr; # ora_fetch() needs to be called in an array context my (@data) = ora_fetch($csr); + die $ora_errstr if $ora_errno; my $blob = ''; my $lump = 4096; # use benchmarks to get best value for you my $offset = 0; while (1) { my $frag = $csr->blob_read(0, $offset, $lump); + die $ora_errstr if $ora_errno; last unless defined $frag; my $ll = length $frag; last unless $ll; diff --git a/README.plsql b/README.plsql new file mode 100644 index 00000000..126301ca --- /dev/null +++ b/README.plsql @@ -0,0 +1,6 @@ +See t/plsql.t for lots of examples. + +begin dbms_output.enable(); end; +begin dbms_output.put_line(:thing); end; +begin dbms_output.get_line(:buffer, :status); end; + diff --git a/README.win32 b/README.win32 new file mode 100644 index 00000000..04e33f24 --- /dev/null +++ b/README.win32 @@ -0,0 +1,25 @@ +4/8/97 -- Jeff Urlwin + +This version requires Perl 5.003_94 or later. (It was tested with +5.003_94 and will be with 5.004). It does *NOT* work with the +(non-standard) ActiveWare port. + +Even though the Oracle libraries under Win32 (NT) do not require the +environment variable ORACLE_HOME be set for proper operation, the +Makefile.PL does. Please set the ORACLE_HOME variable to your oracle +home directory. Mine, for example, is H:\ORANT. + +This version was created and tested with the 7.3 client libraries (see +if you have an OCI73 directory). This version of the Oracle clients +have a convenient organization, including OCI73\INCLUDE, OCI73\LIB, +etc. It also has a nice samples directory to test with. Older +versions had the OCI samples under RDMBS72. This version has not been +tested (and will not currently work) with anything other than the 7.3 +versions. + +Questions should be directed towards the dbi-users mailing list. I will +try to answer them quickly there. Please put something about Win32 or +95 or NT in the subject, as I get TONS of other email and spend a fair +amount of time weeding out messages that are not relevant to what I +do. I may miss something if the subject is not clear. + diff --git a/Todo b/Todo index 7fe2878e..a17d34d1 100644 --- a/Todo +++ b/Todo @@ -1,3 +1,9 @@ +Handle binding of values > 32K long. + +Handle PL/SQL arrays. + +Handle PL/SQL returned cursor variables. + =============================================================================== General Outstanding Issues diff --git a/dbdimp.c b/dbdimp.c index b5f1759e..580ac588 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,10 +1,12 @@ /* - $Id: dbdimp.c,v 1.29 1997/01/14 21:48:19 timbo Exp $ + $Id: dbdimp.c,v 1.31 1997/06/14 17:42:12 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce You may distribute under the terms of either the GNU General Public - License or the Artistic License, as specified in the Perl README file. + License or the Artistic License, as specified in the Perl README file, + with the exception that it cannot be placed on a CD-ROM or similar media + for commercial distribution without the prior approval of the author. */ @@ -15,8 +17,12 @@ DBISTATE_DECLARE; static SV *ora_long; static SV *ora_trunc; +static SV *ora_pad_empty; static SV *ora_cache; -static SV *ora_cache_o; /* temp hack for ora_open() cache override */ +static SV *ora_cache_o; /* temp hack for ora_open() cache override */ +static int ora_login_err; /* fetch & show real login errmsg if true */ + +static int autocommit = 0; /* we assume autocommit is off initially */ void @@ -24,10 +30,17 @@ dbd_init(dbistate) dbistate_t *dbistate; { DBIS = dbistate; - ora_long = perl_get_sv("Oraperl::ora_long", GV_ADDMULTI); - ora_trunc = perl_get_sv("Oraperl::ora_trunc", GV_ADDMULTI); - ora_cache = perl_get_sv("Oraperl::ora_cache", GV_ADDMULTI); - ora_cache_o = perl_get_sv("Oraperl::ora_cache_o", GV_ADDMULTI); + ora_long = perl_get_sv("Oraperl::ora_long", GV_ADDMULTI); + ora_trunc = perl_get_sv("Oraperl::ora_trunc", GV_ADDMULTI); + ora_cache = perl_get_sv("Oraperl::ora_cache", GV_ADDMULTI); + ora_cache_o = perl_get_sv("Oraperl::ora_cache_o", GV_ADDMULTI); + + ora_pad_empty= perl_get_sv("Oraperl::ora_pad_empty", GV_ADDMULTI); + if (!SvOK(ora_pad_empty) && getenv("ORAPERL_PAD_EMPTY")) + sv_setiv(ora_pad_empty, atoi(getenv("ORAPERL_PAD_EMPTY"))); + + if (getenv("DBD_ORACLE_LOGIN_ERR")) + ora_login_err = atoi(getenv("DBD_ORACLE_LOGIN_ERR")); } @@ -47,19 +60,19 @@ ora_error(h, lda, rc, what) { D_imp_xxh(h); SV *errstr = DBIc_ERRSTR(imp_xxh); - if (lda) { /* is oracle error (allow for non-oracle errors) */ + sv_setiv(DBIc_ERR(imp_xxh), (IV)rc); /* set err early */ + if (lda) { /* is oracle error (allow for non-oracle errors) */ int len; char msg[1024]; - /* Oracle oerhms can do duplicate free if connect fails */ + /* Oracle oerhms can do duplicate free if connect fails. */ /* Ignore 'with different width due to prototype' gcc warning */ - oerhms(lda, rc, (text*)msg, sizeof(msg)); + oerhms(lda, rc, (text*)msg, sizeof(msg)); /* may hang! */ len = strlen(msg); if (len && msg[len-1] == '\n') msg[len-1] = '\0'; /* trim off \n from end of message */ sv_setpv(errstr, (char*)msg); } else sv_setpv(errstr, what); - sv_setiv(DBIc_ERR(imp_xxh), (IV)rc); if (what && lda) { sv_catpv(errstr, " (DBD: "); sv_catpv(errstr, what); @@ -180,10 +193,28 @@ dbd_db_login(dbh, dbname, uid, pwd) D_imp_dbh(dbh); int ret; - /* can give duplicate free errors (from Oracle) if connect fails */ + /* can give duplicate free errors (from Oracle) if connect fails */ ret = orlon(&imp_dbh->lda, imp_dbh->hda, (text*)uid,-1, (text*)pwd,-1,0); if (ret) { - ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "login failed"); + int rc = imp_dbh->lda.rc; + /* oerhms in ora_error may hang or corrupt memory (!) after a connect */ + /* failure. So we fake the common error messages unless ora_login_err */ + /* is true (set via env var above). Thank Oracle for this sad hack. */ + char buf[100]; + char *msg="ORA-%d: (Text for error %d not fetched. Use 'oerr ORA %d' command.)"; + switch (rc) { + case 1017: msg="ORA-%d: invalid username/password; login denied"; + break; + case 1034: msg="ORA-%d: ORACLE not available"; + break; + case 2700: msg="ORA-%d: osnoraenv: error translating ORACLE_SID"; + break; + case 12154: msg="ORA-%d: TNS:could not resolve service name"; + break; + } + sprintf(buf, msg, rc, rc, rc); + ora_error(dbh, ora_login_err ? &imp_dbh->lda : NULL, rc, + ora_login_err ? "login failed" : buf); return 0; } DBIc_IMPSET_on(imp_dbh); /* imp_dbh set up now */ @@ -249,7 +280,7 @@ dbd_db_destroy(dbh) int -dbd_db_STORE(dbh, keysv, valuesv) +dbd_db_STORE_attrib(dbh, keysv, valuesv) SV *dbh; SV *keysv; SV *valuesv; @@ -267,7 +298,8 @@ dbd_db_STORE(dbh, keysv, valuesv) /* the best we can do is cache an undef */ cachesv = &sv_undef; } else { - cachesv = (on) ? &sv_yes : &sv_no; /* cache new state */ + autocommit = on; + cachesv = boolSV(on); /* cache new state */ } } else { return FALSE; @@ -279,7 +311,7 @@ dbd_db_STORE(dbh, keysv, valuesv) SV * -dbd_db_FETCH(dbh, keysv) +dbd_db_FETCH_attrib(dbh, keysv) SV *dbh; SV *keysv; { @@ -290,9 +322,11 @@ dbd_db_FETCH(dbh, keysv) /* Default to caching results for DBI dispatch quick_FETCH */ int cacheit = TRUE; - if (1) { /* no attribs defined yet */ - return Nullsv; + if (kl==10 && strEQ(key, "AutoCommit")) { + return boolSV(autocommit); } + else + return Nullsv; if (cacheit) { /* cache for next time (via DBI quick_FETCH) */ SV **svp = hv_fetch((HV*)SvRV(dbh), key, kl, 1); sv_free(*svp); @@ -321,6 +355,10 @@ dbd_st_prepare(sth, statement, attribs) imp_sth->done_desc = 0; imp_sth->cda = &imp_sth->cdabuf; + if (DBIc_COMPAT(imp_sth)) { + imp_sth->ora_pad_empty = (SvOK(ora_pad_empty)) ? SvIV(ora_pad_empty) : 0; + } + if (attribs) { SV **svp; DBD_ATTRIB_GET_IV( attribs, "ora_parse_lang", 14, svp, oparse_lng); @@ -361,16 +399,11 @@ dbd_st_prepare(sth, statement, attribs) ; /* XXX perl_call_method to get error text ? */ } - /* long_buflen: length for long/longraw (if >0) */ - /* long_trunc_ok: is truncating a long an error XXX not implemented */ - - if (DBIc_COMPAT(imp_sth)) { /* is an Oraperl handle */ - imp_sth->long_buflen = SvIV(ora_long); - /* ora_trunc is checked at fetch time */ - } else { - imp_sth->long_buflen = 80; /* typical oracle default */ - imp_sth->long_trunc_ok = 1; /* can use blob_read() */ - } + /* long_buflen: length for long/longraw (if >0), else 80 (ora app dflt) */ + /* long_trunc_ok: is truncating a long an error XXX not implemented */ + imp_sth->long_buflen = (SvOK(ora_long) && SvIV(ora_long)>0) ? SvIV(ora_long) : 80; + imp_sth->long_trunc_ok = 1; /* can use blob_read() */ + /* ora_trunc is checked at fetch time */ if (dbis->debug >= 2) fprintf(DBILOGFP, " dbd_st_prepare'd sql f%d (lb %ld, lt %d)\n", @@ -447,7 +480,7 @@ dbd_preparse(imp_sth, statement) phs_tpl.sv = &sv_undef; phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)+namelen+1); hv_store(imp_sth->all_params_hv, start, namelen, phs_sv, 0); - strcpy( ((phs_t*)SvPVX(phs_sv))->name, start); + strcpy( ((phs_t*)(void*)SvPVX(phs_sv))->name, start); /* warn("params_hv: '%s'\n", start); */ } *dest = '\0'; @@ -607,7 +640,7 @@ dbd_describe(h, imp_sth) /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW? */ /* If so we need to implement oraperl truncation hacks. */ /* This may change in a future release. */ - /* Note that dbtype_is_long() returns alternale dbtype to use */ + /* Note that dbtype_is_long() returns alternate dbtype to use */ if ( (dbtype = dbtype_is_long(fbh->dbtype)) ) { fbh->dbsize = long_buflen; fbh->dsize = long_buflen; @@ -660,41 +693,81 @@ _dbd_rebind_ph(sth, imp_sth, phs) imp_sth_t *imp_sth; phs_t *phs; { - if (dbis->debug >= 2) - fprintf(DBILOGFP, "bind %s <== '%.300s' (size %d/%d, ora_type %d)\n", - phs->name, (char*)phs->progv, phs->alen,phs->maxlen, phs->ftype); + STRLEN value_len; - if (phs->alen_incnull) - ++phs->alen; +/* for strings, must be a PV first for ptr to be valid? */ +/* sv_insert +4 */ +/* sv_chop(phs->sv, SvPV(phs->sv,na)+4); XXX */ + + if (dbis->debug >= 2) { + char *text = neatsvpv(phs->sv,0); + fprintf(DBILOGFP, "bind %s <== %s (size %d/%d/%ld, ptype %ld, otype %d)\n", + phs->name, text, SvCUR(phs->sv),SvLEN(phs->sv),phs->maxlen, + SvTYPE(phs->sv), phs->ftype); + } + + /* At the moment we always do sv_setsv() and rebind. */ + /* Later we may optimise this so that more often we can */ + /* just copy the value & length over and not rebind. */ + + if (phs->is_inout) { /* XXX */ + /* phs->sv _is_ the real live variable, it may 'mutate' later */ + /* pre-upgrade high to reduce risk of SvPVX realloc/move */ + (void)SvUPGRADE(phs->sv, SVt_PVNV); + /* ensure room for result, 28 is magic number (see sv_2pv) */ + SvGROW(phs->sv, (phs->maxlen < 28) ? 28 : phs->maxlen+1); + if (imp_sth->ora_pad_empty) + croak("Can't use ora_pad_empty with bind_param_inout"); + } + else { + /* phs->sv is copy of real variable, upgrade to at least string */ + (void)SvUPGRADE(phs->sv, SVt_PV); + } + + /* At this point phs->sv must be at least a PV with a valid buffer, */ + /* even if it's undef (null) */ + /* Here we set phs->progv, phs->indp, and value_len. */ + if (SvOK(phs->sv)) { + phs->progv = SvPV(phs->sv, value_len); + phs->indp = 0; + } + else { /* it's null but point to buffer incase it's an out var */ + phs->progv = SvPVX(phs->sv); + phs->indp = -1; + value_len = 0; + } + if (imp_sth->ora_pad_empty && value_len==0) { + sv_setpv(phs->sv, " "); + phs->progv = SvPV(phs->sv, value_len); + } + phs->sv_type = SvTYPE(phs->sv); /* part of mutation check */ + phs->alen = value_len + phs->alen_incnull; + phs->maxlen = SvLEN(phs->sv)-1; /* avail buffer space */ + + /* ---------- */ /* Since we don't support LONG VAR types we must check */ /* for lengths too big to pass to obndrv as an sword. */ - if (phs->maxlen > SWORDMAXVAL) /* generally 64K */ - croak("Can't bind %s, value is too long (%d bytes, max %d)", - phs->name, phs->maxlen, SWORDMAXVAL); + if (phs->maxlen > MINSWORDMAXVAL) /* generally 32K */ + croak("Can't bind %s, value is too long (%ld bytes, max %d)", + phs->name, phs->maxlen, MINSWORDMAXVAL); if (phs->alen > phs->maxlen) - croak("panic: _dbd_rebind_ph alen %d > maxlen %d", phs->alen,phs->maxlen); - - if (0) { /* old code */ - if (obndrv(imp_sth->cda, (text*)phs->name, -1, - (ub1*)phs->progv, (sword)phs->alen, - phs->ftype, -1, &phs->indp, - (text*)0, -1, -1)) { - D_imp_dbh_from_sth; - ora_error(sth, &imp_dbh->lda, imp_sth->cda->rc, "obndrv failed"); - return 0; - } + croak("panic: _dbd_rebind_ph alen %ld > maxlen %ld", phs->alen,phs->maxlen); + + if (dbis->debug >= 3) { + fprintf(DBILOGFP, "bind %s <== '%.100s' (size %d/%ld, indp %d)\n", + phs->name, phs->progv, phs->alen, (long)phs->maxlen, phs->indp); } - else { - if (obndra(imp_sth->cda, (text *)phs->name, -1, - (ub1*)phs->progv, phs->maxlen, (sword)phs->ftype, -1, - &phs->indp, &phs->alen, &phs->arcode, 0, (ub4 *)0, - (text *)0, -1, -1)) { - D_imp_dbh_from_sth; - ora_error(sth, &imp_dbh->lda, imp_sth->cda->rc, "obndra failed"); - return 0; - } + + if (obndra(imp_sth->cda, (text *)phs->name, -1, + (ub1*)phs->progv, (ub2)phs->maxlen, /* cast reduces max size */ + (sword)phs->ftype, -1, + &phs->indp, &phs->alen, &phs->arcode, 0, (ub4 *)0, + (text *)0, -1, -1)) { + D_imp_dbh_from_sth; + ora_error(sth, &imp_dbh->lda, imp_sth->cda->rc, "obndra failed"); + return 0; } return 1; } @@ -716,11 +789,13 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) char namebuf[30]; phs_t *phs; - if (SvNIOK(ph_namesv) ) { /* passed as a number */ + /* check if placeholder was passed as a number */ + if (SvNIOK(ph_namesv) || (SvPOK(ph_namesv) && isDIGIT(*SvPVX(ph_namesv)))) { name = namebuf; sprintf(name, ":p%d", (int)SvIV(ph_namesv)); name_len = strlen(name); - } else { + } + else { /* use the supplied placeholder name directly */ name = SvPV(ph_namesv, name_len); } @@ -728,37 +803,26 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) croak("Can't bind non-scalar value (currently)"); if (dbis->debug >= 2) - fprintf(DBILOGFP, "bind %s <== '%.200s' (attribs: %s)\n", - name, SvPV(newvalue,na), attribs ? SvPV(attribs,na) : "" ); + fprintf(DBILOGFP, "bind %s <== %s (attribs: %s)\n", + name, neatsvpv(newvalue,0), attribs ? SvPV(attribs,na) : "" ); phs_svp = hv_fetch(imp_sth->all_params_hv, name, name_len, 0); if (phs_svp == NULL) croak("Can't bind unknown placeholder '%s'", name); - phs = (phs_t*)SvPVX(*phs_svp); /* placeholder struct */ + phs = (phs_t*)(void*)SvPVX(*phs_svp); /* placeholder struct */ if (phs->sv == &sv_undef) { /* first bind for this placeholder */ - phs->ftype = 1; /* our default type VARCHAR2 */ + phs->ftype = 1; /* our default type VARCHAR2 */ + phs->maxlen = maxlen; /* 0 if not inout */ + phs->is_inout = is_inout; if (is_inout) { - /* ensure room for result, 28 is magic number (see sv_2pv) */ - I32 grow_len = (maxlen < 28) ? 28 : maxlen+1; + phs->sv = SvREFCNT_inc(newvalue); /* point to live var */ ++imp_sth->has_inout_params; - phs->is_inout = 1; - phs->sv = SvREFCNT_inc(newvalue); - /* pre-upgrade to cut down risks of SvPVX realloc/move */ - (void)SvUPGRADE(phs->sv, SVt_PVNV); - /* ensure we have a string to point oracle at */ - (void)SvPV(phs->sv, na); - SvGROW(phs->sv, grow_len); - phs->progv = SvPVX(phs->sv); /* build array of phs's so we can deal with out vars fast */ if (!imp_sth->out_params_av) imp_sth->out_params_av = newAV(); av_push(imp_sth->out_params_av, SvREFCNT_inc(*phs_svp)); } - else { - phs->sv = newSV(0); - phs->is_inout = 0; - } if (attribs) { /* only look for ora_type on first bind of var */ SV **svp; @@ -778,40 +842,18 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) } /* check later rebinds for any changes */ - else if (is_inout != phs->is_inout) { - croak("Can't change param %s in/out mode after first bind", phs->name); + else if (is_inout || phs->is_inout) { + croak("Can't rebind or change param %s in/out mode after first bind", phs->name); } else if (maxlen && maxlen != phs->maxlen) { - croak("Can't change param %s maxlen (%d->%d) after first bind", - phs->name, phs->maxlen, (int)maxlen); + croak("Can't change param %s maxlen (%ld->%ld) after first bind", + phs->name, phs->maxlen, maxlen); } - - /* At the moment we always do sv_setsv() and rebind. */ - /* Later we may optimise this so that more often we can */ - /* just copy the value & length over and not rebind. */ - - if (!SvOK(newvalue)) { /* undef == NULL */ - phs->indp = -1; - phs->progv = ""; - phs->alen = 0; - phs->maxlen = 0; - } - else { - STRLEN value_len; - phs->indp = 0; - /* XXX need to consider oraperl null vs space issues? */ - if (is_inout) { /* XXX */ - /* point Oracle at the real live variable memory */ - phs->progv = SvPV(phs->sv, value_len); - } - else { - /* point Oracle at the real live variable memory */ - sv_setsv(phs->sv, newvalue); - phs->progv = SvPV(phs->sv, value_len); - } - phs->alen = value_len + phs->alen_incnull; - phs->maxlen = SvLEN(phs->sv); /* avail buffer space */ + if (!is_inout) { /* normal bind to take a (new) copy of current value */ + if (phs->sv == &sv_undef) /* (first time bind) */ + phs->sv = newSV(0); + sv_setsv(phs->sv, newvalue); } return _dbd_rebind_ph(sth, imp_sth, phs); @@ -835,31 +877,38 @@ dbd_st_execute(sth) /* <0 is error, >=0 is ok (row count) */ if (debug >= 2) fprintf(DBILOGFP, - " dbd_st_execute (for sql f%d after oci f%d)...\n", - imp_sth->cda->ft, imp_sth->cda->fc); + " dbd_st_execute (for sql f%d after oci f%d, outs %d)...\n", + imp_sth->cda->ft, imp_sth->cda->fc, outparams); if (outparams) { /* check validity of bound SV's */ int i = outparams; STRLEN phs_len; while(--i >= 0) { - phs_t *phs = (phs_t*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); + phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); /* Make sure we have the value in string format. Typically a number */ /* will be converted back into a string using the same bound buffer */ /* so the progv test below will not trip. */ - if (!SvPOK(phs->sv)) { /* ooops, no string ($var = 42) */ - SvPV(phs->sv, phs_len); /* get a string ("42") */ - phs->alen = phs_len + phs->alen_incnull; +/* XXX needs reworking +call rebind for all changes +consider also case of undef and bind time and not undef at execute +*/ + if (SvOK(phs->sv)) { + if (!SvPOK(phs->sv)) /* ooops, no string ($var = 42) */ + SvPV(phs->sv, phs_len); /* get string ("42"), see progv */ + phs_len = SvCUR(phs->sv) + phs->alen_incnull; + if (phs_len >= 65535) /* alen is only 16 bit. XXX maxlen */ + croak("Placeholder %s value too long",phs->name); + phs->alen = phs_len; + phs->indp = 0; /* mark as not null */ } else { - phs->alen = SvCUR(phs->sv) + phs->alen_incnull; + phs->indp = -1; /* mark as null */ } /* Some checks for mutated storage since we pointed oracle at it. */ - /* XXX Instead of croaking we could rebind (probably will later). */ - if (SvTYPE(phs->sv) != SVt_PVNV) - croak("Placeholder %s value mutated type after bind (now %ld).\n", - phs->name, SvTYPE(phs->sv)); - if (SvPVX(phs->sv) != phs->progv) - croak("Placeholder %s value mutated location after bind.\n", phs->name); + if (SvTYPE(phs->sv) != phs->sv_type || SvPVX(phs->sv) != phs->progv) { + if (!_dbd_rebind_ph(sth, imp_sth, phs)) + croak("Can't rebind placeholder %s", phs->name); + } if (debug >= 2) warn("pre %s = '%s' (len %d)\n", phs->name, SvPVX(phs->sv), phs->alen); } @@ -900,7 +949,7 @@ dbd_st_execute(sth) /* <0 is error, >=0 is ok (row count) */ int i = outparams; STRLEN retlen; while(--i >= 0) { - phs_t *phs = (phs_t*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); + phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); SV *sv = phs->sv; if (phs->indp == 0) { /* is okay */ SvPOK_only(sv); @@ -941,6 +990,7 @@ dbd_st_fetch(sth) D_imp_sth(sth); int debug = dbis->debug; int num_fields; + int ChopBlanks; int i; AV *av; @@ -965,7 +1015,7 @@ dbd_st_fetch(sth) fprintf(DBILOGFP, " dbd_st_fetch no-more-data, rc=%d, rpc=%ld\n", imp_sth->cda->rc, imp_sth->cda->rpc); } - imp_sth->eod_errno = 0; /* let user retry if they want */ + /* further fetches without an execute will arrive back here */ return Nullav; } @@ -979,17 +1029,20 @@ dbd_st_fetch(sth) goto end_of_data; /* else fall through and return the first of the fetched rows */ } - imp_sth->in_cache = imp_sth->cda->rpc - rows_returned; imp_sth->next_entry = 0; + imp_sth->in_cache = imp_sth->cda->rpc - rows_returned; + assert(imp_sth->in_cache > 0); } av = DBIS->get_fbav(imp_sth); num_fields = AvFILL(av)+1; if (debug >= 3) - fprintf(DBILOGFP, " dbd_st_fetch %d fields (cache: %d/%d/%d)\n", - num_fields, imp_sth->next_entry, imp_sth->in_cache, - imp_sth->cache_size); + fprintf(DBILOGFP, " dbd_st_fetch %d fields, rpc %ld (cache: %d/%d/%d)\n", + num_fields, (long)imp_sth->cda->rpc, imp_sth->next_entry, + imp_sth->in_cache, imp_sth->cache_size); + + ChopBlanks = DBIc_has(imp_sth, DBIcf_ChopBlanks); for(i=0; i < num_fields; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i]; @@ -1012,6 +1065,17 @@ dbd_st_fetch(sth) if (rc == 0) { /* the normal case */ sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], fb_ary->arlen[cache_entry]); + /* if ChopBlanks check for Oracle CHAR type (blank padded) */ + if (ChopBlanks && fbh->dbtype == 96) { + char *p = SvEND(sv); + int len = SvCUR(sv); + while(len && *--p == ' ') + --len; + if (len != SvCUR(sv)) { + SvCUR_set(sv, len); + *SvEND(sv) = '\0'; + } + } } else if (rc == 1405) { /* field is null - return undef */ (void)SvOK_off(sv); @@ -1154,7 +1218,7 @@ dbd_st_destroy(sth) hv_iterinit(hv); while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) { if (sv != &sv_undef) { - phs_t *phs_tpl = (phs_t*)SvPVX(sv); + phs_t *phs_tpl = (phs_t*)(void*)SvPVX(sv); sv_free(phs_tpl->sv); } } @@ -1166,7 +1230,7 @@ dbd_st_destroy(sth) int -dbd_st_STORE(sth, keysv, valuesv) +dbd_st_STORE_attrib(sth, keysv, valuesv) SV *sth; SV *keysv; SV *valuesv; @@ -1188,7 +1252,7 @@ dbd_st_STORE(sth, keysv, valuesv) SV * -dbd_st_FETCH(sth, keysv) +dbd_st_FETCH_attrib(sth, keysv) SV *sth; SV *keysv; { @@ -1238,6 +1302,12 @@ dbd_st_FETCH(sth, keysv) while(--i >= 0) av_store(av, i, newSVpv((char*)imp_sth->fbh[i].cbuf,0)); + } else if (kl==8 && strEQ(key, "NULLABLE")) { + AV *av = newAV(); + retsv = newRV(sv_2mortal((SV*)av)); + while(--i >= 0) + av_store(av, i, boolSV(imp_sth->fbh[i].nullok)); + } else { return Nullsv; } diff --git a/dbdimp.h b/dbdimp.h index fed0461b..825a7788 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,10 +1,12 @@ /* - $Id: dbdimp.h,v 1.17 1997/01/14 21:48:19 timbo Exp $ + $Id: dbdimp.h,v 1.18 1997/06/14 17:42:12 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce You may distribute under the terms of either the GNU General Public - License or the Artistic License, as specified in the Perl README file. + License or the Artistic License, as specified in the Perl README file, + with the exception that it cannot be placed on a CD-ROM or similar media + for commercial distribution without the prior approval of the author. */ @@ -45,6 +47,7 @@ struct imp_sth_st { char *statement; /* sql (see sth_scan) */ HV *all_params_hv; /* all params, keyed by name */ AV *out_params_av; /* quick access to inout params */ + int ora_pad_empty; /* convert ""->" " when binding */ /* Select Column Output Details */ int done_desc; /* have we described this sth yet ? */ @@ -80,9 +83,9 @@ struct imp_fbh_st { /* field buffer EXPERIMENTAL */ /* Oracle's description of the field */ sb4 dbsize; - sb2 dbtype; - sb1 *cbuf; /* ptr to name of select-list item */ - sb4 cbufl; /* length of select-list item name */ + sb2 dbtype; /* actual type of field (see ftype) */ + sb1 *cbuf; /* ptr to name of select-list item */ + sb4 cbufl; /* length of select-list item name */ sb4 dsize; /* max display size if field is a char */ sb2 prec; sb2 scale; @@ -100,14 +103,17 @@ struct phs_st { /* scalar placeholder EXPERIMENTAL */ sword ftype; /* external OCI field type */ SV *sv; /* the scalar holding the value */ + int sv_type; /* original sv type at time of bind */ + bool is_inout; + + IV maxlen; /* max possible len (=allocated buffer) */ + /* these will become an array */ sb2 indp; /* null indicator */ char *progv; ub2 arcode; ub2 alen; /* effective length ( <= maxlen ) */ - ub2 maxlen; /* max possible len (=allocated buffer) */ - bool is_inout; int alen_incnull; /* 0 or 1 if alen should include null */ char name[1]; /* struct is malloc'd bigger as needed */ }; @@ -121,8 +127,10 @@ void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); int dbd_describe _((SV *h, imp_sth_t *imp_sth)); int dbd_st_blob_read _((SV *sth, int field, long offset, long len, SV *destrv, long destoffset)); -SV *dbd_st_FETCH _((SV *sth, SV *keysv)); -SV *dbd_db_FETCH _((SV *dbh, SV *keysv)); +int dbd_db_STORE_attrib _((SV *dbh, SV *keysv, SV *valuesv)); +SV *dbd_db_FETCH_attrib _((SV *dbh, SV *keysv)); +int dbd_st_STORE_attrib _((SV *dbh, SV *keysv, SV *valuesv)); +SV *dbd_st_FETCH_attrib _((SV *sth, SV *keysv)); /* end */ diff --git a/t/base.t b/t/base.t index 24e16768..8826ea12 100755 --- a/t/base.t +++ b/t/base.t @@ -13,6 +13,7 @@ print "ok 2\n"; $switch = DBI->internal; (ref $switch eq 'DBI::dr') ? print "ok 3\n" : print "not ok 3\n"; +# This is a special case. install_driver should not normally be used. $drh = DBI->install_driver('Oracle'); (ref $drh eq 'DBI::dr') ? print "ok 4\n" : print "not ok 4\n"; diff --git a/t/plsql.t b/t/plsql.t new file mode 100644 index 00000000..8c377bd4 --- /dev/null +++ b/t/plsql.t @@ -0,0 +1,145 @@ +#!/usr/local/bin/perl -w + +sub ok ($$;$) { + my($n, $ok, $warn) = @_; + ++$t; + die "sequence error, expected $n but actually $t" + if $n and $n != $t; + ($ok) ? print "ok $t\n" : print "not ok $t\n"; + if (!$ok && $warn) { + $warn = $DBI::errstr if $warn eq '1'; + warn "$warn\n"; + } +} + +use DBI; + +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dbh = DBI->connect('', $dbuser, '', 'Oracle'); + +unless($dbh) { + warn "Unable to connect to Oracle ($DBI::errstr)\n"; + print "1..0\n"; + exit 0; +} + +print "1..$tests\n"; + +my($csr, $p1, $p2); + + +# --- test raising predefined exception +ok(0, $csr = $dbh->prepare(q{ + begin RAISE INVALID_NUMBER; end; +}), 1); + +# ORA-01722: invalid number +ok(0, ! $csr->execute, 1); +ok(0, $DBI::err == 1722); + + +# --- test raising user defined exception +ok(0, $csr = $dbh->prepare(q{ + DECLARE FOO EXCEPTION; + begin raise FOO; end; +}), 1); + +# ORA-06510: PL/SQL: unhandled user-defined exception +ok(0, ! $csr->execute, 1); +ok(0, $DBI::err == 6510); + + +# --- test raise_application_error with literal values +ok(0, $csr = $dbh->prepare(q{ + begin RAISE_APPLICATION_ERROR(-20101,'app error'); end; +}), 1); + +# ORA-20101: app error +ok(0, ! $csr->execute, 1); +ok(0, $DBI::err == 20101); +ok(0, $DBI::errstr =~ m/app error/); + + +# --- test raise_application_error with 'in' parameters +ok(0, $csr = $dbh->prepare(q{ + declare err_num number; err_msg char(510); + begin + err_num := :1; + err_msg := :2; + raise_application_error(-20000-err_num, 'msg is '||err_msg); + end; +}), 1); + +ok(0, ! $csr->execute(42, "hello world"), 1); +ok(0, $DBI::err == 20042, $DBI::err); +ok(0, $DBI::errstr =~ m/msg is hello world/, 1); + + +# --- test named numeric in/out parameters +ok(0, $csr = $dbh->prepare(q{ + begin + :arg := :arg * 2; + end; +}), 1); + +$p1 = 3; +ok(0, $csr->bind_param_inout(':arg', \$p1, 100), 1); +ok(0, $csr->execute, 1); +ok(0, $p1 == 6); +# execute 10 times from $p1=1, 2, 4, 8, ... 1024 +$p1 = 1; foreach (1..10) { $csr->execute || die $DBI::errstr; } +ok(0, $p1 == 1024); + + +# --- test named string in/out parameters +ok(0, $csr = $dbh->prepare(q{ + declare str varchar2(1000); + begin + :arg := nvl(nls_upper(:arg), 'null'); + :arg := :arg || '!'; + end; +}), 1); + +undef $p1; +$p1 = "hello world"; +ok(0, $csr->bind_param_inout(':arg', \$p1, 1000), 1); +ok(0, $csr->execute, 1); +ok(0, $p1 eq "HELLO WORLD!"); +# execute 10 times growing $p1 to force realloc +foreach (1..10) { + $p1 .= " xxxxxxxxxx"; + $csr->execute || die $DBI::errstr; +} +my $expect = "HELLO WORLD!" . (" XXXXXXXXXX!" x 10); +ok(0, $p1 eq $expect); + + +# --- test binding a null and getting a string back +undef $p1; +ok(0, $csr->execute, 1); +ok(0, $p1 eq 'null!'); + + +# --- test plsql_errstr +ok(0, $csr = $dbh->prepare(q{ + create or replace package doit as + procedure filltab( stuff out tab ); asdf + end doit; +}), 1); +my $msg = $dbh->func('plsql_errstr'); +ok(0, $msg =~ /Encountered the symbol/, $msg); + + + # To do + # test NULLs at first bind + # NULLS later binds. + # returning NULLS + # multiple params, mixed types and in only vs inout + + +$csr->finish; +$dbh->disconnect; +exit 0; +BEGIN { $tests = 28 } +# end. + diff --git a/test.pl b/test.pl index d969d1b9..a60f2486 100755 --- a/test.pl +++ b/test.pl @@ -1,8 +1,10 @@ #!/usr/local/bin/perl -w +use ExtUtils::testlib; + die "Use 'make test' to run test.pl\n" unless "@INC" =~ /\bblib\b/; -# $Id: test.pl,v 1.29 1997/01/14 21:48:19 timbo Exp $ +# $Id: test.pl,v 1.30 1997/06/14 17:42:12 timbo Exp $ # # Copyright (c) 1995, Tim Bunce # @@ -12,10 +14,11 @@ require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.29 $}."\n"; +print q{Oraperl test application $Revision: 1.30 $}."\n"; $SIG{__WARN__} = sub { - ($_[0] =~ /^Bad free/) ? warn "See README about Bad free() warnings!\n": warn @_; + ($_[0] =~ /^(Bad|Duplicate) free/) + ? warn "\n*** Read the README file about Bad free() warnings!\n": warn @_; }; $opt_d = 0; # debug @@ -23,8 +26,7 @@ $opt_n = 5; # num of loops $opt_m = 0; # count for mem leek test $opt_c = 1; # do cache test -$opt_p = 1; # test pl/sql code -&Getopts('m:d:n:clp ') || die "Invalid options\n"; +&Getopts('m:d:n:cl ') || die "Invalid options\n"; $ENV{PERL_DBI_DEBUG} = 2 if $opt_d; $ENV{ORACLE_HOME} = '/usr/oracle' unless $ENV{ORACLE_HOME}; @@ -68,7 +70,7 @@ $start = time; rename("test.log","test.olog") if $opt_l; -eval 'DBI->internal->{DebugLog} = "test.log";' if $opt_l; +eval 'DBI->_debug_dispatch(3,"test.log");' if $opt_l; &test3($opt_m) if $opt_m; @@ -92,8 +94,6 @@ &test_cache() if $opt_c; -&test_plsql() if $opt_p; - $dur = time - $start; print "\nTest complete ($dur seconds).\n"; print "If the tests above have produced the 'expected' output then they have passed.\n"; @@ -241,85 +241,4 @@ sub count_fetch { } -sub test_plsql { - print "\nTesting PL/SQL interaction.\n"; - local($l) = &ora_login($dbname, $dbuser, '') - || die "ora_login: $ora_errno: $ora_errstr\n"; - my $c; - - # $l->debug(2); - $c = &ora_open($l, q{ - begin RAISE invalid_number; end; - }); - # Expect ORA-01722: invalid number - die "ora_open: $ora_errstr" unless $ora_errno == 1722; - - $c = &ora_open($l, q{ - DECLARE FOO EXCEPTION; - begin raise foo; end; - }); - # Expect ORA-06510: PL/SQL: unhandled user-defined exception - die "ora_open: $ora_errstr" unless $ora_errno == 6510; - - $c = &ora_open($l, q{ - begin raise_application_error(-20101,'app error'); end; - }); - # Expect our exception number and error text - die "ora_open: $ora_errno $ora_errstr" - unless $ora_errno == 20101; # our exception number - die "ora_open: $ora_errstr" - unless $ora_errstr =~ m/app error/; # our exception text - - $c = &ora_open($l, q{ - declare err_num number; err_msg char(510); - begin - err_num := :1; - err_msg := :2; - raise_application_error(-20000-err_num, 'plus '||err_msg); - end; - }) || die "ora_open: $ora_errstr"; - $c->execute(42,"my msg"); - # Expect our exception number and error text - die "ora_open: $ora_errno $ora_errstr" - unless $ora_errno == 20042; # our exception number - die "ora_open: $ora_errstr" - unless $ora_errstr =~ m/plus my msg/; # our exception text - - print "Testing numeric bind_param_inout. Expect '200', '3800', '75800':\n"; - #$l->debug(2); - #DBI->internal->{DebugDispatch} = 2; - $c = &ora_open($l, q{ - declare bar number; - begin bar := :1; bar := bar * 20; :1 := bar; end; - }) || die "ora_open: $ora_errstr"; - $param = 10; - $c->bind_param_inout(1, \$param, 100) || die "bind_param_inout $ora_errstr"; - do { - $c->execute || die "execute $ora_errstr"; - print "param='$param'\n"; - $param -= 10; - } while ($param < 70000); - - print "Testing string bind_param_inout. Expect '**foo**':\n"; - #$l->debug(2); - #DBI->internal->{DebugDispatch} = 2; - $c = &ora_open($l, q{ - declare bar varchar2(200); - begin bar := :1; bar := '**'||bar||'**'; :1 := bar; end; - }) || die "ora_open: $ora_errstr"; - $param = "foo"; - $c->bind_param_inout(1, \$param, 100) || die "bind_param_inout $ora_errstr"; - # can be used for force realloc and thus a 'mutated location' error: - # $param = "ffffffffffffffffffffffffffffffffffffffffffffffffoo" x 3; - $c->execute || die "execute $ora_errstr"; - print "param='$param'\n"; - - # To do - # test NULLs at first bind - # NULLS later binds. - # returning NULLS - # multiple params, mixed types and in only vs inout - # automatic rebind if location changes -} - # end. From 4be096f98a1eee892f66ff7aa9d013d02716b8f9 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Fri, 20 Jun 1997 14:22:00 -0500 Subject: [PATCH 024/637] import DBD-Oracle 0.46 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.46 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.46.tar.gz --- Changes | 11 +++- Makefile.PL | 151 ++++++++++++++++++++++++++++++++++------------------ Oracle.pm | 31 +++++------ Oracle.xs | 19 ++++--- Oraperl.pm | 18 ++++--- README | 10 ++-- dbdimp.c | 32 +++++------ t/plsql.t | 11 ++-- test.pl | 21 ++++++++ 9 files changed, 188 insertions(+), 116 deletions(-) diff --git a/Changes b/Changes index 2d96c4de..88f8658e 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,12 @@ -Changes in DBD::Oracle 0.45 (Oraperl 1.32), 16th June 1997 +Changes in DBD::Oracle 0.46 (Oraperl 1.34), 20th June 1997 + + Fixed Makefile.PL to work with 5.004_01. + Some VMS support from Dan Sugalski + If ORACLE_HOME isn't set, Oracle.pm no longer tries to guess it. + bind_param_inout now checks for read-only variables. + Requires DBI 0.84. + +Changes in DBD::Oracle 0.45 (Oraperl 1.33), 16th June 1997 A $dbh DESTROY without an explicit disconnect does a rollback. Note that this may 'break' existing 'lazy' code but is completely @@ -21,6 +29,7 @@ Changes in DBD::Oracle 0.45 (Oraperl 1.32), 16th June 1997 Added some documentation to DBD::Oracle for 'perldoc DBD::Oracle'. + Most tests now converted to standard t/*.t format. Added $sth->{NULLABLE}->[$field]. Added private plsql_errstr method: $txt=$dbh->func('plsql_errstr') to fetch PL/SQL error messages. Thanks to Bob Menteer. diff --git a/Makefile.PL b/Makefile.PL index 5eb58fbe..a2082705 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.53 1997/06/14 17:42:12 timbo Exp $ +# $Id: Makefile.PL,v 1.55 1997/06/20 21:18:11 timbo Exp $ BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -10,13 +10,20 @@ use strict; # Some MakeMaker's forged some FileHandle methods require FileHandle unless defined(&FileHandle::new); +BEGIN { if ($^O eq 'VMS') { + require vmsish; + import vmsish; + require VMS::Filespec; + import VMS::Filespec; +}} + # This DBI must be installed before we can build a DBD. # For those not using Dynamic loading this means building a # new static perl in the DBI directory by saying 'make perl' # and then using _that_ perl to make this one. -use DBI 0.82; +use DBI 0.84; -my $osname = $^O; +my $os = $^O; my $osvers = $Config{osvers}; $osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 @@ -34,15 +41,18 @@ $::opt_p = ''; # prefer oracle.mk over proc $::opt_g = ''; # enable debugging (s/-O/-g/g) $::opt_s = ''; # Find a symbol, Don't build a Makefile $::opt_v = 0; # be more verbose +$::opt_d = 0; # much more verbose for debugging $::opt_old = 0; # old style .mk file parsing -GetOptions(qw(v! g! old! p! m=s s=s)) or die "Invalid arguments"; +GetOptions(qw(v! d! g! old! p! m=s s=s)) or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string +$::opt_v = 1 if $::opt_d; $Verbose = 1 if $::opt_v; # --- Introduction +my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORACLE_ROOT' : 'ORACLE_HOME'; print "\n Configuring DBD::Oracle ...\n >>>\tRemember to actually *READ* the README file! @@ -51,20 +61,18 @@ print "\n Configuring DBD::Oracle ...\n # --- Where is Oracle installed... -die "ORACLE_HOME environment variable must be set.\n" - unless $ENV{ORACLE_HOME}; -my $OH = $ENV{ORACLE_HOME}; -die "ORACLE_HOME environment variable ($OH) not value.\n" - unless -d $OH; +my $OH = $ENV{$ORACLE_ENV}; +die "$ORACLE_ENV environment variable must be set.\n" unless $OH; +die "$ORACLE_ENV environment variable ($OH) not valid.\n" unless -d $OH; + my $OCIDIR = "OCI73"; # For MSWin32. XXX what about 7.4 etc? print "Using Oracle in $OH\n"; my @mkplaces = qw( - rdbms/demo/oracle.mk - proc/lib/proc.mk - precomp/demo/proc/proc.mk + rdbms/lib/oracle.mk rdbms/demo/oracle.mk + proc/lib/proc.mk precomp/demo/proc/proc.mk proc16/lib/proc16.mk ); # if -p then remove oracle.mk from search list, prefer Pro*C @@ -77,7 +85,7 @@ foreach $place (@mkplaces) { last if $mkfile; } if (!$mkfile and "@mkplaces" !~ m/oracle\.mk/) { - warn "Unable to locate a Pro*C *.mk. Falling back to oracle.mk.\n"; + print "Unable to locate a Pro*C *.mk. Falling back to oracle.mk.\n"; $mkfile = "$OH/oracle.mk"; push @mkplaces, $mkfile; # just for error message below } @@ -95,16 +103,16 @@ die qq{ See README.clients for more information and some alternatives. -} unless ($osname eq 'MSWin32') || ($mkfile && -f $mkfile); +} unless ($os eq 'MSWin32') || ($mkfile && -f $mkfile); my(@mkfiles, $linkvia, $libhome, $linkwith, $linkwith_s, @linkwith_o, $OCIINCLUDE); -if ($osname ne 'MSWin32') { +if ($os ne 'MSWin32') { $linkvia = fetch_oci_macros($mkfile); $libhome = expand_mkvars($MK{LIBHOME}, 0, 1, 0) || "$OH/lib"; $linkwith = expand_mkvars($linkvia, 0, 1, 0); $linkwith =~ s/-Y P,/-YP,/g if $Config{'cc'} =~ /gcc/; - $linkwith =~ s:-R /:-R/:g if $osname eq 'solaris'; + $linkwith =~ s:-R /:-R/:g if $os eq 'solaris'; # get a cut down $linkwith to pass to MakeMaker liblist $linkwith_s = expand_mkvars($linkwith, 1, 1, 0); @@ -116,55 +124,56 @@ if ($osname ne 'MSWin32') { push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; if ($::opt_s) { - warn "Searching for symbol '$::opt_s' in $OH ...\n"; + print "Searching for symbol '$::opt_s' in $OH ...\n"; my $dlext = $Config{dlext}; system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; do echo " searching \$i ..."; nm \$i | grep $::opt_s; done }); - warn "Search done.\n"; + print "Search done.\n"; exit; } - if ($osname eq 'solaris' and $osvers >= 2.3 + if ($os eq 'solaris' and $osvers >= 2.3 and $linkwith_s =~ /-lthread/) { - warn "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; - warn "Deleting -lthread from link list as a possible workround.\n"; + print "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; + print "Deleting -lthread from link list as a possible workround.\n"; $linkwith_s =~ s/\s*-lthread\b/ /g; } $OCIINCLUDE = $MK{INCLUDE} || ''; - $opts{LIBS} = [ "-L$libhome $linkwith_s" ]; + $OCIINCLUDE .= " -I$OH/rdbms/demo"; + $opts{LIBS} = [ "-L$libhome $linkwith_s" ] unless $os eq 'VMS'; $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o \$(COMPOBJS)" }; $opts{OBJECT} = '$(O_FILES)'; } else { # MSWin32 # this assumes MSVC... - $OCIINCLUDE = "-I$OH/$OCIDIR/include"; + $OCIINCLUDE = "-I$OH/$OCIDIR/include -I$OH/rdbms/demo"; $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/MSVC/OCIW32.LIB"]; $opts{dynamic_lib} = { OTHERLDFLAGS => " $OH/$OCIDIR/LIB/MSVC/OCIW32.LIB" }; $opts{OBJECT} = '$(O_FILES)'; $opts{SKIP} = ['processPL']; # XXX caused problems with Nmake... } -$opts{INC} = "$OCIINCLUDE -I$OH/rdbms/demo -I\$(INSTALLSITEARCH)/auto/DBI"; +$opts{INC} = "$OCIINCLUDE -I\$(INSTALLSITEARCH)/auto/DBI"; # --- Handle special cases --- # HP-UX 9 cannot link a non-PIC object file into a shared library. # Since the # .a libs that Oracle supplies contain non-PIC object # files, we sadly have to build static on HP-UX 9 :( -if ($osname eq 'hpux' and $osvers < 10) { +if ($os eq 'hpux' and $osvers < 10) { $opts{LINKTYPE} = 'static'; - print "Warning: Forced to build static not dynamic on $osname $osvers.\a\n"; + print "Warning: Forced to build static not dynamic on $os $osvers.\a\n"; print "** Note: DBD::Oracle will be built *into* a NEW perl binary. You MUST use that new perl.\n"; print " See README and Makefile.PL for more information.\a\n"; } -if ($osname eq 'hpux' and $osvers >= 10) { +if ($os eq 'hpux' and $osvers >= 10) { print "Warning: You may need to build using static linking. See the README file.\n\a"; } -if ($osname eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { +if ($os eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { print "Warning: You may need to rebuild perl using the xlc_r compiler.\a\n"; print " You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV\n"; } @@ -174,7 +183,7 @@ $opts{DEFINE} = '-Wall -pedantic -Wno-comment -Wtraditional' $opts{DEFINE} .= '-Xa' if $Config{cc} eq 'clcc'; # CenterLine CC -warn "WARNING: Your GNU C compiler is very old. Please upgrade.\n" +print "WARNING: Your GNU C compiler is very old. Please upgrade.\n" if ($Config{gccversion} and $Config{gccversion} =~ m/^(1|2\.[1-5])/); # Set some private WriteMakefile options if this is 'me' :-) @@ -187,7 +196,7 @@ if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess # log key platform information to help me help you quickly print "System: perl$] @Config{qw(myuname)}\n"; print "Compiler: @Config{qw(cc optimize ccflags)}\n"; -print "Linker: ". (find_bin('ld')||"not found") ."\n"; +print "Linker: ". (find_bin('ld')||"not found") ."\n" unless $os eq 'VMS'; print "Oracle proc.mk would have used these values but we override them:\n"; print " CC: $MK{CC}\n" if $MK{CC}; print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; @@ -208,7 +217,7 @@ sub MY::post_initialize { my $self = shift; if (-f "$Config{installprivlib}/DBD/Oraperl.pm"){ # very old now - warn " + print " Please note: the Oraperl.pm installation location has changed. It was: $Config{installprivlib}/DBD/Oraperl.pm Is now: $Config{installprivlib}/Oraperl.pm @@ -216,7 +225,7 @@ You have an old copy which you should delete when installing this one.\n"; } if ($Config{privlibexp} ne $Config{sitelibexp}) { - warn " + print " Warning: By default new modules are installed into your 'site_lib' directories. Since site_lib directories come after the normal library directories you must delete any old DBD::Oracle files and directories from @@ -224,7 +233,7 @@ your 'privlib' and 'archlib' directories and their auto subdirectories. "; my $find = "find $Config{privlibexp} $Config{archlibexp} "; $find .= "-name 'Oracle*' -print | sort | uniq"; - if (open(FIND, "$find |")) { + if ($os ne 'VMS' and open(FIND, "$find |")) { my @old; while() { next if m:^$Config{sitelibexp}/:; @@ -233,9 +242,9 @@ your 'privlib' and 'archlib' directories and their auto subdirectories. push @old, $_; } close(FIND); - warn "Here's a list of probable old files and directories:\n ", + print "Here's a list of probable old files and directories:\n ", join("\n ",@old),"\n" if @old; - warn "\n"; + print "\n"; } } @@ -258,7 +267,7 @@ sub MY::post_constants { ' ################################################################### # -ORACLE_HOME = '.$ENV{ORACLE_HOME}.' +ORACLE_HOME = '.$OH.' # The following text has been extracted from '."@mkfiles".' @@ -295,7 +304,7 @@ sub fetch_oci_macros { $edit{COMPOBJS} = q{ # Firstly a Solaris specific edit: - del_crtobj() if $osname eq 'solaris'; + del_crtobj() if $os eq 'solaris'; # Delete any object files in COMPOBJS that don't actually exist my $of; @@ -340,17 +349,24 @@ sub fetch_oci_macros { # We always store values into %MK before checking %edit # %edit can edit this in addition to $_ if needed. + my $name; if ($::opt_old) { $MK{$1} = $2 if m/^\s*(\w+)\s*=\s*([\s\S]*)/; + $name = $1; } else { $MK{$1}= $' if m/^\s*(\w+)\s*=\s*/; + $name = $1; } - if ($1 and exists $edit{$1}) { - my $name = $1; + if ($name and exists $edit{$name}) { + my $pre = $_; eval $edit{$name}; # execute code to edit $_ - warn "Edit $name ($edit{$name}) failed: $@\n" if $@; + print "Edit $name ($edit{$name}) failed: $@\n" if $@; + if ($_ ne $pre and $::opt_v) { + $_ ? print "Edited $name definition\n from: $pre\n to: $_\n" + : print "Deleted $name definition: $pre\n"; + } } push(@MK, $_); @@ -363,7 +379,7 @@ sub fetch_oci_macros { if ($MK{LLIBOCIC}) { $linkwith = '$(LLIBOCIC) $(TTLIBS)'; } else { - warn "Warning: Guessing what to link with.\n"; + print "Warning: Guessing what to link with.\n"; $linkwith = '-locic $(TTLIBS)'; # XXX GUESS HACK } } @@ -395,11 +411,11 @@ sub read_inc_file { # soak up while looking for include directives push(@lines, $_), next unless /^\s*include\s+(.*?)\s*$/m; - $file = $1; + my $inc_file = $1; # deal with "include $(ORACLE_HOME)/..." # (can't use expand_mkvars() here) - $file =~ s/\$\(ORACLE_HOME\)/$ENV{ORACLE_HOME}/g; - push(@lines, read_inc_file($file)); + $inc_file =~ s/\$\((ORACLE_HOME|ORACLE_ROOT)\)/$ENV{$ORACLE_ENV}/og; + push(@lines, read_inc_file($inc_file)); } print "Read a total of ".@lines." lines from $file (including inclusions)\n" if $::opt_v; return @lines; @@ -409,33 +425,38 @@ sub read_inc_file { sub expand_shellescape { my($orig, $level) = @_; my $cmd = $orig; - warn "\n$level * Evaluating \`$orig\`\n" if $::opt_v; + print "\n$level * Evaluating \`$orig\`\n" if $::opt_d; # ensure we have no $(...) vars left - strip out undefined ones: $cmd =~ s/\$\((\w+)\)/mkvar("$1", 1, 0, $level+1)/ge; - warn "\n$level * After reducing to \`$cmd\`\n" if $::opt_v and $cmd ne $orig; + print "\n$level * After reducing to \`$cmd\`\n" if $::opt_d and $cmd ne $orig; my $result = `$cmd`; - warn "$level * Returned $result\n\n" if $::opt_v; + print "$level * Returned $result\n\n" if $::opt_d; $result; } sub expand_mkvars { my($string, $strip, $backtick, $level) = @_; local($_) = $string; - warn "$level Expanding $_\n" if $::opt_v; + print "$level Expanding $_\n" if $::opt_d; s/\$\((\w+)\)/mkvar("$1", $strip, $backtick, $level+1)/ge; # can recurse s/`(.*?[^\\])`/expand_shellescape("$1", $level+1)/esg if $backtick; # can recurse s/\s*\\\n\s*/ /g; # merge continuations s/\s+/ /g; # shrink whitespace - warn "$level Expanded $string\n to $_\n\n" if $::opt_v and $_ ne $string; + print "$level Expanded $string\n to $_\n\n" if $::opt_d and $_ ne $string; $_; } sub mkvar { my($var, $strip, $backtick, $level) = @_; my $default = $strip ? '' : "\$($var)"; - warn "$level Variable: $var\n" if $::opt_v; + print "$level Variable: $var\n" if $::opt_d; return '$(LIBHOME)' if $var eq 'LIBHOME' && !$strip; # gets noisy - return $ENV{ORACLE_HOME} if $var eq 'ORACLE_HOME'; - return $default unless exists $MK{$var}; - return expand_mkvars($MK{$var}, $strip, $backtick, $level+1); # can recurse + return $ENV{$ORACLE_ENV} if $var eq 'ORACLE_HOME'; + my $val = $MK{$var}; + if (!defined $val and exists $ENV{$var}) { + $val = $ENV{$var}; + print "Using value of $var from environment: $val\n"; + } + return $default unless defined $val; + return expand_mkvars($val, $strip, $backtick, $level+1); # can recurse } sub find_bin{ @@ -458,6 +479,30 @@ sub find_bin{ $_; } + sub dynamic_lib { + return shift->SUPER::dynamic_lib(@_) unless $os eq 'VMS'; + + # special code for VMS only + my($self, %attribs) = @_; + return '' unless $self->needs_linking(); #might be because of a subdir + return '' unless $self->has_link_code(); + + my $OtherText; + my($otherldflags) = $attribs{OTHERLDFLAGS} || ""; + my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || ""; + my @m; + push @m, "OTHERLDFLAGS = $otherldflags\n"; + push @m, "INST_DYNAMIC_DEP = $inst_dynamic_dep\n"; + push @m, ' +$(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt rtls.opt $(INST_ARCHAUTODIR).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) If F$TrnLNm("PerlShr").eqs."" Then Define/NoLog/User PerlShr Sys$Share:PerlShr.',$Config::Config{'dlext'},' + Lnproc $(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,rtls.opt/Option,$(PERL_INC)perlshr_attr.opt/Option i +'; + push @m, $self->dir_target('$(INST_ARCHAUTODIR)'); + join('',@m); + } + } __END__ diff --git a/Oracle.pm b/Oracle.pm index 5a354425..7e3350dc 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.44 1997/06/14 17:42:12 timbo Exp $ +# $Id: Oracle.pm,v 1.45 1997/06/20 21:18:11 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997 Tim Bunce # @@ -7,10 +7,11 @@ # with the exception that it cannot be placed on a CD-ROM or similar media # for commercial distribution without the prior approval of the author. -my $oracle_home; - require 5.002; +my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORACLE_ROOT' : 'ORACLE_HOME'; +my $oracle_home = $ENV{$ORACLE_ENV}; + { package DBD::Oracle; @@ -18,10 +19,10 @@ require 5.002; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.45'; - my $Revision = substr(q$Revision: 1.44 $, 10); + $VERSION = '0.46'; + my $Revision = substr(q$Revision: 1.45 $, 10); - require_version DBI 0.83; + require_version DBI 0.84; bootstrap DBD::Oracle $VERSION; @@ -34,12 +35,6 @@ require 5.002; return $drh if $drh; my($class, $attr) = @_; - unless ($ENV{'ORACLE_HOME'}){ - foreach(qw(/usr/oracle /opt/oracle /home/oracle /usr/soft/oracle)){ - $oracle_home = $_,last if -d "$_/rdbms/lib"; - } - } - $class .= "::dr"; # not a 'my' since we use it above to prevent multiple drivers @@ -120,9 +115,9 @@ require 5.002; my $orahome = $DBD::Oracle::oratab{$dbname}; if ($orahome) { # is in oratab == is local - warn "Changing ORACLE_HOME for $dbname" - if ($ENV{ORACLE_HOME} and $orahome ne $ENV{ORACLE_HOME}); - $ENV{ORACLE_HOME} = $orahome; + warn "Changing $ORACLE_ENV for $dbname" + if ($ENV{$ORACLE_ENV} and $orahome ne $ENV{$ORACLE_ENV}); + $ENV{$ORACLE_ENV} = $orahome; $ENV{ORACLE_SID} = $dbname; delete $ENV{TWO_TASK}; } @@ -132,10 +127,10 @@ require 5.002; } } - unless($ENV{ORACLE_HOME}) { # last chance... - $ENV{ORACLE_HOME} = $oracle_home if $oracle_home; + unless($ENV{$ORACLE_ENV}) { # last chance... + $ENV{$ORACLE_ENV} = $oracle_home if $oracle_home; my $msg = ($oracle_home) ? "set to $oracle_home" : "not set!"; - warn "ORACLE_HOME $msg\n"; + warn "$ORACLE_ENV $msg\n"; } # create a 'blank' dbh diff --git a/Oracle.xs b/Oracle.xs index 79c0e29c..6708de7d 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -1,5 +1,5 @@ /* - $Id: Oracle.xs,v 1.44 1997/06/14 17:42:12 timbo Exp $ + $Id: Oracle.xs,v 1.45 1997/06/20 21:18:11 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -202,8 +202,10 @@ bind_param_inout(sth, param, value_ref, maxlen, attribs=Nullsv) SV * attribs CODE: DBD_ATTRIBS_CHECK("bind_param_inout", sth, attribs); - if (!SvROK(value_ref)) /* XXX needs better message */ - croak("bind_param_inout needs a reference to the value"); + if (!SvROK(value_ref) || SvTYPE(SvRV(value_ref)) > SVt_PVMG) + croak("bind_param_inout needs a reference to a scalar value"); + if (SvREADONLY(SvRV(value_ref))) + croak(no_modify); ST(0) = dbd_bind_ph(sth, param, SvRV(value_ref), attribs, TRUE, maxlen) ? &sv_yes : &sv_no; @@ -233,12 +235,13 @@ execute(sth, ...) } } retval = dbd_st_execute(sth); - if (retval < 0) - XST_mUNDEF(0); /* error */ - else if (retval == 0) - XST_mPV(0, "0E0"); /* true but zero */ + /* remember that dbd_st_execute must return <= -2 for error */ + if (retval == 0) /* ok with no rows affected */ + XST_mPV(0, "0E0"); /* (true but zero) */ + else if (retval < -1) /* -1 == unknown number of rows */ + XST_mUNDEF(0); /* <= -2 means error */ else - XST_mIV(0, retval); /* typically 1 or rowcount */ + XST_mIV(0, retval); /* typically 1, rowcount or -1 */ void diff --git a/Oraperl.pm b/Oraperl.pm index 535c5229..a62b67e5 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.33 1997/06/14 17:42:12 timbo Exp $ +# $Id: Oraperl.pm,v 1.34 1997/06/20 21:03:56 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -22,10 +22,10 @@ package Oraperl; require 5.002; -use DBI 0.70; +use DBI 0.84; use Exporter; -$VERSION = substr(q$Revision: 1.33 $, 10); +$VERSION = substr(q$Revision: 1.34 $, 10); @ISA = qw(Exporter); @@ -92,14 +92,16 @@ sub _warn { sub ora_login { my($system_id, $name, $password) = @_; - local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local - local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; - DBI->connect($system_id, $name, $password, 'Oracle'); + local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local + local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; + # we still use the old style connect call with an explicit driver + my $dbh = DBI->connect($system_id, $name, $password, 'Oracle'); + return $dbh; } sub ora_logoff { my($dbh) = @_; - local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local - local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; + local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local + local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; $dbh->disconnect(); } diff --git a/README b/README index 70c8582a..10f65e71 100644 --- a/README +++ b/README @@ -82,6 +82,9 @@ Make sure you are using a recent perl 5.003 or preferably 5.004 and make sure it's on your path so you can say 'perl Makefile.PL' and not '/path/to/perl Makefile.PL'. +If you have build/link problems try using "perl Makefile.PL -p". +If that helps then *please* let me know. + Do not hand edit the generated Makefile unless you are completely sure you understand the implications! Always try to make changes via the Makefile.PL command line and/or editing the Makefile.PL. @@ -99,7 +102,7 @@ Others on the dbi-users mailing list probably can. If you have linking problems (errors related to libraries or functions) then you could try forcing a 'static' build using: - make clean + make realclean perl Makefile.PL LINKTYPE=static make make perl (you'll need to use and install _this_ new perl binary) @@ -120,11 +123,12 @@ may take a few days to be processed). Please post details of any problems (or changes you needed to make) to dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. But note... -** IT IS IMPORTANT TO INCLUDE THE FOLLOWING INFORMATION: +** IT IS IMPORTANT TO INCLUDE *ALL* THE FOLLOWING INFORMATION: 1. A complete log of a all steps of the build, e.g.: - perl Makefile.PL (do a make realclean first) + (do a make realclean first) + perl Makefile.PL -v (note the -v for verbose) make make test make test TEST_VERBOSE=1 (only if any of the t/* tests fail) diff --git a/dbdimp.c b/dbdimp.c index 580ac588..80b73187 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.31 1997/06/14 17:42:12 timbo Exp $ + $Id: dbdimp.c,v 1.32 1997/06/20 21:18:11 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -169,18 +169,6 @@ fb_ary_t *fb_ary; -static void -dump_error_status(cda) - struct cda_def *cda; -{ - fprintf(DBILOGFP, - "(rc %ld, v2 %ld, ft %ld, rpc %ld, peo %ld, fc %ld, ose %ld)\n", - (long)cda->rc, (long)cda->v2_rc, (long)cda->ft, (long)cda->rpc, - (long)cda->peo, (long)cda->fc, (long)cda->ose - ); -} - - /* ================================================================== */ int @@ -711,6 +699,8 @@ _dbd_rebind_ph(sth, imp_sth, phs) /* just copy the value & length over and not rebind. */ if (phs->is_inout) { /* XXX */ + if (SvREADONLY(phs->sv)) + croak(no_modify); /* phs->sv _is_ the real live variable, it may 'mutate' later */ /* pre-upgrade high to reduce risk of SvPVX realloc/move */ (void)SvUPGRADE(phs->sv, SVt_PVNV); @@ -748,7 +738,7 @@ _dbd_rebind_ph(sth, imp_sth, phs) /* Since we don't support LONG VAR types we must check */ /* for lengths too big to pass to obndrv as an sword. */ - if (phs->maxlen > MINSWORDMAXVAL) /* generally 32K */ + if (sizeof(sword) < 4 && phs->maxlen > MINSWORDMAXVAL) /* generally 32K */ croak("Can't bind %s, value is too long (%ld bytes, max %d)", phs->name, phs->maxlen, MINSWORDMAXVAL); @@ -761,7 +751,7 @@ _dbd_rebind_ph(sth, imp_sth, phs) } if (obndra(imp_sth->cda, (text *)phs->name, -1, - (ub1*)phs->progv, (ub2)phs->maxlen, /* cast reduces max size */ + (ub1*)phs->progv, (sword)phs->maxlen, /* cast reduces max size */ (sword)phs->ftype, -1, &phs->indp, &phs->alen, &phs->arcode, 0, (ub4 *)0, (text *)0, -1, -1)) { @@ -862,7 +852,7 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) int -dbd_st_execute(sth) /* <0 is error, >=0 is ok (row count) */ +dbd_st_execute(sth) /* <= -2:error, >=0:ok row count, (-1=unknown count) */ SV *sth; { D_imp_sth(sth); @@ -872,7 +862,7 @@ dbd_st_execute(sth) /* <0 is error, >=0 is ok (row count) */ if (!imp_sth->done_desc) { /* describe and allocate storage for results (if any needed) */ if (!dbd_describe(sth, imp_sth)) - return -1; /* dbd_describe already called ora_error() */ + return -2; /* dbd_describe already called ora_error() */ } if (debug >= 2) @@ -910,7 +900,9 @@ consider also case of undef and bind time and not undef at execute croak("Can't rebind placeholder %s", phs->name); } if (debug >= 2) - warn("pre %s = '%s' (len %d)\n", phs->name, SvPVX(phs->sv), phs->alen); + warn(" with %s = '%.100s' (len %d/%d, indp %d, ptype %ld, otype %d)\n", + phs->name, SvPVX(phs->sv), phs->alen, phs->maxlen, + phs->indp, SvTYPE(phs->sv), phs->ftype); } } @@ -926,7 +918,7 @@ consider also case of undef and bind time and not undef at execute if (oexfet(imp_sth->cda, (ub4)imp_sth->cache_size, 0, 0) && imp_sth->cda->rc != 1403 /* other than no more data */ ) { ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexfet error"); - return -1; + return -2; } imp_sth->in_cache = imp_sth->cda->rpc; /* cache loaded */ if (imp_sth->cda->rc == 1403) @@ -935,7 +927,7 @@ consider also case of undef and bind time and not undef at execute else { /* NOT a select */ if (oexec(imp_sth->cda)) { ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexec error"); - return -1; + return -2; } } diff --git a/t/plsql.t b/t/plsql.t index 8c377bd4..106dee44 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -119,13 +119,15 @@ undef $p1; ok(0, $csr->execute, 1); ok(0, $p1 eq 'null!'); +$csr->finish; # --- test plsql_errstr -ok(0, $csr = $dbh->prepare(q{ - create or replace package doit as +ok(0, ! $dbh->prepare(q{ + begin procedure filltab( stuff out tab ); asdf - end doit; + end; }), 1); +ok(0, $dbh->err == 6550); # PL/SQL error my $msg = $dbh->func('plsql_errstr'); ok(0, $msg =~ /Encountered the symbol/, $msg); @@ -137,9 +139,8 @@ ok(0, $msg =~ /Encountered the symbol/, $msg); # multiple params, mixed types and in only vs inout -$csr->finish; $dbh->disconnect; exit 0; -BEGIN { $tests = 28 } +BEGIN { $tests = 29 } # end. diff --git a/test.pl b/test.pl index a60f2486..1c8e040a 100755 --- a/test.pl +++ b/test.pl @@ -65,6 +65,7 @@ warn "Try leaving dbname value empty and set dbuser to name/passwd\@dbname.\n"; die "\nTest aborted.\n"; } + # test_other($l); &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; } $start = time; @@ -241,4 +242,24 @@ sub count_fetch { } +sub test_other { + local($lda) = @_; + #$lda->debug(2); + $lda->{RaiseError} = 1; + local($c) = $lda->prepare(q{ + begin + :a2 := :a1 + 10; + end; + }); + local($p,$q) = (42,43); + $p += 1; $q += 1; + $c->bind_param_inout(':a1', \$p, 100); + $c->bind_param_inout(':a2', \$q, 100); + foreach (1..1000) { + $c->execute || die $c->errstr; + $p += 1; + } + exit 1; +} + # end. From 1309546331ebda0a7159e70ae4bc4a8a3a0ffc66 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Mon, 8 Sep 1997 18:16:42 -0500 Subject: [PATCH 025/637] import DBD-Oracle 0.47 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.47 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.47.tar.gz --- Changes | 14 ++ MANIFEST | 1 - Makefile.PL | 85 ++++++++++--- Oracle.h | 88 +++++-------- Oracle.pm | 220 +++++++++++++++++++++++++++++--- Oracle.xs | 354 ++++----------------------------------------------- Oraperl.pm | 38 ++++-- README | 5 +- README.plsql | 6 - dbdimp.c | 309 ++++++++++++++++++++++++++------------------ dbdimp.h | 61 ++++++--- t/plsql.t | 24 ++-- test.pl | 6 +- 13 files changed, 611 insertions(+), 600 deletions(-) delete mode 100644 README.plsql diff --git a/Changes b/Changes index 88f8658e..1cd6ae98 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,17 @@ +Changes in DBD::Oracle 0.47 (Oraperl 1.XX), XXth June 1997 + + $h->{InactiveDestroy} = 1; now works reliably (with DBI 0.90). + Makefile.PL changed for Oracle8. Thanks to Philippe Vanhaesendonck. + Long params now work. Thanks to Michael Harvey. + (Long params don't yet work for inout params.) + AutoCommit flag now per-dbh. Thanks to Irving Reid. + Fixed panic: _dbd_rebind_ph when binding an undef. + Added $dbh->ping method (for Apache::DBI users). + Some field-level fetch errors didn't cause the fetch to fail + (the field was simply set undef). + LongReadLen now works (if $Oraperl::ora_trunc unset or <= 0) + LongTruncOk now works (for non oraperl mode handle). + Changes in DBD::Oracle 0.46 (Oraperl 1.34), 20th June 1997 Fixed Makefile.PL to work with 5.004_01. diff --git a/MANIFEST b/MANIFEST index db9898a4..1d746b57 100644 --- a/MANIFEST +++ b/MANIFEST @@ -2,7 +2,6 @@ MANIFEST README README.login README.win32 -README.plsql README.clients README.help README.longs diff --git a/Makefile.PL b/Makefile.PL index a2082705..ef382ce6 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,5 +1,6 @@ -# $Id: Makefile.PL,v 1.55 1997/06/20 21:18:11 timbo Exp $ +# $Id: Makefile.PL,v 1.57 1997/09/08 23:12:57 timbo Exp $ +BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs use ExtUtils::MakeMaker 5.16, qw(&WriteMakefile $Verbose); @@ -21,7 +22,8 @@ BEGIN { if ($^O eq 'VMS') { # For those not using Dynamic loading this means building a # new static perl in the DBI directory by saying 'make perl' # and then using _that_ perl to make this one. -use DBI 0.84; +use DBI 0.86; +use DBI::DBD; # DBD creation tools my $os = $^O; my $osvers = $Config{osvers}; @@ -30,8 +32,11 @@ $osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 my %opts = ( NAME => 'DBD::Oracle', VERSION_FROM => 'Oracle.pm', + DIR => [], + clean => { FILES=> 'Oracle.xsi' }, dist => { DIST_DEFAULT=> 'clean distcheck disttest ci tardist', PREOP => '$(MAKE) -f Makefile.old distdir' }, + COMPRESS => 'gzip -v9', SUFFIX => 'gz', ); my(@MK, %MK, $MK); # parsed macros from Oracle's makefiles @@ -52,7 +57,7 @@ $Verbose = 1 if $::opt_v; # --- Introduction -my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORACLE_ROOT' : 'ORACLE_HOME'; +my $ORACLE_ENV = ($os eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; print "\n Configuring DBD::Oracle ...\n >>>\tRemember to actually *READ* the README file! @@ -62,21 +67,23 @@ print "\n Configuring DBD::Oracle ...\n # --- Where is Oracle installed... my $OH = $ENV{$ORACLE_ENV}; +($OH = unixify $OH) =~ s:/$:: if $os eq 'VMS'; die "$ORACLE_ENV environment variable must be set.\n" unless $OH; die "$ORACLE_ENV environment variable ($OH) not valid.\n" unless -d $OH; my $OCIDIR = "OCI73"; # For MSWin32. XXX what about 7.4 etc? + # need to start "looking" for this... print "Using Oracle in $OH\n"; my @mkplaces = qw( - rdbms/lib/oracle.mk rdbms/demo/oracle.mk - proc/lib/proc.mk precomp/demo/proc/proc.mk + rdbms/lib/oracle.mk rdbms/demo/oracle.mk rdbms/demo/demo_rdbms.mk + proc/lib/proc.mk precomp/demo/proc/proc.mk precomp/demo/proc/demo_proc.mk proc16/lib/proc16.mk ); -# if -p then remove oracle.mk from search list, prefer Pro*C -@mkplaces = grep { !m/oracle\.mk\b/ } @mkplaces if $::opt_p; +# if -p then remove oracle.mk from search list and thus prefer Pro*C +@mkplaces = grep { !m/(oracle|rdbms)\.mk\b/ } @mkplaces if $::opt_p; unshift @mkplaces, $::opt_m if $::opt_m; my($mkfile, $place); foreach $place (@mkplaces) { @@ -103,11 +110,11 @@ die qq{ See README.clients for more information and some alternatives. -} unless ($os eq 'MSWin32') || ($mkfile && -f $mkfile); +} unless ($os eq 'MSWin32') || ($os eq 'VMS') || ($mkfile && -f $mkfile); my(@mkfiles, $linkvia, $libhome, $linkwith, $linkwith_s, @linkwith_o, $OCIINCLUDE); -if ($os ne 'MSWin32') { +if ($os ne 'MSWin32' and $os ne 'VMS') { $linkvia = fetch_oci_macros($mkfile); $libhome = expand_mkvars($MK{LIBHOME}, 0, 1, 0) || "$OH/lib"; $linkwith = expand_mkvars($linkvia, 0, 1, 0); @@ -116,8 +123,13 @@ if ($os ne 'MSWin32') { # get a cut down $linkwith to pass to MakeMaker liblist $linkwith_s = expand_mkvars($linkwith, 1, 1, 0); + + # delete problematic crt?.o on solaris + $linkwith_s = del_crtobj($linkwith_s) if $os eq 'solaris'; + # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" $linkwith_s =~ s!([/\w.]+)/lib(\w+).a!-L$1 -l$2!g; + # extract object files, keep for use later push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; # also extract AIX .exp files since they confuse MakeMaker @@ -143,20 +155,41 @@ if ($os ne 'MSWin32') { $OCIINCLUDE = $MK{INCLUDE} || ''; $OCIINCLUDE .= " -I$OH/rdbms/demo"; - $opts{LIBS} = [ "-L$libhome $linkwith_s" ] unless $os eq 'VMS'; + $opts{LIBS} = [ "-L$libhome $linkwith_s" ]; $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o \$(COMPOBJS)" }; $opts{OBJECT} = '$(O_FILES)'; + $opts{INC} = "$OCIINCLUDE -I\$(INSTALLSITEARCH)/auto/DBI"; } -else { # MSWin32 +elsif ($os eq 'MSWin32') { # this assumes MSVC... + # find OCI dir here... + die qq{ + Unable to find required Oracle OCI files for the build. Please check + that you have your OCI installed in your oracle home ($OH) + directory and that it has the following files (and probably more): + + $OH\\$OCIDIR\\include\\oratypes.h + $OH\\$OCIDIR\\lib\\msvc\\ociw32.lib + + Please install OCI or send comments back to dbi-users\@fugue.com you + have an OCI directory other than $OCIDIR. + + } unless (-e "$OH/$OCIDIR/include/oratypes.h" + && -e "$OH/$OCIDIR/lib/msvc/ociw32.lib"); + $OCIINCLUDE = "-I$OH/$OCIDIR/include -I$OH/rdbms/demo"; $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/MSVC/OCIW32.LIB"]; $opts{dynamic_lib} = { OTHERLDFLAGS => " $OH/$OCIDIR/LIB/MSVC/OCIW32.LIB" }; - $opts{OBJECT} = '$(O_FILES)'; $opts{SKIP} = ['processPL']; # XXX caused problems with Nmake... + $opts{OBJECT} = '$(O_FILES)'; + $opts{INC} = "$OCIINCLUDE -I\$(INSTALLSITEARCH)/auto/DBI"; +} +elsif ($os eq 'VMS') { + $OCIINCLUDE = vmsify("$OH/rdbms/") ." ". vmsify("$OH/rdbms/demo/oci_demo/"); + $opts{OBJECT} = 'oracle.obj dbdimp.obj'; + $opts{INC} = "$OCIINCLUDE \$(INSTALLSITEARCH)/auto/DBI"; } -$opts{INC} = "$OCIINCLUDE -I\$(INSTALLSITEARCH)/auto/DBI"; # --- Handle special cases --- @@ -258,6 +291,10 @@ your 'privlib' and 'archlib' directories and their auto subdirectories. ''; } +sub MY::postamble { + return dbd_postamble(); +} + sub MY::post_constants { my $self = shift; @@ -281,10 +318,12 @@ ORACLE_HOME = '.$OH.' sub del_crtobj { - # E.g. for changing the COMPOBJS line + my $str = shift; + # E.g. for changing the COMPOBJS line (and sometimes LDSTRING) # old: $(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/__fstd.o # new: $(COMPOBJ)/__fstd.o - s:\$\S+?/crt[1in]\.o\b::g; + $str =~ s:\$\S+?/crt[1in]\.o\b::g; + return $str; } @@ -298,13 +337,13 @@ sub fetch_oci_macros { # makefile (note that %MK stills gets these values). my @edit = qw( SHELL CC CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS - AR ECHO EXE OBJS PERL + AR ECHO EXE OBJS PERL OBJ_EXT LIB_EXT ); my %edit; @edit{@edit} = ('$_ = ""') x @edit; $edit{COMPOBJS} = q{ # Firstly a Solaris specific edit: - del_crtobj() if $os eq 'solaris'; + $_ = del_crtobj($_) if $os eq 'solaris'; # Delete any object files in COMPOBJS that don't actually exist my $of; @@ -328,6 +367,10 @@ sub fetch_oci_macros { push @MK, '' if $_ eq '' and $lastline ne ''; # squeeze multiple blank lines next unless $_; + # deal with Oracle8's incompatible use of OBJ_EXT + s/\.(\$\(OBJ_EXT\))/$1/g; + s/\.(\$\(LIB_EXT\))/$1/g; + if ($::opt_old) { last if m/^\w+\s*:[^=]/; # gone too far, reached actual targets } @@ -467,11 +510,14 @@ sub find_bin{ return "<$bin not found>"; } -{ # If perl Makefile.PL *-g* then switch on debugging + +{ package MY; # SUPER needs package context, $self is not sufficient + sub const_cccmd { my($self) = shift; local($_) = $self->SUPER::const_cccmd(@_); + # If perl Makefile.PL *-g* then switch on debugging if ($::opt_g) { s/\s-O\d?\b//; # delete optimise option s/\s-/ -g -/; # add -g option @@ -506,3 +552,6 @@ $(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt rtls.opt $(INST_ARC } __END__ + +test.xs: $(INSTALLSITEARCH)/auto/DBI/Driver.xst + perl -p -e 's/{DRIVER}/$(BASEEXT)/g' < $(INSTALLSITEARCH)/auto/DBI/Driver.xst > test.xs diff --git a/Oracle.h b/Oracle.h index f6604b81..70e8ebd4 100644 --- a/Oracle.h +++ b/Oracle.h @@ -1,5 +1,5 @@ /* - $Id: Oracle.h,v 1.10 1997/06/14 17:42:12 timbo Exp $ + $Id: Oracle.h,v 1.11 1997/09/08 22:43:59 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -11,62 +11,44 @@ */ -#define NEED_DBIXS_VERSION 8 +#define NEED_DBIXS_VERSION 9 #include /* installed by the DBI module */ - -/* try uncommenting this line if you get a syntax error on - * typedef signed long sbig_ora; - * in oratypes.h for Oracle 7.1.3. Don't you just love Oracle! - */ -/* #define signed */ - -/* Hack to fix broken Oracle oratypes.h on OSF Alpha. Sigh. */ -#if defined(__osf__) && defined(__alpha) -#ifndef A_OSF -#define A_OSF -#endif -#endif - -#include - -#include - -#ifdef CAN_PROTOTYPE -# include -#else -# include -#endif - - -/* read in our implementation details */ - #include "dbdimp.h" -void dbd_init _((dbistate_t *dbistate)); - -int dbd_db_login _((SV *dbh, char *dbname, char *uid, char *pwd)); -int dbd_db_do _((SV *sv, char *statement)); -int dbd_db_commit _((SV *dbh)); -int dbd_db_rollback _((SV *dbh)); -int dbd_db_disconnect _((SV *dbh)); -void dbd_db_destroy _((SV *dbh)); -int dbd_db_STORE _((SV *dbh, SV *keysv, SV *valuesv)); -SV *dbd_db_FETCH _((SV *dbh, SV *keysv)); - - -int dbd_st_prepare _((SV *sth, char *statement, SV *attribs)); -int dbd_st_rows _((SV *sv)); -int dbd_bind_ph _((SV *h, SV *param, SV *value, SV *attribs, int is_inout, IV maxlen)); -int dbd_st_execute _((SV *sv)); -AV *dbd_st_fetch _((SV *sv)); -int dbd_st_finish _((SV *sth)); -void dbd_st_destroy _((SV *sth)); -int dbd_st_readblob _((SV *sth, int field, long offset, long len, - SV *destrv, long destoffset)); -int dbd_st_STORE _((SV *dbh, SV *keysv, SV *valuesv)); -SV *dbd_st_FETCH _((SV *dbh, SV *keysv)); - +#include /* installed by the DBI module */ + +#ifdef yxyxyxyx +/* These prototypes are for dbdimp.c funcs used in the XS file */ +/* These names are #defined to driver specific names in dbdimp.h */ + +void dbd_init _((dbistate_t *dbistate)); + +int dbd_db_login _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd)); +int dbd_db_do _((SV *sv, char *statement)); +int dbd_db_commit _((SV *dbh, imp_dbh_t *imp_dbh)); +int dbd_db_rollback _((SV *dbh, imp_dbh_t *imp_dbh)); +int dbd_db_disconnect _((SV *dbh, imp_dbh_t *imp_dbh)); +void dbd_db_destroy _((SV *dbh, imp_dbh_t *imp_dbh)); +int dbd_db_STORE_attrib _((SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)); +SV *dbd_db_FETCH_attrib _((SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)); + +int dbd_st_prepare _((SV *sth, imp_sth_t *imp_sth, + char *statement, SV *attribs)); +int dbd_st_rows _((SV *sth, imp_sth_t *imp_sth)); +int dbd_st_execute _((SV *sth, imp_sth_t *imp_sth)); +AV *dbd_st_fetch _((SV *sth, imp_sth_t *imp_sth)); +int dbd_st_finish _((SV *sth, imp_sth_t *imp_sth)); +void dbd_st_destroy _((SV *sth, imp_sth_t *imp_sth)); +int dbd_st_blob_read _((SV *sth, imp_sth_t *imp_sth, + int field, long offset, long len, SV *destrv, long destoffset)); +int dbd_st_STORE_attrib _((SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv)); +SV *dbd_st_FETCH_attrib _((SV *sth, imp_sth_t *imp_sth, SV *keysv)); + +int dbd_describe _((SV *sth, imp_sth_t *imp_sth)); +int dbd_bind_ph _((SV *sth, imp_sth_t *imp_sth, + SV *param, SV *value, SV *attribs, int is_inout, IV maxlen)); +#endif /* end of Oracle.h */ diff --git a/Oracle.pm b/Oracle.pm index 7e3350dc..43f60fde 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,4 @@ -# $Id: Oracle.pm,v 1.45 1997/06/20 21:18:11 timbo Exp $ +# $Id: Oracle.pm,v 1.47 1997/09/08 23:12:57 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997 Tim Bunce # @@ -9,7 +9,7 @@ require 5.002; -my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORACLE_ROOT' : 'ORACLE_HOME'; +my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; my $oracle_home = $ENV{$ORACLE_ENV}; { @@ -19,10 +19,10 @@ my $oracle_home = $ENV{$ORACLE_ENV}; use DynaLoader (); @ISA = qw(DynaLoader); - $VERSION = '0.46'; - my $Revision = substr(q$Revision: 1.45 $, 10); + $VERSION = '0.47'; + my $Revision = substr(q$Revision: 1.47 $, 10); - require_version DBI 0.84; + require_version DBI 0.85; bootstrap DBD::Oracle $VERSION; @@ -64,10 +64,6 @@ my $oracle_home = $ENV{$ORACLE_ENV}; { package DBD::Oracle::dr; # ====== DRIVER ====== use strict; - sub errstr { - return $DBD::Oracle::errstr; - } - sub load_oratab { # get list of 'local' databases my($drh) = @_; my $debug = $drh->debug; @@ -135,17 +131,17 @@ my $oracle_home = $ENV{$ORACLE_ENV}; # create a 'blank' dbh - my $this = DBI::_new_dbh($drh, { + my $dbh = DBI::_new_dbh($drh, { 'Name' => $dbname, 'USER' => $user, 'CURRENT_USER' => $user, }); # Call Oracle OCI orlon func in Oracle.xs file # and populate internal handle data. - DBD::Oracle::db::_login($this, $dbname, $user, $auth) + DBD::Oracle::db::_login($dbh, $dbname, $user, $auth) or return undef; - $this; + $dbh; } } @@ -154,14 +150,10 @@ my $oracle_home = $ENV{$ORACLE_ENV}; { package DBD::Oracle::db; # ====== DATABASE ====== use strict; - sub errstr { - return $DBD::Oracle::errstr; - } - sub prepare { my($dbh, $statement, @attribs)= @_; - # create a 'blank' dbh + # create a 'blank' sth my $sth = DBI::_new_sth($dbh, { 'Statement' => $statement, @@ -177,6 +169,16 @@ my $oracle_home = $ENV{$ORACLE_ENV}; $sth; } + + sub ping { + my($dbh) = @_; + # we know that DBD::Oracle prepare does a describe so this will + # actually talk to the server and is this a valid and cheap test. + return 1 if $dbh->prepare("select SYSDATE from DUAL"); + return 0; + } + + sub tables { my($dbh) = @_; # XXX add qualification my $sth = $dbh->prepare("select @@ -212,11 +214,8 @@ my $oracle_home = $ENV{$ORACLE_ENV}; { package DBD::Oracle::st; # ====== STATEMENT ====== - use strict; - sub errstr { - return $DBD::Oracle::errstr; - } + # all done in XS } 1; @@ -444,10 +443,189 @@ Also note that the NLS files $ORACLE_HOME/ocommon/nls/admin/data changed extension (from .d to .nlb) between 7.2.3 and 7.3.2. +=head1 SEE ALSO + +These PL/SQL examples come from: Eric Bartley . + + # we assume this package already exists + my $plsql = q{ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + }; + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + # Example 2 + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + # Example 3 + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + # Example 4 + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + +You can find more examples in the t/plsql.t file in the DBD::Oracle +source directory. + + =head1 SEE ALSO L +Linux uses should read: + + http://www.wmd.de/wmd/staff/pauck/misc/oracle_on_linux.html + =head1 AUTHOR DBD::Oracle by Tim Bunce. diff --git a/Oracle.xs b/Oracle.xs index 6708de7d..39fb88b4 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -1,271 +1,37 @@ -/* - $Id: Oracle.xs,v 1.45 1997/06/20 21:18:11 timbo Exp $ - - Copyright (c) 1994,1995 Tim Bunce - - You may distribute under the terms of either the GNU General Public - License or the Artistic License, as specified in the Perl README file, - with the exception that it cannot be placed on a CD-ROM or similar media - for commercial distribution without the prior approval of the author. - -*/ - #include "Oracle.h" - -/* --- Variables --- */ - - DBISTATE_DECLARE; + +MODULE = DBD::Oracle PACKAGE = DBD::Oracle - -MODULE = DBD::Oracle PACKAGE = DBD::Oracle - -REQUIRE: 1.929 -PROTOTYPES: DISABLE - -BOOT: - items = 0; /* avoid 'unused variable' warning */ - DBISTATE_INIT; - /* XXX this interface will change: */ - DBI_IMP_SIZE("DBD::Oracle::dr::imp_data_size", sizeof(imp_drh_t)); - DBI_IMP_SIZE("DBD::Oracle::db::imp_data_size", sizeof(imp_dbh_t)); - DBI_IMP_SIZE("DBD::Oracle::st::imp_data_size", sizeof(imp_sth_t)); - dbd_init(DBIS); - - -MODULE = DBD::Oracle PACKAGE = DBD::Oracle::dr - -# disconnect_all renamed and ALIAS'd to avoid length clash on VMS :-( -void -discon_all_(drh) - SV * drh - ALIAS: - disconnect_all = 1 - CODE: - if (!dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { - D_imp_drh(drh); - sv_setiv(DBIc_ERR(imp_drh), (IV)1); - sv_setpv(DBIc_ERRSTR(imp_drh), - (char*)"disconnect_all not implemented"); - DBIh_EVENT2(drh, ERROR_event, - DBIc_ERR(imp_drh), DBIc_ERRSTR(imp_drh)); - XSRETURN(0); - } - /* perl_destruct with perl_destruct_level and $SIG{__WARN__} set */ - /* to a code ref core dumps when sv_2cv triggers warn loop. */ - if (perl_destruct_level) - perl_destruct_level = 0; - XST_mIV(0, 1); - - - -MODULE = DBD::Oracle PACKAGE = DBD::Oracle::db - -void -_login(dbh, dbname, uid, pwd) - SV * dbh - char * dbname - char * uid - char * pwd - CODE: - ST(0) = dbd_db_login(dbh, dbname, uid, pwd) ? &sv_yes : &sv_no; - - -void -commit(dbh) - SV * dbh - CODE: - ST(0) = dbd_db_commit(dbh) ? &sv_yes : &sv_no; - -void -rollback(dbh) - SV * dbh - CODE: - ST(0) = dbd_db_rollback(dbh) ? &sv_yes : &sv_no; - - -void -STORE(dbh, keysv, valuesv) - SV * dbh - SV * keysv - SV * valuesv - CODE: - ST(0) = &sv_yes; - if (!dbd_db_STORE_attrib(dbh, keysv, valuesv)) - if (!DBIS->set_attr(dbh, keysv, valuesv)) - ST(0) = &sv_no; - -void -FETCH(dbh, keysv) - SV * dbh - SV * keysv - CODE: - SV *valuesv = dbd_db_FETCH_attrib(dbh, keysv); - if (!valuesv) - valuesv = DBIS->get_attr(dbh, keysv); - ST(0) = valuesv; /* dbd_db_FETCH_attrib did sv_2mortal */ - - -void -disconnect(dbh) - SV * dbh - CODE: - D_imp_dbh(dbh); - if ( !DBIc_ACTIVE(imp_dbh) ) { - XSRETURN_YES; - } - /* Check for disconnect() being called whilst refs to cursors */ - /* still exists. This possibly needs some more thought. */ - if (DBIc_ACTIVE_KIDS(imp_dbh) && DBIc_WARN(imp_dbh) && !dirty) { - warn("disconnect(%s) invalidates %d active cursor(s)", - SvPV(dbh,na), (int)DBIc_ACTIVE_KIDS(imp_dbh)); - } - ST(0) = dbd_db_disconnect(dbh) ? &sv_yes : &sv_no; - - -void -DESTROY(dbh) - SV * dbh - PPCODE: - D_imp_dbh(dbh); - ST(0) = &sv_yes; - if (!DBIc_IMPSET(imp_dbh)) { /* was never fully set up */ - if (DBIc_WARN(imp_dbh) && !dirty && dbis->debug >= 2) - warn("Database handle %s DESTROY ignored - never set up", - SvPV(dbh,na)); - } - else { - if (DBIc_ACTIVE(imp_dbh)) { - static int auto_rollback = -1; - if (DBIc_WARN(imp_dbh) && (!dirty || dbis->debug >= 3)) - warn("Database handle destroyed without explicit disconnect"); - /* The application has not explicitly disconnected. That's bad. */ - /* To ensure integrity we *must* issue a rollback. This will be */ - /* harmless if the application has issued a commit. If it hasn't */ - /* then it'll ensure integrity. Consider a Ctrl-C killing perl */ - /* between two statements that must be executed as a transaction. */ - /* Perl will call DESTROY on the dbh and, if we don't rollback, */ - /* the server will automatically commit! Bham! Corrupt database! */ - if (auto_rollback == -1) { /* need to determine behaviour */ - /* DBD_ORACLE_AUTO_ROLLBACK is offered as a _temporary_ sop to */ - /* those who can't fix their code in a short timescale. */ - char *p = getenv("DBD_ORACLE_AUTO_ROLLBACK"); - auto_rollback = (p) ? atoi(p) : 1; - } - if (auto_rollback) - dbd_db_rollback(dbh); /* ROLLBACK! */ - dbd_db_disconnect(dbh); - } - dbd_db_destroy(dbh); - } - - +INCLUDE: Oracle.xsi MODULE = DBD::Oracle PACKAGE = DBD::Oracle::st - -void -_prepare(sth, statement, attribs=Nullsv) - SV * sth - char * statement - SV * attribs - CODE: - DBD_ATTRIBS_CHECK("_prepare", sth, attribs); - ST(0) = dbd_st_prepare(sth, statement, attribs) ? &sv_yes : &sv_no; - - -void -rows(sth) - SV * sth - CODE: - XST_mIV(0, dbd_st_rows(sth)); - - -void -bind_param(sth, param, value, attribs=Nullsv) - SV * sth - SV * param - SV * value - SV * attribs - CODE: - DBD_ATTRIBS_CHECK("bind_param", sth, attribs); - ST(0) = dbd_bind_ph(sth, param, value, attribs, FALSE, 0) ? &sv_yes : &sv_no; - - -void -bind_param_inout(sth, param, value_ref, maxlen, attribs=Nullsv) - SV * sth - SV * param - SV * value_ref - IV maxlen - SV * attribs - CODE: - DBD_ATTRIBS_CHECK("bind_param_inout", sth, attribs); - if (!SvROK(value_ref) || SvTYPE(SvRV(value_ref)) > SVt_PVMG) - croak("bind_param_inout needs a reference to a scalar value"); - if (SvREADONLY(SvRV(value_ref))) - croak(no_modify); - ST(0) = dbd_bind_ph(sth, param, SvRV(value_ref), attribs, TRUE, maxlen) ? &sv_yes : &sv_no; - - -void -execute(sth, ...) - SV * sth - CODE: - D_imp_sth(sth); - int retval; - if (items > 1) { - /* Handle binding supplied values to placeholders */ - int i, error = 0; - SV *idx; - if (items-1 != DBIc_NUM_PARAMS(imp_sth)) { - croak("execute called with %ld bind variables, %d needed", - items-1, DBIc_NUM_PARAMS(imp_sth)); - XSRETURN_UNDEF; - } - idx = sv_2mortal(newSViv(0)); - for(i=1; i < items ; ++i) { - sv_setiv(idx, i); - if (!dbd_bind_ph(sth, idx, ST(i), Nullsv, FALSE, 0)) - ++error; - } - if (error) { - XSRETURN_UNDEF; /* dbd_bind_ph already registered error */ - } - } - retval = dbd_st_execute(sth); - /* remember that dbd_st_execute must return <= -2 for error */ - if (retval == 0) /* ok with no rows affected */ - XST_mPV(0, "0E0"); /* (true but zero) */ - else if (retval < -1) /* -1 == unknown number of rows */ - XST_mUNDEF(0); /* <= -2 means error */ - else - XST_mIV(0, retval); /* typically 1, rowcount or -1 */ - - void -fetch(sth) - SV * sth - CODE: - AV *av = dbd_st_fetch(sth); - ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &sv_undef; - - -void -fetchrow(sth) +ora_fetch(sth) SV * sth PPCODE: + /* fetchrow: but with scalar fetch returning NUM_FIELDS for Oraperl */ + /* This code is called _directly_ by Oraperl.pm bypassing the DBI. */ + /* as a result we have to do some things ourselves (like calling */ + /* CLEAR_ERROR) and we loose the tracing that the DBI offers :-( */ D_imp_sth(sth); AV *av; - if (DBIc_COMPAT(imp_sth) && GIMME == G_SCALAR) { /* XXX Oraperl */ + int debug = DBIc_DEBUGIV(imp_sth); + if (dbis->debug > debug) + debug = dbis->debug; + DBIh_CLEAR_ERROR(imp_sth); + if (GIMME == G_SCALAR) { /* XXX Oraperl */ /* This non-standard behaviour added only to increase the */ /* performance of the oraperl emulation layer (Oraperl.pm) */ if (!imp_sth->done_desc && !dbd_describe(sth, imp_sth)) XSRETURN_UNDEF; XSRETURN_IV(DBIc_NUM_FIELDS(imp_sth)); } - av = dbd_st_fetch(sth); + if (debug >= 2) + fprintf(DBILOGFP, " -> ora_fetch\n"); + av = dbd_st_fetch(sth, imp_sth); if (av) { int num_fields = AvFILL(av)+1; int i; @@ -273,88 +39,14 @@ fetchrow(sth) for(i=0; i < num_fields; ++i) { PUSHs(AvARRAY(av)[i]); } - } - - - -void -blob_read(sth, field, offset, len, destrv=Nullsv, destoffset=0) - SV * sth - int field - long offset - long len - SV * destrv - long destoffset - CODE: - if (!destrv) - destrv = sv_2mortal(newRV(sv_2mortal(newSV(0)))); - if (dbd_st_blob_read(sth, field, offset, len, destrv, destoffset)) - ST(0) = SvRV(destrv); - else ST(0) = &sv_undef; - - -void -STORE(sth, keysv, valuesv) - SV * sth - SV * keysv - SV * valuesv - CODE: - ST(0) = &sv_yes; - if (!dbd_st_STORE_attrib(sth, keysv, valuesv)) - if (!DBIS->set_attr(sth, keysv, valuesv)) - ST(0) = &sv_no; - - -# FETCH renamed and ALIAS'd to avoid case clash on VMS :-( -void -FETCH_attrib(sth, keysv) - SV * sth - SV * keysv - ALIAS: - FETCH = 1 - CODE: - SV *valuesv = dbd_st_FETCH_attrib(sth, keysv); - if (!valuesv) - valuesv = DBIS->get_attr(sth, keysv); - ST(0) = valuesv; /* dbd_st_FETCH_attrib did sv_2mortal */ - - -void -finish(sth) - SV * sth - CODE: - D_imp_sth(sth); - D_imp_dbh_from_sth; - if (!DBIc_ACTIVE(imp_dbh)) { - /* Either an explicit disconnect() or global destruction */ - /* has disconnected us from the database. Finish is meaningless */ - /* XXX warn */ - XSRETURN_YES; - } - if (!DBIc_ACTIVE(imp_sth)) { - /* No active statement to finish */ - XSRETURN_YES; - } - ST(0) = dbd_st_finish(sth) ? &sv_yes : &sv_no; - - -void -DESTROY(sth) - SV * sth - PPCODE: - D_imp_sth(sth); - ST(0) = &sv_yes; - if (!DBIc_IMPSET(imp_sth)) { /* was never fully set up */ - if (DBIc_WARN(imp_sth) && !dirty && dbis->debug >= 2) - warn("Statement handle %s DESTROY ignored - never set up", - SvPV(sth,na)); + if (debug >= 2) + fprintf(DBILOGFP, " <- (...) [%d items]\n", num_fields); } else { - if (DBIc_ACTIVE(imp_sth)) - dbd_st_finish(sth); - dbd_st_destroy(sth); + if (debug >= 2) + fprintf(DBILOGFP, " <- () [0 items]\n"); } + if (debug >= 2 && SvTRUE(DBIc_ERR(imp_sth))) + fprintf(DBILOGFP, " !! ERROR: %s %s", + neatsvpv(DBIc_ERR(imp_sth),0), neatsvpv(DBIc_ERRSTR(imp_sth),0)); - - -# end of Oracle.xs diff --git a/Oraperl.pm b/Oraperl.pm index a62b67e5..e3830205 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.34 1997/06/20 21:03:56 timbo Exp $ +# $Id: Oraperl.pm,v 1.35 1997/09/08 22:43:59 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -25,7 +25,7 @@ require 5.002; use DBI 0.84; use Exporter; -$VERSION = substr(q$Revision: 1.34 $, 10); +$VERSION = substr(q$Revision: 1.35 $, 10); @ISA = qw(Exporter); @@ -73,15 +73,13 @@ sub _func_ref { } sub _warn { - my $prev_warn = shift; - if ($_[0] =~ /^(Bad|Duplicate) free/) { - if ($ENV{PERL_DBD_DUMP} eq 'dump') { - print STDERR "Aborting with a core dump for diagnostics (PERL_DBD_DUMP)\n"; - dump; - } - return; - } - $prev_warn ? &$prev_warn(@_) : warn @_; + my $prev_warn = shift; + if ($_[0] =~ /^(Bad|Duplicate) free/) { + return unless $ENV{PERL_DBD_DUMP} eq 'dump'; + print STDERR "Aborting with a core dump for diagnostics (PERL_DBD_DUMP)\n"; + dump; + } + $prev_warn ? &$prev_warn(@_) : warn @_; } @@ -128,7 +126,7 @@ sub ora_open { } *ora_bind = _func_ref('st::execute'); -*ora_fetch = _func_ref('st::fetchrow'); +*ora_fetch = \&{"DBD::Oracle::st::ora_fetch"}; *ora_close = _func_ref('st::finish'); sub ora_do { @@ -216,7 +214,10 @@ sub ora_version { $Oraperl::ora_verno = '3.000'; # to distinguish it from oraperl 2.4 -$Oraperl::ora_long = 80; # 80, oraperl default +# ora_long is left unset so that the DBI $h->{LongReadLen} attrib will be used +# by default. If ora_long is set then LongReadLen will be ignored (sadly) but +# that behaviour may change later to only apply to oraperl mode handles. +#$Oraperl::ora_long = 80; # 80, oraperl default $Oraperl::ora_trunc = 0; # long trunc is error, oraperl default @@ -237,6 +238,8 @@ Oraperl - Perl access to Oracle databases for old oraperl scripts =head1 SYNOPSIS + eval 'use Oraperl; 1' || die $@ if $] >= 5; # ADD THIS LINE TO OLD SCRIPTS + $lda = &ora_login($system_id, $name, $password) $csr = &ora_open($lda, $stmt [, $cache]) &ora_bind($csr, $var, ...) @@ -277,6 +280,15 @@ The text in this document is largely unchanged from the original Perl4 oraperl manual written by Kevin Stock . Any comments specific to the DBD::Oracle Oraperl emulation are prefixed by B. +B In order to make the oraperl function definitions available in +perl5 you need to arrange to 'use' the Oraperl.pm module in each file +or package which uses them. You can do this by simply adding S> in each file or package. If you need to make the scripts work +with both the perl4 oraperl and perl5 you should add add the following +text instead: + + eval 'use Oraperl; 1' || die $@ if $] >= 5; + =head2 Principal Functions The main functions for database access are &ora_login(), &ora_open(), diff --git a/README b/README index 10f65e71..7295263a 100644 --- a/README +++ b/README @@ -82,8 +82,8 @@ Make sure you are using a recent perl 5.003 or preferably 5.004 and make sure it's on your path so you can say 'perl Makefile.PL' and not '/path/to/perl Makefile.PL'. -If you have build/link problems try using "perl Makefile.PL -p". -If that helps then *please* let me know. +If you have build/link or core dump problems try using +"perl Makefile.PL -p". If that helps then *please* let me know. Do not hand edit the generated Makefile unless you are completely sure you understand the implications! Always try to make changes via the @@ -214,6 +214,7 @@ ftp://ftp.bf.rmit.edu.au/pub/Oracle ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip +http://www.wmd.de/wmd/staff/pauck/misc/oracle_on_linux.html =============================================================================== Some platforms on which the DBI and DBD::Oracle modules run: diff --git a/README.plsql b/README.plsql deleted file mode 100644 index 126301ca..00000000 --- a/README.plsql +++ /dev/null @@ -1,6 +0,0 @@ -See t/plsql.t for lots of examples. - -begin dbms_output.enable(); end; -begin dbms_output.put_line(:thing); end; -begin dbms_output.get_line(:buffer, :status); end; - diff --git a/dbdimp.c b/dbdimp.c index 80b73187..4cb8955b 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.32 1997/06/20 21:18:11 timbo Exp $ + $Id: dbdimp.c,v 1.33 1997/09/08 22:43:59 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -22,7 +22,7 @@ static SV *ora_cache; static SV *ora_cache_o; /* temp hack for ora_open() cache override */ static int ora_login_err; /* fetch & show real login errmsg if true */ -static int autocommit = 0; /* we assume autocommit is off initially */ +static void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); void @@ -44,6 +44,26 @@ dbd_init(dbistate) } +int +dbd_discon_all(drh, imp_drh) + SV *drh; + imp_drh_t *imp_drh; +{ + /* The disconnect_all concept is flawed and needs more work */ + if (!dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { + sv_setiv(DBIc_ERR(imp_drh), (IV)1); + sv_setpv(DBIc_ERRSTR(imp_drh), + (char*)"disconnect_all not implemented"); + DBIh_EVENT2(drh, ERROR_event, + DBIc_ERR(imp_drh), DBIc_ERRSTR(imp_drh)); + return FALSE; + } + if (perl_destruct_level) + perl_destruct_level = 0; + return FALSE; +} + + /* Database specific error handling. This will be split up into specific routines for dbh and sth level. @@ -51,7 +71,7 @@ dbd_init(dbistate) Err, many changes needed, ramble ... */ -void +static void ora_error(h, lda, rc, what) SV *h; Lda_Def *lda; @@ -85,7 +105,7 @@ ora_error(h, lda, rc, what) } -void +static void fbh_dump(fbh, i, aidx) imp_fbh_t *fbh; int i; @@ -172,13 +192,13 @@ fb_ary_t *fb_ary; /* ================================================================== */ int -dbd_db_login(dbh, dbname, uid, pwd) +dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) SV *dbh; + imp_dbh_t *imp_dbh; char *dbname; char *uid; char *pwd; { - D_imp_dbh(dbh); int ret; /* can give duplicate free errors (from Oracle) if connect fails */ @@ -190,16 +210,24 @@ dbd_db_login(dbh, dbname, uid, pwd) /* is true (set via env var above). Thank Oracle for this sad hack. */ char buf[100]; char *msg="ORA-%d: (Text for error %d not fetched. Use 'oerr ORA %d' command.)"; - switch (rc) { + switch (rc) { + case 1019: msg="ORA-%d: unable to allocate memory in the user side (probably a symptom of a deeper problem)"; + break; case 1017: msg="ORA-%d: invalid username/password; login denied"; break; case 1034: msg="ORA-%d: ORACLE not available"; break; case 2700: msg="ORA-%d: osnoraenv: error translating ORACLE_SID"; break; - case 12154: msg="ORA-%d: TNS:could not resolve service name"; + case 3106: msg="ORA-%d: fatal two-task communication protocol error"; + break; + case 3121: msg="no interface driver connected - function not performed"; + break; + case 12154: msg="TNS-%d: TNS:could not resolve service name"; break; - } + case 12203: msg="TNS-%d: TNS:unable to connect to destination"; + break; + } sprintf(buf, msg, rc, rc, rc); ora_error(dbh, ora_login_err ? &imp_dbh->lda : NULL, rc, ora_login_err ? "login failed" : buf); @@ -212,10 +240,10 @@ dbd_db_login(dbh, dbname, uid, pwd) int -dbd_db_commit(dbh) +dbd_db_commit(dbh, imp_dbh) SV *dbh; + imp_dbh_t *imp_dbh; { - D_imp_dbh(dbh); if (ocom(&imp_dbh->lda)) { ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "commit failed"); return 0; @@ -224,10 +252,10 @@ dbd_db_commit(dbh) } int -dbd_db_rollback(dbh) +dbd_db_rollback(dbh, imp_dbh) SV *dbh; + imp_dbh_t *imp_dbh; { - D_imp_dbh(dbh); if (orol(&imp_dbh->lda)) { ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "rollback failed"); return 0; @@ -237,10 +265,10 @@ dbd_db_rollback(dbh) int -dbd_db_disconnect(dbh) +dbd_db_disconnect(dbh, imp_dbh) SV *dbh; + imp_dbh_t *imp_dbh; { - D_imp_dbh(dbh); /* We assume that disconnect will always work */ /* since most errors imply already disconnected. */ DBIc_ACTIVE_off(imp_dbh); @@ -256,24 +284,24 @@ dbd_db_disconnect(dbh) void -dbd_db_destroy(dbh) +dbd_db_destroy(dbh, imp_dbh) SV *dbh; + imp_dbh_t *imp_dbh; { - D_imp_dbh(dbh); if (DBIc_ACTIVE(imp_dbh)) - dbd_db_disconnect(dbh); + dbd_db_disconnect(dbh, imp_dbh); /* Nothing in imp_dbh to be freed */ DBIc_IMPSET_off(imp_dbh); } int -dbd_db_STORE_attrib(dbh, keysv, valuesv) +dbd_db_STORE_attrib(dbh, imp_dbh, keysv, valuesv) SV *dbh; + imp_dbh_t *imp_dbh; SV *keysv; SV *valuesv; { - D_imp_dbh(dbh); STRLEN kl; char *key = SvPV(keysv,kl); SV *cachesv = NULL; @@ -282,13 +310,10 @@ dbd_db_STORE_attrib(dbh, keysv, valuesv) if (kl==10 && strEQ(key, "AutoCommit")) { if ( (on) ? ocon(&imp_dbh->lda) : ocof(&imp_dbh->lda) ) { ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "ocon/ocof failed"); - /* XXX um, we can't return FALSE and true isn't acurate */ - /* the best we can do is cache an undef */ - cachesv = &sv_undef; - } else { - autocommit = on; - cachesv = boolSV(on); /* cache new state */ + /* XXX um, we can't return FALSE and true isn't acurate so we croak */ + croak(SvPV(DBIc_ERRSTR(imp_dbh),na)); } + DBIc_set(imp_dbh,DBIcf_AutoCommit, on); } else { return FALSE; } @@ -299,21 +324,23 @@ dbd_db_STORE_attrib(dbh, keysv, valuesv) SV * -dbd_db_FETCH_attrib(dbh, keysv) +dbd_db_FETCH_attrib(dbh, imp_dbh, keysv) SV *dbh; + imp_dbh_t *imp_dbh; SV *keysv; { - /* D_imp_dbh(dbh); */ STRLEN kl; char *key = SvPV(keysv,kl); - SV *retsv = NULL; + SV *retsv = Nullsv; /* Default to caching results for DBI dispatch quick_FETCH */ - int cacheit = TRUE; + int cacheit = FALSE; + + /* AutoCommit FETCH via DBI */ if (kl==10 && strEQ(key, "AutoCommit")) { - return boolSV(autocommit); + retsv = boolSV(DBIc_has(imp_dbh,DBIcf_AutoCommit)); } - else + if (!retsv) return Nullsv; if (cacheit) { /* cache for next time (via DBI quick_FETCH) */ SV **svp = hv_fetch((HV*)SvRV(dbh), key, kl, 1); @@ -328,20 +355,52 @@ dbd_db_FETCH_attrib(dbh, keysv) /* ================================================================== */ +static int +get_cursor(imp_dbh, sth, imp_sth) + imp_dbh_t *imp_dbh; + SV *sth; + imp_sth_t *imp_sth; +{ + imp_sth->cda = &imp_sth->cdabuf; + if (oopen(imp_sth->cda, &imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oopen error"); + return 0; + } + return 1; +} + +static int +free_cursor(sth, imp_sth) + SV *sth; + imp_sth_t *imp_sth; +{ + if (DBIc_ACTIVE(imp_sth)) /* should never happen here */ + ocan(imp_sth->cda); + + if (oclose(imp_sth->cda)) { /* close the cursor */ + /* Check for ORA-01041: 'hostdef extension doesn't exist' ? */ + /* which indicates that the lda had already been logged out */ + /* in which case only complain if not in 'global destruction'? */ + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oclose error"); + return 0; + } + imp_sth->cda = NULL; + return 1; +} + int -dbd_st_prepare(sth, statement, attribs) +dbd_st_prepare(sth, imp_sth, statement, attribs) SV *sth; + imp_sth_t *imp_sth; char *statement; SV *attribs; { - D_imp_sth(sth); D_imp_dbh_from_sth; sword oparse_defer = 0; /* PARSE_NO_DEFER */ ub4 oparse_lng = 1; /* auto v6 or v7 as suits db connected to */ imp_sth->done_desc = 0; - imp_sth->cda = &imp_sth->cdabuf; if (DBIc_COMPAT(imp_sth)) { imp_sth->ora_pad_empty = (SvOK(ora_pad_empty)) ? SvIV(ora_pad_empty) : 0; @@ -353,8 +412,7 @@ dbd_st_prepare(sth, statement, attribs) DBD_ATTRIB_GET_BOOL(attribs, "ora_parse_defer",15, svp, oparse_defer); } - if (oopen(imp_sth->cda, &imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oopen error"); + if (!get_cursor(imp_dbh, sth, imp_sth)) { return 0; } @@ -378,7 +436,7 @@ dbd_st_prepare(sth, statement, attribs) sv_catsv(msgsv, sqlsv); sv_catpv(msgsv, "'"); ora_error(sth, imp_sth->cda, imp_sth->cda->rc, SvPV(msgsv,na)); - oclose(imp_sth->cda); /* close the cursor */ + free_cursor(sth, imp_sth); return 0; } @@ -387,15 +445,8 @@ dbd_st_prepare(sth, statement, attribs) ; /* XXX perl_call_method to get error text ? */ } - /* long_buflen: length for long/longraw (if >0), else 80 (ora app dflt) */ - /* long_trunc_ok: is truncating a long an error XXX not implemented */ - imp_sth->long_buflen = (SvOK(ora_long) && SvIV(ora_long)>0) ? SvIV(ora_long) : 80; - imp_sth->long_trunc_ok = 1; /* can use blob_read() */ - /* ora_trunc is checked at fetch time */ - if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_st_prepare'd sql f%d (lb %ld, lt %d)\n", - imp_sth->cda->ft, (long)imp_sth->long_buflen, imp_sth->long_trunc_ok); + fprintf(DBILOGFP, " dbd_st_prepare'd sql f%d\n", imp_sth->cda->ft); /* Describe and allocate storage for results. */ if (!dbd_describe(sth, imp_sth)) { @@ -406,7 +457,7 @@ dbd_st_prepare(sth, statement, attribs) } -void +static void dbd_preparse(imp_sth, statement) imp_sth_t *imp_sth; char *statement; @@ -490,6 +541,7 @@ dbd_describe(h, imp_sth) static sb4 *f_cbufl; /* XXX not thread safe */ static U32 f_cbufl_max; + I32 long_buflen; sb1 *cbuf_ptr; int t_cbufl=0; I32 num_fields; @@ -497,25 +549,30 @@ dbd_describe(h, imp_sth) int est_width = 0; /* estimated avg row width (for cache) */ int i = 0; - I32 long_buflen = imp_sth->long_buflen; - if (long_buflen < 0) - long_buflen = 80; /* typical oracle app default */ if (imp_sth->done_desc) return 1; /* success, already done it */ imp_sth->done_desc = 1; + /* ora_trunc is checked at fetch time */ + /* long_buflen: length for long/longraw (if >0), else 80 (ora app dflt) */ + /* Ought to be for COMPAT mode only but was relaxed before LongReadLen existed */ + long_buflen = (SvOK(ora_long) && SvIV(ora_long)>0) + ? SvIV(ora_long) : DBIc_LongReadLen(imp_sth); + if (long_buflen < 0) /* trap any sillyness */ + long_buflen = 80; /* typical oracle app default */ + if (imp_sth->cda->ft != FT_SELECT) { if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_describe skipped for non-select (sql f%d)\n", - imp_sth->cda->ft); + fprintf(DBILOGFP, " dbd_describe skipped for non-select (sql f%d, lb %ld)\n", + imp_sth->cda->ft, (long)long_buflen); /* imp_sth memory was cleared when created so no setup required here */ return 1; } if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_describe (for sql f%d after oci f%d)...\n", - imp_sth->cda->ft, imp_sth->cda->fc); + fprintf(DBILOGFP, " dbd_describe (for sql f%d after oci f%d, lb %ld)...\n", + imp_sth->cda->ft, imp_sth->cda->fc, (long)long_buflen); if (!f_cbufl) { f_cbufl_max = 120; @@ -682,6 +739,7 @@ _dbd_rebind_ph(sth, imp_sth, phs) phs_t *phs; { STRLEN value_len; + ub2 *alen_ptr; /* for strings, must be a PV first for ptr to be valid? */ /* sv_insert +4 */ @@ -689,8 +747,8 @@ _dbd_rebind_ph(sth, imp_sth, phs) if (dbis->debug >= 2) { char *text = neatsvpv(phs->sv,0); - fprintf(DBILOGFP, "bind %s <== %s (size %d/%d/%ld, ptype %ld, otype %d)\n", - phs->name, text, SvCUR(phs->sv),SvLEN(phs->sv),phs->maxlen, + fprintf(DBILOGFP, "bind %s <== %s (size %ld/%ld/%ld, ptype %ld, otype %d)\n", + phs->name, text, (long)SvCUR(phs->sv),(long)SvLEN(phs->sv),phs->maxlen, SvTYPE(phs->sv), phs->ftype); } @@ -731,20 +789,29 @@ _dbd_rebind_ph(sth, imp_sth, phs) phs->progv = SvPV(phs->sv, value_len); } phs->sv_type = SvTYPE(phs->sv); /* part of mutation check */ - phs->alen = value_len + phs->alen_incnull; phs->maxlen = SvLEN(phs->sv)-1; /* avail buffer space */ + if (value_len + phs->alen_incnull <= UB2MAXVAL) { + phs->alen = value_len + phs->alen_incnull; + alen_ptr = &phs->alen; + if (phs->alen > phs->maxlen && phs->indp != -1) + croak("panic: _dbd_rebind_ph alen %ld > maxlen %ld", phs->alen,phs->maxlen); + } + else { + phs->alen = 0; + alen_ptr = NULL; /* Can't use alen */ + if (phs->is_inout) + croak("Can't bind LONG values (>%ld) as in/out parameters", (long)UB2MAXVAL); + } + /* ---------- */ /* Since we don't support LONG VAR types we must check */ /* for lengths too big to pass to obndrv as an sword. */ - if (sizeof(sword) < 4 && phs->maxlen > MINSWORDMAXVAL) /* generally 32K */ + if (phs->maxlen > MINSWORDMAXVAL && sizeof(sword)<4) /* generally 32K */ croak("Can't bind %s, value is too long (%ld bytes, max %d)", phs->name, phs->maxlen, MINSWORDMAXVAL); - if (phs->alen > phs->maxlen) - croak("panic: _dbd_rebind_ph alen %ld > maxlen %ld", phs->alen,phs->maxlen); - if (dbis->debug >= 3) { fprintf(DBILOGFP, "bind %s <== '%.100s' (size %d/%ld, indp %d)\n", phs->name, phs->progv, phs->alen, (long)phs->maxlen, phs->indp); @@ -753,7 +820,7 @@ _dbd_rebind_ph(sth, imp_sth, phs) if (obndra(imp_sth->cda, (text *)phs->name, -1, (ub1*)phs->progv, (sword)phs->maxlen, /* cast reduces max size */ (sword)phs->ftype, -1, - &phs->indp, &phs->alen, &phs->arcode, 0, (ub4 *)0, + &phs->indp, alen_ptr, &phs->arcode, 0, (ub4 *)0, (text *)0, -1, -1)) { D_imp_dbh_from_sth; ora_error(sth, &imp_dbh->lda, imp_sth->cda->rc, "obndra failed"); @@ -764,15 +831,16 @@ _dbd_rebind_ph(sth, imp_sth, phs) int -dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) +dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxlen) SV *sth; + imp_sth_t *imp_sth; SV *ph_namesv; SV *newvalue; + IV sql_type; SV *attribs; int is_inout; IV maxlen; { - D_imp_sth(sth); SV **phs_svp; STRLEN name_len; char *name; @@ -852,10 +920,10 @@ dbd_bind_ph(sth, ph_namesv, newvalue, attribs, is_inout, maxlen) int -dbd_st_execute(sth) /* <= -2:error, >=0:ok row count, (-1=unknown count) */ +dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count) */ SV *sth; + imp_sth_t *imp_sth; { - D_imp_sth(sth); int debug = dbis->debug; int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0; @@ -872,33 +940,25 @@ dbd_st_execute(sth) /* <= -2:error, >=0:ok row count, (-1=unknown count) */ if (outparams) { /* check validity of bound SV's */ int i = outparams; - STRLEN phs_len; while(--i >= 0) { phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); /* Make sure we have the value in string format. Typically a number */ /* will be converted back into a string using the same bound buffer */ /* so the progv test below will not trip. */ -/* XXX needs reworking -call rebind for all changes -consider also case of undef and bind time and not undef at execute -*/ - if (SvOK(phs->sv)) { - if (!SvPOK(phs->sv)) /* ooops, no string ($var = 42) */ - SvPV(phs->sv, phs_len); /* get string ("42"), see progv */ - phs_len = SvCUR(phs->sv) + phs->alen_incnull; - if (phs_len >= 65535) /* alen is only 16 bit. XXX maxlen */ - croak("Placeholder %s value too long",phs->name); - phs->alen = phs_len; - phs->indp = 0; /* mark as not null */ - } - else { - phs->indp = -1; /* mark as null */ - } + + /* is the value a null? */ + phs->indp = (SvOK(phs->sv)) ? 0 : -1; + /* Some checks for mutated storage since we pointed oracle at it. */ - if (SvTYPE(phs->sv) != phs->sv_type || SvPVX(phs->sv) != phs->progv) { + if (SvTYPE(phs->sv) != phs->sv_type + || (SvOK(phs->sv) && !SvPOK(phs->sv)) + || SvPVX(phs->sv) != phs->progv + || SvCUR(phs->sv) > UB2MAXVAL + ) { if (!_dbd_rebind_ph(sth, imp_sth, phs)) croak("Can't rebind placeholder %s", phs->name); } + phs->alen = SvCUR(phs->sv) + phs->alen_incnull; if (debug >= 2) warn(" with %s = '%.100s' (len %d/%d, indp %d, ptype %ld, otype %d)\n", phs->name, SvPVX(phs->sv), phs->alen, phs->maxlen, @@ -976,13 +1036,14 @@ consider also case of undef and bind time and not undef at execute AV * -dbd_st_fetch(sth) +dbd_st_fetch(sth, imp_sth) SV * sth; + imp_sth_t *imp_sth; { - D_imp_sth(sth); int debug = dbis->debug; int num_fields; int ChopBlanks; + int err = 0; int i; AV *av; @@ -995,7 +1056,7 @@ dbd_st_fetch(sth) } if (!imp_sth->in_cache) { /* refill cache if empty */ - int rows_returned; + int previous_rpc; if (imp_sth->eod_errno) { end_of_data: @@ -1011,18 +1072,18 @@ dbd_st_fetch(sth) return Nullav; } - rows_returned = imp_sth->cda->rpc; /* remember rpc before re-fetch */ + previous_rpc = imp_sth->cda->rpc; /* remember rpc before re-fetch */ if (ofen(imp_sth->cda, imp_sth->cache_size)) { /* Note that errors may happen after one or more rows have been */ /* added to the cache. We record the error but don't handle it till */ /* the cache is empty (which may be at once if no rows returned). */ imp_sth->eod_errno = imp_sth->cda->rc; /* store rc for later */ - if (imp_sth->cda->rpc == rows_returned) /* no more rows fetched */ + if (imp_sth->cda->rpc == previous_rpc) /* no more rows fetched */ goto end_of_data; /* else fall through and return the first of the fetched rows */ } imp_sth->next_entry = 0; - imp_sth->in_cache = imp_sth->cda->rpc - rows_returned; + imp_sth->in_cache = imp_sth->cda->rpc - previous_rpc; assert(imp_sth->in_cache > 0); } @@ -1046,28 +1107,25 @@ dbd_st_fetch(sth) if (rc == 1406 && dbtype_is_long(fbh->dbtype)) { /* We have a LONG field which has been truncated. */ int oraperl = DBIc_COMPAT(imp_sth); - if ((oraperl) ? SvIV(ora_trunc) : imp_sth->long_trunc_ok) { + if ((oraperl) ? SvIV(ora_trunc) : DBIc_has(imp_sth,DBIcf_LongTruncOk)) { /* Oraperl recorded the truncation in ora_errno. */ /* We do so but it's not part of the DBI spec. */ - sv_setiv(DBIc_ERR(imp_sth), (IV)rc); /* record it */ + if (oraperl) + sv_setiv(DBIc_ERR(imp_sth), (IV)rc); /* record it */ rc = 0; /* but don't provoke an error */ } + /* else provoke an error */ } if (rc == 0) { /* the normal case */ - sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], - fb_ary->arlen[cache_entry]); + int datalen = fb_ary->arlen[cache_entry]; + char *p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; /* if ChopBlanks check for Oracle CHAR type (blank padded) */ if (ChopBlanks && fbh->dbtype == 96) { - char *p = SvEND(sv); - int len = SvCUR(sv); - while(len && *--p == ' ') - --len; - if (len != SvCUR(sv)) { - SvCUR_set(sv, len); - *SvEND(sv) = '\0'; - } + while(datalen && p[datalen - 1]==' ') + --datalen; } + sv_setpvn(sv, p, datalen); } else if (rc == 1405) { /* field is null - return undef */ (void)SvOK_off(sv); @@ -1078,34 +1136,34 @@ dbd_st_fetch(sth) /* for now we just treat them all as errors */ ora_error(sth, imp_sth->cda, rc, "ofetch rcode"); (void)SvOK_off(sv); + ++err; /* 'fail' this fetch but continue getting fields */ } if (debug >= 3) - fprintf(DBILOGFP, " %d: rc=%d '%s'\n", - i, rc, SvPV(sv,na)); - + fprintf(DBILOGFP, " %d (rc=%d): %s\n", + i, rc, neatsvpv(sv,0)); } /* update cache counters */ --imp_sth->in_cache; ++imp_sth->next_entry; - return av; + return (err) ? Nullav : av; } int -dbd_st_blob_read(sth, field, offset, len, destrv, destoffset) +dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset) SV *sth; + imp_sth_t *imp_sth; int field; long offset; long len; SV *destrv; long destoffset; { - D_imp_sth(sth); ub4 retl; SV *bufsv; @@ -1113,6 +1171,7 @@ dbd_st_blob_read(sth, field, offset, len, destrv, destoffset) sv_setpvn(bufsv,"",0); /* ensure it's writable string */ SvGROW(bufsv, len+destoffset+1); /* SvGROW doesn't do +1 */ + /* The +1 on field was a mistake tht's too late to fix :-( */ if (oflng(imp_sth->cda, (sword)field+1, ((ub1*)SvPVX(bufsv)) + destoffset, len, imp_sth->fbh[field].ftype, /* original long type */ @@ -1135,19 +1194,19 @@ dbd_st_blob_read(sth, field, offset, len, destrv, destoffset) int -dbd_st_rows(sth) +dbd_st_rows(sth, imp_sth) SV *sth; + imp_sth_t *imp_sth; { - D_imp_sth(sth); return imp_sth->cda->rpc; } int -dbd_st_finish(sth) +dbd_st_finish(sth, imp_sth) SV *sth; + imp_sth_t *imp_sth; { - D_imp_sth(sth); /* Cancel further fetches from this cursor. */ /* We don't close the cursor till DESTROY (dbd_st_destroy). */ /* The application may re execute(...) it. */ @@ -1168,28 +1227,26 @@ dbd_st_finish(sth) void -dbd_st_destroy(sth) +dbd_st_destroy(sth, imp_sth) SV *sth; + imp_sth_t *imp_sth; { - D_imp_sth(sth); D_imp_dbh_from_sth; int fields; int i; + + /* dbd_st_finish has already been called by .xs code if needed. */ + /* Check if an explicit disconnect() or global destruction has */ /* disconnected us from the database before attempting to close. */ - if (DBIc_ACTIVE(imp_dbh) && oclose(imp_sth->cda)) { - /* Check for ORA-01041: 'hostdef extension doesn't exist' */ - /* which indicates that the lda had already been logged out */ - /* in which case only complain if not in 'global destruction'. */ - /* NOT NEEDED NOW? if ( ! (imp_sth->cda->rc == 1041 && dirty) ) */ - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oclose error"); - /* fall through */ + if (DBIc_ACTIVE(imp_dbh) && !free_cursor(sth, imp_sth)) { + /* fall through anyway to free up our memory */ } /* Free off contents of imp_sth */ fields = DBIc_NUM_FIELDS(imp_sth); - imp_sth->in_cache = 0; + imp_sth->in_cache = 0; imp_sth->eod_errno = 1403; for(i=0; i < fields; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i]; @@ -1222,14 +1279,14 @@ dbd_st_destroy(sth) int -dbd_st_STORE_attrib(sth, keysv, valuesv) +dbd_st_STORE_attrib(sth, imp_sth, keysv, valuesv) SV *sth; + imp_sth_t *imp_sth; SV *keysv; SV *valuesv; { return FALSE; #ifdef not_used_yet - D_imp_sth(sth); STRLEN kl; char *key = SvPV(keysv,kl); int on = SvTRUE(valuesv); @@ -1244,11 +1301,11 @@ dbd_st_STORE_attrib(sth, keysv, valuesv) SV * -dbd_st_FETCH_attrib(sth, keysv) +dbd_st_FETCH_attrib(sth, imp_sth, keysv) SV *sth; + imp_sth_t *imp_sth; SV *keysv; { - D_imp_sth(sth); STRLEN kl; char *key = SvPV(keysv,kl); int i; diff --git a/dbdimp.h b/dbdimp.h index 825a7788..10385e8c 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.18 1997/06/14 17:42:12 timbo Exp $ + $Id: dbdimp.h,v 1.19 1997/09/08 22:43:59 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -12,6 +12,26 @@ /* #define MAX_COLS 1025 */ +/* try uncommenting this line if you get a syntax error on + * typedef signed long sbig_ora; + * in oratypes.h for Oracle 7.1.3. Don't you just love Oracle! + */ +/* #define signed */ + +/* Hack to fix broken Oracle oratypes.h on OSF Alpha. Sigh. */ +#if defined(__osf__) && defined(__alpha) +#ifndef A_OSF +#define A_OSF +#endif +#endif + +#include +#include +#ifdef CAN_PROTOTYPE +# include +#else +# include +#endif #ifndef HDA_SIZE #define HDA_SIZE 512 #endif @@ -33,6 +53,8 @@ struct imp_dbh_st { Lda_Def lda; ub1 hda[HDA_SIZE]; + + int autocommit; /* we assume autocommit is off initially */ }; @@ -54,8 +76,6 @@ struct imp_sth_st { imp_fbh_t *fbh; /* array of imp_fbh_t structs */ char *fbh_cbuf; /* memory for all field names */ int t_dbsize; /* raw data width of a row */ - sb4 long_buflen; /* length for long/longraw (if >0) */ - bool long_trunc_ok; /* is truncating a long an error */ /* Select Row Cache Details */ int cache_size; @@ -119,18 +139,27 @@ struct phs_st { /* scalar placeholder EXPERIMENTAL */ }; -void ora_error _((SV *h, Lda_Def *lda, int rc, char *what)); -void fbh_dump _((imp_fbh_t *fbh, int i, int cacheidx)); - -void dbd_init _((dbistate_t *dbistate)); -void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); -int dbd_describe _((SV *h, imp_sth_t *imp_sth)); -int dbd_st_blob_read _((SV *sth, int field, long offset, long len, - SV *destrv, long destoffset)); -int dbd_db_STORE_attrib _((SV *dbh, SV *keysv, SV *valuesv)); -SV *dbd_db_FETCH_attrib _((SV *dbh, SV *keysv)); -int dbd_st_STORE_attrib _((SV *dbh, SV *keysv, SV *valuesv)); -SV *dbd_st_FETCH_attrib _((SV *sth, SV *keysv)); - +/* These defines avoid name clashes for multiple statically linked DBD's */ + +#define dbd_init ora_init +#define dbd_db_login ora_db_login +#define dbd_db_do ora_db_do +#define dbd_db_commit ora_db_commit +#define dbd_db_rollback ora_db_rollback +#define dbd_db_disconnect ora_db_disconnect +#define dbd_db_destroy ora_db_destroy +#define dbd_db_STORE_attrib ora_db_STORE_attrib +#define dbd_db_FETCH_attrib ora_db_FETCH_attrib +#define dbd_st_prepare ora_st_prepare +#define dbd_st_rows ora_st_rows +#define dbd_st_execute ora_st_execute +#define dbd_st_fetch ora_st_fetch +#define dbd_st_finish ora_st_finish +#define dbd_st_destroy ora_st_destroy +#define dbd_st_blob_read ora_st_blob_read +#define dbd_st_STORE_attrib ora_st_STORE_attrib +#define dbd_st_FETCH_attrib ora_st_FETCH_attrib +#define dbd_describe ora_describe +#define dbd_bind_ph ora_bind_ph /* end */ diff --git a/t/plsql.t b/t/plsql.t index 106dee44..9ea4f883 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -90,6 +90,14 @@ ok(0, $p1 == 6); $p1 = 1; foreach (1..10) { $csr->execute || die $DBI::errstr; } ok(0, $p1 == 1024); +# --- test undef parameters +ok(0, $csr = $dbh->prepare(q{ + declare foo char(500); + begin foo := :arg; end; +}), 1); +my $undef; +ok(0, $csr->bind_param_inout(':arg', \$undef,10), 1); +ok(0, $csr->execute, 1); # --- test named string in/out parameters ok(0, $csr = $dbh->prepare(q{ @@ -121,16 +129,6 @@ ok(0, $p1 eq 'null!'); $csr->finish; -# --- test plsql_errstr -ok(0, ! $dbh->prepare(q{ - begin - procedure filltab( stuff out tab ); asdf - end; -}), 1); -ok(0, $dbh->err == 6550); # PL/SQL error -my $msg = $dbh->func('plsql_errstr'); -ok(0, $msg =~ /Encountered the symbol/, $msg); - # To do # test NULLs at first bind @@ -144,3 +142,9 @@ exit 0; BEGIN { $tests = 29 } # end. +__END__ +t/plsql.............ORA-06502: PL/SQL: numeric or value error +ORA-06512: at line 4 (DBD: oexec error) +Use of uninitialized value at t/plsql.t line 120. +Error in PL/SQL block +3.5: PLS-00103: The symbol "an optional basic declaration item" was ignored. diff --git a/test.pl b/test.pl index 1c8e040a..6a749a24 100755 --- a/test.pl +++ b/test.pl @@ -168,7 +168,6 @@ sub test1 { print "Test ora_do with harmless non-select statement ", "(set transaction read only)\n"; - # example: push(@{$lda->{Handlers}}, sub { die "ora_errno=$ora_errno" } ); print "Expect error message:\n"; &ora_do($lda, "set transaction read only ") || warn "ora_do: $ora_errno: $ora_errstr\n"; @@ -215,6 +214,7 @@ sub test_cache { || die "ora_login: $ora_errno: $ora_errstr\n"; local($csr, $rows, $max); local($start) = time; + #$l->debug(3); foreach $max (1, 0, $cache-1, $cache, $cache+1) { $csr = &ora_open($l, q{ select object_name from all_objects where rownum <= :1 @@ -222,9 +222,9 @@ sub test_cache { &ora_bind($csr, $max) || die $ora_errstr; $rows = count_fetch($csr); die "test_cache $rows/$max" if $rows != $max; - &ora_bind($csr, $max+1) || die $ora_errstr; + &ora_bind($csr, $max+2) || die $ora_errstr; $rows = count_fetch($csr); - die "test_cache $rows/$max+1" if $rows != $max+1; + die "test_cache $rows/$max+2" if $rows != $max+2; } # this test will only show timing improvements when # run over a modem link. It's primarily designed to From 85a51274f04afb653501014b94865b598a23085a Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Mon, 8 Sep 1997 18:16:42 -0500 Subject: [PATCH 026/637] import DBD-Oracle 0.47 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.47 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD/Oracle/DBD-Oracle-0.47.tar.gz From db35bfc8c3b84ffff84b0d90156f9102fd3f90bf Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Tue, 26 May 1998 06:27:31 -0500 Subject: [PATCH 027/637] import DBD-Oracle 0.48 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.48 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.48.tar.gz --- Changes | 514 +++++++++++++++++++++++++------------------------ MANIFEST | 1 + Makefile.PL | 374 +++++++++++++++++++++-------------- Oracle.pm | 141 ++++++++++---- Oraperl.pm | 5 +- README | 64 +++--- README.clients | 81 ++++++++ README.help | 51 +++-- README.win32 | 16 ++ Todo | 35 ++++ dbdimp.c | 321 ++++++++++++++++++++---------- dbdimp.h | 32 ++- t/general.t | 64 ++++++ t/plsql.t | 63 +++++- test.pl | 45 ++++- 15 files changed, 1209 insertions(+), 598 deletions(-) create mode 100644 t/general.t diff --git a/Changes b/Changes index 1cd6ae98..6c5a2ac5 100644 --- a/Changes +++ b/Changes @@ -1,381 +1,397 @@ -Changes in DBD::Oracle 0.47 (Oraperl 1.XX), XXth June 1997 - - $h->{InactiveDestroy} = 1; now works reliably (with DBI 0.90). - Makefile.PL changed for Oracle8. Thanks to Philippe Vanhaesendonck. - Long params now work. Thanks to Michael Harvey. - (Long params don't yet work for inout params.) - AutoCommit flag now per-dbh. Thanks to Irving Reid. - Fixed panic: _dbd_rebind_ph when binding an undef. - Added $dbh->ping method (for Apache::DBI users). - Some field-level fetch errors didn't cause the fetch to fail - (the field was simply set undef). - LongReadLen now works (if $Oraperl::ora_trunc unset or <= 0) - LongTruncOk now works (for non oraperl mode handle). +Changes in DBD::Oracle 0.48 (Oraperl 1.36), 25th May 1998 + + THIS IS AN EXPERIMENTAL RELEASE - USE WITH CAUTION! + Now links to -lclntsh directly (Thanks to Bruce Nelson and others) + Workaround for broken backticks after login (Thanks to Warren Jones) + Now finds and reads tnsnames.ora to disambiguate dbnames in connect. + Added basic support for bind_param(..., SQL_TYPE). + Fixed bind_param_inout after execute. + Added dbms_output_(enable|put|get) functions. + Added $dbh->ping. + Added DBI->data_sources('Oracle'); + $sth->rows now warns if called for select before rows fetched. + Fixed RAW types to not truncate. + Improved quality and clarity of trace information. + Requires DBI 0.92 + +Changes in DBD::Oracle 0.47 (Oraperl 1.35), 8th Sept 1997 + + $h->{InactiveDestroy} = 1; now works reliably (with DBI 0.90). + Makefile.PL changed for Oracle8. Thanks to Philippe Vanhaesendonck. + Long params now work. Thanks to Michael Harvey. + (Long params don't yet work for inout params.) + AutoCommit flag now per-dbh. Thanks to Irving Reid. + Fixed panic: _dbd_rebind_ph when binding an undef. + Added $dbh->ping method (for Apache::DBI users). + Some field-level fetch errors didn't cause the fetch to fail + (the field was simply set undef). + LongReadLen now works (if $Oraperl::ora_trunc unset or <= 0) + LongTruncOk now works (for non oraperl mode handle). Changes in DBD::Oracle 0.46 (Oraperl 1.34), 20th June 1997 - Fixed Makefile.PL to work with 5.004_01. - Some VMS support from Dan Sugalski - If ORACLE_HOME isn't set, Oracle.pm no longer tries to guess it. - bind_param_inout now checks for read-only variables. - Requires DBI 0.84. + Fixed Makefile.PL to work with 5.004_01. + Some VMS support from Dan Sugalski + If ORACLE_HOME isn't set, Oracle.pm no longer tries to guess it. + bind_param_inout now checks for read-only variables. + Requires DBI 0.84. Changes in DBD::Oracle 0.45 (Oraperl 1.33), 16th June 1997 - A $dbh DESTROY without an explicit disconnect does a rollback. - Note that this may 'break' existing 'lazy' code but is completely - essential for robust applications. See comments in Oracle.xs. + A $dbh DESTROY without an explicit disconnect does a rollback. + Note that this may 'break' existing 'lazy' code but is completely + essential for robust applications. See comments in Oracle.xs. - Added Makefile.PL changes from Eric Bartley and others. - The changes should fix build problems for Oracle 7.3.x. + Added Makefile.PL changes from Eric Bartley and others. + The changes should fix build problems for Oracle 7.3.x. - Requires DBI 0.83. + Requires DBI 0.83. - Oraperl now uses DBI->connect and thus works with DBI 0.81 to - automatically support Apache without requiring script changes. + Oraperl now uses DBI->connect and thus works with DBI 0.81 to + automatically support Apache without requiring script changes. - Reworked parameter binding in preparation for future changes. - - mutated placeholder values are now automatically rebound. - - in/out vars that become undef/null after binding now work. - - transparent support for longs should be easier to implement. + Reworked parameter binding in preparation for future changes. + - mutated placeholder values are now automatically rebound. + - in/out vars that become undef/null after binding now work. + - transparent support for longs should be easier to implement. - Added Win32 support from Jeff Urlwin. + Added Win32 support from Jeff Urlwin. - Added some documentation to DBD::Oracle for 'perldoc DBD::Oracle'. + Added some documentation to DBD::Oracle for 'perldoc DBD::Oracle'. - Most tests now converted to standard t/*.t format. - Added $sth->{NULLABLE}->[$field]. - Added private plsql_errstr method: $txt=$dbh->func('plsql_errstr') - to fetch PL/SQL error messages. Thanks to Bob Menteer. - Added $sth->{ora_pad_empty} and ORAPERL_PAD_EMPTY env var - for better compatibility with old oraperl. - Added $sth->{AutoCommit} FETCH. - Added $sth->{ChopBlanks} (but not yet tested). - No longer asks Oracle for text of login failure message since - that can cause oracle's code to hang (sigh). We provide fake text - for the most common errors and a useful default for the rest. - You can set DBD_ORACLE_LOGIN_ERR env var to revert to old behaviour. + Most tests now converted to standard t/*.t format. + Added $sth->{NULLABLE}->[$field]. + Added private plsql_errstr method: $txt=$dbh->func('plsql_errstr') + to fetch PL/SQL error messages. Thanks to Bob Menteer. + Added $sth->{ora_pad_empty} and ORAPERL_PAD_EMPTY env var + for better compatibility with old oraperl. + Added $sth->{AutoCommit} FETCH. + Added $sth->{ChopBlanks} (but not yet tested). + No longer asks Oracle for text of login failure message since + that can cause oracle's code to hang (sigh). We provide fake text + for the most common errors and a useful default for the rest. + You can set DBD_ORACLE_LOGIN_ERR env var to revert to old behaviour. The Copyright terms for DBD::Oracle have changed and now read as follows: - You may distribute under the terms of either the GNU General Public - License or the Artistic License, as specified in the Perl README file, - with the exception that it cannot be placed on a CD-ROM or similar media - for commercial distribution without the prior approval of the author. + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the Perl README file, + with the exception that it cannot be placed on a CD-ROM or similar media + for commercial distribution without the prior approval of the author. Changes in DBD::Oracle 0.44 (Oraperl 1.30), 14th Jan 1997 - Fixed leak in read_blob (thanks to Jurgen Botz for the patch). - Improved automatic cache sizing (so better default caching). - Negative cache size specifies desired cache/transfer size in bytes. - Added $rowid = $csr->{ora_rowid} attribute (untested, please test). - (Use via $csr->bind_param(1, $rowid, { ora_type => 11 });) - Queries returning LONG's are no longer cached (so there's no - need to set the cache to 1 explicitly to get read_blob to work). - Added a test using string type with bind_param_inout in test.pl. - Worked around the rather sad VMS linker case insensitivity. - Worked around VMS linker length warning on XS...disconnect_all. - Makefile.PL deletes non-existant files from $(COMPOBJS) - (thanks to aburlison@cix.compulink.co.uk for the original patch) + Fixed leak in read_blob (thanks to Jurgen Botz for the patch). + Improved automatic cache sizing (so better default caching). + Negative cache size specifies desired cache/transfer size in bytes. + Added $rowid = $csr->{ora_rowid} attribute (untested, please test). + (Use via $csr->bind_param(1, $rowid, { ora_type => 11 });) + Queries returning LONG's are no longer cached (so there's no + need to set the cache to 1 explicitly to get read_blob to work). + Added a test using string type with bind_param_inout in test.pl. + Worked around the rather sad VMS linker case insensitivity. + Worked around VMS linker length warning on XS...disconnect_all. + Makefile.PL deletes non-existant files from $(COMPOBJS) + (thanks to aburlison@cix.compulink.co.uk for the original patch) Changes in DBD::Oracle 0.43 (Oraperl 1.30), 29nd Oct 1996 - Fixed serious 'false ora_errno 1 after short select' bug. - Worked around oracle bug that makes cda->ft unreliable. - Do not use DBD::Oracle 0.41 or 0.42. - Cursors are now 'describe'd at prepare time thus making - NUM_OF_FIELDS always available. Describe does nothing for - non-select operations. NUM_OF_FIELDS > 0 is now used to - select between oexec() and oexfet() in execute(). - Added more internal debugging. Improved test.pl. + Fixed serious 'false ora_errno 1 after short select' bug. + Worked around oracle bug that makes cda->ft unreliable. + Do not use DBD::Oracle 0.41 or 0.42. + Cursors are now 'describe'd at prepare time thus making + NUM_OF_FIELDS always available. Describe does nothing for + non-select operations. NUM_OF_FIELDS > 0 is now used to + select between oexec() and oexfet() in execute(). + Added more internal debugging. Improved test.pl. Changes in DBD::Oracle 0.42 (Oraperl 1.30), 28nd Oct 1996 - Fixed serious 'cache empty after re-bind' bug. - Do not use DBD::Oracle 0.41. - Implemented oexfet (combined execute and cache fetch) for - select operations. This is a further significant speed up. - Many selects now make only one trip to Oracle (after prepare) - which combines the execute and fetching multiple rows. + Fixed serious 'cache empty after re-bind' bug. + Do not use DBD::Oracle 0.41. + Implemented oexfet (combined execute and cache fetch) for + select operations. This is a further significant speed up. + Many selects now make only one trip to Oracle (after prepare) + which combines the execute and fetching multiple rows. Changes in DBD::Oracle 0.41 (Oraperl 1.30), 22nd Oct 1996 - Added the long overdue row cache to DBD::Oracle. - (Thanks to Reetnem@aol.com for providing a patch that prompted - me to complete the work.) - Oraperl $ora_cache and cache parameter to ora_open now work. - Default cache size is adjusted automatically for row width. - Major reworking of field buffer memory management. - Added a more internal debugging. - Further updates to the README files. + Added the long overdue row cache to DBD::Oracle. + (Thanks to Reetnem@aol.com for providing a patch that prompted + me to complete the work.) + Oraperl $ora_cache and cache parameter to ora_open now work. + Default cache size is adjusted automatically for row width. + Major reworking of field buffer memory management. + Added a more internal debugging. + Further updates to the README files. Changes in DBD::Oracle 0.40 (Oraperl 1.29), 14th Oct 1996 - WARNING - This release contains significant changes to the - placeholding binding code. You should test it carefully - before using in live systems. + WARNING - This release contains significant changes to the + placeholding binding code. You should test it carefully + before using in live systems. - Implemented PL/SQL output values via $sth->bind_param_inout. - See the code at the end of test.pl for example usage. + Implemented PL/SQL output values via $sth->bind_param_inout. + See the code at the end of test.pl for example usage. - Binding is now implemented using obndra rather than obndrv. - This may have a subtle effect when matching char fields - against placeholders with trailing spaces. + Binding is now implemented using obndra rather than obndrv. + This may have a subtle effect when matching char fields + against placeholders with trailing spaces. - Fixed bind_param ora_type attribute. Thanks to Stephen Zander - for the patch. Updated README's. Added README.longs. + Fixed bind_param ora_type attribute. Thanks to Stephen Zander + for the patch. Updated README's. Added README.longs. Changes in DBD::Oracle 0.39 (Oraperl 1.29), 23rd Sep 1996 - Fix for DEC "target := MACRO = string" Makefile syntax. - Added README notes from Dave Moellenhoff, Lou Henefeld and others. - Added README.login from James Taylor. - Added README.client with various notes about building DBD::Oracle - on minimaly configured client systems. - Extra parameters to ora_do are now passed to DBI's do(). - (This is an extension to the original oraperl ora_do.) + Fix for DEC "target := MACRO = string" Makefile syntax. + Added README notes from Dave Moellenhoff, Lou Henefeld and others. + Added README.login from James Taylor. + Added README.client with various notes about building DBD::Oracle + on minimaly configured client systems. + Extra parameters to ora_do are now passed to DBI's do(). + (This is an extension to the original oraperl ora_do.) Changes in DBD::Oracle 0.38 (Oraperl 1.28), 22th Aug 1996 - Overhaul of Makefile variable parsing. Should now cope with - complex variables which expand to nested shell escapes. - Try perl Makefile.PL -v to watch the fun. - Updated README, Makefile.PL and test.pl messages for clarity. - Fixed possible memory corruption in dbd_bind_ph(). + Overhaul of Makefile variable parsing. Should now cope with + complex variables which expand to nested shell escapes. + Try perl Makefile.PL -v to watch the fun. + Updated README, Makefile.PL and test.pl messages for clarity. + Fixed possible memory corruption in dbd_bind_ph(). Changes in DBD::Oracle 0.37 (Oraperl 1.28), 25th July 1996 - Fixed Makefile.PL for Oracle 7.3.2. - Fixed $num_fields = ora_fetch($csr) before first fetch for - queries with bind vars. - Fixed occasional core dump on global destruct. + Fixed Makefile.PL for Oracle 7.3.2. + Fixed $num_fields = ora_fetch($csr) before first fetch for + queries with bind vars. + Fixed occasional core dump on global destruct. Changes in DBD::Oracle 0.36 (Oraperl 1.28), 10th July 1996 - Fixed bind_param ora_type attribute. - Fixed preparse to allocate enough memory for worst case. - Fixed broken HP-UX 10 check in Makefile.PL. - Other assorted Makefile.PL improvements. - (Many thanks to those who sent in fixes.) + Fixed bind_param ora_type attribute. + Fixed preparse to allocate enough memory for worst case. + Fixed broken HP-UX 10 check in Makefile.PL. + Other assorted Makefile.PL improvements. + (Many thanks to those who sent in fixes.) Changes in DBD::Oracle 0.35 (Oraperl 1.28), 21st June 1996 - Fixed broken Solaris 2.5 check in Makefile.PL. - Added ld path to the log. + Fixed broken Solaris 2.5 check in Makefile.PL. + Added ld path to the log. Changes in DBD::Oracle 0.34 (Oraperl 1.28), 21st June 1996 - Workaround Solaris 2 bug #1224467 (_rmutex_unlock). - With many thanks to James Taylor. + Workaround Solaris 2 bug #1224467 (_rmutex_unlock). + With many thanks to James Taylor. - Added 'Bad free()' warning suppression to ora_logon and - ora_logoff(). Setting the DBD_DUMP environment variable - will trigger a (handy for me) core dump if a Bad free - warning is detected. + Added 'Bad free()' warning suppression to ora_logon and + ora_logoff(). Setting the DBD_DUMP environment variable + will trigger a (handy for me) core dump if a Bad free + warning is detected. - Further additions to the README about Bad free()'s. + Further additions to the README about Bad free()'s. Changes in DBD::Oracle 0.33 (Oraperl 1.27), 19th June 1996 - Added Makefile.PL -g option to enable debugging. - Added Makefile.PL -s symbol_name option to search for symbols. - Reorganised the way Makefile.PL uses MakeMaker liblist code. - Oraperl defaults to the 'safe' (normal) mode of using the DBI. - Oraperl uses sigtrap on SEGV & BUS to give a perl stack trace. - Added README notes about -g option, core files and stack traces. - Small change to $dbname/$user/$passwd logic in connect. + Added Makefile.PL -g option to enable debugging. + Added Makefile.PL -s symbol_name option to search for symbols. + Reorganised the way Makefile.PL uses MakeMaker liblist code. + Oraperl defaults to the 'safe' (normal) mode of using the DBI. + Oraperl uses sigtrap on SEGV & BUS to give a perl stack trace. + Added README notes about -g option, core files and stack traces. + Small change to $dbname/$user/$passwd logic in connect. Changes in DBD::Oracle 0.32 (Oraperl 1.25), 30th May 1996 - Fixed memory leak when FETCH'ing attributes. - Fixed Makefile.PL FileHandle problem (forgot 'use FileHandle;'). - Enhanced Makefile.PL support for Oracle 7.3. + Fixed memory leak when FETCH'ing attributes. + Fixed Makefile.PL FileHandle problem (forgot 'use FileHandle;'). + Enhanced Makefile.PL support for Oracle 7.3. Changes in DBD::Oracle 0.31 (Oraperl 1.25), 20th May 1996 - Makefile.PL for HP-UX now defaults to dynamic for hpux >= 10. + Makefile.PL for HP-UX now defaults to dynamic for hpux >= 10. - execute (ora_bind/ora_do) now returns undef on error or the - number of rows affected (0 is returned as 0E0, hence true, for - okay but no rows affected or no row count available/applicable). - This matches the oraperl version 2.4 behaviour. + execute (ora_bind/ora_do) now returns undef on error or the + number of rows affected (0 is returned as 0E0, hence true, for + okay but no rows affected or no row count available/applicable). + This matches the oraperl version 2.4 behaviour. - Made an attempt at supporting Oracle 7.3 (e.g. include's in proc.mk) - Please let me know if it works (else supply patches to fix it :-) + Made an attempt at supporting Oracle 7.3 (e.g. include's in proc.mk) + Please let me know if it works (else supply patches to fix it :-) - Fixed small memory leak in ora_titles etc functions. + Fixed small memory leak in ora_titles etc functions. Changes in DBD::Oracle 0.30, 7th May 1996 - THE ORAPERL EMULATION LAYER IS NOW FORMALLY RELEASED (NO LONGER ALPHA). + THE ORAPERL EMULATION LAYER IS NOW FORMALLY RELEASED (NO LONGER ALPHA). - Note that the underlying DBI and DBD::Oracle interfaces remain alpha - because they are still subject to (possibly significant) change. + Note that the underlying DBI and DBD::Oracle interfaces remain alpha + because they are still subject to (possibly significant) change. - Oraperl v2 used to return the string 'OK' to indicate success - with a zero numeric value. The Oraperl emulation now uses the - string '0E0' to achieve the same effect since it does not cause - any -w warnings when used in a numeric context. + Oraperl v2 used to return the string 'OK' to indicate success + with a zero numeric value. The Oraperl emulation now uses the + string '0E0' to achieve the same effect since it does not cause + any -w warnings when used in a numeric context. - Fixed typecast warning (s/safefree/Safefree). - Automatically sets/resets ORACLE_HOME from oratab value for sid. + Fixed typecast warning (s/safefree/Safefree). + Automatically sets/resets ORACLE_HOME from oratab value for sid. - TO DO: Automatic configuration from Oracle 7.3 is not yet working - (Oracle have reorganised the makefiles yet again!). + TO DO: Automatic configuration from Oracle 7.3 is not yet working + (Oracle have reorganised the makefiles yet again!). Changes in DBD::Oracle 0.29, 2 March 1996 - Fixed Makefile.PL to get DBIXS.h from right spot. - Changes to suit perl5.002 and site_lib directories. - Detects old versions ahead of new in @INC. - Random tidy-ups. + Fixed Makefile.PL to get DBIXS.h from right spot. + Changes to suit perl5.002 and site_lib directories. + Detects old versions ahead of new in @INC. + Random tidy-ups. Changes in DBD::Oracle 0.28, 29 Jan 1996: - Minor release for Perl5.002 (beta2 or later). - Requires Perl5.002 and DBI 0.66; + Minor release for Perl5.002 (beta2 or later). + Requires Perl5.002 and DBI 0.66; - Only functional change is to suppress (rare) 'handle not setup' - warnings unless debugging. + Only functional change is to suppress (rare) 'handle not setup' + warnings unless debugging. Changes in DBD::Oracle 0.27, 16 Nov 1995: - Improved oraperl compatibility in assorted ways. - Added the original oraperl manual to Oraperl.pm as pod. - (perldoc Oraperl will display the manual). - The manual highlights remaining differences in the emulation. - Added original oraperl examples into oraperl.ex directory. + Improved oraperl compatibility in assorted ways. + Added the original oraperl manual to Oraperl.pm as pod. + (perldoc Oraperl will display the manual). + The manual highlights remaining differences in the emulation. + Added original oraperl examples into oraperl.ex directory. - Improved error reporting in test.pl. - Removed some internal limits. - Renamed readblob to blob_read and fixed return value. - Implemented $sth = $dbh->tables method (see DBI changes file). - Uses $Config{archlibexp} not $Config{archlib} in makefile.PL - Requires DBI-0.65. + Improved error reporting in test.pl. + Removed some internal limits. + Renamed readblob to blob_read and fixed return value. + Implemented $sth = $dbh->tables method (see DBI changes file). + Uses $Config{archlibexp} not $Config{archlib} in makefile.PL + Requires DBI-0.65. - I've still not got around to implementing a row cache (array - fetch) but it's next on my list. + I've still not got around to implementing a row cache (array + fetch) but it's next on my list. - This should be the last alpha release of the oraperl emulation. - (The DBD::Oracle module itself will remain alpha for awhile yet.) + This should be the last alpha release of the oraperl emulation. + (The DBD::Oracle module itself will remain alpha for awhile yet.) Changes in DBD::Oracle 0.26, 23 Oct 1995: - Removed error message (sql) size limits in parse and ora_error. - Fixed FETCH NUM_OF_PARAMS so it doesn't trigger a describe. - The ora_lengths and ora_types attributes work in non-oraperl mode. + Removed error message (sql) size limits in parse and ora_error. + Fixed FETCH NUM_OF_PARAMS so it doesn't trigger a describe. + The ora_lengths and ora_types attributes work in non-oraperl mode. Changes in DBD::Oracle 0.25, 26 Aug 1995: - User visible changes: + User visible changes: - Fixed bug in parsing '?' style placeholders. - $sth->bind_param now checks for a too long LONG type string. - $sth->prepare now takes attributes: - ora_parse_lang => 0 | 1 | 2 (v6, auto v6/v7, v7) - ora_parse_defer => 0 | 1 (control defered parsing) + Fixed bug in parsing '?' style placeholders. + $sth->bind_param now checks for a too long LONG type string. + $sth->prepare now takes attributes: + ora_parse_lang => 0 | 1 | 2 (v6, auto v6/v7, v7) + ora_parse_defer => 0 | 1 (control defered parsing) - Other changes to be propogated to other drivers: + Other changes to be propogated to other drivers: - Added usage of new DBD_ATTRIB_* macros to XS and C code. - dbd_bind_ph return value inverted to make it consistent. - Added braces around XSRETURN_UNDEF in execute. - Checked for describe failure in FETCH. - Removed NumParams since it's now called NUM_OF_PARAMS in DBI. - Updated NEED_DBIXS_VERSION in Oracle.h + Added usage of new DBD_ATTRIB_* macros to XS and C code. + dbd_bind_ph return value inverted to make it consistent. + Added braces around XSRETURN_UNDEF in execute. + Checked for describe failure in FETCH. + Removed NumParams since it's now called NUM_OF_PARAMS in DBI. + Updated NEED_DBIXS_VERSION in Oracle.h Changes in DBD::Oracle 0.24, 22 Aug 1995: - User visible changes: + User visible changes: - $sth->bind_param method implemented (needs testing :-) - and new DBI $sth->bind_col* methods work for DBD::Oracle. + $sth->bind_param method implemented (needs testing :-) + and new DBI $sth->bind_col* methods work for DBD::Oracle. - Other changes to be propogated to other drivers: + Other changes to be propogated to other drivers: - - Slight change to STORE functions to allow them to return status - if called as $h->STORE(...). + - Slight change to STORE functions to allow them to return status + if called as $h->STORE(...). - - Revised signature of dbd_bind_ph function and added a bind_param - method for it. Prototype moved from dbdimp.h to Oracle.h + - Revised signature of dbd_bind_ph function and added a bind_param + method for it. Prototype moved from dbdimp.h to Oracle.h - - Revised execute method to use modified dbd_bind_ph function and - remove remaining oracle specifics. + - Revised execute method to use modified dbd_bind_ph function and + remove remaining oracle specifics. - - imp_xxh_t structures first element now called 'com' not 'dbihcom' - and new DBI macros used to access fields. + - imp_xxh_t structures first element now called 'com' not 'dbihcom' + and new DBI macros used to access fields. Changes in DBD::Oracle 0.23, 18 Aug 1995: - Fixed Oraperl.pm debug which was left on by default by accident. - Added small patches from Davide.Migliavacca@inferentia.it for - longs (dbtype_is_long, dbd_describe and dbd_st_readblob). - Added svr4 hints from Alan Burlison - Changed dbd_describe to return true for success (to be consistent). + Fixed Oraperl.pm debug which was left on by default by accident. + Added small patches from Davide.Migliavacca@inferentia.it for + longs (dbtype_is_long, dbd_describe and dbd_st_readblob). + Added svr4 hints from Alan Burlison + Changed dbd_describe to return true for success (to be consistent). Changes in DBD::Oracle 0.22, 17 Aug 1995: - Much more maturity, in line with the required DBI-0.60 release. - The .xs file is now very 'clean'. It's an excellent base for - developing other drivers. See notes in the DBI Changes file. + Much more maturity, in line with the required DBI-0.60 release. + The .xs file is now very 'clean'. It's an excellent base for + developing other drivers. See notes in the DBI Changes file. - The oraperl &ora_do should be working now (along with $sth->do()). - It does not leak (as far as I can tell). + The oraperl &ora_do should be working now (along with $sth->do()). + It does not leak (as far as I can tell). - This release is stable enough for general use again (like 0.20). - Please test heavily. + This release is stable enough for general use again (like 0.20). + Please test heavily. Changes in DBD::Oracle 0.21, 15 Aug 1995: - NOTE: THIS IS AN UNSTABLE RELEASE! - It requires the closely related DBI 0.59 release. - See Changes file in that release. - Major reworking of internal data management! + NOTE: THIS IS AN UNSTABLE RELEASE! + It requires the closely related DBI 0.59 release. + See Changes file in that release. + Major reworking of internal data management! - Only execute and fetchrow have yet to move into dbdimp.c. - These were kept back since I plan other associated changes. + Only execute and fetchrow have yet to move into dbdimp.c. + These were kept back since I plan other associated changes. - Known problems: - Warning mode is on by default so certain oraperl coding - styles cause warnings such as: - Statement handle ... destroyed without finish() at ... - disconnect(...) invalidates 1 associated cursor(s) at ... - In future oraperl mode handles will have those warnings disabled. - ...other changes to numerous/minor to mention + Known problems: + Warning mode is on by default so certain oraperl coding + styles cause warnings such as: + Statement handle ... destroyed without finish() at ... + disconnect(...) invalidates 1 associated cursor(s) at ... + In future oraperl mode handles will have those warnings disabled. + ...other changes to numerous/minor to mention Changes in DBD::Oracle 0.20, 1 Aug 1995: - Fixed core dump when binding an undef (treated as a NULL) - Binding a string longer that 2000 bytes will use LONG type. - Workaround OSF makefile and oratype.h problems - PL/SQL := construct will no longer confuse dbd_preparse() + Fixed core dump when binding an undef (treated as a NULL) + Binding a string longer that 2000 bytes will use LONG type. + Workaround OSF makefile and oratype.h problems + PL/SQL := construct will no longer confuse dbd_preparse() Changes in DBD::Oracle 0.19, 21 June 1995: - Added $VERSION - disconnect_all now gives error 'not implemented'. - Reworked memory management, imp_dbh's are cached. - imp_dbh_t now has an in_use flag and generation counter. - st::DESTROY now checks its imp_dbh for validity. - &ora_do() now returns "OK" for 0 rows (as per oraperl). - Reworked logging to use DBILOGFP macro. - Now test code added to loop through logon/prep/fin/logoff. - + Added $VERSION + disconnect_all now gives error 'not implemented'. + Reworked memory management, imp_dbh's are cached. + imp_dbh_t now has an in_use flag and generation counter. + st::DESTROY now checks its imp_dbh for validity. + &ora_do() now returns "OK" for 0 rows (as per oraperl). + Reworked logging to use DBILOGFP macro. + Now test code added to loop through logon/prep/fin/logoff. + Changes in DBD::Oracle 0.18: - Makefile.PL: HPUX now builds with LINKTYPE=static automatically. - Fixed errors on logout/global destruction. - Added logout/global destruction test to test.pl. - Changed Oraperl.pm default mode from safe to fast (see func_ref()). - Added platform who's-who list to README. - Added $sth->readblob($field, $offset, $length [, \$dest) method. - (You need to add the following after line 80 in DBI/DBI.pm: - 'readblob' => {'U'=>[4,5,'$field, $offset, $len [, \\$buf]']}, - in order to access the new readblob method.) + Makefile.PL: HPUX now builds with LINKTYPE=static automatically. + Fixed errors on logout/global destruction. + Added logout/global destruction test to test.pl. + Changed Oraperl.pm default mode from safe to fast (see func_ref()). + Added platform who's-who list to README. + Added $sth->readblob($field, $offset, $length [, \$dest) method. + (You need to add the following after line 80 in DBI/DBI.pm: + 'readblob' => {'U'=>[4,5,'$field, $offset, $len [, \\$buf]']}, + in order to access the new readblob method.) diff --git a/MANIFEST b/MANIFEST index 1d746b57..d0decafa 100644 --- a/MANIFEST +++ b/MANIFEST @@ -16,6 +16,7 @@ dbdimp.h dbdimp.c test.pl t/base.t +t/general.t t/plsql.t hints/svr4.pl .purify Ignore most of the (many) problems in Oracle's libraries. Very sad. diff --git a/Makefile.PL b/Makefile.PL index ef382ce6..480f3af8 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.57 1997/09/08 23:12:57 timbo Exp $ +# $Id: Makefile.PL,v 1.59 1998/05/25 22:11:34 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -6,6 +6,8 @@ BEGIN { require 5.003 } # 5.003 fixes very important bugs use ExtUtils::MakeMaker 5.16, qw(&WriteMakefile $Verbose); use Getopt::Long; use Config; +use Cwd; +use File::Find; use strict; # Some MakeMaker's forged some FileHandle methods @@ -22,9 +24,11 @@ BEGIN { if ($^O eq 'VMS') { # For those not using Dynamic loading this means building a # new static perl in the DBI directory by saying 'make perl' # and then using _that_ perl to make this one. -use DBI 0.86; +use DBI 0.92; use DBI::DBD; # DBD creation tools +my $dbi_dir = dbd_dbi_dir(); +my $dbi_arch_dir = dbd_dbi_arch_dir(); my $os = $^O; my $osvers = $Config{osvers}; $osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 @@ -32,13 +36,15 @@ $osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 my %opts = ( NAME => 'DBD::Oracle', VERSION_FROM => 'Oracle.pm', - DIR => [], - clean => { FILES=> 'Oracle.xsi' }, - dist => { DIST_DEFAULT=> 'clean distcheck disttest ci tardist', - PREOP => '$(MAKE) -f Makefile.old distdir' }, - COMPRESS => 'gzip -v9', SUFFIX => 'gz', + OBJECT => '$(O_FILES)', + DIR => [], + clean => { FILES=> 'Oracle.xsi' }, + dist => { DIST_DEFAULT => 'clean distcheck disttest ci tardist', + PREOP => '$(MAKE) -f Makefile.old distdir', + COMPRESS => 'gzip -v9', SUFFIX => 'gz', + }, ); -my(@MK, %MK, $MK); # parsed macros from Oracle's makefiles +my(@MK, %MK, $MK, %MK_expanding); # parsed macros from Oracle's makefiles # Options (rarely needed) $::opt_m = ''; # path to proc.mk or oracle.mk file to read @@ -54,140 +60,133 @@ GetOptions(qw(v! d! g! old! p! m=s s=s)) or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string $::opt_v = 1 if $::opt_d; $Verbose = 1 if $::opt_v; +my $use_clntsh = 1; -# --- Introduction -my $ORACLE_ENV = ($os eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; +# --- Introduction print "\n Configuring DBD::Oracle ...\n >>>\tRemember to actually *READ* the README file! \tEspecially if you have any problems.\n " unless $::opt_s; + # --- Where is Oracle installed... +my $ORACLE_ENV = ($os eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; + my $OH = $ENV{$ORACLE_ENV}; +$OH =~ s:\\:/:g; # for Win32 ($OH = unixify $OH) =~ s:/$:: if $os eq 'VMS'; die "$ORACLE_ENV environment variable must be set.\n" unless $OH; die "$ORACLE_ENV environment variable ($OH) not valid.\n" unless -d $OH; -my $OCIDIR = "OCI73"; # For MSWin32. XXX what about 7.4 etc? - # need to start "looking" for this... - print "Using Oracle in $OH\n"; - -my @mkplaces = qw( - rdbms/lib/oracle.mk rdbms/demo/oracle.mk rdbms/demo/demo_rdbms.mk - proc/lib/proc.mk precomp/demo/proc/proc.mk precomp/demo/proc/demo_proc.mk - proc16/lib/proc16.mk -); -# if -p then remove oracle.mk from search list and thus prefer Pro*C -@mkplaces = grep { !m/(oracle|rdbms)\.mk\b/ } @mkplaces if $::opt_p; -unshift @mkplaces, $::opt_m if $::opt_m; -my($mkfile, $place); -foreach $place (@mkplaces) { - $place = "$OH/$place" unless $place =~ m:^[./]:; - $mkfile = $place if -f $place; - last if $mkfile; +if ($::opt_s) { + print "Searching for symbol '$::opt_s' in $OH ...\n"; + my $dlext = $Config{dlext}; + system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; + do echo " searching \$i ..."; nm \$i | grep $::opt_s; + done + }); + print "Search done.\n"; + exit; } -if (!$mkfile and "@mkplaces" !~ m/oracle\.mk/) { - print "Unable to locate a Pro*C *.mk. Falling back to oracle.mk.\n"; - $mkfile = "$OH/oracle.mk"; - push @mkplaces, $mkfile; # just for error message below + + +# --- How shall we link with Oracle? Let me count the ways... + +my @mkfiles; +my $linkwith; +my $linkwith_msg; + +if ($os eq 'VMS') { + my $OCIINCLUDE = vmsify("$OH/rdbms/") ." ". vmsify("$OH/rdbms/demo/oci_demo/"); + $opts{INC} = "$OCIINCLUDE $dbi_arch_dir"; + $opts{OBJECT} = 'oracle.obj dbdimp.obj'; } -die qq{ - Unable to locate an oracle.mk or proc.mk file in your Oracle installation. - (Looked in @mkplaces) - The oracle.mk file is part of the Oracle RDBMS product. The - proc.mk file is part of the Oracle Pro*C product. You need to - build DBD::Oracle on a system which has one of these installed. +elsif ($os eq 'MSWin32') { + my $OCIDIR = ""; + find( sub { + print "Found $_\n" if /^OCI\d+/i; + $OCIDIR = $_ if /^OCI\d\d$/i && $OCIDIR lt $_; + $File::Find::prune = 1 if -d $_ && $_ ne "." && $_ ne ".."; + }, $OH ); + print "Using OCI directory: $OCIDIR\n"; + + my $oci_compiler_dir = ($Config{cc} eq 'bcc32' ? "BORLAND" : "MSVC"); + die qq{ + Unable to find required Oracle OCI files for the build. Please check + that you have your OCI installed in your oracle home ($OH) + directory and that it has the following files (and probably more): + + $OH\\$OCIDIR\\include\\oratypes.h + $OH\\$OCIDIR\\lib\\$oci_compiler_dir\\ociw32.lib - If your oracle.mk or proc.mk file is installed somewhere - non-standard you can specify where it is using the -m option: - perl Makefile.PL -m /path/to/your.mk + Please install OCI or send comments back to dbi-users\@fugue.com you + have an OCI directory other than $OCIDIR. + + } unless (-e "$OH/$OCIDIR/include/oratypes.h" + && -e "$OH/$OCIDIR/lib/$oci_compiler_dir/ociw32.lib"); + + my $OCIINCLUDE = "-I$OH/$OCIDIR/include -I$OH/rdbms/demo"; + $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/$oci_compiler_dir -lOCIW32" ]; + $opts{SKIP} = ['processPL']; # XXX caused problems with Nmake... + $opts{INC} = "$OCIINCLUDE -I$dbi_arch_dir"; +} - See README.clients for more information and some alternatives. +# --- UNIX Variants --- -} unless ($os eq 'MSWin32') || ($os eq 'VMS') || ($mkfile && -f $mkfile); +elsif (@_=grep { m:/lib(clntsh|oracle).$Config{so}$:o } <$OH/lib/lib*>) { + # --- the simple modern way --- + my $lib = ("@_" =~ m:/libclntsh\.:) ? "clntsh" : "oracle"; + $linkwith_msg = "$lib"; + $opts{LIBS} = [ "-L$OH/lib -l$lib" ]; + $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; + $opts{INC} = "-I$OH/rdbms/demo -I$dbi_arch_dir"; +} +else { # --- trawl the guts of Oracle's make files looking the how it wants to link -my(@mkfiles, $linkvia, $libhome, $linkwith, $linkwith_s, @linkwith_o, $OCIINCLUDE); + my @ora_libs = <$OH/lib/lib*>; + warn "\nYou don't seem to have many Oracle libraries installed. If the" + ."\nbuild fails you probably need to install more Oracle software.\n\n" + if @ora_libs < 6; # just a helpful hint -if ($os ne 'MSWin32' and $os ne 'VMS') { - $linkvia = fetch_oci_macros($mkfile); - $libhome = expand_mkvars($MK{LIBHOME}, 0, 1, 0) || "$OH/lib"; + my $mkfile = find_mkfile(); + my $linkvia = fetch_oci_macros($mkfile); + my $libhome = expand_mkvars($MK{LIBHOME}, 0, 1, 0) || "$OH/lib"; $linkwith = expand_mkvars($linkvia, 0, 1, 0); $linkwith =~ s/-Y P,/-YP,/g if $Config{'cc'} =~ /gcc/; $linkwith =~ s:-R /:-R/:g if $os eq 'solaris'; # get a cut down $linkwith to pass to MakeMaker liblist - $linkwith_s = expand_mkvars($linkwith, 1, 1, 0); - + my $linkwith_s = expand_mkvars($linkwith, 1, 1, 0); # delete problematic crt?.o on solaris $linkwith_s = del_crtobj($linkwith_s) if $os eq 'solaris'; - # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" - $linkwith_s =~ s!([/\w.]+)/lib(\w+).a!-L$1 -l$2!g; + $linkwith_s =~ s!(\S+)/lib(\w+).a!-L$1 -l$2!g; # extract object files, keep for use later + my @linkwith_o; push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; # also extract AIX .exp files since they confuse MakeMaker push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; - if ($::opt_s) { - print "Searching for symbol '$::opt_s' in $OH ...\n"; - my $dlext = $Config{dlext}; - system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; - do echo " searching \$i ..."; nm \$i | grep $::opt_s; - done - }); - print "Search done.\n"; - exit; - } - - if ($os eq 'solaris' and $osvers >= 2.3 - and $linkwith_s =~ /-lthread/) { + if ($os eq 'solaris' and $osvers >= 2.3 and $linkwith_s =~ /-lthread/) { print "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; print "Deleting -lthread from link list as a possible workround.\n"; $linkwith_s =~ s/\s*-lthread\b/ /g; } - $OCIINCLUDE = $MK{INCLUDE} || ''; + $linkwith_msg = "@linkwith_o $linkwith_s [from $linkvia]"; + my $OCIINCLUDE = $MK{INCLUDE} || ''; $OCIINCLUDE .= " -I$OH/rdbms/demo"; $opts{LIBS} = [ "-L$libhome $linkwith_s" ]; - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o \$(COMPOBJS)" }; - $opts{OBJECT} = '$(O_FILES)'; - $opts{INC} = "$OCIINCLUDE -I\$(INSTALLSITEARCH)/auto/DBI"; -} -elsif ($os eq 'MSWin32') { - # this assumes MSVC... - # find OCI dir here... - die qq{ - Unable to find required Oracle OCI files for the build. Please check - that you have your OCI installed in your oracle home ($OH) - directory and that it has the following files (and probably more): - - $OH\\$OCIDIR\\include\\oratypes.h - $OH\\$OCIDIR\\lib\\msvc\\ociw32.lib - - Please install OCI or send comments back to dbi-users\@fugue.com you - have an OCI directory other than $OCIDIR. - - } unless (-e "$OH/$OCIDIR/include/oratypes.h" - && -e "$OH/$OCIDIR/lib/msvc/ociw32.lib"); - - $OCIINCLUDE = "-I$OH/$OCIDIR/include -I$OH/rdbms/demo"; - $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/MSVC/OCIW32.LIB"]; - $opts{dynamic_lib} = { OTHERLDFLAGS => " $OH/$OCIDIR/LIB/MSVC/OCIW32.LIB" }; - $opts{SKIP} = ['processPL']; # XXX caused problems with Nmake... - $opts{OBJECT} = '$(O_FILES)'; - $opts{INC} = "$OCIINCLUDE -I\$(INSTALLSITEARCH)/auto/DBI"; -} -elsif ($os eq 'VMS') { - $OCIINCLUDE = vmsify("$OH/rdbms/") ." ". vmsify("$OH/rdbms/demo/oci_demo/"); - $opts{OBJECT} = 'oracle.obj dbdimp.obj'; - $opts{INC} = "$OCIINCLUDE \$(INSTALLSITEARCH)/auto/DBI"; + my $compobj = '$(COMPOBJS)'; + $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o $compobj" }; + $opts{INC} = "$OCIINCLUDE -I$dbi_arch_dir"; } @@ -199,20 +198,17 @@ elsif ($os eq 'VMS') { if ($os eq 'hpux' and $osvers < 10) { $opts{LINKTYPE} = 'static'; print "Warning: Forced to build static not dynamic on $os $osvers.\a\n"; - print "** Note: DBD::Oracle will be built *into* a NEW perl binary. You MUST use that new perl.\n"; - print " See README and Makefile.PL for more information.\a\n"; } if ($os eq 'hpux' and $osvers >= 10) { - print "Warning: You may need to build using static linking. See the README file.\n\a"; + print "Warning: You may need to build using static linking. See the README file.\n\a"; } if ($os eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { - print "Warning: You may need to rebuild perl using the xlc_r compiler.\a\n"; - print " You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV\n"; + print "Warning: You may need to rebuild perl using the xlc_r compiler.\a\n"; + print " You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV\n"; } -$opts{DEFINE} = '-Wall -pedantic -Wno-comment -Wtraditional' - if $Config{cc} eq 'gcc'; +$opts{DEFINE} = '-Wall -Wno-comment' if $Config{cc} eq 'gcc'; $opts{DEFINE} .= '-Xa' if $Config{cc} eq 'clcc'; # CenterLine CC @@ -222,15 +218,25 @@ print "WARNING: Your GNU C compiler is very old. Please upgrade.\n" # Set some private WriteMakefile options if this is 'me' :-) if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess $Verbose = 1; - $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith' + $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith -pedantic -Wtraditional' . ' -Wbad-function-cast -Wcast-qual' if $Config{cc} eq 'gcc'; } -# log key platform information to help me help you quickly +if ($opts{LINKTYPE} && $opts{LINKTYPE} eq 'static') { + print "** Note: DBD::Oracle will be built *into* a NEW perl binary. You MUST use that new perl.\n"; + print " See README and Makefile.PL for more information.\a\n"; +} + + +# --- final information dumps and generation of the Makefile + +# log key platform information to help others help you quickly if needed +print "\n"; print "System: perl$] @Config{qw(myuname)}\n"; print "Compiler: @Config{qw(cc optimize ccflags)}\n"; print "Linker: ". (find_bin('ld')||"not found") ."\n" unless $os eq 'VMS'; -print "Oracle proc.mk would have used these values but we override them:\n"; +print "Oracle makefiles would have used these values but we override them:\n" + if $MK{CFLAGS} || $MK{LDFLAGS} || $MK{LDSTRING}; print " CC: $MK{CC}\n" if $MK{CC}; print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; print " [".mkvar('CFLAGS',1,0,0). "]\n" if $MK{CFLAGS}; @@ -238,7 +244,7 @@ print " LDFLAGS: $MK{LDFLAGS}\n" if $MK{LDFLAGS}; print " [".mkvar('LDFLAGS',1,0,0). "]\n" if $MK{LDFLAGS}; print " LDSTRING: $MK{LDSTRING}\n" if $MK{LDSTRING}; print " [".mkvar('LDSTRING',1,0,0)."]\n" if $MK{LDSTRING}; -print "\nLinking with @linkwith_o $linkwith_s [from $linkvia]\n"; +print "\nLinking with $linkwith_msg\n" if $linkwith_msg; print "\n"; WriteMakefile(%opts); @@ -246,6 +252,9 @@ WriteMakefile(%opts); exit 0; +# ===================================================================== + + sub MY::post_initialize { my $self = shift; @@ -264,21 +273,23 @@ directories. Since site_lib directories come after the normal library directories you must delete any old DBD::Oracle files and directories from your 'privlib' and 'archlib' directories and their auto subdirectories. "; - my $find = "find $Config{privlibexp} $Config{archlibexp} "; - $find .= "-name 'Oracle*' -print | sort | uniq"; - if ($os ne 'VMS' and open(FIND, "$find |")) { - my @old; - while() { - next if m:^$Config{sitelibexp}/:; - next if m:^$Config{sitearchexp}/:; - chop; - push @old, $_; - } - close(FIND); - print "Here's a list of probable old files and directories:\n ", - join("\n ",@old),"\n" if @old; - print "\n"; - } + if ( $os ne 'VMS' ) { + my ( $sl_exp, $sa_exp, $pl_exp, $al_exp, %old ); + ( $sl_exp = $Config{sitelibexp} ) =~ s:\\:/:g; + ( $sa_exp = $Config{sitearchexp} ) =~ s:\\:/:g; + ( $pl_exp = $Config{privlibexp} ) =~ s:\\:/:g; + ( $al_exp = $Config{archlibexp} ) =~ s:\\:/:g; + my $wanted = sub { + $File::Find::prune = ($File::Find::name eq $sl_exp || + $File::Find::name eq $sa_exp ) && -d $_; + $old{$File::Find::name} = 1 + if ! $File::Find::prune && /^Oracle/; + }; + find( $wanted, $pl_exp, $al_exp ); + print "Here's a list of probable old files and directories:\n ", + join( "\n ", sort keys %old ), "\n" if keys %old; + print "\n"; + } } # Ensure Oraperl.pm and oraperl.ph are installed into top lib dir @@ -291,8 +302,9 @@ your 'privlib' and 'archlib' directories and their auto subdirectories. ''; } + sub MY::postamble { - return dbd_postamble(); + return dbd_postamble(@_); } @@ -306,7 +318,7 @@ sub MY::post_constants { # ORACLE_HOME = '.$OH.' -# The following text has been extracted from '."@mkfiles".' +# The following text has been extracted from '.join("\n#\t", '', @mkfiles).' '.$MK.' @@ -318,15 +330,66 @@ ORACLE_HOME = '.$OH.' sub del_crtobj { - my $str = shift; + my $orig = shift; + my $str; # E.g. for changing the COMPOBJS line (and sometimes LDSTRING) - # old: $(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/__fstd.o - # new: $(COMPOBJ)/__fstd.o - $str =~ s:\$\S+?/crt[1in]\.o\b::g; + # old: COMPOBJS=$(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/__fstd.o + # new: COMPOBJS=$(COMPOBJ)/__fstd.o + ($str = $orig) =~ s:[^\s=]*\bcrt[1in]\.o\b::g; + warn "del_crtobj: $orig\n : $str\n" if $orig ne $str and $::opt_v; return $str; } +sub find_mkfile { + + my @mkfiles; + my @mkplaces = qw( + proc/lib/proc.mk precomp/demo/proc/proc.mk precomp/demo/proc/demo_proc.mk + rdbms/lib/oracle.mk rdbms/demo/oracle.mk rdbms/demo/demo_rdbms.mk + proc16/lib/proc16.mk + ); + # if -p then remove oracle.mk from search list and thus prefer Pro*C + @mkplaces = grep { !m/(oracle|rdbms)\.mk\b/ } @mkplaces if $::opt_p; + if ($::opt_m) { + $::opt_m = cwd()."/$::opt_m" unless $::opt_m =~ m:/\\:; + die "-m $::opt_m: not found" unless -f $::opt_m; + unshift @mkplaces, $::opt_m; + } + my ($mkfile, $place); + foreach $place (@mkplaces) { + $place = "$OH/$place" unless $place =~ m:^[/\.]:; # abs or relative path + next unless -f $place; + push @mkfiles, $place; + print "Found $place\n"; + } + $mkfile = $mkfiles[0]; # use first one found + if (!$mkfile and "@mkplaces" !~ m/oracle\.mk/) { + print "Unable to locate a Pro*C *.mk. Falling back to oracle.mk.\n"; + $mkfile = "$OH/oracle.mk"; + push @mkplaces, $mkfile; # just for error message below + } + die qq{ + Unable to locate an oracle.mk or proc.mk file in your Oracle installation. + (Looked in @mkplaces) + + The oracle.mk file is part of the Oracle RDBMS product. The + proc.mk file is part of the Oracle Pro*C product. You need to + build DBD::Oracle on a system which has one of these installed. + + If your oracle.mk or proc.mk file is installed somewhere + non-standard you can specify where it is using the -m option: + perl Makefile.PL -m /path/to/your.mk + + See README.clients for more information and some alternatives. + + } unless ($os eq 'MSWin32') || ($os eq 'VMS') || ($mkfile && -f $mkfile); + + print "Using $mkfile\n"; + return $mkfile; +} + + sub fetch_oci_macros { my $file = shift; @@ -336,9 +399,9 @@ sub fetch_oci_macros { # Don't include the following definitions in the generated # makefile (note that %MK stills gets these values). my @edit = qw( - SHELL CC CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS - AR ECHO EXE OBJS PERL OBJ_EXT LIB_EXT - ); + SHELL CC CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS + AR ECHO EXE OBJS PERL OBJ_EXT LIB_EXT + ); my %edit; @edit{@edit} = ('$_ = ""') x @edit; $edit{COMPOBJS} = q{ @@ -356,8 +419,12 @@ sub fetch_oci_macros { } }; + # deal with (some subversions) of Oracle8.0.3's incompatible use of OBJ_EXT + my $incompat_ext = ($MK{OBJ_EXT} && $MK{OBJ_EXT} !~ /^\./); + warn "OBJ_EXT correction enabled ($MK{OBJ_EXT})\n" if $incompat_ext; + my $mkver = 0; - my $linkwith = ''; + my $linkvia = ''; my $lastline = ''; my @lines = read_inc_file($file); for(1; $_ = shift(@lines); $lastline = $_){ @@ -367,9 +434,10 @@ sub fetch_oci_macros { push @MK, '' if $_ eq '' and $lastline ne ''; # squeeze multiple blank lines next unless $_; - # deal with Oracle8's incompatible use of OBJ_EXT - s/\.(\$\(OBJ_EXT\))/$1/g; - s/\.(\$\(LIB_EXT\))/$1/g; + if ($incompat_ext) { + s/\.(\$\(OBJ_EXT\))/$1/g; + s/\.(\$\(LIB_EXT\))/$1/g; + } if ($::opt_old) { last if m/^\w+\s*:[^=]/; # gone too far, reached actual targets @@ -415,26 +483,32 @@ sub fetch_oci_macros { push(@MK, $_); } - if ($MK{OCILDLIBS}) { - $linkwith = '$(OCILDLIBS)'; - - } elsif (int($mkver) == 1) { + if ($MK{LCLSH} and $use_clntsh) { + $linkvia = '$(LCLSH)'; + } + elsif ($MK{LLIBCLNTSH} and $use_clntsh) { + $linkvia = '$(LLIBCLNTSH)'; + } + elsif ($MK{OCILDLIBS}) { + $linkvia = '$(OCILDLIBS)'; + } + elsif (int($mkver) == 1) { if ($MK{LLIBOCIC}) { - $linkwith = '$(LLIBOCIC) $(TTLIBS)'; + $linkvia = '$(LLIBOCIC) $(TTLIBS)'; } else { print "Warning: Guessing what to link with.\n"; - $linkwith = '-locic $(TTLIBS)'; # XXX GUESS HACK + $linkvia = '-locic $(TTLIBS)'; # XXX GUESS HACK } } elsif ($MK{PROLDLIBS}) { # Oracle 7.3.x - $linkwith = '$(PROLDLIBS)'; + $linkvia = '$(PROLDLIBS)'; } - unless ($linkwith){ + unless ($linkvia){ die "ERROR parsing $file: Unable to determine what to link with.\n" ."Please send me copies of these files (one per mail message):\n@mkfiles\n"; } $MK = join("\n", @MK); - return $linkwith; + return $linkvia; } @@ -495,10 +569,15 @@ sub mkvar { return $ENV{$ORACLE_ENV} if $var eq 'ORACLE_HOME'; my $val = $MK{$var}; if (!defined $val and exists $ENV{$var}) { - $val = $ENV{$var}; - print "Using value of $var from environment: $val\n"; + $val = $ENV{$var}; + print "Using value of $var from environment: $val\n"; } return $default unless defined $val; + if ($MK_expanding{$var}) { + print "Definition of \$($var) includes \$($var).\n"; + return "\$($var)"; + } + local($MK_expanding{$var}) = 1; return expand_mkvars($val, $strip, $backtick, $level+1); # can recurse } @@ -552,6 +631,3 @@ $(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt rtls.opt $(INST_ARC } __END__ - -test.xs: $(INSTALLSITEARCH)/auto/DBI/Driver.xst - perl -p -e 's/{DRIVER}/$(BASEEXT)/g' < $(INSTALLSITEARCH)/auto/DBI/Driver.xst > test.xs diff --git a/Oracle.pm b/Oracle.pm index 43f60fde..99dc8960 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,4 +1,5 @@ -# $Id: Oracle.pm,v 1.47 1997/09/08 23:12:57 timbo Exp $ + +# $Id: Oracle.pm,v 1.49 1998/05/25 22:26:55 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997 Tim Bunce # @@ -9,27 +10,29 @@ require 5.002; +$DBD::Oracle::VERSION = '0.48'; + my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; -my $oracle_home = $ENV{$ORACLE_ENV}; { package DBD::Oracle; use DBI (); use DynaLoader (); - @ISA = qw(DynaLoader); + use Exporter (); + @ISA = qw(DynaLoader Exporter); - $VERSION = '0.47'; - my $Revision = substr(q$Revision: 1.47 $, 10); + my $Revision = substr(q$Revision: 1.49 $, 10); - require_version DBI 0.85; + require_version DBI 0.92; bootstrap DBD::Oracle $VERSION; - $err = 0; # holds error code for DBI::err - $errstr = ""; # holds error string for DBI::errstr + $err = 0; # holds error code for DBI::err (XXX SHARED!) + $errstr = ""; # holds error string for DBI::errstr (XXX SHARED!) $drh = undef; # holds driver handle once initialised %oratab = (); # holds list of oratab databases (e.g., local) + %tnstab = (); # holds list of names in tnsnames.ora sub driver{ return $drh if $drh; @@ -63,25 +66,55 @@ my $oracle_home = $ENV{$ORACLE_ENV}; { package DBD::Oracle::dr; # ====== DRIVER ====== use strict; + my %oratab; + my %tnstab; - sub load_oratab { # get list of 'local' databases - my($drh) = @_; + sub load_oratab { # get list of 'local' database SIDs + my ($drh) = @_; my $debug = $drh->debug; - foreach(qw(/etc /var/opt/oracle), $ENV{TNS_ADMIN}) { - next unless defined $_; - warn "Checking for $_/oratab\n" if $debug; + foreach (qw(/etc /var/opt/oracle), $ENV{TNS_ADMIN}) { + next unless defined $_; next unless open(ORATAB, "<$_/oratab"); - while() { - next unless m/^(\w+)\s*:\s*(.*?)\s*:/; - warn "Duplicate SID $1 in $_/oratab" if $DBD::Oracle::oratab{$1}; - $DBD::Oracle::oratab{$1} = $2; # store ORACLE_HOME value - warn "$DBD::Oracle::oratab{$1} = $_" if $debug; + warn "Loading $_/oratab\n" if $debug; + while () { + next unless m/^\s*(\w+)\s*:\s*(.*?)\s*:/; + $oratab{$1} = $2; # store ORACLE_HOME value + warn "Found $oratab{$1} = $_" if $debug; } close(ORATAB); last; - } + } + $oratab{' dummy '} = 1; # prevent reloads } + sub load_tnstab { # get list of 'remote' database connection identifiers + my ($drh) = @_; + my $debug = $drh->debug; + my $oracle_home = $ENV{$ORACLE_ENV} || ''; + my $d; + foreach $d ($ENV{TNS_ADMIN}, "$oracle_home/network/admin", '/var/opt/oracle') { + next unless defined $d; + next unless open(TNSTAB, "<$d/tnsnames.ora"); + warn "Loading $d/tnsnames.ora\n" if $debug; + while () { + next unless m/^\s*([\w\.]+)\s*=/; + $tnstab{$1} = 1; + warn "Found $1" if $debug; + } + close(TNSTAB); + last; + } + $tnstab{' dummy '} = 1; # prevent reloads + } + + sub data_sources { + my $drh = shift; + load_oratab($drh) unless %oratab; + load_tnstab($drh) unless %tnstab; + return (keys %oratab, keys %tnstab); # done't eliminate dups + } + + sub connect { my($drh, $dbname, $user, $auth)= @_; @@ -107,27 +140,26 @@ my $oracle_home = $ENV{$ORACLE_ENV}; # Sadly the 'user/passwd@machine' form only works # for Sql*NET connections. - load_oratab($drh) unless %DBD::Oracle::oratab; + load_oratab($drh) unless %oratab; + load_tnstab($drh) unless %tnstab; - my $orahome = $DBD::Oracle::oratab{$dbname}; - if ($orahome) { # is in oratab == is local + if ($tnstab{$dbname}) { + $user .= '@'.$dbname; # assume it's a TNS alias + } + elsif ($oratab{$dbname}) { # is in oratab == is local warn "Changing $ORACLE_ENV for $dbname" - if ($ENV{$ORACLE_ENV} and $orahome ne $ENV{$ORACLE_ENV}); - $ENV{$ORACLE_ENV} = $orahome; + if ($ENV{$ORACLE_ENV} and $oratab{$dbname} ne $ENV{$ORACLE_ENV}); + $ENV{$ORACLE_ENV} = $oratab{$dbname}; $ENV{ORACLE_SID} = $dbname; delete $ENV{TWO_TASK}; } else { - $user .= '@'.$dbname; # assume it's an alias + $user .= '@'.$dbname; # assume it's a TNS alias } } } - unless($ENV{$ORACLE_ENV}) { # last chance... - $ENV{$ORACLE_ENV} = $oracle_home if $oracle_home; - my $msg = ($oracle_home) ? "set to $oracle_home" : "not set!"; - warn "$ORACLE_ENV $msg\n"; - } + warn "$ORACLE_ENV not set!\n" unless $ENV{$ORACLE_ENV}; # create a 'blank' dbh @@ -196,21 +228,58 @@ my $oracle_home = $ENV{$ORACLE_ENV}; } sub plsql_errstr { - my ($dbh) = @_; - # with thanks to Bob Menteer - my (@msg, $line,$pos,$text); - my $sth = $dbh->prepare(q{ + # original version thanks to Bob Menteer + my $sth = shift->prepare_cached(q{ select line,position,text from user_errors order by sequence }); return undef unless $sth; $sth->execute or return undef; + my (@msg, $line,$pos,$text); while(($line,$pos,$text) = $sth->fetchrow){ push @msg, "Error in PL/SQL block" unless @msg; push @msg, "$line.$pos: $text"; } join("\n", @msg); } -} + + # + # note, dbms_output must be enabled prior to usage + # + sub dbms_output_enable { + my ($dbh, $buffersize) = @_; + $buffersize ||= 20000; # use oracle 7.x default + $dbh->do("begin dbms_output.enable(:1); end;", undef, $buffersize); + } + + sub dbms_output_get { + my $dbh = shift; + my $sth = $dbh->prepare_cached("begin dbms_output.get_line(:1, :2); end;") + or return; + my ($line, $status, @lines); + # line can be greater that 255 (e.g. 7 byte date is expanded on output) + $sth->bind_param_inout(1, \$line, 400); + $sth->bind_param_inout(2, \$status, 20); + if (!wantarray) { + $sth->execute or return undef; + return $line if $status == 0; + return undef; + } + push @lines, $line while($sth->execute && $status==0); + return @lines; + } + + sub dbms_output_put { + my $dbh = shift; + my $sth = $dbh->prepare_cached("begin dbms_output.put_line(:1); end;") + or return; + my $line; + foreach $line (@_) { + $sth->execute($line) or return; + } + return 1; + } + +} # end of package DBD::Oracle::db { package DBD::Oracle::st; # ====== STATEMENT ====== @@ -632,7 +701,7 @@ DBD::Oracle by Tim Bunce. =head1 COPYRIGHT -The DBD::Oracle module is Copyright (c) 1995,1996,1997 Tim Bunce. England. +The DBD::Oracle module is Copyright (c) 1995,1996,1997,1998 Tim Bunce. England. The DBD::Oracle module is free software; you can redistribute it and/or modify it under the same terms as Perl itself with the exception that it cannot be placed on a CD-ROM or similar media for commercial distribution diff --git a/Oraperl.pm b/Oraperl.pm index e3830205..6d653e32 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.35 1997/09/08 22:43:59 timbo Exp $ +# $Id: Oraperl.pm,v 1.36 1998/05/25 22:11:34 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -25,7 +25,7 @@ require 5.002; use DBI 0.84; use Exporter; -$VERSION = substr(q$Revision: 1.35 $, 10); +$VERSION = substr(q$Revision: 1.36 $, 10); @ISA = qw(Exporter); @@ -279,6 +279,7 @@ those who wish to extend the routines or to port them to new machines. The text in this document is largely unchanged from the original Perl4 oraperl manual written by Kevin Stock . Any comments specific to the DBD::Oracle Oraperl emulation are prefixed by B. +See the DBD::Oracle and DBI manuals for more information. B In order to make the oraperl function definitions available in perl5 you need to arrange to 'use' the Oraperl.pm module in each file diff --git a/README b/README index 7295263a..47a2cfd7 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ -DBD::Oracle -- an Oracle 7 interface for Perl 5. +DBD::Oracle -- an Oracle 7 and Oracle 8 interface for Perl 5. - Copyright (c) 1994,1995,1996,1997 Tim Bunce + Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce, England. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file, @@ -23,7 +23,7 @@ WARNING: | Execute "perldoc Oraperl" after installing for full information. | -QUICK START GUIDE: +*** QUICK START GUIDE: The DBI requires one or more 'driver' modules to talk to databases. Fetch, build and install the DBI module as per it's README file. @@ -33,21 +33,22 @@ QUICK START GUIDE: Follow the guidelines in this README file caefully. -*BEFORE* BUILDING, TESTING AND INSTALLING this you will need to: +*** *BEFORE* BUILDING, TESTING AND INSTALLING this you will need to: - Build, test and install Perl 5 (at least 5.003). + Build, test and install Perl 5 (at least 5.003, preferably + version 5.004_01 or later). It is very important to TEST it and INSTALL it! - Build, test and install the DBI module (at least DBI 0.71). + Build, test and install the DBI module (at least DBI 0.86). It is very important to TEST it and INSTALL it! - Remember to *read* the DBI README file and this one fully! + Remember to *read* the DBI README file and this one CAREFULLY! Install enough Oracle software to enable DBD::Oracle to build. That includes Pro*C. -BUILDING: +*** BUILDING: perl Makefile.PL # use a perl that's in your PATH make @@ -76,7 +77,7 @@ value before starting the test. Please read README.login. make install (if the tests look okay) -IF YOU HAVE PROBLEMS: +*** IF YOU HAVE PROBLEMS: Make sure you are using a recent perl 5.003 or preferably 5.004 and make sure it's on your path so you can say 'perl Makefile.PL' and @@ -110,10 +111,14 @@ then you could try forcing a 'static' build using: make -f Makefile.aperl inst_perl MAP_TARGET=perl make install -Also read the README.help file which is full of useful tips and -workarounds for various problems of various systems. -Please don't post problems to comp.lang.perl.misc or perl5-porters. +>>> Also carefully read the README.help file which is full of useful +>>> tips and workarounds for various problems of various systems. + + +*** HOW TO REPORT PROBLEMS + +Please don't post problems to comp.lang.perl.* or perl5-porters. This software is supported via the dbi-users mailing list. For more information and to keep informed about progress you can join the a mailing list via http://www.fugue.com/dbi (if you are unable to use the @@ -125,22 +130,23 @@ dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. But note... ** IT IS IMPORTANT TO INCLUDE *ALL* THE FOLLOWING INFORMATION: -1. A complete log of a all steps of the build, e.g.: +1. A complete log of all steps of the build, e.g.: (do a make realclean first) - perl Makefile.PL -v (note the -v for verbose) - make - make test - make test TEST_VERBOSE=1 (only if any of the t/* tests fail) + perl Makefile.PL -v (note the -v for verbose) + make + make test + make test TEST_VERBOSE=1 (only if any of the t/* tests fail) 2. Full details of which version of Oracle you're using. -3. The output of perl -V +3. The output of perl -V (that a capital V, not lowercase) -4. If you get errors like "undefined symbol", "symbol not found" - or "Text relocation remains" then include the output of - "perl Makefile.PL -s XXX" where XXX is the name of one of the - symbols. Please don't send the entire output of this command, +4. If you get errors like "undefined symbol", "symbol not found", + "undefined reference", "Text relocation remains" or any similar + error then include the output of "perl Makefile.PL -s XXX" + where XXX is the name of one of the symbols. + Please don't send the entire output of this command, just any obviously 'interesting' parts (if there are any). See also the LINKTYPE=static notes above. @@ -169,12 +175,12 @@ Tim. =============================================================================== Examples and other info: -README.help -- Read it first if you have any problems at all +README.help -- READ IT FIRST IF YOU HAVE ANY PROBLEMS AT ALL! README.clients -- building/using DBD::Oracle on minimally configured systems README.login -- help for login problems README.longs -- examples dealing with LONG types (blobs) -DBI 'home page': http://www.hermetica.com/technologia/DBI +DBI 'home page': http://www.arcana.co.uk/technologia/DBI Master archive site for Perl DB information: ftp://ftp.demon.co.uk/pub/perl/db/ @@ -228,11 +234,15 @@ Some platforms on which the DBI and DBD::Oracle modules run: Motorola M88100 (SVR3.2) DEC UNIX 3.2 DEC Alpha - OSF/1 v2 + DG/UX 5.4 + OSF/1 SGI IRIX 5 & 6 - AIX 3 & 4 and others + AIX 3 & 4 + Pyramid SMP DC/OSx + VMS + and others -(please let me know if you system is not listed). +(please let me know if your system is not listed). =============================================================================== diff --git a/README.clients b/README.clients index 2151ffd5..4446fea4 100644 --- a/README.clients +++ b/README.clients @@ -192,3 +192,84 @@ But this is what my sales rep tells me as of today. Mark ------------------------------------------------------------------------------- + +From: Wintermute + +Ok, you may think me daft for this but I just figured out what was +necessary in using DBI/DBD:Oracle on a machine that needs to access a +remote Oracle database. + +What the docs tell you is that you just need enough of Oracle installed +to compile it. They don't say that you need to keep that "just enough" +around for the DBI to work properly!! + +So here's my predicament so that others might benefit from my bumbling. + +I needed to install Perl, DBI, and DBD:Oracle on a machine running a +Fast Track web server (hostname Leviathan) that is to access a remote +Oracle database (henceforth called Yog-Sothoth (appropriate for the +beast that it is)). Leviathan doesn't have enough space for the 500M +install that Oracle 7 for Solaris 2.5.1 wants so I had to figure out a +way to get things done. Here's a brief list of the steps I took for +Leviathan. + +1. Got the GCC binary dist for Solaris 2.6 and installed +2. Got Perl 5.004_01 source/compiled/installed +3. Got the DBI .90 compiled/installed +4. Got DBD:Oracle... + + (and here's where it gets interesting). + + I exported the /opt/oracle7 directory from Yog-Sothoth to +Leviathan in +order to compile DBD:Oracle, then umount'ed it afterwards. Tried 'make +test' after it had compiled and watched it flounder and fail. For the +life of me I couldn't figure out why this could be so, so I went back +and adjusted my TWO_TASK/ORACLE_USERID env vars. + No luck. + Wash/Rinse/Repeat. + Still no luck. +I started to get desperate about this time, so instead of screwing with +it anymore I installed the module under the Perl heirarchy just to be +done for the moment with it (figuring that the 'make test' script could +be fallible). I neglected to mention that the errors I was getting were +coming from the Oracle database on the remote machine, so I knew it +worked in part, just not well enough to hold the connection for some +reason. + +After having no luck with my own Perl connect script I tried remounting +the nfs volume with Oracle on it and setting ORACLE_HOME to it. When I +ran that very same Perl script it WORKED! Well sort of. None of the +short connection methods worked, I was forced to use the long method of +connecting IE: name/password@dbname(DESCRIPTION=(ADDRESS=(...etc.etc. + +So here I am figuring that I'm doing something right, but there's +something I'm missing. Well it turns out that it's not me, it's the +machine that's missing it. If you are going to be using the DBD:Oracle +driver with DBI, you'll need more than just it after compile time, +you'll need some Oracle files as well. + +(BTW I'm running Oracle 7.3.2.2.0) + +You'll need everything in /var/opt/oracle (on the machine that houses +Oracle), as well as $ORACLE_HOME/ocommon/nls. Why National Language +Support is needed I'll never know. ocommon/nls has to reside under the +directory your $ORACLE_HOME points to, and it's best to leave +/var/opt/oracle/'s path alone. + +When I made these adjustments on the Oracle'less box and tried the 'make + +test' again, it ran through without a hitch. I'll be doing some more +intensive things with it from here on out and if anything changes I'll +let you all know, however this seems odd that nothing is mentioned in +the documentation about what residual files need to be around after +compiling the DBD:Oracle for it to work successfully. + +Like I said, don't flame me for being stupid, but I just had to get this +story off my chest since I've been puzzling over it all day and I feel +that other people may want to do the same thing as I did, and will run +into the same problems. + +-- Wintermute + +------------------------------------------------------------------------------- diff --git a/README.help b/README.help index 49981d0f..8491b42c 100644 --- a/README.help +++ b/README.help @@ -10,6 +10,21 @@ Assorted runtime problems are caused by Oracle version mismatches: If you have problems then ensure that the version of Oracle you are talking to is the same one you used to build your DBD::Oracle module. +------------------------------------------------------------------------------- +Bad free() warnings: + +These are generally caused by problems in Oracle's own library code. +You can use this code to hide them: + + $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Bad free/ } + +If you're using an old perl version (below 5.004) then upgrading will +probably fix the warnings (since later versions can disable that warning) +and is highly recommended anyway. + +Alternatively you can rebuild Perl without perl's own malloc and/or +upgrade Oracle to a more recent version that doesn't have the problem. + ------------------------------------------------------------------------------- Can't find libclntsh.so at run time: @@ -64,11 +79,6 @@ ORA-01019 can also be caused by corrupt Oracle config files such as Also try building with oracle.mk if your DBD::Oracle defaulted to proc.mk. -------------------------------------------------------------------------------- -Login takes a long time - -Try connect('', 'user/passwd@tnsname', ''). See README.login. - ------------------------------------------------------------------------------- AIX - warnings like these when building perl are not usually a problem: @@ -131,7 +141,7 @@ to build DBD::Oracle statically linked (see below). The problem seems to be related to Oracle's own shared library code trying to do a dynamic load (from lxfgno() in libnlsrtl3.a or libclntsh.sl). If you get core dumps on login try uncommenting the /* #define signed */ line -in Oracle.h as a long-shot. Please let me know if this fixes it for you +in dbdimp.h as a long-shot. Please let me know if this fixes it for you (but I doubt it will). ------------------------------------------------------------------------------- @@ -161,9 +171,9 @@ more info. If your platform supports dynamic linking then try to work out why DBD::Oracle got built for static linking. ------------------------------------------------------------------------------- -Error: Syntax error in oratypes.h +Error: Syntax warnings/errors relating to 'signed' -Try uncommenting the '#define signed' line in Oracle.h +Remove the /* and */ surrounding the '/* #define signed */' line in dbdimp.h ------------------------------------------------------------------------------- ORA-00900: invalid SQL statement "begin ... end" @@ -171,10 +181,10 @@ ORA-00900: invalid SQL statement "begin ... end" You probably don't have PL/SQL Oracle properly/fully installed. ------------------------------------------------------------------------------- -Oracle 7.1 and 7.2: Connection takes a long time and may coredump +Connection/Login slow. Takes a long time and may coredump Oracle bug number: 227321 related to changing the environment before -connecting to oracle. +connecting to oracle. Reported to be fixed in 7.1.6 (or by patch 353611). To work around this bug, do not set any environment variables in your oraperl script before you call ora_login, and when you do call @@ -186,6 +196,20 @@ part of the username (for example, ora_login("", "SCOTT/TIGER@PROD", "")), although I have not tested this. This workaround is based on information from Kevin Stock. +Also check $ORACLE_HOME/otrace/admin. If it contains big *.dat files +then you may have otrace enabled. Try setting EPC_DISABLED=TRUE +in the environment of the database and listener before they're started. +Oracle 7.3.2.2.0 sets this to FALSE by default, which turns on tracing +of all SQL statements, and will cause very slow connects once that +trace file gets big. You can also add (ENVS='EPC_DISABLED=TRUE') to +the SID_DESC part of listener.ora entries. (With thanks to Johan +Verbrugghen jverbrug@be.oracle.com) + +------------------------------------------------------------------------------- +Connection/Login takes a long time + +Try connect('', 'user/passwd@tnsname', ''). See README.login and item above. + ------------------------------------------------------------------------------- Oracle 7.1.4/5: ORA-01002: fetch out of sequence @@ -270,7 +294,7 @@ $ORACLE_HOME/bin. Try a more limited path and reinstall Oracle again. Environment: SGI IRIX 6 - Mark Duffield Oracle only supports "-32" and "-mips2" compilation flags, not "-n32". -Configure and build perl with -32 flag (see hints/irix_6.sh file). +Configure and build perl with -32 flag (see perl hints/irix_6.sh file). Rebuild DBI (which will now use the -32 flag). Rebuild DBD::Oracle (which will now use the -32 flag). @@ -287,10 +311,9 @@ versions of V7.3.3 for SGI (or MIPS ABI as they call it), but I don't have any firm dates. ------------------------------------------------------------------------------- -Environment: DEC Alpha, OSF, Jonathan Olson +Environment: 64-bit platforms (DEC Alpha, OSF, SGI/IRIX64 v6.4) -Problem: ERROR EVENT: DBI::dr=HASH(0x14011fee8)->DBI::default_handler: - 0 ORA-00000: normal, successful completion (DBD: login failed) +Problem: 0 ORA-00000: normal, successful completion Solution: Add '#define A_OSF' to Oracle.h above '#include ' and complain to Oracle about bugs in their header files on 64 bit systems. diff --git a/README.win32 b/README.win32 index 04e33f24..039ef07d 100644 --- a/README.win32 +++ b/README.win32 @@ -1,3 +1,14 @@ +Update 10/24/97 -- Jeff Urlwin + +Tested with Oracle 8 and OCI 8. Well, not the *new* OCI api, but +using the same api as always. This version now searches for OCI +include and library files in $ORACLE_HOME\OCI80, then +$ORACLE_HOME\OCI73. It will use the first of these found. + +In order for the tests to connect successfully, I had to +set the environment variable ORACLE_USERID to +scott/tiger@mydb (where mydb is the tns name of your server) + 4/8/97 -- Jeff Urlwin This version requires Perl 5.003_94 or later. (It was tested with @@ -9,6 +20,11 @@ environment variable ORACLE_HOME be set for proper operation, the Makefile.PL does. Please set the ORACLE_HOME variable to your oracle home directory. Mine, for example, is H:\ORANT. +The environment variable TWO_TASK is not supported under Windows. +Instead Oracle uses the settings LOCAL and REMOTE as described in +the Oracle Networking Documentation, "Oracle Network Products Getting +Started for Windows Platforms." + This version was created and tested with the 7.3 client libraries (see if you have an OCI73 directory). This version of the Oracle clients have a convenient organization, including OCI73\INCLUDE, OCI73\LIB, diff --git a/Todo b/Todo index a17d34d1..1f3c2918 100644 --- a/Todo +++ b/Todo @@ -1,9 +1,38 @@ +Oracle 8 + +$drh->debug oddities (re data_source debugging) + +ora_bind() failed err = ORA-01026: multiple buffers of size > 4000 in +the bind list (DBD: oexec error) + +bind_param(... { TYPE => SQL_* }) + +Can't bind unknown placeholder '3' at ... + +DBI::st=HASH(0x5b5c2c) debug level set to 2 ... (add perl version +number and other info here). + +http://outside.organic.com/mail-archives/dbi-users/Nov1997/0116.html + +LongReadLen and LongTruncOk + +Add explain to dist + +imp_dbh->ldaptr=&imp_dbh->lda for Francois DESARMENIEN + +AIX build + Handle binding of values > 32K long. Handle PL/SQL arrays. Handle PL/SQL returned cursor variables. +Non-blocking + +Tests + RAW types at max length + =============================================================================== General Outstanding Issues @@ -22,3 +51,9 @@ Below is just a personal dumping ground for thoughts and issues, don't expect any structure: (or even anything at all) + +Check -R etc for libsunmath.so.1 +ldd /cmi/run/lib/perl5/site_perl/sun4-solaris/auto/DBD/Oracle/Oracle.so + libclntsh.so.1.0 => /home/oracle/home/lib/libclntsh.so.1.0 + libsunmath.so.1 => (not found) + diff --git a/dbdimp.c b/dbdimp.c index 4cb8955b..7a1685bf 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.33 1997/09/08 22:43:59 timbo Exp $ + $Id: dbdimp.c,v 1.34 1998/05/25 22:11:34 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -21,6 +21,7 @@ static SV *ora_pad_empty; static SV *ora_cache; static SV *ora_cache_o; /* temp hack for ora_open() cache override */ static int ora_login_err; /* fetch & show real login errmsg if true */ +static int ora_fetchtest = 0; static void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); @@ -112,12 +113,12 @@ fbh_dump(fbh, i, aidx) int aidx; /* array index */ { FILE *fp = DBILOGFP; - fprintf(fp, "fbh %d: '%s' %s, ", + fprintf(fp, " fbh %d: '%s' %s, ", i, fbh->cbuf, (fbh->nullok) ? "NULLable" : ""); fprintf(fp, "type %d, dbsize %ld, dsize %ld, p%d s%d\n", fbh->dbtype, (long)fbh->dbsize, (long)fbh->dsize, fbh->prec, fbh->scale); - fprintf(fp, " out: ftype %d, bufl %d. cache@%d: indp %d, rlen %d, rcode %d\n", + fprintf(fp, " out: ftype %d, bufl %d. cache@%d: indp %d, rlen %d, rcode %d\n", fbh->ftype, fbh->fb_ary->bufl, aidx, fbh->fb_ary->aindp[aidx], fbh->fb_ary->arlen[aidx], fbh->fb_ary->arcode[aidx]); } @@ -139,7 +140,7 @@ dbtype_is_long(dbtype) } static int -dbtype_is_string(dbtype) /* 'can we use SvPV to pass buffer?' */ +dbtype_can_be_string(dbtype) /* 'can we use SvPV to pass buffer?' */ int dbtype; { switch(dbtype) { @@ -201,17 +202,40 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) { int ret; + imp_dbh->lda = &imp_dbh->ldabuf; + imp_dbh->hda = &imp_dbh->hdabuf[0]; /* can give duplicate free errors (from Oracle) if connect fails */ - ret = orlon(&imp_dbh->lda, imp_dbh->hda, (text*)uid,-1, (text*)pwd,-1,0); + ret = orlon(imp_dbh->lda, imp_dbh->hda, (text*)uid,-1, (text*)pwd,-1,0); + +#ifdef SA_RESTART +#ifndef SIGCLD +#define SIGCLD SIGCHLD +#endif + { /* If orlon has installed a handler for SIGCLD, */ + /* reinstall it with SA_RESTART: */ + struct sigaction act; + if (sigaction( SIGCLD, (struct sigaction*)0, &act ) == 0 + && (act.sa_handler != SIG_DFL && act.sa_handler != SIG_IGN) + && (act.sa_flags & SA_RESTART) == 0) { + act.sa_flags |= SA_RESTART; + sigaction( SIGCLD, &act, (struct sigaction*)0 ); + if (dbis->debug >= 3) + warn("errno %d, handler %lx, flags %lx",errno,act.sa_handler,act.sa_flags); + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_db_login: set SA_RESTART on Oracle SIGCLD handler.\n"); + } + } +#endif /* HAS_SIGACTION */ + if (ret) { - int rc = imp_dbh->lda.rc; + int rc = imp_dbh->lda->rc; /* oerhms in ora_error may hang or corrupt memory (!) after a connect */ /* failure. So we fake the common error messages unless ora_login_err */ /* is true (set via env var above). Thank Oracle for this sad hack. */ char buf[100]; char *msg="ORA-%d: (Text for error %d not fetched. Use 'oerr ORA %d' command.)"; switch (rc) { - case 1019: msg="ORA-%d: unable to allocate memory in the user side (probably a symptom of a deeper problem)"; + case 1019: msg="ORA-%d: unable to allocate memory in the user side (probably a symptom of a deeper problem)"; break; case 1017: msg="ORA-%d: invalid username/password; login denied"; break; @@ -225,11 +249,13 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) break; case 12154: msg="TNS-%d: TNS:could not resolve service name"; break; + case 12545: msg="TNS-%d: TNS:name lookup failure"; + break; case 12203: msg="TNS-%d: TNS:unable to connect to destination"; break; } sprintf(buf, msg, rc, rc, rc); - ora_error(dbh, ora_login_err ? &imp_dbh->lda : NULL, rc, + ora_error(dbh, ora_login_err ? imp_dbh->lda : NULL, rc, ora_login_err ? "login failed" : buf); return 0; } @@ -244,8 +270,8 @@ dbd_db_commit(dbh, imp_dbh) SV *dbh; imp_dbh_t *imp_dbh; { - if (ocom(&imp_dbh->lda)) { - ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "commit failed"); + if (ocom(imp_dbh->lda)) { + ora_error(dbh, imp_dbh->lda, imp_dbh->lda->rc, "commit failed"); return 0; } return 1; @@ -256,8 +282,8 @@ dbd_db_rollback(dbh, imp_dbh) SV *dbh; imp_dbh_t *imp_dbh; { - if (orol(&imp_dbh->lda)) { - ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "rollback failed"); + if (orol(imp_dbh->lda)) { + ora_error(dbh, imp_dbh->lda, imp_dbh->lda->rc, "rollback failed"); return 0; } return 1; @@ -272,8 +298,8 @@ dbd_db_disconnect(dbh, imp_dbh) /* We assume that disconnect will always work */ /* since most errors imply already disconnected. */ DBIc_ACTIVE_off(imp_dbh); - if (ologof(&imp_dbh->lda)) { - ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "disconnect error"); + if (ologof(imp_dbh->lda)) { + ora_error(dbh, imp_dbh->lda, imp_dbh->lda->rc, "disconnect error"); return 0; } /* We don't free imp_dbh since a reference still exists */ @@ -308,8 +334,8 @@ dbd_db_STORE_attrib(dbh, imp_dbh, keysv, valuesv) int on = SvTRUE(valuesv); if (kl==10 && strEQ(key, "AutoCommit")) { - if ( (on) ? ocon(&imp_dbh->lda) : ocof(&imp_dbh->lda) ) { - ora_error(dbh, &imp_dbh->lda, imp_dbh->lda.rc, "ocon/ocof failed"); + if ( (on) ? ocon(imp_dbh->lda) : ocof(imp_dbh->lda) ) { + ora_error(dbh, imp_dbh->lda, imp_dbh->lda->rc, "ocon/ocof failed"); /* XXX um, we can't return FALSE and true isn't acurate so we croak */ croak(SvPV(DBIc_ERRSTR(imp_dbh),na)); } @@ -348,6 +374,8 @@ dbd_db_FETCH_attrib(dbh, imp_dbh, keysv) *svp = retsv; (void)SvREFCNT_inc(retsv); /* so sv_2mortal won't free it */ } + if (retsv == &sv_yes || retsv == &sv_no) + return retsv; /* no need to mortalize yes or no */ return sv_2mortal(retsv); } @@ -362,7 +390,7 @@ get_cursor(imp_dbh, sth, imp_sth) imp_sth_t *imp_sth; { imp_sth->cda = &imp_sth->cdabuf; - if (oopen(imp_sth->cda, &imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { + if (oopen(imp_sth->cda, imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oopen error"); return 0; } @@ -466,7 +494,8 @@ dbd_preparse(imp_sth, statement) char *src, *start, *dest; phs_t phs_tpl; SV *phs_sv; - int idx=0, style=0, laststyle=0; + int idx=0; + char *style="", *laststyle=Nullch; STRLEN namelen; /* allocate room for copy of statement with spare capacity */ @@ -491,28 +520,28 @@ dbd_preparse(imp_sth, statement) if (*start == '?') { /* X/Open standard */ sprintf(start,":p%d", ++idx); /* '?' -> ':p1' (etc) */ dest = start+strlen(start); - style = 3; + style = "?"; } else if (isDIGIT(*src)) { /* ':1' */ idx = atoi(src); *dest++ = 'p'; /* ':1'->':p1' */ if (idx <= 0) - croak("Placeholder :%d must be a positive number", idx); + croak("Placeholder :%d invalid, placeholders must be >= 1", idx); while(isDIGIT(*src)) *dest++ = *src++; - style = 1; + style = ":1"; } else if (isALNUM(*src)) { /* ':foo' */ while(isALNUM(*src)) /* includes '_' */ *dest++ = *src++; - style = 2; + style = ":foo"; } else { /* perhaps ':=' PL/SQL construct */ continue; } *dest = '\0'; /* handy for debugging */ namelen = (dest-start); if (laststyle && style != laststyle) - croak("Can't mix placeholder styles (%d/%d)",style,laststyle); + croak("Can't mix placeholder styles (%s/%s)",style,laststyle); laststyle = style; if (imp_sth->all_params_hv == NULL) imp_sth->all_params_hv = newHV(); @@ -520,7 +549,6 @@ dbd_preparse(imp_sth, statement) phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)+namelen+1); hv_store(imp_sth->all_params_hv, start, namelen, phs_sv, 0); strcpy( ((phs_t*)(void*)SvPVX(phs_sv))->name, start); - /* warn("params_hv: '%s'\n", start); */ } *dest = '\0'; if (imp_sth->all_params_hv) { @@ -580,9 +608,9 @@ dbd_describe(h, imp_sth) } /* number of rows to cache */ - if (SvOK(ora_cache_o)) imp_sth->cache_size = SvIV(ora_cache_o); - else if (SvOK(ora_cache)) imp_sth->cache_size = SvIV(ora_cache); - else imp_sth->cache_size = 0; /* auto size */ + if (SvOK(ora_cache_o)) imp_sth->cache_rows = SvIV(ora_cache_o); + else if (SvOK(ora_cache)) imp_sth->cache_rows = SvIV(ora_cache); + else imp_sth->cache_rows = 0; /* auto size */ /* Get number of fields and space needed for field names */ while(++i) { /* break out within loop */ @@ -602,7 +630,7 @@ dbd_describe(h, imp_sth) /* now we calculate the approx average on-the-wire width of */ /* each field (and thus row) to determine a 'good' cache size. */ - if (imp_sth->cache_size > 0) + if (imp_sth->cache_rows > 0) continue; /* no need, user specified a size */ if (dbsize==0) { /* is a LONG type or 'select NULL' */ if (dbtype_is_long(dbtype)) { @@ -626,7 +654,7 @@ dbd_describe(h, imp_sth) } if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { D_imp_dbh_from_sth; - ora_error(h, &imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); + ora_error(h, imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); return 0; } imp_sth->cda->rc = 0; @@ -636,9 +664,9 @@ dbd_describe(h, imp_sth) /* --- Setup the row cache for this query --- */ if (has_longs) /* override/disable caching */ - imp_sth->cache_size = 1; /* else read_blob can't work */ + imp_sth->cache_rows = 1; /* else read_blob can't work */ - else if (imp_sth->cache_size < 1) { /* automaticaly size the cache */ + else if (imp_sth->cache_rows < 1) { /* automaticaly size the cache */ /* 0 == try to pick 'optimal' cache for this query. */ /* <0 == base cache on transfer size of -n bytes (default 2048) */ /* Use guessed average on-the-wire row width calculated above */ @@ -646,14 +674,14 @@ dbd_describe(h, imp_sth) int width = est_width + num_fields*5 + 8; /* How many rows fit in 2Kb? (2Kb is a reasonable compromise) */ int hunk = 2048; /* default cache size */ - if (imp_sth->cache_size < 0) /* user is specifying txfr size */ - hunk = -imp_sth->cache_size;/* is also approx cache size */ - imp_sth->cache_size = hunk / width; - if (imp_sth->cache_size < 5) /* always cache at least 5 */ - imp_sth->cache_size = 5; - } - if (imp_sth->cache_size > 32767) /* keep within Oracle's limits */ - imp_sth->cache_size = 32767; + if (imp_sth->cache_rows < 0) /* user is specifying txfr size */ + hunk = -imp_sth->cache_rows;/* is also approx cache size */ + imp_sth->cache_rows = hunk / width; + if (imp_sth->cache_rows < 5) /* always cache at least 5 */ + imp_sth->cache_rows = 5; + } + if (imp_sth->cache_rows > 32767) /* keep within Oracle's limits */ + imp_sth->cache_rows = 32767; /* Initialise cache counters */ imp_sth->in_cache = 0; imp_sth->eod_errno = 0; @@ -682,6 +710,12 @@ dbd_describe(h, imp_sth) /* Now define the storage for this field data. */ + if (fbh->dbtype==23 || fbh->dbtype==24) { /* RAW types */ + /* is this the right thing to do? what about longraw? XXX */ + fbh->dbsize *= 2; + fbh->dsize *= 2; + } + /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW? */ /* If so we need to implement oraperl truncation hacks. */ /* This may change in a future release. */ @@ -702,7 +736,7 @@ dbd_describe(h, imp_sth) fbh->fb_ary = fb_ary = fb_ary_alloc( fbh->dsize+1, /* +1: STRING null terminator */ - imp_sth->cache_size + imp_sth->cache_rows ); /* DEFINE output column variable storage */ @@ -718,12 +752,12 @@ dbd_describe(h, imp_sth) if (dbis->debug >= 2) fprintf(DBILOGFP, - " dbd_describe'd %d columns (~%d data bytes, %d cache rows @%db)\n", - (int)num_fields, imp_sth->t_dbsize, imp_sth->cache_size, est_width); + " dbd_describe'd %d columns (Row bytes: %d max, %d avg. Will prefetch %d rows)\n", + (int)num_fields, imp_sth->t_dbsize, est_width, imp_sth->cache_rows); if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { D_imp_dbh_from_sth; - ora_error(h, &imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); + ora_error(h, imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); return 0; } @@ -731,6 +765,34 @@ dbd_describe(h, imp_sth) } +static int +ora_sql_type(imp_sth, name, sql_type) + imp_sth_t *imp_sth; + char *name; + int sql_type; +{ + switch (sql_type) { + case SQL_NUMERIC: + case SQL_DECIMAL: + case SQL_INTEGER: + case SQL_SMALLINT: + case SQL_FLOAT: + case SQL_REAL: + case SQL_DOUBLE: + case SQL_VARCHAR: + return 1; /* Oracle VARCHAR2 */ + + case SQL_CHAR: + return 5; /* Oracle CHAR */ + + default: + if (DBIc_WARN(imp_sth) && imp_sth && name) + warn("SQL type %d for '%s' is not fully supported, bound as VARCHAR instead"); + return ora_sql_type(imp_sth, name, SQL_VARCHAR); + } +} + + static int _dbd_rebind_ph(sth, imp_sth, phs) @@ -747,9 +809,13 @@ _dbd_rebind_ph(sth, imp_sth, phs) if (dbis->debug >= 2) { char *text = neatsvpv(phs->sv,0); - fprintf(DBILOGFP, "bind %s <== %s (size %ld/%ld/%ld, ptype %ld, otype %d)\n", - phs->name, text, (long)SvCUR(phs->sv),(long)SvLEN(phs->sv),phs->maxlen, - SvTYPE(phs->sv), phs->ftype); + fprintf(DBILOGFP, " bind %s <== %s (", phs->name, text); + if (SvOK(phs->sv)) + fprintf(DBILOGFP, "size %ld/%ld/%ld, ", + (long)SvCUR(phs->sv),(long)SvLEN(phs->sv),phs->maxlen); + fprintf(DBILOGFP, "ptype %ld, otype %d%s)\n", + SvTYPE(phs->sv), phs->ftype, + (phs->is_inout) ? ", inout" : ""); } /* At the moment we always do sv_setsv() and rebind. */ @@ -780,7 +846,7 @@ _dbd_rebind_ph(sth, imp_sth, phs) phs->indp = 0; } else { /* it's null but point to buffer incase it's an out var */ - phs->progv = SvPVX(phs->sv); + phs->progv = SvPVX(phs->sv); /* can be NULL (undef) */ phs->indp = -1; value_len = 0; } @@ -799,7 +865,7 @@ _dbd_rebind_ph(sth, imp_sth, phs) } else { phs->alen = 0; - alen_ptr = NULL; /* Can't use alen */ + alen_ptr = NULL; /* Can't use alen for long LONGs (>64k) */ if (phs->is_inout) croak("Can't bind LONG values (>%ld) as in/out parameters", (long)UB2MAXVAL); } @@ -813,8 +879,9 @@ _dbd_rebind_ph(sth, imp_sth, phs) phs->name, phs->maxlen, MINSWORDMAXVAL); if (dbis->debug >= 3) { - fprintf(DBILOGFP, "bind %s <== '%.100s' (size %d/%ld, indp %d)\n", - phs->name, phs->progv, phs->alen, (long)phs->maxlen, phs->indp); + fprintf(DBILOGFP, "bind %s <== '%.*s' (size %d/%ld, otype %d, indp %d)\n", + phs->name, phs->alen, (phs->progv) ? phs->progv : "", + phs->alen, (long)phs->maxlen, phs->ftype, phs->indp); } if (obndra(imp_sth->cda, (text *)phs->name, -1, @@ -823,7 +890,7 @@ _dbd_rebind_ph(sth, imp_sth, phs) &phs->indp, alen_ptr, &phs->arcode, 0, (ub4 *)0, (text *)0, -1, -1)) { D_imp_dbh_from_sth; - ora_error(sth, &imp_dbh->lda, imp_sth->cda->rc, "obndra failed"); + ora_error(sth, imp_dbh->lda, imp_sth->cda->rc, "obndra failed"); return 0; } return 1; @@ -855,14 +922,24 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl } else { /* use the supplied placeholder name directly */ name = SvPV(ph_namesv, name_len); + /* could check for leading colon here */ } - if (SvTYPE(newvalue) > SVt_PVMG) /* hook for later array logic */ - croak("Can't bind non-scalar value (currently)"); + /* hook for later array logic */ + if (SvTYPE(newvalue)==SVt_RV || SvTYPE(newvalue) > SVt_PVLV) + croak("Can't bind reference or non-scalar value (currently)"); + if (SvTYPE(newvalue) == SVt_PVLV && is_inout) /* may allow later */ + croak("Can't bind ``lvalue'' mode scalar as inout parameter (currently)"); - if (dbis->debug >= 2) - fprintf(DBILOGFP, "bind %s <== %s (attribs: %s)\n", - name, neatsvpv(newvalue,0), attribs ? SvPV(attribs,na) : "" ); + if (dbis->debug >= 2) { + fprintf(DBILOGFP, " bind %s <== %s (type %ld", + name, neatsvpv(newvalue,0), (long)sql_type); + if (is_inout) + fprintf(DBILOGFP, ", inout 0x%lx", (long)newvalue); + if (attribs) + fprintf(DBILOGFP, ", attribs: %s", SvPV(attribs,na)); + fprintf(DBILOGFP, ")\n"); + } phs_svp = hv_fetch(imp_sth->all_params_hv, name, name_len, 0); if (phs_svp == NULL) @@ -874,7 +951,7 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl phs->maxlen = maxlen; /* 0 if not inout */ phs->is_inout = is_inout; if (is_inout) { - phs->sv = SvREFCNT_inc(newvalue); /* point to live var */ + /* phs->sv assigned in the code below */ ++imp_sth->has_inout_params; /* build array of phs's so we can deal with out vars fast */ if (!imp_sth->out_params_av) @@ -888,24 +965,30 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl /* XXX If attribs is EMPTY then reset attribs to default? */ if ( (svp=hv_fetch((HV*)SvRV(attribs), "ora_type",8, 0)) != NULL) { int ora_type = SvIV(*svp); - if (!dbtype_is_string(ora_type)) /* mean but safe */ + if (!dbtype_can_be_string(ora_type)) /* mean but safe */ croak("Can't bind %s, ora_type %d not a simple string type", phs->name, ora_type); + if (sql_type) + croak("Can't specify both TYPE (%d) and ora_type (%d) for %s", + sql_type, ora_type, phs->name); phs->ftype = ora_type; } } + if (sql_type) + phs->ftype = ora_sql_type(imp_sth, phs->name, sql_type); /* some types require the trailing null included in the length. */ phs->alen_incnull = (phs->ftype==SQLT_STR || phs->ftype==SQLT_AVC); } /* check later rebinds for any changes */ - else if (is_inout || phs->is_inout) { - croak("Can't rebind or change param %s in/out mode after first bind", phs->name); + else if (is_inout != phs->is_inout) { + croak("Can't rebind or change param %s in/out mode after first bind (%d => %d)", + phs->name, phs->is_inout , is_inout); } - else if (maxlen && maxlen != phs->maxlen) { - croak("Can't change param %s maxlen (%ld->%ld) after first bind", - phs->name, phs->maxlen, maxlen); + else if (sql_type && phs->ftype != ora_sql_type(imp_sth, phs->name, sql_type)) { + croak("Can't change TYPE of param %s to %d after initial bind", + phs->name, sql_type); } if (!is_inout) { /* normal bind to take a (new) copy of current value */ @@ -913,12 +996,16 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl phs->sv = newSV(0); sv_setsv(phs->sv, newvalue); } + else if (newvalue != phs->sv) { + if (phs->sv) + SvREFCNT_dec(phs->sv); + phs->sv = SvREFCNT_inc(newvalue); /* point to live var */ + } return _dbd_rebind_ph(sth, imp_sth, phs); } - int dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count) */ SV *sth; @@ -958,11 +1045,16 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count if (!_dbd_rebind_ph(sth, imp_sth, phs)) croak("Can't rebind placeholder %s", phs->name); } - phs->alen = SvCUR(phs->sv) + phs->alen_incnull; - if (debug >= 2) - warn(" with %s = '%.100s' (len %d/%d, indp %d, ptype %ld, otype %d)\n", - phs->name, SvPVX(phs->sv), phs->alen, phs->maxlen, - phs->indp, SvTYPE(phs->sv), phs->ftype); + else { + /* String may have grown or shrunk since it was bound */ + /* so tell Oracle about it's current length */ + phs->alen = SvCUR(phs->sv) + phs->alen_incnull; + if (debug >= 2) + fprintf(DBILOGFP, + " with %s = '%.*s' (len %d/%d, indp %d, otype %d, ptype %ld)\n", + phs->name, phs->alen, SvPVX(phs->sv), phs->alen, (int)phs->maxlen, + phs->indp, phs->ftype, SvTYPE(phs->sv)); + } } } @@ -975,7 +1067,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count if (DBIc_NUM_FIELDS(imp_sth) > 0) { /* is a SELECT */ /* The number of fields is used because imp_sth->cda->ft is unreliable. */ /* Specifically an update (5) may change to select (4) after odesc(). */ - if (oexfet(imp_sth->cda, (ub4)imp_sth->cache_size, 0, 0) + if (oexfet(imp_sth->cda, (ub4)imp_sth->cache_rows, 0, 0) && imp_sth->cda->rc != 1403 /* other than no more data */ ) { ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexfet error"); return -2; @@ -999,16 +1091,18 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count if (outparams) { /* check validity of bound SV's */ int i = outparams; - STRLEN retlen; while(--i >= 0) { phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); SV *sv = phs->sv; + /* phs->alen has been updated by Oracle to hold the length of the result */ if (phs->indp == 0) { /* is okay */ SvPOK_only(sv); SvCUR(sv) = phs->alen; *SvEND(sv) = '\0'; if (debug >= 2) - warn(" %s = '%s' (len %d)\n", phs->name, SvPV(sv,retlen),retlen); + fprintf(DBILOGFP, + " out %s = '%s'\t(len %d)\n", + phs->name, SvPV(sv,na),phs->alen); } else if (phs->indp > 0 || phs->indp == -2) { /* truncated */ @@ -1016,21 +1110,23 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count SvCUR(sv) = phs->alen; *SvEND(sv) = '\0'; if (debug >= 2) - warn(" %s = '%s' (TRUNCATED from %d to %d)\n", phs->name, - SvPV(sv,retlen), phs->indp, retlen); + fprintf(DBILOGFP, + " out %s = '%s'\t(TRUNCATED from %d to %d)\n", phs->name, + SvPV(sv,na), phs->indp, phs->alen); } else if (phs->indp == -1) { /* is NULL */ (void)SvOK_off(phs->sv); if (debug >= 2) - warn(" %s = undef (NULL)\n", phs->name); + fprintf(DBILOGFP, + " out %s = undef (NULL)\n", phs->name); } - else croak("%s bad indp %d", phs->name, phs->indp); + else croak("panic: %s bad indp %d", phs->name, phs->indp); } } DBIc_ACTIVE_on(imp_sth); /* XXX should only set for select ? */ - return imp_sth->cda->rpc; /* row count */ + return imp_sth->cda->rpc; /* row count (0 will be returned as "0E0") */ } @@ -1047,17 +1143,17 @@ dbd_st_fetch(sth, imp_sth) int i; AV *av; - /* Check that execute() was executed sucessfully. This also implies */ - /* that dbd_describe() executed sucessfuly so the memory buffers */ - /* are allocated and bound. */ - if ( !DBIc_ACTIVE(imp_sth) ) { - ora_error(sth, NULL, 1, "no statement executing"); - return Nullav; - } - if (!imp_sth->in_cache) { /* refill cache if empty */ int previous_rpc; + /* Check that execute() was executed sucessfully. This also implies */ + /* that dbd_describe() executed sucessfuly so the memory buffers */ + /* are allocated and bound. */ + if ( !DBIc_ACTIVE(imp_sth) ) { + ora_error(sth, NULL, 1, "no statement executing (perhaps you need to call execute first)"); + return Nullav; + } + if (imp_sth->eod_errno) { end_of_data: if (imp_sth->eod_errno != 1403) { /* was not just end-of-fetch */ @@ -1073,7 +1169,7 @@ dbd_st_fetch(sth, imp_sth) } previous_rpc = imp_sth->cda->rpc; /* remember rpc before re-fetch */ - if (ofen(imp_sth->cda, imp_sth->cache_size)) { + if (ofen(imp_sth->cda, imp_sth->cache_rows)) { /* Note that errors may happen after one or more rows have been */ /* added to the cache. We record the error but don't handle it till */ /* the cache is empty (which may be at once if no rows returned). */ @@ -1093,7 +1189,7 @@ dbd_st_fetch(sth, imp_sth) if (debug >= 3) fprintf(DBILOGFP, " dbd_st_fetch %d fields, rpc %ld (cache: %d/%d/%d)\n", num_fields, (long)imp_sth->cda->rpc, imp_sth->next_entry, - imp_sth->in_cache, imp_sth->cache_size); + imp_sth->in_cache, imp_sth->cache_rows); ChopBlanks = DBIc_has(imp_sth, DBIcf_ChopBlanks); @@ -1108,13 +1204,14 @@ dbd_st_fetch(sth, imp_sth) /* We have a LONG field which has been truncated. */ int oraperl = DBIc_COMPAT(imp_sth); if ((oraperl) ? SvIV(ora_trunc) : DBIc_has(imp_sth,DBIcf_LongTruncOk)) { - /* Oraperl recorded the truncation in ora_errno. */ - /* We do so but it's not part of the DBI spec. */ + /* user says truncation is ok */ + /* Oraperl recorded the truncation in ora_errno so we */ + /* so also but only for Oraperl mode handles. */ if (oraperl) - sv_setiv(DBIc_ERR(imp_sth), (IV)rc); /* record it */ - rc = 0; /* but don't provoke an error */ + sv_setiv(DBIc_ERR(imp_sth), (IV)rc); + rc = 0; /* but don't provoke an error here */ } - /* else provoke an error */ + /* else fall through and let rc trigger failure below */ } if (rc == 0) { /* the normal case */ @@ -1125,11 +1222,17 @@ dbd_st_fetch(sth, imp_sth) while(datalen && p[datalen - 1]==' ') --datalen; } - sv_setpvn(sv, p, datalen); + sv_setpvn(sv, p, (STRLEN)datalen); } else if (rc == 1405) { /* field is null - return undef */ (void)SvOK_off(sv); + } else if (rc == 1406) { /* field truncated (see above) */ + /* copy the truncated value anyway, it may be of use */ + sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], + fb_ary->arlen[cache_entry]); + ++err; /* 'fail' this fetch but continue getting fields */ + } else { /* See odefin rcode arg description in OCI docs */ /* These may get case-by-case treatment eventually. */ /* Some should probably be treated as warnings but */ @@ -1145,8 +1248,12 @@ dbd_st_fetch(sth, imp_sth) } /* update cache counters */ - --imp_sth->in_cache; - ++imp_sth->next_entry; + if (ora_fetchtest) /* unless we're testing performance */ + --ora_fetchtest; + else { + --imp_sth->in_cache; + ++imp_sth->next_entry; + } return (err) ? Nullav : av; } @@ -1198,7 +1305,15 @@ dbd_st_rows(sth, imp_sth) SV *sth; imp_sth_t *imp_sth; { - return imp_sth->cda->rpc; + /* spot common mistake of checking $h->rows just after ->execute */ + if ( imp_sth->in_cache > 0 /* has unfetched rows */ + && imp_sth->in_cache== imp_sth->cda->rpc /* NO rows fetched yet */ + && DBIc_WARN(imp_sth) /* provide a way to disable warning */ + ) { + warn("$h->rows count is incomplete before all rows fetched.\n"); + } + /* imp_sth->in_cache should always be 0 for non-select statements */ + return imp_sth->cda->rpc - imp_sth->in_cache; /* fetched rows */ } @@ -1239,7 +1354,8 @@ dbd_st_destroy(sth, imp_sth) /* Check if an explicit disconnect() or global destruction has */ /* disconnected us from the database before attempting to close. */ - if (DBIc_ACTIVE(imp_dbh) && !free_cursor(sth, imp_sth)) { + if (DBIc_ACTIVE(imp_dbh) && DBIc_ACTIVE(imp_sth)) { + free_cursor(sth, imp_sth); /* ignore errors here */ /* fall through anyway to free up our memory */ } @@ -1285,18 +1401,21 @@ dbd_st_STORE_attrib(sth, imp_sth, keysv, valuesv) SV *keysv; SV *valuesv; { - return FALSE; -#ifdef not_used_yet STRLEN kl; char *key = SvPV(keysv,kl); int on = SvTRUE(valuesv); SV *cachesv = NULL; - int oraperl = DBIc_COMPAT(imp_sth); +/* int oraperl = DBIc_COMPAT(imp_sth); */ + + if (strEQ(key, "ora_fetchtest")) { + ora_fetchtest = SvIV(valuesv); + } + else + return FALSE; if (cachesv) /* cache value for later DBI 'quick' fetch? */ hv_store((HV*)SvRV(sth), key, kl, cachesv, 0); return TRUE; -#endif } diff --git a/dbdimp.h b/dbdimp.h index 10385e8c..a13481fa 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.19 1997/09/08 22:43:59 timbo Exp $ + $Id: dbdimp.h,v 1.20 1998/05/25 22:11:34 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -10,13 +10,25 @@ */ -/* #define MAX_COLS 1025 */ /* try uncommenting this line if you get a syntax error on - * typedef signed long sbig_ora; + * typedef signed long sbig_ora; * in oratypes.h for Oracle 7.1.3. Don't you just love Oracle! */ -/* #define signed */ +/* now changed to only define it for non ansi-ish compilers */ +#ifndef CAN_PROTOTYPE +#define signed +#endif + + +/* The following define avoids a problem with Oracle >=7.3 where + * ociapr.h has the line: + * sword obindps(struct cda_def *cursor, ub1 opcode, text *sqlvar, ... + * In some compilers that clashes with perls 'opcode' enum definition. + */ +#define opcode opcode_redefined + + /* Hack to fix broken Oracle oratypes.h on OSF Alpha. Sigh. */ #if defined(__osf__) && defined(__alpha) @@ -36,7 +48,7 @@ #define HDA_SIZE 512 #endif -#ifndef FT_SELECT +#ifndef FT_SELECT /* old Oracle version */ #define FT_SELECT 4 /* from rdbms/demo/ocidem.h */ #endif @@ -51,10 +63,12 @@ struct imp_drh_st { struct imp_dbh_st { dbih_dbc_t com; /* MUST be first element in structure */ - Lda_Def lda; - ub1 hda[HDA_SIZE]; + Lda_Def ldabuf; + Lda_Def *lda; /* points to ldabuf */ + ub1 hdabuf[HDA_SIZE]; + ub1 *hda; /* points to hdabuf */ - int autocommit; /* we assume autocommit is off initially */ + int autocommit; /* we assume autocommit is off initially */ }; @@ -78,7 +92,7 @@ struct imp_sth_st { int t_dbsize; /* raw data width of a row */ /* Select Row Cache Details */ - int cache_size; + int cache_rows; int in_cache; int next_entry; int eod_errno; diff --git a/t/general.t b/t/general.t new file mode 100644 index 00000000..d2d7f6df --- /dev/null +++ b/t/general.t @@ -0,0 +1,64 @@ +#!/usr/local/bin/perl -w + +sub ok ($$;$) { + my($n, $ok, $warn) = @_; + ++$t; + die "sequence error, expected $n but actually $t" + if $n and $n != $t; + ($ok) ? print "ok $t\n" : print "not ok $t\n"; + if (!$ok && $warn) { + $warn = $DBI::errstr || "(DBI::errstr undefined)" if $warn eq '1'; + warn "$warn\n"; + } +} + +use DBI; +$| = 1; + +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dbh = DBI->connect('', $dbuser, '', 'Oracle'); + +unless($dbh) { + warn "Unable to connect to Oracle ($DBI::errstr)\nTests skiped.\n"; + print "1..0\n"; + exit 0; +} + +print "1..$tests\n"; + +my($csr, $p1, $p2); + +# --- test named numeric in/out parameters +#$dbh->trace(2); +my $sql = q{ + declare foo char(500); + begin + foo := :p1; + foo := :p2; + foo := :p3; + foo := :p4; + end; +}; +ok(0, $csr = $dbh->prepare($sql), 1); + +foreach (1..3) { + ok(0, $dbh->do($sql, undef, 7,8,9,1), 1); +# ok(0, $csr->execute(7,8,9,1), 1); +} + + + # To do + # test NULLs at first bind + # NULLs later binds. + # returning NULLs + # multiple params, mixed types and in only vs inout + +ok(0, $dbh->ping); +$dbh->disconnect; +ok(0, !$dbh->ping); + +exit 0; +BEGIN { $tests = 6 } +# end. + +__END__ diff --git a/t/plsql.t b/t/plsql.t index 9ea4f883..b6434080 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -7,18 +7,26 @@ sub ok ($$;$) { if $n and $n != $t; ($ok) ? print "ok $t\n" : print "not ok $t\n"; if (!$ok && $warn) { - $warn = $DBI::errstr if $warn eq '1'; + $warn = $DBI::errstr || "(DBI::errstr undefined)" if $warn eq '1'; warn "$warn\n"; } } use DBI; +$| = 1; my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbh = DBI->connect('', $dbuser, '', 'Oracle'); unless($dbh) { - warn "Unable to connect to Oracle ($DBI::errstr)\n"; + warn "Unable to connect to Oracle ($DBI::errstr)\nTests skiped.\n"; + print "1..0\n"; + exit 0; +} + +# ORA-00900: invalid SQL statement +if (!$dbh->prepare(q{begin RAISE INVALID_NUMBER; end;}) && $dbh->err==900) { + warn "Your Oracle server doesn't support PL/SQL - Tests skipped.\n"; print "1..0\n"; exit 0; } @@ -26,6 +34,7 @@ unless($dbh) { print "1..$tests\n"; my($csr, $p1, $p2); +#DBI->trace(4,"trace.log"); # --- test raising predefined exception @@ -36,6 +45,7 @@ ok(0, $csr = $dbh->prepare(q{ # ORA-01722: invalid number ok(0, ! $csr->execute, 1); ok(0, $DBI::err == 1722); +ok(0, $DBI::err == 1722); # make sure error doesn't get cleared # --- test raising user defined exception @@ -90,6 +100,7 @@ ok(0, $p1 == 6); $p1 = 1; foreach (1..10) { $csr->execute || die $DBI::errstr; } ok(0, $p1 == 1024); + # --- test undef parameters ok(0, $csr = $dbh->prepare(q{ declare foo char(500); @@ -99,6 +110,7 @@ my $undef; ok(0, $csr->bind_param_inout(':arg', \$undef,10), 1); ok(0, $csr->execute, 1); + # --- test named string in/out parameters ok(0, $csr = $dbh->prepare(q{ declare str varchar2(1000); @@ -130,16 +142,55 @@ ok(0, $p1 eq 'null!'); $csr->finish; +# --- test plsql_errstr function +#$csr = $dbh->prepare(q{ +# create or replace procedure perl_dbd_oracle_test as +# begin +# procedure filltab( stuff out tab ); asdf +# end; +#}); +#ok(0, ! $csr); +#if ($dbh->err && $dbh->err == 6550) { # PL/SQL error +# warn "errstr: ".$dbh->errstr; +# my $msg = $dbh->func('plsql_errstr'); +# warn "plsql_errstr: $msg"; +# ok(0, $msg =~ /Encountered the symbol/, "plsql_errstr: $msg"); +#} +#else { +# warn "plsql_errstr test skipped ($DBI::err)\n"; +# ok(0, 1); +#} +#die; + +# --- test dbms_output_* functions +$dbh->{PrintError} = 1; +ok(0, $dbh->func(30000, 'dbms_output_enable'), 1); + +my @ary = qw(foo bar baz boo); +ok(0, $dbh->func(@ary, 'dbms_output_put'), 1); + +@ary = scalar $dbh->func('dbms_output_get'); # scalar context +ok(0, @ary==1 && $ary[0] eq 'foo', 0); + +@ary = scalar $dbh->func('dbms_output_get'); # scalar context +ok(0, @ary==1 && $ary[0] eq 'bar', 0); + +@ary = $dbh->func('dbms_output_get'); # list context +ok(0, join(':',@ary) eq 'baz:boo', 0); +$dbh->{PrintError} = 0; + # To do # test NULLs at first bind - # NULLS later binds. - # returning NULLS + # NULLs later binds. + # returning NULLs # multiple params, mixed types and in only vs inout - +ok(0, $dbh->ping); $dbh->disconnect; +ok(0, !$dbh->ping); + exit 0; -BEGIN { $tests = 29 } +BEGIN { $tests = 37 } # end. __END__ diff --git a/test.pl b/test.pl index 6a749a24..ecefcbde 100755 --- a/test.pl +++ b/test.pl @@ -21,12 +21,15 @@ ? warn "\n*** Read the README file about Bad free() warnings!\n": warn @_; }; +use Config; +my $os = $Config{osname}; $opt_d = 0; # debug $opt_l = 0; # log $opt_n = 5; # num of loops $opt_m = 0; # count for mem leek test $opt_c = 1; # do cache test -&Getopts('m:d:n:cl ') || die "Invalid options\n"; +$opt_p = 1; # do perf test +&Getopts('m:d:n:clp ') || die "Invalid options\n"; $ENV{PERL_DBI_DEBUG} = 2 if $opt_d; $ENV{ORACLE_HOME} = '/usr/oracle' unless $ENV{ORACLE_HOME}; @@ -39,10 +42,15 @@ &ora_version; +my @data_sources = DBI->data_sources('Oracle'); +print "Data sources: @data_sources\n\n"; + print "\nConnecting\n", " to '$dbname' (from command line, else uses ORACLE_SID or TWO_TASK - recommended)\n"; print " as '$dbuser' (via ORACLE_USERID env var or default - recommend name/passwd\@dbname)\n"; printf("(ORACLE_SID='%s', TWO_TASK='%s')\n", $ENV{ORACLE_SID}||'', $ENV{TWO_TASK}||''); +printf("(LOCAL='%s', REMOTE='%s')\n", $ENV{LOCAL}||'', $ENV{REMOTE}||'') if $os eq 'MSWin32'; + { # test connect works first local($l) = &ora_login($dbname, $dbuser, ''); @@ -60,6 +68,7 @@ warn "\nTWO_TASK possibly not set correctly right.\n" if ($ora_errno == 12545); warn "\n"; + warn "Generally set TWO_TASK or ORACLE_SID but not both at the same time.\n"; warn "Try to connect to the database using an oracle tool like sqlplus\n"; warn "only if that works should you suspect problems with DBD::Oracle.\n"; warn "Try leaving dbname value empty and set dbuser to name/passwd\@dbname.\n"; @@ -73,6 +82,8 @@ rename("test.log","test.olog") if $opt_l; eval 'DBI->_debug_dispatch(3,"test.log");' if $opt_l; +&test_fetch_perf() if $opt_p; + &test3($opt_m) if $opt_m; &test1(); @@ -91,8 +102,6 @@ &ora_logoff($lda2) || warn "ora_logoff($lda2): $ora_errno: $ora_errstr\n"; print "done.\n"; -&test3($opt_m) if $opt_m; - &test_cache() if $opt_c; $dur = time - $start; @@ -168,7 +177,7 @@ sub test1 { print "Test ora_do with harmless non-select statement ", "(set transaction read only)\n"; - print "Expect error message:\n"; + print "Expect an 'ORA-01453' error message:\n"; &ora_do($lda, "set transaction read only ") || warn "ora_do: $ora_errno: $ora_errstr\n"; @@ -234,7 +243,8 @@ sub test_cache { sub count_fetch { local($csr) = @_; local($rows) = 0; - while((@row) = &ora_fetch($csr)) { + # while((@row) = &ora_fetch($csr)) { + while((@row) = $csr->fetchrow_array) { ++$rows; } die "count_fetch $ora_errstr" if $ora_errno; @@ -242,6 +252,31 @@ sub count_fetch { } +sub test_fetch_perf { + print "\nTesting internal row fetch overhead.\n"; + local($lda) = &ora_login($dbname, $dbuser, '') + || die "ora_login: $ora_errno: $ora_errstr\n"; + #$lda->trace(2); + $lda->trace(0); + local($csr) = &ora_open($lda,"select 0,1,2,3,4,5,6,7,8,9 from dual"); + #local($csr) = &ora_open($lda,"select 9 from dual"); + local($max) = 50000; + $csr->{ora_fetchtest} = $max; + require Benchmark; + $t0 = new Benchmark; + #local($rows) = count_fetch($csr); die "count_fetch $rows != $max" if $rows-1 != $max; + my $code = $csr->can('fetch'); + #1 while &$code($csr); + 1 while $csr->fetchrow_arrayref; + #1 while @row = $csr->fetchrow_array; + #while(@row = $csr->fetchrow_array) { $hash{++$i} = [ @row ]; } + $td = Benchmark::timediff((new Benchmark), $t0); + $csr->{ora_fetchtest} = 0; + printf("$max fetches: ".Benchmark::timestr($td)."\n"); + printf("%d per clock second, %d per cpu second\n\n", $max/$td->real, $max/$td->cpu_a); +} + + sub test_other { local($lda) = @_; #$lda->debug(2); From e69259fe024cb14caa9ffa65e3d0b98748df6366 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Tue, 2 Jun 1998 15:59:30 -0500 Subject: [PATCH 028/637] import DBD-Oracle 0.49 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.49 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.49.tar.gz --- Changes | 9 ++++ Makefile.PL | 152 +++++++++++++++++++++++++++++++++++----------------- Oracle.pm | 103 +++++++++++++++++++---------------- Oraperl.pm | 12 ++--- README | 13 +++-- dbdimp.c | 97 ++++++++++++++++++++++----------- dbdimp.h | 3 +- t/general.t | 21 +------- t/plsql.t | 8 ++- test.pl | 4 ++ 10 files changed, 263 insertions(+), 159 deletions(-) diff --git a/Changes b/Changes index 6c5a2ac5..2c9620fa 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,12 @@ +Changes in DBD::Oracle 0.49 (Oraperl 1.36), 1st June 1998 + + Further improvements to build process over 0.48. + Fixed broken truncation error in 0.48. + Fetch ORACLE_SID from Win32 registry (thanks to Preston Bannister) + Improved automatic row cache sizing (prompted by Jon Meek). + Added $sth->{ora_cache_size} and $sth->{ora_est_row_width} + as read-only attributes to make cache size logic easier to test. + Changes in DBD::Oracle 0.48 (Oraperl 1.36), 25th May 1998 THIS IS AN EXPERIMENTAL RELEASE - USE WITH CAUTION! diff --git a/Makefile.PL b/Makefile.PL index 480f3af8..15b44e8e 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.59 1998/05/25 22:11:34 timbo Exp $ +# $Id: Makefile.PL,v 1.60 1998/06/01 18:34:16 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -47,20 +47,21 @@ my %opts = ( my(@MK, %MK, $MK, %MK_expanding); # parsed macros from Oracle's makefiles # Options (rarely needed) -$::opt_m = ''; # path to proc.mk or oracle.mk file to read +$::opt_m = undef; # path to proc.mk or oracle.mk file to read $::opt_p = ''; # prefer oracle.mk over proc -$::opt_g = ''; # enable debugging (s/-O/-g/g) -$::opt_s = ''; # Find a symbol, Don't build a Makefile +$::opt_g = ''; # enable debugging (-g for compiler and linker) +$::opt_c = ''; # disable linking to clntsh (LCLSH/LLIBCLNTSH in *.mk) +$::opt_s = ''; # Find a symbol in oracle libs, Don't build a Makefile +$::opt_S = ''; # Find a symbol in oracle & system libs, Don't build a Makefile $::opt_v = 0; # be more verbose $::opt_d = 0; # much more verbose for debugging $::opt_old = 0; # old style .mk file parsing -GetOptions(qw(v! d! g! old! p! m=s s=s)) or die "Invalid arguments"; +GetOptions(qw(v! d! g! old! p! m=s s=s S=s)) or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string $::opt_v = 1 if $::opt_d; $Verbose = 1 if $::opt_v; -my $use_clntsh = 1; # --- Introduction @@ -83,14 +84,36 @@ die "$ORACLE_ENV environment variable ($OH) not valid.\n" unless -d $OH; print "Using Oracle in $OH\n"; -if ($::opt_s) { +if ($os ne 'VMS' and $os ne 'MSWin32' and -d "$OH/orainst") { + open INST, "$OH/orainst/inspdver |"; + my @inspdver = ; + close INST; + foreach (@inspdver) { + next unless $::opt_v + or m/Common Libraries/i + or m/RDBMS/i or m/PL.SQL/i + or m/Precomp/i or m/Pro\*C/i; + print; + } +} + +if ($::opt_s or $::opt_S) { + $::opt_s ||= $::opt_S; print "Searching for symbol '$::opt_s' in $OH ...\n"; my $dlext = $Config{dlext}; system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; - do echo " searching \$i ..."; nm \$i | grep $::opt_s; - done + do echo " searching oracle \$i ..."; nm \$i | grep $::opt_s; done }); + if ($::opt_S) { + my @libpth = split ' ', $Config{libpth}; + print "Searching for symbol '$::opt_s' in @libpth ...\n"; + @libpth = map { ("$_/lib*.$dlext", "$_/lib*.a") } @libpth; + system(qq{ cd $OH; for i in @libpth; + do echo " searching \$i ..."; nm \$i | grep $::opt_s; done + }); + } print "Search done.\n"; + print "(Please only include the 'interesting' parts when mailing.)\n"; exit; } @@ -139,11 +162,17 @@ elsif ($os eq 'MSWin32') { # --- UNIX Variants --- -elsif (@_=grep { m:/lib(clntsh|oracle).$Config{so}$:o } <$OH/lib/lib*>) { +elsif (@_=grep { m:/lib(cl(ie)?ntsh|oracle).\w+$:o } <$OH/lib/lib*> + and !defined $::opt_m) { # use -m 0 to disable this direct-link approach # --- the simple modern way --- - my $lib = ("@_" =~ m:/libclntsh\.:) ? "clntsh" : "oracle"; - $linkwith_msg = "$lib"; - $opts{LIBS} = [ "-L$OH/lib -l$lib" ]; + foreach(@_) { s:\Q$OH/lib/::g } + print "Found direct-link candidates: @_\n"; + my $lib = ("@_" =~ m:lib(cl(ie)?ntsh)\.:) ? $1 : "oracle"; + $linkwith_msg = "-l$lib."; + my $syslibs = read_file("$OH/rdbms/lib/sysliblist"); + $syslibs =~ s/-l:lib(\w+).sl\b/-l$1/g; # for hp-ux + print "Oracle sysliblist: $syslibs\n"; + $opts{LIBS} = [ "-L$OH/lib -l$lib $syslibs" ]; $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; $opts{INC} = "-I$OH/rdbms/demo -I$dbi_arch_dir"; } @@ -155,31 +184,34 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l if @ora_libs < 6; # just a helpful hint my $mkfile = find_mkfile(); - my $linkvia = fetch_oci_macros($mkfile); - my $libhome = expand_mkvars($MK{LIBHOME}, 0, 1, 0) || "$OH/lib"; + my $linkvia = fetch_oci_macros($mkfile); + my $libhome = expand_mkvars($MK{LIBHOME}, 0, 1, 0) || "$OH/lib"; $linkwith = expand_mkvars($linkvia, 0, 1, 0); $linkwith =~ s/-Y P,/-YP,/g if $Config{'cc'} =~ /gcc/; $linkwith =~ s:-R /:-R/:g if $os eq 'solaris'; # get a cut down $linkwith to pass to MakeMaker liblist my $linkwith_s = expand_mkvars($linkwith, 1, 1, 0); - # delete problematic crt?.o on solaris - $linkwith_s = del_crtobj($linkwith_s) if $os eq 'solaris'; # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" $linkwith_s =~ s!(\S+)/lib(\w+).a!-L$1 -l$2!g; - # extract object files, keep for use later - my @linkwith_o; - push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; - # also extract AIX .exp files since they confuse MakeMaker - push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; - + # Platform specific fix-ups: + # delete problematic crt?.o on solaris + $linkwith_s = del_crtobj($linkwith_s) if $os eq 'solaris'; + $linkwith_s =~ s/-l:lib(\w+).sl\b/-l$1/g; # for hp-ux + $linkwith_s .= " -lc" if $Config{archname} eq 'i386-dynixptx'; if ($os eq 'solaris' and $osvers >= 2.3 and $linkwith_s =~ /-lthread/) { print "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; print "Deleting -lthread from link list as a possible workround.\n"; $linkwith_s =~ s/\s*-lthread\b/ /g; } + # extract object files, keep for use later + my @linkwith_o; + push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; + # also extract AIX .exp files since they confuse MakeMaker + push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; + $linkwith_msg = "@linkwith_o $linkwith_s [from $linkvia]"; my $OCIINCLUDE = $MK{INCLUDE} || ''; $OCIINCLUDE .= " -I$OH/rdbms/demo"; @@ -308,27 +340,6 @@ sub MY::postamble { } -sub MY::post_constants { - my $self = shift; - - # Oracle Definitions, based on $(ORACLE_HOME)/proc/lib/proc.mk - # Please let me know if this does, or does not, work for you. - ' -################################################################### -# -ORACLE_HOME = '.$OH.' - -# The following text has been extracted from '.join("\n#\t", '', @mkfiles).' - -'.$MK.' - -# End of extract from '."@mkfiles".' -# -################################################################### -'; -} - - sub del_crtobj { my $orig = shift; my $str; @@ -346,11 +357,14 @@ sub find_mkfile { my @mkfiles; my @mkplaces = qw( proc/lib/proc.mk precomp/demo/proc/proc.mk precomp/demo/proc/demo_proc.mk - rdbms/lib/oracle.mk rdbms/demo/oracle.mk rdbms/demo/demo_rdbms.mk proc16/lib/proc16.mk + rdbms/lib/oracle.mk rdbms/demo/oracle.mk rdbms/demo/demo_rdbms.mk ); - # if -p then remove oracle.mk from search list and thus prefer Pro*C - @mkplaces = grep { !m/(oracle|rdbms)\.mk\b/ } @mkplaces if $::opt_p; + if ($::opt_p) { + # if -p then copy oracle.mk to start of search list and thus prefer it + my @ora = grep { !m/(oracle|rdbms)\.mk\b/ } @mkplaces; + unshift @mkplaces, @ora; + } if ($::opt_m) { $::opt_m = cwd()."/$::opt_m" unless $::opt_m =~ m:/\\:; die "-m $::opt_m: not found" unless -f $::opt_m; @@ -483,10 +497,10 @@ sub fetch_oci_macros { push(@MK, $_); } - if ($MK{LCLSH} and $use_clntsh) { + if ($MK{LCLSH} and !$::opt_c) { $linkvia = '$(LCLSH)'; } - elsif ($MK{LLIBCLNTSH} and $use_clntsh) { + elsif ($MK{LLIBCLNTSH} and !$::opt_c) { $linkvia = '$(LLIBCLNTSH)'; } elsif ($MK{OCILDLIBS}) { @@ -581,9 +595,24 @@ sub mkvar { return expand_mkvars($val, $strip, $backtick, $level+1); # can recurse } + +sub read_file { + my $file = shift; + unless (open(ROL, "<$file")) { + warn "Unable to open $file: $!"; + return ""; + } + my $text = join "", ; + $text =~ s/\n+/ /g; + close ROL; + return $text; +} + + sub find_bin{ my $bin = shift; - foreach(split(/:/, $ENV{PATH})){ + my $path_sep = $Config{path_sep}; + foreach (split(/$path_sep/, $ENV{PATH})){ return "$_/$bin" if -x "$_/$bin"; } return "<$bin not found>"; @@ -593,8 +622,31 @@ sub find_bin{ { package MY; # SUPER needs package context, $self is not sufficient + + sub post_constants { + my $self = shift; + # Oracle Definitions, based on $(ORACLE_HOME)/proc/lib/proc.mk + # Please let me know if this does, or does not, work for you. + ' +################################################################### +# +ORACLE_HOME = '.$OH.' + +# The following text has been extracted from '.join("\n#\t", '', @mkfiles).' + +'.$MK.' + +# End of extract from '."@mkfiles".' +# +################################################################### +'; + } + + sub const_cccmd { my($self) = shift; + print "Using DBD::Oracle $self->{VERSION}.\n"; + local($_) = $self->SUPER::const_cccmd(@_); # If perl Makefile.PL *-g* then switch on debugging if ($::opt_g) { diff --git a/Oracle.pm b/Oracle.pm index 99dc8960..b79165b0 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.49 1998/05/25 22:26:55 timbo Exp $ +# $Id: Oracle.pm,v 1.50 1998/06/01 18:34:16 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.48'; +$DBD::Oracle::VERSION = '0.49'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -22,7 +22,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; use Exporter (); @ISA = qw(DynaLoader Exporter); - my $Revision = substr(q$Revision: 1.49 $, 10); + my $Revision = substr(q$Revision: 1.50 $, 10); require_version DBI 0.92; @@ -31,8 +31,6 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; $err = 0; # holds error code for DBI::err (XXX SHARED!) $errstr = ""; # holds error string for DBI::errstr (XXX SHARED!) $drh = undef; # holds driver handle once initialised - %oratab = (); # holds list of oratab databases (e.g., local) - %tnstab = (); # holds list of names in tnsnames.ora sub driver{ return $drh if $drh; @@ -66,52 +64,65 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle::dr; # ====== DRIVER ====== use strict; - my %oratab; - my %tnstab; - sub load_oratab { # get list of 'local' database SIDs + my %dbnames = (); # holds list of known databases (oratab + tnsnames) + + sub load_dbnames { my ($drh) = @_; my $debug = $drh->debug; - foreach (qw(/etc /var/opt/oracle), $ENV{TNS_ADMIN}) { - next unless defined $_; - next unless open(ORATAB, "<$_/oratab"); - warn "Loading $_/oratab\n" if $debug; - while () { + my $oracle_home = $ENV{$ORACLE_ENV} || ''; + local *FH; + my $d; + + # get list of 'local' database SIDs from oratab + foreach $d (qw(/etc /var/opt/oracle), $ENV{TNS_ADMIN}) { + next unless defined $d; + next unless open(FH, "<$d/oratab"); + warn "Loading $d/oratab\n" if $debug; + while () { next unless m/^\s*(\w+)\s*:\s*(.*?)\s*:/; - $oratab{$1} = $2; # store ORACLE_HOME value - warn "Found $oratab{$1} = $_" if $debug; + $dbnames{$1} = $2; # store ORACLE_HOME value + warn "Found $1 \@ $2.\n" if $debug; } - close(ORATAB); + close FH; last; } - $oratab{' dummy '} = 1; # prevent reloads - } - sub load_tnstab { # get list of 'remote' database connection identifiers - my ($drh) = @_; - my $debug = $drh->debug; - my $oracle_home = $ENV{$ORACLE_ENV} || ''; - my $d; + # get list of 'remote' database connection identifiers foreach $d ($ENV{TNS_ADMIN}, "$oracle_home/network/admin", '/var/opt/oracle') { next unless defined $d; - next unless open(TNSTAB, "<$d/tnsnames.ora"); + next unless open(FH, "<$d/tnsnames.ora"); warn "Loading $d/tnsnames.ora\n" if $debug; - while () { - next unless m/^\s*([\w\.]+)\s*=/; - $tnstab{$1} = 1; - warn "Found $1" if $debug; + while () { + next unless m/^\s*([-\w\.]+)\s*=/; + if ($debug) { + warn "Found $1. ".($dbnames{$1} ? "(oratab entry overridded)" : "")."\n"; + } + $dbnames{$1} = 0; # exists but false (to distinguish from oratab) } - close(TNSTAB); + close FH; last; } - $tnstab{' dummy '} = 1; # prevent reloads + + eval q{ + warn "Fetching ORACLE_SID from Registry.\n" if $debug; + require Tie::Registry; + import Tie::Registry; + $Registry->Delimeter("/"); + my $hkey= $Registry->{"LMachine/Software/Oracle/"}; + my $sid = $hkey->{ORACLE_SID}; + my $home= $hkey->{ORACLE_HOME} || $ENV{ORACLE_HOME}; + $dbnames{$sid} = $home if $sid and $home; + warn "Found $sid \@ $home.\n" if $debug; + } if ($^O eq "MSWin32"); + + $dbnames{' dummy '} = 1; # mark as loaded (even if empty) } sub data_sources { my $drh = shift; - load_oratab($drh) unless %oratab; - load_tnstab($drh) unless %tnstab; - return (keys %oratab, keys %tnstab); # done't eliminate dups + load_dbnames($drh) unless %dbnames; + return (keys %dbnames); } @@ -140,18 +151,20 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; # Sadly the 'user/passwd@machine' form only works # for Sql*NET connections. - load_oratab($drh) unless %oratab; - load_tnstab($drh) unless %tnstab; - - if ($tnstab{$dbname}) { - $user .= '@'.$dbname; # assume it's a TNS alias - } - elsif ($oratab{$dbname}) { # is in oratab == is local - warn "Changing $ORACLE_ENV for $dbname" - if ($ENV{$ORACLE_ENV} and $oratab{$dbname} ne $ENV{$ORACLE_ENV}); - $ENV{$ORACLE_ENV} = $oratab{$dbname}; - $ENV{ORACLE_SID} = $dbname; - delete $ENV{TWO_TASK}; + load_dbnames($drh) unless %dbnames; + + if (exists $dbnames{$dbname}) { # known name + my $dbhome = $dbnames{$dbname}; # local=>ENV, remote=>0 + if ($dbhome) { + warn "Changing $ORACLE_ENV for $dbname to $dbhome" + if ($ENV{$ORACLE_ENV} and $dbhome ne $ENV{$ORACLE_ENV}); + $ENV{ORACLE_SID} = $dbname; + $ENV{$ORACLE_ENV} = $dbhome; + delete $ENV{TWO_TASK}; + } + else { + $user .= '@'.$dbname; # it's a known TNS alias + } } else { $user .= '@'.$dbname; # assume it's a TNS alias diff --git a/Oraperl.pm b/Oraperl.pm index 6d653e32..e5b67d50 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.36 1998/05/25 22:11:34 timbo Exp $ +# $Id: Oraperl.pm,v 1.37 1998/06/01 18:34:16 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -25,7 +25,7 @@ require 5.002; use DBI 0.84; use Exporter; -$VERSION = substr(q$Revision: 1.36 $, 10); +$VERSION = substr(q$Revision: 1.37 $, 10); @ISA = qw(Exporter); @@ -224,9 +224,9 @@ $Oraperl::ora_trunc = 0; # long trunc is error, oraperl default # ----------------------------------------------------------------- # # Non-oraperl extensions added here to make it easy to still run -# script using oraperl (by avoiding $csr->readblob(...)) +# script using oraperl (by avoiding $csr->blob_read(...)) -*ora_readblob = _func_ref('st::readblob'); +*ora_readblob = _func_ref('st::blob_read'); 1; @@ -421,9 +421,9 @@ other datatypes is always considered a error. B The optional second parameter to ora_fetch is not supported. A DBI usage error will be generated if a second parameter is supplied. Use the global variable $ora_trunc instead. Also note that the -experimental DBI readblob method can be used to retrieve a long: +experimental DBI blob_read method can be used to retrieve a long: - $csr->readblob($field, $offset, $len [, \$dest, $destoffset]); + $csr->blob_read($field, $offset, $len [, \$dest, $destoffset]); If truncation occurs, $ora_errno will be set to 1406. &ora_fetch() will complete successfully if truncation is permitted, otherwise it diff --git a/README b/README index 47a2cfd7..cd0c7622 100644 --- a/README +++ b/README @@ -83,14 +83,18 @@ Make sure you are using a recent perl 5.003 or preferably 5.004 and make sure it's on your path so you can say 'perl Makefile.PL' and not '/path/to/perl Makefile.PL'. -If you have build/link or core dump problems try using -"perl Makefile.PL -p". If that helps then *please* let me know. +If you have build/link or core dump problems try using one of these: + perl Makefile.PL -m 0 + perl Makefile.PL -m 0 -c + perl Makefile.PL -m 0 -p + perl Makefile.PL -m 0 -p -c +If one of them helps then please let me know. Do not hand edit the generated Makefile unless you are completely sure you understand the implications! Always try to make changes via the Makefile.PL command line and/or editing the Makefile.PL. -You should not need to make any changes. If you do *please* let me +You should not need to make any changes. If you do please let me know so that I can try to make it automatic in a later release. If you just can't login or login takes a long time then read @@ -104,13 +108,14 @@ If you have linking problems (errors related to libraries or functions) then you could try forcing a 'static' build using: make realclean - perl Makefile.PL LINKTYPE=static + perl Makefile.PL -XXX LINKTYPE=static make make perl (you'll need to use and install _this_ new perl binary) make test make -f Makefile.aperl inst_perl MAP_TARGET=perl make install +Where -XXX are zero or more options from the -m/-p/-c set listed above. >>> Also carefully read the README.help file which is full of useful >>> tips and workarounds for various problems of various systems. diff --git a/dbdimp.c b/dbdimp.c index 7a1685bf..baeab4ac 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.34 1998/05/25 22:11:34 timbo Exp $ + $Id: dbdimp.c,v 1.35 1998/06/01 18:34:16 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -220,7 +220,8 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) act.sa_flags |= SA_RESTART; sigaction( SIGCLD, &act, (struct sigaction*)0 ); if (dbis->debug >= 3) - warn("errno %d, handler %lx, flags %lx",errno,act.sa_handler,act.sa_flags); + warn("dbd_db_login: sigaction errno %d, handler %lx, flags %lx", + errno,act.sa_handler,act.sa_flags); if (dbis->debug >= 2) fprintf(DBILOGFP, " dbd_db_login: set SA_RESTART on Oracle SIGCLD handler.\n"); } @@ -663,22 +664,34 @@ dbd_describe(h, imp_sth) /* --- Setup the row cache for this query --- */ + /* Use guessed average on-the-wire row width calculated above */ + /* and add in overhead of 5 bytes per field plus 8 bytes per row. */ + /* The n*5+8 was determined by studying SQL*Net v2 packets. */ + /* It could probably benefit from a more detailed anaylsis. */ + est_width += num_fields*5 + 8; + if (has_longs) /* override/disable caching */ imp_sth->cache_rows = 1; /* else read_blob can't work */ - else if (imp_sth->cache_rows < 1) { /* automaticaly size the cache */ - /* 0 == try to pick 'optimal' cache for this query. */ - /* <0 == base cache on transfer size of -n bytes (default 2048) */ - /* Use guessed average on-the-wire row width calculated above */ - /* + overhead of 5 bytes per field plus 8 bytes per row. */ - int width = est_width + num_fields*5 + 8; - /* How many rows fit in 2Kb? (2Kb is a reasonable compromise) */ - int hunk = 2048; /* default cache size */ - if (imp_sth->cache_rows < 0) /* user is specifying txfr size */ - hunk = -imp_sth->cache_rows;/* is also approx cache size */ - imp_sth->cache_rows = hunk / width; - if (imp_sth->cache_rows < 5) /* always cache at least 5 */ - imp_sth->cache_rows = 5; + else if (imp_sth->cache_rows < 1) { /* automatically size the cache */ + int txfr_size; + /* 0 == try to pick 'optimal' cache for this query (default) */ + /* <0 == base cache on target transfer size of -n bytes. */ + if (imp_sth->cache_rows == 0) { + /* Oracle packets on ethernet have max size of around 1460. */ + /* We'll aim to fill our row cache with slightly less than */ + /* two packets (to err on the safe side and avoid a third */ + /* almost empty packet being generated in some cases). */ + txfr_size = 1460 * 1.6; /* default transfer/cache size */ + } + else { /* user is specifying desired transfer size in bytes */ + txfr_size = -imp_sth->cache_rows; + } + imp_sth->cache_rows = txfr_size / est_width; /* maybe 1 or 0 */ + /* To ensure good performance with large rows (near or larger */ + /* than our target transfer size) we set a minimum cache size. */ + if (imp_sth->cache_rows < 6) /* is cache a 'useful' size? */ + imp_sth->cache_rows = (imp_sth->cache_rows>0) ? 6 : 4; } if (imp_sth->cache_rows > 32767) /* keep within Oracle's limits */ imp_sth->cache_rows = 32767; @@ -749,11 +762,12 @@ dbd_describe(h, imp_sth) if (dbis->debug >= 2) fbh_dump(fbh, i, 0); } + imp_sth->est_width = est_width; if (dbis->debug >= 2) fprintf(DBILOGFP, - " dbd_describe'd %d columns (Row bytes: %d max, %d avg. Will prefetch %d rows)\n", - (int)num_fields, imp_sth->t_dbsize, est_width, imp_sth->cache_rows); + " dbd_describe'd %d columns (Row bytes: %d max, %d est avg. Cache: %d rows)\n", + (int)num_fields, imp_sth->t_dbsize, est_width, imp_sth->cache_rows); if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { D_imp_dbh_from_sth; @@ -915,6 +929,17 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl phs_t *phs; /* check if placeholder was passed as a number */ + + /* possible workaround for "unknown placeholder '3'" problem */ + if (!SvNIOK(ph_namesv) && !SvPOK(ph_namesv)) { + /* force SvPOK true before following tests */ + if (dbis->debug >= 2) + fprintf(DBILOGFP, + " bind warning: forcing placeholder flags: type %d, flags 0x%lx\n", + SvTYPE(ph_namesv), SvFLAGS(ph_namesv)); + name = SvPV(ph_namesv, name_len); + } + if (SvNIOK(ph_namesv) || (SvPOK(ph_namesv) && isDIGIT(*SvPVX(ph_namesv)))) { name = namebuf; sprintf(name, ":p%d", (int)SvIV(ph_namesv)); @@ -1203,7 +1228,7 @@ dbd_st_fetch(sth, imp_sth) if (rc == 1406 && dbtype_is_long(fbh->dbtype)) { /* We have a LONG field which has been truncated. */ int oraperl = DBIc_COMPAT(imp_sth); - if ((oraperl) ? SvIV(ora_trunc) : DBIc_has(imp_sth,DBIcf_LongTruncOk)) { + if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { /* user says truncation is ok */ /* Oraperl recorded the truncation in ora_errno so we */ /* so also but only for Oraperl mode handles. */ @@ -1227,19 +1252,21 @@ dbd_st_fetch(sth, imp_sth) } else if (rc == 1405) { /* field is null - return undef */ (void)SvOK_off(sv); - } else if (rc == 1406) { /* field truncated (see above) */ - /* copy the truncated value anyway, it may be of use */ - sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], + } else { /* See odefin rcode arg description in OCI docs */ + /* These may get more case-by-case treatment eventually. */ + if (rc == 1406) { /* field truncated (see above) */ + /* Copy the truncated value anyway, it may be of use, */ + /* but it'll only be accessible via prior bind_column() */ + sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], fb_ary->arlen[cache_entry]); + } + else { + SvOK_off(sv); /* set field that caused error to undef */ + } ++err; /* 'fail' this fetch but continue getting fields */ - - } else { /* See odefin rcode arg description in OCI docs */ - /* These may get case-by-case treatment eventually. */ /* Some should probably be treated as warnings but */ /* for now we just treat them all as errors */ - ora_error(sth, imp_sth->cda, rc, "ofetch rcode"); - (void)SvOK_off(sv); - ++err; /* 'fail' this fetch but continue getting fields */ + ora_error(sth, imp_sth->cda, rc, "ofetch field error"); } if (debug >= 3) @@ -1249,10 +1276,10 @@ dbd_st_fetch(sth, imp_sth) /* update cache counters */ if (ora_fetchtest) /* unless we're testing performance */ - --ora_fetchtest; - else { - --imp_sth->in_cache; - ++imp_sth->next_entry; + --ora_fetchtest; + else { + --imp_sth->in_cache; + ++imp_sth->next_entry; } return (err) ? Nullav : av; @@ -1464,6 +1491,14 @@ dbd_st_FETCH_attrib(sth, imp_sth, keysv) retsv = newSVpv((char*)&imp_sth->cda->rid, sizeof(imp_sth->cda->rid)); cacheit = FALSE; + } else if (kl==17 && strEQ(key, "ora_est_row_width")) { + retsv = newSViv(imp_sth->est_width); + cacheit = TRUE; + + } else if (kl==14 && strEQ(key, "ora_cache_rows")) { + retsv = newSViv(imp_sth->cache_rows); + cacheit = TRUE; + } else if (kl==4 && strEQ(key, "NAME")) { AV *av = newAV(); retsv = newRV(sv_2mortal((SV*)av)); diff --git a/dbdimp.h b/dbdimp.h index a13481fa..2be512e0 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.20 1998/05/25 22:11:34 timbo Exp $ + $Id: dbdimp.h,v 1.21 1998/06/01 18:34:16 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -96,6 +96,7 @@ struct imp_sth_st { int in_cache; int next_entry; int eod_errno; + int est_width; /* est'd avg row width on-the-wire */ /* (In/)Out Parameter Details */ bool has_inout_params; diff --git a/t/general.t b/t/general.t index d2d7f6df..ccd6c13b 100644 --- a/t/general.t +++ b/t/general.t @@ -28,25 +28,6 @@ print "1..$tests\n"; my($csr, $p1, $p2); -# --- test named numeric in/out parameters -#$dbh->trace(2); -my $sql = q{ - declare foo char(500); - begin - foo := :p1; - foo := :p2; - foo := :p3; - foo := :p4; - end; -}; -ok(0, $csr = $dbh->prepare($sql), 1); - -foreach (1..3) { - ok(0, $dbh->do($sql, undef, 7,8,9,1), 1); -# ok(0, $csr->execute(7,8,9,1), 1); -} - - # To do # test NULLs at first bind # NULLs later binds. @@ -58,7 +39,7 @@ $dbh->disconnect; ok(0, !$dbh->ping); exit 0; -BEGIN { $tests = 6 } +BEGIN { $tests = 2 } # end. __END__ diff --git a/t/plsql.t b/t/plsql.t index b6434080..b7554379 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -25,8 +25,12 @@ unless($dbh) { } # ORA-00900: invalid SQL statement -if (!$dbh->prepare(q{begin RAISE INVALID_NUMBER; end;}) && $dbh->err==900) { - warn "Your Oracle server doesn't support PL/SQL - Tests skipped.\n"; +# ORA-06553: PLS-213: package STANDARD not accessible +my $tst = $dbh->prepare(q{declare foo char(50); begin RAISE INVALID_NUMBER; end;}); +if ($dbh->err && ($dbh->err==900 || $dbh->err==6553)) { + warn "Your Oracle server doesn't support PL/SQL" if $dbh->err== 900; + warn "Your Oracle PL/SQL is not properly installed" if $dbh->err==6553; + warn "Tests skipped\n"; print "1..0\n"; exit 0; } diff --git a/test.pl b/test.pl index ecefcbde..6a9fd708 100755 --- a/test.pl +++ b/test.pl @@ -75,6 +75,8 @@ die "\nTest aborted.\n"; } # test_other($l); + print `sleep 1; echo Backticks OK` || "Backticks failed: $!\n" + if ($os ne 'MSWin32' and $os ne 'VMS'); &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; } $start = time; @@ -141,6 +143,8 @@ sub test1 { print "Names: '",join("',\t'", &ora_titles($csr)),"'\n"; print "Lengths: '",join("',\t'", &ora_lengths($csr)),"'\n"; print "Types: '",join("',\t'", &ora_types($csr)),"'\n"; + print "Est row width: $csr->{ora_est_row_width}\n"; + print "Prefetch cache: $csr->{ora_cache_rows}\n"; print "Data rows:\n"; #$csr->debug(2); From a6886cbc02dfeb0aa72eb3e8264341953c7e9052 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Thu, 4 Jun 1998 05:24:49 -0500 Subject: [PATCH 029/637] import DBD-Oracle 0.50 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.50 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.50.tar.gz --- Changes | 8 +++++ Makefile.PL | 95 ++++++++++++++++++++++++++++++++++++----------------- Oracle.pm | 16 +++++---- dbdimp.c | 10 +++--- 4 files changed, 88 insertions(+), 41 deletions(-) diff --git a/Changes b/Changes index 2c9620fa..12714c72 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,11 @@ +Changes in DBD::Oracle 0.50 (Oraperl 1.36), 3rd June 1998 + + Makefile.PL changes: fixed -c option, now searches for .h files, + tries alternate location for sysliblist, checks for executable + orainst/inspdver before using it. + Fixed cursor leak. + Added first word of tnsnames.ora name as aliases if no clash. + Changes in DBD::Oracle 0.49 (Oraperl 1.36), 1st June 1998 Further improvements to build process over 0.48. diff --git a/Makefile.PL b/Makefile.PL index 15b44e8e..064f0c3f 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.60 1998/06/01 18:34:16 timbo Exp $ +# $Id: Makefile.PL,v 1.61 1998/06/03 21:04:51 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -57,7 +57,7 @@ $::opt_v = 0; # be more verbose $::opt_d = 0; # much more verbose for debugging $::opt_old = 0; # old style .mk file parsing -GetOptions(qw(v! d! g! old! p! m=s s=s S=s)) or die "Invalid arguments"; +GetOptions(qw(v! d! g! c! old! p! m=s s=s S=s)) or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string $::opt_v = 1 if $::opt_d; @@ -77,45 +77,37 @@ print "\n Configuring DBD::Oracle ...\n my $ORACLE_ENV = ($os eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; my $OH = $ENV{$ORACLE_ENV}; -$OH =~ s:\\:/:g; # for Win32 +$OH =~ s:\\:/:g if $os eq 'MSWin32'; ($OH = unixify $OH) =~ s:/$:: if $os eq 'VMS'; die "$ORACLE_ENV environment variable must be set.\n" unless $OH; die "$ORACLE_ENV environment variable ($OH) not valid.\n" unless -d $OH; print "Using Oracle in $OH\n"; -if ($os ne 'VMS' and $os ne 'MSWin32' and -d "$OH/orainst") { +my (@inspdver, %inspdver); +if ($os ne 'VMS' and $os ne 'MSWin32' and -x "$OH/orainst/inspdver") { open INST, "$OH/orainst/inspdver |"; my @inspdver = ; close INST; foreach (@inspdver) { + chop; + $inspdver{$2} = $1 if m/^(\S+)\s+(.*)/; + $inspdver{RDBMS} = $1 if m/^(\d+\.\d+\.\d+)\S*\s+.*RDBMS/; next unless $::opt_v - or m/Common Libraries/i or m/RDBMS/i or m/PL.SQL/i or m/Precomp/i or m/Pro\*C/i; - print; + print "$_\n"; + } + print "\n"; + if ($inspdver{RDBMS} =~ /^7.3.[12]/ and $os eq 'hpux') { + print "DBD::Oracle for Oracle $inspdver{RDBMS} on HP-UX may not build ok.\n"; + print "If your have problems read the README (in fact, read it anyway!)\n"; + print "An upgrade to Oracle 7.3.3 is probably a good idea.\n"; + sleep 5; } } -if ($::opt_s or $::opt_S) { - $::opt_s ||= $::opt_S; - print "Searching for symbol '$::opt_s' in $OH ...\n"; - my $dlext = $Config{dlext}; - system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; - do echo " searching oracle \$i ..."; nm \$i | grep $::opt_s; done - }); - if ($::opt_S) { - my @libpth = split ' ', $Config{libpth}; - print "Searching for symbol '$::opt_s' in @libpth ...\n"; - @libpth = map { ("$_/lib*.$dlext", "$_/lib*.a") } @libpth; - system(qq{ cd $OH; for i in @libpth; - do echo " searching \$i ..."; nm \$i | grep $::opt_s; done - }); - } - print "Search done.\n"; - print "(Please only include the 'interesting' parts when mailing.)\n"; - exit; -} +symbol_search() if $::opt_s or $::opt_S; # --- How shall we link with Oracle? Let me count the ways... @@ -163,18 +155,21 @@ elsif ($os eq 'MSWin32') { # --- UNIX Variants --- elsif (@_=grep { m:/lib(cl(ie)?ntsh|oracle).\w+$:o } <$OH/lib/lib*> - and !defined $::opt_m) { # use -m 0 to disable this direct-link approach + and !defined $::opt_m) { # use -m 0 to disable this direct-link approach # --- the simple modern way --- foreach(@_) { s:\Q$OH/lib/::g } print "Found direct-link candidates: @_\n"; my $lib = ("@_" =~ m:lib(cl(ie)?ntsh)\.:) ? $1 : "oracle"; $linkwith_msg = "-l$lib."; - my $syslibs = read_file("$OH/rdbms/lib/sysliblist"); + my $syslibs = (-f "$OH/lib/sysliblist") + ? read_file("$OH/lib/sysliblist") + : read_file("$OH/rdbms/lib/sysliblist"); $syslibs =~ s/-l:lib(\w+).sl\b/-l$1/g; # for hp-ux print "Oracle sysliblist: $syslibs\n"; $opts{LIBS} = [ "-L$OH/lib -l$lib $syslibs" ]; $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; - $opts{INC} = "-I$OH/rdbms/demo -I$dbi_arch_dir"; + my $inc = join " ", map { "-I$OH/$_" } find_headers(); + $opts{INC} = "$inc -I$dbi_arch_dir"; } else { # --- trawl the guts of Oracle's make files looking the how it wants to link @@ -218,7 +213,8 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l $opts{LIBS} = [ "-L$libhome $linkwith_s" ]; my $compobj = '$(COMPOBJS)'; $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o $compobj" }; - $opts{INC} = "$OCIINCLUDE -I$dbi_arch_dir"; + my $inc = join " ", map { "-I$OH/$_" } find_headers(); + $opts{INC} = "$OCIINCLUDE $inc -I$dbi_arch_dir"; } @@ -599,7 +595,7 @@ sub mkvar { sub read_file { my $file = shift; unless (open(ROL, "<$file")) { - warn "Unable to open $file: $!"; + warn "WARNING: Unable to open $file: $!\n"; return ""; } my $text = join "", ; @@ -619,6 +615,45 @@ sub find_bin{ } +sub find_headers { + my (%h_dir, @h_dir); + find( sub { + return unless /^o(ci...|ratypes)\.h$/i; + my $dir = $File::Find::dir; + $dir =~ s:^\Q$OH/::; + $h_dir{$dir} = $_; + print "Found $dir/$_\n" if $::opt_v; + }, "$OH/rdbms" ); + @h_dir = keys %h_dir; + print "Found header files in @h_dir.\n" if @h_dir; + return @h_dir; +} + + +sub symbol_search { + $::opt_s ||= $::opt_S; + print "Searching for symbol '$::opt_s' in $OH ...\n"; + my $dlext = $Config{dlext}; + system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; + do echo " searching oracle \$i ..."; nm \$i | grep $::opt_s; done + }); + if ($::opt_S) { + my @libpth = split ' ', $Config{libpth}; + print "Searching for symbol '$::opt_s' in @libpth ...\n"; + @libpth = map { ("$_/lib*.$dlext", "$_/lib*.a") } @libpth; + system(qq{ cd $OH; for i in @libpth; + do echo " searching \$i ..."; nm \$i | grep $::opt_s; done + }); + } + print "Search done.\n"; + print "(Please only include the 'interesting' parts when mailing.)\n"; + exit; +} + + +# ===================================================================== + + { package MY; # SUPER needs package context, $self is not sufficient diff --git a/Oracle.pm b/Oracle.pm index b79165b0..11e8c31b 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.50 1998/06/01 18:34:16 timbo Exp $ +# $Id: Oracle.pm,v 1.51 1998/06/03 21:04:51 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.49'; +$DBD::Oracle::VERSION = '0.50'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -22,7 +22,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; use Exporter (); @ISA = qw(DynaLoader Exporter); - my $Revision = substr(q$Revision: 1.50 $, 10); + my $Revision = substr(q$Revision: 1.51 $, 10); require_version DBI 0.92; @@ -95,10 +95,14 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; warn "Loading $d/tnsnames.ora\n" if $debug; while () { next unless m/^\s*([-\w\.]+)\s*=/; - if ($debug) { - warn "Found $1. ".($dbnames{$1} ? "(oratab entry overridded)" : "")."\n"; + my $name = $1; + warn "Found $name. ".($dbnames{$name} ? "(oratab entry overridden)" : "")."\n" + if $debug; + $dbnames{$name} = 0; # exists but false (to distinguish from oratab) + if ($name =~ /^([-\w]+)\.([-\w\.]+)/ && !exists $dbnames{$1}) { + warn " also $1. \n" if $debug; + $dbnames{$1} = 0; # exists but false (to distinguish from oratab) } - $dbnames{$1} = 0; # exists but false (to distinguish from oratab) } close FH; last; diff --git a/dbdimp.c b/dbdimp.c index baeab4ac..c6b920c3 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.35 1998/06/01 18:34:16 timbo Exp $ + $Id: dbdimp.c,v 1.36 1998/06/03 21:04:51 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -403,7 +403,7 @@ free_cursor(sth, imp_sth) SV *sth; imp_sth_t *imp_sth; { - if (DBIc_ACTIVE(imp_sth)) /* should never happen here */ + if (DBIc_ACTIVE(imp_sth)) /* should never happen here */ ocan(imp_sth->cda); if (oclose(imp_sth->cda)) { /* close the cursor */ @@ -935,7 +935,7 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl /* force SvPOK true before following tests */ if (dbis->debug >= 2) fprintf(DBILOGFP, - " bind warning: forcing placeholder flags: type %d, flags 0x%lx\n", + " bind warning: forcing placeholder flags: type %l, flags 0x%lx\n", SvTYPE(ph_namesv), SvFLAGS(ph_namesv)); name = SvPV(ph_namesv, name_len); } @@ -1381,8 +1381,8 @@ dbd_st_destroy(sth, imp_sth) /* Check if an explicit disconnect() or global destruction has */ /* disconnected us from the database before attempting to close. */ - if (DBIc_ACTIVE(imp_dbh) && DBIc_ACTIVE(imp_sth)) { - free_cursor(sth, imp_sth); /* ignore errors here */ + if (DBIc_ACTIVE(imp_dbh)) { + free_cursor(sth, imp_sth); /* ignore errors here */ /* fall through anyway to free up our memory */ } From 6f4b8d0db4cd7943d31578249a32f8d0f677d436 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Mon, 6 Jul 1998 08:46:20 -0500 Subject: [PATCH 030/637] import DBD-Oracle 0.51 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.51 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.51.tar.gz --- Changes | 8 ++ Makefile.PL | 89 +++++++++++---------- Oracle.pm | 31 ++++++-- README | 43 ++++++----- Todo | 2 +- dbdimp.c | 219 ++++++++++++++++++++++++++++++++++------------------ dbdimp.h | 4 +- t/plsql.t | 27 ++++++- test.pl | 115 ++++++++++++++------------- 9 files changed, 325 insertions(+), 213 deletions(-) diff --git a/Changes b/Changes index 12714c72..57862027 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,11 @@ +Changes in DBD::Oracle 0.51 (Oraperl 1.37), 5rd July 1998 + + Makefile.PL no longer tries to link with just -lclntsh directly :-( + Improvements to some HP-UX builds (hopefully). + DBI->data_sources ' dummy ' value removed (and list now sorted). + connect failure now shows actual Oracle error message again. + Initial (incomplete) support for binding cursor vars (see t/plsql.t). + Changes in DBD::Oracle 0.50 (Oraperl 1.36), 3rd June 1998 Makefile.PL changes: fixed -c option, now searches for .h files, diff --git a/Makefile.PL b/Makefile.PL index 064f0c3f..692d854a 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.61 1998/06/03 21:04:51 timbo Exp $ +# $Id: Makefile.PL,v 1.62 1998/07/05 21:25:07 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -37,6 +37,7 @@ my %opts = ( NAME => 'DBD::Oracle', VERSION_FROM => 'Oracle.pm', OBJECT => '$(O_FILES)', + DEFINE => '', DIR => [], clean => { FILES=> 'Oracle.xsi' }, dist => { DIST_DEFAULT => 'clean distcheck disttest ci tardist', @@ -47,17 +48,16 @@ my %opts = ( my(@MK, %MK, $MK, %MK_expanding); # parsed macros from Oracle's makefiles # Options (rarely needed) -$::opt_m = undef; # path to proc.mk or oracle.mk file to read +$::opt_m = 0; # path to proc.mk or oracle.mk file to read $::opt_p = ''; # prefer oracle.mk over proc +$::opt_l = 0; # try direct-link to libclntsh $::opt_g = ''; # enable debugging (-g for compiler and linker) -$::opt_c = ''; # disable linking to clntsh (LCLSH/LLIBCLNTSH in *.mk) $::opt_s = ''; # Find a symbol in oracle libs, Don't build a Makefile $::opt_S = ''; # Find a symbol in oracle & system libs, Don't build a Makefile $::opt_v = 0; # be more verbose $::opt_d = 0; # much more verbose for debugging -$::opt_old = 0; # old style .mk file parsing -GetOptions(qw(v! d! g! c! old! p! m=s s=s S=s)) or die "Invalid arguments"; +GetOptions(qw(v! d! g! p! l! m=s s=s S=s)) or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string $::opt_v = 1 if $::opt_d; @@ -154,8 +154,9 @@ elsif ($os eq 'MSWin32') { # --- UNIX Variants --- -elsif (@_=grep { m:/lib(cl(ie)?ntsh|oracle).\w+$:o } <$OH/lib/lib*> - and !defined $::opt_m) { # use -m 0 to disable this direct-link approach +elsif ($::opt_l and # use -l to enable this direct-link approach + @_=grep { m:/lib(cl(ie)?ntsh|oracle).\w+$:o } <$OH/lib/lib*> + ) { # --- the simple modern way --- foreach(@_) { s:\Q$OH/lib/::g } print "Found direct-link candidates: @_\n"; @@ -164,7 +165,7 @@ elsif (@_=grep { m:/lib(cl(ie)?ntsh|oracle).\w+$:o } <$OH/lib/lib*> my $syslibs = (-f "$OH/lib/sysliblist") ? read_file("$OH/lib/sysliblist") : read_file("$OH/rdbms/lib/sysliblist"); - $syslibs =~ s/-l:lib(\w+).sl\b/-l$1/g; # for hp-ux + $syslibs =~ s/-l:lib(\w+).(sl|a)\b/-l$1/g if $os eq 'hpux'; print "Oracle sysliblist: $syslibs\n"; $opts{LIBS} = [ "-L$OH/lib -l$lib $syslibs" ]; $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; @@ -223,12 +224,15 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l # HP-UX 9 cannot link a non-PIC object file into a shared library. # Since the # .a libs that Oracle supplies contain non-PIC object # files, we sadly have to build static on HP-UX 9 :( -if ($os eq 'hpux' and $osvers < 10) { - $opts{LINKTYPE} = 'static'; - print "Warning: Forced to build static not dynamic on $os $osvers.\a\n"; -} -if ($os eq 'hpux' and $osvers >= 10) { - print "Warning: You may need to build using static linking. See the README file.\n\a"; +if ($os eq 'hpux') { + if ($osvers < 10) { + print "Warning: Forced to build static not dynamic on $os $osvers.\a\n"; + $opts{LINKTYPE} = 'static'; + } + else { + print "Warning: You may need to build using static linking. See the README file.\n"; + } + # see const_cccmd for -Aa to -Ae flag change } if ($os eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { @@ -236,7 +240,7 @@ if ($os eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { print " You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV\n"; } -$opts{DEFINE} = '-Wall -Wno-comment' if $Config{cc} eq 'gcc'; +$opts{DEFINE} .= '-Wall -Wno-comment' if $Config{cc} eq 'gcc'; $opts{DEFINE} .= '-Xa' if $Config{cc} eq 'clcc'; # CenterLine CC @@ -248,6 +252,9 @@ if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess $Verbose = 1; $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith -pedantic -Wtraditional' . ' -Wbad-function-cast -Wcast-qual' if $Config{cc} eq 'gcc'; + $::opt_g = '-g'; + $opts{dynamic_lib}->{OTHERLDFLAGS} ||= ''; + $opts{dynamic_lib}->{OTHERLDFLAGS} .= " $::opt_g"; } if ($opts{LINKTYPE} && $opts{LINKTYPE} eq 'static') { @@ -449,21 +456,12 @@ sub fetch_oci_macros { s/\.(\$\(LIB_EXT\))/$1/g; } - if ($::opt_old) { - last if m/^\w+\s*:[^=]/; # gone too far, reached actual targets - } - else { - next if m!^[-\w/+.\$()]+\s*:+[^=]*!; # skip targets - next if m!^\t!; # skip target build rules - } + next if m!^[-\w/+.\$()]+\s*:+[^=]*!; # skip targets + next if m!^\t!; # skip target build rules next if m/^\s*\.SUFFIXES/; - unless($MK{mkver}) { # still need to get version number - # This is tough since some versions of proc.mk split the - # RCS header over three lines! Later versions don't even - # have one. That's Oracle for you. - my $line = $_; - $line =~ s/[\\\r\n]/ /g; + unless($MK{mkver}) { # still want to get version number + my $line = $_; $line =~ s/[\\\r\n]/ /g; $MK{mkver} = $mkver = $1 if $line =~ m/\$Header:.*?\.mk.+(\d+\.\d+)/; } @@ -471,14 +469,8 @@ sub fetch_oci_macros { # We always store values into %MK before checking %edit # %edit can edit this in addition to $_ if needed. my $name; - if ($::opt_old) { - $MK{$1} = $2 if m/^\s*(\w+)\s*=\s*([\s\S]*)/; - $name = $1; - } - else { - $MK{$1}= $' if m/^\s*(\w+)\s*=\s*/; - $name = $1; - } + $MK{$1}= $' if m/^\s*(\w+)\s*=\s*/; + $name = $1; if ($name and exists $edit{$name}) { my $pre = $_; @@ -493,15 +485,18 @@ sub fetch_oci_macros { push(@MK, $_); } - if ($MK{LCLSH} and !$::opt_c) { - $linkvia = '$(LCLSH)'; - } - elsif ($MK{LLIBCLNTSH} and !$::opt_c) { - $linkvia = '$(LLIBCLNTSH)'; - } - elsif ($MK{OCILDLIBS}) { + # --- now decide what to link with --- + if ($MK{OCILDLIBS}) { $linkvia = '$(OCILDLIBS)'; } + elsif ($MK{PROLDLIBS}) { # Oracle 7.3.x + if ($MK{PROLDLIBS} =~ /thread/i && $MK{PROLLSshared}) { + $linkvia = '$(PROLLSshared)'; + } + else { + $linkvia = '$(PROLDLIBS)'; + } + } elsif (int($mkver) == 1) { if ($MK{LLIBOCIC}) { $linkvia = '$(LLIBOCIC) $(TTLIBS)'; @@ -510,9 +505,6 @@ sub fetch_oci_macros { $linkvia = '-locic $(TTLIBS)'; # XXX GUESS HACK } } - elsif ($MK{PROLDLIBS}) { # Oracle 7.3.x - $linkvia = '$(PROLDLIBS)'; - } unless ($linkvia){ die "ERROR parsing $file: Unable to determine what to link with.\n" ."Please send me copies of these files (one per mail message):\n@mkfiles\n"; @@ -688,6 +680,11 @@ ORACLE_HOME = '.$OH.' s/\s-O\d?\b//; # delete optimise option s/\s-/ -g -/; # add -g option } + # are we using the non-bundled hpux compiler? + if ($os eq "hpux" and $Config::Config{ccflags} =~ /-Aa\b/) { + print "Changing -Aa to -Ae for HP-UX.\n"; + s/-Aa\b/-Ae/g; # allow "long long" in oratypes.h + } $_; } diff --git a/Oracle.pm b/Oracle.pm index 11e8c31b..4512633d 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.51 1998/06/03 21:04:51 timbo Exp $ +# $Id: Oracle.pm,v 1.53 1998/07/05 21:49:00 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.50'; +$DBD::Oracle::VERSION = '0.51'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -22,7 +22,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; use Exporter (); @ISA = qw(DynaLoader Exporter); - my $Revision = substr(q$Revision: 1.51 $, 10); + my $Revision = substr(q$Revision: 1.53 $, 10); require_version DBI 0.92; @@ -108,7 +108,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; last; } - eval q{ + eval q{ # XXX experimental, will probably change warn "Fetching ORACLE_SID from Registry.\n" if $debug; require Tie::Registry; import Tie::Registry; @@ -120,13 +120,15 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; warn "Found $sid \@ $home.\n" if $debug; } if ($^O eq "MSWin32"); - $dbnames{' dummy '} = 1; # mark as loaded (even if empty) + $dbnames{0} = 1; # mark as loaded (even if empty) } sub data_sources { my $drh = shift; load_dbnames($drh) unless %dbnames; - return (keys %dbnames); + my @names = sort keys %dbnames; + my @sources = map { $_ ? ("dbi:Oracle:$_") : () } @names; + return @sources; } @@ -529,7 +531,7 @@ Also note that the NLS files $ORACLE_HOME/ocommon/nls/admin/data changed extension (from .d to .nlb) between 7.2.3 and 7.3.2. -=head1 SEE ALSO +=head1 PL/SQL Examples These PL/SQL examples come from: Eric Bartley . @@ -704,6 +706,19 @@ You can find more examples in the t/plsql.t file in the DBD::Oracle source directory. +=head1 Commercial Oracle Tools + +Assorted tools and references for general information. No recommendation implied. + +PL/Vision from RevealNet and Steven Feuerstein. + +Platinum Technology: http://www.platinum.com/products/oracle.htm + +"Q" from Savant Corporation. + +http://www.databasegroup.com + + =head1 SEE ALSO L @@ -714,7 +729,7 @@ Linux uses should read: =head1 AUTHOR -DBD::Oracle by Tim Bunce. +DBD::Oracle by Tim Bunce. DBI by Tim Bunce. =head1 COPYRIGHT diff --git a/README b/README index cd0c7622..100f5333 100644 --- a/README +++ b/README @@ -45,7 +45,7 @@ WARNING: Remember to *read* the DBI README file and this one CAREFULLY! Install enough Oracle software to enable DBD::Oracle to build. - That includes Pro*C. + That usually includes Pro*C. *** BUILDING: @@ -83,22 +83,20 @@ Make sure you are using a recent perl 5.003 or preferably 5.004 and make sure it's on your path so you can say 'perl Makefile.PL' and not '/path/to/perl Makefile.PL'. -If you have build/link or core dump problems try using one of these: - perl Makefile.PL -m 0 - perl Makefile.PL -m 0 -c - perl Makefile.PL -m 0 -p - perl Makefile.PL -m 0 -p -c -If one of them helps then please let me know. +If you have build/link or core dump problems try: + perl Makefile.PL -p +If it helps then please let me know (and please include a copy +of the log from the failed default build, the log from the build that +worked, plus the output of the "perl -V" command). Do not hand edit the generated Makefile unless you are completely sure you understand the implications! Always try to make changes via the Makefile.PL command line and/or editing the Makefile.PL. - You should not need to make any changes. If you do please let me know so that I can try to make it automatic in a later release. If you just can't login or login takes a long time then read -README.login and edit test.pl to suit. +README.login and possibly edit test.pl to suit. If you can't get it to build on a minimally configured client system then read README.client, it might help but basically I can't help much. @@ -107,15 +105,14 @@ Others on the dbi-users mailing list probably can. If you have linking problems (errors related to libraries or functions) then you could try forcing a 'static' build using: - make realclean - perl Makefile.PL -XXX LINKTYPE=static - make - make perl (you'll need to use and install _this_ new perl binary) - make test - make -f Makefile.aperl inst_perl MAP_TARGET=perl - make install + make realclean + perl Makefile.PL LINKTYPE=static + make + make perl (you'll need to use and install _this_ new perl binary) + make test + make -f Makefile.aperl inst_perl MAP_TARGET=perl (install new perl) + make install (install DBD::Oracle) -Where -XXX are zero or more options from the -m/-p/-c set listed above. >>> Also carefully read the README.help file which is full of useful >>> tips and workarounds for various problems of various systems. @@ -125,7 +122,7 @@ Where -XXX are zero or more options from the -m/-p/-c set listed above. Please don't post problems to comp.lang.perl.* or perl5-porters. This software is supported via the dbi-users mailing list. For more -information and to keep informed about progress you can join the a +information and to keep informed about progress you can join the mailing list via http://www.fugue.com/dbi (if you are unable to use the web you can subscribe by sending a message to dbi-request@fugue.com, it may take a few days to be processed). @@ -143,9 +140,10 @@ dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. But note... make test make test TEST_VERBOSE=1 (only if any of the t/* tests fail) -2. Full details of which version of Oracle you're using. +2. Full details of which version of Oracle you're using (if it + wasn't automatically found and printed by "perl Makefile.PL") -3. The output of perl -V (that a capital V, not lowercase) +3. The output of perl -V (that's a capital V, not lowercase) 4. If you get errors like "undefined symbol", "symbol not found", "undefined reference", "Text relocation remains" or any similar @@ -173,6 +171,8 @@ the latest". You would do yourself a favour by upgrading beforehand. Please remember that I'm _very_ busy. Try to help yourself first, then try to help me help you by following these guidelines carefully. +And remember, please don't mail me directly - use the dbi-users +mailing list. Regards, Tim. @@ -185,7 +185,8 @@ README.clients -- building/using DBD::Oracle on minimally configured systems README.login -- help for login problems README.longs -- examples dealing with LONG types (blobs) -DBI 'home page': http://www.arcana.co.uk/technologia/DBI +DBI 'home page': http://www.arcana.co.uk/technologia/DBI (sadly often +out of date) Master archive site for Perl DB information: ftp://ftp.demon.co.uk/pub/perl/db/ diff --git a/Todo b/Todo index 1f3c2918..1d03e32a 100644 --- a/Todo +++ b/Todo @@ -14,7 +14,7 @@ number and other info here). http://outside.organic.com/mail-archives/dbi-users/Nov1997/0116.html -LongReadLen and LongTruncOk +Test LongReadLen and especially the default behaviour of LongTruncOk Add explain to dist diff --git a/dbdimp.c b/dbdimp.c index c6b920c3..d2adeedd 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.36 1998/06/03 21:04:51 timbo Exp $ + $Id: dbdimp.c,v 1.37 1998/07/05 21:25:07 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -12,6 +12,10 @@ #include "Oracle.h" +/* XXX DBI should provide a better version of this */ +#define IS_DBI_HANDLE(h) \ + (SvROK(h) && SvTYPE(SvRV(h)) == SVt_PVHV && \ + SvRMAGICAL(SvRV(h)) && (SvMAGIC(SvRV(h)))->mg_type == 'P') DBISTATE_DECLARE; @@ -20,7 +24,7 @@ static SV *ora_trunc; static SV *ora_pad_empty; static SV *ora_cache; static SV *ora_cache_o; /* temp hack for ora_open() cache override */ -static int ora_login_err; /* fetch & show real login errmsg if true */ +static int ora_login_nomsg; /* don't fetch real login errmsg if true */ static int ora_fetchtest = 0; static void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); @@ -41,7 +45,7 @@ dbd_init(dbistate) sv_setiv(ora_pad_empty, atoi(getenv("ORAPERL_PAD_EMPTY"))); if (getenv("DBD_ORACLE_LOGIN_ERR")) - ora_login_err = atoi(getenv("DBD_ORACLE_LOGIN_ERR")); + ora_login_nomsg = atoi(getenv("DBD_ORACLE_LOGIN_NOMSG")); } @@ -140,9 +144,10 @@ dbtype_is_long(dbtype) } static int -dbtype_can_be_string(dbtype) /* 'can we use SvPV to pass buffer?' */ +oratype_bind_ok(dbtype) /* It's a type we support for placeholders */ int dbtype; { + /* basically we support types that can be returned as strings */ switch(dbtype) { case 1: /* VARCHAR2 */ case 5: /* STRING */ @@ -152,6 +157,9 @@ dbtype_can_be_string(dbtype) /* 'can we use SvPV to pass buffer?' */ case 96: /* CHAR */ case 97: /* CHARZ */ case 106: /* MLSLABEL */ +#ifdef SQLT_CUR + case SQLT_CUR: /* cursor variable */ +#endif return 1; } return 0; @@ -230,34 +238,19 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) if (ret) { int rc = imp_dbh->lda->rc; + char *msg; /* oerhms in ora_error may hang or corrupt memory (!) after a connect */ - /* failure. So we fake the common error messages unless ora_login_err */ - /* is true (set via env var above). Thank Oracle for this sad hack. */ + /* failure in some specific versions of Oracle 7.3.x. So we provide a */ + /* way to skip the message lookup if ora_login_nomsg is true (set via */ + /* env var above). */ char buf[100]; - char *msg="ORA-%d: (Text for error %d not fetched. Use 'oerr ORA %d' command.)"; - switch (rc) { - case 1019: msg="ORA-%d: unable to allocate memory in the user side (probably a symptom of a deeper problem)"; - break; - case 1017: msg="ORA-%d: invalid username/password; login denied"; - break; - case 1034: msg="ORA-%d: ORACLE not available"; - break; - case 2700: msg="ORA-%d: osnoraenv: error translating ORACLE_SID"; - break; - case 3106: msg="ORA-%d: fatal two-task communication protocol error"; - break; - case 3121: msg="no interface driver connected - function not performed"; - break; - case 12154: msg="TNS-%d: TNS:could not resolve service name"; - break; - case 12545: msg="TNS-%d: TNS:name lookup failure"; - break; - case 12203: msg="TNS-%d: TNS:unable to connect to destination"; - break; - } - sprintf(buf, msg, rc, rc, rc); - ora_error(dbh, ora_login_err ? imp_dbh->lda : NULL, rc, - ora_login_err ? "login failed" : buf); + sprintf(buf, + "ORA-%05d: (Text for error %d not fetched. Use 'oerr ORA %d' command.)", + rc, rc, rc); + /* 1019 is a common but misleading error code (often NLS msg cat related) */ + msg = (rc!=1019) ? "login failed" + : "login failed, probably a symptom of a deeper problem"; + ora_error(dbh, ora_login_nomsg ? NULL : imp_dbh->lda, rc, msg); return 0; } DBIc_IMPSET_on(imp_dbh); /* imp_dbh set up now */ @@ -390,11 +383,11 @@ get_cursor(imp_dbh, sth, imp_sth) SV *sth; imp_sth_t *imp_sth; { - imp_sth->cda = &imp_sth->cdabuf; - if (oopen(imp_sth->cda, imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oopen error"); + if (oopen(&imp_sth->cdabuf, imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { + ora_error(sth, &imp_sth->cdabuf, imp_sth->cdabuf.rc, "oopen error"); return 0; } + imp_sth->cda = &imp_sth->cdabuf; return 1; } @@ -403,11 +396,14 @@ free_cursor(sth, imp_sth) SV *sth; imp_sth_t *imp_sth; { + if (!imp_sth->cda) + return 0; + if (DBIc_ACTIVE(imp_sth)) /* should never happen here */ - ocan(imp_sth->cda); + ocan(imp_sth->cda); /* XXX probably not needed before oclose */ if (oclose(imp_sth->cda)) { /* close the cursor */ - /* Check for ORA-01041: 'hostdef extension doesn't exist' ? */ + /* Check for ORA-01041: 'hostdef extension doesn't exist' ? XXX */ /* which indicates that the lda had already been logged out */ /* in which case only complain if not in 'global destruction'? */ ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oclose error"); @@ -593,15 +589,16 @@ dbd_describe(h, imp_sth) if (imp_sth->cda->ft != FT_SELECT) { if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_describe skipped for non-select (sql f%d, lb %ld)\n", - imp_sth->cda->ft, (long)long_buflen); + fprintf(DBILOGFP, + " dbd_describe skipped for non-select (sql f%d, lb %ld, csr 0x%lx)\n", + imp_sth->cda->ft, (long)long_buflen, (long)imp_sth->cda); /* imp_sth memory was cleared when created so no setup required here */ return 1; } if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_describe (for sql f%d after oci f%d, lb %ld)...\n", - imp_sth->cda->ft, imp_sth->cda->fc, (long)long_buflen); + fprintf(DBILOGFP, " dbd_describe (for sql f%d after oci f%d, lb %ld, csr 0x%lx)...\n", + imp_sth->cda->ft, imp_sth->cda->fc, (long)long_buflen, (long)imp_sth->cda); if (!f_cbufl) { f_cbufl_max = 120; @@ -808,22 +805,22 @@ ora_sql_type(imp_sth, name, sql_type) -static int -_dbd_rebind_ph(sth, imp_sth, phs) +static void +_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) SV *sth; imp_sth_t *imp_sth; phs_t *phs; + ub2 **alen_ptr_ptr; { STRLEN value_len; - ub2 *alen_ptr; -/* for strings, must be a PV first for ptr to be valid? */ +/* for inserting longs: */ /* sv_insert +4 */ /* sv_chop(phs->sv, SvPV(phs->sv,na)+4); XXX */ if (dbis->debug >= 2) { - char *text = neatsvpv(phs->sv,0); - fprintf(DBILOGFP, " bind %s <== %s (", phs->name, text); + char *val = neatsvpv(phs->sv,0); + fprintf(DBILOGFP, " bind %s <== %s (", phs->name, val); if (SvOK(phs->sv)) fprintf(DBILOGFP, "size %ld/%ld/%ld, ", (long)SvCUR(phs->sv),(long)SvLEN(phs->sv),phs->maxlen); @@ -839,13 +836,13 @@ _dbd_rebind_ph(sth, imp_sth, phs) if (phs->is_inout) { /* XXX */ if (SvREADONLY(phs->sv)) croak(no_modify); + if (imp_sth->ora_pad_empty) + croak("Can't use ora_pad_empty with bind_param_inout"); /* phs->sv _is_ the real live variable, it may 'mutate' later */ /* pre-upgrade high to reduce risk of SvPVX realloc/move */ (void)SvUPGRADE(phs->sv, SVt_PVNV); /* ensure room for result, 28 is magic number (see sv_2pv) */ SvGROW(phs->sv, (phs->maxlen < 28) ? 28 : phs->maxlen+1); - if (imp_sth->ora_pad_empty) - croak("Can't use ora_pad_empty with bind_param_inout"); } else { /* phs->sv is copy of real variable, upgrade to at least string */ @@ -873,18 +870,70 @@ _dbd_rebind_ph(sth, imp_sth, phs) if (value_len + phs->alen_incnull <= UB2MAXVAL) { phs->alen = value_len + phs->alen_incnull; - alen_ptr = &phs->alen; - if (phs->alen > phs->maxlen && phs->indp != -1) + *alen_ptr_ptr = &phs->alen; + if (((IV)phs->alen) > phs->maxlen && phs->indp != -1) croak("panic: _dbd_rebind_ph alen %ld > maxlen %ld", phs->alen,phs->maxlen); } else { phs->alen = 0; - alen_ptr = NULL; /* Can't use alen for long LONGs (>64k) */ + *alen_ptr_ptr = NULL; /* Can't use alen for long LONGs (>64k) */ if (phs->is_inout) croak("Can't bind LONG values (>%ld) as in/out parameters", (long)UB2MAXVAL); } - /* ---------- */ + if (dbis->debug >= 3) { + fprintf(DBILOGFP, "bind %s <== '%.*s' (size %d/%ld, otype %d, indp %d)\n", + phs->name, phs->alen, (phs->progv) ? phs->progv : "", + phs->alen, (long)phs->maxlen, phs->ftype, phs->indp); + } + +} + + +#ifdef SQLT_CUR +static void +_rebind_ph_cursor(sth, imp_sth, phs) + SV *sth; + imp_sth_t *imp_sth; + phs_t *phs; +{ + SV *phs_sth = phs->sv; + D_impdata(phs_imp_sth, imp_sth_t, phs_sth); + + /* as a short-term hack we use and sacrifice an existing */ + /* statement handle. This will be changed later. */ + + /* close cursor if open (the pl/sql code can/will open it?) */ +/* + if (phs_imp_sth->cda) + free_cursor(phs_sth, phs_imp_sth); + phs_imp_sth->cda = &phs_imp_sth->cdabuf; +*/ + + assert(phs->ftype == SQLT_CUR); + phs->progv = (void*)phs_imp_sth->cda; + phs->maxlen = -1; + + warn("Cursor variables not yet supported"); +} +#endif + + +static int +_dbd_rebind_ph(sth, imp_sth, phs) + SV *sth; + imp_sth_t *imp_sth; + phs_t *phs; +{ + ub2 *alen_ptr = NULL; + +#ifdef SQLT_CUR + if (phs->ftype != SQLT_CUR) { + _rebind_ph_char(sth, imp_sth, phs, &alen_ptr); + } + else +#endif + _rebind_ph_cursor(sth, imp_sth, phs); /* Since we don't support LONG VAR types we must check */ /* for lengths too big to pass to obndrv as an sword. */ @@ -892,12 +941,6 @@ _dbd_rebind_ph(sth, imp_sth, phs) croak("Can't bind %s, value is too long (%ld bytes, max %d)", phs->name, phs->maxlen, MINSWORDMAXVAL); - if (dbis->debug >= 3) { - fprintf(DBILOGFP, "bind %s <== '%.*s' (size %d/%ld, otype %d, indp %d)\n", - phs->name, phs->alen, (phs->progv) ? phs->progv : "", - phs->alen, (long)phs->maxlen, phs->ftype, phs->indp); - } - if (obndra(imp_sth->cda, (text *)phs->name, -1, (ub1*)phs->progv, (sword)phs->maxlen, /* cast reduces max size */ (sword)phs->ftype, -1, @@ -935,7 +978,7 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl /* force SvPOK true before following tests */ if (dbis->debug >= 2) fprintf(DBILOGFP, - " bind warning: forcing placeholder flags: type %l, flags 0x%lx\n", + " bind warning: forcing placeholder flags: type %ld, flags 0x%lx\n", SvTYPE(ph_namesv), SvFLAGS(ph_namesv)); name = SvPV(ph_namesv, name_len); } @@ -950,9 +993,11 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl /* could check for leading colon here */ } - /* hook for later array logic */ - if (SvTYPE(newvalue)==SVt_RV || SvTYPE(newvalue) > SVt_PVLV) - croak("Can't bind reference or non-scalar value (currently)"); + if (SvTYPE(newvalue) > SVt_PVLV) /* hook for later array logic */ + croak("Can't bind a non-scalar value (%s)", neatsvpv(newvalue,0)); + if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) + /* dbi handle allowed for cursor variables */ + croak("Can't bind a reference (%s)", neatsvpv(newvalue,0)); if (SvTYPE(newvalue) == SVt_PVLV && is_inout) /* may allow later */ croak("Can't bind ``lvalue'' mode scalar as inout parameter (currently)"); @@ -972,7 +1017,7 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl phs = (phs_t*)(void*)SvPVX(*phs_svp); /* placeholder struct */ if (phs->sv == &sv_undef) { /* first bind for this placeholder */ - phs->ftype = 1; /* our default type VARCHAR2 */ + phs->ftype = 1; /* our default type: VARCHAR2 */ phs->maxlen = maxlen; /* 0 if not inout */ phs->is_inout = is_inout; if (is_inout) { @@ -990,8 +1035,8 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl /* XXX If attribs is EMPTY then reset attribs to default? */ if ( (svp=hv_fetch((HV*)SvRV(attribs), "ora_type",8, 0)) != NULL) { int ora_type = SvIV(*svp); - if (!dbtype_can_be_string(ora_type)) /* mean but safe */ - croak("Can't bind %s, ora_type %d not a simple string type", + if (!oratype_bind_ok(ora_type)) + croak("Can't bind %s, ora_type %d not supported by DBD::Oracle", phs->name, ora_type); if (sql_type) croak("Can't specify both TYPE (%d) and ora_type (%d) for %s", @@ -1064,6 +1109,8 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count /* Some checks for mutated storage since we pointed oracle at it. */ if (SvTYPE(phs->sv) != phs->sv_type || (SvOK(phs->sv) && !SvPOK(phs->sv)) + /* SvROK==!SvPOK so cursor (SQLT_CUR) handle will call _dbd_rebind_ph */ + /* that suits us for now */ || SvPVX(phs->sv) != phs->progv || SvCUR(phs->sv) > UB2MAXVAL ) { @@ -1109,16 +1156,36 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count } if (debug >= 2) - fprintf(DBILOGFP, " dbd_st_execute complete (rc%d, w%02x, rpc%ld, eod%d, out%d)\n", + fprintf(DBILOGFP, + " dbd_st_execute complete (rc%d, w%02x, rpc%ld, eod%d, out%d)\n", imp_sth->cda->rc, imp_sth->cda->wrn, imp_sth->cda->rpc, imp_sth->eod_errno, imp_sth->has_inout_params); - if (outparams) { /* check validity of bound SV's */ + if (outparams) { /* check validity of bound output SV's */ int i = outparams; while(--i >= 0) { phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); SV *sv = phs->sv; + if (SvROK(sv)) { /* XXX assume it's a cursor variable sth */ + D_impdata(phs_imp_sth, imp_sth_t, sv); + if (debug >= 2) + fprintf(DBILOGFP, + " out %s = %s (oracle cursor 0x%lx, indp %d, arcode %d)\n", + phs->name, neatsvpv(sv,0), (long)phs_imp_sth->cda, + phs->indp, phs->arcode); + /* XXX !!! */ + free_cursor(sth, imp_sth); /* oracle's cdemo5.c does an oclose */ + /* reset cache counters */ + phs_imp_sth->in_cache = 0; + phs_imp_sth->next_entry = 0; + phs_imp_sth->eod_errno = 0; + phs_imp_sth->done_desc = 0; + /* describe and allocate storage for results (if any needed) */ + if (!dbd_describe(sv, phs_imp_sth)) + return -2; /* dbd_describe already called ora_error() */ + } + else /* phs->alen has been updated by Oracle to hold the length of the result */ if (phs->indp == 0) { /* is okay */ SvPOK_only(sv); @@ -1126,8 +1193,8 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count *SvEND(sv) = '\0'; if (debug >= 2) fprintf(DBILOGFP, - " out %s = '%s'\t(len %d)\n", - phs->name, SvPV(sv,na),phs->alen); + " out %s = '%s'\t(len %d, arcode %d)\n", + phs->name, SvPV(sv,na),phs->alen, phs->arcode); } else if (phs->indp > 0 || phs->indp == -2) { /* truncated */ @@ -1136,21 +1203,27 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count *SvEND(sv) = '\0'; if (debug >= 2) fprintf(DBILOGFP, - " out %s = '%s'\t(TRUNCATED from %d to %d)\n", phs->name, - SvPV(sv,na), phs->indp, phs->alen); + " out %s = '%s'\t(TRUNCATED from %d to %d, arcode %d)\n", + phs->name, SvPV(sv,na), phs->indp, phs->alen, phs->arcode); } else if (phs->indp == -1) { /* is NULL */ (void)SvOK_off(phs->sv); if (debug >= 2) fprintf(DBILOGFP, - " out %s = undef (NULL)\n", phs->name); + " out %s = undef (NULL, arcode %d)\n", + phs->name, phs->arcode); } - else croak("panic: %s bad indp %d", phs->name, phs->indp); + else croak("panic: %s bad indp %d, arcode %d", + phs->name, phs->indp, phs->arcode); } } - DBIc_ACTIVE_on(imp_sth); /* XXX should only set for select ? */ + if (DBIc_NUM_FIELDS(imp_sth) > 0) { /* is a SELECT */ + DBIc_ACTIVE_on(imp_sth); + } + if (!imp_sth->cda) /* XXX closed cursor after exe for cursor vars */ + return 0; return imp_sth->cda->rpc; /* row count (0 will be returned as "0E0") */ } diff --git a/dbdimp.h b/dbdimp.h index 2be512e0..754f8271 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.21 1998/06/01 18:34:16 timbo Exp $ + $Id: dbdimp.h,v 1.22 1998/07/05 21:25:07 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -143,7 +143,7 @@ struct phs_st { /* scalar placeholder EXPERIMENTAL */ IV maxlen; /* max possible len (=allocated buffer) */ - /* these will become an array */ + /* these will become an array one day */ sb2 indp; /* null indicator */ char *progv; ub2 arcode; diff --git a/t/plsql.t b/t/plsql.t index b7554379..747d4454 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -119,7 +119,7 @@ ok(0, $csr->execute, 1); ok(0, $csr = $dbh->prepare(q{ declare str varchar2(1000); begin - :arg := nvl(nls_upper(:arg), 'null'); + :arg := nvl(upper(:arg), 'null'); :arg := :arg || '!'; end; }), 1); @@ -183,18 +183,39 @@ ok(0, @ary==1 && $ary[0] eq 'bar', 0); ok(0, join(':',@ary) eq 'baz:boo', 0); $dbh->{PrintError} = 0; - # To do +# --- test cursor variables +$csr = $dbh->prepare(q{ + begin + :var := :var * 2; + end; +}); +ok(0, $csr); +my $out_csr = $dbh->prepare(q{select 42 from dual}); # sacrificial csr XXX +ok(0, $out_csr); +if (0) { + ok(0, $csr->bind_param_inout(':var', \$out_csr, 100, { ora_type => 102 })); + ok(0, $csr->execute()); +} +else { + ok(0,1); + ok(0,1); +} +# at this point $out_csr should be a handle on a new oracle cursor + + +# --- To do # test NULLs at first bind # NULLs later binds. # returning NULLs # multiple params, mixed types and in only vs inout +# --- test ping ok(0, $dbh->ping); $dbh->disconnect; ok(0, !$dbh->ping); exit 0; -BEGIN { $tests = 37 } +BEGIN { $tests = 41 } # end. __END__ diff --git a/test.pl b/test.pl index 6a9fd708..cb95d905 100755 --- a/test.pl +++ b/test.pl @@ -34,16 +34,15 @@ $ENV{PERL_DBI_DEBUG} = 2 if $opt_d; $ENV{ORACLE_HOME} = '/usr/oracle' unless $ENV{ORACLE_HOME}; -$dbname = $ARGV[0] || ''; # $ENV{TWO_TASK} || $ENV{ORACLE_SID} || 'crgs'; +$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -eval '$Oraperl::safe = 1' if $] >= 5; eval 'use Oraperl; 1' || die $@ if $] >= 5; &ora_version; my @data_sources = DBI->data_sources('Oracle'); -print "Data sources: @data_sources\n\n"; +print "Data sources:\n\t", join("\n\t",@data_sources),"\n\n"; print "\nConnecting\n", " to '$dbname' (from command line, else uses ORACLE_SID or TWO_TASK - recommended)\n"; @@ -53,31 +52,31 @@ { # test connect works first - local($l) = &ora_login($dbname, $dbuser, ''); + local($l) = &ora_login($dbname, $dbuser, ''); unless($l) { - warn "ora_login: $ora_errno: $ora_errstr\n"; - # Try to help dumb users who don't know how to connect to oracle... - warn "\nHave you set the environment variable ORACLE_USERID ?\n" - if ($ora_errno == 1017); # ORA-01017: invalid username/password - warn "\nHave you included your password in ORACLE_USERID ? (e.g., 'user/passwd')\n" - if ($ora_errno == 1017 and $dbuser !~ m:/:); - warn "\nHave you set the environment variable ORACLE_SID or TWO_TASK?\n" - if ($ora_errno == 2700); # error translating ORACLE_SID - warn "\nORACLE_SID or TWO_TASK possibly not right, or server not running.\n" - if ($ora_errno == 1034); # ORA-01034: ORACLE not available - warn "\nTWO_TASK possibly not set correctly right.\n" - if ($ora_errno == 12545); - warn "\n"; + warn "ora_login: $ora_errno: $ora_errstr\n"; + # Try to help dumb users who don't know how to connect to oracle... + warn "\nHave you set the environment variable ORACLE_USERID ?\n" + if ($ora_errno == 1017); # ORA-01017: invalid username/password + warn "\nHave you included your password in ORACLE_USERID ? (e.g., 'user/passwd')\n" + if ($ora_errno == 1017 and $dbuser !~ m:/:); + warn "\nHave you set the environment variable ORACLE_SID or TWO_TASK?\n" + if ($ora_errno == 2700); # error translating ORACLE_SID + warn "\nORACLE_SID or TWO_TASK possibly not right, or server not running.\n" + if ($ora_errno == 1034); # ORA-01034: ORACLE not available + warn "\nTWO_TASK possibly not set correctly right.\n" + if ($ora_errno == 12545); + warn "\n"; warn "Generally set TWO_TASK or ORACLE_SID but not both at the same time.\n"; warn "Try to connect to the database using an oracle tool like sqlplus\n"; warn "only if that works should you suspect problems with DBD::Oracle.\n"; warn "Try leaving dbname value empty and set dbuser to name/passwd\@dbname.\n"; - die "\nTest aborted.\n"; + die "\nTest aborted.\n"; } - # test_other($l); - print `sleep 1; echo Backticks OK` || "Backticks failed: $!\n" - if ($os ne 'MSWin32' and $os ne 'VMS'); - &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; + # test_other($l); + print `sleep 1; echo Backticks OK` || "Backticks failed: $!\n" + if ($os ne 'MSWin32' and $os ne 'VMS'); + &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; } $start = time; @@ -257,48 +256,46 @@ sub count_fetch { sub test_fetch_perf { - print "\nTesting internal row fetch overhead.\n"; + print "\nTesting internal row fetch overhead.\n"; local($lda) = &ora_login($dbname, $dbuser, '') - || die "ora_login: $ora_errno: $ora_errstr\n"; - #$lda->trace(2); - $lda->trace(0); - local($csr) = &ora_open($lda,"select 0,1,2,3,4,5,6,7,8,9 from dual"); - #local($csr) = &ora_open($lda,"select 9 from dual"); - local($max) = 50000; - $csr->{ora_fetchtest} = $max; - require Benchmark; - $t0 = new Benchmark; - #local($rows) = count_fetch($csr); die "count_fetch $rows != $max" if $rows-1 != $max; - my $code = $csr->can('fetch'); - #1 while &$code($csr); - 1 while $csr->fetchrow_arrayref; - #1 while @row = $csr->fetchrow_array; - #while(@row = $csr->fetchrow_array) { $hash{++$i} = [ @row ]; } - $td = Benchmark::timediff((new Benchmark), $t0); - $csr->{ora_fetchtest} = 0; - printf("$max fetches: ".Benchmark::timestr($td)."\n"); - printf("%d per clock second, %d per cpu second\n\n", $max/$td->real, $max/$td->cpu_a); + || die "ora_login: $ora_errno: $ora_errstr\n"; + #$lda->trace(2); + $lda->trace(0); + local($csr) = &ora_open($lda,"select 0,1,2,3,4,5,6,7,8,9 from dual"); + #local($csr) = &ora_open($lda,"select 9 from dual"); + local($max) = 50000; + $csr->{ora_fetchtest} = $max; + require Benchmark; + $t0 = new Benchmark; + #local($rows) = count_fetch($csr); die "count_fetch $rows != $max" if $rows-1 != $max; + my $code = $csr->can('fetch'); + #1 while &$code($csr); + 1 while $csr->fetchrow_arrayref; + #1 while @row = $csr->fetchrow_array; + #while(@row = $csr->fetchrow_array) { $hash{++$i} = [ @row ]; } + $td = Benchmark::timediff((new Benchmark), $t0); + $csr->{ora_fetchtest} = 0; + printf("$max fetches: ".Benchmark::timestr($td)."\n"); + printf("%d per clock second, %d per cpu second\n\n", $max/$td->real, $max/$td->cpu_a); } sub test_other { - local($lda) = @_; - #$lda->debug(2); - $lda->{RaiseError} = 1; - local($c) = $lda->prepare(q{ - begin - :a2 := :a1 + 10; - end; - }); - local($p,$q) = (42,43); - $p += 1; $q += 1; - $c->bind_param_inout(':a1', \$p, 100); - $c->bind_param_inout(':a2', \$q, 100); - foreach (1..1000) { - $c->execute || die $c->errstr; - $p += 1; - } - exit 1; + local($lda) = @_; +$lda->{RaiseError} =1; +$lda->trace(2); +my $out_csr = $lda->prepare(q{select 42 from dual}); # sacrificial csr XXX +$csr = $lda->prepare(q{ + begin + OPEN :csr_var FOR select * from all_tables; + end; +}); +$csr->bind_param_inout(':csr_var', \$out_csr, 100, { ora_type => 102 }); +$csr->execute(); +# at this point $out_csr should be a handle on a new oracle cursor +@row = $out_csr->fetchrow_array; + + exit 1; } # end. From beabdaf702660624fefd299a4255d553b5d319aa Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Tue, 28 Jul 1998 17:39:44 -0500 Subject: [PATCH 031/637] import DBD-Oracle 0.52 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.52 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.52.tar.gz --- Changes | 10 +++++- Makefile.PL | 87 ++++++++++++++++++++++++++++++++++++++++++----------- Oracle.h | 4 +-- Oracle.pm | 11 +++---- README | 6 ++++ README.help | 4 +++ Todo | 30 ++---------------- dbdimp.c | 76 ++++++++++++++++++++++++++++------------------ 8 files changed, 144 insertions(+), 84 deletions(-) diff --git a/Changes b/Changes index 57862027..81c1c944 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,11 @@ +Changes in DBD::Oracle 0.52 (Oraperl 1.37), 28th July 1998 + + Assorted build fixes (esp. Win32, HP-UX and AIX). + More hints on error messages, especially long truncation and + field-level errors when fetching. + Compiles okay now for systems without SQLT_CUR defined. + Only sets SA_RESTART on SIGCLD if connect was successful. + Changes in DBD::Oracle 0.51 (Oraperl 1.37), 5rd July 1998 Makefile.PL no longer tries to link with just -lclntsh directly :-( @@ -20,7 +28,7 @@ Changes in DBD::Oracle 0.49 (Oraperl 1.36), 1st June 1998 Fixed broken truncation error in 0.48. Fetch ORACLE_SID from Win32 registry (thanks to Preston Bannister) Improved automatic row cache sizing (prompted by Jon Meek). - Added $sth->{ora_cache_size} and $sth->{ora_est_row_width} + Added $sth->{ora_cache_rows} and $sth->{ora_est_row_width} as read-only attributes to make cache size logic easier to test. Changes in DBD::Oracle 0.48 (Oraperl 1.36), 25th May 1998 diff --git a/Makefile.PL b/Makefile.PL index 692d854a..4efe7f46 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.62 1998/07/05 21:25:07 timbo Exp $ +# $Id: Makefile.PL,v 1.65 1998/07/28 17:33:37 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -45,10 +45,20 @@ my %opts = ( COMPRESS => 'gzip -v9', SUFFIX => 'gz', }, ); +if ($ExtUtils::MakeMaker::VERSION >= 5.43) { + $opts{AUTHOR} = 'Tim Bunce (dbi-users@fugue.com)'; + $opts{ABSTRACT_FROM} = 'Oracle.pm'; + $opts{PREREQ_PM} = { DBI => 0 }; + $opts{CAPI} = 'TRUE' if $Config{archname} =~ /-object\b/i; +} + +$opts{LINKTYPE} = 'static' if $Config{dlsrc} =~ /dl_none/; + my(@MK, %MK, $MK, %MK_expanding); # parsed macros from Oracle's makefiles # Options (rarely needed) $::opt_m = 0; # path to proc.mk or oracle.mk file to read +$::opt_n = ''; # Oracle .mk macro name to use for library list to link with $::opt_p = ''; # prefer oracle.mk over proc $::opt_l = 0; # try direct-link to libclntsh $::opt_g = ''; # enable debugging (-g for compiler and linker) @@ -57,7 +67,7 @@ $::opt_S = ''; # Find a symbol in oracle & system libs, Don't build a Makefile $::opt_v = 0; # be more verbose $::opt_d = 0; # much more verbose for debugging -GetOptions(qw(v! d! g! p! l! m=s s=s S=s)) or die "Invalid arguments"; +GetOptions(qw(v! d! g! p! l! m=s n=s s=s S=s)) or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string $::opt_v = 1 if $::opt_d; @@ -84,11 +94,17 @@ die "$ORACLE_ENV environment variable ($OH) not valid.\n" unless -d $OH; print "Using Oracle in $OH\n"; +# show original value of ORA_CLIENT_LIB if defined ... +print "\$ORA_CLIENT_LIB=$ENV{ORA_CLIENT_LIB}\n" if $ENV{ORA_CLIENT_LIB}; +# ... before we then set it how it probably should be set +$ENV{ORA_CLIENT_LIB} ||= 'shared' unless ($opts{LINKTYPE}||'') eq 'static'; + my (@inspdver, %inspdver); if ($os ne 'VMS' and $os ne 'MSWin32' and -x "$OH/orainst/inspdver") { open INST, "$OH/orainst/inspdver |"; my @inspdver = ; close INST; + $inspdver{RDBMS} = 0; foreach (@inspdver) { chop; $inspdver{$2} = $1 if m/^(\S+)\s+(.*)/; @@ -147,8 +163,8 @@ elsif ($os eq 'MSWin32') { && -e "$OH/$OCIDIR/lib/$oci_compiler_dir/ociw32.lib"); my $OCIINCLUDE = "-I$OH/$OCIDIR/include -I$OH/rdbms/demo"; - $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/$oci_compiler_dir -lOCIW32" ]; - $opts{SKIP} = ['processPL']; # XXX caused problems with Nmake... + $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/$oci_compiler_dir OCIW32" ]; + $opts{SKIP} = ['processPL']; # XXX added because it caused problems with Nmake... $opts{INC} = "$OCIINCLUDE -I$dbi_arch_dir"; } @@ -188,13 +204,17 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l # get a cut down $linkwith to pass to MakeMaker liblist my $linkwith_s = expand_mkvars($linkwith, 1, 1, 0); + # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" - $linkwith_s =~ s!(\S+)/lib(\w+).a!-L$1 -l$2!g; + # to cater for lack of smarts in MakeMaker / Liblist + # which ignores /foo/bar.a entries! + my $lib_ext_re = "(a|$Config{dlext}|$Config{so})"; + $linkwith_s =~ s!(\S+)/lib(\w+)\.($lib_ext_re)\b!-L$1 -l$2!g; # Platform specific fix-ups: # delete problematic crt?.o on solaris $linkwith_s = del_crtobj($linkwith_s) if $os eq 'solaris'; - $linkwith_s =~ s/-l:lib(\w+).sl\b/-l$1/g; # for hp-ux + $linkwith_s =~ s/-l:lib(\w+)\.sl\b/-l$1/g; # for hp-ux $linkwith_s .= " -lc" if $Config{archname} eq 'i386-dynixptx'; if ($os eq 'solaris' and $osvers >= 2.3 and $linkwith_s =~ /-lthread/) { print "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; @@ -365,11 +385,11 @@ sub find_mkfile { ); if ($::opt_p) { # if -p then copy oracle.mk to start of search list and thus prefer it - my @ora = grep { !m/(oracle|rdbms)\.mk\b/ } @mkplaces; + my @ora = grep { m/(oracle|rdbms)\.mk\b/ } @mkplaces; unshift @mkplaces, @ora; } if ($::opt_m) { - $::opt_m = cwd()."/$::opt_m" unless $::opt_m =~ m:/\\:; + $::opt_m = cwd()."/$::opt_m" unless $::opt_m =~ m:^/:; die "-m $::opt_m: not found" unless -f $::opt_m; unshift @mkplaces, $::opt_m; } @@ -441,7 +461,6 @@ sub fetch_oci_macros { warn "OBJ_EXT correction enabled ($MK{OBJ_EXT})\n" if $incompat_ext; my $mkver = 0; - my $linkvia = ''; my $lastline = ''; my @lines = read_inc_file($file); for(1; $_ = shift(@lines); $lastline = $_){ @@ -472,6 +491,8 @@ sub fetch_oci_macros { $MK{$1}= $' if m/^\s*(\w+)\s*=\s*/; $name = $1; + $MK{$1} =~ s/^([^#]*)#.*/$1/ if $1 && $MK{$1}; # remove comments + if ($name and exists $edit{$name}) { my $pre = $_; eval $edit{$name}; # execute code to edit $_ @@ -486,10 +507,28 @@ sub fetch_oci_macros { } # --- now decide what to link with --- - if ($MK{OCILDLIBS}) { - $linkvia = '$(OCILDLIBS)'; + my $linkvia; + + if ($::opt_n) { + $linkvia = "\$($::opt_n)" if $MK{$::opt_n}; + warn "Can't use '$::opt_n': not defined by .mk files\n" + unless $linkvia; } - elsif ($MK{PROLDLIBS}) { # Oracle 7.3.x + + # modern Oracle .mk files define OCISTATICLIBS and OCISHAREDLIBS + $linkvia = '$(OCISTATICLIBS)' + if !$linkvia && $MK{OCISTATICLIBS} + && $opts{LINKTYPE} && $opts{LINKTYPE} eq 'static'; + $linkvia = '$(OCISHAREDLIBS)' + if !$linkvia && $MK{OCISHAREDLIBS}; + + # The oracle.mk file tends to define OCILDLIBS + $linkvia = '$(OCILDLIBS)' + if !$linkvia && $MK{OCILDLIBS}; + + # Now we get into strange land of twisty turny macros + if (!$linkvia && $MK{PROLDLIBS}) { # Oracle 7.3.x + # XXX tweak for threaded perl? - use PROLLSsharedthread if ($MK{PROLDLIBS} =~ /thread/i && $MK{PROLLSshared}) { $linkvia = '$(PROLLSshared)'; } @@ -497,7 +536,7 @@ sub fetch_oci_macros { $linkvia = '$(PROLDLIBS)'; } } - elsif (int($mkver) == 1) { + elsif (!$linkvia && int($mkver) == 1) { if ($MK{LLIBOCIC}) { $linkvia = '$(LLIBOCIC) $(TTLIBS)'; } else { @@ -544,25 +583,37 @@ sub read_inc_file { sub expand_shellescape { my($orig, $level) = @_; my $cmd = $orig; - print "\n$level * Evaluating \`$orig\`\n" if $::opt_d; + my $debug = $::opt_d || 1; + print "Evaluating `$orig`\n" if $debug; # ensure we have no $(...) vars left - strip out undefined ones: $cmd =~ s/\$\((\w+)\)/mkvar("$1", 1, 0, $level+1)/ge; - print "\n$level * After reducing to \`$cmd\`\n" if $::opt_d and $cmd ne $orig; + print " expanded `$cmd`\n" if $debug and $cmd ne $orig; my $result = `$cmd`; - print "$level * Returned $result\n\n" if $::opt_d; + chop $result; + print " returned '$result'\n" if $debug; $result; } + sub expand_mkvars { my($string, $strip, $backtick, $level) = @_; local($_) = $string; print "$level Expanding $_\n" if $::opt_d; - s/\$\((\w+)\)/mkvar("$1", $strip, $backtick, $level+1)/ge; # can recurse + # handle whizzo AIX make feature used by Oracle + s/\$\( (\w+) \? ([^(]*?) : ([^(]*?) \)/ + my ($vname, $vT, $vF) = ($1,$2,$3); + $MK{$vname} = (mkvar($vname, 1, $backtick, $level+1)) ? $vT : $vF + /xge; # can recurse + s/\$\( (\w+) \)/ + mkvar("$1", $strip, $backtick, $level+1) + /xge; # can recurse s/`(.*?[^\\])`/expand_shellescape("$1", $level+1)/esg if $backtick; # can recurse s/\s*\\\n\s*/ /g; # merge continuations - s/\s+/ /g; # shrink whitespace + s/\s+/ /g; # shrink whitespace print "$level Expanded $string\n to $_\n\n" if $::opt_d and $_ ne $string; $_; } + + sub mkvar { my($var, $strip, $backtick, $level) = @_; my $default = $strip ? '' : "\$($var)"; diff --git a/Oracle.h b/Oracle.h index 70e8ebd4..f7a0fd0d 100644 --- a/Oracle.h +++ b/Oracle.h @@ -1,5 +1,5 @@ /* - $Id: Oracle.h,v 1.11 1997/09/08 22:43:59 timbo Exp $ + $Id: Oracle.h,v 1.12 1998/07/28 17:33:37 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -25,7 +25,7 @@ void dbd_init _((dbistate_t *dbistate)); -int dbd_db_login _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd)); +int dbd_db_login _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pwd)); int dbd_db_do _((SV *sv, char *statement)); int dbd_db_commit _((SV *dbh, imp_dbh_t *imp_dbh)); int dbd_db_rollback _((SV *dbh, imp_dbh_t *imp_dbh)); diff --git a/Oracle.pm b/Oracle.pm index 4512633d..0d667a5a 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.53 1998/07/05 21:49:00 timbo Exp $ +# $Id: Oracle.pm,v 1.54 1998/07/21 00:07:30 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.51'; +$DBD::Oracle::VERSION = '0.52'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -22,7 +22,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; use Exporter (); @ISA = qw(DynaLoader Exporter); - my $Revision = substr(q$Revision: 1.53 $, 10); + my $Revision = substr(q$Revision: 1.54 $, 10); require_version DBI 0.92; @@ -111,9 +111,8 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; eval q{ # XXX experimental, will probably change warn "Fetching ORACLE_SID from Registry.\n" if $debug; require Tie::Registry; - import Tie::Registry; - $Registry->Delimeter("/"); - my $hkey= $Registry->{"LMachine/Software/Oracle/"}; + $Tie::Registry::Registry->Delimeter("/"); + my $hkey= $Tie::Registry::Registry->{"LMachine/Software/Oracle/"}; my $sid = $hkey->{ORACLE_SID}; my $home= $hkey->{ORACLE_HOME} || $ENV{ORACLE_HOME}; $dbnames{$sid} = $home if $sid and $home; diff --git a/README b/README index 100f5333..e75ce620 100644 --- a/README +++ b/README @@ -140,6 +140,12 @@ dbi-users@fugue.com and CC them to me at Tim.Bunce@ig.co.uk. But note... make test make test TEST_VERBOSE=1 (only if any of the t/* tests fail) + Make sure to include the 'stderr' output. The best way to do this is + to use the "script" command (man script). If that's not available + then (assuming you're not using csh) do "command > command.log 2>&1" + The "2>&1" is required (after the stdout redirect) to redirect stderr + to the same place. + 2. Full details of which version of Oracle you're using (if it wasn't automatically found and printed by "perl Makefile.PL") diff --git a/README.help b/README.help index 8491b42c..b2e546ac 100644 --- a/README.help +++ b/README.help @@ -77,6 +77,10 @@ where DBD-Oracle was compiled. ORA-01019 can also be caused by corrupt Oracle config files such as /etc/oratab. +ORA-01019 can also be caused by using a different version of the +message catalogs ($ORACLE_HOME/ocommon/nls/admin/data) to that used +when DBD::Oracle was compiled. + Also try building with oracle.mk if your DBD::Oracle defaulted to proc.mk. ------------------------------------------------------------------------------- diff --git a/Todo b/Todo index 1d03e32a..1bf310ad 100644 --- a/Todo +++ b/Todo @@ -1,5 +1,7 @@ Oracle 8 +If LongReadLen > 64k then automatocally call oflng for each long LONG. + $drh->debug oddities (re data_source debugging) ora_bind() failed err = ORA-01026: multiple buffers of size > 4000 in @@ -18,10 +20,6 @@ Test LongReadLen and especially the default behaviour of LongTruncOk Add explain to dist -imp_dbh->ldaptr=&imp_dbh->lda for Francois DESARMENIEN - -AIX build - Handle binding of values > 32K long. Handle PL/SQL arrays. @@ -33,27 +31,3 @@ Non-blocking Tests RAW types at max length -=============================================================================== -General Outstanding Issues - -Return codes and error handling not quite same as oraperl? - -Many others. Remember, this is still alpha software! - -Support shared libraries with Oracle 7.3 - -Add a mechanism for fork style tasks so dbh of parent -doesn't get freed by child. - - -=============================================================================== -Below is just a personal dumping ground for thoughts and issues, don't -expect any structure: - -(or even anything at all) - -Check -R etc for libsunmath.so.1 -ldd /cmi/run/lib/perl5/site_perl/sun4-solaris/auto/DBD/Oracle/Oracle.so - libclntsh.so.1.0 => /home/oracle/home/lib/libclntsh.so.1.0 - libsunmath.so.1 => (not found) - diff --git a/dbdimp.c b/dbdimp.c index d2adeedd..2e540b83 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.37 1998/07/05 21:25:07 timbo Exp $ + $Id: dbdimp.c,v 1.38 1998/07/28 17:33:37 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -219,12 +219,15 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) #ifndef SIGCLD #define SIGCLD SIGCHLD #endif - { /* If orlon has installed a handler for SIGCLD, */ - /* reinstall it with SA_RESTART: */ + /* If orlon has installed a handler for SIGCLD, then reinstall it */ + /* with SA_RESTART. We only do this if connected ok since I've */ + /* seen the process loop after being interrupted after connect failed. */ + if (ret == 0 && imp_dbh->lda->rc == 0) { struct sigaction act; if (sigaction( SIGCLD, (struct sigaction*)0, &act ) == 0 && (act.sa_handler != SIG_DFL && act.sa_handler != SIG_IGN) && (act.sa_flags & SA_RESTART) == 0) { + /* XXX we should also check that act.sa_handler is not the perl handler */ act.sa_flags |= SA_RESTART; sigaction( SIGCLD, &act, (struct sigaction*)0 ); if (dbis->debug >= 3) @@ -238,18 +241,23 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) if (ret) { int rc = imp_dbh->lda->rc; - char *msg; - /* oerhms in ora_error may hang or corrupt memory (!) after a connect */ - /* failure in some specific versions of Oracle 7.3.x. So we provide a */ - /* way to skip the message lookup if ora_login_nomsg is true (set via */ - /* env var above). */ char buf[100]; - sprintf(buf, - "ORA-%05d: (Text for error %d not fetched. Use 'oerr ORA %d' command.)", - rc, rc, rc); - /* 1019 is a common but misleading error code (often NLS msg cat related) */ - msg = (rc!=1019) ? "login failed" - : "login failed, probably a symptom of a deeper problem"; + char *msg; + switch(rc) { /* add helpful hints to some errors */ + case 0: msg = "login failed, check ORACLE_HOME/bin is on your PATH"; break; + case 1019: msg = "login failed, probably a symptom of a deeper problem"; break; + default: msg = "login failed"; break; + } + if (ora_login_nomsg) { + /* oerhms in ora_error may hang or corrupt memory (!) after a connect */ + /* failure in some specific versions of Oracle 7.3.x. So we provide a */ + /* way to skip the message lookup if ora_login_nomsg is true (set via */ + /* env var above). */ + sprintf(buf, + "ORA-%05d: (Text for error %d not fetched. Use 'oerr ORA %d' command.)", + rc, rc, rc); + msg = buf; + } ora_error(dbh, ora_login_nomsg ? NULL : imp_dbh->lda, rc, msg); return 0; } @@ -451,16 +459,20 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) if (oparse(imp_sth->cda, (text*)imp_sth->statement, (sb4)-1, (sword)oparse_defer, (ub4)oparse_lng) ) { - SV *msgsv, *sqlsv; - char msg[99]; - sqlsv = sv_2mortal(newSVpv(imp_sth->statement,0)); - sv_insert(sqlsv, imp_sth->cda->peo, 0, "<*>",3); - sprintf(msg,"error possibly near <*> indicator at char %d in '", - imp_sth->cda->peo+1); - msgsv = sv_2mortal(newSVpv(msg,0)); - sv_catsv(msgsv, sqlsv); - sv_catpv(msgsv, "'"); - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, SvPV(msgsv,na)); + char buf[99]; + char *hint = ""; + if (1) { /* XXX could make optional one day */ + SV *msgsv, *sqlsv; + sprintf(buf,"error possibly near <*> indicator at char %d in '", + imp_sth->cda->peo+1); + msgsv = sv_2mortal(newSVpv(buf,0)); + sqlsv = sv_2mortal(newSVpv(imp_sth->statement,0)); + sv_insert(sqlsv, imp_sth->cda->peo, 0, "<*>",3); + sv_catsv(msgsv, sqlsv); + sv_catpv(msgsv, "'"); + hint = SvPV(msgsv,na); + } + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, hint); free_cursor(sth, imp_sth); return 0; } @@ -928,12 +940,12 @@ _dbd_rebind_ph(sth, imp_sth, phs) ub2 *alen_ptr = NULL; #ifdef SQLT_CUR - if (phs->ftype != SQLT_CUR) { - _rebind_ph_char(sth, imp_sth, phs, &alen_ptr); + if (phs->ftype == SQLT_CUR) { + _rebind_ph_cursor(sth, imp_sth, phs); } else #endif - _rebind_ph_cursor(sth, imp_sth, phs); + _rebind_ph_char(sth, imp_sth, phs, &alen_ptr); /* Since we don't support LONG VAR types we must check */ /* for lengths too big to pass to obndrv as an sword. */ @@ -1255,7 +1267,7 @@ dbd_st_fetch(sth, imp_sth) if (imp_sth->eod_errno) { end_of_data: if (imp_sth->eod_errno != 1403) { /* was not just end-of-fetch */ - ora_error(sth, imp_sth->cda, imp_sth->eod_errno, "ofetch error"); + ora_error(sth, imp_sth->cda, imp_sth->eod_errno, "cached ofetch error"); } else { /* is simply no more data */ sv_setiv(DBIc_ERR(imp_sth), 0); /* ensure errno set to 0 here */ if (debug >= 2) @@ -1326,12 +1338,16 @@ dbd_st_fetch(sth, imp_sth) (void)SvOK_off(sv); } else { /* See odefin rcode arg description in OCI docs */ + char buf[200]; + char *hint = ""; /* These may get more case-by-case treatment eventually. */ if (rc == 1406) { /* field truncated (see above) */ /* Copy the truncated value anyway, it may be of use, */ /* but it'll only be accessible via prior bind_column() */ sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], fb_ary->arlen[cache_entry]); + if (dbtype_is_long(fbh->dbtype)) /* double check */ + hint = ", LongReadLen too small and/or LongTruncOk not set"; } else { SvOK_off(sv); /* set field that caused error to undef */ @@ -1339,7 +1355,9 @@ dbd_st_fetch(sth, imp_sth) ++err; /* 'fail' this fetch but continue getting fields */ /* Some should probably be treated as warnings but */ /* for now we just treat them all as errors */ - ora_error(sth, imp_sth->cda, rc, "ofetch field error"); + sprintf(buf,"ofetch error on field %d (of %d), ora_type %d%s", + i+1, num_fields, fbh->dbtype, hint); + ora_error(sth, imp_sth->cda, rc, buf); } if (debug >= 3) From 2446800a50ccc2d9bfb8070cba21422b45933386 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Mon, 3 Aug 1998 16:44:35 -0500 Subject: [PATCH 032/637] import DBD-Oracle 0.53 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.53 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.53.tar.gz --- Changes | 7 ++++ Makefile.PL | 94 ++++++++++++++++++++++++++++++++--------------------- Oracle.pm | 6 ++-- Todo | 3 +- dbdimp.c | 12 ++++++- test.pl | 9 +++-- 6 files changed, 87 insertions(+), 44 deletions(-) diff --git a/Changes b/Changes index 81c1c944..2ac45119 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,10 @@ +Changes in DBD::Oracle 0.53 (Oraperl 1.37), 3rd August 1998 + + Further build fixes (esp kpudc problem with Oracle 8). + Now prefers oracle.mk over proc.mk again. + Only $ENV{ORA_CLIENT_LIB} ||= 'shared' if shared lib exists. + Builds okay with 5.005-thread (not tested). + Changes in DBD::Oracle 0.52 (Oraperl 1.37), 28th July 1998 Assorted build fixes (esp. Win32, HP-UX and AIX). diff --git a/Makefile.PL b/Makefile.PL index 4efe7f46..8ba45578 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.65 1998/07/28 17:33:37 timbo Exp $ +# $Id: Makefile.PL,v 1.67 1998/08/03 20:51:25 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -57,17 +57,19 @@ $opts{LINKTYPE} = 'static' if $Config{dlsrc} =~ /dl_none/; my(@MK, %MK, $MK, %MK_expanding); # parsed macros from Oracle's makefiles # Options (rarely needed) -$::opt_m = 0; # path to proc.mk or oracle.mk file to read -$::opt_n = ''; # Oracle .mk macro name to use for library list to link with -$::opt_p = ''; # prefer oracle.mk over proc -$::opt_l = 0; # try direct-link to libclntsh -$::opt_g = ''; # enable debugging (-g for compiler and linker) -$::opt_s = ''; # Find a symbol in oracle libs, Don't build a Makefile -$::opt_S = ''; # Find a symbol in oracle & system libs, Don't build a Makefile -$::opt_v = 0; # be more verbose -$::opt_d = 0; # much more verbose for debugging - -GetOptions(qw(v! d! g! p! l! m=s n=s s=s S=s)) or die "Invalid arguments"; +$::opt_m = 0; # path to proc.mk or oracle.mk file to read +$::opt_c = 0; # don't encourage use of shared library +$::opt_n = ''; # Oracle .mk macro name to use for library list to link with +$::opt_p = ''; # alter preference for oracle.mk over proc +$::opt_l = 0; # try direct-link to libclntsh +$::opt_g = ''; # enable debugging (-g for compiler and linker) +$::opt_s = ''; # Find a symbol in oracle libs, Don't build a Makefile +$::opt_S = ''; # Find a symbol in oracle & system libs, Don't build a Makefile +$::opt_v = 0; # be more verbose +$::opt_d = 0; # much more verbose for debugging + +GetOptions(qw(v! d! g! p! l! c! m=s n=s s=s S=s)) + or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string $::opt_v = 1 if $::opt_d; @@ -94,11 +96,6 @@ die "$ORACLE_ENV environment variable ($OH) not valid.\n" unless -d $OH; print "Using Oracle in $OH\n"; -# show original value of ORA_CLIENT_LIB if defined ... -print "\$ORA_CLIENT_LIB=$ENV{ORA_CLIENT_LIB}\n" if $ENV{ORA_CLIENT_LIB}; -# ... before we then set it how it probably should be set -$ENV{ORA_CLIENT_LIB} ||= 'shared' unless ($opts{LINKTYPE}||'') eq 'static'; - my (@inspdver, %inspdver); if ($os ne 'VMS' and $os ne 'MSWin32' and -x "$OH/orainst/inspdver") { open INST, "$OH/orainst/inspdver |"; @@ -195,15 +192,23 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l ."\nbuild fails you probably need to install more Oracle software.\n\n" if @ora_libs < 6; # just a helpful hint + # can we give the shared library a helping hand? + my @shared = grep { m:/lib(cl(ie)?ntsh|oracle).\w+$:o } @ora_libs; + # show original value of ORA_CLIENT_LIB if defined ... + print "\$ORA_CLIENT_LIB=$ENV{ORA_CLIENT_LIB}\n" if $ENV{ORA_CLIENT_LIB}; + # ... before we then set it how it probably should be set + $ENV{ORA_CLIENT_LIB} ||= 'shared' + if ($opts{LINKTYPE}||'') ne 'static' && @shared && !$::opt_c; + my $mkfile = find_mkfile(); my $linkvia = fetch_oci_macros($mkfile); - my $libhome = expand_mkvars($MK{LIBHOME}, 0, 1, 0) || "$OH/lib"; - $linkwith = expand_mkvars($linkvia, 0, 1, 0); + my $libhome = expand_mkvars($MK{LIBHOME}, 0, 1) || "$OH/lib"; + $linkwith = expand_mkvars($linkvia, 0, 1); $linkwith =~ s/-Y P,/-YP,/g if $Config{'cc'} =~ /gcc/; $linkwith =~ s:-R /:-R/:g if $os eq 'solaris'; # get a cut down $linkwith to pass to MakeMaker liblist - my $linkwith_s = expand_mkvars($linkwith, 1, 1, 0); + my $linkwith_s = expand_mkvars($linkwith, 1, 1); # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" # to cater for lack of smarts in MakeMaker / Liblist @@ -295,6 +300,8 @@ print "Oracle makefiles would have used these values but we override them:\n" print " CC: $MK{CC}\n" if $MK{CC}; print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; print " [".mkvar('CFLAGS',1,0,0). "]\n" if $MK{CFLAGS}; +print " CLIBS: $MK{CLIBS}\n" if $MK{CLIBS}; +print " [".mkvar('CLIBS',1,0,0). "]\n" if $MK{CLIBS}; print " LDFLAGS: $MK{LDFLAGS}\n" if $MK{LDFLAGS}; print " [".mkvar('LDFLAGS',1,0,0). "]\n" if $MK{LDFLAGS}; print " LDSTRING: $MK{LDSTRING}\n" if $MK{LDSTRING}; @@ -370,7 +377,8 @@ sub del_crtobj { # old: COMPOBJS=$(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/__fstd.o # new: COMPOBJS=$(COMPOBJ)/__fstd.o ($str = $orig) =~ s:[^\s=]*\bcrt[1in]\.o\b::g; - warn "del_crtobj: $orig\n : $str\n" if $orig ne $str and $::opt_v; + print "del_crtobj: $orig\n : $str\n" + if $orig ne $str and $::opt_v; return $str; } @@ -378,16 +386,18 @@ sub del_crtobj { sub find_mkfile { my @mkfiles; - my @mkplaces = qw( - proc/lib/proc.mk precomp/demo/proc/proc.mk precomp/demo/proc/demo_proc.mk - proc16/lib/proc16.mk - rdbms/lib/oracle.mk rdbms/demo/oracle.mk rdbms/demo/demo_rdbms.mk + my @mk_proc = ( + 'precomp/demo/proc/proc.mk', + 'precomp/demo/proc/demo_proc.mk', + 'proc/lib/proc.mk', + 'proc16/lib/proc16.mk', ); - if ($::opt_p) { - # if -p then copy oracle.mk to start of search list and thus prefer it - my @ora = grep { m/(oracle|rdbms)\.mk\b/ } @mkplaces; - unshift @mkplaces, @ora; - } + my @mk_oci = ( + 'rdbms/lib/oracle.mk', + 'rdbms/demo/oracle.mk', + 'rdbms/demo/demo_rdbms.mk', + ); + my @mkplaces = ($::opt_p) ? @mk_proc : @mk_oci; if ($::opt_m) { $::opt_m = cwd()."/$::opt_m" unless $::opt_m =~ m:^/:; die "-m $::opt_m: not found" unless -f $::opt_m; @@ -449,7 +459,7 @@ sub fetch_oci_macros { my $of; foreach $of (split(/=|\s+/)) { next if !$of or $of eq "COMPOBJS"; - my $obj = expand_mkvars($of,0,0,0); + my $obj = expand_mkvars($of,0,0); next if -e $obj; print "Deleting $of from COMPOBJS because $obj doesn't exist.\n"; s:\Q$of::; @@ -516,11 +526,19 @@ sub fetch_oci_macros { } # modern Oracle .mk files define OCISTATICLIBS and OCISHAREDLIBS - $linkvia = '$(OCISTATICLIBS)' - if !$linkvia && $MK{OCISTATICLIBS} - && $opts{LINKTYPE} && $opts{LINKTYPE} eq 'static'; - $linkvia = '$(OCISHAREDLIBS)' - if !$linkvia && $MK{OCISHAREDLIBS}; + if (!$linkvia && $MK{OCISHAREDLIBS}) { + $linkvia = ''; + if ($opts{LINKTYPE} && $opts{LINKTYPE} eq 'static' && $MK{OCISTATICLIBS}) { + $linkvia .= '$(DEF_ON) ' if $MK{DEF_ON}; + $linkvia .= '$(SSCOREED) ' if $MK{SSCOREED}; + $linkvia .= '$(OCISTATICLIBS)'; + } + else { + $linkvia .= '$(SSDBED) ' if $MK{SSDBED}; + $linkvia .= '$(DEF_OPT) ' if $MK{DEF_OPT}; + $linkvia .= '$(OCISHAREDLIBS)'; + } + } # The oracle.mk file tends to define OCILDLIBS $linkvia = '$(OCILDLIBS)' @@ -596,6 +614,7 @@ sub expand_shellescape { sub expand_mkvars { my($string, $strip, $backtick, $level) = @_; + $level ||= 1; local($_) = $string; print "$level Expanding $_\n" if $::opt_d; # handle whizzo AIX make feature used by Oracle @@ -623,7 +642,8 @@ sub mkvar { my $val = $MK{$var}; if (!defined $val and exists $ENV{$var}) { $val = $ENV{$var}; - print "Using value of $var from environment: $val\n"; + print "Using value of $var from environment: $val\n" + unless $var eq 'LD_LIBRARY_PATH'; } return $default unless defined $val; if ($MK_expanding{$var}) { diff --git a/Oracle.pm b/Oracle.pm index 0d667a5a..085bdb4d 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.54 1998/07/21 00:07:30 timbo Exp $ +# $Id: Oracle.pm,v 1.55 1998/08/03 19:43:39 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.52'; +$DBD::Oracle::VERSION = '0.53'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -22,7 +22,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; use Exporter (); @ISA = qw(DynaLoader Exporter); - my $Revision = substr(q$Revision: 1.54 $, 10); + my $Revision = substr(q$Revision: 1.55 $, 10); require_version DBI 0.92; diff --git a/Todo b/Todo index 1bf310ad..ababd7c5 100644 --- a/Todo +++ b/Todo @@ -1,6 +1,7 @@ Oracle 8 -If LongReadLen > 64k then automatocally call oflng for each long LONG. +Fetch: If LongReadLen > 64k then automatocally call oflng for each long LONG. +Bind: Automatically do piecewise insert of longs. $drh->debug oddities (re data_source debugging) diff --git a/dbdimp.c b/dbdimp.c index 2e540b83..5ab10e0c 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.38 1998/07/28 17:33:37 timbo Exp $ + $Id: dbdimp.c,v 1.39 1998/08/03 19:43:39 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -54,6 +54,8 @@ dbd_discon_all(drh, imp_drh) SV *drh; imp_drh_t *imp_drh; { + dTHR; + /* The disconnect_all concept is flawed and needs more work */ if (!dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { sv_setiv(DBIc_ERR(imp_drh), (IV)1); @@ -208,6 +210,8 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) char *uid; char *pwd; { + + dTHR; int ret; imp_dbh->lda = &imp_dbh->ldabuf; @@ -297,6 +301,8 @@ dbd_db_disconnect(dbh, imp_dbh) SV *dbh; imp_dbh_t *imp_dbh; { + dTHR; + /* We assume that disconnect will always work */ /* since most errors imply already disconnected. */ DBIc_ACTIVE_off(imp_dbh); @@ -1093,6 +1099,8 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count SV *sth; imp_sth_t *imp_sth; { + dTHR; + int debug = dbis->debug; int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0; @@ -1440,6 +1448,8 @@ dbd_st_finish(sth, imp_sth) SV *sth; imp_sth_t *imp_sth; { + dTHR; + /* Cancel further fetches from this cursor. */ /* We don't close the cursor till DESTROY (dbd_st_destroy). */ /* The application may re execute(...) it. */ diff --git a/test.pl b/test.pl index cb95d905..6fdc266f 100755 --- a/test.pl +++ b/test.pl @@ -74,8 +74,13 @@ die "\nTest aborted.\n"; } # test_other($l); - print `sleep 1; echo Backticks OK` || "Backticks failed: $!\n" - if ($os ne 'MSWin32' and $os ne 'VMS'); + if ($os ne 'MSWin32' and $os ne 'VMS') { + my $backtick = `sleep 1; echo Backticks OK`; + unless ($backtick) { # $! == Interrupted system call + print "Warning: Oracle's SIGCHLD signal handler breaks perl ", + "`backticks` commands: $!\n(d_sigaction=$Config{d_sigaction})\n"; + } + } &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; } $start = time; From f528bd53e55962d4ebfa9738eb6ff9d333bff55e Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Fri, 14 Aug 1998 14:41:19 -0500 Subject: [PATCH 033/637] import DBD-Oracle 0.54 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.54 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.54.tar.gz --- Changes | 12 + MANIFEST | 33 +- Makefile.PL | 16 +- Oracle.pm | 75 +++- README.explain | 193 ++++++++++ dbdimp.c | 71 ++-- ora_explain.PL | 935 +++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1264 insertions(+), 71 deletions(-) create mode 100644 README.explain create mode 100644 ora_explain.PL diff --git a/Changes b/Changes index 2ac45119..19bf8f09 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,15 @@ +Changes in DBD::Oracle 0.54 (Oraperl 1.37), 14th August 1998 + + Added $dbh->type_info_all. + Fixed $dbh->tables (partly by renaming to new $dbh->table_info). + data_sources no longer adds abbreviated versions of tnsnames. + Alan Burlison's whizzo Tk based explain script now bundled. + Revised workaround for "Can't bind unknown placeholder '3'" errors. + Doubled default automatic row cache size (now approx 5KB). + The resetting of Oracle's SIGCHD handler to SA_RESTART can + now be disabled by setting the env var DBD_ORACLE_SIGCHLD=0. + Fixed Makefile.PL -c to better avoid shared Oracle lib. + Changes in DBD::Oracle 0.53 (Oraperl 1.37), 3rd August 1998 Further build fixes (esp kpudc problem with Oracle 8). diff --git a/MANIFEST b/MANIFEST index d0decafa..5a461791 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,26 +1,22 @@ +Changes MANIFEST +Makefile.PL +Oracle.h +Oracle.pm +Oracle.xs +Oraperl.pm README -README.login -README.win32 README.clients README.help +README.login README.longs -Changes +README.win32 +README.explain Todo -Makefile.PL -Oracle.pm -Oracle.xs -Oracle.h -Oraperl.pm -dbdimp.h dbdimp.c -test.pl -t/base.t -t/general.t -t/plsql.t +dbdimp.h hints/svr4.pl -.purify Ignore most of the (many) problems in Oracle's libraries. Very sad. -oraperl.ph Old oraperl file included for completeness of emulation +ora_explain.PL oraperl.ex/Readme Oraperl examples (copied mostly unchanged from oraperl-2.4) oraperl.ex/bind.pl oraperl.ex/commit.pl @@ -30,4 +26,9 @@ oraperl.ex/mkdb.pl oraperl.ex/oradump.pl oraperl.ex/sql oraperl.ex/tabinfo.pl - +oraperl.ph Old oraperl file included for completeness of emulation +t/base.t +t/general.t +t/plsql.t +test.pl +.purify Ignore most of the (many) problems in Oracle's libraries. Very sad. diff --git a/Makefile.PL b/Makefile.PL index 8ba45578..e7022fbc 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.67 1998/08/03 20:51:25 timbo Exp $ +# $Id: Makefile.PL,v 1.68 1998/08/14 18:07:46 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -36,6 +36,7 @@ $osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 my %opts = ( NAME => 'DBD::Oracle', VERSION_FROM => 'Oracle.pm', + EXE_FILES => [ 'ora_explain' ], OBJECT => '$(O_FILES)', DEFINE => '', DIR => [], @@ -195,10 +196,12 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l # can we give the shared library a helping hand? my @shared = grep { m:/lib(cl(ie)?ntsh|oracle).\w+$:o } @ora_libs; # show original value of ORA_CLIENT_LIB if defined ... - print "\$ORA_CLIENT_LIB=$ENV{ORA_CLIENT_LIB}\n" if $ENV{ORA_CLIENT_LIB}; + print "\$ORA_CLIENT_LIB=$ENV{ORA_CLIENT_LIB}\n" + if defined $ENV{ORA_CLIENT_LIB}; # ... before we then set it how it probably should be set - $ENV{ORA_CLIENT_LIB} ||= 'shared' - if ($opts{LINKTYPE}||'') ne 'static' && @shared && !$::opt_c; + $ENV{ORA_CLIENT_LIB} = 'shared' + if !defined $ENV{ORA_CLIENT_LIB} + && ($opts{LINKTYPE}||'') ne 'static' && @shared && !$::opt_c; my $mkfile = find_mkfile(); my $linkvia = fetch_oci_macros($mkfile); @@ -526,9 +529,10 @@ sub fetch_oci_macros { } # modern Oracle .mk files define OCISTATICLIBS and OCISHAREDLIBS - if (!$linkvia && $MK{OCISHAREDLIBS}) { + if (!$linkvia && ($MK{OCISHAREDLIBS} || $MK{OCISTATICLIBS})) { $linkvia = ''; - if ($opts{LINKTYPE} && $opts{LINKTYPE} eq 'static' && $MK{OCISTATICLIBS}) { + if ($MK{OCISTATICLIBS} && + (($opts{LINKTYPE}||'') eq 'static' || $::opt_c)) { $linkvia .= '$(DEF_ON) ' if $MK{DEF_ON}; $linkvia .= '$(SSCOREED) ' if $MK{SSCOREED}; $linkvia .= '$(OCISTATICLIBS)'; diff --git a/Oracle.pm b/Oracle.pm index 085bdb4d..462cf515 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.55 1998/08/03 19:43:39 timbo Exp $ +# $Id: Oracle.pm,v 1.57 1998/08/14 18:23:00 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.53'; +$DBD::Oracle::VERSION = '0.54'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -22,7 +22,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; use Exporter (); @ISA = qw(DynaLoader Exporter); - my $Revision = substr(q$Revision: 1.55 $, 10); + my $Revision = substr(q$Revision: 1.57 $, 10); require_version DBI 0.92; @@ -99,10 +99,6 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; warn "Found $name. ".($dbnames{$name} ? "(oratab entry overridden)" : "")."\n" if $debug; $dbnames{$name} = 0; # exists but false (to distinguish from oratab) - if ($name =~ /^([-\w]+)\.([-\w\.]+)/ && !exists $dbnames{$1}) { - warn " also $1. \n" if $debug; - $dbnames{$1} = 0; # exists but false (to distinguish from oratab) - } } close FH; last; @@ -229,22 +225,77 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; } - sub tables { + sub table_info { my($dbh) = @_; # XXX add qualification + # XXX add knowledge of public synonmys views etc + # The SYS/SYSTEM should probably be a decode that + # prepends 'SYSTEM ' to TABLE_TYPE. my $sth = $dbh->prepare("select - NULL TABLE_CAT, - at.OWNER TABLE_SCHEM, + NULL TABLE_QUALIFIER, + at.OWNER TABLE_OWNER, at.TABLE_NAME, tc.TABLE_TYPE, - tc.COMMENTS TABLE_REMARKS + tc.COMMENTS REMARKS from ALL_TABLES at, ALL_TAB_COMMENTS tc where at.OWNER = tc.OWNER and at.TABLE_NAME = tc.TABLE_NAME - "); + and at.OWNER <> 'SYS' and at.OWNER <> 'SYSTEM' + order by tc.TABLE_TYPE, at.OWNER, at.TABLE_NAME + ") or return undef; $sth->execute or return undef; $sth; } + sub type_info_all { + my ($dbh) = @_; + my $names = { + TYPE_NAME => 0, + DATA_TYPE => 1, + COLUMN_SIZE => 2, + LITERAL_PREFIX => 3, + LITERAL_SUFFIX => 4, + CREATE_PARAMS => 5, + NULLABLE => 6, + CASE_SENSITIVE => 7, + SEARCHABLE => 8, + UNSIGNED_ATTRIBUTE => 9, + FIXED_PREC_SCALE =>10, + AUTO_UNIQUE_VALUE =>11, + LOCAL_TYPE_NAME =>12, + MINIMUM_SCALE =>13, + MAXIMUM_SCALE =>14, + }; + # Based on the values from Oracle 8.0.4 ODBC driver + my $ti = [ + $names, + [ 'LONG RAW', -4, '2147483647', '\'', '\'', undef, 1, '0', '0', + undef, '0', undef, undef, undef, undef + ], + [ 'RAW', -3, 255, '\'', '\'', 'max length', 1, '0', 3, + undef, '0', undef, undef, undef, undef + ], + [ 'LONG', -1, '2147483647', '\'', '\'', undef, 1, 1, '0', + undef, '0', undef, undef, undef, undef + ], + [ 'CHAR', 1, 255, '\'', '\'', 'max length', 1, 1, 3, + undef, '0', '0', undef, undef, undef + ], + [ 'NUMBER', 3, 38, undef, undef, 'precision,scale', 1, '0', 3, + '0', '0', '0', undef, '0', 38 + ], + [ 'DOUBLE', 8, 15, undef, undef, undef, 1, '0', 3, + '0', '0', '0', undef, undef, undef + ], + [ 'DATE', 11, 19, '\'', '\'', undef, 1, '0', 3, + undef, '0', '0', undef, '0', '0' + ], + [ 'VARCHAR2', 12, 2000, '\'', '\'', 'max length', 1, 1, 3, + undef, '0', '0', undef, undef, undef + ] + ]; + return $ti; + } + sub plsql_errstr { # original version thanks to Bob Menteer my $sth = shift->prepare_cached(q{ diff --git a/README.explain b/README.explain new file mode 100644 index 00000000..ca03be3e --- /dev/null +++ b/README.explain @@ -0,0 +1,193 @@ +explain +======= + +DISCLAIMER & COPYRIGHT +---------------------- + +Copyright (c) 1998 Alan Burlison + +You may distribute under the terms of either the GNU General Public License +or the Artistic License, as specified in the Perl README file, with the +exception that it cannot be placed on a CD-ROM or similar media for commercial +distribution without the prior approval of the author. + +This code is provided with no warranty of any kind, and is used entirely at +your own risk. + +This code was written by the author as a private individual, and is in no way +endorsed or warrantied by Sun Microsystems. + +WHAT IS IT? +----------- +explain is a GUI-based tool that enables easier visualisation of Oracle Query +plans. A query plan is the access path that Oracle will use to satisfy a SQL +query. The Oracle query optimiser is responsible for deciding on the optimal +path to use. Needless to say, understanding such plans requires a fairly +sophisticated knowledge of Oracle architecture and internals. + +explain allows a user to interactively edit a SQL statemant and view the +resulting query plan with the click of a single button. The effects of +modifying the SQL or of adding hints can be rapidly established. + +explain allows the user to grab all the SQL currently cached by Oracle. The SQL +capture can be filtered and sorted by different criterea, e.g. all SQL matching +a pattern, order by number of executions etc. + +explain is written using Perl, DBI/DBD::Oracle and Tk. + +PREREQUISITES +------------- +1. Oracle 7 or Oracle 8, with SQL*Net if appropriate +2. Perl 5.004_04 or later +3. DBI version 0.93 or later +4. DBD::Oracle 0.49 or later +5. Tk 800.005 or later +6. Tk-Tree 3.00401 or later + +Items 2 through 6 can be obtained from any CPAN mirror. + +INSTALLATION +------------ +1. Check you have all the prequisites installed and working. +2. Check the #! line in the script points to where your Perl interpreter is + installed. +3. Copy the "explain" script to somewhere on your path. +4. Make sure the "explain" script is executable. +5. Make sure you have run the script $ORACLE_HOME/rdbms/admin/utlxplan.sql + from a SQL*Plus session. This script creates the PLAN_TABLE that is used + by Oracle when explaining query plans. + +HOW TO USE +---------- + +Type "explain" at the shell prompt. A window will appear with a menu bar and +three frames, labelled "Query Plan", "Query Step Details" and "SQL Editor". At +the bottom of the window is a single button labelled "Explain". A login dialog +will also appear, into which you should enter the database username, password +and database instance name (SID). The parameters you enter are passed to the +DBI->connect() method, so if you have any problems refer to the DBI and +DBD::Oracle documentation. + +Optionally you may supply up to two command-line arguments. If the first +argument is of the form username/password@database, explain will use this to +log in to Oracle, otherwise if it is a filename it will be loaded into the SQL +editor. If two arguments are supplied, the second one will be assumed to be a +filename. + +Examples: + explain scott/tiger@DB query.sql + explain / query.sql (assumes OPS$ user authentication) + explain query.sql + + +Explain functionality +--------------------- + +The menu bar has one pulldown menu, "File", which allows you to login to Oracle, +Grab the contents of the Oracle SQL cache, Load SLQ from files, Save SQL to +files and to Exit the program. + +The "SQL Editor" frame allows the editing of a SQL statement. This should be +just a single statement - multiple statements are not allowed. Refer to the +documentation for the Tk text widget for a description of the editing keys +available. Text may be loaded and saved by using the "File" pulldown menu. + +Once you have entered a SQL statement, the "Explain" button at the bottom of +the window will generate the query plan for the statement. A tree +representation of the plan will appear in the "Query Plan" frame. Individual +"legs" of the plan may be expanded and collapsed by clicking on the "+' and "-" +boxes on the plan tree. The tree is drawn so that the "innermost" or "first" +query steps are indented most deeply. The connecting lines show the +"parent-child" relationships between the query steps. For a comprehensive +explanation of the meaning of query plans you should refer to the relevant +Oracle documentation. + +Single-clicking on a plan step in the Query Plan pane will display more +detailed information on that query step in the Query Step Details frame. This +information includes Oracle's estimates of cost, cardinality and bytes +returned. The exact information displayed depends on the Oracle version. +Again, for detailed information on the meaning of these fields, refer to the +Oracle documentation. + +Double-clicking on a plan step that refers to either a table or an index will +pop up a dialog box showing the definitiaon of the table or index in a format +similar to that of the SQL*Plus 'desc' command. + +Grab functionality +----------------- + +The explain window has an option on the "File" menu labelled "Grab SQL ...". +Selecting this will popup a new top-level window containing a menu bar and +three frames, labelled "SQL Cache", "SQL Statement Statistics" and "SQL +Selection Criterea". At the bottom of the window is a single button labelled +"Grab". + +The menu bar has one pulldown menu, "File", which allows you to Save the +contents of the SQL Cache frame and Close the Grab window. + +The "SQL Cache" frame shows the statements currently in the Oracle SQL cache. +Text may be saved by using the "File" pulldown menu. + +The "SQL Selection Criterea" frame allows you to specify which SQL statements +you are interested in, and how you want them sorted. The pattern used to select +statements is a normal perl regexp. Once you have defined the selection +criterea, clicking the "Grab" button will read all the matching statements from +the SQL cache and display them in the top frame. + +Single-clicking on a statement in the SQL Cache pane will display more +detailed information on that statement in the Sql Statement Statistics frame, +including the number of times the statement has been executed and the numbers +of rows processed by the statement. + +Double-clicking on a statement will copy it into the SQL editor in the Explain +window, so that the query plan for the statement can be examined. + +SUPPORT +------- + +Support questions and suggestions can be directed to Alan.Burlison@uk.sun.com + + +CHANGES +======= + +Version 0.51 beta 09/08/98 +--------------------------- + +Integrated into DBD::Oracle release 0.54. + +Version 0.5 beta 02/06/98 +-------------------------- +Changes made to work with Tk800.005. +Fixed bug with grab due to Oracle's inconsistent storage of the hash_value +column in v$sqlarea and v$sqltext_with_newlines. +Disallowed multiple concurrent login/save/open dialogs. +Fixed double-posting of login dialog on startup. +Tried to make it less Oracle version dependent. + +Version 0.4 beta 27/02/98 +-------------------------- +Grab functionality added, to allow interrogation of Oracle's SQL cache +Bind variables used wherever possible to prevent unnecessary reparses of the +SQL generated by explain +Extra error checking +Various code cleanups & restructuring +More extensive commenting of the source + +Version 0.3 beta 19/02/98 +-------------------------- +Changed to use new Tk FileSelect instead of older FileDialog. +Added facility to supply user/pass@database & SQL filename on the command-line. +Thanks to Eric Zylberstejn for the patch + suggestions. +Added check on login to Oracle for a PLAN_TABLE in the user's schema. + +Version 0.2 beta 05/02/98 +-------------------------- +Changed to work with both Oracle 7 and 8 statistics. +Pop-up table & index description dialogs added. +First public version. + +Version 0.1 beta 27/01/98 +-------------------------- +Initial version. +Not publically released. diff --git a/dbdimp.c b/dbdimp.c index 5ab10e0c..5dc49626 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.39 1998/08/03 19:43:39 timbo Exp $ + $Id: dbdimp.c,v 1.40 1998/08/14 18:07:46 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -25,7 +25,8 @@ static SV *ora_pad_empty; static SV *ora_cache; static SV *ora_cache_o; /* temp hack for ora_open() cache override */ static int ora_login_nomsg; /* don't fetch real login errmsg if true */ -static int ora_fetchtest = 0; +static int ora_fetchtest; +static int ora_sigchld_restart = 1; static void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); @@ -46,6 +47,8 @@ dbd_init(dbistate) if (getenv("DBD_ORACLE_LOGIN_ERR")) ora_login_nomsg = atoi(getenv("DBD_ORACLE_LOGIN_NOMSG")); + if (getenv("DBD_ORACLE_SIGCHLD")) + ora_sigchld_restart = atoi(getenv("DBD_ORACLE_SIGCHLD")); } @@ -219,6 +222,29 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) /* can give duplicate free errors (from Oracle) if connect fails */ ret = orlon(imp_dbh->lda, imp_dbh->hda, (text*)uid,-1, (text*)pwd,-1,0); + if (ret) { + int rc = imp_dbh->lda->rc; + char buf[100]; + char *msg; + switch(rc) { /* add helpful hints to some errors */ + case 0: msg = "login failed, check ORACLE_HOME/bin is on your PATH"; break; + case 1019: msg = "login failed, probably a symptom of a deeper problem"; break; + default: msg = "login failed"; break; + } + if (ora_login_nomsg) { + /* oerhms in ora_error may hang or corrupt memory (!) after a connect */ + /* failure in some specific versions of Oracle 7.3.x. So we provide a */ + /* way to skip the message lookup if ora_login_nomsg is true (set via */ + /* env var above). */ + sprintf(buf, + "ORA-%05d: (Text for error %d not fetched. Use 'oerr ORA %d' command.)", + rc, rc, rc); + msg = buf; + } + ora_error(dbh, ora_login_nomsg ? NULL : imp_dbh->lda, rc, msg); + return 0; + } + #ifdef SA_RESTART #ifndef SIGCLD #define SIGCLD SIGCHLD @@ -226,7 +252,7 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) /* If orlon has installed a handler for SIGCLD, then reinstall it */ /* with SA_RESTART. We only do this if connected ok since I've */ /* seen the process loop after being interrupted after connect failed. */ - if (ret == 0 && imp_dbh->lda->rc == 0) { + if (ora_sigchld_restart) { struct sigaction act; if (sigaction( SIGCLD, (struct sigaction*)0, &act ) == 0 && (act.sa_handler != SIG_DFL && act.sa_handler != SIG_IGN) @@ -243,28 +269,6 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) } #endif /* HAS_SIGACTION */ - if (ret) { - int rc = imp_dbh->lda->rc; - char buf[100]; - char *msg; - switch(rc) { /* add helpful hints to some errors */ - case 0: msg = "login failed, check ORACLE_HOME/bin is on your PATH"; break; - case 1019: msg = "login failed, probably a symptom of a deeper problem"; break; - default: msg = "login failed"; break; - } - if (ora_login_nomsg) { - /* oerhms in ora_error may hang or corrupt memory (!) after a connect */ - /* failure in some specific versions of Oracle 7.3.x. So we provide a */ - /* way to skip the message lookup if ora_login_nomsg is true (set via */ - /* env var above). */ - sprintf(buf, - "ORA-%05d: (Text for error %d not fetched. Use 'oerr ORA %d' command.)", - rc, rc, rc); - msg = buf; - } - ora_error(dbh, ora_login_nomsg ? NULL : imp_dbh->lda, rc, msg); - return 0; - } DBIc_IMPSET_on(imp_dbh); /* imp_dbh set up now */ DBIc_ACTIVE_on(imp_dbh); /* call disconnect before freeing */ return 1; @@ -682,7 +686,7 @@ dbd_describe(h, imp_sth) /* Use guessed average on-the-wire row width calculated above */ /* and add in overhead of 5 bytes per field plus 8 bytes per row. */ /* The n*5+8 was determined by studying SQL*Net v2 packets. */ - /* It could probably benefit from a more detailed anaylsis. */ + /* It could probably benefit from a more detailed analysis. */ est_width += num_fields*5 + 8; if (has_longs) /* override/disable caching */ @@ -697,7 +701,7 @@ dbd_describe(h, imp_sth) /* We'll aim to fill our row cache with slightly less than */ /* two packets (to err on the safe side and avoid a third */ /* almost empty packet being generated in some cases). */ - txfr_size = 1460 * 1.6; /* default transfer/cache size */ + txfr_size = 1460 * 3.6; /* default transfer/cache size */ } else { /* user is specifying desired transfer size in bytes */ txfr_size = -imp_sth->cache_rows; @@ -991,19 +995,12 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl /* check if placeholder was passed as a number */ - /* possible workaround for "unknown placeholder '3'" problem */ if (!SvNIOK(ph_namesv) && !SvPOK(ph_namesv)) { - /* force SvPOK true before following tests */ - if (dbis->debug >= 2) - fprintf(DBILOGFP, - " bind warning: forcing placeholder flags: type %ld, flags 0x%lx\n", - SvTYPE(ph_namesv), SvFLAGS(ph_namesv)); - name = SvPV(ph_namesv, name_len); + SvPV(ph_namesv, na); /* force SvPOK */ } - if (SvNIOK(ph_namesv) || (SvPOK(ph_namesv) && isDIGIT(*SvPVX(ph_namesv)))) { + sprintf(namebuf, ":p%d", (int)SvIV(ph_namesv)); name = namebuf; - sprintf(name, ":p%d", (int)SvIV(ph_namesv)); name_len = strlen(name); } else { /* use the supplied placeholder name directly */ @@ -1031,7 +1028,7 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl phs_svp = hv_fetch(imp_sth->all_params_hv, name, name_len, 0); if (phs_svp == NULL) - croak("Can't bind unknown placeholder '%s'", name); + croak("Can't bind unknown placeholder '%s' (%s)", name, neatsvpv(ph_namesv,0)); phs = (phs_t*)(void*)SvPVX(*phs_svp); /* placeholder struct */ if (phs->sv == &sv_undef) { /* first bind for this placeholder */ diff --git a/ora_explain.PL b/ora_explain.PL new file mode 100644 index 00000000..c68184b6 --- /dev/null +++ b/ora_explain.PL @@ -0,0 +1,935 @@ +# -*- perl -*- + +use strict; + +my $script = <<'SCRIPT'; +~startperl~ -w +#!/usr/local/bin/perl -w + +################################################################################ +# Copyright (c) 1998 Alan Burlison +# +# You may distribute under the terms of either the GNU General Public License +# or the Artistic License, as specified in the Perl README file, with the +# exception that it cannot be placed on a CD-ROM or similar media for commercial +# distribution without the prior approval of the author. +# +# This code is provided with no warranty of any kind, and is used entirely at +# your own risk. +# +# This code was written by the author as a private individual, and is in no way +# endorsed or warrantied by Sun Microsystems. +# +# Support questions and suggestions can be directed to Alan.Burlison@uk.sun.com +# +################################################################################ + +use strict; +use IO::File; +use File::Basename; +use Cwd; +use DBI; +use Tk; +use Tk::Dialog; +use Tk::FileSelect; +use Tk::ROText; +use Tk::Tree; + +use vars qw($VERSION); +$VERSION = "0.6 beta"; + +# Globals +# $Db Database handle +# $SqlMarker String used to identify SQL generated by explain +# $OracleVersion Oracle version number +# $Plan Current query plan as a Perl data structure +# $LoginDialog Login dialog +# $SaveDialog Save File dialog +# $OpenDialog Open File dialog +# $FileDir Current file save/open directory +# $PlanMain Query plan main window +# $PlanTitle Title of query plan main window +# $PlanTree Tree used to display the query plan +# $PlanStep ROText used to display the selected plan step details +# $PlanSql Text used to allow SQL editing +# $GrabMain SQL cache grab main window +# $GrabSql ROText used to hold the contents of the SQL cache +# $GrabDetails ROText used to display the selected statement details +use vars qw($Db $SqlMarker $OracleVersion $Plan + $LoginDialog $OpenDialog $SaveDialog $FileDir + $PlanMain $PlanTitle $PlanTree $PlanStep $PlanSql + $GrabMain $GrabSql $GrabDetails); +$SqlMarker = '/* This statement was generated by explain */'; + +################################################################################ +# Display an error message in a dialog + +sub error($@) +{ +my ($parent) = shift(@_); +$PlanMain->Dialog(-title => "Error", + -bitmap => "error", + -text => join("\n", @_), + -wraplength => "5i", + -buttons => ["OK"] )->Show(); +} + +################################################################################ +# Login to the database. The new database handle is put into $Db, and the +# Oracle version number is put into $OracleVersion + +sub login($$$) +{ +my ($database, $username, $password) = @_; + +# Close any existing handle +if ($Db) + { + $Db->disconnect(); + $Db = undef; + } + +# Connect and initialise +$Db = DBI->connect("dbi:Oracle:$database", $username, $password, + { AutoCommit => 0, PrintError => 0}) + || die("Can't login to Oracle: $DBI::errstr\n"); +$Db->{LongReadLen} = 4096; +$Db->{LongTruncOk} = 1; + +# Check there is a plan_table for this user +my $qry = $Db->prepare(qq( + $SqlMarker select 1 from user_tables where table_name = 'PLAN_TABLE' +)); +$qry->execute(); +if (! $qry->fetchrow_arrayref()) + { + $qry->finish(); + $Db->disconnect(); + $Db = undef; + die("User $username does not have a PLAN_TABLE.\n", + "Run the script utlxplan.sql to create one.\n"); + } + +# Check the Oracle version +$qry = $Db->prepare(qq( + $SqlMarker select version from product_component_version + where lower(product) like '%oracle%' +)); +if (! $qry->execute()) + { + my $err = $DBI::errstr; + $qry->finish(); + $Db->disconnect(); + $Db = undef; + die("Can't fetch Oracle version: $err\n"); + } +($OracleVersion) = $qry->fetchrow_array(); +$qry->finish(); +} + +################################################################################ +# Clear the plan tree & details windows + +sub clear_plan() +{ +$PlanTitle->configure(-text => 'Query Plan') if ($PlanTitle); +$PlanTree->delete('all') if ($PlanTree); +$PlanStep->delete('1.0', 'end') if ($PlanStep); +} + +################################################################################ + +sub clear_editor() +{ +$PlanTitle->configure(-text => 'Query Plan') if ($PlanTitle); +$PlanTree->delete('all') if ($PlanTree); +$PlanStep->delete('1.0', 'end') if ($PlanStep); +$PlanSql->delete('1.0', 'end'); +} + +################################################################################ +# Display the query plan tree + +sub disp_plan_tree() +{ +$PlanTitle->configure(-text => $Plan->{title}); +$PlanTree->delete('all'); +foreach my $step (@{$Plan->{id}}) + { + $PlanTree->add($step->{key}, -text => $step->{desc}); + } +$PlanTree->autosetmode(); +} + +################################################################################ +# Display the statistics for a given plan step + +sub disp_plan_step($) +{ +my ($key) = @_; +my $row = $Plan->{key}{$key}; +$PlanStep->delete('1.0', 'end'); +my $info = ""; +$info .= "Id:\t$row->{ID}\tPosition:\t$row->{POSITION}\t" + . "Parent Id:\t$row->{PARENT_ID}\n"; +$info .= "Cost:\t$row->{COST}\tCardinality:\t$row->{CARDINALITY}\t" + . "Bytes:\t\t$row->{BYTES}\n" + if ($row->{COST}); +$info .= "\nPartition\nStart:\t$row->{PARTITION_START}\tStop:\t\t" + . "$row->{PARTITION_STOP}\tId:\t\t$row->{PARTITION_ID}\n" + if ($row->{PARTITION_START}); +$info .= "\n$row->{OTHER}" if ($row->{OTHER}); +$PlanStep->insert('1.0', $info); +} + +################################################################################ +# Display a popup dialog showing the structure of the table or index used in +# the passed plan step + +sub disp_plan_step_obj($) +{ +my ($key) = @_; + +# Get the plan step & return if it doesn't refer to an object +my $row = $Plan->{key}{$key}; +return(1) if (! $row->{OBJECT_NAME}); + +# Work out the type of the object - table or index +my $qry = $Db->prepare(qq( + $SqlMarker select object_type from all_objects + where object_name = :1 and owner = :2 +)); +$qry->execute($row->{OBJECT_NAME}, $row->{OBJECT_OWNER}) + || die("Object type: $DBI::errstr\n"); +my ($object_type) = $qry->fetchrow_array(); +$qry->finish(); +$object_type = ucfirst(lc($object_type)); + +# We only know about Tables and Indexes +if ($object_type ne 'Table' && $object_type ne 'Index') + { + die("Unknown object type $object_type", + "for $row->{OBJECT_OWNER}.$row->{OBJECT_NAME}\n"); + } + +# Create the dialog for displaying the object details +my $dialog = $PlanMain->Toplevel(-title => $object_type); +my $box = $dialog->Frame(-borderwidth => 2, -relief => 'raised'); +$box->Label(-text => "$row->{OBJECT_OWNER}.$row->{OBJECT_NAME}", + -relief => 'ridge', -borderwidth => 1) + ->grid(-column => 0, -row => 0, -columnspan => 2, -sticky => 'we'); + +# For tables we mimic the SqlPlus 'desc' command +if ($object_type eq 'Table') + { + $box->Label(-text => " Name ", -relief => 'ridge', -borderwidth => 1) + ->grid(-column => 0, -row => 1, -sticky => 'we'); + $box->Label(-text => " Type ", -relief => 'ridge', -borderwidth => 1) + ->grid(-column => 1, -row => 1, -sticky => 'we'); + + # This will get the table description + $qry = $Db->prepare(qq( + $SqlMarker select column_name, data_type, data_length, + data_precision, data_scale + from all_tab_columns + where owner = :1 and table_name = :2 + order by column_id + )); + $qry->execute($row->{OBJECT_OWNER}, $row->{OBJECT_NAME}) + || die("Table columns: $DBI::errstr\n"); + + # For each column in the table, display its details + my $row = 2; + while ((my ($name, $type, $length, $precision, $scale) + = $qry->fetchrow_array())) + { + $box->Label(-text => "$name ") + ->grid(-column => 0, -row => $row, -sticky => 'w'); + if ($precision) + { + $type .= "($precision"; + $type .= ",$scale" if ($scale); + $type .= ")"; + } + elsif ($type =~ /CHAR/) + { + $type .= "($length)"; + } + $box->Label(-text => $type) + ->grid(-column => 1, -row => $row, -sticky => 'w'); + $row++; + } + $qry->finish(); + } + +# For indexes we show the table columns the index is built upon +else + { + $box->Label(-text => " Table ", -relief => 'ridge', -borderwidth => 1) + ->grid(-column => 0, -row => 1, -sticky => 'we'); + $box->Label(-text => " Column ", -relief => 'ridge', -borderwidth => 1) + ->grid(-column => 1, -row => 1, -sticky => 'we'); + $qry = $Db->prepare(qq( + $SqlMarker select table_owner, table_name, column_name + from all_ind_columns + where index_owner = :1 and index_name = :2 + order by column_position + )); + $qry->execute($row->{OBJECT_OWNER}, $row->{OBJECT_NAME}) + || die("Index columns: $DBI::errstr\n"); + + # For each column in the index, display its details + my $row = 2; + while ((my ($owner, $table, $column) = $qry->fetchrow_array())) + { + $box->Label(-text => "$owner.$table ") + ->grid(-column => 0, -row => $row, -sticky => 'w'); + $box->Label(-text => $column) + ->grid(-column => 1, -row => $row, -sticky => 'w'); + $row++; + } + $qry->finish(); + } + +# Pack the grid and add the close button +$box->pack(); +$dialog->Button(-text => 'Close', -command => sub { $dialog->destroy(); }) + ->pack(-pady => 3); +} + +################################################################################ +# Produce the query plan for the SQL in $PlanSql and store it in $Plan + +sub _explain() +{ +# Check there is some SQL +my $stmt = $PlanSql->get('1.0', 'end'); +$stmt =~ s/;//g; +die("You have not supplied any SQL\n") if ($stmt =~ /^\s*$/); + +# Check we are logged on +die("You are not logged on to Oracle\n") if (! $Db); + +# Set up the various query strings +# Note that for some reason you can't use bind variables in 'explain plan' +my $prefix = "explain plan set statement_id = '$$' for "; +my $plan_sql = qq( + $SqlMarker select level, operation, options, object_node, object_owner, + object_name, object_instance, object_type, id, parent_id, position, + other); +if ($OracleVersion ge '7.3') + { $plan_sql .= qq(, cost, cardinality, bytes, other_tag) }; +if ($OracleVersion ge '8') + { $plan_sql .= qq(, partition_start, partition_stop, partition_id) }; +$plan_sql .= qq( + from plan_table + where statement_id = :1 + connect by prior id = parent_id and statement_id = :1 + start with id = 0 and statement_id = :1 +); + +# Clean any old stuff from the plan_table +$Db->do(qq($SqlMarker delete from plan_table where statement_id = :1), + undef, $$) + || die("Delete from plan_table: $DBI::errstr\n"); +$Db->commit(); + +# Explain the plan +$Plan = { sql => $stmt }; +$Db->do($prefix . $stmt) || die("Explain plan: $DBI::errstr\n"); + +# Read back the plan +my $qry = $Db->prepare($plan_sql) + || die("Unsupported PLAN_TABLE format: $DBI::errstr\n"); +$qry->execute($$) || die("Read plan: $DBI::errstr\n"); +while (my $row = $qry->fetchrow_hashref()) + { + if ($row->{ID} == 0) + { + $Plan->{title} = "Query Plan for " . lc($row->{OPERATION}); + $Plan->{title} .= ". Cost = $row->{POSITION}" if ($row->{POSITION}); + } + else + { + # Line wrap the OTHER field + $row->{OTHER} =~ s/((.{1,80})(\s+|,|$))/$1\n/g if ($row->{OTHER}); + + # Construct a descriptive string for the query step + my $desc = "$row->{OPERATION}"; + $desc .= " $row->{OPTIONS}" if ($row->{OPTIONS}); + $desc .= " $row->{OBJECT_TYPE}" if ($row->{OBJECT_TYPE}); + $desc .= " of $row->{OBJECT_OWNER}.$row->{OBJECT_NAME}" + if ($row->{OBJECT_OWNER}); + $desc .= " using PQS $row->{OBJECT_NODE} $row->{OTHER_TAG}" + if ($row->{OBJECT_NODE}); + $row->{desc} = $desc; + + # Construct a hierarchical key for the query step + if (! $row->{PARENT_ID}) + { + my $key = "$row->{POSITION}"; + $row->{key} = $key; + $Plan->{id}[$row->{ID} - 1] = $row; + $Plan->{key}{$key} = $row; + } + else + { + my $parent = $Plan->{id}[$row->{PARENT_ID} - 1]; + my $key = "$parent->{key}.$row->{POSITION}"; + $row->{key} = $key; + $Plan->{id}[$row->{ID} - 1] = $row; + $Plan->{key}{$key} = $row; + $parent->{child}[$row->{POSITION} - 1] = $row; + } + } + } +# Top of the tree is step 0 +$Plan->{tree} = $Plan->{id}[0]; + +# Clean up +$qry->finish(); +$Db->do(qq($SqlMarker delete from plan_table where statement_id = :1), + undef, $$); +$Db->commit(); +} + +################################################################################ +# Wrapper for _explain - adds error handling + +sub explain +{ +clear_plan(); +if (! eval { _explain(); }) { error($PlanMain, $@); } +else { disp_plan_tree(); } +} + +################################################################################ +# Display a login dialog + +sub login_dialog($) +{ +my ($parent) = @_; + +# Set up defaults +# Create the dialog +if (! $LoginDialog) + { + my $username = '/'; + my $password = ''; + my $database = $ENV{TWO_TASK} || $ENV{ORACLE_SID}; + + $LoginDialog = $parent->Toplevel(-title => 'Login to Oracle'); + $LoginDialog->withdraw(); + $LoginDialog->transient($parent); + my $box; + + # Create the entry labels & fields + $box = $LoginDialog->Frame(-borderwidth => 1, -relief => 'raised'); + $box->Label(-text => 'Username') + ->grid(-column => 0, -row => 0, -sticky => 'w'); + $box->Entry(-textvariable => \$username, -width => 30) + ->grid(-column => 1, -row => 0, -sticky => 'w'); + $box->Label(-text => 'Password') + ->grid(-column => 0, -row => 1, -sticky => 'w'); + $box->Entry(-textvariable => \$password, -width => 30, -show => '*') + ->grid(-column => 1, -row => 1, -sticky => 'w'); + $box->Label(-text => 'Database') + ->grid(-column => 0, -row => 2, -sticky => 'w'); + $box->Entry(-textvariable => \$database, -width => 30) + ->grid(-column => 1, -row => 2, -sticky => 'w'); + $box->pack(-expand => 1, -fill => 'both'); + + # Create the buttons & callbacks + $box = $LoginDialog->Frame(-borderwidth => 1, -relief => 'raised'); + my $cb = sub + { + if (! eval { login($database, $username, $password); }) + { + error($parent, $@); + $LoginDialog->raise(); + } + else + { + $LoginDialog->withdraw(); + } + }; + $box->Button(-text => 'Login', -command => $cb) + ->pack(-side => 'left', -expand => 1, -pady => 3); + $box->Button(-text => 'Cancel', -command => sub { $LoginDialog->withdraw() }) + ->pack(-side => 'right', -expand => 1, -pady => 3); + $box->pack(-expand => 1, -fill => 'both'); + } + +# Activate the dialog +$LoginDialog->Popup(); +} + +################################################################################ +# Open a file and read it into the SQL editor frame + +sub open_file($) +{ +# Open the file +my ($file) = @_; +my $fh; +if (! ($fh = IO::File->new($file, "r"))) + { + error("Cannot open $file", $!); + return(0); + } + +# Clear the plan, plan details & SQL editor, then load into the SQL editor +clear_editor(); +while (my $line = $fh->getline()) + { + $PlanSql->insert('end', $line); + } +$fh->close(); +return(1); +} + +################################################################################ +# Display a file open dialog & load into the SQL editor + +sub open_dialog($) +{ +my ($parent) = @_; + +$FileDir = cwd() if (! $FileDir); +if (! $OpenDialog) + { + $OpenDialog = $parent->FileSelect(-title => "Open File", + -create => 0); + } +$OpenDialog->configure(-directory => $FileDir); +my $file = $OpenDialog->Show(); +return if (! $file); +$FileDir = $OpenDialog->cget(-directory); +open_file($file); +} + +################################################################################ +# Display a file save dialog & save the contents of the passed Text widget + +sub save_dialog($$) +{ +my ($parent, $text) = @_; + +# Put up the dialog +$FileDir = cwd() if (! $FileDir); +if (! $SaveDialog) + { + $SaveDialog = $parent->FileSelect(-title => "Save File", + -create => 1); + } +$SaveDialog->configure(-directory => $FileDir); +my $file = $SaveDialog->Show(); +return if (! $file); +$FileDir = $SaveDialog->cget(-directory); + +# Save the Text widget contents to the selected file +my $fh; +if (! ($fh = IO::File->new($file, "w"))) + { + error("Cannot open $file", $!); + return; + } +$fh->print($text->get('1.0', 'end')); +$fh->close(); +} + +################################################################################ +# Copy SQL from the grab window into the explain SQL editor + +sub copy_sql() +{ +my ($text, $tag) = @_; +clear_editor(); +$PlanSql->insert('end', $text->get("$tag.first", "$tag.last")); +explain(); +} + +################################################################################ +# Display info from v$sqlarea for the selected statement in the SQL cache + +sub disp_sql_cache_info($) +{ +my ($address) = @_; + +# Empty the widget & prepare the SQL +$GrabDetails->delete('1.0', 'end'); +my $qry = $Db->prepare(qq( + $SqlMarker select sorts, executions, loads, parse_calls, disk_reads, + buffer_gets, rows_processed + from v\$sqlarea where address = :1 +)) || die("$DBI::errstr\n"); + +# Read the info. Note that the statement *may* have been purged from the cache! +$qry->execute($address); +my $info; +if (! (my ($sorts, $executions, $loads, $parse_calls, + $disk_reads, $buffer_gets, $rows_processed) + = $qry->fetchrow_array())) + { + $info = "This statement is no longer in the SQL cache"; + } +else + { + $info = "Sorts:\t\t$sorts\tExecutions:\t$executions\tLoads:\t\t$loads\n" + . "Parse calls:\t$parse_calls\tDisk reads:\t$disk_reads\t" + . "Buffer gets:\t$buffer_gets\nRows processed:\t$rows_processed"; + } + +# Display the formated info +$GrabDetails->insert('1.0', $info); +return(1); +} + +################################################################################ +# Scan v$sqlarea for SQL statements matching the specified conditions. +# $order_by is a v$sqlarea colum name used to rank the statements +# $user is who first issued the statement (case insensitive) +# $pattern is a perl regexp used to filter the SQL +# $rows is the maximum number of rows to display + +sub grab($$$$$) +{ +my ($order_by, $no_sys, $user, $pattern, $rows) = @_; + +# Check we are logged on +die("You are not logged on to Oracle\n") if (! $Db); + +# Munge args as necessary +$no_sys = $no_sys ? qq{and user_name not in ('SYS', 'SYSTEM')} : qq{}; +$rows = -1 if ($rows !~ /^\d+$/); +$user = uc($user); + +# Clear the frames +$GrabSql->delete('1.0', 'end'); +$GrabDetails->delete('1.0', 'end'); + +# Define the callbacks for highlighting etc +my ($bold, $normal); +if ($GrabMain->depth > 1) + { + $bold = sub + { + my ($text, $tag) = @_; + $text->tag('configure', $tag, -background => '#43ce80', + -relief => 'raised', -borderwidth => 1); + }; + $normal = sub + { + my ($text, $tag) = @_; + $text->tag('configure', $tag, -background => undef, -relief => 'flat'); + }; + } +else + { + $bold = sub + { + my ($text, $tag) = @_; + $text->tag('configure', $tag, -foreground => 'white', + -background => 'black'); + }; + $normal = sub + { + my ($text, $tag) = @_; + $text->tag('configure', $tag, -foreground => undef, -background => undef); + }; + } +my $disp_cb = sub + { + my ($text, $address) = @_; + if (! eval { disp_sql_cache_info($address); }) + { error($GrabMain, $@); } + }; + +# Prepare the queries +my $qry1 = qq{$SqlMarker select address from v\$sqlarea}; +$qry1 .= qq{, all_users} if ($user || $no_sys); +$qry1 .= qq{ where sql_text not like '\%$SqlMarker\%'}; +$qry1 .= qq{ and user_id = parsing_user_id} if($user || $no_sys); +$qry1 .= qq{ and username = :1} if ($user); +$qry1 .= qq{ and username not in ('SYS', 'SYSTEM')} if ($no_sys); +$qry1 .= qq{ order by $order_by desc} if ($order_by); +$qry1 = $Db->prepare($qry1) || die("$DBI::errstr\n"); + +my $qry2; +if ($OracleVersion ge '7.2') + { + $qry2 = $Db->prepare(qq( + $SqlMarker select sql_text from v\$sqltext_with_newlines + where address = :1 order by piece)) + || die("$DBI::errstr\n"); + } +else{ + $qry2 = $Db->prepare(qq( + $SqlMarker select sql_text from v\$sqltext + where address = :1 order by piece)) + || die("$DBI::errstr\n"); + } + +# For each SQL query in the shared pool... +$PlanMain->Busy(); +$GrabMain->Busy(); +if ($user) { $qry1->execute($user) || die("$DBI::errstr\n"); } +else { $qry1->execute() || die("$DBI::errstr\n"); } +while ($rows != 0 + && (my ($address) = $qry1->fetchrow_array())) + { + # ...glue together the components of the SQL string & print out + $qry2->execute($address) || die("$DBI::errstr\n"); + my ($sql_text) = ""; + while (my ($sql) = $qry2->fetchrow_array()) + { + $sql_text .= $sql; + } + $qry2->finish(); + $sql_text =~ s/^\s+//; + $sql_text =~ s/\n\s*\n/\n/; + $sql_text =~ s/\s+$//s; + + # Skip if it doesn't match the supplied pattern + next if ($pattern && eval { $sql_text !~ /$pattern/is; }); + + # Display the statement and set up the bindings + $GrabSql->insert('end', $sql_text, $address, "\n\n"); + $GrabSql->tag('bind', $address, '' => [ $bold, $address ]); + $GrabSql->tag('bind', $address, '' => [ $normal, $address ]); + $GrabSql->tag('bind', $address, '' => [ \©_sql, $address]); + $GrabSql->tag('bind', $address, '<1>' => [ $disp_cb, $address ]); + $GrabSql->update(); + + $rows--; + } + +# Clean up +$qry1->finish(); +$GrabMain->Unbusy(); +$PlanMain->Unbusy(); +return(1); +} + +################################################################################ +# Create a top-level window for getting SQL from the shared pool cache + +sub grab_main +{ +# Only create if it doesn't already exist +return if ($GrabMain); +$GrabMain = $PlanMain->Toplevel(-title => 'explain - SQL cache'); + +### Menubar +my $menubar = $GrabMain->Frame(-relief => 'raised', -borderwidth => 2); +$menubar->pack(-fill => 'x'); + +my $menubar_file = $menubar->Menubutton(-text => 'File', -underline => 0); +$menubar_file->command(-label => 'Save File ...', -underline => 0, + -command => sub { save_dialog($PlanMain, $GrabSql); }); +$menubar_file->separator(); +$menubar_file->command(-label => 'Close', -underline => 1, + -command => sub { $GrabMain->destroy(); }); +$menubar_file->pack(-side => 'left'); + +### SQL cache display +my $frame; +$frame = $GrabMain->Frame(-borderwidth => 3, -relief => 'raised'); +$frame->Label(-text => 'SQL Cache')->pack(-anchor => 'nw'); +$GrabSql = $frame->Scrolled('ROText', -setgrid => 'true', -scrollbars => 'oe', + -height => 15, -width => 80, -borderwidth => 0, + -wrap => 'word') + ->pack(-fill => 'both', -expand => 1); +$frame->pack(-fill => 'both', -expand => 1); + +### SQL statement details +$frame = $GrabMain->Frame(-borderwidth => 3, -relief => 'raised'); +$frame->Label(-text => 'SQL Statement Statistics')->pack(-anchor => 'nw'); +$GrabDetails = $frame->ROText(-height => 3, -width => 80, -borderwidth => 0, + -setgrid => 'true', -wrap => 'word') + ->pack(-fill => 'x'); +$frame->pack(-fill => 'x'); + +### SQL selection +$frame = $GrabMain->Frame(-borderwidth => 3, -relief => 'raised'); +$frame->Label(-text => 'SQL Selection Criterea')->pack(-anchor => 'nw'); + +my $frame1 = $frame->Frame(-highlightthickness => 2); +$frame1->Label(-text => 'Order SQL by number of:') + ->grid(-column => 0, -row => 0, -columnspan => 3, -sticky => 'w'); +my $order_by = 'disk_reads'; +$frame1->Radiobutton(-text => 'Disk reads', -highlightthickness => 0, + -value => 'disk_reads', -variable => \$order_by) + ->grid(-column => 0, -row => 1, -sticky => 'w'); +$frame1->Radiobutton(-text => 'Buffer gets', -highlightthickness => 0, + -value => 'buffer_gets', -variable => \$order_by) + ->grid(-column => 1, -row => 1, -sticky => 'w'); +$frame1->Radiobutton(-text => 'Rows processed', -highlightthickness => 0, + -value => 'rows_processed', -variable => \$order_by) + ->grid(-column => 2, -row => 1, -sticky => 'w'); +$frame1->Radiobutton(-text => 'Executions', -highlightthickness => 0, + -value => 'executions', -variable => \$order_by) + ->grid(-column => 3, -row => 1, -sticky => 'w'); +$frame1->Radiobutton(-text => 'Sorts', -highlightthickness => 0, + -value => 'sorts', -variable => \$order_by) + ->grid(-column => 0, -row => 2, -sticky => 'w'); +$frame1->Radiobutton(-text => 'Loads', -highlightthickness => 0, + -value => 'loads', -variable => \$order_by) + ->grid(-column => 1, -row => 2, -sticky => 'w'); +$frame1->Radiobutton(-text => 'No ordering', -highlightthickness => 0, + -value => '', -variable => \$order_by) + ->grid(-column => 2, -row => 2, -sticky => 'w'); + +my $no_sys = 1; +$frame1->Checkbutton(-text => 'Exclude queries by SYS or SYSTEM', + -variable => \$no_sys, -offvalue => 0, -onvalue => 1, + -highlightthickness => 0) + ->grid(-column => 0, -row => 3, -sticky => 'w', -columnspan => 3); + + +my $user = ''; +$frame1->Label(-text => 'First user to execute statement') + ->grid(-column => 0, -row => 4, -sticky => 'w', -columnspan => 2); +$frame1->Entry(-textvariable => \$user, -width => 30) + ->grid(-column => 2, -row => 4, -sticky => 'w', -columnspan => 2); + +my $pattern = ''; +$frame1->Label(-text => 'SQL matches pattern') + ->grid(-column => 0, -row => 5, -sticky => 'w', -columnspan => 2); +$frame1->Entry(-textvariable => \$pattern, -width => 30) + ->grid(-column => 2, -row => 5, -sticky => 'w', -columnspan => 2); + +my $rows = 100; +$frame1->Label(-text => 'Maximum number of statements') + ->grid(-column => 0, -row => 6, -sticky => 'w', -columnspan => 2); +$frame1->Entry(-textvariable => \$rows, -width => 4) + ->grid(-column => 2, -row => 6, -sticky => 'w', -columnspan => 2); + +$frame1->pack(-fill => 'x'); +$frame->pack(-fill => 'x'); + +### Buttons +$frame = $GrabMain->Frame(-borderwidth => 3, -relief => 'raised'); +my $grab_cb = sub + { + if (! eval { grab($order_by, $no_sys, $user, $pattern, $rows); }) + { error($GrabMain, $@); } + }; +$frame->Button(-text => 'Grab', -command => $grab_cb) + ->pack(-side => 'left', -expand => 1, -pady => 3); +$frame->Button(-text => 'Close', -command => sub { $GrabMain->destroy(); }) + ->pack(-side => 'left', -expand => 1, -pady => 3); +$frame->pack(-fill => 'x'); +#$GrabMain->bind('', sub { $GrabMain = undef; }); +$GrabMain->OnDestroy(sub { $GrabMain = undef; }); +} + +################################################################################ +# Main + +### Main window +$PlanMain = MainWindow->new(); +$PlanMain->title('explain'); + +### Menubar +my $menubar = $PlanMain->Frame(-relief => 'raised', -borderwidth => 2); +$menubar->pack(-fill => 'x'); + +my $menubar_file = $menubar->Menubutton(-text => 'File', -underline => 0); +$menubar_file->command(-label => 'Login ...', -underline => 0, + -command => sub { login_dialog($PlanMain); }); +$menubar_file->command(-label => 'Grab SQL ...', -underline => 0, + -command => sub { grab_main(); }); +$menubar_file->separator(); +$menubar_file->command(-label => 'Open File ...', -underline => 0, + -command => sub { open_dialog($PlanMain); }); +$menubar_file->command(-label => 'Save File ...', -underline => 0, + -command => sub { save_dialog($PlanMain, $PlanSql); }); +$menubar_file->separator(); +$menubar_file->command(-label => 'Exit', -underline => 1, + -command => sub { $Db->disconnect() if ($Db); exit(0); }); +$menubar_file->pack(-side => 'left'); + +### Query plan tree +my $frame; +$frame = $PlanMain->Frame(-borderwidth => 3, -relief => 'raised'); +$PlanTitle = $frame->Label(-text => 'Query Plan')->pack(-anchor => 'nw'); +my $cb = sub { error($PlanMain, $@) if (! eval { disp_plan_step_obj($_[0])}); }; +$PlanTree = $frame->Scrolled('Tree', -height => 15, -width => 80, + -borderwidth => 0, -scrollbars => 'osoe', + -browsecmd => \&disp_plan_step, + -command => $cb, ) + ->pack(-expand => 1, -fill => 'both'); +$frame->pack(-expand => 1, -fill => 'both'); + +### Query plan statement details +$frame = $PlanMain->Frame(-borderwidth => 3, -relief => 'raised'); +$frame->Label(-text => 'Query Step Details')->pack(-anchor => 'nw'); +$PlanStep = $frame->Scrolled('ROText', -height => 10, -width => 80, + -borderwidth => 0, -wrap => 'word', + -setgrid => 'true', -scrollbars => 'oe') + ->pack(-fill => 'x'); +$frame->pack(-fill => 'x'); + +### SQL text editor +$frame = $PlanMain->Frame(-borderwidth => 3, -relief => 'raised'); +$frame->Label(-text => 'SQL Editor')->pack(-anchor => 'nw'); +$PlanSql = $frame->Scrolled('Text', -setgrid => 'true', -scrollbars => 'oe', + -borderwidth => 0, -height => 15, -width => 80, + -wrap => 'word') + ->pack(-expand => 1, -fill => 'both'); +$frame->pack(-expand => 1, -fill => 'both'); + +### Buttons +$frame = $PlanMain->Frame(-borderwidth => 3, -relief => 'raised'); +$frame->Button(-text => 'Explain', -command => \&explain) + ->pack(-side => 'left', -expand => 1, -pady => 3); +$frame->Button(-text => 'Clear', -command => \&clear_editor) + ->pack(-side => 'left', -expand => 1, -pady => 3); +$frame->Button(-text => 'Grab', -command => \&grab_main) + ->pack(-side => 'left', -expand => 1, -pady => 3); +$frame->pack(-fill => 'x'); + +### user/pass@db command-line argument processing +if (@ARGV >= 1 && $ARGV[0] =~ /\w*\/\w*(@\w+)?/) + { + my ($username, $password, $database) = split(/[\/@]/, shift(@ARGV)); + if (! $username) { $username = '/'; $password = ''; } + if (! $database) { $database = $ENV{TWO_TASK} || $ENV{ORACLE_SID}; } + error($PlanMain, $@) if (! eval { login($database, $username, $password); }); + } +else + { + login_dialog($PlanMain); + } + +### SQL filename argument processing +if (@ARGV >= 1 && -r $ARGV[0]) + { + my $file = shift(@ARGV); + if (open_file($file)) + { + $FileDir = dirname($file); + explain() if ($Db); + } + } + +# Doncha just love GUI programming :-) +MainLoop(); + +################################################################################ +SCRIPT + +use Config; + +my $file = __FILE__; $file =~ s/\.PL$//; + +$script =~ s/\~(\w+)\~/$Config{$1}/eg; +if (!(open(FILE, ">$file")) || + !(print FILE $script) || + !(close(FILE))) { + die "Error while writing $file: $!\n"; +} +print "Extracted $file from ",__FILE__," with variable substitutions.\n"; + +# End. From 021d9df8b3f3895ec5651711d61f31405d250718 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Sat, 28 Nov 1998 19:21:29 -0500 Subject: [PATCH 034/637] import DBD-Oracle 0.54_90 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.54_90 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.54_90.tar.gz --- .purify | 11 - MANIFEST | 3 +- Makefile.PL | 95 ++++-- Oracle.pm | 26 +- README | 12 +- Todo | 24 +- dbdimp.c | 842 ++++++++++++++++++++++++---------------------------- dbdimp.h | 115 ++++++- oci7.h | 443 +++++++++++++++++++++++++++ oci8.h | 450 ++++++++++++++++++++++++++++ t/general.t | 9 +- t/plsql.t | 12 +- test.pl | 93 ++++-- 13 files changed, 1578 insertions(+), 557 deletions(-) delete mode 100644 .purify create mode 100644 oci7.h create mode 100644 oci8.h diff --git a/.purify b/.purify deleted file mode 100644 index ef7a6ae0..00000000 --- a/.purify +++ /dev/null @@ -1,11 +0,0 @@ -suppress umr strlen; sosngun -suppress umr "libclntsh.so.1.0" -suppress umr _nsc_trydoorcall; _door_gethostbyname_r; _get_hostserv_inetnetdir_byname; gethostbyname_r; nttbnd2addr -suppress umr process_gethost -suppress umr _get_hostserv_inetnetdir_byname -suppress umr _s_cpaddr; __getsockname; getsockname; nttcni -suppress umr _libc_write; write; nttwr -suppress umr _nsc_trydoorcall; getpwuid_r; sigunmu -suppress umr strlen; sigunmu -suppress umr _nsc_trydoorcall; getpwuid_r; sosngun - diff --git a/MANIFEST b/MANIFEST index 5a461791..7fe0ea9c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -16,6 +16,8 @@ Todo dbdimp.c dbdimp.h hints/svr4.pl +oci7.h +oci8.h ora_explain.PL oraperl.ex/Readme Oraperl examples (copied mostly unchanged from oraperl-2.4) oraperl.ex/bind.pl @@ -31,4 +33,3 @@ t/base.t t/general.t t/plsql.t test.pl -.purify Ignore most of the (many) problems in Oracle's libraries. Very sad. diff --git a/Makefile.PL b/Makefile.PL index e7022fbc..cf9cf1f3 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.68 1998/08/14 18:07:46 timbo Exp $ +# $Id: Makefile.PL,v 1.69 1998/11/29 00:14:07 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -68,8 +68,9 @@ $::opt_s = ''; # Find a symbol in oracle libs, Don't build a Makefile $::opt_S = ''; # Find a symbol in oracle & system libs, Don't build a Makefile $::opt_v = 0; # be more verbose $::opt_d = 0; # much more verbose for debugging +$::opt_8 = 0; # disable use of OCI 8 (where available) -GetOptions(qw(v! d! g! p! l! c! m=s n=s s=s S=s)) +GetOptions(qw(v! d! g! p! l! c! 8! m=s n=s s=s S=s)) or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string @@ -89,7 +90,7 @@ print "\n Configuring DBD::Oracle ...\n my $ORACLE_ENV = ($os eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; -my $OH = $ENV{$ORACLE_ENV}; +my $OH = $ENV{$ORACLE_ENV} || ''; $OH =~ s:\\:/:g if $os eq 'MSWin32'; ($OH = unixify $OH) =~ s:/$:: if $os eq 'VMS'; die "$ORACLE_ENV environment variable must be set.\n" unless $OH; @@ -109,6 +110,7 @@ if ($os ne 'VMS' and $os ne 'MSWin32' and -x "$OH/orainst/inspdver") { $inspdver{RDBMS} = $1 if m/^(\d+\.\d+\.\d+)\S*\s+.*RDBMS/; next unless $::opt_v or m/RDBMS/i or m/PL.SQL/i + or m/Precomp/i or m/Pro\*C/i; print "$_\n"; } @@ -129,6 +131,7 @@ symbol_search() if $::opt_s or $::opt_S; my @mkfiles; my $linkwith; my $linkwith_msg; +my $need_ldlp_env; if ($os eq 'VMS') { my $OCIINCLUDE = vmsify("$OH/rdbms/") ." ". vmsify("$OH/rdbms/demo/oci_demo/"); @@ -162,7 +165,7 @@ elsif ($os eq 'MSWin32') { my $OCIINCLUDE = "-I$OH/$OCIDIR/include -I$OH/rdbms/demo"; $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/$oci_compiler_dir OCIW32" ]; - $opts{SKIP} = ['processPL']; # XXX added because it caused problems with Nmake... + #$opts{SKIP} = ['processPL']; # XXX added because it caused problems with Nmake... $opts{INC} = "$OCIINCLUDE -I$dbi_arch_dir"; } @@ -266,18 +269,20 @@ if ($os eq 'hpux') { if ($os eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { print "Warning: You may need to rebuild perl using the xlc_r compiler.\a\n"; print " You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV\n"; + sleep 4; } -$opts{DEFINE} .= '-Wall -Wno-comment' if $Config{cc} eq 'gcc'; +$opts{DEFINE} .= ' -Wall -Wno-comment' if $Config{cc} eq 'gcc'; + +$opts{DEFINE} .= ' -Xa' if $Config{cc} eq 'clcc'; # CenterLine CC -$opts{DEFINE} .= '-Xa' if $Config{cc} eq 'clcc'; # CenterLine CC +$opts{DEFINE} .= ' -DNO_OCI8' if $::opt_8; print "WARNING: Your GNU C compiler is very old. Please upgrade.\n" if ($Config{gccversion} and $Config{gccversion} =~ m/^(1|2\.[1-5])/); # Set some private WriteMakefile options if this is 'me' :-) -if ($ENV{LOGNAME} eq 'timbo' and $ENV{S_ARCH_SW}){ # a reasonable guess - $Verbose = 1; +if ($ENV{S_ARCH_SW} && $ENV{LOGNAME} eq 'timbo'){ # a reasonable guess $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith -pedantic -Wtraditional' . ' -Wbad-function-cast -Wcast-qual' if $Config{cc} eq 'gcc'; $::opt_g = '-g'; @@ -302,13 +307,13 @@ print "Oracle makefiles would have used these values but we override them:\n" if $MK{CFLAGS} || $MK{LDFLAGS} || $MK{LDSTRING}; print " CC: $MK{CC}\n" if $MK{CC}; print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; -print " [".mkvar('CFLAGS',1,0,0). "]\n" if $MK{CFLAGS}; +print " [".mkvar('CFLAGS',0,1,0). "]\n" if $MK{CFLAGS}; print " CLIBS: $MK{CLIBS}\n" if $MK{CLIBS}; -print " [".mkvar('CLIBS',1,0,0). "]\n" if $MK{CLIBS}; +print " [".mkvar('CLIBS',0,1,0). "]\n" if $MK{CLIBS}; print " LDFLAGS: $MK{LDFLAGS}\n" if $MK{LDFLAGS}; -print " [".mkvar('LDFLAGS',1,0,0). "]\n" if $MK{LDFLAGS}; +print " [".mkvar('LDFLAGS',0,1,0). "]\n" if $MK{LDFLAGS}; print " LDSTRING: $MK{LDSTRING}\n" if $MK{LDSTRING}; -print " [".mkvar('LDSTRING',1,0,0)."]\n" if $MK{LDSTRING}; +print " [".mkvar('LDSTRING',0,1,0)."]\n" if $MK{LDSTRING}; print "\nLinking with $linkwith_msg\n" if $linkwith_msg; print "\n"; @@ -357,6 +362,10 @@ your 'privlib' and 'archlib' directories and their auto subdirectories. } } + print "\nNote: \$ORACLE_HOME/lib must be added to your $need_ldlp_env environment variable\n", + "before running \"make test\" and whenever DBD::Oracle is used.\n\n" + if $need_ldlp_env && ($ENV{$need_ldlp_env}||'') !~ m:\Q$OH/lib\b:; + # Ensure Oraperl.pm and oraperl.ph are installed into top lib dir $self->{PM}->{'Oraperl.pm'} = '$(INST_LIB)/Oraperl.pm'; $self->{PM}->{'oraperl.ph'} = '$(INST_LIB)/oraperl.ph'; @@ -400,7 +409,7 @@ sub find_mkfile { 'rdbms/demo/oracle.mk', 'rdbms/demo/demo_rdbms.mk', ); - my @mkplaces = ($::opt_p) ? @mk_proc : @mk_oci; + my @mkplaces = ($::opt_p) ? (@mk_proc,@mk_oci) : (@mk_oci,@mk_proc); if ($::opt_m) { $::opt_m = cwd()."/$::opt_m" unless $::opt_m =~ m:^/:; die "-m $::opt_m: not found" unless -f $::opt_m; @@ -408,20 +417,16 @@ sub find_mkfile { } my ($mkfile, $place); foreach $place (@mkplaces) { - $place = "$OH/$place" unless $place =~ m:^[/\.]:; # abs or relative path + $place = "$OH/$place" + unless $place =~ m:^[/\.]:; # abs or relative path next unless -f $place; push @mkfiles, $place; print "Found $place\n"; } $mkfile = $mkfiles[0]; # use first one found - if (!$mkfile and "@mkplaces" !~ m/oracle\.mk/) { - print "Unable to locate a Pro*C *.mk. Falling back to oracle.mk.\n"; - $mkfile = "$OH/oracle.mk"; - push @mkplaces, $mkfile; # just for error message below - } die qq{ - Unable to locate an oracle.mk or proc.mk file in your Oracle installation. - (Looked in @mkplaces) + Unable to locate an oracle.mk, proc.mk or other suitable file + in your Oracle installation. (I looked in @mkplaces) The oracle.mk file is part of the Oracle RDBMS product. The proc.mk file is part of the Oracle Pro*C product. You need to @@ -449,11 +454,18 @@ sub fetch_oci_macros { # Don't include the following definitions in the generated # makefile (note that %MK stills gets these values). my @edit = qw( - SHELL CC CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS - AR ECHO EXE OBJS PERL OBJ_EXT LIB_EXT + SHELL CC CPP CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS + AR AS CHMOD ECHO EXE OBJS PERL OBJ_EXT LIB_EXT ); my %edit; @edit{@edit} = ('$_ = ""') x @edit; + $edit{ORA_NLS} = $edit{ORA_NLS33} = q{ + print "Deleting $_\n", + "because it is not already set in the environment\n", + "and it can cause ORA-01019 errors.\n"; + $_ = ''; + } unless $ENV{ORA_NLS} || $ENV{ORA_NLS33}; + $edit{COMPOBJS} = q{ # Firstly a Solaris specific edit: $_ = del_crtobj($_) if $os eq 'solaris'; @@ -540,6 +552,11 @@ sub fetch_oci_macros { else { $linkvia .= '$(SSDBED) ' if $MK{SSDBED}; $linkvia .= '$(DEF_OPT) ' if $MK{DEF_OPT}; + if ($inspdver{RDBMS} =~ /^8\.0\./ and $os eq 'dec_osf' and $osvers >= 4.0) { + $linkvia .= '$(SCOREPT) $(NAETAB) $(NAEDHS) $(LLIBRDBMS_CLT) $(LLIBMM) '; + $linkvia .= '$(NETLIBS) $(CORELIBS) $(LLIBCOMMON) $(LLIBEPC) '; + $need_ldlp_env = "LD_LIBRARY_PATH"; + } $linkvia .= '$(OCISHAREDLIBS)'; } } @@ -746,7 +763,7 @@ ORACLE_HOME = '.$OH.' sub const_cccmd { - my($self) = shift; + my ($self) = shift; print "Using DBD::Oracle $self->{VERSION}.\n"; local($_) = $self->SUPER::const_cccmd(@_); @@ -757,8 +774,24 @@ ORACLE_HOME = '.$OH.' } # are we using the non-bundled hpux compiler? if ($os eq "hpux" and $Config::Config{ccflags} =~ /-Aa\b/) { - print "Changing -Aa to -Ae for HP-UX.\n"; - s/-Aa\b/-Ae/g; # allow "long long" in oratypes.h + print "Changing -Aa to -Ae for HP-UX in ccmd.\n" + if s/-Aa\b/-Ae/g; # allow "long long" in oratypes.h + } + $_; + } + + sub cflags { + my ($self) = shift; + local($_) = $self->SUPER::cflags(@_); + # If perl Makefile.PL *-g* then switch on debugging + if ($::opt_g) { + s/\s-O\d?\b//; # delete optimise option + s/\s-/ -g -/; # add -g option + } + # are we using the non-bundled hpux compiler? + if ($os eq "hpux" and $Config::Config{ccflags} =~ /-Aa\b/) { + print "Changing -Aa to -Ae for HP-UX in cflags.\n" + if s/-Aa\b/-Ae/g; # allow "long long" in oratypes.h } $_; } @@ -777,12 +810,22 @@ ORACLE_HOME = '.$OH.' my @m; push @m, "OTHERLDFLAGS = $otherldflags\n"; push @m, "INST_DYNAMIC_DEP = $inst_dynamic_dep\n"; + if ($] < 5.00450) { push @m, ' $(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt rtls.opt $(INST_ARCHAUTODIR).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) $(NOECHO) If F$TrnLNm("PerlShr").eqs."" Then Define/NoLog/User PerlShr Sys$Share:PerlShr.',$Config::Config{'dlext'},' Lnproc $(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,rtls.opt/Option,$(PERL_INC)perlshr_attr.opt/Option i '; + } else { + push @m, ' +$(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt $(INST_ARCHAUTODIR).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) If F$TrnLNm("PerlShr").eqs."" Then Define/NoLog/User PerlShr Sys$Share:PerlShr.',$Config::Config{'dlext'},' + Lnproc $(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,$(PERL_INC)perlshr_attr.opt/Option i +'; + + } push @m, $self->dir_target('$(INST_ARCHAUTODIR)'); join('',@m); } diff --git a/Oracle.pm b/Oracle.pm index 462cf515..b3e2a5ce 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,7 +1,7 @@ -# $Id: Oracle.pm,v 1.57 1998/08/14 18:23:00 timbo Exp $ +# $Id: Oracle.pm,v 1.58 1998/11/29 00:14:07 timbo Exp $ # -# Copyright (c) 1994,1995,1996,1997 Tim Bunce +# Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce # # You may distribute under the terms of either the GNU General Public # License or the Artistic License, as specified in the Perl README file, @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.54'; +$DBD::Oracle::VERSION = '0.54_90'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -22,7 +22,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; use Exporter (); @ISA = qw(DynaLoader Exporter); - my $Revision = substr(q$Revision: 1.57 $, 10); + my $Revision = substr(q$Revision: 1.58 $, 10); require_version DBI 0.92; @@ -157,7 +157,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; if (exists $dbnames{$dbname}) { # known name my $dbhome = $dbnames{$dbname}; # local=>ENV, remote=>0 if ($dbhome) { - warn "Changing $ORACLE_ENV for $dbname to $dbhome" + warn "Changing $ORACLE_ENV for $dbname to $dbhome (to match oratab entry)" if ($ENV{$ORACLE_ENV} and $dbhome ne $ENV{$ORACLE_ENV}); $ENV{ORACLE_SID} = $dbname; $ENV{$ORACLE_ENV} = $dbhome; @@ -218,9 +218,11 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; sub ping { my($dbh) = @_; - # we know that DBD::Oracle prepare does a describe so this will + # we know that Oracle 7 prepare does a describe so this will # actually talk to the server and is this a valid and cheap test. - return 1 if $dbh->prepare("select SYSDATE from DUAL"); + my $sth = $dbh->prepare("select SYSDATE from DUAL"); + # But Oracle 8 doesn't talk to server unless we describe the query + return 1 if $sth && $sth->{NUM_OF_FIELDS}; return 0; } @@ -756,6 +758,14 @@ You can find more examples in the t/plsql.t file in the DBD::Oracle source directory. +=head1 Oracle on Linix + +To join the oracle-on-linux mailing list, see: + + http://www.datamgmt.com/maillist.html + http://www.eGroups.com/list/oracle-on-linux + mailto:oracle-on-linux-subscribe@egroups.com + =head1 Commercial Oracle Tools Assorted tools and references for general information. No recommendation implied. @@ -764,6 +774,8 @@ PL/Vision from RevealNet and Steven Feuerstein. Platinum Technology: http://www.platinum.com/products/oracle.htm +SoftTree Technologies: http://www.SoftTreeTech.com + "Q" from Savant Corporation. http://www.databasegroup.com diff --git a/README b/README index e75ce620..99f95d5a 100644 --- a/README +++ b/README @@ -17,6 +17,11 @@ WARNING: because the interface (api) is not finalised. The Alpha status does not reflect code quality or stability. + NEWS: The new enhanced Oracle 8 OCI is now supported by DBD::Oracle + versions above 0.54. If the new code causes you problems you can + build DBD::Oracle for Oracle 8 to use the Oracle 7 OCI by doing: + perl Makefile.PL -8 + | NOTE: | The only currently supported interface is via Oraperl.pm, the | | oraperl emulation layer. This is fairly complete and stable. | @@ -69,7 +74,7 @@ the database using an Oracle tool such as sqlplus. Once you can do that then you can test DBD::Oracle knowing that it should work. The supplied test will connect to the database using the value of the -ORACLE_USER environment variable so you should set that to the correct +ORACLE_USERID environment variable so you should set that to the correct value before starting the test. Please read README.login. make test @@ -89,6 +94,11 @@ If it helps then please let me know (and please include a copy of the log from the failed default build, the log from the build that worked, plus the output of the "perl -V" command). +The new enhanced Oracle 8 OCI is now supported by DBD::Oracle versions +above 0.54. If the new code causes you problems you can build +DBD::Oracle for Oracle 8 to use the Oracle 7 OCI API by doing: + perl Makefile.PL -8 + Do not hand edit the generated Makefile unless you are completely sure you understand the implications! Always try to make changes via the Makefile.PL command line and/or editing the Makefile.PL. diff --git a/Todo b/Todo index ababd7c5..2e0df965 100644 --- a/Todo +++ b/Todo @@ -1,4 +1,16 @@ -Oracle 8 +Oracle 8 esp *LOBS + +SCALE, PRECISION + +prepare("insert .. into ... RETURNING foo INTO :bar") + +bind_param(... { TYPE => SQL_* }) esp SQL_LONGVARCHAR etc + +use DBD::Oracle qw(:ora_types); + +$sth = $dbh->prepare("select ... for update"); +$dbh->commit; +$sth->execute; # fails ? auto-re-prepare? Fetch: If LongReadLen > 64k then automatocally call oflng for each long LONG. Bind: Automatically do piecewise insert of longs. @@ -8,10 +20,6 @@ $drh->debug oddities (re data_source debugging) ora_bind() failed err = ORA-01026: multiple buffers of size > 4000 in the bind list (DBD: oexec error) -bind_param(... { TYPE => SQL_* }) - -Can't bind unknown placeholder '3' at ... - DBI::st=HASH(0x5b5c2c) debug level set to 2 ... (add perl version number and other info here). @@ -19,7 +27,7 @@ http://outside.organic.com/mail-archives/dbi-users/Nov1997/0116.html Test LongReadLen and especially the default behaviour of LongTruncOk -Add explain to dist +Add/update explain to dist Handle binding of values > 32K long. @@ -32,3 +40,7 @@ Non-blocking Tests RAW types at max length +http://www.oracle-users.com/html/freeware.html + +http://freespace.virgin.net/j.hatcher/ociwrap.htm + diff --git a/dbdimp.c b/dbdimp.c index 5dc49626..c29d7a85 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,7 +1,7 @@ /* - $Id: dbdimp.c,v 1.40 1998/08/14 18:07:46 timbo Exp $ + $Id: dbdimp.c,v 1.41 1998/11/29 00:14:07 timbo Exp $ - Copyright (c) 1994,1995 Tim Bunce + Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file, @@ -12,11 +12,20 @@ #include "Oracle.h" +#if !defined(dirty) && !defined(PL_dirty) +#define PL_dirty dirty +#endif + /* XXX DBI should provide a better version of this */ #define IS_DBI_HANDLE(h) \ (SvROK(h) && SvTYPE(SvRV(h)) == SVt_PVHV && \ SvRMAGICAL(SvRV(h)) && (SvMAGIC(SvRV(h)))->mg_type == 'P') +#define OCIAttrGet_stmhp(imp_sth, p, l, a) \ + OCIAttrGet(imp_sth->stmhp, OCI_HTYPE_STMT, (dvoid*)(p), (l), (a), imp_sth->errhp); +#define OCIAttrGet_parmdp(imp_sth, parmdp, p, l, a) \ + OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (dvoid*)(p), (l), (a), imp_sth->errhp); + DBISTATE_DECLARE; static SV *ora_long; @@ -27,8 +36,11 @@ static SV *ora_cache_o; /* temp hack for ora_open() cache override */ static int ora_login_nomsg; /* don't fetch real login errmsg if true */ static int ora_fetchtest; static int ora_sigchld_restart = 1; +static int set_sigint_handler = 0; static void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); +static int ora2sql_type _((int oratype)); +static int calc_cache_rows _((int f, int ew, int cr, int hl)); void @@ -60,7 +72,7 @@ dbd_discon_all(drh, imp_drh) dTHR; /* The disconnect_all concept is flawed and needs more work */ - if (!dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { + if (!PL_dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { sv_setiv(DBIc_ERR(imp_drh), (IV)1); sv_setpv(DBIc_ERRSTR(imp_drh), (char*)"disconnect_all not implemented"); @@ -74,46 +86,6 @@ dbd_discon_all(drh, imp_drh) } -/* Database specific error handling. - This will be split up into specific routines - for dbh and sth level. - Also split into helper routine to set number & string. - Err, many changes needed, ramble ... -*/ - -static void -ora_error(h, lda, rc, what) - SV *h; - Lda_Def *lda; - sb2 rc; - char *what; -{ - D_imp_xxh(h); - SV *errstr = DBIc_ERRSTR(imp_xxh); - sv_setiv(DBIc_ERR(imp_xxh), (IV)rc); /* set err early */ - if (lda) { /* is oracle error (allow for non-oracle errors) */ - int len; - char msg[1024]; - /* Oracle oerhms can do duplicate free if connect fails. */ - /* Ignore 'with different width due to prototype' gcc warning */ - oerhms(lda, rc, (text*)msg, sizeof(msg)); /* may hang! */ - len = strlen(msg); - if (len && msg[len-1] == '\n') - msg[len-1] = '\0'; /* trim off \n from end of message */ - sv_setpv(errstr, (char*)msg); - } - else sv_setpv(errstr, what); - if (what && lda) { - sv_catpv(errstr, " (DBD: "); - sv_catpv(errstr, what); - sv_catpv(errstr, ")"); - } - DBIh_EVENT2(h, ERROR_event, DBIc_ERR(imp_xxh), errstr); - if (dbis->debug >= 2) - fprintf(DBILOGFP, "%s error %d recorded: %s\n", - what, rc, SvPV(errstr,na)); -} - static void fbh_dump(fbh, i, aidx) @@ -122,14 +94,16 @@ fbh_dump(fbh, i, aidx) int aidx; /* array index */ { FILE *fp = DBILOGFP; - fprintf(fp, " fbh %d: '%s' %s, ", - i, fbh->cbuf, (fbh->nullok) ? "NULLable" : ""); - fprintf(fp, "type %d, dbsize %ld, dsize %ld, p%d s%d\n", - fbh->dbtype, (long)fbh->dbsize, (long)fbh->dsize, + fprintf(fp, " fbh %d: '%s'\t%s, ", + i, fbh->name, (fbh->nullok) ? "NULLable" : ""); + fprintf(fp, "type %3d->%2d, dbsize %ld/%ld, p%d s%d\n", + fbh->dbtype, fbh->ftype, (long)fbh->dbsize,(long)fbh->disize, fbh->prec, fbh->scale); - fprintf(fp, " out: ftype %d, bufl %d. cache@%d: indp %d, rlen %d, rcode %d\n", - fbh->ftype, fbh->fb_ary->bufl, aidx, fbh->fb_ary->aindp[aidx], + if (fbh->fb_ary) { + fprintf(fp, " out: ftype %d, bufl %d. indp %d, rlen %d, rcode %d\n", + fbh->ftype, fbh->fb_ary->bufl, fbh->fb_ary->aindp[aidx], fbh->fb_ary->arlen[aidx], fbh->fb_ary->arcode[aidx]); + } } @@ -202,6 +176,15 @@ fb_ary_t *fb_ary; } +/* ================================================================== */ + + +#ifdef OCI_V8_SYNTAX +#include "oci8.h" +#else +#include "oci7.h" +#endif + /* ================================================================== */ @@ -213,10 +196,74 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) char *uid; char *pwd; { - dTHR; int ret; +#ifdef OCI_V8_SYNTAX + D_imp_drh_from_dbh; + + if (!imp_drh->envhp) { + OCIInitialize((ub4) OCI_DEFAULT, 0, 0,0,0); + ret = OCIEnvInit( &imp_drh->envhp, OCI_DEFAULT, 0, 0 ); + } + imp_dbh->envhp = imp_drh->envhp; + + OCIHandleAlloc(imp_dbh->envhp, (dvoid**)&imp_dbh->errhp, OCI_HTYPE_ERROR, 0,0); + OCIHandleAlloc(imp_dbh->envhp, (dvoid**)&imp_dbh->srvhp, OCI_HTYPE_SERVER,0,0); + + /* OCI 8 does not seem to allow uid to be "name/pass" :-( */ + /* so we have to split it up ourselves */ + if (strlen(pwd)==0 && strchr(uid,'/')) { + SV *tmpsv = sv_2mortal(newSVpv(uid,0)); + uid = SvPVX(tmpsv); + pwd = strchr(uid, '/'); + *pwd++ = '\0'; + /* XXX look for '@', e.g. "u/p@d" and "u@d" and maybe "@d" */ + } + + ret=OCIServerAttach(imp_dbh->srvhp, imp_dbh->errhp, + dbname, strlen(dbname), 0); + if (ret != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, ret, "OCIServerAttach"); + OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); + OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); + return 0; + } + + OCIHandleAlloc(imp_dbh->envhp, (dvoid**)&imp_dbh->svchp, OCI_HTYPE_SVCCTX,0,0); + OCIAttrSet( imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, + (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp); + + OCIHandleAlloc(imp_dbh->envhp, (dvoid **)&imp_dbh->authp, + (ub4) OCI_HTYPE_SESSION, 0,0); + OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, + uid, strlen(uid), + (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp); + OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, + (strlen(pwd)) ? pwd : NULL, strlen(pwd), + (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp); + + ret=OCISessionBegin( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, + OCI_CRED_RDBMS, (ub4) OCI_DEFAULT); + if (ret != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, ret, "OCISessionBegin"); + OCIServerDetach(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT ); + OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); + OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); + OCIHandleFree(imp_dbh->svchp, OCI_HTYPE_SVCCTX); + return 0; + } + + OCIAttrSet(imp_dbh->svchp, (ub4) OCI_HTYPE_SVCCTX, + imp_dbh->authp, (ub4) 0, + (ub4) OCI_ATTR_SESSION, imp_dbh->errhp); + +/* XXX to be removed */ + imp_dbh->lda = &imp_dbh->ldabuf; + OCISvcCtxToLda( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->lda); + OCILdaToSvcCtx(&imp_dbh->svchp, imp_dbh->errhp, imp_dbh->lda); + +#else imp_dbh->lda = &imp_dbh->ldabuf; imp_dbh->hda = &imp_dbh->hdabuf[0]; /* can give duplicate free errors (from Oracle) if connect fails */ @@ -245,6 +292,22 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) return 0; } + if (!set_sigint_handler) { + set_sigint_handler = 1; + /* perl's sign handler is sighandler */ + /* osnsui(??, sighandler, NULL?) */ + /* OCI8: osnsui(word *handlp, void (*astp), char * ctx) + ** osnsui: Operating System dependent Network Set User-side + ** Interrupt. Add an interrupt handling procedure astp. + ** Whenever a user interrupt(such as a ^C) occurs, call astp + ** with argument ctx. Put in *handlp handle for this + ** handler so that it may be cleared with osncui. + ** Note that there may be many handlers; each should + ** be cleared using osncui. An error code is + ** returned if an error occurs. + */ + } + #ifdef SA_RESTART #ifndef SIGCLD #define SIGCLD SIGCHLD @@ -267,7 +330,9 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) fprintf(DBILOGFP, " dbd_db_login: set SA_RESTART on Oracle SIGCLD handler.\n"); } } -#endif /* HAS_SIGACTION */ +#endif /* HAS_SIGACTION */ + +#endif /* OCI_V8_SYNTAX */ DBIc_IMPSET_on(imp_dbh); /* imp_dbh set up now */ DBIc_ACTIVE_on(imp_dbh); /* call disconnect before freeing */ @@ -280,8 +345,14 @@ dbd_db_commit(dbh, imp_dbh) SV *dbh; imp_dbh_t *imp_dbh; { +#ifdef OCI_V8_SYNTAX + sword status = OCITransCommit(imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCITransCommit"); +#else if (ocom(imp_dbh->lda)) { ora_error(dbh, imp_dbh->lda, imp_dbh->lda->rc, "commit failed"); +#endif return 0; } return 1; @@ -292,8 +363,14 @@ dbd_db_rollback(dbh, imp_dbh) SV *dbh; imp_dbh_t *imp_dbh; { +#ifdef OCI_V8_SYNTAX + sword status = OCITransRollback(imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCITransRollback"); +#else if (orol(imp_dbh->lda)) { ora_error(dbh, imp_dbh->lda, imp_dbh->lda->rc, "rollback failed"); +#endif return 0; } return 1; @@ -310,10 +387,30 @@ dbd_db_disconnect(dbh, imp_dbh) /* We assume that disconnect will always work */ /* since most errors imply already disconnected. */ DBIc_ACTIVE_off(imp_dbh); + + /* Oracle will commit on an orderly disconnect. */ + /* See DBI Driver.xst file for the DBI approach. */ + +#ifdef OCI_V8_SYNTAX + { + sword s_se = OCISessionEnd( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, OCI_DEFAULT); + sword s_sd = OCIServerDetach(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT ); + if (s_se) + oci_error(dbh, imp_dbh->errhp, s_se, "OCISessionEnd"); + if (s_sd) + oci_error(dbh, imp_dbh->errhp, s_sd, "OCIServerDetach"); + OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); + OCIHandleFree(imp_dbh->svchp, OCI_HTYPE_SVCCTX); + OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); + if (s_se || s_sd) + return 0; + } +#else if (ologof(imp_dbh->lda)) { ora_error(dbh, imp_dbh->lda, imp_dbh->lda->rc, "disconnect error"); return 0; } +#endif /* We don't free imp_dbh since a reference still exists */ /* The DESTROY method is the only one to 'free' memory. */ /* Note that statement objects may still exists for this dbh! */ @@ -346,13 +443,19 @@ dbd_db_STORE_attrib(dbh, imp_dbh, keysv, valuesv) int on = SvTRUE(valuesv); if (kl==10 && strEQ(key, "AutoCommit")) { +#ifndef OCI_V8_SYNTAX if ( (on) ? ocon(imp_dbh->lda) : ocof(imp_dbh->lda) ) { ora_error(dbh, imp_dbh->lda, imp_dbh->lda->rc, "ocon/ocof failed"); /* XXX um, we can't return FALSE and true isn't acurate so we croak */ croak(SvPV(DBIc_ERRSTR(imp_dbh),na)); } +#endif /* OCI V8 handles this as OCIExecuteStmt */ DBIc_set(imp_dbh,DBIcf_AutoCommit, on); - } else { + } + else if (kl==12 && strEQ(key, "RowCacheSize")) { + imp_dbh->RowCacheSize = SvIV(valuesv); + } + else { return FALSE; } if (cachesv) /* cache value for later DBI 'quick' fetch? */ @@ -378,6 +481,9 @@ dbd_db_FETCH_attrib(dbh, imp_dbh, keysv) if (kl==10 && strEQ(key, "AutoCommit")) { retsv = boolSV(DBIc_has(imp_dbh,DBIcf_AutoCommit)); } + else if (kl==12 && strEQ(key, "RowCacheSize")) { + retsv = newSViv(imp_dbh->RowCacheSize); + } if (!retsv) return Nullsv; if (cacheit) { /* cache for next time (via DBI quick_FETCH) */ @@ -395,42 +501,6 @@ dbd_db_FETCH_attrib(dbh, imp_dbh, keysv) /* ================================================================== */ -static int -get_cursor(imp_dbh, sth, imp_sth) - imp_dbh_t *imp_dbh; - SV *sth; - imp_sth_t *imp_sth; -{ - if (oopen(&imp_sth->cdabuf, imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { - ora_error(sth, &imp_sth->cdabuf, imp_sth->cdabuf.rc, "oopen error"); - return 0; - } - imp_sth->cda = &imp_sth->cdabuf; - return 1; -} - -static int -free_cursor(sth, imp_sth) - SV *sth; - imp_sth_t *imp_sth; -{ - if (!imp_sth->cda) - return 0; - - if (DBIc_ACTIVE(imp_sth)) /* should never happen here */ - ocan(imp_sth->cda); /* XXX probably not needed before oclose */ - - if (oclose(imp_sth->cda)) { /* close the cursor */ - /* Check for ORA-01041: 'hostdef extension doesn't exist' ? XXX */ - /* which indicates that the lda had already been logged out */ - /* in which case only complain if not in 'global destruction'? */ - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oclose error"); - return 0; - } - imp_sth->cda = NULL; - return 1; -} - int dbd_st_prepare(sth, imp_sth, statement, attribs) @@ -440,8 +510,10 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) SV *attribs; { D_imp_dbh_from_sth; - sword oparse_defer = 0; /* PARSE_NO_DEFER */ ub4 oparse_lng = 1; /* auto v6 or v7 as suits db connected to */ +#ifdef OCI_V8_SYNTAX + sword status = 0; +#endif imp_sth->done_desc = 0; @@ -452,22 +524,49 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) if (attribs) { SV **svp; DBD_ATTRIB_GET_IV( attribs, "ora_parse_lang", 14, svp, oparse_lng); - DBD_ATTRIB_GET_BOOL(attribs, "ora_parse_defer",15, svp, oparse_defer); - } - - if (!get_cursor(imp_dbh, sth, imp_sth)) { - return 0; } /* scan statement for '?', ':1' and/or ':foo' style placeholders */ dbd_preparse(imp_sth, statement); +#ifdef OCI_V8_SYNTAX + + imp_sth->errhp = imp_dbh->errhp; + imp_sth->srvhp = imp_dbh->srvhp; + imp_sth->svchp = imp_dbh->svchp; + + switch(oparse_lng) { + case 0: /* old: calls for V6 syntax - give them V7 */ + case 2: /* old: calls for V7 syntax */ + case 7: oparse_lng = OCI_V7_SYNTAX; break; + case 8: oparse_lng = OCI_V8_SYNTAX; break; + default: oparse_lng = OCI_NTV_SYNTAX; break; + } + + OCIHandleAlloc(imp_dbh->envhp, (dvoid**)&imp_sth->stmhp, OCI_HTYPE_STMT, 0,0); + status = OCIStmtPrepare(imp_sth->stmhp, imp_sth->errhp, + imp_sth->statement, (ub4)strlen(imp_sth->statement), + oparse_lng, OCI_DEFAULT); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIStmtPrepare"); + OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); + return 0; + } + + OCIAttrGet_stmhp(imp_sth, &imp_sth->stmt_type, 0, OCI_ATTR_STMT_TYPE); + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_st_prepare'd sql %s\n", + oci_stmt_type_name(imp_sth->stmt_type)); + +#else + + if (!get_cursor(imp_dbh, sth, imp_sth)) + return 0; + /* parse the (possibly edited) SQL statement */ - /* Note that (if oparse_defer=0, the default) Data Definition */ - /* statements will be executed at once. This is a major pain! */ imp_sth->cda->peo = 0; if (oparse(imp_sth->cda, (text*)imp_sth->statement, (sb4)-1, - (sword)oparse_defer, (ub4)oparse_lng) + (sword)0/*oparse_defer*/, (ub4)oparse_lng) ) { char buf[99]; char *hint = ""; @@ -486,12 +585,6 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) free_cursor(sth, imp_sth); return 0; } - - /* detect warning for pl/sql create errors */ - if (imp_sth->cda->wrn & 32) { - ; /* XXX perl_call_method to get error text ? */ - } - if (dbis->debug >= 2) fprintf(DBILOGFP, " dbd_st_prepare'd sql f%d\n", imp_sth->cda->ft); @@ -499,6 +592,8 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) if (!dbd_describe(sth, imp_sth)) { return 0; } +#endif + DBIc_IMPSET_on(imp_sth); return 1; } @@ -524,6 +619,8 @@ dbd_preparse(imp_sth, statement) /* initialise phs ready to be cloned per placeholder */ memset(&phs_tpl, 0, sizeof(phs_tpl)); phs_tpl.ftype = 1; /* VARCHAR2 */ + phs_tpl.aryelem_max = 0; + phs_tpl.aryelem_cur = 1; src = statement; dest = imp_sth->statement; @@ -579,110 +676,10 @@ dbd_preparse(imp_sth, statement) } - -int -dbd_describe(h, imp_sth) - SV *h; - imp_sth_t *imp_sth; +static int +calc_cache_rows(num_fields, est_width, cache_rows, has_longs) + int num_fields, est_width, cache_rows, has_longs; { - static sb4 *f_cbufl; /* XXX not thread safe */ - static U32 f_cbufl_max; - - I32 long_buflen; - sb1 *cbuf_ptr; - int t_cbufl=0; - I32 num_fields; - int has_longs = 0; - int est_width = 0; /* estimated avg row width (for cache) */ - int i = 0; - - - if (imp_sth->done_desc) - return 1; /* success, already done it */ - imp_sth->done_desc = 1; - - /* ora_trunc is checked at fetch time */ - /* long_buflen: length for long/longraw (if >0), else 80 (ora app dflt) */ - /* Ought to be for COMPAT mode only but was relaxed before LongReadLen existed */ - long_buflen = (SvOK(ora_long) && SvIV(ora_long)>0) - ? SvIV(ora_long) : DBIc_LongReadLen(imp_sth); - if (long_buflen < 0) /* trap any sillyness */ - long_buflen = 80; /* typical oracle app default */ - - if (imp_sth->cda->ft != FT_SELECT) { - if (dbis->debug >= 2) - fprintf(DBILOGFP, - " dbd_describe skipped for non-select (sql f%d, lb %ld, csr 0x%lx)\n", - imp_sth->cda->ft, (long)long_buflen, (long)imp_sth->cda); - /* imp_sth memory was cleared when created so no setup required here */ - return 1; - } - - if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_describe (for sql f%d after oci f%d, lb %ld, csr 0x%lx)...\n", - imp_sth->cda->ft, imp_sth->cda->fc, (long)long_buflen, (long)imp_sth->cda); - - if (!f_cbufl) { - f_cbufl_max = 120; - New(1, f_cbufl, f_cbufl_max, sb4); - } - - /* number of rows to cache */ - if (SvOK(ora_cache_o)) imp_sth->cache_rows = SvIV(ora_cache_o); - else if (SvOK(ora_cache)) imp_sth->cache_rows = SvIV(ora_cache); - else imp_sth->cache_rows = 0; /* auto size */ - - /* Get number of fields and space needed for field names */ - while(++i) { /* break out within loop */ - sb1 cbuf[257]; /* generous max column name length */ - sb2 dbtype = 0; /* workaround for Oracle bug #405032 */ - sb4 dbsize; - if (i >= f_cbufl_max) { - f_cbufl_max *= 2; - Renew(f_cbufl, f_cbufl_max, sb4); - } - f_cbufl[i] = sizeof(cbuf); - odescr(imp_sth->cda, i, &dbsize, &dbtype, - cbuf, &f_cbufl[i], (sb4*)0, (sb2*)0, (sb2*)0, (sb2*)0); - if (imp_sth->cda->rc || dbtype == 0) - break; - t_cbufl += f_cbufl[i]; - - /* now we calculate the approx average on-the-wire width of */ - /* each field (and thus row) to determine a 'good' cache size. */ - if (imp_sth->cache_rows > 0) - continue; /* no need, user specified a size */ - if (dbsize==0) { /* is a LONG type or 'select NULL' */ - if (dbtype_is_long(dbtype)) { - est_width += long_buflen; - ++has_longs; /* hint to auto cache sizing code */ - } - } - else /* deal with dbtypes with overblown dbsizes */ - switch(dbtype) { - case 1: /* VARCHAR2 - result of to_char() has dbsize==75 */ - /* for all but small strings we take off 25% */ - est_width += (dbsize < 32) ? dbsize : dbsize-(dbsize>>2); - break; - case 2: /* NUMBER - e.g., from a sum() or max(), dbsize==22 */ - /* Most numbers are _much_ smaller than 22 bytes */ - est_width += 4; /* > approx +/- 1_000_000 ? */ - break; - default: est_width += dbsize; - break; - } - } - if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { - D_imp_dbh_from_sth; - ora_error(h, imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); - return 0; - } - imp_sth->cda->rc = 0; - num_fields = i - 1; - DBIc_NUM_FIELDS(imp_sth) = num_fields; - - /* --- Setup the row cache for this query --- */ - /* Use guessed average on-the-wire row width calculated above */ /* and add in overhead of 5 bytes per field plus 8 bytes per row. */ /* The n*5+8 was determined by studying SQL*Net v2 packets. */ @@ -690,13 +687,13 @@ dbd_describe(h, imp_sth) est_width += num_fields*5 + 8; if (has_longs) /* override/disable caching */ - imp_sth->cache_rows = 1; /* else read_blob can't work */ + cache_rows = 1; /* else read_blob can't work */ - else if (imp_sth->cache_rows < 1) { /* automatically size the cache */ + else if (cache_rows < 1) { /* automatically size the cache */ int txfr_size; /* 0 == try to pick 'optimal' cache for this query (default) */ /* <0 == base cache on target transfer size of -n bytes. */ - if (imp_sth->cache_rows == 0) { + if (cache_rows == 0) { /* Oracle packets on ethernet have max size of around 1460. */ /* We'll aim to fill our row cache with slightly less than */ /* two packets (to err on the safe side and avoid a third */ @@ -704,97 +701,18 @@ dbd_describe(h, imp_sth) txfr_size = 1460 * 3.6; /* default transfer/cache size */ } else { /* user is specifying desired transfer size in bytes */ - txfr_size = -imp_sth->cache_rows; + txfr_size = -cache_rows; } - imp_sth->cache_rows = txfr_size / est_width; /* maybe 1 or 0 */ + cache_rows = txfr_size / est_width; /* maybe 1 or 0 */ /* To ensure good performance with large rows (near or larger */ /* than our target transfer size) we set a minimum cache size. */ - if (imp_sth->cache_rows < 6) /* is cache a 'useful' size? */ - imp_sth->cache_rows = (imp_sth->cache_rows>0) ? 6 : 4; - } - if (imp_sth->cache_rows > 32767) /* keep within Oracle's limits */ - imp_sth->cache_rows = 32767; - /* Initialise cache counters */ - imp_sth->in_cache = 0; - imp_sth->eod_errno = 0; - - - /* allocate field buffers */ - Newz(42, imp_sth->fbh, num_fields, imp_fbh_t); - /* allocate a buffer to hold all the column names */ - Newz(42, imp_sth->fbh_cbuf, t_cbufl + num_fields, char); - - cbuf_ptr = (sb1*)imp_sth->fbh_cbuf; - for(i=1; i <= num_fields && imp_sth->cda->rc != 10; ++i) { - imp_fbh_t *fbh = &imp_sth->fbh[i-1]; - fb_ary_t *fb_ary; - int dbtype; - - fbh->imp_sth = imp_sth; - fbh->cbuf = cbuf_ptr; - fbh->cbufl = f_cbufl[i]; - /* DESCRIBE */ - odescr(imp_sth->cda, i, - &fbh->dbsize, &fbh->dbtype, fbh->cbuf, &fbh->cbufl, - &fbh->dsize, &fbh->prec, &fbh->scale, &fbh->nullok); - fbh->cbuf[fbh->cbufl] = '\0'; /* ensure null terminated */ - cbuf_ptr += fbh->cbufl + 1; /* increment name pointer */ - - /* Now define the storage for this field data. */ - - if (fbh->dbtype==23 || fbh->dbtype==24) { /* RAW types */ - /* is this the right thing to do? what about longraw? XXX */ - fbh->dbsize *= 2; - fbh->dsize *= 2; - } - - /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW? */ - /* If so we need to implement oraperl truncation hacks. */ - /* This may change in a future release. */ - /* Note that dbtype_is_long() returns alternate dbtype to use */ - if ( (dbtype = dbtype_is_long(fbh->dbtype)) ) { - fbh->dbsize = long_buflen; - fbh->dsize = long_buflen; - fbh->ftype = dbtype; /* get long in non-var form */ - imp_sth->t_dbsize += long_buflen; - - } else { - /* for the time being we fetch everything (except longs) */ - /* as strings, that'll change (IV, NV and binary data etc) */ - fbh->ftype = 5; /* oraperl used 5 'STRING' */ - /* dbsize can be zero for 'select NULL ...' */ - imp_sth->t_dbsize += fbh->dbsize; - } - - fbh->fb_ary = fb_ary = fb_ary_alloc( - fbh->dsize+1, /* +1: STRING null terminator */ - imp_sth->cache_rows - ); - - /* DEFINE output column variable storage */ - if (odefin(imp_sth->cda, i, fb_ary->abuf, fb_ary->bufl, - fbh->ftype, -1, fb_ary->aindp, (text*)0, -1, -1, - fb_ary->arlen, fb_ary->arcode)) { - warn("odefin error on %s: %d", fbh->cbuf, imp_sth->cda->rc); - } - - if (dbis->debug >= 2) - fbh_dump(fbh, i, 0); + if (cache_rows < 6) /* is cache a 'useful' size? */ + cache_rows = (cache_rows>0) ? 6 : 4; } - imp_sth->est_width = est_width; + if (cache_rows > 32767) /* keep within Oracle's limits */ + cache_rows = 32767; - if (dbis->debug >= 2) - fprintf(DBILOGFP, - " dbd_describe'd %d columns (Row bytes: %d max, %d est avg. Cache: %d rows)\n", - (int)num_fields, imp_sth->t_dbsize, est_width, imp_sth->cache_rows); - - if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { - D_imp_dbh_from_sth; - ora_error(h, imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); - return 0; - } - - return 1; + return cache_rows; } @@ -904,7 +822,7 @@ _rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) } if (dbis->debug >= 3) { - fprintf(DBILOGFP, "bind %s <== '%.*s' (size %d/%ld, otype %d, indp %d)\n", + fprintf(DBILOGFP, " bind %s <== '%.*s' (size %d/%ld, otype %d, indp %d)\n", phs->name, phs->alen, (phs->progv) ? phs->progv : "", phs->alen, (long)phs->maxlen, phs->ftype, phs->indp); } @@ -919,6 +837,7 @@ _rebind_ph_cursor(sth, imp_sth, phs) imp_sth_t *imp_sth; phs_t *phs; { +#ifndef OCI_V8_SYNTAX SV *phs_sth = phs->sv; D_impdata(phs_imp_sth, imp_sth_t, phs_sth); @@ -935,8 +854,10 @@ _rebind_ph_cursor(sth, imp_sth, phs) assert(phs->ftype == SQLT_CUR); phs->progv = (void*)phs_imp_sth->cda; phs->maxlen = -1; - warn("Cursor variables not yet supported"); +#else + die("Cursor variables not yet supported"); +#endif } #endif @@ -948,6 +869,10 @@ _dbd_rebind_ph(sth, imp_sth, phs) phs_t *phs; { ub2 *alen_ptr = NULL; +#ifdef OCI_V8_SYNTAX + sword status; + ub4 *aryelem_cur_ptr = NULL; +#endif #ifdef SQLT_CUR if (phs->ftype == SQLT_CUR) { @@ -963,6 +888,21 @@ _dbd_rebind_ph(sth, imp_sth, phs) croak("Can't bind %s, value is too long (%ld bytes, max %d)", phs->name, phs->maxlen, MINSWORDMAXVAL); +#ifdef OCI_V8_SYNTAX + status = OCIBindByName(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + phs->name, strlen(phs->name), + phs->progv, phs->maxlen, + phs->ftype, &phs->indp, + alen_ptr, &phs->arcode, + phs->aryelem_max, /* max elements that can fit in allocated array */ + aryelem_cur_ptr, /* (ptr to) current number of elements in array */ + OCI_DEFAULT); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); + return 0; + } + +#else if (obndra(imp_sth->cda, (text *)phs->name, -1, (ub1*)phs->progv, (sword)phs->maxlen, /* cast reduces max size */ (sword)phs->ftype, -1, @@ -972,6 +912,7 @@ _dbd_rebind_ph(sth, imp_sth, phs) ora_error(sth, imp_dbh->lda, imp_sth->cda->rc, "obndra failed"); return 0; } +#endif return 1; } @@ -1017,7 +958,7 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl croak("Can't bind ``lvalue'' mode scalar as inout parameter (currently)"); if (dbis->debug >= 2) { - fprintf(DBILOGFP, " bind %s <== %s (type %ld", + fprintf(DBILOGFP, " bind %s <== %s (type %ld", name, neatsvpv(newvalue,0), (long)sql_type); if (is_inout) fprintf(DBILOGFP, ", inout 0x%lx", (long)newvalue); @@ -1065,7 +1006,8 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl /* some types require the trailing null included in the length. */ phs->alen_incnull = (phs->ftype==SQLT_STR || phs->ftype==SQLT_AVC); - } + } /* was first bind for this placeholder */ + /* check later rebinds for any changes */ else if (is_inout != phs->is_inout) { croak("Can't rebind or change param %s in/out mode after first bind (%d => %d)", @@ -1097,22 +1039,32 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count imp_sth_t *imp_sth; { dTHR; - + ub4 row_count = 0; int debug = dbis->debug; int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0; +#ifdef OCI_V8_SYNTAX + D_imp_dbh_from_sth; + sword status; + int is_select = (imp_sth->stmt_type == OCI_STMT_SELECT); + + if (debug >= 2) + fprintf(DBILOGFP, " dbd_st_execute %s (out%d)...\n", + oci_stmt_type_name(imp_sth->stmt_type), outparams); +#else + if (!imp_sth->done_desc) { /* describe and allocate storage for results (if any needed) */ if (!dbd_describe(sth, imp_sth)) return -2; /* dbd_describe already called ora_error() */ } - if (debug >= 2) fprintf(DBILOGFP, - " dbd_st_execute (for sql f%d after oci f%d, outs %d)...\n", + " dbd_st_execute (for sql f%d after oci f%d, out%d)...\n", imp_sth->cda->ft, imp_sth->cda->fc, outparams); +#endif - if (outparams) { /* check validity of bound SV's */ + if (outparams) { /* check validity of bind_param_inout SV's */ int i = outparams; while(--i >= 0) { phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); @@ -1147,6 +1099,44 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count } } +#ifdef OCI_V8_SYNTAX + + status = OCIStmtExecute(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, + (is_select) ? 0 : 1, + 0, 0, 0, + (DBIc_has(imp_dbh,DBIcf_AutoCommit)) + ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIStmtExecute"); + return -2; + } + if (is_select) { + DBIc_ACTIVE_on(imp_sth); + DBIc_ROW_COUNT(imp_sth) = 0; /* reset (possibly re-exec'ing) */ + row_count = 0; + } + else { + OCIAttrGet_stmhp(imp_sth, &row_count, 0, OCI_ATTR_ROW_COUNT); + } + + if (debug >= 2) { + ub2 sqlfncode; + OCIAttrGet_stmhp(imp_sth, &sqlfncode, 0, OCI_ATTR_SQLFNCODE); + fprintf(DBILOGFP, + " dbd_st_execute %s ok (%s, rpc%ld, fn%d, out%d)\n", + oci_stmt_type_name(imp_sth->stmt_type), + oci_status_name(status), + row_count, sqlfncode, imp_sth->has_inout_params); + } + + if (is_select && !imp_sth->done_desc) { + /* describe and allocate storage for results (if any needed) */ + if (!dbd_describe(sth, imp_sth)) + return -2; /* dbd_describe already called ora_error() */ + } + +#else + /* reset cache counters */ imp_sth->in_cache = 0; imp_sth->next_entry = 0; @@ -1161,6 +1151,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexfet error"); return -2; } + DBIc_ACTIVE_on(imp_sth); imp_sth->in_cache = imp_sth->cda->rpc; /* cache loaded */ if (imp_sth->cda->rc == 1403) imp_sth->eod_errno = 1403; @@ -1171,19 +1162,22 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count return -2; } } + row_count = (imp_sth->cda) ? 0 : imp_sth->cda->rpc; if (debug >= 2) fprintf(DBILOGFP, " dbd_st_execute complete (rc%d, w%02x, rpc%ld, eod%d, out%d)\n", imp_sth->cda->rc, imp_sth->cda->wrn, - imp_sth->cda->rpc, imp_sth->eod_errno, + row_count, imp_sth->eod_errno, imp_sth->has_inout_params); +#endif if (outparams) { /* check validity of bound output SV's */ int i = outparams; while(--i >= 0) { phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); SV *sv = phs->sv; +#ifndef OCI_V8_SYNTAX if (SvROK(sv)) { /* XXX assume it's a cursor variable sth */ D_impdata(phs_imp_sth, imp_sth_t, sv); if (debug >= 2) @@ -1203,6 +1197,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count return -2; /* dbd_describe already called ora_error() */ } else +#endif /* phs->alen has been updated by Oracle to hold the length of the result */ if (phs->indp == 0) { /* is okay */ SvPOK_only(sv); @@ -1236,149 +1231,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count } } - if (DBIc_NUM_FIELDS(imp_sth) > 0) { /* is a SELECT */ - DBIc_ACTIVE_on(imp_sth); - } - if (!imp_sth->cda) /* XXX closed cursor after exe for cursor vars */ - return 0; - return imp_sth->cda->rpc; /* row count (0 will be returned as "0E0") */ -} - - - -AV * -dbd_st_fetch(sth, imp_sth) - SV * sth; - imp_sth_t *imp_sth; -{ - int debug = dbis->debug; - int num_fields; - int ChopBlanks; - int err = 0; - int i; - AV *av; - - if (!imp_sth->in_cache) { /* refill cache if empty */ - int previous_rpc; - - /* Check that execute() was executed sucessfully. This also implies */ - /* that dbd_describe() executed sucessfuly so the memory buffers */ - /* are allocated and bound. */ - if ( !DBIc_ACTIVE(imp_sth) ) { - ora_error(sth, NULL, 1, "no statement executing (perhaps you need to call execute first)"); - return Nullav; - } - - if (imp_sth->eod_errno) { - end_of_data: - if (imp_sth->eod_errno != 1403) { /* was not just end-of-fetch */ - ora_error(sth, imp_sth->cda, imp_sth->eod_errno, "cached ofetch error"); - } else { /* is simply no more data */ - sv_setiv(DBIc_ERR(imp_sth), 0); /* ensure errno set to 0 here */ - if (debug >= 2) - fprintf(DBILOGFP, " dbd_st_fetch no-more-data, rc=%d, rpc=%ld\n", - imp_sth->cda->rc, imp_sth->cda->rpc); - } - /* further fetches without an execute will arrive back here */ - return Nullav; - } - - previous_rpc = imp_sth->cda->rpc; /* remember rpc before re-fetch */ - if (ofen(imp_sth->cda, imp_sth->cache_rows)) { - /* Note that errors may happen after one or more rows have been */ - /* added to the cache. We record the error but don't handle it till */ - /* the cache is empty (which may be at once if no rows returned). */ - imp_sth->eod_errno = imp_sth->cda->rc; /* store rc for later */ - if (imp_sth->cda->rpc == previous_rpc) /* no more rows fetched */ - goto end_of_data; - /* else fall through and return the first of the fetched rows */ - } - imp_sth->next_entry = 0; - imp_sth->in_cache = imp_sth->cda->rpc - previous_rpc; - assert(imp_sth->in_cache > 0); - } - - av = DBIS->get_fbav(imp_sth); - num_fields = AvFILL(av)+1; - - if (debug >= 3) - fprintf(DBILOGFP, " dbd_st_fetch %d fields, rpc %ld (cache: %d/%d/%d)\n", - num_fields, (long)imp_sth->cda->rpc, imp_sth->next_entry, - imp_sth->in_cache, imp_sth->cache_rows); - - ChopBlanks = DBIc_has(imp_sth, DBIcf_ChopBlanks); - - for(i=0; i < num_fields; ++i) { - imp_fbh_t *fbh = &imp_sth->fbh[i]; - int cache_entry = imp_sth->next_entry; - fb_ary_t *fb_ary = fbh->fb_ary; - int rc = fb_ary->arcode[cache_entry]; - SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */ - - if (rc == 1406 && dbtype_is_long(fbh->dbtype)) { - /* We have a LONG field which has been truncated. */ - int oraperl = DBIc_COMPAT(imp_sth); - if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { - /* user says truncation is ok */ - /* Oraperl recorded the truncation in ora_errno so we */ - /* so also but only for Oraperl mode handles. */ - if (oraperl) - sv_setiv(DBIc_ERR(imp_sth), (IV)rc); - rc = 0; /* but don't provoke an error here */ - } - /* else fall through and let rc trigger failure below */ - } - - if (rc == 0) { /* the normal case */ - int datalen = fb_ary->arlen[cache_entry]; - char *p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; - /* if ChopBlanks check for Oracle CHAR type (blank padded) */ - if (ChopBlanks && fbh->dbtype == 96) { - while(datalen && p[datalen - 1]==' ') - --datalen; - } - sv_setpvn(sv, p, (STRLEN)datalen); - - } else if (rc == 1405) { /* field is null - return undef */ - (void)SvOK_off(sv); - - } else { /* See odefin rcode arg description in OCI docs */ - char buf[200]; - char *hint = ""; - /* These may get more case-by-case treatment eventually. */ - if (rc == 1406) { /* field truncated (see above) */ - /* Copy the truncated value anyway, it may be of use, */ - /* but it'll only be accessible via prior bind_column() */ - sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], - fb_ary->arlen[cache_entry]); - if (dbtype_is_long(fbh->dbtype)) /* double check */ - hint = ", LongReadLen too small and/or LongTruncOk not set"; - } - else { - SvOK_off(sv); /* set field that caused error to undef */ - } - ++err; /* 'fail' this fetch but continue getting fields */ - /* Some should probably be treated as warnings but */ - /* for now we just treat them all as errors */ - sprintf(buf,"ofetch error on field %d (of %d), ora_type %d%s", - i+1, num_fields, fbh->dbtype, hint); - ora_error(sth, imp_sth->cda, rc, buf); - } - - if (debug >= 3) - fprintf(DBILOGFP, " %d (rc=%d): %s\n", - i, rc, neatsvpv(sv,0)); - } - - /* update cache counters */ - if (ora_fetchtest) /* unless we're testing performance */ - --ora_fetchtest; - else { - --imp_sth->in_cache; - ++imp_sth->next_entry; - } - - return (err) ? Nullav : av; + return row_count; /* row count (0 will be returned as "0E0") */ } @@ -1394,6 +1247,9 @@ dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset) SV *destrv; long destoffset; { +#ifdef OCI_V8_SYNTAX + croak("blob_read not currently supported with OCI 8"); +#else ub4 retl; SV *bufsv; @@ -1418,6 +1274,7 @@ dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset) /* retl is exactly 65535 we assume that all data was read. */ SvCUR_set(bufsv, destoffset+((retl == 65535) ? len : retl)); *SvEND(bufsv) = '\0'; /* consistent with perl sv_setpvn etc */ +#endif return 1; } @@ -1428,6 +1285,16 @@ dbd_st_rows(sth, imp_sth) SV *sth; imp_sth_t *imp_sth; { +#ifdef OCI_V8_SYNTAX + ub4 row_count = 0; + sword status; + status = OCIAttrGet_stmhp(imp_sth, &row_count, 0, OCI_ATTR_ROW_COUNT); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIAttrGet OCI_ATTR_ROW_COUNT"); + return -1; + } + return row_count; +#else /* spot common mistake of checking $h->rows just after ->execute */ if ( imp_sth->in_cache > 0 /* has unfetched rows */ && imp_sth->in_cache== imp_sth->cda->rpc /* NO rows fetched yet */ @@ -1437,6 +1304,7 @@ dbd_st_rows(sth, imp_sth) } /* imp_sth->in_cache should always be 0 for non-select statements */ return imp_sth->cda->rpc - imp_sth->in_cache; /* fetched rows */ +#endif } @@ -1447,20 +1315,28 @@ dbd_st_finish(sth, imp_sth) { dTHR; + if (!DBIc_ACTIVE(imp_sth)) + return 1; + /* Cancel further fetches from this cursor. */ /* We don't close the cursor till DESTROY (dbd_st_destroy). */ /* The application may re execute(...) it. */ - if (DBIc_ACTIVE(imp_sth) && ocan(imp_sth->cda) ) { +#ifdef OCI_V8_SYNTAX + /* OCI 8 manual says there's no equiv of OCI7 ocan() */ + /* An OCIBreak() might be relevant */ +#else + if (ocan(imp_sth->cda) ) { /* oracle 7.3 code can core dump looking up an error message */ /* if we have logged out of the database. This typically */ /* happens during global destruction. This should catch most: */ - if (dirty && imp_sth->cda->rc == 3114) + if (PL_dirty && imp_sth->cda->rc == 3114) ora_error(sth, NULL, imp_sth->cda->rc, "ORA-03114: not connected to ORACLE (ocan)"); else ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "ocan error"); return 0; } +#endif DBIc_ACTIVE_off(imp_sth); return 1; } @@ -1480,10 +1356,22 @@ dbd_st_destroy(sth, imp_sth) /* Check if an explicit disconnect() or global destruction has */ /* disconnected us from the database before attempting to close. */ if (DBIc_ACTIVE(imp_dbh)) { +#ifdef OCI_V8_SYNTAX + /* nothing to do here ? */ +#else free_cursor(sth, imp_sth); /* ignore errors here */ +#endif /* fall through anyway to free up our memory */ } +#ifdef OCI_V8_SYNTAX + { + sword status = OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); + if (status != OCI_SUCCESS) + oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); + } +#endif + /* Free off contents of imp_sth */ fields = DBIc_NUM_FIELDS(imp_sth); @@ -1491,10 +1379,11 @@ dbd_st_destroy(sth, imp_sth) imp_sth->eod_errno = 1403; for(i=0; i < fields; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i]; - fb_ary_free(fbh->fb_ary); + if (fbh->fb_ary) + fb_ary_free(fbh->fb_ary); + sv_free(fbh->name_sv); } Safefree(imp_sth->fbh); - Safefree(imp_sth->fbh_cbuf); Safefree(imp_sth->statement); if (imp_sth->out_params_av) @@ -1527,10 +1416,11 @@ dbd_st_STORE_attrib(sth, imp_sth, keysv, valuesv) SV *valuesv; { STRLEN kl; + SV *cachesv = NULL; char *key = SvPV(keysv,kl); +/* int on = SvTRUE(valuesv); - SV *cachesv = NULL; -/* int oraperl = DBIc_COMPAT(imp_sth); */ + int oraperl = DBIc_COMPAT(imp_sth); */ if (strEQ(key, "ora_fetchtest")) { ora_fetchtest = SvIV(valuesv); @@ -1575,7 +1465,7 @@ dbd_st_FETCH_attrib(sth, imp_sth, keysv) AV *av = newAV(); retsv = newRV(sv_2mortal((SV*)av)); while(--i >= 0) - av_store(av, i, newSViv((IV)imp_sth->fbh[i].dsize)); + av_store(av, i, newSViv((IV)imp_sth->fbh[i].disize)); } else if (kl==9 && strEQ(key, "ora_types")) { AV *av = newAV(); @@ -1583,25 +1473,43 @@ dbd_st_FETCH_attrib(sth, imp_sth, keysv) while(--i >= 0) av_store(av, i, newSViv(imp_sth->fbh[i].dbtype)); + } else if (kl==4 && strEQ(key, "TYPE")) { + AV *av = newAV(); + retsv = newRV(sv_2mortal((SV*)av)); + while(--i >= 0) + av_store(av, i, newSViv(ora2sql_type(imp_sth->fbh[i].dbtype))); + + } else if (kl==5 && strEQ(key, "SCALE")) { + AV *av = newAV(); + retsv = newRV(sv_2mortal((SV*)av)); + while(--i >= 0) + av_store(av, i, newSViv(imp_sth->fbh[i].scale)); + + } else if (kl==9 && strEQ(key, "PRECISION")) { + AV *av = newAV(); + retsv = newRV(sv_2mortal((SV*)av)); + while(--i >= 0) + av_store(av, i, newSViv(imp_sth->fbh[i].prec)); + +#ifndef OCI_V8_SYNTAX +#ifdef XXXXX } else if (kl==9 && strEQ(key, "ora_rowid")) { /* return current _binary_ ROWID (oratype 11) uncached */ /* Use { ora_type => 11 } when binding to a placeholder */ retsv = newSVpv((char*)&imp_sth->cda->rid, sizeof(imp_sth->cda->rid)); cacheit = FALSE; +#endif +#endif } else if (kl==17 && strEQ(key, "ora_est_row_width")) { retsv = newSViv(imp_sth->est_width); cacheit = TRUE; - } else if (kl==14 && strEQ(key, "ora_cache_rows")) { - retsv = newSViv(imp_sth->cache_rows); - cacheit = TRUE; - } else if (kl==4 && strEQ(key, "NAME")) { AV *av = newAV(); retsv = newRV(sv_2mortal((SV*)av)); while(--i >= 0) - av_store(av, i, newSVpv((char*)imp_sth->fbh[i].cbuf,0)); + av_store(av, i, newSVpv((char*)imp_sth->fbh[i].name,0)); } else if (kl==8 && strEQ(key, "NULLABLE")) { AV *av = newAV(); @@ -1625,3 +1533,19 @@ dbd_st_FETCH_attrib(sth, imp_sth, keysv) /* --------------------------------------- */ +static int +ora2sql_type(oratype) + int oratype; +{ + switch(oratype) { /* oracle Internal (not external) types */ + case SQLT_CHR: return SQL_VARCHAR; + case SQLT_NUM: return SQL_DECIMAL; + case SQLT_LNG: return SQL_LONGVARCHAR; /* long */ + case SQLT_DAT: return SQL_DATE; + case SQLT_BIN: return SQL_BINARY; /* raw */ + case SQLT_LBI: return SQL_LONGVARBINARY; /* long raw */ + case SQLT_AFC: return SQL_CHAR; /* Ansi fixed char */ + } + /* else map type into DBI reserved standard range */ + return -9000 - oratype; +} diff --git a/dbdimp.h b/dbdimp.h index 754f8271..2f6953a3 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.22 1998/07/05 21:25:07 timbo Exp $ + $Id: dbdimp.h,v 1.23 1998/11/29 00:14:07 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -29,7 +29,6 @@ #define opcode opcode_redefined - /* Hack to fix broken Oracle oratypes.h on OSF Alpha. Sigh. */ #if defined(__osf__) && defined(__alpha) #ifndef A_OSF @@ -37,13 +36,26 @@ #endif #endif +/* This is slightly backwards because we want to auto-detect OCI8 */ +/* and thus the existance of oci.h while still working for Oracle7 */ #include #include + +#if defined(SQLT_NTY) && !defined(NO_OCI8) /* use Oracle 8 */ + +#ifdef dirty +#undef dirty /* appears in OCI prototypes as parameter name */ +#endif +#include + +#else /* use Oracle 7 */ + #ifdef CAN_PROTOTYPE # include #else # include #endif + #ifndef HDA_SIZE #define HDA_SIZE 512 #endif @@ -52,11 +64,16 @@ #define FT_SELECT 4 /* from rdbms/demo/ocidem.h */ #endif +#endif + typedef struct imp_fbh_st imp_fbh_t; struct imp_drh_st { dbih_drc_t com; /* MUST be first element in structure */ +#ifdef OCI_V8_SYNTAX + OCIEnv *envhp; +#endif }; /* Define dbh implementor data structure */ @@ -65,10 +82,18 @@ struct imp_dbh_st { Lda_Def ldabuf; Lda_Def *lda; /* points to ldabuf */ +#ifdef OCI_V8_SYNTAX + OCIEnv *envhp; /* copy of drh pointer */ + OCIError *errhp; + OCIServer *srvhp; + OCISvcCtx *svchp; + OCISession *authp; +#else ub1 hdabuf[HDA_SIZE]; ub1 *hda; /* points to hdabuf */ +#endif - int autocommit; /* we assume autocommit is off initially */ + int RowCacheSize; }; @@ -76,8 +101,16 @@ struct imp_dbh_st { struct imp_sth_st { dbih_stc_t com; /* MUST be first element in structure */ +#ifdef OCI_V8_SYNTAX + OCIError *errhp; /* copy of dbh pointer */ + OCIServer *srvhp; /* copy of dbh pointer */ + OCISvcCtx *svchp; /* copy of dbh pointer */ + OCIStmt *stmhp; + ub2 stmt_type; /* OCIAttrGet OCI_ATTR_STMT_TYPE */ +#else Cda_Def *cda; /* currently just points to cdabuf below */ Cda_Def cdabuf; +#endif /* Input Details */ char *statement; /* sql (see sth_scan) */ @@ -117,20 +150,84 @@ struct imp_fbh_st { /* field buffer EXPERIMENTAL */ imp_sth_t *imp_sth; /* 'parent' statement */ /* Oracle's description of the field */ +#ifdef OCI_V8_SYNTAX + OCIParam *parmdp; + OCIDefine *defnp; + ub2 dbsize; + ub2 dbtype; /* actual type of field (see ftype) */ + ub1 prec; + sb1 scale; + ub1 nullok; +#else sb4 dbsize; sb2 dbtype; /* actual type of field (see ftype) */ - sb1 *cbuf; /* ptr to name of select-list item */ - sb4 cbufl; /* length of select-list item name */ - sb4 dsize; /* max display size if field is a char */ sb2 prec; sb2 scale; sb2 nullok; + sb4 cbufl; /* length of select-list item 'name' */ +#endif + SV *name_sv; /* only set for OCI8 */ + text *name; + sb4 disize; /* max display/buffer size */ /* Our storage space for the field data as it's fetched */ sword ftype; /* external datatype we wish to get */ fb_ary_t *fb_ary; /* field buffer array */ }; +/* Table 6-13 Attributes Belonging to Columns of Tables or Views + + Attribute Description Attribute + Datatype + OCI_ATTR_DATA_SIZE the maximum size of the column. This length is returned in + bytes and not characters for strings and raws. It returns 22 for + NUMBERs. + ub2 + OCI_ATTR_DATA_TYPE + the data type of the column. See "Note on Datatype Codes" + on page 6-4. + ub2 + OCI_ATTR_PRECISION + the precision of numeric columns. If a describe returns a value + of zero for precision or -127 for scale, this indicates that the + item being described is uninitialized; i.e., it is NULL in the data + dictionary. + ub1 + OCI_ATTR_SCALE + the scale of numeric columns. If a describe returns a value of + zero for precision or -127 for scale, this indicates that the + item being described is uninitialized; i.e., it is NULL in the data + dictionary. + sb1 + OCI_ATTR_IS_NULL + returns 0 if null values are not permitted for the column + ub1 + OCI_ATTR_TYPE_NAME + returns a string which is the type name. The returned value + will contain the type name if the data type is SQLT_NTY or + SQLT_REF. If the data type is SQLT_NTY, the name of the + named data type's type is returned. If the data type is + SQLT_REF, the type name of the named data type pointed to + by the REF is returned + text * + OCI_ATTR_SCHEMA_NAME + returns a string with the schema name under which the type + has been created + text * + OCI_ATTR_REF_TDO + the REF of the TDO for the type, if the column type is an + object type + OCIRef * + OCI_ATTR_CHARSET_ID + the character set id, if the column is of a string/character type + + ub2 + OCI_ATTR_CHARSET_FORM + the character set form, if the column is of a string/character + type + ub1 +*/ + typedef struct phs_st phs_t; /* scalar placeholder */ @@ -143,6 +240,12 @@ struct phs_st { /* scalar placeholder EXPERIMENTAL */ IV maxlen; /* max possible len (=allocated buffer) */ + ub4 aryelem_max; /* max elements in allocated array */ + ub4 aryelem_cur; /* current elements in allocated array */ +#ifdef OCI_V8_SYNTAX + OCIBind *bndhp; +#endif + /* these will become an array one day */ sb2 indp; /* null indicator */ char *progv; diff --git a/oci7.h b/oci7.h new file mode 100644 index 00000000..ddfb31ed --- /dev/null +++ b/oci7.h @@ -0,0 +1,443 @@ +/* + $Id: oci7.h,v 1.2 1998/11/29 00:14:07 timbo Exp $ + + Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce + + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the Perl README file, + with the exception that it cannot be placed on a CD-ROM or similar media + for commercial distribution without the prior approval of the author. + +*/ + + + +static void +ora_error(h, lda, rc, what) + SV *h; + Lda_Def *lda; + sb2 rc; + char *what; +{ + D_imp_xxh(h); + SV *errstr = DBIc_ERRSTR(imp_xxh); + sv_setiv(DBIc_ERR(imp_xxh), (IV)rc); /* set err early */ + if (lda) { /* is oracle error (allow for non-oracle errors) */ + int len; + char msg[1024]; + /* Oracle oerhms can do duplicate free if connect fails. */ + /* Ignore 'with different width due to prototype' gcc warning */ + oerhms(lda, rc, (text*)msg, sizeof(msg)); /* may hang! */ + len = strlen(msg); + if (len && msg[len-1] == '\n') + msg[len-1] = '\0'; /* trim off \n from end of message */ + sv_setpv(errstr, (char*)msg); + if (what) { + sv_catpv(errstr, " (DBD: "); + sv_catpv(errstr, what); + sv_catpv(errstr, ")"); + } + } + else sv_setpv(errstr, what); + DBIh_EVENT2(h, ERROR_event, DBIc_ERR(imp_xxh), errstr); +} + + +int +dbd_describe(h, imp_sth) + SV *h; + imp_sth_t *imp_sth; +{ + static sb4 *f_cbufl; /* XXX not thread safe */ + static U32 f_cbufl_max; + + D_imp_dbh_from_sth; + I32 long_buflen; + sb1 *cbuf_ptr; + int t_cbufl=0; + I32 num_fields; + int has_longs = 0; + int est_width = 0; /* estimated avg row width (for cache) */ + int i = 0; + + + if (imp_sth->done_desc) + return 1; /* success, already done it */ + imp_sth->done_desc = 1; + + /* ora_trunc is checked at fetch time */ + /* long_buflen: length for long/longraw (if >0), else 80 (ora app dflt) */ + /* Ought to be for COMPAT mode only but was relaxed before LongReadLen existed */ + long_buflen = (SvOK(ora_long) && SvIV(ora_long)>0) + ? SvIV(ora_long) : DBIc_LongReadLen(imp_sth); + if (long_buflen < 0) /* trap any sillyness */ + long_buflen = 80; /* typical oracle app default */ + +#ifndef FT_SELECT +#define FT_SELECT 4 +#endif + if (imp_sth->cda->ft != FT_SELECT) { + if (dbis->debug >= 2) + fprintf(DBILOGFP, + " dbd_describe skipped for non-select (sql f%d, lb %ld, csr 0x%lx)\n", + imp_sth->cda->ft, (long)long_buflen, (long)imp_sth->cda); + /* imp_sth memory was cleared when created so no setup required here */ + return 1; + } + + if (dbis->debug >= 2) + fprintf(DBILOGFP, + " dbd_describe (for sql f%d after oci f%d, lb %ld, csr 0x%lx)...\n", + imp_sth->cda->ft, imp_sth->cda->fc, (long)long_buflen, (long)imp_sth->cda); + + if (!f_cbufl) { + f_cbufl_max = 120; + New(1, f_cbufl, f_cbufl_max, sb4); + } + + /* number of rows to cache */ + if (SvOK(ora_cache_o)) imp_sth->cache_rows = SvIV(ora_cache_o); + else if (SvOK(ora_cache)) imp_sth->cache_rows = SvIV(ora_cache); + else imp_sth->cache_rows = imp_dbh->RowCacheSize; + + /* Get number of fields and space needed for field names */ + while(++i) { /* break out within loop */ + sb1 cbuf[257]; /* generous max column name length */ + sb2 dbtype = 0; /* workaround for Oracle bug #405032 */ + sb4 dbsize; + if (i >= f_cbufl_max) { + f_cbufl_max *= 2; + Renew(f_cbufl, f_cbufl_max, sb4); + } + f_cbufl[i] = sizeof(cbuf); + odescr(imp_sth->cda, i, &dbsize, &dbtype, + cbuf, &f_cbufl[i], (sb4*)0, (sb2*)0, (sb2*)0, (sb2*)0); + if (imp_sth->cda->rc || dbtype == 0) + break; + t_cbufl += f_cbufl[i]; + + /* now we calculate the approx average on-the-wire width of */ + /* each field (and thus row) to determine a 'good' cache size. */ + if (imp_sth->cache_rows > 0) + continue; /* no need, user specified a size */ + if (dbsize==0) { /* is a LONG type or 'select NULL' */ + if (dbtype_is_long(dbtype)) { + est_width += long_buflen; + ++has_longs; /* hint to auto cache sizing code */ + } + } + else /* deal with dbtypes with overblown dbsizes */ + switch(dbtype) { + case 1: /* VARCHAR2 - result of to_char() has dbsize==75 */ + /* for all but small strings we take off 25% */ + est_width += (dbsize < 32) ? dbsize : dbsize-(dbsize>>2); + break; + case 2: /* NUMBER - e.g., from a sum() or max(), dbsize==22 */ + /* Most numbers are _much_ smaller than 22 bytes */ + est_width += 4; /* > approx +/- 1_000_000 ? */ + break; + default: est_width += dbsize; + break; + } + } + if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { + D_imp_dbh_from_sth; + ora_error(h, imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); + return 0; + } + imp_sth->cda->rc = 0; + num_fields = i - 1; + DBIc_NUM_FIELDS(imp_sth) = num_fields; + + /* --- Setup the row cache for this query --- */ + + /* Use guessed average on-the-wire row width calculated above */ + /* and add in overhead of 5 bytes per field plus 8 bytes per row. */ + /* The n*5+8 was determined by studying SQL*Net v2 packets. */ + /* It could probably benefit from a more detailed analysis. */ + est_width += num_fields*5 + 8; + + if (has_longs) /* override/disable caching */ + imp_sth->cache_rows = 1; /* else read_blob can't work */ + + else if (imp_sth->cache_rows < 1) { /* automatically size the cache */ + int txfr_size; + /* 0 == try to pick 'optimal' cache for this query (default) */ + /* <0 == base cache on target transfer size of -n bytes. */ + if (imp_sth->cache_rows == 0) { + /* Oracle packets on ethernet have max size of around 1460. */ + /* We'll aim to fill our row cache with slightly less than */ + /* two packets (to err on the safe side and avoid a third */ + /* almost empty packet being generated in some cases). */ + txfr_size = 1460 * 3.6; /* default transfer/cache size */ + } + else { /* user is specifying desired transfer size in bytes */ + txfr_size = -imp_sth->cache_rows; + } + imp_sth->cache_rows = txfr_size / est_width; /* maybe 1 or 0 */ + /* To ensure good performance with large rows (near or larger */ + /* than our target transfer size) we set a minimum cache size. */ + if (imp_sth->cache_rows < 6) /* is cache a 'useful' size? */ + imp_sth->cache_rows = (imp_sth->cache_rows>0) ? 6 : 4; + } + if (imp_sth->cache_rows > 32767) /* keep within Oracle's limits */ + imp_sth->cache_rows = 32767; + /* Initialise cache counters */ + imp_sth->in_cache = 0; + imp_sth->eod_errno = 0; + + + /* allocate field buffers */ + Newz(42, imp_sth->fbh, num_fields, imp_fbh_t); + /* allocate a buffer to hold all the column names */ + Newz(42, imp_sth->fbh_cbuf, t_cbufl + num_fields, char); + + cbuf_ptr = (sb1*)imp_sth->fbh_cbuf; + for(i=1; i <= num_fields && imp_sth->cda->rc != 10; ++i) { + imp_fbh_t *fbh = &imp_sth->fbh[i-1]; + fb_ary_t *fb_ary; + int dbtype; + + fbh->imp_sth = imp_sth; + fbh->name = cbuf_ptr; + fbh->cbufl = f_cbufl[i]; + /* DESCRIBE */ + odescr(imp_sth->cda, i, + &fbh->dbsize, &fbh->dbtype, fbh->name, &fbh->cbufl, + &fbh->disize, &fbh->prec, &fbh->scale, &fbh->nullok); + fbh->name[fbh->cbufl] = '\0'; /* ensure null terminated */ + cbuf_ptr += fbh->cbufl + 1; /* increment name pointer */ + + /* Now define the storage for this field data. */ + + if (fbh->dbtype==23 || fbh->dbtype==24) { /* RAW types */ + /* is this the right thing to do? what about longraw? XXX */ + fbh->dbsize *= 2; + fbh->disize *= 2; + } + + /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW? */ + /* If so we need to implement oraperl truncation hacks. */ + /* This may change in a future release. */ + /* Note that dbtype_is_long() returns alternate dbtype to use */ + if ( (dbtype = dbtype_is_long(fbh->dbtype)) ) { + fbh->dbsize = long_buflen; + fbh->disize = long_buflen; + fbh->ftype = dbtype; /* get long in non-var form */ + imp_sth->t_dbsize += long_buflen; + + } else { + /* for the time being we fetch everything (except longs) */ + /* as strings, that'll change (IV, NV and binary data etc) */ + fbh->ftype = 5; /* oraperl used 5 'STRING' */ + /* dbsize can be zero for 'select NULL ...' */ + imp_sth->t_dbsize += fbh->dbsize; + } + + fbh->fb_ary = fb_ary = fb_ary_alloc( + fbh->disize+1, /* +1: STRING null terminator */ + imp_sth->cache_rows + ); + + /* DEFINE output column variable storage */ + if (odefin(imp_sth->cda, i, fb_ary->abuf, fb_ary->bufl, + fbh->ftype, -1, fb_ary->aindp, (text*)0, -1, -1, + fb_ary->arlen, fb_ary->arcode)) { + warn("odefin error on %s: %d", fbh->name, imp_sth->cda->rc); + } + + if (dbis->debug >= 2) + fbh_dump(fbh, i, 0); + } + imp_sth->est_width = est_width; + + if (dbis->debug >= 2) + fprintf(DBILOGFP, + " dbd_describe'd %d columns (Row bytes: %d max, %d est avg. Cache: %d rows)\n", + (int)num_fields, imp_sth->t_dbsize, est_width, imp_sth->cache_rows); + + if (imp_sth->cda->rc && imp_sth->cda->rc != 1007) { + D_imp_dbh_from_sth; + ora_error(h, imp_dbh->lda, imp_sth->cda->rc, "odescr failed"); + return 0; + } + + return 1; +} + + +AV * +dbd_st_fetch(sth, imp_sth) + SV * sth; + imp_sth_t *imp_sth; +{ + int debug = dbis->debug; + int num_fields; + int ChopBlanks; + int err = 0; + int i; + AV *av; + + if (!imp_sth->in_cache) { /* refill cache if empty */ + int previous_rpc; + + /* Check that execute() was executed sucessfully. This also implies */ + /* that dbd_describe() executed sucessfuly so the memory buffers */ + /* are allocated and bound. */ + if ( !DBIc_ACTIVE(imp_sth) ) { + ora_error(sth, NULL, 1, "no statement executing (perhaps you need to call execute first)"); + return Nullav; + } + + if (imp_sth->eod_errno) { + end_of_data: + if (imp_sth->eod_errno != 1403) { /* was not just end-of-fetch */ + ora_error(sth, imp_sth->cda, imp_sth->eod_errno, "cached ofetch error"); + } else { /* is simply no more data */ + sv_setiv(DBIc_ERR(imp_sth), 0); /* ensure errno set to 0 here */ + if (debug >= 2) + fprintf(DBILOGFP, " dbd_st_fetch no-more-data, rc=%d, rpc=%ld\n", + imp_sth->cda->rc, imp_sth->cda->rpc); + } + /* further fetches without an execute will arrive back here */ + return Nullav; + } + + previous_rpc = imp_sth->cda->rpc; /* remember rpc before re-fetch */ + if (ofen(imp_sth->cda, imp_sth->cache_rows)) { + /* Note that errors may happen after one or more rows have been */ + /* added to the cache. We record the error but don't handle it till */ + /* the cache is empty (which may be at once if no rows returned). */ + imp_sth->eod_errno = imp_sth->cda->rc; /* store rc for later */ + if (imp_sth->cda->rpc == previous_rpc) /* no more rows fetched */ + goto end_of_data; + /* else fall through and return the first of the fetched rows */ + } + imp_sth->next_entry = 0; + imp_sth->in_cache = imp_sth->cda->rpc - previous_rpc; + assert(imp_sth->in_cache > 0); + } + + av = DBIS->get_fbav(imp_sth); + num_fields = AvFILL(av)+1; + + if (debug >= 3) + fprintf(DBILOGFP, " dbd_st_fetch %d fields, rpc %ld (cache: %d/%d/%d)\n", + num_fields, (long)imp_sth->cda->rpc, imp_sth->next_entry, + imp_sth->in_cache, imp_sth->cache_rows); + + ChopBlanks = DBIc_has(imp_sth, DBIcf_ChopBlanks); + + for(i=0; i < num_fields; ++i) { + imp_fbh_t *fbh = &imp_sth->fbh[i]; + int cache_entry = imp_sth->next_entry; + fb_ary_t *fb_ary = fbh->fb_ary; + int rc = fb_ary->arcode[cache_entry]; + SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */ + + if (rc == 1406 && dbtype_is_long(fbh->dbtype)) { + /* We have a LONG field which has been truncated. */ + int oraperl = DBIc_COMPAT(imp_sth); + if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { + /* user says truncation is ok */ + /* Oraperl recorded the truncation in ora_errno so we */ + /* so also but only for Oraperl mode handles. */ + if (oraperl) + sv_setiv(DBIc_ERR(imp_sth), (IV)rc); + rc = 0; /* but don't provoke an error here */ + } + /* else fall through and let rc trigger failure below */ + } + + if (rc == 0) { /* the normal case */ + int datalen = fb_ary->arlen[cache_entry]; + char *p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; + /* if ChopBlanks check for Oracle CHAR type (blank padded) */ + if (ChopBlanks && fbh->dbtype == 96) { + while(datalen && p[datalen - 1]==' ') + --datalen; + } + sv_setpvn(sv, p, (STRLEN)datalen); + + } else if (rc == 1405) { /* field is null - return undef */ + (void)SvOK_off(sv); + + } else { /* See odefin rcode arg description in OCI docs */ + char buf[200]; + char *hint = ""; + /* These may get more case-by-case treatment eventually. */ + if (rc == 1406) { /* field truncated (see above) */ + /* Copy the truncated value anyway, it may be of use, */ + /* but it'll only be accessible via prior bind_column() */ + sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], + fb_ary->arlen[cache_entry]); + if (dbtype_is_long(fbh->dbtype)) /* double check */ + hint = ", LongReadLen too small and/or LongTruncOk not set"; + } + else { + SvOK_off(sv); /* set field that caused error to undef */ + } + ++err; /* 'fail' this fetch but continue getting fields */ + /* Some should probably be treated as warnings but */ + /* for now we just treat them all as errors */ + sprintf(buf,"ofetch error on field %d (of %d), ora_type %d%s", + i+1, num_fields, fbh->dbtype, hint); + ora_error(sth, imp_sth->cda, rc, buf); + } + + if (debug >= 3) + fprintf(DBILOGFP, " %d (rc=%d): %s\n", + i, rc, neatsvpv(sv,0)); + } + + /* update cache counters */ + if (ora_fetchtest) /* unless we're testing performance */ + --ora_fetchtest; + else { + --imp_sth->in_cache; + ++imp_sth->next_entry; + } + + return (err) ? Nullav : av; +} + + +/* ------------------------------------------------------------ */ + + +static int +get_cursor(imp_dbh, sth, imp_sth) + imp_dbh_t *imp_dbh; + SV *sth; + imp_sth_t *imp_sth; +{ + if (oopen(&imp_sth->cdabuf, imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { + ora_error(sth, &imp_sth->cdabuf, imp_sth->cdabuf.rc, "oopen error"); + return 0; + } + imp_sth->cda = &imp_sth->cdabuf; + return 1; +} + +static int +free_cursor(sth, imp_sth) + SV *sth; + imp_sth_t *imp_sth; +{ + if (!imp_sth->cda) + return 0; + + if (DBIc_ACTIVE(imp_sth)) /* should never happen here */ + ocan(imp_sth->cda); /* XXX probably not needed before oclose */ + + if (oclose(imp_sth->cda)) { /* close the cursor */ + /* Check for ORA-01041: 'hostdef extension doesn't exist' ? XXX */ + /* which indicates that the lda had already been logged out */ + /* in which case only complain if not in 'global destruction'? */ + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oclose error"); + return 0; + } + imp_sth->cda = NULL; + return 1; +} + diff --git a/oci8.h b/oci8.h new file mode 100644 index 00000000..0113eabc --- /dev/null +++ b/oci8.h @@ -0,0 +1,450 @@ +/* + $Id: oci8.h,v 1.2 1998/11/29 00:14:07 timbo Exp $ + + Copyright (c) 1998 Tim Bunce + + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the Perl README file, + with the exception that it cannot be placed on a CD-ROM or similar media + for commercial distribution without the prior approval of the author. + +*/ + + +static char * +oci_status_name(status) + int status; +{ + SV *sv; + switch (status) { + case OCI_SUCCESS: return "SUCCESS"; + case OCI_SUCCESS_WITH_INFO: return "SUCCESS_WITH_INFO"; + case OCI_NEED_DATA: return "NEED_DATA"; + case OCI_NO_DATA: return "NO_DATA"; + case OCI_ERROR: return "ERROR"; + case OCI_INVALID_HANDLE: return "INVALID_HANDLE"; + case OCI_STILL_EXECUTING: return "STILL_EXECUTING"; + case OCI_CONTINUE: return "CONTINUE"; + } + sv = sv_2mortal(newSVpv("",0)); + sv_grow(sv, 50); + sprintf(SvPVX(sv),"(UNKNOWN OCI STATUS %d)", status); + return SvPVX(sv); +} + + +static char * +oci_stmt_type_name(stmt_type) + int stmt_type; +{ + SV *sv; + switch (stmt_type) { + case OCI_STMT_SELECT: return "SELECT"; + case OCI_STMT_UPDATE: return "UPDATE"; + case OCI_STMT_DELETE: return "DELETE"; + case OCI_STMT_INSERT: return "INSERT"; + case OCI_STMT_CREATE: return "CREATE"; + case OCI_STMT_DROP: return "DROP"; + case OCI_STMT_ALTER: return "ALTER"; + case OCI_STMT_BEGIN: return "BEGIN"; + case OCI_STMT_DECLARE: return "DECLARE"; + } + sv = sv_2mortal(newSVpv("",0)); + sv_grow(sv, 50); + sprintf(SvPVX(sv),"(STMT TYPE %d)", stmt_type); + return SvPVX(sv); +} + + +static int +oci_error(h, errhp, status, what) + SV *h; + OCIError *errhp; + sword status; + char *what; +{ + D_imp_xxh(h); + SV *errstr = DBIc_ERRSTR(imp_xxh); + sv_setpv(errstr, ""); + if (errhp) { + char errbuf[1024]; + ub4 recno = 0; + sb4 errcode = 0; + sb4 eg_errcode = 0; + sword eg_status; + while( (eg_status = OCIErrorGet(errhp, ++recno, (text*)NULL, + &eg_errcode, errbuf, + (ub4)sizeof(errbuf), OCI_HTYPE_ERROR)) != OCI_NO_DATA + && eg_status != OCI_INVALID_HANDLE + && recno < 100 + ) { + if (dbis->debug >= 4 || recno>1/*XXX temp*/) + fprintf(DBILOGFP, "OCIErrorGet after %s (err rec %ld = %s): %d, %ld: %s\n", + what, (long)recno, oci_status_name(eg_status), + status, (long)eg_errcode, errbuf); + errcode = eg_errcode; + sv_catpv(errstr, errbuf); + if (*(SvEND(errstr)-1) == '\n') + --SvCUR(errstr); + } + if (what || status != OCI_ERROR) { + sv_catpv(errstr, " (DBD "); + sv_catpv(errstr, oci_status_name(status)); + if (what) { + sv_catpv(errstr, ": "); + sv_catpv(errstr, what); + } + sv_catpv(errstr, ")"); + } + /* DBIc_ERR *must* be SvTRUE (for RaiseError etc), some */ + /* errors, like OCI_INVALID_HANDLE, don't set errcode. */ + if (errcode == 0) + errcode = (status != 0) ? status : -10000; + sv_setiv(DBIc_ERR(imp_xxh), (IV)errcode); + } + else { + sv_setiv(DBIc_ERR(imp_xxh), (IV)status); + sv_catpv(errstr, oci_status_name(status)); + sv_catpv(errstr, " "); + sv_catpv(errstr, what); + } + DBIh_EVENT2(h, ERROR_event, DBIc_ERR(imp_xxh), errstr); + return 0; /* always returns 0 */ +} + + +int +dbd_describe(h, imp_sth) + SV *h; + imp_sth_t *imp_sth; +{ + D_imp_dbh_from_sth; + I32 long_buflen; + ub4 num_fields; + int has_longs = 0; + int est_width = 0; /* estimated avg row width (for cache) */ + int i = 0; + sword status; + + + if (imp_sth->done_desc) + return 1; /* success, already done it */ + imp_sth->done_desc = 1; + + /* ora_trunc is checked at fetch time */ + /* long_buflen: length for long/longraw (if >0), else 80 (ora app dflt) */ + /* Ought to be for COMPAT mode only but was relaxed before LongReadLen existed */ + long_buflen = (SvOK(ora_long) && SvIV(ora_long)>0) + ? SvIV(ora_long) : DBIc_LongReadLen(imp_sth); + if (long_buflen < 0) /* trap any sillyness */ + long_buflen = 80; /* typical oracle app default */ + + if (imp_sth->stmt_type != OCI_STMT_SELECT) { + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_describe skipped for %s\n", + oci_stmt_type_name(imp_sth->stmt_type)); + /* imp_sth memory was cleared when created so no setup required here */ + return 1; + } + + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_describe %s (%s, lb %ld)...\n", + oci_stmt_type_name(imp_sth->stmt_type), + DBIc_ACTIVE(imp_sth) ? "implicit" : "EXPLICIT", (long)long_buflen); + + /* We know it's a select and we've not got the description yet, so if the */ + /* sth is not 'active' (executing) then we need an explicit describe. */ + if ( !DBIc_ACTIVE(imp_sth) ) { + status = OCIStmtExecute(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, + 0, 0, 0, 0, OCI_DESCRIBE_ONLY); + if (status != OCI_SUCCESS) { + oci_error(h, imp_sth->errhp, status, "OCIStmtExecute/Describe"); + return 0; + } + } + + status = OCIAttrGet_stmhp(imp_sth, &num_fields, 0, OCI_ATTR_PARAM_COUNT) + if (status != OCI_SUCCESS) { + oci_error(h, imp_sth->errhp, status, "OCIAttrGet OCI_ATTR_PARAM_COUNT"); + return 0; + } + DBIc_NUM_FIELDS(imp_sth) = num_fields; + Newz(42, imp_sth->fbh, num_fields, imp_fbh_t); + + + /* Get number of fields and space needed for field names */ + for(i = 1; i <= num_fields; ++i) { + ub4 atrlen; + imp_fbh_t *fbh = &imp_sth->fbh[i-1]; + fbh->imp_sth = imp_sth; + + status = OCIParamGet(imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, + (dvoid*)&fbh->parmdp, (ub4)i); + if (status != OCI_SUCCESS) { + oci_error(h, imp_sth->errhp, status, "OCIParamGet"); + return 0; + } + + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->dbtype, 0, OCI_ATTR_DATA_TYPE); + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->dbsize, 0, OCI_ATTR_DATA_SIZE); + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->prec, 0, OCI_ATTR_PRECISION); + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->scale, 0, OCI_ATTR_SCALE); + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->nullok, 0, OCI_ATTR_IS_NULL); + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->name, &atrlen, OCI_ATTR_NAME); + fbh->name_sv = newSVpv(fbh->name,atrlen); + fbh->name = SvPVX(fbh->name_sv); + + fbh->ftype = 5; /* default: return as null terminated string */ + switch (fbh->dbtype) { + /* the simple types */ + case 1: /* VARCHAR2 */ + case 96: /* CHAR */ + fbh->disize = fbh->dbsize; + break; + case 23: /* RAW */ + fbh->disize = fbh->dbsize * 2; + break; + + case 2: /* NUMBER */ + /* actually dependent on scale & precision */ + if (!fbh->scale && !fbh->prec) /* always 0! */ + fbh->disize = 38 + 2; /* max prec */ + else fbh->disize = fbh->prec + 2; /* sign + dot */ + break; + + case 12: /* DATE */ + /* actually dependent on NLS default date format*/ + fbh->disize = 75; /* a generous default */ + break; + + case 8: /* LONG */ + fbh->disize = fbh->dbsize; + fbh->dbsize = long_buflen; + fbh->ftype = 8; + break; + case 24: /* LONG RAW */ + fbh->disize = fbh->dbsize; + fbh->dbsize = long_buflen * 2; + fbh->ftype = 24; + break; + + case 11: /* ROWID */ + fbh->disize = 20; + break; + case 104: /* ROWID Desc */ + fbh->disize = 20; + break; + + case 105: /* MLSLABEL */ + case 108: /* User Defined */ + case 111: /* REF */ + case 112: /* CLOB */ + case 113: /* BLOB */ + default: + fbh->disize = fbh->dbsize; + break; + } + + /* dbsize can be zero for 'select NULL ...' */ + imp_sth->t_dbsize += fbh->dbsize; + + if (dbis->debug >= 2) + fbh_dump(fbh, i, 0); + + /* now we calculate the approx average on-the-wire width of */ + /* each field (and thus row) to determine a 'good' cache size. */ + if (fbh->dbsize==0) { /* is a LONG type or 'select NULL' */ + if (dbtype_is_long(fbh->dbtype)) { + est_width += long_buflen; + ++has_longs; /* hint to auto cache sizing code */ + } + } + else /* deal with dbtypes with overblown dbsizes */ + switch(fbh->dbtype) { + case 1: /* VARCHAR2 - result of to_char() has dbsize==75 */ + /* for all but small strings we take off 25% */ + est_width += (fbh->dbsize < 32) ? fbh->dbsize : fbh->dbsize-(fbh->dbsize>>2); + break; + case 2: /* NUMBER - e.g., from a sum() or max(), dbsize==22 */ + /* Most numbers are _much_ smaller than 22 bytes */ + est_width += 4; /* > approx +/- 1_000_000 ? */ + break; + default: est_width += fbh->dbsize; + break; + } + } + imp_sth->est_width = est_width; + + /* --- Setup the row cache for this query --- */ + + /* number of rows to cache */ + if (SvOK(ora_cache_o)) imp_sth->cache_rows = SvIV(ora_cache_o); + else if (SvOK(ora_cache)) imp_sth->cache_rows = SvIV(ora_cache); + else imp_sth->cache_rows = imp_dbh->RowCacheSize; + if (imp_sth->cache_rows >= 0) { /* set cache size by row count */ + ub4 cache_rows; + cache_rows = calc_cache_rows(num_fields, est_width, imp_sth->cache_rows, has_longs); + imp_sth->cache_rows = cache_rows; + OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, + &cache_rows, 0, OCI_ATTR_PREFETCH_ROWS, imp_dbh->errhp); + } + else { /* set cache size by memory */ + ub4 cache_rows = 100000; + ub4 cache_mem = -imp_sth->cache_rows; + OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, + &cache_rows, 0, OCI_ATTR_PREFETCH_ROWS, imp_dbh->errhp); + OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, + &cache_mem, 0, OCI_ATTR_PREFETCH_MEMORY, imp_dbh->errhp); + } + + /* Initialise cache counters */ + imp_sth->in_cache = 0; + imp_sth->eod_errno = 0; + + for(i=1; i <= num_fields; ++i) { + imp_fbh_t *fbh = &imp_sth->fbh[i-1]; + fb_ary_t *fb_ary; + + fbh->fb_ary = fb_ary = fb_ary_alloc( + fbh->disize+1, /* +1: STRING null terminator */ + 1); + + status = OCIDefineByPos(imp_sth->stmhp, &fbh->defnp, imp_sth->errhp, (ub4) i, + fb_ary->abuf, fbh->disize, /* valuep, value_sz */ + fbh->ftype, + fb_ary->aindp, fb_ary->arlen, fb_ary->arcode, OCI_DEFAULT); + if (status != OCI_SUCCESS) { + oci_error(h, imp_sth->errhp, status, "OCIDefineByPos"); + return 0; + } + + } + + if (dbis->debug >= 2) + fprintf(DBILOGFP, + " dbd_describe'd %d columns (row bytes: %d max, %d est avg, cache: %d)\n", + (int)num_fields, imp_sth->t_dbsize, imp_sth->est_width, imp_sth->cache_rows); + + return 1; +} + + +AV * +dbd_st_fetch(sth, imp_sth) + SV * sth; + imp_sth_t *imp_sth; +{ + sword status; + int num_fields; + int ChopBlanks; + int err; + int i; + AV *av; + + /* Check that execute() was executed sucessfully. This also implies */ + /* that dbd_describe() executed sucessfuly so the memory buffers */ + /* are allocated and bound. */ + if ( !DBIc_ACTIVE(imp_sth) ) { + oci_error(sth, NULL, OCI_ERROR, + "no statement executing (perhaps you need to call execute first)"); + return Nullav; + } + + if (ora_fetchtest && DBIc_ROW_COUNT(imp_sth)>0) { + --ora_fetchtest; /* trick for testing performance */ + status = OCI_SUCCESS; + } + else { + status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT); + } + if (status != OCI_SUCCESS) { + ora_fetchtest = 0; + if (status == OCI_NO_DATA) { + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_st_fetch no-more-data\n"); + return Nullav; + } + if (status != OCI_SUCCESS_WITH_INFO) { + oci_error(sth, imp_sth->errhp, status, "OCIStmtFetch"); + return Nullav; + } + /* for OCI_SUCCESS_WITH_INFO we fall through and let the */ + /* per-field rcode value be dealt with as we fetch the data */ + } + + av = DBIS->get_fbav(imp_sth); + num_fields = AvFILL(av)+1; + + if (dbis->debug >= 3) + fprintf(DBILOGFP, " dbd_st_fetch %d fields %s:\n", + num_fields, oci_status_name(status)); + + ChopBlanks = DBIc_has(imp_sth, DBIcf_ChopBlanks); + + err = 0; + for(i=0; i < num_fields; ++i) { + imp_fbh_t *fbh = &imp_sth->fbh[i]; + int cache_entry = 0; + fb_ary_t *fb_ary = fbh->fb_ary; + int rc = fb_ary->arcode[cache_entry]; + SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */ + + if (rc == 1406 && dbtype_is_long(fbh->dbtype)) { + /* We have a LONG field which has been truncated. */ + int oraperl = DBIc_COMPAT(imp_sth); + if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { + /* user says truncation is ok */ + /* Oraperl recorded the truncation in ora_errno so we */ + /* so also but only for Oraperl mode handles. */ + if (oraperl) + sv_setiv(DBIc_ERR(imp_sth), (IV)rc); + rc = 0; /* but don't provoke an error here */ + } + /* else fall through and let rc trigger failure below */ + } + + if (rc == 0) { /* the normal case */ + int datalen = fb_ary->arlen[cache_entry]; + char *p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; + /* if ChopBlanks check for Oracle CHAR type (blank padded) */ + if (ChopBlanks && fbh->dbtype == 96) { + while(datalen && p[datalen - 1]==' ') + --datalen; + } + sv_setpvn(sv, p, (STRLEN)datalen); + + } else if (rc == 1405) { /* field is null - return undef */ + (void)SvOK_off(sv); + + } else { /* See odefin rcode arg description in OCI docs */ + char buf[200]; + char *hint = ""; + /* These may get more case-by-case treatment eventually. */ + if (rc == 1406) { /* field truncated (see above) */ + /* Copy the truncated value anyway, it may be of use, */ + /* but it'll only be accessible via prior bind_column() */ + sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], + fb_ary->arlen[cache_entry]); + if (dbtype_is_long(fbh->dbtype)) /* double check */ + hint = ", LongReadLen too small and/or LongTruncOk not set"; + } + else { + SvOK_off(sv); /* set field that caused error to undef */ + } + ++err; /* 'fail' this fetch but continue getting fields */ + /* Some should probably be treated as warnings but */ + /* for now we just treat them all as errors */ + sprintf(buf,"ORA-%05d error on field %d of %d, ora_type %d%s", + rc, i+1, num_fields, fbh->dbtype, hint); + oci_error(sth, imp_sth->errhp, OCI_ERROR, buf); + } + + if (dbis->debug >= 3) + fprintf(DBILOGFP, " %d (rc=%d): %s\n", + i, rc, neatsvpv(sv,0)); + } + + return (err) ? Nullav : av; +} + + diff --git a/t/general.t b/t/general.t index ccd6c13b..ee6eb855 100644 --- a/t/general.t +++ b/t/general.t @@ -26,7 +26,12 @@ unless($dbh) { print "1..$tests\n"; -my($csr, $p1, $p2); +my($sth, $p1, $p2); + +$sth = $dbh->prepare("select * from user_tables"); +ok(0, $sth->{NUM_OF_FIELDS}); +eval { $p1=$sth->{NUM_OFFIELDS_typo} }; +ok(0, $@ =~ /attribute/); # To do # test NULLs at first bind @@ -39,7 +44,7 @@ $dbh->disconnect; ok(0, !$dbh->ping); exit 0; -BEGIN { $tests = 2 } +BEGIN { $tests = 4 } # end. __END__ diff --git a/t/plsql.t b/t/plsql.t index 747d4454..f33251d8 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -5,7 +5,8 @@ sub ok ($$;$) { ++$t; die "sequence error, expected $n but actually $t" if $n and $n != $t; - ($ok) ? print "ok $t\n" : print "not ok $t\n"; + ($ok) ? print "ok $t\n" + : print "# failed test $t at line ".(caller)[2]."\nnot ok $t\n"; if (!$ok && $warn) { $warn = $DBI::errstr || "(DBI::errstr undefined)" if $warn eq '1'; warn "$warn\n"; @@ -27,9 +28,9 @@ unless($dbh) { # ORA-00900: invalid SQL statement # ORA-06553: PLS-213: package STANDARD not accessible my $tst = $dbh->prepare(q{declare foo char(50); begin RAISE INVALID_NUMBER; end;}); -if ($dbh->err && ($dbh->err==900 || $dbh->err==6553)) { +if ($dbh->err && ($dbh->err==900 || $dbh->err==6553 || $dbh->err==600)) { warn "Your Oracle server doesn't support PL/SQL" if $dbh->err== 900; - warn "Your Oracle PL/SQL is not properly installed" if $dbh->err==6553; + warn "Your Oracle PL/SQL is not properly installed" if $dbh->err==6553||$dbh->err==600; warn "Tests skipped\n"; print "1..0\n"; exit 0; @@ -65,6 +66,7 @@ ok(0, $DBI::err == 6510); # --- test raise_application_error with literal values ok(0, $csr = $dbh->prepare(q{ + declare err_num number; err_msg char(510); begin RAISE_APPLICATION_ERROR(-20101,'app error'); end; }), 1); @@ -76,7 +78,8 @@ ok(0, $DBI::errstr =~ m/app error/); # --- test raise_application_error with 'in' parameters ok(0, $csr = $dbh->prepare(q{ - declare err_num number; err_msg char(510); + declare err_num varchar2(555); err_msg varchar2(510); + --declare err_num number; err_msg char(510); begin err_num := :1; err_msg := :2; @@ -88,7 +91,6 @@ ok(0, ! $csr->execute(42, "hello world"), 1); ok(0, $DBI::err == 20042, $DBI::err); ok(0, $DBI::errstr =~ m/msg is hello world/, 1); - # --- test named numeric in/out parameters ok(0, $csr = $dbh->prepare(q{ begin diff --git a/test.pl b/test.pl index 6fdc266f..ad3d6b09 100755 --- a/test.pl +++ b/test.pl @@ -4,17 +4,22 @@ die "Use 'make test' to run test.pl\n" unless "@INC" =~ /\bblib\b/; -# $Id: test.pl,v 1.30 1997/06/14 17:42:12 timbo Exp $ +# $Id: test.pl,v 1.32 1998/11/29 00:14:07 timbo Exp $ # -# Copyright (c) 1995, Tim Bunce +# Copyright (c) 1995-1998, Tim Bunce # # You may distribute under the terms of either the GNU General Public # License or the Artistic License, as specified in the Perl README file. +# XXX +# XXX Please note that this code is a random hotch-potch of tests and +# XXX test frameworks and is in *no way* a to be used as a style guide! +# XXX + require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.30 $}."\n"; +print q{Oraperl test application $Revision: 1.32 $}."\n"; $SIG{__WARN__} = sub { ($_[0] =~ /^(Bad|Duplicate) free/) @@ -73,14 +78,15 @@ warn "Try leaving dbname value empty and set dbuser to name/passwd\@dbname.\n"; die "\nTest aborted.\n"; } - # test_other($l); - if ($os ne 'MSWin32' and $os ne 'VMS') { - my $backtick = `sleep 1; echo Backticks OK`; - unless ($backtick) { # $! == Interrupted system call - print "Warning: Oracle's SIGCHLD signal handler breaks perl ", - "`backticks` commands: $!\n(d_sigaction=$Config{d_sigaction})\n"; - } + if ($os ne 'MSWin32' and $os ne 'VMS') { + my $backtick = `sleep 1; echo Backticks OK`; + unless ($backtick) { # $! == Interrupted system call + print "Warning: Oracle's SIGCHLD signal handler breaks perl ", + "`backticks` commands: $!\n(d_sigaction=$Config{d_sigaction})\n"; } + } + #test_bind_csr($l); + #test_auto_reprepare($l); &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; } $start = time; @@ -135,29 +141,34 @@ sub test1 { # $lda->debug(2); { + #$lda->trace(2); local($csr) = &ora_open($lda, "select 11*7.2 num_t, SYSDATE date_t, USER char_t, + ROWID rowid_t, NULL null_t from dual") || die "ora_open: $ora_errno: $ora_errstr\n"; - - print "Fields: ",scalar(&ora_fetch($csr)),"\n"; - die "ora_fetch in scalar context error\n" unless &ora_fetch($csr)==4; - print "Names: '",join("',\t'", &ora_titles($csr)),"'\n"; - print "Lengths: '",join("',\t'", &ora_lengths($csr)),"'\n"; - print "Types: '",join("',\t'", &ora_types($csr)),"'\n"; + $csr->{RaiseError} = 1; + + print "Fields: ",scalar(&ora_fetch($csr)),"\n"; + die "ora_fetch in scalar context error\n" unless &ora_fetch($csr)==5; + print "Names: ",DBI::neat_list([&ora_titles($csr)], 0,"\t"),"\n"; + print "Lengths: ",DBI::neat_list([&ora_lengths($csr)],0,"\t"),"\n"; + print "OraTypes: ",DBI::neat_list([&ora_types($csr)], 0,"\t"),"\n"; + print "SQLTypes: ",DBI::neat_list($csr->{TYPE}, 0,"\t"),"\n"; + print "Scale: ",DBI::neat_list($csr->{SCALE}, 0,"\t"),"\n"; + print "Precision: ",DBI::neat_list($csr->{PRECISION}, 0,"\t"),"\n"; print "Est row width: $csr->{ora_est_row_width}\n"; - print "Prefetch cache: $csr->{ora_cache_rows}\n"; + print "Prefetch cache: $csr->{RowsInCache}\n" if $csr->{RowsInCache}; print "Data rows:\n"; #$csr->debug(2); - while(@fields = &ora_fetch($csr)) { - warn "ora_fetch returned .".@fields." fields instead of 4!" - if (@fields!=4); + while(@fields = $csr->fetchrow_array) { + die "ora_fetch returned .".@fields." fields instead of 5!" + if @fields != 5; die "Perl list/scalar context error" if @fields==1; - $fields[3] = "NULL" unless defined $fields[3]; - print " fetch: "; print "@fields\n"; + print " fetch: ", DBI::neat_list(\@fields),"\n"; } &ora_close($csr) || warn "ora_close($csr): $ora_errno: $ora_errstr\n"; @@ -231,10 +242,10 @@ sub test_cache { || die "ora_login: $ora_errno: $ora_errstr\n"; local($csr, $rows, $max); local($start) = time; - #$l->debug(3); + #$l->trace(3); foreach $max (1, 0, $cache-1, $cache, $cache+1) { $csr = &ora_open($l, q{ - select object_name from all_objects where rownum <= :1 + select object_name, rownum from all_objects where rownum <= :1 }, $cache); &ora_bind($csr, $max) || die $ora_errstr; $rows = count_fetch($csr); @@ -264,28 +275,23 @@ sub test_fetch_perf { print "\nTesting internal row fetch overhead.\n"; local($lda) = &ora_login($dbname, $dbuser, '') || die "ora_login: $ora_errno: $ora_errstr\n"; - #$lda->trace(2); $lda->trace(0); local($csr) = &ora_open($lda,"select 0,1,2,3,4,5,6,7,8,9 from dual"); - #local($csr) = &ora_open($lda,"select 9 from dual"); local($max) = 50000; $csr->{ora_fetchtest} = $max; require Benchmark; $t0 = new Benchmark; - #local($rows) = count_fetch($csr); die "count_fetch $rows != $max" if $rows-1 != $max; - my $code = $csr->can('fetch'); - #1 while &$code($csr); 1 while $csr->fetchrow_arrayref; - #1 while @row = $csr->fetchrow_array; - #while(@row = $csr->fetchrow_array) { $hash{++$i} = [ @row ]; } $td = Benchmark::timediff((new Benchmark), $t0); $csr->{ora_fetchtest} = 0; printf("$max fetches: ".Benchmark::timestr($td)."\n"); - printf("%d per clock second, %d per cpu second\n\n", $max/$td->real, $max/$td->cpu_a); + printf("%d per clock second, %d per cpu second\n\n", + $max/($td->real ? $td->real : 1), + $max/($td->cpu_a ? $td->cpu_a : 1)); } -sub test_other { +sub test_bind_csr { local($lda) = @_; $lda->{RaiseError} =1; $lda->trace(2); @@ -303,4 +309,25 @@ sub test_other { exit 1; } +sub test_auto_reprepare { + local($dbh) = @_; + $dbh->do(q{drop table timbo}); + $dbh->{RaiseError} =1; + #$dbh->trace(2); + $dbh->do(q{create table timbo ( foo integer)}); + $dbh->do(q{insert into timbo values (91)}); + $dbh->do(q{insert into timbo values (92)}); + $dbh->do(q{insert into timbo values (93)}); + $dbh->commit; + $Oraperl::ora_cache = $Oraperl::ora_cache = 1; + my $sth = $dbh->prepare(q{select * from timbo for update}); + $sth->execute; $sth->dump_results; + $sth->execute; + print $sth->fetchrow_array,"\n"; + $dbh->commit; + print $sth->fetchrow_array,"\n"; + $dbh->do(q{drop table timbo}); + exit 1; +} + # end. From 9aeb9aed86b9916fb1b3d0e6a17fcc819f2074b3 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Wed, 2 Dec 1998 03:24:49 -0500 Subject: [PATCH 035/637] import DBD-Oracle 0.54_91 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.54_91 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.54_91.tar.gz --- Oracle.pm | 6 +-- dbdimp.c | 8 ++- dbdimp.h | 23 ++++++--- oci8.h | 152 +++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 149 insertions(+), 40 deletions(-) diff --git a/Oracle.pm b/Oracle.pm index b3e2a5ce..4e1cceba 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.58 1998/11/29 00:14:07 timbo Exp $ +# $Id: Oracle.pm,v 1.59 1998/12/02 02:48:32 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.54_90'; +$DBD::Oracle::VERSION = '0.54_91'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -22,7 +22,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; use Exporter (); @ISA = qw(DynaLoader Exporter); - my $Revision = substr(q$Revision: 1.58 $, 10); + my $Revision = substr(q$Revision: 1.59 $, 10); require_version DBI 0.92; diff --git a/dbdimp.c b/dbdimp.c index c29d7a85..e6393a84 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.41 1998/11/29 00:14:07 timbo Exp $ + $Id: dbdimp.c,v 1.42 1998/12/02 02:48:32 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -12,7 +12,7 @@ #include "Oracle.h" -#if !defined(dirty) && !defined(PL_dirty) +#if PATCHLEVEL < 5 && !defined(PL_dirty) #define PL_dirty dirty #endif @@ -1382,6 +1382,10 @@ dbd_st_destroy(sth, imp_sth) if (fbh->fb_ary) fb_ary_free(fbh->fb_ary); sv_free(fbh->name_sv); +#ifdef OCI_V8_SYNTAX + if (fbh->descriptorh) + OCIDescriptorFree(fbh->descriptorh, fbh->descriptort); +#endif } Safefree(imp_sth->fbh); Safefree(imp_sth->statement); diff --git a/dbdimp.h b/dbdimp.h index 2f6953a3..a6de35b6 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,7 +1,7 @@ /* - $Id: dbdimp.h,v 1.23 1998/11/29 00:14:07 timbo Exp $ + $Id: dbdimp.h,v 1.24 1998/12/02 02:48:32 timbo Exp $ - Copyright (c) 1994,1995 Tim Bunce + Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file, @@ -11,6 +11,11 @@ */ +#if PATCHLEVEL < 5 && !defined(PL_dirty) +#define PL_dirty dirty +#endif + + /* try uncommenting this line if you get a syntax error on * typedef signed long sbig_ora; * in oratypes.h for Oracle 7.1.3. Don't you just love Oracle! @@ -43,9 +48,10 @@ #if defined(SQLT_NTY) && !defined(NO_OCI8) /* use Oracle 8 */ -#ifdef dirty -#undef dirty /* appears in OCI prototypes as parameter name */ -#endif +/* ori.h uses 'dirty' as an arg name in prototypes so we use this */ +/* hack to prevent ori.h being read (since we don't need it) */ +#define ORI_ORACLE + #include #else /* use Oracle 7 */ @@ -123,6 +129,7 @@ struct imp_sth_st { imp_fbh_t *fbh; /* array of imp_fbh_t structs */ char *fbh_cbuf; /* memory for all field names */ int t_dbsize; /* raw data width of a row */ + IV long_readlen; /* local copy to handle oraperl */ /* Select Row Cache Details */ int cache_rows; @@ -147,12 +154,16 @@ struct fb_ary_st { /* field buffer array EXPERIMENTAL */ }; struct imp_fbh_st { /* field buffer EXPERIMENTAL */ - imp_sth_t *imp_sth; /* 'parent' statement */ + imp_sth_t *imp_sth; /* 'parent' statement */ + int field_num; /* 0..n-1 */ /* Oracle's description of the field */ #ifdef OCI_V8_SYNTAX OCIParam *parmdp; OCIDefine *defnp; + void *descriptorh; /* descriptor if needed (LOBs etc) */ + ub4 descriptort; /* OCI type of descriptorh */ + int (*fetch_func) _((SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv)); ub2 dbsize; ub2 dbtype; /* actual type of field (see ftype) */ ub1 prec; diff --git a/oci8.h b/oci8.h index 0113eabc..de67cc66 100644 --- a/oci8.h +++ b/oci8.h @@ -1,5 +1,5 @@ /* - $Id: oci8.h,v 1.2 1998/11/29 00:14:07 timbo Exp $ + $Id: oci8.h,v 1.3 1998/12/02 02:48:32 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -113,13 +113,79 @@ oci_error(h, errhp, status, what) } +int fetch_func_lob(sth, imp_sth, fbh, dest_sv) + SV *sth; + imp_sth_t *imp_sth; + imp_fbh_t *fbh; + SV *dest_sv; +{ + char *hint = ""; + ub4 loblen = 0; + ub4 getlen; + ub4 amtp = 0; + OCILobLocator *lobl = (OCILobLocator*)fbh->descriptorh; + sword status; + + status = OCILobGetLength(imp_sth->svchp, imp_sth->errhp, lobl, &loblen); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCILobGetLength"); + return 0; + } + + getlen = imp_sth->long_readlen; + if (loblen < getlen) + getlen = loblen; + amtp = getlen; /* set right semantics */ + + SvUPGRADE(dest_sv, SVt_PV); + SvGROW(dest_sv, getlen+1); + + status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobl, + &amtp, 1, + SvPVX(dest_sv), getlen, + (dvoid *)0, (sb4 (*)(dvoid *, const dvoid *, ub4, ub1)) 0, + (ub2) 0, (ub1) SQLCS_IMPLICIT); + if (dbis->debug >= 3) + fprintf(DBILOGFP, " OCILobRead %s: %ld/%ld/%ld\n", + oci_status_name(status), getlen, amtp, imp_sth->long_readlen); + if (status == OCI_NEED_DATA) { + int oraperl = DBIc_COMPAT(imp_sth); + if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { + /* user says truncation is ok */ + /* Oraperl recorded the truncation in ora_errno so we */ + /* so also but only for Oraperl mode handles. */ + if (oraperl) + sv_setiv(DBIc_ERR(imp_sth), 1406); + status = OCI_SUCCESS; /* but don't provoke an error here */ + } + else { + /* else fall through and let status trigger failure below */ + hint = ", LongReadLen too small and/or LongTruncOk not set"; + } + } + if (status != OCI_SUCCESS) { + char buf[300]; + sprintf(buf,"OCILobRead of %ld bytes on field %d of %d%s", + getlen, fbh->field_num+1, DBIc_NUM_FIELDS(imp_sth), hint); + oci_error(sth, imp_sth->errhp, status, buf); + return 0; + } + /* tell perl what we've put in its dest_sv */ + SvCUR(dest_sv) = amtp; + *SvEND(dest_sv) = '\0'; + SvPOK_on(dest_sv); + + return 1; +} + + int dbd_describe(h, imp_sth) SV *h; imp_sth_t *imp_sth; { D_imp_dbh_from_sth; - I32 long_buflen; + I32 long_readlen; ub4 num_fields; int has_longs = 0; int est_width = 0; /* estimated avg row width (for cache) */ @@ -132,12 +198,12 @@ dbd_describe(h, imp_sth) imp_sth->done_desc = 1; /* ora_trunc is checked at fetch time */ - /* long_buflen: length for long/longraw (if >0), else 80 (ora app dflt) */ + /* long_readlen: length for long/longraw (if >0), else 80 (ora app dflt) */ /* Ought to be for COMPAT mode only but was relaxed before LongReadLen existed */ - long_buflen = (SvOK(ora_long) && SvIV(ora_long)>0) + long_readlen = (SvOK(ora_long) && SvIV(ora_long)>0) ? SvIV(ora_long) : DBIc_LongReadLen(imp_sth); - if (long_buflen < 0) /* trap any sillyness */ - long_buflen = 80; /* typical oracle app default */ + if (long_readlen < 0) /* trap any sillyness */ + long_readlen = 80; /* typical oracle app default */ if (imp_sth->stmt_type != OCI_STMT_SELECT) { if (dbis->debug >= 2) @@ -150,7 +216,7 @@ dbd_describe(h, imp_sth) if (dbis->debug >= 2) fprintf(DBILOGFP, " dbd_describe %s (%s, lb %ld)...\n", oci_stmt_type_name(imp_sth->stmt_type), - DBIc_ACTIVE(imp_sth) ? "implicit" : "EXPLICIT", (long)long_buflen); + DBIc_ACTIVE(imp_sth) ? "implicit" : "EXPLICIT", (long)long_readlen); /* We know it's a select and we've not got the description yet, so if the */ /* sth is not 'active' (executing) then we need an explicit describe. */ @@ -176,7 +242,8 @@ dbd_describe(h, imp_sth) for(i = 1; i <= num_fields; ++i) { ub4 atrlen; imp_fbh_t *fbh = &imp_sth->fbh[i-1]; - fbh->imp_sth = imp_sth; + fbh->imp_sth = imp_sth; + fbh->field_num = i; status = OCIParamGet(imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, (dvoid*)&fbh->parmdp, (ub4)i); @@ -219,12 +286,12 @@ dbd_describe(h, imp_sth) case 8: /* LONG */ fbh->disize = fbh->dbsize; - fbh->dbsize = long_buflen; + fbh->dbsize = long_readlen; fbh->ftype = 8; break; case 24: /* LONG RAW */ fbh->disize = fbh->dbsize; - fbh->dbsize = long_buflen * 2; + fbh->dbsize = long_readlen * 2; fbh->ftype = 24; break; @@ -235,13 +302,26 @@ dbd_describe(h, imp_sth) fbh->disize = 20; break; + case 112: /* CLOB */ + case 113: /* BLOB */ + fbh->ftype = fbh->dbtype; + fbh->disize = fbh->dbsize; + fbh->fetch_func = fetch_func_lob; + fbh->descriptort = OCI_DTYPE_LOB; + status = OCIDescriptorAlloc(imp_dbh->envhp, (dvoid **)&fbh->descriptorh, + fbh->descriptort, 0, 0); + if (status != OCI_SUCCESS) { + oci_error(h, imp_sth->errhp, status, "OCIDescriptorAlloc"); + return 0; + } + break; + case 105: /* MLSLABEL */ case 108: /* User Defined */ case 111: /* REF */ - case 112: /* CLOB */ - case 113: /* BLOB */ default: fbh->disize = fbh->dbsize; + /* XXX unhandled type may lead to core dump */ break; } @@ -255,7 +335,7 @@ dbd_describe(h, imp_sth) /* each field (and thus row) to determine a 'good' cache size. */ if (fbh->dbsize==0) { /* is a LONG type or 'select NULL' */ if (dbtype_is_long(fbh->dbtype)) { - est_width += long_buflen; + est_width += long_readlen; ++has_longs; /* hint to auto cache sizing code */ } } @@ -297,6 +377,7 @@ dbd_describe(h, imp_sth) &cache_mem, 0, OCI_ATTR_PREFETCH_MEMORY, imp_dbh->errhp); } + imp_sth->long_readlen = long_readlen; /* Initialise cache counters */ imp_sth->in_cache = 0; imp_sth->eod_errno = 0; @@ -305,14 +386,14 @@ dbd_describe(h, imp_sth) imp_fbh_t *fbh = &imp_sth->fbh[i-1]; fb_ary_t *fb_ary; - fbh->fb_ary = fb_ary = fb_ary_alloc( - fbh->disize+1, /* +1: STRING null terminator */ - 1); + fbh->fb_ary = fb_ary_alloc(fbh->disize+1 /* +1: STRING null terminator */, 1); + fb_ary = fbh->fb_ary; status = OCIDefineByPos(imp_sth->stmhp, &fbh->defnp, imp_sth->errhp, (ub4) i, - fb_ary->abuf, fbh->disize, /* valuep, value_sz */ - fbh->ftype, - fb_ary->aindp, fb_ary->arlen, fb_ary->arcode, OCI_DEFAULT); + (fbh->descriptorh) ? (dvoid*)&fbh->descriptorh : (dvoid*)fb_ary->abuf, + (fbh->descriptorh) ? -1 : fbh->disize, + fbh->ftype, + fb_ary->aindp, fb_ary->arlen, fb_ary->arcode, OCI_DEFAULT); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIDefineByPos"); return 0; @@ -355,6 +436,8 @@ dbd_st_fetch(sth, imp_sth) status = OCI_SUCCESS; } else { + if (dbis->debug >= 3) + fprintf(DBILOGFP, " dbd_st_fetch %d fields...\n", DBIc_NUM_FIELDS(imp_sth)); status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT); } if (status != OCI_SUCCESS) { @@ -389,8 +472,9 @@ dbd_st_fetch(sth, imp_sth) int rc = fb_ary->arcode[cache_entry]; SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */ - if (rc == 1406 && dbtype_is_long(fbh->dbtype)) { - /* We have a LONG field which has been truncated. */ + if (rc == 1406 /* field was truncated */ + && dbtype_is_long(fbh->dbtype) /* field is a LONG */ + ) { int oraperl = DBIc_COMPAT(imp_sth); if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { /* user says truncation is ok */ @@ -404,14 +488,24 @@ dbd_st_fetch(sth, imp_sth) } if (rc == 0) { /* the normal case */ - int datalen = fb_ary->arlen[cache_entry]; - char *p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; - /* if ChopBlanks check for Oracle CHAR type (blank padded) */ - if (ChopBlanks && fbh->dbtype == 96) { - while(datalen && p[datalen - 1]==' ') - --datalen; + if (fbh->ftype == 5) { + int datalen = fb_ary->arlen[cache_entry]; + char *p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; + /* if ChopBlanks check for Oracle CHAR type (blank padded) */ + if (ChopBlanks && fbh->dbtype == 96) { + while(datalen && p[datalen - 1]==' ') + --datalen; + } + sv_setpvn(sv, p, (STRLEN)datalen); + } + else if (fbh->descriptorh) { + if (!fbh->fetch_func(sth, imp_sth, fbh, sv)) + ++err; /* fetch_func already called oci_error */ + } + else { + ++err; + oci_error(sth, imp_sth->errhp, OCI_ERROR, "panic: unhandled field type"); } - sv_setpvn(sv, p, (STRLEN)datalen); } else if (rc == 1405) { /* field is null - return undef */ (void)SvOK_off(sv); @@ -420,7 +514,7 @@ dbd_st_fetch(sth, imp_sth) char buf[200]; char *hint = ""; /* These may get more case-by-case treatment eventually. */ - if (rc == 1406) { /* field truncated (see above) */ + if (rc == 1406 && fbh->ftype == 5) { /* field truncated (see above) */ /* Copy the truncated value anyway, it may be of use, */ /* but it'll only be accessible via prior bind_column() */ sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], From f901999658ed0cd047cf816ac740c98af150d00a Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Wed, 9 Dec 1998 20:52:25 -0500 Subject: [PATCH 036/637] import DBD-Oracle 0.54_92 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.54_92 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.54_92.tar.gz --- Makefile.PL | 20 ++- Oracle.pm | 27 +++- Oracle.xs | 34 +++++ dbdimp.c | 180 ++++++++++++++++------ dbdimp.h | 77 ++-------- oci8.h | 428 ++++++++++++++++++++++++++++++++++++++++++++++------ 6 files changed, 603 insertions(+), 163 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index cf9cf1f3..1c91356c 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.69 1998/11/29 00:14:07 timbo Exp $ +# $Id: Makefile.PL,v 1.70 1998/12/10 01:19:19 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -141,30 +141,35 @@ if ($os eq 'VMS') { elsif ($os eq 'MSWin32') { my $OCIDIR = ""; + my $OCILIB = "OCI"; + if ($::opt_8) { # opt_8 means DISABLE use of OCI 8 API + $OCILIB = "OCIW32"; + } find( sub { print "Found $_\n" if /^OCI\d+/i; $OCIDIR = $_ if /^OCI\d\d$/i && $OCIDIR lt $_; $File::Find::prune = 1 if -d $_ && $_ ne "." && $_ ne ".."; }, $OH ); - print "Using OCI directory: $OCIDIR\n"; + print "Using $OCILIB in directory: $OCIDIR\n"; my $oci_compiler_dir = ($Config{cc} eq 'bcc32' ? "BORLAND" : "MSVC"); + die qq{ Unable to find required Oracle OCI files for the build. Please check that you have your OCI installed in your oracle home ($OH) directory and that it has the following files (and probably more): $OH\\$OCIDIR\\include\\oratypes.h - $OH\\$OCIDIR\\lib\\$oci_compiler_dir\\ociw32.lib + $OH\\$OCIDIR\\lib\\$oci_compiler_dir\\$OCILIB.lib Please install OCI or send comments back to dbi-users\@fugue.com you have an OCI directory other than $OCIDIR. } unless (-e "$OH/$OCIDIR/include/oratypes.h" - && -e "$OH/$OCIDIR/lib/$oci_compiler_dir/ociw32.lib"); + && -e "$OH/$OCIDIR/lib/$oci_compiler_dir/$OCILIB.lib"); my $OCIINCLUDE = "-I$OH/$OCIDIR/include -I$OH/rdbms/demo"; - $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/$oci_compiler_dir OCIW32" ]; + $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/$oci_compiler_dir $OCILIB" ]; #$opts{SKIP} = ['processPL']; # XXX added because it caused problems with Nmake... $opts{INC} = "$OCIINCLUDE -I$dbi_arch_dir"; } @@ -544,7 +549,10 @@ sub fetch_oci_macros { if (!$linkvia && ($MK{OCISHAREDLIBS} || $MK{OCISTATICLIBS})) { $linkvia = ''; if ($MK{OCISTATICLIBS} && - (($opts{LINKTYPE}||'') eq 'static' || $::opt_c)) { + ( ($opts{LINKTYPE}||'') eq 'static' + || "@ARGV" =~ m/\bLINKTYPE=static\b/ + || $::opt_c) + ) { $linkvia .= '$(DEF_ON) ' if $MK{DEF_ON}; $linkvia .= '$(SSCOREED) ' if $MK{SSCOREED}; $linkvia .= '$(OCISTATICLIBS)'; diff --git a/Oracle.pm b/Oracle.pm index 4e1cceba..d70a0ce1 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.59 1998/12/02 02:48:32 timbo Exp $ +# $Id: Oracle.pm,v 1.60 1998/12/10 01:19:19 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.54_91'; +$DBD::Oracle::VERSION = '0.54_92'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -21,10 +21,19 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; use DynaLoader (); use Exporter (); @ISA = qw(DynaLoader Exporter); + %EXPORT_TAGS = ( + ora_types => [ qw( + ORA_VARCHAR2 ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE + ORA_RAW ORA_LONGRAW ORA_CHAR ORA_MLSLABEL ORA_NTY + ORA_CLOB ORA_BLOB + ) ], + ); + Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.59 $, 10); - require_version DBI 0.92; + my $Revision = substr(q$Revision: 1.60 $, 10); + + require_version DBI 1.02; bootstrap DBD::Oracle $VERSION; @@ -128,9 +137,15 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; sub connect { - my($drh, $dbname, $user, $auth)= @_; + my ($drh, $dbname, $user, $auth)= @_; + + # If the application is asking for specific database + # then we have to mung the - if ($dbname){ # application is asking for specific database + if (DBD::Oracle::OCI() >= 8) { + $dbname = $1 if !$dbname && $user =~ s/\@(.*)//; + } + elsif ($dbname) { # We can use the 'user/passwd@machine' form of user. # $TWO_TASK and $ORACLE_SID will be ignored in that case. diff --git a/Oracle.xs b/Oracle.xs index 39fb88b4..75b59f2f 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -4,6 +4,40 @@ DBISTATE_DECLARE; MODULE = DBD::Oracle PACKAGE = DBD::Oracle +I32 +constant() + PROTOTYPE: + ALIAS: + OCI = 0 + ORA_VARCHAR2= 1 + ORA_NUMBER = 2 + ORA_LONG = 8 + ORA_ROWID = 11 + ORA_DATE = 12 + ORA_RAW = 23 + ORA_LONGRAW = 24 + ORA_CHAR = 96 + ORA_MLSLABEL= 105 + ORA_NTY = 108 + ORA_CLOB = 112 + ORA_BLOB = 113 + CODE: + if (!ix) { + char *what = GvNAME(CvGV(cv)); + if (strEQ(what,"OCI")) +#ifdef OCI_V8_SYNTAX + RETVAL = 8; +#else + RETVAL = 7; +#endif + else croak("Unknown DBD::Oracle constant '%s'", what); + } + else RETVAL = ix; + OUTPUT: + RETVAL + +MODULE = DBD::Oracle PACKAGE = DBD::Oracle + INCLUDE: Oracle.xsi MODULE = DBD::Oracle PACKAGE = DBD::Oracle::st diff --git a/dbdimp.c b/dbdimp.c index e6393a84..594533e6 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.42 1998/12/02 02:48:32 timbo Exp $ + $Id: dbdimp.c,v 1.43 1998/12/10 01:19:19 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -21,10 +21,6 @@ (SvROK(h) && SvTYPE(SvRV(h)) == SVt_PVHV && \ SvRMAGICAL(SvRV(h)) && (SvMAGIC(SvRV(h)))->mg_type == 'P') -#define OCIAttrGet_stmhp(imp_sth, p, l, a) \ - OCIAttrGet(imp_sth->stmhp, OCI_HTYPE_STMT, (dvoid*)(p), (l), (a), imp_sth->errhp); -#define OCIAttrGet_parmdp(imp_sth, parmdp, p, l, a) \ - OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (dvoid*)(p), (l), (a), imp_sth->errhp); DBISTATE_DECLARE; @@ -42,6 +38,8 @@ static void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); static int ora2sql_type _((int oratype)); static int calc_cache_rows _((int f, int ew, int cr, int hl)); +void ora_free_fbh_contents(imp_fbh_t *fbh); +void ora_free_phs_contents(phs_t *phs); void dbd_init(dbistate) @@ -52,6 +50,11 @@ dbd_init(dbistate) ora_trunc = perl_get_sv("Oraperl::ora_trunc", GV_ADDMULTI); ora_cache = perl_get_sv("Oraperl::ora_cache", GV_ADDMULTI); ora_cache_o = perl_get_sv("Oraperl::ora_cache_o", GV_ADDMULTI); +#ifdef USE_V8_SYNTAX + sv_setiv(perl_get_sv("DBD::Oracle::OCI", GV_ADDMULTI), 8); +#else + sv_setiv(perl_get_sv("DBD::Oracle::OCI", GV_ADDMULTI), 7); +#endif ora_pad_empty= perl_get_sv("Oraperl::ora_pad_empty", GV_ADDMULTI); if (!SvOK(ora_pad_empty) && getenv("ORAPERL_PAD_EMPTY")) @@ -139,6 +142,8 @@ oratype_bind_ok(dbtype) /* It's a type we support for placeholders */ #ifdef SQLT_CUR case SQLT_CUR: /* cursor variable */ #endif + case 112: /* SQLT_CLOB */ + case 113: /* SQLT_BLOB */ return 1; } return 0; @@ -203,13 +208,17 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) D_imp_drh_from_dbh; if (!imp_drh->envhp) { - OCIInitialize((ub4) OCI_DEFAULT, 0, 0,0,0); + /* OCI_OBJECT mode needed for OCIDescribeAny (even if not */ + /* describing anything related to or using objects). */ + /* If you don't you get a core dump (8.0.4). Thanks Oracle! */ + OCIInitialize((ub4) OCI_OBJECT, 0, 0,0,0); ret = OCIEnvInit( &imp_drh->envhp, OCI_DEFAULT, 0, 0 ); } imp_dbh->envhp = imp_drh->envhp; - OCIHandleAlloc(imp_dbh->envhp, (dvoid**)&imp_dbh->errhp, OCI_HTYPE_ERROR, 0,0); - OCIHandleAlloc(imp_dbh->envhp, (dvoid**)&imp_dbh->srvhp, OCI_HTYPE_SERVER,0,0); + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR); + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER); + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX); /* OCI 8 does not seem to allow uid to be "name/pass" :-( */ /* so we have to split it up ourselves */ @@ -226,16 +235,15 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) if (ret != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, ret, "OCIServerAttach"); OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); + OCIHandleFree(imp_dbh->svchp, OCI_HTYPE_SVCCTX); OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); return 0; } - OCIHandleAlloc(imp_dbh->envhp, (dvoid**)&imp_dbh->svchp, OCI_HTYPE_SVCCTX,0,0); OCIAttrSet( imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp); - OCIHandleAlloc(imp_dbh->envhp, (dvoid **)&imp_dbh->authp, - (ub4) OCI_HTYPE_SESSION, 0,0); + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_SESSION); OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, uid, strlen(uid), (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp); @@ -531,6 +539,7 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) #ifdef OCI_V8_SYNTAX + imp_sth->envhp = imp_dbh->envhp; imp_sth->errhp = imp_dbh->errhp; imp_sth->srvhp = imp_dbh->srvhp; imp_sth->svchp = imp_dbh->svchp; @@ -543,7 +552,7 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) default: oparse_lng = OCI_NTV_SYNTAX; break; } - OCIHandleAlloc(imp_dbh->envhp, (dvoid**)&imp_sth->stmhp, OCI_HTYPE_STMT, 0,0); + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_sth->stmhp, OCI_HTYPE_STMT); status = OCIStmtPrepare(imp_sth->stmhp, imp_sth->errhp, imp_sth->statement, (ub4)strlen(imp_sth->statement), oparse_lng, OCI_DEFAULT); @@ -745,7 +754,7 @@ ora_sql_type(imp_sth, name, sql_type) -static void +static int _rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) SV *sth; imp_sth_t *imp_sth; @@ -758,12 +767,17 @@ _rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) /* sv_insert +4 */ /* sv_chop(phs->sv, SvPV(phs->sv,na)+4); XXX */ + /* convert to a string ASAP */ + if (!SvPOK(phs->sv) && SvOK(phs->sv)) + sv_2pv(phs->sv, &na); + if (dbis->debug >= 2) { char *val = neatsvpv(phs->sv,0); fprintf(DBILOGFP, " bind %s <== %s (", phs->name, val); if (SvOK(phs->sv)) - fprintf(DBILOGFP, "size %ld/%ld/%ld, ", + fprintf(DBILOGFP, "size %ld/%ld/%ld, ", (long)SvCUR(phs->sv),(long)SvLEN(phs->sv),phs->maxlen); + else fprintf(DBILOGFP, "NULL, "); fprintf(DBILOGFP, "ptype %ld, otype %d%s)\n", SvTYPE(phs->sv), phs->ftype, (phs->is_inout) ? ", inout" : ""); @@ -806,7 +820,9 @@ _rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) phs->progv = SvPV(phs->sv, value_len); } phs->sv_type = SvTYPE(phs->sv); /* part of mutation check */ - phs->maxlen = SvLEN(phs->sv)-1; /* avail buffer space */ + phs->maxlen = SvLEN(phs->sv)-1; /* avail buffer space */ + if (phs->maxlen < 0) /* can happen with nulls */ + phs->maxlen = 0; if (value_len + phs->alen_incnull <= UB2MAXVAL) { phs->alen = value_len + phs->alen_incnull; @@ -827,11 +843,12 @@ _rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) phs->alen, (long)phs->maxlen, phs->ftype, phs->indp); } + return 1; } #ifdef SQLT_CUR -static void +static int _rebind_ph_cursor(sth, imp_sth, phs) SV *sth; imp_sth_t *imp_sth; @@ -858,6 +875,35 @@ _rebind_ph_cursor(sth, imp_sth, phs) #else die("Cursor variables not yet supported"); #endif + return 1; +} +#endif + + +#ifdef SQLT_CLOB +static int +_rebind_ph_lob(sth, imp_sth, phs) + SV *sth; + imp_sth_t *imp_sth; + phs_t *phs; +{ + sword status; + ub4 lobEmpty = 0; + + if (!phs->desc_h) { + ++imp_sth->has_lobs; + phs->desc_t = OCI_DTYPE_LOB; + OCIDescriptorAlloc_ok(imp_sth->envhp, + &phs->desc_h, phs->desc_t); + } + status = OCIAttrSet(phs->desc_h, phs->desc_t, + &lobEmpty, 0, OCI_ATTR_LOBEMPTY, imp_sth->errhp); + if (status != OCI_SUCCESS) + return oci_error(sth, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_LOBEMPTY"); + phs->progv = (void*)&phs->desc_h; + phs->maxlen = sizeof(OCILobLocator*); + + return 1; } #endif @@ -871,16 +917,26 @@ _dbd_rebind_ph(sth, imp_sth, phs) ub2 *alen_ptr = NULL; #ifdef OCI_V8_SYNTAX sword status; - ub4 *aryelem_cur_ptr = NULL; #endif + switch (phs->ftype) { #ifdef SQLT_CUR - if (phs->ftype == SQLT_CUR) { - _rebind_ph_cursor(sth, imp_sth, phs); - } - else + case SQLT_CUR: + if (!_rebind_ph_cursor(sth, imp_sth, phs)) + return 0; + break; #endif - _rebind_ph_char(sth, imp_sth, phs, &alen_ptr); +#ifdef SQLT_CLOB + case SQLT_CLOB: + case SQLT_BLOB: + if (!_rebind_ph_lob(sth, imp_sth, phs)) + return 0; + break; +#endif + default: + if (!_rebind_ph_char(sth, imp_sth, phs, &alen_ptr)) + return 0; + } /* Since we don't support LONG VAR types we must check */ /* for lengths too big to pass to obndrv as an sword. */ @@ -895,7 +951,7 @@ _dbd_rebind_ph(sth, imp_sth, phs) phs->ftype, &phs->indp, alen_ptr, &phs->arcode, phs->aryelem_max, /* max elements that can fit in allocated array */ - aryelem_cur_ptr, /* (ptr to) current number of elements in array */ + NULL, /* (ptr to) current number of elements in array */ OCI_DEFAULT); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); @@ -913,6 +969,8 @@ _dbd_rebind_ph(sth, imp_sth, phs) return 0; } #endif + if (dbis->debug >= 3) + fprintf(DBILOGFP, " bind %s done\n", phs->name); return 1; } @@ -997,6 +1055,10 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl if (sql_type) croak("Can't specify both TYPE (%d) and ora_type (%d) for %s", sql_type, ora_type, phs->name); +#ifndef OCI_V8_SYNTAX /* treat Oracle8 LOBS as simple LONGs for Oracle7 */ + if (ora_type==112 || ora_type==113) + ora_type = 8; +#endif phs->ftype = ora_type; } } @@ -1049,8 +1111,8 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count int is_select = (imp_sth->stmt_type == OCI_STMT_SELECT); if (debug >= 2) - fprintf(DBILOGFP, " dbd_st_execute %s (out%d)...\n", - oci_stmt_type_name(imp_sth->stmt_type), outparams); + fprintf(DBILOGFP, " dbd_st_execute %s (out%d, lob%d)...\n", + oci_stmt_type_name(imp_sth->stmt_type), outparams, imp_sth->has_lobs); #else if (!imp_sth->done_desc) { @@ -1061,7 +1123,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count if (debug >= 2) fprintf(DBILOGFP, " dbd_st_execute (for sql f%d after oci f%d, out%d)...\n", - imp_sth->cda->ft, imp_sth->cda->fc, outparams); + imp_sth->cda->ft, imp_sth->cda->fc, outparams); #endif if (outparams) { /* check validity of bind_param_inout SV's */ @@ -1123,7 +1185,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count ub2 sqlfncode; OCIAttrGet_stmhp(imp_sth, &sqlfncode, 0, OCI_ATTR_SQLFNCODE); fprintf(DBILOGFP, - " dbd_st_execute %s ok (%s, rpc%ld, fn%d, out%d)\n", + " dbd_st_execute %s returned (%s, rpc%ld, fn%d, out%d)\n", oci_stmt_type_name(imp_sth->stmt_type), oci_status_name(status), row_count, sqlfncode, imp_sth->has_inout_params); @@ -1132,7 +1194,11 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count if (is_select && !imp_sth->done_desc) { /* describe and allocate storage for results (if any needed) */ if (!dbd_describe(sth, imp_sth)) - return -2; /* dbd_describe already called ora_error() */ + return -2; /* dbd_describe already called oci_error() */ + } + if (imp_sth->has_lobs && imp_sth->stmt_type == OCI_STMT_INSERT) { + if (!post_insert_lobs(sth, imp_sth)) + return -2; /* post_insert_lobs already called oci_error() */ } #else @@ -1321,11 +1387,22 @@ dbd_st_finish(sth, imp_sth) /* Cancel further fetches from this cursor. */ /* We don't close the cursor till DESTROY (dbd_st_destroy). */ /* The application may re execute(...) it. */ + + /* Turn off ACTIVE here regardless of errors below. */ + DBIc_ACTIVE_off(imp_sth); + #ifdef OCI_V8_SYNTAX - /* OCI 8 manual says there's no equiv of OCI7 ocan() */ - /* An OCIBreak() might be relevant */ +{ sword status; + /* OCI 8 manual says there's no equiv of OCI7 ocan() */ + /* But elsewhere says a OCIStmtFetch with nrows==0 does that */ + status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 0, OCI_FETCH_NEXT, OCI_DEFAULT); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "Finish OCIStmtFetch"); + return 0; + } +} #else - if (ocan(imp_sth->cda) ) { + if (ocan(imp_sth->cda)) { /* oracle 7.3 code can core dump looking up an error message */ /* if we have logged out of the database. This typically */ /* happens during global destruction. This should catch most: */ @@ -1337,11 +1414,33 @@ dbd_st_finish(sth, imp_sth) return 0; } #endif - DBIc_ACTIVE_off(imp_sth); return 1; } +void +ora_free_fbh_contents(imp_fbh_t *fbh) +{ + if (fbh->fb_ary) + fb_ary_free(fbh->fb_ary); + sv_free(fbh->name_sv); +#ifdef OCI_V8_SYNTAX + if (fbh->desc_h) + OCIDescriptorFree(fbh->desc_h, fbh->desc_t); +#endif +} + +void +ora_free_phs_contents(phs_t *phs) +{ +#ifdef OCI_V8_SYNTAX + if (phs->desc_h) + OCIDescriptorFree(phs->desc_h, phs->desc_t); +#endif + sv_free(phs->sv); +} + + void dbd_st_destroy(sth, imp_sth) SV *sth; @@ -1366,7 +1465,10 @@ dbd_st_destroy(sth, imp_sth) #ifdef OCI_V8_SYNTAX { - sword status = OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); + sword status; + if (imp_sth->lob_refetch) + ora_free_lob_refetch(imp_sth); + status = OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); if (status != OCI_SUCCESS) oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); } @@ -1379,13 +1481,7 @@ dbd_st_destroy(sth, imp_sth) imp_sth->eod_errno = 1403; for(i=0; i < fields; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i]; - if (fbh->fb_ary) - fb_ary_free(fbh->fb_ary); - sv_free(fbh->name_sv); -#ifdef OCI_V8_SYNTAX - if (fbh->descriptorh) - OCIDescriptorFree(fbh->descriptorh, fbh->descriptort); -#endif + ora_free_fbh_contents(fbh); } Safefree(imp_sth->fbh); Safefree(imp_sth->statement); @@ -1401,8 +1497,8 @@ dbd_st_destroy(sth, imp_sth) hv_iterinit(hv); while( (sv = hv_iternextsv(hv, &key, &retlen)) != NULL ) { if (sv != &sv_undef) { - phs_t *phs_tpl = (phs_t*)(void*)SvPVX(sv); - sv_free(phs_tpl->sv); + phs_t *phs = (phs_t*)(void*)SvPVX(sv); + ora_free_phs_contents(phs); } } sv_free((SV*)imp_sth->all_params_hv); diff --git a/dbdimp.h b/dbdimp.h index a6de35b6..38f2ea80 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.24 1998/12/02 02:48:32 timbo Exp $ + $Id: dbdimp.h,v 1.25 1998/12/10 01:19:19 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -103,16 +103,21 @@ struct imp_dbh_st { }; +typedef struct lob_refetch_st lob_refetch_t; + /* Define sth implementor data structure */ struct imp_sth_st { dbih_stc_t com; /* MUST be first element in structure */ #ifdef OCI_V8_SYNTAX - OCIError *errhp; /* copy of dbh pointer */ - OCIServer *srvhp; /* copy of dbh pointer */ - OCISvcCtx *svchp; /* copy of dbh pointer */ - OCIStmt *stmhp; - ub2 stmt_type; /* OCIAttrGet OCI_ATTR_STMT_TYPE */ + OCIEnv *envhp; /* copy of dbh pointer */ + OCIError *errhp; /* copy of dbh pointer */ + OCIServer *srvhp; /* copy of dbh pointer */ + OCISvcCtx *svchp; /* copy of dbh pointer */ + OCIStmt *stmhp; + ub2 stmt_type; /* OCIAttrGet OCI_ATTR_STMT_TYPE */ + int has_lobs; + lob_refetch_t *lob_refetch; #else Cda_Def *cda; /* currently just points to cdabuf below */ Cda_Def cdabuf; @@ -161,14 +166,15 @@ struct imp_fbh_st { /* field buffer EXPERIMENTAL */ #ifdef OCI_V8_SYNTAX OCIParam *parmdp; OCIDefine *defnp; - void *descriptorh; /* descriptor if needed (LOBs etc) */ - ub4 descriptort; /* OCI type of descriptorh */ + void *desc_h; /* descriptor if needed (LOBs etc) */ + ub4 desc_t; /* OCI type of descriptorh */ int (*fetch_func) _((SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv)); ub2 dbsize; ub2 dbtype; /* actual type of field (see ftype) */ ub1 prec; sb1 scale; ub1 nullok; + void *special; /* hook for special purposes (LOBs etc) */ #else sb4 dbsize; sb2 dbtype; /* actual type of field (see ftype) */ @@ -186,59 +192,6 @@ struct imp_fbh_st { /* field buffer EXPERIMENTAL */ fb_ary_t *fb_ary; /* field buffer array */ }; -/* Table 6-13 Attributes Belonging to Columns of Tables or Views - - Attribute Description Attribute - Datatype - OCI_ATTR_DATA_SIZE the maximum size of the column. This length is returned in - bytes and not characters for strings and raws. It returns 22 for - NUMBERs. - ub2 - OCI_ATTR_DATA_TYPE - the data type of the column. See "Note on Datatype Codes" - on page 6-4. - ub2 - OCI_ATTR_PRECISION - the precision of numeric columns. If a describe returns a value - of zero for precision or -127 for scale, this indicates that the - item being described is uninitialized; i.e., it is NULL in the data - dictionary. - ub1 - OCI_ATTR_SCALE - the scale of numeric columns. If a describe returns a value of - zero for precision or -127 for scale, this indicates that the - item being described is uninitialized; i.e., it is NULL in the data - dictionary. - sb1 - OCI_ATTR_IS_NULL - returns 0 if null values are not permitted for the column - ub1 - OCI_ATTR_TYPE_NAME - returns a string which is the type name. The returned value - will contain the type name if the data type is SQLT_NTY or - SQLT_REF. If the data type is SQLT_NTY, the name of the - named data type's type is returned. If the data type is - SQLT_REF, the type name of the named data type pointed to - by the REF is returned - text * - OCI_ATTR_SCHEMA_NAME - returns a string with the schema name under which the type - has been created - text * - OCI_ATTR_REF_TDO - the REF of the TDO for the type, if the column type is an - object type - OCIRef * - OCI_ATTR_CHARSET_ID - the character set id, if the column is of a string/character type - - ub2 - OCI_ATTR_CHARSET_FORM - the character set form, if the column is of a string/character - type - ub1 -*/ - typedef struct phs_st phs_t; /* scalar placeholder */ @@ -255,6 +208,8 @@ struct phs_st { /* scalar placeholder EXPERIMENTAL */ ub4 aryelem_cur; /* current elements in allocated array */ #ifdef OCI_V8_SYNTAX OCIBind *bndhp; + void *desc_h; /* descriptor if needed (LOBs etc) */ + ub4 desc_t; /* OCI type of desc_h */ #endif /* these will become an array one day */ diff --git a/oci8.h b/oci8.h index de67cc66..c2caf6a0 100644 --- a/oci8.h +++ b/oci8.h @@ -1,5 +1,5 @@ /* - $Id: oci8.h,v 1.3 1998/12/02 02:48:32 timbo Exp $ + $Id: oci8.h,v 1.4 1998/12/10 01:19:19 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -10,6 +10,18 @@ */ +#define OCIAttrGet_stmhp(imp_sth, p, l, a) \ + OCIAttrGet(imp_sth->stmhp, OCI_HTYPE_STMT, (dvoid*)(p), (l), (a), imp_sth->errhp) +#define OCIAttrGet_parmdp(imp_sth, parmdp, p, l, a) \ + OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (dvoid*)(p), (l), (a), imp_sth->errhp) + +#define OCIHandleAlloc_ok(envhp, p, t) \ + if (OCIHandleAlloc((envhp), (dvoid**)(p), (t), 0, 0)==OCI_SUCCESS) ; \ + else croak("OCIHandleAlloc (type %d) failed",t) +#define OCIDescriptorAlloc_ok(envhp, p, t) \ + if (OCIDescriptorAlloc((envhp), (dvoid**)(p), (t), 0, 0)==OCI_SUCCESS) ; \ + else croak("OCIDescriptorAlloc (type %d) failed",t) + static char * oci_status_name(status) @@ -123,7 +135,7 @@ int fetch_func_lob(sth, imp_sth, fbh, dest_sv) ub4 loblen = 0; ub4 getlen; ub4 amtp = 0; - OCILobLocator *lobl = (OCILobLocator*)fbh->descriptorh; + OCILobLocator *lobl = (OCILobLocator*)fbh->desc_h; sword status; status = OCILobGetLength(imp_sth->svchp, imp_sth->errhp, lobl, &loblen); @@ -132,23 +144,19 @@ int fetch_func_lob(sth, imp_sth, fbh, dest_sv) return 0; } - getlen = imp_sth->long_readlen; - if (loblen < getlen) - getlen = loblen; - amtp = getlen; /* set right semantics */ + getlen = (loblen > imp_sth->long_readlen) ? imp_sth->long_readlen : loblen; + amtp = getlen; /* set right semantics for OCILobRead */ SvUPGRADE(dest_sv, SVt_PV); SvGROW(dest_sv, getlen+1); status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobl, - &amtp, 1, - SvPVX(dest_sv), getlen, - (dvoid *)0, (sb4 (*)(dvoid *, const dvoid *, ub4, ub1)) 0, - (ub2) 0, (ub1) SQLCS_IMPLICIT); + &amtp, 1, SvPVX(dest_sv), getlen, 0, 0, 0, SQLCS_IMPLICIT); if (dbis->debug >= 3) - fprintf(DBILOGFP, " OCILobRead %s: %ld/%ld/%ld\n", + fprintf(DBILOGFP, " OCILobRead %s: %ld/%ld/%ld\n", oci_status_name(status), getlen, amtp, imp_sth->long_readlen); - if (status == OCI_NEED_DATA) { + + if (status == OCI_NEED_DATA) { /* LOB was truncated */ int oraperl = DBIc_COMPAT(imp_sth); if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { /* user says truncation is ok */ @@ -192,7 +200,6 @@ dbd_describe(h, imp_sth) int i = 0; sword status; - if (imp_sth->done_desc) return 1; /* success, already done it */ imp_sth->done_desc = 1; @@ -229,7 +236,7 @@ dbd_describe(h, imp_sth) } } - status = OCIAttrGet_stmhp(imp_sth, &num_fields, 0, OCI_ATTR_PARAM_COUNT) + status = OCIAttrGet_stmhp(imp_sth, &num_fields, 0, OCI_ATTR_PARAM_COUNT); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrGet OCI_ATTR_PARAM_COUNT"); return 0; @@ -241,6 +248,7 @@ dbd_describe(h, imp_sth) /* Get number of fields and space needed for field names */ for(i = 1; i <= num_fields; ++i) { ub4 atrlen; + int avg_width = 0; imp_fbh_t *fbh = &imp_sth->fbh[i-1]; fbh->imp_sth = imp_sth; fbh->field_num = i; @@ -277,6 +285,7 @@ dbd_describe(h, imp_sth) if (!fbh->scale && !fbh->prec) /* always 0! */ fbh->disize = 38 + 2; /* max prec */ else fbh->disize = fbh->prec + 2; /* sign + dot */ + avg_width = 4; /* > approx +/- 1_000_000 ? */ break; case 12: /* DATE */ @@ -290,6 +299,7 @@ dbd_describe(h, imp_sth) fbh->ftype = 8; break; case 24: /* LONG RAW */ + avg_width = fbh->dbsize; fbh->disize = fbh->dbsize; fbh->dbsize = long_readlen * 2; fbh->ftype = 24; @@ -306,14 +316,9 @@ dbd_describe(h, imp_sth) case 113: /* BLOB */ fbh->ftype = fbh->dbtype; fbh->disize = fbh->dbsize; - fbh->fetch_func = fetch_func_lob; - fbh->descriptort = OCI_DTYPE_LOB; - status = OCIDescriptorAlloc(imp_dbh->envhp, (dvoid **)&fbh->descriptorh, - fbh->descriptort, 0, 0); - if (status != OCI_SUCCESS) { - oci_error(h, imp_sth->errhp, status, "OCIDescriptorAlloc"); - return 0; - } + fbh->fetch_func = fetch_func_lob; + fbh->desc_t = OCI_DTYPE_LOB; + OCIDescriptorAlloc_ok(imp_dbh->envhp, &fbh->desc_h, fbh->desc_t); break; case 105: /* MLSLABEL */ @@ -327,33 +332,13 @@ dbd_describe(h, imp_sth) /* dbsize can be zero for 'select NULL ...' */ imp_sth->t_dbsize += fbh->dbsize; + if (!avg_width) + avg_width = fbh->dbsize; + imp_sth->est_width += avg_width; if (dbis->debug >= 2) fbh_dump(fbh, i, 0); - - /* now we calculate the approx average on-the-wire width of */ - /* each field (and thus row) to determine a 'good' cache size. */ - if (fbh->dbsize==0) { /* is a LONG type or 'select NULL' */ - if (dbtype_is_long(fbh->dbtype)) { - est_width += long_readlen; - ++has_longs; /* hint to auto cache sizing code */ - } - } - else /* deal with dbtypes with overblown dbsizes */ - switch(fbh->dbtype) { - case 1: /* VARCHAR2 - result of to_char() has dbsize==75 */ - /* for all but small strings we take off 25% */ - est_width += (fbh->dbsize < 32) ? fbh->dbsize : fbh->dbsize-(fbh->dbsize>>2); - break; - case 2: /* NUMBER - e.g., from a sum() or max(), dbsize==22 */ - /* Most numbers are _much_ smaller than 22 bytes */ - est_width += 4; /* > approx +/- 1_000_000 ? */ - break; - default: est_width += fbh->dbsize; - break; - } } - imp_sth->est_width = est_width; /* --- Setup the row cache for this query --- */ @@ -390,8 +375,8 @@ dbd_describe(h, imp_sth) fb_ary = fbh->fb_ary; status = OCIDefineByPos(imp_sth->stmhp, &fbh->defnp, imp_sth->errhp, (ub4) i, - (fbh->descriptorh) ? (dvoid*)&fbh->descriptorh : (dvoid*)fb_ary->abuf, - (fbh->descriptorh) ? -1 : fbh->disize, + (fbh->desc_h) ? (dvoid*)&fbh->desc_h : (dvoid*)fb_ary->abuf, + (fbh->desc_h) ? -1 : fbh->disize, fbh->ftype, fb_ary->aindp, fb_ary->arlen, fb_ary->arcode, OCI_DEFAULT); if (status != OCI_SUCCESS) { @@ -498,7 +483,7 @@ dbd_st_fetch(sth, imp_sth) } sv_setpvn(sv, p, (STRLEN)datalen); } - else if (fbh->descriptorh) { + else if (fbh->desc_h) { if (!fbh->fetch_func(sth, imp_sth, fbh, sv)) ++err; /* fetch_func already called oci_error */ } @@ -542,3 +527,350 @@ dbd_st_fetch(sth, imp_sth) } +#ifdef not_used_curently +static char * +rowid2hex(OCIRowid *rowid) +{ + int i; + SV *sv = sv_2mortal(newSVpv("",0)); + for (i = 0; i < OCI_ROWID_LEN; i++) { + char buf[6]; + sprintf(buf, "%02X ", (int)(((ub1*)rowid)[i])); + sv_catpv(sv, buf); + } + return SvPVX(sv); +} +#endif + + +static void * +alloc_via_sv(STRLEN len, SV **svp, int mortal) +{ + SV *sv = newSVpv("",0); + sv_grow(sv, len+1); + memset(SvPVX(sv), 0, len); + if (mortal) + sv_2mortal(sv); + if (svp) + *svp = sv; + return SvPVX(sv); +} + + +char * +find_ident_after(char *src, char *after, STRLEN *len, int copy) +{ + int seen_key = 0; + char *orig = src; + char *p; + while(*src) { + if (*src == '\'' || *src == '"') { + char delim = *src; + while(*src && *src != delim) ++src; + } + else if (*src == '-' && src[1] == '-') { + while(*src && *src != '\n') ++src; + } + else if (*src == '/' && src[1] == '*') { + while(*src && !(*src == '*' && src[1]=='/')) ++src; + } + else if (isALPHA(*src)) { + if (seen_key) { + char *start = src; + while(*src && (isALPHA(*src) || *src=='.')) + ++src; + *len = src - start; + if (copy) { + p = alloc_via_sv(*len, 0, 1); + strncpy(p, start, *len); + p[*len] = '\0'; + return p; + } + return start; + } + else if ( toLOWER(*src)==toLOWER(*after) + && (src==orig ? 1 : !isALPHA(src[-1])) + ) { + p = after; + while(*p && *src && toLOWER(*p)==toLOWER(*src)) + ++p, ++src; + if (!*p) + seen_key = 1; + } + ++src; + } + else + ++src; + } + return NULL; +} + + +struct lob_refetch_st { + SV *sql_select; + OCIStmt *stmthp; + OCIBind *bindhp; + OCIRowid *rowid; + OCIParam *parmdp_tmp; + OCIParam *parmdp_lob; + int num_fields; + SV *fbh_ary_sv; + imp_fbh_t *fbh_ary; +}; + + +static int +init_lob_refetch(SV *sth, imp_sth_t *imp_sth) +{ + SV *sv; + SV *sql_select; + HV *lob_cols_hv = NULL; + sword status; + OCIError *errhp = imp_sth->errhp; + OCIDescribe *dschp = NULL; + OCIParam *parmhp = NULL, *collisthd = NULL; + ub2 numcols = 0; + imp_fbh_t *fbh; + int unmatched_params; + I32 i; + char *p; + lob_refetch_t *lr = NULL; + + STRLEN tablename_len; + char *tablename = find_ident_after(imp_sth->statement, + "into", &tablename_len, 1); + if (!tablename) + return oci_error(sth, errhp, OCI_ERROR, + "Unable to parse table name for LOB refetch"); + + OCIHandleAlloc_ok(imp_sth->envhp, &dschp, OCI_HTYPE_DESCRIBE); + status = OCIDescribeAny(imp_sth->svchp, errhp, tablename, strlen(tablename), + OCI_OTYPE_NAME, 1, OCI_PTYPE_TABLE, dschp); + if (status != OCI_SUCCESS) { + OCIHandleFree(dschp, OCI_HTYPE_DESCRIBE); + return oci_error(sth, errhp, status, "OCIDescribeAny/LOB refetch"); + } + + status = OCIAttrGet(dschp, OCI_HTYPE_DESCRIBE, + &parmhp, 0, OCI_ATTR_PARAM, errhp) + || OCIAttrGet(parmhp, OCI_DTYPE_PARAM, + &numcols, 0, OCI_ATTR_NUM_COLS, errhp) + || OCIAttrGet(parmhp, OCI_DTYPE_PARAM, + &collisthd, 0, OCI_ATTR_LIST_COLUMNS, errhp); + if (status != OCI_SUCCESS) { + OCIHandleFree(dschp, OCI_HTYPE_DESCRIBE); + return oci_error(sth, errhp, status, "OCIDescribeAny/OCIAttrGet/LOB refetch"); + } + if (dbis->debug >= 3) + fprintf(DBILOGFP, " lob refetch from table %s, %d columns:\n", + tablename, numcols); + + for (i = 1; i <= numcols; i++) { + OCIParam *colhd; + ub2 col_dbtype; + text *col_name; + ub4 col_name_len; + if ((status=OCIParamGet(collisthd, OCI_DTYPE_PARAM, errhp, (dvoid**)&colhd, i))) + break; + if ((status=OCIAttrGet(colhd, OCI_DTYPE_PARAM, &col_dbtype, 0, + OCI_ATTR_DATA_TYPE, errhp))) + break; + if ((status=OCIAttrGet(colhd, OCI_DTYPE_PARAM, &col_name, &col_name_len, + OCI_ATTR_NAME, errhp))) + break; + if (dbis->debug >= 3) + fprintf(DBILOGFP, " lob refetch table col %d: '%.*s' otype %d\n", + (int)i, (int)col_name_len,col_name, col_dbtype); + if (col_dbtype != SQLT_CLOB && col_dbtype != SQLT_BLOB) + continue; + if (!lob_cols_hv) + lob_cols_hv = newHV(); + sv = newSViv(col_dbtype); + sv_setpvn(sv, col_name, col_name_len); + SvIOK_on(sv); /* what a wonderful hack! */ + hv_store(lob_cols_hv, col_name,col_name_len, sv,0); + } + if (status != OCI_SUCCESS) { + OCIHandleFree(dschp, OCI_HTYPE_DESCRIBE); + return oci_error(sth, errhp, status, + "OCIDescribeAny/OCIParamGet/OCIAttrGet/LOB refetch"); + } + if (!lob_cols_hv) + return oci_error(sth, errhp, OCI_ERROR, + "LOB refetch failed, no lobs in table"); + + /* our bind params are in imp_sth->all_params_hv + our table cols are in lob_cols_hv + we now iterate through our bind params + and allocate them to the appropriate table columns + */ + Newz(1, lr, 1, lob_refetch_t); + unmatched_params = 0; + lr->num_fields = 0; + lr->fbh_ary = alloc_via_sv(sizeof(imp_fbh_t) * HvFILL(lob_cols_hv)+1, + &lr->fbh_ary_sv, 0); + + sql_select = newSVpv("select ",0); + + hv_iterinit(imp_sth->all_params_hv); + while( (sv = hv_iternextsv(imp_sth->all_params_hv, &p, &i)) != NULL ) { + int matched = 0; + phs_t *phs = (phs_t*)(void*)SvPVX(sv); + if (sv == &sv_undef || !phs) + croak("panic: unbound params"); + if (phs->ftype != SQLT_CLOB && phs->ftype != SQLT_BLOB) + continue; + hv_iterinit(lob_cols_hv); + while( (sv = hv_iternextsv(lob_cols_hv, &p, &i)) != NULL ) { + char sql_field[200]; + if (SvIV(sv) != phs->ftype) + continue; + matched = 1; + sprintf(sql_field, "%s%s \"%s\"", + (SvCUR(sql_select)>7)?", ":"", p, &phs->name[1]); + sv_catpv(sql_select, sql_field); + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " lob refetch %s param: otype %d, matched field '%s' (%s)\n", + phs->name, phs->ftype, p, sql_field); + hv_delete(lob_cols_hv, p, i, 0); + fbh = &lr->fbh_ary[lr->num_fields++]; + fbh->name = phs->name; + fbh->dbtype = phs->ftype; + fbh->ftype = fbh->dbtype; + fbh->disize = 99; + fbh->desc_t = OCI_DTYPE_LOB; + OCIDescriptorAlloc_ok(imp_sth->envhp, &fbh->desc_h, fbh->desc_t); + break; + } + if (!matched) { + ++unmatched_params; + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " lob refetch %s param: otype %d, UNMATCHED\n", + phs->name, phs->ftype); + } + } + if (unmatched_params) { + /* not all the lob columns in the table were accounted for */ + Safefree(lr); + return oci_error(sth, errhp, OCI_ERROR, + "Can't refetch LOBs, LOB column mismatch (too many or wrong type)"); + } + + sv_catpv(sql_select, " from "); + sv_catpv(sql_select, tablename); + sv_catpv(sql_select, " where rowid = :rid"); + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " lob refetch sql: %s\n", SvPVX(sql_select)); + lr->sql_select = sql_select; + + lr->stmthp = NULL; + lr->bindhp = NULL; + lr->rowid = NULL; + lr->parmdp_tmp = NULL; + lr->parmdp_lob = NULL; + + + OCIHandleAlloc_ok(imp_sth->envhp, &lr->stmthp, OCI_HTYPE_STMT); + status = OCIStmtPrepare(lr->stmthp, errhp, + SvPVX(sql_select), SvCUR(sql_select), OCI_NTV_SYNTAX, OCI_DEFAULT); + if (status != OCI_SUCCESS) + return oci_error(sth, errhp, status, "OCIStmtPrepare/LOB refetch"); + + /* bind the rowid input */ + OCIDescriptorAlloc_ok(imp_sth->envhp, &lr->rowid, OCI_DTYPE_ROWID); + status = OCIBindByName(lr->stmthp, &lr->bindhp, errhp, ":rid", 4, + &lr->rowid, sizeof(OCIRowid*), SQLT_RDD, 0,0,0,0,0, OCI_DEFAULT); + if (status != OCI_SUCCESS) + return oci_error(sth, errhp, status, "OCIBindByPos/LOB refetch"); + + /* define the output fields */ + for(i=0; i < lr->num_fields; ++i) { + OCIDefine *defnp = NULL; + imp_fbh_t *fbh = &lr->fbh_ary[i]; + phs_t *phs; + SV **phs_svp = hv_fetch(imp_sth->all_params_hv, fbh->name,strlen(fbh->name), 0); + if (!phs_svp) + croak("panic: LOB refetch for '%s' param (%d) - name not found", + fbh->name,i+1); + phs = (phs_t*)(void*)SvPVX(*phs_svp); + fbh->special = phs; + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " lob refetch %ld for '%s' param: ftype %d setup\n", + i+1,fbh->name, fbh->dbtype); + status = OCIDefineByPos(lr->stmthp, &defnp, errhp, i+1, + &fbh->desc_h, -1, fbh->ftype, 0,0,0, OCI_DEFAULT); + if (status != OCI_SUCCESS) + return oci_error(sth, errhp, status, "OCIDefineByPos/LOB refetch"); + } + + imp_sth->lob_refetch = lr; /* structure copy */ + return 1; +} + + +static int +post_insert_lobs(sth, imp_sth) /* XXX leaks handles on error */ + SV * sth; + imp_sth_t *imp_sth; +{ + /* To insert a new LOB transparently (without using 'INSERT . RETURNING .') */ + /* we have to insert an empty LobLocator and then fetch it back from the */ + /* server before we can call OCILobWrite on it! This function handles that. */ + sword status; + int i; + OCIError *errhp = imp_sth->errhp; + ub4 rowid_iter = 0; + lob_refetch_t *lr; + + if (!imp_sth->lob_refetch) + if (!init_lob_refetch(sth, imp_sth)) + return 0; + lr = imp_sth->lob_refetch; + + status = OCIAttrGet_stmhp(imp_sth, (dvoid**)lr->rowid, &rowid_iter, OCI_ATTR_ROWID); + if (status != OCI_SUCCESS) + return oci_error(sth, errhp, status, "OCIAttrGet OCI_ATTR_ROWID /LOB refetch"); + + status = OCIStmtExecute(imp_sth->svchp, lr->stmthp, errhp, + 1, 0, NULL, NULL, OCI_DEFAULT); /* execute and fetch */ + if (status != OCI_SUCCESS) + return oci_error(sth, errhp, status, "OCIStmtExecute/LOB refetch"); + + for(i=0; i < lr->num_fields; ++i) { + imp_fbh_t *fbh = &lr->fbh_ary[i]; + phs_t *phs = (phs_t*)fbh->special; + ub4 amtp = SvCUR(phs->sv); + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " lob refetch %d for '%s' param: ftype %d, len %ld\n", + i+1,fbh->name, fbh->dbtype, amtp); + status = OCILobWrite(imp_sth->svchp, errhp, + fbh->desc_h, &amtp, 1, SvPVX(phs->sv), amtp, OCI_ONE_PIECE, + 0,0, 0,SQLCS_IMPLICIT); + if (status != OCI_SUCCESS) { + oci_error(sth, errhp, status, "OCILobWrite"); + return -2; + } + } + + return 1; +} + +static void +ora_free_lob_refetch(imp_sth_t *imp_sth) +{ + lob_refetch_t *lr = imp_sth->lob_refetch; + int i; + for(i=0; i < lr->num_fields; ++i) { + imp_fbh_t *fbh = &lr->fbh_ary[i]; + ora_free_fbh_contents(fbh); + } + sv_free(lr->sql_select); + sv_free(lr->fbh_ary_sv); + Safefree(imp_sth->lob_refetch); + imp_sth->lob_refetch = NULL; +} From e40f61f7d74f2823b431ccf2d4b08a88134ef60a Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Sun, 13 Dec 1998 19:23:50 -0500 Subject: [PATCH 037/637] import DBD-Oracle 0.54_93 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.54_93 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.54_93.tar.gz --- Makefile.PL | 4 +- Oracle.h | 4 +- Oracle.pm | 135 ++++--- dbdimp.c | 27 +- dbdimp.h | 22 +- oci8.h | 46 ++- ora_explain.PL | 943 +++++++++++++++++++++++++++++++++++-------------- 7 files changed, 836 insertions(+), 345 deletions(-) mode change 100644 => 100755 ora_explain.PL diff --git a/Makefile.PL b/Makefile.PL index 1c91356c..169ebfbe 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.70 1998/12/10 01:19:19 timbo Exp $ +# $Id: Makefile.PL,v 1.69 1998/11/29 00:14:07 timbo Exp timbo $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -24,7 +24,7 @@ BEGIN { if ($^O eq 'VMS') { # For those not using Dynamic loading this means building a # new static perl in the DBI directory by saying 'make perl' # and then using _that_ perl to make this one. -use DBI 0.92; +use DBI 1.02; use DBI::DBD; # DBD creation tools my $dbi_dir = dbd_dbi_dir(); diff --git a/Oracle.h b/Oracle.h index f7a0fd0d..600b3491 100644 --- a/Oracle.h +++ b/Oracle.h @@ -1,5 +1,5 @@ /* - $Id: Oracle.h,v 1.12 1998/07/28 17:33:37 timbo Exp $ + $Id: Oracle.h,v 1.13 1998/12/14 00:14:22 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -13,6 +13,8 @@ #define NEED_DBIXS_VERSION 9 +#define PERL_POLLUTE + #include /* installed by the DBI module */ #include "dbdimp.h" diff --git a/Oracle.pm b/Oracle.pm index d70a0ce1..4e5d5a9e 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.60 1998/12/10 01:19:19 timbo Exp $ +# $Id: Oracle.pm,v 1.59 1998/12/02 02:48:32 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.54_92'; +$DBD::Oracle::VERSION = '0.54_93'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -31,7 +31,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.60 $, 10); + my $Revision = substr(q$Revision: 1.59 $, 10); require_version DBI 1.02; @@ -140,7 +140,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; my ($drh, $dbname, $user, $auth)= @_; # If the application is asking for specific database - # then we have to mung the + # then we have to mung the if (DBD::Oracle::OCI() >= 8) { $dbname = $1 if !$dbname && $user =~ s/\@(.*)//; @@ -385,14 +385,14 @@ DBD::Oracle - Oracle database driver for the DBI module use DBI; - $dbh = DBI->connect("dbi:Oracle:", $user, $passwd); + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); # See the DBI module documentation for full details =head1 DESCRIPTION DBD::Oracle is a Perl module which works with the DBI module to provide -access to Oracle databases. +access to Oracle databases (both version 7 and 8). =head1 CONNECTING TO ORACLE @@ -441,16 +441,18 @@ what is going on. (It's unfortunate that TWO_TASK couldn't be renamed, since it makes no sense to the end user, and doesn't have the ORACLE prefix). -=head2 Using DBD::Oracle +=head2 Connection Examples Using DBD::Oracle Below are various ways of connecting to an oracle database using SQL*Net 1.x and SQL*Net 2.x. "Machine" is the computer the database is running on, "SID" is the SID of the database, "DB" is the SQL*Net 2.x connection descriptor for the database. - BEGIN { +B Some of these formats don't work with Oracle 8. + + BEGIN { $ENV{ORACLE_HOME} = '/home/oracle/product/7.x.x'; - $ENV{TWO_TASK} = 'DB'; + $ENV{TWO_TASK} = 'DB'; } $dbh = DBI->connect('dbi:Oracle:','scott', 'tiger'); # - or - @@ -497,12 +499,12 @@ a small proportion of people experience these problems.) [By Lane Sharman ] I spent a LOT of time optimizing listener.ora and I am including it here for anyone to benefit from. My connections over tnslistener on the same humble Netra 1 take an average -of 10-20 millies according to tnsping. If anyone knows how to make it -better, please let me know! +of 10-20 milli seconds according to tnsping. If anyone knows how to +make it better, please let me know! LISTENER = (ADDRESS_LIST = - (ADDRESS = + (ADDRESS = (PROTOCOL = TCP) (Host = aa.bbb.cc.d) (Port = 1521) @@ -541,13 +543,13 @@ space for the system as well. 5) Use large tuning settings and get lots of RAM. Check out all the parameters you can set in v$parameters because there are quite a few not -documented you may to set in your initxxx.ora file. +documented you may to set in your initxxx.ora file. 6) Use svrmgrl to control oracle from the command line. Write lots of small SQL scripts to get at V$ info. use DBI; - # Environmental variables used by Oracle + # Environmental variables used by Oracle $ENV{ORACLE_SID} = "xxx"; $ENV{ORACLE_HOME} = "/opt/oracle7"; $ENV{EPC_DISABLED} = "TRUE"; @@ -608,21 +610,21 @@ These PL/SQL examples come from: Eric Bartley . CREATE OR REPLACE PACKAGE plsql_example IS PROCEDURE proc_np; - + PROCEDURE proc_in ( err_code IN NUMBER ); - + PROCEDURE proc_in_inout ( test_num IN NUMBER, is_odd IN OUT NUMBER ); - + FUNCTION func_np RETURN VARCHAR2; - + END plsql_example; - + CREATE OR REPLACE PACKAGE BODY plsql_example IS PROCEDURE proc_np @@ -631,7 +633,7 @@ These PL/SQL examples come from: Eric Bartley . BEGIN SELECT USER INTO whoami FROM DUAL; END; - + PROCEDURE proc_in ( err_code IN NUMBER ) @@ -639,7 +641,7 @@ These PL/SQL examples come from: Eric Bartley . BEGIN RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); END; - + PROCEDURE proc_in_inout ( test_num IN NUMBER, is_odd IN OUT NUMBER @@ -648,7 +650,7 @@ These PL/SQL examples come from: Eric Bartley . BEGIN is_odd := MOD(test_num, 2); END; - + FUNCTION func_np RETURN VARCHAR2 IS @@ -657,38 +659,38 @@ These PL/SQL examples come from: Eric Bartley . SELECT USER INTO ret_val FROM DUAL; RETURN ret_val; END; - + END plsql_example; }; - + use DBI; my($db, $csr, $ret_val); - + $db = DBI->connect('dbi:Oracle:database','user','password') or die "Unable to connect: $DBI::errstr"; - + # So we don't have to check every DBI call we set RaiseError. # See the DBI docs now if you're not familiar with RaiseError. $db->{RaiseError} = 1; - + # Example 1 # # Calling a PLSQL procedure that takes no parameters. This shows you the # basic's of what you need to execute a PLSQL procedure. Just wrap your # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. - # + # # p.s. If you've used SQL*Plus's exec command all it does is wrap the # command in a BEGIN END; block for you. - + $csr = $db->prepare(q{ BEGIN PLSQL_EXAMPLE.PROC_NP; END; }); $csr->execute; - - + + # Example 2 # # Now we call a procedure that has 1 IN parameter. Here we use bind_param @@ -700,13 +702,13 @@ These PL/SQL examples come from: Eric Bartley . # placeholders (but few DBI drivers support them so they're not portable). my $err_code = -20001; - + $csr = $db->prepare(q{ BEGIN PLSQL_EXAMPLE.PROC_IN(:err_code); END; }); - + $csr->bind_param(":err_code", $err_code); # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. @@ -715,8 +717,8 @@ These PL/SQL examples come from: Eric Bartley . $csr->execute; }; print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; - - + + # Example 3 # # Building on the last example, I've added 1 IN OUT parameter. We still @@ -730,13 +732,13 @@ These PL/SQL examples come from: Eric Bartley . my $test_num = 5; my $is_odd; - + $csr = $db->prepare(q{ BEGIN PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); END; }); - + # The value of $test_num is _copied_ here $csr->bind_param(":test_num", $test_num); @@ -744,9 +746,9 @@ These PL/SQL examples come from: Eric Bartley . # The execute will automagically update the value of $is_odd $csr->execute; - + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; - + # Example 4 # @@ -756,30 +758,77 @@ These PL/SQL examples come from: Eric Bartley . # we can access it's value after execute. my $whoami = ""; - + $csr = $db->prepare(q{ BEGIN :whoami := PLSQL_EXAMPLE.FUNC_NP; END; }); - + $csr->bind_param_inout(":whoami", \$whoami, 20); $csr->execute; print "Your database user name is $whoami\n"; - + $db->disconnect; You can find more examples in the t/plsql.t file in the DBD::Oracle source directory. +=head1 Oracle 8 Issues + +DBD::Oracle version 0.55 onwards can be built to use either the Oracle 7 +or Oracle 8 OCI (Oracle Call Interface) API functions. The new Oracle 8 +API is used by default and offers several advantages, including support +for LOB type. Here's a quote from the Oracle OCI documentation: + + The Oracle8 OCI has several enhancements to improve application + performance and scalability. Application performance has been improved + by reducing the number of client to server round trips required and + scalability improvements have been facilitated by reducing the amount + of state information that needs to be retained on the server side. + +(Note that the use of Oracle 8 OCI represents a major amount of +rewriting of the internals of the drivers. There are bound to be some +minor problems.) + +When fetching LOBs, they are treated just like LONGs and are subject to +$sth->{LongReadLen} and $sth->{LongTruncOk}. + +When inserting or updating LOBs some *major* magic has to be performed +behind the scenes to make it transparent. Basically the driver has to +refetch the newly inserted 'Lob Locators' before being able to write to +them. However, it works, and I've made it as fast as possible (just +one extra server-round-trip per insert or update after the first). +For the time being, only single-row LOB updates are supported. + +To insert or update a LOB, DBD::Oracle has to know in advance that it +is a LOB type, there's no way around this. So you need to say: + + $sth->bind_param($idx, $value, { ora_type => ORA_CLOB }); + +The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + +or just use the corresponding integer values (112 and 113). + +To make scripts work with both Oracle7 and Oracle8, the Oracle7 +DBD::Oracle will treat the LOB ora_types as LONGs without error. +So any code you may have now that looks like + + $sth->bind_param($idx, $value, { ora_type => 8 }); + +should change the 8 (LONG type) to ORA_CLOB or ORA_BLOB +(or 112 or 113). + =head1 Oracle on Linix To join the oracle-on-linux mailing list, see: http://www.datamgmt.com/maillist.html http://www.eGroups.com/list/oracle-on-linux - mailto:oracle-on-linux-subscribe@egroups.com + mailto:oracle-on-linux-subscribe@egroups.com =head1 Commercial Oracle Tools diff --git a/dbdimp.c b/dbdimp.c index 594533e6..9c4bbd68 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.43 1998/12/10 01:19:19 timbo Exp $ + $Id: dbdimp.c,v 1.42 1998/12/02 02:48:32 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -12,9 +12,6 @@ #include "Oracle.h" -#if PATCHLEVEL < 5 && !defined(PL_dirty) -#define PL_dirty dirty -#endif /* XXX DBI should provide a better version of this */ #define IS_DBI_HANDLE(h) \ @@ -75,7 +72,7 @@ dbd_discon_all(drh, imp_drh) dTHR; /* The disconnect_all concept is flawed and needs more work */ - if (!PL_dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { + if (!dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { sv_setiv(DBIc_ERR(imp_drh), (IV)1); sv_setpv(DBIc_ERRSTR(imp_drh), (char*)"disconnect_all not implemented"); @@ -231,7 +228,7 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) } ret=OCIServerAttach(imp_dbh->srvhp, imp_dbh->errhp, - dbname, strlen(dbname), 0); + (text*)dbname, strlen(dbname), 0); if (ret != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, ret, "OCIServerAttach"); OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); @@ -554,7 +551,7 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) OCIHandleAlloc_ok(imp_dbh->envhp, &imp_sth->stmhp, OCI_HTYPE_STMT); status = OCIStmtPrepare(imp_sth->stmhp, imp_sth->errhp, - imp_sth->statement, (ub4)strlen(imp_sth->statement), + (text*)imp_sth->statement, (ub4)strlen(imp_sth->statement), oparse_lng, OCI_DEFAULT); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIStmtPrepare"); @@ -778,8 +775,8 @@ _rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) fprintf(DBILOGFP, "size %ld/%ld/%ld, ", (long)SvCUR(phs->sv),(long)SvLEN(phs->sv),phs->maxlen); else fprintf(DBILOGFP, "NULL, "); - fprintf(DBILOGFP, "ptype %ld, otype %d%s)\n", - SvTYPE(phs->sv), phs->ftype, + fprintf(DBILOGFP, "ptype %d, otype %d%s)\n", + (int)SvTYPE(phs->sv), phs->ftype, (phs->is_inout) ? ", inout" : ""); } @@ -946,7 +943,7 @@ _dbd_rebind_ph(sth, imp_sth, phs) #ifdef OCI_V8_SYNTAX status = OCIBindByName(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - phs->name, strlen(phs->name), + (text*)phs->name, strlen(phs->name), phs->progv, phs->maxlen, phs->ftype, &phs->indp, alen_ptr, &phs->arcode, @@ -1154,9 +1151,9 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count phs->alen = SvCUR(phs->sv) + phs->alen_incnull; if (debug >= 2) fprintf(DBILOGFP, - " with %s = '%.*s' (len %d/%d, indp %d, otype %d, ptype %ld)\n", + " with %s = '%.*s' (len %d/%d, indp %d, otype %d, ptype %d)\n", phs->name, phs->alen, SvPVX(phs->sv), phs->alen, (int)phs->maxlen, - phs->indp, phs->ftype, SvTYPE(phs->sv)); + phs->indp, phs->ftype, (int)SvTYPE(phs->sv)); } } } @@ -1196,8 +1193,8 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count if (!dbd_describe(sth, imp_sth)) return -2; /* dbd_describe already called oci_error() */ } - if (imp_sth->has_lobs && imp_sth->stmt_type == OCI_STMT_INSERT) { - if (!post_insert_lobs(sth, imp_sth)) + if (imp_sth->has_lobs && imp_sth->stmt_type != OCI_STMT_SELECT) { + if (!post_execute_lobs(sth, imp_sth, row_count)) return -2; /* post_insert_lobs already called oci_error() */ } @@ -1406,7 +1403,7 @@ dbd_st_finish(sth, imp_sth) /* oracle 7.3 code can core dump looking up an error message */ /* if we have logged out of the database. This typically */ /* happens during global destruction. This should catch most: */ - if (PL_dirty && imp_sth->cda->rc == 3114) + if (dirty && imp_sth->cda->rc == 3114) ora_error(sth, NULL, imp_sth->cda->rc, "ORA-03114: not connected to ORACLE (ocan)"); else diff --git a/dbdimp.h b/dbdimp.h index 38f2ea80..db5459df 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.25 1998/12/10 01:19:19 timbo Exp $ + $Id: dbdimp.h,v 1.24 1998/12/02 02:48:32 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -11,18 +11,20 @@ */ -#if PATCHLEVEL < 5 && !defined(PL_dirty) -#define PL_dirty dirty +/* Perl <= 5.004_0x defines dirty as either Perl_dirty or curinterp->Idirty */ +/* Perl > 5.005_54 defines dirty as PL_dirty if PERL_POLLUTE is defined */ +/* +#xif !defined(dirty) +#xdefine dirty PL_dirty +#xendif +*/ +#if defined(get_no_modify) && !defined(no_modify) +#define no_modify PL_no_modify #endif -/* try uncommenting this line if you get a syntax error on - * typedef signed long sbig_ora; - * in oratypes.h for Oracle 7.1.3. Don't you just love Oracle! - */ -/* now changed to only define it for non ansi-ish compilers */ #ifndef CAN_PROTOTYPE -#define signed +#define signed /* Oracle headers use signed */ #endif @@ -184,7 +186,7 @@ struct imp_fbh_st { /* field buffer EXPERIMENTAL */ sb4 cbufl; /* length of select-list item 'name' */ #endif SV *name_sv; /* only set for OCI8 */ - text *name; + char *name; sb4 disize; /* max display/buffer size */ /* Our storage space for the field data as it's fetched */ diff --git a/oci8.h b/oci8.h index c2caf6a0..496e3281 100644 --- a/oci8.h +++ b/oci8.h @@ -1,5 +1,5 @@ /* - $Id: oci8.h,v 1.4 1998/12/10 01:19:19 timbo Exp $ + $Id: oci8.h,v 1.3 1998/12/02 02:48:32 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -79,7 +79,7 @@ oci_error(h, errhp, status, what) SV *errstr = DBIc_ERRSTR(imp_xxh); sv_setpv(errstr, ""); if (errhp) { - char errbuf[1024]; + text errbuf[1024]; ub4 recno = 0; sb4 errcode = 0; sb4 eg_errcode = 0; @@ -95,7 +95,7 @@ oci_error(h, errhp, status, what) what, (long)recno, oci_status_name(eg_status), status, (long)eg_errcode, errbuf); errcode = eg_errcode; - sv_catpv(errstr, errbuf); + sv_catpv(errstr, (char*)errbuf); if (*(SvEND(errstr)-1) == '\n') --SvCUR(errstr); } @@ -329,6 +329,8 @@ dbd_describe(h, imp_sth) /* XXX unhandled type may lead to core dump */ break; } + if (fbh->ftype == 5) + fbh->disize += 1; /* allow for null terminator */ /* dbsize can be zero for 'select NULL ...' */ imp_sth->t_dbsize += fbh->dbsize; @@ -635,10 +637,22 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) I32 i; char *p; lob_refetch_t *lr = NULL; - STRLEN tablename_len; - char *tablename = find_ident_after(imp_sth->statement, + char *tablename; + + switch (imp_sth->stmt_type) { + case OCI_STMT_UPDATE: + tablename = find_ident_after(imp_sth->statement, + "update", &tablename_len, 1); + break; + case OCI_STMT_INSERT: + tablename = find_ident_after(imp_sth->statement, "into", &tablename_len, 1); + break; + default: + return oci_error(sth, errhp, OCI_ERROR, + "LOB refetch attempted for unsupported statement type"); + } if (!tablename) return oci_error(sth, errhp, OCI_ERROR, "Unable to parse table name for LOB refetch"); @@ -668,7 +682,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) for (i = 1; i <= numcols; i++) { OCIParam *colhd; ub2 col_dbtype; - text *col_name; + char *col_name; ub4 col_name_len; if ((status=OCIParamGet(collisthd, OCI_DTYPE_PARAM, errhp, (dvoid**)&colhd, i))) break; @@ -735,7 +749,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) phs->name, phs->ftype, p, sql_field); hv_delete(lob_cols_hv, p, i, 0); fbh = &lr->fbh_ary[lr->num_fields++]; - fbh->name = phs->name; + fbh->name = phs->name; fbh->dbtype = phs->ftype; fbh->ftype = fbh->dbtype; fbh->disize = 99; @@ -775,13 +789,13 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) OCIHandleAlloc_ok(imp_sth->envhp, &lr->stmthp, OCI_HTYPE_STMT); status = OCIStmtPrepare(lr->stmthp, errhp, - SvPVX(sql_select), SvCUR(sql_select), OCI_NTV_SYNTAX, OCI_DEFAULT); + (text*)SvPVX(sql_select), SvCUR(sql_select), OCI_NTV_SYNTAX, OCI_DEFAULT); if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCIStmtPrepare/LOB refetch"); /* bind the rowid input */ OCIDescriptorAlloc_ok(imp_sth->envhp, &lr->rowid, OCI_DTYPE_ROWID); - status = OCIBindByName(lr->stmthp, &lr->bindhp, errhp, ":rid", 4, + status = OCIBindByName(lr->stmthp, &lr->bindhp, errhp, (text*)":rid", 4, &lr->rowid, sizeof(OCIRowid*), SQLT_RDD, 0,0,0,0,0, OCI_DEFAULT); if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCIBindByPos/LOB refetch"); @@ -799,8 +813,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) fbh->special = phs; if (dbis->debug >= 3) fprintf(DBILOGFP, - " lob refetch %ld for '%s' param: ftype %d setup\n", - i+1,fbh->name, fbh->dbtype); + " lob refetch %d for '%s' param: ftype %d setup\n", + (int)i+1,fbh->name, fbh->dbtype); status = OCIDefineByPos(lr->stmthp, &defnp, errhp, i+1, &fbh->desc_h, -1, fbh->ftype, 0,0,0, OCI_DEFAULT); if (status != OCI_SUCCESS) @@ -813,9 +827,10 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) static int -post_insert_lobs(sth, imp_sth) /* XXX leaks handles on error */ +post_execute_lobs(sth, imp_sth, row_count) /* XXX leaks handles on error */ SV * sth; imp_sth_t *imp_sth; + ub4 row_count; { /* To insert a new LOB transparently (without using 'INSERT . RETURNING .') */ /* we have to insert an empty LobLocator and then fetch it back from the */ @@ -826,9 +841,14 @@ post_insert_lobs(sth, imp_sth) /* XXX leaks handles on error */ ub4 rowid_iter = 0; lob_refetch_t *lr; + if (row_count == 0) + return 1; /* nothing to do */ + if (row_count > 1) + return oci_error(sth, errhp, OCI_ERROR, "LOB refetch attempted for multiple rows"); + if (!imp_sth->lob_refetch) if (!init_lob_refetch(sth, imp_sth)) - return 0; + return 0; /* init_lob_refetch already called oci_error */ lr = imp_sth->lob_refetch; status = OCIAttrGet_stmhp(imp_sth, (dvoid**)lr->rowid, &rowid_iter, OCI_ATTR_ROWID); diff --git a/ora_explain.PL b/ora_explain.PL old mode 100644 new mode 100755 index c68184b6..58c5997c --- a/ora_explain.PL +++ b/ora_explain.PL @@ -30,13 +30,51 @@ use File::Basename; use Cwd; use DBI; use Tk; +use Tk::ErrorDialog; +use Tk::Pod; use Tk::Dialog; use Tk::FileSelect; use Tk::ROText; use Tk::Tree; +################################################################################ +# Subclassed version of Tk::Tree that allows button3 to have a callback attached + +package Tk::B3Tree; +use strict; +use base qw(Tk::Tree); +Construct Tk::Widget qw(B3Tree); + +sub ClassInit +{ +my ($class, $mw) = @_; +$class->SUPER::ClassInit($mw); +$mw->bind($class, "<3>", "Button3"); +return $class; +} + +sub Populate +{ +my ($self, $args) = @_; +$self->SUPER::Populate($args); +$self->ConfigSpecs(-b3command => [ "CALLBACK", "b3command", "B3command", + undef ]); +} + +sub Button3 +{ +my $w = shift; +my $Ev = $w->XEvent; +my $ent = $w->GetNearest($Ev->y); +return unless (defined($ent) and length($ent)); +$w->Callback(-b3command => $ent); +} + +################################################################################ + +package main; use vars qw($VERSION); -$VERSION = "0.6 beta"; +$VERSION = "0.7 beta TEST RELEASE 1"; # Globals # $Db Database handle @@ -53,13 +91,36 @@ $VERSION = "0.6 beta"; # $PlanStep ROText used to display the selected plan step details # $PlanSql Text used to allow SQL editing # $GrabMain SQL cache grab main window +# $GrabFeedback Label used for feedback during grab # $GrabSql ROText used to hold the contents of the SQL cache # $GrabDetails ROText used to display the selected statement details use vars qw($Db $SqlMarker $OracleVersion $Plan $LoginDialog $OpenDialog $SaveDialog $FileDir $PlanMain $PlanTitle $PlanTree $PlanStep $PlanSql - $GrabMain $GrabSql $GrabDetails); -$SqlMarker = '/* This statement was generated by explain */'; + $GrabMain $GrabFeedback $GrabSql $GrabDetails); +$SqlMarker = "/* This statement was generated by explain */"; + +################################################################################ +# Switch the hourglass on or off + +sub busy($$) +{ +my ($win, $state) = @_; +if ($state eq "on") + { + if ($win eq "plan" || $win eq "all") + { $PlanMain->Busy(); } + if (defined($GrabMain) && ($win eq "grab" || $win eq "all")) + { $GrabMain->Busy(); } + } +else + { + if ($win eq "plan" || $win eq "all") + { $PlanMain->Unbusy(); } + if (defined($GrabMain) && ($win eq "grab" || $win eq "all")) + { $GrabMain->Unbusy(); } + } +} ################################################################################ # Display an error message in a dialog @@ -67,11 +128,47 @@ $SqlMarker = '/* This statement was generated by explain */'; sub error($@) { my ($parent) = shift(@_); -$PlanMain->Dialog(-title => "Error", - -bitmap => "error", - -text => join("\n", @_), - -wraplength => "5i", - -buttons => ["OK"] )->Show(); +busy("all", "off"); +$PlanMain->Dialog(-title => "Error", + -bitmap => "error", + -text => join("\n", @_), + -wraplength => "80c", + -buttons => ["OK"] )->Show(); +} + +################################################################################ + +sub about($) +{ +my $msg = <Dialog(-title => "About Explain", + -text => $msg, + -wraplength => "80c", + -buttons => ["OK"] )->Show(); +} + +################################################################################ + +sub help($) +{ +my ($parent) = @_; +$parent->Pod(-file => $0, -scrollbars => "e"); } ################################################################################ @@ -82,6 +179,7 @@ sub login($$$) { my ($database, $username, $password) = @_; +busy("all", "on"); # Close any existing handle if ($Db) { @@ -125,6 +223,8 @@ if (! $qry->execute()) } ($OracleVersion) = $qry->fetchrow_array(); $qry->finish(); +busy("all", "off"); +return(1); } ################################################################################ @@ -132,19 +232,129 @@ $qry->finish(); sub clear_plan() { -$PlanTitle->configure(-text => 'Query Plan') if ($PlanTitle); -$PlanTree->delete('all') if ($PlanTree); -$PlanStep->delete('1.0', 'end') if ($PlanStep); +$PlanTitle->configure(-text => "Query Plan") if ($PlanTitle); +$PlanTree->delete("all") if ($PlanTree); +$PlanStep->delete("1.0", "end") if ($PlanStep); } ################################################################################ sub clear_editor() { -$PlanTitle->configure(-text => 'Query Plan') if ($PlanTitle); -$PlanTree->delete('all') if ($PlanTree); -$PlanStep->delete('1.0', 'end') if ($PlanStep); -$PlanSql->delete('1.0', 'end'); +$PlanTitle->configure(-text => "Query Plan") if ($PlanTitle); +$PlanTree->delete("all") if ($PlanTree); +$PlanStep->delete("1.0", "end") if ($PlanStep); +$PlanSql->delete("1.0", "end"); +} + +################################################################################ +# Display a popup dialog showing the structure of a table + +sub disp_table($$) +{ +my ($owner, $table) = @_; + +# Create the dialog for displaying the object details +my $dialog = $PlanMain->Toplevel(-title => "Table"); +my $box = $dialog->Frame(-borderwidth => 3, -relief => "raised"); +$box->Label(-text => "$owner.$table", + -relief => "ridge", -borderwidth => 1) + ->grid(-column => 0, -row => 0, -columnspan => 2, -sticky => "we"); + +# Mimic the SqlPlus "desc" command +$box->Label(-text => " Name ", -relief => "ridge", -borderwidth => 1) + ->grid(-column => 0, -row => 1, -sticky => "we"); +$box->Label(-text => " Type ", -relief => "ridge", -borderwidth => 1) + ->grid(-column => 1, -row => 1, -sticky => "we"); + +# This will get the table description +busy("plan", "on"); +my $qry = $Db->prepare(qq( + $SqlMarker select column_name, data_type, data_length, + data_precision, data_scale + from all_tab_columns + where owner = :1 and table_name = :2 + order by column_id + )); +$qry->execute($owner, $table) + || die("Table columns: $DBI::errstr\n"); + +# For each column in the table, display its details +my $row = 2; +while ((my ($name, $type, $length, $precision, $scale) + = $qry->fetchrow_array())) + { + $box->Label(-text => "$name ") + ->grid(-column => 0, -row => $row, -sticky => "w"); + if ($precision) + { + $type .= "($precision"; + $type .= ",$scale" if ($scale); + $type .= ")"; + } + elsif ($type =~ /CHAR/) + { + $type .= "($length)"; + } + $box->Label(-text => $type) + ->grid(-column => 1, -row => $row, -sticky => "w"); + $row++; + } +$qry->finish(); +busy("plan", "off"); + +# Pack the grid and add the close button +$box->pack(); +$dialog->Button(-text => "Close", -command => sub { $dialog->destroy(); }) + ->pack(-pady => 3); +} + +################################################################################ +# Display the structure of an index + +sub disp_index($$) +{ +my ($owner, $index) = @_; + +# Create the dialog for displaying the object details +my $dialog = $PlanMain->Toplevel(-title => "Index"); +my $box = $dialog->Frame(-borderwidth => 3, -relief => "raised"); +$box->Label(-text => "$owner.$index", + -relief => "ridge", -borderwidth => 1) + ->grid(-column => 0, -row => 0, -columnspan => 2, -sticky => "we"); + +# Show the table columns the index is built upon +$box->Label(-text => " Table ", -relief => "ridge", -borderwidth => 1) + ->grid(-column => 0, -row => 1, -sticky => "we"); +$box->Label(-text => " Column ", -relief => "ridge", -borderwidth => 1) + ->grid(-column => 1, -row => 1, -sticky => "we"); +busy("plan", "on"); +my $qry = $Db->prepare(qq( + $SqlMarker select table_owner, table_name, column_name + from all_ind_columns + where index_owner = :1 and index_name = :2 + order by column_position +)); +$qry->execute($owner, $index) + || die("Index columns: $DBI::errstr\n"); + +# For each column in the index, display its details +my $row = 2; +while ((my ($tab_owner, $table, $column) = $qry->fetchrow_array())) + { + $box->Label(-text => "$tab_owner.$table ") + ->grid(-column => 0, -row => $row, -sticky => "w"); + $box->Label(-text => $column) + ->grid(-column => 1, -row => $row, -sticky => "w"); + $row++; + } +$qry->finish(); +busy("plan", "off"); + +# Pack the grid and add the close button +$box->pack(); +$dialog->Button(-text => "Close", -command => sub { $dialog->destroy(); }) + ->pack(-pady => 3); } ################################################################################ @@ -153,12 +363,19 @@ $PlanSql->delete('1.0', 'end'); sub disp_plan_tree() { $PlanTitle->configure(-text => $Plan->{title}); -$PlanTree->delete('all'); +$PlanTree->delete("all"); +my $steps = 0; foreach my $step (@{$Plan->{id}}) { - $PlanTree->add($step->{key}, -text => $step->{desc}); + my $item = $PlanTree->add($step->{key}, -text => $step->{desc}); + $steps++; } $PlanTree->autosetmode(); +if ($steps) + { + $PlanTree->selectionSet("1"); + disp_plan_step("1"); + } } ################################################################################ @@ -168,7 +385,7 @@ sub disp_plan_step($) { my ($key) = @_; my $row = $Plan->{key}{$key}; -$PlanStep->delete('1.0', 'end'); +$PlanStep->delete("1.0", "end"); my $info = ""; $info .= "Id:\t$row->{ID}\tPosition:\t$row->{POSITION}\t" . "Parent Id:\t$row->{PARENT_ID}\n"; @@ -179,7 +396,7 @@ $info .= "\nPartition\nStart:\t$row->{PARTITION_START}\tStop:\t\t" . "$row->{PARTITION_STOP}\tId:\t\t$row->{PARTITION_ID}\n" if ($row->{PARTITION_START}); $info .= "\n$row->{OTHER}" if ($row->{OTHER}); -$PlanStep->insert('1.0', $info); +$PlanStep->insert("1.0", $info); } ################################################################################ @@ -195,6 +412,7 @@ my $row = $Plan->{key}{$key}; return(1) if (! $row->{OBJECT_NAME}); # Work out the type of the object - table or index +busy("plan", "on"); my $qry = $Db->prepare(qq( $SqlMarker select object_type from all_objects where object_name = :1 and owner = :2 @@ -203,98 +421,71 @@ $qry->execute($row->{OBJECT_NAME}, $row->{OBJECT_OWNER}) || die("Object type: $DBI::errstr\n"); my ($object_type) = $qry->fetchrow_array(); $qry->finish(); -$object_type = ucfirst(lc($object_type)); +busy("plan", "off"); -# We only know about Tables and Indexes -if ($object_type ne 'Table' && $object_type ne 'Index') +if ($object_type eq "TABLE") + { + disp_table($row->{OBJECT_OWNER}, $row->{OBJECT_NAME}); + } +elsif ($object_type eq "INDEX") + { + disp_index($row->{OBJECT_OWNER}, $row->{OBJECT_NAME}); + } +else { die("Unknown object type $object_type", "for $row->{OBJECT_OWNER}.$row->{OBJECT_NAME}\n"); } +} -# Create the dialog for displaying the object details -my $dialog = $PlanMain->Toplevel(-title => $object_type); -my $box = $dialog->Frame(-borderwidth => 2, -relief => 'raised'); -$box->Label(-text => "$row->{OBJECT_OWNER}.$row->{OBJECT_NAME}", - -relief => 'ridge', -borderwidth => 1) - ->grid(-column => 0, -row => 0, -columnspan => 2, -sticky => 'we'); - -# For tables we mimic the SqlPlus 'desc' command -if ($object_type eq 'Table') - { - $box->Label(-text => " Name ", -relief => 'ridge', -borderwidth => 1) - ->grid(-column => 0, -row => 1, -sticky => 'we'); - $box->Label(-text => " Type ", -relief => 'ridge', -borderwidth => 1) - ->grid(-column => 1, -row => 1, -sticky => 'we'); - - # This will get the table description - $qry = $Db->prepare(qq( - $SqlMarker select column_name, data_type, data_length, - data_precision, data_scale - from all_tab_columns - where owner = :1 and table_name = :2 - order by column_id - )); - $qry->execute($row->{OBJECT_OWNER}, $row->{OBJECT_NAME}) - || die("Table columns: $DBI::errstr\n"); +################################################################################ +# Display a list of available indexes on a table, and display the selected +# table definition - # For each column in the table, display its details - my $row = 2; - while ((my ($name, $type, $length, $precision, $scale) - = $qry->fetchrow_array())) - { - $box->Label(-text => "$name ") - ->grid(-column => 0, -row => $row, -sticky => 'w'); - if ($precision) - { - $type .= "($precision"; - $type .= ",$scale" if ($scale); - $type .= ")"; - } - elsif ($type =~ /CHAR/) - { - $type .= "($length)"; - } - $box->Label(-text => $type) - ->grid(-column => 1, -row => $row, -sticky => 'w'); - $row++; - } - $qry->finish(); - } +sub disp_index_popup($) +{ +my ($key) = @_; -# For indexes we show the table columns the index is built upon -else - { - $box->Label(-text => " Table ", -relief => 'ridge', -borderwidth => 1) - ->grid(-column => 0, -row => 1, -sticky => 'we'); - $box->Label(-text => " Column ", -relief => 'ridge', -borderwidth => 1) - ->grid(-column => 1, -row => 1, -sticky => 'we'); - $qry = $Db->prepare(qq( - $SqlMarker select table_owner, table_name, column_name - from all_ind_columns - where index_owner = :1 and index_name = :2 - order by column_position - )); - $qry->execute($row->{OBJECT_OWNER}, $row->{OBJECT_NAME}) - || die("Index columns: $DBI::errstr\n"); +# Get the plan step & return if it doesn't refer to an object +my $row = $Plan->{key}{$key}; +return(1) if (! $row->{OBJECT_NAME}); - # For each column in the index, display its details - my $row = 2; - while ((my ($owner, $table, $column) = $qry->fetchrow_array())) - { - $box->Label(-text => "$owner.$table ") - ->grid(-column => 0, -row => $row, -sticky => 'w'); - $box->Label(-text => $column) - ->grid(-column => 1, -row => $row, -sticky => 'w'); - $row++; - } - $qry->finish(); +# Work out the type of the object - table or index +busy("plan", "on"); +my $qry = $Db->prepare(qq( + $SqlMarker select object_type from all_objects + where object_name = :1 and owner = :2 +)); +$qry->execute($row->{OBJECT_NAME}, $row->{OBJECT_OWNER}) + || die("Object type: $DBI::errstr\n"); +my ($object_type) = $qry->fetchrow_array(); +$qry->finish(); +if ($object_type ne "TABLE") + { + busy("plan", "off"); + return(1); } -# Pack the grid and add the close button -$box->pack(); -$dialog->Button(-text => 'Close', -command => sub { $dialog->destroy(); }) - ->pack(-pady => 3); +# Build the popup menu +$qry = $Db->prepare(qq( + $SqlMarker select owner, index_name from all_indexes + where table_name = :1 and table_owner = :2 +)); +$qry->execute($row->{OBJECT_NAME}, $row->{OBJECT_OWNER}) + || die("Table indexes: $DBI::errstr\n"); +my $menu = $PlanMain->Menu(-tearoff => 0, -disabledforeground => "#0000f0"); +$menu->command(-label => "Indexes", -state => "disabled"); +my $count = 0; +while ((my ($index_owner, $index_name) = $qry->fetchrow_array())) + { + $menu->command(-label => "$index_owner.$index_name", + -command => sub { disp_index($index_owner, $index_name); }); + $count++; + } +$qry->finish(); +busy("plan", "off"); +$menu->Popup(-popover => "cursor", -popanchor => "nw") if ($count); +return(1); } ################################################################################ @@ -303,7 +494,7 @@ $dialog->Button(-text => 'Close', -command => sub { $dialog->destroy(); }) sub _explain() { # Check there is some SQL -my $stmt = $PlanSql->get('1.0', 'end'); +my $stmt = $PlanSql->get("1.0", "end"); $stmt =~ s/;//g; die("You have not supplied any SQL\n") if ($stmt =~ /^\s*$/); @@ -312,14 +503,14 @@ die("You are not logged on to Oracle\n") if (! $Db); # Set up the various query strings # Note that for some reason you can't use bind variables in 'explain plan' -my $prefix = "explain plan set statement_id = '$$' for "; +my $prefix = "$SqlMarker explain plan set statement_id = '$$' for "; my $plan_sql = qq( $SqlMarker select level, operation, options, object_node, object_owner, object_name, object_instance, object_type, id, parent_id, position, other); -if ($OracleVersion ge '7.3') +if ($OracleVersion ge "7.3") { $plan_sql .= qq(, cost, cardinality, bytes, other_tag) }; -if ($OracleVersion ge '8') +if ($OracleVersion ge "8") { $plan_sql .= qq(, partition_start, partition_stop, partition_id) }; $plan_sql .= qq( from plan_table @@ -329,6 +520,7 @@ $plan_sql .= qq( ); # Clean any old stuff from the plan_table +busy("plan", "on"); $Db->do(qq($SqlMarker delete from plan_table where statement_id = :1), undef, $$) || die("Delete from plan_table: $DBI::errstr\n"); @@ -391,6 +583,8 @@ $qry->finish(); $Db->do(qq($SqlMarker delete from plan_table where statement_id = :1), undef, $$); $Db->commit(); +busy("plan", "off"); +return(1); } ################################################################################ @@ -414,33 +608,33 @@ my ($parent) = @_; # Create the dialog if (! $LoginDialog) { - my $username = '/'; - my $password = ''; + my $username = "/"; + my $password = ""; my $database = $ENV{TWO_TASK} || $ENV{ORACLE_SID}; - $LoginDialog = $parent->Toplevel(-title => 'Login to Oracle'); + $LoginDialog = $parent->Toplevel(-title => "Login to Oracle"); $LoginDialog->withdraw(); $LoginDialog->transient($parent); my $box; # Create the entry labels & fields - $box = $LoginDialog->Frame(-borderwidth => 1, -relief => 'raised'); - $box->Label(-text => 'Username') - ->grid(-column => 0, -row => 0, -sticky => 'w'); + $box = $LoginDialog->Frame(-borderwidth => 1, -relief => "raised"); + $box->Label(-text => "Username") + ->grid(-column => 0, -row => 0, -sticky => "w"); $box->Entry(-textvariable => \$username, -width => 30) - ->grid(-column => 1, -row => 0, -sticky => 'w'); - $box->Label(-text => 'Password') - ->grid(-column => 0, -row => 1, -sticky => 'w'); - $box->Entry(-textvariable => \$password, -width => 30, -show => '*') - ->grid(-column => 1, -row => 1, -sticky => 'w'); - $box->Label(-text => 'Database') - ->grid(-column => 0, -row => 2, -sticky => 'w'); + ->grid(-column => 1, -row => 0, -sticky => "w"); + $box->Label(-text => "Password") + ->grid(-column => 0, -row => 1, -sticky => "w"); + $box->Entry(-textvariable => \$password, -width => 30, -show => "*") + ->grid(-column => 1, -row => 1, -sticky => "w"); + $box->Label(-text => "Database") + ->grid(-column => 0, -row => 2, -sticky => "w"); $box->Entry(-textvariable => \$database, -width => 30) - ->grid(-column => 1, -row => 2, -sticky => 'w'); - $box->pack(-expand => 1, -fill => 'both'); + ->grid(-column => 1, -row => 2, -sticky => "w"); + $box->pack(-expand => 1, -fill => "both"); # Create the buttons & callbacks - $box = $LoginDialog->Frame(-borderwidth => 1, -relief => 'raised'); + $box = $LoginDialog->Frame(-borderwidth => 1, -relief => "raised"); my $cb = sub { if (! eval { login($database, $username, $password); }) @@ -453,11 +647,11 @@ if (! $LoginDialog) $LoginDialog->withdraw(); } }; - $box->Button(-text => 'Login', -command => $cb) - ->pack(-side => 'left', -expand => 1, -pady => 3); - $box->Button(-text => 'Cancel', -command => sub { $LoginDialog->withdraw() }) - ->pack(-side => 'right', -expand => 1, -pady => 3); - $box->pack(-expand => 1, -fill => 'both'); + $box->Button(-text => "Login", -command => $cb) + ->pack(-side => "left", -expand => 1, -pady => 3); + $box->Button(-text => "Cancel", -command => sub { $LoginDialog->withdraw() }) + ->pack(-side => "right", -expand => 1, -pady => 3); + $box->pack(-expand => 1, -fill => "both"); } # Activate the dialog @@ -482,7 +676,7 @@ if (! ($fh = IO::File->new($file, "r"))) clear_editor(); while (my $line = $fh->getline()) { - $PlanSql->insert('end', $line); + $PlanSql->insert("end", $line); } $fh->close(); return(1); @@ -534,7 +728,7 @@ if (! ($fh = IO::File->new($file, "w"))) error("Cannot open $file", $!); return; } -$fh->print($text->get('1.0', 'end')); +$fh->print($text->get("1.0", "end")); $fh->close(); } @@ -545,7 +739,7 @@ sub copy_sql() { my ($text, $tag) = @_; clear_editor(); -$PlanSql->insert('end', $text->get("$tag.first", "$tag.last")); +$PlanSql->insert("end", $text->get("$tag.first", "$tag.last")); explain(); } @@ -557,7 +751,8 @@ sub disp_sql_cache_info($) my ($address) = @_; # Empty the widget & prepare the SQL -$GrabDetails->delete('1.0', 'end'); +$GrabDetails->delete("1.0", "end"); +busy("grab", "on"); my $qry = $Db->prepare(qq( $SqlMarker select sorts, executions, loads, parse_calls, disk_reads, buffer_gets, rows_processed @@ -579,9 +774,10 @@ else . "Parse calls:\t$parse_calls\tDisk reads:\t$disk_reads\t" . "Buffer gets:\t$buffer_gets\nRows processed:\t$rows_processed"; } +busy("grab", "off"); # Display the formated info -$GrabDetails->insert('1.0', $info); +$GrabDetails->insert("1.0", $info); return(1); } @@ -605,8 +801,8 @@ $rows = -1 if ($rows !~ /^\d+$/); $user = uc($user); # Clear the frames -$GrabSql->delete('1.0', 'end'); -$GrabDetails->delete('1.0', 'end'); +$GrabSql->delete("1.0", "end"); +$GrabDetails->delete("1.0", "end"); # Define the callbacks for highlighting etc my ($bold, $normal); @@ -615,13 +811,13 @@ if ($GrabMain->depth > 1) $bold = sub { my ($text, $tag) = @_; - $text->tag('configure', $tag, -background => '#43ce80', - -relief => 'raised', -borderwidth => 1); + $text->tag("configure", $tag, -background => "#43ce80", + -relief => "raised", -borderwidth => 1); }; $normal = sub { my ($text, $tag) = @_; - $text->tag('configure', $tag, -background => undef, -relief => 'flat'); + $text->tag("configure", $tag, -background => undef, -relief => "flat"); }; } else @@ -629,13 +825,13 @@ else $bold = sub { my ($text, $tag) = @_; - $text->tag('configure', $tag, -foreground => 'white', - -background => 'black'); + $text->tag("configure", $tag, -foreground => "white", + -background => "black"); }; $normal = sub { my ($text, $tag) = @_; - $text->tag('configure', $tag, -foreground => undef, -background => undef); + $text->tag("configure", $tag, -foreground => undef, -background => undef); }; } my $disp_cb = sub @@ -646,9 +842,11 @@ my $disp_cb = sub }; # Prepare the queries +busy("grab", "on"); my $qry1 = qq{$SqlMarker select address from v\$sqlarea}; $qry1 .= qq{, all_users} if ($user || $no_sys); $qry1 .= qq{ where sql_text not like '\%$SqlMarker\%'}; +$qry1 .= qq{ and sql_text not like 'insert into plan_table\%'}; $qry1 .= qq{ and user_id = parsing_user_id} if($user || $no_sys); $qry1 .= qq{ and username = :1} if ($user); $qry1 .= qq{ and username not in ('SYS', 'SYSTEM')} if ($no_sys); @@ -656,7 +854,7 @@ $qry1 .= qq{ order by $order_by desc} if ($order_by); $qry1 = $Db->prepare($qry1) || die("$DBI::errstr\n"); my $qry2; -if ($OracleVersion ge '7.2') +if ($OracleVersion ge "7.2") { $qry2 = $Db->prepare(qq( $SqlMarker select sql_text from v\$sqltext_with_newlines @@ -671,12 +869,10 @@ else{ } # For each SQL query in the shared pool... -$PlanMain->Busy(); -$GrabMain->Busy(); if ($user) { $qry1->execute($user) || die("$DBI::errstr\n"); } else { $qry1->execute() || die("$DBI::errstr\n"); } -while ($rows != 0 - && (my ($address) = $qry1->fetchrow_array())) +my $count = 0; +while ($count != $rows && (my ($address) = $qry1->fetchrow_array())) { # ...glue together the components of the SQL string & print out $qry2->execute($address) || die("$DBI::errstr\n"); @@ -694,20 +890,24 @@ while ($rows != 0 next if ($pattern && eval { $sql_text !~ /$pattern/is; }); # Display the statement and set up the bindings - $GrabSql->insert('end', $sql_text, $address, "\n\n"); - $GrabSql->tag('bind', $address, '' => [ $bold, $address ]); - $GrabSql->tag('bind', $address, '' => [ $normal, $address ]); - $GrabSql->tag('bind', $address, '' => [ \©_sql, $address]); - $GrabSql->tag('bind', $address, '<1>' => [ $disp_cb, $address ]); + $GrabSql->insert("end", $sql_text, $address, "\n\n"); + $GrabSql->tag("bind", $address, "" => [ $bold, $address ]); + $GrabSql->tag("bind", $address, "" => [ $normal, $address ]); + $GrabSql->tag("bind", $address, "" => [ \©_sql, $address]); + $GrabSql->tag("bind", $address, "<1>" => [ $disp_cb, $address ]); $GrabSql->update(); - $rows--; + $count++; + if ($rows > 0) + { $GrabFeedback->configure(-text => "$count of $rows queries grabbed"); } + else + { $GrabFeedback->configure(-text => "$count queries grabbed"); } } # Clean up $qry1->finish(); -$GrabMain->Unbusy(); -$PlanMain->Unbusy(); +$GrabFeedback->configure(-text => "$count queries grabbed"); +busy("grab", "off"); return(1); } @@ -718,109 +918,123 @@ sub grab_main { # Only create if it doesn't already exist return if ($GrabMain); -$GrabMain = $PlanMain->Toplevel(-title => 'explain - SQL cache'); +$GrabMain = $PlanMain->Toplevel(-title => "explain - SQL cache"); ### Menubar -my $menubar = $GrabMain->Frame(-relief => 'raised', -borderwidth => 2); -$menubar->pack(-fill => 'x'); +my $menubar = $GrabMain->Frame(-relief => "raised", -borderwidth => 3); +$menubar->pack(-fill => "x"); -my $menubar_file = $menubar->Menubutton(-text => 'File', -underline => 0); -$menubar_file->command(-label => 'Save File ...', -underline => 0, +my $menubar_file = $menubar->Menubutton(-text => "File", -underline => 0); +$menubar_file->command(-label => "Save File ...", -underline => 0, -command => sub { save_dialog($PlanMain, $GrabSql); }); $menubar_file->separator(); -$menubar_file->command(-label => 'Close', -underline => 1, +$menubar_file->command(-label => "Close", -underline => 1, -command => sub { $GrabMain->destroy(); }); -$menubar_file->pack(-side => 'left'); +$menubar_file->pack(-side => "left"); + +my $menubar_help = $menubar->Menubutton(-text => "Help", -underline => 0); +$menubar_help->command(-label => "About ...", -underline => 0, + -command => sub { about($GrabMain); }); +$menubar_help->command(-label => "Usage", -underline => 0, + -command => sub { help($GrabMain); }); +$menubar_help->pack(-side => "right"); ### SQL cache display -my $frame; -$frame = $GrabMain->Frame(-borderwidth => 3, -relief => 'raised'); -$frame->Label(-text => 'SQL Cache')->pack(-anchor => 'nw'); -$GrabSql = $frame->Scrolled('ROText', -setgrid => 'true', -scrollbars => 'oe', +my ($frame, $frame1); +$frame = $GrabMain->Frame(-borderwidth => 3, -relief => "raised"); +$frame1 = $frame->Frame(-highlightthickness => 0); +$frame1->Label(-text => "SQL Cache")->pack(-side => "left"); +$GrabFeedback = $frame1->Label(-text => "", -foreground => "#ff0000") + ->pack(-side => "right"); +$frame1->pack(-fill => "x"); +$GrabSql = $frame->Scrolled("ROText", -setgrid => "true", -scrollbars => "oe", -height => 15, -width => 80, -borderwidth => 0, - -wrap => 'word') - ->pack(-fill => 'both', -expand => 1); -$frame->pack(-fill => 'both', -expand => 1); + -wrap => "word") + ->pack(-fill => "both", -expand => 1); +$frame->pack(-fill => "both", -expand => 1); ### SQL statement details -$frame = $GrabMain->Frame(-borderwidth => 3, -relief => 'raised'); -$frame->Label(-text => 'SQL Statement Statistics')->pack(-anchor => 'nw'); +$frame = $GrabMain->Frame(-borderwidth => 3, -relief => "raised"); +$frame->Label(-text => "SQL Statement Statistics")->pack(-anchor => "nw"); $GrabDetails = $frame->ROText(-height => 3, -width => 80, -borderwidth => 0, - -setgrid => 'true', -wrap => 'word') - ->pack(-fill => 'x'); -$frame->pack(-fill => 'x'); + -setgrid => "true", -wrap => "word") + ->pack(-fill => "x"); +$frame->pack(-fill => "x"); ### SQL selection -$frame = $GrabMain->Frame(-borderwidth => 3, -relief => 'raised'); -$frame->Label(-text => 'SQL Selection Criterea')->pack(-anchor => 'nw'); - -my $frame1 = $frame->Frame(-highlightthickness => 2); -$frame1->Label(-text => 'Order SQL by number of:') - ->grid(-column => 0, -row => 0, -columnspan => 3, -sticky => 'w'); -my $order_by = 'disk_reads'; -$frame1->Radiobutton(-text => 'Disk reads', -highlightthickness => 0, - -value => 'disk_reads', -variable => \$order_by) - ->grid(-column => 0, -row => 1, -sticky => 'w'); -$frame1->Radiobutton(-text => 'Buffer gets', -highlightthickness => 0, - -value => 'buffer_gets', -variable => \$order_by) - ->grid(-column => 1, -row => 1, -sticky => 'w'); -$frame1->Radiobutton(-text => 'Rows processed', -highlightthickness => 0, - -value => 'rows_processed', -variable => \$order_by) - ->grid(-column => 2, -row => 1, -sticky => 'w'); -$frame1->Radiobutton(-text => 'Executions', -highlightthickness => 0, - -value => 'executions', -variable => \$order_by) - ->grid(-column => 3, -row => 1, -sticky => 'w'); -$frame1->Radiobutton(-text => 'Sorts', -highlightthickness => 0, - -value => 'sorts', -variable => \$order_by) - ->grid(-column => 0, -row => 2, -sticky => 'w'); -$frame1->Radiobutton(-text => 'Loads', -highlightthickness => 0, - -value => 'loads', -variable => \$order_by) - ->grid(-column => 1, -row => 2, -sticky => 'w'); -$frame1->Radiobutton(-text => 'No ordering', -highlightthickness => 0, - -value => '', -variable => \$order_by) - ->grid(-column => 2, -row => 2, -sticky => 'w'); +$frame = $GrabMain->Frame(-borderwidth => 3, -relief => "raised"); +$frame->Label(-text => "SQL Selection Criterea")->pack(-anchor => "nw"); + +$frame1 = $frame->Frame(-highlightthickness => 1); +$frame1->Label(-text => "Order SQL by number of:") + ->grid(-column => 0, -row => 0, -columnspan => 3, -sticky => "w"); +my $order_by = "disk_reads"; +$frame1->Radiobutton(-text => "Disk reads", -highlightthickness => 0, + -value => "disk_reads", -variable => \$order_by) + ->grid(-column => 0, -row => 1, -sticky => "w"); +$frame1->Radiobutton(-text => "Buffer gets", -highlightthickness => 0, + -value => "buffer_gets", -variable => \$order_by) + ->grid(-column => 1, -row => 1, -sticky => "w"); +$frame1->Radiobutton(-text => "Rows processed", -highlightthickness => 0, + -value => "rows_processed", -variable => \$order_by) + ->grid(-column => 2, -row => 1, -sticky => "w"); +$frame1->Radiobutton(-text => "Executions", -highlightthickness => 0, + -value => "executions", -variable => \$order_by) + ->grid(-column => 3, -row => 1, -sticky => "w"); +$frame1->Radiobutton(-text => "Parse calls", -highlightthickness => 0, + -value => "parse_calls", -variable => \$order_by) + ->grid(-column => 0, -row => 2, -sticky => "w"); +$frame1->Radiobutton(-text => "Sorts", -highlightthickness => 0, + -value => "sorts", -variable => \$order_by) + ->grid(-column => 1, -row => 2, -sticky => "w"); +$frame1->Radiobutton(-text => "Loads", -highlightthickness => 0, + -value => "loads", -variable => \$order_by) + ->grid(-column => 2, -row => 2, -sticky => "w"); +$frame1->Radiobutton(-text => "No ordering", -highlightthickness => 0, + -value => "", -variable => \$order_by) + ->grid(-column => 3, -row => 2, -sticky => "w"); my $no_sys = 1; -$frame1->Checkbutton(-text => 'Exclude queries by SYS or SYSTEM', +$frame1->Checkbutton(-text => "Exclude queries by SYS or SYSTEM", -variable => \$no_sys, -offvalue => 0, -onvalue => 1, -highlightthickness => 0) - ->grid(-column => 0, -row => 3, -sticky => 'w', -columnspan => 3); + ->grid(-column => 0, -row => 3, -sticky => "w", -columnspan => 3); -my $user = ''; -$frame1->Label(-text => 'First user to execute statement') - ->grid(-column => 0, -row => 4, -sticky => 'w', -columnspan => 2); +my $user = ""; +$frame1->Label(-text => "First user to execute statement") + ->grid(-column => 0, -row => 4, -sticky => "w", -columnspan => 2); $frame1->Entry(-textvariable => \$user, -width => 30) - ->grid(-column => 2, -row => 4, -sticky => 'w', -columnspan => 2); + ->grid(-column => 2, -row => 4, -sticky => "w", -columnspan => 2); -my $pattern = ''; -$frame1->Label(-text => 'SQL matches pattern') - ->grid(-column => 0, -row => 5, -sticky => 'w', -columnspan => 2); +my $pattern = ""; +$frame1->Label(-text => "SQL matches pattern") + ->grid(-column => 0, -row => 5, -sticky => "w", -columnspan => 2); $frame1->Entry(-textvariable => \$pattern, -width => 30) - ->grid(-column => 2, -row => 5, -sticky => 'w', -columnspan => 2); + ->grid(-column => 2, -row => 5, -sticky => "w", -columnspan => 2); my $rows = 100; -$frame1->Label(-text => 'Maximum number of statements') - ->grid(-column => 0, -row => 6, -sticky => 'w', -columnspan => 2); +$frame1->Label(-text => "Maximum number of statements") + ->grid(-column => 0, -row => 6, -sticky => "w", -columnspan => 2); $frame1->Entry(-textvariable => \$rows, -width => 4) - ->grid(-column => 2, -row => 6, -sticky => 'w', -columnspan => 2); + ->grid(-column => 2, -row => 6, -sticky => "w", -columnspan => 2); -$frame1->pack(-fill => 'x'); -$frame->pack(-fill => 'x'); +$frame1->pack(-fill => "x"); +$frame->pack(-fill => "x"); ### Buttons -$frame = $GrabMain->Frame(-borderwidth => 3, -relief => 'raised'); +$frame = $GrabMain->Frame(-borderwidth => 3, -relief => "raised"); my $grab_cb = sub { if (! eval { grab($order_by, $no_sys, $user, $pattern, $rows); }) { error($GrabMain, $@); } }; -$frame->Button(-text => 'Grab', -command => $grab_cb) - ->pack(-side => 'left', -expand => 1, -pady => 3); -$frame->Button(-text => 'Close', -command => sub { $GrabMain->destroy(); }) - ->pack(-side => 'left', -expand => 1, -pady => 3); -$frame->pack(-fill => 'x'); -#$GrabMain->bind('', sub { $GrabMain = undef; }); +$frame->Button(-text => "Grab", -command => $grab_cb) + ->pack(-side => "left", -expand => 1, -pady => 3); +$frame->Button(-text => "Close", -command => sub { $GrabMain->destroy(); }) + ->pack(-side => "left", -expand => 1, -pady => 3); +$frame->pack(-fill => "x"); +#$GrabMain->bind("", sub { $GrabMain = undef; }); $GrabMain->OnDestroy(sub { $GrabMain = undef; }); } @@ -829,72 +1043,83 @@ $GrabMain->OnDestroy(sub { $GrabMain = undef; }); ### Main window $PlanMain = MainWindow->new(); -$PlanMain->title('explain'); +$PlanMain->title("explain"); ### Menubar -my $menubar = $PlanMain->Frame(-relief => 'raised', -borderwidth => 2); -$menubar->pack(-fill => 'x'); +my $menubar = $PlanMain->Frame(-relief => "raised", -borderwidth => 3); +$menubar->pack(-fill => "x"); -my $menubar_file = $menubar->Menubutton(-text => 'File', -underline => 0); -$menubar_file->command(-label => 'Login ...', -underline => 0, +my $menubar_file = $menubar->Menubutton(-text => "File", -underline => 0); +$menubar_file->command(-label => "Login ...", -underline => 0, -command => sub { login_dialog($PlanMain); }); -$menubar_file->command(-label => 'Grab SQL ...', -underline => 0, +$menubar_file->command(-label => "Grab SQL ...", -underline => 0, -command => sub { grab_main(); }); $menubar_file->separator(); -$menubar_file->command(-label => 'Open File ...', -underline => 0, +$menubar_file->command(-label => "Open File ...", -underline => 0, -command => sub { open_dialog($PlanMain); }); -$menubar_file->command(-label => 'Save File ...', -underline => 0, +$menubar_file->command(-label => "Save File ...", -underline => 0, -command => sub { save_dialog($PlanMain, $PlanSql); }); $menubar_file->separator(); -$menubar_file->command(-label => 'Exit', -underline => 1, +$menubar_file->command(-label => "Exit", -underline => 1, -command => sub { $Db->disconnect() if ($Db); exit(0); }); -$menubar_file->pack(-side => 'left'); +$menubar_file->pack(-side => "left"); + +my $menubar_help = $menubar->Menubutton(-text => "Help", -underline => 0); +$menubar_help->command(-label => "About ...", -underline => 0, + -command => sub { about($PlanMain); }); +$menubar_help->command(-label => "Usage", -underline => 0, + -command => sub { help($PlanMain); }); +$menubar_help->pack(-side => "right"); ### Query plan tree my $frame; -$frame = $PlanMain->Frame(-borderwidth => 3, -relief => 'raised'); -$PlanTitle = $frame->Label(-text => 'Query Plan')->pack(-anchor => 'nw'); -my $cb = sub { error($PlanMain, $@) if (! eval { disp_plan_step_obj($_[0])}); }; -$PlanTree = $frame->Scrolled('Tree', -height => 15, -width => 80, - -borderwidth => 0, -scrollbars => 'osoe', - -browsecmd => \&disp_plan_step, - -command => $cb, ) - ->pack(-expand => 1, -fill => 'both'); -$frame->pack(-expand => 1, -fill => 'both'); +$frame = $PlanMain->Frame(-borderwidth => 3, -relief => "raised"); +$PlanTitle = $frame->Label(-text => "Query Plan")->pack(-anchor => "nw"); +my $b1_cb = sub + { error($PlanMain, $@) if (! eval { disp_plan_step_obj($_[0])}); }; +my $b3_cb = sub + { error($PlanMain, $@) if (! eval { disp_index_popup($_[0])}); }; +$PlanTree = $frame->Scrolled("B3Tree", -height => 15, -width => 80, + -borderwidth => 0, -highlightthickness => 1, + -scrollbars => "osoe", + -browsecmd => \&disp_plan_step, + -command => $b1_cb, -b3command => $b3_cb) + ->pack(-expand => 1, -fill => "both"); +$frame->pack(-expand => 1, -fill => "both"); ### Query plan statement details -$frame = $PlanMain->Frame(-borderwidth => 3, -relief => 'raised'); -$frame->Label(-text => 'Query Step Details')->pack(-anchor => 'nw'); -$PlanStep = $frame->Scrolled('ROText', -height => 10, -width => 80, - -borderwidth => 0, -wrap => 'word', - -setgrid => 'true', -scrollbars => 'oe') - ->pack(-fill => 'x'); -$frame->pack(-fill => 'x'); +$frame = $PlanMain->Frame(-borderwidth => 3, -relief => "raised"); +$frame->Label(-text => "Query Step Details")->pack(-anchor => "nw"); +$PlanStep = $frame->Scrolled("ROText", -height => 10, -width => 80, + -borderwidth => 0, -wrap => "word", + -setgrid => "true", -scrollbars => "oe") + ->pack(-fill => "x"); +$frame->pack(-fill => "x"); ### SQL text editor -$frame = $PlanMain->Frame(-borderwidth => 3, -relief => 'raised'); -$frame->Label(-text => 'SQL Editor')->pack(-anchor => 'nw'); -$PlanSql = $frame->Scrolled('Text', -setgrid => 'true', -scrollbars => 'oe', +$frame = $PlanMain->Frame(-borderwidth => 3, -relief => "raised"); +$frame->Label(-text => "SQL Editor")->pack(-anchor => "nw"); +$PlanSql = $frame->Scrolled("Text", -setgrid => "true", -scrollbars => "oe", -borderwidth => 0, -height => 15, -width => 80, - -wrap => 'word') - ->pack(-expand => 1, -fill => 'both'); -$frame->pack(-expand => 1, -fill => 'both'); + -wrap => "word") + ->pack(-expand => 1, -fill => "both"); +$frame->pack(-expand => 1, -fill => "both"); ### Buttons -$frame = $PlanMain->Frame(-borderwidth => 3, -relief => 'raised'); -$frame->Button(-text => 'Explain', -command => \&explain) - ->pack(-side => 'left', -expand => 1, -pady => 3); -$frame->Button(-text => 'Clear', -command => \&clear_editor) - ->pack(-side => 'left', -expand => 1, -pady => 3); -$frame->Button(-text => 'Grab', -command => \&grab_main) - ->pack(-side => 'left', -expand => 1, -pady => 3); -$frame->pack(-fill => 'x'); +$frame = $PlanMain->Frame(-borderwidth => 3, -relief => "raised"); +$frame->Button(-text => "Explain", -command => \&explain) + ->pack(-side => "left", -expand => 1, -pady => 3); +$frame->Button(-text => "Clear", -command => \&clear_editor) + ->pack(-side => "left", -expand => 1, -pady => 3); +$frame->Button(-text => "Grab", -command => \&grab_main) + ->pack(-side => "left", -expand => 1, -pady => 3); +$frame->pack(-fill => "x"); ### user/pass@db command-line argument processing if (@ARGV >= 1 && $ARGV[0] =~ /\w*\/\w*(@\w+)?/) { my ($username, $password, $database) = split(/[\/@]/, shift(@ARGV)); - if (! $username) { $username = '/'; $password = ''; } + if (! $username) { $username = "/"; $password = ""; } if (! $database) { $database = $ENV{TWO_TASK} || $ENV{ORACLE_SID}; } error($PlanMain, $@) if (! eval { login($database, $username, $password); }); } @@ -918,6 +1143,202 @@ if (@ARGV >= 1 && -r $ARGV[0]) MainLoop(); ################################################################################ +__END__ + +=head1 NAME + +explain, ora_explain - visualise Oracle query plans + +=head1 SYNOPSIS + + $ explain [ [ user/password@database ] sql script ] + $ ora_explain [ [ user/password@database ] sql script ] + +=head1 DESCRIPTION + +explain is a GUI-based tool that enables easier visualisation of Oracle Query +plans. A query plan is the access path that Oracle will use to satisfy a SQL +query. The Oracle query optimiser is responsible for deciding on the optimal +path to use. Needless to say, understanding such plans requires a fairly +sophisticated knowledge of Oracle architecture and internals. + +explain allows a user to interactively edit a SQL statemant and view the +resulting query plan with the click of a single button. The effects of +modifying the SQL or of adding hints can be rapidly established. + +explain allows the user to grab all the SQL currently cached by Oracle. The SQL +capture can be filtered and sorted by different criterea, e.g. all SQL matching +a pattern, order by number of executions etc. + +explain is written using Perl, DBI/DBD::Oracle and Tk. + +=head1 PREREQUISITES + +=over 2 + +=item 1. + +Oracle 7 or Oracle 8, with SQL*Net if appropriate + +=item 2. + +L or later + +=item 3. + +L version 0.93 or later + +=item 4. + +L 0.49 or later + +=item 5. + +L 8.005 or later + +=item 6. + +L 3.15 or later + +=back + +Items 2 through 6 can be obtained from any CPAN mirror. + +=head1 INSTALLATION + +=over 2 + +=item 1. + +Check you have all the prequisites installed and working. + +=item 2. + +Check the #! line in the script points to where your Perl interpreter is +installed. + +=item 3. + +Copy the "explain" script to somewhere on your path. + +=item 4. + +Make sure the "explain" script is executable. + +=item 5. + +Make sure you have run the script $ORACLE_HOME/rdbms/admin/utlxplan.sql +from a SQL*Plus session. This script creates the PLAN_TABLE that is used +by Oracle when explaining query plans. + +=back + +=head1 HOW TO USE + +Type "explain" at the shell prompt. A window will appear with a menu bar and +three frames, labelled "Query Plan", "Query Step Details" and "SQL Editor". At +the bottom of the window is a single button labelled "Explain". A login dialog +will also appear, into which you should enter the database username, password +and database instance name (SID). The parameters you enter are passed to the +DBI->connect() method, so if you have any problems refer to the DBI and +DBD::Oracle documentation. + +Optionally you may supply up to two command-line arguments. If the first +argument is of the form username/password@database, explain will use this to +log in to Oracle, otherwise if it is a filename it will be loaded into the SQL +editor. If two arguments are supplied, the second one will be assumed to be a +filename. + +Examples: + + explain scott/tiger@DEMO query.sql + explain / query.sql + explain query.sql + +=head2 Explain functionality + +The menu bar has one pulldown menu, "File", which allows you to login to Oracle, +Grab the contents of the Oracle SQL cache, Load SLQ from files, Save SQL to +files and to Exit the program. + +The "SQL Editor" frame allows the editing of a SQL statement. This should be +just a single statement - multiple statements are not allowed. Refer to the +documentation for the Tk text widget for a description of the editing keys +available. Text may be loaded and saved by using the "File" pulldown menu. + +Once you have entered a SQL statement, the "Explain" button at the bottom of +the window will generate the query plan for the statement. A tree +representation of the plan will appear in the "Query Plan" frame. Individual +"legs" of the plan may be expanded and collapsed by clicking on the "+' and "-" +boxes on the plan tree. The tree is drawn so that the "innermost" or "first" +query steps are indented most deeply. The connecting lines show the +"parent-child" relationships between the query steps. For a comprehensive +explanation of the meaning of query plans you should refer to the relevant +Oracle documentation. + +Single-clicking on a plan step in the Query Plan pane will display more +detailed information on that query step in the Query Step Details frame. This +information includes Oracle's estimates of cost, cardinality and bytes +returned. The exact information displayed depends on the Oracle version. +Again, for detailed information on the meaning of these fields, refer to the +Oracle documentation. + +Double-clicking on a plan step that refers to either a table or an index will +pop up a dialog box showing the definition of the table or index in a format +similar to that of the SQL*Plus 'desc' command. + +Right-clicking on a plan step that refers to a table will pop up a menu showing +a list of the indexes available for the table. Selecting an index will display +its definition in a dialog box. + +=head2 Grab functionality + +The explain window has an option on the "File" menu labelled "Grab SQL ...". +Selecting this will popup a new top-level window containing a menu bar and +three frames, labelled "SQL Cache", "SQL Statement Statistics" and "SQL +Selection Criterea". At the bottom of the window is a single button labelled +"Grab". + +The menu bar has one pulldown menu, "File", which allows you to Save the +contents of the SQL Cache frame and Close the Grab window. + +The "SQL Cache" frame shows the statements currently in the Oracle SQL cache. +Text may be saved by using the "File" pulldown menu. + +The "SQL Selection Criterea" frame allows you to specify which SQL statements +you are interested in, and how you want them sorted. The pattern used to select +statements is a normal perl regexp. Once you have defined the selection +criterea, clicking the "Grab" button will read all the matching statements from +the SQL cache and display them in the top frame. + +Single-clicking on a statement in the SQL Cache pane will display more +detailed information on that statement in the Sql Statement Statistics frame, +including the number of times the statement has been executed and the numbers +of rows processed by the statement. + +Double-clicking on a statement will copy it into the SQL editor in the Explain +window, so that the query plan for the statement can be examined. + +=head1 SUPPORT + +Support questions and suggestions can be directed to Alan.Burlison@uk.sun.com + +=head1 COPYRIGHT AND DISCLAIMER + +Copyright (c) 1998 Alan Burlison + +You may distribute under the terms of either the GNU General Public License +or the Artistic License, as specified in the Perl README file, with the +exception that it cannot be placed on a CD-ROM or similar media for commercial +distribution without the prior approval of the author. + +This code is provided with no warranty of any kind, and is used entirely at +your own risk. + +This code was written by the author as a private individual, and is in no way +endorsed or warrantied by Sun Microsystems. + +=cut SCRIPT use Config; From 45aed768137fad4d8066e92f18257fd514e45334 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Tue, 15 Dec 1998 19:49:48 -0500 Subject: [PATCH 038/637] import DBD-Oracle 0.55 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.55 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.55.tar.gz --- Changes | 13 +++++++++++++ Makefile.PL | 23 +++++++++++++---------- Oracle.pm | 47 ++++++++++++++++++++++++++++++++--------------- Oracle.xs | 4 ++-- Todo | 9 +-------- dbdimp.c | 5 +++-- dbdimp.h | 2 +- oci7.h | 6 +++--- oci8.h | 4 ++-- ora_explain.PL | 0 test.pl | 13 +++++++------ 11 files changed, 77 insertions(+), 49 deletions(-) mode change 100755 => 100644 ora_explain.PL diff --git a/Changes b/Changes index 19bf8f09..ff3b57e0 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,16 @@ +Changes in DBD::Oracle 0.55 (Oraperl 1.37), 16th December 1998 + + Major internal work to support Oracle 8 OCI. + Oracle 8 LOBs are supported and treated as LONGs (DBD::Oracle works + hard to hide the complexities of handling Lob Locators for you). + See Oracle 8 section in the docs for more details. + Added $sth->{TYPE}. + SCALE & PRECISION are implemented but return 0 (Oracle bug?). + DBI 1.02 or later is required. + Assorted build time Makefile.PL improvements. + Builds with 5.004_04, 5.005_02 and 5.005_54 (not _53). + Added "use DBD::Oracle qw(:ora_types);" + Changes in DBD::Oracle 0.54 (Oraperl 1.37), 14th August 1998 Added $dbh->type_info_all. diff --git a/Makefile.PL b/Makefile.PL index 169ebfbe..9a43c5f6 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.69 1998/11/29 00:14:07 timbo Exp timbo $ +# $Id: Makefile.PL,v 1.71 1998/12/16 00:23:12 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -10,6 +10,14 @@ use Cwd; use File::Find; use strict; +# This DBI must be installed before we can build a DBD. +# For those not using Dynamic loading this means building a +# new static perl in the DBI directory by saying 'make perl' +# and then using _that_ perl to make this one. +use DBI 1.02; +use DBI::DBD; # DBD creation tools + + # Some MakeMaker's forged some FileHandle methods require FileHandle unless defined(&FileHandle::new); @@ -20,23 +28,18 @@ BEGIN { if ($^O eq 'VMS') { import VMS::Filespec; }} -# This DBI must be installed before we can build a DBD. -# For those not using Dynamic loading this means building a -# new static perl in the DBI directory by saying 'make perl' -# and then using _that_ perl to make this one. -use DBI 1.02; -use DBI::DBD; # DBD creation tools my $dbi_dir = dbd_dbi_dir(); my $dbi_arch_dir = dbd_dbi_arch_dir(); my $os = $^O; my $osvers = $Config{osvers}; $osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 +my $exe_ext = ($os eq 'VMS') ? '.pl' : ''; my %opts = ( NAME => 'DBD::Oracle', VERSION_FROM => 'Oracle.pm', - EXE_FILES => [ 'ora_explain' ], + EXE_FILES => [ "ora_explain$exe_ext" ], OBJECT => '$(O_FILES)', DEFINE => '', DIR => [], @@ -466,8 +469,8 @@ sub fetch_oci_macros { $edit{ORA_NLS} = $edit{ORA_NLS33} = q{ print "Deleting $_\n", - "because it is not already set in the environment\n", - "and it can cause ORA-01019 errors.\n"; + " because it is not already set in the environment\n", + " and it can cause ORA-01019 errors.\n"; $_ = ''; } unless $ENV{ORA_NLS} || $ENV{ORA_NLS33}; diff --git a/Oracle.pm b/Oracle.pm index 4e5d5a9e..6641aa04 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.59 1998/12/02 02:48:32 timbo Exp $ +# $Id: Oracle.pm,v 1.61 1998/12/16 00:23:12 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.54_93'; +$DBD::Oracle::VERSION = '0.55'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -31,7 +31,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.59 $, 10); + my $Revision = substr(q$Revision: 1.61 $, 10); require_version DBI 1.02; @@ -142,7 +142,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; # If the application is asking for specific database # then we have to mung the - if (DBD::Oracle::OCI() >= 8) { + if (DBD::Oracle::ORA_OCI() >= 8) { $dbname = $1 if !$dbname && $user =~ s/\@(.*)//; } elsif ($dbname) { @@ -197,7 +197,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; 'USER' => $user, 'CURRENT_USER' => $user, }); - # Call Oracle OCI orlon func in Oracle.xs file + # Call Oracle OCI logon func in Oracle.xs file # and populate internal handle data. DBD::Oracle::db::_login($dbh, $dbname, $user, $auth) or return undef; @@ -220,8 +220,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; 'Statement' => $statement, }); - # Call Oracle OCI oparse func in Oracle.xs file. - # (This will actually also call oopen for you.) + # Call Oracle OCI parse func in Oracle.xs file. # and populate internal handle data. DBD::Oracle::st::_prepare($sth, $statement, @attribs) @@ -389,6 +388,10 @@ DBD::Oracle - Oracle database driver for the DBI module # See the DBI module documentation for full details + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); + + =head1 DESCRIPTION DBD::Oracle is a Perl module which works with the DBI module to provide @@ -576,7 +579,8 @@ If it generates any errors which look relevant then please talk to yor Oracle technical support (and not the dbi-users mailing list). Thanks. Thanks to Mark Dedlow for this information. -=head2 International NLS / 8-bit text issues + +=head1 International NLS / 8-bit text issues If 8-bit text is returned as '?' characters or can't be inserted make sure the following environment vaiables are set correctly: @@ -792,6 +796,11 @@ for LOB type. Here's a quote from the Oracle OCI documentation: rewriting of the internals of the drivers. There are bound to be some minor problems.) +The DBD::Oracle module will avoid an explicit 'describe' operation +prior to the execution of the statement unless the application requests +information about the results (such as $sth->{NAME}). This reduces +Communication with the server and increases performance. + When fetching LOBs, they are treated just like LONGs and are subject to $sth->{LongReadLen} and $sth->{LongTruncOk}. @@ -802,8 +811,8 @@ them. However, it works, and I've made it as fast as possible (just one extra server-round-trip per insert or update after the first). For the time being, only single-row LOB updates are supported. -To insert or update a LOB, DBD::Oracle has to know in advance that it -is a LOB type, there's no way around this. So you need to say: +To insert or update a large LOB, DBD::Oracle has to know in advance +that it is a LOB type. So you need to say: $sth->bind_param($idx, $value, { ora_type => ORA_CLOB }); @@ -822,17 +831,21 @@ So any code you may have now that looks like should change the 8 (LONG type) to ORA_CLOB or ORA_BLOB (or 112 or 113). + =head1 Oracle on Linix To join the oracle-on-linux mailing list, see: http://www.datamgmt.com/maillist.html http://www.eGroups.com/list/oracle-on-linux + http://www.wmd.de/wmd/staff/pauck/misc/oracle_on_linux.html mailto:oracle-on-linux-subscribe@egroups.com + =head1 Commercial Oracle Tools -Assorted tools and references for general information. No recommendation implied. +Assorted tools and references for general information. +No recommendation implied. PL/Vision from RevealNet and Steven Feuerstein. @@ -845,13 +858,14 @@ SoftTree Technologies: http://www.SoftTreeTech.com http://www.databasegroup.com -=head1 SEE ALSO +=head1 BUGS -L +For $sth->{SCALE} and $sth->{PRECISION} Oracle always returns 0. Both +with Oracle 7 and Oracle 8 OCI. Any idea why? -Linux uses should read: +=head1 SEE ALSO - http://www.wmd.de/wmd/staff/pauck/misc/oracle_on_linux.html +L =head1 AUTHOR @@ -867,6 +881,9 @@ without the prior approval of the author. =head1 ACKNOWLEDGEMENTS +A great many people have helped me over the years. Far too many to +name, but I thank them all. + See also L. =cut diff --git a/Oracle.xs b/Oracle.xs index 75b59f2f..3ab8704c 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -8,7 +8,7 @@ I32 constant() PROTOTYPE: ALIAS: - OCI = 0 + ORA_OCI = 0 ORA_VARCHAR2= 1 ORA_NUMBER = 2 ORA_LONG = 8 @@ -24,7 +24,7 @@ constant() CODE: if (!ix) { char *what = GvNAME(CvGV(cv)); - if (strEQ(what,"OCI")) + if (strEQ(what,"ORA_OCI")) #ifdef OCI_V8_SYNTAX RETVAL = 8; #else diff --git a/Todo b/Todo index 2e0df965..606ace54 100644 --- a/Todo +++ b/Todo @@ -1,13 +1,9 @@ -Oracle 8 esp *LOBS - -SCALE, PRECISION +SCALE, PRECISION return 0! prepare("insert .. into ... RETURNING foo INTO :bar") bind_param(... { TYPE => SQL_* }) esp SQL_LONGVARCHAR etc -use DBD::Oracle qw(:ora_types); - $sth = $dbh->prepare("select ... for update"); $dbh->commit; $sth->execute; # fails ? auto-re-prepare? @@ -20,9 +16,6 @@ $drh->debug oddities (re data_source debugging) ora_bind() failed err = ORA-01026: multiple buffers of size > 4000 in the bind list (DBD: oexec error) -DBI::st=HASH(0x5b5c2c) debug level set to 2 ... (add perl version -number and other info here). - http://outside.organic.com/mail-archives/dbi-users/Nov1997/0116.html Test LongReadLen and especially the default behaviour of LongTruncOk diff --git a/dbdimp.c b/dbdimp.c index 9c4bbd68..037ad276 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.42 1998/12/02 02:48:32 timbo Exp $ + $Id: dbdimp.c,v 1.44 1998/12/16 00:41:53 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -1163,7 +1163,8 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count status = OCIStmtExecute(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, (is_select) ? 0 : 1, 0, 0, 0, - (DBIc_has(imp_dbh,DBIcf_AutoCommit)) + /* we don't AutoCommit on select so LOB locators work */ + (DBIc_has(imp_dbh,DBIcf_AutoCommit) && !is_select) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIStmtExecute"); diff --git a/dbdimp.h b/dbdimp.h index db5459df..fd082767 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.24 1998/12/02 02:48:32 timbo Exp $ + $Id: dbdimp.h,v 1.26 1998/12/16 00:23:12 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce diff --git a/oci7.h b/oci7.h index ddfb31ed..c0f9831e 100644 --- a/oci7.h +++ b/oci7.h @@ -1,5 +1,5 @@ /* - $Id: oci7.h,v 1.2 1998/11/29 00:14:07 timbo Exp $ + $Id: oci7.h,v 1.3 1998/12/16 00:19:34 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -199,11 +199,11 @@ dbd_describe(h, imp_sth) int dbtype; fbh->imp_sth = imp_sth; - fbh->name = cbuf_ptr; + fbh->name = (char*)cbuf_ptr; fbh->cbufl = f_cbufl[i]; /* DESCRIBE */ odescr(imp_sth->cda, i, - &fbh->dbsize, &fbh->dbtype, fbh->name, &fbh->cbufl, + &fbh->dbsize, &fbh->dbtype, (sb1*)fbh->name, &fbh->cbufl, &fbh->disize, &fbh->prec, &fbh->scale, &fbh->nullok); fbh->name[fbh->cbufl] = '\0'; /* ensure null terminated */ cbuf_ptr += fbh->cbufl + 1; /* increment name pointer */ diff --git a/oci8.h b/oci8.h index 496e3281..ddd427b0 100644 --- a/oci8.h +++ b/oci8.h @@ -1,5 +1,5 @@ /* - $Id: oci8.h,v 1.3 1998/12/02 02:48:32 timbo Exp $ + $Id: oci8.h,v 1.5 1998/12/16 00:23:12 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -774,7 +774,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) sv_catpv(sql_select, " from "); sv_catpv(sql_select, tablename); - sv_catpv(sql_select, " where rowid = :rid"); + sv_catpv(sql_select, " where rowid = :rid for update"); /* get row with lock */ if (dbis->debug >= 3) fprintf(DBILOGFP, " lob refetch sql: %s\n", SvPVX(sql_select)); diff --git a/ora_explain.PL b/ora_explain.PL old mode 100755 new mode 100644 diff --git a/test.pl b/test.pl index ad3d6b09..c7abe12d 100755 --- a/test.pl +++ b/test.pl @@ -4,7 +4,7 @@ die "Use 'make test' to run test.pl\n" unless "@INC" =~ /\bblib\b/; -# $Id: test.pl,v 1.32 1998/11/29 00:14:07 timbo Exp $ +# $Id: test.pl,v 1.33 1998/12/16 00:19:34 timbo Exp $ # # Copyright (c) 1995-1998, Tim Bunce # @@ -12,14 +12,14 @@ # License or the Artistic License, as specified in the Perl README file. # XXX -# XXX Please note that this code is a random hotch-potch of tests and -# XXX test frameworks and is in *no way* a to be used as a style guide! +# XXX PLEASE NOTE THAT THIS CODE IS A RANDOM HOTCH-POTCH OF TESTS AND +# XXX TEST FRAMEWORKS AND IS IN *NO WAY* A TO BE USED AS A STYLE GUIDE! # XXX require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.32 $}."\n"; +print q{Oraperl test application $Revision: 1.33 $}."\n"; $SIG{__WARN__} = sub { ($_[0] =~ /^(Bad|Duplicate) free/) @@ -152,20 +152,21 @@ sub test1 { $csr->{RaiseError} = 1; print "Fields: ",scalar(&ora_fetch($csr)),"\n"; - die "ora_fetch in scalar context error\n" unless &ora_fetch($csr)==5; + die "ora_fetch in scalar context error" unless &ora_fetch($csr)==5; print "Names: ",DBI::neat_list([&ora_titles($csr)], 0,"\t"),"\n"; print "Lengths: ",DBI::neat_list([&ora_lengths($csr)],0,"\t"),"\n"; print "OraTypes: ",DBI::neat_list([&ora_types($csr)], 0,"\t"),"\n"; print "SQLTypes: ",DBI::neat_list($csr->{TYPE}, 0,"\t"),"\n"; print "Scale: ",DBI::neat_list($csr->{SCALE}, 0,"\t"),"\n"; print "Precision: ",DBI::neat_list($csr->{PRECISION}, 0,"\t"),"\n"; + print "Nullable: ",DBI::neat_list($csr->{NULLABLE}, 0,"\t"),"\n"; print "Est row width: $csr->{ora_est_row_width}\n"; print "Prefetch cache: $csr->{RowsInCache}\n" if $csr->{RowsInCache}; print "Data rows:\n"; #$csr->debug(2); while(@fields = $csr->fetchrow_array) { - die "ora_fetch returned .".@fields." fields instead of 5!" + die "ora_fetch returned ".@fields." fields instead of 5!" if @fields != 5; die "Perl list/scalar context error" if @fields==1; print " fetch: ", DBI::neat_list(\@fields),"\n"; From 9f469fac900704da638a36b15884ffdc567f3868 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Sun, 27 Dec 1998 19:09:19 -0500 Subject: [PATCH 039/637] import DBD-Oracle 0.59 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.59 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.59.tar.gz --- Changes | 27 +++ MANIFEST | 4 +- Makefile.PL | 39 +++-- Oracle.h | 6 +- Oracle.pm | 86 +++++++--- Oracle.xs | 24 +-- README | 3 +- Todo | 11 +- dbdimp.c | 285 +++++++++---------------------- dbdimp.h | 94 ++++++++--- oci7.h => oci7.c | 126 ++++++++++---- oci8.h => oci8.c | 431 +++++++++++++++++++++++++++++++++++------------ t/plsql.t | 43 +++-- test.pl | 7 +- 14 files changed, 740 insertions(+), 446 deletions(-) rename oci7.h => oci7.c (82%) rename oci8.h => oci8.c (69%) diff --git a/Changes b/Changes index ff3b57e0..b135b641 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,30 @@ +Changes in DBD::Oracle 0.59 (Oraperl 1.37), 27th December 1998 + + Fixed detection of ambiguous LOB-param-to-table-field assignment + (previous fix had typo). Only affects multiple LOBs in same table. + Added support for Oracle 8's "... RETURNING foo,bar INTO :foo,:bar" + for simple scalar types (not LOBs or arrays) via bind_param_inout. + Cleaned up the code. + Improved Oracle 8 library selection code for Win32 (untested). + +Changes in DBD::Oracle 0.58 (Oraperl 1.37), 22nd December 1998 + + Fixed detection of ambiguous LOB-param-to-table-field assignment. + Added bind_param ora_field attribute to disambiguate if needed. + +Changes in DBD::Oracle 0.57 (Oraperl 1.37), 21st December 1998 + + Fixed bug preventing fetching LONGs when using OCI 8, better. + (Oracle bug #641812 not involved. Should work for all 8.0.x) + +Changes in DBD::Oracle 0.56 (Oraperl 1.37), 19th December 1998 + + Fixed bug preventing fetching LONGs when using OCI 8. + (Oracle bug #641812 may still cause failure prior to v8.0.5.) + Fixed LongTruncOk to work when using OCI 8. + Fixed bug in table name detection code for OCI8 LOB refetch. + SCALE & PRECISION work for OCI 7 & 8. + Changes in DBD::Oracle 0.55 (Oraperl 1.37), 16th December 1998 Major internal work to support Oracle 8 OCI. diff --git a/MANIFEST b/MANIFEST index 7fe0ea9c..31ebde4e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -16,8 +16,8 @@ Todo dbdimp.c dbdimp.h hints/svr4.pl -oci7.h -oci8.h +oci7.c +oci8.c ora_explain.PL oraperl.ex/Readme Oraperl examples (copied mostly unchanged from oraperl-2.4) oraperl.ex/bind.pl diff --git a/Makefile.PL b/Makefile.PL index 9a43c5f6..5a58d5fa 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.71 1998/12/16 00:23:12 timbo Exp $ +# $Id: Makefile.PL,v 1.72 1998/12/28 00:04:37 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -143,19 +143,31 @@ if ($os eq 'VMS') { } elsif ($os eq 'MSWin32') { + my $oci_compiler_dir = ($Config{cc} eq 'bcc32' ? "BORLAND" : "MSVC"); + my $OCIDIR = ""; - my $OCILIB = "OCI"; - if ($::opt_8) { # opt_8 means DISABLE use of OCI 8 API - $OCILIB = "OCIW32"; - } find( sub { - print "Found $_\n" if /^OCI\d+/i; - $OCIDIR = $_ if /^OCI\d\d$/i && $OCIDIR lt $_; - $File::Find::prune = 1 if -d $_ && $_ ne "." && $_ ne ".."; + print "Found $_ directory\n" if /^OCI\d+/i; + $OCIDIR = $_ if /^OCI\d\d+$/i && $OCIDIR lt $_; + $File::Find::prune = 1 if -d $_ && $_ !~ /^\./; }, $OH ); - print "Using $OCILIB in directory: $OCIDIR\n"; + print "Using OCI directory '$OCIDIR'\n"; - my $oci_compiler_dir = ($Config{cc} eq 'bcc32' ? "BORLAND" : "MSVC"); + my %OCILIB; + find( sub { + $File::Find::prune = 1 if -d $_ && $_ !~ /^\./; + return unless /^OCI.*\.LIB$/i; + print "Found $OCIDIR/lib/$oci_compiler_dir/$_ library\n"; + $OCILIB{uc($_)} = $_; + }, "$OH/$OCIDIR/lib/$oci_compiler_dir" ) if $OCIDIR; + # sort the version numbered libs into assending order + my @OCILIB = sort grep { /OCI\d\d+\./i } keys %OCILIB; + # prefer the non-versioned library if present + push @OCILIB, "OCI.LIB" if $OCILIB{'OCI.LIB'}; + # opt_8 means DISABLE use of OCI 8 API + push @OCILIB, "OCIW32.LIB" if $OCILIB{'OCIW32.LIB'} && $::opt_8; + my $OCILIB = pop @OCILIB || ''; + $OCILIB =~ s/\.LIB$//i; die qq{ Unable to find required Oracle OCI files for the build. Please check @@ -165,15 +177,16 @@ elsif ($os eq 'MSWin32') { $OH\\$OCIDIR\\include\\oratypes.h $OH\\$OCIDIR\\lib\\$oci_compiler_dir\\$OCILIB.lib - Please install OCI or send comments back to dbi-users\@fugue.com you - have an OCI directory other than $OCIDIR. + Please install OCI or send comments back to dbi-users\@fugue.com + if you have an OCI directory other than $OCIDIR. } unless (-e "$OH/$OCIDIR/include/oratypes.h" && -e "$OH/$OCIDIR/lib/$oci_compiler_dir/$OCILIB.lib"); + print "Using $OCIDIR/lib/$oci_compiler_dir/$OCILIB.lib\n"; + my $OCIINCLUDE = "-I$OH/$OCIDIR/include -I$OH/rdbms/demo"; $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/$oci_compiler_dir $OCILIB" ]; - #$opts{SKIP} = ['processPL']; # XXX added because it caused problems with Nmake... $opts{INC} = "$OCIINCLUDE -I$dbi_arch_dir"; } diff --git a/Oracle.h b/Oracle.h index 600b3491..00525640 100644 --- a/Oracle.h +++ b/Oracle.h @@ -1,5 +1,5 @@ /* - $Id: Oracle.h,v 1.13 1998/12/14 00:14:22 timbo Exp $ + $Id: Oracle.h,v 1.14 1998/12/28 00:04:37 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -11,7 +11,7 @@ */ -#define NEED_DBIXS_VERSION 9 +#define NEED_DBIXS_VERSION 93 #define PERL_POLLUTE @@ -19,7 +19,7 @@ #include "dbdimp.h" -#include /* installed by the DBI module */ +#include /* installed by the DBI module */ #ifdef yxyxyxyx /* These prototypes are for dbdimp.c funcs used in the XS file */ diff --git a/Oracle.pm b/Oracle.pm index 6641aa04..8f2b617e 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.61 1998/12/16 00:23:12 timbo Exp $ +# $Id: Oracle.pm,v 1.65 1998/12/28 00:04:37 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.55'; +$DBD::Oracle::VERSION = '0.59'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -31,7 +31,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.61 $, 10); + my $Revision = substr(q$Revision: 1.65 $, 10); require_version DBI 1.02; @@ -87,11 +87,11 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; foreach $d (qw(/etc /var/opt/oracle), $ENV{TNS_ADMIN}) { next unless defined $d; next unless open(FH, "<$d/oratab"); - warn "Loading $d/oratab\n" if $debug; + $drh->log_msg("Loading $d/oratab\n") if $debug; while () { next unless m/^\s*(\w+)\s*:\s*(.*?)\s*:/; $dbnames{$1} = $2; # store ORACLE_HOME value - warn "Found $1 \@ $2.\n" if $debug; + $drh->log_msg("Found $1 \@ $2.\n") if $debug; } close FH; last; @@ -101,11 +101,11 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; foreach $d ($ENV{TNS_ADMIN}, "$oracle_home/network/admin", '/var/opt/oracle') { next unless defined $d; next unless open(FH, "<$d/tnsnames.ora"); - warn "Loading $d/tnsnames.ora\n" if $debug; + $drh->log_msg("Loading $d/tnsnames.ora\n") if $debug; while () { next unless m/^\s*([-\w\.]+)\s*=/; my $name = $1; - warn "Found $name. ".($dbnames{$name} ? "(oratab entry overridden)" : "")."\n" + $drh->log_msg("Found $name. ".($dbnames{$name} ? "(oratab entry overridden)" : "")."\n") if $debug; $dbnames{$name} = 0; # exists but false (to distinguish from oratab) } @@ -114,14 +114,14 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; } eval q{ # XXX experimental, will probably change - warn "Fetching ORACLE_SID from Registry.\n" if $debug; + $drh->log_msg("Fetching ORACLE_SID from Registry.\n") if $debug; require Tie::Registry; $Tie::Registry::Registry->Delimeter("/"); my $hkey= $Tie::Registry::Registry->{"LMachine/Software/Oracle/"}; my $sid = $hkey->{ORACLE_SID}; my $home= $hkey->{ORACLE_HOME} || $ENV{ORACLE_HOME}; $dbnames{$sid} = $home if $sid and $home; - warn "Found $sid \@ $home.\n" if $debug; + $drh->log_msg("Found $sid \@ $home.\n") if $debug; } if ($^O eq "MSWin32"); $dbnames{0} = 1; # mark as loaded (even if empty) @@ -137,7 +137,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; sub connect { - my ($drh, $dbname, $user, $auth)= @_; + my ($drh, $dbname, $user, $auth, $attr)= @_; # If the application is asking for specific database # then we have to mung the @@ -202,6 +202,13 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; DBD::Oracle::db::_login($dbh, $dbname, $user, $auth) or return undef; + if ($attr && $attr->{ora_module_name}) { + eval { + $dbh->do(q{BEGIN DBMS_APPLICATION_NAME.SET_MODULE(:1,NULL); END;}, + undef, $attr->{ora_module_name}); + }; + } + $dbh; } @@ -338,18 +345,18 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; sub dbms_output_get { my $dbh = shift; - my $sth = $dbh->prepare_cached("begin dbms_output.get_line(:1, :2); end;") + my $sth = $dbh->prepare_cached("begin dbms_output.get_line(:l, :s); end;") or return; my ($line, $status, @lines); # line can be greater that 255 (e.g. 7 byte date is expanded on output) - $sth->bind_param_inout(1, \$line, 400); - $sth->bind_param_inout(2, \$status, 20); + $sth->bind_param_inout(':l', \$line, 400); + $sth->bind_param_inout(':s', \$status, 20); if (!wantarray) { $sth->execute or return undef; - return $line if $status == 0; + return $line if $status eq '0'; return undef; } - push @lines, $line while($sth->execute && $status==0); + push @lines, $line while($sth->execute && $status eq '0'); return @lines; } @@ -364,6 +371,33 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; return 1; } + + sub dbms_msgpipe_get { + my $dbh = shift; + my $sth = $dbh->prepare_cached(q{ + begin dbms_msgpipe.get_request(:returnpipe, :proc, :param); end; + }) or return; + my $msg = ['','','']; + $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); + $sth->bind_param_inout(":proc", \$msg->[1], 30); + $sth->bind_param_inout(":param", \$msg->[2], 4000); + $sth->execute or return undef; + return $msg; + } + + sub dbms_msgpipe_ack { + my $dbh = shift; + my $msg = shift; + my $sth = $dbh->prepare_cached(q{ + begin dbms_msgpipe.acknowledge(:returnpipe, :errormsg, :param); end; + }) or return; + $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); + $sth->bind_param_inout(":proc", \$msg->[1], 30); + $sth->bind_param_inout(":param", \$msg->[2], 4000); + $sth->execute or return undef; + return 1; + } + } # end of package DBD::Oracle::db @@ -451,7 +485,7 @@ SQL*Net 1.x and SQL*Net 2.x. "Machine" is the computer the database is running on, "SID" is the SID of the database, "DB" is the SQL*Net 2.x connection descriptor for the database. -B Some of these formats don't work with Oracle 8. +B Some of these formats may not work with Oracle 8. BEGIN { $ENV{ORACLE_HOME} = '/home/oracle/product/7.x.x'; @@ -784,7 +818,7 @@ source directory. DBD::Oracle version 0.55 onwards can be built to use either the Oracle 7 or Oracle 8 OCI (Oracle Call Interface) API functions. The new Oracle 8 API is used by default and offers several advantages, including support -for LOB type. Here's a quote from the Oracle OCI documentation: +for LOB types. Here's a quote from the Oracle OCI documentation: The Oracle8 OCI has several enhancements to improve application performance and scalability. Application performance has been improved @@ -799,14 +833,14 @@ minor problems.) The DBD::Oracle module will avoid an explicit 'describe' operation prior to the execution of the statement unless the application requests information about the results (such as $sth->{NAME}). This reduces -Communication with the server and increases performance. +communication with the server and increases performance. When fetching LOBs, they are treated just like LONGs and are subject to $sth->{LongReadLen} and $sth->{LongTruncOk}. When inserting or updating LOBs some *major* magic has to be performed behind the scenes to make it transparent. Basically the driver has to -refetch the newly inserted 'Lob Locators' before being able to write to +refetch the newly inserted 'LOB Locators' before being able to write to them. However, it works, and I've made it as fast as possible (just one extra server-round-trip per insert or update after the first). For the time being, only single-row LOB updates are supported. @@ -814,11 +848,11 @@ For the time being, only single-row LOB updates are supported. To insert or update a large LOB, DBD::Oracle has to know in advance that it is a LOB type. So you need to say: - $sth->bind_param($idx, $value, { ora_type => ORA_CLOB }); + $sth->bind_param($idx, $value, { ora_type => ORA_CLOB }); The ORA_CLOB and ORA_BLOB constants can be imported using - use DBD::Oracle qw(:ora_types); + use DBD::Oracle qw(:ora_types); or just use the corresponding integer values (112 and 113). @@ -826,11 +860,19 @@ To make scripts work with both Oracle7 and Oracle8, the Oracle7 DBD::Oracle will treat the LOB ora_types as LONGs without error. So any code you may have now that looks like - $sth->bind_param($idx, $value, { ora_type => 8 }); + $sth->bind_param($idx, $value, { ora_type => 8 }); should change the 8 (LONG type) to ORA_CLOB or ORA_BLOB (or 112 or 113). +One further wrinkle: for inserts and updates of LOBs DBD::Oracle has +to be able to tell which parameters relate to which table field. In +all cases where it can possibly work it out for itself, it does, +however, if there are multiple LOB fields of the same type in the table +then you need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + =head1 Oracle on Linix diff --git a/Oracle.xs b/Oracle.xs index 3ab8704c..d3980afd 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -8,19 +8,19 @@ I32 constant() PROTOTYPE: ALIAS: + ORA_VARCHAR2 = 1 + ORA_NUMBER = 2 + ORA_LONG = 8 + ORA_ROWID = 11 + ORA_DATE = 12 + ORA_RAW = 23 + ORA_LONGRAW = 24 + ORA_CHAR = 96 + ORA_MLSLABEL = 105 + ORA_NTY = 108 + ORA_CLOB = 112 + ORA_BLOB = 113 ORA_OCI = 0 - ORA_VARCHAR2= 1 - ORA_NUMBER = 2 - ORA_LONG = 8 - ORA_ROWID = 11 - ORA_DATE = 12 - ORA_RAW = 23 - ORA_LONGRAW = 24 - ORA_CHAR = 96 - ORA_MLSLABEL= 105 - ORA_NTY = 108 - ORA_CLOB = 112 - ORA_BLOB = 113 CODE: if (!ix) { char *what = GvNAME(CvGV(cv)); diff --git a/README b/README index 99f95d5a..bf67fee6 100644 --- a/README +++ b/README @@ -201,8 +201,7 @@ README.clients -- building/using DBD::Oracle on minimally configured systems README.login -- help for login problems README.longs -- examples dealing with LONG types (blobs) -DBI 'home page': http://www.arcana.co.uk/technologia/DBI (sadly often -out of date) +DBI 'home page': http://www.arcana.co.uk/technologia/DBI Master archive site for Perl DB information: ftp://ftp.demon.co.uk/pub/perl/db/ diff --git a/Todo b/Todo index 606ace54..b6aaa4e4 100644 --- a/Todo +++ b/Todo @@ -1,4 +1,5 @@ -SCALE, PRECISION return 0! + +connect(..., { ora_module_name => $0 }); prepare("insert .. into ... RETURNING foo INTO :bar") @@ -8,20 +9,14 @@ $sth = $dbh->prepare("select ... for update"); $dbh->commit; $sth->execute; # fails ? auto-re-prepare? -Fetch: If LongReadLen > 64k then automatocally call oflng for each long LONG. +Fetch: If LongReadLen > 64k then automatically call oflng for each long LONG. Bind: Automatically do piecewise insert of longs. -$drh->debug oddities (re data_source debugging) - ora_bind() failed err = ORA-01026: multiple buffers of size > 4000 in the bind list (DBD: oexec error) http://outside.organic.com/mail-archives/dbi-users/Nov1997/0116.html -Test LongReadLen and especially the default behaviour of LongTruncOk - -Add/update explain to dist - Handle binding of values > 32K long. Handle PL/SQL arrays. diff --git a/dbdimp.c b/dbdimp.c index 037ad276..3c527103 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.44 1998/12/16 00:41:53 timbo Exp $ + $Id: dbdimp.c,v 1.47 1998/12/28 00:04:37 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -21,21 +21,14 @@ DBISTATE_DECLARE; -static SV *ora_long; -static SV *ora_trunc; -static SV *ora_pad_empty; -static SV *ora_cache; -static SV *ora_cache_o; /* temp hack for ora_open() cache override */ +int ora_fetchtest; + static int ora_login_nomsg; /* don't fetch real login errmsg if true */ -static int ora_fetchtest; static int ora_sigchld_restart = 1; static int set_sigint_handler = 0; -static void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); static int ora2sql_type _((int oratype)); -static int calc_cache_rows _((int f, int ew, int cr, int hl)); -void ora_free_fbh_contents(imp_fbh_t *fbh); void ora_free_phs_contents(phs_t *phs); void @@ -43,21 +36,9 @@ dbd_init(dbistate) dbistate_t *dbistate; { DBIS = dbistate; - ora_long = perl_get_sv("Oraperl::ora_long", GV_ADDMULTI); - ora_trunc = perl_get_sv("Oraperl::ora_trunc", GV_ADDMULTI); - ora_cache = perl_get_sv("Oraperl::ora_cache", GV_ADDMULTI); - ora_cache_o = perl_get_sv("Oraperl::ora_cache_o", GV_ADDMULTI); -#ifdef USE_V8_SYNTAX - sv_setiv(perl_get_sv("DBD::Oracle::OCI", GV_ADDMULTI), 8); -#else - sv_setiv(perl_get_sv("DBD::Oracle::OCI", GV_ADDMULTI), 7); -#endif + dbd_init_oci(dbistate); - ora_pad_empty= perl_get_sv("Oraperl::ora_pad_empty", GV_ADDMULTI); - if (!SvOK(ora_pad_empty) && getenv("ORAPERL_PAD_EMPTY")) - sv_setiv(ora_pad_empty, atoi(getenv("ORAPERL_PAD_EMPTY"))); - - if (getenv("DBD_ORACLE_LOGIN_ERR")) + if (getenv("DBD_ORACLE_LOGIN_NOMSG")) ora_login_nomsg = atoi(getenv("DBD_ORACLE_LOGIN_NOMSG")); if (getenv("DBD_ORACLE_SIGCHLD")) ora_sigchld_restart = atoi(getenv("DBD_ORACLE_SIGCHLD")); @@ -87,16 +68,16 @@ dbd_discon_all(drh, imp_drh) -static void -fbh_dump(fbh, i, aidx) +void +dbd_fbh_dump(fbh, i, aidx) imp_fbh_t *fbh; int i; int aidx; /* array index */ { FILE *fp = DBILOGFP; fprintf(fp, " fbh %d: '%s'\t%s, ", - i, fbh->name, (fbh->nullok) ? "NULLable" : ""); - fprintf(fp, "type %3d->%2d, dbsize %ld/%ld, p%d s%d\n", + i, fbh->name, (fbh->nullok) ? "NULLable" : "NO null "); + fprintf(fp, "otype %3d->%3d, dbsize %ld/%ld, p%d.s%d\n", fbh->dbtype, fbh->ftype, (long)fbh->dbsize,(long)fbh->disize, fbh->prec, fbh->scale); if (fbh->fb_ary) { @@ -107,8 +88,8 @@ fbh_dump(fbh, i, aidx) } -static int -dbtype_is_long(dbtype) +int +ora_dbtype_is_long(dbtype) int dbtype; { /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW type? */ @@ -151,8 +132,8 @@ oratype_bind_ok(dbtype) /* It's a type we support for placeholders */ fb_ary_t * fb_ary_alloc(bufl, size) -int bufl; -int size; + int bufl; + int size; { fb_ary_t *fb_ary; /* these should be reworked to only to one Newz() */ @@ -168,7 +149,7 @@ int size; void fb_ary_free(fb_ary) -fb_ary_t *fb_ary; + fb_ary_t *fb_ary; { Safefree(fb_ary->abuf); Safefree(fb_ary->aindp); @@ -181,15 +162,6 @@ fb_ary_t *fb_ary; /* ================================================================== */ -#ifdef OCI_V8_SYNTAX -#include "oci8.h" -#else -#include "oci7.h" -#endif - - -/* ================================================================== */ - int dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) SV *dbh; @@ -205,9 +177,8 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) D_imp_drh_from_dbh; if (!imp_drh->envhp) { - /* OCI_OBJECT mode needed for OCIDescribeAny (even if not */ - /* describing anything related to or using objects). */ - /* If you don't you get a core dump (8.0.4). Thanks Oracle! */ + /* OCI_OBJECT needed for OCIDescribeAny of table with LOBs */ + /* else you get a core dump (8.0.4). Thanks Oracle! */ OCIInitialize((ub4) OCI_OBJECT, 0, 0,0,0); ret = OCIEnvInit( &imp_drh->envhp, OCI_DEFAULT, 0, 0 ); } @@ -507,105 +478,8 @@ dbd_db_FETCH_attrib(dbh, imp_dbh, keysv) /* ================================================================== */ -int -dbd_st_prepare(sth, imp_sth, statement, attribs) - SV *sth; - imp_sth_t *imp_sth; - char *statement; - SV *attribs; -{ - D_imp_dbh_from_sth; - ub4 oparse_lng = 1; /* auto v6 or v7 as suits db connected to */ -#ifdef OCI_V8_SYNTAX - sword status = 0; -#endif - - imp_sth->done_desc = 0; - - if (DBIc_COMPAT(imp_sth)) { - imp_sth->ora_pad_empty = (SvOK(ora_pad_empty)) ? SvIV(ora_pad_empty) : 0; - } - - if (attribs) { - SV **svp; - DBD_ATTRIB_GET_IV( attribs, "ora_parse_lang", 14, svp, oparse_lng); - } - - /* scan statement for '?', ':1' and/or ':foo' style placeholders */ - dbd_preparse(imp_sth, statement); - -#ifdef OCI_V8_SYNTAX - - imp_sth->envhp = imp_dbh->envhp; - imp_sth->errhp = imp_dbh->errhp; - imp_sth->srvhp = imp_dbh->srvhp; - imp_sth->svchp = imp_dbh->svchp; - - switch(oparse_lng) { - case 0: /* old: calls for V6 syntax - give them V7 */ - case 2: /* old: calls for V7 syntax */ - case 7: oparse_lng = OCI_V7_SYNTAX; break; - case 8: oparse_lng = OCI_V8_SYNTAX; break; - default: oparse_lng = OCI_NTV_SYNTAX; break; - } - - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_sth->stmhp, OCI_HTYPE_STMT); - status = OCIStmtPrepare(imp_sth->stmhp, imp_sth->errhp, - (text*)imp_sth->statement, (ub4)strlen(imp_sth->statement), - oparse_lng, OCI_DEFAULT); - if (status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, status, "OCIStmtPrepare"); - OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); - return 0; - } - - OCIAttrGet_stmhp(imp_sth, &imp_sth->stmt_type, 0, OCI_ATTR_STMT_TYPE); - if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_st_prepare'd sql %s\n", - oci_stmt_type_name(imp_sth->stmt_type)); - -#else - - if (!get_cursor(imp_dbh, sth, imp_sth)) - return 0; - - /* parse the (possibly edited) SQL statement */ - imp_sth->cda->peo = 0; - if (oparse(imp_sth->cda, (text*)imp_sth->statement, (sb4)-1, - (sword)0/*oparse_defer*/, (ub4)oparse_lng) - ) { - char buf[99]; - char *hint = ""; - if (1) { /* XXX could make optional one day */ - SV *msgsv, *sqlsv; - sprintf(buf,"error possibly near <*> indicator at char %d in '", - imp_sth->cda->peo+1); - msgsv = sv_2mortal(newSVpv(buf,0)); - sqlsv = sv_2mortal(newSVpv(imp_sth->statement,0)); - sv_insert(sqlsv, imp_sth->cda->peo, 0, "<*>",3); - sv_catsv(msgsv, sqlsv); - sv_catpv(msgsv, "'"); - hint = SvPV(msgsv,na); - } - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, hint); - free_cursor(sth, imp_sth); - return 0; - } - if (dbis->debug >= 2) - fprintf(DBILOGFP, " dbd_st_prepare'd sql f%d\n", imp_sth->cda->ft); - - /* Describe and allocate storage for results. */ - if (!dbd_describe(sth, imp_sth)) { - return 0; - } -#endif - - DBIc_IMPSET_on(imp_sth); - return 1; -} - -static void +void dbd_preparse(imp_sth, statement) imp_sth_t *imp_sth; char *statement; @@ -624,9 +498,8 @@ dbd_preparse(imp_sth, statement) /* initialise phs ready to be cloned per placeholder */ memset(&phs_tpl, 0, sizeof(phs_tpl)); + phs_tpl.imp_sth = imp_sth; phs_tpl.ftype = 1; /* VARCHAR2 */ - phs_tpl.aryelem_max = 0; - phs_tpl.aryelem_cur = 1; src = statement; dest = imp_sth->statement; @@ -682,7 +555,7 @@ dbd_preparse(imp_sth, statement) } -static int +int calc_cache_rows(num_fields, est_width, cache_rows, has_longs) int num_fields, est_width, cache_rows, has_longs; { @@ -752,7 +625,7 @@ ora_sql_type(imp_sth, name, sql_type) static int -_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) +dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) SV *sth; imp_sth_t *imp_sth; phs_t *phs; @@ -793,7 +666,7 @@ _rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) /* pre-upgrade high to reduce risk of SvPVX realloc/move */ (void)SvUPGRADE(phs->sv, SVt_PVNV); /* ensure room for result, 28 is magic number (see sv_2pv) */ - SvGROW(phs->sv, (phs->maxlen < 28) ? 28 : phs->maxlen+1); + SvGROW(phs->sv, (phs->maxlen < 28) ? 28 : phs->maxlen+1/*for null*/); } else { /* phs->sv is copy of real variable, upgrade to at least string */ @@ -821,11 +694,14 @@ _rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) if (phs->maxlen < 0) /* can happen with nulls */ phs->maxlen = 0; +#ifdef OCI_V8_SYNTAX + phs->alen = value_len + phs->alen_incnull; +#else if (value_len + phs->alen_incnull <= UB2MAXVAL) { phs->alen = value_len + phs->alen_incnull; *alen_ptr_ptr = &phs->alen; if (((IV)phs->alen) > phs->maxlen && phs->indp != -1) - croak("panic: _dbd_rebind_ph alen %ld > maxlen %ld", phs->alen,phs->maxlen); + croak("panic: dbd_rebind_ph alen %ld > maxlen %ld", phs->alen,phs->maxlen); } else { phs->alen = 0; @@ -833,11 +709,12 @@ _rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) if (phs->is_inout) croak("Can't bind LONG values (>%ld) as in/out parameters", (long)UB2MAXVAL); } +#endif if (dbis->debug >= 3) { - fprintf(DBILOGFP, " bind %s <== '%.*s' (size %d/%ld, otype %d, indp %d)\n", - phs->name, phs->alen, (phs->progv) ? phs->progv : "", - phs->alen, (long)phs->maxlen, phs->ftype, phs->indp); + fprintf(DBILOGFP, " bind %s <== '%.*s' (size %ld/%ld, otype %d, indp %d)\n", + phs->name, (int)phs->alen, (phs->progv) ? phs->progv : "", + (long)phs->alen, (long)phs->maxlen, phs->ftype, phs->indp); } return 1; @@ -846,7 +723,7 @@ _rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) #ifdef SQLT_CUR static int -_rebind_ph_cursor(sth, imp_sth, phs) +dbd_rebind_ph_cursor(sth, imp_sth, phs) SV *sth; imp_sth_t *imp_sth; phs_t *phs; @@ -877,36 +754,10 @@ _rebind_ph_cursor(sth, imp_sth, phs) #endif -#ifdef SQLT_CLOB -static int -_rebind_ph_lob(sth, imp_sth, phs) - SV *sth; - imp_sth_t *imp_sth; - phs_t *phs; -{ - sword status; - ub4 lobEmpty = 0; - - if (!phs->desc_h) { - ++imp_sth->has_lobs; - phs->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_sth->envhp, - &phs->desc_h, phs->desc_t); - } - status = OCIAttrSet(phs->desc_h, phs->desc_t, - &lobEmpty, 0, OCI_ATTR_LOBEMPTY, imp_sth->errhp); - if (status != OCI_SUCCESS) - return oci_error(sth, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_LOBEMPTY"); - phs->progv = (void*)&phs->desc_h; - phs->maxlen = sizeof(OCILobLocator*); - - return 1; -} -#endif static int -_dbd_rebind_ph(sth, imp_sth, phs) +dbd_rebind_ph(sth, imp_sth, phs) SV *sth; imp_sth_t *imp_sth; phs_t *phs; @@ -919,43 +770,50 @@ _dbd_rebind_ph(sth, imp_sth, phs) switch (phs->ftype) { #ifdef SQLT_CUR case SQLT_CUR: - if (!_rebind_ph_cursor(sth, imp_sth, phs)) + if (!dbd_rebind_ph_cursor(sth, imp_sth, phs)) return 0; break; #endif -#ifdef SQLT_CLOB +#ifdef OCI_V8_SYNTAX case SQLT_CLOB: case SQLT_BLOB: - if (!_rebind_ph_lob(sth, imp_sth, phs)) + if (!dbd_rebind_ph_lob(sth, imp_sth, phs)) return 0; break; #endif default: - if (!_rebind_ph_char(sth, imp_sth, phs, &alen_ptr)) + if (!dbd_rebind_ph_char(sth, imp_sth, phs, &alen_ptr)) return 0; } - /* Since we don't support LONG VAR types we must check */ - /* for lengths too big to pass to obndrv as an sword. */ - if (phs->maxlen > MINSWORDMAXVAL && sizeof(sword)<4) /* generally 32K */ - croak("Can't bind %s, value is too long (%ld bytes, max %d)", - phs->name, phs->maxlen, MINSWORDMAXVAL); - #ifdef OCI_V8_SYNTAX status = OCIBindByName(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, strlen(phs->name), phs->progv, phs->maxlen, phs->ftype, &phs->indp, - alen_ptr, &phs->arcode, - phs->aryelem_max, /* max elements that can fit in allocated array */ - NULL, /* (ptr to) current number of elements in array */ - OCI_DEFAULT); + NULL, /* ub2 *alen_ptr not needed with OCIBindDynamic */ + &phs->arcode, + 0, /* max elements that can fit in allocated array */ + NULL, /* (ptr to) current number of elements in array */ + OCI_DATA_AT_EXEC); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); + return 0; + } + status = OCIBindDynamic(phs->bndhp, imp_sth->errhp, + (dvoid *)phs, dbd_phs_in, (dvoid *)phs, dbd_phs_out); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); return 0; } #else + /* Since we don't support LONG VAR types we must check */ + /* for lengths too big to pass to obndrv as an sword. */ + if (phs->maxlen > MINSWORDMAXVAL && sizeof(sword)<4) /* generally 32K */ + croak("Can't bind %s, value is too long (%ld bytes, max %d)", + phs->name, phs->maxlen, MINSWORDMAXVAL); + if (obndra(imp_sth->cda, (text *)phs->name, -1, (ub1*)phs->progv, (sword)phs->maxlen, /* cast reduces max size */ (sword)phs->ftype, -1, @@ -1016,7 +874,8 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl fprintf(DBILOGFP, " bind %s <== %s (type %ld", name, neatsvpv(newvalue,0), (long)sql_type); if (is_inout) - fprintf(DBILOGFP, ", inout 0x%lx", (long)newvalue); + fprintf(DBILOGFP, ", inout 0x%lx, maxlen %ld,", + (long)newvalue, (long)maxlen); if (attribs) fprintf(DBILOGFP, ", attribs: %s", SvPV(attribs,na)); fprintf(DBILOGFP, ")\n"); @@ -1029,7 +888,6 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl if (phs->sv == &sv_undef) { /* first bind for this placeholder */ phs->ftype = 1; /* our default type: VARCHAR2 */ - phs->maxlen = maxlen; /* 0 if not inout */ phs->is_inout = is_inout; if (is_inout) { /* phs->sv assigned in the code below */ @@ -1058,6 +916,9 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl #endif phs->ftype = ora_type; } + if ( (svp=hv_fetch((HV*)SvRV(attribs), "ora_field",9, 0)) != NULL) { + phs->ora_field = SvREFCNT_inc(*svp); + } } if (sql_type) phs->ftype = ora_sql_type(imp_sth, phs->name, sql_type); @@ -1077,6 +938,8 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl phs->name, sql_type); } + phs->maxlen = maxlen; /* 0 if not inout */ + if (!is_inout) { /* normal bind to take a (new) copy of current value */ if (phs->sv == &sv_undef) /* (first time bind) */ phs->sv = newSV(0); @@ -1088,7 +951,7 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl phs->sv = SvREFCNT_inc(newvalue); /* point to live var */ } - return _dbd_rebind_ph(sth, imp_sth, phs); + return dbd_rebind_ph(sth, imp_sth, phs); } @@ -1137,12 +1000,12 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count /* Some checks for mutated storage since we pointed oracle at it. */ if (SvTYPE(phs->sv) != phs->sv_type || (SvOK(phs->sv) && !SvPOK(phs->sv)) - /* SvROK==!SvPOK so cursor (SQLT_CUR) handle will call _dbd_rebind_ph */ + /* SvROK==!SvPOK so cursor (SQLT_CUR) handle will call dbd_rebind_ph */ /* that suits us for now */ || SvPVX(phs->sv) != phs->progv || SvCUR(phs->sv) > UB2MAXVAL ) { - if (!_dbd_rebind_ph(sth, imp_sth, phs)) + if (!dbd_rebind_ph(sth, imp_sth, phs)) croak("Can't rebind placeholder %s", phs->name); } else { @@ -1151,9 +1014,11 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count phs->alen = SvCUR(phs->sv) + phs->alen_incnull; if (debug >= 2) fprintf(DBILOGFP, - " with %s = '%.*s' (len %d/%d, indp %d, otype %d, ptype %d)\n", - phs->name, phs->alen, SvPVX(phs->sv), phs->alen, (int)phs->maxlen, - phs->indp, phs->ftype, (int)SvTYPE(phs->sv)); + " with %s = '%.*s' (len %ld/%ld, indp %d, otype %d, ptype %d)\n", + phs->name, (int)phs->alen, + (phs->indp == -1) ? "" : SvPVX(phs->sv), + (long)phs->alen, (long)phs->maxlen, phs->indp, + phs->ftype, (int)SvTYPE(phs->sv)); } } } @@ -1241,7 +1106,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count while(--i >= 0) { phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); SV *sv = phs->sv; -#ifndef OCI_V8_SYNTAX +#ifdef cursor_vars_are_broken if (SvROK(sv)) { /* XXX assume it's a cursor variable sth */ D_impdata(phs_imp_sth, imp_sth_t, sv); if (debug >= 2) @@ -1269,8 +1134,8 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count *SvEND(sv) = '\0'; if (debug >= 2) fprintf(DBILOGFP, - " out %s = '%s'\t(len %d, arcode %d)\n", - phs->name, SvPV(sv,na),phs->alen, phs->arcode); + " out %s = '%s'\t(len %ld, arcode %d)\n", + phs->name, SvPV(sv,na), (long)phs->alen, phs->arcode); } else if (phs->indp > 0 || phs->indp == -2) { /* truncated */ @@ -1279,8 +1144,8 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count *SvEND(sv) = '\0'; if (debug >= 2) fprintf(DBILOGFP, - " out %s = '%s'\t(TRUNCATED from %d to %d, arcode %d)\n", - phs->name, SvPV(sv,na), phs->indp, phs->alen, phs->arcode); + " out %s = '%s'\t(TRUNCATED from %d to %ld, arcode %d)\n", + phs->name, SvPV(sv,na), phs->indp, (long)phs->alen, phs->arcode); } else if (phs->indp == -1) { /* is NULL */ @@ -1435,6 +1300,7 @@ ora_free_phs_contents(phs_t *phs) if (phs->desc_h) OCIDescriptorFree(phs->desc_h, phs->desc_t); #endif + sv_free(phs->ora_field); sv_free(phs->sv); } @@ -1451,12 +1317,13 @@ dbd_st_destroy(sth, imp_sth) /* dbd_st_finish has already been called by .xs code if needed. */ /* Check if an explicit disconnect() or global destruction has */ - /* disconnected us from the database before attempting to close. */ + /* disconnected us from the *database* before attempting to close. */ if (DBIc_ACTIVE(imp_dbh)) { #ifdef OCI_V8_SYNTAX /* nothing to do here ? */ #else - free_cursor(sth, imp_sth); /* ignore errors here */ + oclose(imp_sth->cda); + imp_sth->cda = NULL; #endif /* fall through anyway to free up our memory */ } diff --git a/dbdimp.h b/dbdimp.h index fd082767..8798c952 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.26 1998/12/16 00:23:12 timbo Exp $ + $Id: dbdimp.h,v 1.29 1998/12/28 00:04:37 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -11,23 +11,17 @@ */ -/* Perl <= 5.004_0x defines dirty as either Perl_dirty or curinterp->Idirty */ -/* Perl > 5.005_54 defines dirty as PL_dirty if PERL_POLLUTE is defined */ -/* -#xif !defined(dirty) -#xdefine dirty PL_dirty -#xendif -*/ #if defined(get_no_modify) && !defined(no_modify) #define no_modify PL_no_modify #endif +/* ====== Include Oracle Header Files ====== */ + #ifndef CAN_PROTOTYPE #define signed /* Oracle headers use signed */ #endif - /* The following define avoids a problem with Oracle >=7.3 where * ociapr.h has the line: * sword obindps(struct cda_def *cursor, ub1 opcode, text *sqlvar, ... @@ -35,7 +29,6 @@ */ #define opcode opcode_redefined - /* Hack to fix broken Oracle oratypes.h on OSF Alpha. Sigh. */ #if defined(__osf__) && defined(__alpha) #ifndef A_OSF @@ -48,7 +41,7 @@ #include #include -#if defined(SQLT_NTY) && !defined(NO_OCI8) /* use Oracle 8 */ +#if defined(SQLT_NTY) && !defined(NO_OCI8) /* === use Oracle 8 === */ /* ori.h uses 'dirty' as an arg name in prototypes so we use this */ /* hack to prevent ori.h being read (since we don't need it) */ @@ -56,7 +49,7 @@ #include -#else /* use Oracle 7 */ +#else /* === use Oracle 7 === */ #ifdef CAN_PROTOTYPE # include @@ -68,15 +61,16 @@ #define HDA_SIZE 512 #endif -#ifndef FT_SELECT /* old Oracle version */ -#define FT_SELECT 4 /* from rdbms/demo/ocidem.h */ -#endif +#endif /* === ------------ === */ + +/* ------ end of Oracle include files ------ */ -#endif +/* ====== define data types ====== */ typedef struct imp_fbh_st imp_fbh_t; + struct imp_drh_st { dbih_drc_t com; /* MUST be first element in structure */ #ifdef OCI_V8_SYNTAX @@ -84,6 +78,7 @@ struct imp_drh_st { #endif }; + /* Define dbh implementor data structure */ struct imp_dbh_st { dbih_dbc_t com; /* MUST be first element in structure */ @@ -117,11 +112,11 @@ struct imp_sth_st { OCIServer *srvhp; /* copy of dbh pointer */ OCISvcCtx *svchp; /* copy of dbh pointer */ OCIStmt *stmhp; - ub2 stmt_type; /* OCIAttrGet OCI_ATTR_STMT_TYPE */ + ub2 stmt_type; /* OCIAttrGet OCI_ATTR_STMT_TYPE */ int has_lobs; lob_refetch_t *lob_refetch; #else - Cda_Def *cda; /* currently just points to cdabuf below */ + Cda_Def *cda; /* normally just points to cdabuf below */ Cda_Def cdabuf; #endif @@ -173,7 +168,7 @@ struct imp_fbh_st { /* field buffer EXPERIMENTAL */ int (*fetch_func) _((SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv)); ub2 dbsize; ub2 dbtype; /* actual type of field (see ftype) */ - ub1 prec; + ub2 prec; /* XXX docs say ub1 but ub2 is needed */ sb1 scale; ub1 nullok; void *special; /* hook for special purposes (LOBs etc) */ @@ -198,6 +193,7 @@ struct imp_fbh_st { /* field buffer EXPERIMENTAL */ typedef struct phs_st phs_t; /* scalar placeholder */ struct phs_st { /* scalar placeholder EXPERIMENTAL */ + imp_sth_t *imp_sth; /* 'parent' statement */ sword ftype; /* external OCI field type */ SV *sv; /* the scalar holding the value */ @@ -206,25 +202,75 @@ struct phs_st { /* scalar placeholder EXPERIMENTAL */ IV maxlen; /* max possible len (=allocated buffer) */ - ub4 aryelem_max; /* max elements in allocated array */ - ub4 aryelem_cur; /* current elements in allocated array */ #ifdef OCI_V8_SYNTAX OCIBind *bndhp; void *desc_h; /* descriptor if needed (LOBs etc) */ ub4 desc_t; /* OCI type of desc_h */ + ub4 alen; +#else + ub2 alen; /* effective length ( <= maxlen ) */ #endif + ub2 arcode; - /* these will become an array one day */ sb2 indp; /* null indicator */ char *progv; - ub2 arcode; - ub2 alen; /* effective length ( <= maxlen ) */ + SV *ora_field; /* from attribute (for LOB binds) */ int alen_incnull; /* 0 or 1 if alen should include null */ char name[1]; /* struct is malloc'd bigger as needed */ }; +/* ------ define functions and external variables ------ */ + +extern int ora_fetchtest; + +void dbd_init_oci _((dbistate_t *dbistate)); +void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); +void dbd_fbh_dump _((imp_fbh_t *fbh, int i, int aidx)); +void ora_free_fbh_contents _((imp_fbh_t *fbh)); +int ora_dbtype_is_long _((int dbtype)); +int calc_cache_rows _((int num_fields, int est_width, int cache_rows, int has_longs)); +fb_ary_t *fb_ary_alloc _((int bufl, int size)); + +#ifdef OCI_V8_SYNTAX + +int oci_error _((SV *h, OCIError *errhp, sword status, char *what)); +char *oci_stmt_type_name _((int stmt_type)); +char *oci_status_name _((sword status)); +int dbd_rebind_ph_lob _((SV *sth, imp_sth_t *imp_sth, phs_t *phs)); +void ora_free_lob_refetch _((imp_sth_t *imp_sth)); +int post_execute_lobs _((SV *sth, imp_sth_t *imp_sth, ub4 row_count)); + +#define OCIAttrGet_stmhp(imp_sth, p, l, a) \ + OCIAttrGet(imp_sth->stmhp, OCI_HTYPE_STMT, (dvoid*)(p), (l), (a), imp_sth->errhp) + +#define OCIAttrGet_parmdp(imp_sth, parmdp, p, l, a) \ + OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (dvoid*)(p), (l), (a), imp_sth->errhp) + +#define OCIHandleAlloc_ok(envhp, p, t) \ + if (OCIHandleAlloc( (envhp), (dvoid**)(p), (t), 0, 0)==OCI_SUCCESS) ; \ + else croak("OCIHandleAlloc (type %d) failed",t) + +#define OCIDescriptorAlloc_ok(envhp, p, t) \ + if (OCIDescriptorAlloc((envhp), (dvoid**)(p), (t), 0, 0)==OCI_SUCCESS) ; \ + else croak("OCIDescriptorAlloc (type %d) failed",t) + +sb4 dbd_phs_in _((dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, + dvoid **bufpp, ub4 *alenp, ub1 *piecep, dvoid **indpp)); +sb4 dbd_phs_out _((dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, + dvoid **bufpp, ub4 **alenpp, ub1 *piecep, + dvoid **indpp, ub2 **rcodepp)); + + +#else /* is OCI 7 */ + +void ora_error _((SV *h, Lda_Def *lda, int rc, char *what)); + +#endif /* OCI_V8_SYNTAX */ + + + /* These defines avoid name clashes for multiple statically linked DBD's */ #define dbd_init ora_init diff --git a/oci7.h b/oci7.c similarity index 82% rename from oci7.h rename to oci7.c index c0f9831e..2f8189ac 100644 --- a/oci7.h +++ b/oci7.c @@ -1,5 +1,5 @@ /* - $Id: oci7.h,v 1.3 1998/12/16 00:19:34 timbo Exp $ + $Id: oci7.c,v 1.5 1998/12/28 00:04:37 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -10,13 +10,39 @@ */ +#include "Oracle.h" -static void +#ifdef OCI_V8_SYNTAX + + /* see oci8.c */ + +#else + +DBISTATE_DECLARE; + +static SV *ora_long; +static SV *ora_trunc; +static SV *ora_cache; +static SV *ora_cache_o; /* for ora_open() cache override */ + +void +dbd_init_oci(dbistate) + dbistate_t *dbistate; +{ + DBIS = dbistate; + ora_long = perl_get_sv("Oraperl::ora_long", GV_ADDMULTI); + ora_trunc = perl_get_sv("Oraperl::ora_trunc", GV_ADDMULTI); + ora_cache = perl_get_sv("Oraperl::ora_cache", GV_ADDMULTI); + ora_cache_o = perl_get_sv("Oraperl::ora_cache_o", GV_ADDMULTI); +} + + +void ora_error(h, lda, rc, what) SV *h; Lda_Def *lda; - sb2 rc; + int rc; char *what; { D_imp_xxh(h); @@ -121,7 +147,7 @@ dbd_describe(h, imp_sth) if (imp_sth->cache_rows > 0) continue; /* no need, user specified a size */ if (dbsize==0) { /* is a LONG type or 'select NULL' */ - if (dbtype_is_long(dbtype)) { + if (ora_dbtype_is_long(dbtype)) { est_width += long_buflen; ++has_longs; /* hint to auto cache sizing code */ } @@ -215,12 +241,15 @@ dbd_describe(h, imp_sth) fbh->dbsize *= 2; fbh->disize *= 2; } + else if (fbh->dbtype == 2 && fbh->prec == 0) { + fbh->prec = 38; + } /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW? */ /* If so we need to implement oraperl truncation hacks. */ /* This may change in a future release. */ - /* Note that dbtype_is_long() returns alternate dbtype to use */ - if ( (dbtype = dbtype_is_long(fbh->dbtype)) ) { + /* Note that ora_dbtype_is_long() returns alternate dbtype to use */ + if ( (dbtype = ora_dbtype_is_long(fbh->dbtype)) ) { fbh->dbsize = long_buflen; fbh->disize = long_buflen; fbh->ftype = dbtype; /* get long in non-var form */ @@ -247,7 +276,7 @@ dbd_describe(h, imp_sth) } if (dbis->debug >= 2) - fbh_dump(fbh, i, 0); + dbd_fbh_dump(fbh, i, 0); } imp_sth->est_width = est_width; @@ -335,7 +364,7 @@ dbd_st_fetch(sth, imp_sth) int rc = fb_ary->arcode[cache_entry]; SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */ - if (rc == 1406 && dbtype_is_long(fbh->dbtype)) { + if (rc == 1406 && ora_dbtype_is_long(fbh->dbtype)) { /* We have a LONG field which has been truncated. */ int oraperl = DBIc_COMPAT(imp_sth); if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { @@ -371,7 +400,7 @@ dbd_st_fetch(sth, imp_sth) /* but it'll only be accessible via prior bind_column() */ sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], fb_ary->arlen[cache_entry]); - if (dbtype_is_long(fbh->dbtype)) /* double check */ + if (ora_dbtype_is_long(fbh->dbtype)) /* double check */ hint = ", LongReadLen too small and/or LongTruncOk not set"; } else { @@ -385,7 +414,7 @@ dbd_st_fetch(sth, imp_sth) ora_error(sth, imp_sth->cda, rc, buf); } - if (debug >= 3) + if (debug >= 5) fprintf(DBILOGFP, " %d (rc=%d): %s\n", i, rc, neatsvpv(sv,0)); } @@ -405,39 +434,76 @@ dbd_st_fetch(sth, imp_sth) /* ------------------------------------------------------------ */ -static int -get_cursor(imp_dbh, sth, imp_sth) - imp_dbh_t *imp_dbh; + +int +dbd_st_prepare(sth, imp_sth, statement, attribs) SV *sth; imp_sth_t *imp_sth; + char *statement; + SV *attribs; { + D_imp_dbh_from_sth; + ub4 oparse_lng = 1; /* auto v6 or v7 as suits db connected to */ + + imp_sth->done_desc = 0; + + if (DBIc_COMPAT(imp_sth)) { + static SV *ora_pad_empty; + if (!ora_pad_empty) { + ora_pad_empty= perl_get_sv("Oraperl::ora_pad_empty", GV_ADDMULTI); + if (!SvOK(ora_pad_empty) && getenv("ORAPERL_PAD_EMPTY")) + sv_setiv(ora_pad_empty, atoi(getenv("ORAPERL_PAD_EMPTY"))); + } + imp_sth->ora_pad_empty = (SvOK(ora_pad_empty)) ? SvIV(ora_pad_empty) : 0; + } + + if (attribs) { + SV **svp; + DBD_ATTRIB_GET_IV( attribs, "ora_parse_lang", 14, svp, oparse_lng); + } + + /* scan statement for '?', ':1' and/or ':foo' style placeholders */ + dbd_preparse(imp_sth, statement); + if (oopen(&imp_sth->cdabuf, imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { ora_error(sth, &imp_sth->cdabuf, imp_sth->cdabuf.rc, "oopen error"); return 0; } imp_sth->cda = &imp_sth->cdabuf; - return 1; -} -static int -free_cursor(sth, imp_sth) - SV *sth; - imp_sth_t *imp_sth; -{ - if (!imp_sth->cda) + /* parse the (possibly edited) SQL statement */ + imp_sth->cda->peo = 0; + if (oparse(imp_sth->cda, (text*)imp_sth->statement, (sb4)-1, + (sword)0/*oparse_defer*/, (ub4)oparse_lng) + ) { + char buf[99]; + char *hint = ""; + if (1) { /* XXX could make optional one day */ + SV *msgsv, *sqlsv; + sprintf(buf,"error possibly near <*> indicator at char %d in '", + imp_sth->cda->peo+1); + msgsv = sv_2mortal(newSVpv(buf,0)); + sqlsv = sv_2mortal(newSVpv(imp_sth->statement,0)); + sv_insert(sqlsv, imp_sth->cda->peo, 0, "<*>",3); + sv_catsv(msgsv, sqlsv); + sv_catpv(msgsv, "'"); + hint = SvPV(msgsv,na); + } + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, hint); + oclose(imp_sth->cda); /* close the cursor */ + imp_sth->cda = NULL; return 0; + } + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_st_prepare'd sql f%d\n", imp_sth->cda->ft); - if (DBIc_ACTIVE(imp_sth)) /* should never happen here */ - ocan(imp_sth->cda); /* XXX probably not needed before oclose */ - - if (oclose(imp_sth->cda)) { /* close the cursor */ - /* Check for ORA-01041: 'hostdef extension doesn't exist' ? XXX */ - /* which indicates that the lda had already been logged out */ - /* in which case only complain if not in 'global destruction'? */ - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oclose error"); + /* Describe and allocate storage for results. */ + if (!dbd_describe(sth, imp_sth)) { return 0; } - imp_sth->cda = NULL; + + DBIc_IMPSET_on(imp_sth); return 1; } +#endif diff --git a/oci8.h b/oci8.c similarity index 69% rename from oci8.h rename to oci8.c index ddd427b0..c5c06553 100644 --- a/oci8.h +++ b/oci8.c @@ -1,5 +1,5 @@ /* - $Id: oci8.h,v 1.5 1998/12/16 00:23:12 timbo Exp $ + $Id: oci8.c,v 1.10 1998/12/28 00:04:37 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -10,22 +10,32 @@ */ -#define OCIAttrGet_stmhp(imp_sth, p, l, a) \ - OCIAttrGet(imp_sth->stmhp, OCI_HTYPE_STMT, (dvoid*)(p), (l), (a), imp_sth->errhp) -#define OCIAttrGet_parmdp(imp_sth, parmdp, p, l, a) \ - OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (dvoid*)(p), (l), (a), imp_sth->errhp) +#include "Oracle.h" -#define OCIHandleAlloc_ok(envhp, p, t) \ - if (OCIHandleAlloc((envhp), (dvoid**)(p), (t), 0, 0)==OCI_SUCCESS) ; \ - else croak("OCIHandleAlloc (type %d) failed",t) -#define OCIDescriptorAlloc_ok(envhp, p, t) \ - if (OCIDescriptorAlloc((envhp), (dvoid**)(p), (t), 0, 0)==OCI_SUCCESS) ; \ - else croak("OCIDescriptorAlloc (type %d) failed",t) +#ifdef OCI_V8_SYNTAX -static char * -oci_status_name(status) - int status; + +DBISTATE_DECLARE; + +static SV *ora_long; +static SV *ora_trunc; +static SV *ora_cache; +static SV *ora_cache_o; /* for ora_open() cache override */ + +void +dbd_init_oci(dbistate_t *dbistate) +{ + DBIS = dbistate; + ora_long = perl_get_sv("Oraperl::ora_long", GV_ADDMULTI); + ora_trunc = perl_get_sv("Oraperl::ora_trunc", GV_ADDMULTI); + ora_cache = perl_get_sv("Oraperl::ora_cache", GV_ADDMULTI); + ora_cache_o = perl_get_sv("Oraperl::ora_cache_o", GV_ADDMULTI); +} + + +char * +oci_status_name(sword status) { SV *sv; switch (status) { @@ -45,9 +55,8 @@ oci_status_name(status) } -static char * -oci_stmt_type_name(stmt_type) - int stmt_type; +char * +oci_stmt_type_name(int stmt_type) { SV *sv; switch (stmt_type) { @@ -68,12 +77,8 @@ oci_stmt_type_name(stmt_type) } -static int -oci_error(h, errhp, status, what) - SV *h; - OCIError *errhp; - sword status; - char *what; +int +oci_error(SV *h, OCIError *errhp, sword status, char *what) { D_imp_xxh(h); SV *errstr = DBIc_ERRSTR(imp_xxh); @@ -125,15 +130,159 @@ oci_error(h, errhp, status, what) } -int fetch_func_lob(sth, imp_sth, fbh, dest_sv) +int +dbd_st_prepare(sth, imp_sth, statement, attribs) SV *sth; imp_sth_t *imp_sth; - imp_fbh_t *fbh; - SV *dest_sv; + char *statement; + SV *attribs; +{ + D_imp_dbh_from_sth; + ub4 oparse_lng = 1; /* auto v6 or v7 as suits db connected to */ + sword status = 0; + + imp_sth->done_desc = 0; + + if (DBIc_COMPAT(imp_sth)) { + static SV *ora_pad_empty; + if (!ora_pad_empty) { + ora_pad_empty= perl_get_sv("Oraperl::ora_pad_empty", GV_ADDMULTI); + if (!SvOK(ora_pad_empty) && getenv("ORAPERL_PAD_EMPTY")) + sv_setiv(ora_pad_empty, atoi(getenv("ORAPERL_PAD_EMPTY"))); + } + imp_sth->ora_pad_empty = (SvOK(ora_pad_empty)) ? SvIV(ora_pad_empty) : 0; + } + + if (attribs) { + SV **svp; + DBD_ATTRIB_GET_IV( attribs, "ora_parse_lang", 14, svp, oparse_lng); + } + + /* scan statement for '?', ':1' and/or ':foo' style placeholders */ + dbd_preparse(imp_sth, statement); + + imp_sth->envhp = imp_dbh->envhp; + imp_sth->errhp = imp_dbh->errhp; + imp_sth->srvhp = imp_dbh->srvhp; + imp_sth->svchp = imp_dbh->svchp; + + switch(oparse_lng) { + case 0: /* old: calls for V6 syntax - give them V7 */ + case 2: /* old: calls for V7 syntax */ + case 7: oparse_lng = OCI_V7_SYNTAX; break; + case 8: oparse_lng = OCI_V8_SYNTAX; break; + default: oparse_lng = OCI_NTV_SYNTAX; break; + } + + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_sth->stmhp, OCI_HTYPE_STMT); + status = OCIStmtPrepare(imp_sth->stmhp, imp_sth->errhp, + (text*)imp_sth->statement, (ub4)strlen(imp_sth->statement), + oparse_lng, OCI_DEFAULT); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIStmtPrepare"); + OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); + return 0; + } + + OCIAttrGet_stmhp(imp_sth, &imp_sth->stmt_type, 0, OCI_ATTR_STMT_TYPE); + if (dbis->debug >= 2) + fprintf(DBILOGFP, " dbd_st_prepare'd sql %s\n", + oci_stmt_type_name(imp_sth->stmt_type)); + + DBIc_IMPSET_on(imp_sth); + return 1; +} + + +sb4 +dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, + dvoid **bufpp, ub4 *alenp, ub1 *piecep, dvoid **indpp) +{ + phs_t *phs = octxp; + STRLEN phs_len; + if (phs->desc_h) { + *bufpp = phs->desc_h; + phs->alen = 0; + phs->indp = 0; + } + else + if (SvOK(phs->sv)) { + *bufpp = SvPV(phs->sv, phs_len); + phs->alen = (phs->alen_incnull) ? phs_len+1 : phs_len;; + phs->indp = 0; + } + else { + *bufpp = SvPVX(phs->sv); /* not actually used? */ + phs->alen = 0; + phs->indp = -1; + } + *alenp = phs->alen; + *indpp = &phs->indp; + *piecep = OCI_ONE_PIECE; + if (dbis->debug >= 3) + fprintf(DBILOGFP, " dbd_phs_in '%s' (%ld,%ld): len %ld, ind %d\n", + phs->name, iter, index, phs->alen, phs->indp); + if (index > 0 || iter > 0) + croak("Arrays and multiple iterations not currently supported by DBD::Oracle"); + return OCI_CONTINUE; +} + +sb4 +dbd_phs_out(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, + dvoid **bufpp, ub4 **alenpp, ub1 *piecep, + dvoid **indpp, ub2 **rcodepp) +{ + phs_t *phs = octxp; + if (phs->desc_h) { + *bufpp = phs->desc_h; + phs->alen = 0; + } + else { + *bufpp = SvPVX(phs->sv); + phs->alen = SvLEN(phs->sv); /* max buffer size now, actual data len later */ + } + *alenpp = &phs->alen; + *indpp = &phs->indp; + *rcodepp= &phs->arcode; + if (dbis->debug >= 3) + fprintf(DBILOGFP, " dbd_phs_out '%s' (%ld,%ld): len %ld, piece %d\n", + phs->name, iter, index, phs->alen, *piecep); + if (index > 0 || iter > 0) + croak("Arrays and multiple iterations not currently supported by DBD::Oracle"); + *piecep = OCI_ONE_PIECE; + return OCI_CONTINUE; +} + + +int +dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) +{ + sword status; + ub4 lobEmpty = 0; + + if (!phs->desc_h) { + ++imp_sth->has_lobs; + phs->desc_t = OCI_DTYPE_LOB; + OCIDescriptorAlloc_ok(imp_sth->envhp, + &phs->desc_h, phs->desc_t); + } + status = OCIAttrSet(phs->desc_h, phs->desc_t, + &lobEmpty, 0, OCI_ATTR_LOBEMPTY, imp_sth->errhp); + if (status != OCI_SUCCESS) + return oci_error(sth, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_LOBEMPTY"); + phs->progv = (void*)&phs->desc_h; + phs->maxlen = sizeof(OCILobLocator*); + + return 1; +} + + + +int +fetch_func_lob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) { - char *hint = ""; ub4 loblen = 0; - ub4 getlen; + ub4 buflen; ub4 amtp = 0; OCILobLocator *lobl = (OCILobLocator*)fbh->desc_h; sword status; @@ -144,19 +293,10 @@ int fetch_func_lob(sth, imp_sth, fbh, dest_sv) return 0; } - getlen = (loblen > imp_sth->long_readlen) ? imp_sth->long_readlen : loblen; - amtp = getlen; /* set right semantics for OCILobRead */ + buflen = (loblen > imp_sth->long_readlen) ? imp_sth->long_readlen : loblen; + amtp = buflen; /* set right semantics for OCILobRead */ - SvUPGRADE(dest_sv, SVt_PV); - SvGROW(dest_sv, getlen+1); - - status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobl, - &amtp, 1, SvPVX(dest_sv), getlen, 0, 0, 0, SQLCS_IMPLICIT); - if (dbis->debug >= 3) - fprintf(DBILOGFP, " OCILobRead %s: %ld/%ld/%ld\n", - oci_status_name(status), getlen, amtp, imp_sth->long_readlen); - - if (status == OCI_NEED_DATA) { /* LOB was truncated */ + if (loblen > imp_sth->long_readlen) { /* LOB will be truncated */ int oraperl = DBIc_COMPAT(imp_sth); if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { /* user says truncation is ok */ @@ -164,18 +304,31 @@ int fetch_func_lob(sth, imp_sth, fbh, dest_sv) /* so also but only for Oraperl mode handles. */ if (oraperl) sv_setiv(DBIc_ERR(imp_sth), 1406); - status = OCI_SUCCESS; /* but don't provoke an error here */ } else { - /* else fall through and let status trigger failure below */ - hint = ", LongReadLen too small and/or LongTruncOk not set"; + char buf[300]; + sprintf(buf,"fetching field %d of %d. LOB value truncated from %ld to %ld. %s", + fbh->field_num+1, DBIc_NUM_FIELDS(imp_sth), loblen, amtp, + "LongReadLen too small and/or LongTruncOk not set"); + oci_error(sth, NULL, OCI_ERROR, buf); + SvOK_off(dest_sv); + return 0; } } + + SvUPGRADE(dest_sv, SVt_PV); + SvGROW(dest_sv, buflen+1); + + status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobl, + &amtp, 1, SvPVX(dest_sv), buflen, 0, 0, 0, SQLCS_IMPLICIT); + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", + fbh->field_num+1, oci_status_name(status), loblen, imp_sth->long_readlen, buflen, amtp); + if (status != OCI_SUCCESS) { - char buf[300]; - sprintf(buf,"OCILobRead of %ld bytes on field %d of %d%s", - getlen, fbh->field_num+1, DBIc_NUM_FIELDS(imp_sth), hint); - oci_error(sth, imp_sth->errhp, status, buf); + oci_error(sth, imp_sth->errhp, status, "OCILobRead"); + SvOK_off(dest_sv); return 0; } /* tell perl what we've put in its dest_sv */ @@ -188,9 +341,7 @@ int fetch_func_lob(sth, imp_sth, fbh, dest_sv) int -dbd_describe(h, imp_sth) - SV *h; - imp_sth_t *imp_sth; +dbd_describe(SV *h, imp_sth_t *imp_sth) { D_imp_dbh_from_sth; I32 long_readlen; @@ -247,6 +398,7 @@ dbd_describe(h, imp_sth) /* Get number of fields and space needed for field names */ for(i = 1; i <= num_fields; ++i) { + char *p; ub4 atrlen; int avg_width = 0; imp_fbh_t *fbh = &imp_sth->fbh[i-1]; @@ -262,6 +414,7 @@ dbd_describe(h, imp_sth) OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->dbtype, 0, OCI_ATTR_DATA_TYPE); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->dbsize, 0, OCI_ATTR_DATA_SIZE); + /* OCI_ATTR_PRECISION returns 0 for most types and even some numbers! */ OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->prec, 0, OCI_ATTR_PRECISION); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->scale, 0, OCI_ATTR_SCALE); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->nullok, 0, OCI_ATTR_IS_NULL); @@ -275,41 +428,42 @@ dbd_describe(h, imp_sth) case 1: /* VARCHAR2 */ case 96: /* CHAR */ fbh->disize = fbh->dbsize; + fbh->prec = fbh->disize; break; case 23: /* RAW */ fbh->disize = fbh->dbsize * 2; + fbh->prec = fbh->disize; break; case 2: /* NUMBER */ - /* actually dependent on scale & precision */ - if (!fbh->scale && !fbh->prec) /* always 0! */ - fbh->disize = 38 + 2; /* max prec */ - else fbh->disize = fbh->prec + 2; /* sign + dot */ + if (!fbh->prec) /* XXX seems sometimes 0! */ + fbh->prec = 38; /* max prec */ + fbh->disize = fbh->prec + 2; /* sign + dot */ avg_width = 4; /* > approx +/- 1_000_000 ? */ break; case 12: /* DATE */ /* actually dependent on NLS default date format*/ fbh->disize = 75; /* a generous default */ + fbh->prec = fbh->disize; break; case 8: /* LONG */ - fbh->disize = fbh->dbsize; fbh->dbsize = long_readlen; + fbh->disize = fbh->dbsize; fbh->ftype = 8; break; case 24: /* LONG RAW */ - avg_width = fbh->dbsize; - fbh->disize = fbh->dbsize; fbh->dbsize = long_readlen * 2; + fbh->disize = fbh->dbsize; + avg_width = fbh->dbsize; fbh->ftype = 24; break; case 11: /* ROWID */ - fbh->disize = 20; - break; case 104: /* ROWID Desc */ fbh->disize = 20; + fbh->prec = fbh->disize; break; case 112: /* CLOB */ @@ -318,15 +472,20 @@ dbd_describe(h, imp_sth) fbh->disize = fbh->dbsize; fbh->fetch_func = fetch_func_lob; fbh->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_dbh->envhp, &fbh->desc_h, fbh->desc_t); + OCIDescriptorAlloc_ok(imp_sth->envhp, &fbh->desc_h, fbh->desc_t); break; case 105: /* MLSLABEL */ case 108: /* User Defined */ case 111: /* REF */ default: + /* XXX unhandled type may lead to errors or worse */ fbh->disize = fbh->dbsize; - /* XXX unhandled type may lead to core dump */ + p = "Field %d has an Oracle type (%d) which is not explicitly supported"; + if (dbis->debug >= 2) + fprintf(DBILOGFP, p, i, fbh->dbtype); + if (dowarn) + warn(p, i, fbh->dbtype); break; } if (fbh->ftype == 5) @@ -339,7 +498,7 @@ dbd_describe(h, imp_sth) imp_sth->est_width += avg_width; if (dbis->debug >= 2) - fbh_dump(fbh, i, 0); + dbd_fbh_dump(fbh, i, 0); } /* --- Setup the row cache for this query --- */ @@ -349,19 +508,28 @@ dbd_describe(h, imp_sth) else if (SvOK(ora_cache)) imp_sth->cache_rows = SvIV(ora_cache); else imp_sth->cache_rows = imp_dbh->RowCacheSize; if (imp_sth->cache_rows >= 0) { /* set cache size by row count */ - ub4 cache_rows; - cache_rows = calc_cache_rows(num_fields, est_width, imp_sth->cache_rows, has_longs); - imp_sth->cache_rows = cache_rows; - OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, - &cache_rows, 0, OCI_ATTR_PREFETCH_ROWS, imp_dbh->errhp); + ub4 cache_rows = calc_cache_rows(num_fields, + est_width, imp_sth->cache_rows, has_longs); + imp_sth->cache_rows = cache_rows; /* record updated value */ + status = OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, + &cache_rows, 3, OCI_ATTR_PREFETCH_ROWS, imp_sth->errhp); + if (status != OCI_SUCCESS) { + oci_error(h, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_PREFETCH_ROWS"); + return 0; + } } else { /* set cache size by memory */ - ub4 cache_rows = 100000; ub4 cache_mem = -imp_sth->cache_rows; - OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, - &cache_rows, 0, OCI_ATTR_PREFETCH_ROWS, imp_dbh->errhp); - OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, - &cache_mem, 0, OCI_ATTR_PREFETCH_MEMORY, imp_dbh->errhp); + ub4 cache_rows = 100000; /* set high so memory is the limit */ + status = OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, + &cache_rows, 0, OCI_ATTR_PREFETCH_ROWS, imp_sth->errhp) + || OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, + &cache_mem, 0, OCI_ATTR_PREFETCH_MEMORY, imp_sth->errhp); + if (status != OCI_SUCCESS) { + oci_error(h, imp_sth->errhp, status, + "OCIAttrSet OCI_ATTR_PREFETCH_ROWS/OCI_ATTR_PREFETCH_MEMORY"); + return 0; + } } imp_sth->long_readlen = long_readlen; @@ -398,12 +566,10 @@ dbd_describe(h, imp_sth) AV * -dbd_st_fetch(sth, imp_sth) - SV * sth; - imp_sth_t *imp_sth; +dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) { sword status; - int num_fields; + int num_fields = DBIc_NUM_FIELDS(imp_sth); int ChopBlanks; int err; int i; @@ -427,6 +593,44 @@ dbd_st_fetch(sth, imp_sth) fprintf(DBILOGFP, " dbd_st_fetch %d fields...\n", DBIc_NUM_FIELDS(imp_sth)); status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT); } + +#ifdef incomplete_and_not_needed_anyway + while (status == OCI_NEED_DATA) { + imp_fbh_t *p_fbh = NULL; + fb_ary_t *fb_ary; + sword p_status; + OCIDefine *p_defnp; + ub1 *bufp; + ub4 p_htype, iter, idx, piece_len; + ub1 in_out, piece; + p_status = OCIStmtGetPieceInfo(imp_sth->stmhp, imp_sth->errhp, (void **)&p_defnp, + &p_htype, &in_out, &iter, &idx, &piece ); + for(i=0; i < num_fields; ++i) { + if (p_defnp == (p_fbh=&imp_sth->fbh[i])->defnp) + break; + } + if (i>=num_fields || p_status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, p_status, "OCIStmtGetPieceInfo"); + return Nullav; + } + piece_len = p_fbh->dbsize / 2; + if (dbis->debug >= 3) + fprintf(DBILOGFP, " field %d piece %d (plen %ld)\n", i+1, piece, piece_len); + bufp = p_fbh->fb_ary->abuf; + p_status = OCIStmtSetPieceInfo((void *)p_defnp, OCI_HTYPE_DEFINE, imp_sth->errhp, + (dvoid*)bufp, &piece_len, piece, p_fbh->fb_ary->aindp, p_fbh->fb_ary->arcode); + if (p_status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, p_status, "OCIStmtSetPieceInfo"); + return Nullav; + } + status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT); + *p_fbh->fb_ary->arlen = piece_len; + if (dbis->debug >= 3) + fprintf(DBILOGFP, " piece %d (%s, len %ld, rcode %d)\n", + piece, oci_status_name(status), piece_len, *p_fbh->fb_ary->arcode); + } +#endif + if (status != OCI_SUCCESS) { ora_fetchtest = 0; if (status == OCI_NO_DATA) { @@ -443,10 +647,9 @@ dbd_st_fetch(sth, imp_sth) } av = DBIS->get_fbav(imp_sth); - num_fields = AvFILL(av)+1; if (dbis->debug >= 3) - fprintf(DBILOGFP, " dbd_st_fetch %d fields %s:\n", + fprintf(DBILOGFP, " dbd_st_fetch %d fields %s\n", num_fields, oci_status_name(status)); ChopBlanks = DBIc_has(imp_sth, DBIcf_ChopBlanks); @@ -460,7 +663,7 @@ dbd_st_fetch(sth, imp_sth) SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */ if (rc == 1406 /* field was truncated */ - && dbtype_is_long(fbh->dbtype) /* field is a LONG */ + && ora_dbtype_is_long(fbh->dbtype) /* field is a LONG */ ) { int oraperl = DBIc_COMPAT(imp_sth); if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { @@ -475,7 +678,11 @@ dbd_st_fetch(sth, imp_sth) } if (rc == 0) { /* the normal case */ - if (fbh->ftype == 5) { + if (fbh->fetch_func) { + if (!fbh->fetch_func(sth, imp_sth, fbh, sv)) + ++err; /* fetch_func already called oci_error */ + } + else { int datalen = fb_ary->arlen[cache_entry]; char *p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; /* if ChopBlanks check for Oracle CHAR type (blank padded) */ @@ -485,14 +692,6 @@ dbd_st_fetch(sth, imp_sth) } sv_setpvn(sv, p, (STRLEN)datalen); } - else if (fbh->desc_h) { - if (!fbh->fetch_func(sth, imp_sth, fbh, sv)) - ++err; /* fetch_func already called oci_error */ - } - else { - ++err; - oci_error(sth, imp_sth->errhp, OCI_ERROR, "panic: unhandled field type"); - } } else if (rc == 1405) { /* field is null - return undef */ (void)SvOK_off(sv); @@ -506,7 +705,7 @@ dbd_st_fetch(sth, imp_sth) /* but it'll only be accessible via prior bind_column() */ sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], fb_ary->arlen[cache_entry]); - if (dbtype_is_long(fbh->dbtype)) /* double check */ + if (ora_dbtype_is_long(fbh->dbtype)) /* double check */ hint = ", LongReadLen too small and/or LongTruncOk not set"; } else { @@ -520,7 +719,7 @@ dbd_st_fetch(sth, imp_sth) oci_error(sth, imp_sth->errhp, OCI_ERROR, buf); } - if (dbis->debug >= 3) + if (dbis->debug >= 5) fprintf(DBILOGFP, " %d (rc=%d): %s\n", i, rc, neatsvpv(sv,0)); } @@ -579,7 +778,7 @@ find_ident_after(char *src, char *after, STRLEN *len, int copy) else if (isALPHA(*src)) { if (seen_key) { char *start = src; - while(*src && (isALPHA(*src) || *src=='.')) + while(*src && (isALNUM(*src) || *src=='.')) ++src; *len = src - start; if (copy) { @@ -713,8 +912,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) return oci_error(sth, errhp, OCI_ERROR, "LOB refetch failed, no lobs in table"); - /* our bind params are in imp_sth->all_params_hv - our table cols are in lob_cols_hv + /* our bind params are in %imp_sth->all_params_hv + our table cols are in %lob_cols_hv we now iterate through our bind params and allocate them to the appropriate table columns */ @@ -734,19 +933,43 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) croak("panic: unbound params"); if (phs->ftype != SQLT_CLOB && phs->ftype != SQLT_BLOB) continue; + hv_iterinit(lob_cols_hv); while( (sv = hv_iternextsv(lob_cols_hv, &p, &i)) != NULL ) { char sql_field[200]; - if (SvIV(sv) != phs->ftype) + if (phs->ora_field) { /* must match this phs by field name */ + if (SvCUR(phs->ora_field) != SvCUR(sv) + || ibcmp( SvPV(phs->ora_field,na), SvPV(sv,na), SvCUR(sv) ) ) + continue; + } + else /* basic dumb match by type */ + if (phs->ftype != SvIV(sv)) continue; + else { /* got a type match - check it's safe */ + SV *sv_other; + char *p_other; + /* would any other lob field match this type? */ + while( (sv_other = hv_iternextsv(lob_cols_hv, &p_other, &i)) != NULL ) { + if (phs->ftype != SvIV(sv_other)) + continue; + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " both %s and %s have type %d - ambiguous\n", + SvPV(sv,na), SvPV(sv_other,na), (int)SvIV(sv_other)); + Safefree(lr); + return oci_error(sth, errhp, OCI_ERROR, + "Need bind_param(..., { ora_field=>... }) attribute to identify table LOB field names"); + } + } matched = 1; sprintf(sql_field, "%s%s \"%s\"", (SvCUR(sql_select)>7)?", ":"", p, &phs->name[1]); sv_catpv(sql_select, sql_field); if (dbis->debug >= 3) fprintf(DBILOGFP, - " lob refetch %s param: otype %d, matched field '%s' (%s)\n", - phs->name, phs->ftype, p, sql_field); + " lob refetch %s param: otype %d, matched field '%s' %s(%s)\n", + phs->name, phs->ftype, p, + (phs->ora_field) ? "by name " : "by type ", sql_field); hv_delete(lob_cols_hv, p, i, 0); fbh = &lr->fbh_ary[lr->num_fields++]; fbh->name = phs->name; @@ -755,7 +978,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) fbh->disize = 99; fbh->desc_t = OCI_DTYPE_LOB; OCIDescriptorAlloc_ok(imp_sth->envhp, &fbh->desc_h, fbh->desc_t); - break; + break; /* we're done with this placeholder now */ } if (!matched) { ++unmatched_params; @@ -766,10 +989,9 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } } if (unmatched_params) { - /* not all the lob columns in the table were accounted for */ Safefree(lr); return oci_error(sth, errhp, OCI_ERROR, - "Can't refetch LOBs, LOB column mismatch (too many or wrong type)"); + "Can't match some parameters to LOB fields in the table, check type and name"); } sv_catpv(sql_select, " from "); @@ -826,11 +1048,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } -static int -post_execute_lobs(sth, imp_sth, row_count) /* XXX leaks handles on error */ - SV * sth; - imp_sth_t *imp_sth; - ub4 row_count; +int +post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handles on error */ { /* To insert a new LOB transparently (without using 'INSERT . RETURNING .') */ /* we have to insert an empty LobLocator and then fetch it back from the */ @@ -880,7 +1099,7 @@ post_execute_lobs(sth, imp_sth, row_count) /* XXX leaks handles on error */ return 1; } -static void +void ora_free_lob_refetch(imp_sth_t *imp_sth) { lob_refetch_t *lr = imp_sth->lob_refetch; @@ -894,3 +1113,5 @@ ora_free_lob_refetch(imp_sth_t *imp_sth) Safefree(imp_sth->lob_refetch); imp_sth->lob_refetch = NULL; } + +#endif diff --git a/t/plsql.t b/t/plsql.t index f33251d8..1f62b356 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -94,19 +94,19 @@ ok(0, $DBI::errstr =~ m/msg is hello world/, 1); # --- test named numeric in/out parameters ok(0, $csr = $dbh->prepare(q{ begin - :arg := :arg * 2; + :arg := :arg * :mult; end; }), 1); $p1 = 3; -ok(0, $csr->bind_param_inout(':arg', \$p1, 100), 1); +ok(0, $csr->bind_param_inout(':arg', \$p1, 4), 1); +ok(0, $csr->bind_param(':mult', 2), 1); ok(0, $csr->execute, 1); ok(0, $p1 == 6); # execute 10 times from $p1=1, 2, 4, 8, ... 1024 $p1 = 1; foreach (1..10) { $csr->execute || die $DBI::errstr; } ok(0, $p1 == 1024); - # --- test undef parameters ok(0, $csr = $dbh->prepare(q{ declare foo char(500); @@ -122,13 +122,14 @@ ok(0, $csr = $dbh->prepare(q{ declare str varchar2(1000); begin :arg := nvl(upper(:arg), 'null'); - :arg := :arg || '!'; + :arg := :arg || :append; end; }), 1); undef $p1; $p1 = "hello world"; ok(0, $csr->bind_param_inout(':arg', \$p1, 1000), 1); +ok(0, $csr->bind_param(':append', "!"), 1); ok(0, $csr->execute, 1); ok(0, $p1 eq "HELLO WORLD!"); # execute 10 times growing $p1 to force realloc @@ -148,6 +149,25 @@ ok(0, $p1 eq 'null!'); $csr->finish; +# --- test out buffer being too small +ok(0, $csr = $dbh->prepare(q{ + begin + select rpad('foo',200) into :arg from dual; + end; +}), 1); +#$csr->trace(3); +undef $p1; # force buffer to be freed +ok(0, $csr->bind_param_inout(':arg', \$p1, 20), 1); +# Fails with: +# ORA-06502: PL/SQL: numeric or value error +# ORA-06512: at line 3 (DBD ERROR: OCIStmtExecute) +ok(0, !defined $csr->execute, 1); +# rebind with more space - and it should work +ok(0, $csr->bind_param_inout(':arg', \$p1, 200), 1); +ok(0, $csr->execute, 1); +ok(0, length($p1) == 200, 0); + + # --- test plsql_errstr function #$csr = $dbh->prepare(q{ # create or replace procedure perl_dbd_oracle_test as @@ -172,18 +192,20 @@ $csr->finish; $dbh->{PrintError} = 1; ok(0, $dbh->func(30000, 'dbms_output_enable'), 1); -my @ary = qw(foo bar baz boo); +#$dbh->trace(3); +my @ary = ("foo", ("bar" x 15), "baz", "boo"); ok(0, $dbh->func(@ary, 'dbms_output_put'), 1); @ary = scalar $dbh->func('dbms_output_get'); # scalar context -ok(0, @ary==1 && $ary[0] eq 'foo', 0); +ok(0, @ary==1 && $ary[0] && $ary[0] eq 'foo', 0); @ary = scalar $dbh->func('dbms_output_get'); # scalar context -ok(0, @ary==1 && $ary[0] eq 'bar', 0); +ok(0, @ary==1 && $ary[0] && $ary[0] eq 'bar' x 15, 0); @ary = $dbh->func('dbms_output_get'); # list context ok(0, join(':',@ary) eq 'baz:boo', 0); $dbh->{PrintError} = 0; +#$dbh->trace(0); # --- test cursor variables $csr = $dbh->prepare(q{ @@ -217,12 +239,7 @@ $dbh->disconnect; ok(0, !$dbh->ping); exit 0; -BEGIN { $tests = 41 } +BEGIN { $tests = 49 } # end. __END__ -t/plsql.............ORA-06502: PL/SQL: numeric or value error -ORA-06512: at line 4 (DBD: oexec error) -Use of uninitialized value at t/plsql.t line 120. -Error in PL/SQL block -3.5: PLS-00103: The symbol "an optional basic declaration item" was ignored. diff --git a/test.pl b/test.pl index c7abe12d..6899eedc 100755 --- a/test.pl +++ b/test.pl @@ -4,7 +4,7 @@ die "Use 'make test' to run test.pl\n" unless "@INC" =~ /\bblib\b/; -# $Id: test.pl,v 1.33 1998/12/16 00:19:34 timbo Exp $ +# $Id: test.pl,v 1.34 1998/12/19 23:19:56 timbo Exp $ # # Copyright (c) 1995-1998, Tim Bunce # @@ -19,7 +19,7 @@ require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.33 $}."\n"; +print q{Oraperl test application $Revision: 1.34 $}."\n"; $SIG{__WARN__} = sub { ($_[0] =~ /^(Bad|Duplicate) free/) @@ -143,7 +143,7 @@ sub test1 { { #$lda->trace(2); local($csr) = &ora_open($lda, - "select 11*7.2 num_t, + "select to_number('7.2') num_t, SYSDATE date_t, USER char_t, ROWID rowid_t, @@ -276,6 +276,7 @@ sub test_fetch_perf { print "\nTesting internal row fetch overhead.\n"; local($lda) = &ora_login($dbname, $dbuser, '') || die "ora_login: $ora_errno: $ora_errstr\n"; + DBI->trace(0); $lda->trace(0); local($csr) = &ora_open($lda,"select 0,1,2,3,4,5,6,7,8,9 from dual"); local($max) = 50000; From 9ec15e820c7ffd0510ded1d3b861792015422855 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Wed, 10 Mar 1999 15:57:21 -0500 Subject: [PATCH 040/637] import DBD-Oracle 0.60 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.60 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.60.tar.gz --- Changes | 21 + Makefile.PL | 15 +- Oracle.pm | 48 +- README | 21 +- README.help | 3 +- README.longs | 3 +- Todo | 8 +- dbdimp.c | 166 +++++-- dbdimp.h | 6 +- hints/svr4.pl | 24 +- oci7.c | 14 +- oci8.c | 135 +++--- ora_explain.PL | 1181 ++++++++++++++++++++++++++++++++---------------- t/general.t | 39 +- t/plsql.t | 28 +- 15 files changed, 1156 insertions(+), 556 deletions(-) diff --git a/Changes b/Changes index b135b641..5bcc6c97 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,24 @@ + +Changes in DBD::Oracle 0.60, 10th March 1999 + + Fetching all records now resets Active flag as it should. + Finally fixed "Can't bind unknown placeholder" (hopefully :-). + Fixed placeholder parser to ignore comments, thanks to JD Laub. + Fixed placeholder parser to ignore double-quotes strings. + No longer changes ORACLE_HOME to match oratab, by default. + Fixes for OCI 8: + Fixed selection of very large numbers (132 digits). + Fixed small memory leak in parameter binding. + Fixed small memory leak in prepare of statements using LOBs. + Fixed binding empty strings. + Fixed OCILobRead error when fetching of zero length LOBs. + Fixed OCILobWrite of zero length to use OCILobTrim instead. + Treat SUCCESS_WITH_INFO from OCIStmtExecute as SUCCESS. + Enabled OCI_CRED_EXT login thanks to Alan Burlison & Jeremy Brinkley. + Modified hints/svr4.pl - SVR4 users please test. + Updated Alan Burlison's ora_explain Tk tool to version 1.0. + Documented dbms_msgpipe_get and dbms_msgpipe_ack methods. + Changes in DBD::Oracle 0.59 (Oraperl 1.37), 27th December 1998 Fixed detection of ambiguous LOB-param-to-table-field assignment diff --git a/Makefile.PL b/Makefile.PL index 5a58d5fa..56621f85 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.72 1998/12/28 00:04:37 timbo Exp $ +# $Id: Makefile.PL,v 1.73 1999/03/10 20:42:24 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -96,8 +96,10 @@ my $ORACLE_ENV = ($os eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; my $OH = $ENV{$ORACLE_ENV} || ''; $OH =~ s:\\:/:g if $os eq 'MSWin32'; ($OH = unixify $OH) =~ s:/$:: if $os eq 'VMS'; -die "$ORACLE_ENV environment variable must be set.\n" unless $OH; -die "$ORACLE_ENV environment variable ($OH) not valid.\n" unless -d $OH; +die "The $ORACLE_ENV environment variable must be set.\n" + unless $OH; +die "The $ORACLE_ENV environment variable value ($OH) is not valid.\n" + unless -d $OH; print "Using Oracle in $OH\n"; @@ -156,12 +158,12 @@ elsif ($os eq 'MSWin32') { my %OCILIB; find( sub { $File::Find::prune = 1 if -d $_ && $_ !~ /^\./; - return unless /^OCI.*\.LIB$/i; + return unless /^(OCI|ORA).*\.LIB$/i; print "Found $OCIDIR/lib/$oci_compiler_dir/$_ library\n"; $OCILIB{uc($_)} = $_; }, "$OH/$OCIDIR/lib/$oci_compiler_dir" ) if $OCIDIR; # sort the version numbered libs into assending order - my @OCILIB = sort grep { /OCI\d\d+\./i } keys %OCILIB; + my @OCILIB = sort grep { /(OCI|ORA)\d\d+\./i } keys %OCILIB; # prefer the non-versioned library if present push @OCILIB, "OCI.LIB" if $OCILIB{'OCI.LIB'}; # opt_8 means DISABLE use of OCI 8 API @@ -340,6 +342,9 @@ print "\n"; WriteMakefile(%opts); +print "\n*** If you have problems, read the README and README.help files ***\n"; +print " (Of course, you have read README by now anyway, haven't you?)\n\n"; + exit 0; diff --git a/Oracle.pm b/Oracle.pm index 8f2b617e..31722326 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,7 +1,7 @@ -# $Id: Oracle.pm,v 1.65 1998/12/28 00:04:37 timbo Exp $ +# $Id: Oracle.pm,v 1.66 1999/03/10 20:42:24 timbo Exp $ # -# Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce +# Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce # # You may distribute under the terms of either the GNU General Public # License or the Artistic License, as specified in the Perl README file, @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.59'; +$DBD::Oracle::VERSION = '0.60'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -31,7 +31,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.65 $, 10); + my $Revision = substr(q$Revision: 1.66 $, 10); require_version DBI 1.02; @@ -67,7 +67,13 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; $ENV{PERL_BADFREE} = 0; } - 1; + #sub AUTOLOAD { + # (my $constname = $AUTOLOAD) =~ s/.*:://; + # my $val = constant($constname); + # *$AUTOLOAD = sub { $val }; + # goto &$AUTOLOAD; + #} + } @@ -88,8 +94,9 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; next unless defined $d; next unless open(FH, "<$d/oratab"); $drh->log_msg("Loading $d/oratab\n") if $debug; - while () { - next unless m/^\s*(\w+)\s*:\s*(.*?)\s*:/; + my $ot; + while (defined($ot = )) { + next unless $ot =~ m/^\s*(\w+)\s*:\s*(.*?)\s*:/; $dbnames{$1} = $2; # store ORACLE_HOME value $drh->log_msg("Found $1 \@ $2.\n") if $debug; } @@ -145,38 +152,34 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; if (DBD::Oracle::ORA_OCI() >= 8) { $dbname = $1 if !$dbname && $user =~ s/\@(.*)//; } - elsif ($dbname) { + elsif ($dbname) { # OCI 7 handling below # We can use the 'user/passwd@machine' form of user. # $TWO_TASK and $ORACLE_SID will be ignored in that case. - if ($dbname =~ /@/){ # Implies an Sql*NET connection - $user = "$user/$auth$dbname"; $auth = ""; } elsif ($dbname =~ /:/){ # Implies an Sql*NET connection - $user = "$user/$auth".'@'.$dbname; $auth = ""; } else { - # Is this a NON-Sql*NET connection (ORACLE_SID)? # Or is it an alias for an Sql*NET connection (TWO_TASK)? # Sadly the 'user/passwd@machine' form only works # for Sql*NET connections. - load_dbnames($drh) unless %dbnames; - - if (exists $dbnames{$dbname}) { # known name - my $dbhome = $dbnames{$dbname}; # local=>ENV, remote=>0 + if (exists $dbnames{$dbname}) { # known name + my $dbhome = $dbnames{$dbname}; # local=>ORACLE_HOME, remote=>0 if ($dbhome) { - warn "Changing $ORACLE_ENV for $dbname to $dbhome (to match oratab entry)" - if ($ENV{$ORACLE_ENV} and $dbhome ne $ENV{$ORACLE_ENV}); $ENV{ORACLE_SID} = $dbname; - $ENV{$ORACLE_ENV} = $dbhome; delete $ENV{TWO_TASK}; + if ($attr && $attr->{ora_oratab_orahome}) { + warn "Changing $ORACLE_ENV for $dbname to $dbhome (to match oratab entry)" + if ($ENV{$ORACLE_ENV} and $dbhome ne $ENV{$ORACLE_ENV}); + $ENV{$ORACLE_ENV} = $dbhome; + } } else { $user .= '@'.$dbname; # it's a known TNS alias @@ -188,7 +191,8 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; } } - warn "$ORACLE_ENV not set!\n" unless $ENV{$ORACLE_ENV}; + warn "$ORACLE_ENV environment variable not set!\n" + if !$ENV{$ORACLE_ENV} and $^O ne "MSWin32"; # create a 'blank' dbh @@ -858,11 +862,11 @@ or just use the corresponding integer values (112 and 113). To make scripts work with both Oracle7 and Oracle8, the Oracle7 DBD::Oracle will treat the LOB ora_types as LONGs without error. -So any code you may have now that looks like +So in any code you may have now that looks like $sth->bind_param($idx, $value, { ora_type => 8 }); -should change the 8 (LONG type) to ORA_CLOB or ORA_BLOB +you could change the 8 (LONG type) to ORA_CLOB or ORA_BLOB (or 112 or 113). One further wrinkle: for inserts and updates of LOBs DBD::Oracle has diff --git a/README b/README index bf67fee6..243a73a3 100644 --- a/README +++ b/README @@ -246,21 +246,22 @@ http://www.wmd.de/wmd/staff/pauck/misc/oracle_on_linux.html =============================================================================== Some platforms on which the DBI and DBD::Oracle modules run: - Solaris 1 and 2 - Windows NT (using Perl5.004) - HP-UX 9 and 10 - Unisys U6000/300 - SCO 3 - Sequent DYNIX/ptx 2 - Motorola M88100 (SVR3.2) - DEC UNIX 3.2 + AIX 3 & 4 DEC Alpha + DEC UNIX 3.2 DG/UX 5.4 + HP-UX 9 and 10 + Linux (on platforms supported by Oracle 8) + Motorola M88100 (SVR3.2) OSF/1 - SGI IRIX 5 & 6 - AIX 3 & 4 Pyramid SMP DC/OSx + SCO 3 + SGI IRIX 5 & 6 + Sequent DYNIX/ptx 2 + Solaris 1 and 2 + Unisys U6000/300 VMS + Windows NT (using Perl5.004) and others (please let me know if your system is not listed). diff --git a/README.help b/README.help index b2e546ac..7e74c838 100644 --- a/README.help +++ b/README.help @@ -298,7 +298,8 @@ $ORACLE_HOME/bin. Try a more limited path and reinstall Oracle again. Environment: SGI IRIX 6 - Mark Duffield Oracle only supports "-32" and "-mips2" compilation flags, not "-n32". -Configure and build perl with -32 flag (see perl hints/irix_6.sh file). +Configure and build perl with -32 flag (see perl hints/irix_6.sh file +in the perl distribution). Rebuild DBI (which will now use the -32 flag). Rebuild DBD::Oracle (which will now use the -32 flag). diff --git a/README.longs b/README.longs index 96e92bab..31be075a 100644 --- a/README.longs +++ b/README.longs @@ -24,12 +24,13 @@ Thanks to Jurgen Botz ---------------------------------------------------------------------- Example for reading LONG fields via blob_read: + $ora_trunc = 1; # truncation on initial fetch is ok my $sql = "SELECT long_field FROM table_name WHERE id = :1"; my $csr = ora_open($lda, $sql) or die $ora_errstr; ora_bind($csr, $id) or die $ora_errstr; # ora_fetch() needs to be called in an array context my (@data) = ora_fetch($csr); - die $ora_errstr if $ora_errno; + die $ora_errstr if $ora_errno and $ora_errno != 1406; my $blob = ''; my $lump = 4096; # use benchmarks to get best value for you my $offset = 0; diff --git a/Todo b/Todo index b6aaa4e4..5861fa6b 100644 --- a/Todo +++ b/Todo @@ -1,7 +1,11 @@ +PRECISION for oci7 on VARCHAR etc -connect(..., { ora_module_name => $0 }); +Detect "Error while trying to retrieve text for error ORA-XXXX" +and add "refer to oracle docs or use 'oerr ora XXXX'". + +blob_read for oci8 -prepare("insert .. into ... RETURNING foo INTO :bar") +connect(..., { ora_module_name => $0 }); bind_param(... { TYPE => SQL_* }) esp SQL_LONGVARCHAR etc diff --git a/dbdimp.c b/dbdimp.c index 3c527103..28ce4271 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.47 1998/12/28 00:04:37 timbo Exp $ + $Id: dbdimp.c,v 1.48 1999/03/10 20:42:24 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -175,6 +175,7 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) #ifdef OCI_V8_SYNTAX D_imp_drh_from_dbh; + ub4 cred_type; if (!imp_drh->envhp) { /* OCI_OBJECT needed for OCIDescribeAny of table with LOBs */ @@ -212,15 +213,20 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp); OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_SESSION); - OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, - uid, strlen(uid), - (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp); - OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, - (strlen(pwd)) ? pwd : NULL, strlen(pwd), - (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp); - + if (*uid == '\0' && *pwd == '\0') { + cred_type = OCI_CRED_EXT; + } + else { + OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, + uid, strlen(uid), + (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp); + OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, + (strlen(pwd)) ? pwd : NULL, strlen(pwd), + (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp); + cred_type = OCI_CRED_RDBMS; + } ret=OCISessionBegin( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, - OCI_CRED_RDBMS, (ub4) OCI_DEFAULT); + cred_type, (ub4) OCI_DEFAULT); if (ret != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, ret, "OCISessionBegin"); OCIServerDetach(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT ); @@ -485,6 +491,7 @@ dbd_preparse(imp_sth, statement) char *statement; { bool in_literal = FALSE; + char in_comment = '\0'; char *src, *start, *dest; phs_t phs_tpl; SV *phs_sv; @@ -500,16 +507,63 @@ dbd_preparse(imp_sth, statement) memset(&phs_tpl, 0, sizeof(phs_tpl)); phs_tpl.imp_sth = imp_sth; phs_tpl.ftype = 1; /* VARCHAR2 */ + phs_tpl.maxlen_bound = -1; /* not yet bound */ src = statement; dest = imp_sth->statement; while(*src) { - if (*src == '\'') - in_literal = ~in_literal; - if ((*src != ':' && *src != '?') || in_literal) { + + if (in_comment) { + /* 981028-jdl on mocha. Adding all code which deals with */ + /* in_comment variable (its declaration plus 2 code blocks). */ + /* Text appearing within comments should be scanned for neither */ + /* placeholders nor for single quotes (which toggle the in_literal */ + /* boolean). Comments like "3:00" demonstrate the former problem, */ + /* and contractions like "don't" demonstrate the latter problem. */ + /* The comment style is stored in in_comment; each style is */ + /* terminated in a different way. */ + if (in_comment == '-' && *src == '\n') { + in_comment = '\0'; + } + else if (in_comment == '/' && *src == '*' && *(src+1) == '/') { + *dest++ = *src++; /* avoids asterisk-slash-asterisk issues */ + in_comment = '\0'; + } + *dest++ = *src++; + continue; + } + + if (in_literal) { + if (*src == in_literal) + in_literal = 0; + *dest++ = *src++; + continue; + } + + /* Look for comments: '-- oracle-style' or C-style */ + if ((*src == '-' && *(src+1) == '-') || + (*src == '/' && *(src+1) == '*')) + { + in_comment = *src; + /* We know *src & the next char are to be copied, so do */ + /* it. In the case of C-style comments, it happens to */ + /* help us avoid slash-asterisk-slash oddities. */ + *dest++ = *src++; + *dest++ = *src++; + continue; + } + + if (*src != ':' && *src != '?') { + + if (*src == '\'' || *src == '"') + in_literal = *src; + *dest++ = *src++; continue; } + + /* only here for : or ? outside of a comment or literal */ + start = dest; /* save name inc colon */ *dest++ = *src++; if (*start == '?') { /* X/Open standard */ @@ -601,10 +655,14 @@ ora_sql_type(imp_sth, name, sql_type) char *name; int sql_type; { + /* XXX should detect DBI reserved standard type range here */ + switch (sql_type) { case SQL_NUMERIC: case SQL_DECIMAL: case SQL_INTEGER: + case SQL_BIGINT: + case SQL_TINYINT: case SQL_SMALLINT: case SQL_FLOAT: case SQL_REAL: @@ -615,9 +673,22 @@ ora_sql_type(imp_sth, name, sql_type) case SQL_CHAR: return 5; /* Oracle CHAR */ + case SQL_BINARY: + case SQL_VARBINARY: + return 23; /* Oracle RAW */ + + case SQL_LONGVARBINARY: + return 24; /* Oracle LONG RAW */ + + case SQL_LONGVARCHAR: + return 8; /* Oracle LONG */ + + case SQL_DATE: + case SQL_TIME: + case SQL_TIMESTAMP: default: if (DBIc_WARN(imp_sth) && imp_sth && name) - warn("SQL type %d for '%s' is not fully supported, bound as VARCHAR instead"); + warn("SQL type %d for '%s' is not fully supported, bound as SQL_VARCHAR instead"); return ora_sql_type(imp_sth, name, SQL_VARCHAR); } } @@ -666,7 +737,7 @@ dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) /* pre-upgrade high to reduce risk of SvPVX realloc/move */ (void)SvUPGRADE(phs->sv, SVt_PVNV); /* ensure room for result, 28 is magic number (see sv_2pv) */ - SvGROW(phs->sv, (phs->maxlen < 28) ? 28 : phs->maxlen+1/*for null*/); + SvGROW(phs->sv, ((phs->maxlen < 28) ? 28 : phs->maxlen)+1/*for null*/); } else { /* phs->sv is copy of real variable, upgrade to at least string */ @@ -787,24 +858,27 @@ dbd_rebind_ph(sth, imp_sth, phs) } #ifdef OCI_V8_SYNTAX - status = OCIBindByName(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, strlen(phs->name), - phs->progv, phs->maxlen, - phs->ftype, &phs->indp, - NULL, /* ub2 *alen_ptr not needed with OCIBindDynamic */ - &phs->arcode, - 0, /* max elements that can fit in allocated array */ - NULL, /* (ptr to) current number of elements in array */ - OCI_DATA_AT_EXEC); - if (status != OCI_SUCCESS) { + if (phs->maxlen > phs->maxlen_bound) { + status = OCIBindByName(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + (text*)phs->name, strlen(phs->name), + phs->progv, + phs->maxlen ? phs->maxlen : 1, /* else bind "" fails */ + phs->ftype, &phs->indp, + NULL, /* ub2 *alen_ptr not needed with OCIBindDynamic */ + &phs->arcode, + 0, /* max elements that can fit in allocated array */ + NULL, /* (ptr to) current number of elements in array */ + OCI_DATA_AT_EXEC); + if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); return 0; - } - status = OCIBindDynamic(phs->bndhp, imp_sth->errhp, - (dvoid *)phs, dbd_phs_in, (dvoid *)phs, dbd_phs_out); - if (status != OCI_SUCCESS) { + } + status = OCIBindDynamic(phs->bndhp, imp_sth->errhp, + (dvoid *)phs, dbd_phs_in, (dvoid *)phs, dbd_phs_out); + if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); return 0; + } } #else @@ -824,6 +898,7 @@ dbd_rebind_ph(sth, imp_sth, phs) return 0; } #endif + phs->maxlen_bound = phs->maxlen ? phs->maxlen : 1; if (dbis->debug >= 3) fprintf(DBILOGFP, " bind %s done\n", phs->name); return 1; @@ -843,24 +918,23 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl { SV **phs_svp; STRLEN name_len; - char *name; + char *name = Nullch; char namebuf[30]; phs_t *phs; /* check if placeholder was passed as a number */ - if (!SvNIOK(ph_namesv) && !SvPOK(ph_namesv)) { - SvPV(ph_namesv, na); /* force SvPOK */ + if (SvGMAGICAL(ph_namesv)) /* eg if from tainted expression */ + mg_get(ph_namesv); + if (!SvNIOKp(ph_namesv)) { + name = SvPV(ph_namesv, name_len); } - if (SvNIOK(ph_namesv) || (SvPOK(ph_namesv) && isDIGIT(*SvPVX(ph_namesv)))) { + if (SvNIOKp(ph_namesv) || (name && isDIGIT(name[0]))) { sprintf(namebuf, ":p%d", (int)SvIV(ph_namesv)); name = namebuf; name_len = strlen(name); } - else { /* use the supplied placeholder name directly */ - name = SvPV(ph_namesv, name_len); - /* could check for leading colon here */ - } + assert(name != Nullch); if (SvTYPE(newvalue) > SVt_PVLV) /* hook for later array logic */ croak("Can't bind a non-scalar value (%s)", neatsvpv(newvalue,0)); @@ -910,10 +984,6 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl if (sql_type) croak("Can't specify both TYPE (%d) and ora_type (%d) for %s", sql_type, ora_type, phs->name); -#ifndef OCI_V8_SYNTAX /* treat Oracle8 LOBS as simple LONGs for Oracle7 */ - if (ora_type==112 || ora_type==113) - ora_type = 8; -#endif phs->ftype = ora_type; } if ( (svp=hv_fetch((HV*)SvRV(attribs), "ora_field",9, 0)) != NULL) { @@ -923,6 +993,11 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl if (sql_type) phs->ftype = ora_sql_type(imp_sth, phs->name, sql_type); +#ifndef OCI_V8_SYNTAX /* treat Oracle8 LOBS as simple LONGs for Oracle7 */ + if (phs->ftype==112 || phs->ftype==113) + phs->ftype = 8; +#endif + /* some types require the trailing null included in the length. */ phs->alen_incnull = (phs->ftype==SQLT_STR || phs->ftype==SQLT_AVC); @@ -1031,7 +1106,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count /* we don't AutoCommit on select so LOB locators work */ (DBIc_has(imp_dbh,DBIcf_AutoCommit) && !is_select) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT); - if (status != OCI_SUCCESS) { + if (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO) { oci_error(sth, imp_sth->errhp, status, "OCIStmtExecute"); return -2; } @@ -1332,7 +1407,7 @@ dbd_st_destroy(sth, imp_sth) { sword status; if (imp_sth->lob_refetch) - ora_free_lob_refetch(imp_sth); + ora_free_lob_refetch(sth, imp_sth); status = OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); if (status != OCI_SUCCESS) oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); @@ -1417,11 +1492,14 @@ dbd_st_FETCH_attrib(sth, imp_sth, keysv) return Nullsv; if (!imp_sth->done_desc && !dbd_describe(sth, imp_sth)) { + STRLEN lna; /* dbd_describe has already called ora_error() */ /* we can't return Nullsv here because the xs code will */ /* then just pass the attribute name to DBI for FETCH. */ - croak("Describe failed during %s->FETCH(%s)", - SvPV(sth,na), key); + croak("Describe failed during %s->FETCH(%s): %ld: %s", + SvPV(sth,na), key, (long)SvIV(DBIc_ERR(imp_sth)), + SvPV(DBIc_ERRSTR(imp_sth),lna) + ); } i = DBIc_NUM_FIELDS(imp_sth); diff --git a/dbdimp.h b/dbdimp.h index 8798c952..d2642778 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.29 1998/12/28 00:04:37 timbo Exp $ + $Id: dbdimp.h,v 1.30 1999/03/10 20:42:24 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -113,6 +113,7 @@ struct imp_sth_st { OCISvcCtx *svchp; /* copy of dbh pointer */ OCIStmt *stmhp; ub2 stmt_type; /* OCIAttrGet OCI_ATTR_STMT_TYPE */ + U16 auto_lob; int has_lobs; lob_refetch_t *lob_refetch; #else @@ -201,6 +202,7 @@ struct phs_st { /* scalar placeholder EXPERIMENTAL */ bool is_inout; IV maxlen; /* max possible len (=allocated buffer) */ + sb4 maxlen_bound; /* and Oracle bind has been called */ #ifdef OCI_V8_SYNTAX OCIBind *bndhp; @@ -239,7 +241,7 @@ int oci_error _((SV *h, OCIError *errhp, sword status, char *what)); char *oci_stmt_type_name _((int stmt_type)); char *oci_status_name _((sword status)); int dbd_rebind_ph_lob _((SV *sth, imp_sth_t *imp_sth, phs_t *phs)); -void ora_free_lob_refetch _((imp_sth_t *imp_sth)); +void ora_free_lob_refetch _((SV *sth, imp_sth_t *imp_sth)); int post_execute_lobs _((SV *sth, imp_sth_t *imp_sth, ub4 row_count)); #define OCIAttrGet_stmhp(imp_sth, p, l, a) \ diff --git a/hints/svr4.pl b/hints/svr4.pl index 9b42dd06..762275bc 100644 --- a/hints/svr4.pl +++ b/hints/svr4.pl @@ -1,8 +1,22 @@ -# From: Alan Burlison -# Date: Thu, 17 Aug 95 16:54 BST-1 +my $archname = $Config::Config{archname} || die; +$att{LIBS} ||= []; +$att{LIBS}->[0] ||= ''; # Some SVR4 systems may need to link against -lc to pick up things like -$att{LIBS} = [ '-lsocket -lnsl -lm -ldl -lc' ]; +# fpsetmask and ecvt. +my @libs = qw(-lsocket -lnsl -lm -ldl); + +# modified by Davide Migliavacca +if ($archname eq 'RM400-svr4') { + @libs = qw(-lucb); +} + +push @libs, '-lc'; + +warn "SVR4 LIBS attribute defaulted to '$att{LIBS}->[0]' for '$archname'"; +$att{LIBS}->[0] .= " ".join(" ", @libs); # append libs +warn "SVR4 LIBS attribute updated to '$att{LIBS}->[0]'"; + __END__ @@ -16,8 +30,6 @@ Content-Type: TEXT/PLAIN; charset=US-ASCII On Fri, 18 Aug 1995, Tim Bunce wrote: - -> > > From: Alan Burlison > > > > Tim, @@ -29,7 +41,7 @@ > > > > # Some SVR4 systems may need to link against -lc to pick up things like > > $att{LIBS} = [ '-lsocket -lnsl -lm -ldl -lc' ]; -> > +> > Umm, 'some', 'may', 'things like'. Care to clarify? > > Why _exactly_ is this needed, and why doesn't MakeMaker do this already? diff --git a/oci7.c b/oci7.c index 2f8189ac..0b2b7318 100644 --- a/oci7.c +++ b/oci7.c @@ -1,5 +1,5 @@ /* - $Id: oci7.c,v 1.5 1998/12/28 00:04:37 timbo Exp $ + $Id: oci7.c,v 1.6 1999/03/10 20:42:24 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -244,6 +244,9 @@ dbd_describe(h, imp_sth) else if (fbh->dbtype == 2 && fbh->prec == 0) { fbh->prec = 38; } + else if ((fbh->dbtype == 1 || fbh->dbtype == 96) && fbh->prec == 0) { + fbh->prec = fbh->dbsize; + } /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW? */ /* If so we need to implement oraperl truncation hacks. */ @@ -323,6 +326,8 @@ dbd_st_fetch(sth, imp_sth) if (imp_sth->eod_errno != 1403) { /* was not just end-of-fetch */ ora_error(sth, imp_sth->cda, imp_sth->eod_errno, "cached ofetch error"); } else { /* is simply no more data */ + dTHR; /* for DBIc_ACTIVE_off */ + DBIc_ACTIVE_off(imp_sth); /* eg finish */ sv_setiv(DBIc_ERR(imp_sth), 0); /* ensure errno set to 0 here */ if (debug >= 2) fprintf(DBILOGFP, " dbd_st_fetch no-more-data, rc=%d, rpc=%ld\n", @@ -400,8 +405,11 @@ dbd_st_fetch(sth, imp_sth) /* but it'll only be accessible via prior bind_column() */ sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], fb_ary->arlen[cache_entry]); - if (ora_dbtype_is_long(fbh->dbtype)) /* double check */ - hint = ", LongReadLen too small and/or LongTruncOk not set"; + if (ora_dbtype_is_long(fbh->dbtype)) { /* double check */ + hint = (DBIc_LongReadLen(imp_sth) > 65535) + ? ", LongTruncOk not set and/or LongReadLen too small or > 65535 max" + : ", LongTruncOk not set and/or LongReadLen too small"; + } } else { SvOK_off(sv); /* set field that caused error to undef */ diff --git a/oci8.c b/oci8.c index c5c06553..b842d666 100644 --- a/oci8.c +++ b/oci8.c @@ -1,5 +1,5 @@ /* - $Id: oci8.c,v 1.10 1998/12/28 00:04:37 timbo Exp $ + $Id: oci8.c,v 1.11 1999/03/10 20:42:24 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -153,9 +153,11 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) imp_sth->ora_pad_empty = (SvOK(ora_pad_empty)) ? SvIV(ora_pad_empty) : 0; } + imp_sth->auto_lob = 1; if (attribs) { SV **svp; DBD_ATTRIB_GET_IV( attribs, "ora_parse_lang", 14, svp, oparse_lng); + DBD_ATTRIB_GET_IV( attribs, "ora_auto_lob", 12, svp, imp_sth->auto_lob); } /* scan statement for '?', ':1' and/or ':foo' style placeholders */ @@ -220,7 +222,7 @@ dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, *indpp = &phs->indp; *piecep = OCI_ONE_PIECE; if (dbis->debug >= 3) - fprintf(DBILOGFP, " dbd_phs_in '%s' (%ld,%ld): len %ld, ind %d\n", + fprintf(DBILOGFP, " dbd_phs_in '%s' (%ld,%ld): len %2ld, ind %d\n", phs->name, iter, index, phs->alen, phs->indp); if (index > 0 || iter > 0) croak("Arrays and multiple iterations not currently supported by DBD::Oracle"); @@ -278,8 +280,8 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) -int -fetch_func_lob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) +static int +fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) { ub4 loblen = 0; ub4 buflen; @@ -287,14 +289,16 @@ fetch_func_lob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) OCILobLocator *lobl = (OCILobLocator*)fbh->desc_h; sword status; + /* this function is not called for NULL lobs */ + status = OCILobGetLength(imp_sth->svchp, imp_sth->errhp, lobl, &loblen); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobGetLength"); return 0; } - buflen = (loblen > imp_sth->long_readlen) ? imp_sth->long_readlen : loblen; - amtp = buflen; /* set right semantics for OCILobRead */ + amtp = (loblen > imp_sth->long_readlen) ? imp_sth->long_readlen : loblen; + buflen = amtp; /* set right semantics for OCILobRead */ if (loblen > imp_sth->long_readlen) { /* LOB will be truncated */ int oraperl = DBIc_COMPAT(imp_sth); @@ -311,26 +315,35 @@ fetch_func_lob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) fbh->field_num+1, DBIc_NUM_FIELDS(imp_sth), loblen, amtp, "LongReadLen too small and/or LongTruncOk not set"); oci_error(sth, NULL, OCI_ERROR, buf); - SvOK_off(dest_sv); + (void)SvOK_off(dest_sv); return 0; } } - SvUPGRADE(dest_sv, SVt_PV); + (void)SvUPGRADE(dest_sv, SVt_PV); SvGROW(dest_sv, buflen+1); - status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobl, - &amtp, 1, SvPVX(dest_sv), buflen, 0, 0, 0, SQLCS_IMPLICIT); - if (dbis->debug >= 3) - fprintf(DBILOGFP, - " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", - fbh->field_num+1, oci_status_name(status), loblen, imp_sth->long_readlen, buflen, amtp); - - if (status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, status, "OCILobRead"); - SvOK_off(dest_sv); - return 0; + if (loblen > 0) { + status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobl, + &amtp, 1, SvPVX(dest_sv), buflen, 0, 0, 0, SQLCS_IMPLICIT); + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", + fbh->field_num+1, oci_status_name(status), loblen, imp_sth->long_readlen, buflen, amtp); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCILobRead"); + (void)SvOK_off(dest_sv); + return 0; + } + } + else { + assert(amtp == 0); + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", + fbh->field_num+1, "SKIPPED", loblen, imp_sth->long_readlen, buflen, amtp); } + /* tell perl what we've put in its dest_sv */ SvCUR(dest_sv) = amtp; *SvEND(dest_sv) = '\0'; @@ -340,6 +353,20 @@ fetch_func_lob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) } +static int +fetch_func_loblocator(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) +{ + OCILobLocator *lobl = (OCILobLocator*)fbh->desc_h; + sword status; + + sv_setsv(dest_sv, &sv_no); + + croak("LOB Locators are not directly accessible yet."); + + return 1; +} + + int dbd_describe(SV *h, imp_sth_t *imp_sth) { @@ -436,9 +463,9 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) break; case 2: /* NUMBER */ - if (!fbh->prec) /* XXX seems sometimes 0! */ + if (!fbh->prec) /* is 0 for FLOATing point */ fbh->prec = 38; /* max prec */ - fbh->disize = fbh->prec + 2; /* sign + dot */ + fbh->disize = 130+3; /* worst case! 1**-130 */ avg_width = 4; /* > approx +/- 1_000_000 ? */ break; @@ -470,7 +497,8 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) case 113: /* BLOB */ fbh->ftype = fbh->dbtype; fbh->disize = fbh->dbsize; - fbh->fetch_func = fetch_func_lob; + fbh->fetch_func = (imp_sth->auto_lob) + ? fetch_func_autolob : fetch_func_loblocator; fbh->desc_t = OCI_DTYPE_LOB; OCIDescriptorAlloc_ok(imp_sth->envhp, &fbh->desc_h, fbh->desc_t); break; @@ -594,46 +622,11 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT); } -#ifdef incomplete_and_not_needed_anyway - while (status == OCI_NEED_DATA) { - imp_fbh_t *p_fbh = NULL; - fb_ary_t *fb_ary; - sword p_status; - OCIDefine *p_defnp; - ub1 *bufp; - ub4 p_htype, iter, idx, piece_len; - ub1 in_out, piece; - p_status = OCIStmtGetPieceInfo(imp_sth->stmhp, imp_sth->errhp, (void **)&p_defnp, - &p_htype, &in_out, &iter, &idx, &piece ); - for(i=0; i < num_fields; ++i) { - if (p_defnp == (p_fbh=&imp_sth->fbh[i])->defnp) - break; - } - if (i>=num_fields || p_status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, p_status, "OCIStmtGetPieceInfo"); - return Nullav; - } - piece_len = p_fbh->dbsize / 2; - if (dbis->debug >= 3) - fprintf(DBILOGFP, " field %d piece %d (plen %ld)\n", i+1, piece, piece_len); - bufp = p_fbh->fb_ary->abuf; - p_status = OCIStmtSetPieceInfo((void *)p_defnp, OCI_HTYPE_DEFINE, imp_sth->errhp, - (dvoid*)bufp, &piece_len, piece, p_fbh->fb_ary->aindp, p_fbh->fb_ary->arcode); - if (p_status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, p_status, "OCIStmtSetPieceInfo"); - return Nullav; - } - status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT); - *p_fbh->fb_ary->arlen = piece_len; - if (dbis->debug >= 3) - fprintf(DBILOGFP, " piece %d (%s, len %ld, rcode %d)\n", - piece, oci_status_name(status), piece_len, *p_fbh->fb_ary->arcode); - } -#endif - if (status != OCI_SUCCESS) { ora_fetchtest = 0; if (status == OCI_NO_DATA) { + dTHR; /* for DBIc_ACTIVE_off */ + DBIc_ACTIVE_off(imp_sth); /* eg finish */ if (dbis->debug >= 2) fprintf(DBILOGFP, " dbd_st_fetch no-more-data\n"); return Nullav; @@ -709,7 +702,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) hint = ", LongReadLen too small and/or LongTruncOk not set"; } else { - SvOK_off(sv); /* set field that caused error to undef */ + (void)SvOK_off(sv); /* set field that caused error to undef */ } ++err; /* 'fail' this fetch but continue getting fields */ /* Some should probably be treated as warnings but */ @@ -899,8 +892,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) if (!lob_cols_hv) lob_cols_hv = newHV(); sv = newSViv(col_dbtype); - sv_setpvn(sv, col_name, col_name_len); - SvIOK_on(sv); /* what a wonderful hack! */ + (void)sv_setpvn(sv, col_name, col_name_len); + (void)SvIOK_on(sv); /* what a wonderful hack! */ hv_store(lob_cols_hv, col_name,col_name_len, sv,0); } if (status != OCI_SUCCESS) { @@ -1087,11 +1080,16 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl fprintf(DBILOGFP, " lob refetch %d for '%s' param: ftype %d, len %ld\n", i+1,fbh->name, fbh->dbtype, amtp); - status = OCILobWrite(imp_sth->svchp, errhp, - fbh->desc_h, &amtp, 1, SvPVX(phs->sv), amtp, OCI_ONE_PIECE, - 0,0, 0,SQLCS_IMPLICIT); + if (amtp > 0) { /* since amtp & OCI_ONE_PIECE fail (OCI 8.0.4) */ + status = OCILobWrite(imp_sth->svchp, errhp, + fbh->desc_h, &amtp, 1, SvPVX(phs->sv), amtp, OCI_ONE_PIECE, + 0,0, 0,SQLCS_IMPLICIT); + } + else { + status = OCILobTrim(imp_sth->svchp, errhp, fbh->desc_h, 0); + } if (status != OCI_SUCCESS) { - oci_error(sth, errhp, status, "OCILobWrite"); + oci_error(sth, errhp, status, "OCILobTrim/OCILobWrite/LOB refetch"); return -2; } } @@ -1100,10 +1098,13 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl } void -ora_free_lob_refetch(imp_sth_t *imp_sth) +ora_free_lob_refetch(SV *sth, imp_sth_t *imp_sth) { lob_refetch_t *lr = imp_sth->lob_refetch; int i; + sword status = OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); + if (status != OCI_SUCCESS) + oci_error(sth, imp_sth->errhp, status, "ora_free_lob_refetch/OCIHandleFree"); for(i=0; i < lr->num_fields; ++i) { imp_fbh_t *fbh = &lr->fbh_ary[i]; ora_free_fbh_contents(fbh); diff --git a/ora_explain.PL b/ora_explain.PL index 58c5997c..ac2cc752 100644 --- a/ora_explain.PL +++ b/ora_explain.PL @@ -4,10 +4,11 @@ use strict; my $script = <<'SCRIPT'; ~startperl~ -w + #!/usr/local/bin/perl -w ################################################################################ -# Copyright (c) 1998 Alan Burlison +# Copyright (c) 1999 Alan Burlison # # You may distribute under the terms of either the GNU General Public License # or the Artistic License, as specified in the Perl README file, with the @@ -25,17 +26,12 @@ my $script = <<'SCRIPT'; ################################################################################ use strict; -use IO::File; use File::Basename; -use Cwd; use DBI; -use Tk; +use Tk 800; +use Tk::Balloon; use Tk::ErrorDialog; -use Tk::Pod; -use Tk::Dialog; -use Tk::FileSelect; use Tk::ROText; -use Tk::Tree; ################################################################################ # Subclassed version of Tk::Tree that allows button3 to have a callback attached @@ -74,14 +70,20 @@ $w->Callback(-b3command => $ent); package main; use vars qw($VERSION); -$VERSION = "0.7 beta TEST RELEASE 1"; +$VERSION = "1.0"; # Globals +# $ProgName Program name (without pathname) # $Db Database handle +# $DbName Oracle database name +# $User Oracle user name +# $Schema Oracle schema name # $SqlMarker String used to identify SQL generated by explain # $OracleVersion Oracle version number +# $CharWidth Width of a character in pixels # $Plan Current query plan as a Perl data structure # $LoginDialog Login dialog +# $SchemaDialog Schema dialog # $SaveDialog Save File dialog # $OpenDialog Open File dialog # $FileDir Current file save/open directory @@ -90,36 +92,26 @@ $VERSION = "0.7 beta TEST RELEASE 1"; # $PlanTree Tree used to display the query plan # $PlanStep ROText used to display the selected plan step details # $PlanSql Text used to allow SQL editing +# $Balloon For balloon help # $GrabMain SQL cache grab main window -# $GrabFeedback Label used for feedback during grab +# $GrabStatus Text label used for feedback/status info +# $GrabSelection Tag of currently selected SQL statement in the SQL cache # $GrabSql ROText used to hold the contents of the SQL cache # $GrabDetails ROText used to display the selected statement details -use vars qw($Db $SqlMarker $OracleVersion $Plan - $LoginDialog $OpenDialog $SaveDialog $FileDir - $PlanMain $PlanTitle $PlanTree $PlanStep $PlanSql - $GrabMain $GrabFeedback $GrabSql $GrabDetails); +use vars qw($ProgName $Db $DbName $User $Schema $SqlMarker $OracleVersion + $CharWidth $Plan $LoginDialog $SchemaDialog $OpenDialog $SaveDialog + $FileDir $PlanMain $PlanTitle $PlanTree $PlanStep $PlanSql $Balloon + $GrabMain $GrabStatus $GrabSelection $GrabSql $GrabDetails); $SqlMarker = "/* This statement was generated by explain */"; ################################################################################ # Switch the hourglass on or off -sub busy($$) +sub busy($) { -my ($win, $state) = @_; -if ($state eq "on") - { - if ($win eq "plan" || $win eq "all") - { $PlanMain->Busy(); } - if (defined($GrabMain) && ($win eq "grab" || $win eq "all")) - { $GrabMain->Busy(); } - } -else - { - if ($win eq "plan" || $win eq "all") - { $PlanMain->Unbusy(); } - if (defined($GrabMain) && ($win eq "grab" || $win eq "all")) - { $GrabMain->Unbusy(); } - } +my ($state) = @_; +if ($state && $PlanMain->grabCurrent()) { $PlanMain->Busy(-recurse => 1); } +else { $PlanMain->Unbusy(1); } } ################################################################################ @@ -127,40 +119,96 @@ else sub error($@) { -my ($parent) = shift(@_); -busy("all", "off"); -$PlanMain->Dialog(-title => "Error", - -bitmap => "error", - -text => join("\n", @_), - -wraplength => "80c", - -buttons => ["OK"] )->Show(); +my ($parent, @lines) = @_; + +my ($msg, $height, $width); +$msg = join("\n", @lines); +$msg =~ s/\n$//; +$msg =~ s/ \(DBD:/\n(DBD:/; +$msg =~ s/(indicator at char \d+ in) /$1\n/; +@lines = split("\n", $msg); +$height = @lines; +$width = 0; +foreach my $line (@lines) + { my $l = length($line); $width = $l if ($l > $width); } +$width = 80 if ($width > 80); +$height = 4 if ($height < 4); +$height = 10 if ($height > 10); + +busy(0); +my $dialog = $PlanMain->Toplevel(-title => "Error"); +$dialog->withdraw(); +my $text = $dialog->Scrolled("ROText", -height => $height, -width => $width, + -borderwidth => 3, -relief => "raised", + -wrap => "word", -scrollbars => "oe") + ->pack(-padx => 6, -pady => 6, -expand => 1, -fill => "both"); +$text->insert("1.0", $msg); + +my $ok_cb = sub { $dialog->destroy() }; +$dialog->Button(-text => "OK", -default => "active", -command => $ok_cb) + ->pack(-padx => 6, -pady => 6); +$dialog->bind("", $ok_cb); +$dialog->Popup; } ################################################################################ -sub about($) +sub about($;$) { +my ($parent, $win) = @_; my $msg = <Dialog(-title => "About Explain", - -text => $msg, - -wraplength => "80c", - -buttons => ["OK"] )->Show(); +my $dialog; +$dialog = $parent->Toplevel(-title => "About $ProgName"); +$dialog->withdraw(); +$dialog->resizable(0, 0); +my $text = $dialog->Text(-borderwidth => 3, -width => 80, -height => 16, + -relief => "raised") + ->pack(-padx => 6, -pady => 6); +$text->insert("1.0", $msg); +my $cb; +if ($win) + { + $$win = $dialog; + $cb = sub { $dialog->destroy(); undef($$win); }; + } +else + { + $cb = sub { $dialog->destroy(); }; + } +$dialog->Button(-text => "OK", -command => $cb)->pack(-padx => 6, -pady => 6); +$dialog->Popup(); +return($dialog); +} + +################################################################################ + +sub update_title() +{ +$PlanMain->configure(-title => + $User + ? $User eq $Schema + ? "$ProgName - connected to $DbName as $User" + : "$ProgName - connected to $DbName as $User [schema $Schema]" + : "$ProgName - not connected" + ); } ################################################################################ @@ -168,6 +216,7 @@ $PlanMain->Dialog(-title => "About Explain", sub help($) { my ($parent) = @_; +require Tk::Pod; $parent->Pod(-file => $0, -scrollbars => "e"); } @@ -179,51 +228,56 @@ sub login($$$) { my ($database, $username, $password) = @_; -busy("all", "on"); +busy(1); # Close any existing handle if ($Db) { $Db->disconnect(); $Db = undef; + $DbName = $User = $Schema = undef; + update_title(); } # Connect and initialise $Db = DBI->connect("dbi:Oracle:$database", $username, $password, { AutoCommit => 0, PrintError => 0}) - || die("Can't login to Oracle: $DBI::errstr\n"); + || die("Can't login to Oracle:\n$DBI::errstr\n"); $Db->{LongReadLen} = 4096; $Db->{LongTruncOk} = 1; -# Check there is a plan_table for this user +# Get the user name and check the Oracle version my $qry = $Db->prepare(qq( - $SqlMarker select 1 from user_tables where table_name = 'PLAN_TABLE' + $SqlMarker select user, version from product_component_version + where lower(product) like '%oracle%' )); -$qry->execute(); -if (! $qry->fetchrow_arrayref()) +if (! $qry->execute()) { + my $err = $DBI::errstr; $qry->finish(); $Db->disconnect(); $Db = undef; - die("User $username does not have a PLAN_TABLE.\n", - "Run the script utlxplan.sql to create one.\n"); + die("Can't fetch Oracle version:\n$err\n"); } +($User, $OracleVersion) = $qry->fetchrow_array(); +$qry->finish(); +$DbName = $database || $ENV{TWO_TASK} || $ENV{ORACLE_SID}; +$Schema = $User; -# Check the Oracle version +# Check there is a plan_table for this user $qry = $Db->prepare(qq( - $SqlMarker select version from product_component_version - where lower(product) like '%oracle%' + $SqlMarker select 1 from user_tables where table_name = 'PLAN_TABLE' )); -if (! $qry->execute()) +$qry->execute(); +if (! $qry->fetchrow_arrayref()) { - my $err = $DBI::errstr; $qry->finish(); $Db->disconnect(); $Db = undef; - die("Can't fetch Oracle version: $err\n"); + die("User $User does not have a PLAN_TABLE.\n", + "Run the script utlxplan.sql to create one.\n"); } -($OracleVersion) = $qry->fetchrow_array(); -$qry->finish(); -busy("all", "off"); + +busy(0); return(1); } @@ -238,6 +292,7 @@ $PlanStep->delete("1.0", "end") if ($PlanStep); } ################################################################################ +# Clear the SQL editor pane sub clear_editor() { @@ -247,6 +302,155 @@ $PlanStep->delete("1.0", "end") if ($PlanStep); $PlanSql->delete("1.0", "end"); } +################################################################################ +# Display the structure of an index + +sub disp_index($$) +{ +my ($owner, $index) = @_; + +# Create the index definition frame +busy(1); +my $dialog = $PlanMain->Toplevel(-title => "Index"); +$dialog->withdraw(); +$dialog->resizable(0, 0); +my $index_fr = $dialog->Frame(-borderwidth => 3, -relief => "raised"); +$index_fr->Label(-text => "$owner.$index", -relief => "ridge", + -borderwidth => 1) + ->grid(-column => 0, -row => 0, -columnspan => 2, -sticky => "we", + -ipadx => 3); +$index_fr->Label(-text => "Table", -relief => "ridge", -borderwidth => 1) + ->grid(-column => 0, -row => 1, -sticky => "we", -ipadx => 3); +$index_fr->Label(-text => "Column", -relief => "ridge", -borderwidth => 1) + ->grid(-column => 1, -row => 1, -sticky => "we", -ipadx => 3); + +# Show the table columns the index is built upon +my $qry = $Db->prepare(qq( + $SqlMarker select table_owner, table_name, column_name + from all_ind_columns + where index_owner = :1 and index_name = :2 + order by column_position +)); +$qry->execute($owner, $index) || die("Index columns:\n$DBI::errstr\n"); + +# For each column in the index, display its details +my ($tab_txt, $col_txt); +while ((my ($tab_owner, $table, $column) = $qry->fetchrow_array())) + { + $tab_txt .= "$tab_owner.$table\n"; + $col_txt .= "$column\n"; + } +$qry->finish(); +chop($tab_txt, $col_txt); +$index_fr->Label(-text => $tab_txt, -relief => "ridge", -borderwidth => 1, + -justify => "left") + ->grid(-column => 0, -row => 2, -sticky => "we", -ipadx => 3); +$index_fr->Label(-text => $col_txt, -relief => "ridge", -borderwidth => 1, + -justify => "left") + ->grid(-column => 1, -row => 2, -sticky => "we", -ipadx => 3); +$index_fr->pack(-side => "top", -fill => "x"); + +# Pack the grid and add the close button +$dialog->Button(-text => "Close", -command => sub { $dialog->destroy(); }) + ->pack(-padx => 6, -pady => 6); + +$dialog->Popup(); +busy(0); +return(1); +} + +################################################################################ +# Callback for adding/removing index definitions to a table dialog + +sub disp_table_cb($$$$$) +{ +my ($owner, $table, $num_cols, $index_fr, $index_bn) = @_; + +# If this is the first time through, fetch the index definitions +busy(1); +if (! $index_fr->children()) + { + # This will retrieve the names & owners of all the indexes on the table + my $qry = $Db->prepare(qq( + $SqlMarker select owner, index_name + from all_indexes + where table_owner = :1 and table_name = :2 + order by owner, index_name + )); + + # Build up a list of all the indexes + $qry->execute($owner, $table) || die("Table indexes:\n$DBI::errstr\n"); + my (@indexes, $ind_owner, $ind_name); + while (($ind_owner, $ind_name) = $qry->fetchrow_array()) + { push(@indexes, { owner => $ind_owner, name => $ind_name }); } + $qry->finish(); + + # Special for no indexes + if (@indexes == 0) + { + $index_fr->Label(-text => "No\nindexes\ndefined", -relief => "ridge", + -borderwidth => 1)->pack(-ipadx => 3, -ipady => 4); + } + else + { + # Do the header label + $index_fr->Label(-text => "Index\norder", -relief => "ridge", + -borderwidth => 1) + ->grid(-column => 0, -row => 0, -sticky => "we", -ipadx => 3, + -ipady => 2, -columnspan => scalar(@indexes), -rowspan => 2); + + # This will retrieve (table column id, index position) for an index + $qry = $Db->prepare(qq( + $SqlMarker select atc.column_id, aic.column_position + from all_tab_columns atc, all_ind_columns aic + where aic.index_owner = :1 and aic.index_name = :2 + and atc.owner = aic.table_owner and atc.table_name = aic.table_name + and atc.column_name = aic.column_name + order by aic.index_name, atc.column_id + )); + + # For each index, add a label describing the index + my $cb = sub { disp_index($_[1], $_[2]); }; + my $grid_col = 0; + foreach my $index (@indexes) + { + ($ind_owner, $ind_name) = @{$index}{qw(owner name)}; + $qry->execute($ind_owner, $ind_name) + || die("Index columns:\n$DBI::errstr\n"); + my $index_txt; + my $col = 1; + while (my ($col_id, $col_pos) = $qry->fetchrow_array()) + { + $index_txt .= "\n" x ($col_id - $col) . "$col_pos\n"; + $col = $col_id + 1; + } + $index_txt .= "\n" x ($num_cols - ($col - 1)); + chop($index_txt); + my $label = $index_fr->Label(-text => $index_txt, -relief => "ridge", + -borderwidth => 1, -justify => "left") + ->grid(-column => $grid_col, -row => 2, -sticky => "w", + -ipadx => 3); + $label->bind("<1>", [ $cb, $ind_owner, $ind_name ]); + $Balloon->attach($label, -msg => "$ind_owner.$ind_name", + -balloonposition => "mouse"); + $grid_col++; + } + } + } +if ($index_bn->cget(-text) eq "Indexes") + { + $index_bn->configure(-text => "Hide Indexes"); + $index_fr->pack(-side => "right", -expand => 1); + } +else + { + $index_bn->configure(-text => "Indexes"); + $index_fr->packForget(); + } +busy(0); +return(1); +} + ################################################################################ # Display a popup dialog showing the structure of a table @@ -255,20 +459,24 @@ sub disp_table($$) my ($owner, $table) = @_; # Create the dialog for displaying the object details +busy(1); my $dialog = $PlanMain->Toplevel(-title => "Table"); -my $box = $dialog->Frame(-borderwidth => 3, -relief => "raised"); -$box->Label(-text => "$owner.$table", +$dialog->withdraw(); +$dialog->resizable(0, 0); + +# Create the table definition frame +my $box1 = $dialog->Frame(-borderwidth => 3, -relief => "raised"); +my $box2 = $box1->Frame(-borderwidth => 0); +my $table_fr = $box2->Frame(-borderwidth => 1, -relief => "flat"); +$table_fr->Label(-text => "$owner.$table", -relief => "ridge", -borderwidth => 1) ->grid(-column => 0, -row => 0, -columnspan => 2, -sticky => "we"); - -# Mimic the SqlPlus "desc" command -$box->Label(-text => " Name ", -relief => "ridge", -borderwidth => 1) - ->grid(-column => 0, -row => 1, -sticky => "we"); -$box->Label(-text => " Type ", -relief => "ridge", -borderwidth => 1) - ->grid(-column => 1, -row => 1, -sticky => "we"); +$table_fr->Label(-text => "Name", -relief => "ridge", -borderwidth => 1) + ->grid(-column => 0, -row => 1, -sticky => "we", -ipadx => 3); +$table_fr->Label(-text => "Type", -relief => "ridge", -borderwidth => 1) + ->grid(-column => 1, -row => 1, -sticky => "we", -ipadx => 3); # This will get the table description -busy("plan", "on"); my $qry = $Db->prepare(qq( $SqlMarker select column_name, data_type, data_length, data_precision, data_scale @@ -277,15 +485,12 @@ my $qry = $Db->prepare(qq( order by column_id )); $qry->execute($owner, $table) - || die("Table columns: $DBI::errstr\n"); + || die("Table columns:\n$DBI::errstr\n"); -# For each column in the table, display its details -my $row = 2; +my ($num_cols, $name_txt, $type_txt); while ((my ($name, $type, $length, $precision, $scale) = $qry->fetchrow_array())) { - $box->Label(-text => "$name ") - ->grid(-column => 0, -row => $row, -sticky => "w"); if ($precision) { $type .= "($precision"; @@ -296,65 +501,39 @@ while ((my ($name, $type, $length, $precision, $scale) { $type .= "($length)"; } - $box->Label(-text => $type) - ->grid(-column => 1, -row => $row, -sticky => "w"); - $row++; - } -$qry->finish(); -busy("plan", "off"); - -# Pack the grid and add the close button -$box->pack(); -$dialog->Button(-text => "Close", -command => sub { $dialog->destroy(); }) - ->pack(-pady => 3); -} - -################################################################################ -# Display the structure of an index - -sub disp_index($$) -{ -my ($owner, $index) = @_; - -# Create the dialog for displaying the object details -my $dialog = $PlanMain->Toplevel(-title => "Index"); -my $box = $dialog->Frame(-borderwidth => 3, -relief => "raised"); -$box->Label(-text => "$owner.$index", - -relief => "ridge", -borderwidth => 1) - ->grid(-column => 0, -row => 0, -columnspan => 2, -sticky => "we"); - -# Show the table columns the index is built upon -$box->Label(-text => " Table ", -relief => "ridge", -borderwidth => 1) - ->grid(-column => 0, -row => 1, -sticky => "we"); -$box->Label(-text => " Column ", -relief => "ridge", -borderwidth => 1) - ->grid(-column => 1, -row => 1, -sticky => "we"); -busy("plan", "on"); -my $qry = $Db->prepare(qq( - $SqlMarker select table_owner, table_name, column_name - from all_ind_columns - where index_owner = :1 and index_name = :2 - order by column_position -)); -$qry->execute($owner, $index) - || die("Index columns: $DBI::errstr\n"); - -# For each column in the index, display its details -my $row = 2; -while ((my ($tab_owner, $table, $column) = $qry->fetchrow_array())) - { - $box->Label(-text => "$tab_owner.$table ") - ->grid(-column => 0, -row => $row, -sticky => "w"); - $box->Label(-text => $column) - ->grid(-column => 1, -row => $row, -sticky => "w"); - $row++; + $name_txt .= "$name\n"; + $type_txt .= "$type\n"; + $num_cols++; } $qry->finish(); -busy("plan", "off"); - -# Pack the grid and add the close button -$box->pack(); -$dialog->Button(-text => "Close", -command => sub { $dialog->destroy(); }) - ->pack(-pady => 3); +chop($name_txt, $type_txt); +$table_fr->Label(-text => $name_txt, -relief => "ridge", -borderwidth => 1, + -justify => "left") + ->grid(-column => 0, -row => 2, -sticky => "we", -ipadx => 3); +$table_fr->Label(-text => $type_txt, -relief => "ridge", -borderwidth => 1, + -justify => "left") + ->grid(-column => 1, -row => 2, -sticky => "we", -ipadx => 3); +$table_fr->pack(-side => "left"); + +# Now create a frame for the index definition & pack the whole lot +my $index_fr = $box2->Frame(-borderwidth => 1, -relief => "flat"); +$box2->pack(); +$box1->pack(-side => "top", -fill => "x", -expand => 1); + +# Create the buttons at the bottom +$box1 = $dialog->Frame(-borderwidth => 0); +$box1->Button(-text => "Close", -command => sub { $dialog->destroy(); }) + ->pack(-padx => 6, -side => "left", -expand => 1); +my $index_bn; +$index_bn = $box1->Button(-text => "Indexes") + ->pack(-padx => 6, -side => "left", -expand => 1); +$index_bn->configure(-command => sub { disp_table_cb($owner, $table, $num_cols, + $index_fr, $index_bn); }); +$box1->pack(-side => "bottom", -pady => 6); + +$dialog->Popup(); +busy(0); +return(1); } ################################################################################ @@ -387,15 +566,17 @@ my ($key) = @_; my $row = $Plan->{key}{$key}; $PlanStep->delete("1.0", "end"); my $info = ""; -$info .= "Id:\t$row->{ID}\tPosition:\t$row->{POSITION}\t" - . "Parent Id:\t$row->{PARENT_ID}\n"; -$info .= "Cost:\t$row->{COST}\tCardinality:\t$row->{CARDINALITY}\t" - . "Bytes:\t\t$row->{BYTES}\n" +$info .= "Cost:\t\t$row->{COST}\t(Estimate of the cost of this step)\n" + . "Cardinality:\t$row->{CARDINALITY}\t" + . "(Estimated number of rows fetched by this step)\n" + . "Bytes:\t\t$row->{BYTES}\t" + . "(Estimated number of bytes fetched by this step)\n" if ($row->{COST}); $info .= "\nPartition\nStart:\t$row->{PARTITION_START}\tStop:\t\t" . "$row->{PARTITION_STOP}\tId:\t\t$row->{PARTITION_ID}\n" if ($row->{PARTITION_START}); -$info .= "\n$row->{OTHER}" if ($row->{OTHER}); +$info .= "\nSQL used by Parallel Query Slave:\n$row->{OTHER}" + if ($row->{OTHER}); $PlanStep->insert("1.0", $info); } @@ -412,16 +593,16 @@ my $row = $Plan->{key}{$key}; return(1) if (! $row->{OBJECT_NAME}); # Work out the type of the object - table or index -busy("plan", "on"); +busy(1); my $qry = $Db->prepare(qq( $SqlMarker select object_type from all_objects where object_name = :1 and owner = :2 )); $qry->execute($row->{OBJECT_NAME}, $row->{OBJECT_OWNER}) - || die("Object type: $DBI::errstr\n"); + || die("Object type:\n$DBI::errstr\n"); my ($object_type) = $qry->fetchrow_array(); $qry->finish(); -busy("plan", "off"); +busy(0); if ($object_type eq "TABLE") { @@ -451,18 +632,18 @@ my $row = $Plan->{key}{$key}; return(1) if (! $row->{OBJECT_NAME}); # Work out the type of the object - table or index -busy("plan", "on"); +busy(1); my $qry = $Db->prepare(qq( $SqlMarker select object_type from all_objects where object_name = :1 and owner = :2 )); $qry->execute($row->{OBJECT_NAME}, $row->{OBJECT_OWNER}) - || die("Object type: $DBI::errstr\n"); + || die("Object type:\n$DBI::errstr\n"); my ($object_type) = $qry->fetchrow_array(); $qry->finish(); if ($object_type ne "TABLE") { - busy("plan", "off"); + busy(0); return(1); } @@ -472,18 +653,20 @@ $qry = $Db->prepare(qq( where table_name = :1 and table_owner = :2 )); $qry->execute($row->{OBJECT_NAME}, $row->{OBJECT_OWNER}) - || die("Table indexes: $DBI::errstr\n"); -my $menu = $PlanMain->Menu(-tearoff => 0, -disabledforeground => "#0000f0"); + || die("Table indexes:\n$DBI::errstr\n"); +my $menu = $PlanMain->Menu(-tearoff => 0, -disabledforeground => "#000000"); $menu->command(-label => "Indexes", -state => "disabled"); + +$menu->separator(); my $count = 0; while ((my ($index_owner, $index_name) = $qry->fetchrow_array())) { $menu->command(-label => "$index_owner.$index_name", - -command => sub { disp_index($index_owner, $index_name); }); + -command => [ \&disp_index, $index_owner, $index_name ]); $count++; } $qry->finish(); -busy("plan", "off"); +busy(0); $menu->Popup(-popover => "cursor", -popanchor => "nw") if ($count); return(1); } @@ -503,7 +686,7 @@ die("You are not logged on to Oracle\n") if (! $Db); # Set up the various query strings # Note that for some reason you can't use bind variables in 'explain plan' -my $prefix = "$SqlMarker explain plan set statement_id = '$$' for "; +my $prefix = "explain plan set statement_id = '$$' for\n"; my $plan_sql = qq( $SqlMarker select level, operation, options, object_node, object_owner, object_name, object_instance, object_type, id, parent_id, position, @@ -520,20 +703,37 @@ $plan_sql .= qq( ); # Clean any old stuff from the plan_table -busy("plan", "on"); +busy(1); $Db->do(qq($SqlMarker delete from plan_table where statement_id = :1), undef, $$) - || die("Delete from plan_table: $DBI::errstr\n"); + || die("Delete from plan_table:\n$DBI::errstr\n"); $Db->commit(); -# Explain the plan -$Plan = { sql => $stmt }; -$Db->do($prefix . $stmt) || die("Explain plan: $DBI::errstr\n"); +# Switch schema if required +if ($Schema ne $User) + { + $Db->do(qq($SqlMarker alter session set current_schema = $Schema)) + || die("Cannot change schema to $Schema:\n$DBI::errstr\n"); + } + +# Explain the plan - need to save message if failed! +$Plan = { schema => $Schema, sql => $stmt }; +my $fail; +$fail = $DBI::errstr if (!$Db->do($prefix . $stmt)); + +# Switch back schema if required +if ($Schema ne $User) + { + $Db->do(qq($SqlMarker alter session set current_schema = $User)) + || die("Set current schema to $User:\n$DBI::errstr\n"); + } +# Now we can safely die if the exmplai plan failed +die("Explain plan:\n$fail\n") if ($fail); # Read back the plan my $qry = $Db->prepare($plan_sql) - || die("Unsupported PLAN_TABLE format: $DBI::errstr\n"); -$qry->execute($$) || die("Read plan: $DBI::errstr\n"); + || die("Unsupported PLAN_TABLE format:\n$DBI::errstr\n"); +$qry->execute($$) || die("Read plan:\n$DBI::errstr\n"); while (my $row = $qry->fetchrow_hashref()) { if ($row->{ID} == 0) @@ -551,7 +751,7 @@ while (my $row = $qry->fetchrow_hashref()) $desc .= " $row->{OPTIONS}" if ($row->{OPTIONS}); $desc .= " $row->{OBJECT_TYPE}" if ($row->{OBJECT_TYPE}); $desc .= " of $row->{OBJECT_OWNER}.$row->{OBJECT_NAME}" - if ($row->{OBJECT_OWNER}); + if ($row->{OBJECT_OWNER} && $row->{OBJECT_NAME}); $desc .= " using PQS $row->{OBJECT_NODE} $row->{OTHER_TAG}" if ($row->{OBJECT_NODE}); $row->{desc} = $desc; @@ -583,7 +783,7 @@ $qry->finish(); $Db->do(qq($SqlMarker delete from plan_table where statement_id = :1), undef, $$); $Db->commit(); -busy("plan", "off"); +busy(0); return(1); } @@ -604,7 +804,6 @@ sub login_dialog($) { my ($parent) = @_; -# Set up defaults # Create the dialog if (! $LoginDialog) { @@ -614,7 +813,7 @@ if (! $LoginDialog) $LoginDialog = $parent->Toplevel(-title => "Login to Oracle"); $LoginDialog->withdraw(); - $LoginDialog->transient($parent); + $LoginDialog->resizable(0, 0); my $box; # Create the entry labels & fields @@ -631,7 +830,7 @@ if (! $LoginDialog) ->grid(-column => 0, -row => 2, -sticky => "w"); $box->Entry(-textvariable => \$database, -width => 30) ->grid(-column => 1, -row => 2, -sticky => "w"); - $box->pack(-expand => 1, -fill => "both"); + $box->pack(-expand => 1, -fill => "both", -ipadx => 6, -ipady => 6); # Create the buttons & callbacks $box = $LoginDialog->Frame(-borderwidth => 1, -relief => "raised"); @@ -640,24 +839,90 @@ if (! $LoginDialog) if (! eval { login($database, $username, $password); }) { error($parent, $@); - $LoginDialog->raise(); + $LoginDialog->raise($parent); } else { + update_title(); $LoginDialog->withdraw(); } }; - $box->Button(-text => "Login", -command => $cb) - ->pack(-side => "left", -expand => 1, -pady => 3); + $box->Button(-text => "Login", -default => "active", -command => $cb) + ->pack(-side => "left", -expand => 1, -pady => 6); $box->Button(-text => "Cancel", -command => sub { $LoginDialog->withdraw() }) - ->pack(-side => "right", -expand => 1, -pady => 3); + ->pack(-side => "right", -expand => 1, -pady => 6); $box->pack(-expand => 1, -fill => "both"); + $LoginDialog->bind("", $cb); } # Activate the dialog $LoginDialog->Popup(); } +################################################################################ + +sub schema_dialog($) +{ +my ($parent) = @_; + +if (! $Db) + { + error($parent, "You are not logged on to Oracle\n"); + return; + } + +# Create the dialog +if (! $SchemaDialog) + { + $SchemaDialog = $parent->Toplevel(-title => "Change Schema"); + $SchemaDialog->withdraw(); + $SchemaDialog->resizable(0, 0); + my ($box, $schema); + + # Create the entry labels & fields + $box = $SchemaDialog->Frame(-borderwidth => 1, -relief => "raised"); + $box->Label(-text => "Schema") + ->pack(-side => "left", -anchor => "e", -expand => 1); + $box->Entry(-textvariable => \$schema, -width => 30) + ->pack(-side => "right", -anchor => "w", -expand => 1); + $box->pack(-expand => 1, -fill => "both", -ipadx => 6, -ipady => 6); + + # Create the buttons & callbacks + $box = $SchemaDialog->Frame(-borderwidth => 1, -relief => "raised"); + my $cb = sub + { + # Try changing to the specified schema + $schema = uc($schema); + if (! $Db->do(qq($SqlMarker alter session set current_schema = $schema))) + { + error($parent, "Cannot change schema to $schema:", $DBI::errstr); + $SchemaDialog->raise($parent); + } + else + { + # Change back to the user's schema + $Db->do(qq($SqlMarker alter session set current_schema = $User)) + || die("Cannot change schema to $User\n$DBI::errstr"); + $Schema = $schema; + update_title(); + $SchemaDialog->withdraw(); + } + }; + $box->Button(-text => "Default", -command => sub { $schema = $User; }) + ->pack(-side => "left", -expand => 1, -pady => 6); + $box->Button(-text => "Apply", -default => "active", -command => $cb) + ->pack(-side => "left", -expand => 1, -pady => 6); + $box->Button(-text => "Cancel", + -command => sub { $SchemaDialog->withdraw() }) + ->pack(-side => "left", -expand => 1, -pady => 6); + $box->pack(-expand => 1, -fill => "both"); + $SchemaDialog->bind("", $cb); + } + +# Activate the dialog +$SchemaDialog->Popup(); +} + ################################################################################ # Open a file and read it into the SQL editor frame @@ -665,10 +930,11 @@ sub open_file($) { # Open the file my ($file) = @_; +use IO::File; my $fh; if (! ($fh = IO::File->new($file, "r"))) { - error("Cannot open $file", $!); + error($PlanMain, "Cannot open $file:\n", $!); return(0); } @@ -689,6 +955,9 @@ sub open_dialog($) { my ($parent) = @_; +# Put up the dialog +require Cwd; import Cwd; +require Tk::FileSelect; $FileDir = cwd() if (! $FileDir); if (! $OpenDialog) { @@ -710,6 +979,9 @@ sub save_dialog($$) my ($parent, $text) = @_; # Put up the dialog +require Cwd; import Cwd; +require IO::File; +require Tk::FileSelect; $FileDir = cwd() if (! $FileDir); if (! $SaveDialog) { @@ -725,7 +997,7 @@ $FileDir = $SaveDialog->cget(-directory); my $fh; if (! ($fh = IO::File->new($file, "w"))) { - error("Cannot open $file", $!); + error($PlanMain, "Cannot open $file:\n", $!); return; } $fh->print($text->get("1.0", "end")); @@ -735,52 +1007,88 @@ $fh->close(); ################################################################################ # Copy SQL from the grab window into the explain SQL editor -sub copy_sql() +sub copy_sql($$) { my ($text, $tag) = @_; +return if (! defined($tag)); clear_editor(); $PlanSql->insert("end", $text->get("$tag.first", "$tag.last")); -explain(); +$Schema = $text->tag("cget", $tag, -data); +update_title(); +$PlanMain->deiconify(); } ################################################################################ # Display info from v$sqlarea for the selected statement in the SQL cache -sub disp_sql_cache_info($) +sub disp_sql_cache_info($$) { -my ($address) = @_; +my ($address, $puid) = @_; # Empty the widget & prepare the SQL $GrabDetails->delete("1.0", "end"); -busy("grab", "on"); +busy(1); my $qry = $Db->prepare(qq( - $SqlMarker select sorts, executions, loads, parse_calls, disk_reads, - buffer_gets, rows_processed + $SqlMarker select executions, disk_reads, buffer_gets, rows_processed, + sorts, loads, parse_calls from v\$sqlarea where address = :1 -)) || die("$DBI::errstr\n"); +)) || die("Statement info:\n$DBI::errstr\n"); # Read the info. Note that the statement *may* have been purged from the cache! $qry->execute($address); -my $info; -if (! (my ($sorts, $executions, $loads, $parse_calls, - $disk_reads, $buffer_gets, $rows_processed) +if (! (my ($executions, $disk_reads, $buffer_gets, $rows_processed, + $sorts, $loads, $parse_calls) = $qry->fetchrow_array())) { - $info = "This statement is no longer in the SQL cache"; + $GrabDetails->insert("1.0", "This statement is no longer in the SQL cache"); } else { - $info = "Sorts:\t\t$sorts\tExecutions:\t$executions\tLoads:\t\t$loads\n" - . "Parse calls:\t$parse_calls\tDisk reads:\t$disk_reads\t" - . "Buffer gets:\t$buffer_gets\nRows processed:\t$rows_processed"; + $GrabDetails->insert("1.0", "First executed by user", "bold", + " $puid\n"); + $GrabDetails->insert("end", "Total ", "bold"); + $GrabDetails->insert("end", sprintf("Executions: %8d\n", $executions)); + my $fmt = + "Disk reads: %8d Buffer gets: %8d Rows processed: %8d\n" + . "Sorts: %8d Loads: %8d Parse calls: %8d\n"; + $GrabDetails->insert("end", + sprintf($fmt, $disk_reads, $buffer_gets, $rows_processed, + $sorts, $loads, $parse_calls)); + if ($executions > 0) + { + $GrabDetails->insert("end", "Average per Execution\n", "bold"); + $fmt = + "Disk reads: %8.1f Buffer gets: %8.1f " + . "Rows processed: %8.1f\n" + . "Sorts: %8.1f Loads: %8.1f " + . "Parse calls: %8.1f\n"; + $GrabDetails->insert("end", + sprintf($fmt, $disk_reads / $executions, $buffer_gets / $executions, + $rows_processed / $executions, $sorts / $executions, + $loads / $executions, $parse_calls / $executions)); + } } -busy("grab", "off"); +busy(0); # Display the formated info -$GrabDetails->insert("1.0", $info); return(1); } +################################################################################ +# Callback for whenever a bit of grabbed SQL is selected + +sub grab_select_cb($$) +{ +my ($text, $tag) = @_; +$text->tag("configure", $GrabSelection, -background => undef) + if ($GrabSelection); +$text->tag("configure", $tag, -background => "#43ce80"); +my $puid = $text->tag("cget", $tag, -data); +$GrabSelection = $tag; +if (! eval { disp_sql_cache_info($tag, $puid); }) + { error($GrabMain, $@); } +} + ################################################################################ # Scan v$sqlarea for SQL statements matching the specified conditions. # $order_by is a v$sqlarea colum name used to rank the statements @@ -788,9 +1096,9 @@ return(1); # $pattern is a perl regexp used to filter the SQL # $rows is the maximum number of rows to display -sub grab($$$$$) +sub grab($$$$$$) { -my ($order_by, $no_sys, $user, $pattern, $rows) = @_; +my ($ordering, $order_by, $no_sys, $user, $pattern, $rows) = @_; # Check we are logged on die("You are not logged on to Oracle\n") if (! $Db); @@ -805,53 +1113,31 @@ $GrabSql->delete("1.0", "end"); $GrabDetails->delete("1.0", "end"); # Define the callbacks for highlighting etc -my ($bold, $normal); -if ($GrabMain->depth > 1) +my $highlight = sub { - $bold = sub - { - my ($text, $tag) = @_; - $text->tag("configure", $tag, -background => "#43ce80", - -relief => "raised", -borderwidth => 1); - }; - $normal = sub - { - my ($text, $tag) = @_; - $text->tag("configure", $tag, -background => undef, -relief => "flat"); - }; - } -else - { - $bold = sub - { - my ($text, $tag) = @_; - $text->tag("configure", $tag, -foreground => "white", - -background => "black"); - }; - $normal = sub - { - my ($text, $tag) = @_; - $text->tag("configure", $tag, -foreground => undef, -background => undef); - }; - } -my $disp_cb = sub + my ($text, $tag) = @_; + $text->tag("configure", $tag, -relief => "raised", -borderwidth => 1); + }; +my $normal = sub { - my ($text, $address) = @_; - if (! eval { disp_sql_cache_info($address); }) - { error($GrabMain, $@); } + my ($text, $tag) = @_; + $text->tag("configure", $tag, -relief => "flat"); }; # Prepare the queries -busy("grab", "on"); -my $qry1 = qq{$SqlMarker select address from v\$sqlarea}; -$qry1 .= qq{, all_users} if ($user || $no_sys); +busy(1); +my $qry1 = qq{$SqlMarker select address, username from v\$sqlarea, all_users}; $qry1 .= qq{ where sql_text not like '\%$SqlMarker\%'}; -$qry1 .= qq{ and sql_text not like 'insert into plan_table\%'}; -$qry1 .= qq{ and user_id = parsing_user_id} if($user || $no_sys); +$qry1 .= qq{ and sql_text not like '\%insert into \%plan_table\%'}; +$qry1 .= qq{ and sql_text not like '\%explain plan\%'}; +$qry1 .= qq{ and user_id = parsing_user_id}; # if($user || $no_sys); $qry1 .= qq{ and username = :1} if ($user); $qry1 .= qq{ and username not in ('SYS', 'SYSTEM')} if ($no_sys); -$qry1 .= qq{ order by $order_by desc} if ($order_by); -$qry1 = $Db->prepare($qry1) || die("$DBI::errstr\n"); +if ($ordering eq "total") + { $qry1 .= qq{ order by $order_by desc}; } +elsif ($ordering eq "average") + { $qry1 .= qq{ order by $order_by / greatest(executions, 1) desc}; } +$qry1 = $Db->prepare($qry1) || die("SQL Cache capture:\n$DBI::errstr\n"); my $qry2; if ($OracleVersion ge "7.2") @@ -859,23 +1145,24 @@ if ($OracleVersion ge "7.2") $qry2 = $Db->prepare(qq( $SqlMarker select sql_text from v\$sqltext_with_newlines where address = :1 order by piece)) - || die("$DBI::errstr\n"); + || die("SQL text:\n$DBI::errstr\n"); } else{ $qry2 = $Db->prepare(qq( $SqlMarker select sql_text from v\$sqltext where address = :1 order by piece)) - || die("$DBI::errstr\n"); + || die("SQL text:\n$DBI::errstr\n"); } # For each SQL query in the shared pool... -if ($user) { $qry1->execute($user) || die("$DBI::errstr\n"); } -else { $qry1->execute() || die("$DBI::errstr\n"); } +if ($user) { $qry1->execute($user) || die("SQL text:\n$DBI::errstr\n"); } +else { $qry1->execute() || die("SQL text:\n$DBI::errstr\n"); } my $count = 0; -while ($count != $rows && (my ($address) = $qry1->fetchrow_array())) +my $first_address; +while ($count != $rows && (my ($address, $puid) = $qry1->fetchrow_array())) { # ...glue together the components of the SQL string & print out - $qry2->execute($address) || die("$DBI::errstr\n"); + $qry2->execute($address) || die("SQL text:\n$DBI::errstr\n"); my ($sql_text) = ""; while (my ($sql) = $qry2->fetchrow_array()) { @@ -891,23 +1178,26 @@ while ($count != $rows && (my ($address) = $qry1->fetchrow_array())) # Display the statement and set up the bindings $GrabSql->insert("end", $sql_text, $address, "\n\n"); - $GrabSql->tag("bind", $address, "" => [ $bold, $address ]); + $GrabSql->tag("configure", $address, -data => $puid); + $GrabSql->tag("bind", $address, "" => [ $highlight, $address ]); $GrabSql->tag("bind", $address, "" => [ $normal, $address ]); $GrabSql->tag("bind", $address, "" => [ \©_sql, $address]); - $GrabSql->tag("bind", $address, "<1>" => [ $disp_cb, $address ]); + $GrabSql->tag("bind", $address, "<1>" => [ \&grab_select_cb, $address ]); $GrabSql->update(); $count++; + $first_address = $address if (! defined($first_address)); if ($rows > 0) - { $GrabFeedback->configure(-text => "$count of $rows queries grabbed"); } + { $GrabStatus->configure(-text => "$count of $rows queries grabbed"); } else - { $GrabFeedback->configure(-text => "$count queries grabbed"); } + { $GrabStatus->configure(-text => "$count queries grabbed"); } } # Clean up $qry1->finish(); -$GrabFeedback->configure(-text => "$count queries grabbed"); -busy("grab", "off"); +grab_select_cb($GrabSql, $first_address) if ($first_address); +$GrabStatus->configure(-text => "$count queries grabbed"); +busy(0); return(1); } @@ -916,9 +1206,54 @@ return(1); sub grab_main { -# Only create if it doesn't already exist -return if ($GrabMain); -$GrabMain = $PlanMain->Toplevel(-title => "explain - SQL cache"); +# If it already exists, just make it visible) +if ($GrabMain) + { + $GrabMain->deiconify(); + $GrabMain->raise($PlanMain); + return; + } + +# Otherwise, build the grab window +$GrabMain = $PlanMain->Toplevel(-title => "$ProgName - SQL cache"); +$GrabMain->protocol("WM_DELETE_WINDOW", sub { $GrabMain->withdraw(); }); + +# Defaults & callbacks +my $ordering = ""; +my $order_by = ""; +my $no_sys = 1; +my $user = ""; +my $pattern = ""; +my $rows = 100; +my $grab_cb = sub + { + if (! eval { grab($ordering, $order_by, $no_sys, $user, $pattern, $rows); }) + { error($GrabMain, $@); } + }; +my (%ord_bn); # For "order by" buttons +my $ord_bn_cb = sub + { + if ($ordering eq "") + { + $order_by = ""; + foreach my $bn (values(%ord_bn)) + { $bn->configure(-state => "disabled"); } + } + elsif ($ordering eq "total") + { + $order_by = "disk_reads" if ($order_by eq ""); + foreach my $bn (values(%ord_bn)) + { $bn->configure(-state => "normal"); } + } + else # $ordering eq "average" + { + $order_by = "disk_reads" + if ($order_by eq "" || $order_by eq "executions"); + foreach my $bn (values(%ord_bn)) + { $bn->configure(-state => "normal"); } + $ord_bn{executions}->configure(-state => "disabled"); + } + }; ### Menubar my $menubar = $GrabMain->Frame(-relief => "raised", -borderwidth => 3); @@ -928,24 +1263,27 @@ my $menubar_file = $menubar->Menubutton(-text => "File", -underline => 0); $menubar_file->command(-label => "Save File ...", -underline => 0, -command => sub { save_dialog($PlanMain, $GrabSql); }); $menubar_file->separator(); +$menubar_file->command(-label => "Capture SQL", -underline => 0, + -command => $grab_cb); +$menubar_file->command(-label => "Copy to Explain", -underline => 9, + -command => sub { copy_sql($GrabSql, $GrabSelection); }); $menubar_file->command(-label => "Close", -underline => 1, - -command => sub { $GrabMain->destroy(); }); + -command => sub { $GrabMain->withdraw(); }); $menubar_file->pack(-side => "left"); my $menubar_help = $menubar->Menubutton(-text => "Help", -underline => 0); $menubar_help->command(-label => "About ...", -underline => 0, -command => sub { about($GrabMain); }); -$menubar_help->command(-label => "Usage", -underline => 0, +$menubar_help->command(-label => "Usage ...", -underline => 0, -command => sub { help($GrabMain); }); $menubar_help->pack(-side => "right"); ### SQL cache display -my ($frame, $frame1); +my ($frame, $frame1, $frame2, $frame3); $frame = $GrabMain->Frame(-borderwidth => 3, -relief => "raised"); $frame1 = $frame->Frame(-highlightthickness => 0); $frame1->Label(-text => "SQL Cache")->pack(-side => "left"); -$GrabFeedback = $frame1->Label(-text => "", -foreground => "#ff0000") - ->pack(-side => "right"); +$GrabStatus = $frame1->Label(-text => "")->pack(-side => "right"); $frame1->pack(-fill => "x"); $GrabSql = $frame->Scrolled("ROText", -setgrid => "true", -scrollbars => "oe", -height => 15, -width => 80, -borderwidth => 0, @@ -956,104 +1294,158 @@ $frame->pack(-fill => "both", -expand => 1); ### SQL statement details $frame = $GrabMain->Frame(-borderwidth => 3, -relief => "raised"); $frame->Label(-text => "SQL Statement Statistics")->pack(-anchor => "nw"); -$GrabDetails = $frame->ROText(-height => 3, -width => 80, -borderwidth => 0, - -setgrid => "true", -wrap => "word") +$GrabDetails = $frame->ROText(-height => 7, -width => 80, -borderwidth => 0, + -setgrid => "true", -wrap => "none") ->pack(-fill => "x"); +$GrabDetails->tagConfigure("bold", -font => "bold"); $frame->pack(-fill => "x"); ### SQL selection $frame = $GrabMain->Frame(-borderwidth => 3, -relief => "raised"); -$frame->Label(-text => "SQL Selection Criterea")->pack(-anchor => "nw"); - +$frame->Label(-text => "SQL Selection Criterea")->pack(-anchor => "w"); $frame1 = $frame->Frame(-highlightthickness => 1); -$frame1->Label(-text => "Order SQL by number of:") - ->grid(-column => 0, -row => 0, -columnspan => 3, -sticky => "w"); -my $order_by = "disk_reads"; -$frame1->Radiobutton(-text => "Disk reads", -highlightthickness => 0, - -value => "disk_reads", -variable => \$order_by) + +## SQL sort frame +$frame1->Label(-text => "Order SQL by") + ->grid(-column => 0, -row => 0, -sticky => "w", -columnspan => 2); +$frame2 = $frame1->Frame(-highlightthickness => 0); + +# Ordering frame +$frame3 = $frame2->Frame(-highlightthickness => 1); +$frame3->Radiobutton(-text => "No ordering", -highlightthickness => 0, + -value => "", -variable => \$ordering, + -command => $ord_bn_cb) + ->pack(-anchor => "w"); +$frame3->Radiobutton(-text => "Total", -highlightthickness => 0, + -value => "total", -variable => \$ordering, + -command => $ord_bn_cb) + ->pack(-anchor => "w"); +$frame3->Radiobutton(-text => "Average per execution", + -highlightthickness => 0, -value => "average", + -variable => \$ordering, -command => $ord_bn_cb) + ->pack(-anchor => "w"); +$frame3->pack(-side => "left", -padx => 6); + +# Order by frame +$frame3 = $frame2->Frame(-highlightthickness => 1); +$ord_bn{disk_reads} = + $frame3->Radiobutton(-text => "Disk reads", -highlightthickness => 0, + -value => "disk_reads", -variable => \$order_by, + -command => $ord_bn_cb) + ->grid(-column => 0, -row => 0, -sticky => "w"); +$ord_bn{buffer_gets} = + $frame3->Radiobutton(-text => "Buffer gets", -highlightthickness => 0, + -value => "buffer_gets", -variable => \$order_by, + -command => $ord_bn_cb) + ->grid(-column => 1, -row => 0, -sticky => "w"); +$ord_bn{rows_processed} = + $frame3->Radiobutton(-text => "Rows processed", -highlightthickness => 0, + -value => "rows_processed", -variable => \$order_by, + -command => $ord_bn_cb) + ->grid(-column => 2, -row => 0, -sticky => "w"); +$ord_bn{sorts} = + $frame3->Radiobutton(-text => "Sorts", -highlightthickness => 0, + -value => "sorts", -variable => \$order_by, + -command => $ord_bn_cb) + ->grid(-column => 0, -row => 1, -sticky => "w"); +$ord_bn{loads} = + $frame3->Radiobutton(-text => "Loads", -highlightthickness => 0, + -value => "loads", -variable => \$order_by, + -command => $ord_bn_cb) + ->grid(-column => 1, -row => 1, -sticky => "w"); +$ord_bn{parse_calls} = + $frame3->Radiobutton(-text => "Parse calls", -highlightthickness => 0, + -value => "parse_calls", -variable => \$order_by, + -command => $ord_bn_cb) + ->grid(-column => 2, -row => 1, -sticky => "w"); +$ord_bn{executions} = + $frame3->Radiobutton(-text => "Executions", -highlightthickness => 0, + -value => "executions", -variable => \$order_by, + -command => $ord_bn_cb) + ->grid(-column => 0, -row => 2, -sticky => "w"); +$frame3->pack(-side => "right", -padx => 6); +$frame2->grid(-column => 0, -row => 1, -sticky => "w", -columnspan => 2); + +## Other options frame +$frame2 = $frame1->Frame(-highlightthickness => 0); +$frame2->Checkbutton(-text => "Exclude queries by SYS or SYSTEM", + -variable => \$no_sys, -offvalue => 0, -onvalue => 1, + -highlightthickness => 0) + ->grid(-column => 0, -row => 0, -sticky => "w", -columnspan => 2); +$frame2->Label(-text => "First user to execute statement") ->grid(-column => 0, -row => 1, -sticky => "w"); -$frame1->Radiobutton(-text => "Buffer gets", -highlightthickness => 0, - -value => "buffer_gets", -variable => \$order_by) +$frame2->Entry(-textvariable => \$user, -width => 30) ->grid(-column => 1, -row => 1, -sticky => "w"); -$frame1->Radiobutton(-text => "Rows processed", -highlightthickness => 0, - -value => "rows_processed", -variable => \$order_by) - ->grid(-column => 2, -row => 1, -sticky => "w"); -$frame1->Radiobutton(-text => "Executions", -highlightthickness => 0, - -value => "executions", -variable => \$order_by) - ->grid(-column => 3, -row => 1, -sticky => "w"); -$frame1->Radiobutton(-text => "Parse calls", -highlightthickness => 0, - -value => "parse_calls", -variable => \$order_by) +$frame2->Label(-text => "SQL matches pattern") ->grid(-column => 0, -row => 2, -sticky => "w"); -$frame1->Radiobutton(-text => "Sorts", -highlightthickness => 0, - -value => "sorts", -variable => \$order_by) +$frame2->Entry(-textvariable => \$pattern, -width => 30) ->grid(-column => 1, -row => 2, -sticky => "w"); -$frame1->Radiobutton(-text => "Loads", -highlightthickness => 0, - -value => "loads", -variable => \$order_by) - ->grid(-column => 2, -row => 2, -sticky => "w"); -$frame1->Radiobutton(-text => "No ordering", -highlightthickness => 0, - -value => "", -variable => \$order_by) - ->grid(-column => 3, -row => 2, -sticky => "w"); - -my $no_sys = 1; -$frame1->Checkbutton(-text => "Exclude queries by SYS or SYSTEM", - -variable => \$no_sys, -offvalue => 0, -onvalue => 1, - -highlightthickness => 0) - ->grid(-column => 0, -row => 3, -sticky => "w", -columnspan => 3); - - -my $user = ""; -$frame1->Label(-text => "First user to execute statement") - ->grid(-column => 0, -row => 4, -sticky => "w", -columnspan => 2); -$frame1->Entry(-textvariable => \$user, -width => 30) - ->grid(-column => 2, -row => 4, -sticky => "w", -columnspan => 2); - -my $pattern = ""; -$frame1->Label(-text => "SQL matches pattern") - ->grid(-column => 0, -row => 5, -sticky => "w", -columnspan => 2); -$frame1->Entry(-textvariable => \$pattern, -width => 30) - ->grid(-column => 2, -row => 5, -sticky => "w", -columnspan => 2); - -my $rows = 100; -$frame1->Label(-text => "Maximum number of statements") - ->grid(-column => 0, -row => 6, -sticky => "w", -columnspan => 2); -$frame1->Entry(-textvariable => \$rows, -width => 4) - ->grid(-column => 2, -row => 6, -sticky => "w", -columnspan => 2); - +$frame2->Label(-text => "Maximum number of statements") + ->grid(-column => 0, -row => 3, -sticky => "w"); +$frame2->Entry(-textvariable => \$rows, -width => 4) + ->grid(-column => 1, -row => 3, -sticky => "w"); +$frame2->grid(-column => 0, -row => 2, -sticky => "we", + -columnspan => 2, -padx => 6, -pady => 6); $frame1->pack(-fill => "x"); -$frame->pack(-fill => "x"); +&$ord_bn_cb(); # Set the buttons to the initial state +$frame->pack(-fill => "x", ipadx => 6, -ipady => 6); ### Buttons $frame = $GrabMain->Frame(-borderwidth => 3, -relief => "raised"); -my $grab_cb = sub - { - if (! eval { grab($order_by, $no_sys, $user, $pattern, $rows); }) - { error($GrabMain, $@); } - }; -$frame->Button(-text => "Grab", -command => $grab_cb) - ->pack(-side => "left", -expand => 1, -pady => 3); -$frame->Button(-text => "Close", -command => sub { $GrabMain->destroy(); }) - ->pack(-side => "left", -expand => 1, -pady => 3); +$frame->Button(-text => "Capture SQL", -command => $grab_cb) + ->pack(-side => "left", -expand => 1, -pady => 6); +$frame->Button(-text => "Copy to Explain", + -command => sub { copy_sql($GrabSql, $GrabSelection); }) + ->pack(-side => "left", -expand => 1, -pady => 6); +$frame->Button(-text => "Close", -command => sub { $GrabMain->withdraw(); }) + ->pack(-side => "left", -expand => 1, -pady => 6); $frame->pack(-fill => "x"); -#$GrabMain->bind("", sub { $GrabMain = undef; }); -$GrabMain->OnDestroy(sub { $GrabMain = undef; }); } ################################################################################ # Main ### Main window +$ProgName = basename($0); +$ProgName =~ s/\..*$//; $PlanMain = MainWindow->new(); -$PlanMain->title("explain"); +$PlanMain->withdraw(); +update_title(); +$Balloon = $PlanMain->Balloon(); + +### Splash screen +my $splash; +if (@ARGV == 0 || $ARGV[0] ne '-q') + { + about($PlanMain, \$splash); + $splash->after(10000, + sub { if ($splash) { $splash->destroy(); undef($splash); } }); + $PlanMain->update(); + } +else + { shift(@ARGV); } ### Menubar my $menubar = $PlanMain->Frame(-relief => "raised", -borderwidth => 3); -$menubar->pack(-fill => "x"); + +# Create a bold font $ figure out charcter spacing +my $t = $PlanMain->Text(); +my $f = $t->cget(-font); +$t->fontCreate("bold", $PlanMain->fontActual($f), -weight => "bold"); +$CharWidth = $PlanMain->fontMeasure($f, "X"); +undef($f); +$t->destroy(); +undef($t); my $menubar_file = $menubar->Menubutton(-text => "File", -underline => 0); $menubar_file->command(-label => "Login ...", -underline => 0, -command => sub { login_dialog($PlanMain); }); -$menubar_file->command(-label => "Grab SQL ...", -underline => 0, - -command => sub { grab_main(); }); +$menubar_file->command(-label => "Schema ...", -underline => 2, + -command => sub { schema_dialog($PlanMain); }); +$menubar_file->command(-label => "Explain", -underline => 0, + -command => \&explain); +$menubar_file->command(-label => "SQL Cache ...", -underline => 4, + -command => \&grab_main); $menubar_file->separator(); $menubar_file->command(-label => "Open File ...", -underline => 0, -command => sub { open_dialog($PlanMain); }); @@ -1067,9 +1459,10 @@ $menubar_file->pack(-side => "left"); my $menubar_help = $menubar->Menubutton(-text => "Help", -underline => 0); $menubar_help->command(-label => "About ...", -underline => 0, -command => sub { about($PlanMain); }); -$menubar_help->command(-label => "Usage", -underline => 0, +$menubar_help->command(-label => "Usage ...", -underline => 0, -command => sub { help($PlanMain); }); $menubar_help->pack(-side => "right"); +$menubar->pack(-fill => "x"); ### Query plan tree my $frame; @@ -1090,9 +1483,9 @@ $frame->pack(-expand => 1, -fill => "both"); ### Query plan statement details $frame = $PlanMain->Frame(-borderwidth => 3, -relief => "raised"); $frame->Label(-text => "Query Step Details")->pack(-anchor => "nw"); -$PlanStep = $frame->Scrolled("ROText", -height => 10, -width => 80, - -borderwidth => 0, -wrap => "word", - -setgrid => "true", -scrollbars => "oe") +$PlanStep = $frame->Scrolled("ROText", -height => 8, -width => 80, + -borderwidth => 0, -wrap => "none", + -setgrid => "true", -scrollbars => "osoe") ->pack(-fill => "x"); $frame->pack(-fill => "x"); @@ -1108,20 +1501,24 @@ $frame->pack(-expand => 1, -fill => "both"); ### Buttons $frame = $PlanMain->Frame(-borderwidth => 3, -relief => "raised"); $frame->Button(-text => "Explain", -command => \&explain) - ->pack(-side => "left", -expand => 1, -pady => 3); + ->pack(-side => "left", -expand => 1, -pady => 6); $frame->Button(-text => "Clear", -command => \&clear_editor) - ->pack(-side => "left", -expand => 1, -pady => 3); -$frame->Button(-text => "Grab", -command => \&grab_main) - ->pack(-side => "left", -expand => 1, -pady => 3); + ->pack(-side => "left", -expand => 1, -pady => 6); +$frame->Button(-text => "SQL Cache", -command => \&grab_main) + ->pack(-side => "left", -expand => 1, -pady => 6); $frame->pack(-fill => "x"); ### user/pass@db command-line argument processing +$PlanMain->update(); +$PlanMain->deiconify(); +$splash->raise() if (defined($splash)); if (@ARGV >= 1 && $ARGV[0] =~ /\w*\/\w*(@\w+)?/) { my ($username, $password, $database) = split(/[\/@]/, shift(@ARGV)); if (! $username) { $username = "/"; $password = ""; } if (! $database) { $database = $ENV{TWO_TASK} || $ENV{ORACLE_SID}; } error($PlanMain, $@) if (! eval { login($database, $username, $password); }); + update_title(); } else { @@ -1147,30 +1544,32 @@ __END__ =head1 NAME -explain, ora_explain - visualise Oracle query plans +explain, ora_explain - Visualise Oracle query plans =head1 SYNOPSIS $ explain [ [ user/password@database ] sql script ] $ ora_explain [ [ user/password@database ] sql script ] +B When bundled with DBD::Oracle, the script is called ora_explain + =head1 DESCRIPTION -explain is a GUI-based tool that enables easier visualisation of Oracle Query +Explain is a GUI-based tool that enables easier visualisation of Oracle Query plans. A query plan is the access path that Oracle will use to satisfy a SQL query. The Oracle query optimiser is responsible for deciding on the optimal path to use. Needless to say, understanding such plans requires a fairly sophisticated knowledge of Oracle architecture and internals. -explain allows a user to interactively edit a SQL statemant and view the +Explain allows a user to interactively edit a SQL statemant and view the resulting query plan with the click of a single button. The effects of modifying the SQL or of adding hints can be rapidly established. -explain allows the user to grab all the SQL currently cached by Oracle. The SQL -capture can be filtered and sorted by different criterea, e.g. all SQL matching -a pattern, order by number of executions etc. +Explain allows the user to capture all the SQL currently cached by Oracle. The +SQL capture can be filtered and sorted by different criterea, e.g. all SQL +matching a pattern, order by number of executions etc. -explain is written using Perl, DBI/DBD::Oracle and Tk. +Explain is written using Perl, DBI/DBD::Oracle and Tk. =head1 PREREQUISITES @@ -1186,15 +1585,15 @@ L or later =item 3. -L version 0.93 or later +L version 1.02 or later =item 4. -L 0.49 or later +L 0.54 or later =item 5. -L 8.005 or later +L 800.011 or later =item 6. @@ -1214,19 +1613,10 @@ Check you have all the prequisites installed and working. =item 2. -Check the #! line in the script points to where your Perl interpreter is -installed. +Run 'perl Makefile.PL; make instal1' =item 3. -Copy the "explain" script to somewhere on your path. - -=item 4. - -Make sure the "explain" script is executable. - -=item 5. - Make sure you have run the script $ORACLE_HOME/rdbms/admin/utlxplan.sql from a SQL*Plus session. This script creates the PLAN_TABLE that is used by Oracle when explaining query plans. @@ -1235,13 +1625,13 @@ by Oracle when explaining query plans. =head1 HOW TO USE -Type "explain" at the shell prompt. A window will appear with a menu bar and -three frames, labelled "Query Plan", "Query Step Details" and "SQL Editor". At -the bottom of the window is a single button labelled "Explain". A login dialog -will also appear, into which you should enter the database username, password -and database instance name (SID). The parameters you enter are passed to the -DBI->connect() method, so if you have any problems refer to the DBI and -DBD::Oracle documentation. +Type "explain" or "ora_explain" at the shell prompt. A window will appear with +a menu bar and three frames, labelled "Query Plan", "Query Step Details" and +"SQL Editor". At the bottom of the window are three buttons labelled +"Explain", "Clear" and "SQL Cache". A login dialog will also appear, into +which you should enter the database username, password and database instance +name (SID). The parameters you enter are passed to the DBI->connect() method, +so if you have any problems refer to the DBI and DBD::Oracle documentation. Optionally you may supply up to two command-line arguments. If the first argument is of the form username/password@database, explain will use this to @@ -1257,9 +1647,10 @@ Examples: =head2 Explain functionality -The menu bar has one pulldown menu, "File", which allows you to login to Oracle, -Grab the contents of the Oracle SQL cache, Load SLQ from files, Save SQL to -files and to Exit the program. +The menu bar has two pulldown menus, "File" and "Help". "File" allows you to +login to Oracle, Change the current schema, Capture the contents of the Oracle +SQL cache, Load SQL from files, Save SQL to files and to Exit the program. +"Help" allows you to view release information and read this documentation. The "SQL Editor" frame allows the editing of a SQL statement. This should be just a single statement - multiple statements are not allowed. Refer to the @@ -1274,7 +1665,8 @@ boxes on the plan tree. The tree is drawn so that the "innermost" or "first" query steps are indented most deeply. The connecting lines show the "parent-child" relationships between the query steps. For a comprehensive explanation of the meaning of query plans you should refer to the relevant -Oracle documentation. +Oracle documentation. The "Clear" button will empty the editor & query plan +tree panes. Single-clicking on a plan step in the Query Plan pane will display more detailed information on that query step in the Query Step Details frame. This @@ -1287,37 +1679,68 @@ Double-clicking on a plan step that refers to either a table or an index will pop up a dialog box showing the definition of the table or index in a format similar to that of the SQL*Plus 'desc' command. +The dialog that appears has a button labelled 'Index'. Clicking on this will +expand the table dialog to show all the indexes defined on the table. Each +column represents an index, and the figures define the order that the table +columns appears in the index. To find out the name of an index, position the +mouse over the index column. A single click will display the definition of the +index in a seperate dialog. + Right-clicking on a plan step that refers to a table will pop up a menu showing a list of the indexes available for the table. Selecting an index will display its definition in a dialog box. -=head2 Grab functionality +=head2 Capture SQL Cache functionality -The explain window has an option on the "File" menu labelled "Grab SQL ...". -Selecting this will popup a new top-level window containing a menu bar and -three frames, labelled "SQL Cache", "SQL Statement Statistics" and "SQL -Selection Criterea". At the bottom of the window is a single button labelled -"Grab". +The explain window has an option on the "File" menu labelled "SQL Cache ...", +as well as a button with the same function. Selecting this will popup a new +top-level window containing a menu bar and three frames, labelled "SQL Cache", +"SQL Statement Statistics" and "SQL Selection Criterea". At the bottom of the +window are three buttons labelled "Capture SQL", "Explain" and "Close". -The menu bar has one pulldown menu, "File", which allows you to Save the -contents of the SQL Cache frame and Close the Grab window. +The menu bar has two pulldown menus "File" and "Help". "File" allows you to +Save the contents of the SQL Cache pane to a file, copy the selected SQL +statement to the Explain window and Close the Grab window. The "SQL Cache" frame shows the statements currently in the Oracle SQL cache. -Text may be saved by using the "File" pulldown menu. +As you move the cursor over this window, each SQL statement will be highlighted +with an outline box. Single-clicking on a statement in the SQL Cache pane will +highlight the stamement in green and display more detailed information on that +statement in the SQL Statement Statistics frame. + +If you want to save the entire contents of the SQL Cache pane, you can do this +from the "File" menu. The "SQL Selection Criterea" frame allows you to specify which SQL statements you are interested in, and how you want them sorted. The pattern used to select statements is a normal perl regexp. Once you have defined the selection -criterea, clicking the "Grab" button will read all the matching statements from -the SQL cache and display them in the top frame. - -Single-clicking on a statement in the SQL Cache pane will display more -detailed information on that statement in the Sql Statement Statistics frame, -including the number of times the statement has been executed and the numbers -of rows processed by the statement. - -Double-clicking on a statement will copy it into the SQL editor in the Explain -window, so that the query plan for the statement can be examined. +criterea, clicking the "Capture SQL" button will read all the matching +statements from the SQL cache and display them in the top frame. + +Double-clicking on a statement in the "SQL Cache" pane, selecting "Explain" +from the "File" menu or clicking the "Explain" button will copy the currently +highlighted statement in the "SQL Cache" pane to the SQL editor in the Explain +window, so that the query plan for the statement can be examined. Note also +that the current schema will be changed to that of the user who first executed +the captured statement. + +=head1 SEE ALSO + +This tool assumes that you already know how to interpret Oracle query plans. +If need an explanation of the information displayed by this tool, you should +refer to the appropriate Oracle documentation. Information can be found in the +"Concepts" and "Oracle Tuning" manuals - look for "Query plan" and "Explain +plan". Two other useful sources of information are: + + Oracle Performance Tuning, 2nd ed. + Mark Gurry and Peter Corrigan + O'Reilly & Associates, Inc. + ISBN 1-56592-237-9 + + Advanced Oracle Tuning and Administration + Eyal Aronoff, Kevin Loney and Noorali Sonawalla + Oracle Press (Osborne) + ISBN 0-07-882241-6 =head1 SUPPORT @@ -1325,7 +1748,7 @@ Support questions and suggestions can be directed to Alan.Burlison@uk.sun.com =head1 COPYRIGHT AND DISCLAIMER -Copyright (c) 1998 Alan Burlison +Copyright (c) 1999 Alan Burlison You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file, with the diff --git a/t/general.t b/t/general.t index ee6eb855..455d4ac7 100644 --- a/t/general.t +++ b/t/general.t @@ -5,7 +5,8 @@ sub ok ($$;$) { ++$t; die "sequence error, expected $n but actually $t" if $n and $n != $t; - ($ok) ? print "ok $t\n" : print "not ok $t\n"; + ($ok) ? print "ok $t\n" + : print "# failed test $t at line ".(caller)[2]."\nnot ok $t\n"; if (!$ok && $warn) { $warn = $DBI::errstr || "(DBI::errstr undefined)" if $warn eq '1'; warn "$warn\n"; @@ -16,7 +17,7 @@ use DBI; $| = 1; my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect('', $dbuser, '', 'Oracle'); +my $dbh = DBI->connect('dbi:Oracle:', $dbuser, ''); unless($dbh) { warn "Unable to connect to Oracle ($DBI::errstr)\nTests skiped.\n"; @@ -26,25 +27,43 @@ unless($dbh) { print "1..$tests\n"; -my($sth, $p1, $p2); +my($sth, $p1, $p2, $tmp); -$sth = $dbh->prepare("select * from user_tables"); +$sth = $dbh->prepare(q{ + /* also test preparse doesn't get confused by ? :1 */ + select * from user_tables -- ? :1 +}); +ok(0, $sth->execute); ok(0, $sth->{NUM_OF_FIELDS}); eval { $p1=$sth->{NUM_OFFIELDS_typo} }; ok(0, $@ =~ /attribute/); +ok(0, $sth->{Active}); +ok(0, $sth->finish); +ok(0, !$sth->{Active}); + +$sth = $dbh->prepare("select * from user_tables"); +ok(0, $sth->execute); +ok(0, $sth->{Active}); +1 while ($sth->fetch); # fetch through to end +ok(0, !$sth->{Active}); - # To do - # test NULLs at first bind - # NULLs later binds. - # returning NULLs - # multiple params, mixed types and in only vs inout +ok(0, $tmp = $dbh->selectall_arrayref(q{ + select 1 * power(10,-130) "smallest?", + 9.9999999999 * power(10,125) "biggest?" + from dual +})); +my @tmp = @{$tmp->[0]}; +#warn "@tmp"; $tmp[0]+=0; $tmp[1]+=0; warn "@tmp"; +ok(0, $tmp[0] <= 1e-130, $tmp[0]); +ok(0, $tmp[1] >= 9.99e+125, $tmp[1]); ok(0, $dbh->ping); $dbh->disconnect; +$dbh->{PrintError} = 0; ok(0, !$dbh->ping); exit 0; -BEGIN { $tests = 4 } +BEGIN { $tests = 14 } # end. __END__ diff --git a/t/plsql.t b/t/plsql.t index 1f62b356..78699fc2 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -38,7 +38,7 @@ if ($dbh->err && ($dbh->err==900 || $dbh->err==6553 || $dbh->err==600)) { print "1..$tests\n"; -my($csr, $p1, $p2); +my($csr, $p1, $p2, $tmp); #DBI->trace(4,"trace.log"); @@ -149,6 +149,24 @@ ok(0, $p1 eq 'null!'); $csr->finish; +ok(0, $csr = $dbh->prepare(q{ + begin + :out := nvl(upper(:in), 'null'); + end; +}), 1); +#$csr->trace(3); +my $out; +ok(0, $csr->bind_param_inout(':out', \$out, 1000), 1); + +ok(0, $csr->bind_param(':in', "foo"), 1); +ok(0, $csr->execute, 1); +ok(0, $out eq "FOO"); + +ok(0, $csr->bind_param(':in', ""), 1); +ok(0, $csr->execute, 1); +ok(0, $out eq "null"); + + # --- test out buffer being too small ok(0, $csr = $dbh->prepare(q{ begin @@ -158,10 +176,12 @@ ok(0, $csr = $dbh->prepare(q{ #$csr->trace(3); undef $p1; # force buffer to be freed ok(0, $csr->bind_param_inout(':arg', \$p1, 20), 1); -# Fails with: +# Execute fails with: # ORA-06502: PL/SQL: numeric or value error # ORA-06512: at line 3 (DBD ERROR: OCIStmtExecute) -ok(0, !defined $csr->execute, 1); +$tmp = $csr->execute; +#$tmp = undef if DBD::Oracle::ORA_OCI()==8; # because BindByName given huge max len +ok(0, !defined $tmp, 1); # rebind with more space - and it should work ok(0, $csr->bind_param_inout(':arg', \$p1, 200), 1); ok(0, $csr->execute, 1); @@ -239,7 +259,7 @@ $dbh->disconnect; ok(0, !$dbh->ping); exit 0; -BEGIN { $tests = 49 } +BEGIN { $tests = 57 } # end. __END__ From d55941e5f311c9c4bc1a21f01b06a9287bd65cc5 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Fri, 9 Apr 1999 09:18:57 -0500 Subject: [PATCH 041/637] import DBD-Oracle 0.61 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 0.61 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-0.61.tar.gz --- Changes | 7 ++++- Makefile.PL | 91 ++++++++++++++++++++++++++++++++++------------------- Oracle.pm | 20 +++++++----- README | 15 +++------ Todo | 2 ++ dbdimp.c | 17 +++++----- oci8.c | 10 +++++- t/general.t | 2 ++ t/plsql.t | 2 +- 9 files changed, 105 insertions(+), 61 deletions(-) diff --git a/Changes b/Changes index 5bcc6c97..e53d6f35 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,9 @@ +Changes in DBD::Oracle 0.61, 26th March 1999 + + Fixed execute() always returning 0 rows! (with OCI 7). + Fixed $sth->bind_param(..., SQL_CHAR); + Assorted minor Makefile.PL improvements. + Added ora_check_sql attribute to prepare() for OCI8. Changes in DBD::Oracle 0.60, 10th March 1999 @@ -17,7 +23,6 @@ Changes in DBD::Oracle 0.60, 10th March 1999 Enabled OCI_CRED_EXT login thanks to Alan Burlison & Jeremy Brinkley. Modified hints/svr4.pl - SVR4 users please test. Updated Alan Burlison's ora_explain Tk tool to version 1.0. - Documented dbms_msgpipe_get and dbms_msgpipe_ack methods. Changes in DBD::Oracle 0.59 (Oraperl 1.37), 27th December 1998 diff --git a/Makefile.PL b/Makefile.PL index 56621f85..d21d20c2 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.73 1999/03/10 20:42:24 timbo Exp $ +# $Id: Makefile.PL,v 1.75 1999/04/09 14:07:35 timbo Exp $ BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -59,6 +59,8 @@ if ($ExtUtils::MakeMaker::VERSION >= 5.43) { $opts{LINKTYPE} = 'static' if $Config{dlsrc} =~ /dl_none/; my(@MK, %MK, $MK, %MK_expanding); # parsed macros from Oracle's makefiles +my %mk_target_deps; +my %mk_target_rules; # Options (rarely needed) $::opt_m = 0; # path to proc.mk or oracle.mk file to read @@ -290,9 +292,11 @@ if ($os eq 'hpux') { } if ($os eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { - print "Warning: You may need to rebuild perl using the xlc_r compiler.\a\n"; + print "\n\n"; + print "Warning: You will probably need to rebuild perl using the xlc_r compiler.\a\n"; print " You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV\n"; - sleep 4; + print " Also see the README about the -p option\n"; + sleep 6; } $opts{DEFINE} .= ' -Wall -Wno-comment' if $Config{cc} eq 'gcc'; @@ -326,17 +330,22 @@ print "\n"; print "System: perl$] @Config{qw(myuname)}\n"; print "Compiler: @Config{qw(cc optimize ccflags)}\n"; print "Linker: ". (find_bin('ld')||"not found") ."\n" unless $os eq 'VMS'; -print "Oracle makefiles would have used these values but we override them:\n" +print "Oracle makefiles would have used these definitions but we override them:\n" if $MK{CFLAGS} || $MK{LDFLAGS} || $MK{LDSTRING}; -print " CC: $MK{CC}\n" if $MK{CC}; -print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; -print " [".mkvar('CFLAGS',0,1,0). "]\n" if $MK{CFLAGS}; -print " CLIBS: $MK{CLIBS}\n" if $MK{CLIBS}; -print " [".mkvar('CLIBS',0,1,0). "]\n" if $MK{CLIBS}; -print " LDFLAGS: $MK{LDFLAGS}\n" if $MK{LDFLAGS}; -print " [".mkvar('LDFLAGS',0,1,0). "]\n" if $MK{LDFLAGS}; -print " LDSTRING: $MK{LDSTRING}\n" if $MK{LDSTRING}; -print " [".mkvar('LDSTRING',0,1,0)."]\n" if $MK{LDSTRING}; +print " CC: $MK{CC}\n\n" if $MK{CC}; +print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; +print " [".mkvar('CFLAGS',0,1,0). "]\n\n" if $MK{CFLAGS}; +print " CLIBS: $MK{CLIBS}\n" if $MK{CLIBS}; +print " [".mkvar('CLIBS',0,1,0). "]\n\n" if $MK{CLIBS}; +if ($mk_target_rules{build}) { + my $rules = join "\n", '', @{ $mk_target_rules{build} }; +print " build: $rules\n"; +print " [".expand_mkvars($rules,0,1,0). "]\n\n"; +} +print " LDFLAGS: $MK{LDFLAGS}\n" if $MK{LDFLAGS}; +print " [".mkvar('LDFLAGS',0,1,0). "]\n\n" if $MK{LDFLAGS}; +print " LDSTRING: $MK{LDSTRING}\n" if $MK{LDSTRING}; +print " [".mkvar('LDSTRING',0,1,0)."]\n\n" if $MK{LDSTRING}; print "\nLinking with $linkwith_msg\n" if $linkwith_msg; print "\n"; @@ -485,12 +494,12 @@ sub fetch_oci_macros { ); my %edit; @edit{@edit} = ('$_ = ""') x @edit; - $edit{ORA_NLS} = $edit{ORA_NLS33} = q{ + $edit{ORA_NLS} = $edit{ORA_NLS33} = $edit{ORA_NLS32} = q{ print "Deleting $_\n", " because it is not already set in the environment\n", " and it can cause ORA-01019 errors.\n"; $_ = ''; - } unless $ENV{ORA_NLS} || $ENV{ORA_NLS33}; + } unless $ENV{ORA_NLS} || $ENV{ORA_NLS33} || $ENV{ORA_NLS32}; $edit{COMPOBJS} = q{ # Firstly a Solaris specific edit: @@ -526,8 +535,15 @@ sub fetch_oci_macros { s/\.(\$\(LIB_EXT\))/$1/g; } - next if m!^[-\w/+.\$()]+\s*:+[^=]*!; # skip targets - next if m!^\t!; # skip target build rules + if (m!^([-\w/+.\$()]+)\s*:+\s*([^=]*)!) { # skip targets + my $tgt = $1; + $mk_target_deps{$tgt} = $2 || ''; + push @{ $mk_target_rules{$tgt} ||= [] }, shift @lines + while @lines && $lines[0] =~ m!^\t! && chomp $lines[0]; + #print "target $tgt => $mk_target_deps{$tgt} => @{$mk_target_rules{$tgt}}\n"; + next; + } + next if m!^\t!; # skip target build rules next if m/^\s*\.SUFFIXES/; unless($MK{mkver}) { # still want to get version number @@ -539,18 +555,23 @@ sub fetch_oci_macros { # We always store values into %MK before checking %edit # %edit can edit this in addition to $_ if needed. my $name; - $MK{$1}= $' if m/^\s*(\w+)\s*=\s*/; - $name = $1; - - $MK{$1} =~ s/^([^#]*)#.*/$1/ if $1 && $MK{$1}; # remove comments - - if ($name and exists $edit{$name}) { - my $pre = $_; - eval $edit{$name}; # execute code to edit $_ - print "Edit $name ($edit{$name}) failed: $@\n" if $@; - if ($_ ne $pre and $::opt_v) { - $_ ? print "Edited $name definition\n from: $pre\n to: $_\n" - : print "Deleted $name definition: $pre\n"; + if (m/^\s*(\w+)\s*=\s*/) { + $name = $1; + if ($MK{$name} && $MK{$name} ne $') { + print "$name macro redefined by Oracle\n from $MK{$name}\n to $'\n" + if $::opt_v; + } + $MK{$name} = $'; + $MK{$name} =~ s/^([^#]*)#.*/$1/; # remove comments + + if (exists $edit{$name}) { + my $pre = $_; + eval $edit{$name}; # execute code to edit $_ + print "Edit $name ($edit{$name}) failed: $@\n" if $@; + if ($_ ne $pre and $::opt_v) { + $_ ? print "Edited $name definition\n from: $pre\n to: $_\n" + : print "Deleted $name definition: $pre\n"; + } } } @@ -648,23 +669,27 @@ sub read_inc_file { } +my %expand_shellescape; sub expand_shellescape { my($orig, $level) = @_; my $cmd = $orig; my $debug = $::opt_d || 1; - print "Evaluating `$orig`\n" if $debug; + print "Evaluating `$orig`\n" + if $debug && !$expand_shellescape{$orig}; # ensure we have no $(...) vars left - strip out undefined ones: $cmd =~ s/\$\((\w+)\)/mkvar("$1", 1, 0, $level+1)/ge; print " expanded `$cmd`\n" if $debug and $cmd ne $orig; my $result = `$cmd`; chop $result; - print " returned '$result'\n" if $debug; + print " returned '$result'\n" + if $debug && !$expand_shellescape{$orig}; + $expand_shellescape{$orig} = $result; $result; } sub expand_mkvars { my($string, $strip, $backtick, $level) = @_; - $level ||= 1; + $level ||= 1; local($_) = $string; print "$level Expanding $_\n" if $::opt_d; # handle whizzo AIX make feature used by Oracle @@ -677,7 +702,7 @@ sub expand_mkvars { /xge; # can recurse s/`(.*?[^\\])`/expand_shellescape("$1", $level+1)/esg if $backtick; # can recurse s/\s*\\\n\s*/ /g; # merge continuations - s/\s+/ /g; # shrink whitespace + s/\s+/ /g; # shrink whitespace print "$level Expanded $string\n to $_\n\n" if $::opt_d and $_ ne $string; $_; } diff --git a/Oracle.pm b/Oracle.pm index 31722326..5306f7b6 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.66 1999/03/10 20:42:24 timbo Exp $ +# $Id: Oracle.pm,v 1.68 1999/04/09 14:07:35 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce # @@ -10,7 +10,7 @@ require 5.002; -$DBD::Oracle::VERSION = '0.60'; +$DBD::Oracle::VERSION = '0.61'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -31,7 +31,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.66 $, 10); + my $Revision = substr(q$Revision: 1.68 $, 10); require_version DBI 1.02; @@ -622,12 +622,11 @@ Thanks to Mark Dedlow for this information. If 8-bit text is returned as '?' characters or can't be inserted make sure the following environment vaiables are set correctly: - NLS_LANG, ORA_NLS, ORA_NLS32 + NLS_LANG, ORA_NLS, ORA_NLS32, ORA_NLS33 Thanks to Robin Langdon for this information. Example: $ENV{NLS_LANG} = "american_america.we8iso8859p1"; - $ENV{ORA_NLS} = "/home/oracle/ocommon/nls/admin/data"; - $ENV{ORA_NLS32} = "/home/oracle/ocommon/nls/admin/data"; + $ENV{ORA_NLS} = "$ENV{ORACLE_HOME}/ocommon/nls/admin/data"; Also From: Yngvi Thor Sigurjonsson If you are using 8-bit characters and "export" for backups make sure @@ -840,7 +839,10 @@ information about the results (such as $sth->{NAME}). This reduces communication with the server and increases performance. When fetching LOBs, they are treated just like LONGs and are subject to -$sth->{LongReadLen} and $sth->{LongTruncOk}. +$sth->{LongReadLen} and $sth->{LongTruncOk}. Note that with OCI 7 +DBD::Oracle pre-allocates the whole amount (LongReadLen) before +constructing the returned column. With OCI 8 it grows the buffer to +the amount needed for the largest LOB to be fetched so far. When inserting or updating LOBs some *major* magic has to be performed behind the scenes to make it transparent. Basically the driver has to @@ -886,13 +888,15 @@ To join the oracle-on-linux mailing list, see: http://www.eGroups.com/list/oracle-on-linux http://www.wmd.de/wmd/staff/pauck/misc/oracle_on_linux.html mailto:oracle-on-linux-subscribe@egroups.com - + ftp://oracle-ftp.oracle.com/server/patch_sets/LINUX =head1 Commercial Oracle Tools Assorted tools and references for general information. No recommendation implied. +ora_explain supplied and installed with DBD::Oracle. + PL/Vision from RevealNet and Steven Feuerstein. Platinum Technology: http://www.platinum.com/products/oracle.htm diff --git a/README b/README index 243a73a3..b9fa3ff3 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ DBD::Oracle -- an Oracle 7 and Oracle 8 interface for Perl 5. - Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce, England. + Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce, England. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file, @@ -22,11 +22,6 @@ WARNING: build DBD::Oracle for Oracle 8 to use the Oracle 7 OCI by doing: perl Makefile.PL -8 -| NOTE: -| The only currently supported interface is via Oraperl.pm, the | -| oraperl emulation layer. This is fairly complete and stable. | -| Execute "perldoc Oraperl" after installing for full information. | - *** QUICK START GUIDE: @@ -58,15 +53,15 @@ WARNING: perl Makefile.PL # use a perl that's in your PATH make -If you have problems see the 'IF YOU HAVE PROBLEMS' section below. -If it's builds without error you can then run the tests. For the -main test to work it must be able to connect to an Oracle database. - Don't worry about most warnings, specifically "end-of-loop code not reached", "ANSI C forbids braced-groups within expressions", "cast increases required alignment of target type" and "passing arg 2 of `oerhms' with different width due to prototype". +If you have problems see the 'IF YOU HAVE PROBLEMS' section below. +If it's builds without error you can then run the tests. For the +main test to work it must be able to connect to an Oracle database. + You will need to set either the TWO_TASK or ORACLE_SID environment variables to the correct values for your database. Consult Oracle documentation for more details. Test your setting by connecting to diff --git a/Todo b/Todo index 5861fa6b..58ca3f66 100644 --- a/Todo +++ b/Todo @@ -1,3 +1,5 @@ +wanr when oracle .mk files redefine a macro with a different value. + PRECISION for oci7 on VARCHAR etc Detect "Error while trying to retrieve text for error ORA-XXXX" diff --git a/dbdimp.c b/dbdimp.c index 28ce4271..301a1a7c 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.48 1999/03/10 20:42:24 timbo Exp $ + $Id: dbdimp.c,v 1.49 1999/04/08 11:36:36 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -29,7 +29,7 @@ static int set_sigint_handler = 0; static int ora2sql_type _((int oratype)); -void ora_free_phs_contents(phs_t *phs); +void ora_free_phs_contents _((phs_t *phs)); void dbd_init(dbistate) @@ -671,7 +671,7 @@ ora_sql_type(imp_sth, name, sql_type) return 1; /* Oracle VARCHAR2 */ case SQL_CHAR: - return 5; /* Oracle CHAR */ + return 96; /* Oracle CHAR */ case SQL_BINARY: case SQL_VARBINARY: @@ -772,7 +772,8 @@ dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) phs->alen = value_len + phs->alen_incnull; *alen_ptr_ptr = &phs->alen; if (((IV)phs->alen) > phs->maxlen && phs->indp != -1) - croak("panic: dbd_rebind_ph alen %ld > maxlen %ld", phs->alen,phs->maxlen); + croak("panic: dbd_rebind_ph alen %ld > maxlen %ld (incnul %d)", + phs->alen,phs->maxlen, phs->alen_incnull); } else { phs->alen = 0; @@ -1166,7 +1167,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count return -2; } } - row_count = (imp_sth->cda) ? 0 : imp_sth->cda->rpc; + row_count = imp_sth->cda->rpc; if (debug >= 2) fprintf(DBILOGFP, @@ -1357,7 +1358,8 @@ dbd_st_finish(sth, imp_sth) void -ora_free_fbh_contents(imp_fbh_t *fbh) +ora_free_fbh_contents(fbh) + imp_fbh_t *fbh; { if (fbh->fb_ary) fb_ary_free(fbh->fb_ary); @@ -1369,7 +1371,8 @@ ora_free_fbh_contents(imp_fbh_t *fbh) } void -ora_free_phs_contents(phs_t *phs) +ora_free_phs_contents(phs) + phs_t *phs; { #ifdef OCI_V8_SYNTAX if (phs->desc_h) diff --git a/oci8.c b/oci8.c index b842d666..fd2db689 100644 --- a/oci8.c +++ b/oci8.c @@ -1,5 +1,5 @@ /* - $Id: oci8.c,v 1.11 1999/03/10 20:42:24 timbo Exp $ + $Id: oci8.c,v 1.12 1999/04/08 15:50:37 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -139,6 +139,7 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) { D_imp_dbh_from_sth; ub4 oparse_lng = 1; /* auto v6 or v7 as suits db connected to */ + int ora_check_sql = 0; /* to force a describe to check SQL */ sword status = 0; imp_sth->done_desc = 0; @@ -158,6 +159,7 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) SV **svp; DBD_ATTRIB_GET_IV( attribs, "ora_parse_lang", 14, svp, oparse_lng); DBD_ATTRIB_GET_IV( attribs, "ora_auto_lob", 12, svp, imp_sth->auto_lob); + DBD_ATTRIB_GET_IV( attribs, "ora_check_sql", 15, svp, ora_check_sql); } /* scan statement for '?', ':1' and/or ':foo' style placeholders */ @@ -192,6 +194,12 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) oci_stmt_type_name(imp_sth->stmt_type)); DBIc_IMPSET_on(imp_sth); + + if (ora_check_sql) { + if (!dbd_describe(sth, imp_sth)) + return 0; + } + return 1; } diff --git a/t/general.t b/t/general.t index 455d4ac7..158d5205 100644 --- a/t/general.t +++ b/t/general.t @@ -57,6 +57,8 @@ my @tmp = @{$tmp->[0]}; ok(0, $tmp[0] <= 1e-130, $tmp[0]); ok(0, $tmp[1] >= 9.99e+125, $tmp[1]); +# --- + ok(0, $dbh->ping); $dbh->disconnect; $dbh->{PrintError} = 0; diff --git a/t/plsql.t b/t/plsql.t index 78699fc2..84a8bbae 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -158,7 +158,7 @@ ok(0, $csr = $dbh->prepare(q{ my $out; ok(0, $csr->bind_param_inout(':out', \$out, 1000), 1); -ok(0, $csr->bind_param(':in', "foo"), 1); +ok(0, $csr->bind_param(':in', "foo", DBI::SQL_CHAR()), 1); ok(0, $csr->execute, 1); ok(0, $out eq "FOO"); From f119bbfc7285cbf1a1846e411f7ab70b1af932a9 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Mon, 7 Jun 1999 19:17:03 -0500 Subject: [PATCH 042/637] import DBD-Oracle 1.01 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 1.01 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-1.01.tar.gz --- Changes | 30 ++- MANIFEST | 4 + Makefile.PL | 147 ++++++++++---- Oracle.h | 10 +- Oracle.pm | 188 +++++++++++------- Oracle.xs | 12 ++ Oraperl.pm | 13 +- README | 20 +- README.clients | 14 +- README.longs | 42 ++-- README.wingcc | 22 +++ Todo | 8 +- dbdimp.c | 404 ++++++++++++++++++++++++------------- dbdimp.h | 16 +- hints/svr4.pl | 8 +- oci.def | 368 ++++++++++++++++++++++++++++++++++ oci7.c | 64 +++--- oci8.c | 527 ++++++++++++++++++++++++++++++++++++++++++++----- t/general.t | 13 +- t/long.t | 281 ++++++++++++++++++++++++++ t/plsql.t | 61 ++++-- t/reauth.t | 46 +++++ test.pl | 105 +++++++--- 23 files changed, 1983 insertions(+), 420 deletions(-) create mode 100644 README.wingcc create mode 100644 oci.def create mode 100644 t/long.t create mode 100644 t/reauth.t diff --git a/Changes b/Changes index e53d6f35..390f7ac4 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,32 @@ -Changes in DBD::Oracle 0.61, 26th March 1999 +Changes in DBD::Oracle 1.01 8th June 1999 + + Enhanced diagnostics in t/long.t test suite. + Removed byte with high-bit set from t/long.t test data. + Disable finish if database disconnected or perl is terminating. + Made t/general.t work with other NLS settings. + Added Cygwin support thanks to Alexander Smishlajev. + Fixed 'undeclared identifier' error building with old Oracle's. + +Changes in DBD::Oracle 1.00 4th June 1999 + + Increased default row cache size for improved performance. + Added OCI8 binding of cursors! Sponsored by cp.net. + Added OCI7 binding of cursors! (Was easier after OCI8 work :-) + Added OCI8 blob_read (only for LOBs not LONGs) thanks to Jim Lawson. + Added OCI8 re-authentication thanks to John Tobey. + Added t/long.t test script for LONG/LONG RAW/CLOB/BLOB handling. + Length of fetched LONG RAW string now 2 * LongReadLen for OCI7 & 8. + Fixed LONG fetches being one byte longer than LongReadLen. + Fixed OCI8 non-reporting of LobWrite error. + Fixed OCI8 "LongReadLen too small and/or LongTruncOk not set" hint. + Fixed OCI7 probable cursor leak. + Fixed ping method to be more robust. This should fix + the "morning bug" problem with Apache::DBI. + Fixed t/general.t core dump thanks to Donald Buczek. + Fixed ora_check_sql prepare attribute (for selects). + Fetch errors (non-row level) now turn off the Active attribute. + +Changes in DBD::Oracle 0.61, 9th April 1999 Fixed execute() always returning 0 rows! (with OCI 7). Fixed $sth->bind_param(..., SQL_CHAR); diff --git a/MANIFEST b/MANIFEST index 31ebde4e..e48b6f73 100644 --- a/MANIFEST +++ b/MANIFEST @@ -12,6 +12,8 @@ README.login README.longs README.win32 README.explain +README.wingcc Notes about building with mingw32 and cygwin32 +oci.def OCI.DLL export declarations Todo dbdimp.c dbdimp.h @@ -31,5 +33,7 @@ oraperl.ex/tabinfo.pl oraperl.ph Old oraperl file included for completeness of emulation t/base.t t/general.t +t/long.t t/plsql.t +t/reauth.t test.pl diff --git a/Makefile.PL b/Makefile.PL index d21d20c2..4519fd98 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,8 @@ -# $Id: Makefile.PL,v 1.75 1999/04/09 14:07:35 timbo Exp $ +# $Id: Makefile.PL,v 1.79 1999/06/08 00:15:02 timbo Exp $ + +## +## You should not need to edit this file. +## BEGIN { $^W = 1 } BEGIN { require 5.003 } # 5.003 fixes very important bugs @@ -14,7 +18,7 @@ use strict; # For those not using Dynamic loading this means building a # new static perl in the DBI directory by saying 'make perl' # and then using _that_ perl to make this one. -use DBI 1.02; +use DBI 1.08; use DBI::DBD; # DBD creation tools @@ -43,7 +47,7 @@ my %opts = ( OBJECT => '$(O_FILES)', DEFINE => '', DIR => [], - clean => { FILES=> 'Oracle.xsi' }, + clean => { FILES => 'Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def' }, dist => { DIST_DEFAULT => 'clean distcheck disttest ci tardist', PREOP => '$(MAKE) -f Makefile.old distdir', COMPRESS => 'gzip -v9', SUFFIX => 'gz', @@ -96,7 +100,34 @@ print "\n Configuring DBD::Oracle ...\n my $ORACLE_ENV = ($os eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; my $OH = $ENV{$ORACLE_ENV} || ''; -$OH =~ s:\\:/:g if $os eq 'MSWin32'; + +if (($os eq 'MSWin32') or ($os =~ /cygwin/i)) { + # Win32::TieRegistry is prefered, but it requires Win32API::Registry + # which is not available in mingw or cygwin + eval q{ + require Win32::TieRegistry; + $Win32::TieRegistry::Registry->Delimeter("/"); + my $hkey= $Win32::TieRegistry::Registry->{"LMachine/Software/Oracle/"}; + $OH= $hkey->{ORACLE_HOME}; + } unless $OH; + # older name of Win32::TieRegistry + eval q{ + require Tie::Registry; + $Tie::Registry::Registry->Delimeter("/"); + my $hkey= $Tie::Registry::Registry->{"LMachine/Software/Oracle/"}; + $OH= $hkey->{ORACLE_HOME}; + } unless $OH; + # Win32::Registry imports some symbols into main:: + # this is not commonly wanted thing, so try this as a last resort + eval q{ + require Win32::Registry; + my($reg_key, $hkey); + $main::HKEY_LOCAL_MACHINE->Open('SOFTWARE\\ORACLE', $reg_key); + $reg_key->GetValues( $hkey ); + $OH= $hkey->{ORACLE_HOME}[2]; + } unless $OH; + $OH =~ s:\\:/:g; +}; ($OH = unixify $OH) =~ s:/$:: if $os eq 'VMS'; die "The $ORACLE_ENV environment variable must be set.\n" unless $OH; @@ -143,10 +174,10 @@ my $need_ldlp_env; if ($os eq 'VMS') { my $OCIINCLUDE = vmsify("$OH/rdbms/") ." ". vmsify("$OH/rdbms/demo/oci_demo/"); $opts{INC} = "$OCIINCLUDE $dbi_arch_dir"; - $opts{OBJECT} = 'oracle.obj dbdimp.obj'; + $opts{OBJECT} = 'oracle.obj dbdimp.obj oci7.obj oci8.obj' if $] < 5.005; } -elsif ($os eq 'MSWin32') { +elsif (($os eq 'MSWin32') or ($os =~ /cygwin/i)) { my $oci_compiler_dir = ($Config{cc} eq 'bcc32' ? "BORLAND" : "MSVC"); my $OCIDIR = ""; @@ -157,40 +188,45 @@ elsif ($os eq 'MSWin32') { }, $OH ); print "Using OCI directory '$OCIDIR'\n"; - my %OCILIB; - find( sub { + if ($Config{cc} =~ /gcc/i) { + $opts{LIBS} = [ "-loci" ]; + print "Using liboci.a (did you build it?)\n"; + } else { + my %OCILIB; + find( sub { $File::Find::prune = 1 if -d $_ && $_ !~ /^\./; return unless /^(OCI|ORA).*\.LIB$/i; print "Found $OCIDIR/lib/$oci_compiler_dir/$_ library\n"; $OCILIB{uc($_)} = $_; - }, "$OH/$OCIDIR/lib/$oci_compiler_dir" ) if $OCIDIR; - # sort the version numbered libs into assending order - my @OCILIB = sort grep { /(OCI|ORA)\d\d+\./i } keys %OCILIB; - # prefer the non-versioned library if present - push @OCILIB, "OCI.LIB" if $OCILIB{'OCI.LIB'}; - # opt_8 means DISABLE use of OCI 8 API - push @OCILIB, "OCIW32.LIB" if $OCILIB{'OCIW32.LIB'} && $::opt_8; - my $OCILIB = pop @OCILIB || ''; - $OCILIB =~ s/\.LIB$//i; - - die qq{ - Unable to find required Oracle OCI files for the build. Please check - that you have your OCI installed in your oracle home ($OH) - directory and that it has the following files (and probably more): - + }, "$OH/$OCIDIR/lib/$oci_compiler_dir" ) if $OCIDIR; + # sort the version numbered libs into assending order + my @OCILIB = sort grep { /(OCI|ORA)\d\d+\./i } keys %OCILIB; + # prefer the non-versioned library if present + push @OCILIB, "OCI.LIB" if $OCILIB{'OCI.LIB'}; + # opt_8 means DISABLE use of OCI 8 API + push @OCILIB, "OCIW32.LIB" if $OCILIB{'OCIW32.LIB'} && $::opt_8; + my $OCILIB = pop @OCILIB || ''; + $OCILIB =~ s/\.LIB$//i; + + die qq{ + Unable to find required Oracle OCI files for the build. Please check + that you have your OCI installed in your oracle home ($OH) + directory and that it has the following files (and probably more): + $OH\\$OCIDIR\\include\\oratypes.h $OH\\$OCIDIR\\lib\\$oci_compiler_dir\\$OCILIB.lib - - Please install OCI or send comments back to dbi-users\@fugue.com - if you have an OCI directory other than $OCIDIR. - - } unless (-e "$OH/$OCIDIR/include/oratypes.h" - && -e "$OH/$OCIDIR/lib/$oci_compiler_dir/$OCILIB.lib"); - - print "Using $OCIDIR/lib/$oci_compiler_dir/$OCILIB.lib\n"; + + Please install OCI or send comments back to dbi-users\@fugue.com + if you have an OCI directory other than $OCIDIR. + + } unless (-e "$OH/$OCIDIR/include/oratypes.h" + && -e "$OH/$OCIDIR/lib/$oci_compiler_dir/$OCILIB.lib"); + + print "Using $OCIDIR/lib/$oci_compiler_dir/$OCILIB.lib\n"; + $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/$oci_compiler_dir $OCILIB" ]; + }; my $OCIINCLUDE = "-I$OH/$OCIDIR/include -I$OH/rdbms/demo"; - $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/$oci_compiler_dir $OCILIB" ]; $opts{INC} = "$OCIINCLUDE -I$dbi_arch_dir"; } @@ -251,7 +287,9 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l # delete problematic crt?.o on solaris $linkwith_s = del_crtobj($linkwith_s) if $os eq 'solaris'; $linkwith_s =~ s/-l:lib(\w+)\.sl\b/-l$1/g; # for hp-ux - $linkwith_s .= " -lc" if $Config{archname} eq 'i386-dynixptx'; + # this kind of stuff should be in a ./hints/* file: + $linkwith_s .= " -lc" if $Config{osname} eq 'dynixptx' + or $Config{archname} =~ /-pc-sco3\.2v5/; if ($os eq 'solaris' and $osvers >= 2.3 and $linkwith_s =~ /-lthread/) { print "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; print "Deleting -lthread from link list as a possible workround.\n"; @@ -310,7 +348,7 @@ print "WARNING: Your GNU C compiler is very old. Please upgrade.\n" # Set some private WriteMakefile options if this is 'me' :-) if ($ENV{S_ARCH_SW} && $ENV{LOGNAME} eq 'timbo'){ # a reasonable guess - $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith -pedantic -Wtraditional' + $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith -Wtraditional' . ' -Wbad-function-cast -Wcast-qual' if $Config{cc} eq 'gcc'; $::opt_g = '-g'; $opts{dynamic_lib}->{OTHERLDFLAGS} ||= ''; @@ -339,6 +377,7 @@ print " CLIBS: $MK{CLIBS}\n" if $MK{CLIBS}; print " [".mkvar('CLIBS',0,1,0). "]\n\n" if $MK{CLIBS}; if ($mk_target_rules{build}) { my $rules = join "\n", '', @{ $mk_target_rules{build} }; + $rules = expand_mkvars($rules, 0, 0, 1, 1) if $rules =~ /^\s*\$\(\w+\)\s*$/; print " build: $rules\n"; print " [".expand_mkvars($rules,0,1,0). "]\n\n"; } @@ -688,7 +727,7 @@ sub expand_shellescape { } sub expand_mkvars { - my($string, $strip, $backtick, $level) = @_; + my ($string, $strip, $backtick, $level, $maxlevel) = @_; $level ||= 1; local($_) = $string; print "$level Expanding $_\n" if $::opt_d; @@ -698,7 +737,7 @@ sub expand_mkvars { $MK{$vname} = (mkvar($vname, 1, $backtick, $level+1)) ? $vT : $vF /xge; # can recurse s/\$\( (\w+) \)/ - mkvar("$1", $strip, $backtick, $level+1) + mkvar("$1", $strip, $backtick, $level+1, $maxlevel) /xge; # can recurse s/`(.*?[^\\])`/expand_shellescape("$1", $level+1)/esg if $backtick; # can recurse s/\s*\\\n\s*/ /g; # merge continuations @@ -709,8 +748,8 @@ sub expand_mkvars { sub mkvar { - my($var, $strip, $backtick, $level) = @_; - my $default = $strip ? '' : "\$($var)"; + my($var, $strip, $backtick, $level, $maxlevel) = @_; + my $default = $strip ? '' : "\$($var)"; print "$level Variable: $var\n" if $::opt_d; return '$(LIBHOME)' if $var eq 'LIBHOME' && !$strip; # gets noisy return $ENV{$ORACLE_ENV} if $var eq 'ORACLE_HOME'; @@ -726,7 +765,8 @@ sub mkvar { return "\$($var)"; } local($MK_expanding{$var}) = 1; - return expand_mkvars($val, $strip, $backtick, $level+1); # can recurse + return $val if $maxlevel && $level >= $maxlevel; + return expand_mkvars($val, $strip, $backtick, $level+1, $maxlevel); # can recurse } @@ -886,4 +926,33 @@ $(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt $(INST_ARCHAUTODIR) } + +sub check_oratclsh { + # check for the SUID/SGID bits on ORACLE_HOME/bin/oratclsh + # if set, this allows a user to fork a root shell! + # Get the octal portion of perms that indicates + # SUID and SGID, and warn if either is set + + my $tclfile = "$ENV{$ORACLE_ENV}/bin/oratclsh"; + return unless -e $tclfile; + + my $mode = (stat($tclfile))[2]; + my @bits; + push @bits, "SUID" if $mode & 04000 and $mode & 00111; + push @bits, "SGID" if $mode & 02000 and $mode & 00111; + return unless @bits; + my $bits = join " and ", @bits; + + warn qq{ + WARNING - YOUR ORACLE INSTALLATION HAS A SECURITY PROBLEM. + An Oracle component, probably "Inteligent Agent", has installed + a copy of oratclsh that is $bits. + This warning and the problem it refers to are not related to + the DBI or DBD::Oracle modules in any way. This security check + has been done for your information. Please contact your DBA or + Oracle about the problem. Please do NOT contact myself or dbi-users. +}; + sleep 10; +} + __END__ diff --git a/Oracle.h b/Oracle.h index 00525640..4ef5ed59 100644 --- a/Oracle.h +++ b/Oracle.h @@ -1,5 +1,5 @@ /* - $Id: Oracle.h,v 1.14 1998/12/28 00:04:37 timbo Exp $ + $Id: Oracle.h,v 1.16 1999/06/05 03:23:07 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -47,10 +47,12 @@ int dbd_st_blob_read _((SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, SV *destrv, long destoffset)); int dbd_st_STORE_attrib _((SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv)); SV *dbd_st_FETCH_attrib _((SV *sth, imp_sth_t *imp_sth, SV *keysv)); - -int dbd_describe _((SV *sth, imp_sth_t *imp_sth)); int dbd_bind_ph _((SV *sth, imp_sth_t *imp_sth, - SV *param, SV *value, SV *attribs, int is_inout, IV maxlen)); + SV *param, SV *value, IV sql_type, SV *attribs, int is_inout, IV maxlen)); #endif +int dbd_describe _((SV *sth, imp_sth_t *imp_sth)); +ub4 ora_blob_read_piece _((SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, + long offset, long len, long destoffset)); + /* end of Oracle.h */ diff --git a/Oracle.pm b/Oracle.pm index 5306f7b6..37953cc3 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.68 1999/04/09 14:07:35 timbo Exp $ +# $Id: Oracle.pm,v 1.75 1999/06/08 00:15:02 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce # @@ -8,9 +8,9 @@ # with the exception that it cannot be placed on a CD-ROM or similar media # for commercial distribution without the prior approval of the author. -require 5.002; +require 5.003; -$DBD::Oracle::VERSION = '0.61'; +$DBD::Oracle::VERSION = '1.01'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -25,13 +25,14 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; ora_types => [ qw( ORA_VARCHAR2 ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW ORA_LONGRAW ORA_CHAR ORA_MLSLABEL ORA_NTY - ORA_CLOB ORA_BLOB + ORA_CLOB ORA_BLOB ORA_RSET ) ], ); + @EXPORT_OK = ('ORA_OCI'); Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.68 $, 10); + my $Revision = substr(q$Revision: 1.75 $, 10); require_version DBI 1.02; @@ -44,6 +45,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; sub driver{ return $drh if $drh; my($class, $attr) = @_; + my $oci = DBD::Oracle::ORA_OCI(); $class .= "::dr"; @@ -54,7 +56,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; 'Version' => $VERSION, 'Err' => \$DBD::Oracle::err, 'Errstr' => \$DBD::Oracle::errstr, - 'Attribution' => 'Oracle DBD by Tim Bunce', + 'Attribution' => "DBD::Oracle $VERSION using OCI$oci by Tim Bunce", }); $drh; @@ -89,30 +91,66 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; local *FH; my $d; + if (($^O eq 'MSWin32') or ($^O =~ /cygwin/i)) { + # XXX experimental, will probably change + $drh->log_msg("Fetching ORACLE_SID from Registry.\n") if $debug; + my($hkey, $sid, $home); + eval q{ + require Win32::TieRegistry; + $Win32::TieRegistry::Registry->Delimeter("/"); + $hkey= $Win32::TieRegistry::Registry->{"LMachine/Software/Oracle/"}; + }; + eval q{ + require Tie::Registry; + $Tie::Registry::Registry->Delimeter("/"); + $hkey= $Tie::Registry::Registry->{"LMachine/Software/Oracle/"}; + } unless $hkey; + if ($hkey) { + $sid = $hkey->{ORACLE_SID}; + $home= $hkey->{ORACLE_HOME}; + } else { + eval q{ + my $reg_key; + require Win32::Registry; + $main::HKEY_LOCAL_MACHINE->Open('SOFTWARE\ORACLE', $reg_key); + $reg_key->GetValues( $hkey ); + $sid = $hkey->{ORACLE_SID}[2]; + $home= $hkey->{ORACLE_HOME}[2]; + }; + }; + $home= $ENV{$ORACLE_ENV} unless $home; + $dbnames{$sid} = $home if $sid and $home; + $drh->log_msg("Found $sid \@ $home.\n") if $debug; + $oracle_home =$home unless $oracle_home; + }; + # get list of 'local' database SIDs from oratab foreach $d (qw(/etc /var/opt/oracle), $ENV{TNS_ADMIN}) { next unless defined $d; next unless open(FH, "<$d/oratab"); - $drh->log_msg("Loading $d/oratab\n") if $debug; + $drh->trace_msg("Loading $d/oratab\n") if $debug; my $ot; while (defined($ot = )) { next unless $ot =~ m/^\s*(\w+)\s*:\s*(.*?)\s*:/; $dbnames{$1} = $2; # store ORACLE_HOME value - $drh->log_msg("Found $1 \@ $2.\n") if $debug; + $drh->trace_msg("Found $1 \@ $2.\n") if $debug; } close FH; last; } # get list of 'remote' database connection identifiers - foreach $d ($ENV{TNS_ADMIN}, "$oracle_home/network/admin", '/var/opt/oracle') { - next unless defined $d; - next unless open(FH, "<$d/tnsnames.ora"); - $drh->log_msg("Loading $d/tnsnames.ora\n") if $debug; + foreach $d ( $ENV{TNS_ADMIN}, + "$oracle_home/net80/admin", + "$oracle_home/network/admin", + '/var/opt/oracle' + ) { + next unless $d && open(FH, "<$d/tnsnames.ora"); + $drh->trace_msg("Loading $d/tnsnames.ora\n") if $debug; while () { next unless m/^\s*([-\w\.]+)\s*=/; my $name = $1; - $drh->log_msg("Found $name. ".($dbnames{$name} ? "(oratab entry overridden)" : "")."\n") + $drh->trace_msg("Found $name. ".($dbnames{$name} ? "(oratab entry overridden)" : "")."\n") if $debug; $dbnames{$name} = 0; # exists but false (to distinguish from oratab) } @@ -120,17 +158,6 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; last; } - eval q{ # XXX experimental, will probably change - $drh->log_msg("Fetching ORACLE_SID from Registry.\n") if $debug; - require Tie::Registry; - $Tie::Registry::Registry->Delimeter("/"); - my $hkey= $Tie::Registry::Registry->{"LMachine/Software/Oracle/"}; - my $sid = $hkey->{ORACLE_SID}; - my $home= $hkey->{ORACLE_HOME} || $ENV{ORACLE_HOME}; - $dbnames{$sid} = $home if $sid and $home; - $drh->log_msg("Found $sid \@ $home.\n") if $debug; - } if ($^O eq "MSWin32"); - $dbnames{0} = 1; # mark as loaded (even if empty) } @@ -243,12 +270,16 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; sub ping { my($dbh) = @_; - # we know that Oracle 7 prepare does a describe so this will - # actually talk to the server and is this a valid and cheap test. - my $sth = $dbh->prepare("select SYSDATE from DUAL"); - # But Oracle 8 doesn't talk to server unless we describe the query - return 1 if $sth && $sth->{NUM_OF_FIELDS}; - return 0; + my $ok = 0; + local $SIG{__WARN__} = sub { } if $dbh->{PrintError}; + eval { + # we know that Oracle 7 prepare does a describe so this will + # actually talk to the server and is this a valid and cheap test. + my $sth = $dbh->prepare("select SYSDATE from DUAL /* ping */"); + # But Oracle 8 doesn't talk to server unless we describe the query + $ok = $sth && $sth->{NUM_OF_FIELDS}; + }; + return ($@) ? 0 : $ok; } @@ -258,8 +289,8 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; # The SYS/SYSTEM should probably be a decode that # prepends 'SYSTEM ' to TABLE_TYPE. my $sth = $dbh->prepare("select - NULL TABLE_QUALIFIER, - at.OWNER TABLE_OWNER, + NULL TABLE_CAT, + at.OWNER TABLE_SCHEM, at.TABLE_NAME, tc.TABLE_TYPE, tc.COMMENTS REMARKS @@ -816,12 +847,13 @@ You can find more examples in the t/plsql.t file in the DBD::Oracle source directory. -=head1 Oracle 8 Issues +=head1 Using DBD::Oracle with Oracle 8 - Features and Issues DBD::Oracle version 0.55 onwards can be built to use either the Oracle 7 or Oracle 8 OCI (Oracle Call Interface) API functions. The new Oracle 8 API is used by default and offers several advantages, including support -for LOB types. Here's a quote from the Oracle OCI documentation: +for LOB types and cursor binding. Here's a quote from the Oracle OCI +documentation: The Oracle8 OCI has several enhancements to improve application performance and scalability. Application performance has been improved @@ -829,32 +861,35 @@ for LOB types. Here's a quote from the Oracle OCI documentation: scalability improvements have been facilitated by reducing the amount of state information that needs to be retained on the server side. -(Note that the use of Oracle 8 OCI represents a major amount of -rewriting of the internals of the drivers. There are bound to be some -minor problems.) +=head2 Prepare postponed till execute The DBD::Oracle module will avoid an explicit 'describe' operation prior to the execution of the statement unless the application requests information about the results (such as $sth->{NAME}). This reduces -communication with the server and increases performance. +communication with the server and increases performance. However, it also +means that SQL errors are not detected until C is called +(instead of C as now). + +=head2 Handling LOBs When fetching LOBs, they are treated just like LONGs and are subject to $sth->{LongReadLen} and $sth->{LongTruncOk}. Note that with OCI 7 -DBD::Oracle pre-allocates the whole amount (LongReadLen) before +DBD::Oracle pre-allocates the whole buffer (LongReadLen) before constructing the returned column. With OCI 8 it grows the buffer to the amount needed for the largest LOB to be fetched so far. -When inserting or updating LOBs some *major* magic has to be performed +When inserting or updating LOBs some I magic has to be performed behind the scenes to make it transparent. Basically the driver has to refetch the newly inserted 'LOB Locators' before being able to write to -them. However, it works, and I've made it as fast as possible (just -one extra server-round-trip per insert or update after the first). -For the time being, only single-row LOB updates are supported. +them. However, it works, and I've made it as fast as possible, just +one extra server-round-trip per insert or update after the first. +For the time being, only single-row LOB updates are supported. Also +passing LOBS to PL/SQL blocks doesn't work. To insert or update a large LOB, DBD::Oracle has to know in advance that it is a LOB type. So you need to say: - $sth->bind_param($idx, $value, { ora_type => ORA_CLOB }); + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); The ORA_CLOB and ORA_BLOB constants can be imported using @@ -869,49 +904,70 @@ So in any code you may have now that looks like $sth->bind_param($idx, $value, { ora_type => 8 }); you could change the 8 (LONG type) to ORA_CLOB or ORA_BLOB -(or 112 or 113). +(112 or 113). -One further wrinkle: for inserts and updates of LOBs DBD::Oracle has -to be able to tell which parameters relate to which table field. In -all cases where it can possibly work it out for itself, it does, +One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has +to be able to tell which parameters relate to which table fields. +In all cases where it can possibly work it out for itself, it does, however, if there are multiple LOB fields of the same type in the table then you need to tell it which field each LOB param relates to: $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); +=head2 Binding Cursors -=head1 Oracle on Linix +Cursors can now be returned from PL/SQL blocks. Either from stored +procedures or from direct C statements, as show below: -To join the oracle-on-linux mailing list, see: + use DBI; + use DBD::Oracle qw(:ora_types); + $dbh = DBI->connect(...); + $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute(); + # $sth2 is now a valid DBI statement handle for the cursor + while ( @row = $sth2->fetchrow_array ) { ... } + +The only special requirement is the use of C with an +attribute hash parameter that specifies C as C. +If you don't do that you'll get an error from the C like: +"ORA-06550: line X, column Y: PLS-00306: wrong number or types of +arguments in call to ...". + +=head1 Oracle Related Links + +=head2 Oracle on Linux http://www.datamgmt.com/maillist.html http://www.eGroups.com/list/oracle-on-linux http://www.wmd.de/wmd/staff/pauck/misc/oracle_on_linux.html - mailto:oracle-on-linux-subscribe@egroups.com ftp://oracle-ftp.oracle.com/server/patch_sets/LINUX -=head1 Commercial Oracle Tools +=head2 Free Oracle Tools and Links -Assorted tools and references for general information. -No recommendation implied. + ora_explain supplied and installed with DBD::Oracle. -ora_explain supplied and installed with DBD::Oracle. + http://vonnieda.org/oracletool/ -PL/Vision from RevealNet and Steven Feuerstein. +=head2 Commercial Oracle Tools and Links -Platinum Technology: http://www.platinum.com/products/oracle.htm +Assorted tools and references for general information. +No recommendation implied. -SoftTree Technologies: http://www.SoftTreeTech.com + http://www.platinum.com/products/oracle.htm + http://www.SoftTreeTech.com + http://www.databasegroup.com +Also PL/Vision from RevealNet and Steven Feuerstein, and "Q" from Savant Corporation. -http://www.databasegroup.com - - -=head1 BUGS - -For $sth->{SCALE} and $sth->{PRECISION} Oracle always returns 0. Both -with Oracle 7 and Oracle 8 OCI. Any idea why? =head1 SEE ALSO @@ -923,7 +979,7 @@ DBD::Oracle by Tim Bunce. DBI by Tim Bunce. =head1 COPYRIGHT -The DBD::Oracle module is Copyright (c) 1995,1996,1997,1998 Tim Bunce. England. +The DBD::Oracle module is Copyright (c) 1995,1996,1997,1998,1999 Tim Bunce. England. The DBD::Oracle module is free software; you can redistribute it and/or modify it under the same terms as Perl itself with the exception that it cannot be placed on a CD-ROM or similar media for commercial distribution diff --git a/Oracle.xs b/Oracle.xs index d3980afd..0e7af5b3 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -20,6 +20,7 @@ constant() ORA_NTY = 108 ORA_CLOB = 112 ORA_BLOB = 113 + ORA_RSET = 116 ORA_OCI = 0 CODE: if (!ix) { @@ -84,3 +85,14 @@ ora_fetch(sth) fprintf(DBILOGFP, " !! ERROR: %s %s", neatsvpv(DBIc_ERR(imp_sth),0), neatsvpv(DBIc_ERRSTR(imp_sth),0)); + +MODULE = DBD::Oracle PACKAGE = DBD::Oracle::db + +void +reauthenticate(dbh, uid, pwd) + SV * dbh + char * uid + char * pwd + CODE: + D_imp_dbh(dbh); + ST(0) = ora_db_reauthenticate(dbh, imp_dbh, uid, pwd) ? &sv_yes : &sv_no; diff --git a/Oraperl.pm b/Oraperl.pm index e5b67d50..91c71b63 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -1,6 +1,6 @@ # Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI # -# $Id: Oraperl.pm,v 1.37 1998/06/01 18:34:16 timbo Exp $ +# $Id: Oraperl.pm,v 1.39 1999/06/05 03:23:07 timbo Exp $ # # Copyright (c) 1994,1995 Tim Bunce # @@ -25,7 +25,7 @@ require 5.002; use DBI 0.84; use Exporter; -$VERSION = substr(q$Revision: 1.37 $, 10); +$VERSION = substr(q$Revision: 1.39 $, 10); @ISA = qw(Exporter); @@ -58,7 +58,7 @@ if (!$safe) { $drh = DBI->install_driver('Oracle'); if ($drh) { print "DBD::Oracle driver installed as $drh\n" if $debug; - $drh->debug($debug); + $drh->trace($debug); $drh->{CompatMode} = 1; $drh->{Warn} = 0; } @@ -98,6 +98,7 @@ sub ora_login { } sub ora_logoff { my($dbh) = @_; + return if !$dbh; local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; $dbh->disconnect(); @@ -187,9 +188,9 @@ sub ora_autocommit { sub ora_version { my($sw) = DBI->internal; print "\n"; - print "Oraperl Emulation Interface version $Oraperl::VERSION\n"; - print "Oracle Driver $Oraperl::drh->{Version}\n"; - print "$sw->{Attribution}, version $sw->{Version}\n\n"; + print "Oraperl emulation interface version $Oraperl::VERSION\n"; + print "$Oraperl::drh->{Attribution}\n"; + print "$sw->{Attribution}\n\n"; } diff --git a/README b/README index b9fa3ff3..828d8d41 100644 --- a/README +++ b/README @@ -11,18 +11,6 @@ DBD::Oracle -- an Oracle 7 and Oracle 8 interface for Perl 5. PLEASE READ THE ENTIRE README FILE CAREFULLY ! -WARNING: - - THE DBD::Oracle MODULE IS ALPHA SOFTWARE. It is *only* 'Alpha' - because the interface (api) is not finalised. The Alpha status does - not reflect code quality or stability. - - NEWS: The new enhanced Oracle 8 OCI is now supported by DBD::Oracle - versions above 0.54. If the new code causes you problems you can - build DBD::Oracle for Oracle 8 to use the Oracle 7 OCI by doing: - perl Makefile.PL -8 - - *** QUICK START GUIDE: The DBI requires one or more 'driver' modules to talk to databases. @@ -35,11 +23,11 @@ WARNING: *** *BEFORE* BUILDING, TESTING AND INSTALLING this you will need to: - Build, test and install Perl 5 (at least 5.003, preferably - version 5.004_01 or later). + Build, test and install Perl 5 (at least 5.004, preferably + version 5.004_04 or later). It is very important to TEST it and INSTALL it! - Build, test and install the DBI module (at least DBI 0.86). + Build, test and install the DBI module (at least DBI 1.08). It is very important to TEST it and INSTALL it! Remember to *read* the DBI README file and this one CAREFULLY! @@ -256,7 +244,7 @@ Some platforms on which the DBI and DBD::Oracle modules run: Solaris 1 and 2 Unisys U6000/300 VMS - Windows NT (using Perl5.004) + Windows NT and others (please let me know if your system is not listed). diff --git a/README.clients b/README.clients index 4446fea4..38402033 100644 --- a/README.clients +++ b/README.clients @@ -20,9 +20,9 @@ From: James Cooper > In other words are their some oracle shared objects, etc. I need ? I don't have experience with Solaris, but on IRIX 5.3, I simply installed -SQL*Net (ORACLE_HOME/network/admin/*) and the OCI libraries which are in -ORACLE_HOME/lib. You'll also need the header files from -ORACLE_HOME/sqllib/public/*.h and ORACLE_HOME/rdbms/demo/*.h (you won't +SQL*Net ($ORACLE_HOME/network/admin/*) and the OCI libraries which are in +$ORACLE_HOME/lib. You'll also need the header files from +$ORACLE_HOME/sqllib/public/*.h and $ORACLE_HOME/rdbms/demo/*.h (you won't need them all, but you can get rid of them after DBD::Oracle compiles). [You'll probably need at least ocommon in addition to network. But if you @@ -36,7 +36,7 @@ headers (make sure to keep SQL*Net!) Other than that, getting it working isn't too hard. If you're not familiar with SQL*Net, let me know. I'm no expert, but I know the basics. The main thing is to have a good tnsnames.ora file in -ORACLE_HOME/network/admin +$ORACLE_HOME/network/admin ------------------------------------------------------------------------------- From: Jon Meek @@ -125,9 +125,9 @@ contains no reference to any dynamic Oracle library. > In other words are their some oracle shared objects, etc. I need ? I don't have experience with Solaris, but on IRIX 5.3, I simply installed -SQL*Net (ORACLE_HOME/network/admin/*) and the OCI libraries which are in -ORACLE_HOME/lib. You'll also need the header files from -ORACLE_HOME/sqllib/public/*.h and ORACLE_HOME/rdbms/demo/*.h (you won't +SQL*Net ($ORACLE_HOME/network/admin/*) and the OCI libraries which are in +$ORACLE_HOME/lib. You'll also need the header files from +$ORACLE_HOME/sqllib/public/*.h and $ORACLE_HOME/rdbms/demo/*.h (you won't need them all, but you can get rid of them after DBD::Oracle compiles). So just put that stuff on your client box and install DBI and DBD::Oracle diff --git a/README.longs b/README.longs index 31be075a..623440d5 100644 --- a/README.longs +++ b/README.longs @@ -1,5 +1,7 @@ Some examples related to the use of LONG types. +For complete working code, take a look at the t/long.t file. + ---------------------------------------------------------------------- You must fetch the row before you can fetch the longs associated with @@ -24,27 +26,25 @@ Thanks to Jurgen Botz ---------------------------------------------------------------------- Example for reading LONG fields via blob_read: - $ora_trunc = 1; # truncation on initial fetch is ok - my $sql = "SELECT long_field FROM table_name WHERE id = :1"; - my $csr = ora_open($lda, $sql) or die $ora_errstr; - ora_bind($csr, $id) or die $ora_errstr; - # ora_fetch() needs to be called in an array context - my (@data) = ora_fetch($csr); - die $ora_errstr if $ora_errno and $ora_errno != 1406; - my $blob = ''; - my $lump = 4096; # use benchmarks to get best value for you - my $offset = 0; - while (1) - { - my $frag = $csr->blob_read(0, $offset, $lump); - die $ora_errstr if $ora_errno; - last unless defined $frag; - my $ll = length $frag; - last unless $ll; - $blob .= $frag; - $offset += $ll; - } - print $blob; + $dbh->{RaiseError} = 1; + $dbh->{LongTruncOk} = 1; # truncation on initial fetch is ok + $sth = $dbh->prepare("SELECT key, long_field FROM table_name"); + $sth->execute; + while ( ($key) = $sth->fetchrow_array) { + my $offset = 0; + my $lump = 4096; # use benchmarks to get best value for you + my @frags; + while (1) { + my $frag = $sth->blob_read(1, $offset, $lump); + last unless defined $frag; + my $len = length $frag; + last unless $len; + push @frags, $frag; + $offset += $len; + } + my $blob = join "", @frags; + print "$key: $blob\n"; + } With thanks to james.taylor@srs.gov and desilva@ind70.industry.net. diff --git a/README.wingcc b/README.wingcc new file mode 100644 index 00000000..a1a770ab --- /dev/null +++ b/README.wingcc @@ -0,0 +1,22 @@ +19-may-1999 + +added support for mingw32 and cygwin32 environments. + +Makefile.PL should find and make use of OCI include +files, but you have to build an import library for +OCI.DLL and put it somewhere in library search path. +one of the possible ways to do this is issuing command + +dlltool --input-def oci.def --output-lib liboci.a + +in the directory where you unpacked DBD::Oracle distribution +archive. this will create import library for Oracle 8.0.4. + +BUGS: + +- make clean does not make clean enough. (fixed?) + +- liboci.a must be made before running Makefile.PL + otherwise it will not be added to link list. + +- Win32::Registry access was not tested under cygwin. diff --git a/Todo b/Todo index 58ca3f66..4957bf48 100644 --- a/Todo +++ b/Todo @@ -1,4 +1,10 @@ -wanr when oracle .mk files redefine a macro with a different value. +warn when oracle .mk files redefine a macro with a different value. + +warn (trace_msg?) if ORACLE_HOME changes after first connect +relates to Apache::DBI scenario where changing ORACLE_HOME +upsets existing connections. + +fetchall_arrayref in C (start with XS version in DBI for all drivers?) PRECISION for oci7 on VARCHAR etc diff --git a/dbdimp.c b/dbdimp.c index 301a1a7c..0a9a928d 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.49 1999/04/08 11:36:36 timbo Exp $ + $Id: dbdimp.c,v 1.56 1999/06/08 00:15:02 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -117,11 +117,10 @@ oratype_bind_ok(dbtype) /* It's a type we support for placeholders */ case 96: /* CHAR */ case 97: /* CHARZ */ case 106: /* MLSLABEL */ -#ifdef SQLT_CUR - case SQLT_CUR: /* cursor variable */ -#endif - case 112: /* SQLT_CLOB */ - case 113: /* SQLT_BLOB */ + case 102: /* SQLT_CUR OCI 7 cursor variable */ + case 112: /* SQLT_CLOB / long */ + case 113: /* SQLT_BLOB / long */ + case 116: /* SQLT_RSET OCI 8 cursor variable */ return 1; } return 0; @@ -189,16 +188,6 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER); OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX); - /* OCI 8 does not seem to allow uid to be "name/pass" :-( */ - /* so we have to split it up ourselves */ - if (strlen(pwd)==0 && strchr(uid,'/')) { - SV *tmpsv = sv_2mortal(newSVpv(uid,0)); - uid = SvPVX(tmpsv); - pwd = strchr(uid, '/'); - *pwd++ = '\0'; - /* XXX look for '@', e.g. "u/p@d" and "u@d" and maybe "@d" */ - } - ret=OCIServerAttach(imp_dbh->srvhp, imp_dbh->errhp, (text*)dbname, strlen(dbname), 0); if (ret != OCI_SUCCESS) { @@ -213,23 +202,14 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp); OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_SESSION); - if (*uid == '\0' && *pwd == '\0') { - cred_type = OCI_CRED_EXT; - } - else { - OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, - uid, strlen(uid), - (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp); - OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, - (strlen(pwd)) ? pwd : NULL, strlen(pwd), - (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp); - cred_type = OCI_CRED_RDBMS; - } + + cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); ret=OCISessionBegin( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, cred_type, (ub4) OCI_DEFAULT); if (ret != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, ret, "OCISessionBegin"); OCIServerDetach(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT ); + OCIHandleFree(imp_dbh->authp, OCI_HTYPE_SESSION); OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); OCIHandleFree(imp_dbh->svchp, OCI_HTYPE_SVCCTX); @@ -240,11 +220,6 @@ dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) imp_dbh->authp, (ub4) 0, (ub4) OCI_ATTR_SESSION, imp_dbh->errhp); -/* XXX to be removed */ - imp_dbh->lda = &imp_dbh->ldabuf; - OCISvcCtxToLda( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->lda); - OCILdaToSvcCtx(&imp_dbh->svchp, imp_dbh->errhp, imp_dbh->lda); - #else imp_dbh->lda = &imp_dbh->ldabuf; imp_dbh->hda = &imp_dbh->hdabuf[0]; @@ -377,13 +352,8 @@ dbd_db_disconnect(dbh, imp_dbh) { sword s_se = OCISessionEnd( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, OCI_DEFAULT); sword s_sd = OCIServerDetach(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT ); - if (s_se) - oci_error(dbh, imp_dbh->errhp, s_se, "OCISessionEnd"); - if (s_sd) - oci_error(dbh, imp_dbh->errhp, s_sd, "OCIServerDetach"); - OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); - OCIHandleFree(imp_dbh->svchp, OCI_HTYPE_SVCCTX); - OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); + if (s_se) oci_error(dbh, imp_dbh->errhp, s_se, "OCISessionEnd"); + if (s_sd) oci_error(dbh, imp_dbh->errhp, s_sd, "OCIServerDetach"); if (s_se || s_sd) return 0; } @@ -407,7 +377,13 @@ dbd_db_destroy(dbh, imp_dbh) { if (DBIc_ACTIVE(imp_dbh)) dbd_db_disconnect(dbh, imp_dbh); +#ifdef OCI_V8_SYNTAX + OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); + OCIHandleFree(imp_dbh->svchp, OCI_HTYPE_SVCCTX); + OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); +#else /* Nothing in imp_dbh to be freed */ +#endif DBIc_IMPSET_off(imp_dbh); } @@ -628,10 +604,9 @@ calc_cache_rows(num_fields, est_width, cache_rows, has_longs) /* <0 == base cache on target transfer size of -n bytes. */ if (cache_rows == 0) { /* Oracle packets on ethernet have max size of around 1460. */ - /* We'll aim to fill our row cache with slightly less than */ - /* two packets (to err on the safe side and avoid a third */ - /* almost empty packet being generated in some cases). */ - txfr_size = 1460 * 3.6; /* default transfer/cache size */ + /* We'll aim to fill our row cache with around 10 per go. */ + /* Using 10 means any 'runt' packets will have less impact. */ + txfr_size = 10 * 1460; /* default transfer/cache size */ } else { /* user is specifying desired transfer size in bytes */ txfr_size = -cache_rows; @@ -714,7 +689,7 @@ dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) if (dbis->debug >= 2) { char *val = neatsvpv(phs->sv,0); - fprintf(DBILOGFP, " bind %s <== %s (", phs->name, val); + fprintf(DBILOGFP, " bind %s <== %.1000s (", phs->name, val); if (SvOK(phs->sv)) fprintf(DBILOGFP, "size %ld/%ld/%ld, ", (long)SvCUR(phs->sv),(long)SvLEN(phs->sv),phs->maxlen); @@ -785,7 +760,9 @@ dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) if (dbis->debug >= 3) { fprintf(DBILOGFP, " bind %s <== '%.*s' (size %ld/%ld, otype %d, indp %d)\n", - phs->name, (int)phs->alen, (phs->progv) ? phs->progv : "", + phs->name, + (int)(phs->alen>SvIV(DBIS->neatsvpvlen) ? SvIV(DBIS->neatsvpvlen) : phs->alen), + (phs->progv) ? phs->progv : "", (long)phs->alen, (long)phs->maxlen, phs->ftype, phs->indp); } @@ -793,36 +770,137 @@ dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) } -#ifdef SQLT_CUR -static int -dbd_rebind_ph_cursor(sth, imp_sth, phs) - SV *sth; - imp_sth_t *imp_sth; - phs_t *phs; +int +pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) { -#ifndef OCI_V8_SYNTAX - SV *phs_sth = phs->sv; - D_impdata(phs_imp_sth, imp_sth_t, phs_sth); + if (pre_exec) { /* pre-execute - allocate a statement handle */ + dSP; + D_imp_dbh_from_sth; + SV *sth_i; + HV *init_attr = newHV(); + int count; + if (DBIS->debug >= 3) + fprintf(DBILOGFP, " bind %s - allocating new sth...\n", phs->name); +#ifdef OCI_V8_SYNTAX + { + sword status; + if (!phs->desc_h || 1) { /* XXX phs->desc_t != OCI_HTYPE_STMT) { */ + if (phs->desc_h) { + OCIHandleFree(phs->desc_h, phs->desc_t); + phs->desc_h = NULL; + } + phs->desc_t = OCI_HTYPE_STMT; + OCIHandleAlloc_ok(imp_sth->envhp, &phs->desc_h, phs->desc_t); + } + phs->progv = (void*)&phs->desc_h; + phs->maxlen = 0; + status = OCIBindByName(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + (text*)phs->name, strlen(phs->name), + phs->progv, 0, + phs->ftype, 0, /* using &phs->indp triggers ORA-01001 errors! */ + NULL, 0, 0, NULL, OCI_DEFAULT); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_RSET"); + return 0; + } + } +#else + { + Cda_Def *cda; + assert(phs->ftype == 102); /* SQLT_CUR */ + Newz(0, cda, 1, Cda_Def); + if (oopen(cda, imp_dbh->lda, (text*)0, -1, -1, (text*)0, -1)) { + ora_error(sth, cda, cda->rc, "oopen error for cursor"); + Safefree(cda); + return 0; + } + if (obndra(imp_sth->cda, (text *)phs->name, -1, + (ub1*)cda, (sword)-1, /* cast reduces max size */ + (sword)phs->ftype, -1, 0, 0, &phs->arcode, 0, (ub4 *)0, (text *)0, -1, -1) + ) { + D_imp_dbh_from_sth; + ora_error(sth, imp_dbh->lda, imp_sth->cda->rc, "obndra failed for cursor"); + Safefree(cda); + return 0; + } + phs->progv = (void*)cda; + phs->maxlen = -1; + } +#endif + ENTER; + PUSHMARK(SP); + XPUSHs(sv_2mortal(newRV(DBIc_MY_H(imp_dbh)))); + XPUSHs(sv_2mortal(newRV((SV*)init_attr))); + PUTBACK; + count = perl_call_pv("DBI::_new_sth", G_ARRAY); + SPAGAIN; + if (count != 2) + croak("panic: DBI::_new_sth returned %d values instead of 2", count); + sth_i = SvREFCNT_inc(POPs); + sv_setsv(phs->sv, SvREFCNT_inc(POPs)); /* outer handle */ + PUTBACK; + LEAVE; + if (DBIS->debug >= 3) + fprintf(DBILOGFP, " bind %s - allocated %s...\n", + phs->name, neatsvpv(phs->sv, 0)); + + } + else { /* post-execute - setup the statement handle */ + dTHR; + SV * sth_csr = phs->sv; + D_impdata(imp_sth_csr, imp_sth_t, sth_csr); + + if (DBIS->debug >= 3) + fprintf(DBILOGFP, " bind %s - initialising new %s for cursor 0x%lx...\n", + phs->name, neatsvpv(sth_csr,0), (unsigned long)phs->progv); - /* as a short-term hack we use and sacrifice an existing */ - /* statement handle. This will be changed later. */ +#ifdef OCI_V8_SYNTAX + /* copy appropriate handles from parent statement */ + imp_sth_csr->envhp = imp_sth->envhp; + imp_sth_csr->errhp = imp_sth->errhp; + imp_sth_csr->srvhp = imp_sth->srvhp; + imp_sth_csr->svchp = imp_sth->svchp; + + /* assign statement handle from placeholder descriptor */ + imp_sth_csr->stmhp = phs->desc_h; + imp_sth_csr->disable_finish = 1; /* else finish core dumps in kpuccan()! */ + phs->desc_h = NULL; /* tell phs that we own it now */ + + /* force stmt_type since OCIAttrGet(OCI_ATTR_STMT_TYPE) doesn't work! */ + imp_sth_csr->stmt_type = OCI_STMT_SELECT; +#else - /* close cursor if open (the pl/sql code can/will open it?) */ -/* - if (phs_imp_sth->cda) - free_cursor(phs_sth, phs_imp_sth); - phs_imp_sth->cda = &phs_imp_sth->cdabuf; -*/ + imp_sth_csr->cda = (void*)phs->progv; + imp_sth_csr->cda->ft = 4; /* persuade dbd_describe it's a SELECT */ + phs->progv = NULL; /* tell phs that we own it now */ - assert(phs->ftype == SQLT_CUR); - phs->progv = (void*)phs_imp_sth->cda; - phs->maxlen = -1; - warn("Cursor variables not yet supported"); -#else - die("Cursor variables not yet supported"); #endif + + DBIc_IMPSET_on(imp_sth); + + /* set ACTIVE so dbd_describe doesn't do explicit OCI describe */ + DBIc_ACTIVE_on(imp_sth_csr); + if (!dbd_describe(sth_csr, imp_sth_csr)) { + return 0; + } + } return 1; } + + +#ifndef OCI_V8_SYNTAX +static int +dbd_rebind_ph_cursor(sth, imp_sth, phs) + SV *sth; + imp_sth_t *imp_sth; + phs_t *phs; +{ + assert(phs->ftype == 102); + phs->out_prepost_exec = pp_exec_rset; + if (dbis->debug >= 3) + fprintf(DBILOGFP, " bind %s to cursor (at execute)\n", phs->name); + return 2; +} #endif @@ -835,31 +913,39 @@ dbd_rebind_ph(sth, imp_sth, phs) phs_t *phs; { ub2 *alen_ptr = NULL; -#ifdef OCI_V8_SYNTAX - sword status; -#endif + int done = 0; switch (phs->ftype) { -#ifdef SQLT_CUR - case SQLT_CUR: - if (!dbd_rebind_ph_cursor(sth, imp_sth, phs)) - return 0; - break; -#endif #ifdef OCI_V8_SYNTAX case SQLT_CLOB: case SQLT_BLOB: - if (!dbd_rebind_ph_lob(sth, imp_sth, phs)) - return 0; + done = dbd_rebind_ph_lob(sth, imp_sth, phs); + break; + case SQLT_RSET: + done = dbd_rebind_ph_rset(sth, imp_sth, phs); + break; +#else + case 102: /* SQLT_CUR */ + done = dbd_rebind_ph_cursor(sth, imp_sth, phs); break; #endif default: - if (!dbd_rebind_ph_char(sth, imp_sth, phs, &alen_ptr)) - return 0; + done = dbd_rebind_ph_char(sth, imp_sth, phs, &alen_ptr); + } + if (done != 1) { + if (done == 2) { /* the rebind did the OCI bind call itself successfully */ + if (dbis->debug >= 3) + fprintf(DBILOGFP, " bind %s done for ftype %d\n", + phs->name, phs->ftype); + return 1; + } + return 0; /* the rebind failed */ } #ifdef OCI_V8_SYNTAX if (phs->maxlen > phs->maxlen_bound) { + sword status; + int at_exec = (phs->desc_h == NULL); status = OCIBindByName(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, strlen(phs->name), phs->progv, @@ -869,16 +955,19 @@ dbd_rebind_ph(sth, imp_sth, phs) &phs->arcode, 0, /* max elements that can fit in allocated array */ NULL, /* (ptr to) current number of elements in array */ - OCI_DATA_AT_EXEC); + at_exec ? OCI_DATA_AT_EXEC : OCI_DEFAULT + ); if (status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); - return 0; + oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); + return 0; } - status = OCIBindDynamic(phs->bndhp, imp_sth->errhp, - (dvoid *)phs, dbd_phs_in, (dvoid *)phs, dbd_phs_out); - if (status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); - return 0; + if (at_exec) { + status = OCIBindDynamic(phs->bndhp, imp_sth->errhp, + (dvoid *)phs, dbd_phs_in, (dvoid *)phs, dbd_phs_out); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); + return 0; + } } } @@ -949,10 +1038,10 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl fprintf(DBILOGFP, " bind %s <== %s (type %ld", name, neatsvpv(newvalue,0), (long)sql_type); if (is_inout) - fprintf(DBILOGFP, ", inout 0x%lx, maxlen %ld,", + fprintf(DBILOGFP, ", inout 0x%lx, maxlen %ld", (long)newvalue, (long)maxlen); if (attribs) - fprintf(DBILOGFP, ", attribs: %s", SvPV(attribs,na)); + fprintf(DBILOGFP, ", attribs: %s", neatsvpv(attribs,0)); fprintf(DBILOGFP, ")\n"); } @@ -994,9 +1083,17 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl if (sql_type) phs->ftype = ora_sql_type(imp_sth, phs->name, sql_type); -#ifndef OCI_V8_SYNTAX /* treat Oracle8 LOBS as simple LONGs for Oracle7 */ +#ifndef OCI_V8_SYNTAX + /* treat Oracle8 LOBS as simple LONGs for Oracle7 */ if (phs->ftype==112 || phs->ftype==113) phs->ftype = 8; + /* treat Oracle8 SQLT_RSET as SQLT_CUR for Oracle7 */ + if (phs->ftype==116) + phs->ftype = 102; +#else + /* treat Oracle7 SQLT_CUR as SQLT_RSET for Oracle8 */ + if (phs->ftype==102) + phs->ftype = 116; #endif /* some types require the trailing null included in the length. */ @@ -1074,12 +1171,17 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count phs->indp = (SvOK(phs->sv)) ? 0 : -1; /* Some checks for mutated storage since we pointed oracle at it. */ + if (phs->out_prepost_exec) { + if (!phs->out_prepost_exec(sth, imp_sth, phs, 1)) + return -2; /* out_prepost_exec already called ora_error() */ + } + else if (SvTYPE(phs->sv) != phs->sv_type || (SvOK(phs->sv) && !SvPOK(phs->sv)) /* SvROK==!SvPOK so cursor (SQLT_CUR) handle will call dbd_rebind_ph */ /* that suits us for now */ || SvPVX(phs->sv) != phs->progv - || SvCUR(phs->sv) > UB2MAXVAL + || (SvPOK(phs->sv) && SvCUR(phs->sv) > UB2MAXVAL) ) { if (!dbd_rebind_ph(sth, imp_sth, phs)) croak("Can't rebind placeholder %s", phs->name); @@ -1163,7 +1265,13 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count } else { /* NOT a select */ if (oexec(imp_sth->cda)) { - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexec error"); + char *msg = "oexec error"; + switch(imp_sth->cda->rc) { + case 3108: + msg = "perhaps you're using Oracle 8 functionality but this DBD::Oracle was built for Oracle 7"; + break; + } + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, msg); return -2; } } @@ -1182,27 +1290,12 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count while(--i >= 0) { phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); SV *sv = phs->sv; -#ifdef cursor_vars_are_broken - if (SvROK(sv)) { /* XXX assume it's a cursor variable sth */ - D_impdata(phs_imp_sth, imp_sth_t, sv); - if (debug >= 2) - fprintf(DBILOGFP, - " out %s = %s (oracle cursor 0x%lx, indp %d, arcode %d)\n", - phs->name, neatsvpv(sv,0), (long)phs_imp_sth->cda, - phs->indp, phs->arcode); - /* XXX !!! */ - free_cursor(sth, imp_sth); /* oracle's cdemo5.c does an oclose */ - /* reset cache counters */ - phs_imp_sth->in_cache = 0; - phs_imp_sth->next_entry = 0; - phs_imp_sth->eod_errno = 0; - phs_imp_sth->done_desc = 0; - /* describe and allocate storage for results (if any needed) */ - if (!dbd_describe(sv, phs_imp_sth)) - return -2; /* dbd_describe already called ora_error() */ + + if (phs->out_prepost_exec) { + if (!phs->out_prepost_exec(sth, imp_sth, phs, 0)) + return -2; /* out_prepost_exec already called ora_error() */ } else -#endif /* phs->alen has been updated by Oracle to hold the length of the result */ if (phs->indp == 0) { /* is okay */ SvPOK_only(sv); @@ -1252,35 +1345,47 @@ dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset) SV *destrv; long destoffset; { -#ifdef OCI_V8_SYNTAX - croak("blob_read not currently supported with OCI 8"); -#else - ub4 retl; + ub4 retl = 0; SV *bufsv; + imp_fbh_t *fbh = &imp_sth->fbh[field]; bufsv = SvRV(destrv); sv_setpvn(bufsv,"",0); /* ensure it's writable string */ - SvGROW(bufsv, len+destoffset+1); /* SvGROW doesn't do +1 */ + SvGROW(bufsv, destoffset+len+1); /* SvGROW doesn't do +1 */ + +#ifdef OCI_V8_SYNTAX + retl = ora_blob_read_piece(sth, imp_sth, fbh, bufsv, + offset, len, destoffset); + if (!SvOK(bufsv)) /* ora_blob_read_piece recorded error */ + return 0; + +#else + + if (len > 65535) { + warn("Oracle OCI7 doesn't allow blob_read to reliably fetch chunks longer than 65535 bytes"); + len = 65535; + } - /* The +1 on field was a mistake tht's too late to fix :-( */ + /* The +1 on field was a mistake that's too late to fix :-( */ if (oflng(imp_sth->cda, (sword)field+1, ((ub1*)SvPVX(bufsv)) + destoffset, len, - imp_sth->fbh[field].ftype, /* original long type */ + fbh->ftype, /* original long type */ &retl, offset)) { ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oflng error"); /* XXX database may have altered the buffer contents */ return 0; } - /* Sadly, even though retl is a ub4, oracle will cap the */ - /* value of retl at 65535 even if more was returned! */ - /* This is according to the OCI manual for Oracle 7.0. */ - /* Once again Oracle causes us grief. How can we tell what */ - /* length to assign to destrv? We do have a compromise: if */ - /* retl is exactly 65535 we assume that all data was read. */ - SvCUR_set(bufsv, destoffset+((retl == 65535) ? len : retl)); - *SvEND(bufsv) = '\0'; /* consistent with perl sv_setpvn etc */ #endif + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " blob_read field %d+1, ftype %d, offset %ld, len %ld, destoffset %ld, retlen %ld\n", + field, imp_sth->fbh[field].ftype, offset, len, destoffset, retl); + + SvCUR_set(bufsv, destoffset+retl); + + *SvEND(bufsv) = '\0'; /* consistent with perl sv_setpvn etc */ + return 1; } @@ -1319,6 +1424,7 @@ dbd_st_finish(sth, imp_sth) imp_sth_t *imp_sth; { dTHR; + D_imp_dbh_from_sth; if (!DBIc_ACTIVE(imp_sth)) return 1; @@ -1330,10 +1436,17 @@ dbd_st_finish(sth, imp_sth) /* Turn off ACTIVE here regardless of errors below. */ DBIc_ACTIVE_off(imp_sth); + if (dirty) /* don't walk on the wild side */ + return 1; + + if (imp_sth->disable_finish) /* see ref cursors */ + return 1; + + if (!DBIc_ACTIVE(imp_dbh)) /* no longer connected */ + return 1; + #ifdef OCI_V8_SYNTAX { sword status; - /* OCI 8 manual says there's no equiv of OCI7 ocan() */ - /* But elsewhere says a OCIStmtFetch with nrows==0 does that */ status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 0, OCI_FETCH_NEXT, OCI_DEFAULT); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "Finish OCIStmtFetch"); @@ -1377,6 +1490,14 @@ ora_free_phs_contents(phs) #ifdef OCI_V8_SYNTAX if (phs->desc_h) OCIDescriptorFree(phs->desc_h, phs->desc_t); +#else + if (phs->ftype == 102 && phs->progv) { /* SQLT_CUR */ + /* should not normally happen since new child sth takes */ + /* ownership of the cursor and sets phs->progv to NULL. */ + oclose((Cda_Def*)phs->progv); + Safefree(phs->progv); + phs->progv = NULL; + } #endif sv_free(phs->ora_field); sv_free(phs->sv); @@ -1392,18 +1513,12 @@ dbd_st_destroy(sth, imp_sth) int fields; int i; - /* dbd_st_finish has already been called by .xs code if needed. */ - /* Check if an explicit disconnect() or global destruction has */ /* disconnected us from the *database* before attempting to close. */ + if (DBIc_ACTIVE(imp_dbh)) { -#ifdef OCI_V8_SYNTAX - /* nothing to do here ? */ -#else - oclose(imp_sth->cda); - imp_sth->cda = NULL; -#endif - /* fall through anyway to free up our memory */ + /* dbd_st_finish has already been called by .xs code if needed. */ + /* so this should never get called */ } #ifdef OCI_V8_SYNTAX @@ -1415,6 +1530,15 @@ dbd_st_destroy(sth, imp_sth) if (status != OCI_SUCCESS) oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); } +#else + oclose(imp_sth->cda); + if (imp_sth->cda != &imp_sth->cdabuf) { + /* we assume that the cda was allocated for a ref cursor */ + /* bound to a placeholder on a different statement. */ + /* We own the cda buffer now so we need to free it. */ + Safefree(imp_sth->cda); + } + imp_sth->cda = NULL; #endif /* Free off contents of imp_sth */ diff --git a/dbdimp.h b/dbdimp.h index d2642778..2945f416 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.30 1999/03/10 20:42:24 timbo Exp $ + $Id: dbdimp.h,v 1.34 1999/06/08 00:15:02 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -36,6 +36,11 @@ #endif #endif +/* egcs-1.1.2 does not have _int64 */ +#if defined(__MINGW32__) || defined(__CYGWIN32__) +#define _int64 long long +#endif + /* This is slightly backwards because we want to auto-detect OCI8 */ /* and thus the existance of oci.h while still working for Oracle7 */ #include @@ -83,8 +88,6 @@ struct imp_drh_st { struct imp_dbh_st { dbih_dbc_t com; /* MUST be first element in structure */ - Lda_Def ldabuf; - Lda_Def *lda; /* points to ldabuf */ #ifdef OCI_V8_SYNTAX OCIEnv *envhp; /* copy of drh pointer */ OCIError *errhp; @@ -92,6 +95,8 @@ struct imp_dbh_st { OCISvcCtx *svchp; OCISession *authp; #else + Lda_Def ldabuf; + Lda_Def *lda; /* points to ldabuf */ ub1 hdabuf[HDA_SIZE]; ub1 *hda; /* points to hdabuf */ #endif @@ -120,6 +125,7 @@ struct imp_sth_st { Cda_Def *cda; /* normally just points to cdabuf below */ Cda_Def cdabuf; #endif + int disable_finish; /* fetched cursors can core dump in finish */ /* Input Details */ char *statement; /* sql (see sth_scan) */ @@ -217,6 +223,7 @@ struct phs_st { /* scalar placeholder EXPERIMENTAL */ sb2 indp; /* null indicator */ char *progv; + int (*out_prepost_exec)_((SV *, imp_sth_t *, phs_t *, int pre_exec)); SV *ora_field; /* from attribute (for LOB binds) */ int alen_incnull; /* 0 or 1 if alen should include null */ char name[1]; /* struct is malloc'd bigger as needed */ @@ -234,6 +241,7 @@ void ora_free_fbh_contents _((imp_fbh_t *fbh)); int ora_dbtype_is_long _((int dbtype)); int calc_cache_rows _((int num_fields, int est_width, int cache_rows, int has_longs)); fb_ary_t *fb_ary_alloc _((int bufl, int size)); +int ora_db_reauthenticate _((SV *dbh, imp_dbh_t *imp_dbh, char *uid, char *pwd)); #ifdef OCI_V8_SYNTAX @@ -243,6 +251,7 @@ char *oci_status_name _((sword status)); int dbd_rebind_ph_lob _((SV *sth, imp_sth_t *imp_sth, phs_t *phs)); void ora_free_lob_refetch _((SV *sth, imp_sth_t *imp_sth)); int post_execute_lobs _((SV *sth, imp_sth_t *imp_sth, ub4 row_count)); +ub4 ora_parse_uid _((imp_dbh_t *imp_dbh, char **uidp, char **pwdp)); #define OCIAttrGet_stmhp(imp_sth, p, l, a) \ OCIAttrGet(imp_sth->stmhp, OCI_HTYPE_STMT, (dvoid*)(p), (l), (a), imp_sth->errhp) @@ -263,6 +272,7 @@ sb4 dbd_phs_in _((dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, sb4 dbd_phs_out _((dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcodepp)); +int dbd_rebind_ph_rset _((SV *sth, imp_sth_t *imp_sth, phs_t *phs)); #else /* is OCI 7 */ diff --git a/hints/svr4.pl b/hints/svr4.pl index 762275bc..28d9ea91 100644 --- a/hints/svr4.pl +++ b/hints/svr4.pl @@ -3,8 +3,8 @@ $att{LIBS}->[0] ||= ''; # Some SVR4 systems may need to link against -lc to pick up things like -# fpsetmask and ecvt. -my @libs = qw(-lsocket -lnsl -lm -ldl); +# fpsetmask, sys_nerr and ecvt. +my @libs = qw(-lsocket -lnsl -lm -ldl); # general svr4 default # modified by Davide Migliavacca if ($archname eq 'RM400-svr4') { @@ -13,9 +13,9 @@ push @libs, '-lc'; -warn "SVR4 LIBS attribute defaulted to '$att{LIBS}->[0]' for '$archname'"; +warn "$^O LIBS attribute defaulted to '$att{LIBS}->[0]' for '$archname'"; $att{LIBS}->[0] .= " ".join(" ", @libs); # append libs -warn "SVR4 LIBS attribute updated to '$att{LIBS}->[0]'"; +warn "$^O LIBS attribute updated to '$att{LIBS}->[0]'"; __END__ diff --git a/oci.def b/oci.def new file mode 100644 index 00000000..d39ca971 --- /dev/null +++ b/oci.def @@ -0,0 +1,368 @@ +; this file was produced from Oracle 8.0.4 OCI.DLL by pexports program +; written by Anders Norlander +; http://www.acc.umu.se/~anorland/gnu-win32/index.html +; +; to make liboci.a run +; dlltool --input-def oci.def --output-lib liboci.a +; +LIBRARY OCI.dll +EXPORTS +OCIAQDeq +OCIAQEnq +OCIAttrGet +OCIAttrSet +OCIBindArrayOfStruct +OCIBindByName +OCIBindByPos +OCIBindDynamic +OCIBindObject +OCIBreak +OCICacheFlush +OCICacheFlushRefresh +OCICacheFree +OCICacheGetObjects +OCICacheRefresh +OCICacheRegister +OCICacheUnmark +OCICacheUnpin +OCICollAppend +OCICollAssign +OCICollAssignElem +OCICollGetElem +OCICollMax +OCICollSize +OCICollTrim +OCIDateAddDays +OCIDateAddMonths +OCIDateAssign +OCIDateCheck +OCIDateCompare +OCIDateDaysBetween +OCIDateFromText +OCIDateLastDay +OCIDateNextDay +OCIDateSysDate +OCIDateToText +OCIDateZoneToZone +OCIDefineArrayOfStruct +OCIDefineByPos +OCIDefineDynamic +OCIDefineObject +OCIDescribeAny +OCIDescriptorAlloc +OCIDescriptorFree +OCIDurationBegin +OCIDurationEnd +OCIDurationGetParent +OCIEnvInit +OCIErrorGet +OCIHandleAlloc +OCIHandleFree +OCIInitialize +OCIIterCreate +OCIIterDelete +OCIIterGetCurrent +OCIIterInit +OCIIterNext +OCIIterPrev +OCILdaToSvcCtx +OCILobAppend +OCILobAssign +OCILobCharSetForm +OCILobCharSetId +OCILobCopy +OCILobDisableBuffering +OCILobEnableBuffering +OCILobErase +OCILobFileClose +OCILobFileCloseAll +OCILobFileExists +OCILobFileGetName +OCILobFileIsOpen +OCILobFileOpen +OCILobFileSetName +OCILobFlushBuffer +OCILobGetLength +OCILobIsEqual +OCILobLoadFromFile +OCILobLocatorIsInit +OCILobRead +OCILobTrim +OCILobWrite +OCILogoff +OCILogon +OCINumberAbs +OCINumberAdd +OCINumberArcCos +OCINumberArcSin +OCINumberArcTan +OCINumberArcTan2 +OCINumberAssign +OCINumberCeil +OCINumberCmp +OCINumberCos +OCINumberDiv +OCINumberExp +OCINumberFloor +OCINumberFromInt +OCINumberFromReal +OCINumberFromText +OCINumberHypCos +OCINumberHypSin +OCINumberHypTan +OCINumberIntPower +OCINumberIsZero +OCINumberLn +OCINumberLog +OCINumberMod +OCINumberMul +OCINumberNeg +OCINumberPower +OCINumberRound +OCINumberSetZero +OCINumberSin +OCINumberSqrt +OCINumberSub +OCINumberTan +OCINumberToInt +OCINumberToReal +OCINumberToText +OCINumberTrunc +OCIObjectAlwaysLatest +OCIObjectArrayPin +OCIObjectCopy +OCIObjectExists +OCIObjectFlush +OCIObjectFlushRefresh +OCIObjectFree +OCIObjectGetAttr +OCIObjectGetInd +OCIObjectGetObjectRef +OCIObjectGetProperty +OCIObjectGetTypeRef +OCIObjectIsDirtied +OCIObjectIsDirty +OCIObjectIsLoaded +OCIObjectIsLocked +OCIObjectLock +OCIObjectMarkDelete +OCIObjectMarkDeleteByRef +OCIObjectMarkUpdate +OCIObjectNew +OCIObjectNotAlwaysLatest +OCIObjectPin +OCIObjectPinCountReset +OCIObjectPinTable +OCIObjectRefresh +OCIObjectSetAttr +OCIObjectUnmark +OCIObjectUnmarkByRef +OCIObjectUnpin +OCIParamGet +OCIParamSet +OCIPasswordChange +OCIRawAllocSize +OCIRawAssignBytes +OCIRawAssignRaw +OCIRawPtr +OCIRawResize +OCIRawSize +OCIRefAssign +OCIRefClear +OCIRefFromHex +OCIRefHexSize +OCIRefIsEqual +OCIRefIsNull +OCIRefToHex +OCIResultSetToStmt +OCISecurityAbortIdentity +OCISecurityClosePersona +OCISecurityCloseWallet +OCISecurityCreateIdentity +OCISecurityCreatePersona +OCISecurityCreateWallet +OCISecurityDeEnvelope +OCISecurityDecrypt +OCISecurityDestroyWallet +OCISecurityEncrypt +OCISecurityEncryptExpansion +OCISecurityEnvelope +OCISecurityFreeIdentity +OCISecurityGetIdentity +OCISecurityGetProtection +OCISecurityHash +OCISecurityHashExpansion +OCISecurityInitBlock +OCISecurityInitialize +OCISecurityKeyedHash +OCISecurityKeyedHashExpansion +OCISecurityOpenPersona +OCISecurityOpenWallet +OCISecurityPKDecrypt +OCISecurityPKEncryptExpansion +OCISecurityPurgeBlock +OCISecurityRandomBytes +OCISecurityRandomNumber +OCISecurityRemoveIdentity +OCISecurityRemovePersona +OCISecurityReuseBlock +OCISecuritySeedRandom +OCISecuritySetBlock +OCISecuritySetProtection +OCISecuritySign +OCISecuritySignDetExpansion +OCISecuritySignDetached +OCISecuritySignExpansion +OCISecurityStorePersona +OCISecurityStoreTrustedIdentity +OCISecurityTerminate +OCISecurityValidate +OCISecurityVerify +OCISecurityVerifyDetached +OCISecurity_PKEncrypt +OCIServerAttach +OCIServerDetach +OCIServerVersion +OCISessionBegin +OCISessionEnd +OCIStmtBindByName +OCIStmtBindByPos +OCIStmtExecute +OCIStmtFetch +OCIStmtGetBindInfo +OCIStmtGetPieceInfo +OCIStmtPrepare +OCIStmtSetPieceInfo +OCIStringAllocSize +OCIStringAssign +OCIStringAssignText +OCIStringPtr +OCIStringResize +OCIStringSize +OCISvcCtxToLda +OCITableDelete +OCITableExists +OCITableFirst +OCITableLast +OCITableNext +OCITablePrev +OCITableSize +OCITransCommit +OCITransDetach +OCITransForget +OCITransPrepare +OCITransRollback +OCITransStart +OCITypeArrayByName +OCITypeArrayByRef +OCITypeAttrByName +OCITypeAttrNext +OCITypeAttrs +OCITypeByName +OCITypeByRef +OCITypeCollElem +OCITypeCollExtTypeCode +OCITypeCollSize +OCITypeCollTypeCode +OCITypeElemCharSetForm +OCITypeElemCharSetID +OCITypeElemDefaultValue +OCITypeElemExtTypeCode +OCITypeElemFlags +OCITypeElemLength +OCITypeElemName +OCITypeElemNumPrec +OCITypeElemNumScale +OCITypeElemParamMode +OCITypeElemParameterizedType +OCITypeElemType +OCITypeElemTypeCode +OCITypeIterFree +OCITypeIterNew +OCITypeIterSet +OCITypeMethodByName +OCITypeMethodEncap +OCITypeMethodFlags +OCITypeMethodMap +OCITypeMethodName +OCITypeMethodNext +OCITypeMethodOrder +OCITypeMethodOverload +OCITypeMethodParams +OCITypeMethods +OCITypeName +OCITypeParamByName +OCITypeParamByPos +OCITypeParamPos +OCITypeResult +OCITypeSchema +OCITypeTypeCode +OCITypeVTInit +OCITypeVTInsert +OCITypeVTSelect +OCITypeVersion +obindps +obndra +obndrn +obndrv +obreak +ocan +ocibre +ocibrn +ocibrv +ociclo +ocicof +ocicom +ocidefn +ocidfn +ocidsc +ociepacm +ocieperr +ociepgoe +ociepmsg +ocierr +ociexe +ociexn +ocifet +ocilof +ocilon +ociope +ocirlo +ocirol +ocisq3 +oclose +ocof +ocom +ocon +odefin +odefinps +odescr +odessp +odsc +oerhms +oermsg +oexec +oexfet +oexn +ofen +ofetch +oflng +ogetpi +ognfd +olog +ologof +ologon +olon +oname +onbclr +onbset +onbtst +oopen +oopt +oparse +opinit +orlon +orol +ortgcty +osetpi +osql3 diff --git a/oci7.c b/oci7.c index 0b2b7318..07e60d81 100644 --- a/oci7.c +++ b/oci7.c @@ -1,5 +1,5 @@ /* - $Id: oci7.c,v 1.6 1999/03/10 20:42:24 timbo Exp $ + $Id: oci7.c,v 1.10 1999/06/05 03:23:07 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -103,7 +103,7 @@ dbd_describe(h, imp_sth) #define FT_SELECT 4 #endif if (imp_sth->cda->ft != FT_SELECT) { - if (dbis->debug >= 2) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_describe skipped for non-select (sql f%d, lb %ld, csr 0x%lx)\n", imp_sth->cda->ft, (long)long_buflen, (long)imp_sth->cda); @@ -111,7 +111,7 @@ dbd_describe(h, imp_sth) return 1; } - if (dbis->debug >= 2) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_describe (for sql f%d after oci f%d, lb %ld, csr 0x%lx)...\n", imp_sth->cda->ft, imp_sth->cda->fc, (long)long_buflen, (long)imp_sth->cda); @@ -223,6 +223,7 @@ dbd_describe(h, imp_sth) imp_fbh_t *fbh = &imp_sth->fbh[i-1]; fb_ary_t *fb_ary; int dbtype; + int alen_incnull; fbh->imp_sth = imp_sth; fbh->name = (char*)cbuf_ptr; @@ -236,8 +237,7 @@ dbd_describe(h, imp_sth) /* Now define the storage for this field data. */ - if (fbh->dbtype==23 || fbh->dbtype==24) { /* RAW types */ - /* is this the right thing to do? what about longraw? XXX */ + if (fbh->dbtype==23) { /* RAW type */ fbh->dbsize *= 2; fbh->disize *= 2; } @@ -253,10 +253,12 @@ dbd_describe(h, imp_sth) /* This may change in a future release. */ /* Note that ora_dbtype_is_long() returns alternate dbtype to use */ if ( (dbtype = ora_dbtype_is_long(fbh->dbtype)) ) { - fbh->dbsize = long_buflen; - fbh->disize = long_buflen; + long lbl = (fbh->dbtype==24) ? long_buflen * 2 : long_buflen; + fbh->dbsize = lbl; + fbh->disize = lbl; fbh->ftype = dbtype; /* get long in non-var form */ - imp_sth->t_dbsize += long_buflen; + imp_sth->t_dbsize += lbl; + alen_incnull = 0; } else { /* for the time being we fetch everything (except longs) */ @@ -264,12 +266,13 @@ dbd_describe(h, imp_sth) fbh->ftype = 5; /* oraperl used 5 'STRING' */ /* dbsize can be zero for 'select NULL ...' */ imp_sth->t_dbsize += fbh->dbsize; + alen_incnull = 1; } fbh->fb_ary = fb_ary = fb_ary_alloc( - fbh->disize+1, /* +1: STRING null terminator */ - imp_sth->cache_rows - ); + fbh->disize + alen_incnull, /* +1: STRING null terminator */ + imp_sth->cache_rows + ); /* DEFINE output column variable storage */ if (odefin(imp_sth->cda, i, fb_ary->abuf, fb_ary->bufl, @@ -278,12 +281,12 @@ dbd_describe(h, imp_sth) warn("odefin error on %s: %d", fbh->name, imp_sth->cda->rc); } - if (dbis->debug >= 2) + if (DBIS->debug >= 2) dbd_fbh_dump(fbh, i, 0); } imp_sth->est_width = est_width; - if (dbis->debug >= 2) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_describe'd %d columns (Row bytes: %d max, %d est avg. Cache: %d rows)\n", (int)num_fields, imp_sth->t_dbsize, est_width, imp_sth->cache_rows); @@ -303,7 +306,7 @@ dbd_st_fetch(sth, imp_sth) SV * sth; imp_sth_t *imp_sth; { - int debug = dbis->debug; + int debug = DBIS->debug; int num_fields; int ChopBlanks; int err = 0; @@ -323,13 +326,14 @@ dbd_st_fetch(sth, imp_sth) if (imp_sth->eod_errno) { end_of_data: + { dTHR; /* for DBIc_ACTIVE_off */ + DBIc_ACTIVE_off(imp_sth); /* eg finish */ + } if (imp_sth->eod_errno != 1403) { /* was not just end-of-fetch */ ora_error(sth, imp_sth->cda, imp_sth->eod_errno, "cached ofetch error"); } else { /* is simply no more data */ - dTHR; /* for DBIc_ACTIVE_off */ - DBIc_ACTIVE_off(imp_sth); /* eg finish */ sv_setiv(DBIc_ERR(imp_sth), 0); /* ensure errno set to 0 here */ - if (debug >= 2) + if (debug >= 3) fprintf(DBILOGFP, " dbd_st_fetch no-more-data, rc=%d, rpc=%ld\n", imp_sth->cda->rc, imp_sth->cda->rpc); } @@ -407,8 +411,8 @@ dbd_st_fetch(sth, imp_sth) fb_ary->arlen[cache_entry]); if (ora_dbtype_is_long(fbh->dbtype)) { /* double check */ hint = (DBIc_LongReadLen(imp_sth) > 65535) - ? ", LongTruncOk not set and/or LongReadLen too small or > 65535 max" - : ", LongTruncOk not set and/or LongReadLen too small"; + ? ", DBI attribute LongTruncOk not set and/or LongReadLen too small or > 65535 max" + : ", DBI attribute LongTruncOk not set and/or LongReadLen too small"; } } else { @@ -417,8 +421,8 @@ dbd_st_fetch(sth, imp_sth) ++err; /* 'fail' this fetch but continue getting fields */ /* Some should probably be treated as warnings but */ /* for now we just treat them all as errors */ - sprintf(buf,"ofetch error on field %d (of %d), ora_type %d%s", - i+1, num_fields, fbh->dbtype, hint); + sprintf(buf,"ORA-%05d error on field %d of %d, ora_type %d%s", + rc, i+1, num_fields, fbh->dbtype, hint); ora_error(sth, imp_sth->cda, rc, buf); } @@ -453,6 +457,11 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) D_imp_dbh_from_sth; ub4 oparse_lng = 1; /* auto v6 or v7 as suits db connected to */ + if (!DBIc_ACTIVE(imp_dbh)) { + ora_error(sth, NULL, -1, "Database disconnected"); + return 0; + } + imp_sth->done_desc = 0; if (DBIc_COMPAT(imp_sth)) { @@ -502,7 +511,7 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) imp_sth->cda = NULL; return 0; } - if (dbis->debug >= 2) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_st_prepare'd sql f%d\n", imp_sth->cda->ft); /* Describe and allocate storage for results. */ @@ -514,4 +523,15 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) return 1; } +int +ora_db_reauthenticate(dbh, imp_dbh, uid, pwd) + SV *dbh; + imp_dbh_t *imp_dbh; + char * uid; + char * pwd; +{ + ora_error(dbh, NULL, 1, "reauthenticate not possible when using Oracle OCI 7"); + return 0; +} + #endif diff --git a/oci8.c b/oci8.c index fd2db689..9203b632 100644 --- a/oci8.c +++ b/oci8.c @@ -1,5 +1,5 @@ /* - $Id: oci8.c,v 1.12 1999/04/08 15:50:37 timbo Exp $ + $Id: oci8.c,v 1.18 1999/06/05 03:23:07 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -23,6 +23,8 @@ static SV *ora_trunc; static SV *ora_cache; static SV *ora_cache_o; /* for ora_open() cache override */ +extern int pp_exec_rset _((SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec)); + void dbd_init_oci(dbistate_t *dbistate) { @@ -95,9 +97,10 @@ oci_error(SV *h, OCIError *errhp, sword status, char *what) && eg_status != OCI_INVALID_HANDLE && recno < 100 ) { - if (dbis->debug >= 4 || recno>1/*XXX temp*/) - fprintf(DBILOGFP, "OCIErrorGet after %s (err rec %ld = %s): %d, %ld: %s\n", - what, (long)recno, oci_status_name(eg_status), + if (DBIS->debug >= 4 || recno>1/*XXX temp*/) + fprintf(DBILOGFP, " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", + what, (long)recno, + (eg_status==OCI_SUCCESS) ? "ok" : oci_status_name(eg_status), status, (long)eg_errcode, errbuf); errcode = eg_errcode; sv_catpv(errstr, (char*)errbuf); @@ -142,6 +145,11 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) int ora_check_sql = 0; /* to force a describe to check SQL */ sword status = 0; + if (!DBIc_ACTIVE(imp_dbh)) { + oci_error(sth, NULL, OCI_ERROR, "Database disconnected"); + return 0; + } + imp_sth->done_desc = 0; if (DBIc_COMPAT(imp_sth)) { @@ -159,7 +167,8 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) SV **svp; DBD_ATTRIB_GET_IV( attribs, "ora_parse_lang", 14, svp, oparse_lng); DBD_ATTRIB_GET_IV( attribs, "ora_auto_lob", 12, svp, imp_sth->auto_lob); - DBD_ATTRIB_GET_IV( attribs, "ora_check_sql", 15, svp, ora_check_sql); + /* ora_check_sql only works for selects owing to Oracle behaviour */ + DBD_ATTRIB_GET_IV( attribs, "ora_check_sql", 13, svp, ora_check_sql); } /* scan statement for '?', ':1' and/or ':foo' style placeholders */ @@ -189,7 +198,7 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) } OCIAttrGet_stmhp(imp_sth, &imp_sth->stmt_type, 0, OCI_ATTR_STMT_TYPE); - if (dbis->debug >= 2) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_st_prepare'd sql %s\n", oci_stmt_type_name(imp_sth->stmt_type)); @@ -229,9 +238,10 @@ dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, *alenp = phs->alen; *indpp = &phs->indp; *piecep = OCI_ONE_PIECE; - if (dbis->debug >= 3) - fprintf(DBILOGFP, " dbd_phs_in '%s' (%ld,%ld): len %2ld, ind %d\n", - phs->name, iter, index, phs->alen, phs->indp); + if (DBIS->debug >= 3) + fprintf(DBILOGFP, " dbd_phs_in '%s' (%ld,%ld): len %2ld, ind %d%s\n", + phs->name, iter, index, phs->alen, phs->indp, + (phs->desc_h) ? " via descriptor" : ""); if (index > 0 || iter > 0) croak("Arrays and multiple iterations not currently supported by DBD::Oracle"); return OCI_CONTINUE; @@ -254,9 +264,10 @@ dbd_phs_out(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, *alenpp = &phs->alen; *indpp = &phs->indp; *rcodepp= &phs->arcode; - if (dbis->debug >= 3) - fprintf(DBILOGFP, " dbd_phs_out '%s' (%ld,%ld): len %ld, piece %d\n", - phs->name, iter, index, phs->alen, *piecep); + if (DBIS->debug >= 3) + fprintf(DBILOGFP, " dbd_phs_out '%s' (%ld,%ld): len %ld, piece %d%s\n", + phs->name, iter, index, phs->alen, *piecep, + (phs->desc_h) ? " via descriptor" : ""); if (index > 0 || iter > 0) croak("Arrays and multiple iterations not currently supported by DBD::Oracle"); *piecep = OCI_ONE_PIECE; @@ -264,6 +275,88 @@ dbd_phs_out(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, } +/* ------ */ + + +#ifdef moved_to_dbdimp +int +pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) +{ + if (pre_exec) { /* pre-execute - allocate a statement handle */ + dSP; + D_imp_dbh_from_sth; + SV *sth_i; + HV *init_attr = newHV(); + int count; + if (DBIS->debug >= 3) + fprintf(DBILOGFP, " bind %s - allocating new sth...\n", phs->name); + ENTER; + PUSHMARK(SP); + XPUSHs(sv_2mortal(newRV(DBIc_MY_H(imp_dbh)))); + XPUSHs(sv_2mortal(newRV((SV*)init_attr))); + PUTBACK; + count = perl_call_pv("DBI::_new_sth", G_ARRAY); + SPAGAIN; + if (count != 2) + croak("panic: DBI::_new_sth returned %d values instead of 2", count); + sth_i = SvREFCNT_inc(POPs); + sv_setsv(phs->sv, SvREFCNT_inc(POPs)); /* outer handle */ + PUTBACK; + LEAVE; + if (DBIS->debug >= 3) + fprintf(DBILOGFP, " bind %s - allocated %s...\n", + phs->name, neatsvpv(phs->sv, 0)); + + } + else { /* post-execute - setup the statement handle */ + dTHR; + SV * sth_csr = phs->sv; + D_impdata(imp_sth_csr, imp_sth_t, sth_csr); + + if (DBIS->debug >= 3) + fprintf(DBILOGFP, " bind %s - initialising new %s...\n", + phs->name, neatsvpv(sth_csr,0)); + +#ifdef OCI_V8_SYNTAX + /* copy appropriate handles from parent statement */ + imp_sth_csr->envhp = imp_sth->envhp; + imp_sth_csr->errhp = imp_sth->errhp; + imp_sth_csr->srvhp = imp_sth->srvhp; + imp_sth_csr->svchp = imp_sth->svchp; + + /* assign statement handle from placeholder descriptor */ + imp_sth_csr->stmhp = phs->desc_h; + imp_sth_csr->disable_finish = 1; /* else finish core dumps in kpuccan()! */ + + /* force stmt_type since OCIAttrGet(OCI_ATTR_STMT_TYPE) doesn't work! */ + imp_sth_csr->stmt_type = OCI_STMT_SELECT; +#else + +#endif + + DBIc_IMPSET_on(imp_sth); + + /* set ACTIVE so dbd_describe doesn't do explicit OCI describe */ + DBIc_ACTIVE_on(imp_sth_csr); + if (!dbd_describe(sth_csr, imp_sth_csr)) { + return 0; + } + } + return 1; +} +#endif + + +int +dbd_rebind_ph_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs) +{ + phs->out_prepost_exec = pp_exec_rset; + return 2; /* OCI bind done */ +} + + +/* ------ */ + int dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { @@ -287,6 +380,80 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } +ub4 +ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, + long offset, long len, long destoffset) +{ + ub4 loblen = 0; + ub4 buflen; + ub4 amtp = 0; + OCILobLocator *lobl = (OCILobLocator*)fbh->desc_h; + sword ftype = fbh->ftype; + sword status; + + if (ftype != 112 && ftype != 113) { + oci_error(sth, imp_sth->errhp, OCI_ERROR, + "blob_read not currently supported for non-LOB types with OCI 8 " + "(but with OCI 8 you can set $dbh->{LongReadLen} to the length you need," + "so you don't need to call blob_read at all)"); + SvOK_off(dest_sv); /* signal error */ + return 0; + } + + status = OCILobGetLength(imp_sth->svchp, imp_sth->errhp, lobl, &loblen); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCILobGetLength"); + SvOK_off(dest_sv); /* signal error */ + return 0; + } + + amtp = (loblen > len) ? len : loblen; + buflen = amtp; /* set right semantics for OCILobRead */ + + /* + * We assume our caller has already done the + * equivalent of the following: + * (void)SvUPGRADE(dest_sv, SVt_PV); + * SvGROW(dest_sv, buflen+destoffset+1); + */ + + if (loblen > 0) { + ub1 * bufp = (ub1 *)(SvPVX(dest_sv)); + bufp += destoffset; + + status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobl, + &amtp, 1 + offset, bufp, buflen, + 0, 0, 0, SQLCS_IMPLICIT); + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", + fbh->field_num+1, oci_status_name(status), loblen, imp_sth->long_readlen, buflen, amtp); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCILobRead"); + SvOK_off(dest_sv); /* signal error */ + return 0; + } + } + else { + assert(amtp == 0); + if (dbis->debug >= 3) + fprintf(DBILOGFP, + " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", + fbh->field_num+1, "SKIPPED", loblen, imp_sth->long_readlen, buflen, amtp); + } + + /* + * We assume our caller will perform + * the equivalent of the following: + * SvCUR(dest_sv) = amtp; + * *SvEND(dest_sv) = '\0'; + * SvPOK_on(dest_sv); + */ + + return(amtp); +} + + static int fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) @@ -320,9 +487,10 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) else { char buf[300]; sprintf(buf,"fetching field %d of %d. LOB value truncated from %ld to %ld. %s", - fbh->field_num+1, DBIc_NUM_FIELDS(imp_sth), loblen, amtp, - "LongReadLen too small and/or LongTruncOk not set"); + fbh->field_num+1, DBIc_NUM_FIELDS(imp_sth), amtp, amtp, + "DBI attribute LongReadLen too small and/or LongTruncOk not set"); oci_error(sth, NULL, OCI_ERROR, buf); + sv_setiv(DBIc_ERR(imp_sth), (IV)24345); /* appropriate ORA error number */ (void)SvOK_off(dest_sv); return 0; } @@ -334,7 +502,7 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) if (loblen > 0) { status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobl, &amtp, 1, SvPVX(dest_sv), buflen, 0, 0, 0, SQLCS_IMPLICIT); - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", fbh->field_num+1, oci_status_name(status), loblen, imp_sth->long_readlen, buflen, amtp); @@ -346,7 +514,7 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) } else { assert(amtp == 0); - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", fbh->field_num+1, "SKIPPED", loblen, imp_sth->long_readlen, buflen, amtp); @@ -364,13 +532,12 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) static int fetch_func_loblocator(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) { + /* OCILobLocator *lobl = (OCILobLocator*)fbh->desc_h; sword status; - + */ sv_setsv(dest_sv, &sv_no); - croak("LOB Locators are not directly accessible yet."); - return 1; } @@ -399,14 +566,14 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) long_readlen = 80; /* typical oracle app default */ if (imp_sth->stmt_type != OCI_STMT_SELECT) { - if (dbis->debug >= 2) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_describe skipped for %s\n", oci_stmt_type_name(imp_sth->stmt_type)); /* imp_sth memory was cleared when created so no setup required here */ return 1; } - if (dbis->debug >= 2) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_describe %s (%s, lb %ld)...\n", oci_stmt_type_name(imp_sth->stmt_type), DBIc_ACTIVE(imp_sth) ? "implicit" : "EXPLICIT", (long)long_readlen); @@ -487,12 +654,14 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->dbsize = long_readlen; fbh->disize = fbh->dbsize; fbh->ftype = 8; + ++has_longs; break; case 24: /* LONG RAW */ fbh->dbsize = long_readlen * 2; fbh->disize = fbh->dbsize; avg_width = fbh->dbsize; fbh->ftype = 24; + ++has_longs; break; case 11: /* ROWID */ @@ -518,7 +687,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) /* XXX unhandled type may lead to errors or worse */ fbh->disize = fbh->dbsize; p = "Field %d has an Oracle type (%d) which is not explicitly supported"; - if (dbis->debug >= 2) + if (DBIS->debug >= 1) fprintf(DBILOGFP, p, i, fbh->dbtype); if (dowarn) warn(p, i, fbh->dbtype); @@ -533,7 +702,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) avg_width = fbh->dbsize; imp_sth->est_width += avg_width; - if (dbis->debug >= 2) + if (DBIS->debug >= 2) dbd_fbh_dump(fbh, i, 0); } @@ -548,7 +717,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) est_width, imp_sth->cache_rows, has_longs); imp_sth->cache_rows = cache_rows; /* record updated value */ status = OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, - &cache_rows, 3, OCI_ATTR_PREFETCH_ROWS, imp_sth->errhp); + &cache_rows, sizeof(cache_rows), OCI_ATTR_PREFETCH_ROWS, imp_sth->errhp); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_PREFETCH_ROWS"); return 0; @@ -558,9 +727,9 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) ub4 cache_mem = -imp_sth->cache_rows; ub4 cache_rows = 100000; /* set high so memory is the limit */ status = OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, - &cache_rows, 0, OCI_ATTR_PREFETCH_ROWS, imp_sth->errhp) + &cache_rows, sizeof(cache_rows), OCI_ATTR_PREFETCH_ROWS, imp_sth->errhp) || OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, - &cache_mem, 0, OCI_ATTR_PREFETCH_MEMORY, imp_sth->errhp); + &cache_mem, sizeof(cache_mem), OCI_ATTR_PREFETCH_MEMORY, imp_sth->errhp); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_PREFETCH_ROWS/OCI_ATTR_PREFETCH_MEMORY"); @@ -592,7 +761,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) } - if (dbis->debug >= 2) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_describe'd %d columns (row bytes: %d max, %d est avg, cache: %d)\n", (int)num_fields, imp_sth->t_dbsize, imp_sth->est_width, imp_sth->cache_rows); @@ -625,7 +794,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) status = OCI_SUCCESS; } else { - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_st_fetch %d fields...\n", DBIc_NUM_FIELDS(imp_sth)); status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT); } @@ -633,13 +802,15 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) if (status != OCI_SUCCESS) { ora_fetchtest = 0; if (status == OCI_NO_DATA) { - dTHR; /* for DBIc_ACTIVE_off */ - DBIc_ACTIVE_off(imp_sth); /* eg finish */ - if (dbis->debug >= 2) + dTHR; /* for DBIc_ACTIVE_off */ + DBIc_ACTIVE_off(imp_sth); /* eg finish */ + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_st_fetch no-more-data\n"); return Nullav; } if (status != OCI_SUCCESS_WITH_INFO) { + dTHR; /* for DBIc_ACTIVE_off */ + DBIc_ACTIVE_off(imp_sth); /* eg finish */ oci_error(sth, imp_sth->errhp, status, "OCIStmtFetch"); return Nullav; } @@ -649,7 +820,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) av = DBIS->get_fbav(imp_sth); - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_st_fetch %d fields %s\n", num_fields, oci_status_name(status)); @@ -701,11 +872,13 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) char buf[200]; char *hint = ""; /* These may get more case-by-case treatment eventually. */ - if (rc == 1406 && fbh->ftype == 5) { /* field truncated (see above) */ - /* Copy the truncated value anyway, it may be of use, */ - /* but it'll only be accessible via prior bind_column() */ - sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], + if (rc == 1406) { /* field truncated (see above) */ + if (!fbh->fetch_func) { + /* Copy the truncated value anyway, it may be of use, */ + /* but it'll only be accessible via prior bind_column() */ + sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], fb_ary->arlen[cache_entry]); + } if (ora_dbtype_is_long(fbh->dbtype)) /* double check */ hint = ", LongReadLen too small and/or LongTruncOk not set"; } @@ -720,7 +893,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) oci_error(sth, imp_sth->errhp, OCI_ERROR, buf); } - if (dbis->debug >= 5) + if (DBIS->debug >= 5) fprintf(DBILOGFP, " %d (rc=%d): %s\n", i, rc, neatsvpv(sv,0)); } @@ -729,6 +902,56 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) } +ub4 +ora_parse_uid(imp_dbh, uidp, pwdp) + imp_dbh_t *imp_dbh; + char **uidp; + char **pwdp; +{ + /* OCI 8 does not seem to allow uid to be "name/pass" :-( */ + /* so we have to split it up ourselves */ + if (strlen(*pwdp)==0 && strchr(*uidp,'/')) { + SV *tmpsv = sv_2mortal(newSVpv(*uidp,0)); + *uidp = SvPVX(tmpsv); + *pwdp = strchr(*uidp, '/'); + *(*pwdp)++ = '\0'; + /* XXX look for '@', e.g. "u/p@d" and "u@d" and maybe "@d"? */ + } + if (**uidp == '\0' && **pwdp == '\0') { + return OCI_CRED_EXT; + } + OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, + *uidp, strlen(*uidp), + (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp); + OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, + (strlen(*pwdp)) ? *pwdp : NULL, strlen(*pwdp), + (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp); + return OCI_CRED_RDBMS; +} + + +int +ora_db_reauthenticate(dbh, imp_dbh, uid, pwd) + SV *dbh; + imp_dbh_t *imp_dbh; + char * uid; + char * pwd; +{ + sword status; + /* XXX should possibly create new session before ending the old so */ + /* that if the new one can't be created, the old will still work. */ + OCISessionEnd (imp_dbh->svchp, imp_dbh->errhp, + imp_dbh->authp, OCI_DEFAULT); + status = OCISessionBegin( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, + ora_parse_uid(imp_dbh, &uid, &pwd), (ub4) OCI_DEFAULT); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); + return 0; + } + return 1; +} + + #ifdef not_used_curently static char * rowid2hex(OCIRowid *rowid) @@ -875,7 +1098,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) OCIHandleFree(dschp, OCI_HTYPE_DESCRIBE); return oci_error(sth, errhp, status, "OCIDescribeAny/OCIAttrGet/LOB refetch"); } - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " lob refetch from table %s, %d columns:\n", tablename, numcols); @@ -892,7 +1115,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) if ((status=OCIAttrGet(colhd, OCI_DTYPE_PARAM, &col_name, &col_name_len, OCI_ATTR_NAME, errhp))) break; - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " lob refetch table col %d: '%.*s' otype %d\n", (int)i, (int)col_name_len,col_name, col_dbtype); if (col_dbtype != SQLT_CLOB && col_dbtype != SQLT_BLOB) @@ -953,7 +1176,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) while( (sv_other = hv_iternextsv(lob_cols_hv, &p_other, &i)) != NULL ) { if (phs->ftype != SvIV(sv_other)) continue; - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " both %s and %s have type %d - ambiguous\n", SvPV(sv,na), SvPV(sv_other,na), (int)SvIV(sv_other)); @@ -966,7 +1189,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) sprintf(sql_field, "%s%s \"%s\"", (SvCUR(sql_select)>7)?", ":"", p, &phs->name[1]); sv_catpv(sql_select, sql_field); - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " lob refetch %s param: otype %d, matched field '%s' %s(%s)\n", phs->name, phs->ftype, p, @@ -983,7 +1206,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } if (!matched) { ++unmatched_params; - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " lob refetch %s param: otype %d, UNMATCHED\n", phs->name, phs->ftype); @@ -998,7 +1221,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) sv_catpv(sql_select, " from "); sv_catpv(sql_select, tablename); sv_catpv(sql_select, " where rowid = :rid for update"); /* get row with lock */ - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " lob refetch sql: %s\n", SvPVX(sql_select)); lr->sql_select = sql_select; @@ -1034,7 +1257,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) fbh->name,i+1); phs = (phs_t*)(void*)SvPVX(*phs_svp); fbh->special = phs; - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " lob refetch %d for '%s' param: ftype %d setup\n", (int)i+1,fbh->name, fbh->dbtype); @@ -1084,7 +1307,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl imp_fbh_t *fbh = &lr->fbh_ary[i]; phs_t *phs = (phs_t*)fbh->special; ub4 amtp = SvCUR(phs->sv); - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " lob refetch %d for '%s' param: ftype %d, len %ld\n", i+1,fbh->name, fbh->dbtype, amtp); @@ -1097,8 +1320,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl status = OCILobTrim(imp_sth->svchp, errhp, fbh->desc_h, 0); } if (status != OCI_SUCCESS) { - oci_error(sth, errhp, status, "OCILobTrim/OCILobWrite/LOB refetch"); - return -2; + return oci_error(sth, errhp, status, "OCILobTrim/OCILobWrite/LOB refetch"); } } @@ -1123,4 +1345,215 @@ ora_free_lob_refetch(SV *sth, imp_sth_t *imp_sth) imp_sth->lob_refetch = NULL; } + + +#ifdef OCI8_RSET_TEST_CODE + +#define VARCHAR2_TYPE 1 +#define NUMBER_TYPE 2 +#define INT_TYPE 3 +#define FLOAT_TYPE 4 +#define STRING_TYPE 5 +#define ROWID_TYPE 11 +#define DATE_TYPE 12 +#define LONG_RAW 24 +#define LONG_VARRAW 95 + +/* + * Macro and Other Definitions + */ +#define UNREFERENCED_PARAMETER(x) ((x)=(x)) +#define NO_DATA_FOUND 1403 +#define OCI8_INITIALIZED 1 +#define OCI8_SERVER_ATTACHED 2 +#define OCI8_SESSION_BEGAN 3 +#define BOOL short int +#define UINT unsigned int + +/* + * Oracle 8 OCI Global Variables for this Sample + */ +OCIEnv *or8EnvHandle; +OCIError *or8ErrorHandle; +OCIStmt *or8StmtHandle; +OCIStmt *or8CursorStmtHandle; +OCISvcCtx *or8SrcHandle; + +typedef dvoid * PDV; + +/* + * Function Prototypes + */ + +BOOL oci8Error (sb2 sb2ErrorCode); + +/*****************************************************************/ +BOOL oci8Error (sb2 sb2ErrorCode) +{ + text errbuf[512]; + sb4 errcode; + switch (sb2ErrorCode) { + case OCI_SUCCESS: + break; + case OCI_SUCCESS_WITH_INFO: + printf ("Error - OCI_SUCCESS_WITH_INFO\n"); + break; + case OCI_NEED_DATA: + printf ("Error - OCI_NEED_DATA\n"); + break; + case OCI_NO_DATA: + printf ("Error - OCI_NO_DATA\n"); + break; + case OCI_ERROR: + OCIErrorGet ((dvoid *) or8ErrorHandle, (ub4) 1, (OraText *) + NULL, &errcode, errbuf, (ub4) sizeof(errbuf), + (ub4) OCI_HTYPE_ERROR); + printf ("Error - %s\n", errbuf); + break; + case OCI_INVALID_HANDLE: + printf ("Error - OCI_INVALID_HANDLE\n"); + break; + case OCI_STILL_EXECUTING: + printf ("Error - OCI_STILL_EXECUTE\n"); + break; + case OCI_CONTINUE: + printf ("Error - OCI_CONTINUE\n"); + break; + default: + break; + } + return ((sb2ErrorCode==OCI_SUCCESS) ? FALSE : TRUE ); +} + +/*****************************************************************/ + +int rset_main (imp_dbh_t *imp_dbh) +{ + sword rc; + static unsigned char *szPLSQLBlock = (unsigned char *) +"BEGIN RefTest.GetEmpData (:DEPTNO , :empCursor); END;"; + + static char *pszUserName = "scott"; + static char *pszPassword = "tiger"; + static char *pszConnection = "firstdb"; + + sb2 rv; + int bv_deptno = 10; + char bv_ename[40]; + int bv_ename_len = 40; + OCIBind *ptrBindHandle1; + OCIBind *ptrBindHandle2; + OCIDefine *or8Define1; + char *pszBindVarName; + char *pszBindVarName2; + + /* oci8Connect(pszUserName, pszPassword, pszConnection); */ + or8ErrorHandle= imp_dbh->errhp; + or8SrcHandle = imp_dbh->svchp; + or8EnvHandle = imp_dbh->envhp; + + /* + * Allocate Stmt handle + */ + rv = OCIHandleAlloc ((PDV) or8EnvHandle, (PDV*) &or8StmtHandle, + OCI_HTYPE_STMT, 0, (PDV*) 0); + if (rv) { exit(1); } + + /* + * Allocate Stmt handle for cursor resultset + */ + rv = OCIHandleAlloc ((PDV) or8EnvHandle, (PDV*) &or8CursorStmtHandle, + OCI_HTYPE_STMT, 0, (PDV*) 0); + if (rv) { exit(1); } + + /* + * Prepare statement + */ + rv = OCIStmtPrepare (or8StmtHandle, + or8ErrorHandle, + (OraText *) szPLSQLBlock, + (ub4)strlen((char *)szPLSQLBlock), + (ub4)OCI_NTV_SYNTAX, + (ub4)OCI_DEFAULT); + if (rv) { puts("OCIStmtPrepare"); oci8Error (rv); exit(1); } + +{ ub2 stmt_type = 0; + OCIAttrGet(or8StmtHandle, OCI_HTYPE_STMT, &stmt_type, 0, OCI_ATTR_STMT_TYPE, or8ErrorHandle); +warn("stmt_type=%d\n",stmt_type); +} + + pszBindVarName = ":DEPTNO"; + + rv = OCIBindByName( or8StmtHandle, + (OCIBind **)&ptrBindHandle1, + or8ErrorHandle, + (OraText *) pszBindVarName, + -1, /* (sb4) strlen(pszBindVarName), */ + (dvoid *) &bv_deptno, + (sb4) sizeof (bv_deptno), + (ub2) SQLT_INT, + (dvoid *) 0, + (ub2 *) 0, + (ub2 *) 0, + (ub4) 0, + (ub4 *)0, + (ub4) OCI_DEFAULT); + if (rv) { puts("OCIBindByName"); oci8Error (rv); exit(1); } + + pszBindVarName2 = ":empCursor"; + rv = OCIBindByName(or8StmtHandle, + (OCIBind **)&ptrBindHandle2, + or8ErrorHandle, + (OraText *) pszBindVarName2, + -1, /* (sb4) strlen(pszBindVarName2), */ + (dvoid *)&or8CursorStmtHandle, + (sb4) 0, + SQLT_RSET, + (dvoid *) 0, + (ub2 *) 0, + (ub2 *) 0, + (ub4) 0, + (ub4 *)0, + (ub4) OCI_DEFAULT); + if (rv) { puts("OCIBindByName 2"); oci8Error (rv); exit(1); } + + rv = OCIStmtExecute(or8SrcHandle, + or8StmtHandle, + or8ErrorHandle, + (ub4) 1, + (ub4) 0, + (CONST OCISnapshot *) NULL, + (OCISnapshot *) NULL, + OCI_DEFAULT); + if (rv) { puts("execute"); oci8Error (rv); exit(1); } + + rv = OCIDefineByPos(or8CursorStmtHandle, + (OCIDefine **)&or8Define1, + or8ErrorHandle, + (ub4) 1, + (dvoid *)&bv_ename, + (sb4) bv_ename_len, + SQLT_STR, + (dvoid *)0, + 0, 0, + OCI_DEFAULT); + + if (rv) { puts("OCIDefineByPos post execute"); oci8Error (rv); exit(1); } + + rc = OCIStmtFetch(or8CursorStmtHandle, or8ErrorHandle, 1, 0, 0); + while (rc == OCI_SUCCESS) { + printf("[%s]\n", bv_ename); + rc = OCIStmtFetch(or8CursorStmtHandle, or8ErrorHandle, 1, 0, 0); + } + if (rc != OCI_NO_DATA) { + oci8Error (rc); + exit(1); + } + + oci8Error (OCIHandleFree ((PDV) or8StmtHandle, OCI_HTYPE_STMT)); + return 1; +} +#endif /* OCI8_RSET_TEST_CODE */ + + #endif diff --git a/t/general.t b/t/general.t index 158d5205..dfe335c6 100644 --- a/t/general.t +++ b/t/general.t @@ -47,6 +47,9 @@ ok(0, $sth->{Active}); 1 while ($sth->fetch); # fetch through to end ok(0, !$sth->{Active}); +# so following test works with other NLS settings/locations +ok(0, $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"), 1); + ok(0, $tmp = $dbh->selectall_arrayref(q{ select 1 * power(10,-130) "smallest?", 9.9999999999 * power(10,125) "biggest?" @@ -57,6 +60,14 @@ my @tmp = @{$tmp->[0]}; ok(0, $tmp[0] <= 1e-130, $tmp[0]); ok(0, $tmp[1] >= 9.99e+125, $tmp[1]); + +eval { + $dbh->{RaiseError} = 1; + $dbh->do("some invalid sql statement"); +}; +ok(0, $@ =~ /DBD::Oracle::db do failed:/, "eval error: ``$@'' expected 'do failed:'"); +$dbh->{RaiseError} = 0; + # --- ok(0, $dbh->ping); @@ -65,7 +76,7 @@ $dbh->{PrintError} = 0; ok(0, !$dbh->ping); exit 0; -BEGIN { $tests = 14 } +BEGIN { $tests = 16 } # end. __END__ diff --git a/t/long.t b/t/long.t new file mode 100644 index 00000000..11715d7f --- /dev/null +++ b/t/long.t @@ -0,0 +1,281 @@ +#!/usr/local/bin/perl -w + +use DBI; +use DBD::Oracle qw(:ora_types ORA_OCI); +use strict; + +$| = 1; +my $t = 0; +my $failed = 0; +my $oflng; +my $lrl_limit; +my $table = "dbd_ora__drop_me"; + +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dbh = DBI->connect('dbi:Oracle:', $dbuser, '', { + AutoCommit => 1, + PrintError => 0, +}); + +unless($dbh) { + warn "Unable to connect to Oracle ($DBI::errstr)\nTests skiped.\n"; + print "1..0\n"; + exit 0; +} + +unless(create_table("lng LONG")) { + warn "Unable to create test table ($DBI::errstr)\nTests skiped.\n"; + print "1..0\n"; + exit 0; +} + + +my @test_sets = ([ "LONG", undef ], [ "LONG RAW", ORA_LONGRAW ]); +push @test_sets, [ "CLOB", ORA_CLOB ], [ "BLOB", ORA_BLOB ] if ORA_OCI >= 8; + +my $sz = 8; # Min 8 == 80KB, max = ??? +my $tests; +my $tests_per_set = 35; +$tests = @test_sets * $tests_per_set; +print "1..$tests\n"; + +my($sth, $p1, $p2, $tmp, @tmp); +#$dbh->trace(4); + +foreach (@test_sets) { + run_long_tests( @$_ ); +} + + +sub run_long_tests { + my ($type_name, $type_num) = @_; + +my $long_data0 = "\177.\0.X" x 2048; # 10KB < 64KB +my $long_data1 = ("1234567890" x 1024) x $sz; # 520KB >> 64KB & > long_data2 +my $long_data2 = ("abcdefabcd" x 1024) x 7; # 70KB > 64KB & < long_data1 + +$long_data2 = "00FF" x (length($long_data2) / 2) if $type_name =~ /RAW/i; + +print "long_data0 length ",length($long_data0),"\n"; +print "long_data1 length ",length($long_data1),"\n"; +print "long_data2 length ",length($long_data2),"\n"; + +if (!create_table("lng $type_name", 1)) { + # typically OCI 8 client talking to Oracle 7 database + warn "Unable to create test table for '$type_name' data ($DBI::err). Tests skipped.\n"; + foreach (1..$tests_per_set) { ok(0, 1) } + return; +} + +print " --- insert some $type_name data\n"; +ok(0, $sth = $dbh->prepare("insert into $table values (?, ?)"), 1); +$sth->bind_param(2, undef, { ora_type => $type_num }) or die $DBI::errstr + if $type_num; +ok(0, $sth->execute(40, $long_data0), 1); +ok(0, $sth->execute(41, $long_data1), 1); +ok(0, $sth->execute(42, $long_data2), 1); + + +print " --- fetch it back again -- truncated - LongTruncOk == 1\n"; +$dbh->{LongReadLen} = 20; +# This behaviour isn't specified anywhere, sigh: +my $out_len = ($type_name =~ /RAW/i) ? 40 : 20; +$dbh->{LongTruncOk} = 1; +ok(0, $sth = $dbh->prepare("select * from $table order by idx"), 1); +ok(0, $sth->execute, 1); +ok(0, $tmp = $sth->fetchall_arrayref, 1); +ok(0, $tmp->[0][1] eq substr($long_data0,0,$out_len), length($tmp->[0][1])); +ok(0, $tmp->[1][1] eq substr($long_data1,0,$out_len), length($tmp->[1][1])); +ok(0, $tmp->[2][1] eq substr($long_data2,0,$out_len), + cdif($tmp->[2][1], substr($long_data2,0,$out_len), "Len ".length($tmp->[2][1])) ); + + +print " --- fetch it back again -- truncated - LongTruncOk == 0\n"; +$dbh->{LongReadLen} = 1024 * 50; # first fits, second doesn't +$dbh->{LongTruncOk} = 0; +ok(0, $sth = $dbh->prepare("select * from $table order by idx"), 1); +ok(0, $sth->execute, 1); +ok(0, $tmp = $sth->fetchrow_arrayref, 1); +ok(0, $tmp->[1] eq $long_data0, length($tmp->[1])); +ok(0, !defined $sth->fetchrow_arrayref, 1); +ok(0, $sth->err == 1406 || $sth->err == 24345, $sth->errstr); + + +print " --- fetch it back again -- complete - LongTruncOk == 0\n"; +$dbh->{LongReadLen} = (65535 * 10) - 100; +$dbh->{LongTruncOk} = 0; +ok(0, $sth = $dbh->prepare("select * from $table order by idx"), 1); +ok(0, $sth->execute, 1); +ok(0, $tmp = $sth->fetchrow_arrayref, 1); +ok(0, $tmp->[1] eq $long_data0, length($tmp->[1])); + +if ($tmp = $sth->fetchrow_arrayref) { + ok(0, $tmp, 1); + ok(0, $tmp->[1] eq $long_data1, length($tmp->[1])); + ok(0, $tmp = $sth->fetchrow_arrayref, 1); + ok(0, $tmp->[1] eq $long_data2, + cdif($tmp->[1],$long_data2, "Len ".length($tmp->[1])) ); +} +else { + $lrl_limit = 1; + ok(0,1); ok(0,1); ok(0,1); ok(0,1); +} + + +print " --- fetch it back again -- via blob_read\n"; +if (ORA_OCI >= 8 && $type_name =~ /LONG/i) { + print "Skipped blob_read tests for LONGs with OCI8 - not currently supported.\n"; + foreach (1..11) { ok(0,1) } + return; +} +#$dbh->trace(4); +$dbh->{LongReadLen} = 1024 * 90; +$dbh->{LongTruncOk} = 1; +ok(0, $sth = $dbh->prepare("select * from $table order by idx"), 1); +ok(0, $sth->execute, 1); +ok(0, $tmp = $sth->fetchrow_arrayref, 1); + +ok(0, blob_read_all($sth, 1, \$p1, 4096) == length($long_data0), 1); +ok(0, $p1 eq $long_data0, 1); + +ok(0, $tmp = $sth->fetchrow_arrayref, 1); +ok(0, blob_read_all($sth, 1, \$p1, 12345) == length($long_data1), 1); +ok(0, $p1 eq $long_data1, 1); + +ok(0, $tmp = $sth->fetchrow_arrayref, 1); +my $len = blob_read_all($sth, 1, \$p1, 34567); + +if ($len == length($long_data2)) { + ok(0, $len == length($long_data2), $len); + # Oracle may return the right length but corrupt the string. + ok(0, $p1 eq $long_data2, cdif($p1, $long_data2) ); +} +elsif ($len == length($long_data1) && DBD::Oracle::ORA_OCI() == 7) { + $oflng = __LINE__; + # The bug: + # If you use blob_read to read a LONG field + # and then fetch another row + # and use blob_read to read that LONG field + # If the second LONG is shorter than the first + # then the second long will appear to have the + # longer portion of first appended to it. + ok(0, 1); + ok(0, 1, 0); +} +else { + ok(0, 0, "Fetched length $len, expected ".length($long_data2)); + ok(0, 0, 0); +} + +} # end of run_long_tests + +if ($oflng) { + warn "\nYour version of Oracle 7 OCI has a bug that effects the (undocumented) blob_read method.\n"; + warn "See the t/long.t script near line $oflng for more information.\n"; + warn "(You can safely ignore this if you don't use the blob_read method.)\n"; +} + +if ($lrl_limit) { + warn "\nThe maximum valid value of \$h->{LongReadLen} when fetching LONGs is currently 65535.\n"; + warn "There's no limit when fetching LOB types.\n" if ORA_OCI() >= 8; +} + +if ($failed) { + warn "\nSome tests for LONG data type handling failed. These are generally Oracle bugs.\n"; + warn "Please report this to the dbi-users mailing list, and include the\n"; + warn "Oracle version number of both the client and the server.\n"; + warn "Please also include the output of the 'perl -V' command.\n"; + warn "(If you can, please study t/long.t to investigate the cause.\n"; + warn "Feel free to edit the tests to see what's happening in more detail.\n"; + warn "Especially by adding trace() calls around the failing tests.\n"; + warn "Run the tests manually using the command \"perl -Mblib t/long.t\")\n"; + warn "Meanwhile, if the other tests have passed you can use DBD::Oracle.\n\n"; +} + +exit 0; +BEGIN { $tests = 27 } +END { + $dbh->do(qq{ drop table $table }) if $dbh; +} +# end. + + +# ---- + +sub create_table { + my ($fields, $drop) = @_; + my $sql = "create table $table ( idx integer, $fields )"; + $dbh->do(qq{ drop table $table }) if $drop; + $dbh->do($sql); + if ($dbh->err && $dbh->err==955) { + $dbh->do(qq{ drop table $table }); + warn "Unexpectedly had to drop old test table '$table'\n" unless $dbh->err; + $dbh->do($sql); + } + return 0 if $dbh->err; + print "$sql\n"; + return 1; +} + +sub blob_read_all { + my ($sth, $field_idx, $blob_ref, $lump) = @_; + + $lump ||= 4096; # use benchmarks to get best value for you + my $offset = 0; + my @frags; + while (1) { + my $frag = $sth->blob_read($field_idx, $offset, $lump); + return unless defined $frag; + my $len = length $frag; + last unless $len; + push @frags, $frag; + $offset += $len; + #warn "offset $offset, len $len\n"; + } + $$blob_ref = join "", @frags; + return length($$blob_ref); +} + +sub unc { + my @str = @_; + foreach (@str) { s/([\000-\037\177-\377])/ sprintf "\\%03o", ord($_) /eg; } + return join "", @str unless wantarray; + return @str; +} + +sub cdif { + my ($s1, $s2, $msg) = @_; + $msg = ($msg) ? ", $msg" : ""; + my ($l1, $l2) = (length($s1), length($s2)); + return "Strings are identical$msg" if $s1 eq $s2; + return "Strings are of different lengths ($l1 vs $l2)$msg" # check substr matches? + if $l1 != $l2; + my $i; + for($i=0; $i < $l1; ++$i) { + my ($c1,$c2) = (ord(substr($s1,$i,1)), ord(substr($s2,$i,1))); + next if $c1 == $c2; + return sprintf "Strings differ at position %d (\\%03o vs \\%03o)$msg", + $i,$c1,$c2; + } + return "(cdif error $l1/$l2/$i)"; +} + + +sub ok ($$;$) { + my($n, $ok, $warn) = @_; + $warn ||= ''; + ++$t; + die "sequence error, expected $n but actually $t" + if $n and $n != $t; + if ($ok) { + print "ok $t\n"; + } + else { + $warn = $DBI::errstr || "(DBI::errstr undefined)" if $warn eq '1'; + warn "# failed test $t at line ".(caller)[2].". $warn\n"; + print "not ok $t\n"; + ++$failed; + } +} + +__END__ diff --git a/t/plsql.t b/t/plsql.t index 84a8bbae..f3585581 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -14,6 +14,9 @@ sub ok ($$;$) { } use DBI; +use DBD::Oracle qw(ORA_RSET); +use strict; + $| = 1; my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; @@ -36,6 +39,7 @@ if ($dbh->err && ($dbh->err==900 || $dbh->err==6553 || $dbh->err==600)) { exit 0; } +my $tests; print "1..$tests\n"; my($csr, $p1, $p2, $tmp); @@ -228,23 +232,46 @@ $dbh->{PrintError} = 0; #$dbh->trace(0); # --- test cursor variables -$csr = $dbh->prepare(q{ - begin - :var := :var * 2; - end; -}); -ok(0, $csr); -my $out_csr = $dbh->prepare(q{select 42 from dual}); # sacrificial csr XXX -ok(0, $out_csr); -if (0) { - ok(0, $csr->bind_param_inout(':var', \$out_csr, 100, { ora_type => 102 })); - ok(0, $csr->execute()); +if (1) { + my $cur_query = q{ + SELECT object_name, owner FROM all_objects + WHERE object_name LIKE :p1 ORDER BY object_name, owner + }; + my $cur1 = 42; + #$dbh->trace(4); + my $parent = $dbh->prepare(qq{ + BEGIN OPEN :cur1 FOR $cur_query; END; + }); + ok(0, $parent); + ok(0, $parent->bind_param(":p1", "V%")); + ok(0, $parent->bind_param_inout(":cur1", \$cur1, 0, { ora_type => ORA_RSET } )); + ok(0, $parent->execute()); + my @r; + push @r,$cur1->fetchrow_array; + push @r,$cur1->fetchrow_array; + push @r,$cur1->fetchrow_array; + $cur1->finish; + #$dbh->trace(0); $parent->trace(0); + my $s1 = $dbh->selectall_arrayref($cur_query, undef, "V%"); + my @s1 = map { @$_ } @{$s1}[0..2]; + ok(0, "@r" eq "@s1", "r=(@r), s=(@s1)"); + + # --- test rebind and execute + my $cur1_str = "$cur1"; + #$dbh->trace(4); $parent->trace(4); + ok(0, $parent->bind_param(":p1", "U%")); + ok(0, $parent->execute()); + ok(0, "$cur1" ne $cur1_str); # must be ref to new handle object + @r = (); + push @r,$cur1->fetchrow_array; + push @r,$cur1->fetchrow_array; + push @r,$cur1->fetchrow_array; $cur1->finish; + #$dbh->trace(0); $parent->trace(0); $cur1->trace(0); + my $s2 = $dbh->selectall_arrayref($cur_query, undef, "U%"); + my @s2 = map { @$_ } @{$s2}[0..2]; + ok(0, "@r" eq "@s2", "r=(@r), s=(@s2)"); } -else { - ok(0,1); - ok(0,1); -} -# at this point $out_csr should be a handle on a new oracle cursor + # --- To do @@ -259,7 +286,7 @@ $dbh->disconnect; ok(0, !$dbh->ping); exit 0; -BEGIN { $tests = 57 } +BEGIN { $tests = 62 } # end. __END__ diff --git a/t/reauth.t b/t/reauth.t new file mode 100644 index 00000000..7f7831dd --- /dev/null +++ b/t/reauth.t @@ -0,0 +1,46 @@ +#!/usr/local/bin/perl -w + +sub ok ($$;$) { + my($n, $ok, $warn) = @_; + ++$t; + die "sequence error, expected $n but actually $t" + if $n and $n != $t; + ($ok) ? print "ok $t\n" + : print "# failed test $t at line ".(caller)[2]."\nnot ok $t\n"; + if (!$ok && $warn) { + $warn = $DBI::errstr || "(DBI::errstr undefined)" if $warn eq '1'; + warn "$warn\n"; + } +} + +use DBI; +$| = 1; + +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dbuser_2 = $ENV{ORACLE_USERID_2} || ''; + +sub give_up { warn @_ if @_; print "1..0\n"; exit 0; } + +if ($dbuser_2 eq '') { + print("ORACLE_USERID_2 not defined.\nTests skiped.\n"); + give_up(); +} +(my $uid1 = uc $dbuser) =~ s:/.*::; +(my $uid2 = uc $dbuser_2) =~ s:/.*::; +if ($uid1 eq $uid2) { + give_up("ORACLE_USERID_2 not unique.\nTests skiped.\n") +} + +my $dbh = DBI->connect('dbi:Oracle:', $dbuser, ''); + +unless($dbh) { + give_up("Unable to connect to Oracle ($DBI::errstr)\nTests skiped.\n"); +} + +print "1..3\n"; + +ok(0, ($dbh->selectrow_array("SELECT USER FROM DUAL"))[0] eq $uid1 ); +ok(0, $dbh->func($dbuser_2, '', 'reauthenticate')); +ok(0, ($dbh->selectrow_array("SELECT USER FROM DUAL"))[0] eq $uid2 ); + +$dbh->disconnect; diff --git a/test.pl b/test.pl index 6899eedc..eaf0a6f4 100755 --- a/test.pl +++ b/test.pl @@ -4,7 +4,7 @@ die "Use 'make test' to run test.pl\n" unless "@INC" =~ /\bblib\b/; -# $Id: test.pl,v 1.34 1998/12/19 23:19:56 timbo Exp $ +# $Id: test.pl,v 1.2 1999/06/08 00:15:02 timbo Exp $ # # Copyright (c) 1995-1998, Tim Bunce # @@ -19,7 +19,7 @@ require 'getopts.pl'; $| = 1; -print q{Oraperl test application $Revision: 1.34 $}."\n"; +print q{Oraperl test application $Revision: 1.2 $}."\n"; $SIG{__WARN__} = sub { ($_[0] =~ /^(Bad|Duplicate) free/) @@ -31,19 +31,24 @@ $opt_d = 0; # debug $opt_l = 0; # log $opt_n = 5; # num of loops -$opt_m = 0; # count for mem leek test -$opt_c = 1; # do cache test +$opt_m = 0; # do mem leek test +$opt_c = undef; # set RowCacheSize for some tests $opt_p = 1; # do perf test -&Getopts('m:d:n:clp ') || die "Invalid options\n"; +$opt_f = 0; # do fetch test +&Getopts('md:n:f:c:lp ') || die "Invalid options\n"; $ENV{PERL_DBI_DEBUG} = 2 if $opt_d; -$ENV{ORACLE_HOME} = '/usr/oracle' unless $ENV{ORACLE_HOME}; +#$ENV{ORACLE_HOME} ||= '/usr/oracle' unless ($^O eq 'MSWin32'); $dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; eval 'use Oraperl; 1' || die $@ if $] >= 5; +&test_extfetch_perf($opt_f) if $opt_f; + +&test_leak(100) if $opt_m; + &ora_version; my @data_sources = DBI->data_sources('Oracle'); @@ -55,7 +60,6 @@ printf("(ORACLE_SID='%s', TWO_TASK='%s')\n", $ENV{ORACLE_SID}||'', $ENV{TWO_TASK}||''); printf("(LOCAL='%s', REMOTE='%s')\n", $ENV{LOCAL}||'', $ENV{REMOTE}||'') if $os eq 'MSWin32'; - { # test connect works first local($l) = &ora_login($dbname, $dbuser, ''); unless($l) { @@ -94,9 +98,7 @@ rename("test.log","test.olog") if $opt_l; eval 'DBI->_debug_dispatch(3,"test.log");' if $opt_l; -&test_fetch_perf() if $opt_p; - -&test3($opt_m) if $opt_m; +&test_intfetch_perf() if $opt_p; &test1(); @@ -114,7 +116,7 @@ &ora_logoff($lda2) || warn "ora_logoff($lda2): $ora_errno: $ora_errstr\n"; print "done.\n"; -&test_cache() if $opt_c; +&test_cache(); $dur = time - $start; print "\nTest complete ($dur seconds).\n"; @@ -143,7 +145,9 @@ sub test1 { { #$lda->trace(2); local($csr) = &ora_open($lda, - "select to_number('7.2') num_t, + "select to_number('7.2', '9D9', + 'NLS_NUMERIC_CHARACTERS =''.,''' + ) num_t, SYSDATE date_t, USER char_t, ROWID rowid_t, @@ -211,28 +215,33 @@ sub test1 { } -sub test2 { - local($l) = &ora_login($dbname, $dbuser, '') - || die "ora_login: $ora_errno: $ora_errstr\n"; - local($c) = &ora_open($l, "select 42,42,42,42,42,42,42 from dual") - || die "ora_open: $ora_errno: $ora_errstr\n"; - local(@row); - @row = &ora_fetch($c); - &ora_close($c) || warn "ora_close($c): $ora_errno: $ora_errstr\n"; +sub test2 { # also used by test_leak() + my $skip_sth = shift; + local($l) = &ora_login($dbname, $dbuser, ''); + warn "ora_login: $ora_errno: $ora_errstr\n" if $ora_errno; + return unless $l; + unless ($skip_sth) { + local($c) = &ora_open($l, "set transaction read only")#"select 42,42,42,42,42,42,42 from dual") + || die "ora_open: $ora_errno: $ora_errstr\n"; + local(@row); + @row = &ora_fetch($c); + &ora_close($c) || warn "ora_close($c): $ora_errno: $ora_errstr\n"; + } &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; } -sub test3 { +sub test_leak { local($count) = @_; - local($ps) = (-d '/proc') ? "ps -p " : "ps -l"; + local($ps) = (-d '/proc') ? "ps -lp " : "ps -l"; local($i) = 0; - + print "\nMemory leak test:\n"; while(++$i <= $count) { system("echo $i; $ps$$") if (($i % 10) == 0); - &test2(); + &test2(1); } system("echo $i; $ps$$") if (($i % 10) == 0); + print "Done.\n\n"; } @@ -272,7 +281,7 @@ sub count_fetch { } -sub test_fetch_perf { +sub test_intfetch_perf { print "\nTesting internal row fetch overhead.\n"; local($lda) = &ora_login($dbname, $dbuser, '') || die "ora_login: $ora_errno: $ora_errstr\n"; @@ -292,6 +301,52 @@ sub test_fetch_perf { $max/($td->cpu_a ? $td->cpu_a : 1)); } +sub test_extfetch_perf { + my $max = shift; + print "\nTesting external row fetch overhead.\n"; + my $rows = 0; + my $dbh = DBI->connect("dbi:Oracle:$dbname", $dbuser, '', { RaiseError => 1 }); + #$dbh->trace(2); + $dbh->{RowCacheSize} = $::opt_c if defined $::opt_c; + my $fields = (0) ? "*" : "object_name, status, object_type"; + my $sth = $dbh->prepare(q{ + select all * from all_objects o1 + union all select all * from all_objects o1 + union all select all * from all_objects o1 + union all select all * from all_objects o1 + union all select all * from all_objects o1 + union all select all * from all_objects o1 + union all select all * from all_objects o1 + union all select all * from all_objects o1 + union all select all * from all_objects o1 + --, all_objects o2 + --where o1.object_id <= 400 and o2.object_id <= 400 + }, { ora_check_sql => 1 }); + + require Benchmark; + $t0 = new Benchmark; + $sth->execute; + $sth->trace(0); + $sth->fetchrow_arrayref; # fetch one before starting timer + $td = Benchmark::timediff((new Benchmark), $t0); + printf("Execute: ".Benchmark::timestr($td)."\n"); + + print "Fetching data with RowCacheSize $dbh->{RowCacheSize}...\n"; + $t1 = new Benchmark; + 1 while $sth->fetchrow_arrayref && ++$rows < $max; + $td = Benchmark::timediff((new Benchmark), $t1); + printf("$rows fetches: ".Benchmark::timestr($td)."\n"); + printf("%d per clock second, %d per cpu second\n", + $rows/($td->real ? $td->real : 1), + $rows/($td->cpu_a ? $td->cpu_a : 1)); + my $ps = (-d '/proc') ? "ps -lp " : "ps -l"; + system("echo Process memory size; $ps$$"); + print "\n"; + $sth->finish; + $dbh->disconnect; + exit 1; +} + sub test_bind_csr { local($lda) = @_; From 2b9afa15894bc3c8f653a9b73b1df230bcae1ec8 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Sun, 13 Jun 1999 19:49:19 -0500 Subject: [PATCH 043/637] import DBD-Oracle 1.02 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 1.02 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-1.02.tar.gz --- Changes | 8 ++ Oracle.pm | 6 +- Todo | 2 +- dbdimp.c | 16 +++- dbdimp.h | 4 +- oci7.c | 90 ++++++++++------- oci8.c | 282 +++++++++--------------------------------------------- t/long.t | 178 +++++++++++++++++++++++----------- t/plsql.t | 29 +++--- 9 files changed, 259 insertions(+), 356 deletions(-) diff --git a/Changes b/Changes index 390f7ac4..eb6dcd9c 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,11 @@ +Changes in DBD::Oracle 1.02 14th June 1999 + + LongReadLen no longer limited to 64KB for OCI 7 & 8! + But beware of OCI 7 bug when fetching >64KB. + See t/long.t for more details. + Fixed OCI7 ref cursor missing data row. + Fixed OCI8 LOB statement handle leak & improved trace. + Changes in DBD::Oracle 1.01 8th June 1999 Enhanced diagnostics in t/long.t test suite. diff --git a/Oracle.pm b/Oracle.pm index 37953cc3..1d10abc4 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.75 1999/06/08 00:15:02 timbo Exp $ +# $Id: Oracle.pm,v 1.76 1999/06/14 00:41:48 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce # @@ -10,7 +10,7 @@ require 5.003; -$DBD::Oracle::VERSION = '1.01'; +$DBD::Oracle::VERSION = '1.02'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -32,7 +32,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.75 $, 10); + my $Revision = substr(q$Revision: 1.76 $, 10); require_version DBI 1.02; diff --git a/Todo b/Todo index 4957bf48..d779c0c6 100644 --- a/Todo +++ b/Todo @@ -1,4 +1,4 @@ -warn when oracle .mk files redefine a macro with a different value. +OCI8 mem leak on connect warn (trace_msg?) if ORACLE_HOME changes after first connect relates to Apache::DBI scenario where changing ORACLE_HOME diff --git a/dbdimp.c b/dbdimp.c index 0a9a928d..02e6b2fb 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.56 1999/06/08 00:15:02 timbo Exp $ + $Id: dbdimp.c,v 1.57 1999/06/14 00:41:48 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -883,6 +883,9 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) if (!dbd_describe(sth_csr, imp_sth_csr)) { return 0; } +#ifndef OCI_V8_SYNTAX + imp_sth_csr->cda->rpc= 0; /* nothing already fetched into cache */ +#endif } return 1; } @@ -1348,6 +1351,7 @@ dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset) ub4 retl = 0; SV *bufsv; imp_fbh_t *fbh = &imp_sth->fbh[field]; + int ftype = fbh->ftype; bufsv = SvRV(destrv); sv_setpvn(bufsv,"",0); /* ensure it's writable string */ @@ -1366,11 +1370,15 @@ dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset) len = 65535; } - /* The +1 on field was a mistake that's too late to fix :-( */ + switch (fbh->ftype) { + case 94: ftype = 8; break; + case 95: ftype = 24; break; + } + + /* The +1 on field was a mistake that's too late to fix :-( */ if (oflng(imp_sth->cda, (sword)field+1, ((ub1*)SvPVX(bufsv)) + destoffset, len, - fbh->ftype, /* original long type */ - &retl, offset)) { + ftype, &retl, offset)) { ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oflng error"); /* XXX database may have altered the buffer contents */ return 0; diff --git a/dbdimp.h b/dbdimp.h index 2945f416..45e13def 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.34 1999/06/08 00:15:02 timbo Exp $ + $Id: dbdimp.h,v 1.35 1999/06/14 00:41:48 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -243,6 +243,8 @@ int calc_cache_rows _((int num_fields, int est_width, int cache_rows, int has_lo fb_ary_t *fb_ary_alloc _((int bufl, int size)); int ora_db_reauthenticate _((SV *dbh, imp_dbh_t *imp_dbh, char *uid, char *pwd)); +#define OTYPE_IS_LONG(t) ((t)==8 || (t)==24 || (t)==94 || (t)==95) + #ifdef OCI_V8_SYNTAX int oci_error _((SV *h, OCIError *errhp, sword status, char *what)); diff --git a/oci7.c b/oci7.c index 07e60d81..427d8824 100644 --- a/oci7.c +++ b/oci7.c @@ -1,7 +1,7 @@ /* - $Id: oci7.c,v 1.10 1999/06/05 03:23:07 timbo Exp $ + $Id: oci7.c,v 1.11 1999/06/14 00:41:48 timbo Exp $ - Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce + Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file, @@ -147,7 +147,7 @@ dbd_describe(h, imp_sth) if (imp_sth->cache_rows > 0) continue; /* no need, user specified a size */ if (dbsize==0) { /* is a LONG type or 'select NULL' */ - if (ora_dbtype_is_long(dbtype)) { + if (OTYPE_IS_LONG(dbtype)) { est_width += long_buflen; ++has_longs; /* hint to auto cache sizing code */ } @@ -222,8 +222,7 @@ dbd_describe(h, imp_sth) for(i=1; i <= num_fields && imp_sth->cda->rc != 10; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i-1]; fb_ary_t *fb_ary; - int dbtype; - int alen_incnull; + sb4 defin_len; fbh->imp_sth = imp_sth; fbh->name = (char*)cbuf_ptr; @@ -248,34 +247,33 @@ dbd_describe(h, imp_sth) fbh->prec = fbh->dbsize; } - /* Is it a LONG, LONG RAW, LONG VARCHAR or LONG VARRAW? */ - /* If so we need to implement oraperl truncation hacks. */ - /* This may change in a future release. */ - /* Note that ora_dbtype_is_long() returns alternate dbtype to use */ - if ( (dbtype = ora_dbtype_is_long(fbh->dbtype)) ) { - long lbl = (fbh->dbtype==24) ? long_buflen * 2 : long_buflen; + if (OTYPE_IS_LONG(fbh->dbtype)) { + long lbl; + if (fbh->dbtype==24 || fbh->dbtype==95) { + lbl = long_buflen * 2; + fbh->ftype = 95; /* get long in var raw form */ + } + else { + lbl = long_buflen; + fbh->ftype = 94; /* get long in var form */ + } fbh->dbsize = lbl; fbh->disize = lbl; - fbh->ftype = dbtype; /* get long in non-var form */ - imp_sth->t_dbsize += lbl; - alen_incnull = 0; + defin_len = fbh->disize + 4; } else { /* for the time being we fetch everything (except longs) */ /* as strings, that'll change (IV, NV and binary data etc) */ fbh->ftype = 5; /* oraperl used 5 'STRING' */ - /* dbsize can be zero for 'select NULL ...' */ - imp_sth->t_dbsize += fbh->dbsize; - alen_incnull = 1; + defin_len = fbh->disize + 1; /* +1: STRING null */ } + /* dbsize can be zero for 'select NULL ...' */ + imp_sth->t_dbsize += fbh->dbsize; - fbh->fb_ary = fb_ary = fb_ary_alloc( - fbh->disize + alen_incnull, /* +1: STRING null terminator */ - imp_sth->cache_rows - ); + fbh->fb_ary = fb_ary = fb_ary_alloc(defin_len, imp_sth->cache_rows); /* DEFINE output column variable storage */ - if (odefin(imp_sth->cda, i, fb_ary->abuf, fb_ary->bufl, + if (odefin(imp_sth->cda, i, fb_ary->abuf, defin_len, fbh->ftype, -1, fb_ary->aindp, (text*)0, -1, -1, fb_ary->arlen, fb_ary->arcode)) { warn("odefin error on %s: %d", fbh->name, imp_sth->cda->rc); @@ -353,6 +351,10 @@ dbd_st_fetch(sth, imp_sth) } imp_sth->next_entry = 0; imp_sth->in_cache = imp_sth->cda->rpc - previous_rpc; + if (debug >= 4) + fprintf(DBILOGFP, + " dbd_st_fetch load-cache: prev rpc %d, new rpc %ld, in_cache %d\n", + previous_rpc, (long)imp_sth->cda->rpc, imp_sth->in_cache); assert(imp_sth->in_cache > 0); } @@ -372,8 +374,9 @@ dbd_st_fetch(sth, imp_sth) fb_ary_t *fb_ary = fbh->fb_ary; int rc = fb_ary->arcode[cache_entry]; SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */ + ub4 datalen; - if (rc == 1406 && ora_dbtype_is_long(fbh->dbtype)) { + if (rc == 1406 && OTYPE_IS_LONG(fbh->ftype)) { /* We have a LONG field which has been truncated. */ int oraperl = DBIc_COMPAT(imp_sth); if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { @@ -388,32 +391,45 @@ dbd_st_fetch(sth, imp_sth) } if (rc == 0) { /* the normal case */ - int datalen = fb_ary->arlen[cache_entry]; - char *p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; - /* if ChopBlanks check for Oracle CHAR type (blank padded) */ - if (ChopBlanks && fbh->dbtype == 96) { - while(datalen && p[datalen - 1]==' ') - --datalen; + char *p; + if (fbh->ftype == 94 || fbh->ftype == 95) { /* LONG VAR */ + p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; + datalen = *(ub4*)p; /* XXX alignment ? */ + p += 4; + sv_setpvn(sv, p, (STRLEN)datalen); + } + else { + datalen = fb_ary->arlen[cache_entry]; + p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; + /* if ChopBlanks check for Oracle CHAR type (blank padded) */ + if (ChopBlanks && fbh->dbtype == 96) { + while(datalen && p[datalen - 1]==' ') + --datalen; + } + sv_setpvn(sv, p, (STRLEN)datalen); } - sv_setpvn(sv, p, (STRLEN)datalen); } else if (rc == 1405) { /* field is null - return undef */ + datalen = 0; (void)SvOK_off(sv); } else { /* See odefin rcode arg description in OCI docs */ char buf[200]; char *hint = ""; + datalen = 0; /* These may get more case-by-case treatment eventually. */ if (rc == 1406) { /* field truncated (see above) */ - /* Copy the truncated value anyway, it may be of use, */ - /* but it'll only be accessible via prior bind_column() */ - sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], - fb_ary->arlen[cache_entry]); - if (ora_dbtype_is_long(fbh->dbtype)) { /* double check */ + if (OTYPE_IS_LONG(fbh->ftype)) { /* double check */ hint = (DBIc_LongReadLen(imp_sth) > 65535) ? ", DBI attribute LongTruncOk not set and/or LongReadLen too small or > 65535 max" : ", DBI attribute LongTruncOk not set and/or LongReadLen too small"; } + else { + /* Copy the truncated value anyway, it may be of use, */ + /* but it'll only be accessible via prior bind_column() */ + sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], + fb_ary->arlen[cache_entry]); + } } else { SvOK_off(sv); /* set field that caused error to undef */ @@ -427,8 +443,8 @@ dbd_st_fetch(sth, imp_sth) } if (debug >= 5) - fprintf(DBILOGFP, " %d (rc=%d): %s\n", - i, rc, neatsvpv(sv,0)); + fprintf(DBILOGFP, " %d (rc=%d, otype %d, len %lu): %s\n", + i, rc, fbh->dbtype, datalen, neatsvpv(sv,0)); } /* update cache counters */ diff --git a/oci8.c b/oci8.c index 9203b632..ba444f13 100644 --- a/oci8.c +++ b/oci8.c @@ -1,5 +1,5 @@ /* - $Id: oci8.c,v 1.18 1999/06/05 03:23:07 timbo Exp $ + $Id: oci8.c,v 1.19 1999/06/14 00:41:48 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -275,6 +275,18 @@ dbd_phs_out(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, } +static int +fetch_func_varfield(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) +{ + fb_ary_t *fb_ary = fbh->fb_ary; + char *p = (char*)&fb_ary->abuf[0]; + ub4 datalen = *(ub4*)p; /* XXX alignment ? */ + p += 4; + sv_setpvn(dest_sv, p, (STRLEN)datalen); + return 1; +} + + /* ------ */ @@ -461,12 +473,12 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) ub4 loblen = 0; ub4 buflen; ub4 amtp = 0; - OCILobLocator *lobl = (OCILobLocator*)fbh->desc_h; + OCILobLocator *lobloc = (OCILobLocator*)fbh->desc_h; sword status; /* this function is not called for NULL lobs */ - status = OCILobGetLength(imp_sth->svchp, imp_sth->errhp, lobl, &loblen); + status = OCILobGetLength(imp_sth->svchp, imp_sth->errhp, lobloc, &loblen); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobGetLength"); return 0; @@ -500,7 +512,7 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) SvGROW(dest_sv, buflen+1); if (loblen > 0) { - status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobl, + status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobloc, &amtp, 1, SvPVX(dest_sv), buflen, 0, 0, 0, SQLCS_IMPLICIT); if (DBIS->debug >= 3) fprintf(DBILOGFP, @@ -651,16 +663,17 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) break; case 8: /* LONG */ - fbh->dbsize = long_readlen; - fbh->disize = fbh->dbsize; - fbh->ftype = 8; + fbh->disize = long_readlen; + fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; + fbh->ftype = 94; /* VAR form */ + fbh->fetch_func = fetch_func_varfield; ++has_longs; break; case 24: /* LONG RAW */ - fbh->dbsize = long_readlen * 2; - fbh->disize = fbh->dbsize; - avg_width = fbh->dbsize; - fbh->ftype = 24; + fbh->disize = long_readlen * 2; + fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; + fbh->ftype = 95; /* VAR form */ + fbh->fetch_func = fetch_func_varfield; ++has_longs; break; @@ -744,16 +757,21 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) for(i=1; i <= num_fields; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i-1]; + int ftype = fbh->ftype; + /* add space for STRING null term, or VAR len prefix */ + sb4 define_len = (ftype==94||ftype==95) ? fbh->disize+4 : fbh->disize; fb_ary_t *fb_ary; - fbh->fb_ary = fb_ary_alloc(fbh->disize+1 /* +1: STRING null terminator */, 1); + fbh->fb_ary = fb_ary_alloc(define_len, 1); fb_ary = fbh->fb_ary; status = OCIDefineByPos(imp_sth->stmhp, &fbh->defnp, imp_sth->errhp, (ub4) i, (fbh->desc_h) ? (dvoid*)&fbh->desc_h : (dvoid*)fb_ary->abuf, - (fbh->desc_h) ? -1 : fbh->disize, + (fbh->desc_h) ? -1 : define_len, fbh->ftype, - fb_ary->aindp, fb_ary->arlen, fb_ary->arcode, OCI_DEFAULT); + fb_ary->aindp, + (ftype==94||ftype==95) ? NULL : fb_ary->arlen, + fb_ary->arcode, OCI_DEFAULT); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIDefineByPos"); return 0; @@ -829,13 +847,12 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) err = 0; for(i=0; i < num_fields; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i]; - int cache_entry = 0; fb_ary_t *fb_ary = fbh->fb_ary; - int rc = fb_ary->arcode[cache_entry]; + int rc = fb_ary->arcode[0]; SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */ if (rc == 1406 /* field was truncated */ - && ora_dbtype_is_long(fbh->dbtype) /* field is a LONG */ + && ora_dbtype_is_long(fbh->dbtype)/* field is a LONG */ ) { int oraperl = DBIc_COMPAT(imp_sth); if (DBIc_has(imp_sth,DBIcf_LongTruncOk) || (oraperl && SvIV(ora_trunc))) { @@ -855,8 +872,8 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) ++err; /* fetch_func already called oci_error */ } else { - int datalen = fb_ary->arlen[cache_entry]; - char *p = (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl]; + int datalen = fb_ary->arlen[0]; + char *p = (char*)&fb_ary->abuf[0]; /* if ChopBlanks check for Oracle CHAR type (blank padded) */ if (ChopBlanks && fbh->dbtype == 96) { while(datalen && p[datalen - 1]==' ') @@ -876,8 +893,8 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) if (!fbh->fetch_func) { /* Copy the truncated value anyway, it may be of use, */ /* but it'll only be accessible via prior bind_column() */ - sv_setpvn(sv, (char*)&fb_ary->abuf[cache_entry * fb_ary->bufl], - fb_ary->arlen[cache_entry]); + sv_setpvn(sv, (char*)&fb_ary->abuf[0], + fb_ary->arlen[0]); } if (ora_dbtype_is_long(fbh->dbtype)) /* double check */ hint = ", LongReadLen too small and/or LongTruncOk not set"; @@ -1307,11 +1324,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl imp_fbh_t *fbh = &lr->fbh_ary[i]; phs_t *phs = (phs_t*)fbh->special; ub4 amtp = SvCUR(phs->sv); - if (DBIS->debug >= 3) - fprintf(DBILOGFP, - " lob refetch %d for '%s' param: ftype %d, len %ld\n", - i+1,fbh->name, fbh->dbtype, amtp); - if (amtp > 0) { /* since amtp & OCI_ONE_PIECE fail (OCI 8.0.4) */ + if (amtp > 0) { /* since amtp==0 & OCI_ONE_PIECE fail (OCI 8.0.4) */ status = OCILobWrite(imp_sth->svchp, errhp, fbh->desc_h, &amtp, 1, SvPVX(phs->sv), amtp, OCI_ONE_PIECE, 0,0, 0,SQLCS_IMPLICIT); @@ -1319,6 +1332,11 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl else { status = OCILobTrim(imp_sth->svchp, errhp, fbh->desc_h, 0); } + if (DBIS->debug >= 3) + fprintf(DBILOGFP, + " lob refetch %d for '%s' param: ftype %d, len %ld: %s %s\n", + i+1,fbh->name, fbh->dbtype, amtp, + (amtp > 0) ? "LobWrite" : "LobTrim", oci_status_name(status)); if (status != OCI_SUCCESS) { return oci_error(sth, errhp, status, "OCILobTrim/OCILobWrite/LOB refetch"); } @@ -1332,7 +1350,7 @@ ora_free_lob_refetch(SV *sth, imp_sth_t *imp_sth) { lob_refetch_t *lr = imp_sth->lob_refetch; int i; - sword status = OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); + sword status = OCIHandleFree(lr->stmthp, OCI_HTYPE_STMT); if (status != OCI_SUCCESS) oci_error(sth, imp_sth->errhp, status, "ora_free_lob_refetch/OCIHandleFree"); for(i=0; i < lr->num_fields; ++i) { @@ -1346,214 +1364,4 @@ ora_free_lob_refetch(SV *sth, imp_sth_t *imp_sth) } - -#ifdef OCI8_RSET_TEST_CODE - -#define VARCHAR2_TYPE 1 -#define NUMBER_TYPE 2 -#define INT_TYPE 3 -#define FLOAT_TYPE 4 -#define STRING_TYPE 5 -#define ROWID_TYPE 11 -#define DATE_TYPE 12 -#define LONG_RAW 24 -#define LONG_VARRAW 95 - -/* - * Macro and Other Definitions - */ -#define UNREFERENCED_PARAMETER(x) ((x)=(x)) -#define NO_DATA_FOUND 1403 -#define OCI8_INITIALIZED 1 -#define OCI8_SERVER_ATTACHED 2 -#define OCI8_SESSION_BEGAN 3 -#define BOOL short int -#define UINT unsigned int - -/* - * Oracle 8 OCI Global Variables for this Sample - */ -OCIEnv *or8EnvHandle; -OCIError *or8ErrorHandle; -OCIStmt *or8StmtHandle; -OCIStmt *or8CursorStmtHandle; -OCISvcCtx *or8SrcHandle; - -typedef dvoid * PDV; - -/* - * Function Prototypes - */ - -BOOL oci8Error (sb2 sb2ErrorCode); - -/*****************************************************************/ -BOOL oci8Error (sb2 sb2ErrorCode) -{ - text errbuf[512]; - sb4 errcode; - switch (sb2ErrorCode) { - case OCI_SUCCESS: - break; - case OCI_SUCCESS_WITH_INFO: - printf ("Error - OCI_SUCCESS_WITH_INFO\n"); - break; - case OCI_NEED_DATA: - printf ("Error - OCI_NEED_DATA\n"); - break; - case OCI_NO_DATA: - printf ("Error - OCI_NO_DATA\n"); - break; - case OCI_ERROR: - OCIErrorGet ((dvoid *) or8ErrorHandle, (ub4) 1, (OraText *) - NULL, &errcode, errbuf, (ub4) sizeof(errbuf), - (ub4) OCI_HTYPE_ERROR); - printf ("Error - %s\n", errbuf); - break; - case OCI_INVALID_HANDLE: - printf ("Error - OCI_INVALID_HANDLE\n"); - break; - case OCI_STILL_EXECUTING: - printf ("Error - OCI_STILL_EXECUTE\n"); - break; - case OCI_CONTINUE: - printf ("Error - OCI_CONTINUE\n"); - break; - default: - break; - } - return ((sb2ErrorCode==OCI_SUCCESS) ? FALSE : TRUE ); -} - -/*****************************************************************/ - -int rset_main (imp_dbh_t *imp_dbh) -{ - sword rc; - static unsigned char *szPLSQLBlock = (unsigned char *) -"BEGIN RefTest.GetEmpData (:DEPTNO , :empCursor); END;"; - - static char *pszUserName = "scott"; - static char *pszPassword = "tiger"; - static char *pszConnection = "firstdb"; - - sb2 rv; - int bv_deptno = 10; - char bv_ename[40]; - int bv_ename_len = 40; - OCIBind *ptrBindHandle1; - OCIBind *ptrBindHandle2; - OCIDefine *or8Define1; - char *pszBindVarName; - char *pszBindVarName2; - - /* oci8Connect(pszUserName, pszPassword, pszConnection); */ - or8ErrorHandle= imp_dbh->errhp; - or8SrcHandle = imp_dbh->svchp; - or8EnvHandle = imp_dbh->envhp; - - /* - * Allocate Stmt handle - */ - rv = OCIHandleAlloc ((PDV) or8EnvHandle, (PDV*) &or8StmtHandle, - OCI_HTYPE_STMT, 0, (PDV*) 0); - if (rv) { exit(1); } - - /* - * Allocate Stmt handle for cursor resultset - */ - rv = OCIHandleAlloc ((PDV) or8EnvHandle, (PDV*) &or8CursorStmtHandle, - OCI_HTYPE_STMT, 0, (PDV*) 0); - if (rv) { exit(1); } - - /* - * Prepare statement - */ - rv = OCIStmtPrepare (or8StmtHandle, - or8ErrorHandle, - (OraText *) szPLSQLBlock, - (ub4)strlen((char *)szPLSQLBlock), - (ub4)OCI_NTV_SYNTAX, - (ub4)OCI_DEFAULT); - if (rv) { puts("OCIStmtPrepare"); oci8Error (rv); exit(1); } - -{ ub2 stmt_type = 0; - OCIAttrGet(or8StmtHandle, OCI_HTYPE_STMT, &stmt_type, 0, OCI_ATTR_STMT_TYPE, or8ErrorHandle); -warn("stmt_type=%d\n",stmt_type); -} - - pszBindVarName = ":DEPTNO"; - - rv = OCIBindByName( or8StmtHandle, - (OCIBind **)&ptrBindHandle1, - or8ErrorHandle, - (OraText *) pszBindVarName, - -1, /* (sb4) strlen(pszBindVarName), */ - (dvoid *) &bv_deptno, - (sb4) sizeof (bv_deptno), - (ub2) SQLT_INT, - (dvoid *) 0, - (ub2 *) 0, - (ub2 *) 0, - (ub4) 0, - (ub4 *)0, - (ub4) OCI_DEFAULT); - if (rv) { puts("OCIBindByName"); oci8Error (rv); exit(1); } - - pszBindVarName2 = ":empCursor"; - rv = OCIBindByName(or8StmtHandle, - (OCIBind **)&ptrBindHandle2, - or8ErrorHandle, - (OraText *) pszBindVarName2, - -1, /* (sb4) strlen(pszBindVarName2), */ - (dvoid *)&or8CursorStmtHandle, - (sb4) 0, - SQLT_RSET, - (dvoid *) 0, - (ub2 *) 0, - (ub2 *) 0, - (ub4) 0, - (ub4 *)0, - (ub4) OCI_DEFAULT); - if (rv) { puts("OCIBindByName 2"); oci8Error (rv); exit(1); } - - rv = OCIStmtExecute(or8SrcHandle, - or8StmtHandle, - or8ErrorHandle, - (ub4) 1, - (ub4) 0, - (CONST OCISnapshot *) NULL, - (OCISnapshot *) NULL, - OCI_DEFAULT); - if (rv) { puts("execute"); oci8Error (rv); exit(1); } - - rv = OCIDefineByPos(or8CursorStmtHandle, - (OCIDefine **)&or8Define1, - or8ErrorHandle, - (ub4) 1, - (dvoid *)&bv_ename, - (sb4) bv_ename_len, - SQLT_STR, - (dvoid *)0, - 0, 0, - OCI_DEFAULT); - - if (rv) { puts("OCIDefineByPos post execute"); oci8Error (rv); exit(1); } - - rc = OCIStmtFetch(or8CursorStmtHandle, or8ErrorHandle, 1, 0, 0); - while (rc == OCI_SUCCESS) { - printf("[%s]\n", bv_ename); - rc = OCIStmtFetch(or8CursorStmtHandle, or8ErrorHandle, 1, 0, 0); - } - if (rc != OCI_NO_DATA) { - oci8Error (rc); - exit(1); - } - - oci8Error (OCIHandleFree ((PDV) or8StmtHandle, OCI_HTYPE_STMT)); - return 1; -} -#endif /* OCI8_RSET_TEST_CODE */ - - #endif diff --git a/t/long.t b/t/long.t index 11715d7f..51d04b75 100644 --- a/t/long.t +++ b/t/long.t @@ -4,11 +4,14 @@ use DBI; use DBD::Oracle qw(:ora_types ORA_OCI); use strict; +# +# Search for 'ocibug' to find code related to OCI LONG bugs. +# + $| = 1; my $t = 0; my $failed = 0; -my $oflng; -my $lrl_limit; +my %ocibug; my $table = "dbd_ora__drop_me"; my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; @@ -30,10 +33,20 @@ unless(create_table("lng LONG")) { } -my @test_sets = ([ "LONG", undef ], [ "LONG RAW", ORA_LONGRAW ]); -push @test_sets, [ "CLOB", ORA_CLOB ], [ "BLOB", ORA_BLOB ] if ORA_OCI >= 8; +my @test_sets = ( + [ "LONG", undef ], + [ "LONG RAW", ORA_LONGRAW ] +); +push @test_sets, + [ "CLOB", ORA_CLOB ], + [ "BLOB", ORA_BLOB ] + if ORA_OCI >= 8; + +# Set size of test data (in 10KB units) +# Minimum value 3 (else tests fail because of assumptions) +# Normal value 8 (to test 64KB threshold well) +my $sz = 8; -my $sz = 8; # Min 8 == 80KB, max = ??? my $tests; my $tests_per_set = 35; $tests = @test_sets * $tests_per_set; @@ -50,16 +63,29 @@ foreach (@test_sets) { sub run_long_tests { my ($type_name, $type_num) = @_; -my $long_data0 = "\177.\0.X" x 2048; # 10KB < 64KB -my $long_data1 = ("1234567890" x 1024) x $sz; # 520KB >> 64KB & > long_data2 -my $long_data2 = ("abcdefabcd" x 1024) x 7; # 70KB > 64KB & < long_data1 - -$long_data2 = "00FF" x (length($long_data2) / 2) if $type_name =~ /RAW/i; - -print "long_data0 length ",length($long_data0),"\n"; -print "long_data1 length ",length($long_data1),"\n"; -print "long_data2 length ",length($long_data2),"\n"; +# relationships between these lengths are important # e.g. +my $long_data0 = ("0\177x\0X" x 2048) x (1 ); # 10KB < 64KB +my $long_data1 = ("1234567890" x 1024) x ($sz ); # 80KB >> 64KB && > long_data2 +my $long_data2 = ("2bcdefabcd" x 1024) x ($sz-1); # 70KB > 64KB && < long_data1 + +$long_data0 = "00FF" x (length($long_data0) / 2) if $type_name =~ /RAW/i; + +my $len_data0 = length($long_data0); +my $len_data1 = length($long_data1); +my $len_data2 = length($long_data2); +print "long_data0 length $len_data0\n"; +print "long_data1 length $len_data1\n"; +print "long_data2 length $len_data2\n"; + +# warn if some of the key aspects of the data sizing are tampered with +warn "long_data0 is > 64KB: $len_data0\n" + if $len_data0 > 65535; +warn "long_data1 is < 64KB: $len_data1\n" + if $len_data1 < 65535; +warn "long_data2 is not smaller than $long_data1 ($len_data2 > $len_data1)\n" + if $len_data2 >= $len_data1; + if (!create_table("lng $type_name", 1)) { # typically OCI 8 client talking to Oracle 7 database warn "Unable to create test table for '$type_name' data ($DBI::err). Tests skipped.\n"; @@ -76,53 +102,85 @@ ok(0, $sth->execute(41, $long_data1), 1); ok(0, $sth->execute(42, $long_data2), 1); -print " --- fetch it back again -- truncated - LongTruncOk == 1\n"; +print " --- fetch $type_name data back again -- truncated - LongTruncOk == 1\n"; $dbh->{LongReadLen} = 20; -# This behaviour isn't specified anywhere, sigh: -my $out_len = ($type_name =~ /RAW/i) ? 40 : 20; $dbh->{LongTruncOk} = 1; +print "LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"; + +# This behaviour isn't specified anywhere, sigh: +my $out_len = $dbh->{LongReadLen}; +$out_len *= 2 if ($type_name =~ /RAW/i); + ok(0, $sth = $dbh->prepare("select * from $table order by idx"), 1); ok(0, $sth->execute, 1); ok(0, $tmp = $sth->fetchall_arrayref, 1); -ok(0, $tmp->[0][1] eq substr($long_data0,0,$out_len), length($tmp->[0][1])); -ok(0, $tmp->[1][1] eq substr($long_data1,0,$out_len), length($tmp->[1][1])); +ok(0, $tmp->[0][1] eq substr($long_data0,0,$out_len), + cdif($tmp->[0][1], substr($long_data0,0,$out_len), "Len ".length($tmp->[0][1])) ); +ok(0, $tmp->[1][1] eq substr($long_data1,0,$out_len), + cdif($tmp->[1][1], substr($long_data1,0,$out_len), "Len ".length($tmp->[1][1])) ); ok(0, $tmp->[2][1] eq substr($long_data2,0,$out_len), cdif($tmp->[2][1], substr($long_data2,0,$out_len), "Len ".length($tmp->[2][1])) ); -print " --- fetch it back again -- truncated - LongTruncOk == 0\n"; -$dbh->{LongReadLen} = 1024 * 50; # first fits, second doesn't -$dbh->{LongTruncOk} = 0; +print " --- fetch $type_name data back again -- truncated - LongTruncOk == 0\n"; +$dbh->{LongReadLen} = $len_data1 - 10; # so $long_data0 fits but long_data1 doesn't +$dbh->{LongReadLen} = $dbh->{LongReadLen} / 2 if $type_name =~ /RAW/i; +$dbh->{LongTruncOk} = 0; +print "LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"; + ok(0, $sth = $dbh->prepare("select * from $table order by idx"), 1); ok(0, $sth->execute, 1); + ok(0, $tmp = $sth->fetchrow_arrayref, 1); ok(0, $tmp->[1] eq $long_data0, length($tmp->[1])); -ok(0, !defined $sth->fetchrow_arrayref, 1); -ok(0, $sth->err == 1406 || $sth->err == 24345, $sth->errstr); + +ok(0, !defined $sth->fetchrow_arrayref, + "truncation error not triggered " + ."(LongReadLen $dbh->{LongReadLen}, data ".length($tmp->[1]||0).")"); +$tmp = $sth->err || 0; +ok(0, $tmp == 1406 || $tmp == 24345, 1); -print " --- fetch it back again -- complete - LongTruncOk == 0\n"; -$dbh->{LongReadLen} = (65535 * 10) - 100; -$dbh->{LongTruncOk} = 0; +print " --- fetch $type_name data back again -- complete - LongTruncOk == 0\n"; +$dbh->{LongReadLen} = $len_data1 +1000; +$dbh->{LongTruncOk} = 0; +print "LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"; + ok(0, $sth = $dbh->prepare("select * from $table order by idx"), 1); +#$sth->trace(4); ok(0, $sth->execute, 1); + ok(0, $tmp = $sth->fetchrow_arrayref, 1); ok(0, $tmp->[1] eq $long_data0, length($tmp->[1])); -if ($tmp = $sth->fetchrow_arrayref) { - ok(0, $tmp, 1); - ok(0, $tmp->[1] eq $long_data1, length($tmp->[1])); - ok(0, $tmp = $sth->fetchrow_arrayref, 1); - ok(0, $tmp->[1] eq $long_data2, - cdif($tmp->[1],$long_data2, "Len ".length($tmp->[1])) ); +ok(0, $tmp = $sth->fetchrow_arrayref, 1); +ok(0, $tmp->[1] eq $long_data1, length($tmp->[1])); + +ok(0, $tmp = $sth->fetchrow_arrayref, 1); +if ($tmp->[1] eq $long_data2) { + ok(0, 1); +} +elsif (length($tmp->[1]) == length($long_data1) + && DBD::Oracle::ORA_OCI() == 7 + && substr($tmp->[1], 0, length($long_data2)) eq $long_data2 +) { + print "OCI7 buffer overwite bug detected\n"; + $ocibug{LongReadLen} = __LINE__; # see also blob_read tests below + # The bug: + # If you fetch a LONG field and then fetch another row + # which has a LONG field shorter than the previous + # then the second long will appear to have the + # longer portion of first appended to it! + ok(0, 1); } else { - $lrl_limit = 1; - ok(0,1); ok(0,1); ok(0,1); ok(0,1); + ok(0, $tmp->[1] eq $long_data2, + cdif($tmp->[1],$long_data2, "Len ".length($tmp->[1])) ); } +$sth->trace(0); -print " --- fetch it back again -- via blob_read\n"; +print " --- fetch $type_name data back again -- via blob_read\n"; if (ORA_OCI >= 8 && $type_name =~ /LONG/i) { print "Skipped blob_read tests for LONGs with OCI8 - not currently supported.\n"; foreach (1..11) { ok(0,1) } @@ -136,11 +194,11 @@ ok(0, $sth->execute, 1); ok(0, $tmp = $sth->fetchrow_arrayref, 1); ok(0, blob_read_all($sth, 1, \$p1, 4096) == length($long_data0), 1); -ok(0, $p1 eq $long_data0, 1); +ok(0, $p1 eq $long_data0, cdif($p1, $long_data0)); ok(0, $tmp = $sth->fetchrow_arrayref, 1); ok(0, blob_read_all($sth, 1, \$p1, 12345) == length($long_data1), 1); -ok(0, $p1 eq $long_data1, 1); +ok(0, $p1 eq $long_data1, cdif($p1, $long_data1)); ok(0, $tmp = $sth->fetchrow_arrayref, 1); my $len = blob_read_all($sth, 1, \$p1, 34567); @@ -150,17 +208,21 @@ if ($len == length($long_data2)) { # Oracle may return the right length but corrupt the string. ok(0, $p1 eq $long_data2, cdif($p1, $long_data2) ); } -elsif ($len == length($long_data1) && DBD::Oracle::ORA_OCI() == 7) { - $oflng = __LINE__; - # The bug: - # If you use blob_read to read a LONG field - # and then fetch another row - # and use blob_read to read that LONG field - # If the second LONG is shorter than the first - # then the second long will appear to have the - # longer portion of first appended to it. - ok(0, 1); - ok(0, 1, 0); +elsif ($len == length($long_data1) + && DBD::Oracle::ORA_OCI() == 7 + && substr($p1, 0, length($long_data2)) eq $long_data2 +) { + print "OCI7 buffer overwite bug detected\n"; + $ocibug{blob_read} = __LINE__; # see also blob_read tests below + # The bug: + # If you use blob_read to read a LONG field + # and then fetch another row + # and use blob_read to read that LONG field + # If the second LONG is shorter than the first + # then the second long will appear to have the + # longer portion of first appended to it. + ok(0, 1); + ok(0, 1, 0); } else { ok(0, 0, "Fetched length $len, expected ".length($long_data2)); @@ -169,15 +231,13 @@ else { } # end of run_long_tests -if ($oflng) { - warn "\nYour version of Oracle 7 OCI has a bug that effects the (undocumented) blob_read method.\n"; - warn "See the t/long.t script near line $oflng for more information.\n"; - warn "(You can safely ignore this if you don't use the blob_read method.)\n"; -} - -if ($lrl_limit) { - warn "\nThe maximum valid value of \$h->{LongReadLen} when fetching LONGs is currently 65535.\n"; - warn "There's no limit when fetching LOB types.\n" if ORA_OCI() >= 8; +if (%ocibug) { + my @lines = sort values %ocibug; + warn "\n\aYour version of Oracle 7 OCI has a bug that affects fetching LONG data.\n"; + warn "See the t/long.t script near lines @lines for more information.\n"; + warn "You can safely ignore this if: You don't fetch data from LONG fields;\n"; + warn "Or the LONG data you fetch is never longer than 65535 bytes long;\n"; + warn "Or you only fetch one LONG record in the life of a statement handle.\n"; } if ($failed) { @@ -192,6 +252,8 @@ if ($failed) { warn "Meanwhile, if the other tests have passed you can use DBD::Oracle.\n\n"; } +sleep 6 if $failed || %ocibug; + exit 0; BEGIN { $tests = 27 } END { diff --git a/t/plsql.t b/t/plsql.t index f3585581..f7de6e1d 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -42,7 +42,7 @@ if ($dbh->err && ($dbh->err==900 || $dbh->err==6553 || $dbh->err==600)) { my $tests; print "1..$tests\n"; -my($csr, $p1, $p2, $tmp); +my($csr, $p1, $p2, $tmp, @tmp); #DBI->trace(4,"trace.log"); @@ -235,7 +235,8 @@ $dbh->{PrintError} = 0; if (1) { my $cur_query = q{ SELECT object_name, owner FROM all_objects - WHERE object_name LIKE :p1 ORDER BY object_name, owner + WHERE object_name LIKE :p1 and ROWNUM <= 3 + ORDER BY object_name, owner }; my $cur1 = 42; #$dbh->trace(4); @@ -247,29 +248,27 @@ if (1) { ok(0, $parent->bind_param_inout(":cur1", \$cur1, 0, { ora_type => ORA_RSET } )); ok(0, $parent->execute()); my @r; - push @r,$cur1->fetchrow_array; - push @r,$cur1->fetchrow_array; - push @r,$cur1->fetchrow_array; - $cur1->finish; + push @r, @tmp while @tmp = $cur1->fetchrow_array; + ok(0, @r == 3*2, "rows: ".@r); #$dbh->trace(0); $parent->trace(0); + + # compare results with normal execution of query my $s1 = $dbh->selectall_arrayref($cur_query, undef, "V%"); - my @s1 = map { @$_ } @{$s1}[0..2]; - ok(0, "@r" eq "@s1", "r=(@r), s=(@s1)"); + my @s1 = map { @$_ } @$s1; + ok(0, "@r" eq "@s1", "\nref=(@r),\nsql=(@s1)"); - # --- test rebind and execute + # --- test re-bind and re-execute of same 'parent' statement my $cur1_str = "$cur1"; #$dbh->trace(4); $parent->trace(4); ok(0, $parent->bind_param(":p1", "U%")); ok(0, $parent->execute()); ok(0, "$cur1" ne $cur1_str); # must be ref to new handle object @r = (); - push @r,$cur1->fetchrow_array; - push @r,$cur1->fetchrow_array; - push @r,$cur1->fetchrow_array; $cur1->finish; + push @r, @tmp while @tmp = $cur1->fetchrow_array; #$dbh->trace(0); $parent->trace(0); $cur1->trace(0); my $s2 = $dbh->selectall_arrayref($cur_query, undef, "U%"); - my @s2 = map { @$_ } @{$s2}[0..2]; - ok(0, "@r" eq "@s2", "r=(@r), s=(@s2)"); + my @s2 = map { @$_ } @$s2; + ok(0, "@r" eq "@s2", "\nref=(@r),\nsql=(@s2)"); } @@ -286,7 +285,7 @@ $dbh->disconnect; ok(0, !$dbh->ping); exit 0; -BEGIN { $tests = 62 } +BEGIN { $tests = 63 } # end. __END__ From 7c9b69b00f529b09a02c68b1b58cab579a6a06b6 Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Sun, 11 Jul 1999 22:30:24 -0500 Subject: [PATCH 044/637] import DBD-Oracle 1.03 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 1.03 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-1.03.tar.gz --- Changes | 14 ++ MANIFEST | 25 ++-- Makefile.PL | 307 +++++++++++++++++++++++++++--------------- Oracle.ex/Readme | 36 +++++ Oracle.ex/bind.pl | 45 +++++++ Oracle.ex/commit.pl | 72 ++++++++++ Oracle.ex/ex.pl | 47 +++++++ Oracle.ex/japh | 52 +++++++ Oracle.ex/mktable.pl | 102 ++++++++++++++ Oracle.ex/oradump.pl | 42 ++++++ Oracle.ex/proc.pl | 148 ++++++++++++++++++++ Oracle.ex/sql | 235 ++++++++++++++++++++++++++++++++ Oracle.ex/tabinfo.pl | 68 ++++++++++ Oracle.h | 5 +- Oracle.pm | 237 +++++++++++++++++++++++++++----- README | 12 +- README.help | 49 +++---- README.sec | 132 ++++++++++++++++++ dbdimp.c | 175 +++++++++++++++--------- dbdimp.h | 25 ++-- oci8.c | 225 +++++++++++++++++++------------ ocitrace.h | 245 +++++++++++++++++++++++++++++++++ ora_explain.PL | 69 +++++++--- oraperl.ex/Readme | 38 ------ oraperl.ex/bind.pl | 36 ----- oraperl.ex/commit.pl | 58 -------- oraperl.ex/ex.pl | 35 ----- oraperl.ex/japh | 54 -------- oraperl.ex/mkdb.pl | 172 ----------------------- oraperl.ex/oradump.pl | 28 ---- oraperl.ex/sql | 225 ------------------------------- oraperl.ex/tabinfo.pl | 60 --------- t/base.t | 2 +- t/general.t | 2 +- t/long.t | 7 +- t/plsql.t | 2 +- t/reauth.t | 2 +- 37 files changed, 2013 insertions(+), 1075 deletions(-) create mode 100644 Oracle.ex/Readme create mode 100755 Oracle.ex/bind.pl create mode 100755 Oracle.ex/commit.pl create mode 100755 Oracle.ex/ex.pl create mode 100755 Oracle.ex/japh create mode 100755 Oracle.ex/mktable.pl create mode 100755 Oracle.ex/oradump.pl create mode 100755 Oracle.ex/proc.pl create mode 100755 Oracle.ex/sql create mode 100755 Oracle.ex/tabinfo.pl create mode 100644 README.sec create mode 100644 ocitrace.h delete mode 100644 oraperl.ex/Readme delete mode 100755 oraperl.ex/bind.pl delete mode 100755 oraperl.ex/commit.pl delete mode 100755 oraperl.ex/ex.pl delete mode 100755 oraperl.ex/japh delete mode 100755 oraperl.ex/mkdb.pl delete mode 100755 oraperl.ex/oradump.pl delete mode 100755 oraperl.ex/sql delete mode 100644 oraperl.ex/tabinfo.pl diff --git a/Changes b/Changes index eb6dcd9c..790153f7 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,17 @@ +Changes in DBD::Oracle 1.03 12th July 1999 + + Added "perl Makefile.PL -b" configure option. Links DBD::Oracle + using same linker args as Oracle's own OCI demo applications. + Added connect("dbi:Oracle:host=foo;sid=bar", ...) syntax. + Added OCI8 function trace at level 6, useful for Oracle support. + Added ora_session_mode attribute to connect. + Added test for Oracle security problem. See README.sec. + Updated ora_explain tool to v1.1 thanks to Alan Burlison. + Contributions from Michael Chase (plus docs from Andy Duncan): + Documented plsql_errstr & dbms_output_enable/_put/_get. + Enhanced $dbh->func('plsql_errstr') output. + Replaced old Oraperl examples with DBI/DBD::Oracle ones. + Changes in DBD::Oracle 1.02 14th June 1999 LongReadLen no longer limited to 64KB for OCI 7 & 8! diff --git a/MANIFEST b/MANIFEST index e48b6f73..badef179 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,35 +1,38 @@ Changes MANIFEST Makefile.PL +Oracle.ex/Readme +Oracle.ex/bind.pl +Oracle.ex/commit.pl +Oracle.ex/ex.pl +Oracle.ex/japh +Oracle.ex/mktable.pl +Oracle.ex/oradump.pl +Oracle.ex/proc.pl +Oracle.ex/sql +Oracle.ex/tabinfo.pl Oracle.h Oracle.pm Oracle.xs Oraperl.pm README README.clients +README.explain README.help README.login README.longs +README.sec README.win32 -README.explain README.wingcc Notes about building with mingw32 and cygwin32 -oci.def OCI.DLL export declarations Todo dbdimp.c dbdimp.h hints/svr4.pl +oci.def OCI.DLL export declarations oci7.c oci8.c +ocitrace.h ora_explain.PL -oraperl.ex/Readme Oraperl examples (copied mostly unchanged from oraperl-2.4) -oraperl.ex/bind.pl -oraperl.ex/commit.pl -oraperl.ex/ex.pl -oraperl.ex/japh -oraperl.ex/mkdb.pl -oraperl.ex/oradump.pl -oraperl.ex/sql -oraperl.ex/tabinfo.pl oraperl.ph Old oraperl file included for completeness of emulation t/base.t t/general.t diff --git a/Makefile.PL b/Makefile.PL index 4519fd98..8660c47a 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.79 1999/06/08 00:15:02 timbo Exp $ +# $Id: Makefile.PL,v 1.80 1999/07/12 03:20:42 timbo Exp $ ## ## You should not need to edit this file. @@ -67,10 +67,11 @@ my %mk_target_deps; my %mk_target_rules; # Options (rarely needed) +$::opt_b = 0; # try to use Oracle's own 'build' rule $::opt_m = 0; # path to proc.mk or oracle.mk file to read -$::opt_c = 0; # don't encourage use of shared library -$::opt_n = ''; # Oracle .mk macro name to use for library list to link with $::opt_p = ''; # alter preference for oracle.mk over proc +$::opt_n = ''; # Oracle .mk macro name to use for library list to link with +$::opt_c = 0; # don't encourage use of shared library $::opt_l = 0; # try direct-link to libclntsh $::opt_g = ''; # enable debugging (-g for compiler and linker) $::opt_s = ''; # Find a symbol in oracle libs, Don't build a Makefile @@ -79,7 +80,7 @@ $::opt_v = 0; # be more verbose $::opt_d = 0; # much more verbose for debugging $::opt_8 = 0; # disable use of OCI 8 (where available) -GetOptions(qw(v! d! g! p! l! c! 8! m=s n=s s=s S=s)) +GetOptions(qw(b! v! d! g! p! l! c! 8! m=s n=s s=s S=s)) or die "Invalid arguments"; $::opt_g &&= '-g'; # convert to actual string @@ -100,39 +101,20 @@ print "\n Configuring DBD::Oracle ...\n my $ORACLE_ENV = ($os eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; my $OH = $ENV{$ORACLE_ENV} || ''; - -if (($os eq 'MSWin32') or ($os =~ /cygwin/i)) { - # Win32::TieRegistry is prefered, but it requires Win32API::Registry - # which is not available in mingw or cygwin - eval q{ - require Win32::TieRegistry; - $Win32::TieRegistry::Registry->Delimeter("/"); - my $hkey= $Win32::TieRegistry::Registry->{"LMachine/Software/Oracle/"}; - $OH= $hkey->{ORACLE_HOME}; - } unless $OH; - # older name of Win32::TieRegistry - eval q{ - require Tie::Registry; - $Tie::Registry::Registry->Delimeter("/"); - my $hkey= $Tie::Registry::Registry->{"LMachine/Software/Oracle/"}; - $OH= $hkey->{ORACLE_HOME}; - } unless $OH; - # Win32::Registry imports some symbols into main:: - # this is not commonly wanted thing, so try this as a last resort - eval q{ - require Win32::Registry; - my($reg_key, $hkey); - $main::HKEY_LOCAL_MACHINE->Open('SOFTWARE\\ORACLE', $reg_key); - $reg_key->GetValues( $hkey ); - $OH= $hkey->{ORACLE_HOME}[2]; - } unless $OH; - $OH =~ s:\\:/:g; -}; +$OH = win32_oracle_home($OH) if ($os eq 'MSWin32') or ($os =~ /cygwin/i); ($OH = unixify $OH) =~ s:/$:: if $os eq 'VMS'; -die "The $ORACLE_ENV environment variable must be set.\n" - unless $OH; -die "The $ORACLE_ENV environment variable value ($OH) is not valid.\n" - unless -d $OH; + +die qq{ The $ORACLE_ENV environment variable must be set. + It must be set to hold the path to an Oracle installation directory + on this machine (or a compatible archtecture). + See the README.clients file for more information. +} unless $OH; + +die qq{ The $ORACLE_ENV environment variable value ($OH) is not valid. + It must be set to hold the path to an Oracle installation directory + on this machine (or a compatible archtecture). + See the README.clients file for more information. +} unless -d $OH; print "Using Oracle in $OH\n"; @@ -263,51 +245,99 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l print "\$ORA_CLIENT_LIB=$ENV{ORA_CLIENT_LIB}\n" if defined $ENV{ORA_CLIENT_LIB}; # ... before we then set it how it probably should be set + # XXX but we still need to write it into the generated Makefile. $ENV{ORA_CLIENT_LIB} = 'shared' if !defined $ENV{ORA_CLIENT_LIB} && ($opts{LINKTYPE}||'') ne 'static' && @shared && !$::opt_c; my $mkfile = find_mkfile(); my $linkvia = fetch_oci_macros($mkfile); + my $libhome = expand_mkvars($MK{LIBHOME}, 0, 1) || "$OH/lib"; $linkwith = expand_mkvars($linkvia, 0, 1); + + if ($mk_target_rules{build} && $::opt_b) { + print "\n"; + my $rules = join "\n", '', @{ $mk_target_rules{build} }; + my $DBD_ORA_OBJ = "DBD_ORA_OBJ.o"; + open DBD_ORA_OBJ, ">$DBD_ORA_OBJ" or die; + close DBD_ORA_OBJ; + my $make = "$Config{make} -f $mkfile build " + ."ECHODO=true ECHO=echo GENCLNTSH='echo genclntsh' " + ."EXE=DBD_ORA_EXE OBJS=$DBD_ORA_OBJ"; + print "Discovering Oracle OCI build rules...\n"; + print "by executing:\n$make\n" if $::opt_v; + my @cmds = map { chop; $_ } grep { !m/^\s*$/ } `$make 2>&1`; + warn "Warning: Oracle build rule discovery failed ($?)\n" if $?; + unlink $DBD_ORA_OBJ; + my $prev = ''; + @cmds = grep { my $skip = $prev eq "echo $_"; $prev=$_; !$skip } @cmds; + my @prolog; push @prolog, shift @cmds while @cmds && $cmds[0] !~ /DBD_ORA_EXE/; + print "Oracle oci build prolog:\n\t", join("\n\t", @prolog), "\n"; + print "Oracle oci build command:\n\t", join("\n\t", @cmds), "\n"; + if (@cmds == 1) { + my $build = $cmds[0]; + $build =~ s/^\s*(true\s+)?(\w+)\s*//; # remove 'true' and compiler/linker + $build =~ s/$DBD_ORA_OBJ//; # remove dummy object file + $build =~ s/\S+\s+DBD_ORA_EXE//; # remove dummy exe file and preceding flag + $linkwith = $build; + # delete problematic crt?.o on solaris + $linkwith = del_crtobj($linkwith, 1) if $os eq 'solaris'; + } + else { + print "Unable to interpret Oracle oci build commands. Using fallback approach.\n"; + $::opt_b = 0; + } + print "\n"; + } + else { + print "Oracle $mkfile doesn't define a 'build' rule.\n" if $::opt_b; + $::opt_b = 0; + } + $linkwith =~ s/-Y P,/-YP,/g if $Config{'cc'} =~ /gcc/; $linkwith =~ s:-R /:-R/:g if $os eq 'solaris'; - # get a cut down $linkwith to pass to MakeMaker liblist - my $linkwith_s = expand_mkvars($linkwith, 1, 1); + if ($::opt_b) { # The simple approach + $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g $linkwith" }; + $linkwith_msg = "OTHERLDFLAGS = $linkwith [from 'build' rule]"; + } + else { # the not-so-simple approach! + # get a cut down $linkwith to pass to MakeMaker liblist + my $linkwith_s = expand_mkvars($linkwith, 1, 1); + + # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" + # to cater for lack of smarts in MakeMaker / Liblist + # which ignores /foo/bar.a entries! + my $lib_ext_re = "(a|$Config{dlext}|$Config{so})"; + $linkwith_s =~ s!(\S+)/lib(\w+)\.($lib_ext_re)\b!-L$1 -l$2!g; + + # Platform specific fix-ups: + # delete problematic crt?.o on solaris + $linkwith_s = del_crtobj($linkwith_s) if $os eq 'solaris'; + $linkwith_s =~ s/-l:lib(\w+)\.sl\b/-l$1/g; # for hp-ux + # this kind of stuff should be in a ./hints/* file: + $linkwith_s .= " -lc" if $Config{osname} eq 'dynixptx' + or $Config{archname} =~ /-pc-sco3\.2v5/; + if ($os eq 'solaris' and $osvers >= 2.3 and $linkwith_s =~ /-lthread/) { + print "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; + print "Deleting -lthread from link list as a possible workround.\n"; + $linkwith_s =~ s/\s*-lthread\b/ /g; + } - # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" - # to cater for lack of smarts in MakeMaker / Liblist - # which ignores /foo/bar.a entries! - my $lib_ext_re = "(a|$Config{dlext}|$Config{so})"; - $linkwith_s =~ s!(\S+)/lib(\w+)\.($lib_ext_re)\b!-L$1 -l$2!g; + # extract object files, keep for use later + my @linkwith_o; + push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; + # also extract AIX .exp files since they confuse MakeMaker + push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; - # Platform specific fix-ups: - # delete problematic crt?.o on solaris - $linkwith_s = del_crtobj($linkwith_s) if $os eq 'solaris'; - $linkwith_s =~ s/-l:lib(\w+)\.sl\b/-l$1/g; # for hp-ux - # this kind of stuff should be in a ./hints/* file: - $linkwith_s .= " -lc" if $Config{osname} eq 'dynixptx' - or $Config{archname} =~ /-pc-sco3\.2v5/; - if ($os eq 'solaris' and $osvers >= 2.3 and $linkwith_s =~ /-lthread/) { - print "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; - print "Deleting -lthread from link list as a possible workround.\n"; - $linkwith_s =~ s/\s*-lthread\b/ /g; + $linkwith_msg = "@linkwith_o $linkwith_s [from $linkvia]"; + $opts{LIBS} = [ "-L$libhome $linkwith_s" ]; + $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o \$(COMPOBJS)" }; } - # extract object files, keep for use later - my @linkwith_o; - push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; - # also extract AIX .exp files since they confuse MakeMaker - push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; - - $linkwith_msg = "@linkwith_o $linkwith_s [from $linkvia]"; my $OCIINCLUDE = $MK{INCLUDE} || ''; $OCIINCLUDE .= " -I$OH/rdbms/demo"; - $opts{LIBS} = [ "-L$libhome $linkwith_s" ]; - my $compobj = '$(COMPOBJS)'; - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o $compobj" }; my $inc = join " ", map { "-I$OH/$_" } find_headers(); $opts{INC} = "$OCIINCLUDE $inc -I$dbi_arch_dir"; } @@ -319,22 +349,22 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l # Since the # .a libs that Oracle supplies contain non-PIC object # files, we sadly have to build static on HP-UX 9 :( if ($os eq 'hpux') { - if ($osvers < 10) { - print "Warning: Forced to build static not dynamic on $os $osvers.\a\n"; - $opts{LINKTYPE} = 'static'; - } - else { - print "Warning: You may need to build using static linking. See the README file.\n"; - } - # see const_cccmd for -Aa to -Ae flag change + if ($osvers < 10) { + print "Warning: Forced to build static not dynamic on $os $osvers.\a\n"; + $opts{LINKTYPE} = 'static'; + } + else { + print "Warning: You may need to build using static linking. See the README file.\n"; + } + # see const_cccmd for -Aa to -Ae flag change } if ($os eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { - print "\n\n"; + print "\n\n"; print "Warning: You will probably need to rebuild perl using the xlc_r compiler.\a\n"; print " You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV\n"; print " Also see the README about the -p option\n"; - sleep 6; + sleep 6; } $opts{DEFINE} .= ' -Wall -Wno-comment' if $Config{cc} eq 'gcc'; @@ -343,6 +373,9 @@ $opts{DEFINE} .= ' -Xa' if $Config{cc} eq 'clcc'; # CenterLine CC $opts{DEFINE} .= ' -DNO_OCI8' if $::opt_8; +$opts{DEFINE} .= ' $(HP64DEFINES)' if ($os eq "hpux" and $Config{archname} =~ /-thread\b/i + and $Config{ccflags} =~ /\+DD64\b/); + print "WARNING: Your GNU C compiler is very old. Please upgrade.\n" if ($Config{gccversion} and $Config{gccversion} =~ m/^(1|2\.[1-5])/); @@ -350,7 +383,7 @@ print "WARNING: Your GNU C compiler is very old. Please upgrade.\n" if ($ENV{S_ARCH_SW} && $ENV{LOGNAME} eq 'timbo'){ # a reasonable guess $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith -Wtraditional' . ' -Wbad-function-cast -Wcast-qual' if $Config{cc} eq 'gcc'; - $::opt_g = '-g'; + $::opt_g = '-g'; $opts{dynamic_lib}->{OTHERLDFLAGS} ||= ''; $opts{dynamic_lib}->{OTHERLDFLAGS} .= " $::opt_g"; } @@ -375,7 +408,7 @@ print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; print " [".mkvar('CFLAGS',0,1,0). "]\n\n" if $MK{CFLAGS}; print " CLIBS: $MK{CLIBS}\n" if $MK{CLIBS}; print " [".mkvar('CLIBS',0,1,0). "]\n\n" if $MK{CLIBS}; -if ($mk_target_rules{build}) { +if ($mk_target_rules{build} && !$::opt_b) { my $rules = join "\n", '', @{ $mk_target_rules{build} }; $rules = expand_mkvars($rules, 0, 0, 1, 1) if $rules =~ /^\s*\$\(\w+\)\s*$/; print " build: $rules\n"; @@ -390,15 +423,67 @@ print "\n"; WriteMakefile(%opts); +# deal with Test::Harness bug +eval { package WAIT; require 'wait.ph' }; +if (!$@ && !defined(&WAIT::WCOREDUMP)) { + print "\n"; + print "You have a wait.ph file generated by perl h2ph utility.\n"; + print "It does not define a WCOREDUMP function. That's probably an error.\n"; + print "If a DBD::Oracle test fails then you will probably see a message\n"; + print "from Test::Harness about WCOREDUMP being undefined. You can either ignore\n"; + print "it or try to fix your wait.ph file. The message does not reflect the\n"; + print "cause of the test failure, it's just a problem interpreting the failure.\n"; + print "\n"; +} + print "\n*** If you have problems, read the README and README.help files ***\n"; print " (Of course, you have read README by now anyway, haven't you?)\n\n"; +check_security() unless $os eq 'VMS' or $os eq 'MSWin32' or $os =~ /cygwin/i; + exit 0; # ===================================================================== +sub win32_oracle_home { + my $oh = shift; + + # Win32::TieRegistry is prefered, but it requires Win32API::Registry + # which is not available in mingw or cygwin + eval q{ + require Win32::TieRegistry; + $Win32::TieRegistry::Registry->Delimeter("/"); + my $hkey= $Win32::TieRegistry::Registry->{"LMachine/Software/Oracle/"}; + $oh= $hkey->{ORACLE_HOME}; + } unless $oh; + + eval q{ # older name of Win32::TieRegistry + require Tie::Registry; + $Tie::Registry::Registry->Delimeter("/"); + my $hkey= $Tie::Registry::Registry->{"LMachine/Software/Oracle/"}; + $oh= $hkey->{ORACLE_HOME}; + } unless $oh; + + # Win32::Registry imports some symbols into main:: + # this is not commonly wanted thing, so try this as a last resort + eval q{ + require Win32::Registry; + my($reg_key, $hkey); + $main::HKEY_LOCAL_MACHINE->Open('SOFTWARE\\ORACLE', $reg_key); + $reg_key->GetValues( $hkey ); + $oh= $hkey->{ORACLE_HOME}[2]; + } unless $oh; + + $oh =~ s:\\:/:g; + return $oh +} + + +# ===================================================================== + + sub MY::post_initialize { my $self = shift; @@ -458,13 +543,17 @@ sub MY::postamble { sub del_crtobj { my $orig = shift; - my $str; + my $verbose = shift || $::opt_v; + my $str = $orig; # E.g. for changing the COMPOBJS line (and sometimes LDSTRING) # old: COMPOBJS=$(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/__fstd.o # new: COMPOBJS=$(COMPOBJ)/__fstd.o - ($str = $orig) =~ s:[^\s=]*\bcrt[1in]\.o\b::g; - print "del_crtobj: $orig\n : $str\n" - if $orig ne $str and $::opt_v; + my @del; + push @del, $1 while $str =~ s:([^\s=]*\bcrt[1in]\.o)\b::; + if ($orig ne $str) { + print "Deleted @del from link args.\n" if $verbose; + print "del_crtobj: $orig\n : $str\n@del" if $::opt_v; + } return $str; } @@ -499,15 +588,17 @@ sub find_mkfile { } $mkfile = $mkfiles[0]; # use first one found die qq{ - Unable to locate an oracle.mk, proc.mk or other suitable file - in your Oracle installation. (I looked in @mkplaces) + Unable to locate an oracle.mk, proc.mk or other suitable *.mk + file in your Oracle installation. (I looked in + @mkplaces) - The oracle.mk file is part of the Oracle RDBMS product. The - proc.mk file is part of the Oracle Pro*C product. You need to - build DBD::Oracle on a system which has one of these installed. + The oracle.mk (or similarly named) file is part of the Oracle + RDBMS product. The proc.mk (or similarly named) file is part of + the Oracle Pro*C product. You need to build DBD::Oracle on a + system which has one of these installed. - If your oracle.mk or proc.mk file is installed somewhere - non-standard you can specify where it is using the -m option: + If a suitable *.mk file is installed somewhere non-standard you + can specify where it is using the -m option: perl Makefile.PL -m /path/to/your.mk See README.clients for more information and some alternatives. @@ -927,32 +1018,32 @@ $(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt $(INST_ARCHAUTODIR) } -sub check_oratclsh { +sub check_security { # check for the SUID/SGID bits on ORACLE_HOME/bin/oratclsh # if set, this allows a user to fork a root shell! # Get the octal portion of perms that indicates # SUID and SGID, and warn if either is set + + my @files = map { ($_,$_.'0') } qw( + oratclsh lsnrctl oemevent onrsd osslogin tnslsnr + tnsping trcasst trcroute cmctl cmadmin cmgw names namesctl otrccref + otrcfmt otrcrep otrccol + ); + + my @bad; + foreach (@files) { + my $file = "$ENV{ORACLE_HOME}/bin/$_"; + my ($mode) = (stat($file))[2]; + next unless defined $mode; + push @bad, $file if ($mode & 04000 and $mode & 00111) + or ($mode & 02000 and $mode & 00111); + } + return unless @bad; - my $tclfile = "$ENV{$ORACLE_ENV}/bin/oratclsh"; - return unless -e $tclfile; - - my $mode = (stat($tclfile))[2]; - my @bits; - push @bits, "SUID" if $mode & 04000 and $mode & 00111; - push @bits, "SGID" if $mode & 02000 and $mode & 00111; - return unless @bits; - my $bits = join " and ", @bits; - - warn qq{ - WARNING - YOUR ORACLE INSTALLATION HAS A SECURITY PROBLEM. - An Oracle component, probably "Inteligent Agent", has installed - a copy of oratclsh that is $bits. - This warning and the problem it refers to are not related to - the DBI or DBD::Oracle modules in any way. This security check - has been done for your information. Please contact your DBA or - Oracle about the problem. Please do NOT contact myself or dbi-users. -}; - sleep 10; + print "\n"; + warn "WARNING - YOUR ORACLE INSTALLATION HAS A SECURITY PROBLEM.\a\n"; + warn "Read the README.sec file for more information and patch details.\a\n"; + sleep 5; } __END__ diff --git a/Oracle.ex/Readme b/Oracle.ex/Readme new file mode 100644 index 00000000..82af96c6 --- /dev/null +++ b/Oracle.ex/Readme @@ -0,0 +1,36 @@ +This directory contains a few sample DBI/DBD::Oracle scripts. Some are +genuinely useful while others are just demonstrations of different things. +They are adapted from the Oraperl example scripts in ../Oraperl.ex/ to +show how to do the same things in Perl 5 and DBI. + +$dbh->{RaiseError} is set to 1 in all scripts for automatic error checking. + +bind.pl Demonstrates how execute() and fetchrow_array() may be + combined to make a simple table lookup program with placeholders. + +commit.pl Demonstrates the use of commit() and rollback(). + +ex.pl Reads data from a table and prints it using a format. + Also illustrates how to recognise NULL fields and bind_columns + with known column names. + +japh Just another Perl hacker, written for DBI. + This is no one-liner, but it demonstrates a few things. + +mktable.pl Creates a table, puts some data into it, drops it. + Demonstrates do(), placeholders, inserting and reading NULL values, + and bind_columns() with known columns. + +oradump.pl Dumps an Oracle table as a set of INSERT statements. + Demonstrates the use of $sth->{TYPE}, $dbh->quote(), + and bind_columns() with unknown column names. + +proc.pl Demonstrates how to get values into and out of stored procedures + and how to receive result sets. + +sql Demonstrates the use of $sth->{NUM_OF_FIELDS}, $sth->{NAME}, + $sth->{PRECISION}, and bind_columns() with unknown column names. + +tabinfo.pl Displays the structure of the specified table. + Demonstrates the use of $sth->{NAME}, $sth->{PRECISION}, + $sth->{TYPE}, and type_info_all(). diff --git a/Oracle.ex/bind.pl b/Oracle.ex/bind.pl new file mode 100755 index 00000000..303d96be --- /dev/null +++ b/Oracle.ex/bind.pl @@ -0,0 +1,45 @@ +#!/usr/bin/perl -w +# +# bind.pl +# +# This shows how a placeholder may be used to implement a simple lookup. + +use DBI; + +use strict; + +# Set trace level if '-# trace_level' option is given +DBI->trace( shift ) if 1 < @ARGV && $ARGV[0] =~ /^-#/ && shift; + +die "syntax: $0 [-# trace] base user pass" if 3 > @ARGV; +my ( $inst, $user, $pass ) = @ARGV; + +# Connect to database +my $dbh = DBI->connect( "dbi:Oracle:$inst", $user, $pass, + { AutoCommit => 0, RaiseError => 1, PrintError => 0 } ) + or die $DBI::errstr; + +# Prepare the SELECT statement using a placeholder +my $sth = $dbh->prepare( 'SELECT created FROM all_users WHERE username = ?' ); + +my ( $created ); +$| = 1; +print "Enter an empty line to finish\n"; +print "Userid? "; +while ( ) { + chomp; + last if ! $_; + $sth->execute( uc( $_ ) ); + + # Note that the variable is in parenthesis to give an array context + if ( ( $created ) = $sth->fetchrow_array ) { + print "$created\n"; + } + else { + print "unknown\n"; + } + print "Userid? "; +} + +$sth->finish; +$dbh->disconnect; diff --git a/Oracle.ex/commit.pl b/Oracle.ex/commit.pl new file mode 100755 index 00000000..e6e0da3c --- /dev/null +++ b/Oracle.ex/commit.pl @@ -0,0 +1,72 @@ +#!/usr/bin/perl -w +# +# commit.pl +# +# Simple example of using commit and rollback. + +use DBI; + +use strict; + +# Set trace level if '-# trace_level' option is given +DBI->trace( shift ) if 1 < @ARGV && $ARGV[0] =~ /^-#/ && shift; + +die "syntax: $0 [-# trace] base user pass" if 3 > @ARGV; +my ( $inst, $user, $pass ) = @ARGV; + +# Connect to database +my $dbh = DBI->connect( "dbi:Oracle:$inst", $user, $pass, + { AutoCommit => 0, RaiseError => 1, PrintError => 0 } ) + or die $DBI::errstr; + +# Create the table to hold prime numbers +print "Creating table\n"; +eval { $dbh->do( 'CREATE TABLE primes ( prime NUMBER )' ); }; +warn $@ if $@; + +print "Loading table"; +my $sth = $dbh->prepare( 'INSERT INTO primes VALUES ( ? )' ); +while ( ) { + chomp; + print " $_"; + $sth->execute( $_ ); + print " commit (", $dbh->commit, ")" if 11 == $_; +} +print "\n"; + +my $prime; +print "Reading table for the first time\n"; +$sth = $dbh->prepare( 'SELECT prime FROM primes ORDER BY prime' ); +$sth->execute; +$sth->bind_columns( {}, \$prime ); +while ( $sth->fetch ) { + print " $prime"; +} +$sth->finish; +print "\n"; + +print "rollback (", $dbh->rollback, ")\n"; + +print "Reading table for the second time.\n"; +$sth->execute; +$sth->bind_columns( {}, \$prime ); +while ( $sth->fetch ) { + print " $prime"; +} +$sth->finish; +print "\n"; + +$dbh->do( 'DROP TABLE primes' ); +print "Table Dropped\n"; +$dbh->disconnect; +__END__ +2 +3 +5 +7 +11 +13 +17 +19 +23 +29 diff --git a/Oracle.ex/ex.pl b/Oracle.ex/ex.pl new file mode 100755 index 00000000..95ffa322 --- /dev/null +++ b/Oracle.ex/ex.pl @@ -0,0 +1,47 @@ +#!/usr/bin/perl -w +# Short example using bind_columns() to list a table's values + +use DBI; + +use strict; + +# Set trace level if '-# trace_level' option is given +DBI->trace( shift ) if 1 < @ARGV && $ARGV[0] =~ /^-#/ && shift; + +die "syntax: $0 [-# trace] base user pass [max]" if 3 > @ARGV; +my ( $inst, $user, $pass, $max ) = @ARGV; +$max = 20 if ! $max || 0 > $max; + +my ( $name, $id, $created ); +format STDOUT_TOP = + Name ID Created + ============================== ========= ========= +. + +format STDOUT = + @<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>>>> @<<<<<<<< + $name, $id, $created +. + +# Connect to database +my $dbh = DBI->connect( "dbi:Oracle:$inst", $user, $pass, + { AutoCommit => 0, RaiseError => 1, PrintError => 0 } ) + or die $DBI::errstr; + +my $sth = $dbh->prepare( + "SELECT username, user_id, created FROM all_users ORDER BY username" ); +$sth->execute; + +my $nfields = $sth->{NUM_OF_FIELDS}; +print "Query will return $nfields fields\n\n"; + +$sth->bind_columns( {}, \( $name, $id, $created ) ); +while ( $sth->fetch ) { + last if ! --$max; + # mark any NULL fields found + foreach ( $name, $id, $created ) { $_ = 'NULL' if ! defined; } + write; +} + +$sth->finish; +$dbh->disconnect; diff --git a/Oracle.ex/japh b/Oracle.ex/japh new file mode 100755 index 00000000..1232e60f --- /dev/null +++ b/Oracle.ex/japh @@ -0,0 +1,52 @@ +#!/usr/bin/perl -w +# This is an example of how we could code a JAPH using DBI and DBD::Oracle. +# +# Original oraperl script by Kevin Stock +# Date: 1st December 1992 + +use DBI; + +use strict; + +# Set trace level if '-# trace_level' option is given +DBI->trace( shift ) if 1 < @ARGV && $ARGV[0] =~ /^-#/ && shift; + +die "syntax: $0 [-# trace] base user pass" if 3 > @ARGV; +my ( $inst, $user, $pass ) = @ARGV; + +# Connect to database +my $dbh = DBI->connect( "dbi:Oracle:$inst", $user, $pass, + { AutoCommit => 0, RaiseError => 1, PrintError => 0 } ) + or die $DBI::errstr; + +# Create the sample table +$dbh->do( "CREATE TABLE japh ( word CHAR(7), posn NUMBER(1) )" ); + +# Loop to insert data into the table +my $sth = $dbh->prepare( "INSERT INTO japh VALUES ( ?, ? )" ); +while ( ) { + chomp; + $sth->execute( split ':', $_ ); +} + +# Now retrieve the data, printing it word by word +$sth = $dbh->prepare( "SELECT word FROM japh ORDER BY posn" ); +$sth->execute; +my $word; +$sth->bind_columns( {}, \$word ); +$sth->{ChopBlanks} = 1; # Wouldn't you rather use VARCHAR2 instead of CHAR? +while ( $sth->fetch ) { + print " $word"; +} +$sth->finish; +print "\n"; + +# delete the table +$dbh->do( 'DROP TABLE japh' ); +$dbh->disconnect; + +__END__ +DBI:3 +another:2 +hacker:4 +just:1 diff --git a/Oracle.ex/mktable.pl b/Oracle.ex/mktable.pl new file mode 100755 index 00000000..28d01007 --- /dev/null +++ b/Oracle.ex/mktable.pl @@ -0,0 +1,102 @@ +#!/usr/bin/perl -w +# Sample DBI program to create a new table and load data into it. +# +# Author: Kevin Stock (original oraperl script) +# Date: 5th August 1991 +# Date: 25th September 1992 + +use DBI; + +use strict; + +# Set trace level if '-# trace_level' option is given +DBI->trace( shift ) if 1 < @ARGV && $ARGV[0] =~ /^-#/ && shift; + +die "syntax: $0 [-# trace] base user pass" if 3 > @ARGV; +my ( $inst, $user, $pass ) = @ARGV; + +# Connect to database +my $dbh = DBI->connect( "dbi:Oracle:$inst", $user, $pass, + { AutoCommit => 0, RaiseError => 1, PrintError => 0 } ) + or die $DBI::errstr; + +# set these as strings to make the code more readable +my $CREATE = "CREATE TABLE tryit ( name VARCHAR2(10), ext NUMBER(3) )"; +my $INSERT = "INSERT INTO tryit VALUES ( ?, ? )"; +my $LIST = "SELECT * FROM tryit ORDER BY name"; +my $DELETE = "DELETE FROM tryit WHERE name = ?"; +my $DELETE_NULL = "DELETE FROM tryit WHERE name IS NULL"; +my $DROP = "DROP TABLE tryit"; + +# Can use dynamic variables in write as long as they are visible at format time +my ( $msg, $name, $ext ); + +# Prepare formats for output +format STDOUT_TOP = + + @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + $msg + + Name Ext + ==== === +. + +format STDOUT = + @<<<<<<<<< @>> + $name, $ext +. + +# function to list the table +sub list { + $msg = join "\n", @_; + $- = 0; + my $sth = $dbh->prepare( $LIST ); + $sth->execute; + $sth->bind_columns( {}, \( $name, $ext ) ); + while ( $sth->fetch ) { + $name = '' unless defined $name; + $ext = '' unless defined $ext; + write; + } + $sth->finish; +} + +# create the database +$dbh->do( $CREATE ); + +# put some data into it +my $sth = $dbh->prepare( $INSERT ); +while ( ) { + chomp; + $sth->execute( map { 'NULL' eq $_ ? undef : $_ } split /:/, $_, 2 ); +} +$dbh->commit; +list( 'Initial Data' ); + +# remove a few rows +$sth = $dbh->prepare( $DELETE ); +foreach $name ( 'catherine', 'angela', 'arnold', 'julia' ) { + $sth->execute( $name ); +} +$dbh->commit; +list( 'After removing selected people' ); + +# Remove some rows with NULLs +$dbh->do( $DELETE_NULL ); +list( 'After removing NULL names' ); + +# remove the table and disconnect +$dbh->do( $DROP ); +$dbh->disconnect; + +# This is the data which will go into the table +__END__ +julia:292 +angela:208 +NULL:999 +larry:424 +catherine:201 +nonumber:NULL +randal:306 +arnold:305 +NULL:NULL diff --git a/Oracle.ex/oradump.pl b/Oracle.ex/oradump.pl new file mode 100755 index 00000000..88a8bd01 --- /dev/null +++ b/Oracle.ex/oradump.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl -w +# +# Dump the contents of an Oracle table into a set of insert statements. +# Quoting is controlled by the datatypes of each column. (new with DBI) +# +# Usage: oradump
+# +# Author: Kevin Stock (original oraperl script) +# Date: 28th February 1992 +# + +use DBI; + +use strict; + +# Set trace level if '-# trace_level' option is given +DBI->trace( shift ) if 1 < @ARGV && $ARGV[0] =~ /^-#/ && shift; + +die "syntax: $0 base user pass table\n" if 4 > @ARGV; +my ( $base, $user, $pass, $table ) = @ARGV; + +# Connect to database +my $dbh = DBI->connect( "dbi:Oracle:$base", $user, $pass, + { AutoCommit => 0, RaiseError => 1, PrintError => 0 } ) + or die $DBI::errstr; + +my $sth = $dbh->prepare( "SELECT * FROM $table"); +$sth->execute; +my @name = @{$sth->{NAME}}; +my @type = @{$sth->{TYPE}}; +my $lead = "INSERT INTO $table ( " . join( ', ', @name ) . " ) VALUES ( "; +my ( @data, $i ); +$sth->bind_columns( {}, \( @data[0 .. $#name] ) ); +while ( $sth->fetch ) { + $i = 0; + # print $lead . join( ", ", map { $dbh->quote( $_, $type[$i++] ) } @data ) . + print $lead . join( ", ", map { $dbh->quote( $_ ) } @data ) . + " );\n"; +} + +$sth->finish; +$dbh->disconnect; diff --git a/Oracle.ex/proc.pl b/Oracle.ex/proc.pl new file mode 100755 index 00000000..a8a65a14 --- /dev/null +++ b/Oracle.ex/proc.pl @@ -0,0 +1,148 @@ +#!/usr/bin/perl -w +# Short examples of procedure calls from Oracle.pm +# These PL/SQL examples come from: Eric Bartley . + +use DBI; + +use strict; + +# Set trace level if '-# trace_level' option is given +DBI->trace( shift ) if 1 < @ARGV && $ARGV[0] =~ /^-#/ && shift; + +die "syntax: $0 [-# trace] base user pass" if 3 > @ARGV; +my ( $inst, $user, $pass ) = @ARGV; + +# So we don't have to check every DBI call we set RaiseError. +# See the DBI docs if you're not familiar with RaiseError. +# AutoCommit is currently encouraged and may be required later. +my $dbh = DBI->connect( "dbi:Oracle:$inst", $user, $pass, + { AutoCommit => 0, RaiseError => 1, PrintError => 0 } ) + or die "Unable to connect: $DBI::errstr"; + +# Create the package for the examples +$dbh->do( <do( <prepare( q{ +BEGIN + plsql_example.proc_np; +END; +} ); +$sth->execute; + + +print "\nExample 2\n"; +# Now we call a procedure that has 1 IN parameter. Here we use bind_param +# to bind out parameter to the prepared statement just like you might +# do for an INSERT, UPDATE, DELETE, or SELECT statement. +# +# I could have used positional placeholders (e.g. :1, :2, etc.) or +# ODBC style placeholders (e.g. ?), but I prefer Oracle's named +# placeholders (but few DBI drivers support them so they're not portable). +# +# proc_in() will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. +# Because we set RaiseError, the DBI will die() so we catch that with eval {}. + +my $err_code = -20001; + +$sth = $dbh->prepare( q{ +BEGIN + plsql_example.proc_in( :err_code ); +END; +} ); +$sth->bind_param( ":err_code", $err_code ); +eval { $sth->execute; }; +print 'After proc_in: $@ = ', "'$@', errstr = '$DBI::errstr'\n"; + + +print "\nExample 3\n"; +# Building on the last example, I've added 1 IN OUT parameter. We still +# use a placeholders in the call to prepare, the difference is that +# we now call bind_param_inout to bind the value to the place holder. +# +# Note that the third parameter to bind_param_inout is the maximum size +# of the variable. You normally make this slightly larger than necessary. +# But note that the perl variable will have that much memory assigned to +# it even if the actual value returned is shorter. + +my $test_num = 5; +my $is_odd; + +$sth = $dbh->prepare( q{ +BEGIN + plsql_example.proc_in_inout( :test_num, :is_odd ); +END; +} ); + +# The value of $test_num is _copied_ here +$sth->bind_param( ":test_num", $test_num ); +$sth->bind_param_inout( ":is_odd", \$is_odd, 1 ); + +# The execute will automagically update the value of $is_odd +$sth->execute; +print "$test_num is ", $is_odd ? "odd - ok" : "even - error!", "\n"; + + +print "\nExample 4\n"; +# What about the return value of a PL/SQL function? Well treat it the same +# as you would a call to a function from SQL*Plus. We add a placeholder +# for the return value and bind it with a call to bind_param_inout so +# we can access it's value after execute. + +my $whoami = ""; + +$sth = $dbh->prepare( q{ +BEGIN + :whoami := plsql_example.func_np; +END; +} ); +$sth->bind_param_inout( ":whoami", \$whoami, 30 ); +$sth->execute; +print "Your database user name is $whoami\n"; + +# Get rid of the example package +$dbh->do( 'DROP PACKAGE plsql_example' ); +$dbh->disconnect; diff --git a/Oracle.ex/sql b/Oracle.ex/sql new file mode 100755 index 00000000..acdaa2d3 --- /dev/null +++ b/Oracle.ex/sql @@ -0,0 +1,235 @@ +#!/usr/bin/perl -w +'di'; +'ig00'; +# See usage() for syntax + +use Getopt::Long; + +use DBI; + +use strict; + +# Default values for options +my ( $trace, $inst, $cache, $delim, $format, $headers, $page_len, $null_str ) = + ( 0, $ENV{TWO_TASK} || $ENV{ORACLE_SID} || '', '', "\t", 0, 0, 60, '' ); + +# Syntax description +sub usage { + my ( $sOpt, $sVal, @sMsg ) = @_; + + my $sHelpText = < \&usage, + 'trace|t=i' => \$trace, + 'base|b=s' => \$inst, + 'cache|c=i' => \$cache, + 'delim|d=s' => \$delim, + 'Format!' => \$format, 'F!' => \$format, + 'Headers!' => \$headers, 'H!' => \$headers, + 'len|len=i' => \$page_len, + 'null|n=s' => \$null_str, + ) or usage( 'die', 1 ); +usage( 'die', 1, "Only one of -F and -H may be specified\n" ) + if $format && $headers; + +usage( 'die', 1, 'Username and password are required' ) if 2 > @ARGV; +my ( $user, $pass, @stmt ) = @ARGV; +if ( ! @stmt ) { + print "Enter the statement to execute (^D to end):\n"; + @stmt = ; +} +usage( 'die', 1, "A statement is required" ) if ! @stmt; + +$\ = "\n"; # each record terminated with newline +$, = $delim; # set column delimiter +$= = $page_len; # set page length + +# Set trace level +DBI->trace( $trace ); + +# Connect to database +my $dbh = DBI->connect( "dbi:Oracle:$inst", $user, $pass, + { AutoCommit => 0, RaiseError => 1, PrintError => 0 } ) + or die $DBI::errstr; +$dbh->{RowCacheSize} = $cache if $cache; # set fetch cache + +# Start statement +my $sth = $dbh->prepare( join "\n", @stmt ); +$sth->execute; +my $nfields = $sth->{NUM_OF_FIELDS}; + +# print out any information which comes back +if ( $nfields ) { + # the statement has output columns + my ( @col, $col ); + my @name = @{$sth->{NAME}}; + if ( $format ) { + # build format statements for the data + my @size = @{$sth->{PRECISION}}; + + # First, the header - a list of field names, formatted + # in columns of the appropriate width + my $fmt = join '|', map { "%-${_}.${_}s" } @size; + $fmt = sprintf $fmt, @name; + $format .= "format STDOUT_TOP =\n" . $fmt . "\n"; + + # Then underlines for the field names + $fmt =~ tr/|/-/c; + $fmt =~ tr/|/+/; + $format .= $fmt . "\n.\n"; + + # Then for the data format, a @<<... field per column + $fmt =~ tr/-+/<|/; + $fmt =~ s/(^|\|)bind_columns( {}, \( @col[0 .. $#name] ) ); + while ( $sth->fetch ) { + foreach $col ( @col ) { $col = $null_str if ! defined $col; } + $format ? write : print @col; + } +} + +# finish off neatly +$sth->finish; +$dbh->disconnect; + +__END__ # no need for perl even to scan the rest + +############################################################################## + + # These next few lines are legal in both Perl and nroff. + +.00; # finish .ig + +'di \" finish diversion--previous line must be blank +.nr nl 0-1 \" fake up transition to first page again +.nr % 0 \" start at page 1 +';<<'.ex'; ############## From here on it's a standard manual page ############ +.TH SQL L "5th July 1999" +.ad +.nh +.SH NAME +sql \- execute an Oracle SQL statement from the command line +.SH SYNOPSIS +\fBsql\fP +[\fB\-b\fP\fIbase\fP] +[\fB\-c\fP\fIcache\fP] +[\fB\-d\fP\fIdelim\fP] +[\fB\-F\fP|\fB\-H\fP] +[\fB\-l\fP\fIpage_len\fP] +[\fB\-n\fP\fIstring\fP] +\fIname\fP \fIpassword\fP +\fIstatement\fP +.SH DESCRIPTION +.I Sql +connects to an Oracle database +using the \fIname\fP and \fIpassword\fP supplied +and executes the given SQL \fIstatement\fP +displaying the result +on its standard output. + +The \fB\-b\fP\fIbase\fP flag may be supplied to specify the database to be used. +If it is not given, the database specified by the environment variable +\fBTWO_TASK\fP or \fBORACLE_SID\fP is used. + +The \fB\-c\fP\fIcache\fP flag may be supplied to set the size of fetch cache +to be used. If it is not given, the default is used. + +If the \fB\-n\fP\fIstring\fP flag is supplied, +\fBNULL\fP fields (in the \fIOracle\fP sense) +will replaced in the output by \fIstring\fP. +Normally, they are left blank. + +The \fB\-F\fP and \fB\-H\fP flags may be used to modify the form of the output. +Without either flag, no field headers are printed +and fields are not padded. +With the \fB\-H\fP flag, +field headers are added to the top of the output, +but the format is otherwise unchanged. +With the \fB\-F\fP flag, +the output is formatted in a tabular form similar to that used by \fIsqlplus\fP, +except that all fields are left\-justified, regardless of their data type. +Column headers are printed at the top of each page; +a page is assumed to be 60 lines long, +but this may be overridden with the \fB\-l\fP\fIpage_len\fP flag. + +Without the \fB\-F\fP flag, fields are separated with tabs; +this may be changed to any desired string (\fIdelim\fP) +using the \fB\-d\fP flag. +.SH ENVIRONMENT +The environment variable \fBTWO_TASK\fP or \fBORACLE_SID\fP +determines the Oracle database to be used +if the \fB\-b\fP\fIbase\fP flag is not supplied. +.SH DIAGNOSTICS +.in +5 +.ti -5 +\fBonly one of \-F and \-H may be specified\fP +.br +the \fB\-F\fP and \fB\-H\fP options are mutually exclusive, +but both were specified + +.in -5 +The only other diagnostics generated by \fIsql\fP are usage messages, +which should be self\-explanatory. +However, you may also encounter +error messages from DBI (unlikely) or from Oracle (more common). +See the \fIOracle Error Messages and Codes Manual\fP for details. +.SH NOTES +This program is only intended for use from the command line. +If you use it within a shell script +then you should consider rewriting your script in DBI +to use Perl's text manipulation and formatting commands. +.SH "SEE ALSO" +\fISQL Language Reference Manual\fP +.br +perl(1), +oraperl(1) +.SH AUTHOR +Kevin Stock, +.if t .ft C + +.if t .ft P +.ex diff --git a/Oracle.ex/tabinfo.pl b/Oracle.ex/tabinfo.pl new file mode 100755 index 00000000..307bd6b1 --- /dev/null +++ b/Oracle.ex/tabinfo.pl @@ -0,0 +1,68 @@ +#!/usr/bin/perl -w +# +# tabinfo +# +# Usage: tabinfo base user password table +# +# Displays the structure of the specified table. +# Note that the field names are restricted to the length of the field. +# This is mainly to show the use of &ora_lengths, &ora_titles and &ora_types. +# +use DBI; + +use strict; + +# Set trace level if '-# trace_level' option is given +DBI->trace( shift ) if 1 < @ARGV && $ARGV[0] =~ /^-#/ && shift; + +# read the compulsory arguments +die "syntax: $0 base user password table ...\n" if 4 > @ARGV; +my ( $base, $user, $pass, @table ) = @ARGV; + +my ( $table, @name, @length, @type, %type_name, $i ); +format STDOUT_TOP = +Structure of @<<<<<<<<<<<<<<<<<<<<<<< +$table + +Field name | Length | Type | Type Name +----------------------------------------------+--------+------+----------------- +. + +format STDOUT = +@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | @>>>>> | @>>> | @<<<<<<<<<<<<<<< +$name[$i], $length[$i], $type[$i], $type_name{$type[$i]} +. + +# Connect to database +my $dbh = DBI->connect( "dbi:Oracle:$base", $user, $pass, + { AutoCommit => 0, RaiseError => 1, PrintError => 0 } ) + or die $DBI::errstr; + +# Associate type names to types +{ + my $type_info_all = $dbh->type_info_all; + my $iname = $type_info_all->[0]{TYPE_NAME}; + my $itype = $type_info_all->[0]{DATA_TYPE}; + my $rtype; + shift @$type_info_all; + foreach $rtype ( @$type_info_all ) { + $type_name{$$rtype[$itype]} = $$rtype[$iname] + if ! exists $type_name{$$rtype[$itype]}; + } +} + +my $sth; +foreach $table ( @table ) { + $sth = $dbh->prepare( "SELECT * FROM $table WHERE 1 = 2"); + @name = @{$sth->{NAME}}; + @length = @{$sth->{PRECISION}}; + @type = @{$sth->{TYPE}}; + + foreach $i ( 0 .. $#name ) { + write; + } + $- = 0; + $sth->finish; +} + +$dbh->disconnect; diff --git a/Oracle.h b/Oracle.h index 4ef5ed59..e47b6a80 100644 --- a/Oracle.h +++ b/Oracle.h @@ -1,5 +1,5 @@ /* - $Id: Oracle.h,v 1.16 1999/06/05 03:23:07 timbo Exp $ + $Id: Oracle.h,v 1.17 1999/07/12 03:20:42 timbo Exp $ Copyright (c) 1994,1995 Tim Bunce @@ -27,7 +27,7 @@ void dbd_init _((dbistate_t *dbistate)); -int dbd_db_login _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pwd)); +int dbd_db_login _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pwd)); int dbd_db_do _((SV *sv, char *statement)); int dbd_db_commit _((SV *dbh, imp_dbh_t *imp_dbh)); int dbd_db_rollback _((SV *dbh, imp_dbh_t *imp_dbh)); @@ -51,6 +51,7 @@ int dbd_bind_ph _((SV *sth, imp_sth_t *imp_sth, SV *param, SV *value, IV sql_type, SV *attribs, int is_inout, IV maxlen)); #endif +int dbd_db_login6 _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pwd, SV *attr)); int dbd_describe _((SV *sth, imp_sth_t *imp_sth)); ub4 ora_blob_read_piece _((SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, long offset, long len, long destoffset)); diff --git a/Oracle.pm b/Oracle.pm index 1d10abc4..d5b67c0b 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.76 1999/06/14 00:41:48 timbo Exp $ +# $Id: Oracle.pm,v 1.77 1999/07/12 03:20:42 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce # @@ -10,7 +10,7 @@ require 5.003; -$DBD::Oracle::VERSION = '1.02'; +$DBD::Oracle::VERSION = '1.03'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -32,7 +32,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.76 $, 10); + my $Revision = substr(q$Revision: 1.77 $, 10); require_version DBI 1.02; @@ -141,9 +141,10 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; # get list of 'remote' database connection identifiers foreach $d ( $ENV{TNS_ADMIN}, - "$oracle_home/net80/admin", - "$oracle_home/network/admin", - '/var/opt/oracle' + ".", # current directory + "$oracle_home/network/admin", # OCI 7 and 8.1 + "$oracle_home/net80/admin", # OCI 8.0 + "/var/opt/oracle" ) { next unless $d && open(FH, "<$d/tnsnames.ora"); $drh->trace_msg("Loading $d/tnsnames.ora\n") if $debug; @@ -173,21 +174,49 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; sub connect { my ($drh, $dbname, $user, $auth, $attr)= @_; + if ($dbname =~ /;/) { + my ($n,$v); + $dbname =~ s/^\s+//; + $dbname =~ s/\s+$//; + my @dbname = map { + ($n,$v) = split /\s*=\s*/, $_; (uc($n), $v) + } split /\s*;\s*/, $dbname; + my %dbname = ( PROTOCOL => 'tcp', @dbname ); + my $sid = delete $dbname{SID}; + my $ora = delete $dbname{ORACLE}; + return $drh->DBI::set_err(-1, + "Can't connect using this syntax without specifying a HOST and a SID") + unless $sid and $dbname{HOST}; + my @addrs; + push @addrs, "$n=$v" while ( ($n,$v) = each %dbname ); + my $addrs = "(" . join(")(", @addrs) . ")"; + $dbname{PORT} ||= ($ora eq 7) ? 1521 : 1526 if $ora; + if ($dbname{PORT}) { + $addrs = "(ADDRESS=$addrs)"; + } + else { + $addrs = "(ADDRESS_LIST=(ADDRESS=$addrs(PORT=1526))" # Oracle8 + . "(ADDRESS=$addrs(PORT=1521)))"; # Oracle7 + } + $dbname = "(DESCRIPTION=$addrs(CONNECT_DATA=(SID=$sid)))"; + $drh->trace_msg("connect using '$dbname'"); + } + # If the application is asking for specific database - # then we have to mung the + # then we may have to mung the dbname if (DBD::Oracle::ORA_OCI() >= 8) { - $dbname = $1 if !$dbname && $user =~ s/\@(.*)//; + $dbname = $1 if !$dbname && $user =~ s/\@(.*)//s; } elsif ($dbname) { # OCI 7 handling below # We can use the 'user/passwd@machine' form of user. # $TWO_TASK and $ORACLE_SID will be ignored in that case. - if ($dbname =~ /@/){ # Implies an Sql*NET connection + if ($dbname =~ /^@/){ # Implies an Sql*NET connection $user = "$user/$auth$dbname"; $auth = ""; } - elsif ($dbname =~ /:/){ # Implies an Sql*NET connection + elsif ($dbname =~ /^\w?:/){ # Implies an Sql*NET connection $user = "$user/$auth".'@'.$dbname; $auth = ""; } @@ -357,16 +386,21 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; sub plsql_errstr { # original version thanks to Bob Menteer my $sth = shift->prepare_cached(q{ - select line,position,text from user_errors order by sequence - }); - return undef unless $sth; + SELECT name, type, line, position, text + FROM user_errors ORDER BY name, type, sequence + }) or return undef; $sth->execute or return undef; - my (@msg, $line,$pos,$text); - while(($line,$pos,$text) = $sth->fetchrow){ - push @msg, "Error in PL/SQL block" unless @msg; + my ( @msg, $oname, $otype, $name, $type, $line, $pos, $text ); + $oname = $otype = 0; + while ( ( $name, $type, $line, $pos, $text ) = $sth->fetchrow_array ) { + if ( $oname ne $name || $otype ne $type ) { + push @msg, "Errors for $type $name:"; + $oname = $name; + $otype = $type; + } push @msg, "$line.$pos: $text"; } - join("\n", @msg); + return join( "\n", @msg ); } # @@ -455,6 +489,8 @@ DBD::Oracle - Oracle database driver for the DBI module $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); + # See the DBI module documentation for full details # for some advanced uses you may need Oracle type values: @@ -473,6 +509,18 @@ and sometimes complex ways of specifying and connecting to databases. (James Taylor and Lane Sharman have contributed much of the text in this section.) +=head2 Connecting without environment variables or tnsname.ora file + +If you use the C style syntax, for example: + + $dbh = DBI->connect("dbi:Oracle:host=myhost.com;sid=ORCL", $user, $passwd); + +then DBD::Oracle will construct a full connection descriptor string +for you and Oracle will not need to consult the tnsname.ora file. +If a C number is not specified then the descriptor try +both 1526 and 1521 in that order. + + =head2 Oracle environment variables Oracle typically uses two environment variables to specify default @@ -551,12 +599,14 @@ Here are some variations (not setting TWO_TASK) $dbh = DBI->connect('dbi:Oracle:DB','username/password','') + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521', 'scott/tiger', '') + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) - (CONNECT_DATA=(SID=foobarSID)))}, "") + (CONNECT_DATA=(SID=ORCL)))}, "") If you are having problems with login taking a long time (>10 secs say) -then you might have tripped up on an Oracle bug. Yoy can try using one +then you might have tripped up on an Oracle bug. You can try using one of the ...@DB variants as a workaround. E.g., $dbh = DBI->connect('','username/password@DB',''); @@ -576,12 +626,12 @@ make it better, please let me know! LISTENER = (ADDRESS_LIST = - (ADDRESS = - (PROTOCOL = TCP) - (Host = aa.bbb.cc.d) - (Port = 1521) - (QUEUESIZE=10) - ) + (ADDRESS = + (PROTOCOL = TCP) + (Host = aa.bbb.cc.d) + (Port = 1521) + (QUEUESIZE=10) + ) ) STARTUP_WAIT_TIME_LISTENER = 0 @@ -592,10 +642,10 @@ make it better, please let me know! (SID_DESC = (SID_NAME = xxxx) (ORACLE_HOME = /xxx/local/oracle7-3) - (PRESPAWN_MAX = 40) - (PRESPAWN_LIST= - (PRESPAWN_DESC=(PROTOCOL=tcp) (POOL_SIZE=40) (TIMEOUT=120)) - ) + (PRESPAWN_MAX = 40) + (PRESPAWN_LIST= + (PRESPAWN_DESC=(PROTOCOL=tcp) (POOL_SIZE=40) (TIMEOUT=120)) + ) ) ) @@ -649,6 +699,16 @@ Oracle technical support (and not the dbi-users mailing list). Thanks. Thanks to Mark Dedlow for this information. +=head2 Connect Attributes + +The ora_session_mode attribute can be used to connect with SYSDBA +authorization and SYSOPER authorization. + + $mode = 2; # SYSDBA + $mode = 4; # SYSOPER + DBI->connect($dsn, $user, $passwd, { ora_session_mode => $mode }); + + =head1 International NLS / 8-bit text issues If 8-bit text is returned as '?' characters or can't be inserted @@ -847,6 +907,123 @@ You can find more examples in the t/plsql.t file in the DBD::Oracle source directory. +=head1 Private database handle functions + +These functions are called through the method func() +which is described in the DBI documentation. + +=head2 plsql_errstr + +This function returns a string which describes the errors +from the most recent PL/SQL function, procedure, package, +or package body compile in a format similar to the output +of the SQL*Plus command 'show errors'. + +The function returns undef if the error string could not +be retrieved due to a database error. +Look in $dbh->errstr for the cause of the failure. + +If there are no compile errors, an empty string is returned. + +Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + + +=head2 dbms_output_enable / dbms_output_put / dbms_output_get + +These functions use the PL/SQL DBMS_OUTPUT package to store and +retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer +by dbms_output_put or any PL/SQL block can be retrieved by +dbms_output_get or any PL/SQL block connected to the same database +session. + +Stored text is not available until after dbms_output_put or the PL/SQL +block that saved it completes its execution. This means you B +use these functions to monitor long running PL/SQL procedures. + +Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retreive it later + @text = $dbh->func( 'dbms_output_get' ); + +Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retreive the string + $date_string = $dbh->func( 'dbms_output_get' ); + + +=over 4 + +=item dbms_output_enable ( [ buffer_size ] ) + +This function calls DBMS_OUTPUT.ENABLE to enable calls to package +DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to +these procedures are ignored unless DBMS_OUTPUT.ENABLE is called +first. + +The buffer_size is the maximum amount of text that can be saved in the +buffer and must be between 2000 and 1,000,000. If buffer_size is not +given, the default is 20,000 bytes. + +=item dbms_output_put ( [ @lines ] ) + +This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + +If all lines were saved successfully the function returns 1. Depending +on the context, an empty list or undef is returned for failure. + +If any line causes buffer_size to be exceeded, a buffer overflow error +is raised and the function call fails. Some of the text might be in +the buffer. + +=item dbms_output_get + +This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from +the buffer. + +In an array context, all complete lines are removed from the buffer and +returned as a list. If there are no complete lines, an empty list is +returned. + +In a scalar context, the first complete line is removed from the buffer +and returned. If there are no complete lines, undef is returned. + +Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or +DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, +DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + +=back + + =head1 Using DBD::Oracle with Oracle 8 - Features and Issues DBD::Oracle version 0.55 onwards can be built to use either the Oracle 7 @@ -917,7 +1094,7 @@ then you need to tell it which field each LOB param relates to: =head2 Binding Cursors Cursors can now be returned from PL/SQL blocks. Either from stored -procedures or from direct C statements, as show below: +procedure OUT parameters or from direct C statements, as show below: use DBI; use DBD::Oracle qw(:ora_types); diff --git a/README b/README index 828d8d41..fc7a903f 100644 --- a/README +++ b/README @@ -67,9 +67,15 @@ value before starting the test. Please read README.login. *** IF YOU HAVE PROBLEMS: -Make sure you are using a recent perl 5.003 or preferably 5.004 and -make sure it's on your path so you can say 'perl Makefile.PL' and -not '/path/to/perl Makefile.PL'. +Make sure you are using a recent perl (5.004_05, 5.005_03 or later) and +make sure it's on your PATH so you can say 'perl Makefile.PL' and not +'/path/to/perl Makefile.PL'. + +If you get compiler errors refering to Perl's own header files +(.../CORE/*.h) then there is something wrong with your installation. +It is best to use a Perl that was built on the system you are trying to +use and it's also important to use the same compiler that was used to +build the Perl you are using. If you have build/link or core dump problems try: perl Makefile.PL -p diff --git a/README.help b/README.help index 7e74c838..e72335fb 100644 --- a/README.help +++ b/README.help @@ -4,6 +4,16 @@ Platform or Oracle Version specific notes, hints, tips etc: Note that although some of these refer to specific systems and versions the same or similar problems may exist on other systems or versions. +Most of this mess is due to Oracle's fondness for changing the +build/link process for OCI applications between versions. + +------------------------------------------------------------------------------- +If you get compiler errors refering to Perl's own header files +(.../CORE/*.h) then there is something wrong with your installation. +It is best to use a Perl that was built on the system you are trying to +use and it's also important to use the same compiler that was used to +build the Perl you are using. + ------------------------------------------------------------------------------- Assorted runtime problems are caused by Oracle version mismatches: @@ -112,7 +122,7 @@ HP-UX: General HP's bundled C compiler is dumb. Very dumb. You're almost bound to have problems if you use it - you'll certainly need to do a 'static link' (see elsewhere). It is recommended that you use HP's ANSI C compiler -(which costs) fetch and build the free GNU GCC compiler (v2.7.2.2 or later). +(which costs) or fetch and build the free GNU GCC compiler (v2.7.2.2 or later). Note that using shared libraries on HP-UX 10.10 (and others?) requires patch 441647. With thanks to John Liptak . @@ -158,7 +168,7 @@ into a perl binary: make make perl (makes a perl binary in current directory) make test FULLPERL=./perl (run tests using the new perl binary) - make install + make install You will probably need to have already built and installed a static version of the DBI in order that it be automatically included when @@ -214,31 +224,6 @@ Connection/Login takes a long time Try connect('', 'user/passwd@tnsname', ''). See README.login and item above. -------------------------------------------------------------------------------- -Oracle 7.1.4/5: ORA-01002: fetch out of sequence - -Edited from Message-ID: <3qaui9$ae@usenet.rpi.edu> and -<3qb5dp$2nc@usenet.rpi.edu> in comp.databases.oracle -From: finkej@ts.its.rpi.edu (Jon Finke) - -Every test run results in an "ORA-01002: fetch out of sequence" error. - -The manual claims that this is the result of calling "ofetch" before -oparse/oexec, or running out of things to fetch. Yet, I am calling -oopen, oparse, oexec, (odesc, odefin) all without error. As a control -case, I also built the cdemo2 program, and it appears to be calling -the same routines, yet it is successful. - -Note: In the "broken" program, I am currently calling odsc in a loop - for each column in the query, and then calling odefin, while in the - "working" program, I call odescr/odefin, odesc/odefin for each column. - In both cases, the calls to odefin seem reasonable. - -Both programs are attempting the query "select user,uid from dual". - -This is a known problem in version 7.1.4, and it will be fixed in 7.1.6. -The Oracle bug report is #239128. - ------------------------------------------------------------------------------- Error: ORA-00604: error occurred at recursive SQL level (DBD: login failed) @@ -323,6 +308,16 @@ Problem: 0 ORA-00000: normal, successful completion Solution: Add '#define A_OSF' to Oracle.h above '#include ' and complain to Oracle about bugs in their header files on 64 bit systems. +------------------------------------------------------------------------------- +Link errors or test core dumps + +Try each of these in turn (follow each with a make && make test): + perl Makefile.PL -b + perl Makefile.PL -c + perl Makefile.PL -l + perl Makefile.PL -n LIBCLNTSH +let me know if this helps. + ------------------------------------------------------------------------------- Some runtime problems might be related to perl's malloc. diff --git a/README.sec b/README.sec new file mode 100644 index 00000000..b6049f65 --- /dev/null +++ b/README.sec @@ -0,0 +1,132 @@ + +----- Forwarded message from Oracle Support Services ----- + +Date: Fri, 7 May 1999 06:29:09 -0700 +From: Oracle Support Services +Subject: SUID Security Issue + +Platform: UNIX + +Distribution: Internal & External + +Problem Subject Line: SUID Security + +Product: Oracle Enterprise Manager 2.0.4 + Oracle Data Server + +Oracle Version: 8.0.3, 8.0.4, 8.0.5, 8.1.5 + +Component: Intelligent Agent + Oracle Data Server + +Component Version: 8.0.3, 8.0.4, 8.0.5, 8.1.5 + +Sub-Component: N/A + +Platform Version: All Unix Versions. + +Errors: N/A + +Revision Date: 6-March-1999 + +Problem Description: + +On UNIX platforms, some executable files have the setuid (SUID) +bit on. It may be possible for a knowledgeable user to use +these executables to bypass your system security by elevating +their operating system privileges. Oracle Corporation has +identified issues regarding executables with SUID set in +Oracle releases 8.0.3, 8.0.4, 8.0.5 and 8.1.5 on UNIX platforms +only. This problem will be fixed in Oracle releases 8.0.6 and +8.1.6. + +Depending on your Oracle installation, the available patch will 1) +correct the SUID bits on applicable files, and/or 2) delete the +oratclsh file. This shell script should be run immediately, and also +should be run after each relink of Oracle. + +You can download the patch from Oracle Support?s MetaLink website by +going to the following URL, +http://support.oracle.com/ml/plsql/mlv15.frame?call_type=download&javaFlag=JAVA. +Once you are in this page, select 'Oracle RDBMS' as the product +and then click on the 'Go' button. Then download patch named 'setuid.' + +Please contact Oracle Worldwide Support for any additional issues. + +----- End forwarded message ----- + +Date: Sat, 08 May 1999 19:12:52 -0700 +From: Mark Dedlow + +I went to the URL listed for the patch, but it appears you can't get to +it directly. It requires a Oracle Metalink account, and even then, you +have to follow a bunch of links to get it, you can't go direct (at +least I couldn't at the URL in the announcement). + +You don't really need the patch however, it's just a shell script that +in effect does chmod -s on everything in $ORACLE_HOME/bin except +'oracle' and 'dbsnmp' (needed only for OEM or SNMP). + +Also, although the patch didn't address the issue, make sure _nothing_ +below ORACLE_HOME is owned by root. There are some installations that +make certain files setuid to root (files that are trivial to compromise). + +Mark + + +------------------------------------------------------------------------------ + +From: Dan Sugalski +Date: Mon, 10 May 1999 09:13:28 -0700 + +The patch actually removes the setuid bit on a number of oracle +executables. The 'unset' list is: + +lsnrctl oemevent onrsd osslogin tnslsnr tnsping trcasst trcroute cmctl +cmadmin cmgw names namesctl otrccref otrcfmt otrcrep otrccol oracleO + +While the 'must set' list is: + +oracle dbsnmp + +The shell script to fix the bits properly was posted to the oracle list +running at telelists.com. Check the archives there for it if you want. +(www.telelists.com) I think it's also gone out to one of the BUGTRAQ +lists, and some of the CERTs might have it too. + + Dan + +------------------------------------------------------------------------------ + +Date: Wed, 12 May 1999 11:49:45 -0700 +From: Mark Dedlow + +> The patch actually removes the setuid bit on a number of oracle +> executables. The 'unset' list is: +> +> lsnrctl oemevent onrsd osslogin tnslsnr tnsping trcasst trcroute cmctl +> cmadmin cmgw names namesctl otrccref otrcfmt otrcrep otrccol oracleO + +Actually, there's a little more than that. For each item in that list, +it also looks for a version of the file with a 0 or O appended to it +(these are backups the link makefiles create), so the above list isn't +exactly complete. + +The important issues are simply: + + o *ONLY* $ORACLE_HOME/bin/oracle requires setuid bit set for + the Oracle RDBMS and tools to function. + + o *IF* you run dbsnmp, it must be setuid. (If you don't know what dbsnmp + is, you're probably not running it -- it's a remote monitoring/control + daemon) + +Armed with that knowledge, you can use any technique you like to achieve +the desired results. For example, this achieves it: + +find $ORACLE_HOME/bin -perm -2000 ! -name oracle ! -name dbsnmp | xargs chmod -s + +Mark + +------------------------------------------------------------------------------ + diff --git a/dbdimp.c b/dbdimp.c index 02e6b2fb..6898860a 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.57 1999/06/14 00:41:48 timbo Exp $ + $Id: dbdimp.c,v 1.58 1999/07/12 03:20:42 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -25,11 +25,14 @@ int ora_fetchtest; static int ora_login_nomsg; /* don't fetch real login errmsg if true */ static int ora_sigchld_restart = 1; +#ifndef OCI_V8_SYNTAX static int set_sigint_handler = 0; +#endif static int ora2sql_type _((int oratype)); void ora_free_phs_contents _((phs_t *phs)); +static void dump_env_to_trace(); void dbd_init(dbistate) @@ -163,70 +166,98 @@ fb_ary_free(fb_ary) int dbd_db_login(dbh, imp_dbh, dbname, uid, pwd) + SV *dbh; imp_dbh_t *imp_dbh; char *dbname; char *uid; char *pwd; +{ + return dbd_db_login6(dbh, imp_dbh, dbname, uid, pwd, Nullsv); +} + + +int +dbd_db_login6(dbh, imp_dbh, dbname, uid, pwd, attr) SV *dbh; imp_dbh_t *imp_dbh; char *dbname; char *uid; char *pwd; + SV *attr; { dTHR; - int ret; + sword status; #ifdef OCI_V8_SYNTAX D_imp_drh_from_dbh; ub4 cred_type; + ub4 mode_type = OCI_DEFAULT; + SV **mode_type_sv; + + if (DBIS->debug >= 6 ) + dump_env_to_trace(); if (!imp_drh->envhp) { - /* OCI_OBJECT needed for OCIDescribeAny of table with LOBs */ - /* else you get a core dump (8.0.4). Thanks Oracle! */ - OCIInitialize((ub4) OCI_OBJECT, 0, 0,0,0); - ret = OCIEnvInit( &imp_drh->envhp, OCI_DEFAULT, 0, 0 ); + /* OCI_OBJECT needed for OCIDescribeAny of table with LOBs else */ + /* you get a core dump (Not doc'd in 8.0.4). Thanks Oracle! */ + ub4 init_mode = OCI_OBJECT; + SV **init_mode_sv; + DBD_ATTRIB_GET_IV(attr, "ora_init_mode",15, init_mode_sv, mode_type); + OCIInitialize_log_stat(init_mode, 0, 0,0,0, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, NULL, status, "OCIInitialize"); + return 0; + } + OCIEnvInit_log_stat( &imp_drh->envhp, OCI_DEFAULT, 0, 0, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, (OCIError*)imp_dbh->envhp, status, "OCIEnvInit"); + return 0; + } } imp_dbh->envhp = imp_drh->envhp; - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR); - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER); - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX); - - ret=OCIServerAttach(imp_dbh->srvhp, imp_dbh->errhp, - (text*)dbname, strlen(dbname), 0); - if (ret != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, ret, "OCIServerAttach"); - OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); - OCIHandleFree(imp_dbh->svchp, OCI_HTYPE_SVCCTX); - OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + + OCIServerAttach_log_stat(imp_dbh, dbname, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCIServerAttach"); + OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); return 0; } - OCIAttrSet( imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, - (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp); + OCIAttrSet_log_stat( imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, + (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp, status); - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_SESSION); + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_SESSION, status); cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); - ret=OCISessionBegin( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, - cred_type, (ub4) OCI_DEFAULT); - if (ret != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, ret, "OCISessionBegin"); - OCIServerDetach(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT ); - OCIHandleFree(imp_dbh->authp, OCI_HTYPE_SESSION); - OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); - OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); - OCIHandleFree(imp_dbh->svchp, OCI_HTYPE_SVCCTX); + DBD_ATTRIB_GET_IV(attr, "ora_session_mode",16, mode_type_sv, mode_type); + OCISessionBegin_log_stat( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, + cred_type, mode_type, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); + OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); + OCIHandleFree_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION,status); + OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); return 0; } - OCIAttrSet(imp_dbh->svchp, (ub4) OCI_HTYPE_SVCCTX, + OCIAttrSet_log_stat(imp_dbh->svchp, (ub4) OCI_HTYPE_SVCCTX, imp_dbh->authp, (ub4) 0, - (ub4) OCI_ATTR_SESSION, imp_dbh->errhp); + (ub4) OCI_ATTR_SESSION, imp_dbh->errhp, status); #else + if (DBIS->debug >= 6 ) + dump_env_to_trace(); + imp_dbh->lda = &imp_dbh->ldabuf; imp_dbh->hda = &imp_dbh->hdabuf[0]; /* can give duplicate free errors (from Oracle) if connect fails */ - ret = orlon(imp_dbh->lda, imp_dbh->hda, (text*)uid,-1, (text*)pwd,-1,0); + status = orlon(imp_dbh->lda, imp_dbh->hda, (text*)uid,-1, (text*)pwd,-1,0); - if (ret) { + if (status) { int rc = imp_dbh->lda->rc; char buf[100]; char *msg; @@ -303,7 +334,8 @@ dbd_db_commit(dbh, imp_dbh) imp_dbh_t *imp_dbh; { #ifdef OCI_V8_SYNTAX - sword status = OCITransCommit(imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT); + sword status; + OCITransCommit_log_stat(imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCITransCommit"); #else @@ -321,7 +353,8 @@ dbd_db_rollback(dbh, imp_dbh) imp_dbh_t *imp_dbh; { #ifdef OCI_V8_SYNTAX - sword status = OCITransRollback(imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT); + sword status; + OCITransRollback_log_stat(imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCITransRollback"); #else @@ -350,9 +383,11 @@ dbd_db_disconnect(dbh, imp_dbh) #ifdef OCI_V8_SYNTAX { - sword s_se = OCISessionEnd( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, OCI_DEFAULT); - sword s_sd = OCIServerDetach(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT ); + sword s_se, s_sd; + OCISessionEnd_log_stat(imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, + OCI_DEFAULT, s_se); if (s_se) oci_error(dbh, imp_dbh->errhp, s_se, "OCISessionEnd"); + OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, s_sd); if (s_sd) oci_error(dbh, imp_dbh->errhp, s_sd, "OCIServerDetach"); if (s_se || s_sd) return 0; @@ -378,9 +413,11 @@ dbd_db_destroy(dbh, imp_dbh) if (DBIc_ACTIVE(imp_dbh)) dbd_db_disconnect(dbh, imp_dbh); #ifdef OCI_V8_SYNTAX - OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); - OCIHandleFree(imp_dbh->svchp, OCI_HTYPE_SVCCTX); - OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); + { sword status; + OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); + } #else /* Nothing in imp_dbh to be freed */ #endif @@ -786,19 +823,19 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) sword status; if (!phs->desc_h || 1) { /* XXX phs->desc_t != OCI_HTYPE_STMT) { */ if (phs->desc_h) { - OCIHandleFree(phs->desc_h, phs->desc_t); + OCIHandleFree_log_stat(phs->desc_h, phs->desc_t, status); phs->desc_h = NULL; } phs->desc_t = OCI_HTYPE_STMT; - OCIHandleAlloc_ok(imp_sth->envhp, &phs->desc_h, phs->desc_t); + OCIHandleAlloc_ok(imp_sth->envhp, &phs->desc_h, phs->desc_t, status); } phs->progv = (void*)&phs->desc_h; phs->maxlen = 0; - status = OCIBindByName(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, strlen(phs->name), phs->progv, 0, phs->ftype, 0, /* using &phs->indp triggers ORA-01001 errors! */ - NULL, 0, 0, NULL, OCI_DEFAULT); + NULL, 0, 0, NULL, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_RSET"); return 0; @@ -949,24 +986,25 @@ dbd_rebind_ph(sth, imp_sth, phs) if (phs->maxlen > phs->maxlen_bound) { sword status; int at_exec = (phs->desc_h == NULL); - status = OCIBindByName(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, strlen(phs->name), phs->progv, - phs->maxlen ? phs->maxlen : 1, /* else bind "" fails */ + phs->maxlen ? (sb4)phs->maxlen : 1, /* else bind "" fails */ phs->ftype, &phs->indp, NULL, /* ub2 *alen_ptr not needed with OCIBindDynamic */ &phs->arcode, 0, /* max elements that can fit in allocated array */ NULL, /* (ptr to) current number of elements in array */ - at_exec ? OCI_DATA_AT_EXEC : OCI_DEFAULT + at_exec ? OCI_DATA_AT_EXEC : OCI_DEFAULT, + status ); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); return 0; } if (at_exec) { - status = OCIBindDynamic(phs->bndhp, imp_sth->errhp, - (dvoid *)phs, dbd_phs_in, (dvoid *)phs, dbd_phs_out); + OCIBindDynamic_log(phs->bndhp, imp_sth->errhp, (dvoid *)phs, dbd_phs_in, + (dvoid *)phs, dbd_phs_out, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); return 0; @@ -1206,14 +1244,16 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count #ifdef OCI_V8_SYNTAX - status = OCIStmtExecute(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, + OCIStmtExecute_log_stat(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, (is_select) ? 0 : 1, 0, 0, 0, /* we don't AutoCommit on select so LOB locators work */ (DBIc_has(imp_dbh,DBIcf_AutoCommit) && !is_select) - ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT); + ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT, + status); if (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO) { - oci_error(sth, imp_sth->errhp, status, "OCIStmtExecute"); + oci_error(sth, imp_sth->errhp, status, + ora_sql_error(imp_sth,"OCIStmtExecute")); return -2; } if (is_select) { @@ -1222,12 +1262,12 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count row_count = 0; } else { - OCIAttrGet_stmhp(imp_sth, &row_count, 0, OCI_ATTR_ROW_COUNT); + OCIAttrGet_stmhp_stat(imp_sth, &row_count, 0, OCI_ATTR_ROW_COUNT, status); } if (debug >= 2) { ub2 sqlfncode; - OCIAttrGet_stmhp(imp_sth, &sqlfncode, 0, OCI_ATTR_SQLFNCODE); + OCIAttrGet_stmhp_stat(imp_sth, &sqlfncode, 0, OCI_ATTR_SQLFNCODE, status); fprintf(DBILOGFP, " dbd_st_execute %s returned (%s, rpc%ld, fn%d, out%d)\n", oci_stmt_type_name(imp_sth->stmt_type), @@ -1362,6 +1402,7 @@ dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset) offset, len, destoffset); if (!SvOK(bufsv)) /* ora_blob_read_piece recorded error */ return 0; + ftype = ftype; /* no unused */ #else @@ -1406,7 +1447,7 @@ dbd_st_rows(sth, imp_sth) #ifdef OCI_V8_SYNTAX ub4 row_count = 0; sword status; - status = OCIAttrGet_stmhp(imp_sth, &row_count, 0, OCI_ATTR_ROW_COUNT); + OCIAttrGet_stmhp_stat(imp_sth, &row_count, 0, OCI_ATTR_ROW_COUNT, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIAttrGet OCI_ATTR_ROW_COUNT"); return -1; @@ -1455,7 +1496,8 @@ dbd_st_finish(sth, imp_sth) #ifdef OCI_V8_SYNTAX { sword status; - status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 0, OCI_FETCH_NEXT, OCI_DEFAULT); + OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp, 0, OCI_FETCH_NEXT, + OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "Finish OCIStmtFetch"); return 0; @@ -1487,7 +1529,7 @@ ora_free_fbh_contents(fbh) sv_free(fbh->name_sv); #ifdef OCI_V8_SYNTAX if (fbh->desc_h) - OCIDescriptorFree(fbh->desc_h, fbh->desc_t); + OCIDescriptorFree_log(fbh->desc_h, fbh->desc_t); #endif } @@ -1497,7 +1539,7 @@ ora_free_phs_contents(phs) { #ifdef OCI_V8_SYNTAX if (phs->desc_h) - OCIDescriptorFree(phs->desc_h, phs->desc_t); + OCIDescriptorFree_log(phs->desc_h, phs->desc_t); #else if (phs->ftype == 102 && phs->progv) { /* SQLT_CUR */ /* should not normally happen since new child sth takes */ @@ -1534,7 +1576,7 @@ dbd_st_destroy(sth, imp_sth) sword status; if (imp_sth->lob_refetch) ora_free_lob_refetch(sth, imp_sth); - status = OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); + OCIHandleFree_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, status); if (status != OCI_SUCCESS) oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); } @@ -1707,8 +1749,6 @@ dbd_st_FETCH_attrib(sth, imp_sth, keysv) return sv_2mortal(retsv); } - - /* --------------------------------------- */ static int @@ -1727,3 +1767,16 @@ ora2sql_type(oratype) /* else map type into DBI reserved standard range */ return -9000 - oratype; } + +static void +dump_env_to_trace() { + FILE *fp = DBILOGFP; + int i = 0; + char *p; + extern char **environ; + fprintf(fp, "Environment variables:\n"); + do { + p = (char*)environ[i++]; + fprintf(fp,"\t%s\n",p); + } while ((char*)environ[i] != '\0'); +} diff --git a/dbdimp.h b/dbdimp.h index 45e13def..172b3709 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,7 +1,7 @@ /* - $Id: dbdimp.h,v 1.35 1999/06/14 00:41:48 timbo Exp $ + $Id: dbdimp.h,v 1.36 1999/07/12 03:20:42 timbo Exp $ - Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce + Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file, @@ -41,6 +41,7 @@ #define _int64 long long #endif + /* This is slightly backwards because we want to auto-detect OCI8 */ /* and thus the existance of oci.h while still working for Oracle7 */ #include @@ -71,6 +72,7 @@ /* ------ end of Oracle include files ------ */ + /* ====== define data types ====== */ typedef struct imp_fbh_st imp_fbh_t; @@ -254,20 +256,7 @@ int dbd_rebind_ph_lob _((SV *sth, imp_sth_t *imp_sth, phs_t *phs)); void ora_free_lob_refetch _((SV *sth, imp_sth_t *imp_sth)); int post_execute_lobs _((SV *sth, imp_sth_t *imp_sth, ub4 row_count)); ub4 ora_parse_uid _((imp_dbh_t *imp_dbh, char **uidp, char **pwdp)); - -#define OCIAttrGet_stmhp(imp_sth, p, l, a) \ - OCIAttrGet(imp_sth->stmhp, OCI_HTYPE_STMT, (dvoid*)(p), (l), (a), imp_sth->errhp) - -#define OCIAttrGet_parmdp(imp_sth, parmdp, p, l, a) \ - OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (dvoid*)(p), (l), (a), imp_sth->errhp) - -#define OCIHandleAlloc_ok(envhp, p, t) \ - if (OCIHandleAlloc( (envhp), (dvoid**)(p), (t), 0, 0)==OCI_SUCCESS) ; \ - else croak("OCIHandleAlloc (type %d) failed",t) - -#define OCIDescriptorAlloc_ok(envhp, p, t) \ - if (OCIDescriptorAlloc((envhp), (dvoid**)(p), (t), 0, 0)==OCI_SUCCESS) ; \ - else croak("OCIDescriptorAlloc (type %d) failed",t) +char *ora_sql_error _((imp_sth_t *imp_sth, char *msg)); sb4 dbd_phs_in _((dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 *alenp, ub1 *piecep, dvoid **indpp)); @@ -276,19 +265,21 @@ sb4 dbd_phs_out _((dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, dvoid **indpp, ub2 **rcodepp)); int dbd_rebind_ph_rset _((SV *sth, imp_sth_t *imp_sth, phs_t *phs)); - #else /* is OCI 7 */ void ora_error _((SV *h, Lda_Def *lda, int rc, char *what)); #endif /* OCI_V8_SYNTAX */ +#include "ocitrace.h" + /* These defines avoid name clashes for multiple statically linked DBD's */ #define dbd_init ora_init #define dbd_db_login ora_db_login +#define dbd_db_login6 ora_db_login6 #define dbd_db_do ora_db_do #define dbd_db_commit ora_db_commit #define dbd_db_rollback ora_db_rollback diff --git a/oci8.c b/oci8.c index ba444f13..6bebe910 100644 --- a/oci8.c +++ b/oci8.c @@ -1,5 +1,5 @@ /* - $Id: oci8.c,v 1.19 1999/06/14 00:41:48 timbo Exp $ + $Id: oci8.c,v 1.20 1999/07/12 03:20:42 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -87,15 +87,15 @@ oci_error(SV *h, OCIError *errhp, sword status, char *what) sv_setpv(errstr, ""); if (errhp) { text errbuf[1024]; - ub4 recno = 0; sb4 errcode = 0; + ub4 recno = 0; sb4 eg_errcode = 0; sword eg_status; - while( (eg_status = OCIErrorGet(errhp, ++recno, (text*)NULL, - &eg_errcode, errbuf, - (ub4)sizeof(errbuf), OCI_HTYPE_ERROR)) != OCI_NO_DATA - && eg_status != OCI_INVALID_HANDLE - && recno < 100 + while( ++recno + && OCIErrorGet_log_stat(errhp, recno, (text*)NULL, &eg_errcode, errbuf, + (ub4)sizeof(errbuf), OCI_HTYPE_ERROR, eg_status) != OCI_NO_DATA + && eg_status != OCI_INVALID_HANDLE + && recno < 100 ) { if (DBIS->debug >= 4 || recno>1/*XXX temp*/) fprintf(DBILOGFP, " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", @@ -133,6 +133,39 @@ oci_error(SV *h, OCIError *errhp, sword status, char *what) } +char * +ora_sql_error(imp_sth_t *imp_sth, char *msg) +{ +#ifdef OCI_ATTR_PARSE_ERROR_OFFSET_xxx + imp_sth->cda->peo = 0; + if (oparse(imp_sth->cda, (text*)imp_sth->statement, (sb4)-1, + (sword)0/*oparse_defer*/, (ub4)oparse_lng) + ) { + char buf[99]; + char *hint = ""; + if (1) { /* XXX could make optional one day */ + SV *msgsv, *sqlsv; + sprintf(buf,"error possibly near <*> indicator at char %d in '", + imp_sth->cda->peo+1); + msgsv = sv_2mortal(newSVpv(buf,0)); + sqlsv = sv_2mortal(newSVpv(imp_sth->statement,0)); + sv_insert(sqlsv, imp_sth->cda->peo, 0, "<*>",3); + sv_catsv(msgsv, sqlsv); + sv_catpv(msgsv, "'"); + hint = SvPV(msgsv,na); + } + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, hint); + oclose(imp_sth->cda); /* close the cursor */ + imp_sth->cda = NULL; + return 0; + } +#else + imp_sth = imp_sth; /* not unused */ + return msg; +#endif +} + + int dbd_st_prepare(sth, imp_sth, statement, attribs) SV *sth; @@ -187,17 +220,17 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) default: oparse_lng = OCI_NTV_SYNTAX; break; } - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_sth->stmhp, OCI_HTYPE_STMT); - status = OCIStmtPrepare(imp_sth->stmhp, imp_sth->errhp, + OCIHandleAlloc_ok(imp_dbh->envhp, &imp_sth->stmhp, OCI_HTYPE_STMT, status); + OCIStmtPrepare_log_stat(imp_sth->stmhp, imp_sth->errhp, (text*)imp_sth->statement, (ub4)strlen(imp_sth->statement), - oparse_lng, OCI_DEFAULT); + oparse_lng, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIStmtPrepare"); - OCIHandleFree(imp_sth->stmhp, OCI_HTYPE_STMT); + OCIHandleFree_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, status); return 0; } - OCIAttrGet_stmhp(imp_sth, &imp_sth->stmt_type, 0, OCI_ATTR_STMT_TYPE); + OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->stmt_type, 0, OCI_ATTR_STMT_TYPE, status); if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_st_prepare'd sql %s\n", oci_stmt_type_name(imp_sth->stmt_type)); @@ -265,7 +298,7 @@ dbd_phs_out(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, *indpp = &phs->indp; *rcodepp= &phs->arcode; if (DBIS->debug >= 3) - fprintf(DBILOGFP, " dbd_phs_out '%s' (%ld,%ld): len %ld, piece %d%s\n", + fprintf(DBILOGFP, " dbd_phs_out '%s' (%ld,%ld): len %2ld, piece %d%s\n", phs->name, iter, index, phs->alen, *piecep, (phs->desc_h) ? " via descriptor" : ""); if (index > 0 || iter > 0) @@ -381,8 +414,8 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) OCIDescriptorAlloc_ok(imp_sth->envhp, &phs->desc_h, phs->desc_t); } - status = OCIAttrSet(phs->desc_h, phs->desc_t, - &lobEmpty, 0, OCI_ATTR_LOBEMPTY, imp_sth->errhp); + OCIAttrSet_log_stat(phs->desc_h, phs->desc_t, + &lobEmpty, 0, OCI_ATTR_LOBEMPTY, imp_sth->errhp, status); if (status != OCI_SUCCESS) return oci_error(sth, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_LOBEMPTY"); phs->progv = (void*)&phs->desc_h; @@ -408,14 +441,14 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, "blob_read not currently supported for non-LOB types with OCI 8 " "(but with OCI 8 you can set $dbh->{LongReadLen} to the length you need," "so you don't need to call blob_read at all)"); - SvOK_off(dest_sv); /* signal error */ + (void)SvOK_off(dest_sv); /* signal error */ return 0; } - status = OCILobGetLength(imp_sth->svchp, imp_sth->errhp, lobl, &loblen); + OCILobGetLength_log_stat(imp_sth->svchp, imp_sth->errhp, lobl, &loblen, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobGetLength"); - SvOK_off(dest_sv); /* signal error */ + (void)SvOK_off(dest_sv); /* signal error */ return 0; } @@ -433,16 +466,16 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, ub1 * bufp = (ub1 *)(SvPVX(dest_sv)); bufp += destoffset; - status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobl, + OCILobRead_log_stat(imp_sth->svchp, imp_sth->errhp, lobl, &amtp, 1 + offset, bufp, buflen, - 0, 0, 0, SQLCS_IMPLICIT); + 0, 0, 0, SQLCS_IMPLICIT, status); if (dbis->debug >= 3) fprintf(DBILOGFP, " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", fbh->field_num+1, oci_status_name(status), loblen, imp_sth->long_readlen, buflen, amtp); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobRead"); - SvOK_off(dest_sv); /* signal error */ + (void)SvOK_off(dest_sv); /* signal error */ return 0; } } @@ -478,7 +511,7 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) /* this function is not called for NULL lobs */ - status = OCILobGetLength(imp_sth->svchp, imp_sth->errhp, lobloc, &loblen); + OCILobGetLength_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, &loblen, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobGetLength"); return 0; @@ -512,8 +545,8 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) SvGROW(dest_sv, buflen+1); if (loblen > 0) { - status = OCILobRead(imp_sth->svchp, imp_sth->errhp, lobloc, - &amtp, 1, SvPVX(dest_sv), buflen, 0, 0, 0, SQLCS_IMPLICIT); + OCILobRead_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, + &amtp, 1, SvPVX(dest_sv), buflen, 0, 0, 0, SQLCS_IMPLICIT, status); if (DBIS->debug >= 3) fprintf(DBILOGFP, " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", @@ -593,15 +626,16 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) /* We know it's a select and we've not got the description yet, so if the */ /* sth is not 'active' (executing) then we need an explicit describe. */ if ( !DBIc_ACTIVE(imp_sth) ) { - status = OCIStmtExecute(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, - 0, 0, 0, 0, OCI_DESCRIBE_ONLY); + OCIStmtExecute_log_stat(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, + 0, 0, 0, 0, OCI_DESCRIBE_ONLY, status); if (status != OCI_SUCCESS) { - oci_error(h, imp_sth->errhp, status, "OCIStmtExecute/Describe"); + oci_error(h, imp_sth->errhp, status, + ora_sql_error(imp_sth, "OCIStmtExecute/Describe")); return 0; } } - status = OCIAttrGet_stmhp(imp_sth, &num_fields, 0, OCI_ATTR_PARAM_COUNT); + OCIAttrGet_stmhp_stat(imp_sth, &num_fields, 0, OCI_ATTR_PARAM_COUNT, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrGet OCI_ATTR_PARAM_COUNT"); return 0; @@ -619,20 +653,20 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->imp_sth = imp_sth; fbh->field_num = i; - status = OCIParamGet(imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, - (dvoid*)&fbh->parmdp, (ub4)i); + OCIParamGet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, + (dvoid*)&fbh->parmdp, (ub4)i, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIParamGet"); return 0; } - OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->dbtype, 0, OCI_ATTR_DATA_TYPE); - OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->dbsize, 0, OCI_ATTR_DATA_SIZE); - /* OCI_ATTR_PRECISION returns 0 for most types and even some numbers! */ - OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->prec, 0, OCI_ATTR_PRECISION); - OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->scale, 0, OCI_ATTR_SCALE); - OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->nullok, 0, OCI_ATTR_IS_NULL); - OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->name, &atrlen, OCI_ATTR_NAME); + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->dbtype, 0, OCI_ATTR_DATA_TYPE, status); + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->dbsize, 0, OCI_ATTR_DATA_SIZE, status); + /* OCI_ATTR_PRECISION returns 0 for most types including some numbers */ + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->prec, 0, OCI_ATTR_PRECISION, status); + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->scale, 0, OCI_ATTR_SCALE, status); + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->nullok, 0, OCI_ATTR_IS_NULL, status); + OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->name, &atrlen, OCI_ATTR_NAME,status); fbh->name_sv = newSVpv(fbh->name,atrlen); fbh->name = SvPVX(fbh->name_sv); @@ -729,8 +763,9 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) ub4 cache_rows = calc_cache_rows(num_fields, est_width, imp_sth->cache_rows, has_longs); imp_sth->cache_rows = cache_rows; /* record updated value */ - status = OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, - &cache_rows, sizeof(cache_rows), OCI_ATTR_PREFETCH_ROWS, imp_sth->errhp); + OCIAttrSet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, + &cache_rows, sizeof(cache_rows), OCI_ATTR_PREFETCH_ROWS, + imp_sth->errhp, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_PREFETCH_ROWS"); return 0; @@ -739,10 +774,14 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) else { /* set cache size by memory */ ub4 cache_mem = -imp_sth->cache_rows; ub4 cache_rows = 100000; /* set high so memory is the limit */ - status = OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, - &cache_rows, sizeof(cache_rows), OCI_ATTR_PREFETCH_ROWS, imp_sth->errhp) - || OCIAttrSet(imp_sth->stmhp, OCI_HTYPE_STMT, - &cache_mem, sizeof(cache_mem), OCI_ATTR_PREFETCH_MEMORY, imp_sth->errhp); + OCIAttrSet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, + &cache_rows, sizeof(cache_rows), OCI_ATTR_PREFETCH_ROWS, + imp_sth->errhp, status); + if (! status) { + OCIAttrSet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, + &cache_mem, sizeof(cache_mem), OCI_ATTR_PREFETCH_MEMORY, + imp_sth->errhp, status); + } if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_PREFETCH_ROWS/OCI_ATTR_PREFETCH_MEMORY"); @@ -765,13 +804,13 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->fb_ary = fb_ary_alloc(define_len, 1); fb_ary = fbh->fb_ary; - status = OCIDefineByPos(imp_sth->stmhp, &fbh->defnp, imp_sth->errhp, (ub4) i, + OCIDefineByPos_log_stat(imp_sth->stmhp, &fbh->defnp, imp_sth->errhp, (ub4) i, (fbh->desc_h) ? (dvoid*)&fbh->desc_h : (dvoid*)fb_ary->abuf, (fbh->desc_h) ? -1 : define_len, fbh->ftype, fb_ary->aindp, (ftype==94||ftype==95) ? NULL : fb_ary->arlen, - fb_ary->arcode, OCI_DEFAULT); + fb_ary->arcode, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIDefineByPos"); return 0; @@ -814,7 +853,8 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth) else { if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_st_fetch %d fields...\n", DBIc_NUM_FIELDS(imp_sth)); - status = OCIStmtFetch(imp_sth->stmhp, imp_sth->errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT); + OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp, 1, OCI_FETCH_NEXT, + OCI_DEFAULT, status); } if (status != OCI_SUCCESS) { @@ -925,6 +965,7 @@ ora_parse_uid(imp_dbh, uidp, pwdp) char **uidp; char **pwdp; { + sword status; /* OCI 8 does not seem to allow uid to be "name/pass" :-( */ /* so we have to split it up ourselves */ if (strlen(*pwdp)==0 && strchr(*uidp,'/')) { @@ -937,12 +978,12 @@ ora_parse_uid(imp_dbh, uidp, pwdp) if (**uidp == '\0' && **pwdp == '\0') { return OCI_CRED_EXT; } - OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, + OCIAttrSet_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION, *uidp, strlen(*uidp), - (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp); - OCIAttrSet(imp_dbh->authp, OCI_HTYPE_SESSION, + (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION, (strlen(*pwdp)) ? *pwdp : NULL, strlen(*pwdp), - (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp); + (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp, status); return OCI_CRED_RDBMS; } @@ -957,10 +998,10 @@ ora_db_reauthenticate(dbh, imp_dbh, uid, pwd) sword status; /* XXX should possibly create new session before ending the old so */ /* that if the new one can't be created, the old will still work. */ - OCISessionEnd (imp_dbh->svchp, imp_dbh->errhp, - imp_dbh->authp, OCI_DEFAULT); - status = OCISessionBegin( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, - ora_parse_uid(imp_dbh, &uid, &pwd), (ub4) OCI_DEFAULT); + OCISessionEnd_log_stat(imp_dbh->svchp, imp_dbh->errhp, + imp_dbh->authp, OCI_DEFAULT, status); /* XXX check status here?*/ + OCISessionBegin_log_stat( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, + ora_parse_uid(imp_dbh, &uid, &pwd), (ub4) OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); return 0; @@ -1097,22 +1138,26 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) return oci_error(sth, errhp, OCI_ERROR, "Unable to parse table name for LOB refetch"); - OCIHandleAlloc_ok(imp_sth->envhp, &dschp, OCI_HTYPE_DESCRIBE); - status = OCIDescribeAny(imp_sth->svchp, errhp, tablename, strlen(tablename), - OCI_OTYPE_NAME, 1, OCI_PTYPE_TABLE, dschp); + OCIHandleAlloc_ok(imp_sth->envhp, &dschp, OCI_HTYPE_DESCRIBE, status); + OCIDescribeAny_log_stat(imp_sth->svchp, errhp, tablename, strlen(tablename), + OCI_OTYPE_NAME, 1, OCI_PTYPE_TABLE, dschp, status); if (status != OCI_SUCCESS) { - OCIHandleFree(dschp, OCI_HTYPE_DESCRIBE); + OCIHandleFree_log_stat(dschp, OCI_HTYPE_DESCRIBE, status); return oci_error(sth, errhp, status, "OCIDescribeAny/LOB refetch"); } - status = OCIAttrGet(dschp, OCI_HTYPE_DESCRIBE, - &parmhp, 0, OCI_ATTR_PARAM, errhp) - || OCIAttrGet(parmhp, OCI_DTYPE_PARAM, - &numcols, 0, OCI_ATTR_NUM_COLS, errhp) - || OCIAttrGet(parmhp, OCI_DTYPE_PARAM, - &collisthd, 0, OCI_ATTR_LIST_COLUMNS, errhp); + OCIAttrGet_log_stat(dschp, OCI_HTYPE_DESCRIBE, + &parmhp, 0, OCI_ATTR_PARAM, errhp, status); + if ( ! status ) { + OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM, + &numcols, 0, OCI_ATTR_NUM_COLS, errhp, status); + } + if ( ! status ) { + OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM, + &collisthd, 0, OCI_ATTR_LIST_COLUMNS, errhp, status); + } if (status != OCI_SUCCESS) { - OCIHandleFree(dschp, OCI_HTYPE_DESCRIBE); + OCIHandleFree_log_stat(dschp, OCI_HTYPE_DESCRIBE, status); return oci_error(sth, errhp, status, "OCIDescribeAny/OCIAttrGet/LOB refetch"); } if (DBIS->debug >= 3) @@ -1124,13 +1169,17 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) ub2 col_dbtype; char *col_name; ub4 col_name_len; - if ((status=OCIParamGet(collisthd, OCI_DTYPE_PARAM, errhp, (dvoid**)&colhd, i))) + OCIParamGet_log_stat(collisthd, OCI_DTYPE_PARAM, errhp, (dvoid**)&colhd, + i, status); + if (status) break; - if ((status=OCIAttrGet(colhd, OCI_DTYPE_PARAM, &col_dbtype, 0, - OCI_ATTR_DATA_TYPE, errhp))) + OCIAttrGet_log_stat(colhd, OCI_DTYPE_PARAM, &col_dbtype, 0, + OCI_ATTR_DATA_TYPE, errhp, status); + if (status) break; - if ((status=OCIAttrGet(colhd, OCI_DTYPE_PARAM, &col_name, &col_name_len, - OCI_ATTR_NAME, errhp))) + OCIAttrGet_log_stat(colhd, OCI_DTYPE_PARAM, &col_name, &col_name_len, + OCI_ATTR_NAME, errhp, status); + if (status) break; if (DBIS->debug >= 3) fprintf(DBILOGFP, " lob refetch table col %d: '%.*s' otype %d\n", @@ -1145,7 +1194,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) hv_store(lob_cols_hv, col_name,col_name_len, sv,0); } if (status != OCI_SUCCESS) { - OCIHandleFree(dschp, OCI_HTYPE_DESCRIBE); + OCIHandleFree_log_stat(dschp, OCI_HTYPE_DESCRIBE, status); return oci_error(sth, errhp, status, "OCIDescribeAny/OCIParamGet/OCIAttrGet/LOB refetch"); } @@ -1250,16 +1299,17 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) lr->parmdp_lob = NULL; - OCIHandleAlloc_ok(imp_sth->envhp, &lr->stmthp, OCI_HTYPE_STMT); - status = OCIStmtPrepare(lr->stmthp, errhp, - (text*)SvPVX(sql_select), SvCUR(sql_select), OCI_NTV_SYNTAX, OCI_DEFAULT); + OCIHandleAlloc_ok(imp_sth->envhp, &lr->stmthp, OCI_HTYPE_STMT, status); + OCIStmtPrepare_log_stat(lr->stmthp, errhp, + (text*)SvPVX(sql_select), SvCUR(sql_select), OCI_NTV_SYNTAX, + OCI_DEFAULT, status); if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCIStmtPrepare/LOB refetch"); /* bind the rowid input */ OCIDescriptorAlloc_ok(imp_sth->envhp, &lr->rowid, OCI_DTYPE_ROWID); - status = OCIBindByName(lr->stmthp, &lr->bindhp, errhp, (text*)":rid", 4, - &lr->rowid, sizeof(OCIRowid*), SQLT_RDD, 0,0,0,0,0, OCI_DEFAULT); + OCIBindByName_log_stat(lr->stmthp, &lr->bindhp, errhp, (text*)":rid", 4, + &lr->rowid, sizeof(OCIRowid*), SQLT_RDD, 0,0,0,0,0, OCI_DEFAULT, status); if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCIBindByPos/LOB refetch"); @@ -1278,8 +1328,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) fprintf(DBILOGFP, " lob refetch %d for '%s' param: ftype %d setup\n", (int)i+1,fbh->name, fbh->dbtype); - status = OCIDefineByPos(lr->stmthp, &defnp, errhp, i+1, - &fbh->desc_h, -1, fbh->ftype, 0,0,0, OCI_DEFAULT); + OCIDefineByPos_log_stat(lr->stmthp, &defnp, errhp, i+1, + &fbh->desc_h, -1, fbh->ftype, 0,0,0, OCI_DEFAULT, status); if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCIDefineByPos/LOB refetch"); } @@ -1311,26 +1361,28 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl return 0; /* init_lob_refetch already called oci_error */ lr = imp_sth->lob_refetch; - status = OCIAttrGet_stmhp(imp_sth, (dvoid**)lr->rowid, &rowid_iter, OCI_ATTR_ROWID); + OCIAttrGet_stmhp_stat(imp_sth, (dvoid**)lr->rowid, &rowid_iter, OCI_ATTR_ROWID, + status); if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCIAttrGet OCI_ATTR_ROWID /LOB refetch"); - status = OCIStmtExecute(imp_sth->svchp, lr->stmthp, errhp, - 1, 0, NULL, NULL, OCI_DEFAULT); /* execute and fetch */ + OCIStmtExecute_log_stat(imp_sth->svchp, lr->stmthp, errhp, + 1, 0, NULL, NULL, OCI_DEFAULT, status); /* execute and fetch */ if (status != OCI_SUCCESS) - return oci_error(sth, errhp, status, "OCIStmtExecute/LOB refetch"); + return oci_error(sth, errhp, status, + ora_sql_error(imp_sth,"OCIStmtExecute/LOB refetch")); for(i=0; i < lr->num_fields; ++i) { imp_fbh_t *fbh = &lr->fbh_ary[i]; phs_t *phs = (phs_t*)fbh->special; ub4 amtp = SvCUR(phs->sv); if (amtp > 0) { /* since amtp==0 & OCI_ONE_PIECE fail (OCI 8.0.4) */ - status = OCILobWrite(imp_sth->svchp, errhp, + OCILobWrite_log_stat(imp_sth->svchp, errhp, fbh->desc_h, &amtp, 1, SvPVX(phs->sv), amtp, OCI_ONE_PIECE, - 0,0, 0,SQLCS_IMPLICIT); + 0,0, 0,SQLCS_IMPLICIT, status); } else { - status = OCILobTrim(imp_sth->svchp, errhp, fbh->desc_h, 0); + OCILobTrim_log_stat(imp_sth->svchp, errhp, fbh->desc_h, 0, status); } if (DBIS->debug >= 3) fprintf(DBILOGFP, @@ -1350,7 +1402,8 @@ ora_free_lob_refetch(SV *sth, imp_sth_t *imp_sth) { lob_refetch_t *lr = imp_sth->lob_refetch; int i; - sword status = OCIHandleFree(lr->stmthp, OCI_HTYPE_STMT); + sword status; + OCIHandleFree_log_stat(lr->stmthp, OCI_HTYPE_STMT, status); if (status != OCI_SUCCESS) oci_error(sth, imp_sth->errhp, status, "ora_free_lob_refetch/OCIHandleFree"); for(i=0; i < lr->num_fields; ++i) { diff --git a/ocitrace.h b/ocitrace.h new file mode 100644 index 00000000..4297619d --- /dev/null +++ b/ocitrace.h @@ -0,0 +1,245 @@ +#ifdef OCI_V8_SYNTAX + +/* OCI functions "wrapped" to produce tracefile dumps (may be handy when giving + diagnostic info to Oracle Support, or just learning about OCI) + Macros are named "_log" as a mnemonic that they log to the tracefile if needed + Macros named "_log_stat" return status in last parameter. +*/ + +#define DBD_OCI_TRACEON (DBIS->debug >= 6) +#define DBD_OCI_TRACEFP (DBILOGFP) +#define OciTp ("OCI") /* OCI Trace Prefix */ +#define OciTstr(s) ((s) ? (text*)(s) : (text*)"") + +/* XXX TO DO + + 1. Add parenthesis around all macro args. (or do item 4 below case-by-case) + DMG: Partly done, sort of. At least the types all match the doc'd casts, anyway. + + 2. #define a set of OciTxxx macros for different types of parameters + that would allow + a: casting to be hidden + b: casting easily changed on different platforms (64bit etc) + c: mapping of some type values to strings, + d: return pointed-to value instead of pointer where applicable + + How to output arguments that are handles to opaque entities (OCIEnv*, etc)? + Output of pointer address is a quick n' dirty way of identifying + any number of handles that may be allocated.... yuck... + It sure would be nice to give something more mnemonic! (and meaningful!) + XXX Turn pointers into variable names by adding a prefix letter and, where + appropriate an &, thus: "...,&p%ld,...", + If done well the log will read like a compilable program. +*/ + + +#define OCIAttrGet_log_stat(th,ht,ah,sp,at,eh,stat) \ + stat = OCIAttrGet(th,ht,ah,sp,at,eh); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sAttrGet(%p,%lu,%p,%p,%lu,%p)=%s\n", \ + OciTp, (void*)th,(ub4)ht,(void*)ah,(ub4*)sp,(ub4)at,(void*)eh,\ + oci_status_name(stat)),stat : stat + +#define OCIAttrGet_parmdp(imp_sth, parmdp, p, l, a, stat) \ + OCIAttrGet_log_stat(parmdp, OCI_DTYPE_PARAM, \ + (void*)(p), (l), (a), imp_sth->errhp, stat) + +#define OCIAttrGet_stmhp_stat(imp_sth, p, l, a, stat) \ + OCIAttrGet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, \ + (void*)(p), (l), (a), imp_sth->errhp, stat) + +#define OCIAttrSet_log_stat(th,ht,ah,s,a,eh,stat) \ + stat=OCIAttrSet(th,ht,ah,s,a,eh); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sAttrSet(%p,%lu,%p,%lu,%lu,%p)=%s\n", \ + OciTp, (void*)th,(ub4)ht,(void*)(ah),(ub4)s,(ub4)a,(void*)eh, \ + oci_status_name(stat)),stat : stat + +#define OCIBindByName_log_stat(sh,bp,eh,p,pl,v,vs,dt,in,al,rc,mx,cu,md,stat) \ + stat=OCIBindByName(sh,bp,eh,p,pl,v,vs,dt,in,al,rc,mx,cu,md); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sBindByName(%p,%p,%p,\"%s\",%ld,%p,%ld,%u,%p,%p,%p,%lu,%p,%lu)=%s\n",\ + OciTp, (void*)sh,(void*)bp,(void*)eh,p,(sb4)(pl),(void*)(v), \ + (sb4)(vs),(ub2)(dt),(void*)(in),(ub2*)(al),(ub2*)(rc), \ + (ub4)(mx),(ub4*)(cu),(ub4)(md), \ + oci_status_name(stat)),stat : stat + +#define OCIBindDynamic_log(bh,eh,icx,cbi,ocx,cbo,stat) \ + stat=OCIBindDynamic(bh,eh,icx,cbi,ocx,cbo); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sBindDynamic(%p,%p,%p,%p,%p,%p)=%s\n", \ + OciTp, (void*)bh,(void*)eh,(void*)icx,(void*)cbi, \ + (void*)ocx,(void*)cbo, \ + oci_status_name(stat)),stat : stat + +#define OCIDefineByPos_log_stat(sh,dp,eh,p,vp,vs,dt,ip,rp,cp,m,stat) \ + stat=OCIDefineByPos(sh,dp,eh,p,vp,vs,dt,ip,rp,cp,m); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sDefineByPos(%p,%p,%p,%lu,%p,%ld,%u,%p,%p,%p,%lu)=%s\n", \ + OciTp, (void*)sh,(void*)dp,(void*)eh,(ub4)(p),(void*)(vp), \ + (sb4)vs,(ub2)dt,(void*)(ip),(ub2*)(rp),(ub2*)(cp),(ub4)m, \ + oci_status_name(stat)),stat : stat + +#define OCIDescribeAny_log_stat(sh,eh,op,ol,opt,il,ot,dh,stat) \ + stat=OCIDescribeAny(sh,eh,op,ol,opt,il,ot,dh); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sDescribeAny(%p,%p,%p,%lu,%u,%u,%u,%p)=%s\n", \ + OciTp, (void*)sh,(void*)eh,(void*)op,(ub4)ol, \ + (ub1)opt,(ub1)il,(ub1)ot,(void*)dh, \ + oci_status_name(stat)),stat : stat + +#define OCIDescriptorAlloc_ok(envhp, p, t) \ + if (DBD_OCI_TRACEON) fprintf(DBD_OCI_TRACEFP, \ + "%sDescriptorAlloc(%p,%p,%lu,0,0)\n", \ + OciTp,(void*)envhp,(void*)(p),(ub4)t); \ + if (OCIDescriptorAlloc((envhp), (void**)(p), (t), 0, 0)==OCI_SUCCESS); \ + else croak("OCIDescriptorAlloc (type %ld) failed",t) + +#define OCIDescriptorFree_log(d,t) \ + if (DBD_OCI_TRACEON) fprintf(DBD_OCI_TRACEFP, \ + "%sDescriptorFree(%p,%lu)\n", OciTp, (void*)d,(ub4)t); \ + OCIDescriptorFree(d,t) + +#define OCIEnvInit_log_stat(ev,md,xm,um,stat) \ + stat=OCIEnvInit(ev,md,xm,um); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sEnvInit(%p,%lu,%lu,%p)=%s\n", \ + OciTp, (void*)ev,(ub4)md,(ub4)xm,(void*)um, \ + oci_status_name(stat)),stat : stat + +#define OCIErrorGet_log_stat(hp,rn,ss,ep,bp,bs,t, stat) \ + ((stat = OCIErrorGet(hp,rn,ss,ep,bp,bs,t)), \ + ((DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sErrorGet(%p,%lu,\"%s\",%p,\"%s\",%lu,%lu)=%s\n", \ + OciTp, (void*)hp,(ub4)rn,OciTstr(ss),(sb4*)ep, \ + bp,(ub4)bs,(ub4)t, oci_status_name(stat)),stat : stat)) + +#define OCIHandleAlloc_log_stat(ph,hp,t,xs,ump,stat) \ + stat=OCIHandleAlloc(ph,hp,t,xs,ump); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sHandleAlloc(%p,%p,%lu,%lu,%p)=%s\n", \ + OciTp, (void*)ph,(void*)hp,(ub4)t,(ub4)xs,(void*)ump, \ + oci_status_name(stat)),stat : stat + +#define OCIHandleAlloc_ok(envhp, p, t, stat) \ + OCIHandleAlloc_log_stat((envhp),(void**)(p),(t),0,0, stat); \ + if (stat==OCI_SUCCESS) ; \ + else croak("OCIHandleAlloc (type %lu) failed",(ub4)t) + +#define OCIHandleFree_log_stat(hp,t,stat) \ + stat=OCIHandleFree( (hp), (t)); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sHandleFree(%p,%lu)=%s\n",OciTp,(void*)hp,(ub4)t, \ + oci_status_name(stat)),stat : stat + +#define OCIInitialize_log_stat(md,cp,mlf,rlf,mfp,stat) \ + stat=OCIInitialize(md,cp,mlf,rlf,mfp); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sInitialize(%lu,%p,%p,%p,%p)=%s\n", \ + OciTp, (ub4)md,(void*)cp,(void*)mlf,(void*)rlf,(void*)mfp, \ + oci_status_name(stat)),stat : stat + +#define OCILobGetLength_log_stat(sh,eh,lh,l,stat) \ + stat=OCILobGetLength(sh,eh,lh,l); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sLobGetLength(%p,%p,%p,%p)=%s\n", \ + OciTp, (void*)sh,(void*)eh,(void*)lh,(ub4*)l, \ + oci_status_name(stat)),stat : stat + +#define OCILobRead_log_stat(sv,eh,lh,am,of,bp,bl,cx,cb,csi,csf,stat) \ + stat=OCILobRead(sv,eh,lh,am,of,bp,bl,cx,cb,csi,csf); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sLobRead(%p,%p,%p,%p,%lu,%p,%lu,%p,%p,%u,%u)=%s\n", \ + OciTp, (void*)sv,(void*)eh,(void*)lh,(ub4*)am,(ub4)of, \ + (void*)bp,(ub4)bl,(void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ + oci_status_name(stat)),stat : stat + +#define OCILobTrim_log_stat(sv,eh,lh,l,stat) \ + stat=OCILobTrim(sv,eh,lh,l); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sLobtrim(%p,%p,%p,%lu)=%s\n", \ + OciTp, (void*)sv,(void*)eh,(void*)lh,(ub4)l, \ + oci_status_name(stat)),stat : stat + +#define OCILobWrite_log_stat(sv,eh,lh,am,of,bp,bl,p,cx,cb,csi,csf,stat) \ + stat=OCILobWrite(sv,eh,lh,am,of,bp,bl,p,cx,cb,csi,csf); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sLobWrite(%p,%p,%p,%p,%lu,%p,%lu,%u,%p,%p,%u,%u)=%s\n", \ + OciTp, (void*)sv,(void*)eh,(void*)lh,(ub4*)am,(ub4)of, \ + (void*)bp,(ub4)bl,(ub1)p, \ + (void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ + oci_status_name(stat)),stat : stat + +#define OCIParamGet_log_stat(hp,ht,eh,pp,ps,stat) \ + stat=OCIParamGet(hp,ht,eh,pp,ps); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sParamGet(%p,%lu,%p,%p,%lu)=%s\n", \ + OciTp, (void*)hp,(ub4)(ht),(void*)eh,(void*)pp,(ub4)ps, \ + oci_status_name(stat)),stat : stat + +#define OCIServerAttach_log_stat(imp_dbh, dbname,stat) \ + stat=OCIServerAttach( imp_dbh->srvhp, imp_dbh->errhp, \ + (text*)dbname, strlen(dbname), 0); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sServerAttach(%p, %p, \"%s\", %d, 0)=%s\n", \ + OciTp, (void*)imp_dbh->srvhp,(void*)imp_dbh->errhp, dbname, \ + strlen(dbname), oci_status_name(stat)),stat : stat + +#define OCIStmtExecute_log_stat(sv,st,eh,i,ro,si,so,md,stat) \ + stat=OCIStmtExecute(sv,st,eh,i,ro,si,so,md); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sStmtExecute(%p,%p,%p,%lu,%lu,%p,%p,%lu)=%s\n", \ + OciTp, (void*)sv,(void*)st,(void*)eh,(ub4)(i), \ + (ub4)(ro),(void*)(si),(void*)(so),(ub4)(md), \ + oci_status_name(stat)),stat : stat + +#define OCIStmtFetch_log_stat(sh,eh,nr,or,md,stat) \ + stat=OCIStmtFetch(sh,eh,nr,or,md); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sStmtFetch(%p,%p,%lu,%u,%lu)=%s\n", \ + OciTp, (void*)sh,(void*)eh,(ub4)nr,(ub2)or,(ub4)md, \ + oci_status_name(stat)),stat : stat + +#define OCIStmtPrepare_log_stat(sh,eh,s,sl,l,m,stat) \ + stat=OCIStmtPrepare(sh,eh,s,sl,l,m); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sStmtPrepare(%p,%p,'%s',%lu,%lu,%lu)=%s\n", \ + OciTp, (void*)sh,(void*)eh,s,(ub4)sl,(ub4)l,(ub4)m, \ + oci_status_name(stat)),stat : stat + +#define OCIServerDetach_log_stat(sh,eh,md,stat) \ + stat=OCIServerDetach(sh,eh,md); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sServerDetach(%p,%p,%lu)=%s\n", \ + OciTp, (void*)sh,(void*)eh,(ub4)md, \ + oci_status_name(stat)),stat : stat + +#define OCISessionBegin_log_stat(sh,eh,uh,cr,md,stat) \ + stat=OCISessionBegin(sh,eh,uh,cr,md); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sSessionBegin(%p,%p,%p,%lu,%lu)=%s\n", \ + OciTp, (void*)sh,(void*)eh,(void*)uh,(ub4)cr,(ub4)md, \ + oci_status_name(stat)),stat : stat + +#define OCISessionEnd_log_stat(sh,eh,ah,md,stat) \ + stat=OCISessionEnd(sh,eh,ah,md); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sSessionEnd(%p,%p,%p,%lu)=%s\n", \ + OciTp, (void*)sh,(void*)eh,(void*)ah,(ub4)md, \ + oci_status_name(stat)),stat : stat + +#define OCITransCommit_log_stat(sh,eh,md,stat) \ + stat=OCITransCommit(sh,eh,md); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sTransCommit(%p,%p,%lu)=%s\n", \ + OciTp, (void*)sh,(void*)eh,(ub4)md, \ + oci_status_name(stat)),stat : stat + +#define OCITransRollback_log_stat(sh,eh,md,stat) \ + stat=OCITransRollback(sh,eh,md); \ + (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ + "%sTransRollback(%p,%p,%lu)=%s\n", \ + OciTp, (void*)sh,(void*)eh,(ub4)md, \ + oci_status_name(stat)),stat : stat + +#endif /* OCI_V8_SYNTAX */ diff --git a/ora_explain.PL b/ora_explain.PL index ac2cc752..479bcbaa 100644 --- a/ora_explain.PL +++ b/ora_explain.PL @@ -28,7 +28,7 @@ my $script = <<'SCRIPT'; use strict; use File::Basename; use DBI; -use Tk 800; +use Tk; use Tk::Balloon; use Tk::ErrorDialog; use Tk::ROText; @@ -70,7 +70,7 @@ $w->Callback(-b3command => $ent); package main; use vars qw($VERSION); -$VERSION = "1.0"; +$VERSION = "1.1"; # Globals # $ProgName Program name (without pathname) @@ -1030,22 +1030,24 @@ $GrabDetails->delete("1.0", "end"); busy(1); my $qry = $Db->prepare(qq( $SqlMarker select executions, disk_reads, buffer_gets, rows_processed, - sorts, loads, parse_calls + sorts, loads, parse_calls, first_load_time from v\$sqlarea where address = :1 )) || die("Statement info:\n$DBI::errstr\n"); # Read the info. Note that the statement *may* have been purged from the cache! $qry->execute($address); if (! (my ($executions, $disk_reads, $buffer_gets, $rows_processed, - $sorts, $loads, $parse_calls) + $sorts, $loads, $parse_calls, $first_load_time) = $qry->fetchrow_array())) { $GrabDetails->insert("1.0", "This statement is no longer in the SQL cache"); } else { + $first_load_time =~ s!/! !; $GrabDetails->insert("1.0", "First executed by user", "bold", - " $puid\n"); + " $puid ", "", + " at", "bold", " $first_load_time\n"); $GrabDetails->insert("end", "Total ", "bold"); $GrabDetails->insert("end", sprintf("Executions: %8d\n", $executions)); my $fmt = @@ -1091,14 +1093,15 @@ if (! eval { disp_sql_cache_info($tag, $puid); }) ################################################################################ # Scan v$sqlarea for SQL statements matching the specified conditions. -# $order_by is a v$sqlarea colum name used to rank the statements +# $order_by is a v$sqlarea column name used to rank the statements +# $sort_by is "asc" or "desc" # $user is who first issued the statement (case insensitive) # $pattern is a perl regexp used to filter the SQL # $rows is the maximum number of rows to display -sub grab($$$$$$) +sub grab($$$$$$$) { -my ($ordering, $order_by, $no_sys, $user, $pattern, $rows) = @_; +my ($ordering, $order_by, $sort_by, $no_sys, $user, $pattern, $rows) = @_; # Check we are logged on die("You are not logged on to Oracle\n") if (! $Db); @@ -1111,6 +1114,7 @@ $user = uc($user); # Clear the frames $GrabSql->delete("1.0", "end"); $GrabDetails->delete("1.0", "end"); +$GrabStatus->configure(-text => "Please wait..."); # Define the callbacks for highlighting etc my $highlight = sub @@ -1134,9 +1138,9 @@ $qry1 .= qq{ and user_id = parsing_user_id}; # if($user || $no_sys); $qry1 .= qq{ and username = :1} if ($user); $qry1 .= qq{ and username not in ('SYS', 'SYSTEM')} if ($no_sys); if ($ordering eq "total") - { $qry1 .= qq{ order by $order_by desc}; } + { $qry1 .= qq{ order by $order_by $sort_by}; } elsif ($ordering eq "average") - { $qry1 .= qq{ order by $order_by / greatest(executions, 1) desc}; } + { $qry1 .= qq{ order by $order_by / greatest(executions, 1) $sort_by}; } $qry1 = $Db->prepare($qry1) || die("SQL Cache capture:\n$DBI::errstr\n"); my $qry2; @@ -1221,37 +1225,49 @@ $GrabMain->protocol("WM_DELETE_WINDOW", sub { $GrabMain->withdraw(); }); # Defaults & callbacks my $ordering = ""; my $order_by = ""; +my $sort_by = ""; my $no_sys = 1; my $user = ""; my $pattern = ""; my $rows = 100; my $grab_cb = sub { - if (! eval { grab($ordering, $order_by, $no_sys, $user, $pattern, $rows); }) + if (! eval { grab($ordering, $order_by, $sort_by, $no_sys, + $user, $pattern, $rows); }) { error($GrabMain, $@); } }; -my (%ord_bn); # For "order by" buttons +my (%ord_bn, %sort_bn); # For "order by" and "sort order" buttons my $ord_bn_cb = sub { if ($ordering eq "") { $order_by = ""; + $sort_by = ""; foreach my $bn (values(%ord_bn)) { $bn->configure(-state => "disabled"); } + foreach my $bn (values(%sort_bn)) + { $bn->configure(-state => "disabled"); } } elsif ($ordering eq "total") { $order_by = "disk_reads" if ($order_by eq ""); + $sort_by = "desc" if ($sort_by eq ""); foreach my $bn (values(%ord_bn)) { $bn->configure(-state => "normal"); } + foreach my $bn (values(%sort_bn)) + { $bn->configure(-state => "normal"); } } else # $ordering eq "average" { $order_by = "disk_reads" if ($order_by eq "" || $order_by eq "executions"); + $sort_by = "desc" if ($sort_by eq ""); foreach my $bn (values(%ord_bn)) { $bn->configure(-state => "normal"); } $ord_bn{executions}->configure(-state => "disabled"); + $ord_bn{first_load_time}->configure(-state => "disabled"); + foreach my $bn (values(%sort_bn)) + { $bn->configure(-state => "normal"); } } }; @@ -1342,27 +1358,46 @@ $ord_bn{rows_processed} = $frame3->Radiobutton(-text => "Rows processed", -highlightthickness => 0, -value => "rows_processed", -variable => \$order_by, -command => $ord_bn_cb) - ->grid(-column => 2, -row => 0, -sticky => "w"); + ->grid(-column => 0, -row => 1, -sticky => "w"); $ord_bn{sorts} = $frame3->Radiobutton(-text => "Sorts", -highlightthickness => 0, -value => "sorts", -variable => \$order_by, -command => $ord_bn_cb) - ->grid(-column => 0, -row => 1, -sticky => "w"); + ->grid(-column => 1, -row => 1, -sticky => "w"); $ord_bn{loads} = $frame3->Radiobutton(-text => "Loads", -highlightthickness => 0, -value => "loads", -variable => \$order_by, -command => $ord_bn_cb) - ->grid(-column => 1, -row => 1, -sticky => "w"); + ->grid(-column => 0, -row => 2, -sticky => "w"); $ord_bn{parse_calls} = $frame3->Radiobutton(-text => "Parse calls", -highlightthickness => 0, -value => "parse_calls", -variable => \$order_by, -command => $ord_bn_cb) - ->grid(-column => 2, -row => 1, -sticky => "w"); + ->grid(-column => 1, -row => 2, -sticky => "w"); $ord_bn{executions} = $frame3->Radiobutton(-text => "Executions", -highlightthickness => 0, -value => "executions", -variable => \$order_by, -command => $ord_bn_cb) - ->grid(-column => 0, -row => 2, -sticky => "w"); + ->grid(-column => 0, -row => 3, -sticky => "w"); +$ord_bn{first_load_time} = + $frame3->Radiobutton(-text => "First load", -highlightthickness => 0, + -value => "first_load_time", -variable => \$order_by, + -command => $ord_bn_cb) + ->grid(-column => 1, -row => 3, -sticky => "w"); +$frame3->pack(-side => "left", -padx => 6); + +# Sort order frame +$frame3 = $frame2->Frame(-highlightthickness => 1); +$sort_bn{desc} = + $frame3->Radiobutton(-text => "Descending", -highlightthickness => 0, + -value => "desc", -variable => \$sort_by, + -command => $ord_bn_cb) + ->grid(-column => 0, -row => 0, -sticky => "w"); +$sort_bn{asc} = + $frame3->Radiobutton(-text => "Ascending", -highlightthickness => 0, + -value => "asc", -variable => \$sort_by, + -command => $ord_bn_cb) + ->grid(-column => 0, -row => 1, -sticky => "w"); $frame3->pack(-side => "right", -padx => 6); $frame2->grid(-column => 0, -row => 1, -sticky => "w", -columnspan => 2); diff --git a/oraperl.ex/Readme b/oraperl.ex/Readme deleted file mode 100644 index 2246da37..00000000 --- a/oraperl.ex/Readme +++ /dev/null @@ -1,38 +0,0 @@ -[ Tim Bunce, 16th Nov 1995: The only change I've made to these - original oraperl examples by Kevin Stock is to add the magic - eval 'use Oraperl; 1' || die $@ if $] >= 5; - line to each. ] - -This directory contains a few sample Oraperl scripts. Some are genuinely -useful (sql, for example, is installed as part of make install) while -others are just demonstrations of different things. - -bind.pl Demonstrates how &ora_bind() and &ora_fetch() may be - combined to make a simple table lookup program - -commit.pl Demonstrates the use of &ora_commit() and &ora_rollback() - -ex.pl This was my first ever Oraperl script. I think I wrote it even - before writing Oraperl! It reads data from a table and prints - it using a format. It also illustrates how to recognise NULL - fields. - -japh Just another Perl hacker, written in Oraperl - This is no one-liner, but it demonstrates a few things. - -mkdb.pl Creates a database, puts some data into it, drops it. The nice - thing about this is that it detects whether it is running under - Oraperl or Coraperl, and changes its output accordingly. It - also illustrates handling of NULL fields, with both &ora_bind() - and &ora_fetch(). - -oradump.pl Dumps the contents of an Oracle table into a set of insert - statements. - -sql This was written in response to a posting on the net, asking - whether there was a tool which would execute an SQL statement - specified on the command line. Manual page built-in. - -tabinfo.pl Displays the structure of the specified table. - This is mainly to show the use of &ora_lengths, &ora_titles - and &ora_types. diff --git a/oraperl.ex/bind.pl b/oraperl.ex/bind.pl deleted file mode 100755 index 06df6ec1..00000000 --- a/oraperl.ex/bind.pl +++ /dev/null @@ -1,36 +0,0 @@ -# -# bind.pl -# -# This shows how the ora_bind function may be used to implement a -# simple lookup script. - -eval 'use Oraperl; 1' || die $@ if $] >= 5; - -$ora_debug = shift if $ARGV[0] =~ /^-#/; - -$lda = &ora_login('t', 'kstock', 'kstock') - || die $ora_errstr; -$csr = &ora_open($lda, 'select phone from telno where name = :1') - || die $ora_errstr; - -while() -{ - chop; - &ora_bind($csr, $_) || die $ora_errstr; - - # Note that $phone is placed in brackets to give it array context - # Without them, &ora_fetch() returns the number of columns available - - if (($phone) = &ora_fetch($csr)) - { - print "$phone\n"; - } - else - { - die $ora_errstr if $ora_errno; - print "unknown\n"; - } -} - -&ora_close($csr); -&ora_logoff($lda); diff --git a/oraperl.ex/commit.pl b/oraperl.ex/commit.pl deleted file mode 100755 index d9af8330..00000000 --- a/oraperl.ex/commit.pl +++ /dev/null @@ -1,58 +0,0 @@ -# -# commit.pl -# -# Simple example of using commit and rollback. - -eval 'use Oraperl; 1' || die $@ if $] >= 5; - -$ora_debug = shift if $ARGV[0] =~ /^-#/; - -$lda = &ora_login('t', 'kstock', 'kstock') || die "$ora_errstr\n"; -&ora_do($lda, 'create table primes (prime number)') || die "$ora_errstr\n"; - -$csr = &ora_open($lda, 'insert into primes values(:1)') || die "$ora_errstr\n"; -print 'creating table'; -while () -{ - chop; - print " $_"; - &ora_bind($csr, $_) || die "$_: $ora_errstr\n"; - (print ' committing ', &ora_commit($lda)) if $_ == 11; -} -&ora_close($csr) || die "$ora_errstr\n"; - -print "\n\nReading table for the first time\n\n"; -$csr = &ora_open($lda, 'select prime from primes') || die "$ora_errstr\n"; -while (($prime) = &ora_fetch($csr)) -{ - print "$prime "; -} -die "$ora_errstr\n" if $ora_errno; -&ora_close($csr) || die "$ora_errstr\n"; - -print "\n\nRolling back ", &ora_rollback($lda), "\n\n"; - -print "Attempting to read data for the second time.\n"; -print "Only values up to 11 should appear.\n\n"; -$csr = &ora_open($lda, 'select prime from primes') || die "$ora_errstr\n"; -while (($prime) = &ora_fetch($csr)) -{ - print "$prime "; -} -die "$ora_errstr\n" if $ora_errno; -&ora_close($csr) || die "$ora_errstr\n"; - -&ora_do($lda, 'drop table primes') || die "$ora_errstr\n"; -&ora_logoff($lda); -print "\n" -__END__ -2 -3 -5 -7 -11 -13 -17 -19 -23 -29 diff --git a/oraperl.ex/ex.pl b/oraperl.ex/ex.pl deleted file mode 100755 index 6f361802..00000000 --- a/oraperl.ex/ex.pl +++ /dev/null @@ -1,35 +0,0 @@ -# - -eval 'use Oraperl; 1' || die $@ if $] >= 5; - -$ora_debug = shift if $ARGV[0] =~ /^-#/; - -format STDOUT_TOP = - Name Phone - ==== ===== -. - -format STDOUT = - @<<<<<<<<<< @>>>>>>>>>> - $name, $phone -. - -die ("You should use oraperl, not perl\n") unless defined &ora_login; - -$lda = &ora_login("t", "kstock", "kstock") - || die $ora_errstr; -$csr = &ora_open($lda, "select * from telno order by name", 6) - || die $ora_errstr; - -$nfields = &ora_fetch($csr); -print "Query will return $nfields fields\n\n"; - -while (($name, $phone) = &ora_fetch($csr)) -{ - # mark any NULL fields found - grep(defined || ($_ = ''), $name, $phone); - write; -} - -do ora_close($csr) || die "can't close cursor"; -do ora_logoff($lda) || die "can't log off Oracle"; diff --git a/oraperl.ex/japh b/oraperl.ex/japh deleted file mode 100755 index c103c7e4..00000000 --- a/oraperl.ex/japh +++ /dev/null @@ -1,54 +0,0 @@ -# -# -# This is an example of how we could code a JAPH in Oraperl. -# -# Author: Kevin Stock -# Date: 1st December 1992 - -eval 'use Oraperl; 1' || die $@ if $] >= 5; - -# supply debugging output if desired - -$ora_debug = shift if $ARGV[0] =~ /^-#/; - -# login to the database and create the table - -$lda = &ora_login('t', 'kstock', 'kstock') || die $ora_errstr; -&ora_do($lda, <<) || die $ora_errstr; - create table japh (word char(7), posn number(1)) - -# Loop to insert data into the table - -$csr = &ora_open($lda, <<) || die $ora_errstr; - insert into japh values(:1, :2) - -while () -{ - chop; - &ora_bind($csr, split(':')) || warn "$_: $ora_errstr"; -} -&ora_close($csr) || warn $ora_errstr; - -# Now retrieve the data, printing it word by word - -$csr = &ora_open($lda, <<) || die $ora_errstr; - select word from japh order by posn - -while (($word) = &ora_fetch($csr)) -{ - print "$word "; -} -&ora_close($csr) || warn $ora_errstr; - -print "\n"; - -# delete the table - -&ora_do($lda, 'drop table japh') || warn $ora_errstr; -&ora_logoff($lda) || die $ora_errstr; - -__END__ -Oraperl:3 -another:2 -hacker:4 -just:1 diff --git a/oraperl.ex/mkdb.pl b/oraperl.ex/mkdb.pl deleted file mode 100755 index cd3fefb3..00000000 --- a/oraperl.ex/mkdb.pl +++ /dev/null @@ -1,172 +0,0 @@ -# mkdb.pl -# -# Sample (c)oraperl program to create a new database and load data into it. -# -# Author: Kevin Stock -# Date: 5th August 1991 -# -# Modified to use curses functions if present. -# -# Date: 15th November 1991 -# -# Modified to demonstrate NULL handling in &ora_bind and &ora_fetch() -# -# Date: 25th September 1992 - -eval 'use Oraperl; 1' || die $@ if $] >= 5; - -# make sure that we really are running (c)oraperl -die ("You should use oraperl, not perl\n") unless defined &ora_login; - -# Set up debugging (hope the user has redirected this if we're -# going into curses!) -$ora_debug = shift if $ARGV[0] =~ /^-#/; - -# get error codes -require('oraperl.ph'); - -# Arrange to use curses functions if they're available. -# (This is just showing off) - -if (defined(&initscr) && &initscr()) -{ - eval <<'____END_OF_CURSES_STUFF'; - - $curses = 1; - - # functions used by the list function - - sub before - { - &erase(); - &standout(); - &addstr("Num Name Ext\n\n"); - &standend(); - $lineno = 1; - } - - sub during - { - &addstr(sprintf("%2d %-15s%3s\n", $lineno++, $name, $ext)); - } - - sub after - { - &standout(); - &move($LINES - 1, 0); - &addstr("Press RETURN to continue."); - &standend(); - &refresh(); - &getstr($dummy); - &move($LINES - 1, 0); - &addstr(" "); - &move($LINES - 1, 0); - &refresh(); - } - -____END_OF_CURSES_STUFF -} -else -{ - eval <<'____END_OF_PLAIN_STUFF'; - - $curses = 0; - - format STDOUT_TOP = - Name Ext - ==== === -. - - format STDOUT = - @<<<<<<<<< @>> - $name, $ext -. - - # functions used by the list function - - sub before { $- = 0; } - sub during { write; } - sub after { 1; } - -____END_OF_PLAIN_STUFF -} - -# function to list the database - -sub list -{ - local($csr, $name, $ext); - - do before(); - - $csr = &ora_open($lda, $LIST) || die $ora_errstr; - while (($name, $ext) = &ora_fetch($csr)) - { - $name = '<-NULL->' unless defined($name); - $ext = '<-NULL->' unless defined($ext); - do during(); - } - die $ora_errstr if ($ora_errno != 0); - do ora_close($csr) || die $ora_errstr; - - do after(); -} - -# set these as strings to make the code more readable -$CREATE = "create table tryit (name char(10), ext number(3))"; -$INSERT = "insert into tryit values (:1, :2)"; -$LIST = "select * from tryit order by name"; -$DELETE = "delete from tryit where name = :1"; -$DELETE_NULL = "delete from tryit where name is null"; -$DROP = "drop table tryit"; - -# create the database - -$lda = &ora_login('t', 'kstock', 'kstock') || die $ora_errstr; -&ora_do($lda, $CREATE) || die $ora_errstr; - -# put some data into it - -$csr = &ora_open($lda, $INSERT) || die $ora_errstr; -while () -{ - m/(.*):(.*)/; - $name = ($1 eq 'NULL') ? undef : $1; - $ext = ($2 eq 'NULL') ? undef : $2; - do ora_bind($csr, $name, $ext); -} -do ora_close($csr) || die $ora_errstr; - -# check the result -do list(); - -# remove a few lines - -$csr = &ora_open($lda, $DELETE) || die $ora_errstr; -foreach $name ('catherine', 'angela', 'arnold', 'julia') -{ - &ora_bind($csr, $name) || die $ora_errstr; -} -&ora_close($csr) || die $ora_errstr; -&ora_do($lda, $DELETE_NULL) || die $ora_errstr; - -# check the result -do list(); - -# remove the database and log out -do ora_do($lda, $DROP) || die $ora_errstr; -do ora_logoff($lda) || die $ora_errstr; - -do endwin() if $curses == 1; - -# This is the data which will go into the database -__END__ -julia:292 -angela:208 -NULL:999 -larry:424 -catherine:201 -nonumber:NULL -randal:306 -arnold:305 -NULL:NULL diff --git a/oraperl.ex/oradump.pl b/oraperl.ex/oradump.pl deleted file mode 100755 index 836157f7..00000000 --- a/oraperl.ex/oradump.pl +++ /dev/null @@ -1,28 +0,0 @@ -# -# oradump.pl -# -# Dump the contents of an Oracle table into a set of insert statements. -# Usage: oradump
-# -# Author: Kevin Stock -# Date: 28th February 1992 -# -eval 'use Oraperl; 1' || die $@ if $] >= 5; - -$ora_debug = shift if $ARGV[0] =~ /^-#/; - -(($base = shift) && - ($table = shift) && - ($user = shift)) || die "Usage: $0 base table user/password\n"; - -$lda = &ora_login($base, $user, '') || die $ora_errstr; -$csr = &ora_open($lda, "select * from $table") || die $ora_errstr; - -while (@data = &ora_fetch($csr)) -{ - print "insert into $table values('" . join("', '", @data) . "');\n"; -} -warn "$ora_errstr" if $ora_errno; - -&ora_close($csr) || die $ora_errstr; -&ora_logoff($lda) || die $ora_errstr; diff --git a/oraperl.ex/sql b/oraperl.ex/sql deleted file mode 100755 index 7e8e0f1b..00000000 --- a/oraperl.ex/sql +++ /dev/null @@ -1,225 +0,0 @@ -# -'di'; -'ig00'; -# -# sql -# -# Script to run an Oracle statement from the command line. -# Written in response to in alt.sources.wanted. -# -# Parameters (* = mandatory) -# -# -#debug debugging control string (must be first argument) -# -b base database to use (default $ENV{'ORACLE_SID'}) -# -c cache SQL fetch cache size -# -d delim specifies the field delimiter (default TAB) -# -f formatted output, similar to sqlplus -# -h add headers, no formatting -# -l page_len lines per page, only used by -f (default 60) -# -n string replace NULL fields by string -# name/pass * Oracle username and password -# stmt Oracle statement to be executed -# read from stdin if not given on command line -# -# Author: Kevin Stock -# Date: 18th November 1991 -# Last change: 9th June 1993 -# -eval 'use Oraperl; 1' || die $@ if $] >= 5; - -$ora_debug = shift if $ARGV[0] =~ /^-#/; - -$USAGE = <<; -[-bbase] [-ccache] [-ddelim] [-f|-h] [-lpage_len] [-nstring] name/pass [stmt] - -require 'getopts.pl'; # option parsing -do Getopts('b:c:d:fhl:n:'); -die "$0: only one of -f and -h may be specified\n" if ($opt_f && $opt_h); - -$USER = shift || die "user/password not specified\n"; - -if ($#ARGV >= 0) -{ - @stmt = @ARGV; -} -else -{ - print "Enter the statement to execute (^D to end):\n"; - @stmt = ; -} - -$, = "\t"; # default delimiter is a tab -$\ = "\n"; # each record terminated with newline - -$db = $opt_b if defined($opt_b); # set database -$ora_cache = $opt_c if defined($opt_c); # set fetch cache -$, = $opt_d if defined($opt_d); # set column delimiter -$= = $opt_l if defined($opt_l); # set page length - -# log into the database and execute the statement - -$lda = &ora_login($db, $USER, '') || die "$ora_errstr\n"; -$csr = &ora_open($lda, "@stmt") || die "$ora_errstr\n"; - -# print out any information which comes back - -if (($nfields = &ora_fetch($csr)) > 0) # does the statement return data? -{ - if ($opt_f) # formatted output - { - # Build up format statements for the data - - # First, the header - a list of field names, formatted - # in columns of the appropriate width - - $fmt = ''; - grep($fmt .= "%-${_}.${_}s|", &ora_lengths($csr)); - chop $fmt; - $fmt = sprintf($fmt, &ora_titles($csr, 0)); - $format .= "format STDOUT_TOP =\n" . $fmt . "\n"; - - # Then underlines for the field names - - $fmt =~ tr/|/-/c; - $fmt =~ tr/|/+/; - $format .= $fmt . "\n.\n"; - - # Then for the data format, a @<<... field per column - - $fmt =~ tr/-+/<|/; - $fmt =~ s/(^|\|) -.if t .ft P -.ex diff --git a/oraperl.ex/tabinfo.pl b/oraperl.ex/tabinfo.pl deleted file mode 100644 index 1c6f7b25..00000000 --- a/oraperl.ex/tabinfo.pl +++ /dev/null @@ -1,60 +0,0 @@ -# -# tabinfo -# -# Usage: tabinfo base user password table -# -# Displays the structure of the specified table. -# Note that the field names are restricted to the length of the field. -# This is mainly to show the use of &ora_lengths, &ora_titles and &ora_types. -# -eval 'use Oraperl; 1' || die $@ if $] >= 5; - -# set debugging, if requested -# -$ora_debug = shift if $ARGV[0] =~ /-#/; - -# read the compulsory arguments -# -(($base = shift) && - ($user = shift) && - ($pass = shift) && - ($table = shift)) || die "Usage: $0 base user password table ...\n"; - -# we need this for the table of datatypes -# -require 'oraperl.ph'; - -format STDOUT_TOP = -Structure of @<<<<<<<<<<<<<<<<<<<<<<< -$table - -Field name | Length | Type | Type description -----------------------------------------------+--------+------+----------------- -. - -format STDOUT = -@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | @>>>>> | @>>> | @<<<<<<<<<<<<<<< -$name[$i], $length[$i], $type[$i], $ora_types{$type[$i]} -. - -$lda = &ora_login($base, $user, $pass) || die $ora_errstr . "\n"; - -do -{ - $csr = &ora_open($lda, "select * from $table") || die "$ora_errstr\n"; - - (@name = &ora_titles($csr, 0)) || die $ora_errstr . "\n"; - (@length = &ora_lengths($csr)) || die $ora_errstr . "\n"; - (@type = &ora_types($csr)) || die $ora_errstr . "\n"; - - foreach $i (0 .. $#name) - { - write; - } - - &ora_close($csr); - - $- = 0; -} while ($table = shift); - -&ora_logoff($lda); diff --git a/t/base.t b/t/base.t index 8826ea12..4630b6d1 100755 --- a/t/base.t +++ b/t/base.t @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl -w +#!perl -w # Base DBD Driver Test diff --git a/t/general.t b/t/general.t index dfe335c6..fa95d229 100644 --- a/t/general.t +++ b/t/general.t @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl -w +#!perl -w sub ok ($$;$) { my($n, $ok, $warn) = @_; diff --git a/t/long.t b/t/long.t index 51d04b75..04008c26 100644 --- a/t/long.t +++ b/t/long.t @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl -w +#!perl -w use DBI; use DBD::Oracle qw(:ora_types ORA_OCI); @@ -68,6 +68,7 @@ my $long_data0 = ("0\177x\0X" x 2048) x (1 ); # 10KB < 64KB my $long_data1 = ("1234567890" x 1024) x ($sz ); # 80KB >> 64KB && > long_data2 my $long_data2 = ("2bcdefabcd" x 1024) x ($sz-1); # 70KB > 64KB && < long_data1 +# special hack for long_data0 since RAW types need pairs of HEX $long_data0 = "00FF" x (length($long_data0) / 2) if $type_name =~ /RAW/i; my $len_data0 = length($long_data0); @@ -94,7 +95,7 @@ if (!create_table("lng $type_name", 1)) { } print " --- insert some $type_name data\n"; -ok(0, $sth = $dbh->prepare("insert into $table values (?, ?)"), 1); +ok(0, $sth = $dbh->prepare("insert into $table values (?, ?, SYSDATE)"), 1); $sth->bind_param(2, undef, { ora_type => $type_num }) or die $DBI::errstr if $type_num; ok(0, $sth->execute(40, $long_data0), 1); @@ -266,7 +267,7 @@ END { sub create_table { my ($fields, $drop) = @_; - my $sql = "create table $table ( idx integer, $fields )"; + my $sql = "create table $table ( idx integer, $fields, dt date )"; $dbh->do(qq{ drop table $table }) if $drop; $dbh->do($sql); if ($dbh->err && $dbh->err==955) { diff --git a/t/plsql.t b/t/plsql.t index f7de6e1d..2c300fbf 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl -w +#!perl -w sub ok ($$;$) { my($n, $ok, $warn) = @_; diff --git a/t/reauth.t b/t/reauth.t index 7f7831dd..ca53fca9 100644 --- a/t/reauth.t +++ b/t/reauth.t @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl -w +#!perl -w sub ok ($$;$) { my($n, $ok, $warn) = @_; From 0a098201e9a88c19b444a1655042d741cc465dcd Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Thu, 13 Jul 2000 22:23:51 -0500 Subject: [PATCH 045/637] import DBD-Oracle 1.05 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 1.05 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-1.05.tar.gz --- Changes | 37 +++++++++- MANIFEST | 1 + Makefile.PL | 178 ++++++++++++++++++++++++++++++-------------- Oracle.pm | 82 +++++++++++---------- Oracle.xs | 4 +- README | 17 +++-- README.help | 5 ++ README.java | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.sec | 10 +++ Todo | 24 +++--- dbdimp.c | 154 +++++++++++++++++++++++++------------- dbdimp.h | 3 +- oci8.c | 54 ++++++++++---- ocitrace.h | 74 ++++++++++--------- t/base.t | 24 ++++++ t/plsql.t | 1 - 16 files changed, 656 insertions(+), 219 deletions(-) create mode 100644 README.java diff --git a/Changes b/Changes index 790153f7..02a81337 100644 --- a/Changes +++ b/Changes @@ -1,10 +1,45 @@ +Changes in DBD::Oracle 1.05 13th July 2000 + + Added $dbh->{ora_ph_type} attribute to define default bind type: + 1=> VARCHAR2, does strip trailing spaces, embedded \0 bytes okay + 5=> STRING, doesn't strip trailing spaces, embedded \0 ends string + 96=> CHAR, doesn't strip trailing spaces, embedded \0 okay + 97=> CHARZ, doesn't strip trailing spaces, embedded \0 ends string? + The two CHAR types force 'blank-padded comparison semantics'. + Needs testing and documenting, volunteers most welcome! + Added (many) typecasts to avoid compiler warnings thanks to Denis Goddard. + Added ability to pass existing DBD::Oracle select statement handle + (cursor) back _into_ Oracle as a ref cursor type thanks to Mike Moretti. + Note that this enables a workaround for closing ref cursors: + $dbh->do("BEGIN CLOSE :cursor; END;", undef, $sth_ref_csr_to_close); + Improved Win32 support in Makefile.PL thanks to Michael A. Chase. + Workaround Win32::TieRegistry FETCH error during global destruction. + Re-enable row cache by default for OCI8 (can give big speed increase). + Fixed bug in OCI8 row cache calculation thanks to Greg Stark. + +Changes in DBD::Oracle 1.04 11th July 2000 + + Added info on workarounds for Java thread related linker errors + on Solaris with Oracle 8.1.6. Thanks to Andi Lamprecht. + Fixed memory leak on connect. Thanks to Jeffrey W. Baker. + Fixed memory and ref cursor leaks. Thanks to Mike Moretti and John Tobey. + Fixed SEGV on insert/update or many LOBS. Thanks to Honza Pazdziora. + Fixed treating SUCCESS_WITH_INFO from finish() as an error. + Fixed passing of attribs to connect thanks to K.Takaoka. + Fixed cursor binding example in docs thanks to Michael Chase. + Build using otrace/demo/atmoci.mk as last resort thanks to Chris Sylvain. + Improved reliability of "perl Makefile.PL -b" configure option. + Improved reliability of t/plsql.t cursor tests. Hopefully. + Improved reliability of ping method. + Fixed broken SQL type warning in bind_param. + Changes in DBD::Oracle 1.03 12th July 1999 Added "perl Makefile.PL -b" configure option. Links DBD::Oracle using same linker args as Oracle's own OCI demo applications. Added connect("dbi:Oracle:host=foo;sid=bar", ...) syntax. Added OCI8 function trace at level 6, useful for Oracle support. - Added ora_session_mode attribute to connect. + Added ora_session_mode attribute to connect (eg SYSDBA/SYSOPER). Added test for Oracle security problem. See README.sec. Updated ora_explain tool to v1.1 thanks to Alan Burlison. Contributions from Michael Chase (plus docs from Andy Duncan): diff --git a/MANIFEST b/MANIFEST index badef179..55f43923 100644 --- a/MANIFEST +++ b/MANIFEST @@ -19,6 +19,7 @@ README README.clients README.explain README.help +README.java README.login README.longs README.sec diff --git a/Makefile.PL b/Makefile.PL index 8660c47a..5fc8966b 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.80 1999/07/12 03:20:42 timbo Exp $ +# $Id: Makefile.PL,v 1.84 2000/07/13 22:42:02 timbo Exp $ ## ## You should not need to edit this file. @@ -47,14 +47,14 @@ my %opts = ( OBJECT => '$(O_FILES)', DEFINE => '', DIR => [], - clean => { FILES => 'Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def' }, + clean => { FILES => 'Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain' }, dist => { DIST_DEFAULT => 'clean distcheck disttest ci tardist', PREOP => '$(MAKE) -f Makefile.old distdir', COMPRESS => 'gzip -v9', SUFFIX => 'gz', }, ); if ($ExtUtils::MakeMaker::VERSION >= 5.43) { - $opts{AUTHOR} = 'Tim Bunce (dbi-users@fugue.com)'; + $opts{AUTHOR} = 'Tim Bunce (dbi-users@isc.org)'; $opts{ABSTRACT_FROM} = 'Oracle.pm'; $opts{PREREQ_PM} = { DBI => 0 }; $opts{CAPI} = 'TRUE' if $Config{archname} =~ /-object\b/i; @@ -67,7 +67,7 @@ my %mk_target_deps; my %mk_target_rules; # Options (rarely needed) -$::opt_b = 0; # try to use Oracle's own 'build' rule +$::opt_b = 1; # try to use Oracle's own 'build' rule $::opt_m = 0; # path to proc.mk or oracle.mk file to read $::opt_p = ''; # alter preference for oracle.mk over proc $::opt_n = ''; # Oracle .mk macro name to use for library list to link with @@ -106,24 +106,26 @@ $OH = win32_oracle_home($OH) if ($os eq 'MSWin32') or ($os =~ /cygwin/i); die qq{ The $ORACLE_ENV environment variable must be set. It must be set to hold the path to an Oracle installation directory - on this machine (or a compatible archtecture). + on this machine (or a machine with a compatible architecture). See the README.clients file for more information. + ABORTED! } unless $OH; die qq{ The $ORACLE_ENV environment variable value ($OH) is not valid. It must be set to hold the path to an Oracle installation directory on this machine (or a compatible archtecture). See the README.clients file for more information. + ABORTED! } unless -d $OH; print "Using Oracle in $OH\n"; -my (@inspdver, %inspdver); +# We'll try to dig up some Oracle version information. Not essential. +my (@inspdver, %inspdver); $inspdver{RDBMS} = 0; if ($os ne 'VMS' and $os ne 'MSWin32' and -x "$OH/orainst/inspdver") { open INST, "$OH/orainst/inspdver |"; my @inspdver = ; close INST; - $inspdver{RDBMS} = 0; foreach (@inspdver) { chop; $inspdver{$2} = $1 if m/^(\S+)\s+(.*)/; @@ -160,14 +162,13 @@ if ($os eq 'VMS') { } elsif (($os eq 'MSWin32') or ($os =~ /cygwin/i)) { - my $oci_compiler_dir = ($Config{cc} eq 'bcc32' ? "BORLAND" : "MSVC"); - my $OCIDIR = ""; find( sub { - print "Found $_ directory\n" if /^OCI\d+/i; - $OCIDIR = $_ if /^OCI\d\d+$/i && $OCIDIR lt $_; + print "Found $_ directory\n" if /^OCI\d*$/i; + $OCIDIR = $_ if /^OCI\d*$/i && $OCIDIR lt $_; $File::Find::prune = 1 if -d $_ && $_ !~ /^\./; }, $OH ); + die "OCI directory not found, please install OCI in $OH" if ! $OCIDIR; print "Using OCI directory '$OCIDIR'\n"; if ($Config{cc} =~ /gcc/i) { @@ -175,12 +176,17 @@ elsif (($os eq 'MSWin32') or ($os =~ /cygwin/i)) { print "Using liboci.a (did you build it?)\n"; } else { my %OCILIB; + my $oci_compiler_dir; + my @oci_compiler_dirs = + map { -d "$OH/$OCIDIR/lib/$_" ? "$OH/$OCIDIR/lib/$_": () } + $Config{cc} eq 'bcc32' ? qw(BORLAND BC) : qw(MSVC); find( sub { $File::Find::prune = 1 if -d $_ && $_ !~ /^\./; return unless /^(OCI|ORA).*\.LIB$/i; + ($oci_compiler_dir = $File::Find::dir) =~ s:^.*/::; print "Found $OCIDIR/lib/$oci_compiler_dir/$_ library\n"; $OCILIB{uc($_)} = $_; - }, "$OH/$OCIDIR/lib/$oci_compiler_dir" ) if $OCIDIR; + }, @oci_compiler_dirs ); # sort the version numbered libs into assending order my @OCILIB = sort grep { /(OCI|ORA)\d\d+\./i } keys %OCILIB; # prefer the non-versioned library if present @@ -273,11 +279,14 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l my $prev = ''; @cmds = grep { my $skip = $prev eq "echo $_"; $prev=$_; !$skip } @cmds; my @prolog; push @prolog, shift @cmds while @cmds && $cmds[0] !~ /DBD_ORA_EXE/; - print "Oracle oci build prolog:\n\t", join("\n\t", @prolog), "\n"; + print "Oracle oci build prolog:\n\t", join("\n\t", @prolog), "\n" if @prolog; print "Oracle oci build command:\n\t", join("\n\t", @cmds), "\n"; + while ($cmds[0] =~ s/\\$/ /) { # join lines split with \'s + $cmds[0] .= splice(@cmds,1,1); + } if (@cmds == 1) { my $build = $cmds[0]; - $build =~ s/^\s*(true\s+)?(\w+)\s*//; # remove 'true' and compiler/linker + $build =~ s/^\s*(true\s+)?(\S+)\s*//; # remove 'true' and compiler/linker $build =~ s/$DBD_ORA_OBJ//; # remove dummy object file $build =~ s/\S+\s+DBD_ORA_EXE//; # remove dummy exe file and preceding flag $linkwith = $build; @@ -319,9 +328,11 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l # this kind of stuff should be in a ./hints/* file: $linkwith_s .= " -lc" if $Config{osname} eq 'dynixptx' or $Config{archname} =~ /-pc-sco3\.2v5/; - if ($os eq 'solaris' and $osvers >= 2.3 and $linkwith_s =~ /-lthread/) { + if ($os eq 'solaris' and $linkwith_s =~ /-lthread/ + and $osvers >= 2.3 and $osvers <= 2.6 + ) { print "Warning: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; - print "Deleting -lthread from link list as a possible workround.\n"; + print "Deleting -lthread from link list as a possible workround ($osvers).\n"; $linkwith_s =~ s/\s*-lthread\b/ /g; } @@ -450,33 +461,82 @@ exit 0; sub win32_oracle_home { my $oh = shift; + my ($req_ok, $hkey, $Val, $Keys); + if ( ! $oh ) { + if ( $Config{osname} eq "MSWin32") { # Win32::TieRegistry is prefered, but it requires Win32API::Registry # which is not available in mingw or cygwin - eval q{ + eval { require Win32::TieRegistry; - $Win32::TieRegistry::Registry->Delimeter("/"); - my $hkey= $Win32::TieRegistry::Registry->{"LMachine/Software/Oracle/"}; - $oh= $hkey->{ORACLE_HOME}; - } unless $oh; - - eval q{ # older name of Win32::TieRegistry + $Win32::TieRegistry::Registry->Delimiter("/"); + $req_ok = 1; + $hkey = $Win32::TieRegistry::Registry-> + {"LMachine/SOFTWARE/Oracle/"}; + }; + eval { # older name of Win32::TieRegistry require Tie::Registry; - $Tie::Registry::Registry->Delimeter("/"); - my $hkey= $Tie::Registry::Registry->{"LMachine/Software/Oracle/"}; - $oh= $hkey->{ORACLE_HOME}; - } unless $oh; + $Tie::Registry::Registry->Delimiter("/"); + $req_ok = 1; + $hkey = $Tie::Registry::Registry->{"LMachine/SOFTWARE/Oracle/"}; + } unless $req_ok; + eval { + $Val = sub { + # Return value + my ($hkey) = @_; + return $hkey->{ORACLE_HOME} || ''; + }; + $Keys = sub { + # Return list of sub-folder keys + my ($hkey) = @_; + # MAC: %$hkey and related method calls don't work under + # perl5db, so don't try single stepping through here + return map {m:/$: ? $hkey->{$_} : ()} keys %$hkey; + }; + } if $hkey; + } # Win32::Registry imports some symbols into main:: - # this is not commonly wanted thing, so try this as a last resort - eval q{ + # this is not commonly wanted, so try this as a last resort + # MAC: it is available under mingw and might be available under cygwin + # If cygwin doesn't have it, move the rest inside the other if block + eval { require Win32::Registry; - my($reg_key, $hkey); - $main::HKEY_LOCAL_MACHINE->Open('SOFTWARE\\ORACLE', $reg_key); - $reg_key->GetValues( $hkey ); - $oh= $hkey->{ORACLE_HOME}[2]; - } unless $oh; + $main::HKEY_LOCAL_MACHINE->Open('SOFTWARE\\ORACLE', $hkey); + my $dummy = $main::HKEY_LOCAL_MACHINE; # avoid single use complaint + $Val = sub { + # Return value + my ($hkey) = @_; + my $hval; + $hkey->GetValues($hval); + return $hval->{ORACLE_HOME}[2] || ''; + }; + $Keys = sub { + # Return list of sub-folder keys + my ($hkey) = @_; + my @hkey; + $hkey->GetKeys(\@hkey); + @hkey = map { $hkey->Open($_, $_); $_ } @hkey; + return @hkey; + }; + } unless $req_ok; + + # Look for ORACLE_HOME in all ORACLE sub-folders, use last one found + # before 8.1.5, there should be only one + eval { + my @hkey = ($hkey); + my ($oh1, %oh); + while (@hkey) { + $hkey = shift @hkey; + $oh = $oh1, $oh{$oh1} = 1 + if ($oh1 = &$Val($hkey)) && -d $oh1; + push @hkey, &$Keys($hkey); + } + print "\nMultiple Oracle homes: ", join(" ", sort keys %oh), "\n\n" + if 1 < keys %oh; + } if defined $Keys; + } - $oh =~ s:\\:/:g; + $oh =~ s:\\:/:g if $oh; return $oh } @@ -543,17 +603,17 @@ sub MY::postamble { sub del_crtobj { my $orig = shift; - my $verbose = shift || $::opt_v; - my $str = $orig; + my $verbose = shift || $::opt_v; + my $str = $orig; # E.g. for changing the COMPOBJS line (and sometimes LDSTRING) # old: COMPOBJS=$(COMPOBJ)/crti.o $(COMPOBJ)/crt1.o $(COMPOBJ)/__fstd.o # new: COMPOBJS=$(COMPOBJ)/__fstd.o - my @del; + my @del; push @del, $1 while $str =~ s:([^\s=]*\bcrt[1in]\.o)\b::; - if ($orig ne $str) { - print "Deleted @del from link args.\n" if $verbose; - print "del_crtobj: $orig\n : $str\n@del" if $::opt_v; - } + if ($orig ne $str) { + print "Deleted @del from link args.\n" if $verbose; + print "del_crtobj: $orig\n : $str\n@del\n" if $::opt_v; + } return $str; } @@ -571,6 +631,7 @@ sub find_mkfile { 'rdbms/lib/oracle.mk', 'rdbms/demo/oracle.mk', 'rdbms/demo/demo_rdbms.mk', + 'otrace/demo/atmoci.mk', ); my @mkplaces = ($::opt_p) ? (@mk_proc,@mk_oci) : (@mk_oci,@mk_proc); if ($::opt_m) { @@ -592,13 +653,14 @@ sub find_mkfile { file in your Oracle installation. (I looked in @mkplaces) - The oracle.mk (or similarly named) file is part of the Oracle - RDBMS product. The proc.mk (or similarly named) file is part of + The oracle.mk (or demo_rdbms.mk) file is part of the Oracle + RDBMS product. The proc.mk (or demo_proc.mk) file is part of the Oracle Pro*C product. You need to build DBD::Oracle on a - system which has one of these installed. + system which has one of these Oracle components installed. + (Other *.mk files such as the env_*.mk files will not work.) - If a suitable *.mk file is installed somewhere non-standard you - can specify where it is using the -m option: + In the unlikely event that a suitable *.mk file is installed + somewhere non-standard you can specify where it is using the -m option: perl Makefile.PL -m /path/to/your.mk See README.clients for more information and some alternatives. @@ -606,6 +668,10 @@ sub find_mkfile { } unless ($os eq 'MSWin32') || ($os eq 'VMS') || ($mkfile && -f $mkfile); print "Using $mkfile\n"; + + warn "Note: Attempting to use makefile from otrace component. This may not work.\n" + if ($mkfile =~ /atmoci.mk/); + return $mkfile; } @@ -620,7 +686,7 @@ sub fetch_oci_macros { # makefile (note that %MK stills gets these values). my @edit = qw( SHELL CC CPP CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS - AR AS CHMOD ECHO EXE OBJS PERL OBJ_EXT LIB_EXT + AR AS CHMOD ECHO EXE OBJS PERL OBJ_EXT LIB_EXT VERSION ); my %edit; @edit{@edit} = ('$_ = ""') x @edit; @@ -741,9 +807,10 @@ sub fetch_oci_macros { } } + $linkvia = '$(LIBCLNTSH)' if !$linkvia && $MK{LIBCLNTSH}; + # The oracle.mk file tends to define OCILDLIBS - $linkvia = '$(OCILDLIBS)' - if !$linkvia && $MK{OCILDLIBS}; + $linkvia = '$(OCILDLIBS)' if !$linkvia && $MK{OCILDLIBS}; # Now we get into strange land of twisty turny macros if (!$linkvia && $MK{PROLDLIBS}) { # Oracle 7.3.x @@ -807,7 +874,7 @@ sub expand_shellescape { print "Evaluating `$orig`\n" if $debug && !$expand_shellescape{$orig}; # ensure we have no $(...) vars left - strip out undefined ones: - $cmd =~ s/\$\((\w+)\)/mkvar("$1", 1, 0, $level+1)/ge; + $cmd =~ s/\$[({](\w+)[})]/mkvar("$1", 1, 0, $level+1)/ge; print " expanded `$cmd`\n" if $debug and $cmd ne $orig; my $result = `$cmd`; chop $result; @@ -823,11 +890,11 @@ sub expand_mkvars { local($_) = $string; print "$level Expanding $_\n" if $::opt_d; # handle whizzo AIX make feature used by Oracle - s/\$\( (\w+) \? ([^(]*?) : ([^(]*?) \)/ + s/\$[({] (\w+) \? ([^(]*?) : ([^(]*?) [})]/ my ($vname, $vT, $vF) = ($1,$2,$3); $MK{$vname} = (mkvar($vname, 1, $backtick, $level+1)) ? $vT : $vF /xge; # can recurse - s/\$\( (\w+) \)/ + s/\$[({] (\w+) [})]/ mkvar("$1", $strip, $backtick, $level+1, $maxlevel) /xge; # can recurse s/`(.*?[^\\])`/expand_shellescape("$1", $level+1)/esg if $backtick; # can recurse @@ -904,14 +971,14 @@ sub symbol_search { print "Searching for symbol '$::opt_s' in $OH ...\n"; my $dlext = $Config{dlext}; system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; - do echo " searching oracle \$i ..."; nm \$i | grep $::opt_s; done + do echo " searching oracle \$i ..."; PATH=/usr/ccs/bin:\$PATH nm \$i | grep $::opt_s; done }); if ($::opt_S) { my @libpth = split ' ', $Config{libpth}; print "Searching for symbol '$::opt_s' in @libpth ...\n"; @libpth = map { ("$_/lib*.$dlext", "$_/lib*.a") } @libpth; system(qq{ cd $OH; for i in @libpth; - do echo " searching \$i ..."; nm \$i | grep $::opt_s; done + do echo " searching \$i ..."; PATH=/usr/ccs/bin:\$PATH nm \$i | grep $::opt_s; done }); } print "Search done.\n"; @@ -1043,6 +1110,7 @@ sub check_security { print "\n"; warn "WARNING - YOUR ORACLE INSTALLATION HAS A SECURITY PROBLEM.\a\n"; warn "Read the README.sec file for more information and patch details.\a\n"; + warn "This is just a warning. It does not affect DBD::Oracle in any way.\n"; sleep 5; } diff --git a/Oracle.pm b/Oracle.pm index d5b67c0b..aae523c5 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.77 1999/07/12 03:20:42 timbo Exp $ +# $Id: Oracle.pm,v 1.79 2000/07/13 22:42:02 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce # @@ -10,7 +10,7 @@ require 5.003; -$DBD::Oracle::VERSION = '1.03'; +$DBD::Oracle::VERSION = '1.05'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -32,7 +32,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.77 $, 10); + my $Revision = substr(q$Revision: 1.79 $, 10); require_version DBI 1.02; @@ -67,6 +67,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; # Used to silence 'Bad free() ...' warnings caused by bugs in Oracle's code # being detected by Perl's malloc. $ENV{PERL_BADFREE} = 0; + undef $Win32::TieRegistry::Registry if $Win32::TieRegistry::Registry; } #sub AUTOLOAD { @@ -93,7 +94,8 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; if (($^O eq 'MSWin32') or ($^O =~ /cygwin/i)) { # XXX experimental, will probably change - $drh->log_msg("Fetching ORACLE_SID from Registry.\n") if $debug; + $drh->trace_msg("Trying to fetch ORACLE_HOME and ORACLE_SID from the registry.\n") + if $debug; my($hkey, $sid, $home); eval q{ require Win32::TieRegistry; @@ -120,7 +122,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; }; $home= $ENV{$ORACLE_ENV} unless $home; $dbnames{$sid} = $home if $sid and $home; - $drh->log_msg("Found $sid \@ $home.\n") if $debug; + $drh->trace_msg("Found $sid \@ $home.\n") if $debug; $oracle_home =$home unless $oracle_home; }; @@ -183,14 +185,12 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; } split /\s*;\s*/, $dbname; my %dbname = ( PROTOCOL => 'tcp', @dbname ); my $sid = delete $dbname{SID}; - my $ora = delete $dbname{ORACLE}; return $drh->DBI::set_err(-1, "Can't connect using this syntax without specifying a HOST and a SID") unless $sid and $dbname{HOST}; my @addrs; push @addrs, "$n=$v" while ( ($n,$v) = each %dbname ); my $addrs = "(" . join(")(", @addrs) . ")"; - $dbname{PORT} ||= ($ora eq 7) ? 1521 : 1526 if $ora; if ($dbname{PORT}) { $addrs = "(ADDRESS=$addrs)"; } @@ -259,7 +259,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; # Call Oracle OCI logon func in Oracle.xs file # and populate internal handle data. - DBD::Oracle::db::_login($dbh, $dbname, $user, $auth) + DBD::Oracle::db::_login($dbh, $dbname, $user, $auth, $attr) or return undef; if ($attr && $attr->{ora_module_name}) { @@ -300,13 +300,14 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; sub ping { my($dbh) = @_; my $ok = 0; - local $SIG{__WARN__} = sub { } if $dbh->{PrintError}; eval { + local $SIG{__DIE__}; + local $SIG{__WARN__}; # we know that Oracle 7 prepare does a describe so this will # actually talk to the server and is this a valid and cheap test. my $sth = $dbh->prepare("select SYSDATE from DUAL /* ping */"); # But Oracle 8 doesn't talk to server unless we describe the query - $ok = $sth && $sth->{NUM_OF_FIELDS}; + $ok = $sth && $sth->FETCH('NUM_OF_FIELDS'); }; return ($@) ? 0 : $ok; } @@ -336,48 +337,51 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; sub type_info_all { my ($dbh) = @_; my $names = { - TYPE_NAME => 0, - DATA_TYPE => 1, - COLUMN_SIZE => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE => 9, - FIXED_PREC_SCALE =>10, - AUTO_UNIQUE_VALUE =>11, - LOCAL_TYPE_NAME =>12, - MINIMUM_SCALE =>13, - MAXIMUM_SCALE =>14, - }; + TYPE_NAME => 0, + DATA_TYPE => 1, + COLUMN_SIZE => 2, + LITERAL_PREFIX => 3, + LITERAL_SUFFIX => 4, + CREATE_PARAMS => 5, + NULLABLE => 6, + CASE_SENSITIVE => 7, + SEARCHABLE => 8, + UNSIGNED_ATTRIBUTE => 9, + FIXED_PREC_SCALE =>10, + AUTO_UNIQUE_VALUE =>11, + LOCAL_TYPE_NAME =>12, + MINIMUM_SCALE =>13, + MAXIMUM_SCALE =>14, + SQL_DATA_TYPE =>15, + SQL_DATETIME_SUB =>16, + NUM_PREC_RADIX =>17, + }; # Based on the values from Oracle 8.0.4 ODBC driver my $ti = [ $names, [ 'LONG RAW', -4, '2147483647', '\'', '\'', undef, 1, '0', '0', - undef, '0', undef, undef, undef, undef + undef, '0', undef, undef, undef, undef, -4, undef, undef ], [ 'RAW', -3, 255, '\'', '\'', 'max length', 1, '0', 3, - undef, '0', undef, undef, undef, undef + undef, '0', undef, undef, undef, undef, -3, undef, undef ], [ 'LONG', -1, '2147483647', '\'', '\'', undef, 1, 1, '0', - undef, '0', undef, undef, undef, undef + undef, '0', undef, undef, undef, undef, -1, undef, undef ], [ 'CHAR', 1, 255, '\'', '\'', 'max length', 1, 1, 3, - undef, '0', '0', undef, undef, undef + undef, '0', '0', undef, undef, undef, 1, undef, undef ], [ 'NUMBER', 3, 38, undef, undef, 'precision,scale', 1, '0', 3, - '0', '0', '0', undef, '0', 38 + '0', '0', '0', undef, '0', 38, 3, undef, 10 ], [ 'DOUBLE', 8, 15, undef, undef, undef, 1, '0', 3, - '0', '0', '0', undef, undef, undef + '0', '0', '0', undef, undef, undef, 8, undef, 10 ], [ 'DATE', 11, 19, '\'', '\'', undef, 1, '0', 3, - undef, '0', '0', undef, '0', '0' + undef, '0', '0', undef, '0', '0', 11, undef, undef ], [ 'VARCHAR2', 12, 2000, '\'', '\'', 'max length', 1, 1, 3, - undef, '0', '0', undef, undef, undef + undef, '0', '0', undef, undef, undef, 12, undef, undef ] ]; return $ti; @@ -517,8 +521,10 @@ If you use the C style syntax, for example: then DBD::Oracle will construct a full connection descriptor string for you and Oracle will not need to consult the tnsname.ora file. -If a C number is not specified then the descriptor try -both 1526 and 1521 in that order. + +If a C number is not specified then the descriptor will try both +1526 and 1521 in that order (e.g., new then old). You can check which +port(s) are in use by typing "$ORACLE_HOME/bin/lsnrctl stat" on the server. =head2 Oracle environment variables @@ -1108,7 +1114,6 @@ procedure OUT parameters or from direct C statements, as show below: $sth1->bind_param(":space", "USERS"); my $sth2; $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); - $sth1->execute(); # $sth2 is now a valid DBI statement handle for the cursor while ( @row = $sth2->fetchrow_array ) { ... } @@ -1160,7 +1165,8 @@ The DBD::Oracle module is Copyright (c) 1995,1996,1997,1998,1999 Tim Bunce. Engl The DBD::Oracle module is free software; you can redistribute it and/or modify it under the same terms as Perl itself with the exception that it cannot be placed on a CD-ROM or similar media for commercial distribution -without the prior approval of the author. +without the prior approval of the author unless the CD-ROM is primarily a +copy of the majority of the CPAN archive. =head1 ACKNOWLEDGEMENTS diff --git a/Oracle.xs b/Oracle.xs index 0e7af5b3..096adfbf 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -54,8 +54,8 @@ ora_fetch(sth) D_imp_sth(sth); AV *av; int debug = DBIc_DEBUGIV(imp_sth); - if (dbis->debug > debug) - debug = dbis->debug; + if (DBIS->debug > debug) + debug = DBIS->debug; DBIh_CLEAR_ERROR(imp_sth); if (GIMME == G_SCALAR) { /* XXX Oraperl */ /* This non-standard behaviour added only to increase the */ diff --git a/README b/README index fc7a903f..bba3426d 100644 --- a/README +++ b/README @@ -33,7 +33,8 @@ DBD::Oracle -- an Oracle 7 and Oracle 8 interface for Perl 5. Remember to *read* the DBI README file and this one CAREFULLY! Install enough Oracle software to enable DBD::Oracle to build. - That usually includes Pro*C. + That usually includes Pro*C. That's not very specific because it + varies so much between Oracle releases. *** BUILDING: @@ -235,18 +236,18 @@ http://www.wmd.de/wmd/staff/pauck/misc/oracle_on_linux.html =============================================================================== Some platforms on which the DBI and DBD::Oracle modules run: - AIX 3 & 4 + AIX DEC Alpha - DEC UNIX 3.2 - DG/UX 5.4 - HP-UX 9 and 10 + DEC UNIX + DG/UX + HP-UX Linux (on platforms supported by Oracle 8) Motorola M88100 (SVR3.2) OSF/1 Pyramid SMP DC/OSx - SCO 3 - SGI IRIX 5 & 6 - Sequent DYNIX/ptx 2 + SCO + SGI IRIX + Sequent DYNIX/ptx Solaris 1 and 2 Unisys U6000/300 VMS diff --git a/README.help b/README.help index e72335fb..a4935314 100644 --- a/README.help +++ b/README.help @@ -93,6 +93,11 @@ when DBD::Oracle was compiled. Also try building with oracle.mk if your DBD::Oracle defaulted to proc.mk. +------------------------------------------------------------------------------- +SCO - For general help enabling dynamic loding under SCO 5 + + http://www2.arkansas.net/~jcoy/perl5/ + ------------------------------------------------------------------------------- AIX - warnings like these when building perl are not usually a problem: diff --git a/README.java b/README.java new file mode 100644 index 00000000..7ab3450f --- /dev/null +++ b/README.java @@ -0,0 +1,207 @@ +README.java + +This file relates to a specific problem on Solaris platforms +for Oracle 8.1.6 (and possibly later versions) where loading +DBD::Oracle fails with an error message like: + + ``You must install a Solaris patch to run this version of + the Java runtime. + Please see the README and release notes for more information.'' + +The problem seems to be that: + +1/ By default, the Oracle shared library contains a ``Radius + authentication module'' that is implemented in Java. +2/ The Java implementation requires that the thread library is + also linked into the application. +3/ For some inexplicable reason the thread library has to be + linked to the executable that's doing the dynamic loading. + It's is not sufficient to link -lthread to DBD::Oracle. + +There are several ways to workaround this: + +1/ Remove the Radius authentication module if you don't need it. + This requires you to perform surgery on the Oracle installation. + (If the name Radius doesn't mean anything to you and you're + the person maintaining the Oracle installation then you almost + certainly don't need it.) + +2/ Use the LD_PRELOAD environment variable to force the pre-loading + of the thread library. + +3/ Link the thread library to your perl binary. + You can do that either by (re)building perl with thread support + or, I believe, it should be possible to issue a magic 'ld' command + to add linkage to the thread library to an existing perl executable. + (But you'll need to work that one out yourself. If you do please let + me know so I can add the details here to share with others.) + +Most of this information comes from Andi Lamprecht, to whom I'm very +grateful indeed. + +I've included below two of his email messages, slightly edited, where +he explains the procedure for options 1 and 2 above. I've also +appended a slight reworking of option 1 from Paul Vallee. + +Tim. + +---- + + +From: andi@sunnix.sie.siemens.at + +Have managed it to get DBD to work with Oracle 8i without these nasty Java +error! It seems to be that a thing called "NAU" links in a radius +athentication module which is written in Java and this causes the +additional java libraries in the libclntsh.so. After throwing it all out +DBD tests ran successfully. + +The steps to take are: + + - shut down Oracle server if you have one running in the installation + you're about to modify. + - take a backup copy of your Oracle installation! You have been warned! + + - go to $ORACLE_HOME/network/lib + - rebuild nautab.o with: + + make -f ins_nau.mk NAU_ADAPTERS="IDENTIX KERBEROS5 SECURID" nautab.o + + This build a new nautab.o without the radius authentication module. + + - go to $ORACLE_HOME/lib + - edit file "ldflags" and delete all occurences of "-lnrad8" and "-ljava" + and "-[LR]$ORACLE_HOME/JRE/lib/sparc/native_threads" + + - go to $ORACLE_HOME/bin + - build a new libclntsh.so with: + + genclntsh + + - start up Oracle + + - go back to the DBD-* directory and build the Oracle driver with: + + perl Makefile.PL; make; make test + +This worked for me, the database is still operational, MAYBE SOME JAVA +STUFF ISN'T WORKING. Better someone else with more experience in java +finds out ... + +The problem seems to be a dynamic linking issue. Whenever java virtual +machine is loaded, some symbols are missing (with java 1.2.2_05 these +_thread_something symbols where not found, even with linked-in +libthread.so, with java 1.1.8 some _lseek or so symbols couldn't be +resolved). Seems Oracle did a good job in integration of Java in the +database ... + +Ok, should go out now 'cause its a beatiful wheater here in Vienna! + +Greetings +A. Lamprecht + +----------- + + +From: andi@sunnix.sie.siemens.at + +For some reason libthread.so.1 isn't included as dynamic object in perl +binary and so symbols aren't found. + +The interesting output of LD_DEBUG=symbols: +symbol=thr_getstate; dlsym() starting at file=/usr/local/bin/perl +symbol=thr_getstate; lookup in file=/usr/local/bin/perl [ ELF ] +symbol=thr_getstate; lookup in file=/lib/libsocket.so.1 [ ELF ] +symbol=thr_getstate; lookup in file=/lib/libnsl.so.1 [ ELF ] +symbol=thr_getstate; lookup in file=/lib/libdl.so.1 [ ELF ] +symbol=thr_getstate; lookup in file=/lib/libm.so.1 [ ELF ] +symbol=thr_getstate; lookup in file=/lib/libc.so.1 [ ELF ] +symbol=thr_getstate; lookup in file=/lib/libcrypt_i.so.1 [ ELF ] +symbol=thr_getstate; lookup in file=/lib/libmp.so.2 [ ELF ] +symbol=thr_getstate; lookup in file=/lib/libgen.so.1 [ ELF ] +ld.so.1: /usr/local/bin/perl: fatal: thr_getstate: can't find symbol + +This list looks exactly like the one you get when ldd-ing the perl binary. +There is an option to the dynamic linker "LD_PRELOAD" and if you set it with + + LD_PRELOAD=/lib/libthread.so.1 + export LD_PRELOAD + +before starting any DBD::oracle app, the app works! + +It looks like after libjava and libjvm is loaded, the library search path +is somehow stripped to the one of the perl binary ... + +[That looks like a Solaris bug] + +Hope this helps. + +A. Lamprecht +----------- + + +From: Paul Vallee + +Andi is right. Three cheers for Andi!!! :-) + +Final Summary (this is mostly Andi's work summarized here) + +1. Copy your ORACLE_HOME in it's entirety to a new directory. +cp -r $ORACLE_HOME $ORACLE_HOME.nojava +2. Set your ORACLE_HOME variable to the new one. Save the old one for reference. +export OLD_ORACLE_HOME=$ORACLE_HOME +export ORACLE_HOME=$ORACLE_HOME.nojava +3. cd $ORACLE_HOME/network/lib +(This is your new ORACLE_HOME - the temporary one that will soon be without +Java or Radius) +4. build nautab.o with +make -f ins_nau.mk NAU_ADAPTERS="IDENTIX KERBEROS5 SECURID" nautab.o +5. go to $ORACLE_HOME/lib +edit file "ldflags" and delete all occurences of "-lnrad8" and "-ljava" +and "-[LR]$ORACLE_HOME/JRE/lib/sparc/native_threads" +I wrote this little pipeline to do this. +sed 's/-lnrad8//g' < ldflags | \ +sed 's/-ljava//g' | \ +sed "s%-L$OLD_ORACLE_HOME/JRE/lib/sparc/native_threads%%g" | \ +sed "s%-R$OLD_ORACLE_HOME/JRE/lib/sparc/native_threads%%g" | > newldflags +If you look at newldflags, and like it, then run: +cp ldflags oldldflags; cp newldflags ldflags +6. go to $ORACLE_HOME/bin and build a new libclntsh.so with "genclntsh" +genclntsh +7. go to your DBD::oracle install directory and go through the regular +install process. +perl Makefile.PL; make; make install +(I find the make test less useful than my test.pl perl file.) +8. Set LD_LIBRARY_PATH=$ORACLE_HOME/lib. +This part is very important - remember that at this stage ORACLE_HOME is set +to the nojava home. Make this permanent by explicitly setting +LD_LIBRARY_PATH to the nojava lib directory in your .profile. +This is the step that stalled me - thanks again to Andi. +9. Test this out. I use the following, which I call test.pl, which fails +nicely if we've failed, and is very quiet if we've succeeded: +#!/usr/bin/perl +use strict; +use DBI; +use DBD::Oracle; +0; +./test.pl should have no output. Congratulations. +10. Get rid of everything other than libclntsh.so in your new ORACLE_HOME - +the rest is a waste of space. +cd $ORACLE_HOME; cd .. +mv $ORACLE_HOME $ORACLE_HOME.rmme +mkdir $ORACLE_HOME; mkdir $ORACLE_HOME/lib +cp $ORACLE_HOME.rmme/lib/libclntsh.so $ORACLE_HOME/lib +11. Run test.pl again just to be sure it still works. +12. If test.pl is still working, then we can reclaim space with +rm -fr $ORACLE_HOME.rmme + +Note that in my opinion this is a workaround - there is no reason on the +face of it that I can fathom that we shouldn't be able to use DBD::Oracle to +connect to Oracle with Java compiled in. (?) + +Enjoy, +Paul Vallee +Principal +The Pythian Group, Inc. +------------------------------------------------------------------------------ + diff --git a/README.sec b/README.sec index b6049f65..72920db6 100644 --- a/README.sec +++ b/README.sec @@ -1,3 +1,5 @@ +I have no intention of becoming a channel for Oracle Support Services +but this is a significant security hole and so I'm making an exception. ----- Forwarded message from Oracle Support Services ----- @@ -130,3 +132,11 @@ Mark ------------------------------------------------------------------------------ +One further note I'll pass on anonymously and without comment: + +> please include something like: "After removing the setuid bits, slap +> your system administrator for running root.sh as root without actually +> reading it first." +> :) + +------------------------------------------------------------------------------ diff --git a/Todo b/Todo index d779c0c6..a9d3e219 100644 --- a/Todo +++ b/Todo @@ -1,4 +1,13 @@ -OCI8 mem leak on connect +[ In no particular order ] + +add docs about OPS$ login + +bind type 1 or 5?! + +Add hint about SQL*Plus commands if execute gets an ORA-0900 invalid SQL +statement? Maybe just if common SQL*Plus command word is first word. + +Support SERVICE_NAME in new connect syntax (allow inplace of SID) warn (trace_msg?) if ORACLE_HOME changes after first connect relates to Apache::DBI scenario where changing ORACLE_HOME @@ -11,7 +20,7 @@ PRECISION for oci7 on VARCHAR etc Detect "Error while trying to retrieve text for error ORA-XXXX" and add "refer to oracle docs or use 'oerr ora XXXX'". -blob_read for oci8 +blob_read for oci8 with LONGs connect(..., { ora_module_name => $0 }); @@ -21,24 +30,17 @@ $sth = $dbh->prepare("select ... for update"); $dbh->commit; $sth->execute; # fails ? auto-re-prepare? -Fetch: If LongReadLen > 64k then automatically call oflng for each long LONG. -Bind: Automatically do piecewise insert of longs. - ora_bind() failed err = ORA-01026: multiple buffers of size > 4000 in the bind list (DBD: oexec error) http://outside.organic.com/mail-archives/dbi-users/Nov1997/0116.html -Handle binding of values > 32K long. - Handle PL/SQL arrays. -Handle PL/SQL returned cursor variables. - Non-blocking -Tests - RAW types at max length +Tests: +RAW types at max length http://www.oracle-users.com/html/freeware.html diff --git a/dbdimp.c b/dbdimp.c index 6898860a..a90df2bf 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1,5 +1,5 @@ /* - $Id: dbdimp.c,v 1.58 1999/07/12 03:20:42 timbo Exp $ + $Id: dbdimp.c,v 1.60 2000/07/13 22:42:02 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce @@ -38,13 +38,14 @@ void dbd_init(dbistate) dbistate_t *dbistate; { + char *p; DBIS = dbistate; dbd_init_oci(dbistate); - if (getenv("DBD_ORACLE_LOGIN_NOMSG")) - ora_login_nomsg = atoi(getenv("DBD_ORACLE_LOGIN_NOMSG")); - if (getenv("DBD_ORACLE_SIGCHLD")) - ora_sigchld_restart = atoi(getenv("DBD_ORACLE_SIGCHLD")); + if ((p=getenv("DBD_ORACLE_LOGIN_NOMSG"))) + ora_login_nomsg = atoi(p); + if ((p=getenv("DBD_ORACLE_SIGCHLD"))) + ora_sigchld_restart = atoi(p); } @@ -64,8 +65,6 @@ dbd_discon_all(drh, imp_drh) DBIc_ERR(imp_drh), DBIc_ERRSTR(imp_drh)); return FALSE; } - if (perl_destruct_level) - perl_destruct_level = 0; return FALSE; } @@ -186,9 +185,6 @@ dbd_db_login6(dbh, imp_dbh, dbname, uid, pwd, attr) #ifdef OCI_V8_SYNTAX D_imp_drh_from_dbh; - ub4 cred_type; - ub4 mode_type = OCI_DEFAULT; - SV **mode_type_sv; if (DBIS->debug >= 6 ) dump_env_to_trace(); @@ -198,10 +194,11 @@ dbd_db_login6(dbh, imp_dbh, dbname, uid, pwd, attr) /* you get a core dump (Not doc'd in 8.0.4). Thanks Oracle! */ ub4 init_mode = OCI_OBJECT; SV **init_mode_sv; - DBD_ATTRIB_GET_IV(attr, "ora_init_mode",15, init_mode_sv, mode_type); + DBD_ATTRIB_GET_IV(attr, "ora_init_mode",13, init_mode_sv, init_mode); OCIInitialize_log_stat(init_mode, 0, 0,0,0, status); if (status != OCI_SUCCESS) { - oci_error(dbh, NULL, status, "OCIInitialize"); + oci_error(dbh, NULL, status, + "OCIInitialize. Check ORACLE_HOME and NLS settings etc."); return 0; } OCIEnvInit_log_stat( &imp_drh->envhp, OCI_DEFAULT, 0, 0, status); @@ -230,10 +227,14 @@ dbd_db_login6(dbh, imp_dbh, dbname, uid, pwd, attr) OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_SESSION, status); - cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); - DBD_ATTRIB_GET_IV(attr, "ora_session_mode",16, mode_type_sv, mode_type); - OCISessionBegin_log_stat( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, - cred_type, mode_type, status); + { + ub4 cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); + SV **sess_mode_type_sv; + ub4 sess_mode_type = OCI_DEFAULT; + DBD_ATTRIB_GET_IV(attr, "ora_session_mode",16, sess_mode_type_sv, sess_mode_type); + OCISessionBegin_log_stat( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->authp, + cred_type, sess_mode_type, status); + } if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); @@ -262,7 +263,7 @@ dbd_db_login6(dbh, imp_dbh, dbname, uid, pwd, attr) char buf[100]; char *msg; switch(rc) { /* add helpful hints to some errors */ - case 0: msg = "login failed, check ORACLE_HOME/bin is on your PATH"; break; + case 0: msg = "login failed, check your config, e.g. ORACLE_HOME/bin on your PATH etc"; break; case 1019: msg = "login failed, probably a symptom of a deeper problem"; break; default: msg = "login failed"; break; } @@ -311,10 +312,10 @@ dbd_db_login6(dbh, imp_dbh, dbname, uid, pwd, attr) /* XXX we should also check that act.sa_handler is not the perl handler */ act.sa_flags |= SA_RESTART; sigaction( SIGCLD, &act, (struct sigaction*)0 ); - if (dbis->debug >= 3) + if (DBIS->debug >= 3) warn("dbd_db_login: sigaction errno %d, handler %lx, flags %lx", errno,act.sa_handler,act.sa_flags); - if (dbis->debug >= 2) + if (DBIS->debug >= 2) fprintf(DBILOGFP, " dbd_db_login: set SA_RESTART on Oracle SIGCLD handler.\n"); } } @@ -324,6 +325,7 @@ dbd_db_login6(dbh, imp_dbh, dbname, uid, pwd, attr) DBIc_IMPSET_on(imp_dbh); /* imp_dbh set up now */ DBIc_ACTIVE_on(imp_dbh); /* call disconnect before freeing */ + imp_dbh->ph_type = 1; return 1; } @@ -414,6 +416,7 @@ dbd_db_destroy(dbh, imp_dbh) dbd_db_disconnect(dbh, imp_dbh); #ifdef OCI_V8_SYNTAX { sword status; + OCIHandleFree_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION,status); OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); OCIHandleFree_log_stat(imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); @@ -450,6 +453,11 @@ dbd_db_STORE_attrib(dbh, imp_dbh, keysv, valuesv) else if (kl==12 && strEQ(key, "RowCacheSize")) { imp_dbh->RowCacheSize = SvIV(valuesv); } + else if (kl==11 && strEQ(key, "ora_ph_type")) { + if (SvIV(valuesv)!=1 && SvIV(valuesv)!=5) + croak("ora_ph_type must be either 1 (VARCHAR2) or 5 (STRING)"); + imp_dbh->ph_type = SvIV(valuesv); + } else { return FALSE; } @@ -479,6 +487,9 @@ dbd_db_FETCH_attrib(dbh, imp_dbh, keysv) else if (kl==12 && strEQ(key, "RowCacheSize")) { retsv = newSViv(imp_dbh->RowCacheSize); } + else if (kl==11 && strEQ(key, "ora_ph_type")) { + retsv = newSViv(imp_dbh->ph_type); + } if (!retsv) return Nullsv; if (cacheit) { /* cache for next time (via DBI quick_FETCH) */ @@ -503,6 +514,7 @@ dbd_preparse(imp_sth, statement) imp_sth_t *imp_sth; char *statement; { + D_imp_dbh_from_sth; bool in_literal = FALSE; char in_comment = '\0'; char *src, *start, *dest; @@ -519,7 +531,7 @@ dbd_preparse(imp_sth, statement) /* initialise phs ready to be cloned per placeholder */ memset(&phs_tpl, 0, sizeof(phs_tpl)); phs_tpl.imp_sth = imp_sth; - phs_tpl.ftype = 1; /* VARCHAR2 */ + phs_tpl.ftype = imp_dbh->ph_type; phs_tpl.maxlen_bound = -1; /* not yet bound */ src = statement; @@ -615,7 +627,7 @@ dbd_preparse(imp_sth, statement) *dest = '\0'; if (imp_sth->all_params_hv) { DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv); - if (dbis->debug >= 2) + if (DBIS->debug >= 2) fprintf(DBILOGFP, " dbd_preparse scanned %d distinct placeholders\n", (int)DBIc_NUM_PARAMS(imp_sth)); } @@ -699,8 +711,9 @@ ora_sql_type(imp_sth, name, sql_type) case SQL_TIME: case SQL_TIMESTAMP: default: - if (DBIc_WARN(imp_sth) && imp_sth && name) - warn("SQL type %d for '%s' is not fully supported, bound as SQL_VARCHAR instead"); + if (imp_sth && DBIc_WARN(imp_sth) && name) + warn("SQL type %d for '%s' is not fully supported, bound as SQL_VARCHAR instead", + sql_type, name); return ora_sql_type(imp_sth, name, SQL_VARCHAR); } } @@ -724,7 +737,7 @@ dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) if (!SvPOK(phs->sv) && SvOK(phs->sv)) sv_2pv(phs->sv, &na); - if (dbis->debug >= 2) { + if (DBIS->debug >= 2) { char *val = neatsvpv(phs->sv,0); fprintf(DBILOGFP, " bind %s <== %.1000s (", phs->name, val); if (SvOK(phs->sv)) @@ -795,7 +808,7 @@ dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) } #endif - if (dbis->debug >= 3) { + if (DBIS->debug >= 3) { fprintf(DBILOGFP, " bind %s <== '%.*s' (size %ld/%ld, otype %d, indp %d)\n", phs->name, (int)(phs->alen>SvIV(DBIS->neatsvpvlen) ? SvIV(DBIS->neatsvpvlen) : phs->alen), @@ -807,6 +820,47 @@ dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr) } +#ifndef MM_CURSOR_FIX +/* + * Rebind an "in" cursor ref to its real statement handle + * This allows passing cursor refs as "in" to pl/sql (but only if you got the + * cursor from pl/sql to begin with) + */ +int +pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) +{ + /*dTHR; -- do we need to do this??? */ + SV * sth_csr = phs->sv; + D_impdata(imp_sth_csr, imp_sth_t, sth_csr); + sword status; + + if (dbis->debug >= 3) + fprintf(DBILOGFP, " pp_rebind_ph_rset_in: BEGIN\n calling OCIBindByName(stmhp=%p, bndhp=%p, errhp=%p, name=%s, csrstmhp=%p, ftype=%d)\n", imp_sth->stmhp, phs->bndhp, imp_sth->errhp, phs->name, imp_sth_csr->stmhp, phs->ftype); + + OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + (text*)phs->name, strlen(phs->name), + &imp_sth_csr->stmhp, + 0, + phs->ftype, 0, + NULL, + 0, 0, + NULL, + OCI_DEFAULT, + status + ); + if (dbis->debug >= 3) + fprintf(DBILOGFP, " after OCIBindByName, status=%d\n", status); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_RSET"); + return 0; + } + if (dbis->debug >= 3) + fprintf(DBILOGFP, " pp_rebind_ph_rset_in: END\n"); + return 2; +} +#endif + + int pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) { @@ -865,6 +919,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) } #endif ENTER; + SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newRV(DBIc_MY_H(imp_dbh)))); XPUSHs(sv_2mortal(newRV((SV*)init_attr))); @@ -873,9 +928,11 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) SPAGAIN; if (count != 2) croak("panic: DBI::_new_sth returned %d values instead of 2", count); - sth_i = SvREFCNT_inc(POPs); - sv_setsv(phs->sv, SvREFCNT_inc(POPs)); /* outer handle */ + sth_i = POPs; /* discard inner handle */ + sv_setsv(phs->sv, POPs); /* save outer handle */ + SvREFCNT_dec(init_attr); PUTBACK; + FREETMPS; LEAVE; if (DBIS->debug >= 3) fprintf(DBILOGFP, " bind %s - allocated %s...\n", @@ -900,7 +957,6 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) /* assign statement handle from placeholder descriptor */ imp_sth_csr->stmhp = phs->desc_h; - imp_sth_csr->disable_finish = 1; /* else finish core dumps in kpuccan()! */ phs->desc_h = NULL; /* tell phs that we own it now */ /* force stmt_type since OCIAttrGet(OCI_ATTR_STMT_TYPE) doesn't work! */ @@ -913,7 +969,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) #endif - DBIc_IMPSET_on(imp_sth); + DBIc_IMPSET_on(imp_sth_csr); /* set ACTIVE so dbd_describe doesn't do explicit OCI describe */ DBIc_ACTIVE_on(imp_sth_csr); @@ -937,7 +993,7 @@ dbd_rebind_ph_cursor(sth, imp_sth, phs) { assert(phs->ftype == 102); phs->out_prepost_exec = pp_exec_rset; - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " bind %s to cursor (at execute)\n", phs->name); return 2; } @@ -974,7 +1030,7 @@ dbd_rebind_ph(sth, imp_sth, phs) } if (done != 1) { if (done == 2) { /* the rebind did the OCI bind call itself successfully */ - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " bind %s done for ftype %d\n", phs->name, phs->ftype); return 1; @@ -1030,7 +1086,7 @@ dbd_rebind_ph(sth, imp_sth, phs) } #endif phs->maxlen_bound = phs->maxlen ? phs->maxlen : 1; - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " bind %s done\n", phs->name); return 1; } @@ -1047,6 +1103,7 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl int is_inout; IV maxlen; { + D_imp_dbh_from_sth; SV **phs_svp; STRLEN name_len; char *name = Nullch; @@ -1075,7 +1132,7 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl if (SvTYPE(newvalue) == SVt_PVLV && is_inout) /* may allow later */ croak("Can't bind ``lvalue'' mode scalar as inout parameter (currently)"); - if (dbis->debug >= 2) { + if (DBIS->debug >= 2) { fprintf(DBILOGFP, " bind %s <== %s (type %ld", name, neatsvpv(newvalue,0), (long)sql_type); if (is_inout) @@ -1092,7 +1149,7 @@ dbd_bind_ph(sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxl phs = (phs_t*)(void*)SvPVX(*phs_svp); /* placeholder struct */ if (phs->sv == &sv_undef) { /* first bind for this placeholder */ - phs->ftype = 1; /* our default type: VARCHAR2 */ + phs->ftype = imp_dbh->ph_type; phs->is_inout = is_inout; if (is_inout) { /* phs->sv assigned in the code below */ @@ -1176,7 +1233,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count { dTHR; ub4 row_count = 0; - int debug = dbis->debug; + int debug = DBIS->debug; int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0; #ifdef OCI_V8_SYNTAX @@ -1272,7 +1329,7 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count " dbd_st_execute %s returned (%s, rpc%ld, fn%d, out%d)\n", oci_stmt_type_name(imp_sth->stmt_type), oci_status_name(status), - row_count, sqlfncode, imp_sth->has_inout_params); + (long)row_count, sqlfncode, imp_sth->has_inout_params); } if (is_select && !imp_sth->done_desc) { @@ -1298,7 +1355,10 @@ dbd_st_execute(sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count /* Specifically an update (5) may change to select (4) after odesc(). */ if (oexfet(imp_sth->cda, (ub4)imp_sth->cache_rows, 0, 0) && imp_sth->cda->rc != 1403 /* other than no more data */ ) { - ora_error(sth, imp_sth->cda, imp_sth->cda->rc, "oexfet error"); + char * hint = "oexfet error"; + if (imp_sth->cda->rc == 932) /* inconsistent data types */ + hint = "oexfet error, e.g., can't select LOB fields using DBD::Oracle built for Oracle 7"; + ora_error(sth, imp_sth->cda, imp_sth->cda->rc, hint); return -2; } DBIc_ACTIVE_on(imp_sth); @@ -1426,7 +1486,7 @@ dbd_st_blob_read(sth, imp_sth, field, offset, len, destrv, destoffset) } #endif - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " blob_read field %d+1, ftype %d, offset %ld, len %ld, destoffset %ld, retlen %ld\n", field, imp_sth->fbh[field].ftype, offset, len, destoffset, retl); @@ -1485,20 +1545,20 @@ dbd_st_finish(sth, imp_sth) /* Turn off ACTIVE here regardless of errors below. */ DBIc_ACTIVE_off(imp_sth); - if (dirty) /* don't walk on the wild side */ - return 1; - if (imp_sth->disable_finish) /* see ref cursors */ return 1; if (!DBIc_ACTIVE(imp_dbh)) /* no longer connected */ return 1; + if (dirty) /* don't walk on the wild side */ + return 1; + #ifdef OCI_V8_SYNTAX { sword status; OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp, 0, OCI_FETCH_NEXT, OCI_DEFAULT, status); - if (status != OCI_SUCCESS) { + if (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO) { oci_error(sth, imp_sth->errhp, status, "Finish OCIStmtFetch"); return 0; } @@ -1563,14 +1623,6 @@ dbd_st_destroy(sth, imp_sth) int fields; int i; - /* Check if an explicit disconnect() or global destruction has */ - /* disconnected us from the *database* before attempting to close. */ - - if (DBIc_ACTIVE(imp_dbh)) { - /* dbd_st_finish has already been called by .xs code if needed. */ - /* so this should never get called */ - } - #ifdef OCI_V8_SYNTAX { sword status; @@ -1581,7 +1633,7 @@ dbd_st_destroy(sth, imp_sth) oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); } #else - oclose(imp_sth->cda); + oclose(imp_sth->cda); /* ignore error ? */ if (imp_sth->cda != &imp_sth->cdabuf) { /* we assume that the cda was allocated for a ref cursor */ /* bound to a placeholder on a different statement. */ diff --git a/dbdimp.h b/dbdimp.h index 172b3709..2e102113 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.36 1999/07/12 03:20:42 timbo Exp $ + $Id: dbdimp.h,v 1.37 2000/07/11 22:14:20 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce @@ -104,6 +104,7 @@ struct imp_dbh_st { #endif int RowCacheSize; + int ph_type; /* default oratype for placeholders */ }; diff --git a/oci8.c b/oci8.c index 6bebe910..c73407f0 100644 --- a/oci8.c +++ b/oci8.c @@ -1,5 +1,5 @@ /* - $Id: oci8.c,v 1.20 1999/07/12 03:20:42 timbo Exp $ + $Id: oci8.c,v 1.22 2000/07/13 22:42:02 timbo Exp $ Copyright (c) 1998 Tim Bunce @@ -128,7 +128,9 @@ oci_error(SV *h, OCIError *errhp, sword status, char *what) sv_catpv(errstr, " "); sv_catpv(errstr, what); } - DBIh_EVENT2(h, ERROR_event, DBIc_ERR(imp_xxh), errstr); + DBIh_EVENT2(h, + (status == OCI_SUCCESS_WITH_INFO) ? WARN_event : ERROR_event, + DBIc_ERR(imp_xxh), errstr); return 0; /* always returns 0 */ } @@ -174,9 +176,13 @@ dbd_st_prepare(sth, imp_sth, statement, attribs) SV *attribs; { D_imp_dbh_from_sth; - ub4 oparse_lng = 1; /* auto v6 or v7 as suits db connected to */ - int ora_check_sql = 0; /* to force a describe to check SQL */ sword status = 0; + ub4 oparse_lng = 1; /* auto v6 or v7 as suits db connected to */ + int ora_check_sql = 1; /* to force a describe to check SQL */ + /* XXX we set ora_check_sql on for now to force setup of the */ + /* row cache. Change later to set up row cache using just a */ + /* a memory size, perhaps also default $RowCacheSize to a */ + /* negative value. OCI_ATTR_PREFETCH_MEMORY */ if (!DBIc_ACTIVE(imp_dbh)) { oci_error(sth, NULL, OCI_ERROR, "Database disconnected"); @@ -273,7 +279,7 @@ dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, *piecep = OCI_ONE_PIECE; if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_phs_in '%s' (%ld,%ld): len %2ld, ind %d%s\n", - phs->name, iter, index, phs->alen, phs->indp, + phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), phs->indp, (phs->desc_h) ? " via descriptor" : ""); if (index > 0 || iter > 0) croak("Arrays and multiple iterations not currently supported by DBD::Oracle"); @@ -299,7 +305,7 @@ dbd_phs_out(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, *rcodepp= &phs->arcode; if (DBIS->debug >= 3) fprintf(DBILOGFP, " dbd_phs_out '%s' (%ld,%ld): len %2ld, piece %d%s\n", - phs->name, iter, index, phs->alen, *piecep, + phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), *piecep, (phs->desc_h) ? " via descriptor" : ""); if (index > 0 || iter > 0) croak("Arrays and multiple iterations not currently supported by DBD::Oracle"); @@ -395,8 +401,19 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) int dbd_rebind_ph_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { +#ifndef MM_CURSOR_FIX + /* Only do this part for inout cursor refs because pp_exec_rset only gets called for all the output params */ + if (phs->is_inout) { +#endif phs->out_prepost_exec = pp_exec_rset; return 2; /* OCI bind done */ +#ifndef MM_CURSOR_FIX + } + else { + /* Call a special rebinder for cursor ref "in" params */ + return(pp_rebind_ph_rset_in(sth, imp_sth, phs)); + } +#endif } @@ -469,10 +486,11 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, OCILobRead_log_stat(imp_sth->svchp, imp_sth->errhp, lobl, &amtp, 1 + offset, bufp, buflen, 0, 0, 0, SQLCS_IMPLICIT, status); - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", - fbh->field_num+1, oci_status_name(status), loblen, imp_sth->long_readlen, buflen, amtp); + fbh->field_num+1, oci_status_name(status), ul_t(loblen), + imp_sth->long_readlen, ul_t(buflen), ul_t(amtp)); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobRead"); (void)SvOK_off(dest_sv); /* signal error */ @@ -481,10 +499,11 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, } else { assert(amtp == 0); - if (dbis->debug >= 3) + if (DBIS->debug >= 3) fprintf(DBILOGFP, " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", - fbh->field_num+1, "SKIPPED", loblen, imp_sth->long_readlen, buflen, amtp); + fbh->field_num+1, "SKIPPED", ul_t(loblen), + imp_sth->long_readlen, ul_t(buflen), ul_t(amtp)); } /* @@ -532,7 +551,7 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) else { char buf[300]; sprintf(buf,"fetching field %d of %d. LOB value truncated from %ld to %ld. %s", - fbh->field_num+1, DBIc_NUM_FIELDS(imp_sth), amtp, amtp, + fbh->field_num+1, DBIc_NUM_FIELDS(imp_sth), ul_t(amtp), ul_t(amtp), "DBI attribute LongReadLen too small and/or LongTruncOk not set"); oci_error(sth, NULL, OCI_ERROR, buf); sv_setiv(DBIc_ERR(imp_sth), (IV)24345); /* appropriate ORA error number */ @@ -550,7 +569,8 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) if (DBIS->debug >= 3) fprintf(DBILOGFP, " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", - fbh->field_num+1, oci_status_name(status), loblen, imp_sth->long_readlen, buflen, amtp); + fbh->field_num+1, oci_status_name(status), ul_t(loblen), + imp_sth->long_readlen, ul_t(buflen), ul_t(amtp)); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobRead"); (void)SvOK_off(dest_sv); @@ -562,7 +582,8 @@ fetch_func_autolob(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv) if (DBIS->debug >= 3) fprintf(DBILOGFP, " OCILobRead field %d %s: LOBlen %ld, LongReadLen %ld, BufLen %ld, Got %ld\n", - fbh->field_num+1, "SKIPPED", loblen, imp_sth->long_readlen, buflen, amtp); + fbh->field_num+1, "SKIPPED", ul_t(loblen), + imp_sth->long_readlen, ul_t(buflen), ul_t(amtp)); } /* tell perl what we've put in its dest_sv */ @@ -747,11 +768,12 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) imp_sth->t_dbsize += fbh->dbsize; if (!avg_width) avg_width = fbh->dbsize; - imp_sth->est_width += avg_width; + est_width += avg_width; if (DBIS->debug >= 2) dbd_fbh_dump(fbh, i, 0); } + imp_sth->est_width = est_width; /* --- Setup the row cache for this query --- */ @@ -1210,7 +1232,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) Newz(1, lr, 1, lob_refetch_t); unmatched_params = 0; lr->num_fields = 0; - lr->fbh_ary = alloc_via_sv(sizeof(imp_fbh_t) * HvFILL(lob_cols_hv)+1, + lr->fbh_ary = alloc_via_sv(sizeof(imp_fbh_t) * HvKEYS(lob_cols_hv)+1, &lr->fbh_ary_sv, 0); sql_select = newSVpv("select ",0); @@ -1387,7 +1409,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl if (DBIS->debug >= 3) fprintf(DBILOGFP, " lob refetch %d for '%s' param: ftype %d, len %ld: %s %s\n", - i+1,fbh->name, fbh->dbtype, amtp, + i+1,fbh->name, fbh->dbtype, ul_t(amtp), (amtp > 0) ? "LobWrite" : "LobTrim", oci_status_name(status)); if (status != OCI_SUCCESS) { return oci_error(sth, errhp, status, "OCILobTrim/OCILobWrite/LOB refetch"); diff --git a/ocitrace.h b/ocitrace.h index 4297619d..8f832990 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -10,6 +10,10 @@ #define DBD_OCI_TRACEFP (DBILOGFP) #define OciTp ("OCI") /* OCI Trace Prefix */ #define OciTstr(s) ((s) ? (text*)(s) : (text*)"") +#define ul_t(v) ((unsigned long)(v)) +#define pul_t(v) ((unsigned long *)(v)) +#define sl_t(v) ((signed long)(v)) +#define psl_t(v) ((signed long *)(v)) /* XXX TO DO @@ -36,8 +40,8 @@ #define OCIAttrGet_log_stat(th,ht,ah,sp,at,eh,stat) \ stat = OCIAttrGet(th,ht,ah,sp,at,eh); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ - "%sAttrGet(%p,%lu,%p,%p,%lu,%p)=%s\n", \ - OciTp, (void*)th,(ub4)ht,(void*)ah,(ub4*)sp,(ub4)at,(void*)eh,\ + "%sAttrGet(%p,%lu,%p,%p,%lu,%p)=%s\n", \ + OciTp, (void*)th,ul_t(ht),(void*)ah,pul_t(sp),ul_t(at),(void*)eh,\ oci_status_name(stat)),stat : stat #define OCIAttrGet_parmdp(imp_sth, parmdp, p, l, a, stat) \ @@ -51,17 +55,17 @@ #define OCIAttrSet_log_stat(th,ht,ah,s,a,eh,stat) \ stat=OCIAttrSet(th,ht,ah,s,a,eh); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ - "%sAttrSet(%p,%lu,%p,%lu,%lu,%p)=%s\n", \ - OciTp, (void*)th,(ub4)ht,(void*)(ah),(ub4)s,(ub4)a,(void*)eh, \ + "%sAttrSet(%p,%u,%p,%lu,%lu,%p)=%s\n", \ + OciTp, (void*)th,(ht),(void*)(ah),ul_t(s),ul_t(a),(void*)eh, \ oci_status_name(stat)),stat : stat #define OCIBindByName_log_stat(sh,bp,eh,p,pl,v,vs,dt,in,al,rc,mx,cu,md,stat) \ stat=OCIBindByName(sh,bp,eh,p,pl,v,vs,dt,in,al,rc,mx,cu,md); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sBindByName(%p,%p,%p,\"%s\",%ld,%p,%ld,%u,%p,%p,%p,%lu,%p,%lu)=%s\n",\ - OciTp, (void*)sh,(void*)bp,(void*)eh,p,(sb4)(pl),(void*)(v), \ - (sb4)(vs),(ub2)(dt),(void*)(in),(ub2*)(al),(ub2*)(rc), \ - (ub4)(mx),(ub4*)(cu),(ub4)(md), \ + OciTp, (void*)sh,(void*)bp,(void*)eh,p,sl_t(pl),(void*)(v), \ + sl_t(vs),(ub2)(dt),(void*)(in),(ub2*)(al),(ub2*)(rc), \ + ul_t((mx)),pul_t((cu)),ul_t((md)), \ oci_status_name(stat)),stat : stat #define OCIBindDynamic_log(bh,eh,icx,cbi,ocx,cbo,stat) \ @@ -76,97 +80,97 @@ stat=OCIDefineByPos(sh,dp,eh,p,vp,vs,dt,ip,rp,cp,m); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sDefineByPos(%p,%p,%p,%lu,%p,%ld,%u,%p,%p,%p,%lu)=%s\n", \ - OciTp, (void*)sh,(void*)dp,(void*)eh,(ub4)(p),(void*)(vp), \ - (sb4)vs,(ub2)dt,(void*)(ip),(ub2*)(rp),(ub2*)(cp),(ub4)m, \ + OciTp, (void*)sh,(void*)dp,(void*)eh,ul_t((p)),(void*)(vp), \ + sl_t(vs),(ub2)dt,(void*)(ip),(ub2*)(rp),(ub2*)(cp),ul_t(m), \ oci_status_name(stat)),stat : stat #define OCIDescribeAny_log_stat(sh,eh,op,ol,opt,il,ot,dh,stat) \ stat=OCIDescribeAny(sh,eh,op,ol,opt,il,ot,dh); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sDescribeAny(%p,%p,%p,%lu,%u,%u,%u,%p)=%s\n", \ - OciTp, (void*)sh,(void*)eh,(void*)op,(ub4)ol, \ + OciTp, (void*)sh,(void*)eh,(void*)op,ul_t(ol), \ (ub1)opt,(ub1)il,(ub1)ot,(void*)dh, \ oci_status_name(stat)),stat : stat #define OCIDescriptorAlloc_ok(envhp, p, t) \ if (DBD_OCI_TRACEON) fprintf(DBD_OCI_TRACEFP, \ "%sDescriptorAlloc(%p,%p,%lu,0,0)\n", \ - OciTp,(void*)envhp,(void*)(p),(ub4)t); \ + OciTp,(void*)envhp,(void*)(p),ul_t(t)); \ if (OCIDescriptorAlloc((envhp), (void**)(p), (t), 0, 0)==OCI_SUCCESS); \ else croak("OCIDescriptorAlloc (type %ld) failed",t) #define OCIDescriptorFree_log(d,t) \ if (DBD_OCI_TRACEON) fprintf(DBD_OCI_TRACEFP, \ - "%sDescriptorFree(%p,%lu)\n", OciTp, (void*)d,(ub4)t); \ + "%sDescriptorFree(%p,%lu)\n", OciTp, (void*)d,ul_t(t)); \ OCIDescriptorFree(d,t) #define OCIEnvInit_log_stat(ev,md,xm,um,stat) \ stat=OCIEnvInit(ev,md,xm,um); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sEnvInit(%p,%lu,%lu,%p)=%s\n", \ - OciTp, (void*)ev,(ub4)md,(ub4)xm,(void*)um, \ + OciTp, (void*)ev,ul_t(md),ul_t(xm),(void*)um, \ oci_status_name(stat)),stat : stat #define OCIErrorGet_log_stat(hp,rn,ss,ep,bp,bs,t, stat) \ ((stat = OCIErrorGet(hp,rn,ss,ep,bp,bs,t)), \ ((DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sErrorGet(%p,%lu,\"%s\",%p,\"%s\",%lu,%lu)=%s\n", \ - OciTp, (void*)hp,(ub4)rn,OciTstr(ss),(sb4*)ep, \ - bp,(ub4)bs,(ub4)t, oci_status_name(stat)),stat : stat)) + OciTp, (void*)hp,ul_t(rn),OciTstr(ss),psl_t(ep), \ + bp,ul_t(bs),ul_t(t), oci_status_name(stat)),stat : stat)) #define OCIHandleAlloc_log_stat(ph,hp,t,xs,ump,stat) \ stat=OCIHandleAlloc(ph,hp,t,xs,ump); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sHandleAlloc(%p,%p,%lu,%lu,%p)=%s\n", \ - OciTp, (void*)ph,(void*)hp,(ub4)t,(ub4)xs,(void*)ump, \ + OciTp, (void*)ph,(void*)hp,ul_t(t),ul_t(xs),(void*)ump, \ oci_status_name(stat)),stat : stat #define OCIHandleAlloc_ok(envhp, p, t, stat) \ OCIHandleAlloc_log_stat((envhp),(void**)(p),(t),0,0, stat); \ if (stat==OCI_SUCCESS) ; \ - else croak("OCIHandleAlloc (type %lu) failed",(ub4)t) + else croak("OCIHandleAlloc (type %lu) failed",ul_t(t)) #define OCIHandleFree_log_stat(hp,t,stat) \ stat=OCIHandleFree( (hp), (t)); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ - "%sHandleFree(%p,%lu)=%s\n",OciTp,(void*)hp,(ub4)t, \ + "%sHandleFree(%p,%lu)=%s\n",OciTp,(void*)hp,ul_t(t), \ oci_status_name(stat)),stat : stat #define OCIInitialize_log_stat(md,cp,mlf,rlf,mfp,stat) \ stat=OCIInitialize(md,cp,mlf,rlf,mfp); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sInitialize(%lu,%p,%p,%p,%p)=%s\n", \ - OciTp, (ub4)md,(void*)cp,(void*)mlf,(void*)rlf,(void*)mfp, \ + OciTp, ul_t(md),(void*)cp,(void*)mlf,(void*)rlf,(void*)mfp, \ oci_status_name(stat)),stat : stat #define OCILobGetLength_log_stat(sh,eh,lh,l,stat) \ stat=OCILobGetLength(sh,eh,lh,l); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sLobGetLength(%p,%p,%p,%p)=%s\n", \ - OciTp, (void*)sh,(void*)eh,(void*)lh,(ub4*)l, \ + OciTp, (void*)sh,(void*)eh,(void*)lh,pul_t(l), \ oci_status_name(stat)),stat : stat #define OCILobRead_log_stat(sv,eh,lh,am,of,bp,bl,cx,cb,csi,csf,stat) \ stat=OCILobRead(sv,eh,lh,am,of,bp,bl,cx,cb,csi,csf); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sLobRead(%p,%p,%p,%p,%lu,%p,%lu,%p,%p,%u,%u)=%s\n", \ - OciTp, (void*)sv,(void*)eh,(void*)lh,(ub4*)am,(ub4)of, \ - (void*)bp,(ub4)bl,(void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ + OciTp, (void*)sv,(void*)eh,(void*)lh,pul_t(am),ul_t(of), \ + (void*)bp,ul_t(bl),(void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ oci_status_name(stat)),stat : stat #define OCILobTrim_log_stat(sv,eh,lh,l,stat) \ stat=OCILobTrim(sv,eh,lh,l); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sLobtrim(%p,%p,%p,%lu)=%s\n", \ - OciTp, (void*)sv,(void*)eh,(void*)lh,(ub4)l, \ + OciTp, (void*)sv,(void*)eh,(void*)lh,ul_t(l), \ oci_status_name(stat)),stat : stat #define OCILobWrite_log_stat(sv,eh,lh,am,of,bp,bl,p,cx,cb,csi,csf,stat) \ stat=OCILobWrite(sv,eh,lh,am,of,bp,bl,p,cx,cb,csi,csf); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sLobWrite(%p,%p,%p,%p,%lu,%p,%lu,%u,%p,%p,%u,%u)=%s\n", \ - OciTp, (void*)sv,(void*)eh,(void*)lh,(ub4*)am,(ub4)of, \ - (void*)bp,(ub4)bl,(ub1)p, \ + OciTp, (void*)sv,(void*)eh,(void*)lh,pul_t(am),ul_t(of), \ + (void*)bp,ul_t(bl),(ub1)p, \ (void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ oci_status_name(stat)),stat : stat @@ -174,7 +178,7 @@ stat=OCIParamGet(hp,ht,eh,pp,ps); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sParamGet(%p,%lu,%p,%p,%lu)=%s\n", \ - OciTp, (void*)hp,(ub4)(ht),(void*)eh,(void*)pp,(ub4)ps, \ + OciTp, (void*)hp,ul_t((ht)),(void*)eh,(void*)pp,ul_t(ps), \ oci_status_name(stat)),stat : stat #define OCIServerAttach_log_stat(imp_dbh, dbname,stat) \ @@ -189,57 +193,57 @@ stat=OCIStmtExecute(sv,st,eh,i,ro,si,so,md); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sStmtExecute(%p,%p,%p,%lu,%lu,%p,%p,%lu)=%s\n", \ - OciTp, (void*)sv,(void*)st,(void*)eh,(ub4)(i), \ - (ub4)(ro),(void*)(si),(void*)(so),(ub4)(md), \ + OciTp, (void*)sv,(void*)st,(void*)eh,ul_t((i)), \ + ul_t((ro)),(void*)(si),(void*)(so),ul_t((md)), \ oci_status_name(stat)),stat : stat #define OCIStmtFetch_log_stat(sh,eh,nr,or,md,stat) \ stat=OCIStmtFetch(sh,eh,nr,or,md); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sStmtFetch(%p,%p,%lu,%u,%lu)=%s\n", \ - OciTp, (void*)sh,(void*)eh,(ub4)nr,(ub2)or,(ub4)md, \ + OciTp, (void*)sh,(void*)eh,ul_t(nr),(ub2)or,ul_t(md), \ oci_status_name(stat)),stat : stat #define OCIStmtPrepare_log_stat(sh,eh,s,sl,l,m,stat) \ stat=OCIStmtPrepare(sh,eh,s,sl,l,m); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sStmtPrepare(%p,%p,'%s',%lu,%lu,%lu)=%s\n", \ - OciTp, (void*)sh,(void*)eh,s,(ub4)sl,(ub4)l,(ub4)m, \ + OciTp, (void*)sh,(void*)eh,s,ul_t(sl),ul_t(l),ul_t(m), \ oci_status_name(stat)),stat : stat #define OCIServerDetach_log_stat(sh,eh,md,stat) \ stat=OCIServerDetach(sh,eh,md); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sServerDetach(%p,%p,%lu)=%s\n", \ - OciTp, (void*)sh,(void*)eh,(ub4)md, \ + OciTp, (void*)sh,(void*)eh,ul_t(md), \ oci_status_name(stat)),stat : stat #define OCISessionBegin_log_stat(sh,eh,uh,cr,md,stat) \ stat=OCISessionBegin(sh,eh,uh,cr,md); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sSessionBegin(%p,%p,%p,%lu,%lu)=%s\n", \ - OciTp, (void*)sh,(void*)eh,(void*)uh,(ub4)cr,(ub4)md, \ + OciTp, (void*)sh,(void*)eh,(void*)uh,ul_t(cr),ul_t(md), \ oci_status_name(stat)),stat : stat #define OCISessionEnd_log_stat(sh,eh,ah,md,stat) \ stat=OCISessionEnd(sh,eh,ah,md); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sSessionEnd(%p,%p,%p,%lu)=%s\n", \ - OciTp, (void*)sh,(void*)eh,(void*)ah,(ub4)md, \ + OciTp, (void*)sh,(void*)eh,(void*)ah,ul_t(md), \ oci_status_name(stat)),stat : stat #define OCITransCommit_log_stat(sh,eh,md,stat) \ stat=OCITransCommit(sh,eh,md); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sTransCommit(%p,%p,%lu)=%s\n", \ - OciTp, (void*)sh,(void*)eh,(ub4)md, \ + OciTp, (void*)sh,(void*)eh,ul_t(md), \ oci_status_name(stat)),stat : stat #define OCITransRollback_log_stat(sh,eh,md,stat) \ stat=OCITransRollback(sh,eh,md); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ "%sTransRollback(%p,%p,%lu)=%s\n", \ - OciTp, (void*)sh,(void*)eh,(ub4)md, \ + OciTp, (void*)sh,(void*)eh,ul_t(md), \ oci_status_name(stat)),stat : stat #endif /* OCI_V8_SYNTAX */ diff --git a/t/base.t b/t/base.t index 4630b6d1..f760fdc8 100755 --- a/t/base.t +++ b/t/base.t @@ -13,12 +13,36 @@ print "ok 2\n"; $switch = DBI->internal; (ref $switch eq 'DBI::dr') ? print "ok 3\n" : print "not ok 3\n"; +eval { + # This is a special case. install_driver should not normally be used. $drh = DBI->install_driver('Oracle'); (ref $drh eq 'DBI::dr') ? print "ok 4\n" : print "not ok 4\n"; +}; +if ($@) { + $@ =~ s/\n\n+/\n/g if $@; + warn "Failed to load Oracle extension and/or shared libraries:\n$@" if $@; + warn "The remaining tests will probably also fail with the same error.\a\n\n"; + # try to provide some useful pointers for some cases + if ($@ =~ /Solaris patch.*Java/i) { + warn "*** Please read the README.java file for help. ***\n"; + } + else { + warn "*** Please read the README and README.help files for help. ***\n"; + } + warn "\n"; + sleep 5; +} + print "ok 5\n" if $drh->{Version}; BEGIN { $tests = 5 } exit 0; # end. + +__END__ + +You must install a Solaris patch to run this version of +the Java runtime. +Please see the README and release notes for more information. diff --git a/t/plsql.t b/t/plsql.t index 2c300fbf..0113a719 100644 --- a/t/plsql.t +++ b/t/plsql.t @@ -236,7 +236,6 @@ if (1) { my $cur_query = q{ SELECT object_name, owner FROM all_objects WHERE object_name LIKE :p1 and ROWNUM <= 3 - ORDER BY object_name, owner }; my $cur1 = 42; #$dbh->trace(4); From e4e9f55649af0264d73a4eb7d8ea402664dc3bfd Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Thu, 30 Aug 2001 11:00:13 -0500 Subject: [PATCH 046/637] import DBD-Oracle 1.10 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 1.10 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-1.10.tar.gz --- Changes | 11 +++++++++- Makefile.PL | 34 ++++++++++++++++++++--------- Oracle.pm | 8 +++---- Todo | 3 +++ dbdimp.h | 3 ++- oci8.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++--- ocitrace.h | 24 ++++++++++----------- t/ph_type.t | 17 +++++++++------ 8 files changed, 125 insertions(+), 37 deletions(-) diff --git a/Changes b/Changes index 6e387a00..a58c87d3 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,13 @@ -Changes in DBD::Oracle 1.09 27th August 2001 +Changes in DBD::Oracle 1.10 30th August 2001 + + Explicitly require DBI version 1.20 (or later). + Support multiple oracle home's in Win32 registry thanks to Jeff Urlwin. + Improved build support for Oracle >=8.1.7 (I_SYM) thanks to Stephen Close. + Fixed LOB bug when writing non-string values thanks to Stephen Close. + Fixed t/ph_type.t to be better behaved thanks to Ville Skytta. + Added OCI8 handle/descriptor name to trace output for some API calls. + +Changes in DBD::Oracle 1.09 27th August 2001 Changed behaviour when OCIStmtExecute() returns OCI_SUCCESS_WITH_INFO: used to be treated as OCI_SUCCESS, now also sets $DBI::err/$DBI::errstr diff --git a/Makefile.PL b/Makefile.PL index a5e8b2fd..c6c8469c 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,11 +1,11 @@ -# $Id: Makefile.PL,v 1.93 2001/08/29 19:38:31 timbo Exp $ +# $Id: Makefile.PL,v 1.94 2001/08/30 15:48:36 timbo Exp $ ## ## You should not need to edit this file. ## BEGIN { $^W = 1 } -BEGIN { require 5.003 } # 5.003 fixes very important bugs +BEGIN { require 5.004 } use ExtUtils::MakeMaker 5.16, qw(&WriteMakefile $Verbose); use Getopt::Long; @@ -18,7 +18,7 @@ use strict; # For those not using Dynamic loading this means building a # new static perl in the DBI directory by saying 'make perl' # and then using _that_ perl to make this one. -use DBI 1.08; +use DBI 1.20; use DBI::DBD; # DBD creation tools @@ -337,15 +337,15 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l # modifications by lbaxter@fleetcc.com if ( ($os eq 'hpux') && ($osvers > 10) && ($Config{'cc'} eq 'cc') ) { - # these get dragged in from demo_rdbms.mk where Oralce uses + # these get dragged in from demo_rdbms.mk where Oracle uses them # the linker bitches about them not being valid options # in this context $linkwith =~ s/-Wl,\+[sn]//g; # Oracle 8.0.5 drags in these which also cause link errors: # this produces a good link with the 32bit version of oracle - # (64bit version of 8.0.5 fails to link) - # someone else will have to hack that one out + # (64bit version of 8.0.5 fails to link + # someone else will have to hack that one out) $linkwith =~ s/\+D[AS]2\.0[W]* / /g; # A number of folks have had to add this library to resolve @@ -411,7 +411,7 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o \$(COMPOBJS)" }; } - my $OCIINCLUDE = $MK{INCLUDE} || ''; + my $OCIINCLUDE = expand_mkvars($MK{INCLUDE} || '', 0, 0); $OCIINCLUDE .= " -I$OH/rdbms/demo"; my $inc = join " ", map { "-I$OH/$_" } @h_dirs; $opts{INC} = "$OCIINCLUDE $inc -I$dbi_arch_dir"; @@ -619,16 +619,30 @@ sub win32_oracle_home { # Look for ORACLE_HOME in all ORACLE sub-folders, use last one found # before 8.1.5, there should be only one eval { - my @hkey = ($hkey); my ($oh1, %oh); + my @hkey = ($hkey); while (@hkey) { $hkey = shift @hkey; $oh = $oh1, $oh{$oh1} = 1 if ($oh1 = &$Val($hkey)) && -d $oh1; push @hkey, &$Keys($hkey); } - print "\nMultiple Oracle homes: ", join(" ", sort keys %oh), "\n\n" - if 1 < keys %oh; + if (1 < keys %oh) { + # JLU: 8/21/01 Oracle's default home is the first one in + # the path, at least with 8i + print "\n\007Multiple Oracle homes: ", join(" ", sort keys %oh), "\n\n"; + my @path = split(";", $ENV{PATH}); + my $dir; + foreach $dir (@path) { + # the path will be c:\path\to\home\bin, so remove \bin if it's there. + $dir =~ s/\\bin$//; + if (defined($oh{$dir})) { + print "$dir is first in the PATH, so we'll use that as Oracle's default home.\n\n"; + $oh = $dir; + last; + } + } + } } if defined $Keys; } diff --git a/Oracle.pm b/Oracle.pm index e6317fdb..bed2b68a 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.89 2001/08/29 19:38:31 timbo Exp $ +# $Id: Oracle.pm,v 1.90 2001/08/30 15:48:36 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce # @@ -10,7 +10,7 @@ require 5.003; -$DBD::Oracle::VERSION = '1.09'; +$DBD::Oracle::VERSION = '1.10'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -32,9 +32,9 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.89 $, 10); + my $Revision = substr(q$Revision: 1.90 $, 10); - require_version DBI 1.02; + require_version DBI 1.20; bootstrap DBD::Oracle $VERSION; diff --git a/Todo b/Todo index a734af0c..dbb469cc 100644 --- a/Todo +++ b/Todo @@ -2,6 +2,9 @@ Move urls from README into Oracle.pm +Change all uses of perl global na (SvPV & sv_2pv) to local variables +for better thread safety. + Test script for bind type / field type / length / null interactions of char/varchar types. diff --git a/dbdimp.h b/dbdimp.h index 1127d35e..773b344a 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -1,5 +1,5 @@ /* - $Id: dbdimp.h,v 1.42 2001/08/29 11:32:51 timbo Exp $ + $Id: dbdimp.h,v 1.43 2001/08/30 15:48:36 timbo Exp $ Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce @@ -255,6 +255,7 @@ void dbd_phs_avsv_complete _((phs_t *phs, I32 index, I32 debug)); int oci_error _((SV *h, OCIError *errhp, sword status, char *what)); char *oci_stmt_type_name _((int stmt_type)); char *oci_status_name _((sword status)); +char * oci_hdtype_name _((ub4 hdtype)); int dbd_rebind_ph_lob _((SV *sth, imp_sth_t *imp_sth, phs_t *phs)); void ora_free_lob_refetch _((SV *sth, imp_sth_t *imp_sth)); void dbd_phs_avsv_complete _((phs_t *phs, I32 index, I32 debug)); diff --git a/oci8.c b/oci8.c index fa31a5e6..616e8fcc 100644 --- a/oci8.c +++ b/oci8.c @@ -1,7 +1,7 @@ /* - $Id: oci8.c,v 1.31 2001/08/29 16:37:58 timbo Exp $ + $Id: oci8.c,v 1.32 2001/08/30 15:48:36 timbo Exp $ - Copyright (c) 1998 Tim Bunce + Copyright (c) 1998,1999,2000,2001 Tim Bunce You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file, @@ -79,6 +79,51 @@ oci_stmt_type_name(int stmt_type) } +char * +oci_hdtype_name(ub4 hdtype) +{ + SV *sv; + switch (hdtype) { + /* Handles */ + case OCI_HTYPE_ENV: return "OCI_HTYPE_ENV"; + case OCI_HTYPE_ERROR: return "OCI_HTYPE_ERROR"; + case OCI_HTYPE_SVCCTX: return "OCI_HTYPE_SVCCTX"; + case OCI_HTYPE_STMT: return "OCI_HTYPE_STMT"; + case OCI_HTYPE_BIND: return "OCI_HTYPE_BIND"; + case OCI_HTYPE_DEFINE: return "OCI_HTYPE_DEFINE"; + case OCI_HTYPE_DESCRIBE: return "OCI_HTYPE_DESCRIBE"; + case OCI_HTYPE_SERVER: return "OCI_HTYPE_SERVER"; + case OCI_HTYPE_SESSION: return "OCI_HTYPE_SESSION"; + case OCI_HTYPE_TRANS: return "OCI_HTYPE_TRANS"; + case OCI_HTYPE_COMPLEXOBJECT: return "OCI_HTYPE_COMPLEXOBJECT"; + case OCI_HTYPE_SECURITY: return "OCI_HTYPE_SECURITY"; + case OCI_HTYPE_SUBSCRIPTION: return "OCI_HTYPE_SUBSCRIPTION"; + case OCI_HTYPE_DIRPATH_CTX: return "OCI_HTYPE_DIRPATH_CTX"; + case OCI_HTYPE_DIRPATH_COLUMN_ARRAY:return "OCI_HTYPE_DIRPATH_COLUMN_ARRAY"; + case OCI_HTYPE_DIRPATH_STREAM: return "OCI_HTYPE_DIRPATH_STREAM"; + case OCI_HTYPE_PROC: return "OCI_HTYPE_PROC"; + /* Descriptors */ + case OCI_DTYPE_LOB: return "OCI_DTYPE_LOB"; + case OCI_DTYPE_SNAP: return "OCI_DTYPE_SNAP"; + case OCI_DTYPE_RSET: return "OCI_DTYPE_RSET"; + case OCI_DTYPE_PARAM: return "OCI_DTYPE_PARAM"; + case OCI_DTYPE_ROWID: return "OCI_DTYPE_ROWID"; + case OCI_DTYPE_COMPLEXOBJECTCOMP: return "OCI_DTYPE_COMPLEXOBJECTCOMP"; + case OCI_DTYPE_FILE: return "OCI_DTYPE_FILE"; + case OCI_DTYPE_AQENQ_OPTIONS: return "OCI_DTYPE_AQENQ_OPTIONS"; + case OCI_DTYPE_AQDEQ_OPTIONS: return "OCI_DTYPE_AQDEQ_OPTIONS"; + case OCI_DTYPE_AQMSG_PROPERTIES: return "OCI_DTYPE_AQMSG_PROPERTIES"; + case OCI_DTYPE_AQAGENT: return "OCI_DTYPE_AQAGENT"; + case OCI_DTYPE_LOCATOR: return "OCI_DTYPE_LOCATOR"; + case OCI_DTYPE_DATETIME: return "OCI_DTYPE_DATETIME"; + case OCI_DTYPE_INTERVAL: return "OCI_DTYPE_INTERVAL"; + case OCI_DTYPE_AQNFY_DESCRIPTOR: return "OCI_DTYPE_AQNFY_DESCRIPTOR"; + } + sv = sv_2mortal(newSViv(hdtype)); + return SvPV(sv,na); +} + + sb4 oci_error_get(OCIError *errhp, sword status, char *what, SV *errstr, int debug) { @@ -547,6 +592,15 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) sword status; ub4 lobEmpty = 0; + if (!SvPOK(phs->sv)) { /* normalizations for special cases */ + if (SvOK(phs->sv)) { /* ie a number, convert to string ASAP */ + if (!(SvROK(phs->sv) && phs->is_inout)) + sv_2pv(phs->sv, &na); + } + else /* ensure we're at least an SVt_PV (so SvPVX etc work) */ + SvUPGRADE(phs->sv, SVt_PV); + } + if (!phs->desc_h) { ++imp_sth->has_lobs; phs->desc_t = OCI_DTYPE_LOB; @@ -1558,7 +1612,9 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl for(i=0; i < lr->num_fields; ++i) { imp_fbh_t *fbh = &lr->fbh_ary[i]; phs_t *phs = (phs_t*)fbh->special; - ub4 amtp = SvCUR(phs->sv); + ub4 amtp; + SvUPGRADE(phs->sv, SVt_PV); /* just in case */ + amtp = SvCUR(phs->sv); /* XXX UTF8? */ if (amtp > 0) { /* since amtp==0 & OCI_ONE_PIECE fail (OCI 8.0.4) */ OCILobWrite_log_stat(imp_sth->svchp, errhp, fbh->desc_h, &amtp, 1, SvPVX(phs->sv), amtp, OCI_ONE_PIECE, diff --git a/ocitrace.h b/ocitrace.h index c82a0f56..4fa21e4e 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -40,8 +40,8 @@ #define OCIAttrGet_log_stat(th,ht,ah,sp,at,eh,stat) \ stat = OCIAttrGet(th,ht,ah,sp,at,eh); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ - "%sAttrGet(%p,%lu,%p,%p,%lu,%p)=%s\n", \ - OciTp, (void*)th,ul_t(ht),(void*)ah,pul_t(sp),ul_t(at),(void*)eh,\ + "%sAttrGet(%p,%s,%p,%p,%lu,%p)=%s\n", \ + OciTp, (void*)th,oci_hdtype_name(ht),(void*)ah,pul_t(sp),ul_t(at),(void*)eh,\ oci_status_name(stat)),stat : stat #define OCIAttrGet_parmdp(imp_sth, parmdp, p1, l, a, stat) \ @@ -55,8 +55,8 @@ #define OCIAttrSet_log_stat(th,ht,ah,s1,a,eh,stat) \ stat=OCIAttrSet(th,ht,ah,s1,a,eh); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ - "%sAttrSet(%p,%u,%p,%lu,%lu,%p)=%s\n", \ - OciTp, (void*)th,(ht),(void*)(ah),ul_t(s1),ul_t(a),(void*)eh, \ + "%sAttrSet(%p,%s,%p,%lu,%lu,%p)=%s\n", \ + OciTp, (void*)th,oci_hdtype_name(ht),(void*)(ah),ul_t(s1),ul_t(a),(void*)eh, \ oci_status_name(stat)),stat : stat #define OCIBindByName_log_stat(sh,bp,eh,p1,pl,v,vs,dt,in,al,rc,mx,cu,md,stat) \ @@ -94,14 +94,14 @@ #define OCIDescriptorAlloc_ok(envhp, p1, t) \ if (DBD_OCI_TRACEON) fprintf(DBD_OCI_TRACEFP, \ - "%sDescriptorAlloc(%p,%p,%lu,0,0)\n", \ - OciTp,(void*)envhp,(void*)(p1),ul_t(t)); \ + "%sDescriptorAlloc(%p,%p,%s,0,0)\n", \ + OciTp,(void*)envhp,(void*)(p1),oci_hdtype_name(t)); \ if (OCIDescriptorAlloc((envhp), (void**)(p1), (t), 0, 0)==OCI_SUCCESS); \ else croak("OCIDescriptorAlloc (type %ld) failed",t) #define OCIDescriptorFree_log(d,t) \ if (DBD_OCI_TRACEON) fprintf(DBD_OCI_TRACEFP, \ - "%sDescriptorFree(%p,%lu)\n", OciTp, (void*)d,ul_t(t)); \ + "%sDescriptorFree(%p,%s)\n", OciTp, (void*)d,oci_hdtype_name(t)); \ OCIDescriptorFree(d,t) #define OCIEnvInit_log_stat(ev,md,xm,um,stat) \ @@ -121,19 +121,19 @@ #define OCIHandleAlloc_log_stat(ph,hp,t,xs,ump,stat) \ stat=OCIHandleAlloc(ph,hp,t,xs,ump); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ - "%sHandleAlloc(%p,%p,%lu,%lu,%p)=%s\n", \ - OciTp, (void*)ph,(void*)hp,ul_t(t),ul_t(xs),(void*)ump, \ + "%sHandleAlloc(%p,%p,%s,%lu,%p)=%s\n", \ + OciTp, (void*)ph,(void*)hp,oci_hdtype_name(t),ul_t(xs),(void*)ump, \ oci_status_name(stat)),stat : stat #define OCIHandleAlloc_ok(envhp, p1, t, stat) \ OCIHandleAlloc_log_stat((envhp),(void**)(p1),(t),0,0, stat); \ if (stat==OCI_SUCCESS) ; \ - else croak("OCIHandleAlloc (type %lu) failed",ul_t(t)) + else croak("OCIHandleAlloc(%s) failed",oci_hdtype_name(t)) #define OCIHandleFree_log_stat(hp,t,stat) \ stat=OCIHandleFree( (hp), (t)); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ - "%sHandleFree(%p,%lu)=%s\n",OciTp,(void*)hp,ul_t(t), \ + "%sHandleFree(%p,%s)=%s\n",OciTp,(void*)hp,oci_hdtype_name(t), \ oci_status_name(stat)),stat : stat #define OCIInitialize_log_stat(md,cp,mlf,rlf,mfp,stat) \ @@ -161,7 +161,7 @@ #define OCILobTrim_log_stat(sv,eh,lh,l,stat) \ stat=OCILobTrim(sv,eh,lh,l); \ (DBD_OCI_TRACEON) ? fprintf(DBD_OCI_TRACEFP, \ - "%sLobtrim(%p,%p,%p,%lu)=%s\n", \ + "%sLobTrim(%p,%p,%p,%lu)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,ul_t(l), \ oci_status_name(stat)),stat : stat diff --git a/t/ph_type.t b/t/ph_type.t index 135e1237..8b6ba857 100644 --- a/t/ph_type.t +++ b/t/ph_type.t @@ -39,12 +39,16 @@ $^W = 1; print "1..$tests\n"; my ($sth,$expect,$tmp); +my $table = "dbd_oracle_test__drop_me"; -# drop table but do not even warn if not there -eval { $dbh->do("DROP TABLE foobar") }; +# drop table but don't warn if not there +eval { + local $dbh->{PrintError} = 0; + $dbh->do("DROP TABLE $table"); +}; #warn $@ if $@; -ok(0, $dbh->do("CREATE TABLE foobar (test VARCHAR2(2), foo VARCHAR2(20))")); +ok(0, $dbh->do("CREATE TABLE $table (test VARCHAR2(2), foo VARCHAR2(20))")); my $val_with_trailing_space = "trailing "; my $val_with_embedded_nul = "embedded\0nul"; @@ -70,14 +74,14 @@ for my $test_ary (@tests) { ok(0, $dbh->{ora_ph_type} = $ph_type ); ok(0, $dbh->{ora_ph_type} == $ph_type ); - ok(0, $sth = $dbh->prepare("INSERT INTO foobar VALUES (?,?)")); + ok(0, $sth = $dbh->prepare("INSERT INTO $table VALUES (?,?)")); ok(0, $sth->execute("ts", $val_with_trailing_space)); ok(0, $sth->execute("en", $val_with_embedded_nul)); ok(0, $sth->execute("em", '')); # empty string ok(0, $tmp = $dbh->selectall_hashref(qq{ SELECT test, foo, length(foo) as len, nvl(foo,'ISNULL') as isnull - FROM foobar + FROM $table }, "test")); ok(0, keys(%$tmp) == 3); ok(0, $tmp->{en}->{foo}); @@ -111,9 +115,10 @@ for my $test_ary (@tests) { last if $trace; } +ok(0, $dbh->do("DROP TABLE $table")); ok(0, $dbh->disconnect ); -BEGIN { $tests = 52 } +BEGIN { $tests = 53 } __END__ From 59e185eaa349ef57dbc9aea75e666924a86b7edd Mon Sep 17 00:00:00 2001 From: Tim Bunce Date: Fri, 31 Aug 2001 10:55:32 -0500 Subject: [PATCH 047/637] import DBD-Oracle 1.11 from CPAN git-cpan-module: DBD-Oracle git-cpan-version: 1.11 git-cpan-authorid: TIMB git-cpan-file: authors/id/T/TI/TIMB/DBD-Oracle-1.11.tar.gz --- Changes | 7 +++++++ Makefile.PL | 29 +++++++++++++++++++++-------- Oracle.pm | 15 ++++++++++----- oci8.c | 13 +------------ 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/Changes b/Changes index a58c87d3..f6f41ba2 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,10 @@ +Changes in DBD::Oracle 1.11 31th August 2001 + + Improved LD_RUN_PATH code in Makefile.PL thanks to John Groenveld. + Improved HPUX code in Makefile.PL thanks to H.Merijn Brand. + Fixed handle/descriptor name code to be less Oracle version sensitive. + Updated $dbh->primary_key_info() to new DBI spec thanks to Steffen Goeldner. + Changes in DBD::Oracle 1.10 30th August 2001 Explicitly require DBI version 1.20 (or later). diff --git a/Makefile.PL b/Makefile.PL index c6c8469c..f56053a1 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,3 @@ -# $Id: Makefile.PL,v 1.94 2001/08/30 15:48:36 timbo Exp $ ## ## You should not need to edit this file. @@ -36,10 +35,10 @@ BEGIN { if ($^O eq 'VMS') { my $dbi_dir = dbd_dbi_dir(); my $dbi_arch_dir = dbd_dbi_arch_dir(); my $os = $^O; -my $osvers = $Config{osvers}; -$osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 +my $osvers = $Config{osvers}; $osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 my $exe_ext = ($os eq 'VMS') ? '.pl' : ''; my $BELL = "\a"; +$| = 1; my %opts = ( NAME => 'DBD::Oracle', @@ -334,7 +333,7 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l $linkwith =~ s/-Y P,/-YP,/g if $Config{gccversion}; $linkwith =~ s:-R /:-R/:g if $os eq 'solaris'; - # modifications by lbaxter@fleetcc.com + # modifications (mostly) by lbaxter@fleetcc.com if ( ($os eq 'hpux') && ($osvers > 10) && ($Config{'cc'} eq 'cc') ) { # these get dragged in from demo_rdbms.mk where Oracle uses them @@ -357,6 +356,15 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l $linkwith =~ s/$/ -lqsmashr/ if ( $linkwith !~ m/-lqsmshr/ ); } + if ( $os eq "hpux" && $osvers >= 11 and + $inspdver{RDBMS} =~ /^7.3/ and + $linkwith =~ m/-lcl\b/ && $linkwith =~ m/-l:libcl.a/ + ) { # from h.m.brand@hccnet.nl + print "Warning: Stripping -lcl from the link flags, because it\n" + . " seems to conflict with -l:libcl.a\n" ; + $linkwith =~ s/\s*-lcl\b//g; + } + if (($linkwith !~ m/-lcl/) || ($linkwith !~ m/-lpthread/)) { print "Warning: Oracle is built with multi-threading libraries\n" . " You will most likely need to rebuild perl from sources\n" @@ -427,7 +435,7 @@ $opts{DEFINE} .= ' -Xa' if $Config{cc} eq 'clcc'; # CenterLine CC $opts{DEFINE} .= ' -DNO_OCI8' if $::opt_8; # Set some private WriteMakefile options if this is 'me' :-) -if ($ENV{LOGNAME} eq 'timbo'){ # a reasonable guess +if (($ENV{LOGNAME}||'') eq 'timbo'){ # a reasonable guess $BELL = ""; $opts{DEFINE} .= ' -Wcast-align -Wconversion -Wpointer-arith -Wtraditional' . ' -Wbad-function-cast -Wcast-qual' if $Config{gccversion}; @@ -655,7 +663,12 @@ sub read_sysliblist { my $syslibs = (-f "$OH/lib/sysliblist") ? read_file("$OH/lib/sysliblist") : (-f "$OH/rdbms/lib/sysliblist") ? read_file("$OH/rdbms/lib/sysliblist") : ''; - $syslibs =~ s/-l:lib(\w+).(sl|a)\b/-l$1/g if $os eq 'hpux'; + #$syslibs =~ s/-l:lib(\w+).(sl|a)\b/-l$1/g if $os eq 'hpux'; + if ($os eq "hpux") { + $syslibs =~ s/-l:lib(\w+).(sl|a)\b/-l$1/g; + $linkwith =~ m/-lcl\b/ or + $syslibs =~ s/\s*-lcl\b//g; + } return $syslibs; } @@ -1133,13 +1146,13 @@ You have an old copy which you should delete when installing this one.\n"; my $self = shift; local($_) = $self->SUPER::const_loadlibs(@_); # edit LD_RUN_PATH ... - my ($ldrp) = m/^LD_RUN_PATH=(.*)/m; + my ($ldrp) = m/^LD_RUN_PATH\s*=\s*(.*)/m; # remove redundant /lib or /usr/lib as it can cause problems $ldrp =~ s!:(/usr)?/lib$!!; # if it's empty then set it manually $ldrp ||= "$OH/lib:$OH/rdbms/lib"; # stitch it back in - s/^LD_RUN_PATH=(.*)/LD_RUN_PATH=$ldrp/m; + s/^LD_RUN_PATH\s*=\s*(.*)/LD_RUN_PATH=$ldrp/m; my $env = $ENV{LD_RUN_PATH}; print "Ignoring LD_RUN_PATH='$env' in environment\n" if $env; print "LD_RUN_PATH=$ldrp\n"; diff --git a/Oracle.pm b/Oracle.pm index bed2b68a..505be84d 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1,5 +1,5 @@ -# $Id: Oracle.pm,v 1.90 2001/08/30 15:48:36 timbo Exp $ +# $Id: Oracle.pm,v 1.91 2001/08/31 15:54:13 timbo Exp $ # # Copyright (c) 1994,1995,1996,1997,1998,1999 Tim Bunce # @@ -10,7 +10,7 @@ require 5.003; -$DBD::Oracle::VERSION = '1.10'; +$DBD::Oracle::VERSION = '1.11'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -32,7 +32,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; Exporter::export_ok_tags('ora_types'); - my $Revision = substr(q$Revision: 1.90 $, 10); + my $Revision = substr(q$Revision: 1.91 $, 10); require_version DBI 1.20; @@ -409,8 +409,13 @@ SQL $sth; } + sub primary_key_info { - my($dbh, $attr) = @_; + my($dbh, $catalog, $schema, $table) = @_; + if (ref $catalog eq 'HASH') { + ($schema, $table) = @$catalog{'TABLE_SCHEM','TABLE_NAME'}; + $catalog = undef; + } my $Sql = <<'SQL'; SELECT * FROM @@ -433,7 +438,7 @@ SELECT * ORDER BY TABLE_SCHEM, TABLE_NAME, KEY_SEQ SQL my $sth = $dbh->prepare($Sql) or return undef; - $sth->execute(@$attr{'TABLE_SCHEM','TABLE_NAME'}) or return undef; + $sth->execute($schema, $table) or return undef; $sth; } diff --git a/oci8.c b/oci8.c index 616e8fcc..7286d9d9 100644 --- a/oci8.c +++ b/oci8.c @@ -1,5 +1,5 @@ /* - $Id: oci8.c,v 1.32 2001/08/30 15:48:36 timbo Exp $ + $Id: oci8.c,v 1.33 2001/08/31 15:54:13 timbo Exp $ Copyright (c) 1998,1999,2000,2001 Tim Bunce @@ -98,10 +98,6 @@ oci_hdtype_name(ub4 hdtype) case OCI_HTYPE_COMPLEXOBJECT: return "OCI_HTYPE_COMPLEXOBJECT"; case OCI_HTYPE_SECURITY: return "OCI_HTYPE_SECURITY"; case OCI_HTYPE_SUBSCRIPTION: return "OCI_HTYPE_SUBSCRIPTION"; - case OCI_HTYPE_DIRPATH_CTX: return "OCI_HTYPE_DIRPATH_CTX"; - case OCI_HTYPE_DIRPATH_COLUMN_ARRAY:return "OCI_HTYPE_DIRPATH_COLUMN_ARRAY"; - case OCI_HTYPE_DIRPATH_STREAM: return "OCI_HTYPE_DIRPATH_STREAM"; - case OCI_HTYPE_PROC: return "OCI_HTYPE_PROC"; /* Descriptors */ case OCI_DTYPE_LOB: return "OCI_DTYPE_LOB"; case OCI_DTYPE_SNAP: return "OCI_DTYPE_SNAP"; @@ -110,14 +106,7 @@ oci_hdtype_name(ub4 hdtype) case OCI_DTYPE_ROWID: return "OCI_DTYPE_ROWID"; case OCI_DTYPE_COMPLEXOBJECTCOMP: return "OCI_DTYPE_COMPLEXOBJECTCOMP"; case OCI_DTYPE_FILE: return "OCI_DTYPE_FILE"; - case OCI_DTYPE_AQENQ_OPTIONS: return "OCI_DTYPE_AQENQ_OPTIONS"; - case OCI_DTYPE_AQDEQ_OPTIONS: return "OCI_DTYPE_AQDEQ_OPTIONS"; - case OCI_DTYPE_AQMSG_PROPERTIES: return "OCI_DTYPE_AQMSG_PROPERTIES"; - case OCI_DTYPE_AQAGENT: return "OCI_DTYPE_AQAGENT"; case OCI_DTYPE_LOCATOR: return "OCI_DTYPE_LOCATOR"; - case OCI_DTYPE_DATETIME: return "OCI_DTYPE_DATETIME"; - case OCI_DTYPE_INTERVAL: return "OCI_DTYPE_INTERVAL"; - case OCI_DTYPE_AQNFY_DESCRIPTOR: return "OCI_DTYPE_AQNFY_DESCRIPTOR"; } sv = sv_2mortal(newSViv(hdtype)); return SvPV(sv,na); From f87873e61384c08aa68821371e63bafbfa5fe10b Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 26 Aug 2011 14:23:10 -0400 Subject: [PATCH 048/637] release work --- Changes | 4 ++++ Oracle.pm | 8 +++++++- t/31lob.t | 5 ++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index ba854f36..df19eafe 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,9 @@ Revision history for DBD::Oracle +Changes in DBD-Oracle 1.30 + [DOCUMENTATION] + - add warning about RT##69350 in documentation + Changes in DBD-Oracle 1.29_1 [ENHANCEMENTS] - added support for TAF callback (John Scoles) diff --git a/Oracle.pm b/Oracle.pm index 5c8cf09f..6abf5946 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -7,7 +7,7 @@ require 5.006; -$DBD::Oracle::VERSION = '1.29_1'; +$DBD::Oracle::VERSION = '1.30'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -5584,6 +5584,12 @@ No recommendation implied. Also PL/Vision from RevealNet and Steven Feuerstein, and "Q" from Savant Corporation. +=head1 BUGS AND LIMITATIONS + +There is a known problem with the 11.2g Oracle client and the +C PL/SQL function. +See L for the details. + =head1 SEE ALSO diff --git a/t/31lob.t b/t/31lob.t index ee243b1c..fcbe30f9 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -2,12 +2,15 @@ use strict; use Test::More; -use DBD::Oracle qw(:ora_types); +use DBD::Oracle qw(:ora_types ORA_OCI ); use DBI; unshift @INC ,'t'; require 'nchar_test_lib.pl'; +plan skip_all => "see RT#69350" + if ORA_OCI() =~ /^11\.2\./; + my $dbh; $| = 1; SKIP: { From 664cc4e2f29fbb6cdd31f5c071ed2242525c229f Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 15 Sep 2011 18:50:33 +0000 Subject: [PATCH 049/637] Merge branch 'master' into HEAD Conflicts: Changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14935 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 + MANIFEST | 40 ++-- MANIFEST.SKIP | 2 + Makefile.PL | 3 +- Oraperl.pm | 7 +- README-files/hpux/Conf-Lincoln-1.06 | 37 ---- README-files/hpux/Conf-Lincoln-1.07 | 43 ---- README-files/hpux/Conf-Merijn-580-10.20-cc | 46 ----- README-files/hpux/Conf-Merijn-585-11.00-cc | 46 ----- README-files/hpux/Conf-Merijn-585-11.11-cc | 47 ----- README-files/hpux/Conf-Merijn-587-11.23-cc | 54 ----- README-files/hpux/Conf-Merijn-588-10.20-gcc | 47 ----- README-files/hpux/Conf-Merijn-588-11.00-gcc32 | 47 ----- README-files/hpux/Conf-Merijn-588-11.00-gcc64 | 48 ----- README-files/hpux/Conf-Merijn-588-11.11-gcc32 | 47 ----- README-files/hpux/Conf-Merijn-588-11.11-gcc64 | 48 ----- README-files/hpux/Conf-Merijn-588-11.23-gcc64 | 48 ----- README-files/hpux/Conf-Mike | 39 ---- README-files/hpux/Conf-Roger | 40 ---- README-files/hpux/libjava.eml | 117 ----------- README.explain.txt | 191 ------------------ {Oracle.ex => examples}/README | 0 {Oracle.ex => examples}/bind.pl | 0 {Oracle.ex => examples}/commit.pl | 0 {Oracle.ex => examples}/curref.pl | 0 {Oracle.ex => examples}/ex.pl | 0 {Oracle.ex => examples}/japh | 0 {Oracle.ex => examples}/mktable.pl | 0 ora_explain.PL => examples/ora_explain.pl | 55 +---- {Oracle.ex => examples}/oradump.pl | 0 {Oracle.ex => examples}/proc.pl | 0 {Oracle.ex => examples}/sql | 0 {Oracle.ex => examples}/tabinfo.pl | 0 t/21nchar.t | 4 +- t/30long.t | 54 ++--- t/40ph_type.t | 6 +- t/50cursor.t | 6 +- t/70meta.t | 8 +- t/nchar_test_lib.pl | 8 +- xt/manifest.t | 21 ++ 40 files changed, 96 insertions(+), 1067 deletions(-) delete mode 100644 README-files/hpux/Conf-Lincoln-1.06 delete mode 100644 README-files/hpux/Conf-Lincoln-1.07 delete mode 100644 README-files/hpux/Conf-Merijn-580-10.20-cc delete mode 100644 README-files/hpux/Conf-Merijn-585-11.00-cc delete mode 100644 README-files/hpux/Conf-Merijn-585-11.11-cc delete mode 100644 README-files/hpux/Conf-Merijn-587-11.23-cc delete mode 100644 README-files/hpux/Conf-Merijn-588-10.20-gcc delete mode 100644 README-files/hpux/Conf-Merijn-588-11.00-gcc32 delete mode 100644 README-files/hpux/Conf-Merijn-588-11.00-gcc64 delete mode 100644 README-files/hpux/Conf-Merijn-588-11.11-gcc32 delete mode 100644 README-files/hpux/Conf-Merijn-588-11.11-gcc64 delete mode 100644 README-files/hpux/Conf-Merijn-588-11.23-gcc64 delete mode 100644 README-files/hpux/Conf-Mike delete mode 100644 README-files/hpux/Conf-Roger delete mode 100644 README-files/hpux/libjava.eml delete mode 100644 README.explain.txt rename {Oracle.ex => examples}/README (100%) rename {Oracle.ex => examples}/bind.pl (100%) rename {Oracle.ex => examples}/commit.pl (100%) rename {Oracle.ex => examples}/curref.pl (100%) rename {Oracle.ex => examples}/ex.pl (100%) rename {Oracle.ex => examples}/japh (100%) rename {Oracle.ex => examples}/mktable.pl (100%) rename ora_explain.PL => examples/ora_explain.pl (98%) rename {Oracle.ex => examples}/oradump.pl (100%) rename {Oracle.ex => examples}/proc.pl (100%) rename {Oracle.ex => examples}/sql (100%) rename {Oracle.ex => examples}/tabinfo.pl (100%) create mode 100644 xt/manifest.t diff --git a/Changes b/Changes index 1ed8c9df..564f85f6 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,7 @@ Revision history for DBD::Oracle Changes in DBD-Oracle XXX [ENHANCEMENTS] - Makefile.PL's options are now documented + - move 'explain' to '/examples' directory [BUG FIXES] - support development release versions in GetInfo (Martin J. Evans) @@ -12,6 +13,9 @@ Changes in DBD-Oracle XXX - convert a symbolically linked ORACLE_HOME to an absolute path (patch by H.Merijn Brand, applied by Martin J. Evans) [rt70785] + [DOCUMENTATION] + - announce that Oraperl will be removed from the dist by v1.38. + Changes in DBD-Oracle 1.30 [DOCUMENTATION] - add warning about RT#69350 in documentation diff --git a/MANIFEST b/MANIFEST index 64c37bd5..44af9c60 100644 --- a/MANIFEST +++ b/MANIFEST @@ -15,39 +15,23 @@ mkta.pl oci.def OCI.DLL export declarations oci8.c ocitrace.h -ora_explain.PL -Oracle.ex/bind.pl -Oracle.ex/commit.pl -Oracle.ex/curref.pl -Oracle.ex/ex.pl -Oracle.ex/japh -Oracle.ex/mktable.pl -Oracle.ex/oradump.pl -Oracle.ex/proc.pl -Oracle.ex/README -Oracle.ex/sql -Oracle.ex/tabinfo.pl +examples/bind.pl +examples/commit.pl +examples/curref.pl +examples/ex.pl +examples/japh +examples/mktable.pl +examples/oradump.pl +examples/proc.pl +examples/README +examples/sql +examples/tabinfo.pl Oracle.h Oracle.pm Oracle.xs oraperl.ph Old oraperl file included for completeness of emulation Oraperl.pm README -README-files/hpux/Conf-Lincoln-1.06 -README-files/hpux/Conf-Lincoln-1.07 -README-files/hpux/Conf-Merijn-580-10.20-cc -README-files/hpux/Conf-Merijn-585-11.00-cc -README-files/hpux/Conf-Merijn-585-11.11-cc -README-files/hpux/Conf-Merijn-587-11.23-cc -README-files/hpux/Conf-Merijn-588-10.20-gcc -README-files/hpux/Conf-Merijn-588-11.00-gcc32 -README-files/hpux/Conf-Merijn-588-11.00-gcc64 -README-files/hpux/Conf-Merijn-588-11.11-gcc32 -README-files/hpux/Conf-Merijn-588-11.11-gcc64 -README-files/hpux/Conf-Merijn-588-11.23-gcc64 -README-files/hpux/Conf-Mike -README-files/hpux/Conf-Roger -README-files/hpux/libjava.eml README-files/hpux/Makefile-Lincoln README.64bit.txt README.aix.txt @@ -102,3 +86,5 @@ t/nchar_test_lib.pl test.pl Todo typemap +examples/ora_explain.pl +t/00versions.t diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index d7ed2566..d38951ae 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -15,3 +15,5 @@ ^oracle/ ^tags$ ~$ +^\.git +^xt diff --git a/Makefile.PL b/Makefile.PL index cdcd2cfd..eb04c74f 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -49,11 +49,10 @@ my %opts = ( VERSION_FROM => 'Oracle.pm', PREREQ_PM => { "Test::Simple" => 0.90, # actually Test::More pkg in T::S dist "DBI" => 1.51}, - EXE_FILES => [ "ora_explain$exe_ext" ], OBJECT => '$(O_FILES)', DEFINE => '', DIR => [], - clean => { FILES => 'xstmp.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm DBD_ORA_OBJ.*' }, + clean => { FILES => 'xstmp.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def mk.pm DBD_ORA_OBJ.*' }, dist => { DIST_DEFAULT => 'clean distcheck disttest tardist', PREOP => '$(MAKE) -f Makefile.old distdir', diff --git a/Oraperl.pm b/Oraperl.pm index 81a5fb13..e3796002 100644 --- a/Oraperl.pm +++ b/Oraperl.pm @@ -229,7 +229,7 @@ __END__ =head1 NAME -Oraperl - deprecated (Repreived for now, but Will be removed in a future release) Perl access to Oracle databases for old oraperl scripts +Oraperl - [DEPRECATED] Perl access to Oracle databases for old oraperl scripts =head1 SYNOPSIS @@ -292,6 +292,11 @@ text instead: eval 'use Oraperl; 1;' || die $@ if $] >= 5; + +The use of I is deprecated in favor of L, +and will be removed from the I distribution as of +1.38. + =head2 Principal Functions The main functions for database access are &ora_login(), &ora_open(), diff --git a/README-files/hpux/Conf-Lincoln-1.06 b/README-files/hpux/Conf-Lincoln-1.06 deleted file mode 100644 index fef19ed6..00000000 --- a/README-files/hpux/Conf-Lincoln-1.06 +++ /dev/null @@ -1,37 +0,0 @@ - Platform: - osname=hpux, osvers=11.00, archname=PA-RISC2.0 - uname='hp-ux dhdb108 b.11.00 u 9000800 612309363 unlimited-user license ' - config_args='-Dprefix=/temp_data/baxtlinc/perl -Ubincompat5005' - hint=previous, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=undef d_sfio=undef uselargefiles=define - use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef - Compiler: - cc='cc', optimize='-O', gccversion= - cppflags='-D_HP-UX_SOURCE -I/usr/local/include +z -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Ae' - ccflags ='-D_HP-UX_SOURCE -I/usr/local/include +z -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Ae' - stdchar='unsigned char', d_stdstdio=define, usevfork=false - intsize=4, longsize=4, ptrsize=4, doublesize=8 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 - alignbytes=8, usemymalloc=y, prototype=define - Linker and Libraries: - ld='ld', ldflags =' -Wl,+vnocompatwarnings' - libpth=/lib /usr/lib /usr/ccs/lib - libs=-lnsl -lnm -lndbm -ldld -lm -lc -lndir -lcrypt -lsec -lcl -lpthread - libc=, so=sl, useshrplib=true, libperl=libperl.sl - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred ' - cccdlflags='+z', lddlflags='-b +vnocompatwarnings' - - Characteristics of this binary (from libperl): - Compile-time options: USE_LARGE_FILES - Built under hpux - Compiled at Jan 9 2001 17:36:00 - @INC: - /temp_data/baxtlinc/perl/lib/5.6.0/PA-RISC2.0 - /temp_data/baxtlinc/perl/lib/5.6.0 - /temp_data/baxtlinc/perl/lib/site_perl/5.6.0/PA-RISC2.0 - /temp_data/baxtlinc/perl/lib/site_perl/5.6.0 - /temp_data/baxtlinc/perl/lib/site_perl - . diff --git a/README-files/hpux/Conf-Lincoln-1.07 b/README-files/hpux/Conf-Lincoln-1.07 deleted file mode 100644 index 616349dd..00000000 --- a/README-files/hpux/Conf-Lincoln-1.07 +++ /dev/null @@ -1,43 +0,0 @@ - Platform: - osname=hpux, osvers=11.11, archname=PA-RISC2.0 - uname='hp-ux dhas116 b.11.11 u 9000800 1509760598 unlimited-user license ' - config_args='-Dprefix=/opt/perl/5.6.1-fccs-02 -Ubincompat5005 -Uuselargefiles \ - -A eval:libswanted=\"cl pthread $libswanted\" -des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=undef d_sfio=undef uselargefiles=undef usesocks=undef - use64bitint=undef use64bitall=undef uselongdouble=undef - Compiler: - cc='cc', ccflags ='-D_HP-UX_SOURCE -Aa', - optimize='-O', - cppflags='-D_HP-UX_SOURCE -Aa' - ccversion='B.11.11.02', gccversion='', gccosandvers='' - intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 - d_longlong=undef, longlongsize=, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=4 - alignbytes=8, usemymalloc=y, prototype=define - Linker and Libraries: - ld='ld', ldflags =' -Wl,+vnocompatwarnings -L/usr/local/lib -L/opt/gnu/lib' - libpth=/usr/local/lib /opt/gnu/lib /lib /usr/lib /usr/ccs/lib - libs=-lcl -lpthread -lnsl -lnm -lndbm -ldld -lm -lc -lndir -lcrypt -lsec - perllibs=-lcl -lpthread -lnsl -lnm -ldld -lm -lc -lndir -lcrypt -lsec - libc=/lib/libc.sl, so=sl, useshrplib=false, libperl=libperl.a - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred ' - cccdlflags='+z', lddlflags='-b +vnocompatwarnings -L/usr/local/lib -L/opt/gnu/lib' - - - Characteristics of this binary (from libperl): - Compile-time options: - Built under hpux - Compiled at Feb 26 2002 22:05:51 - %ENV: - PERL5LIB="/home/baxtlinc/local/lib:/home/baxtlinc/perl/lib" - @INC: - /home/baxtlinc/local/lib - /home/baxtlinc/perl/lib - /opt/perl/5.6.1-fccs-02/lib/5.6.1/PA-RISC2.0 - /opt/perl/5.6.1-fccs-02/lib/5.6.1 - /opt/perl/5.6.1-fccs-02/lib/site_perl/5.6.1/PA-RISC2.0 - /opt/perl/5.6.1-fccs-02/lib/site_perl/5.6.1 - /opt/perl/5.6.1-fccs-02/lib/site_perl diff --git a/README-files/hpux/Conf-Merijn-580-10.20-cc b/README-files/hpux/Conf-Merijn-580-10.20-cc deleted file mode 100644 index 618cf172..00000000 --- a/README-files/hpux/Conf-Merijn-580-10.20-cc +++ /dev/null @@ -1,46 +0,0 @@ -Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: - Platform: - osname=hpux, osvers=10.20, archname=PA-RISC2.0 - uname='hp-ux d3 b.10.20 u 9000800 2015358431 unlimited-user license ' - config_args='-des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=define d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=undef uselongdouble=undef - usemymalloc=n, bincompat5005=undef - Compiler: - cc='cc', ccflags =' -Ae -DDEBUGGING +DAportable -D_HPUX_SOURCE -Wl,+vnocompatwarnings -I/pro/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 ', - optimize='+O2 +Onolimit', - cppflags='-Aa -D__STDC_EXT__ -DDEBUGGING +DAportable -D_HPUX_SOURCE -Ae -DDEBUGGING +DAportable -D_HPUX_SOURCE -Wl,+vnocompatwarnings -I/pro/local/include' - ccversion='A.10.32.30', gccversion='', gccosandvers='' - intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 - alignbytes=8, prototype=define - Linker and Libraries: - ld='/usr/bin/ld', ldflags ='-L/pro/local/lib' - libpth=/pro/local/lib /lib /usr/lib /usr/ccs/lib - libs=-lcl -lpthread -lnsl_s -lndbm -lgdbm -ldb -lmalloc -ldld -lm -lc -lndir -lcrypt -lsec - perllibs=-lcl -lpthread -lnsl_s -lmalloc -ldld -lm -lc -lndir -lcrypt -lsec - libc=/lib/libc.sl, so=sl, useshrplib=false, libperl=libperl.a - gnulibc_version='' - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred ' - cccdlflags='+Z', lddlflags='-b +vnocompatwarnings -L/pro/local/lib' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING USE_LARGE_FILES - Locally applied patches: - // patches 17682, 17690, and 17777 - Built under hpux - Compiled at Aug 27 2002 12:28:36 - %ENV: - PERL5_CPANPLUS_CONFIG="/u/usr/merijn/.cpanplus/config" - @INC: - /pro/lib/perl5/5.8.0/PA-RISC2.0 - /pro/lib/perl5/5.8.0 - /pro/lib/perl5/site_perl/5.8.0/PA-RISC2.0 - /pro/lib/perl5/site_perl/5.8.0 - /pro/lib/perl5/site_perl - . diff --git a/README-files/hpux/Conf-Merijn-585-11.00-cc b/README-files/hpux/Conf-Merijn-585-11.00-cc deleted file mode 100644 index b54f7bed..00000000 --- a/README-files/hpux/Conf-Merijn-585-11.00-cc +++ /dev/null @@ -1,46 +0,0 @@ -Summary of my perl5 (revision 5 version 8 subversion 5) configuration: - Platform: - osname=hpux, osvers=11.00, archname=PA-RISC2.0 - uname='hp-ux a5 b.11.00 u 9000800 871940681 unlimited-user license ' - config_args='-des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=define d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=undef uselongdouble=undef - usemymalloc=n, bincompat5005=undef - Compiler: - cc='cc', ccflags =' -Ae -D_HPUX_SOURCE -Wl,+vnocompatwarnings -I/pro/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 ', - optimize='+O2 +Onolimit', - cppflags='-Aa -D__STDC_EXT__ -D_HPUX_SOURCE -Ae -D_HPUX_SOURCE -Wl,+vnocompatwarnings -I/pro/local/include' - ccversion='', gccversion='', gccosandvers='' - intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 - alignbytes=8, prototype=define - Linker and Libraries: - ld='/usr/bin/ld', ldflags ='-L/pro/local/lib' - libpth=/pro/local/lib /lib /usr/lib /usr/ccs/lib /usr/local/lib - libs=-lcl -lpthread -lnsl -lnm -lndbm -lgdbm -ldb -lmalloc -ldld -lm -lcrypt -lsec -lc - perllibs=-lcl -lpthread -lnsl -lnm -lmalloc -ldld -lm -lcrypt -lsec -lc - libc=/lib/libc.sl, so=sl, useshrplib=false, libperl=libperl.a - gnulibc_version='' - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred ' - cccdlflags='+Z', lddlflags='-b +vnocompatwarnings -L/pro/local/lib' - - -Characteristics of this binary (from libperl): - Compile-time options: USE_LARGE_FILES - Locally applied patches: - defined-or - Built under hpux - Compiled at Oct 18 2004 12:41:04 - %ENV: - PERL5_CPANPLUS_CONFIG="/u/usr/merijn/.cpanplus/config" - @INC: - /pro/lib/perl5/5.8.5/PA-RISC2.0 - /pro/lib/perl5/5.8.5 - /pro/lib/perl5/site_perl/5.8.5/PA-RISC2.0 - /pro/lib/perl5/site_perl/5.8.5 - /pro/lib/perl5/site_perl - . diff --git a/README-files/hpux/Conf-Merijn-585-11.11-cc b/README-files/hpux/Conf-Merijn-585-11.11-cc deleted file mode 100644 index c729eb46..00000000 --- a/README-files/hpux/Conf-Merijn-585-11.11-cc +++ /dev/null @@ -1,47 +0,0 @@ -Summary of my perl5 (revision 5 version 8 subversion 5 patch 23110) configuration: - Platform: - osname=hpux, osvers=11.11, archname=PA-RISC2.0-LP64 - uname='hp-ux r3 b.11.11 u 9000800 1909236376 unlimited-user license ' - config_args='-Dusedevel -Duse64bitall -des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=define d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=define use64bitall=define uselongdouble=undef - usemymalloc=n, bincompat5005=undef - Compiler: - cc='cc', ccflags =' -Ae -D_HPUX_SOURCE -Wl,+vnocompatwarnings +DD64 -I/pro/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 ', - optimize='+O2 +Onolimit', - cppflags='-Aa -D__STDC_EXT__ -D_HPUX_SOURCE -D_HPUX_SOURCE -Wl,+vnocompatwarnings +DD64 -I/pro/local/include' - ccversion='B.11.11.10', gccversion='', gccosandvers='' - intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=87654321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 - alignbytes=8, prototype=define - Linker and Libraries: - ld='/usr/bin/ld', ldflags ='+DD64 -L/lib/pa20_64 -L/usr/local/pa20_64/lib -L/pro/local/lib' - libpth=/pro/local/lib /lib/pa20_64 /lib /usr/lib /usr/ccs/lib /usr/local/lib - libs=-lcl -lpthread -lnsl -lnm -lgdbm -ldb -ldl -ldld -lm -lsec -lc - perllibs=-lcl -lpthread -lnsl -lnm -ldl -ldld -lm -lsec -lc - libc=/lib/pa20_64/libc.sl, so=sl, useshrplib=false, libperl=libperl.a - gnulibc_version='' - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred ' - cccdlflags='+Z', lddlflags='-b +vnocompatwarnings -L/lib/pa20_64 -L/usr/local/pa20_64/lib -L/pro/local/lib' - - -Characteristics of this binary (from libperl): - Compile-time options: USE_64_BIT_INT USE_64_BIT_ALL USE_LARGE_FILES - Locally applied patches: - MAINT23067 - defined-or - Built under hpux - Compiled at Jul 15 2004 17:42:08 - %ENV: - PERL5_CPANPLUS_CONFIG="/u/usr/merijn/.cpanplus/config" - @INC: - /pro/lib/perl5/5.8.5/PA-RISC2.0-LP64 - /pro/lib/perl5/5.8.5 - /pro/lib/perl5/site_perl/5.8.5/PA-RISC2.0-LP64 - /pro/lib/perl5/site_perl/5.8.5 - /pro/lib/perl5/site_perl - . diff --git a/README-files/hpux/Conf-Merijn-587-11.23-cc b/README-files/hpux/Conf-Merijn-587-11.23-cc deleted file mode 100644 index a30eba98..00000000 --- a/README-files/hpux/Conf-Merijn-587-11.23-cc +++ /dev/null @@ -1,54 +0,0 @@ -Summary of my perl5 (revision 5 version 8 subversion 7) configuration: - Platform: - osname=hpux, osvers=11.23, archname=IA64.ARCHREV_0-LP64 - uname='hp-ux x1 b.11.23 u ia64 3295073263 unlimited-user license ' - config_args='-Duse64bitall -des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=unde -f - useperlio=define d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=define use64bitall=define uselongdouble=undef - usemymalloc=n, bincompat5005=undef - Compiler: - cc='cc', ccflags =' -Ae -DDEBUGGING +Z -z -D_HPUX_SOURCE -Wl,+vnocompatwarni -ngs +DD64 -I/pro/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 ', - optimize='+O2 +Onolimit', - cppflags='-Aa -D__STDC_EXT__ -DDEBUGGING +Z -z -D_HPUX_SOURCE -Ae -DDEBUGGIN -G +Z -z -D_HPUX_SOURCE -Wl,+vnocompatwarnings +DD64 -I/pro/local/include' - ccversion='B3910B A.06.05', gccversion='', gccosandvers='' - intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=87654321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize -=8 - alignbytes=8, prototype=define - Linker and Libraries: - ld='/usr/bin/ld', ldflags ='-L/pro/local/lib +DD64 -L/usr/lib/hpux64' - libpth=/pro/local/lib /usr/lib/hpux64 /lib /usr/lib /usr/ccs/lib /usr/local/ -lib - libs=-lcl -lpthread -lnsl -lnm -ldb -ldl -ldld -lm -lsec -lc - perllibs=-lcl -lpthread -lnsl -lnm -ldl -ldld -lm -lsec -lc - libc=/usr/lib/hpux64/libc.so, so=so, useshrplib=false, libperl=libperl.a - gnulibc_version='' - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferr -ed ' - cccdlflags='+Z', lddlflags='-b +vnocompatwarnings -L/pro/local/lib -L/usr/li -b/hpux64' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING USE_64_BIT_INT USE_64_BIT_ALL - USE_LARGE_FILES - Locally applied patches: - defined-or - Built under hpux - Compiled at Jan 9 2006 22:10:18 - %ENV: - PERL5_CPANPLUS_CONFIG="/u/usr/merijn/.cpanplus/config" - @INC: - /pro/lib/perl5/5.8.7/IA64.ARCHREV_0-LP64 - /pro/lib/perl5/5.8.7 - /pro/lib/perl5/site_perl/5.8.7/IA64.ARCHREV_0-LP64 - /pro/lib/perl5/site_perl/5.8.7 - /pro/lib/perl5/site_perl - . diff --git a/README-files/hpux/Conf-Merijn-588-10.20-gcc b/README-files/hpux/Conf-Merijn-588-10.20-gcc deleted file mode 100644 index 9f1f699e..00000000 --- a/README-files/hpux/Conf-Merijn-588-10.20-gcc +++ /dev/null @@ -1,47 +0,0 @@ -Summary of my perl5 (revision 5 version 8 subversion 8 patch 27029) configuration: - Platform: - osname=hpux, osvers=10.20, archname=PA-RISC2.0 - uname='hp-ux d3 b.10.20 u 9000800 2015358431 unlimited-user license ' - config_args='-Dusedevel -Dcc=gcc -des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=define d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=undef uselongdouble=undef - usemymalloc=n, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-mpa-risc-1-1 -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/pro/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', - optimize='-g -O', - cppflags='-mpa-risc-1-1 -D_HPUX_SOURCE -mpa-risc-1-1 -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/pro/local/include' - ccversion='', gccversion='4.0.2', gccosandvers='' - intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 - alignbytes=8, prototype=define - Linker and Libraries: - ld='/usr/bin/ld', ldflags ='-L/pro/local/lib' - libpth=/pro/local/lib /lib /usr/lib /usr/ccs/lib /usr/local/lib - libs=-lcl -lpthread -lnsl_s -lndbm -lgdbm -ldb -lmalloc -ldld -lm -lcrypt -lsec -lc - perllibs=-lcl -lpthread -lnsl_s -lmalloc -ldld -lm -lcrypt -lsec -lc - libc=/lib/libc.sl, so=sl, useshrplib=false, libperl=libperl.a - gnulibc_version='' - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred ' - cccdlflags='-fPIC', lddlflags='-b -L/pro/local/lib' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING PERL_MALLOC_WRAP USE_LARGE_FILES - USE_PERLIO - Locally applied patches: - defined-or - Built under hpux - Compiled at Feb 1 2006 12:09:03 - %ENV: - PERL5_CPANPLUS_CONFIG="/u/usr/merijn/.cpanplus/config" - @INC: - /opt/perl/lib/5.8.8/PA-RISC2.0 - /opt/perl/lib/5.8.8 - /opt/perl/lib/site_perl/5.8.8/PA-RISC2.0 - /opt/perl/lib/site_perl/5.8.8 - /opt/perl/lib/site_perl - . diff --git a/README-files/hpux/Conf-Merijn-588-11.00-gcc32 b/README-files/hpux/Conf-Merijn-588-11.00-gcc32 deleted file mode 100644 index e6f4547e..00000000 --- a/README-files/hpux/Conf-Merijn-588-11.00-gcc32 +++ /dev/null @@ -1,47 +0,0 @@ -Summary of my perl5 (revision 5 version 8 subversion 8 patch 27029) configuration: - Platform: - osname=hpux, osvers=11.00, archname=PA-RISC2.0 - uname='hp-ux a5 b.11.00 u 9000800 871940681 unlimited-user license ' - config_args='-Dusedevel -Dcc=gcc -des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=define d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=undef uselongdouble=undef - usemymalloc=n, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-mpa-risc-2-0 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/pro/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', - optimize='-g -O', - cppflags='-mpa-risc-2-0 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -mpa-risc-2-0 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/pro/local/include' - ccversion='', gccversion='4.0.2', gccosandvers='' - intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 - alignbytes=8, prototype=define - Linker and Libraries: - ld='/usr/bin/ld', ldflags ='-L/pro/local/lib' - libpth=/pro/local/lib /lib /usr/lib /usr/ccs/lib /usr/local/lib - libs=-lcl -lpthread -lnsl -lnm -lndbm -lgdbm -ldb -lmalloc -ldld -lm -lcrypt -lsec -lc - perllibs=-lcl -lpthread -lnsl -lnm -lmalloc -ldld -lm -lcrypt -lsec -lc - libc=/lib/libc.sl, so=sl, useshrplib=false, libperl=libperl.a - gnulibc_version='' - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred ' - cccdlflags='-fPIC', lddlflags='-b -L/pro/local/lib' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP - USE_LARGE_FILES USE_PERLIO - Locally applied patches: - defined-or - Built under hpux - Compiled at Feb 1 2006 12:12:58 - %ENV: - PERL5_CPANPLUS_CONFIG="/u/usr/merijn/.cpanplus/config" - @INC: - /opt/perl/lib/5.8.8/PA-RISC2.0 - /opt/perl/lib/5.8.8 - /opt/perl/lib/site_perl/5.8.8/PA-RISC2.0 - /opt/perl/lib/site_perl/5.8.8 - /opt/perl/lib/site_perl - . diff --git a/README-files/hpux/Conf-Merijn-588-11.00-gcc64 b/README-files/hpux/Conf-Merijn-588-11.00-gcc64 deleted file mode 100644 index bde4197d..00000000 --- a/README-files/hpux/Conf-Merijn-588-11.00-gcc64 +++ /dev/null @@ -1,48 +0,0 @@ -Summary of my perl5 (revision 5 version 8 subversion 8 patch 27029) configuration: - Platform: - osname=hpux, osvers=11.00, archname=PA-RISC2.0-LP64 - uname='hp-ux a5 b.11.00 u 9000800 871940681 unlimited-user license ' - config_args='-Dusedevel -Dcc=gcc64 -Duse64bitall -des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=define d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=define use64bitall=define uselongdouble=undef - usemymalloc=n, bincompat5005=undef - Compiler: - cc='gcc64', ccflags ='-mpa-risc-2-0 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/pa20_64/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', - optimize='-g -O', - cppflags='-mpa-risc-2-0 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -mpa-risc-2-0 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/pa20_64/include' - ccversion='', gccversion='4.0.2', gccosandvers='' - intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=87654321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 - alignbytes=8, prototype=define - Linker and Libraries: - ld='/usr/bin/ld', ldflags =' -L/usr/local/pa20_64/lib -L/lib/pa20_64' - libpth=/usr/local/pa20_64/lib /lib/pa20_64 /lib /usr/lib /usr/ccs/lib /usr/local/lib - libs=-lcl -lpthread -lnsl -lnm -lgdbm -ldb -ldl -ldld -lm -lsec -lc - perllibs=-lcl -lpthread -lnsl -lnm -ldl -ldld -lm -lsec -lc - libc=/lib/pa20_64/libc.sl, so=sl, useshrplib=false, libperl=libperl.a - gnulibc_version='' - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E ' - cccdlflags='-fPIC', lddlflags='-b -L/usr/local/pa20_64/lib -L/lib/pa20_64' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP - USE_64_BIT_ALL USE_64_BIT_INT USE_LARGE_FILES - USE_PERLIO - Locally applied patches: - defined-or - Built under hpux - Compiled at Feb 1 2006 12:58:01 - %ENV: - PERL5_CPANPLUS_CONFIG="/u/usr/merijn/.cpanplus/config" - @INC: - /opt/perl64/lib/5.8.8/PA-RISC2.0-LP64 - /opt/perl64/lib/5.8.8 - /opt/perl64/lib/site_perl/5.8.8/PA-RISC2.0-LP64 - /opt/perl64/lib/site_perl/5.8.8 - /opt/perl64/lib/site_perl - . diff --git a/README-files/hpux/Conf-Merijn-588-11.11-gcc32 b/README-files/hpux/Conf-Merijn-588-11.11-gcc32 deleted file mode 100644 index aacc0eef..00000000 --- a/README-files/hpux/Conf-Merijn-588-11.11-gcc32 +++ /dev/null @@ -1,47 +0,0 @@ -Summary of my perl5 (revision 5 version 8 subversion 8 patch 27029) configuration: - Platform: - osname=hpux, osvers=11.11, archname=PA-RISC2.0 - uname='hp-ux r3 b.11.11 u 9000800 1909236376 unlimited-user license ' - config_args='-Dcc=gcc -des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=define d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=undef uselongdouble=undef - usemymalloc=n, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-mpa-risc-2-0 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/pro/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', - optimize='-g -O', - cppflags='-mpa-risc-2-0 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -mpa-risc-2-0 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/pro/local/include' - ccversion='', gccversion='3.4.5', gccosandvers='hpux11.11' - intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 - alignbytes=8, prototype=define - Linker and Libraries: - ld='/usr/bin/ld', ldflags =' -L/usr/local/lib' - libpth=/usr/local/lib /lib /usr/lib /usr/ccs/lib - libs=-lcl -lpthread -lnsl -lnm -lndbm -lgdbm -ldb -lmalloc -ldld -lm -lsec -lc - perllibs=-lcl -lpthread -lnsl -lnm -lmalloc -ldld -lm -lsec -lc - libc=/lib/libc.sl, so=sl, useshrplib=false, libperl=libperl.a - gnulibc_version='' - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred ' - cccdlflags='-fPIC', lddlflags='-b -L/usr/local/lib' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP - USE_LARGE_FILES USE_PERLIO - Locally applied patches: - defined-or - Built under hpux - Compiled at Feb 1 2006 12:07:21 - %ENV: - PERL5_CPANPLUS_CONFIG="/u/usr/merijn/.cpanplus/config" - @INC: - /opt/perl/lib/5.8.8/PA-RISC2.0 - /opt/perl/lib/5.8.8 - /opt/perl/lib/site_perl/5.8.8/PA-RISC2.0 - /opt/perl/lib/site_perl/5.8.8 - /opt/perl/lib/site_perl - . diff --git a/README-files/hpux/Conf-Merijn-588-11.11-gcc64 b/README-files/hpux/Conf-Merijn-588-11.11-gcc64 deleted file mode 100644 index f2637e28..00000000 --- a/README-files/hpux/Conf-Merijn-588-11.11-gcc64 +++ /dev/null @@ -1,48 +0,0 @@ -Summary of my perl5 (revision 5 version 8 subversion 8 patch 27029) configuration: - Platform: - osname=hpux, osvers=11.11, archname=PA-RISC2.0-LP64 - uname='hp-ux r3 b.11.11 u 9000800 1909236376 unlimited-user license ' - config_args='-Dusedevel -Dcc=gcc -Duse64bitall -des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=define d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=define use64bitall=define uselongdouble=undef - usemymalloc=n, bincompat5005=undef - Compiler: - cc='gcc64', ccflags ='-mpa-risc-2-0 -DDEBUGGING -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/pa20_64/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', - optimize='-g -O', - cppflags='-mpa-risc-2-0 -DDEBUGGING -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -mpa-risc-2-0 -DDEBUGGING -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/pa20_64/include' - ccversion='', gccversion='3.4.5', gccosandvers='hpux11.11' - intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=87654321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 - alignbytes=8, prototype=define - Linker and Libraries: - ld='/usr/bin/ld', ldflags =' -L/usr/local/pa20_64/lib -L/lib/pa20_64' - libpth=/usr/local/pa20_64/lib /lib/pa20_64 /lib /usr/lib /usr/ccs/lib /usr/local/lib - libs=-lcl -lpthread -lnsl -lnm -lgdbm -ldb -ldl -ldld -lm -lsec -lc - perllibs=-lcl -lpthread -lnsl -lnm -ldl -ldld -lm -lsec -lc - libc=/lib/pa20_64/libc.sl, so=sl, useshrplib=false, libperl=libperl.a - gnulibc_version='' - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E ' - cccdlflags='-fPIC', lddlflags='-b -L/usr/local/pa20_64/lib -L/lib/pa20_64' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP - USE_64_BIT_ALL USE_64_BIT_INT USE_LARGE_FILES - USE_PERLIO - Locally applied patches: - defined-or - Built under hpux - Compiled at Feb 1 2006 11:39:40 - %ENV: - PERL5_CPANPLUS_CONFIG="/u/usr/merijn/.cpanplus/config" - @INC: - /opt/perl64/lib/5.8.8/PA-RISC2.0-LP64 - /opt/perl64/lib/5.8.8 - /opt/perl64/lib/site_perl/5.8.8/PA-RISC2.0-LP64 - /opt/perl64/lib/site_perl/5.8.8 - /opt/perl64/lib/site_perl - . diff --git a/README-files/hpux/Conf-Merijn-588-11.23-gcc64 b/README-files/hpux/Conf-Merijn-588-11.23-gcc64 deleted file mode 100644 index 89950ad5..00000000 --- a/README-files/hpux/Conf-Merijn-588-11.23-gcc64 +++ /dev/null @@ -1,48 +0,0 @@ -Summary of my perl5 (revision 5 version 8 subversion 8 patch 27029) configuration: - Platform: - osname=hpux, osvers=11.23, archname=IA64.ARCHREV_0-LP64 - uname='hp-ux x1 b.11.23 u ia64 3295073263 unlimited-user license ' - config_args='-Dusedevel -Duse64bitint -Dcc=gcc -des' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=define d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=define use64bitall=define uselongdouble=undef - usemymalloc=n, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-mlp64 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/pro/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', - optimize='-g -O', - cppflags='-mlp64 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -mlp64 -DPERL_DONT_CREATE_GVSV -D_HPUX_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/pro/local/include' - ccversion='', gccversion='4.0.2', gccosandvers='' - intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=87654321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 - alignbytes=8, prototype=define - Linker and Libraries: - ld='/usr/bin/ld', ldflags ='-mlp64 -L/pro/local/lib -L/usr/lib/hpux64' - libpth=/usr/lib/hpux64 /lib /usr/lib /usr/ccs/lib /usr/local/lib - libs=-lcl -lpthread -lnsl -lnm -ldl -ldld -lm -lsec -lc - perllibs=-lcl -lpthread -lnsl -lnm -ldl -ldld -lm -lsec -lc - libc=/usr/lib/hpux64/libc.so, so=so, useshrplib=false, libperl=libperl.a - gnulibc_version='' - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred ' - cccdlflags='-fPIC', lddlflags='-b -L/pro/local/lib -L/usr/lib/hpux64' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP - USE_64_BIT_ALL USE_64_BIT_INT USE_LARGE_FILES - USE_PERLIO - Locally applied patches: - defined-or - Built under hpux - Compiled at Feb 1 2006 12:12:55 - %ENV: - PERL5_CPANPLUS_CONFIG="/u/usr/merijn/.cpanplus/config" - @INC: - /opt/perl64/lib/5.8.8/IA64.ARCHREV_0-LP64 - /opt/perl64/lib/5.8.8 - /opt/perl64/lib/site_perl/5.8.8/IA64.ARCHREV_0-LP64 - /opt/perl64/lib/site_perl/5.8.8 - /opt/perl64/lib/site_perl - . diff --git a/README-files/hpux/Conf-Mike b/README-files/hpux/Conf-Mike deleted file mode 100644 index dac5da5c..00000000 --- a/README-files/hpux/Conf-Mike +++ /dev/null @@ -1,39 +0,0 @@ - Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration: - Platform: - osname=hpux, osvers=11.00, archname=PA-RISC1.1 - uname='hp-ux SYSTEMNAME b.11.00 a 9000800 2002134832 two-user license ' - config_args='-Ubincompat5005 -Dcc=gcc -Duselargefiles' - hint=previous, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=undef uselongdouble=undef - Compiler: - cc='gcc', ccflags ='-D_HPUX_SOURCE -L/lib/pa1.1 -DUINT32_MAX_BROKEN -fno-strict-aliasing -I/usr/local/include -fPIC', - optimize='-O', - cppflags='-D_HPUX_SOURCE -L/lib/pa1.1 -DUINT32_MAX_BROKEN -fno-strict-aliasing -I/usr/local/include -fPIC' - ccversion='', gccversion='3.0.4', gccosandvers='hpux11.00' - intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=4 - alignbytes=8, usemymalloc=y, prototype=define - Linker and Libraries: - ld='ld', ldflags =' -L/usr/local/lib' - libpth=/usr/local/lib /lib /usr/lib /usr/ccs/lib - libs=-lcl -lpthread -lnsl -lnm -lndbm -lgdbm -ldld -lm -lc -lndir -lcrypt -lsec - perllibs=-lcl -lpthread -lnsl -lnm -ldld -lm -lc -lndir -lcrypt -lsec - libc=, so=sl, useshrplib=false, libperl=libperl.a - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred ' - cccdlflags='-fPIC', lddlflags='-b -L/usr/local/lib' - - Characteristics of this binary (from libperl): - Compile-time options: USE_LARGE_FILES - Built under hpux - Compiled at Jul 18 2002 15:28:03 - @INC: - /usr/local/lib/perl5/5.6.1/PA-RISC1.1 - /usr/local/lib/perl5/5.6.1 - /usr/local/lib/perl5/site_perl/5.6.1/PA-RISC1.1 - /usr/local/lib/perl5/site_perl/5.6.1 - /usr/local/lib/perl5/site_perl - . diff --git a/README-files/hpux/Conf-Roger b/README-files/hpux/Conf-Roger deleted file mode 100644 index c6fe9f71..00000000 --- a/README-files/hpux/Conf-Roger +++ /dev/null @@ -1,40 +0,0 @@ - Platform: - osname=hpux, osvers=11.00, archname=PA-RISC2.0 - uname='hp-ux titan b.11.00 u 9000800 103901567 unlimited-user license ' - config_args='-Ubincompat5005' - hint=recommended, useposix=true, d_sigaction=define - usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef - useperlio=undef d_sfio=undef uselargefiles=define - use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef - Compiler: - cc='cc', optimize='-O', gccversion= - cppflags='-D_HP-UX_SOURCE -Aa -I/usr/local/include' - ccflags =' +z -D_HP-UX_SOURCE -I/usr/local/include -D_LARGEFILE_SOURCE - -D_FILE_OFFSET_BITS=64 -Ae ' - stdchar='unsigned char', d_stdstdio=define, usevfork=false - intsize=4, longsize=4, ptrsize=4, doublesize=8 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', - lseeksize=8 - alignbytes=8, usemymalloc=y, prototype=define - Linker and Libraries: - ld='ld', ldflags =' -L/usr/local/lib' - libpth=/usr/local/lib /lib /usr/lib /usr/ccs/lib - libs=-lnsl -lnm -lndbm -lgdbm -ldld -lm -lc -lndir -lcrypt -lsec -lcl - -lpthread - libc=/lib/libc.sl, so=sl, useshrplib=false, libperl=libperl.a - Dynamic Linking: - dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags=' ' - cccdlflags='+z', lddlflags=' -b +vnocompatwarnings -L/usr/local/lib' - - Characteristics of this binary (from libperl): - Compile-time options: USE_LARGE_FILES - Built under hpux - Compiled at Dec 19 2000 19:17:00 - @INC: - /opt/www/perl5/lib/5.6.0/PA-RISC2.0 - /opt/www/perl5/lib/5.6.0 - /opt/www/perl5/lib/site_perl/5.6.0/PA-RISC2.0 - /opt/www/perl5/lib/site_perl/5.6.0 - /opt/www/perl5/lib/site_perl - . diff --git a/README-files/hpux/libjava.eml b/README-files/hpux/libjava.eml deleted file mode 100644 index 89e7524e..00000000 --- a/README-files/hpux/libjava.eml +++ /dev/null @@ -1,117 +0,0 @@ - -----Original Message----- - From: Stevenson, Jonathan [mailto:Jonathan.Stevenson@infores.com.Fix.This] - Sent: Wednesday, March 27, 2002 6:31 AM - To: LBaxter@FLEETCC.COM.Fix.This - Cc: dbi_users@perl.org - Subject: RE: Error on make for DBD-Oracle 1.12 on HP-UX 11.0 - - Hi Lincoln, - - Thanks for your help with this. We now have a working installation, - although we still do have some issues to resolve still. The problem - seems to be the libjava.sl library. Running the make test step - generated this message: Can't shl_load() a library containing Thread - Local Storage. - - We have got round this by setting the LD_PRELOAD to point to the - library - $ORACLE_HOME/JRE/lib/PA_RISC/native_threads/libjava.sl. The - make test passes OK, and make install works. My DBI test script is - able to do some basic stuff, so presumably it is OK. - - There are some problems remaining with it, though. You have to - set the LD_PRELOAD variable before running any perl against Oracle - (as I guess the library does not get built into the DBD). We have - also noticed that if you set LD_PRELOAD as above, then run swlist, - the system coredumps (swlist works normally without this set). - - This worries me, as it may cause other commands to coredump, so we - will need to try to extensively roadtest this before we can move - into production. - - The libjava.sl library is only required for an advanced authentication - module that we do not use, so we are hoping that we can remove this - from our Oracle installation, and get around the problem this way. - - We did manage to install DBD on one of our boxes before Xmas without - this problem, so we know that it can be done, we have just lost the - recipe that we need. If anyone has any suggestions that we could try, - we would be grateful. It is also worth noting that this error was what - hung us up trying to get gcc to work, so with this option, we may be - able to push forward on this. We will give it a go on another box, - and post if we get any joy from this. - - I have included the recipe that we have used below. This does produce - a working build, we are just a little concerned about the side effects. - - Cheers, - - Jon - - - Machine specs: - - HP-UX 11.00 - Oracle 8.1.6 client - HP ANSI C compiler (B.11.02.03) - - - Downloaded: - - Perl 5.6.1 From http://www.cpan.org/src/index.html - (Stable release) - - DBI 1.21 From http://search.cpan.org/search?dist=DBI - - DBD:Oracle 1.12 From http://search.cpan.org/search?module=DBD::Oracle - - - Create /tmp/perl temporary area and extract tar files - - cd /tmp/perl/perl-5.6.1 - ../Configure -Ubincompat5005 - #Prepend additional libraries with "-lcl -lpthread" - #Prepend cc flags with "+z" - - make - make test - make install - - Install DBI - - cd /tmp/perl/DBI-1.21 - perl Makefile.PL - make - make test - make install - - - Install DBD:Oracle - - #Set the Oracle environment - export ORACLE_HOME=/oracle/app/oracle/product/8.1.6 - export SHLIB_PATH=/usr/lib:/oracle/app/oracle/product/8.1.6/lib - export ORACLE_SID=sid - export ORACLE_USERID=userid/password@sid - export LD_LIBRARY_PATH=/oracle/app/oracle/product/8.1.6/lib - - export LD_PRELOAD=/oracle/app/oracle/product/8.1.6/JRE/lib/PA_RISC/native_threads/libjava.sl - # Need to prevent libjava.sl TLS error - need to do this for runtime as well - - cd /tmp/perl/DBD-Oracle-1.12 - perl Makefile.PL - - cat Makefile | sed 's/PERL_DL_NONLAZY=1/PERL_DL_NONLAZY=0/g' > Makefile.tmp - # Need to force load of all libraries - mv Makefile.tmp Makefile - make - make test - make install - - Apparently Oracle stored the 64 bit libraries in .../lib & .../rdbms/lib. - 32 bit libraries are available in .../lib32 and .../rdbms/lib32. I'm forced - to stay with Perl 32bit & the workaround is to manually edit the resulting - Makefile. Anyone have a patch to detect & correct this situation? - - John Schaefer - - BAESystems, San Diego diff --git a/README.explain.txt b/README.explain.txt deleted file mode 100644 index 7af116a6..00000000 --- a/README.explain.txt +++ /dev/null @@ -1,191 +0,0 @@ -explain -======= - -DISCLAIMER & COPYRIGHT ----------------------- - -Copyright (c) 1998 Alan Burlison - -You may distribute under the terms of either the GNU General Public License -or the Artistic License, as specified in the Perl README file. - -This code is provided with no warranty of any kind, and is used entirely at -your own risk. - -This code was written by the author as a private individual, and is in no way -endorsed or warrantied by Sun Microsystems. - -WHAT IS IT? ------------ -explain is a GUI-based tool that enables easier visualisation of Oracle Query -plans. A query plan is the access path that Oracle will use to satisfy a SQL -query. The Oracle query optimiser is responsible for deciding on the optimal -path to use. Needless to say, understanding such plans requires a fairly -sophisticated knowledge of Oracle architecture and internals. - -explain allows a user to interactively edit a SQL statemant and view the -resulting query plan with the click of a single button. The effects of -modifying the SQL or of adding hints can be rapidly established. - -explain allows the user to grab all the SQL currently cached by Oracle. The SQL -capture can be filtered and sorted by different criterea, e.g. all SQL matching -a pattern, order by number of executions etc. - -explain is written using Perl, DBI/DBD::Oracle and Tk. - -PREREQUISITES -------------- -1. Oracle 7 or Oracle 8, with SQL*Net if appropriate -2. Perl 5.004_04 or later -3. DBI version 0.93 or later -4. DBD::Oracle 0.49 or later -5. Tk 800.005 or later -6. Tk-Tree 3.00401 or later - -Items 2 through 6 can be obtained from any CPAN mirror. - -INSTALLATION ------------- -1. Check you have all the prequisites installed and working. -2. Check the #! line in the script points to where your Perl interpreter is - installed. -3. Copy the "explain" script to somewhere on your path. -4. Make sure the "explain" script is executable. -5. Make sure you have run the script $ORACLE_HOME/rdbms/admin/utlxplan.sql - from a SQL*Plus session. This script creates the PLAN_TABLE that is used - by Oracle when explaining query plans. - -HOW TO USE ----------- - -Type "explain" at the shell prompt. A window will appear with a menu bar and -three frames, labelled "Query Plan", "Query Step Details" and "SQL Editor". At -the bottom of the window is a single button labelled "Explain". A login dialog -will also appear, into which you should enter the database username, password -and database instance name (SID). The parameters you enter are passed to the -DBI->connect() method, so if you have any problems refer to the DBI and -DBD::Oracle documentation. - -Optionally you may supply up to two command-line arguments. If the first -argument is of the form username/password@database, explain will use this to -log in to Oracle, otherwise if it is a filename it will be loaded into the SQL -editor. If two arguments are supplied, the second one will be assumed to be a -filename. - -Examples: - explain scott/tiger@DB query.sql - explain / query.sql (assumes OPS$ user authentication) - explain query.sql - - -Explain functionality ---------------------- - -The menu bar has one pulldown menu, "File", which allows you to login to Oracle, -Grab the contents of the Oracle SQL cache, Load SLQ from files, Save SQL to -files and to Exit the program. - -The "SQL Editor" frame allows the editing of a SQL statement. This should be -just a single statement - multiple statements are not allowed. Refer to the -documentation for the Tk text widget for a description of the editing keys -available. Text may be loaded and saved by using the "File" pulldown menu. - -Once you have entered a SQL statement, the "Explain" button at the bottom of -the window will generate the query plan for the statement. A tree -representation of the plan will appear in the "Query Plan" frame. Individual -"legs" of the plan may be expanded and collapsed by clicking on the "+' and "-" -boxes on the plan tree. The tree is drawn so that the "innermost" or "first" -query steps are indented most deeply. The connecting lines show the -"parent-child" relationships between the query steps. For a comprehensive -explanation of the meaning of query plans you should refer to the relevant -Oracle documentation. - -Single-clicking on a plan step in the Query Plan pane will display more -detailed information on that query step in the Query Step Details frame. This -information includes Oracle's estimates of cost, cardinality and bytes -returned. The exact information displayed depends on the Oracle version. -Again, for detailed information on the meaning of these fields, refer to the -Oracle documentation. - -Double-clicking on a plan step that refers to either a table or an index will -pop up a dialog box showing the definitiaon of the table or index in a format -similar to that of the SQL*Plus 'desc' command. - -Grab functionality ------------------ - -The explain window has an option on the "File" menu labelled "Grab SQL ...". -Selecting this will popup a new top-level window containing a menu bar and -three frames, labelled "SQL Cache", "SQL Statement Statistics" and "SQL -Selection Criterea". At the bottom of the window is a single button labelled -"Grab". - -The menu bar has one pulldown menu, "File", which allows you to Save the -contents of the SQL Cache frame and Close the Grab window. - -The "SQL Cache" frame shows the statements currently in the Oracle SQL cache. -Text may be saved by using the "File" pulldown menu. - -The "SQL Selection Criterea" frame allows you to specify which SQL statements -you are interested in, and how you want them sorted. The pattern used to select -statements is a normal perl regexp. Once you have defined the selection -criterea, clicking the "Grab" button will read all the matching statements from -the SQL cache and display them in the top frame. - -Single-clicking on a statement in the SQL Cache pane will display more -detailed information on that statement in the Sql Statement Statistics frame, -including the number of times the statement has been executed and the numbers -of rows processed by the statement. - -Double-clicking on a statement will copy it into the SQL editor in the Explain -window, so that the query plan for the statement can be examined. - -SUPPORT -------- - -Support questions and suggestions can be directed to Alan.Burlison@uk.sun.com - - -CHANGES -======= - -Version 0.51 beta 09/08/98 ---------------------------- - -Integrated into DBD::Oracle release 0.54. - -Version 0.5 beta 02/06/98 --------------------------- -Changes made to work with Tk800.005. -Fixed bug with grab due to Oracle's inconsistent storage of the hash_value -column in v$sqlarea and v$sqltext_with_newlines. -Disallowed multiple concurrent login/save/open dialogs. -Fixed double-posting of login dialog on startup. -Tried to make it less Oracle version dependent. - -Version 0.4 beta 27/02/98 --------------------------- -Grab functionality added, to allow interrogation of Oracle's SQL cache -Bind variables used wherever possible to prevent unnecessary reparses of the -SQL generated by explain -Extra error checking -Various code cleanups & restructuring -More extensive commenting of the source - -Version 0.3 beta 19/02/98 --------------------------- -Changed to use new Tk FileSelect instead of older FileDialog. -Added facility to supply user/pass@database & SQL filename on the command-line. -Thanks to Eric Zylberstejn for the patch + suggestions. -Added check on login to Oracle for a PLAN_TABLE in the user's schema. - -Version 0.2 beta 05/02/98 --------------------------- -Changed to work with both Oracle 7 and 8 statistics. -Pop-up table & index description dialogs added. -First public version. - -Version 0.1 beta 27/01/98 --------------------------- -Initial version. -Not publically released. diff --git a/Oracle.ex/README b/examples/README similarity index 100% rename from Oracle.ex/README rename to examples/README diff --git a/Oracle.ex/bind.pl b/examples/bind.pl similarity index 100% rename from Oracle.ex/bind.pl rename to examples/bind.pl diff --git a/Oracle.ex/commit.pl b/examples/commit.pl similarity index 100% rename from Oracle.ex/commit.pl rename to examples/commit.pl diff --git a/Oracle.ex/curref.pl b/examples/curref.pl similarity index 100% rename from Oracle.ex/curref.pl rename to examples/curref.pl diff --git a/Oracle.ex/ex.pl b/examples/ex.pl similarity index 100% rename from Oracle.ex/ex.pl rename to examples/ex.pl diff --git a/Oracle.ex/japh b/examples/japh similarity index 100% rename from Oracle.ex/japh rename to examples/japh diff --git a/Oracle.ex/mktable.pl b/examples/mktable.pl similarity index 100% rename from Oracle.ex/mktable.pl rename to examples/mktable.pl diff --git a/ora_explain.PL b/examples/ora_explain.pl similarity index 98% rename from ora_explain.PL rename to examples/ora_explain.pl index b79e5eca..b260438a 100644 --- a/ora_explain.PL +++ b/examples/ora_explain.pl @@ -1,9 +1,4 @@ -# -*- perl -*- - -use strict; - -my $script = <<'SCRIPT'; -~startperl~ -w +#!/usr/bin/env perl ################################################################################ # Copyright (c) 1999 Alan Burlison @@ -22,6 +17,8 @@ ################################################################################ use strict; +use warnings; + use File::Basename; use DBI; use Tk; @@ -1417,7 +1414,7 @@ sub grab_main -columnspan => 2, -padx => 6, -pady => 6); $frame1->pack(-fill => "x"); &$ord_bn_cb(); # Set the buttons to the initial state -$frame->pack(-fill => "x", ipadx => 6, -ipady => 6); +$frame->pack(-fill => "x", -padx => 6, -pady => 6); ### Buttons $frame = $GrabMain->Frame(-borderwidth => 3, -relief => "raised"); @@ -1573,14 +1570,11 @@ sub grab_main =head1 NAME -explain, ora_explain - deprecated (Will be removed from DBD::Oracle in 1.29) Visualise Oracle query plans +ora_explain.pl - Visualise Oracle query plans =head1 SYNOPSIS - $ explain [ [ user/password@database ] sql script ] - $ ora_explain [ [ user/password@database ] sql script ] - -B When bundled with DBD::Oracle, the script is called ora_explain + $ ora_explain.pl [ [ user/password@database ] sql script ] =head1 DESCRIPTION @@ -1632,29 +1626,9 @@ =head1 PREREQUISITES Items 2 through 6 can be obtained from any CPAN mirror. -=head1 INSTALLATION - -=over 2 - -=item 1. - -Check you have all the prequisites installed and working. - -=item 2. - -Run 'perl Makefile.PL; make instal1' - -=item 3. - -Make sure you have run the script $ORACLE_HOME/rdbms/admin/utlxplan.sql -from a SQL*Plus session. This script creates the PLAN_TABLE that is used -by Oracle when explaining query plans. - -=back - =head1 HOW TO USE -Type "explain" or "ora_explain" at the shell prompt. A window will appear with +Type "ora_explain.pl" at the shell prompt. A window will appear with a menu bar and three frames, labelled "Query Plan", "Query Step Details" and "SQL Editor". At the bottom of the window are three buttons labelled "Explain", "Clear" and "SQL Cache". A login dialog will also appear, into @@ -1789,18 +1763,3 @@ =head1 COPYRIGHT AND DISCLAIMER endorsed or warrantied by Sun Microsystems. =cut -SCRIPT - -use Config; - -my $file = __FILE__; $file =~ s/\.PL$//; - -$script =~ s/\~(\w+)\~/$Config{$1}/eg; -if (!(open(FILE, ">$file")) || - !(print FILE $script) || - !(close(FILE))) { - die "Error while writing $file: $!\n"; -} -print "Extracted $file from ",__FILE__," with variable substitutions.\n"; - -# End. diff --git a/Oracle.ex/oradump.pl b/examples/oradump.pl similarity index 100% rename from Oracle.ex/oradump.pl rename to examples/oradump.pl diff --git a/Oracle.ex/proc.pl b/examples/proc.pl similarity index 100% rename from Oracle.ex/proc.pl rename to examples/proc.pl diff --git a/Oracle.ex/sql b/examples/sql similarity index 100% rename from Oracle.ex/sql rename to examples/sql diff --git a/Oracle.ex/tabinfo.pl b/examples/tabinfo.pl similarity index 100% rename from Oracle.ex/tabinfo.pl rename to examples/tabinfo.pl diff --git a/t/21nchar.t b/t/21nchar.t index 96d4187e..70faf494 100644 --- a/t/21nchar.t +++ b/t/21nchar.t @@ -20,8 +20,8 @@ SKIP: { # $dbh->{PrintError} = 1; plan skip_all => "Unable to connect to Oracle" if not $dbh; - diag("testing control and 8 bit chars:\n") ; - diag(" Database and client versions and character sets:\n"); + note("testing control and 8 bit chars:\n") ; + note(" Database and client versions and character sets:\n"); show_db_charsets( $dbh); plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" diff --git a/t/30long.t b/t/30long.t index db3cc20f..1ad52565 100644 --- a/t/30long.t +++ b/t/30long.t @@ -56,13 +56,13 @@ if ($dbh) { } my $ora_server_version = $dbh->func("ora_server_version"); -diag("ora_server_version: @$ora_server_version\n"); +note("ora_server_version: @$ora_server_version\n"); show_db_charsets($dbh) if $dbh; foreach (@test_sets) { my ($type_name, $type_num, $test_no_type) = @$_; $use_utf8_data = use_utf8_data($dbh,$type_name); - diag( qq( + note( qq( ========================================================================= Running long test for $type_name ($type_num) use_utf8_data=$use_utf8_data )); @@ -111,7 +111,7 @@ sub run_long_tests my $utf_x = "0\x{263A}xyX"; #lab: the ubiquitous smiley face $long_data[0] = ($utf_x x 2048) x (1 ); # 10KB < 64KB if (length($long_data[0]) > 10240) { - diag "known bug in perl5.6.0 utf8 support, applying workaround\n"; + note "known bug in perl5.6.0 utf8 support, applying workaround\n"; my $utf_z = "0\x{263A}xyZ" ; $long_data[0] = $utf_z; $long_data[0] .= $utf_z foreach (1..2047); @@ -151,11 +151,11 @@ sub run_long_tests if (!create_table($dbh, $tdata, 1)); # typically OCI 8 client talking to Oracle 7 database - diag("long_data[0] length $len_data0\n"); - diag("long_data[1] length $len_data1\n"); - diag("long_data[2] length $len_data2\n"); + note("long_data[0] length $len_data0\n"); + note("long_data[1] length $len_data1\n"); + note("long_data[2] length $len_data2\n"); - diag(" --- insert some $type_name data (ora_type $type_num)\n"); + note(" --- insert some $type_name data (ora_type $type_num)\n"); my $sqlstr = "insert into $table values (?, ?, SYSDATE)" ; ok( $sth = $dbh->prepare( $sqlstr ), "prepare: $sqlstr" ); my $bind_attr = { ora_type => $type_num }; @@ -172,10 +172,10 @@ sub run_long_tests array_test($dbh); - diag(" --- fetch $type_name data back again -- truncated - LongTruncOk == 1\n"); + note(" --- fetch $type_name data back again -- truncated - LongTruncOk == 1\n"); $dbh->{LongReadLen} = 20; $dbh->{LongTruncOk} = 1; - diag("LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"); + note("LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"); # This behaviour isn't specified anywhere, sigh: my $out_len = $dbh->{LongReadLen}; @@ -212,12 +212,12 @@ sub run_long_tests ok(!defined $tmp->[3][1], "last row undefined"); # NULL # known bug in DBD::Oracle <= 1.13 } - diag(" --- fetch $type_name data back again -- truncated - LongTruncOk == 0\n"); + note(" --- fetch $type_name data back again -- truncated - LongTruncOk == 0\n"); $dbh->{LongReadLen} = $len_data1 - 10; # so $long_data[0] fits but long_data[1] doesn't $dbh->{LongReadLen} = $dbh->{LongReadLen} / 2 if $type_name =~ /RAW/i; my $LongReadLen = $dbh->{LongReadLen}; $dbh->{LongTruncOk} = 0; - diag("LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"); + note("LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"); $sqlstr = "select * from $table order by idx"; ok($sth = $dbh->prepare($sqlstr), "prepare $sqlstr" ); @@ -235,10 +235,10 @@ sub run_long_tests } $sth->finish; - diag(" --- fetch $type_name data back again -- complete - LongTruncOk == 0\n"); + note(" --- fetch $type_name data back again -- complete - LongTruncOk == 0\n"); $dbh->{LongReadLen} = $len_data1 +1000; $dbh->{LongTruncOk} = 0; - diag("LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"); + note("LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"); $sqlstr = "select * from $table order by idx"; ok($sth = $dbh->prepare($sqlstr), "prepare: $sqlstr" ); @@ -257,7 +257,7 @@ sub run_long_tests if ($type_name =~ /LONG/i) ; #$dbh->trace(4); - diag(" --- fetch $type_name data back again -- via blob_read\n\n"); + note(" --- fetch $type_name data back again -- via blob_read\n\n"); $dbh->{LongReadLen} = 1024 * 90; $dbh->{LongTruncOk} = 1; @@ -266,11 +266,11 @@ sub run_long_tests ok($sth->execute, "execute $sqlstr" ); - diag("fetch via fetchrow_arrayref\n"); + note("fetch via fetchrow_arrayref\n"); ok($tmp = $sth->fetchrow_arrayref, "fetchrow_arrayref 1: $sqlstr" ); cmp_ok_byte_nice($tmp->[1], $long_data[0], "truncated to LongReadLen $out_len"); - diag("read via blob_read_all\n"); + note("read via blob_read_all\n"); cmp_ok(blob_read_all($sth, 1, \$p1, 4096) ,'==', length($long_data[0]), "blob_read_all = length(\$long_data[0])" ); ok($p1 eq $long_data[0], cdif($p1, $long_data[0]) ); @@ -289,7 +289,7 @@ sub run_long_tests cmp_ok($len,'==', length($long_data[2]), "length of long_data[2] = $len" ); cmp_ok_byte_nice($p1, $long_data[2], "3rd row via blob_read_all"); - diag("result is ".(utf8::is_utf8($p1) ? "UTF8" : "non-UTF8")."\n"); + note("result is ".(utf8::is_utf8($p1) ? "UTF8" : "non-UTF8")."\n"); if ($be_utf8) { ok( utf8::is_utf8($p1), "result should be utf8"); } @@ -303,7 +303,7 @@ sub run_long_tests skip( "ora_auto_lob tests for $type_name" ."s - not supported", 7+(13*3) ) if not ( $type_name =~ /LOB/i ); - diag(" --- testing ora_auto_lob to access $type_name LobLocator\n\n"); + note(" --- testing ora_auto_lob to access $type_name LobLocator\n\n"); my $data_fmt = "%03d foo!"; $sqlstr = qq{ @@ -315,7 +315,7 @@ sub run_long_tests ok($ll_sth->execute ,"execute $sqlstr" ); while (my ($lob_locator, $idx) = $ll_sth->fetchrow_array) { - diag("$idx: ".DBI::neat($lob_locator)."\n"); + note("$idx: ".DBI::neat($lob_locator)."\n"); last if !defined($lob_locator) && $idx == 43; ok($lob_locator, '$lob_locator is true' ); @@ -327,22 +327,22 @@ sub run_long_tests ok(!$DBI::err, "DBI::errstr"); my $data = sprintf $data_fmt, $idx; #create a little data - diag("length of data to be written at offset 1: " .length($data) ."\n" ); + note("length of data to be written at offset 1: " .length($data) ."\n" ); ok($dbh->func($lob_locator, 1, $data, 'ora_lob_write') ,"ora_lob_write" ); } is($ll_sth->rows, 4); - diag(" --- round again to check contents after $type_name write updates...\n"); + note(" --- round again to check contents after $type_name write updates...\n"); ok($ll_sth->execute,"execute (again 1) $sqlstr" ); while (my ($lob_locator, $idx) = $ll_sth->fetchrow_array) { - diag("$idx locator: ".DBI::neat($lob_locator)."\n"); + note("$idx locator: ".DBI::neat($lob_locator)."\n"); next if !defined($lob_locator) && $idx == 43; diag("DBI::errstr=$DBI::errstr\n") if $DBI::err ; my $content = $dbh->func($lob_locator, 1, 20, 'ora_lob_read'); diag("DBI::errstr=$DBI::errstr\n") if $DBI::err ; ok($content,"content is true" ); - diag("$idx content: ".nice_string($content)."\n"); #.DBI::neat($content)."\n"; + note("$idx content: ".nice_string($content)."\n"); #.DBI::neat($content)."\n"; cmp_ok(length($content) ,'==', 20 ,"lenth(content)" ); # but prefix has been overwritten: @@ -374,10 +374,10 @@ sub run_long_tests } #while fetchrow is($ll_sth->rows, 4); - diag(" --- round again to check the $type_name length...\n"); + note(" --- round again to check the $type_name length...\n"); ok($ll_sth->execute ,"execute (again 2) $sqlstr" ); while (my ($lob_locator, $idx) = $ll_sth->fetchrow_array) { - diag("$idx locator: ".DBI::neat($lob_locator)."\n"); + note("$idx locator: ".DBI::neat($lob_locator)."\n"); next if !defined($lob_locator) && $idx == 43; my $len = $dbh->func($lob_locator, 'ora_lob_length'); #lab: possible logic error here w/resp. to len @@ -410,8 +410,8 @@ sub array_test { $a = []; $sth->bind_param_inout(1,\$a, 2); $sth->execute; - diag("a=$a\n"); - diag("a=@$a\n"); + note("a=$a\n"); + note("a=@$a\n"); }; die "RETURNING array: $@"; } diff --git a/t/40ph_type.t b/t/40ph_type.t index b5ba1cef..594a6b2a 100644 --- a/t/40ph_type.t +++ b/t/40ph_type.t @@ -69,9 +69,7 @@ for my $test_info (@tests) { my $ph_type = $test_info->{type} || die; my $name = $test_info->{name} || die; - diag("\n"); - diag("testing @{[ %$test_info ]} ...\n"); - diag("\n"); + note("\ntesting @{[ %$test_info ]} ...\n\n"); SKIP: { skip "skipping tests", 12 if ($test_info->{SKIP}); @@ -95,7 +93,7 @@ for my $test_info (@tests) { $dbh->rollback; delete $_->{name} foreach values %$tmp; - diag(Data::Dumper::Dumper($tmp)); + note(Data::Dumper::Dumper($tmp)); # check trailing_space behaviour my $expect = $val_with_trailing_space; diff --git a/t/50cursor.t b/t/50cursor.t index 168d6ed3..df010925 100644 --- a/t/50cursor.t +++ b/t/50cursor.t @@ -49,7 +49,7 @@ if ($dbh) { my @cursors; my @row; -diag("opening cursors\n"); +note("opening cursors\n"); my $open_cursor = $dbh->prepare( qq{ BEGIN OPEN :kursor FOR SELECT * FROM all_objects WHERE rownum < 5; @@ -58,7 +58,7 @@ my $open_cursor = $dbh->prepare( qq{ ok($open_cursor, 'open cursor' ); foreach ( 1 .. $limit ) { - diag("opening cursor $_\n"); + note("opening cursor $_\n"); ok( $open_cursor->bind_param_inout( ":kursor", \my $cursor, 0, { ora_type => ORA_RSET } ), 'open cursor bind param inout' ); ok( $open_cursor->execute, 'open cursor execute' ); ok(!$open_cursor->{Active}, 'open cursor Active'); @@ -72,7 +72,7 @@ foreach ( 1 .. $limit ) { push @cursors, $cursor; } -diag("closing cursors\n"); +note("closing cursors\n"); my $close_cursor = $dbh->prepare( qq{ BEGIN CLOSE :kursor; END; } ); ok($close_cursor, 'close cursor'); foreach ( 1 .. @cursors ) { diff --git a/t/70meta.t b/t/70meta.t index 221a0645..d2d29e91 100644 --- a/t/70meta.t +++ b/t/70meta.t @@ -20,14 +20,14 @@ if ($dbh) { plan skip_all => "Unable to connect to Oracle"; } -diag("type_info_all\n"); +note("type_info_all\n"); my @types = $dbh->type_info(SQL_ALL_TYPES); ok(@types >= 8, 'more than 8 types'); -diag(Dumper( @types )); +note(Dumper( @types )); -diag("tables():\n"); +note("tables():\n"); my @tables = $dbh->tables; -diag(@tables." tables\n"); +note(@tables." tables\n"); ok(scalar @tables, 'tables'); my @table_info_params = ( diff --git a/t/nchar_test_lib.pl b/t/nchar_test_lib.pl index 0445854c..f589d66a 100644 --- a/t/nchar_test_lib.pl +++ b/t/nchar_test_lib.pl @@ -189,7 +189,7 @@ sub show_test_data my $nice_string = nice_string($v); my $out = sprintf( "row: %3d: nice_string=%s byte_string=%s (%s, %s)\n", $cnt, $nice_string, $byte_string, $v, DBI::neat($v)); - diag($out); + note($out); } return $cnt; } @@ -387,7 +387,7 @@ sub create_table } else { #$sql =~ s/ \( */(\n\t/g; #$sql =~ s/, */,\n\t/g; - diag("$sql\n") ; + note("$sql\n") ; } return $table; # ok( not $dbh->err, "create table $table..." ); @@ -406,11 +406,11 @@ sub show_db_charsets db_ochar_is_utf($dbh) ? "Unicode" : "Non-Unicode", $paramsH->{NLS_NCHAR_CHARACTERSET}, db_nchar_is_utf($dbh) ? "Unicode" : "Non-Unicode"; - diag($out); + note($out); my $ora_client_version = ORA_OCI(); $out = sprintf "Client $ora_client_version NLS_LANG is '%s', NLS_NCHAR is '%s'\n", ora_env_var("NLS_LANG") || "", ora_env_var("NLS_NCHAR") || ""; - diag($out); + note($out); } sub db_ochar_is_utf { return shift->ora_can_unicode & 2 } sub db_nchar_is_utf { return shift->ora_can_unicode & 1 } diff --git a/xt/manifest.t b/xt/manifest.t new file mode 100644 index 00000000..00df9957 --- /dev/null +++ b/xt/manifest.t @@ -0,0 +1,21 @@ +use strict; +use warnings; + +use ExtUtils::Manifest qw/ fullcheck /; + +use Test::More tests => 1; + +my ( $missing, $extra ) = do { + local *STDERR; + + # hush little baby, don't you cry + open STDERR, '>', \my $stderr; + + fullcheck(); +}; + +ok @$missing + @$extra == 0, 'manifest in sync' or do { + diag "missing files:\n", map { " \t $_\n " } @$missing if @$missing; + diag "extra files: \n", map { "\t$_\n" } @$extra if @$extra; +}; + From 423fae7c8e92cb0a5d78bfffcedc2076528a80a6 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Sep 2011 19:23:20 +0000 Subject: [PATCH 050/637] Merge branch 'master' into HEAD git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14937 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 1 + README.macosx.txt | 41 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index 564f85f6..709d68b6 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,7 @@ Changes in DBD-Oracle XXX [DOCUMENTATION] - announce that Oraperl will be removed from the dist by v1.38. + - add Mac OS instructions for Lion (patch by David Wheeler) [rt71109] Changes in DBD-Oracle 1.30 [DOCUMENTATION] diff --git a/README.macosx.txt b/README.macosx.txt index c341a339..fa20aa1f 100644 --- a/README.macosx.txt +++ b/README.macosx.txt @@ -4,10 +4,10 @@ DBD::Oracle on MacOS X 10.2.4 and higher, using Oracle 9iR2 DR time of writing). MacOS X DBD::Oracle has been tested (and used) under Jaguar (10.2.x), -Panther (10.3.x), Snow Leopard (10.6.x). Jaguar comes with a Perl -version of 5.6.0., which I can report to work with DBD::Oracle 1.14 -and higher once you take certain steps (see below). You may want to -install a later perl, e.g., Perl 5.8.x. Please refer to: +Panther (10.3.x), Snow Leopard (10.6.x), Lion (10.7.x). Jaguar comes +with a Perl version of 5.6.0., which I can report to work with +DBD::Oracle 1.14 and higher once you take certain steps (see below). +You may want to install a later perl, e.g., Perl 5.8.x. Please refer to: Installing Perl 5.8 on Jaguar http://developer.apple.com/internet/macosx/perl.html @@ -47,6 +47,39 @@ if you are on 10.3 (Panther) and you do not intend to run the Oracle database server on your MacOSX box. See below (Instructions for 10.3.x) for details. +====================================================================== +Instructions for 10.7.x (Lion) + +Because the 64 bit instantclient is currently [incompatible with Lion][], +DBD::Oracle can only be compiled with the 32-bit instantclient libraries, and +therefore requires 32-bit Perl. If your Perl is 64-bit (which, by defaul, it +is on Mac OS X), you will not be able to build DBD::Oracle until an updated +64-bit instantclient is released. + +[incompatible with Lion]: http://only4left.jpiwowar.com/2011/08/instant-client-osx-lion-32-bit-only/ + +If you have a 32-bit Perl, however, then the following steps should work: + +* Download and install the 32-bit basic, sqlplus, and sdk instantclient + libraries and install them in a central location, such as + `/usr/oracle_instantclient`. [Downloads here][]. + + [Downloads here]: http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html + +* Create a symlink from `libclntsh.dylib.10.1` to `libclntsh.dylib`: + + cd /usr/oracle_instantclient/ + link -s libclntsh.dylib.10.1 libclntsh.dylib + +* Update your environment to point to the libraries: + + export ORACLE_HOME=/usr/oracle_instantclient + export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/usr/oracle_instantclient + +* You should now be able to install DBD::Oracle from CPAN: + + cpan DBD::Oracle + ====================================================================== Instructions for 10.6.x (Snow Leopard) From f559930e0b8bc670df34160755f118c574543147 Mon Sep 17 00:00:00 2001 From: byterock Date: Fri, 30 Sep 2011 14:50:03 +0000 Subject: [PATCH 051/637] fixed minor typo in POD git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14938 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 1 + Oracle.pm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 709d68b6..730bf2a1 100644 --- a/Changes +++ b/Changes @@ -16,6 +16,7 @@ Changes in DBD-Oracle XXX [DOCUMENTATION] - announce that Oraperl will be removed from the dist by v1.38. - add Mac OS instructions for Lion (patch by David Wheeler) [rt71109] + - fixed minor typo in POD (John Scoles) Changes in DBD-Oracle 1.30 [DOCUMENTATION] diff --git a/Oracle.pm b/Oracle.pm index 6abf5946..2a1730ea 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1580,7 +1580,7 @@ attempts another event. #import the ora fail over constants #set up TAF on the connection - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taft'}); + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function From 72a40557ecddfc1907cc1cd41c84816dc007de03 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 6 Oct 2011 20:38:16 +0000 Subject: [PATCH 052/637] Merge branch 'master' into HEAD git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14940 50811bd7-b8ce-0310-adc1-d9db26280581 --- README.macosx.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.macosx.txt b/README.macosx.txt index fa20aa1f..e854e4c6 100644 --- a/README.macosx.txt +++ b/README.macosx.txt @@ -52,7 +52,7 @@ Instructions for 10.7.x (Lion) Because the 64 bit instantclient is currently [incompatible with Lion][], DBD::Oracle can only be compiled with the 32-bit instantclient libraries, and -therefore requires 32-bit Perl. If your Perl is 64-bit (which, by defaul, it +therefore requires 32-bit Perl. If your Perl is 64-bit (which, by default, it is on Mac OS X), you will not be able to build DBD::Oracle until an updated 64-bit instantclient is released. From 545fbe7b23b5471853152b0f0080f3d2ef660274 Mon Sep 17 00:00:00 2001 From: yanick Date: Wed, 12 Oct 2011 17:22:10 +0000 Subject: [PATCH 053/637] Merge branch 'master' into HEAD git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14943 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/01base.t | 3 +-- t/10general.t | 8 +++----- t/15nls.t | 1 - t/20select.t | 3 ++- t/22nchar_utf8.t | 5 +++-- t/23wide_db.t | 3 ++- t/23wide_db_al32utf8.t | 2 +- t/24implicit_utf8.t | 4 ++-- t/25plsql.t | 15 ++++++++------- t/31lob_extended.t | 35 ++++++++++++++++------------------- t/36lob_leak.t | 4 ++-- t/40ph_type.t | 6 +++--- t/50cursor.t | 3 ++- t/55nested.t | 4 +++- t/70meta.t | 7 +++---- t/nchar_test_lib.pl | 16 +++++++--------- 16 files changed, 58 insertions(+), 61 deletions(-) diff --git a/t/01base.t b/t/01base.t index d545045c..b06c84b1 100755 --- a/t/01base.t +++ b/t/01base.t @@ -3,8 +3,7 @@ # Base DBD Driver Test use Test::More tests => 6; -diag('Test loading DBI, DBD::Oracle and version'); -require_ok(DBI); +require_ok('DBI'); eval { import DBI; diff --git a/t/10general.t b/t/10general.t index 88f3b8b5..eefa5d88 100644 --- a/t/10general.t +++ b/t/10general.t @@ -13,8 +13,6 @@ require 'nchar_test_lib.pl'; $| = 1; -diag('Test preparsing, Active, NLS_NUMERIC_CHARACTERS, err, ping and OCI version'); - my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; @@ -105,10 +103,10 @@ $dbh->{PrintError} = 0; ok( $dbh->ping, 'ping - connected'); my $ora_oci = DBD::Oracle::ORA_OCI(); # dualvar -printf "ORA_OCI = %d (%s)\n", $ora_oci, $ora_oci; +note sprintf "ORA_OCI = %d (%s)\n", $ora_oci, $ora_oci; + ok("$ora_oci", 'ora_oci defined'); -ok($ora_oci >= 8, 'ora_oci >= 8'); -diag($ora_oci); +ok($ora_oci >= 8, "ora_oci $ora_oci >= 8"); my @ora_oci = split(/\./, $ora_oci,-1); ok(scalar @ora_oci >= 2, 'version has 2 or more components'); ok((scalar @ora_oci == grep { DBI::looks_like_number($_) } @ora_oci), diff --git a/t/15nls.t b/t/15nls.t index 3975d9de..b9c23a16 100644 --- a/t/15nls.t +++ b/t/15nls.t @@ -12,7 +12,6 @@ my $testcount = 9; $| = 1; -diag('test nls_date_format, ora_can_unicode'); my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; diff --git a/t/20select.t b/t/20select.t index 87189659..c19d23d3 100644 --- a/t/20select.t +++ b/t/20select.t @@ -44,7 +44,8 @@ if ($dbh) { plan skip_all => "Unable to connect to oracle\n"; } -diag('test simple select statements with [utf8]'); +# test simple select statements with [utf8] + my $utf8_test = ($] >= 5.006) && client_ochar_is_utf8() # for correct output (utf8 bind vars should be fine regardless) && ($dbh->ora_can_unicode() & 2); diff --git a/t/22nchar_utf8.t b/t/22nchar_utf8.t index 4b8c35af..68e08040 100644 --- a/t/22nchar_utf8.t +++ b/t/22nchar_utf8.t @@ -24,14 +24,15 @@ SKIP: { plan skip_all => "Unable to connect to Oracle" if not $dbh; plan skip_all => "Database NCHAR character set is not Unicode" if not db_nchar_is_utf($dbh) ; - diag("testing utf8 with nchar columns\n"); + + # testing utf8 with nchar columns show_db_charsets( $dbh ); my $tdata = test_data( 'wide_nchar' ); if ( $dbh->ora_can_unicode & 1 ) { push( @{$tdata->{rows}} ,extra_wide_rows() ) ; - diag(" --- added 2 rows with extra wide chars to test data\n"); + # added 2 rows with extra wide chars to test data } my $testcount = 0 #create table diff --git a/t/23wide_db.t b/t/23wide_db.t index 6542e325..25541111 100644 --- a/t/23wide_db.t +++ b/t/23wide_db.t @@ -27,7 +27,8 @@ SKIP: { plan skip_all => "Unable to connect to Oracle" if not $dbh; plan skip_all => "Database character set is not Unicode" if not db_ochar_is_utf($dbh) ; - print "testing utf8 with char columns (wide mode database)\n" ; + + # testing utf8 with char columns (wide mode database) my $tdata = test_data( 'wide_char' ); my $testcount = 0 #create table diff --git a/t/23wide_db_al32utf8.t b/t/23wide_db_al32utf8.t index ef839f46..b0ba18a6 100644 --- a/t/23wide_db_al32utf8.t +++ b/t/23wide_db_al32utf8.t @@ -25,7 +25,7 @@ SKIP: { plan skip_all => "Unable to connect to Oracle" if not $dbh; plan skip_all => "Database character set is not Unicode" if not db_ochar_is_utf($dbh) ; - diag("testing utf8 with char columns (wide mode database)\n") ; + # testing utf8 with char columns (wide mode database) my $tdata = test_data( 'wide_char' ); my $testcount = 0 #create table diff --git a/t/24implicit_utf8.t b/t/24implicit_utf8.t index 94089f4c..518297b1 100644 --- a/t/24implicit_utf8.t +++ b/t/24implicit_utf8.t @@ -25,7 +25,7 @@ SKIP: { plan skip_all => "Database NCHAR character set is not Unicode" if not db_nchar_is_utf($dbh) ; $dbh->disconnect(); - diag(" --- testing implicit csform (dbhimp.c sets csform implicitly)\n") ; + # testing implicit csform (dbhimp.c sets csform implicitly) my $tdata = test_data( 'wide_nchar' ); my $testcount = 0 + insert_test_count( $tdata ) @@ -39,7 +39,7 @@ SKIP: { foreach my $nchar_cset (@nchar_cset) { $dbh->disconnect() if $dbh; undef $dbh; - diag(" --- testing with NLS_NCHAR=$nchar_cset\n") ; + # testing with NLS_NCHAR=$nchar_cset SKIP: { set_nls_nchar( $nchar_cset ,1 ); $dbh = db_handle(); diff --git a/t/25plsql.t b/t/25plsql.t index ebd2f039..da18a8b1 100644 --- a/t/25plsql.t +++ b/t/25plsql.t @@ -261,10 +261,9 @@ if (1) { is("@r", "@s2", "ref = sql"); } -diag("test bind_param_inout of param that's not assigned to in executed statement\n"); +# test bind_param_inout of param that's not assigned to in executed statement # See http://www.mail-archive.com/dbi-users@perl.org/msg18835.html -if (1) { - my $sth = $dbh->prepare (q( +my $sth = $dbh->prepare (q( BEGIN -- :p1 := :p1 ; -- :p2 := :p2 ; @@ -272,21 +271,23 @@ if (1) { :p1 := 'AAA' ; :p2 := 'Z' ; END IF ; - END ;)); +END ;)); + +{ my ($p1, $p2, $p3) = ('Hello', 'Y', 'Y') ; $sth->bind_param_inout(':p1', \$p1, 30) ; $sth->bind_param_inout(':p2', \$p2, 1) ; $sth->bind_param_inout(':p3', \$p3, 1) ; - diag("Before p1=[$p1] p2=[$p2] p3=[$p3]\n"); + note("Before p1=[$p1] p2=[$p2] p3=[$p3]\n"); ok($sth->execute, 'test bind_param_inout for non assigned'); is($p1, 'Hello', 'p1 ok'); is($p2, 'Y', 'p2 ok'); is($p3, 'Y', 'p3 ok'); - diag("After p1=[$p1] p2=[$p2] p3=[$p3]\n"); + note("After p1=[$p1] p2=[$p2] p3=[$p3]\n"); } SKIP: { - diag("test nvarchar2 arg passing to functions\n"); + # test nvarchar2 arg passing to functions # http://www.nntp.perl.org/group/perl.dbi.users/24217 my $ora_server_version = $dbh->func("ora_server_version"); skip "Client/server version < 9.0", 15 diff --git a/t/31lob_extended.t b/t/31lob_extended.t index 21ad9e7c..3c084065 100644 --- a/t/31lob_extended.t +++ b/t/31lob_extended.t @@ -171,24 +171,21 @@ EOT } END { - if ($dbh) { - local $dbh->{PrintError} = 0; - local $dbh->{RaiseError} = 1; - eval {$dbh->do(q/drop procedure p_DBD_Oracle_drop_me/);}; - if ($@) { - warn("procedure p_DBD_Oracle_drop_me possibly not dropped" . - "- check - $@\n") if $dbh->err ne '4043'; - } else { - diag("procedure p_DBD_Oracle_drop_me dropped"); - } - eval {drop_table($dbh);}; - if ($@) { - warn("table $table possibly not dropped - check - $@\n") - - if $dbh->err ne '942'; - } else { - diag("table $table dropped"); - } + return unless $dbh; + + local $dbh->{PrintError} = 0; + local $dbh->{RaiseError} = 1; + + eval {$dbh->do(q/drop procedure p_DBD_Oracle_drop_me/);}; + if ($@) { + diag("procedure p_DBD_Oracle_drop_me possibly not dropped" . + "- check - $@\n") if $dbh->err ne '4043'; } -}; + + eval {drop_table($dbh);}; + if ($@) { + diag("table $table possibly not dropped - check - $@\n") + if $dbh->err ne '942'; + } +} diff --git a/t/36lob_leak.t b/t/36lob_leak.t index 2fb6878e..119662a5 100644 --- a/t/36lob_leak.t +++ b/t/36lob_leak.t @@ -157,10 +157,10 @@ END { if ($function){ eval {$dbh->do(qq/drop function $function/);}; if ($@) { - warn("function p_DBD_Oracle_drop_me possibly not dropped" . + diag("function p_DBD_Oracle_drop_me possibly not dropped" . "- check - $@\n") if $dbh->err ne '4043'; } else { - diag("function p_DBD_Oracle_drop_me dropped"); + note("function p_DBD_Oracle_drop_me dropped"); } } } diff --git a/t/40ph_type.t b/t/40ph_type.t index 594a6b2a..38239b82 100644 --- a/t/40ph_type.t +++ b/t/40ph_type.t @@ -100,9 +100,9 @@ for my $test_info (@tests) { $expect =~ s/\s+$// if $test_info->{chops_space}; my $ok = ($tmp->{ts}->{vc} eq $expect); if (!$ok && $ph_type==1 && $name eq 'VARCHAR2') { - warn " Placeholder behaviour for ora_type=1 VARCHAR2 (the default) varies with Oracle version.\n"; - warn " Oracle 7 didn't strip trailing spaces, Oracle 8 did, until 9.2.x\n"; - warn " Your system doesn't. If that seems odd, let us know.\n"; + note " Placeholder behaviour for ora_type=1 VARCHAR2 (the default) varies with Oracle version.\n" + . " Oracle 7 didn't strip trailing spaces, Oracle 8 did, until 9.2.x\n" + . " Your system doesn't. If that seems odd, let us know.\n"; $ok = 1; } ok($ok, sprintf(" using ora_type %d expected %s but got %s for $name", diff --git a/t/50cursor.t b/t/50cursor.t index df010925..fa40a060 100644 --- a/t/50cursor.t +++ b/t/50cursor.t @@ -41,7 +41,8 @@ if ($dbh) { plan tests => $tests; - diag("Max cursors: $limit\n"); + note "Max cursors: $limit"; + } else { plan skip_all => "Unable to connect to Oracle"; } diff --git a/t/55nested.t b/t/55nested.t index d470d356..a311d80c 100644 --- a/t/55nested.t +++ b/t/55nested.t @@ -89,7 +89,9 @@ sub timed_fetch { my $tm_start = DBI::dbi_time(); $row_count++ while $rs->fetch; my $elapsed = DBI::dbi_time() - $tm_start; - diag("Fetched $row_count rows ($caption): $elapsed secs.\n"); + + note "Fetched $row_count rows ($caption): $elapsed secs."; + return $elapsed; } diff --git a/t/70meta.t b/t/70meta.t index d2d29e91..d8e29938 100644 --- a/t/70meta.t +++ b/t/70meta.t @@ -38,20 +38,19 @@ my @table_info_params = ( foreach my $table_info_params (@table_info_params) { my ($name) = shift @$table_info_params; my $start = time; - diag("$name: table_info(".DBI::neat_list($table_info_params).")\n"); + note("$name: table_info(".DBI::neat_list($table_info_params).")\n"); my $table_info_sth = $dbh->table_info(@$table_info_params); ok($table_info_sth, 'table_info'); my $data = $table_info_sth->fetchall_arrayref; ok($data, 'table_info fetch'); ok(scalar @$data, 'table_info data returned'); my $dur = time - $start; - diag("$name: ".@$data." rows, $dur seconds\n"); -# print Dumper($data); + note("$name: ".@$data." rows, $dur seconds\n"); } my $sql_dbms_version = $dbh->get_info(18); ok($sql_dbms_version, 'dbms_version'); -diag("sql_dbms_version=$sql_dbms_version\n"); +note "sql_dbms_version=$sql_dbms_version"; like($sql_dbms_version, qr/^\d+\.\d+\.\d+$/, 'matched'); $dbh->disconnect; diff --git a/t/nchar_test_lib.pl b/t/nchar_test_lib.pl index f589d66a..1b249962 100644 --- a/t/nchar_test_lib.pl +++ b/t/nchar_test_lib.pl @@ -444,7 +444,7 @@ sub set_nls_nchar # see comments in dbdimp.c for details. DBD::Oracle::ora_cygwin_set_env('NLS_NCHAR', $ENV{NLS_NCHAR}||'') if $^O eq 'cygwin'; - diag(defined ora_env_var("NLS_NCHAR") ? # defined? + note(defined ora_env_var("NLS_NCHAR") ? # defined? "set \$ENV{NLS_NCHAR}=$cset\n" : "set \$ENV{NLS_LANG}=undef\n") # XXX ? if defined $verbose; @@ -453,17 +453,15 @@ sub set_nls_nchar sub set_nls_lang_charset { my ($lang,$verbose) = @_; - if ( $lang ) { - $ENV{NLS_LANG} = "AMERICAN_AMERICA.$lang"; - diag("set \$ENV{NLS_LANG}=AMERICAN_AMERICA.$lang\n") if ( $verbose ); - } else { - $ENV{NLS_LANG} = ""; # not the same as set_nls_nchar() above which uses undef - diag("set \$ENV{NLS_LANG}=''\n") if ( $verbose ); - } + + $ENV{NLS_LANG} = $lang ? "AMERICAN_AMERICA.$lang" : ''; + + note "set \$ENV{NLS_LANG='$ENV{NLS_LANG}'"; + # Special treatment for environment variables under Cygwin - # see comments in dbdimp.c for details. DBD::Oracle::ora_cygwin_set_env('NLS_LANG', $ENV{NLS_LANG}||'') - if $^O eq 'cygwin'; + if $^O eq 'cygwin'; } sub byte_string { From 4dc0b735e571d7318a3618ae5b6f4a07e831daec Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 13 Oct 2011 17:28:11 +0000 Subject: [PATCH 054/637] add github url git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14944 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 ++++++- Oracle.pm | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 730bf2a1..367e009f 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,11 @@ Revision history for DBD::Oracle -Changes in DBD-Oracle XXX +Changes in DBD-Oracle 1.XX + [DOCUMENTATION] + - add mention of the github mirror of the subversion repository + +Changes in DBD-Oracle 1.31_00 + [ENHANCEMENTS] - Makefile.PL's options are now documented - move 'explain' to '/examples' directory diff --git a/Oracle.pm b/Oracle.pm index 2a1730ea..c76743f5 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -5551,6 +5551,11 @@ actually spending time working on them. Otherwise you run the risk of them being rejected because they don't fit into some larger plans you may not be aware of. +=head2 GitHub repository + +A git mirror of the subversion is also available at +`https://github.com/yanick/DBD-Oracle`. + =head1 Oracle Related Links =head2 DBD::Oracle Tutorial From 76f96c69afc424a6e1dc98dad7f5ca2d4adfe95e Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 13 Oct 2011 17:28:15 +0000 Subject: [PATCH 055/637] add resource info to Makefile.PL git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14945 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 1 + Makefile.PL | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 367e009f..af4630c1 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,7 @@ Revision history for DBD::Oracle Changes in DBD-Oracle 1.XX [DOCUMENTATION] - add mention of the github mirror of the subversion repository + - add 'resources' info to META.yml Changes in DBD-Oracle 1.31_00 diff --git a/Makefile.PL b/Makefile.PL index eb04c74f..2c1ff707 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -62,7 +62,20 @@ my %opts = ( configure_requires => { "DBI" => '1.51' }, build_requires => {"DBI" => '1.51', "ExtUtils::MakeMaker" => 0, - "Test::Simple" => '0.90'} + "Test::Simple" => '0.90'}, + resources => { + bugtracker => { + mailto => 'bug-dbd-oracle at rt.cpan.org', + web => + 'http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle', + }, + homepage => 'http://search.cpan.org/dist/DBD-Oracle', + repository => { + type => 'git', + url => 'git://github.com/yanick/DBD-Oracle.git', + web => 'http://github.com/yanick/DBD-Oracle/tree', + }, + }, }, ); my $eumm = $ExtUtils::MakeMaker::VERSION; From c91153d3506d262d7a4d33ab95f16fce4b26d5b2 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 13 Oct 2011 17:28:20 +0000 Subject: [PATCH 056/637] COLUMN_SIZE of VARCHAR2 is in chars, not bytes. (rt-13865) git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14946 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++++ Oracle.pm | 1 + t/rt13865.t | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 t/rt13865.t diff --git a/Changes b/Changes index af4630c1..215652c7 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,11 @@ Revision history for DBD::Oracle Changes in DBD-Oracle 1.XX + [BUG FIXES] + - COLUMN_SIZE of VARCHAR2 returns size in chars, not bytes. [RT#13865] + (reported by Stefano and Laurent Dami) + + [DOCUMENTATION] - add mention of the github mirror of the subversion repository - add 'resources' info to META.yml diff --git a/Oracle.pm b/Oracle.pm index c76743f5..a037aa80 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -650,6 +650,7 @@ SELECT * ) , 'FLOAT' , tc.DATA_PRECISION , 'DATE' , 19 + , 'VARCHAR2' , tc.CHAR_LENGTH , tc.DATA_LENGTH ) COLUMN_SIZE , decode( tc.DATA_TYPE diff --git a/t/rt13865.t b/t/rt13865.t new file mode 100644 index 00000000..7edee833 --- /dev/null +++ b/t/rt13865.t @@ -0,0 +1,69 @@ +use strict; + +use DBI; +use DBD::Oracle; + +use Test::More; + +use lib 't'; +require 'nchar_test_lib.pl'; + +my $dbh = db_handle() or plan skip_all => "can't connect to database"; + +my %priv = map { $_ => 1 } get_privs( $dbh ); + +unless ( ( $priv{'CREATE TABLE'} or $priv{'CREATE ANY TABLE'} ) + and ( $priv{'DROP TABLE'} or $priv{'DROP ANY TABLE'} ) ) { + plan skip_all => q{requires permissions 'CREATE TABLE' and 'DROP TABLE'}; +} + +plan tests => 5; + +$dbh->do( 'DROP TABLE RT13865' ); + +$dbh->do( <<'END_SQL' ) or die $dbh->errstr; +CREATE TABLE RT13865( + COL_INTEGER INTEGER, + COL_NUMBER NUMBER, + COL_NUMBER_37 NUMBER(37), + COL_DECIMAL NUMBER(9,2), + COL_FLOAT FLOAT(126), + COL_VC2 VARCHAR2(67), + COL_VC2_69CHAR VARCHAR2(69 CHAR) +) +END_SQL + +my $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_INTEGER' ); + +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 38, + "INTEGER is alias for NUMBER(38)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NUMBER_37' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 37, + "NUMBER(37)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NUMBER' ); +cmp_ok $col_h->fetchrow_hashref->{COLUMN_SIZE}, '>', 0, + "NUMBER"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_VC2' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, + "VARCHAR(67)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_VC2_69CHAR' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, + "VARCHAR(69)"; + + +$dbh->do( 'DROP TABLE RT13865' ); + +# utility functions + +sub get_privs { + my $dbh = shift; + + my $sth = $dbh->prepare( 'SELECT PRIVILEGE from session_privs' ); + $sth->execute; + + return map { $_->[0] } @{ $sth->fetchall_arrayref }; +} From 7c8f319f35687c8b7bf43ab2ba0d9f4a2bbb5ff4 Mon Sep 17 00:00:00 2001 From: byterock Date: Fri, 14 Oct 2011 22:02:41 +0000 Subject: [PATCH 057/637] fixed broken link to Oracle DRCP doc git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14947 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 1 + Oracle.pm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 215652c7..e7d353de 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,7 @@ Changes in DBD-Oracle 1.XX [DOCUMENTATION] - add mention of the github mirror of the subversion repository - add 'resources' info to META.yml + - fixed broken link to Oracle DRCP doc Changes in DBD-Oracle 1.31_00 diff --git a/Oracle.pm b/Oracle.pm index a037aa80..5ffb5f68 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1533,7 +1533,7 @@ environment variable ORA_DRCP. All of which are demonstrated below; $dbh = DBI->connect('dbi:Oracle:DB','username','password') -You can find a white paper on setting up DRCP and its advantages at L. +You can find a white paper on setting up DRCP and its advantages at L. Please note that DRCP support in DBD::Oracle is relatively new so the mechanics or its implementation are subject to change. From 1e17b3d8863123df0f3420046b107d672bc1cbab Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sun, 16 Oct 2011 20:31:03 -0400 Subject: [PATCH 058/637] release 1.32 --- Changes | 3 +++ Oracle.pm | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index f1310191..07e1db0e 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,8 @@ Revision history for DBD::Oracle +Changes in DBD-Oracle 1.32 (16-10-2011) + - promote 1.31_00 to official release + Changes in DBD-Oracle 1.31_00 [ENHANCEMENTS] diff --git a/Oracle.pm b/Oracle.pm index 174d9f42..de75606f 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -7,7 +7,7 @@ require 5.006; -$DBD::Oracle::VERSION = '1.31_00'; +$DBD::Oracle::VERSION = '1.32'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; From 1ae7111f9154f091c1d8f17609d5fd863fd23c13 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 18 Oct 2011 17:25:51 +0000 Subject: [PATCH 059/637] in sync with master git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14957 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 10 +++++++--- Oracle.pm | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index e7d353de..9b4ddb96 100644 --- a/Changes +++ b/Changes @@ -1,15 +1,19 @@ Revision history for DBD::Oracle -Changes in DBD-Oracle 1.XX +Changes in DBD-Oracle 1.33_00 (18-10-2011) + [BUG FIXES] - COLUMN_SIZE of VARCHAR2 returns size in chars, not bytes. [RT#13865] (reported by Stefano and Laurent Dami) - [DOCUMENTATION] - add mention of the github mirror of the subversion repository - add 'resources' info to META.yml - - fixed broken link to Oracle DRCP doc + - fixed broken link to Oracle DRCP doc in POD (John Scoles) + +Changes in DBD-Oracle 1.32 (16-10-2011) + + - promote 1.31_00 to official release Changes in DBD-Oracle 1.31_00 diff --git a/Oracle.pm b/Oracle.pm index 5ffb5f68..8cbe4a77 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -7,7 +7,7 @@ require 5.006; -$DBD::Oracle::VERSION = '1.30'; +$DBD::Oracle::VERSION = '1.33_00'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; From bc78bfe16bfd9672d1f0c98357c89775fb7af750 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sat, 22 Oct 2011 11:07:35 +0000 Subject: [PATCH 060/637] Fix problems with bind_col where TYPE is specified but no attributes Add warning if TYPE to bind_col is not supported in sql_type_cast Add note to bind_col pod re use of TYPE git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14958 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 16 ++++++++++++++++ Oracle.pm | 6 ++++++ oci8.c | 12 +++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 9b4ddb96..dfba757f 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,21 @@ Revision history for DBD::Oracle +Changes in DBD-Oracle 1.33_01 (xx-xx-xxxx) + + [BUG FIXES] + - if bind_col is called with a TYPE but no bind attributes like + StrictlyTyped or DiscardString are set DBD::Oracle still attempts + to call sql_type_cast which is pointless (Martin J. Evans) + - if bind_col is called with a TYPE other than SQL_NUMERIC, + SQL_INTEGER or SQL_DOUBLE and bind attributes like StrictlyTyped or + DiscardString a warning was not issued that the type is unsupported + and no data was returned (Martin J. Evans) + + [DOCUMENTATION] + - Added notes to bind_col documenting the fact that setting a TYPE + does not affect how the column is bound in Oracle, only what + happens after the column data is retrieved (Martin J. Evans) + Changes in DBD-Oracle 1.33_00 (18-10-2011) [BUG FIXES] diff --git a/Oracle.pm b/Oracle.pm index 8cbe4a77..da516eac 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -4148,6 +4148,12 @@ Returns the number of rows affected for updates, deletes and inserts and -1 for Binds a Perl variable and/or some attributes to an output column of a SELECT statement. Column numbers count up from 1. You do not need to bind output columns in order to fetch data. +NOTE: DBD::Oracle does not use the C<$bind_type> to determine how to +bind the column; it uses what Oracle says the data type is. You can +however set a numeric bind type with the bind attributes +StrictlyTyped/DiscardString as these attributes are applied after the +column is retrieved. + See the DBI documentation for a discussion of the optional parameters C<\%attr> and C<$bind_type> =head3 B diff --git a/oci8.c b/oci8.c index 2c906c77..19be2418 100644 --- a/oci8.c +++ b/oci8.c @@ -3738,6 +3738,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) AV * dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ dTHX; + D_imp_xxh(sth); sword status; D_imp_dbh_from_sth; int num_fields = DBIc_NUM_FIELDS(imp_sth); @@ -3927,12 +3928,13 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ #if DBIXS_REVISION > 13590 /* If a bind type was specified we use DBI's sql_type_cast to cast it - currently only number types are handled */ - if (fbh->req_type != 0) { + if ((fbh->req_type != 0) && (fbh->bind_flags != 0)) { int sts; char errstr[256]; sts = DBIc_DBISTATE(imp_sth)->sql_type_cast_svpv( aTHX_ sv, fbh->req_type, fbh->bind_flags, NULL); + if (sts == 0) { sprintf(errstr, "over/under flow converting column %d to type %"IVdf"", @@ -3945,7 +3947,11 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ sprintf(errstr, "unsupported bind type %"IVdf" for column %d", fbh->req_type, i+1); - return Nullav; + /* issue warning */ + DBIh_SET_ERR_CHAR(sth, imp_xxh, "0", 1, errstr, Nullch, Nullch); + if (CSFORM_IMPLIES_UTF8(fbh->csform) ){ + SvUTF8_on(sv); + } } } else @@ -4669,4 +4675,4 @@ ora_db_version(SV *dbh, imp_dbh_t *imp_dbh) } imp_dbh->server_version = vernum; return vernum; -} \ No newline at end of file +} From cffacfb614561f4fc8cffa404bac92b0b4502834 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sat, 22 Oct 2011 11:51:19 +0000 Subject: [PATCH 061/637] Commented out unused code git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@14959 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ dbdimp.h | 4 ++-- oci8.c | 9 +++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index dfba757f..8530fcf1 100644 --- a/Changes +++ b/Changes @@ -16,6 +16,10 @@ Changes in DBD-Oracle 1.33_01 (xx-xx-xxxx) does not affect how the column is bound in Oracle, only what happens after the column data is retrieved (Martin J. Evans) + [OTHER] + - Commented out some functions in oci8.c which were not used to + reduce the size of the driver a little (Martin J. Evans) + Changes in DBD-Oracle 1.33_00 (18-10-2011) [BUG FIXES] diff --git a/dbdimp.h b/dbdimp.h index 1007b3e1..632e2814 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -352,8 +352,8 @@ char *oci_exe_mode _((ub4 mode)); char *dbd_yes_no _((int yes_no)); char *oci_col_return_codes _((int rc)); char *oci_csform_name _((ub4 attr)); -char *oci_sql_function_code_name _((int sqlfncode)); -char *oci_ptype_name _((int ptype)); +/*char *oci_sql_function_code_name _((int sqlfncode)); + char *oci_ptype_name _((int ptype));*/ int dbd_rebind_ph_lob _((SV *sth, imp_sth_t *imp_sth, phs_t *phs)); diff --git a/oci8.c b/oci8.c index 19be2418..351410ba 100644 --- a/oci8.c +++ b/oci8.c @@ -23,7 +23,7 @@ int describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ); int dump_struct(imp_sth_t *imp_sth,fbh_obj_t *obj,int level); - +/* char * dbd_yes_no(int yes_no) { @@ -33,6 +33,7 @@ dbd_yes_no(int yes_no) } return "No"; } +*/ void dbd_init_oci(dbistate_t *dbistate) @@ -52,6 +53,7 @@ dbd_init_oci_drh(imp_drh_t * imp_drh) } +/* char * oci_sql_function_code_name(int sqlfncode) { @@ -71,7 +73,9 @@ oci_sql_function_code_name(int sqlfncode) sprintf(SvPVX(sv),"(UNKNOWN SQL FN Code %d)", sqlfncode); return SvPVX(sv); } +*/ + /* char * oci_ptype_name(int ptype) { @@ -104,7 +108,8 @@ oci_ptype_name(int ptype) sprintf(SvPVX(sv),"(UNKNOWN PTYPE Code %d)", ptype); return SvPVX(sv); } - + */ + char * oci_exe_mode(ub4 mode) { From 0efab33dafa12792b91838315a18e8d7ceaf5788 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 31 Oct 2011 16:28:52 -0400 Subject: [PATCH 062/637] release v1.34 --- Changes | 4 ++++ Oracle.pm | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 9b4ddb96..f2aeab43 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,9 @@ Revision history for DBD::Oracle +Changes in DBD-Oracle 1.34 (31-10-2011) + + - promote 1.33_00 to official release + Changes in DBD-Oracle 1.33_00 (18-10-2011) [BUG FIXES] diff --git a/Oracle.pm b/Oracle.pm index 8cbe4a77..e509e001 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -7,7 +7,7 @@ require 5.006; -$DBD::Oracle::VERSION = '1.33_00'; +$DBD::Oracle::VERSION = '1.34'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; From bd5a118184a4c0b71cd15a32eff597166d0b42e2 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 15 Nov 2011 22:12:13 -0500 Subject: [PATCH 063/637] updating Changes --- Changes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 8cfee7be..7e65f856 100644 --- a/Changes +++ b/Changes @@ -17,7 +17,8 @@ Changes in DBD-Oracle XXX does not affect how the column is bound in Oracle, only what happens after the column data is retrieved (Martin J. Evans) - fix typo (thanks to Julián Moreno Patiño) [RT72038] - - shuffle POd around to improve documentation flow [RT72252] + - shuffle POD around to improve documentation flow [RT72252] + - major tidying up of the connect() documentation. (by Gwen Shapira) [OTHER] - Commented out some functions in oci8.c which were not used to From 46c0dcf75ba2c39deb31d5bd13eec213d028980a Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 15 Nov 2011 22:15:31 -0500 Subject: [PATCH 064/637] fix the numbered list --- Oracle.pm | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Oracle.pm b/Oracle.pm index f4811a34..5acabc43 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1198,10 +1198,24 @@ To open a connection to an Oracle database you need to specify a database connec The connection string is always of the form: "dbi:Oracle:" There are several ways to identify a database: -1. If the database is local, specifying the SID or service name will be enough. -2. If the database is defined in a TNSNAMES.ORA file, you can use the service name given in the file -3. To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: + +=over + +=item 1 + +If the database is local, specifying the SID or service name will be enough. + +=item 2 + +If the database is defined in a TNSNAMES.ORA file, you can use the service name given in the file + +=item 3 + +To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: //host[:port][/service_name] + +=back + If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. The following examples show several ways a connection can be created: From c44a80fd432e94f2099381c32d95954e3e7fbf96 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 17 Nov 2011 12:53:34 +0000 Subject: [PATCH 065/637] Merge commit '82f4c03a21f0839cf8' into HEAD Conflicts: Changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15003 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 8530fcf1..cf50c7e8 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -Changes in DBD-Oracle 1.33_01 (xx-xx-xxxx) +Changes in DBD-Oracle XXX [BUG FIXES] - if bind_col is called with a TYPE but no bind attributes like @@ -20,6 +20,10 @@ Changes in DBD-Oracle 1.33_01 (xx-xx-xxxx) - Commented out some functions in oci8.c which were not used to reduce the size of the driver a little (Martin J. Evans) +Changes in DBD-Oracle 1.34 (31-10-2011) + + - promote 1.33_00 to official release + Changes in DBD-Oracle 1.33_00 (18-10-2011) [BUG FIXES] From 52be16933643bba11fb4094722e86697b0fc6354 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 17 Nov 2011 12:53:46 +0000 Subject: [PATCH 066/637] Merge branch 'master' into HEAD git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15004 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 + MANIFEST | 8 +- Oracle.pm | 4022 ++++++++++++++--------------- README.linux.txt | 123 - README.login.txt | 7 - README.longs.txt | 81 - README.sun.txt | 19 - README.vms.txt | 87 - README.wingcc.txt | 74 - examples/ora_explain.pl | 2 +- lib/DBD/Oracle/Troubleshooting.pm | 407 +++ t/58object.t | 22 +- 12 files changed, 2311 insertions(+), 2545 deletions(-) delete mode 100644 README.linux.txt delete mode 100644 README.login.txt delete mode 100644 README.longs.txt delete mode 100644 README.sun.txt delete mode 100644 README.vms.txt delete mode 100644 README.wingcc.txt create mode 100644 lib/DBD/Oracle/Troubleshooting.pm diff --git a/Changes b/Changes index cf50c7e8..7e65f856 100644 --- a/Changes +++ b/Changes @@ -10,11 +10,15 @@ Changes in DBD-Oracle XXX SQL_INTEGER or SQL_DOUBLE and bind attributes like StrictlyTyped or DiscardString a warning was not issued that the type is unsupported and no data was returned (Martin J. Evans) + - Fix test so it works with perl compiled with -Duselongdouble [RT71852] [DOCUMENTATION] - Added notes to bind_col documenting the fact that setting a TYPE does not affect how the column is bound in Oracle, only what happens after the column data is retrieved (Martin J. Evans) + - fix typo (thanks to Julián Moreno Patiño) [RT72038] + - shuffle POD around to improve documentation flow [RT72252] + - major tidying up of the connect() documentation. (by Gwen Shapira) [OTHER] - Commented out some functions in oci8.c which were not used to diff --git a/MANIFEST b/MANIFEST index 44af9c60..baf4733c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -36,20 +36,13 @@ README-files/hpux/Makefile-Lincoln README.64bit.txt README.aix.txt README.clients.txt -README.explain.txt README.help.txt README.hpux.txt README.java.txt -README.linux.txt -README.login.txt -README.longs.txt README.macosx.txt README.sec.txt -README.sun.txt -README.vms.txt README.win32.txt README.win64.txt -README.wingcc.txt Notes about building with mingw32 and cygwin32 t/01base.t t/10general.t t/12impdata.t @@ -88,3 +81,4 @@ Todo typemap examples/ora_explain.pl t/00versions.t +lib/DBD/Oracle/Troubleshooting.pm diff --git a/Oracle.pm b/Oracle.pm index da516eac..5acabc43 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -1118,66 +1118,11 @@ DBD::Oracle - Oracle database driver for the DBI module DBD::Oracle is a Perl module which works with the DBI module to provide access to Oracle databases. -=head1 Module Documentation - - This documentation describes driver specific behaviour and restrictions. It is not supposed to be used as the only reference for the user. In any case -consult the B documentation first! - -=for html Latest DBI documentation. - -=head1 Which version DBD::Oracle is for me? - -From version 1.25 onwards DBD::Oracle will only support Oracle clients -9.2 or greater. Support for ProC connections was dropped in 1.29. - -If you are still stuck with an older version of Oracle or its client you might want to look at the table below. - - +---------------------+-----------------------------------------------------+ - | | Oracle Version | - +---------------------+----+-------------+---------+------+--------+--------+ - | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | - +---------------------+----+-------------+---------+------+--------+--------+ - | 0.1~16 | Y | Y | Y | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.17 | Y | Y | Y | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.18 | N | N | N | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.19 | N | N | N | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.20 | N | N | N | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.21~1.24 | N | N | N | N | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.25+ | N | N | N | N | N | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - -As there are dozens of different versions of Oracle's clients this -list does not include all of them, just the major released versions of -Oracle. +consult the L documentation first! -Note that one can still connect to any Oracle version with the older -DBD::Oracle versions the only problem you will have is that some of -the newer OCI and Oracle features available in later DBD::Oracle -releases will not be available to you. - -So to make a short story a little longer; - - 1) If you are using Oracle 7 or early 8 DB and you can manage to get a 9 client and you can use - any DBD::Oracle version. - 2) If you have to use an Oracle 7 client then DBD::Oracle 1.17 should work - 3) Same thing for 8 up to R2, use 1.17, if you are lucky and have the right patch-set you might - go with 1.18. - 4) For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. Again this depends on your - patch-set, If you run into trouble go with 1.19 - 5) After 9.2 you can use any version you want. - 6) For you Luddites out there ORAPERL still works and is still included but not updated or supported anymore and was removed in 1.29. - 7) It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go back to 7 - and even get to 10. I am not sure what the 11g client can connect to. - -=head1 Constants +=head1 CONSTANTS =over 4 @@ -1244,143 +1189,49 @@ These constants are used to set the orientation of a fetch on a scrollable curso =back -=head1 The DBI Class - -=head2 DBI Class Methods - -=head3 B - -This method creates a database handle by connecting to a database, and is the DBI -equivalent of the "new" method. - -This is a topic which often causes problems. Mainly due to Oracle's many -and sometimes complex ways of specifying and connecting to databases. -James Taylor and Lane Sharman have contributed much of the text in -this section. Unfortunately it is only really relative for connecting into older Oracle (<9) versions. -Most of this stuff is well out of date but it will be left in for now. -See the next section L for some more up to date connection hints. - -=head4 Connecting without environment variables or tnsnames.ora file - -If you use the C style syntax, for example: - - $dbh = DBI->connect("dbi:Oracle:host=myhost.com;sid=ORCL", $user, $passwd); - -then DBD::Oracle will construct a full connection descriptor string -for you and Oracle will not need to consult the tnsnames.ora file. - -If a C number is not specified then the descriptor will try both -1526 and 1521 in that order (e.g., new then old). You can check which -port(s) are in use by typing "$ORACLE_HOME/bin/lsnrctl stat" on the server. - -=head4 Oracle Environment Variables - -Oracle typically no longer needs two environment variables to specify default -connections: ORACLE_SID and TWO_TASK. - -ORACLE_SID is really unnecessary to set since TWO_TASK provides the -same functionality in addition to allowing remote connections. - - % setenv //xxx.yyy.zzz:1521/ORACLE_SID # for csh shell - $ TWO_TASK=T:hostname:ORACLE_SID export TWO_TASK # for sh shell - - % sqlplus username/password - -Note that if you have *both* local and remote databases, and you -have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully -qualified connect string on the command line, TWO_TASK takes precedence -over ORACLE_SID (i.e. you get connected to remote system). - - TWO_TASK=P:sid - -will use the pipe driver for local connections using SQL*Net v1. - - TWO_TASK=T:machine:sid - -will use TCP/IP (or D for DECNET, etc.) for remote SQL*Net v1 connection. - - TWO_TASK=dbname - -will use the info stored in the SQL*Net v2 F -configuration file for local or remote connections. - -Support for 'T:' syntax of Oracle SQL*Net V1 is only supported on older 7 clients and -I have my doubts it will even work if the DB or client has been patched and I know it -will not work on any later clients. - -The ORACLE_HOME environment variable should be set correctly. -In general, the value used should match the version of Oracle that -was used to build DBD::Oracle. If using dynamic linking then -ORACLE_HOME should match the version of Oracle that will be used -to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, -or similar on Unix). - -ORACLE_HOME can be left unset if you aren't using any of Oracle's -executables, but it is I recommended and error messages may not display. -It should be set to the ORACLE_HOME directory of the version of Oracle -that DBD::Oracle was compiled with. - -Discouraging the use of ORACLE_SID makes it easier on the users to see -what is going on. (It's unfortunate that TWO_TASK couldn't be renamed, -since it makes no sense to the end user, and doesn't have the ORACLE prefix). +=head1 DBI CLASS METHODS -Also remember that depending on the operating system you are using -the differing "ORACLE" environment variables may be case sensitive, so if you are not connecting -as you should double check the case of both the variable and its value. +=head2 B -=head4 Connection Examples Using DBD::Oracle +This method creates a database handle by connecting to a database, and is the DBI equivalent of the "new" method. +To open a connection to an Oracle database you need to specify a database connection string (URL), username and password. -First, how to connect to a local database I using a Listener: +The connection string is always of the form: "dbi:Oracle:" +There are several ways to identify a database: - $dbh = DBI->connect('dbi:Oracle:SID','scott', 'tiger'); +=over -you can also leave the SID empty: +=item 1 - $dbh = DBI->connect('dbi:Oracle:','scott', 'tiger'); +If the database is local, specifying the SID or service name will be enough. -in which case Oracle client code will use the ORACLE_SID environment -variable (if the TWO_TASK environment varariable is not defined). +=item 2 -Below are various ways of connecting to an Oracle database using -SQL*Net 1.x and SQL*Net 2.x. "Machine" is the computer the database is -running on, "SID" is the SID of the database, "DB" is the SQL*Net 2.x -connection descriptor for the database. +If the database is defined in a TNSNAMES.ORA file, you can use the service name given in the file -B Some of these formats may not work with Oracle 9+. +=item 3 - BEGIN { - $ENV{ORACLE_HOME} = '/home/oracle/product/10.x.x'; - $ENV{TWO_TASK} = 'DB'; - } - $dbh = DBI->connect('dbi:Oracle:','scott', 'tiger'); - # - or - - $dbh = DBI->connect('dbi:Oracle:','scott/tiger'); +To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: +//host[:port][/service_name] -Refer to your Oracle documentation for valid values of TWO_TASK. +=back -Here are some variations (not setting TWO_TASK) in order of preference: +If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. - $dbh = DBI->connect('dbi:Oracle:DB','username','password') +The following examples show several ways a connection can be created: - $dbh = DBI->connect('dbi:Oracle:DB','username/password','') - $dbh = DBI->connect('dbi:Oracle:','username@DB','password') + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521', 'scott/tiger', '') + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); - $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= - (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) - (CONNECT_DATA=(SID=ORCL)))}, "") + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); -If you are having problems with login taking a long time (>10 seconds say) -then you might have tripped up on an Oracle bug. You can try using one -of the ...@DB variants as a workaround. e.g., + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); - $dbh = DBI->connect('','username/password@DB',''); + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); -On the other hand, that may cause you to trip up on another Oracle bug -that causes alternating connection attempts to fail! (in reality only -a small proportion of people experience these problems) +=head3 OS authentication To connect to a local database with a user which has been set up to authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): @@ -1394,121 +1245,37 @@ That only works for local databases. (Authentication to remote Oracle databases using your Unix login name without a password is possible but it is not secure and not recommended so not documented here. +=head3 Oracle Environment Variables -=head4 Connecting To Oracle - -If you are reading this it is assumed that you have successfully -installed DBD::Oracle and you are having some problems connecting to -Oracle. - -First off you will have to tell DBD::Oracle where the binaries reside -for the Oracle client it was compiled against. This is the case when -you encounter a - - DBI connect('','system',...) failed: ERROR OCIEnvNlsCreate. - -error in Linux or in Windows when you get - - OCI.DLL not found - -The solution to this problem in the case of Linux is to ensure your -'ORACLE_HOME' (or LD_LIBRARY_PATH for InstantClient) environment -variable points to the correct directory. - - export ORACLE_HOME=/app/oracle/product/xx.x.x - -For Windows the solution is to add this value to you PATH - - PATH=c:\app\oracle\product\xx.x.x;%PATH% - - -If you get past this stage and get a - - ORA-12154: TNS:could not resolve the connect identifier specified - -error then the most likely cause is DBD::ORACLE cannot find your .ORA -(F, F, F) files. This can be -solved by setting the TNS_ADMIN environment variable to the directory -where these files can be found. - -If you get to this stage and you have either one of the following -errors; - - ORA-12560: TNS:protocol adapter error - ORA-12162: TNS:net service name is incorrectly specified - -usually means that DBD::Oracle can find the listener but the it cannot connect to the DB because the listener cannot find the DB you asked for. - -=head4 Connection Examples Using DBD::Oracle - -It is best to not use ORACLE_SID or TWO_TASK as both of these are rather out of date. You are better off keeping it simple like the following examples - - $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - - $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); - - $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); - - $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); - - -For those who really want to use ORACLE_SID and TWO_TASK here are examples of it in use; - -Given this TNS entry; - - DB.TEST = - (DESCRIPTION = - (ADDRESS = - (PROTOCOL = TCP) - (HOST = xxx.xxx.xxx.xx) - (PORT = 1523)) - (CONNECT_DATA = (SID = DB) ) -) - -and this code - - BEGIN { - $ENV{ORACLE_SID} = 'DB'; - } - - $dbh = DBI->connect('dbi:Oracle:','username/password',''); +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). -you will be able to connect to DB. Note this may not work for Windows. +Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. -TWO_TASK works the same way except it should override the value in ORACLE_SID so this +To use them, specify either a local SID or service name, or a service name that is specified in the TNSNAMES.ORA file. - BEGIN { - $ENV{ORACLE_SID} = 'DB'; - $ENV{TWO_TASK} = 'DB.TEST'; +Note that if you have *both* local and remote databases, and you have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO_TASK takes precedence over ORACLE_SID (i.e. you get connected to remote system). - } - - $dbh = DBI->connect('dbi:Oracle:','username/password',''); +It is highly recommended not to rely on environment variables and to always explicitly specify the SID in the connection string. This can prevent serious mistakes such as dropping a schema in the wrong database, and generally makes debugging and troubleshooting easier. -will work as well. Note this may not work for Windows. +Also remember that depending on the operating system you are using the differing "ORACLE" environment variables may be case sensitive, so if you are not connecting as you should double check the case of both the variable and its value. -=head4 Timezones +=head3 Timezones -If TWO_TASK isn't set, Oracle uses the TZ variable from the local environment. +If the query is run through SQL*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. -If TWO_TASK IS set, Oracle uses the TZ variable of the listener process -running on the server. +If the query is run locally, Oracle will return the time zone based on the "TZ" environment variable setting of the user running +the query. -You could have multiple listeners, each with their own TZ, and assign -users to the appropriate listener by setting TNS_ADMIN to a directory -that contains a tnsnames.ora file that points to the port that their -listener is on. +With local queries, you can change the time zone for a particular user by simply changing the setting of "TZ". To check the current setting, +issue the UNIX "date" command. -[Brad Howerter, who supplied this info said: "I've done this to simulate -running a Perl script at the end of the previous month even though it -was the 6th of the new month. I had the dba start up a listener with -TZ=X+144. (144 hours = 6 days)"] +=head3 Oracle DRCP -=head4 Oracle DRCP - -DBD::Oracle now supports DRCP (Database Resident Connection Pool) so -if you have an 11.2 database and DRCP is enabled you can now direct -all of your connections to it by simply adding ':POOLED' to the SID or +DBD::Oracle supports DRCP (Database Resident Connection Pool) so +if you have an 11.2 database and DRCP is enabled you can direct +all of your connections to it by adding ':POOLED' to the SID or setting a connection attribute of ora_drcp, or set the SERVER=POOLED when using a TNSENTRY style connection or even by setting an environment variable ORA_DRCP. All of which are demonstrated below; @@ -1538,7 +1305,7 @@ You can find a white paper on setting up DRCP and its advantages at L] I spent a lot of time optimizing -listener.ora and I am including it here for anyone to benefit from. My -connections over tnslistener on the same humble Netra 1 take an average -of 10-20 milli seconds according to tnsping. If anyone knows how to -make it better, please let me know! - - LISTENER = - (ADDRESS_LIST = - (ADDRESS = - (PROTOCOL = TCP) - (Host = aa.bbb.cc.d) - (Port = 1521) - (QUEUESIZE=10) - ) - ) - - STARTUP_WAIT_TIME_LISTENER = 0 - CONNECT_TIMEOUT_LISTENER = 10 - TRACE_LEVEL_LISTENER = OFF - SID_LIST_LISTENER = - (SID_LIST = - (SID_DESC = - (SID_NAME = xxxx) - (ORACLE_HOME = /xxx/local/oracle7-3) - (PRESPAWN_MAX = 40) - (PRESPAWN_LIST= - (PRESPAWN_DESC=(PROTOCOL=tcp) (POOL_SIZE=40) (TIMEOUT=120)) - ) - ) - ) - -1) When the application is co-located on the host and there is no need for -outside SQLNet connectivity, stop the listener. You do not need it. Get -your application/cgi/whatever working using pipes and shared memory. I am -convinced that this is one of the connection bugs (sockets over the same -machine). Note the $ENV{ORAPIPES} env var. The essential code to do -this at the end of this section. - -2) Be careful in how you implement the multi-threaded server. Currently I -am not using it in the initxxxx.ora file but will be doing some more testing. - -3) Be sure to create user rollback segments and use them; do not use the -system rollback segments; however, you must also create a small rollback -space for the system as well. - -5) Use large tuning settings and get lots of RAM. Check out all the -parameters you can set in v$parameters because there are quite a few not -documented you may to set in your initxxx.ora file. - -6) Use svrmgrl to control oracle from the command line. Write lots of small -SQL scripts to get at V$ info. - - use DBI; - # Environmental variables used by Oracle - $ENV{ORACLE_SID} = "xxx"; - $ENV{ORACLE_HOME} = "/opt/oracle7"; - $ENV{EPC_DISABLED} = "TRUE"; - $ENV{ORAPIPES} = "V2"; - my $dbname = "xxx"; - my $dbuser = "xxx"; - my $dbpass = "xxx"; - my $dbh = DBI->connect("dbi:Oracle:$dbname", $dbuser, $dbpass) - || die "Unable to connect to $dbname: $DBI::errstr\n"; - -=head4 Oracle utilities - -If you are still having problems connecting then the Oracle adapters -utility may offer some help. Run these two commands: - - $ORACLE_HOME/bin/adapters - $ORACLE_HOME/bin/adapters $ORACLE_HOME/bin/sqlplus - -and check the output. The "Protocol Adapters" section should be the -same. It should include at least "IPC Protocol Adapter" and "TCP/IP -Protocol Adapter". - -If it generates any errors which look relevant then please talk to your -Oracle technical support (and not the dbi-users mailing list). Thanks. -Thanks to Mark Dedlow for this information. - -=head3 Private Connect Attributes +=head3 Connect Attributes =head4 ora_ncs_buff_mtpl -You can now customize the size of the buffer when selecting LOBs with -the built in AUTO Lob. The default value is 4 which is probably +You can customize the size of the buffer when selecting LOBs with +the built-in AUTO Lob. The default value is 4 which is probably excessive for most situations but is needed for backward compatibility. If you not converting between a NCS on the DB and the Client then you might want to set this to 1 to reduce memory usage. @@ -1730,14 +1414,11 @@ This value can also be specified with the C environment variable in which case it sets the value at the connect stage. -See more details in the LOB section of the POD - =head4 ora_drcp -If you have an 11.2 or greater database your can utilize the DRCP by setting -this attribute to 1 at connect time. +For Oracle 11.2 or greater. -This value can also be set with the C environment variable. +Set to I<1> to enable DRCP. Can also be set via the C environment variable. =head4 ora_drcp_class @@ -1792,7 +1473,7 @@ variable. =head4 ora_taf If your Oracle instance has been configured to use TAF events you can -enable the TAF callback by setting this value to anything other than 0. +enable the TAF callback by setting this option to any I value. =head4 ora_taf_function @@ -1814,7 +1495,6 @@ and the failover type. Below is an example of a TAF function The amount of time in seconds the OCI client will sleep between attempting successive failover events when the event is OCI_FO_ERROR. - =head4 ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA @@ -1911,7 +1591,9 @@ on the server side using C view. =head4 ora_dbh_share -Requires at least Perl 5.8.0 compiled with ithreads. Allows you to share +Requires at least Perl 5.8.0 compiled with ithreads. + +Allows you to share database connections between threads. The first connect will make the connection, all following calls to connect with the same ora_dbh_share attribute will use the same database connection. The value must be a @@ -2074,11 +1756,12 @@ For example: NOTE disabling the signal handlers the OCI library sets up may affect functionality in the OCI library. -=head3 B +=head2 B -Implemented by DBI, no driver-specific impact. Please note that connect_cached as not been tested with DRCP. +Implemented by DBI, no driver-specific impact. +Please note that connect_cached as not been tested with DRCP. -=head3 B +=head2 B @data_sources = DBI->data_sources('Oracle'); @data_sources = $dbh->data_sources(); @@ -2087,29 +1770,26 @@ Returns a list of available databases. You will have to set either the 'ORACLE_H 'TNS_ADMIN' environment value to retrieve this list. It will read these values from TNSNAMES.ORA file entries. - - - -=head2 Methods Common To All Handles +=head1 METHODS COMMON TO ALL HANDLES For all of the methods below, B<$h> can be either a database handle (B<$dbh>) or a statement handle (B<$sth>). Note that I<$dbh> and I<$sth> can be replaced with any variable name you choose: these are just the names most often used. Another common variable used in this documentation is $I, which stands for "return value". -=head3 B +=head2 B $rv = $h->err; Returns the error code from the last method called. -=head3 B +=head2 B $str = $h->errstr; Returns the last error that was reported by Oracle. Starting with "ORA-00000" code followed by the error message. -=head3 B +=head2 B $str = $h->state; @@ -2119,29 +1799,29 @@ Oracle hasn't supported SQLSTATE since the early versions OCI. It will return em While this method can be called as either C<< $sth->state >> or C<< $dbh->state >>, it is usually clearer to always use C<< $dbh->state >>. -=head3 B +=head2 B Implemented by DBI, no driver-specific impact. -=head3 B +=head2 B Implemented by DBI, no driver-specific impact. -=head3 B and B +=head2 B and B Implemented by DBI, no driver-specific impact. -=head3 B +=head2 B DBD::Oracle uses the C method to support a variety of functions. -=head3 B +=head2 B Some of these functions are called through the method func() which is described in the DBI documentation. Any function that begins with ora_ can be called directly. -=head3 B +=head2 B This function returns a string which describes the errors from the most recent PL/SQL function, procedure, package, @@ -2171,7 +1851,7 @@ Example: die $msg if $msg; } -=head3 B +=head2 B These functions use the PL/SQL DBMS_OUTPUT package to store and retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer @@ -2210,7 +1890,7 @@ Example 2: # retrieve the string $date_string = $dbh->func( 'dbms_output_get' ); -=head3 B +=head2 B This function calls DBMS_OUTPUT.ENABLE to enable calls to package DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to @@ -2221,7 +1901,7 @@ The buffer_size is the maximum amount of text that can be saved in the buffer and must be between 2000 and 1,000,000. If buffer_size is not given, the default is 20,000 bytes. -=head3 B +=head2 B This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. @@ -2232,7 +1912,7 @@ If any line causes buffer_size to be exceeded, a buffer overflow error is raised and the function call fails. Some of the text might be in the buffer. -=head3 B +=head2 B This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from the buffer. @@ -2248,13 +1928,13 @@ Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. -=head3 B +=head2 B Starts a new session against the current database using the credentials supplied. -=head3 B +=head2 B $hashref = $dbh->private_attribute_info(); $hashref = $sth->private_attribute_info(); @@ -2262,127 +1942,127 @@ supplied. Returns a hash of all private attributes used by DBD::Oracle, for either a database or a statement handle. Currently, all the hash values are undef. -=head2 Attributes Common To All Handles +=head1 ATTRIBUTES COMMON TO ALL HANDLES -=head3 B (boolean) +=head2 B (boolean) Implemented by DBI, no driver-specific impact. -=head3 B (boolean, inherited) +=head2 B (boolean, inherited) Forces errors to always raise an exception. Although it defaults to off, it is recommended that this be turned on, as the alternative is to check the return value of every method (prepare, execute, fetch, etc.) manually, which is easy to forget to do. -=head3 B (boolean, inherited) +=head2 B (boolean, inherited) Forces database errors to also generate warnings, which can then be filtered with methods such as locally redefining I<$SIG{__WARN__}> or using modules such as C. This attribute is on by default. -=head3 B (boolean, inherited) +=head2 B (boolean, inherited) Appends information about the current statement to error messages. If placeholder information is available, adds that as well. Defaults to true. -=head3 B (boolean, inherited) +=head2 B (boolean, inherited) Enables warnings. This is on by default, and should only be turned off in a local block for a short a time only when absolutely needed. -=head3 B (boolean, read-only) +=head2 B (boolean, read-only) Indicates if a handle has been executed. For database handles, this value is true after the L method has been called, or when one of the child statement handles has issued an L. Issuing a L or L always resets the attribute to false for database handles. For statement handles, any call to L or its variants will flip the value to true for the lifetime of the statement handle. -=head3 B (integer, inherited) +=head2 B (integer, inherited) Sets the trace level, similar to the L method. See the sections on L and L for more details. -=head3 B (boolean, read-only) +=head2 B (boolean, read-only) Indicates if a handle is active or not. For database handles, this indicates if the database has been disconnected or not. For statement handles, it indicates if all the data has been fetched yet or not. Use of this attribute is not encouraged. -=head3 B (integer, read-only) +=head2 B (integer, read-only) Returns the number of child processes created for each handle type. For a driver handle, indicates the number of database handles created. For a database handle, indicates the number of statement handles created. For statement handles, it always returns zero, because statement handles do not create kids. -=head3 B (integer, read-only) +=head2 B (integer, read-only) Same as C, but only returns those that are active. -=head3 B (hash ref) +=head2 B (hash ref) Returns a hashref of handles. If called on a database handle, returns all statement handles created by use of the C method. If called on a driver handle, returns all database handles created by the L method. -=head3 B (array ref) +=head2 B (array ref) Implemented by DBI, no driver-specific impact. -=head3 B (boolean, inherited) +=head2 B (boolean, inherited) Implemented by DBI, no driver-specific impact. -=head3 B (boolean, inherited) +=head2 B (boolean, inherited) Implemented by DBI, no driver-specific impact. -=head3 B (code ref, inherited) +=head2 B (code ref, inherited) Implemented by DBI, no driver-specific impact. -=head3 B (unsigned integer) +=head2 B (unsigned integer) Implemented by DBI, no driver-specific impact. -=head3 B (string, inherited) +=head2 B (string, inherited) Implemented by DBI, no driver-specific impact. -=head3 B (boolean, inherited) +=head2 B (boolean, inherited) Implemented by DBI, no driver-specific impact. -=head3 B (boolean, inherited) +=head2 B (boolean, inherited) Implemented by DBI, no driver-specific impact. -=head3 B (boolean, inherited) +=head2 B (boolean, inherited) Implemented by DBI, no driver-specific impact. -=head3 B (boolean, inherited) +=head2 B (boolean, inherited) Implemented by DBI, no driver-specific impact. -=head3 B (inherited) +=head2 B (inherited) Implemented by DBI, no driver-specific impact. -=head3 B (scalar) +=head2 B (scalar) Returns C for a driver handle, C for a database handle, and C for a statement handle. Should be rarely needed. -=head3 B +=head2 B Implemented by DBI, no driver-specific impact. -=head3 B +=head2 B Implemented by DBI, no driver-specific impact. -=head3 B +=head2 B Type: boolean, inherited @@ -2391,11 +2071,35 @@ The CompatMode attribute is used by emulation layers (such as Oraperl) to enable It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. -=head1 DBI Database Handle Object +=head1 ORACLE-SPECIFIC DATABASE HANDLE METHODS + +=head2 B + +Returns a number indicating whether either of the database character sets +is a Unicode encoding. Calls ora_nls_parameters() and passes the optional +$refresh parameter to it. + +0 = Neither character set is a Unicode encoding. + +1 = National character set is a Unicode encoding. + +2 = Database character set is a Unicode encoding. + +3 = Both character sets are Unicode encodings. + +=head2 B + +Returns true if the current connection supports TAF events. False if otherise. + +=head2 B + +Returns a hash reference containing the current NLS parameters, as given +by the v$nls_parameters view. The values fetched are cached between calls. +To cause the latest values to be fetched, pass a true value to the function. -=head2 Database Handle Methods +=head1 DATABASE HANDLE METHODS -=head3 B +=head2 B $ary_ref = $dbh->selectall_arrayref($sql); $ary_ref = $dbh->selectall_arrayref($sql, \%attr); @@ -2404,14 +2108,14 @@ It also has the effect of disabling the 'quick FETCH' of attribute values from t Returns a reference to an array containing the rows returned by preparing and executing the SQL string. See the DBI documentation for full details. -=head3 B +=head2 B $hash_ref = $dbh->selectall_hashref($sql, $key_field); Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. See the DBI documentation for full details. -=head3 B +=head2 B $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); @@ -2419,13 +2123,13 @@ Returns a reference to an array containing the first column from each rows returned by preparing and executing the SQL string. It is possible to specify exactly which columns to return. See the DBI documentation for full details. -=head3 B +=head2 B $sth = $dbh->prepare($statement, \%attr); Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. -=head4 B +=head3 B These attributes may be used in the C<\%attr> parameter of the L database handle method. @@ -2506,7 +2210,7 @@ See L for more details. =back -=head4 B +=head3 B There are two types of placeholders that can be used in DBD::Oracle. The first is the "question mark" type, in which each placeholder is represented by a single @@ -2527,14 +2231,14 @@ use different ones for each statement handle you have. This is confusing at best stick to one style within your program. -=head3 B +=head2 B $sth = $dbh->prepare_cached($statement, \%attr); Implemented by DBI, no driver-specific impact. This method is most useful if the same query is used over and over as it will cut down round trips to the server. -=head3 B +=head2 B $rv = $dbh->do($statement); $rv = $dbh->do($statement, \%attr); @@ -2546,7 +2250,7 @@ number of rows is unknown or not available. Note that this method will return B< of 0 for 'no rows were affected', in order to always return a true value if no error occurred. -=head3 B +=head2 B Oracle does not implement auto_increment of serial type columns it uses predefined sequences where the id numbers are either selected before insert, at insert time with a trigger, @@ -2567,7 +2271,7 @@ on insert with the bind_param_inout method. $sth->execute(); $db->commit(); -=head3 B +=head2 B $rv = $dbh->commit; @@ -2575,7 +2279,7 @@ Issues a COMMIT to the server, indicating that the current transaction is finish all changes made will be visible to other processes. If AutoCommit is enabled, then a warning is given and no COMMIT is issued. Returns true on success, false on error. -=head3 B +=head2 B $rv = $dbh->rollback; @@ -2583,13 +2287,13 @@ Issues a ROLLBACK to the server, which discards any changes made in the current is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and false on error. -=head3 B +=head2 B This method turns on transactions until the next call to L or L, if L is currently enabled. If it is not enabled, calling begin_work will issue an error. Note that the transaction will not actually begin until the first statement after begin_work is called. -=head3 B +=head2 B $rv = $dbh->disconnect; @@ -2602,7 +2306,7 @@ referenced by anything), then the database handle's DESTROY method will call the methods automatically. It is best to explicitly disconnect rather than rely on this behavior. -=head3 B +=head2 B $rv = $dbh->ping; @@ -2610,13 +2314,13 @@ This C method is used to check the validity of a database handle. The valu either 0, indicating that the connection is no longer valid, or 1, indicating the connection is valid. This function does 1 round trip to the Oracle Server. -=head3 B +=head2 B $value = $dbh->get_info($info_type); DBD::Oracle supports C, but (currently) only a few info types. -=head3 B +=head2 B DBD::Oracle supports attributes for C. @@ -2653,7 +2357,7 @@ upper case). Oracle stores and returns it as given. C has no special quote handling, neither adds nor removes quotes. -=head3 B +=head2 B Oracle does not support catalogues so TABLE_CAT is ignored as selection criterion. @@ -2669,7 +2373,7 @@ An identifier is passed I, i.e. as the user provides or Oracle returns it. See L for more detailed information. -=head3 B +=head2 B This method (currently) supports the extended behaviour of SQL/CLI, i.e. the result set contains foreign keys that refer to primary B alternate keys. @@ -2702,7 +2406,7 @@ An identifier is passed I, i.e. as the user provides or Oracle returns it. See L for more detailed information. -=head3 B +=head2 B Oracle does not support catalogues so TABLE_CAT is ignored as selection criterion. @@ -2735,7 +2439,7 @@ So in the example the exact case "Bla_BLA" must be used to get it info on the co any case can be used to get info on the column. -=head3 B +=head2 B @row_ary = $dbh->selectrow_array($sql); @row_ary = $dbh->selectrow_array($sql, \%attr); @@ -2746,7 +2450,7 @@ by calling L. The string can also be a statement handle generat only the first row of data is returned. If called in a scalar context, only the first column of the first row is returned. Because this is not portable, it is not recommended that you use this method in that way. -=head3 B +=head2 B $ary_ref = $dbh->selectrow_arrayref($statement); $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); @@ -2755,7 +2459,7 @@ returned. Because this is not portable, it is not recommended that you use this Exactly the same as L, except that it returns a reference to an array, by internal use of the L method. -=head3 B +=head2 B $hash_ref = $dbh->selectrow_hashref($sql); $hash_ref = $dbh->selectrow_hashref($sql, \%attr); @@ -2764,49 +2468,22 @@ the L method. Exactly the same as L, except that it returns a reference to an hash, by internal use of the L method. -=head3 B +=head2 B $other_dbh = $dbh->clone(); Creates a copy of the database handle by connecting with the same parameters as the original handle, then trying to merge the attributes. See the DBI documentation for complete usage. -=head2 Private Database Handle Methods - -=head3 B - -Returns a number indicating whether either of the database character sets -is a Unicode encoding. Calls ora_nls_parameters() and passes the optional -$refresh parameter to it. - -0 = Neither character set is a Unicode encoding. - -1 = National character set is a Unicode encoding. - -2 = Database character set is a Unicode encoding. - -3 = Both character sets are Unicode encodings. - -=head3 B +=head1 DATABASE HANDLE ATTRIBUTES -Returns true if the current connection supports TAF events. False if otherise. - -=head3 B - -Returns a hash reference containing the current NLS parameters, as given -by the v$nls_parameters view. The values fetched are cached between calls. -To cause the latest values to be fetched, pass a true value to the function. - - -=head2 Database Handle Attributes - -=head3 B (boolean) +=head2 B (boolean) Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change in the future, so it is highly recommended that you explicitly set it when calling L. -=head3 B (boolean) +=head2 B (boolean) $dbh->{ReadOnly} = 1; @@ -2818,29 +2495,29 @@ issuing commands such as INSERT, UPDATE, or DELETE. This method method requires DBI version 1.55 or better. -=head3 B (string, read-only) +=head2 B (string, read-only) Returns the name of the current database. This is the same as the DSN, without the "dbi:Oracle:" part. -=head3 B (string, read-only) +=head2 B (string, read-only) Returns the name of the user connected to the database. -=head3 B (handle, read-only) +=head2 B (handle, read-only) Holds the handle of the parent driver. The only recommended use for this is to find the name of the driver using: $dbh->{Driver}->{Name} -=head3 B +=head2 B DBD::Oracle supports both Server pre-fetch and Client side row caching. By default both are turned on to give optimum performance. Most of the time one can just let DBD::Oracle figure out the best optimization. -=head4 B +=head3 B Row caching occurs on the client side and the object of it is to cut down the number of round trips made to the server when fetching rows. At each fetch a set number of rows will be retrieved @@ -2858,7 +2535,7 @@ By default C is automatically set. If you want to totally turn off For any SQL statement that contains a LOB, Long or Object Type Row Caching will be turned off. However server side caching still works. If you are only selecting a LOB Locator then Row Caching will still work. -=head4 Row Prefetching +=head3 Row Prefetching Row prefetching occurs on the server side and uses the DBI database handle attribute C and or the Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improved performance. @@ -2884,12 +2561,19 @@ If the ora_prefetch_memory less than 1 or not present then memory size is not in number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it is not included in the computing of the prefetch rows. +=head1 ORACLE-SPECIFIC STATEMENT HANDLE METHODS + +=head2 B + +Returns the OCI Statement Type number for the SQL of a statement handle. + +=head2 B -=head1 DBI Statement Handle Object +Returns the OCI Statement Type name for the SQL of a statement handle. -=head2 Statement Handle Methods +=head1 DBI STATEMENT HANDLE OBJECT METHODS -=head3 B +=head2 B $rv = $sth->bind_param($param_num, $bind_value); $rv = $sth->bind_param($param_num, $bind_value, $bind_type); @@ -3061,2232 +2745,2220 @@ I even if C is false! Set L to 0 in prepare() to enable this behaviour. -=head3 Spaces & Padding - -=head4 Trailing Spaces - -Please note that only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder -values and uses Nonpadded Comparison Semantics with the result. -This causes trouble if the spaces are needed for -comparison with a CHAR value or to prevent the value from -becoming '' which Oracle treats as NULL. -Look for Blank-padded Comparison Semantics and Nonpadded -Comparison Semantics in Oracle's SQL Reference or Server -SQL Reference for more details. - -To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, -either change the default placeholder type with L or the placeholder -type for a particular call to L or L -with L or C. -Using L with L or C with C -allows the placeholder to be used with Padded Comparison Semantics -if the value it is being compared to is a CHAR, NCHAR, or literal. - -Please remember that using spaces as a value or at the end of -a value makes visually distinguishing values with different -numbers of spaces difficult and should be avoided. - -Oracle Clients that use OCI 9.2 do not strip trailing spaces. +=head2 B -=head4 Padded Char Fields + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); -Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. -As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will -have to change the default placeholder type with L or placeholder -type for a particular call with L or L -with L. -=head4 Unicode +DBD::Oracle fully supports bind_param_inout below are some uses for this method. -DBD::Oracle now supports Unicode UTF-8. There are, however, a number -of issues you should be aware of, so please read all this section -carefully. -In this section we'll discuss "Perl and Unicode", then "Oracle and -Unicode", and finally "DBD::Oracle and Unicode". +=head3 B -Information about Unicode in general can be found at: -L. It is well worth reading because there are -many misconceptions about Unicode and you may be holding some of them. +Oracle supports an extended SQL insert syntax which will return one +or more of the values inserted. This can be particularly useful for +single-pass insertion of values with re-used sequence values +(avoiding a separate "select seq.nextval from dual" step). -=head4 Perl and Unicode + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; -Perl began implementing Unicode with version 5.6, but the implementation -did not mature until version 5.8 and later. If you plan to use Unicode -you are I urged to use Perl 5.8.2 or later and to I read -the Perl documentation on Unicode: +If you have many columns to bind you can use code like this: - perldoc perluniintro # in Perl 5.8 or later - perldoc perlunicode + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; -And then read it again. +If you have many rows to insert you can take advantage of Oracle's built in execute array feature +with code like this: -Perl's internal Unicode format is UTF-8 -which corresponds to the Oracle character set called AL32UTF8. + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } -=head4 Oracle and Unicode +Which will return all the ids into @out_values. -Oracle supports many characters sets, including several different forms -of Unicode. These include: +=over - AL16UTF16 => valid for NCHAR columns (CSID=2000) - UTF8 => valid for NCHAR columns (CSID=871), deprecated - AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) +=item B -When you create an Oracle database, you must specify the DATABASE -character set (used for DDL, DML and CHAR datatypes) and the NATIONAL -character set (used for NCHAR and NCLOB types). -The character sets used in your database can be found using: +=item This will only work for numbered (?) placeholders, - $hash_ref = $dbh->ora_nls_parameters() - $database_charset = $hash_ref->{NLS_CHARACTERSET}; - $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; +=item The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle -The Oracle 9.2 and later default for the national character set is AL16UTF16. -The default for the database character set is often US7ASCII. -Although many experienced DBAs will consider an 8bit character set like -WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle -other than US7ASCII, requires that the NLS_LANG environment variable be set. -See the L<"Oracle UTF8 is not UTF-8"> section below. +=item The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. +=back -You are strongly urged to read the Oracle Internationalization documentation -specifically with respect the choices and trade offs for creating -a databases for use with international character sets. +=head3 Returning A Recordset -Oracle uses the NLS_LANG environment variable to indicate what -character set is being used on the client. When fetching data Oracle -will convert from whatever the database character set is to the client -character set specified by NLS_LANG. Similarly, when sending data to -the database Oracle will convert from the character set specified by -NLS_LANG to the database character set. +DBD::Oracle does not currently support binding a PL/SQL table (aka array) +as an IN OUT parameter to any Perl data structure. You cannot therefore call +a PL/SQL function or procedure from DBI that uses a non-atomic datatype as +either a parameter, or a return value. However, if you are using Oracle 9.0.1 +or later, you can make use of table (or pipelined) functions. -The NLS_NCHAR environment variable can be used to define a different -character set for 'national' (NCHAR) character types. +For example, assume you have the existing PL/SQL Package : -Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. -For example: + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; - NLS_LANG=AMERICAN_AMERICA.UTF8 - NLS_LANG=AMERICAN_AMERICA.AL32UTF8 - NLS_NCHAR=UTF8 - NLS_NCHAR=AL32UTF8 + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / -=head4 Oracle UTF8 is not UTF-8 +Currently, there is no way to directly call the function +Array_Example.Array_Func from DBI. However, by making the following relatively +painless additions, its not only possible, but extremely efficient. -AL32UTF8 should be used in preference to UTF8 if it works for you, -which it should for Oracle 9.2 or later. If you're using an old -version of Oracle that doesn't support AL32UTF8 then you should -avoid using any Unicode characters that require surrogates, in other -words characters beyond the Unicode BMP (Basic Multilingual Plane). +First, you need to create database object types that correspond to the record +and table types in the package. From the above example, these would be : -That's because the character set that Oracle calls "UTF8" doesn't -conform to the UTF-8 standard in its handling of surrogate characters. -Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". -Here are a couple of extracts from L: + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; - CESU-8 is useful in 8-bit processing environments where binary - collation with UTF-16 is required. It is designed and recommended - for use only within products requiring this UTF-16 binary collation - equivalence. It is not intended nor recommended for open interchange. + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; - As a very small percentage of characters in a typical data stream - are expected to be supplementary characters, there is a strong - possibility that CESU-8 data may be misinterpreted as UTF-8. - Therefore, all use of CESU-8 outside closed implementations is - strongly discouraged, such as the emittance of CESU-8 in output - files, markup language or other open transmission forms. +Now, assuming the existing function needs to remain unchanged (it is probably +being called from other PL/SQL code), we need to add a new function to the +package. Here's the new package specification and body : -Oracle uses this internally because it collates (sorts) in the same order -as UTF16, which is the basis of Oracle's internal collation definitions. + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; -Rather than change UTF8 for clients Oracle chose to define a new character -set called "AL32UTF8" which does conform to the UTF-8 standard. -(The AL32UTF8 character set can't be used on the server because it -would break collation.) + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; -Because of that, for the rest of this document we'll use "AL32UTF8". -If you're using an Oracle version below 9.2 you'll need to use "UTF8" -until you upgrade. + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; -=head4 DBD::Oracle and Unicode +As you can see, the new function is very simple. Now, it is a simple matter +of calling the function as a straight-forward SELECT from your DBI code. From +the above example, the code would look something like this : -DBD::Oracle Unicode support has been implemented for Oracle versions 9 -or greater, and Perl version 5.6 or greater (though we I -suggest that you use Perl 5.8.2 or later). + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } -You can check which Oracle version your DBD::Oracle was built with by -importing the C constant from DBD::Oracle. -B -Any data returned from Oracle to DBD::Oracle in the AL32UTF8 -character set will be marked as UTF-8 to ensure correct handling by Perl. -For Oracle to return data in the AL32UTF8 character set the -NLS_LANG or NLS_NCHAR environment variable I be set as described -in the previous section. -When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle -will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR -is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. +=head3 B -When fetching other character data from Oracle, DBD::Oracle -will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. +DBD::Oracle has built-in support for B +and B datatypes. The simple example is here: -B + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; -Data bound to a placeholder is assumed to be in the default client -character set (specified by NLS_LANG) except for a few special -cases. These are listed here with the highest precedence first: + my $sth=$dbh->prepare( $statement ); -If the C attribute is given to bind_param() then that -is passed to Oracle and takes precedence. + my @arr=( "abc","efg","hij" ); -If the value is a Perl Unicode string (UTF-8) then DBD::Oracle -ensures that Oracle uses the Unicode character set, regardless of -the NLS_LANG and NLS_NCHAR settings. + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; -If the placeholder is for inserting an NCLOB then the client NLS_NCHAR -character set is used. (That's useful but inconsistent with the other behaviour -so may change. Best to be explicit by using the C -attribute.) +=over -If the C attribute is given to bind_param() then that -determines if the value should be assumed to be in the default -(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. +=item B +=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' + will only take a reference to a scalar. - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); - ... - $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); +=back -or - $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders -Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to -insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert -will still happen but a error code of 0 will be returned with the following warning; +=head3 B - DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. - The Query charset id=1, name=US7ASCII +SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. +( in bind_param() and bind_param_inout() ). When you bind array, you need +to specify full buffer size for OUT data. So, there are two parameters: +I (specified as 3rd argument of bind_param_inout() ), +and I. They define maximum array entry length and +maximum rows, that can be passed to Oracle and back to you. In this +example we send array with 1 element with length=3, but allocate space for 100 +Oracle array entries with maximum length 10 of each. So, you can get no more +than 100 array entries with length <= 10. -The warning will report the parameter number and the NCHAR setting that the query is running. +If you set I to zero, maximum array entry length is calculated +as maximum length of entry of array bound. If 0 < I < length( $some_element ), +truncation occur. -B +If you set I to zero, current (at bind time) bound +array length is used as maximum. If 0 < I < scalar(@array), +not all array entries are bound. -Oracle assumes the SQL statement is in the default client character -set (as specified by NLS_LANG). So Unicode strings containing -non-ASCII characters should not be used unless the default client -character set is AL32UTF8. +=head3 B -=head4 DBD::Oracle and Other Character Sets and Encodings +SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. +The main difference is internal data representation. Currently 2 types of +bind is allowed : as C-integer, or as C-double type. To select one of them, +you may specify additional bind parameter I as either +B or B for C-integer and C-double types. +Integer size is architecture-specific and is usually 32 or 64 bit. +Double is standard IEEE 754 type. -The only multi-byte Oracle character set supported by DBD::Oracle is -"AL32UTF8" (and "UTF8"). Single-byte character sets should work well. +I defaults to double (SQLT_FLT). -=head4 Other Data Types +I is ignored for OCI_NUMBER_TABLE. -DBD::Oracle does not I support most Oracle datatypes. -It simply asks Oracle to return them as strings and Oracle does so. -Mostly. Similarly when binding placeholder values DBD::Oracle binds -them as strings and Oracle converts them to the appropriate type, -such as DATE, when used. +Currently, you cannot bind full native Oracle NUMBER(38). If you really need, +send request to dbi-dev list. -Some of these automatic conversions to and from strings use NLS -settings to control the formatting for output and the parsing for -input. The most common example is the DATE type. The default NLS -format for DATE might be DD-MON-YYYY and so when a DATE type is -fetched that's how Oracle will format the date. NLS settings also -control the default parsing of strings into DATE values. An error -will be generated if the contents of the string don't match the -NLS format. If you're dealing in dates which don't match the default -NLS format then you can either change the default NLS format or, more -commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") -to explicitly specify formats for converting to and from strings. +The usage example is here: -A slightly more subtle problem can occur with NUMBER types. The -default NLS settings might format numbers with a fullstop ("C<.>") -to separate thousands and a comma ("C<,>") as the decimal point. -Perl will generate warnings and use incorrect values when numbers, -returned and formatted as strings in this way by Oracle, are used -in a numeric context. You could explicitly convert each numeric -value using the TO_CHAR(...) function but that gets tedious very -quickly. The best fix is to change the NLS settings. That can be -done for an individual connection by doing: + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; - $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + $sth=$dbh->prepare( $statement ); -There are some types, like BOOLEAN, that Oracle does not automatically -convert to or from strings (pity). These need to be converted -explicitly using SQL or PL/SQL functions. + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + @arr=( 1,"2E0","3.5" ); -Examples: + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } - # DATE values - my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) - SQL_END - $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; - # BOOLEAN values - my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); - $sth2->bind_param( ":i1", $i1 ); - $sth2->bind_param_inout( ":o0", \$o0, 32 ); - $sth2->bind_param_inout( ":o1", \$o1, 32 ); - $sth2->execute(); - foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { - $_ = "(undef)" if ! defined $_; - } - print "$i0 to $o0, $i1 to $o1\n"; - # Result is : "'' to '(undef)', 'Something else' to '1'" +If you change bind type to B, like: + ora_internal_type => SQLT_INT -=head4 Object & Collection Data Types +you get: -Oracle databases allow for the creation of object oriented like user-defined types. -There are two types of objects, Embedded--an object stored in a column of a regular table -and REF--an object that uses the REF retrieval mechanism. + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; -DBD::Oracle supports only the 'selection' of embedded objects of the following types OBJECT, VARRAY -and TABLE in any combination. Support is seamless and recursive, meaning you -need only supply a simple SQL statement to get all the values in an embedded object. -You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. +=head2 B +DBD::Oracle supports this undocumented feature of DBI. See L for an example. -Array example, given this type and table; - CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); +=head2 B - CREATE TABLE "CONTACT" - ( "COMPANYNAME" VARCHAR2(40), - "ADDRESS" VARCHAR2(100), - "PHONE_NUMBERS" "PHONE_NUMBERS" - ) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) -The code to access all the data in the table could be something like this; +Binds an array of values to a placeholder, so that each is used in turn by a call +to the L method. - my $sth = $dbh->prepare('SELECT * FROM CONTACT'); - $sth->execute; - while ( my ($company, $address, $phone) = $sth->fetchrow()) { - print "Company: ".$company."\n"; - print "Address: ".$address."\n"; - print "Phone #: "; - foreach my $items (@$phone){ - print $items.", "; - } - print "\n"; - } -Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. +=head2 B -As stated before DBD::Oracle will automatically drill into the embedded object and extract -all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an -SQL TABLE; + $rv = $sth->execute(@bind_values); - CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; +Perform whatever processing is necessary to execute the prepared statement. - CREATE OR REPLACE TYPE STUDENT AS OBJECT( - NAME VARCHAR2(60), - SOME_GRADES GRADELIST); +=head2 B - CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; - CREATE TABLE GROUPS( - GRP_ID NUMBER(4), - GRP_NAME VARCHAR2(10), - STUDENTS STUDENTS_T) - NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB - (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; -The following code will access all of the embedded data; +Execute a prepared statement once for each item in a passed-in hashref, or items that +were previously bound via the L method. See the DBI documentation +for more details. - $SQL='select grp_id,grp_name,students as my_students_test from groups'; - $sth=$dbh->prepare($SQL); - $sth->execute(); - while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ - print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; - foreach my $student (@$students){ - print "Name:".$student->[0]."\n"; - print "Marks:"; - foreach my $grades (@$student->[1]){ - foreach my $marks (@$grades){ - print $marks.","; - } - } - print "\n"; - } - print "\n"; - } +DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very +quickly. -Object example, given this object and table; +=head2 B - CREATE OR REPLACE TYPE Person AS OBJECT ( - name VARCHAR2(20), - age INTEGER) - ) NOT FINAL; + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); - CREATE TYPE Employee UNDER Person ( - salary NUMERIC(8,2) - ); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); - CREATE TABLE people (id INTEGER, obj Person); +Used internally by the L method, and rarely used directly. See the +DBI documentation for more details. - INSERT INTO people VALUES (1, Person('Black', 25)); - INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); +=head2 B -The following code will access the data; + $ary_ref = $sth->fetchrow_arrayref; - $dbh{'ora_objects'} =>1; +Fetches the next row of data from the statement handle, and returns a reference to an array +holding the column values. Any columns that are NULL are returned as undef within the array. - $sth = $dbh->prepare("select * from people order by id"); - $sth->execute(); +If there are no more rows or if an error occurs, the this method return undef. You should +check C<< $sth->err >> afterwards (or use the L attribute) to discover if the undef returned +was due to an error. - # object are fetched as instance of DBD::Oracle::Object - my ($id1, $obj1) = $sth->fetchrow(); - my ($id2, $obj2) = $sth->fetchrow(); +Note that the same array reference is returned for each fetch, so don't store the reference and +then use it after a later fetch. Also, the elements of the array are also reused for each row, +so take care if you want to take a reference to an element. See also L. - # get full type-name of object - print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed - print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed +=head2 B - # get attribute NAME from object - print $obj1->attr('NAME')."3\n"; # 'Black' is printed - print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + @ary = $sth->fetchrow_array; - # get all atributes as hash reference - my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} - my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, - # 'SALARY' => 5000 } +Similar to the L method, but returns a list of column information rather than +a reference to a list. Do not use this in a scalar context. - # get all attributes (names and values) as array - my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) - my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, - # 'SALARY', 5000 ) +=head2 B -So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables -nested to 10 levels. + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); -Any NULL values found in the embedded object will be returned as 'undef'. +Fetches the next row of data and returns a hashref containing the name of the columns as the keys +and the data itself as the values. Any NULL value is returned as as undef value. -=head4 Support for Insert of XMLType (ORA_XMLTYPE) +If there are no more rows or if an error occurs, the this method return undef. You should +check C<< $sth->err >> afterwards (or use the L attribute) to discover if the undef returned +was due to an error. -Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special -requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For -example with a table like this; +The optional C<$name> argument should be either C, C or C, and indicates +what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. - create table books (book_id number, book_xml XMLType); +=head2 B -one can insert data using this code + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); - $SQL='insert into books values (1,:p_xml)'; - $xml= ' - - Programming the Perl DBI - The Cheetah Book - - T. Bunce - Alligator Descartes - +Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the +statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, +the data read in so far will be returned. Because of this, you should always check C<< $sth->err >> after +calling this method, unless L has been enabled. - - ... - '; - my $sth =$dbh-> prepare($SQL); - $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); - $sth-> execute(); +If C<$slice> is an array reference, fetchall_arrayref uses the L method to fetch each +row as an array ref. If the C<$slice> array is not empty then it is used as a slice to select individual +columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). -In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. -This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. +With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. -=head4 Binding Cursors +If C<$slice> is a hash reference, fetchall_arrayref uses L to fetch each row as a hash reference. -Cursors can be returned from PL/SQL blocks, either from stored -functions (or procedures with OUT parameters) or -from direct C statements, as shown below: +See the DBI documentation for a complete discussion. - use DBI; - use DBD::Oracle qw(:ora_types); - my $dbh = DBI->connect(...); - my $sth1 = $dbh->prepare(q{ - BEGIN OPEN :cursor FOR - SELECT table_name, tablespace_name - FROM user_tables WHERE tablespace_name = :space; - END; - }); - $sth1->bind_param(":space", "USERS"); - my $sth2; - $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); - $sth1->execute; - # $sth2 is now a valid DBI statement handle for the cursor - while ( my @row = $sth2->fetchrow_array ) { ... } +=head2 B -The only special requirement is the use of C with an -attribute hash parameter that specifies C as C. -If you don't do that you'll get an error from the C like: -"ORA-06550: line X, column Y: PLS-00306: wrong number or types of -arguments in call to ...". + $hash_ref = $sth->fetchall_hashref( $key_field ); -Here's an alternative form using a function that returns a cursor. -This example uses the pre-defined weak (or generic) REF CURSOR type -SYS_REFCURSOR. This is an Oracle 9 feature. +Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for +a full discussion. - # Create the function that returns a cursor - $dbh->do(q{ - CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR - AS l_cursor SYS_REFCURSOR; - BEGIN - OPEN l_cursor FOR select ename, empno from emp - ORDER BY ename; - RETURN l_cursor; - END; - }); +=head2 B - # Use the function that returns a cursor - my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); - my $sth2; - $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); - $sth1->execute; - # $sth2 is now a valid DBI statement handle for the cursor - while ( my @row = $sth2->fetchrow_array ) { ... } + $rv = $sth->finish; -A cursor obtained from PL/SQL as above may be passed back to PL/SQL -by binding for input, as shown in this example, which explicitly -closes a cursor: +Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed +when you have not fetched all the possible rows. - my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); - $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); - $sth3->execute; +=head2 B -It is not normally necessary to close a cursor -explicitly in this way. Oracle will close the cursor automatically -at the first client-server interaction after the cursor statement handle is -destroyed. An explicit close may be desirable if the reference to -the cursor handle from the PL/SQL statement handle delays the destruction -of the cursor handle for too long. This reference remains until the -PL/SQL handle is re-bound, re-executed or destroyed. + $rv = $sth->rows; -See the C script in the Oracle.ex directory in the DBD::Oracle -source distribution for a complete working example. +Returns the number of rows affected for updates, deletes and inserts and -1 for selects. -=head4 Fetching Nested Cursors +=head2 B -Oracle supports the use of select list expressions of type REF CURSOR. -These may be explicit cursor expressions - C, or -calls to PL/SQL functions which return REF CURSOR values. The values -of these expressions are known as nested cursors. + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); -The value returned to a Perl program when a nested cursor is fetched -is a statement handle. This statement handle is ready to be fetched from. -It should not (indeed, must not) be executed. +Binds a Perl variable and/or some attributes to an output column of a SELECT statement. +Column numbers count up from 1. You do not need to bind output columns in order to fetch data. -Oracle imposes a restriction on the order of fetching when nested -cursors are used. Suppose C<$sth1> is a handle for a select statement -involving nested cursors, and C<$sth2> is a nested cursor handle fetched -from C<$sth1>. C<$sth2> can only be fetched from while C<$sth1> is -still active, and the row containing C<$sth2> is still current in C<$sth1>. -Any attempt to fetch another row from C<$sth1> renders all nested cursor -handles previously fetched from C<$sth1> defunct. +NOTE: DBD::Oracle does not use the C<$bind_type> to determine how to +bind the column; it uses what Oracle says the data type is. You can +however set a numeric bind type with the bind attributes +StrictlyTyped/DiscardString as these attributes are applied after the +column is retrieved. -Fetching from such a defunct handle results in an error with the message -C. +See the DBI documentation for a discussion of the optional parameters C<\%attr> and C<$bind_type> -This means that the C or C methods are not useful -for queries returning nested cursors. By the time such a method returns, -all the nested cursor handles it has fetched will be defunct. +=head2 B -It is necessary to use an explicit fetch loop, and to do all the -fetching of nested cursors within the loop, as the following example -shows: + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); - use DBI; - my $dbh = DBI->connect(...); - my $sth = $dbh->prepare(q{ - SELECT dname, CURSOR( - SELECT ename FROM emp - WHERE emp.deptno = dept.deptno - ORDER BY ename - ) FROM dept ORDER BY dname - }); - $sth->execute; - while ( my ($dname, $nested) = $sth->fetchrow_array ) { - print "$dname\n"; - while ( my ($ename) = $nested->fetchrow_array ) { - print " $ename\n"; - } - } +Calls the L method for each column in the SELECT statement, using the supplied list. +=head2 B -The cursor returned by the function C defined in the -previous section can be fetched as a nested cursor as follows: + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); - my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); - $sth->execute; - my ($nested) = $sth->fetchrow_array; - while ( my @row = $nested->fetchrow_array ) { ... } +Fetches all the rows from the statement handle, calls C for each row, and +prints the results to C<$fh> (which defaults to F). Rows are separated by C<$lsep> (which defaults +to a newline). Columns are separated by C<$fsep> (which defaults to a comma). The C<$maxlen> controls +how wide the output can be, and defaults to 35. -=head4 Pre-fetching Nested Cursors +This method is designed as a handy utility for prototyping and testing queries. Since it uses +"neat_list" to format and edit the string for reading by humans, it is not recommended +for data transfer applications. -By default, DBD::Oracle pre-fetches rows in order to reduce the number of -round trips to the server. For queries which do not involve nested cursors, -the number of pre-fetched rows is controlled by the DBI database handle -attribute C (q.v.). +=head1 STATEMENT HANDLE ATTRIBUTES -In Oracle, server side open cursors are a controlled resource, limited in -number, on a per session basis, to the value of the initialization -parameter C. Nested cursors count towards this limit. -Each nested cursor in the current row counts 1, as does -each nested cursor in a pre-fetched row. Defunct nested cursors do not count. +=head2 B (integer, read-only) -An Oracle specific database handle attribute, C, -further controls pre-fetching for queries involving nested cursors. For -each statement handle, the total number of nested cursors in pre-fetched -rows is limited to the value of this parameter. The default value -is 0, which disables pre-fetching for queries involving nested cursors. +Returns the number of columns returned by the current statement. A number will only be returned for +SELECT statements for INSERT, +UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before C. +=head2 B (integer, read-only) -=head3 B +Returns the number of placeholders in the current statement. - $rv = $sth->bind_param_inout($param_num, \$scalar, 0); +=head2 B (arrayref, read-only) +Returns an arrayref of column names for the current statement. This +method will only work for SELECT statements, for SHOW statements, and for +INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before C. -DBD::Oracle fully supports bind_param_inout below are some uses for this method. +=head2 B (arrayref, read-only) +The same as the C attribute, except that all column names are forced to lower case. -=head4 B +=head2 B (arrayref, read-only) -Oracle supports an extended SQL insert syntax which will return one -or more of the values inserted. This can be particularly useful for -single-pass insertion of values with re-used sequence values -(avoiding a separate "select seq.nextval from dual" step). +The same as the C attribute, except that all column names are forced to upper case. - $sth = $dbh->prepare(qq{ - INSERT INTO foo (id, bar) - VALUES (foo_id_seq.nextval, :bar) - RETURNING id INTO :id - }); - $sth->bind_param(":bar", 42); - $sth->bind_param_inout(":id", \my $new_id, 99); - $sth->execute; - print "The id of the new record is $new_id\n"; - -If you have many columns to bind you can use code like this: - - @params = (... column values for record to be inserted ...); - $sth->bind_param($_, $params[$_-1]) for (1..@params); - $sth->bind_param_inout(@params+1, \my $new_id, 99); - $sth->execute; +=head2 B (hashref, read-only) -If you have many rows to insert you can take advantage of Oracle's built in execute array feature -with code like this: +Similar to the C attribute, but returns a hashref of column names instead of an arrayref. The names of the columns +are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. +This method returns undef if called before C. - my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); - my @out_values; - my @status; - my $sth = $dbh->prepare(qq{ - INSERT INTO foo (id, bar) - VALUES (foo_id_seq.nextval, ?) - RETURNING id INTO ? - }); - $sth->bind_param_array(1,\@in_values); - $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); - $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; - foreach my $id (@out_values){ - print 'returned id='.$id.'\n'; - } +=head2 B (hashref, read-only) -Which will return all the ids into @out_values. +The same as the C attribute, except that all column names are forced to lower case. -=over +=head2 B (hashref, read-only) -=item B +The same as the C attribute, except that all column names are forced to lower case. -=item This will only work for numbered (?) placeholders, +=head2 B (arrayref, read-only) -=item The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle +Returns an arrayref indicating the data type for each column in the statement. +This method returns undef if called before C. -=item The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. +=head2 B (arrayref, read-only) -=back +Returns an arrayref of integer values for each column returned by the statement. +The number indicates the precision for C columns, the size in number of +characters for C and C columns, and for all other types of columns +it returns the number of I. +This method returns undef if called before C. -=head4 Returning A Recordset +=head2 B (arrayref, read-only) -DBD::Oracle does not currently support binding a PL/SQL table (aka array) -as an IN OUT parameter to any Perl data structure. You cannot therefore call -a PL/SQL function or procedure from DBI that uses a non-atomic datatype as -either a parameter, or a return value. However, if you are using Oracle 9.0.1 -or later, you can make use of table (or pipelined) functions. +Returns an arrayref of integer values for each column returned by the statement. The number +indicates the scale of the that column. The only type that will return a value is C. +This method returns undef if called before C. -For example, assume you have the existing PL/SQL Package : +=head2 B (arrayref, read-only) - CREATE OR REPLACE PACKAGE Array_Example AS - -- - TYPE tRec IS RECORD ( - Col1 NUMBER, - Col2 VARCHAR2 (10), - Col3 DATE) ; - -- - TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; - -- - FUNCTION Array_Func RETURN taRec ; - -- - END Array_Example ; +Returns an arrayref of integer values for each column returned by the statement. The number +indicates if the column is nullable or not. 0 = not nullable, 1 = nullable, 2 = unknown. +This method returns undef if called before C. - CREATE OR REPLACE PACKAGE BODY Array_Example AS - -- - FUNCTION Array_Func RETURN taRec AS - -- - l_Ret taRec ; - -- - BEGIN - FOR i IN 1 .. 5 LOOP - l_Ret (i).Col1 := i ; - l_Ret (i).Col2 := 'Row : ' || i ; - l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; - END LOOP ; - RETURN l_Ret ; - END ; - -- - END Array_Example ; - / +=head2 B (dbh, read-only) -Currently, there is no way to directly call the function -Array_Example.Array_Func from DBI. However, by making the following relatively -painless additions, its not only possible, but extremely efficient. +Returns the database handle this statement handle was created from. -First, you need to create database object types that correspond to the record -and table types in the package. From the above example, these would be : +=head2 B (hash ref, read-only) - CREATE OR REPLACE TYPE tArray_Example__taRec - AS OBJECT ( - Col1 NUMBER, - Col2 VARCHAR2 (10), - Col3 DATE - ) ; +Returns a reference to a hash containing the values currently bound to placeholders. If the "named parameters" +type of placeholders are being used (such as ":foo"), then the keys of the hash will be the names of the +placeholders (without the colon). If the "dollar sign numbers" type of placeholders are being used, the keys of the hash will +be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, +starting at one and increasing for every placeholder. - CREATE OR REPLACE TYPE taArray_Example__taRec - AS TABLE OF tArray_Example__taRec ; +If this method is called before L, the literal values passed in are returned. If called after +L, then the quoted versions of the values are returned. -Now, assuming the existing function needs to remain unchanged (it is probably -being called from other PL/SQL code), we need to add a new function to the -package. Here's the new package specification and body : +=head2 B (hash ref, read-only) - CREATE OR REPLACE PACKAGE Array_Example AS - -- - TYPE tRec IS RECORD ( - Col1 NUMBER, - Col2 VARCHAR2 (10), - Col3 DATE) ; - -- - TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; - -- - FUNCTION Array_Func RETURN taRec ; - FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; - -- - END Array_Example ; +Returns a reference to a hash containing the type names currently bound to placeholders. The keys +are the same as returned by the ParamValues method. The values are hashrefs containing a single key value +pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can +only be expressed by a Postgres type. The value is the internal number corresponding to the type originally +passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of +ParamTypes to be passed back to the L method. - CREATE OR REPLACE PACKAGE BODY Array_Example AS - -- - FUNCTION Array_Func RETURN taRec AS - l_Ret taRec ; - BEGIN - FOR i IN 1 .. 5 LOOP - l_Ret (i).Col1 := i ; - l_Ret (i).Col2 := 'Row : ' || i ; - l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; - END LOOP ; - RETURN l_Ret ; - END ; +=head2 B (string, read-only) - FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS - l_Set taRec ; - BEGIN - l_Set := Array_Func ; - FOR i IN l_Set.FIRST .. l_Set.LAST LOOP - PIPE ROW ( - tArray_Example__taRec ( - l_Set (i).Col1, - l_Set (i).Col2, - l_Set (i).Col3 - ) - ) ; - END LOOP ; - RETURN ; - END ; - -- - END Array_Example ; +Returns the statement string passed to the most recent "prepare" method called in this database handle, even if that method +failed. This is especially useful where "RaiseError" is enabled and the exception handler checks $@ and sees that a C +method call failed. -As you can see, the new function is very simple. Now, it is a simple matter -of calling the function as a straight-forward SELECT from your DBI code. From -the above example, the code would look something like this : +=head2 B - my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); - $sth->execute; - while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { - ... - } +Returns the number of un-fetched rows in the cache for selects. +=head1 SCROLLABLE CURSORS +Oracle supports the concept of a 'Scrollable Cursor' which is defined as a 'Result Set' where +the rows can be fetched either sequentially or non-sequentially. One can fetch rows forward, +backwards, from any given position or the n-th row from the current position in the result set. +Rows are numbered sequentially starting at one and client-side caching of the partial or entire result set +can improve performance by limiting round trips to the server. +Oracle does not support DML type operations with scrollable cursors so you are limited +to simple 'Select' operations only. As well you can not use this functionality with remote +mapped queries or if the LONG datatype is part of the select list. -=head4 B +However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch methods. -DBD::Oracle has built-in support for B -and B datatypes. The simple example is here: +Only use scrollable cursors if you really have a good reason to. They do use up considerable +more server and client resources and have poorer response times than non-scrolling cursors. - my $statement=' - DECLARE - tbl SYS.DBMS_SQL.VARCHAR2_TABLE; - BEGIN - tbl := :mytable; - :cc := tbl.count(); - tbl(1) := \'def\'; - tbl(2) := \'ijk\'; - :mytable := tbl; - END; - '; - my $sth=$dbh->prepare( $statement ); +=head2 Enabling Scrollable Cursors - my @arr=( "abc","efg","hij" ); +To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; - $sth->bind_param_inout(":mytable", \\@arr, 10, { - ora_type => ORA_VARCHAR2_TABLE, - ora_maxarray_numentries => 100 - } ) ; - $sth->bind_param_inout(":cc", \$cc, 100 ); - $sth->execute(); - print "Result: cc=",$cc,"\n", - "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); -=over +Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the +statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; -=item B + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); -=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' - will only take a reference to a scalar. +When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row +or you can still use any of the other fetch methods but with a poorer response time than if you used a +non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. -=back +=head2 Scrollable Cursor Methods +The following driver-specific methods are used with scrollable cursors. -=head4 B +=over -SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. -( in bind_param() and bind_param_inout() ). When you bind array, you need -to specify full buffer size for OUT data. So, there are two parameters: -I (specified as 3rd argument of bind_param_inout() ), -and I. They define maximum array entry length and -maximum rows, that can be passed to Oracle and back to you. In this -example we send array with 1 element with length=3, but allocate space for 100 -Oracle array entries with maximum length 10 of each. So, you can get no more -than 100 array entries with length <= 10. +=item ora_scroll_position -If you set I to zero, maximum array entry length is calculated -as maximum length of entry of array bound. If 0 < I < length( $some_element ), -truncation occur. + $position = $sth->ora_scroll_position(); -If you set I to zero, current (at bind time) bound -array length is used as maximum. If 0 < I < scalar(@array), -not all array entries are bound. +This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time +this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. +The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. -=head4 B +=item ora_fetch_scroll -SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. -The main difference is internal data representation. Currently 2 types of -bind is allowed : as C-integer, or as C-double type. To select one of them, -you may specify additional bind parameter I as either -B or B for C-integer and C-double types. -Integer size is architecture-specific and is usually 32 or 64 bit. -Double is standard IEEE 754 type. + @ary = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); -I defaults to double (SQLT_FLT). +Works the same as fetchrow_array method however, one passes in a 'Fetch Orientation' constant and a fetch_offset +value which will then determine the row that will be fetched. It returns the row as a list containing the field values. +Null fields are returned as undef values in the list. -I is ignored for OCI_NUMBER_TABLE. +The valid orientation constant and fetch offset values combination are detailed below -Currently, you cannot bind full native Oracle NUMBER(38). If you really need, -send request to dbi-dev list. + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. -The usage example is here: + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. - $statement=' - DECLARE - tbl SYS.DBMS_SQL.NUMBER_TABLE; - BEGIN - tbl := :mytable; - :cc := tbl(2); - tbl(4) := -1; - tbl(5) := -2; - :mytable := tbl; - END; - '; + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. - $sth=$dbh->prepare( $statement ); +The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. - if( ! defined($sth) ){ - die "Prepare error: ",$dbh->errstr,"\n"; - } + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. - @arr=( 1,"2E0","3.5" ); + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. - # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . - if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { - ora_type => ORA_NUMBER_TABLE, - ora_maxarray_numentries => (scalar(@arr)+2), - ora_internal_type => SQLT_FLT - } ) ){ - die "bind :mytable error: ",$dbh->errstr,"\n"; - } - $cc=undef; - if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ - die "bind :cc error: ",$dbh->errstr,"\n"; - } +The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. - if( not $sth->execute() ){ - die "Execute failed: ",$dbh->errstr,"\n"; - } - print "Result: cc=",$cc,"\n", - "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. -The result is like: + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. - Result: cc=2 - arr=$VAR1 = [ - '1', - '2', - '3.5', - '-1', - '-2' - ]; +=back -If you change bind type to B, like: +=head2 Scrollable Cursor Usage - ora_internal_type => SQLT_INT +Given a simple code like this: -you get: + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; - Result: cc=2 - arr=$VAR1 = [ - 1, - 2, - 3, - -1, - -2 - ]; +and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll +method; -=head3 B +=over -DBD::Oracle supports this undocumented feature of DBI. See L for an example. +=item Fetching the Last Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -=head3 B +The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +if the record set is large this could take some time. - $rv = $sth->bind_param_array($param_num, $array_ref_or_value) - $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) - $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) +=item Fetching the Current Row -Binds an array of values to a placeholder, so that each is used in turn by a call -to the L method. + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; +The current_positon attribute will still be 20 after this snippet. +=item Fetching the First Row -=head3 B + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; - $rv = $sth->execute(@bind_values); +The current_positon attribute will be 1 after this snippet. -Perform whatever processing is necessary to execute the prepared statement. +=item Fetching the Next Row -=head3 B + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; - $tuples = $sth->execute_array() or die $sth->errstr; - $tuples = $sth->execute_array(\%attr) or die $sth->errstr; - $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; +The current_positon attribute will be 5 after this snippet. - ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; - ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; +=item Fetching the Prior Row -Execute a prepared statement once for each item in a passed-in hashref, or items that -were previously bound via the L method. See the DBI documentation -for more details. + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; -DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very -quickly. +The current_positon attribute will be 1 after this snippet. -=head3 B +=item Fetching the 10th Row - $tuples = $sth->execute_for_fetch($fetch_tuple_sub); - $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; - ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); - ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); +The current_positon attribute will be 10 after this snippet. -Used internally by the L method, and rarely used directly. See the -DBI documentation for more details. +=item Fetching the 10th to 14th Row -=head3 B + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; - $ary_ref = $sth->fetchrow_arrayref; +The current_positon attribute will be 14 after this snippet. -Fetches the next row of data from the statement handle, and returns a reference to an array -holding the column values. Any columns that are NULL are returned as undef within the array. +=item Fetching the 14th to 10th Row -If there are no more rows or if an error occurs, the this method return undef. You should -check C<< $sth->err >> afterwards (or use the L attribute) to discover if the undef returned -was due to an error. + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; -Note that the same array reference is returned for each fetch, so don't store the reference and -then use it after a later fetch. Also, the elements of the array are also reused for each row, -so take care if you want to take a reference to an element. See also L. +The current_positon attribute will be 10 after this snippet. -=head3 B +=item Fetching the 5th Row From the Present Position. - @ary = $sth->fetchrow_array; + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -Similar to the L method, but returns a list of column information rather than -a reference to a list. Do not use this in a scalar context. +The current_positon attribute will be 15 after this snippet. -=head3 B +=item Fetching the 9th Row Prior From the Present Position - $hash_ref = $sth->fetchrow_hashref; - $hash_ref = $sth->fetchrow_hashref($name); + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -Fetches the next row of data and returns a hashref containing the name of the columns as the keys -and the data itself as the values. Any NULL value is returned as as undef value. +The current_positon attribute will be 6 after this snippet. -If there are no more rows or if an error occurs, the this method return undef. You should -check C<< $sth->err >> afterwards (or use the L attribute) to discover if the undef returned -was due to an error. +=item Use Finish -The optional C<$name> argument should be either C, C or C, and indicates -what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. + $sth->finish(); -=head3 B +When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of +cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. - $tbl_ary_ref = $sth->fetchall_arrayref(); - $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); - $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); +=back -Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the -statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, -the data read in so far will be returned. Because of this, you should always check C<< $sth->err >> after -calling this method, unless L has been enabled. +=head1 LOBS AND LONGS -If C<$slice> is an array reference, fetchall_arrayref uses the L method to fetch each -row as an array ref. If the C<$slice> array is not empty then it is used as a slice to select individual -columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). +The key to working with LOBs (CLOB, BLOBs) is to remember the value of an Oracle LOB column is not the content of the LOB. It's a +'LOB Locator' which, after being selected or inserted needs extra processing to read or write the content of the LOB. There are also legacy LONG types (LONG, LONG RAW, VARCHAR2) +which are presently deprecated by Oracle but are still in use. These LONG types do not utilize a 'LOB Locator' and also are more limited in +functionality than CLOB or BLOB fields. -With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. +DBD::Oracle now offers three interfaces to LOB and LONG data, -If C<$slice> is a hash reference, fetchall_arrayref uses L to fetch each row as a hash reference. +=over -See the DBI documentation for a complete discussion. +=item L -=head3 B +With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of +BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. - $hash_ref = $sth->fetchall_hashref( $key_field ); +=item L -Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for -a full discussion. - -=head3 B +With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. - $rv = $sth->finish; +=item L -Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed -when you have not fetched all the possible rows. +This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. -=head3 B +=back - $rv = $sth->rows; +Generally speaking the interface that you will chose will be dependent on what end you are trying to achieve. All have their benefits and +drawbacks. -Returns the number of rows affected for updates, deletes and inserts and -1 for selects. +One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB column can be in one of three states; -=head3 B +=over - $rv = $sth->bind_col($column_number, \$var_to_bind); - $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); - $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); +=item NULL -Binds a Perl variable and/or some attributes to an output column of a SELECT statement. -Column numbers count up from 1. You do not need to bind output columns in order to fetch data. +The table cell is created, but the cell holds no locator or value. +If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a -NOTE: DBD::Oracle does not use the C<$bind_type> to determine how to -bind the column; it uses what Oracle says the data type is. You can -however set a numeric bind type with the bind attributes -StrictlyTyped/DiscardString as these attributes are applied after the -column is retrieved. + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr -See the DBI documentation for a discussion of the optional parameters C<\%attr> and C<$bind_type> +error when working with a LOB. -=head3 B +You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; - $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. -Calls the L method for each column in the SELECT statement, using the supplied list. +=item Empty -=head3 B +A LOB instance with a locator exists in the cell, but it has no value. The length of the LOB is zero. In this case DBD::Oracle will return 'undef' for the field. - $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); +=item Populated -Fetches all the rows from the statement handle, calls C for each row, and -prints the results to C<$fh> (which defaults to F). Rows are separated by C<$lsep> (which defaults -to a newline). Columns are separated by C<$fsep> (which defaults to a comma). The C<$maxlen> controls -how wide the output can be, and defaults to 35. +A LOB instance with a locator and a value exists in the cell. You actually get the LOB value. -This method is designed as a handy utility for prototyping and testing queries. Since it uses -"neat_list" to format and edit the string for reading by humans, it is not recommended -for data transfer applications. +=back +=head2 Data Interface for Persistent LOBs -=head2 Private Statement Handle Methods +This is the original interface for LONG and LONG RAW datatypes and from Oracle 9iR1 and later the OCI API was extended to work directly with the other LOB datatypes. +In other words you can treat all LOB type data (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using the same techniques +you would use on other datatypes that store character or binary data. In some cases there are fewer round trips to the server as no 'LOB Locators' are +used, normally one can get an entire LOB is a single round trip. -=head3 B +=head3 Simple Fetch for LONGs and LONG RAWs -Returns the OCI Statement Type number for the SQL of a statement handle. +As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG datatypes as a single large piece. +There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. +If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into +an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. -=head3 B +For example give this table; -Returns the OCI Statement Type name for the SQL of a statement handle. + CREATE TABLE test_long ( + id NUMBER, + long1 long) -=head2 Statement Handle Attributes +this code; -=head3 B (integer, read-only) + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } -Returns the number of columns returned by the current statement. A number will only be returned for -SELECT statements for INSERT, -UPDATE, and DELETE statements which contain a RETURNING clause. -This method returns undef if called before C. +Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; -=head3 B (integer, read-only) + $dbh->{LongTruncOk}=1; -Returns the number of placeholders in the current statement. +before the execute will return all the long1 fields but they will be truncated at 2MBs. -=head3 B (arrayref, read-only) +=head3 Using ora_ncs_buff_mtpl -Returns an arrayref of column names for the current statement. This -method will only work for SELECT statements, for SHOW statements, and for -INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. -This method returns undef if called before C. +When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the +Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. +Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. -=head3 B (arrayref, read-only) +However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer +value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes +but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes +(maybe less characters though) but you are using allot more memory that you need. -The same as the C attribute, except that all column names are forced to lower case. +You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can +also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. -=head3 B (arrayref, read-only) +The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the +ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. -The same as the C attribute, except that all column names are forced to upper case. +If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; -=head3 B (hashref, read-only) + ORA-03127: no new operations allowed until the active operation ends -Similar to the C attribute, but returns a hashref of column names instead of an arrayref. The names of the columns -are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. -This method returns undef if called before C. +This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) -=head3 B (hashref, read-only) +If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. -The same as the C attribute, except that all column names are forced to lower case. +This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. -=head3 B (hashref, read-only) +You can tune this value by setting ora_oci_success_warn which will display the following -The same as the C attribute, except that all column names are forced to lower case. + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) -=head3 B (arrayref, read-only) +In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. -Returns an arrayref indicating the data type for each column in the statement. -This method returns undef if called before C. -=head3 B (arrayref, read-only) +=head3 Simple Fetch for CLOBs and BLOBs -Returns an arrayref of integer values for each column returned by the statement. -The number indicates the precision for C columns, the size in number of -characters for C and C columns, and for all other types of columns -it returns the number of I. -This method returns undef if called before C. +To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well +set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds +the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. -=head3 B (arrayref, read-only) +For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this +and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. -Returns an arrayref of integer values for each column returned by the statement. The number -indicates the scale of the that column. The only type that will return a value is C. -This method returns undef if called before C. +It seems with BLOBs you are not limited by the 64k. -=head3 B (arrayref, read-only) +For example give this table; -Returns an arrayref of integer values for each column returned by the statement. The number -indicates if the column is nullable or not. 0 = not nullable, 1 = nullable, 2 = unknown. -This method returns undef if called before C. + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) -=head3 B (dbh, read-only) +this code; -Returns the database handle this statement handle was created from. + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } -=head3 B (hash ref, read-only) +Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; -Returns a reference to a hash containing the values currently bound to placeholders. If the "named parameters" -type of placeholders are being used (such as ":foo"), then the keys of the hash will be the names of the -placeholders (without the colon). If the "dollar sign numbers" type of placeholders are being used, the keys of the hash will -be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, -starting at one and increasing for every placeholder. + $dbh->{LongTruncOk}=1; -If this method is called before L, the literal values passed in are returned. If called after -L, then the quoted versions of the values are returned. +before the execute will return all the lobs but they will be truncated at 2MBs. -=head3 B (hash ref, read-only) +=head3 Piecewise Fetch with Callback -Returns a reference to a hash containing the type names currently bound to placeholders. The keys -are the same as returned by the ParamValues method. The values are hashrefs containing a single key value -pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can -only be expressed by a Postgres type. The value is the internal number corresponding to the type originally -passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of -ParamTypes to be passed back to the L method. +With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. +To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the L and L the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is +dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. -=head3 B (string, read-only) +Using the table from the last example this code; -Returns the statement string passed to the most recent "prepare" method called in this database handle, even if that method -failed. This is especially useful where "RaiseError" is enabled and the exception handler checks $@ and sees that a C -method call failed. + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } -=head3 B +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. -Returns the number of un-fetched rows in the cache for selects. +Using the table from the first example (LONG) this code; -=head2 Scrollable Cursors + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } -Oracle supports the concept of a 'Scrollable Cursor' which is defined as a 'Result Set' where -the rows can be fetched either sequentially or non-sequentially. One can fetch rows forward, -backwards, from any given position or the n-th row from the current position in the result set. +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. -Rows are numbered sequentially starting at one and client-side caching of the partial or entire result set -can improve performance by limiting round trips to the server. +=head4 Piecewise Fetch with Polling -Oracle does not support DML type operations with scrollable cursors so you are limited -to simple 'Select' operations only. As well you can not use this functionality with remote -mapped queries or if the LONG datatype is part of the select list. +With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' +attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the L and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the L. -However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch methods. +Using the table from the example above this code; -Only use scrollable cursors if you really have a good reason to. They do use up considerable -more server and client resources and have poorer response times than non-scrolling cursors. + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. -=head3 B +Finally with this code; -To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } - use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. -Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the -statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; +=head3 Binding for Updates and Inserts for CLOBs and BLOBs - $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); - -When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row -or you can still use any of the other fetch methods but with a poorer response time than if you used a -non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. +To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method +'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; -=head3 B + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); -The following driver-specific methods are used with scrollable cursors. +So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. -=over +=head3 Support for Remote LOBs; -=item ora_scroll_position +Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; - $position = $sth->ora_scroll_position(); + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; -This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time -this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. -The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. +to a remote database called 'test_lobs', the following code will work; -=item ora_fetch_scroll + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } - @ary = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); +Below are the limitations of Remote LOBs; -Works the same as fetchrow_array method however, one passes in a 'Fetch Orientation' constant and a fetch_offset -value which will then determine the row that will be fetched. It returns the row as a list containing the field values. -Null fields are returned as undef values in the list. +=over -The valid orientation constant and fetch offset values combination are detailed below +=item Queries involving more than one database are not supported; - OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. - OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value - is ignored. - OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. - OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. - OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset - value is ignored. - OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. - OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the - fetch offset value. +so the following returns an error: - OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. - OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); - OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. - OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. +as does: -The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; - OCI_FETCH_CURRENT, has no effect on the current_positon attribute. - OCI_FETCH_NEXT, increments current_positon attribute by 1 - OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon - attribute, it is equivalent to a OCI_FETCH_CURRENT - OCI_FETCH_FIRST, sets the current_positon attribute to 1. - OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the - record set. - OCI_FETCH_PRIOR, decrements current_positon attribute by 1. - OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon - attribute, it is equivalent to a OCI_FETCH_CURRENT. +=item DDL commands are not supported; - OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. - OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change - current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in - the record set, does not change current_positon attribute, it is - equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + - fetch offset value). - OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, - does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records - in the record set, does not change fetch offset value so it is equivalent - to a OCI_FETCH_CURRENT. +so the following returns an error: -The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; - OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. - OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. - OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon - attribute to the total number of rows in the record set. - OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. - OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. +=item Only binds and defines for data going into remote persistent LOBs are supported. - OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a - OCI_FETCH_CURRENT. - OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of - records in the record set is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent - to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number - of records in the record set, is equivalent to a OCI_FETCH_CURRENT. +so that parameter passing in PL/SQL where CHAR data is bound or defined for remote LOBs is not allowed . -=back +These statements all produce errors: -=head3 B + SELECT foo() FROM table1@dbs2; -Given a simple code like this: + SELECT foo()@dbs INTO char_val FROM DUAL; - use DBI; - use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); - my $dbh = DBI->connect($dsn, $dbuser, ''); - my $SQL = "select id, - first_name, - last_name - from employee"; - my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); - $sth->execute(); - my $value; + SELECT XMLType().getclobval FROM table1@dbs2; -and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll -method; +=item If the remote object is a view such as -=over + CREATE VIEW v AS SELECT foo() FROM ... -=item Fetching the Last Row +the following would not work: - $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + SELECT * FROM v@dbs2; -The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, -if the record set is large this could take some time. +=item Limited PL/SQL parameter passing -=item Fetching the Current Row +PL/SQL parameter passing is not allowed where the actual argument is a LOB type +and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. - $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; +=item RETURNING INTO does not support implicit conversions between CHAR and CLOB. -The current_positon attribute will still be 20 after this snippet. +so the following returns an error: -=item Fetching the First Row + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test - $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; +=back -The current_positon attribute will be 1 after this snippet. +=head2 Locator Data Interface -=item Fetching the Next Row +=head3 Simple Usage - for(my $i=0;$i<=3;$i++){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; +When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob with the LongReadLen and LongTruncOk attributes. +The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. -The current_positon attribute will be 5 after this snippet. +When inserting or updating LOBs some I magic has to be performed +behind the scenes to make it transparent. Basically the driver has to +insert a 'LOB Locator' and then refetch the newly inserted LOB +Locator before being able to write the data into it. However, it works +well most of the time, and I've made it as fast as possible, just one +extra server-round-trip per insert or update after the first. For the +time being, only single-row LOB updates are supported. -=item Fetching the Prior Row +To insert or update a large LOB using a placeholder, DBD::Oracle has to +know in advance that it is a LOB type. So you need to say: - for(my $i=0;$i<=3;$i++){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); -The current_positon attribute will be 1 after this snippet. +The ORA_CLOB and ORA_BLOB constants can be imported using -=item Fetching the 10th Row + use DBD::Oracle qw(:ora_types); - $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; +or use the corresponding integer values (112 and 113). -The current_positon attribute will be 10 after this snippet. +One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has +to be able to tell which parameters relate to which table fields. +In all cases where it can possibly work it out for itself, it does, +however, if there are multiple LOB fields of the same type in the table +then you need to tell it which field each LOB param relates to: -=item Fetching the 10th to 14th Row + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); - for(my $i=10;$i<15;$i++){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; +There are some limitations inherent in the way DBD::Oracle makes typical +LOB operations simple by hiding the LOB Locator processing: -The current_positon attribute will be 14 after this snippet. + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. -=item Fetching the 14th to 10th Row +The alternative is to disable the automatic LOB Locator processing. +If L is 0 in prepare(), you can fetch the LOB Locators and +do all the work yourself using the ora_lob_*() methods. +See the L section below. - for(my $i=14;$i>9;$i--){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; +=head3 LOB support in PL/SQL -The current_positon attribute will be 10 after this snippet. +LOB Locators can be passed to PL/SQL calls by binding them to placeholders +with the proper C. If L is true, output LOB +parameters will be automatically returned as strings. -=item Fetching the 5th Row From the Present Position. +If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), +strings can be bound to input LOB placeholders and will be automatically +converted to LOBs. - $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; +Example: + # Build a large XML document, bind it as a CLOB, + # extract elements through PL/SQL and return as a CLOB -The current_positon attribute will be 15 after this snippet. + # $dbh is a connected database handle + # output will be large -=item Fetching the 9th Row Prior From the Present Position + local $dbh->{LongReadLen} = 1_000_000; - $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; -The current_positon attribute will be 6 after this snippet. + my $out_clob; -=item Use Finish - $sth->finish(); - -When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of -cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. - -=back + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; -=over +If you ever get an -=item L + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt -With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of -BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. +error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. +One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. -=item L +=head2 Persistent & Locator Interface Caveats -With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. +Now that one has the option of using the Persistent or the Locator interface for LOBs the questions arises +which one to use. For starters, if you want to access LOBs over a dblink you will have to use the Persistent +interface so that choice is simple. The question of which one to use after that is a little more tricky. +It basically boils down to a choice between LOB size and speed. -=item L +The Callback and Polling piecewise fetches are very very slow +when compared to the Simple and the Locator fetches but they can handle very large blocks of data. Given a situation where a +large LOB is to be read the Locator fetch may time out while either of the piecewise fetches may not. -This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. +With the Simple fetch you are limited by physical memory of your server but it runs a little faster than the Locator, as there are fewer round trips +to the server. So if you have small LOBs and need to save a little bandwidth this is the one to use. It you are going after large LOBs then the Locator interface is the one to use. -=back +If you need to update more than a single row of with LOB data then the Persistent interface can do it while the Locator can't. -Generally speaking the interface that you will chose will be dependent on what end you are trying to achieve. All have their benefits and -drawbacks. +If you encounter a situation where you have to access the legacy LOBs (LONG, LONG RAW) and the values are to large for you system then you can use +the Callback or Polling piecewise fetches to get all of the data. -One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB column can be in one of three states; +Not all of the Persistent interface has been implemented yet, the following are not supported; -=over + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. -=item NULL +Most of the time you should just use the L as this is in one that has the best combination of speed and size. -The table cell is created, but the cell holds no locator or value. -If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a +All this being said if you are doing some critical programming I would use the L as this gives you very +fine grain control of your LOBs, of course the code for this will be somewhat more involved. - DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr +=head2 Data Interface for LOB Locators -error when working with a LOB. +The following driver-specific methods let you manipulate "LOB Locators" directly. +To select a LOB locator directly set the if the C +attribute to false, or alternatively they can be returned via PL/SQL procedure calls. -You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; +(If using a DBI version earlier than 1.36 they must be called via the +func() method. Note that methods called via func() don't honour +RaiseError etc, and so it's important to check $dbh->err after each call. +It's recommended that you upgrade to DBI 1.38 or later.) - UPDATE lob_example - SET bindata=EMPTY_BLOB() - WHERE bindata IS NULL. +Note that LOB locators are only valid while the statement handle that +created them is valid. When all references to the original statement +handle are lost, the handle is destroyed and the locators are freed. -=item Empty +=over 4 -A LOB instance with a locator exists in the cell, but it has no value. The length of the LOB is zero. In this case DBD::Oracle will return 'undef' for the field. +=item ora_lob_read -=item Populated + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); -A LOB instance with a locator and a value exists in the cell. You actually get the LOB value. +Read a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobRead function. -=back +=item ora_lob_write -=head3 B + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); -This is the original interface for LONG and LONG RAW datatypes and from Oracle 9iR1 and later the OCI API was extended to work directly with the other LOB datatypes. -In other words you can treat all LOB type data (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using the same techniques -you would use on other datatypes that store character or binary data. In some cases there are fewer round trips to the server as no 'LOB Locators' are -used, normally one can get an entire LOB is a single round trip. +Write/overwrite a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobWrite function. -=head4 Simple Fetch for LONGs and LONG RAWs +=item ora_lob_append -As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG datatypes as a single large piece. -There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. -If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. -The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into -an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. + $rc = $dbh->ora_lob_append($lob_locator, $data); -For example give this table; +Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. - CREATE TABLE test_long ( - id NUMBER, - long1 long) +=item ora_lob_trim -this code; + $rc = $dbh->ora_lob_trim($lob_locator, $length); - $dbh->{LongReadLen} = 2*1024*1024; #2 meg - $SQL='select p_id,long1 from test_long'; - $sth=$dbh->prepare($SQL); - $sth->execute(); - while (my ( $p_id,$long )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "long=".$long."\n"; - } +Trims the length of the LOB to $length. +Uses the Oracle OCILobTrim function. -Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; +=item ora_lob_length - $dbh->{LongTruncOk}=1; + $length = $dbh->ora_lob_length($lob_locator); -before the execute will return all the long1 fields but they will be truncated at 2MBs. +Returns the length of the LOB. +Uses the Oracle OCILobGetLength function. -=head4 Using ora_ncs_buff_mtpl -When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the -Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. -Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. +=item ora_lob_is_init -However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer -value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes -but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes -(maybe less characters though) but you are using allot more memory that you need. + $is_init = $dbh->ora_lob_is_init($lob_locator); -You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can -also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. +Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' +if there is an error. +Uses the Oracle OCILobLocatorIsInit function. -The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the -ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. +=item ora_lob_chunk_size -If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); - ORA-03127: no new operations allowed until the active operation ends +Returns the chunk size of the LOB. +Uses the Oracle OCILobGetChunkSize function. -This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) +For optimal performance, Oracle recommends reading from and +writing to a LOB in batches using a multiple of the LOB chunk size. +In Oracle 10g and before, when all defaults are in place, this +chunk size defaults to 8k (8192). -If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. +=back -This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. +=head3 LOB Locator Method Examples -You can tune this value by setting ora_oci_success_warn which will display the following +I Make sure you first read the note in the section above about +multi-byte character set issues with these methods. - OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen - 20(characters), BufLen 80(characters), Got 28(characters) +The following examples demonstrate the usage of LOB Locators +to read, write, and append data, and to query the size of +large data. -In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. +The following examples assume a table containing two large +object columns, one binary and one character, with a primary +key column, defined as follows: + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) -=head4 Simple Fetch for CLOBs and BLOBs +It also assumes a sequence for use in generating unique +lob_id field values, defined as follows: -To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well -set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds -the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. -The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. + CREATE SEQUENCE lob_example_seq -For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this -and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. -It seems with BLOBs you are not limited by the 64k. +=head3 Example: Inserting a new row with large data -For example give this table; +Unless enough memory is available to store and bind the +entire LOB data for insert all at once, the LOB columns must +be written interactively, piece by piece. In the case of a new row, +this is performed by first inserting a row, with empty values in +the LOB columns, then modifying the row by writing the large data +interactively to the LOB columns using their LOB locators as handles. - CREATE TABLE test_lob (id NUMBER, - clob1 CLOB, - clob2 CLOB, - blob1 BLOB, - blob2 BLOB) +The insert statement must create token values in the LOB +columns. Here, we use the empty string for both the binary +and character large object columns 'bindata' and 'chardata'. -this code; +After the INSERT statement, a SELECT statement is used to +acquire LOB locators to the 'bindata' and 'chardata' fields +of the newly inserted row. Because these LOB locators are +subsequently written, they must be acquired from a select +statement containing the clause 'FOR UPDATE' (LOB locators +are only valid within the transaction that fetched them, so +can't be used effectively if AutoCommit is enabled). - $dbh->{LongReadLen} = 2*1024*1024; #2 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; - $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL -Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); - $dbh->{LongTruncOk}=1; + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); -before the execute will return all the lobs but they will be truncated at 2MBs. + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); -=head4 Piecewise Fetch with Callback + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } -With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. -To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that -you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected -size of the LOB. Like the L and L the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB -or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on -the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is -dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs -in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. - -Using the table from the last example this code; + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } - $dbh->{LongReadLen} = 20*1024*1024; #20 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; - $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } -Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. +In this example we demonstrate the use of ora_lob_write() +interactively to append data to the columns 'bin_data' and +'char_data'. Had we used ora_lob_append(), we could have +saved ourselves the trouble of keeping track of the offset +into the lobs. The snippet of code beneath the comment +'BEGIN WRITING BIN_DATA COLUMN' could look as follows: -Using the table from the first example (LONG) this code; + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } - $dbh->{LongReadLen} = 20*1024*1024; #2 meg - $SQL='select p_id,long1 from test_long'; - $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$long )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "long=".$long."\n"; - } +The scalar variables $offset and $length are no longer +needed, because ora_lob_append() keeps track of the offset +for us. -Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. -=head4 Piecewise Fetch with Polling +=head3 Example: Updating an existing row with large data -With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' -attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that -you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected -size of the LOB. Like the L and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB -or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on -the L. +In this example, we demonstrate a technique for overwriting +a portion of a blob field with new binary data. The blob +data before and after the section overwritten remains +unchanged. Hence, this technique could be used for updating +fixed length subfields embedded in a binary field. -Using the table from the example above this code; + my $lob_id = 5; # Arbitrary row identifier, for example - $dbh->{LongReadLen} = 20*1024*1024; #20 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; - $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); -Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); -Finally with this code; +After running this code, the row where lob_id = 5 will +contain, starting at position 100234 in the bin_data column, +the string "This string will overwrite a portion of the blob". - $dbh->{LongReadLen} = 20*1024*1024; #2 meg - $SQL='select p_id,long1 from test_long'; - $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$long )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "long=".$long."\n"; - } +=head3 Example: Streaming character data from the database -Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. +In this example, we demonstrate a technique for streaming +data from the database to a file handle, in this case +STDOUT. This allows more data to be read in and written out +than could be stored in memory at a given time. -=head4 Binding for Updates and Inserts for CLOBs and BLOBs + my $lob_id = 17; # Arbitrary row identifier, for example -To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method -'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); - my $in_clob = "\n"; - $in_clob .= " $_\n" for 1 .. 10_000; - $in_clob .= "\n"; - my $in_blob ="0101" for 1 .. 10_000; + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } - $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; - $sth=$dbh->prepare($SQL ); - $sth->bind_param(1,3); - $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); - $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); - $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); - $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); - $sth->execute(); +Notice that the select statement does not contain the phrase +"FOR UPDATE". Because we are only reading from the LOB +Locator returned, and not modifying the LOB it refers to, +the select statement does not require the "FOR UPDATE" +clause. -So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. +A word of caution when using the data returned from an ora_lob_read in a conditional statement. +for example if the code below; -=head4 Support for Remote LOBs; + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } -Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; +was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return +the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte +as $data will contain 0 which PERL will see as false and not print it out. - CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; +=head3 Example: Truncating existing large data -to a remote database called 'test_lobs', the following code will work; +In this example, we truncate the data already present in a +large object column in the database. Specifically, for each +row in the table, we truncate the 'bindata' value to half +its previous length. - $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); - $dbh->{LongReadLen} = 2*1024*1024; #2 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; - $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } +After acquiring a LOB Locator for the column, we query its +length, then we trim the length by half. Because we modify +the large objects with the call to ora_lob_trim(), we must +select the LOB locators 'FOR UPDATE'. -Below are the limitations of Remote LOBs; + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } -=over +=head1 SPACES AND PADDING -=item Queries involving more than one database are not supported; +=head2 Trailing Spaces -so the following returns an error: +Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder +values and uses Nonpadded Comparison Semantics with the result. +This causes trouble if the spaces are needed for +comparison with a CHAR value or to prevent the value from +becoming '' which Oracle treats as NULL. +Look for Blank-padded Comparison Semantics and Nonpadded +Comparison Semantics in Oracle's SQL Reference or Server +SQL Reference for more details. - SELECT t1.lobcol, - a2.lobcol - FROM t1, - t2.lobcol@dbs2 a2 W - WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); +To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, +either change the default placeholder type with L or the placeholder +type for a particular call to L or L +with L or C. +Using L with L or C with C +allows the placeholder to be used with Padded Comparison Semantics +if the value it is being compared to is a CHAR, NCHAR, or literal. -as does: +Please remember that using spaces as a value or at the end of +a value makes visually distinguishing values with different +numbers of spaces difficult and should be avoided. - SELECT t1.lobcol - FROM t1@dbs1 - UNION ALL - SELECT t2.lobcol - FROM t2@dbs2; +Oracle Clients that use OCI 9.2 do not strip trailing spaces. -=item DDL commands are not supported; +=head2 Padded Char Fields -so the following returns an error: +Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. +As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will +have to change the default placeholder type with L or placeholder +type for a particular call with L or L +with L. - CREATE VIEW v AS SELECT lob_col FROM tab@dbs; +=head1 UNICODE -=item Only binds and defines for data going into remote persistent LOBs are supported. +DBD::Oracle now supports Unicode UTF-8. There are, however, a number +of issues you should be aware of, so please read all this section +carefully. -so that parameter passing in PL/SQL where CHAR data is bound or defined for remote LOBs is not allowed . +In this section we'll discuss "Perl and Unicode", then "Oracle and +Unicode", and finally "DBD::Oracle and Unicode". -These statements all produce errors: +Information about Unicode in general can be found at: +L. It is well worth reading because there are +many misconceptions about Unicode and you may be holding some of them. - SELECT foo() FROM table1@dbs2; +=head2 Perl and Unicode - SELECT foo()@dbs INTO char_val FROM DUAL; +Perl began implementing Unicode with version 5.6, but the implementation +did not mature until version 5.8 and later. If you plan to use Unicode +you are I urged to use Perl 5.8.2 or later and to I read +the Perl documentation on Unicode: - SELECT XMLType().getclobval FROM table1@dbs2; + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode -=item If the remote object is a view such as +And then read it again. - CREATE VIEW v AS SELECT foo() FROM ... +Perl's internal Unicode format is UTF-8 +which corresponds to the Oracle character set called AL32UTF8. -the following would not work: +=head2 Oracle and Unicode - SELECT * FROM v@dbs2; +Oracle supports many characters sets, including several different forms +of Unicode. These include: -=item Limited PL/SQL parameter passing - -PL/SQL parameter passing is not allowed where the actual argument is a LOB type -and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) -=item RETURNING INTO does not support implicit conversions between CHAR and CLOB. +When you create an Oracle database, you must specify the DATABASE +character set (used for DDL, DML and CHAR datatypes) and the NATIONAL +character set (used for NCHAR and NCLOB types). +The character sets used in your database can be found using: -so the following returns an error: + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; - SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test +The Oracle 9.2 and later default for the national character set is AL16UTF16. +The default for the database character set is often US7ASCII. +Although many experienced DBAs will consider an 8bit character set like +WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle +other than US7ASCII, requires that the NLS_LANG environment variable be set. +See the L<"Oracle UTF8 is not UTF-8"> section below. -=back -=head3 B +You are strongly urged to read the Oracle Internationalization documentation +specifically with respect the choices and trade offs for creating +a databases for use with international character sets. -=head4 Simple Usage +Oracle uses the NLS_LANG environment variable to indicate what +character set is being used on the client. When fetching data Oracle +will convert from whatever the database character set is to the client +character set specified by NLS_LANG. Similarly, when sending data to +the database Oracle will convert from the character set specified by +NLS_LANG to the database character set. -When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob with the LongReadLen and LongTruncOk attributes. -The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs -in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. +The NLS_NCHAR environment variable can be used to define a different +character set for 'national' (NCHAR) character types. -When inserting or updating LOBs some I magic has to be performed -behind the scenes to make it transparent. Basically the driver has to -insert a 'LOB Locator' and then refetch the newly inserted LOB -Locator before being able to write the data into it. However, it works -well most of the time, and I've made it as fast as possible, just one -extra server-round-trip per insert or update after the first. For the -time being, only single-row LOB updates are supported. +Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. +For example: -To insert or update a large LOB using a placeholder, DBD::Oracle has to -know in advance that it is a LOB type. So you need to say: + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 - $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); +=head2 Oracle UTF8 is not UTF-8 -The ORA_CLOB and ORA_BLOB constants can be imported using +AL32UTF8 should be used in preference to UTF8 if it works for you, +which it should for Oracle 9.2 or later. If you're using an old +version of Oracle that doesn't support AL32UTF8 then you should +avoid using any Unicode characters that require surrogates, in other +words characters beyond the Unicode BMP (Basic Multilingual Plane). - use DBD::Oracle qw(:ora_types); +That's because the character set that Oracle calls "UTF8" doesn't +conform to the UTF-8 standard in its handling of surrogate characters. +Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". +Here are a couple of extracts from L: -or use the corresponding integer values (112 and 113). + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. -One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has -to be able to tell which parameters relate to which table fields. -In all cases where it can possibly work it out for itself, it does, -however, if there are multiple LOB fields of the same type in the table -then you need to tell it which field each LOB param relates to: + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. - $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); +Oracle uses this internally because it collates (sorts) in the same order +as UTF16, which is the basis of Oracle's internal collation definitions. -There are some limitations inherent in the way DBD::Oracle makes typical -LOB operations simple by hiding the LOB Locator processing: +Rather than change UTF8 for clients Oracle chose to define a new character +set called "AL32UTF8" which does conform to the UTF-8 standard. +(The AL32UTF8 character set can't be used on the server because it +would break collation.) - - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) - - To INSERT a LOB, you need UPDATE privilege. +Because of that, for the rest of this document we'll use "AL32UTF8". +If you're using an Oracle version below 9.2 you'll need to use "UTF8" +until you upgrade. -The alternative is to disable the automatic LOB Locator processing. -If L is 0 in prepare(), you can fetch the LOB Locators and -do all the work yourself using the ora_lob_*() methods. -See the L section below. +=head2 DBD::Oracle and Unicode -=head4 LOB support in PL/SQL +DBD::Oracle Unicode support has been implemented for Oracle versions 9 +or greater, and Perl version 5.6 or greater (though we I +suggest that you use Perl 5.8.2 or later). -LOB Locators can be passed to PL/SQL calls by binding them to placeholders -with the proper C. If L is true, output LOB -parameters will be automatically returned as strings. +You can check which Oracle version your DBD::Oracle was built with by +importing the C constant from DBD::Oracle. -If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), -strings can be bound to input LOB placeholders and will be automatically -converted to LOBs. +B -Example: - # Build a large XML document, bind it as a CLOB, - # extract elements through PL/SQL and return as a CLOB +Any data returned from Oracle to DBD::Oracle in the AL32UTF8 +character set will be marked as UTF-8 to ensure correct handling by Perl. - # $dbh is a connected database handle - # output will be large +For Oracle to return data in the AL32UTF8 character set the +NLS_LANG or NLS_NCHAR environment variable I be set as described +in the previous section. - local $dbh->{LongReadLen} = 1_000_000; +When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR +is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. - my $in_clob = "\n"; - $in_clob .= " $_\n" for 1 .. 10_000; - $in_clob .= "\n"; +When fetching other character data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. - my $out_clob; +B +Data bound to a placeholder is assumed to be in the default client +character set (specified by NLS_LANG) except for a few special +cases. These are listed here with the highest precedence first: - my $sth = $dbh->prepare(< attribute is given to bind_param() then that +is passed to Oracle and takes precedence. - PLSQL_END +If the value is a Perl Unicode string (UTF-8) then DBD::Oracle +ensures that Oracle uses the Unicode character set, regardless of +the NLS_LANG and NLS_NCHAR settings. - # :in param will be converted to a temp lob - # :out parameter will be returned as a string. +If the placeholder is for inserting an NCLOB then the client NLS_NCHAR +character set is used. (That's useful but inconsistent with the other behaviour +so may change. Best to be explicit by using the C +attribute.) - $sth->bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); - $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); - $sth->execute; +If the C attribute is given to bind_param() then that +determines if the value should be assumed to be in the default +(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. -If you ever get an - ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); -error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. -One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. +or -=head3 B + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders -Now that one has the option of using the Persistent or the Locator interface for LOBs the questions arises -which one to use. For starters, if you want to access LOBs over a dblink you will have to use the Persistent -interface so that choice is simple. The question of which one to use after that is a little more tricky. -It basically boils down to a choice between LOB size and speed. +Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to +insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert +will still happen but a error code of 0 will be returned with the following warning; -The Callback and Polling piecewise fetches are very very slow -when compared to the Simple and the Locator fetches but they can handle very large blocks of data. Given a situation where a -large LOB is to be read the Locator fetch may time out while either of the piecewise fetches may not. + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII -With the Simple fetch you are limited by physical memory of your server but it runs a little faster than the Locator, as there are fewer round trips -to the server. So if you have small LOBs and need to save a little bandwidth this is the one to use. It you are going after large LOBs then the Locator interface is the one to use. +The warning will report the parameter number and the NCHAR setting that the query is running. -If you need to update more than a single row of with LOB data then the Persistent interface can do it while the Locator can't. +B -If you encounter a situation where you have to access the legacy LOBs (LONG, LONG RAW) and the values are to large for you system then you can use -the Callback or Polling piecewise fetches to get all of the data. +Oracle assumes the SQL statement is in the default client character +set (as specified by NLS_LANG). So Unicode strings containing +non-ASCII characters should not be used unless the default client +character set is AL32UTF8. -Not all of the Persistent interface has been implemented yet, the following are not supported; +=head2 DBD::Oracle and Other Character Sets and Encodings - 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. - 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. +The only multi-byte Oracle character set supported by DBD::Oracle is +"AL32UTF8" (and "UTF8"). Single-byte character sets should work well. -Most of the time you should just use the L as this is in one that has the best combination of speed and size. +=head1 OBJECT & COLLECTION DATA TYPES -All this being said if you are doing some critical programming I would use the L as this gives you very -fine grain control of your LOBs, of course the code for this will be somewhat more involved. +Oracle databases allow for the creation of object oriented like user-defined types. +There are two types of objects, Embedded--an object stored in a column of a regular table +and REF--an object that uses the REF retrieval mechanism. -=head3 B +DBD::Oracle supports only the 'selection' of embedded objects of the following types OBJECT, VARRAY +and TABLE in any combination. Support is seamless and recursive, meaning you +need only supply a simple SQL statement to get all the values in an embedded object. +You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. -The following driver-specific methods let you manipulate "LOB Locators" directly. -To select a LOB locator directly set the if the C -attribute to false, or alternatively they can be returned via PL/SQL procedure calls. -(If using a DBI version earlier than 1.36 they must be called via the -func() method. Note that methods called via func() don't honour -RaiseError etc, and so it's important to check $dbh->err after each call. -It's recommended that you upgrade to DBI 1.38 or later.) +Array example, given this type and table; -Note that LOB locators are only valid while the statement handle that -created them is valid. When all references to the original statement -handle are lost, the handle is destroyed and the locators are freed. + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); -=over 4 + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) -=item ora_lob_read +The code to access all the data in the table could be something like this; - $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; -Read a portion of the LOB. $offset starts at 1. -Uses the Oracle OCILobRead function. + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } -=item ora_lob_write +Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. - $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); +As stated before DBD::Oracle will automatically drill into the embedded object and extract +all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an +SQL TABLE; -Write/overwrite a portion of the LOB. $offset starts at 1. -Uses the Oracle OCILobWrite function. + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; -=item ora_lob_append + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); - $rc = $dbh->ora_lob_append($lob_locator, $data); + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; -Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); -=item ora_lob_trim +The following code will access all of the embedded data; - $rc = $dbh->ora_lob_trim($lob_locator, $length); + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } -Trims the length of the LOB to $length. -Uses the Oracle OCILobTrim function. +Object example, given this object and table; -=item ora_lob_length + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; - $length = $dbh->ora_lob_length($lob_locator); + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); -Returns the length of the LOB. -Uses the Oracle OCILobGetLength function. + CREATE TABLE people (id INTEGER, obj Person); + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); -=item ora_lob_is_init +The following code will access the data; - $is_init = $dbh->ora_lob_is_init($lob_locator); + $dbh{'ora_objects'} =>1; -Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' -if there is an error. -Uses the Oracle OCILobLocatorIsInit function. + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); -=item ora_lob_chunk_size + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); - $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed -Returns the chunk size of the LOB. -Uses the Oracle OCILobGetChunkSize function. + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed -For optimal performance, Oracle recommends reading from and -writing to a LOB in batches using a multiple of the LOB chunk size. -In Oracle 10g and before, when all defaults are in place, this -chunk size defaults to 8k (8192). + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } -=back + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) -=head4 LOB Locator Method Examples +So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables +nested to 10 levels. -I Make sure you first read the note in the section above about -multi-byte character set issues with these methods. +Any NULL values found in the embedded object will be returned as 'undef'. -The following examples demonstrate the usage of LOB Locators -to read, write, and append data, and to query the size of -large data. +=head1 OTHER DATA TYPES -The following examples assume a table containing two large -object columns, one binary and one character, with a primary -key column, defined as follows: +DBD::Oracle does not I support most Oracle datatypes. +It simply asks Oracle to return them as strings and Oracle does so. +Mostly. Similarly when binding placeholder values DBD::Oracle binds +them as strings and Oracle converts them to the appropriate type, +such as DATE, when used. - CREATE TABLE lob_example ( - lob_id INTEGER PRIMARY KEY, - bindata BLOB, - chardata CLOB - ) +Some of these automatic conversions to and from strings use NLS +settings to control the formatting for output and the parsing for +input. The most common example is the DATE type. The default NLS +format for DATE might be DD-MON-YYYY and so when a DATE type is +fetched that's how Oracle will format the date. NLS settings also +control the default parsing of strings into DATE values. An error +will be generated if the contents of the string don't match the +NLS format. If you're dealing in dates which don't match the default +NLS format then you can either change the default NLS format or, more +commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") +to explicitly specify formats for converting to and from strings. -It also assumes a sequence for use in generating unique -lob_id field values, defined as follows: +A slightly more subtle problem can occur with NUMBER types. The +default NLS settings might format numbers with a fullstop ("C<.>") +to separate thousands and a comma ("C<,>") as the decimal point. +Perl will generate warnings and use incorrect values when numbers, +returned and formatted as strings in this way by Oracle, are used +in a numeric context. You could explicitly convert each numeric +value using the TO_CHAR(...) function but that gets tedious very +quickly. The best fix is to change the NLS settings. That can be +done for an individual connection by doing: - CREATE SEQUENCE lob_example_seq + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); +There are some types, like BOOLEAN, that Oracle does not automatically +convert to or from strings (pity). These need to be converted +explicitly using SQL or PL/SQL functions. -=head4 Example: Inserting a new row with large data -Unless enough memory is available to store and bind the -entire LOB data for insert all at once, the LOB columns must -be written interactively, piece by piece. In the case of a new row, -this is performed by first inserting a row, with empty values in -the LOB columns, then modifying the row by writing the large data -interactively to the LOB columns using their LOB locators as handles. +Examples: -The insert statement must create token values in the LOB -columns. Here, we use the empty string for both the binary -and character large object columns 'bindata' and 'chardata'. + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); -After the INSERT statement, a SELECT statement is used to -acquire LOB locators to the 'bindata' and 'chardata' fields -of the newly inserted row. Because these LOB locators are -subsequently written, they must be acquired from a select -statement containing the clause 'FOR UPDATE' (LOB locators -are only valid within the transaction that fetched them, so -can't be used effectively if AutoCommit is enabled). + # BOOLEAN values + my $sth2 = $dbh->prepare( <selectrow_array( <<" SQL" ); - SELECT lob_example_seq.nextval FROM DUAL - SQL + FUNCTION to_bool( i VARCHAR2 ) RETURN BOOLEAN IS + BEGIN + IF i IS NULL THEN RETURN NULL; + ELSIF i = 'F' OR i = '0' THEN RETURN FALSE; + ELSE RETURN TRUE; + END IF; + END; + FUNCTION from_bool( i BOOLEAN ) RETURN NUMBER IS + BEGIN + IF i IS NULL THEN RETURN NULL; + ELSIF i THEN RETURN 1; + ELSE RETURN 0; + END IF; + END; + BEGIN + -- Converting values to BOOLEAN + b0 := to_bool( :i0 ); + b1 := to_bool( :i1 ); - my $sth = $dbh->prepare( <<" SQL" ); - INSERT INTO lob_example - ( lob_id, bindata, chardata ) - VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) - SQL - $sth->execute( $lob_id ); + -- Converting values from BOOLEAN + :o0 := from_bool( b0 ); + :o1 := from_bool( b1 ); + END; + PLSQL_END + my ( $i0, $i1, $o0, $o1 ) = ( "", "Something else" ); + $sth2->bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" - $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT bindata, chardata - FROM lob_example - WHERE lob_id = ? - FOR UPDATE - SQL - $sth->execute( $lob_id ); - my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); - $sth->finish(); - open BIN_FH, "/binary/data/source" or die; - open CHAR_FH, "/character/data/source" or die; - my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); +=head4 Support for Insert of XMLType (ORA_XMLTYPE) - # BEGIN WRITING BIN_DATA COLUMN - my $offset = 1; # Offsets start at 1, not 0 - my $length = 0; - my $buffer = ''; - while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { - $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); - $offset += $length; - } +Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special +requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For +example with a table like this; - # BEGIN WRITING CHAR_DATA COLUMN - $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); - $offset = 1; # Offsets start at 1, not 0 - $length = 0; - $buffer = ''; - while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { - $dbh->ora_lob_write( $char_locator, $offset, $buffer ); - $offset += $length; - } + create table books (book_id number, book_xml XMLType); + +one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + +In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. +This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. + +=head4 Binding Cursors + +Cursors can be returned from PL/SQL blocks, either from stored +functions (or procedures with OUT parameters) or +from direct C statements, as shown below: + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } -In this example we demonstrate the use of ora_lob_write() -interactively to append data to the columns 'bin_data' and -'char_data'. Had we used ora_lob_append(), we could have -saved ourselves the trouble of keeping track of the offset -into the lobs. The snippet of code beneath the comment -'BEGIN WRITING BIN_DATA COLUMN' could look as follows: +The only special requirement is the use of C with an +attribute hash parameter that specifies C as C. +If you don't do that you'll get an error from the C like: +"ORA-06550: line X, column Y: PLS-00306: wrong number or types of +arguments in call to ...". - my $buffer = ''; - while ( read( BIN_FH, $buffer, $chunk_size ) ) { - $dbh->ora_lob_append( $bin_locator, $buffer ); - } +Here's an alternative form using a function that returns a cursor. +This example uses the pre-defined weak (or generic) REF CURSOR type +SYS_REFCURSOR. This is an Oracle 9 feature. -The scalar variables $offset and $length are no longer -needed, because ora_lob_append() keeps track of the offset -for us. + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } -=head4 Example: Updating an existing row with large data +A cursor obtained from PL/SQL as above may be passed back to PL/SQL +by binding for input, as shown in this example, which explicitly +closes a cursor: -In this example, we demonstrate a technique for overwriting -a portion of a blob field with new binary data. The blob -data before and after the section overwritten remains -unchanged. Hence, this technique could be used for updating -fixed length subfields embedded in a binary field. + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; - my $lob_id = 5; # Arbitrary row identifier, for example +It is not normally necessary to close a cursor +explicitly in this way. Oracle will close the cursor automatically +at the first client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to +the cursor handle from the PL/SQL statement handle delays the destruction +of the cursor handle for too long. This reference remains until the +PL/SQL handle is re-bound, re-executed or destroyed. - $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT bindata - FROM lob_example - WHERE lob_id = ? - FOR UPDATE - SQL - $sth->execute( $lob_id ); - my ( $bin_locator ) = $sth->fetchrow_array(); +See the C script in the Oracle.ex directory in the DBD::Oracle +source distribution for a complete working example. - my $offset = 100234; - my $data = "This string will overwrite a portion of the blob"; - $dbh->ora_lob_write( $bin_locator, $offset, $data ); +=head4 Fetching Nested Cursors -After running this code, the row where lob_id = 5 will -contain, starting at position 100234 in the bin_data column, -the string "This string will overwrite a portion of the blob". +Oracle supports the use of select list expressions of type REF CURSOR. +These may be explicit cursor expressions - C, or +calls to PL/SQL functions which return REF CURSOR values. The values +of these expressions are known as nested cursors. -=head4 Example: Streaming character data from the database +The value returned to a Perl program when a nested cursor is fetched +is a statement handle. This statement handle is ready to be fetched from. +It should not (indeed, must not) be executed. -In this example, we demonstrate a technique for streaming -data from the database to a file handle, in this case -STDOUT. This allows more data to be read in and written out -than could be stored in memory at a given time. +Oracle imposes a restriction on the order of fetching when nested +cursors are used. Suppose C<$sth1> is a handle for a select statement +involving nested cursors, and C<$sth2> is a nested cursor handle fetched +from C<$sth1>. C<$sth2> can only be fetched from while C<$sth1> is +still active, and the row containing C<$sth2> is still current in C<$sth1>. +Any attempt to fetch another row from C<$sth1> renders all nested cursor +handles previously fetched from C<$sth1> defunct. - my $lob_id = 17; # Arbitrary row identifier, for example +Fetching from such a defunct handle results in an error with the message +C. - $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT chardata - FROM lob_example - WHERE lob_id = ? - SQL - $sth->execute( $lob_id ); - my ( $char_locator ) = $sth->fetchrow_array(); +This means that the C or C methods are not useful +for queries returning nested cursors. By the time such a method returns, +all the nested cursor handles it has fetched will be defunct. - my $chunk_size = 1034; # Arbitrary chunk size, for example - my $offset = 1; # Offsets start at 1, not 0 - while(1) { - my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); - last unless length $data; - print STDOUT $data; - $offset += $chunk_size; - } +It is necessary to use an explicit fetch loop, and to do all the +fetching of nested cursors within the loop, as the following example +shows: -Notice that the select statement does not contain the phrase -"FOR UPDATE". Because we are only reading from the LOB -Locator returned, and not modifying the LOB it refers to, -the select statement does not require the "FOR UPDATE" -clause. + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } -A word of caution when using the data returned from an ora_lob_read in a conditional statement. -for example if the code below; - while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { - print STDOUT $data; - $offset += $chunk_size; - } +The cursor returned by the function C defined in the +previous section can be fetched as a nested cursor as follows: -was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return -the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte -as $data will contain 0 which PERL will see as false and not print it out. + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } -=head4 Example: Truncating existing large data +=head4 Pre-fetching Nested Cursors -In this example, we truncate the data already present in a -large object column in the database. Specifically, for each -row in the table, we truncate the 'bindata' value to half -its previous length. +By default, DBD::Oracle pre-fetches rows in order to reduce the number of +round trips to the server. For queries which do not involve nested cursors, +the number of pre-fetched rows is controlled by the DBI database handle +attribute C (q.v.). -After acquiring a LOB Locator for the column, we query its -length, then we trim the length by half. Because we modify -the large objects with the call to ora_lob_trim(), we must -select the LOB locators 'FOR UPDATE'. +In Oracle, server side open cursors are a controlled resource, limited in +number, on a per session basis, to the value of the initialization +parameter C. Nested cursors count towards this limit. +Each nested cursor in the current row counts 1, as does +each nested cursor in a pre-fetched row. Defunct nested cursors do not count. - my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT bindata - FROM lob_example - FOR UPATE - SQL - $sth->execute(); - while( my ( $bin_locator ) = $sth->fetchrow_array() ) { - my $binlength = $dbh->ora_lob_length( $bin_locator ); - if( $binlength > 0 ) { - $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); - } - } +An Oracle specific database handle attribute, C, +further controls pre-fetching for queries involving nested cursors. For +each statement handle, the total number of nested cursors in pre-fetched +rows is limited to the value of this parameter. The default value +is 0, which disables pre-fetching for queries involving nested cursors. =head1 PL/SQL Examples @@ -5565,37 +5237,75 @@ A git mirror of the subversion is also available at =head1 Oracle Related Links -=head2 DBD::Oracle Tutorial +=head1 WHICH VERSION OF DBD::ORACLE IS FOR ME? + +From version 1.25 onwards DBD::Oracle only support Oracle clients +9.2 or greater. Support for ProC connections was dropped in 1.29. + +If you are still stuck with an older version of Oracle or its client you might want to look at the table below. - http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-oracle.html + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ -=head2 Oracle Instant Client +As there are dozens of different versions of Oracle's clients this +list does not include all of them, just the major released versions of +Oracle. - http://www.oracle.com/technology/tech/oci/instantclient/index.html +Note that one can still connect to any Oracle version with the older +DBD::Oracle versions the only problem you will have is that some of +the newer OCI and Oracle features available in later DBD::Oracle +releases will not be available to you. -=head2 Oracle on Linux +So to make a short story a little longer: - http://www.ixora.com.au/ +=over -=head2 Free Oracle Tools and Links +=item 1 - ora_explain supplied and installed with DBD::Oracle. +If you are using Oracle 7 or early 8 DB and you can manage to get a 9 client and you can use +any DBD::Oracle version. - http://www.orafaq.com/ +=item 2 - http://vonnieda.org/oracletool/ +If you have to use an Oracle 7 client then DBD::Oracle 1.17 should work -=head2 Commercial Oracle Tools and Links +=item 3 -Assorted tools and references for general information. -No recommendation implied. +Same thing for 8 up to R2, use 1.17, if you are lucky and have the right patch-set you might +go with 1.18. - http://www.platinum.com - http://www.SoftTreeTech.com +=item 4 -Also PL/Vision from RevealNet and Steven Feuerstein, and -"Q" from Savant Corporation. +For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. Again this depends on your +patch-set, If you run into trouble go with 1.19 + +=item 5 +After 9.2 you can use any version you want. + +=item 6 + +It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go back to 7 +and even get to 10. I am not sure what the 11g client can connect to. + +=back =head1 BUGS AND LIMITATIONS There is a known problem with the 11.2g Oracle client and the @@ -5605,31 +5315,61 @@ See L for the details. =head1 SEE ALSO -DBI +=over + +=item L http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in the DBD::Oracle source distribution including the examples in the Oracle.ex directory - http://search.cpan.org/search?query=Oracle&mode=dist +=item DBD::Oracle Tutorial -=head1 AUTHOR +http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-oracle.html -DBD::Oracle by Tim Bunce. DBI by Tim Bunce. +=item Oracle Instant Client -=head1 ACKNOWLEDGEMENTS +http://www.oracle.com/technology/tech/oci/instantclient/index.html -A great many people have helped me with DBD::Oracle over the 17 years -between 1994 and 2011. Far too many to name, but I thank them all. -Many are named in the Changes file. +=item Oracle on Linux + +http://www.ixora.com.au/ + +=item Free Oracle Tools and Links + +ora_explain supplied and installed with DBD::Oracle. + +http://www.orafaq.com/ -See also L. +http://vonnieda.org/oracletool/ -=head1 MAINTAINER +=item Commercial Oracle Tools and Links -As of release 1.17 in February 2006 The Pythian Group, Inc. (L) -are taking the lead in maintaining DBD::Oracle with my assistance and -gratitude. That frees more of my time to work on DBI for Perl 5 and Perl 6. +Assorted tools and references for general information. +No recommendation implied. + +http://www.platinum.com + +http://www.SoftTreeTech.com + +Also PL/Vision from RevealNet and Steven Feuerstein, and +"Q" from Savant Corporation. + +=back + +=head1 AUTHORS + +DBI by Tim Bunce L. + +The original C was by Tim Bunce. +Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the +auspice of the Pythian Group (L). + +=head1 ACKNOWLEDGEMENTS + +A great many people have helped with DBD::Oracle over the 17 years +between 1994 and 2011. Far too many to name, but we thank them all. +Many are named in the Changes file. =head1 COPYRIGHT diff --git a/README.linux.txt b/README.linux.txt deleted file mode 100644 index f7361205..00000000 --- a/README.linux.txt +++ /dev/null @@ -1,123 +0,0 @@ -From: John Scoles -Date: April 05 2010 - -The Dreaded "cc1: invalid option `tune=pentium4'" error. - -If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. - -No real problem with the above however you will have to - -1) run Perl Makefile.PL -2) edit the Makefile and remove the ofending '-mtune=pentium4' text -3) save and exit -4) do the make install and it should work fine for you - - - - - -From: John Scoles -Date: Fri, 25 May 2007 - -Installing with Instantclient .rpm files. -Nothing special with this you just have to set up you permissions as follows; - 1) Have permission for RWE on 'usr/lib/oracle/10.2.0.3/client/' or the other directory where you RPMed to - 2) Set export ORACLE_HOME=/usr/lib/oracle/10.2.0.3/client/lib - 3) Set export LD_LIBRARY_PATH=$ORACLE_HOME - 4) You will also have to tell DBD:Oracle where the TNS names is with Export TNS_ADMIN=dir to where your tnsnames.ora file is - -From: William Fishburne -Date: Tue, 20 May 2003 09:22:30 -0400 - -undefined symbol: __cmpdi2 comes up when Oracle isn't properly linked -to the libgcc.a library. - -In version 8, this was correctd by changing the SYSLIBS entry in -$ORACLE_HOME/bin/genclntsh to include -"-L/usr/lib/gcc-lib/i386-redhat-linux/3.2 -lgcc". - -I had tried this with no success as when this program was then run, the -error "unable to find libgcc" was generated. Of course, this was the -library I was trying to describe! - -It turns out that now it is necessary to edit the same file and append -"`gcc -print-libgcc-file-name`" (including the backquotes!). If you do -this and then run "genclntsh", the libclntsh is properly generated and -the linkage with DBD::Oracle proceeds properly. - - - -From: Brent LaVelle -Date: Tue, 2 Sep 2003 11:07:47 -0700 (PDT) -Message-ID: <20030902180747.69838.qmail@web14310.mail.yahoo.com> -Subject: RE: Oracle 9i Lite and DBD::Oracle problems [solved] - -With the help of Brian Haas and Ian Harisay I got DBD::Oracle working. -The advice is to use the regular Oracle9i not the lite version. -Another great source of help was: - http://www.puschitz.com/InstallingOracle9i.html -just getting 9i and 9i lite installed. I use fvwm2(nvidia X driver) as -a window manager which does not work with the 9i install program, works -fine with the default Gnomish(nv X driver), it could have been the X -driver too. - -With Redhat9 it is REAL important to set LD_ASSUME_KERNEL to 2.4.1. - -I didn't try this but it may be possible to install what is needed by -only downloading the first disk saving some 1.3GB of download fun. - -I installed a custom install from the client group. The packages I -installed are the Programmers section and sqlplus. I noticed that the -Pro*C when on as a result of the checking the Programmers section I -assume. - -Once Oracle was installed properly the DBD::Oracle install went as -smooth as just about every other CPAN module. - -I don't know if Oracle is bulletproof on Linux but the install process -has some problems. - - -From: John Scoles -Date: Fri, 29 Sep 2005 10:48:47 -0700 (EST) -Subject: RE: Oracle 10g Instantclient - -The Makefile.PL will now work for Oracle 10g Instantclient. To have both the Compile and -the test.pl to work you must first have the LD_LIBRARY_PATH correctly set to your -"instantclient" directory. (http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html) -The present version of the make creates a link on your "instantclient" directory as follows -"ln -s libclntsh.so.10.1 libclntsh.so". It is needed for both the makefile creation and the compile -but is not need for the test.pl. It should be removed after the compile. -If the Makefile.PL or make fails try creating this link directly in your "instantclient" directory. - -From: John Scoles -Date: Thurs, 19 Jan 2006 11:48:47 -0700 (EST) -Subject: RE: Oracle Database 10g Express Edition 10.2 - -To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY_PATH -as you would for an install against 10g Standard Edition, Standard Edition One, or -Enterprise Edition - -From John Scoles -Date: Fri, 21 July 2006 13:42:47 -0700 (EST) -Subject: UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 - -DBD::Oracle from version 1.16 forward seems to hit some sort of bug with the above two versions of DB. -The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also -been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. - -So far there is no patch for this but here are some work arounds - -use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); -... -$sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); - -or this way - -$dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders - -or this way - -utf8::downgrade($parameter, 1); - - diff --git a/README.login.txt b/README.login.txt deleted file mode 100644 index 35d8f82e..00000000 --- a/README.login.txt +++ /dev/null @@ -1,7 +0,0 @@ -This information is now in the DBD::Oracle module pod documentation. -Use the 'perldoc DBD::Oracle' command to read it. - -Note: The test scripts use the ORACLE_USERID environment variable -to determine who to login as. It's common to use the Oracle demo user -'scott' with the standard password 'tiger', thus ORACLE_USERID can be -set to 'scott/tiger', or set it to your own username and password. diff --git a/README.longs.txt b/README.longs.txt deleted file mode 100644 index 623440d5..00000000 --- a/README.longs.txt +++ /dev/null @@ -1,81 +0,0 @@ -Some examples related to the use of LONG types. - -For complete working code, take a look at the t/long.t file. - ----------------------------------------------------------------------- - -You must fetch the row before you can fetch the longs associated with -that row. In other words, use the following alorithm... - - 1) login - 2) prepare( select ... ) - 3) execute - 4) while rows to fetch do - 5) fetch row - 6) repeat - 7) fetch chunk of long - 8) until have all of it - 9) done - -If your select selects more than one row the need for step 4 may -become a bit clearer... the blob_read always applies to the row -that was last fetched. - -Thanks to Jurgen Botz - ----------------------------------------------------------------------- -Example for reading LONG fields via blob_read: - - $dbh->{RaiseError} = 1; - $dbh->{LongTruncOk} = 1; # truncation on initial fetch is ok - $sth = $dbh->prepare("SELECT key, long_field FROM table_name"); - $sth->execute; - while ( ($key) = $sth->fetchrow_array) { - my $offset = 0; - my $lump = 4096; # use benchmarks to get best value for you - my @frags; - while (1) { - my $frag = $sth->blob_read(1, $offset, $lump); - last unless defined $frag; - my $len = length $frag; - last unless $len; - push @frags, $frag; - $offset += $len; - } - my $blob = join "", @frags; - print "$key: $blob\n"; - } - -With thanks to james.taylor@srs.gov and desilva@ind70.industry.net. - ----------------------------------------------------------------------- - -Example for inserting LONGS From: Andrew Berry - -# Assuming the existence of @row and an associative array (%clauses) containing the -# column names and placeholders, and an array @types containing column types ... - - $ih = $db->prepare("INSERT INTO $table ($clauses{names}) - VALUES ($clauses{places})") - || die "prepare insert into $table: " . $db->errstr; - - $attrib{'ora_type'} = $longrawtype; # $longrawtype == 24 - - ##-- bind the parameter for each of the columns - for ($i = 0; $i < @types; $i++) { - - ##-- long raw values must have their type attribute explicitly specified - if ($types[$i] == $longrawtype) { - $ih->bind_param($i+1, $row[$i], \%attrib) - || die "binding placeholder for LONG RAW " . $db->errstr; - } - ##-- other values work OK with the default attributes - else { - $ih->bind_param($i+1, $row[$i]) - || die "binding placeholder" . $db->errstr; - } - } - - $ih->execute || die "execute INSERT into $table: " . $db->errstr; - ----------------------------------------------------------------------- diff --git a/README.sun.txt b/README.sun.txt deleted file mode 100644 index 8de1cb4d..00000000 --- a/README.sun.txt +++ /dev/null @@ -1,19 +0,0 @@ -DBD::Oracle SUB-specific README - -So far mot much to but here but here is one hint - - -If you get this on a Solaris 9 and 10 box - - "Outofmemory! - Callback called exit. - END failed--call queue aborted." - -The solution may be as simple as not having you "ORACLE_HOME" Defined in the enviornment. - -Seems as long as it defined it will stop the above error. - -Thanks to Rich White for figuring this out and Jim McCullars fr sugessting I make this README for sun - - - diff --git a/README.vms.txt b/README.vms.txt deleted file mode 100644 index 03484549..00000000 --- a/README.vms.txt +++ /dev/null @@ -1,87 +0,0 @@ -=head1 README.vms.txt for DBI and DBD::Oracle - -Date: Wed, 15 Sep 2004 11:44:09 +0300 -From: Jakob Snoer - -This is related to Oracle RDBMS 9.2 and later, since Oracle -made fundamental changes to oracle installation requirements -and factual installation with this release. - -Oracle's goal was to make VMS installation be more like on -*nix and Windows, with an all new Oracle Home structure too, -requiring an ODS-5 disk to install Oracle Home on instead of -the good old ODS-2. - -Another major change is the introduction of an Oracle generated -logical name table for oracle logical names like ORA_ROOT and all -its derivatives like ORA_PROGINT etc. And that this logical name -table is inserted in LNM$FILE_DEV in LNM$PROCESS_DIRECTORY. - -(LNM$PROCESS_DIRECTORY) - - "LNM$FILE_DEV" = "SERVER_810111112" - = "LNM$PROCESS" - = "LNM$JOB" - = "LNM$GROUP" - = "LNM$SYSTEM" - = "DECW$LOGICAL_NAMES" - -This ensures that any process that needs to have access to -oracle gets the environment by just adding one logical name table -to a central process specific mechanism. - -But as it is inserted at the very top of LNM$FILE_DEV it also -represents a source of misfortune - especially if a user with -enough privilege to update the oracle table does so (presumably -unintentionally), as an examble by changing NLS_LANG. - -PERL has the abillity to define, redefine and undefine (deassign) -logical names, but if not told otherwise by the user does it -in the first table in above list, and not as one would normally -expect in the process table. - -Installing DBI and DBD::Oracle has influence upon this since in -both cases a few enviroment variables are read or set in the -test phase. -For DBI it is the logical SYS$SCRATCH, which is a JOB logical. -For DBD-Oracle it is when testing a new feature in the Oracle -RDBMS: UTF8 and UTF16 character set functionallity, and in order -to do this it sets and unsets the related environment variables -NLS_NCHAR and NLS_LANG. - -If one is not careful this changes the values set in the oracle -table - and in the worst case stays active until the next major -system reset. It can also be a very hard error to track down -since it happens in a place where one normally never looks. - -Furthermore, it is very possibly that some or all of the UTF tests -fails, since if one have a variable like NLS_LANG in his process -table, then even though 'mms test' sets it in the wrong table -it is not invoked as it is overruled by the process logical... - -The way to ensure that no logicals are set in the oracle table and -that the UTF tests get the best environment to test in, and that -DBI correctly translates the SYS$SCRATCH logical, use the -logical - - PERL_ENV_TABLES - -to ensure that PERL's behavior is to leave the oracle table alone and -use the process table instead: - - $ DEFINE PERL_ENV_TABLES LNM$PROCESS, LNM$JOB - -This tells PERL to use the LNM$PROCESS table as the default place to -set and unset variables so that only the perl users environment -is affected when installing DBD::Oracle, and ensures that the -LNM$JOB table is read when SYS$SCRATCH is to be translated. - -PERL_ENV_TABLES is well documented in the PERLVMS man page. - -Oracle8 releases are not affected, as they don't have the -oracle table implementation, and no UTF support. - -Oracle 9.0 is uncertain, since testing has not been possible yet, -but the remedy will not hurt :) - -=cut diff --git a/README.wingcc.txt b/README.wingcc.txt deleted file mode 100644 index ea7225e4..00000000 --- a/README.wingcc.txt +++ /dev/null @@ -1,74 +0,0 @@ -29th April 2008 -From Nathan Vonnahme (nathan.vonnahme at bannerhealth.com) - -Hi! Thanks for maintaining DBD::Oracle! - -It might help people like me in the future to include these notes in -README.wingcc.txt or README.win32.txt (hopefully Outlook won't destroy -them)... there might be better ways of doing some of the details too but -it seems to have worked for me: - - -Compiling DBD::Oracle using the Oracle Instant Client, Cygwin Perl and -gcc - - 1. Download these two packages from Oracle's Instant Client for -Windows site -(http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs -/winsoft.html): - - Instant Client Package - Basic: All files required to run OCI, -OCCI, and JDBC-OCI applications - Instant Client Package - SDK: Additional header files and an -example makefile for developing Oracle applications with Instant Client - - (I usually just use the latest version of the client) - - 2. Unpack both into C:\oracle\instantclient_11_1 - 3. Download and unpack DBD::Oracle from CPAN to some place with no -spaces in the path (I used /tmp/DBD-Oracle) and cd to it. - 4. Set up some environment variables (it didn;t work until I got the -DSN right): - - ORACLE_DSN=DBI:Oracle:host=oraclehost;sid=oracledb1 - ORACLE_USERID=username/password - - 5. - - perl Makefile.PL - make - make test - make install - -Note, the TNS Names stuff doesn't always seem to work with the instant -client so Perl scripts need to explicitly use host/sid in the DSN, like -this: - -my $dbh = DBI->connect('dbi:Oracle:host=oraclehost;sid=oracledb1', -'username', 'password'); - - - - - -14-Sep-2002 -- Michael Chase - -Makefile.PL should now create liboci.a for you. If it fails, follow the -directions below. - -19-may-1999 - -added support for mingw32 and cygwin32 environments. - -Makefile.PL should find and make use of OCI include -files, but you have to build an import library for -OCI.DLL and put it somewhere in library search path. -one of the possible ways to do this is issuing command - -dlltool --input-def oci.def --output-lib liboci.a - -in the directory where you unpacked DBD::Oracle distribution -archive. this will create import library for Oracle 8.0.4. - -Note: make clean removes *.a files, so put a copy in a safe place. - diff --git a/examples/ora_explain.pl b/examples/ora_explain.pl index b260438a..36e2b3d5 100644 --- a/examples/ora_explain.pl +++ b/examples/ora_explain.pl @@ -1687,7 +1687,7 @@ =head2 Explain functionality column represents an index, and the figures define the order that the table columns appears in the index. To find out the name of an index, position the mouse over the index column. A single click will display the definition of the -index in a seperate dialog. +index in a separate dialog. Right-clicking on a plan step that refers to a table will pop up a menu showing a list of the indexes available for the table. Selecting an index will display diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm new file mode 100644 index 00000000..c0675fe9 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -0,0 +1,407 @@ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle + +=head1 CONNECTING TO ORACLE + +If you are reading this it is assumed that you have successfully +installed DBD::Oracle and you are having some problems connecting to +Oracle. + +First off you will have to tell DBD::Oracle where the binaries reside +for the Oracle client it was compiled against. This is the case when +you encounter a + + DBI connect('','system',...) failed: ERROR OCIEnvNlsCreate. + +error in Linux or in Windows when you get + + OCI.DLL not found + +The solution to this problem in the case of Linux is to ensure your +'ORACLE_HOME' (or LD_LIBRARY_PATH for InstantClient) environment +variable points to the correct directory. + + export ORACLE_HOME=/app/oracle/product/xx.x.x + +For Windows the solution is to add this value to you PATH + + PATH=c:\app\oracle\product\xx.x.x;%PATH% + + +If you get past this stage and get a + + ORA-12154: TNS:could not resolve the connect identifier specified + +error then the most likely cause is DBD::ORACLE cannot find your .ORA +(F, F, F) files. This can be +solved by setting the TNS_ADMIN environment variable to the directory +where these files can be found. + +If you get to this stage and you have either one of the following +errors; + + ORA-12560: TNS:protocol adapter error + ORA-12162: TNS:net service name is incorrectly specified + +usually means that DBD::Oracle can find the listener but the it cannot connect to the DB because the listener cannot find the DB you asked for. + +=head2 Oracle utilities + +If you are still having problems connecting then the Oracle adapters +utility may offer some help. Run these two commands: + + $ORACLE_HOME/bin/adapters + $ORACLE_HOME/bin/adapters $ORACLE_HOME/bin/sqlplus + +and check the output. The "Protocol Adapters" should include at least "IPC Protocol Adapter" and "TCP/IP +Protocol Adapter". + +If it generates any errors which look relevant then please talk to your +Oracle technical support (and not the dbi-users mailing list). + + +=head1 LONGS + +Some examples related to the use of LONG types. + +For complete working code, take a look at the t/long.t file. + +You must fetch the row before you can fetch the longs associated with +that row. In other words, use the following algorithm... + + 1) login + 2) prepare( select ... ) + 3) execute + 4) while rows to fetch do + 5) fetch row + 6) repeat + 7) fetch chunk of long + 8) until have all of it + 9) done + +If your select selects more than one row the need for step 4 may +become a bit clearer... the blob_read always applies to the row +that was last fetched. + +=head2 Example for reading LONG fields via blob_read + + $dbh->{RaiseError} = 1; + $dbh->{LongTruncOk} = 1; # truncation on initial fetch is ok + $sth = $dbh->prepare("SELECT key, long_field FROM table_name"); + $sth->execute; + while ( ($key) = $sth->fetchrow_array) { + my $offset = 0; + my $lump = 4096; # use benchmarks to get best value for you + my @frags; + while (1) { + my $frag = $sth->blob_read(1, $offset, $lump); + last unless defined $frag; + my $len = length $frag; + last unless $len; + push @frags, $frag; + $offset += $len; + } + my $blob = join "", @frags; + print "$key: $blob\n"; + } + +=head2 Example for inserting LONGS + + # Assuming the existence of @row and an associative array (%clauses) containing the + # column names and placeholders, and an array @types containing column types ... + + $ih = $db->prepare("INSERT INTO $table ($clauses{names}) + VALUES ($clauses{places})") + || die "prepare insert into $table: " . $db->errstr; + + $attrib{'ora_type'} = $longrawtype; # $longrawtype == 24 + + ##-- bind the parameter for each of the columns + for ($i = 0; $i < @types; $i++) { + + ##-- long raw values must have their type attribute explicitly specified + if ($types[$i] == $longrawtype) { + $ih->bind_param($i+1, $row[$i], \%attrib) + || die "binding placeholder for LONG RAW " . $db->errstr; + } + ##-- other values work OK with the default attributes + else { + $ih->bind_param($i+1, $row[$i]) + || die "binding placeholder" . $db->errstr; + } + } + + $ih->execute || die "execute INSERT into $table: " . $db->errstr; + +=head1 LINUX + +=head2 Installing with Instantclient .rpm files. + +Nothing special with this you just have to set up you permissions as follows; + +1) Have permission for RWE on '/usr/lib/oracle/10.2.0.3/client/' or the other directory where you RPMed to + +2) Set export ORACLE_HOME=/usr/lib/oracle/10.2.0.3/client + +3) Set export LD_LIBRARY_PATH=$ORACLE_HOME/lib + +4) If you plan to use tnsnames to connect to remote servers and your tnsnames.ora file is not in $ORACLE_HOME/network/admin, you will need to Export TNS_ADMIN=dir to point DBD::Oracle to where your tnsnames.ora file is + +=head2 undefined symbol: __cmpdi2 comes up when Oracle isn't properly linked to the libgcc.a library. + +In version 8, this was correctd by changing the SYSLIBS entry in +$ORACLE_HOME/bin/genclntsh to include +"-L/usr/lib/gcc-lib/i386-redhat-linux/3.2 -lgcc". + +I had tried this with no success as when this program was then run, the +error "unable to find libgcc" was generated. Of course, this was the +library I was trying to describe! + +It turns out that now it is necessary to edit the same file and append +"`gcc -print-libgcc-file-name`" (including the backquotes!). If you do +this and then run "genclntsh", the libclntsh is properly generated and +the linkage with DBD::Oracle proceeds properly. + + +=head2 cc1: invalid option `tune=pentium4'" error + +If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. + +No real problem with the above however you will have to + +1) run Perl Makefile.PL + +2) edit the Makefile and remove the offending '-mtune=pentium4' text + +3) save and exit + +4) do the make install and it should work fine for you + +=head2 Oracle 9i Lite + +The advice is to use the regular Oracle9i not the lite version. + +Another great source of help was: http://www.puschitz.com/InstallingOracle9i.html + +just getting 9i and 9i lite installed. I use fvwm2(nvidia X driver) as +a window manager which does not work with the 9i install program, works +fine with the default Gnomish(nv X driver), it could have been the X +driver too. + +With Redhat9 it is REAL important to set LD_ASSUME_KERNEL to 2.4.1. + +I didn't try this but it may be possible to install what is needed by +only downloading the first disk saving some 1.3GB of download fun. + +I installed a custom install from the client group. The packages I +installed are the Programmers section and sqlplus. I noticed that the +Pro*C when on as a result of the checking the Programmers section I +assume. + +Once Oracle was installed properly the DBD::Oracle install went as +smooth as just about every other CPAN module. + +=head2 Oracle 10g Instantclient + +The Makefile.PL will now work for Oracle 10g Instantclient. To have both the Compile and +the test.pl to work you must first have the LD_LIBRARY_PATH correctly set to your +"instantclient" directory. (http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html) + +The present version of the make creates a link on your "instantclient" directory as follows +"ln -s libclntsh.so.10.1 libclntsh.so". It is needed for both the makefile creation and the compile +but is not need for the test.pl. It should be removed after the compile. + +If the Makefile.PL or make fails try creating this link directly in your "instantclient" directory. + +=head2 Oracle Database 10g Express Edition 10.2 + +To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY_PATH +as you would for an install against 10g Standard Edition, Standard Edition One, or +Enterprise Edition + +=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 + +DBD::Oracle seems to hit some sort of bug with the above two versions of DB. +The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also +been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. + +So far there is no patch for this but here are some work arounds + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or this way + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + or this way + + utf8::downgrade($parameter, 1); + + +=head1 CYGWIN + +Makefile.PL should find and make use of OCI include +files, but you have to build an import library for +OCI.DLL and put it somewhere in library search path. +one of the possible ways to do this is issuing command + + dlltool --input-def oci.def --output-lib liboci.a + +in the directory where you unpacked DBD::Oracle distribution +archive. this will create import library for Oracle 8.0.4. + +Note: make clean removes '*.a' files, so put a copy in a safe place. + +=head2 Compiling DBD::Oracle using the Oracle Instant Client, Cygwin Perl and gcc + +=over + +=item 1 + +Download these two packages from Oracle's Instant Client for +Windows site +(http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/winsoft.html): + +Instant Client Package - Basic: All files required to run OCI, +OCCI, and JDBC-OCI applications + +Instant Client Package - SDK: Additional header files and an +example makefile for developing Oracle applications with Instant Client + +(I usually just use the latest version of the client) + +=item 2 + +Unpack both into C:\oracle\instantclient_11_1 + +=item 3 + +Download and unpack DBD::Oracle from CPAN to some place with no +spaces in the path (I used /tmp/DBD-Oracle) and cd to it. + +=item 4 + +Set up some environment variables (it didn't work until I got the +DSN right): + + ORACLE_DSN=DBI:Oracle:host=oraclehost;sid=oracledb1 + ORACLE_USERID=username/password + +=item 5 + + perl Makefile.PL + make + make test + make install + +=back + +Note, the TNS Names stuff doesn't always seem to work with the instant +client so Perl scripts need to explicitly use host/sid in the DSN, like +this: + + my $dbh = DBI->connect('dbi:Oracle:host=oraclehost;sid=oracledb1', + 'username', 'password'); + +=head2 SUN + +If you get this on a Solaris 9 and 10 box + + "Outofmemory! + Callback called exit. + END failed--call queue aborted." + +The solution may be as simple as not having you "ORACLE_HOME" Defined in the +environment. + +It seems that having it defined will prevent the error. + +=head2 VMS + +This is related to Oracle RDBMS 9.2 and later, since Oracle +made fundamental changes to oracle installation requirements +and factual installation with this release. + +Oracle's goal was to make VMS installation be more like on +*nix and Windows, with an all new Oracle Home structure too, +requiring an ODS-5 disk to install Oracle Home on instead of +the good old ODS-2. + +Another major change is the introduction of an Oracle generated +logical name table for oracle logical names like ORA_ROOT and all +its derivatives like ORA_PROGINT etc. And that this logical name +table is inserted in LNM$FILE_DEV in LNM$PROCESS_DIRECTORY. + + (LNM$PROCESS_DIRECTORY) + + "LNM$FILE_DEV" = "SERVER_810111112" + = "LNM$PROCESS" + = "LNM$JOB" + = "LNM$GROUP" + = "LNM$SYSTEM" + = "DECW$LOGICAL_NAMES" + +This ensures that any process that needs to have access to +oracle gets the environment by just adding one logical name table +to a central process specific mechanism. + +But as it is inserted at the very top of LNM$FILE_DEV it also +represents a source of misfortune - especially if a user with +enough privilege to update the oracle table does so (presumably +unintentionally), as an examble by changing NLS_LANG. + +PERL has the abillity to define, redefine and undefine (deassign) +logical names, but if not told otherwise by the user does it +in the first table in above list, and not as one would normally +expect in the process table. + +Installing DBI and DBD::Oracle has influence upon this since in +both cases a few enviroment variables are read or set in the +test phase. +For DBI it is the logical SYS$SCRATCH, which is a JOB logical. +For DBD-Oracle it is when testing a new feature in the Oracle +RDBMS: UTF8 and UTF16 character set functionallity, and in order +to do this it sets and unsets the related environment variables +NLS_NCHAR and NLS_LANG. + +If one is not careful this changes the values set in the oracle +table - and in the worst case stays active until the next major +system reset. It can also be a very hard error to track down +since it happens in a place where one normally never looks. + +Furthermore, it is very possibly that some or all of the UTF tests +fails, since if one have a variable like NLS_LANG in his process +table, then even though 'mms test' sets it in the wrong table +it is not invoked as it is overruled by the process logical... + +The way to ensure that no logicals are set in the oracle table and +that the UTF tests get the best environment to test in, and that +DBI correctly translates the SYS$SCRATCH logical, use the +logical + + PERL_ENV_TABLES + +to ensure that PERL's behavior is to leave the oracle table alone and +use the process table instead: + + $ DEFINE PERL_ENV_TABLES LNM$PROCESS, LNM$JOB + +This tells PERL to use the LNM$PROCESS table as the default place to +set and unset variables so that only the perl users environment +is affected when installing DBD::Oracle, and ensures that the +LNM$JOB table is read when SYS$SCRATCH is to be translated. + +PERL_ENV_TABLES is well documented in the PERLVMS man page. + +Oracle8 releases are not affected, as they don't have the +oracle table implementation, and no UTF support. + +Oracle 9.0 is uncertain, since testing has not been possible yet, +but the remedy will not hurt :) + +=cut diff --git a/t/58object.t b/t/58object.t index 4da295be..28be915e 100644 --- a/t/58object.t +++ b/t/58object.t @@ -174,15 +174,24 @@ is_deeply([$row1[1]->attributes], ['NUM', 13, 'NAME', 'obj1'], "new: Row 1 colum ok (scalar @row2, 'new: Fetch second row'); cmp_ok(ref $row2[1], 'eq', 'DBD::Oracle::Object', 'new: Row 2 column 2 is an DBD::Oracle::Object'); cmp_ok(uc $row2[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 2 column 2 object type"); -is_deeply([$row2[1]->attributes], ['NUM', undef, 'NAME', 'obj2', - 'DATETIME', '2004-11-30T14:27:18', 'AMOUNT', 12345.6789], "new: Row 1 column 2 object attributes"); + +my %attrs = $row2[1]->attributes; + +$attrs{AMOUNT} = sprintf "%9.4f", $attrs{AMOUNT}; + +is_deeply( \%attrs, {'NUM', undef, 'NAME', 'obj2', + 'DATETIME', '2004-11-30T14:27:18', 'AMOUNT', '12345.6789'}, "new: Row 1 column 2 object attributes"); @row3 = $sth->fetchrow(); ok (scalar @row3, 'new: Fetch third row'); cmp_ok(ref $row3[1], 'eq', 'DBD::Oracle::Object', 'new: Row 3 column 2 is an DBD::Oracle::Object'); cmp_ok(uc $row3[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 3 column 2 object type"); -is_deeply([$row3[1]->attributes], ['NUM', 5, 'NAME', 'obj3', - 'DATETIME', undef, 'AMOUNT', 777.666], "new: Row 1 column 2 object attributes"); + +%attrs = $row3[1]->attributes; +$attrs{AMOUNT} = sprintf "%6.3f", $attrs{AMOUNT}; + +is_deeply( \%attrs, {'NUM', 5, 'NAME', 'obj3', + 'DATETIME', undef, 'AMOUNT', '777.666'}, "new: Row 1 column 2 object attributes"); ok (!$sth->fetchrow(), 'new: No more rows expected'); @@ -196,7 +205,10 @@ my $expected_hash = { DATETIME => undef, AMOUNT => 777.666, }; -is_deeply($obj->attr_hash, $expected_hash, 'DBD::Oracle::Object->attr_hash'); +my $attrs = $obj->attr_hash; +$attrs->{AMOUNT} = sprintf "%6.3f", $attrs->{AMOUNT}; + +is_deeply($attrs, $expected_hash, 'DBD::Oracle::Object->attr_hash'); is_deeply($obj->attr, $expected_hash, 'DBD::Oracle::Object->attr'); is($obj->attr("NAME"), 'obj3', 'DBD::Oracle::Object->attr("NAME")'); From 446826a5097b49e863584d59283d947ce6033e41 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 17 Nov 2011 13:16:20 +0000 Subject: [PATCH 067/637] Apply patch from Charles Jardine for better/fixed building against Oracle 11 full version. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15005 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ Makefile.PL | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 7e65f856..073e3a46 100644 --- a/Changes +++ b/Changes @@ -11,6 +11,8 @@ Changes in DBD-Oracle XXX DiscardString a warning was not issued that the type is unsupported and no data was returned (Martin J. Evans) - Fix test so it works with perl compiled with -Duselongdouble [RT71852] + - Apply patch from Charles Jardine for better building against a full + Oracle 11 install [72463] (Martin J. Evans) [DOCUMENTATION] - Added notes to bind_col documenting the fact that setting a TYPE diff --git a/Makefile.PL b/Makefile.PL index 2c1ff707..834cd0e7 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1149,7 +1149,9 @@ sub find_mkfile { my @mk_oci32 = ( 'rdbms/demo/demo_xe.mk', - 'rdbms/demo/demo_rdbms32.mk' + 'rdbms/demo/demo_rdbms32.mk', + 'rdbms/demo/demo_rdbms.mk', + 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client ); my @mk_oci64 = ( 'rdbms/demo/demo_xe.mk', @@ -1157,7 +1159,7 @@ sub find_mkfile { 'rdbms/demo/oracle.mk', 'rdbms/demo/demo_rdbms.mk', 'rdbms/demo/demo_rdbms64.mk', - 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client for 64 bit and maybe 32 bit?? + 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client ); my @mk_oci = perl_is_64bit() ? @mk_oci64 : @mk_oci32; From 6a48300d949f777309ea4119241b20bf1e92256d Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 17 Nov 2011 13:16:20 +0000 Subject: [PATCH 068/637] Apply patch from Charles Jardine for better/fixed building against Oracle 11 full version. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15005 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ Makefile.PL | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 7e65f856..073e3a46 100644 --- a/Changes +++ b/Changes @@ -11,6 +11,8 @@ Changes in DBD-Oracle XXX DiscardString a warning was not issued that the type is unsupported and no data was returned (Martin J. Evans) - Fix test so it works with perl compiled with -Duselongdouble [RT71852] + - Apply patch from Charles Jardine for better building against a full + Oracle 11 install [72463] (Martin J. Evans) [DOCUMENTATION] - Added notes to bind_col documenting the fact that setting a TYPE diff --git a/Makefile.PL b/Makefile.PL index 2c1ff707..834cd0e7 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1149,7 +1149,9 @@ sub find_mkfile { my @mk_oci32 = ( 'rdbms/demo/demo_xe.mk', - 'rdbms/demo/demo_rdbms32.mk' + 'rdbms/demo/demo_rdbms32.mk', + 'rdbms/demo/demo_rdbms.mk', + 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client ); my @mk_oci64 = ( 'rdbms/demo/demo_xe.mk', @@ -1157,7 +1159,7 @@ sub find_mkfile { 'rdbms/demo/oracle.mk', 'rdbms/demo/demo_rdbms.mk', 'rdbms/demo/demo_rdbms64.mk', - 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client for 64 bit and maybe 32 bit?? + 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client ); my @mk_oci = perl_is_64bit() ? @mk_oci64 : @mk_oci32; From 6d0afaa149a392e8ba790b7cef20e47e0b3eb40a Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 17 Nov 2011 13:16:20 +0000 Subject: [PATCH 069/637] Apply patch from Charles Jardine for better/fixed building against Oracle 11 full version. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15005 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ Makefile.PL | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 8cfee7be..9a572006 100644 --- a/Changes +++ b/Changes @@ -11,6 +11,8 @@ Changes in DBD-Oracle XXX DiscardString a warning was not issued that the type is unsupported and no data was returned (Martin J. Evans) - Fix test so it works with perl compiled with -Duselongdouble [RT71852] + - Apply patch from Charles Jardine for better building against a full + Oracle 11 install [72463] (Martin J. Evans) [DOCUMENTATION] - Added notes to bind_col documenting the fact that setting a TYPE diff --git a/Makefile.PL b/Makefile.PL index 2c1ff707..834cd0e7 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1149,7 +1149,9 @@ sub find_mkfile { my @mk_oci32 = ( 'rdbms/demo/demo_xe.mk', - 'rdbms/demo/demo_rdbms32.mk' + 'rdbms/demo/demo_rdbms32.mk', + 'rdbms/demo/demo_rdbms.mk', + 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client ); my @mk_oci64 = ( 'rdbms/demo/demo_xe.mk', @@ -1157,7 +1159,7 @@ sub find_mkfile { 'rdbms/demo/oracle.mk', 'rdbms/demo/demo_rdbms.mk', 'rdbms/demo/demo_rdbms64.mk', - 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client for 64 bit and maybe 32 bit?? + 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client ); my @mk_oci = perl_is_64bit() ? @mk_oci64 : @mk_oci32; From 6fc3edae59c0402afdb6b2dae687d19b7c72d230 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 17 Nov 2011 09:54:09 -0500 Subject: [PATCH 070/637] add RT keyword --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index 9a572006..ef4a33e9 100644 --- a/Changes +++ b/Changes @@ -12,7 +12,7 @@ Changes in DBD-Oracle XXX and no data was returned (Martin J. Evans) - Fix test so it works with perl compiled with -Duselongdouble [RT71852] - Apply patch from Charles Jardine for better building against a full - Oracle 11 install [72463] (Martin J. Evans) + Oracle 11 install [RT72463] (Martin J. Evans) [DOCUMENTATION] - Added notes to bind_col documenting the fact that setting a TYPE From c76e6108c5a4799a56997553a39c39458eb3217d Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 18 Nov 2011 13:06:10 -0500 Subject: [PATCH 071/637] move long examples out of POD and into examples/ --- Changes | 1 + examples/inserting_longs.pl | 43 ++++++++++++++++ examples/read_long_via_blob_read.pl | 31 ++++++++++++ lib/DBD/Oracle/Troubleshooting.pm | 76 ++--------------------------- 4 files changed, 79 insertions(+), 72 deletions(-) create mode 100644 examples/inserting_longs.pl create mode 100644 examples/read_long_via_blob_read.pl diff --git a/Changes b/Changes index 24e27c08..8df1a19e 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,7 @@ Changes in DBD-Oracle XXX - fix typo (thanks to Julián Moreno Patiño) [RT72038] - shuffle POD around to improve documentation flow [RT72252] - major tidying up of the connect() documentation. (by Gwen Shapira) + - Moved LONG examples out of POD and into examples/ [OTHER] - Commented out some functions in oci8.c which were not used to diff --git a/examples/inserting_longs.pl b/examples/inserting_longs.pl new file mode 100644 index 00000000..191a0c3d --- /dev/null +++ b/examples/inserting_longs.pl @@ -0,0 +1,43 @@ +#!perl + +use strict; +use warnings; + +use DBI; + +my $db = DBI->connect( 'dbi:Oracle:mydb', 'username', 'password' ); + +my $table = 'TABLE'; +my %clauses; +my %attrib; +my @types; +my $longrawtype; +my @row; + +# Assuming the existence of @row and an associative array (%clauses) containing the +# column names and placeholders, and an array @types containing column types ... + +my $ih = $db->prepare("INSERT INTO $table ($clauses{names}) + VALUES ($clauses{places})") + or die "prepare insert into $table: " . $db->errstr; + +$attrib{'ora_type'} = $longrawtype; # $longrawtype == 24 + +##-- bind the parameter for each of the columns +for my $i ( 0..$#types ) { + + ##-- long raw values must have their type attribute explicitly specified + if ($types[$i] == $longrawtype) { + $ih->bind_param($i+1, $row[$i], \%attrib) + || die "binding placeholder for LONG RAW " . $db->errstr; + } + ##-- other values work OK with the default attributes + else { + $ih->bind_param($i+1, $row[$i]) + || die "binding placeholder" . $db->errstr; + } +} + +$ih->execute || die "execute INSERT into $table: " . $db->errstr; + + diff --git a/examples/read_long_via_blob_read.pl b/examples/read_long_via_blob_read.pl new file mode 100644 index 00000000..70631d8d --- /dev/null +++ b/examples/read_long_via_blob_read.pl @@ -0,0 +1,31 @@ +#!perl + +use strict; +use warnings; + +use DBI; + +my $dbh = DBI->connect( 'dbi:Oracle:mydb', 'username', 'password' ); + +$dbh->{RaiseError} = 1; +$dbh->{LongTruncOk} = 1; # truncation on initial fetch is ok + +my $sth = $dbh->prepare("SELECT key, long_field FROM table_name"); +$sth->execute; + +while ( my ($key) = $sth->fetchrow_array) { + my $offset = 0; + my $lump = 4096; # use benchmarks to get best value for you + my @frags; + while (1) { + my $frag = $sth->blob_read(1, $offset, $lump); + last unless defined $frag; + my $len = length $frag; + last unless $len; + push @frags, $frag; + $offset += $len; + } + my $blob = join "", @frags; + print "$key: $blob\n"; +} + diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index c0675fe9..7522d8c9 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -63,78 +63,10 @@ If it generates any errors which look relevant then please talk to your Oracle technical support (and not the dbi-users mailing list). -=head1 LONGS - -Some examples related to the use of LONG types. - -For complete working code, take a look at the t/long.t file. - -You must fetch the row before you can fetch the longs associated with -that row. In other words, use the following algorithm... - - 1) login - 2) prepare( select ... ) - 3) execute - 4) while rows to fetch do - 5) fetch row - 6) repeat - 7) fetch chunk of long - 8) until have all of it - 9) done - -If your select selects more than one row the need for step 4 may -become a bit clearer... the blob_read always applies to the row -that was last fetched. - -=head2 Example for reading LONG fields via blob_read - - $dbh->{RaiseError} = 1; - $dbh->{LongTruncOk} = 1; # truncation on initial fetch is ok - $sth = $dbh->prepare("SELECT key, long_field FROM table_name"); - $sth->execute; - while ( ($key) = $sth->fetchrow_array) { - my $offset = 0; - my $lump = 4096; # use benchmarks to get best value for you - my @frags; - while (1) { - my $frag = $sth->blob_read(1, $offset, $lump); - last unless defined $frag; - my $len = length $frag; - last unless $len; - push @frags, $frag; - $offset += $len; - } - my $blob = join "", @frags; - print "$key: $blob\n"; - } - -=head2 Example for inserting LONGS - - # Assuming the existence of @row and an associative array (%clauses) containing the - # column names and placeholders, and an array @types containing column types ... - - $ih = $db->prepare("INSERT INTO $table ($clauses{names}) - VALUES ($clauses{places})") - || die "prepare insert into $table: " . $db->errstr; - - $attrib{'ora_type'} = $longrawtype; # $longrawtype == 24 - - ##-- bind the parameter for each of the columns - for ($i = 0; $i < @types; $i++) { - - ##-- long raw values must have their type attribute explicitly specified - if ($types[$i] == $longrawtype) { - $ih->bind_param($i+1, $row[$i], \%attrib) - || die "binding placeholder for LONG RAW " . $db->errstr; - } - ##-- other values work OK with the default attributes - else { - $ih->bind_param($i+1, $row[$i]) - || die "binding placeholder" . $db->errstr; - } - } - - $ih->execute || die "execute INSERT into $table: " . $db->errstr; +=head1 USING THE LONG TYPES + +Some examples related to the use of LONG types are available in +the C directory of the distribution. =head1 LINUX From 0d0857e6a09c584188934cf273da3be9c7f94cbd Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 18 Nov 2011 14:18:27 -0500 Subject: [PATCH 072/637] update MANIFEST --- MANIFEST | 3 +++ MANIFEST.SKIP | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/MANIFEST b/MANIFEST index baf4733c..96251b9e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -82,3 +82,6 @@ typemap examples/ora_explain.pl t/00versions.t lib/DBD/Oracle/Troubleshooting.pm +examples/inserting_longs.pl +examples/read_long_via_blob_read.pl +t/rt13865.t diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index d38951ae..a880e9d5 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -17,3 +17,15 @@ ~$ ^\.git ^xt +dbdimp.o +Makefile.old +mk.pm +MYMETA.json +MYMETA.yml +oci8.o +Oracle.bs +Oracle.c +Oracle.o +Oracle.xsi +pm_to_blib + From 4a53c701bd5c2058a1fefbb5f641577cdc944d11 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 18 Nov 2011 13:14:02 -0500 Subject: [PATCH 073/637] populate .gitignore --- .gitignore | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..4b3129c9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +pm_to_blib +MYMETA.yml +Makefile +Makefile.old +Oracle.bs +Oracle.c +Oracle.o +Oracle.xsi +blib +MYMETA.json +dbdimp.o +mk.pm +oci8.o From 50286150c962d56dad27c4694800a8bf7f9d19f7 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 18 Nov 2011 14:18:44 -0500 Subject: [PATCH 074/637] POD booboo --- Oracle.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/Oracle.pm b/Oracle.pm index 5acabc43..2c9872e8 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -5306,6 +5306,7 @@ It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go and even get to 10. I am not sure what the 11g client can connect to. =back + =head1 BUGS AND LIMITATIONS There is a known problem with the 11.2g Oracle client and the From 8f9819b57636a51129b05005b0d3439c2aadf0cc Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 18 Nov 2011 14:25:54 -0500 Subject: [PATCH 075/637] bump the version to 1.35_00 --- Changes | 2 +- Oracle.pm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 8df1a19e..d595259c 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -Changes in DBD-Oracle XXX +Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] - if bind_col is called with a TYPE but no bind attributes like diff --git a/Oracle.pm b/Oracle.pm index 2c9872e8..a7c7ac36 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -7,7 +7,7 @@ require 5.006; -$DBD::Oracle::VERSION = '1.33_00'; +$DBD::Oracle::VERSION = '1.35_00'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; From 9e0a61e1fa7b3bd2915b6fddfa9529f4b9ce0009 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 18 Nov 2011 19:39:31 +0000 Subject: [PATCH 076/637] Merge branch 'master' into HEAD Conflicts: Changes MANIFEST Oracle.pm lib/DBD/Oracle/Troubleshooting.pm git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15006 50811bd7-b8ce-0310-adc1-d9db26280581 --- .gitignore | 13 +++++ Changes | 5 +- MANIFEST | 3 ++ MANIFEST.SKIP | 12 +++++ Oracle.pm | 3 +- examples/inserting_longs.pl | 43 ++++++++++++++++ examples/read_long_via_blob_read.pl | 31 ++++++++++++ lib/DBD/Oracle/Troubleshooting.pm | 76 ++--------------------------- 8 files changed, 111 insertions(+), 75 deletions(-) create mode 100644 .gitignore create mode 100644 examples/inserting_longs.pl create mode 100644 examples/read_long_via_blob_read.pl diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..4b3129c9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +pm_to_blib +MYMETA.yml +Makefile +Makefile.old +Oracle.bs +Oracle.c +Oracle.o +Oracle.xsi +blib +MYMETA.json +dbdimp.o +mk.pm +oci8.o diff --git a/Changes b/Changes index 073e3a46..d595259c 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -Changes in DBD-Oracle XXX +Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] - if bind_col is called with a TYPE but no bind attributes like @@ -12,7 +12,7 @@ Changes in DBD-Oracle XXX and no data was returned (Martin J. Evans) - Fix test so it works with perl compiled with -Duselongdouble [RT71852] - Apply patch from Charles Jardine for better building against a full - Oracle 11 install [72463] (Martin J. Evans) + Oracle 11 install [RT72463] (Martin J. Evans) [DOCUMENTATION] - Added notes to bind_col documenting the fact that setting a TYPE @@ -21,6 +21,7 @@ Changes in DBD-Oracle XXX - fix typo (thanks to Julián Moreno Patiño) [RT72038] - shuffle POD around to improve documentation flow [RT72252] - major tidying up of the connect() documentation. (by Gwen Shapira) + - Moved LONG examples out of POD and into examples/ [OTHER] - Commented out some functions in oci8.c which were not used to diff --git a/MANIFEST b/MANIFEST index baf4733c..96251b9e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -82,3 +82,6 @@ typemap examples/ora_explain.pl t/00versions.t lib/DBD/Oracle/Troubleshooting.pm +examples/inserting_longs.pl +examples/read_long_via_blob_read.pl +t/rt13865.t diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index d38951ae..a880e9d5 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -17,3 +17,15 @@ ~$ ^\.git ^xt +dbdimp.o +Makefile.old +mk.pm +MYMETA.json +MYMETA.yml +oci8.o +Oracle.bs +Oracle.c +Oracle.o +Oracle.xsi +pm_to_blib + diff --git a/Oracle.pm b/Oracle.pm index 5acabc43..a7c7ac36 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -7,7 +7,7 @@ require 5.006; -$DBD::Oracle::VERSION = '1.33_00'; +$DBD::Oracle::VERSION = '1.35_00'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; @@ -5306,6 +5306,7 @@ It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go and even get to 10. I am not sure what the 11g client can connect to. =back + =head1 BUGS AND LIMITATIONS There is a known problem with the 11.2g Oracle client and the diff --git a/examples/inserting_longs.pl b/examples/inserting_longs.pl new file mode 100644 index 00000000..191a0c3d --- /dev/null +++ b/examples/inserting_longs.pl @@ -0,0 +1,43 @@ +#!perl + +use strict; +use warnings; + +use DBI; + +my $db = DBI->connect( 'dbi:Oracle:mydb', 'username', 'password' ); + +my $table = 'TABLE'; +my %clauses; +my %attrib; +my @types; +my $longrawtype; +my @row; + +# Assuming the existence of @row and an associative array (%clauses) containing the +# column names and placeholders, and an array @types containing column types ... + +my $ih = $db->prepare("INSERT INTO $table ($clauses{names}) + VALUES ($clauses{places})") + or die "prepare insert into $table: " . $db->errstr; + +$attrib{'ora_type'} = $longrawtype; # $longrawtype == 24 + +##-- bind the parameter for each of the columns +for my $i ( 0..$#types ) { + + ##-- long raw values must have their type attribute explicitly specified + if ($types[$i] == $longrawtype) { + $ih->bind_param($i+1, $row[$i], \%attrib) + || die "binding placeholder for LONG RAW " . $db->errstr; + } + ##-- other values work OK with the default attributes + else { + $ih->bind_param($i+1, $row[$i]) + || die "binding placeholder" . $db->errstr; + } +} + +$ih->execute || die "execute INSERT into $table: " . $db->errstr; + + diff --git a/examples/read_long_via_blob_read.pl b/examples/read_long_via_blob_read.pl new file mode 100644 index 00000000..70631d8d --- /dev/null +++ b/examples/read_long_via_blob_read.pl @@ -0,0 +1,31 @@ +#!perl + +use strict; +use warnings; + +use DBI; + +my $dbh = DBI->connect( 'dbi:Oracle:mydb', 'username', 'password' ); + +$dbh->{RaiseError} = 1; +$dbh->{LongTruncOk} = 1; # truncation on initial fetch is ok + +my $sth = $dbh->prepare("SELECT key, long_field FROM table_name"); +$sth->execute; + +while ( my ($key) = $sth->fetchrow_array) { + my $offset = 0; + my $lump = 4096; # use benchmarks to get best value for you + my @frags; + while (1) { + my $frag = $sth->blob_read(1, $offset, $lump); + last unless defined $frag; + my $len = length $frag; + last unless $len; + push @frags, $frag; + $offset += $len; + } + my $blob = join "", @frags; + print "$key: $blob\n"; +} + diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index c0675fe9..7522d8c9 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -63,78 +63,10 @@ If it generates any errors which look relevant then please talk to your Oracle technical support (and not the dbi-users mailing list). -=head1 LONGS - -Some examples related to the use of LONG types. - -For complete working code, take a look at the t/long.t file. - -You must fetch the row before you can fetch the longs associated with -that row. In other words, use the following algorithm... - - 1) login - 2) prepare( select ... ) - 3) execute - 4) while rows to fetch do - 5) fetch row - 6) repeat - 7) fetch chunk of long - 8) until have all of it - 9) done - -If your select selects more than one row the need for step 4 may -become a bit clearer... the blob_read always applies to the row -that was last fetched. - -=head2 Example for reading LONG fields via blob_read - - $dbh->{RaiseError} = 1; - $dbh->{LongTruncOk} = 1; # truncation on initial fetch is ok - $sth = $dbh->prepare("SELECT key, long_field FROM table_name"); - $sth->execute; - while ( ($key) = $sth->fetchrow_array) { - my $offset = 0; - my $lump = 4096; # use benchmarks to get best value for you - my @frags; - while (1) { - my $frag = $sth->blob_read(1, $offset, $lump); - last unless defined $frag; - my $len = length $frag; - last unless $len; - push @frags, $frag; - $offset += $len; - } - my $blob = join "", @frags; - print "$key: $blob\n"; - } - -=head2 Example for inserting LONGS - - # Assuming the existence of @row and an associative array (%clauses) containing the - # column names and placeholders, and an array @types containing column types ... - - $ih = $db->prepare("INSERT INTO $table ($clauses{names}) - VALUES ($clauses{places})") - || die "prepare insert into $table: " . $db->errstr; - - $attrib{'ora_type'} = $longrawtype; # $longrawtype == 24 - - ##-- bind the parameter for each of the columns - for ($i = 0; $i < @types; $i++) { - - ##-- long raw values must have their type attribute explicitly specified - if ($types[$i] == $longrawtype) { - $ih->bind_param($i+1, $row[$i], \%attrib) - || die "binding placeholder for LONG RAW " . $db->errstr; - } - ##-- other values work OK with the default attributes - else { - $ih->bind_param($i+1, $row[$i]) - || die "binding placeholder" . $db->errstr; - } - } - - $ih->execute || die "execute INSERT into $table: " . $db->errstr; +=head1 USING THE LONG TYPES + +Some examples related to the use of LONG types are available in +the C directory of the distribution. =head1 LINUX From f40c1bbc253c94f5fb98cd8254b246da79d7e8b2 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 24 Nov 2011 13:23:29 +0000 Subject: [PATCH 077/637] patch for ora_server_version and dbs not open git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15017 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 ++++++++ Oracle.pm | 13 ++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index d595259c..ac1f374d 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,13 @@ Revision history for DBD::Oracle +Changes in DBD-Oracle X.XX (XX-XX-XXXX) + + [BEG FIXES] + + - applied patch from Charles Jardine avoiding undefined values + warnings in ora_server_version when the database is not open + [RT72623] (Martin J. Evans) + Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] diff --git a/Oracle.pm b/Oracle.pm index a7c7ac36..c4d25ae2 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -952,12 +952,15 @@ SQL sub ora_server_version { my $dbh = shift; return $dbh->{ora_server_version} if defined $dbh->{ora_server_version}; - $dbh->{ora_server_version} = - [ split /\./, $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%') .'']; -SELECT version - FROM product_component_version - WHERE product LIKE ? or product LIKE ? + my $banner = $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%'); +SELECT banner + FROM v$version + WHERE banner LIKE ? OR banner LIKE ? SQL + if (defined $banner) { + my @version = $banner =~ /(?:^|\s)(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\s|$)/; + $dbh->{ora_server_version} = \@version if @version; + } } sub ora_nls_parameters { From 269ccfc246fa214626f92fdee828c4ef3916a1bd Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 24 Nov 2011 13:23:29 +0000 Subject: [PATCH 078/637] patch for ora_server_version and dbs not open git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15017 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 ++++++++ Oracle.pm | 13 ++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index d595259c..ac1f374d 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,13 @@ Revision history for DBD::Oracle +Changes in DBD-Oracle X.XX (XX-XX-XXXX) + + [BEG FIXES] + + - applied patch from Charles Jardine avoiding undefined values + warnings in ora_server_version when the database is not open + [RT72623] (Martin J. Evans) + Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] diff --git a/Oracle.pm b/Oracle.pm index a7c7ac36..c4d25ae2 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -952,12 +952,15 @@ SQL sub ora_server_version { my $dbh = shift; return $dbh->{ora_server_version} if defined $dbh->{ora_server_version}; - $dbh->{ora_server_version} = - [ split /\./, $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%') .'']; -SELECT version - FROM product_component_version - WHERE product LIKE ? or product LIKE ? + my $banner = $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%'); +SELECT banner + FROM v$version + WHERE banner LIKE ? OR banner LIKE ? SQL + if (defined $banner) { + my @version = $banner =~ /(?:^|\s)(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\s|$)/; + $dbh->{ora_server_version} = \@version if @version; + } } sub ora_nls_parameters { From 178bd9727727a5fda4ab739e0fea269c8e0cd0f8 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 25 Nov 2011 19:27:08 +0000 Subject: [PATCH 079/637] rt72716 - document problems with ora_connect_with_default_signals and connect_cached git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15018 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 +++++++- Oracle.pm | 34 +++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Changes b/Changes index ac1f374d..21617056 100644 --- a/Changes +++ b/Changes @@ -2,12 +2,18 @@ Revision history for DBD::Oracle Changes in DBD-Oracle X.XX (XX-XX-XXXX) - [BEG FIXES] + [BUG FIXES] - applied patch from Charles Jardine avoiding undefined values warnings in ora_server_version when the database is not open [RT72623] (Martin J. Evans) + [DOCUMENTATION] + + - [rt72716] Document possible problem with + ora_connect_with_default_signals and connect_cached + (Martin J. Evans) + Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] diff --git a/Oracle.pm b/Oracle.pm index c4d25ae2..e5f26d02 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -148,7 +148,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; # get list of 'remote' database connection identifiers my @tns_admin = ( DBD::Oracle::ora_env_var("TNS_ADMIN"), '.' ); - push @tns_admin, map { join '/', $oracle_home, $_ } + push @tns_admin, map { join '/', $oracle_home, $_ } 'network/admin', # OCI 7 and 8.1 'net80/admin', # OCI 8.0 if $oracle_home; @@ -650,7 +650,7 @@ SELECT * ) , 'FLOAT' , tc.DATA_PRECISION , 'DATE' , 19 - , 'VARCHAR2' , tc.CHAR_LENGTH + , 'VARCHAR2' , tc.CHAR_LENGTH , tc.DATA_LENGTH ) COLUMN_SIZE , decode( tc.DATA_TYPE @@ -1250,7 +1250,7 @@ but it is not secure and not recommended so not documented here. =head3 Oracle Environment Variables -To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. @@ -1594,7 +1594,7 @@ on the server side using C view. =head4 ora_dbh_share -Requires at least Perl 5.8.0 compiled with ithreads. +Requires at least Perl 5.8.0 compiled with ithreads. Allows you to share database connections between threads. The first connect will make the @@ -1759,9 +1759,21 @@ For example: NOTE disabling the signal handlers the OCI library sets up may affect functionality in the OCI library. +NOTE If you are using connect_cached then the above example will lead +to DBI thinking each connection is different as an anonymous array reference +is being used. To avoid this when using connect_cached you are advised +to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + +In more recent Perl versions you could possibly make use of new state +variables. + =head2 B -Implemented by DBI, no driver-specific impact. +Implemented by DBI, no driver-specific impact. Please note that connect_cached as not been tested with DRCP. =head2 B @@ -2288,7 +2300,7 @@ a warning is given and no COMMIT is issued. Returns true on success, false on er Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and -false on error. +false on error. =head2 B @@ -2484,7 +2496,7 @@ handle, then trying to merge the attributes. See the DBI documentation for compl Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change in the future, so it is highly recommended that you explicitly set it when -calling L. +calling L. =head2 B (boolean) @@ -5236,7 +5248,7 @@ you may not be aware of. =head2 GitHub repository A git mirror of the subversion is also available at -`https://github.com/yanick/DBD-Oracle`. +`https://github.com/yanick/DBD-Oracle`. =head1 Oracle Related Links @@ -5312,8 +5324,8 @@ and even get to 10. I am not sure what the 11g client can connect to. =head1 BUGS AND LIMITATIONS -There is a known problem with the 11.2g Oracle client and the -C PL/SQL function. +There is a known problem with the 11.2g Oracle client and the +C PL/SQL function. See L for the details. @@ -5365,7 +5377,7 @@ Also PL/Vision from RevealNet and Steven Feuerstein, and DBI by Tim Bunce L. -The original C was by Tim Bunce. +The original C was by Tim Bunce. Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the auspice of the Pythian Group (L). From d36280426157c84760d15a97b61539245ff27acc Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 25 Nov 2011 19:27:08 +0000 Subject: [PATCH 080/637] rt72716 - document problems with ora_connect_with_default_signals and connect_cached git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15018 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 +++++++- Oracle.pm | 34 +++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Changes b/Changes index ac1f374d..21617056 100644 --- a/Changes +++ b/Changes @@ -2,12 +2,18 @@ Revision history for DBD::Oracle Changes in DBD-Oracle X.XX (XX-XX-XXXX) - [BEG FIXES] + [BUG FIXES] - applied patch from Charles Jardine avoiding undefined values warnings in ora_server_version when the database is not open [RT72623] (Martin J. Evans) + [DOCUMENTATION] + + - [rt72716] Document possible problem with + ora_connect_with_default_signals and connect_cached + (Martin J. Evans) + Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] diff --git a/Oracle.pm b/Oracle.pm index c4d25ae2..e5f26d02 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -148,7 +148,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; # get list of 'remote' database connection identifiers my @tns_admin = ( DBD::Oracle::ora_env_var("TNS_ADMIN"), '.' ); - push @tns_admin, map { join '/', $oracle_home, $_ } + push @tns_admin, map { join '/', $oracle_home, $_ } 'network/admin', # OCI 7 and 8.1 'net80/admin', # OCI 8.0 if $oracle_home; @@ -650,7 +650,7 @@ SELECT * ) , 'FLOAT' , tc.DATA_PRECISION , 'DATE' , 19 - , 'VARCHAR2' , tc.CHAR_LENGTH + , 'VARCHAR2' , tc.CHAR_LENGTH , tc.DATA_LENGTH ) COLUMN_SIZE , decode( tc.DATA_TYPE @@ -1250,7 +1250,7 @@ but it is not secure and not recommended so not documented here. =head3 Oracle Environment Variables -To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. @@ -1594,7 +1594,7 @@ on the server side using C view. =head4 ora_dbh_share -Requires at least Perl 5.8.0 compiled with ithreads. +Requires at least Perl 5.8.0 compiled with ithreads. Allows you to share database connections between threads. The first connect will make the @@ -1759,9 +1759,21 @@ For example: NOTE disabling the signal handlers the OCI library sets up may affect functionality in the OCI library. +NOTE If you are using connect_cached then the above example will lead +to DBI thinking each connection is different as an anonymous array reference +is being used. To avoid this when using connect_cached you are advised +to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + +In more recent Perl versions you could possibly make use of new state +variables. + =head2 B -Implemented by DBI, no driver-specific impact. +Implemented by DBI, no driver-specific impact. Please note that connect_cached as not been tested with DRCP. =head2 B @@ -2288,7 +2300,7 @@ a warning is given and no COMMIT is issued. Returns true on success, false on er Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and -false on error. +false on error. =head2 B @@ -2484,7 +2496,7 @@ handle, then trying to merge the attributes. See the DBI documentation for compl Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change in the future, so it is highly recommended that you explicitly set it when -calling L. +calling L. =head2 B (boolean) @@ -5236,7 +5248,7 @@ you may not be aware of. =head2 GitHub repository A git mirror of the subversion is also available at -`https://github.com/yanick/DBD-Oracle`. +`https://github.com/yanick/DBD-Oracle`. =head1 Oracle Related Links @@ -5312,8 +5324,8 @@ and even get to 10. I am not sure what the 11g client can connect to. =head1 BUGS AND LIMITATIONS -There is a known problem with the 11.2g Oracle client and the -C PL/SQL function. +There is a known problem with the 11.2g Oracle client and the +C PL/SQL function. See L for the details. @@ -5365,7 +5377,7 @@ Also PL/Vision from RevealNet and Steven Feuerstein, and DBI by Tim Bunce L. -The original C was by Tim Bunce. +The original C was by Tim Bunce. Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the auspice of the Pythian Group (L). From 58aad0f033c8e40eb8823693c9f01186870b2aa4 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 24 Nov 2011 13:23:29 +0000 Subject: [PATCH 081/637] patch for ora_server_version and dbs not open git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15017 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 ++++++++ Oracle.pm | 13 ++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index d595259c..ac1f374d 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,13 @@ Revision history for DBD::Oracle +Changes in DBD-Oracle X.XX (XX-XX-XXXX) + + [BEG FIXES] + + - applied patch from Charles Jardine avoiding undefined values + warnings in ora_server_version when the database is not open + [RT72623] (Martin J. Evans) + Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] diff --git a/Oracle.pm b/Oracle.pm index a7c7ac36..c4d25ae2 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -952,12 +952,15 @@ SQL sub ora_server_version { my $dbh = shift; return $dbh->{ora_server_version} if defined $dbh->{ora_server_version}; - $dbh->{ora_server_version} = - [ split /\./, $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%') .'']; -SELECT version - FROM product_component_version - WHERE product LIKE ? or product LIKE ? + my $banner = $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%'); +SELECT banner + FROM v$version + WHERE banner LIKE ? OR banner LIKE ? SQL + if (defined $banner) { + my @version = $banner =~ /(?:^|\s)(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\s|$)/; + $dbh->{ora_server_version} = \@version if @version; + } } sub ora_nls_parameters { From 50d8d8f41f51f377fbca831fc719f1a759ed44cc Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 25 Nov 2011 19:27:08 +0000 Subject: [PATCH 082/637] rt72716 - document problems with ora_connect_with_default_signals and connect_cached git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15018 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 +++++++- Oracle.pm | 34 +++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Changes b/Changes index ac1f374d..21617056 100644 --- a/Changes +++ b/Changes @@ -2,12 +2,18 @@ Revision history for DBD::Oracle Changes in DBD-Oracle X.XX (XX-XX-XXXX) - [BEG FIXES] + [BUG FIXES] - applied patch from Charles Jardine avoiding undefined values warnings in ora_server_version when the database is not open [RT72623] (Martin J. Evans) + [DOCUMENTATION] + + - [rt72716] Document possible problem with + ora_connect_with_default_signals and connect_cached + (Martin J. Evans) + Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] diff --git a/Oracle.pm b/Oracle.pm index c4d25ae2..e5f26d02 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -148,7 +148,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; # get list of 'remote' database connection identifiers my @tns_admin = ( DBD::Oracle::ora_env_var("TNS_ADMIN"), '.' ); - push @tns_admin, map { join '/', $oracle_home, $_ } + push @tns_admin, map { join '/', $oracle_home, $_ } 'network/admin', # OCI 7 and 8.1 'net80/admin', # OCI 8.0 if $oracle_home; @@ -650,7 +650,7 @@ SELECT * ) , 'FLOAT' , tc.DATA_PRECISION , 'DATE' , 19 - , 'VARCHAR2' , tc.CHAR_LENGTH + , 'VARCHAR2' , tc.CHAR_LENGTH , tc.DATA_LENGTH ) COLUMN_SIZE , decode( tc.DATA_TYPE @@ -1250,7 +1250,7 @@ but it is not secure and not recommended so not documented here. =head3 Oracle Environment Variables -To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. @@ -1594,7 +1594,7 @@ on the server side using C view. =head4 ora_dbh_share -Requires at least Perl 5.8.0 compiled with ithreads. +Requires at least Perl 5.8.0 compiled with ithreads. Allows you to share database connections between threads. The first connect will make the @@ -1759,9 +1759,21 @@ For example: NOTE disabling the signal handlers the OCI library sets up may affect functionality in the OCI library. +NOTE If you are using connect_cached then the above example will lead +to DBI thinking each connection is different as an anonymous array reference +is being used. To avoid this when using connect_cached you are advised +to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + +In more recent Perl versions you could possibly make use of new state +variables. + =head2 B -Implemented by DBI, no driver-specific impact. +Implemented by DBI, no driver-specific impact. Please note that connect_cached as not been tested with DRCP. =head2 B @@ -2288,7 +2300,7 @@ a warning is given and no COMMIT is issued. Returns true on success, false on er Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and -false on error. +false on error. =head2 B @@ -2484,7 +2496,7 @@ handle, then trying to merge the attributes. See the DBI documentation for compl Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change in the future, so it is highly recommended that you explicitly set it when -calling L. +calling L. =head2 B (boolean) @@ -5236,7 +5248,7 @@ you may not be aware of. =head2 GitHub repository A git mirror of the subversion is also available at -`https://github.com/yanick/DBD-Oracle`. +`https://github.com/yanick/DBD-Oracle`. =head1 Oracle Related Links @@ -5312,8 +5324,8 @@ and even get to 10. I am not sure what the 11g client can connect to. =head1 BUGS AND LIMITATIONS -There is a known problem with the 11.2g Oracle client and the -C PL/SQL function. +There is a known problem with the 11.2g Oracle client and the +C PL/SQL function. See L for the details. @@ -5365,7 +5377,7 @@ Also PL/Vision from RevealNet and Steven Feuerstein, and DBI by Tim Bunce L. -The original C was by Tim Bunce. +The original C was by Tim Bunce. Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the auspice of the Pythian Group (L). From d6f15a9d6c337ec3e1091540deba0c55b076a16e Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 6 Dec 2011 16:19:53 -0500 Subject: [PATCH 083/637] v1.36 --- Changes | 4 ++++ Oracle.pm | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index d595259c..212994ef 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,9 @@ Revision history for DBD::Oracle +Changes in DBD-Oracle 1.36 (6-12-2011) + + - promote 1.35_00 to official release + Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] diff --git a/Oracle.pm b/Oracle.pm index a7c7ac36..9edc3648 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -7,7 +7,7 @@ require 5.006; -$DBD::Oracle::VERSION = '1.35_00'; +$DBD::Oracle::VERSION = '1.36'; my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; From 2b70a29b3bc78ed6d31de6a8c46062fb486611e6 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 16 Dec 2011 15:34:20 -0500 Subject: [PATCH 084/637] fix documentation --- Changes | 5 +++-- Oracle.pm | 12 +++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index 21617056..e2d5a81e 100644 --- a/Changes +++ b/Changes @@ -10,9 +10,10 @@ Changes in DBD-Oracle X.XX (XX-XX-XXXX) [DOCUMENTATION] - - [rt72716] Document possible problem with + - Document possible problem with ora_connect_with_default_signals and connect_cached - (Martin J. Evans) + [RT72716] (Martin J. Evans) + - Fix documentation for 'ora_fetch_scroll()' Changes in DBD-Oracle 1.35_00 (18-11-2011) diff --git a/Oracle.pm b/Oracle.pm index e5f26d02..fd69818f 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -3405,11 +3405,11 @@ The minimum value will always be 1 after the first fetch. The maximum value will =item ora_fetch_scroll - @ary = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); -Works the same as fetchrow_array method however, one passes in a 'Fetch Orientation' constant and a fetch_offset +Works the same as C, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset value which will then determine the row that will be fetched. It returns the row as a list containing the field values. -Null fields are returned as undef values in the list. +Null fields are returned as I values in the list. The valid orientation constant and fetch offset values combination are detailed below @@ -3420,13 +3420,15 @@ The valid orientation constant and fetch offset values combination are detailed OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset value is ignored. + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. - OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the - fetch offset value. OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. From 7fffbd92c708acfd9bdadefe63c18311e43a7048 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 16 Dec 2011 20:42:40 +0000 Subject: [PATCH 085/637] fix documentation for ora_fetch_scroll Conflicts: Changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15049 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 +++-- Oracle.pm | 12 +++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index 21617056..e2d5a81e 100644 --- a/Changes +++ b/Changes @@ -10,9 +10,10 @@ Changes in DBD-Oracle X.XX (XX-XX-XXXX) [DOCUMENTATION] - - [rt72716] Document possible problem with + - Document possible problem with ora_connect_with_default_signals and connect_cached - (Martin J. Evans) + [RT72716] (Martin J. Evans) + - Fix documentation for 'ora_fetch_scroll()' Changes in DBD-Oracle 1.35_00 (18-11-2011) diff --git a/Oracle.pm b/Oracle.pm index e5f26d02..fd69818f 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -3405,11 +3405,11 @@ The minimum value will always be 1 after the first fetch. The maximum value will =item ora_fetch_scroll - @ary = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); -Works the same as fetchrow_array method however, one passes in a 'Fetch Orientation' constant and a fetch_offset +Works the same as C, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset value which will then determine the row that will be fetched. It returns the row as a list containing the field values. -Null fields are returned as undef values in the list. +Null fields are returned as I values in the list. The valid orientation constant and fetch offset values combination are detailed below @@ -3420,13 +3420,15 @@ The valid orientation constant and fetch offset values combination are detailed OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset value is ignored. + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. - OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the - fetch offset value. OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. From addd9ae295524fba6ee000861f13b45cc75b6512 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 16 Dec 2011 15:49:54 -0500 Subject: [PATCH 086/637] add sysasm mode --- Changes | 4 ++++ Oracle.pm | 10 +++++----- Oracle.xs | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index e2d5a81e..19f21f8a 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,10 @@ Revision history for DBD::Oracle Changes in DBD-Oracle X.XX (XX-XX-XXXX) + [ENHANCEMENTS] + - added SYSASM session mode. [RT651211] (patch from + Anthony DeRobertis, reported by Julián Moreno Patiño) + [BUG FIXES] - applied patch from Charles Jardine avoiding undefined values diff --git a/Oracle.pm b/Oracle.pm index fd69818f..f268f4e0 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -27,7 +27,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; ORA_CLOB ORA_BLOB ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI SQLT_CHR SQLT_BIN ) ], - ora_session_modes => [ qw( ORA_SYSDBA ORA_SYSOPER ) ], + ora_session_modes => [ qw( ORA_SYSDBA ORA_SYSOPER ORA_SYSASM) ], ora_fetch_orient => [ qw( OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST OCI_FETCH_LAST OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE)], @@ -1131,7 +1131,7 @@ consult the L documentation first! =item :ora_session_modes -ORA_SYSDBA ORA_SYSOPER +ORA_SYSDBA ORA_SYSOPER ORA_SYSASM =item :ora_types @@ -1500,9 +1500,9 @@ successive failover events when the event is OCI_FO_ERROR. =head4 ora_session_mode -The ora_session_mode attribute can be used to connect with SYSDBA -authorization and SYSOPER authorization. -The ORA_SYSDBA and ORA_SYSOPER constants can be imported using +The ora_session_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA_SYSASM authorization. +The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using use DBD::Oracle qw(:ora_session_modes); diff --git a/Oracle.xs b/Oracle.xs index 84667512..fa79d0bf 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -29,6 +29,7 @@ constant(name=Nullch) ORA_NUMBER_TABLE = ORA_NUMBER_TABLE ORA_SYSDBA = 0x0002 ORA_SYSOPER = 0x0004 + ORA_SYSASM = 0x8000 SQLCS_IMPLICIT = SQLCS_IMPLICIT SQLCS_NCHAR = SQLCS_NCHAR SQLT_INT = SQLT_INT From dbc6904caaf13744a39602bd1c9a04c20aa26ef4 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 16 Dec 2011 20:51:01 +0000 Subject: [PATCH 087/637] add sysasm mode git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15050 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ Oracle.pm | 10 +++++----- Oracle.xs | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index e2d5a81e..19f21f8a 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,10 @@ Revision history for DBD::Oracle Changes in DBD-Oracle X.XX (XX-XX-XXXX) + [ENHANCEMENTS] + - added SYSASM session mode. [RT651211] (patch from + Anthony DeRobertis, reported by Julián Moreno Patiño) + [BUG FIXES] - applied patch from Charles Jardine avoiding undefined values diff --git a/Oracle.pm b/Oracle.pm index fd69818f..f268f4e0 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -27,7 +27,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; ORA_CLOB ORA_BLOB ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI SQLT_CHR SQLT_BIN ) ], - ora_session_modes => [ qw( ORA_SYSDBA ORA_SYSOPER ) ], + ora_session_modes => [ qw( ORA_SYSDBA ORA_SYSOPER ORA_SYSASM) ], ora_fetch_orient => [ qw( OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST OCI_FETCH_LAST OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE)], @@ -1131,7 +1131,7 @@ consult the L documentation first! =item :ora_session_modes -ORA_SYSDBA ORA_SYSOPER +ORA_SYSDBA ORA_SYSOPER ORA_SYSASM =item :ora_types @@ -1500,9 +1500,9 @@ successive failover events when the event is OCI_FO_ERROR. =head4 ora_session_mode -The ora_session_mode attribute can be used to connect with SYSDBA -authorization and SYSOPER authorization. -The ORA_SYSDBA and ORA_SYSOPER constants can be imported using +The ora_session_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA_SYSASM authorization. +The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using use DBD::Oracle qw(:ora_session_modes); diff --git a/Oracle.xs b/Oracle.xs index 84667512..fa79d0bf 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -29,6 +29,7 @@ constant(name=Nullch) ORA_NUMBER_TABLE = ORA_NUMBER_TABLE ORA_SYSDBA = 0x0002 ORA_SYSOPER = 0x0004 + ORA_SYSASM = 0x8000 SQLCS_IMPLICIT = SQLCS_IMPLICIT SQLCS_NCHAR = SQLCS_NCHAR SQLT_INT = SQLT_INT From 3f6ca72143f7efd1108c64d59830c42f08533ea5 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 23 Dec 2011 13:57:17 -0500 Subject: [PATCH 088/637] TNS_ADMIN check fixed --- Changes | 1 + Oracle.pm | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 19f21f8a..7314eeaa 100644 --- a/Changes +++ b/Changes @@ -11,6 +11,7 @@ Changes in DBD-Oracle X.XX (XX-XX-XXXX) - applied patch from Charles Jardine avoiding undefined values warnings in ora_server_version when the database is not open [RT72623] (Martin J. Evans) + - TNS_ADMIN was ignored [RT73456] [DOCUMENTATION] diff --git a/Oracle.pm b/Oracle.pm index f268f4e0..75d7f2a8 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -155,8 +155,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; push @tns_admin, '/var/opt/oracle', '/etc'; TNS_ADMIN: - foreach $d ( @tns_admin ) { - next TNS_ADMIN unless $d and -f $d; + foreach $d ( grep { $_ and -d $_ } @tns_admin ) { open FH, '<', "$d/tnsnames.ora" or next TNS_ADMIN; $drh->trace_msg("Loading $d/tnsnames.ora\n") if $debug; From 9a252de0db01ee04910c6acbd414ce0ef3081268 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 23 Dec 2011 13:58:58 -0500 Subject: [PATCH 089/637] bring in changelog from v1.36 --- Changes | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changes b/Changes index 7314eeaa..1b21a226 100644 --- a/Changes +++ b/Changes @@ -20,6 +20,10 @@ Changes in DBD-Oracle X.XX (XX-XX-XXXX) [RT72716] (Martin J. Evans) - Fix documentation for 'ora_fetch_scroll()' +Changes in DBD-Oracle 1.36 (6-12-2011) + + - promote 1.35_00 to official release + Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] From 4a9eba9fe8565ef293ddd7c1e6dbce28dbe36861 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 23 Dec 2011 14:26:15 -0500 Subject: [PATCH 090/637] groom for dist.ini --- .gitignore | 1 + MANIFEST | 76 +++++++++++++++++-------------- MANIFEST.SKIP | 1 + Makefile.PL | 4 +- dist.ini | 20 ++++++++ Oracle.pm => lib/DBD/Oracle.pm | 8 +--- lib/DBD/Oracle/Object.pm | 3 +- lib/DBD/Oracle/Troubleshooting.pm | 7 ++- 8 files changed, 72 insertions(+), 48 deletions(-) create mode 100644 dist.ini rename Oracle.pm => lib/DBD/Oracle.pm (99%) diff --git a/.gitignore b/.gitignore index 4b3129c9..15e927c8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ MYMETA.json dbdimp.o mk.pm oci8.o +DBD-Oracle* diff --git a/MANIFEST b/MANIFEST index 96251b9e..436c409e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,35 +1,12 @@ Changes -dbdimp.c -dbdimp.h -dbivport.h -hints/dgux.pl -hints/macos_bundle.syms -hints/macos_lib.syms -hints/macos_syms.pl -hints/svr4.pl -lib/DBD/Oracle/GetInfo.pm -lib/DBD/Oracle/Object.pm -Makefile.PL +INSTALL +LICENSE MANIFEST -mkta.pl -oci.def OCI.DLL export declarations -oci8.c -ocitrace.h -examples/bind.pl -examples/commit.pl -examples/curref.pl -examples/ex.pl -examples/japh -examples/mktable.pl -examples/oradump.pl -examples/proc.pl -examples/README -examples/sql -examples/tabinfo.pl +META.json +META.yml +Makefile.PL Oracle.h -Oracle.pm Oracle.xs -oraperl.ph Old oraperl file included for completeness of emulation Oraperl.pm README README-files/hpux/Makefile-Lincoln @@ -40,9 +17,44 @@ README.help.txt README.hpux.txt README.java.txt README.macosx.txt +README.mkdn README.sec.txt README.win32.txt README.win64.txt +Todo +dbdimp.c +dbdimp.h +dbivport.h +examples/README +examples/bind.pl +examples/commit.pl +examples/curref.pl +examples/ex.pl +examples/inserting_longs.pl +examples/japh +examples/mktable.pl +examples/ora_explain.pl +examples/oradump.pl +examples/proc.pl +examples/read_long_via_blob_read.pl +examples/sql +examples/tabinfo.pl +hints/dgux.pl +hints/macos_bundle.syms +hints/macos_lib.syms +hints/macos_syms.pl +hints/svr4.pl +lib/DBD/Oracle.pm +lib/DBD/Oracle/GetInfo.pm +lib/DBD/Oracle/Object.pm +lib/DBD/Oracle/Troubleshooting.pm +mkta.pl +oci.def +oci8.c +ocitrace.h +oraperl.ph +t/000-report-versions.t +t/00versions.t t/01base.t t/10general.t t/12impdata.t @@ -76,12 +88,6 @@ t/60reauth.t t/70meta.t t/80ora_charset.t t/nchar_test_lib.pl +t/rt13865.t test.pl -Todo typemap -examples/ora_explain.pl -t/00versions.t -lib/DBD/Oracle/Troubleshooting.pm -examples/inserting_longs.pl -examples/read_long_via_blob_read.pl -t/rt13865.t diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index a880e9d5..c7db4c66 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -29,3 +29,4 @@ Oracle.o Oracle.xsi pm_to_blib +dist.ini diff --git a/Makefile.PL b/Makefile.PL index 834cd0e7..878be69d 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -46,7 +46,7 @@ $| = 1; my %opts = ( NAME => 'DBD::Oracle', - VERSION_FROM => 'Oracle.pm', + VERSION_FROM => 'lib/DBD/Oracle.pm', PREREQ_PM => { "Test::Simple" => 0.90, # actually Test::More pkg in T::S dist "DBI" => 1.51}, OBJECT => '$(O_FILES)', @@ -83,7 +83,7 @@ $eumm =~ tr/_//d; if ($eumm >= 5.43) { $opts{AUTHOR} = 'Tim Bunce (dbi-users@perl.org)'; - $opts{ABSTRACT_FROM} = 'Oracle.pm'; + $opts{ABSTRACT_FROM} = 'lib/DBD/Oracle.pm'; $opts{PREREQ_PM} = { DBI => 1.51 }; $opts{CAPI} = 'TRUE' if $Config{archname} =~ /-object\b/i; } diff --git a/dist.ini b/dist.ini new file mode 100644 index 00000000..20726fc4 --- /dev/null +++ b/dist.ini @@ -0,0 +1,20 @@ +name = DBD-Oracle +author = Tim Bunce +author = John Scoles +author = Yanick Champoux +license = Perl_5 +copyright_holder = Tim Bunce +copyright_year = 1994 + +version = 1.37_00 + +[Authority] +authority=cpan:PYTHIAN + +[@Filter] +-bundle=@YANICK +-remove=Author::YANICK::NextSemanticVersion +-remove=ModuleBuild +-remove=Authority +-remove=Signature + diff --git a/Oracle.pm b/lib/DBD/Oracle.pm similarity index 99% rename from Oracle.pm rename to lib/DBD/Oracle.pm index 75d7f2a8..cd863cd9 100644 --- a/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -7,12 +7,11 @@ require 5.006; -$DBD::Oracle::VERSION = '1.35_00'; - my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { - package DBD::Oracle; +package DBD::Oracle; +# ABSTRACT: Oracle database driver for the DBI module use DBI (); use DynaLoader (); @@ -1097,9 +1096,6 @@ SQL __END__ -=head1 NAME - -DBD::Oracle - Oracle database driver for the DBI module =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 4af4cdbc..39a99498 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,4 +1,5 @@ package DBD::Oracle::Object; +# ABSTRACT: Wrapper for Oracle objects use strict; use warnings; @@ -21,4 +22,4 @@ sub attr { return $self->attr_hash; } -1; \ No newline at end of file +1; diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 7522d8c9..24855d20 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,8 +1,7 @@ -=pod - -=head1 NAME +package DBD::Oracle::Troubleshooting; +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle -DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle +=pod =head1 CONNECTING TO ORACLE From 9c3d519275161c6846377541065cc61622b9d075 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 30 Dec 2011 15:47:14 -0500 Subject: [PATCH 091/637] Changes now using {{$NEXT}} --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index 1b21a226..e5a50cae 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -Changes in DBD-Oracle X.XX (XX-XX-XXXX) +{{$NEXT}} [ENHANCEMENTS] - added SYSASM session mode. [RT651211] (patch from From 07464d529787deb29f82c93f4226cebe204ec3f8 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 30 Dec 2011 15:59:30 -0500 Subject: [PATCH 092/637] add MakeMaker::Custom --- dist.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dist.ini b/dist.ini index 20726fc4..148ecba4 100644 --- a/dist.ini +++ b/dist.ini @@ -11,6 +11,8 @@ version = 1.37_00 [Authority] authority=cpan:PYTHIAN +[MakeMaker::Custom] + [@Filter] -bundle=@YANICK -remove=Author::YANICK::NextSemanticVersion From 541a7e5545e3d272ee6bcecb441eff0b9fea9b56 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 30 Dec 2011 21:13:06 +0000 Subject: [PATCH 093/637] bring in changelog from v1.36 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15053 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 +++++ Oracle.pm | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 19f21f8a..1b21a226 100644 --- a/Changes +++ b/Changes @@ -11,6 +11,7 @@ Changes in DBD-Oracle X.XX (XX-XX-XXXX) - applied patch from Charles Jardine avoiding undefined values warnings in ora_server_version when the database is not open [RT72623] (Martin J. Evans) + - TNS_ADMIN was ignored [RT73456] [DOCUMENTATION] @@ -19,6 +20,10 @@ Changes in DBD-Oracle X.XX (XX-XX-XXXX) [RT72716] (Martin J. Evans) - Fix documentation for 'ora_fetch_scroll()' +Changes in DBD-Oracle 1.36 (6-12-2011) + + - promote 1.35_00 to official release + Changes in DBD-Oracle 1.35_00 (18-11-2011) [BUG FIXES] diff --git a/Oracle.pm b/Oracle.pm index f268f4e0..75d7f2a8 100644 --- a/Oracle.pm +++ b/Oracle.pm @@ -155,8 +155,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; push @tns_admin, '/var/opt/oracle', '/etc'; TNS_ADMIN: - foreach $d ( @tns_admin ) { - next TNS_ADMIN unless $d and -f $d; + foreach $d ( grep { $_ and -d $_ } @tns_admin ) { open FH, '<', "$d/tnsnames.ora" or next TNS_ADMIN; $drh->trace_msg("Loading $d/tnsnames.ora\n") if $debug; From 4aa505f08f119ef7604b527fa42bb7093e8e1556 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 30 Dec 2011 21:15:36 +0000 Subject: [PATCH 094/637] Merge branch 'releases' into my_trunk git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15054 50811bd7-b8ce-0310-adc1-d9db26280581 --- .gitignore | 13 - Changes | 2 +- INSTALL | 44 + LICENSE | 377 ++ MANIFEST | 76 +- MANIFEST.SKIP | 31 - META.json | 97 + META.yml | 63 + Makefile.PL | 4 +- README | 4338 ++++++++++++++- README.mkdn | 4228 +++++++++++++++ err_bind/err_bind_param_inout_overrun_bug.msg | 108 - err_bind/err_bindarrays.msg | 241 - err_bind/err_bindclobleak.msg | 58 - err_bind/err_bindnullhash.msg | 77 - err_bind/err_trailingblank.msg | 345 -- err_build/err_aix64.msg | 142 - err_build/err_hpux_ld.msg | 89 - err_build/err_hpuxsuccess.msg | 279 - err_build/err_instantclient.msg | 207 - err_build/err_makefileundef.msg | 87 - err_build/err_memleak.msg | 95 - err_build/err_solarisnotes.msg | 482 -- err_build/err_testfailnotable.msg | 97 - err_docs/err_trace.msg | 14 - err_lob/err_csr_clob.msg | 65 - err_lob/err_loblenwide.msg | 95 - err_lob/err_lobtesttblfail.msg | 208 - err_lob/err_nclob_form.msg | 189 - err_lob/err_nulllobsegv.msg | 93 - err_lob/err_tmplobfree.msg | 537 -- err_unicode/err_char.msg | 129 - err_unicode/err_twolongstr.msg | 1256 ----- err_unsorted/err_etherreal.msg | 90 - err_unsorted/err_memleak2.msg | 476 -- err_unsorted/err_multiora.msg | 470 -- err_unsorted/err_ora9ir2oci.msg | 27 - err_unsorted/err_ref_type.msg | 115 - err_unsorted/err_refcsr_rowcache.msg | 85 - err_unsorted/err_refcsr_slow.msg | 347 -- err_unsorted/err_slowcsr.msg | 316 -- err_unsorted/err_svrparse.msg | 4717 ----------------- err_unsorted/err_xml.msg | 118 - err_unsorted/err_xml2.msg | 700 --- err_unsorted/err_xmltypebindplsql.msg | 174 - Oracle.pm => lib/DBD/Oracle.pm | 111 +- lib/DBD/Oracle/GetInfo.pm | 46 + lib/DBD/Oracle/Object.pm | 94 +- lib/DBD/Oracle/Troubleshooting.pm | 47 +- t/000-report-versions.t | 446 ++ xt/changes.t | 8 - xt/manifest.t | 21 - xt/pod.t | 11 - 53 files changed, 9634 insertions(+), 12951 deletions(-) delete mode 100644 .gitignore create mode 100644 INSTALL create mode 100644 LICENSE delete mode 100644 MANIFEST.SKIP create mode 100644 META.json create mode 100644 META.yml create mode 100644 README.mkdn delete mode 100644 err_bind/err_bind_param_inout_overrun_bug.msg delete mode 100644 err_bind/err_bindarrays.msg delete mode 100644 err_bind/err_bindclobleak.msg delete mode 100644 err_bind/err_bindnullhash.msg delete mode 100644 err_bind/err_trailingblank.msg delete mode 100644 err_build/err_aix64.msg delete mode 100644 err_build/err_hpux_ld.msg delete mode 100644 err_build/err_hpuxsuccess.msg delete mode 100644 err_build/err_instantclient.msg delete mode 100644 err_build/err_makefileundef.msg delete mode 100644 err_build/err_memleak.msg delete mode 100644 err_build/err_solarisnotes.msg delete mode 100644 err_build/err_testfailnotable.msg delete mode 100644 err_docs/err_trace.msg delete mode 100644 err_lob/err_csr_clob.msg delete mode 100644 err_lob/err_loblenwide.msg delete mode 100644 err_lob/err_lobtesttblfail.msg delete mode 100644 err_lob/err_nclob_form.msg delete mode 100644 err_lob/err_nulllobsegv.msg delete mode 100644 err_lob/err_tmplobfree.msg delete mode 100644 err_unicode/err_char.msg delete mode 100644 err_unicode/err_twolongstr.msg delete mode 100644 err_unsorted/err_etherreal.msg delete mode 100644 err_unsorted/err_memleak2.msg delete mode 100644 err_unsorted/err_multiora.msg delete mode 100644 err_unsorted/err_ora9ir2oci.msg delete mode 100644 err_unsorted/err_ref_type.msg delete mode 100644 err_unsorted/err_refcsr_rowcache.msg delete mode 100644 err_unsorted/err_refcsr_slow.msg delete mode 100644 err_unsorted/err_slowcsr.msg delete mode 100644 err_unsorted/err_svrparse.msg delete mode 100644 err_unsorted/err_xml.msg delete mode 100644 err_unsorted/err_xml2.msg delete mode 100644 err_unsorted/err_xmltypebindplsql.msg rename Oracle.pm => lib/DBD/Oracle.pm (99%) create mode 100644 t/000-report-versions.t delete mode 100644 xt/changes.t delete mode 100644 xt/manifest.t delete mode 100644 xt/pod.t diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 4b3129c9..00000000 --- a/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -pm_to_blib -MYMETA.yml -Makefile -Makefile.old -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -blib -MYMETA.json -dbdimp.o -mk.pm -oci8.o diff --git a/Changes b/Changes index 1b21a226..63244b32 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -Changes in DBD-Oracle X.XX (XX-XX-XXXX) +1.37_00 2011-12-30 [ENHANCEMENTS] - added SYSASM session mode. [RT651211] (patch from diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..b5ab17a0 --- /dev/null +++ b/INSTALL @@ -0,0 +1,44 @@ + +This is the Perl distribution DBD-Oracle. + +Installing DBD-Oracle is straightforward. + +## Installation with cpanm + +If you have cpanm, you only need one line: + + % cpanm DBD::Oracle + +If you are installing into a system-wide directory, you may need to pass the +"-S" flag to cpanm, which uses sudo to install the module: + + % cpanm -S DBD::Oracle + +## Installing with the CPAN shell + +Alternatively, if your CPAN shell is set up, you should just be able to do: + + % cpan DBD::Oracle + +## Manual installation + +As a last resort, you can manually install it. Download the tarball, untar it, +then build it: + + % perl Makefile.PL + % make && make test + +Then install it: + + % make install + +If you are installing into a system-wide directory, you may need to run: + + % sudo make install + +## Documentation + +DBD-Oracle documentation is available as POD. +You can run perldoc from a shell to read the documentation: + + % perldoc DBD::Oracle diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..a6a371c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,377 @@ +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +Terms of the Perl programming language system itself + +a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or +b) the "Artistic License" + +--- The GNU General Public License, Version 1, February 1989 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The GNU General Public License, Version 1, February 1989 + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! + + +--- The Artistic License 1.0 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The Artistic License 1.0 + +The Artistic License + +Preamble + +The intent of this document is to state the conditions under which a Package +may be copied, such that the Copyright Holder maintains some semblance of +artistic control over the development of the package, while giving the users of +the package the right to use and distribute the Package in a more-or-less +customary fashion, plus the right to make reasonable modifications. + +Definitions: + + - "Package" refers to the collection of files distributed by the Copyright + Holder, and derivatives of that collection of files created through + textual modification. + - "Standard Version" refers to such a Package if it has not been modified, + or has been modified in accordance with the wishes of the Copyright + Holder. + - "Copyright Holder" is whoever is named in the copyright or copyrights for + the package. + - "You" is you, if you're thinking about copying or distributing this Package. + - "Reasonable copying fee" is whatever you can justify on the basis of media + cost, duplication charges, time of people involved, and so on. (You will + not be required to justify it to the Copyright Holder, but only to the + computing community at large as a market that must bear the fee.) + - "Freely Available" means that no fee is charged for the item itself, though + there may be fees involved in handling the item. It also means that + recipients of the item may redistribute it under the same conditions they + received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications derived +from the Public Domain or from the Copyright Holder. A Package modified in such +a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided that +you insert a prominent notice in each changed file stating how and when you +changed that file, and provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major archive site + such as ftp.uu.net, or by allowing the Copyright Holder to include your + modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict with + standard executables, which must also be provided, and provide a separate + manual page for each non-standard executable that clearly documents how it + differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or executable +form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where to + get the Standard Version. + + b) accompany the distribution with the machine-readable source of the Package + with your modifications. + + c) accompany any non-standard executables with their corresponding Standard + Version executables, giving the non-standard executables non-standard + names, and clearly documenting the differences in manual pages (or + equivalent), together with instructions on where to get the Standard + Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. You +may not charge a fee for this Package itself. However, you may distribute this +Package in aggregate with other (possibly commercial) programs as part of a +larger (possibly commercial) software distribution provided that you do not +advertise this Package as a product of your own. + +6. The scripts and library files supplied as input to or produced as output +from the programs of this Package do not automatically fall under the copyright +of this Package, but belong to whomever generated them, and may be sold +commercially, and may be aggregated with this Package. + +7. C or perl subroutines supplied by you and linked into this Package shall not +be considered part of this Package. + +8. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +The End + diff --git a/MANIFEST b/MANIFEST index 96251b9e..436c409e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,35 +1,12 @@ Changes -dbdimp.c -dbdimp.h -dbivport.h -hints/dgux.pl -hints/macos_bundle.syms -hints/macos_lib.syms -hints/macos_syms.pl -hints/svr4.pl -lib/DBD/Oracle/GetInfo.pm -lib/DBD/Oracle/Object.pm -Makefile.PL +INSTALL +LICENSE MANIFEST -mkta.pl -oci.def OCI.DLL export declarations -oci8.c -ocitrace.h -examples/bind.pl -examples/commit.pl -examples/curref.pl -examples/ex.pl -examples/japh -examples/mktable.pl -examples/oradump.pl -examples/proc.pl -examples/README -examples/sql -examples/tabinfo.pl +META.json +META.yml +Makefile.PL Oracle.h -Oracle.pm Oracle.xs -oraperl.ph Old oraperl file included for completeness of emulation Oraperl.pm README README-files/hpux/Makefile-Lincoln @@ -40,9 +17,44 @@ README.help.txt README.hpux.txt README.java.txt README.macosx.txt +README.mkdn README.sec.txt README.win32.txt README.win64.txt +Todo +dbdimp.c +dbdimp.h +dbivport.h +examples/README +examples/bind.pl +examples/commit.pl +examples/curref.pl +examples/ex.pl +examples/inserting_longs.pl +examples/japh +examples/mktable.pl +examples/ora_explain.pl +examples/oradump.pl +examples/proc.pl +examples/read_long_via_blob_read.pl +examples/sql +examples/tabinfo.pl +hints/dgux.pl +hints/macos_bundle.syms +hints/macos_lib.syms +hints/macos_syms.pl +hints/svr4.pl +lib/DBD/Oracle.pm +lib/DBD/Oracle/GetInfo.pm +lib/DBD/Oracle/Object.pm +lib/DBD/Oracle/Troubleshooting.pm +mkta.pl +oci.def +oci8.c +ocitrace.h +oraperl.ph +t/000-report-versions.t +t/00versions.t t/01base.t t/10general.t t/12impdata.t @@ -76,12 +88,6 @@ t/60reauth.t t/70meta.t t/80ora_charset.t t/nchar_test_lib.pl +t/rt13865.t test.pl -Todo typemap -examples/ora_explain.pl -t/00versions.t -lib/DBD/Oracle/Troubleshooting.pm -examples/inserting_longs.pl -examples/read_long_via_blob_read.pl -t/rt13865.t diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP deleted file mode 100644 index a880e9d5..00000000 --- a/MANIFEST.SKIP +++ /dev/null @@ -1,31 +0,0 @@ -^DBD-Oracle-.* -\.svn\b -\.orig$ -\..*.swp$ -^.pure -^DIST/ -^MANIFEST\. -^Makefile$ -^blib/ -^csr/ -^err[/_] -^old/ -^info/ -^oci8/ -^oracle/ -^tags$ -~$ -^\.git -^xt -dbdimp.o -Makefile.old -mk.pm -MYMETA.json -MYMETA.yml -oci8.o -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -pm_to_blib - diff --git a/META.json b/META.json new file mode 100644 index 00000000..3ce64a33 --- /dev/null +++ b/META.json @@ -0,0 +1,97 @@ +{ + "abstract" : "Oracle database driver for the DBI module", + "author" : [ + "Tim Bunce ", + "John Scoles", + "Yanick Champoux " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "DBD-Oracle", + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "6.30" + } + }, + "runtime" : { + "requires" : { + "DBI" : 0, + "DynaLoader" : 0, + "Exporter" : 0, + "perl" : "5.006", + "strict" : 0, + "warnings" : 0 + } + }, + "test" : { + "requires" : { + "Carp" : 0, + "Config" : 0, + "Data::Dumper" : 0, + "Devel::Peek" : 0, + "Encode" : 0, + "Math::BigInt" : 0, + "Oraperl" : 0, + "Scalar::Util" : 0, + "Test::More" : "0.94", + "Thread::Semaphore" : 0, + "utf8" : 0, + "vars" : 0 + } + } + }, + "provides" : { + "DBD::Oracle" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.37_00" + }, + "DBD::Oracle::GetInfo" : { + "file" : "lib/DBD/Oracle/GetInfo.pm", + "version" : "1.37_00" + }, + "DBD::Oracle::Object" : { + "file" : "lib/DBD/Oracle/Object.pm", + "version" : "1.37_00" + }, + "DBD::Oracle::Troubleshooting" : { + "file" : "lib/DBD/Oracle/Troubleshooting.pm", + "version" : "1.37_00" + }, + "DBD::Oracle::db" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.37_00" + }, + "DBD::Oracle::dr" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.37_00" + }, + "DBD::Oracle::st" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.37_00" + } + }, + "release_status" : "testing", + "resources" : { + "bugtracker" : { + "mailto" : "bug-dbd-oracle at rt.cpan.org", + "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle" + }, + "homepage" : "http://search.cpan.org/dist/DBD-Oracle/", + "repository" : { + "type" : "git", + "url" : "git://github.com/yanick/DBD-Oracle.git", + "web" : "http://github.com/yanick/DBD-Oracle/tree" + } + }, + "version" : "1.37_00", + "x_authority" : "cpan:PYTHIAN" +} + diff --git a/META.yml b/META.yml new file mode 100644 index 00000000..7247e13c --- /dev/null +++ b/META.yml @@ -0,0 +1,63 @@ +--- +abstract: 'Oracle database driver for the DBI module' +author: + - 'Tim Bunce ' + - 'John Scoles' + - 'Yanick Champoux ' +build_requires: + Carp: 0 + Config: 0 + Data::Dumper: 0 + Devel::Peek: 0 + Encode: 0 + Math::BigInt: 0 + Oraperl: 0 + Scalar::Util: 0 + Test::More: 0.94 + Thread::Semaphore: 0 + utf8: 0 + vars: 0 +configure_requires: + ExtUtils::MakeMaker: 6.30 +dynamic_config: 0 +generated_by: 'Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: DBD-Oracle +provides: + DBD::Oracle: + file: lib/DBD/Oracle.pm + version: 1.37_00 + DBD::Oracle::GetInfo: + file: lib/DBD/Oracle/GetInfo.pm + version: 1.37_00 + DBD::Oracle::Object: + file: lib/DBD/Oracle/Object.pm + version: 1.37_00 + DBD::Oracle::Troubleshooting: + file: lib/DBD/Oracle/Troubleshooting.pm + version: 1.37_00 + DBD::Oracle::db: + file: lib/DBD/Oracle.pm + version: 1.37_00 + DBD::Oracle::dr: + file: lib/DBD/Oracle.pm + version: 1.37_00 + DBD::Oracle::st: + file: lib/DBD/Oracle.pm + version: 1.37_00 +requires: + DBI: 0 + DynaLoader: 0 + Exporter: 0 + perl: 5.006 + strict: 0 + warnings: 0 +resources: + bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle + homepage: http://search.cpan.org/dist/DBD-Oracle/ + repository: git://github.com/yanick/DBD-Oracle.git +version: 1.37_00 +x_authority: cpan:PYTHIAN diff --git a/Makefile.PL b/Makefile.PL index 834cd0e7..878be69d 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -46,7 +46,7 @@ $| = 1; my %opts = ( NAME => 'DBD::Oracle', - VERSION_FROM => 'Oracle.pm', + VERSION_FROM => 'lib/DBD/Oracle.pm', PREREQ_PM => { "Test::Simple" => 0.90, # actually Test::More pkg in T::S dist "DBI" => 1.51}, OBJECT => '$(O_FILES)', @@ -83,7 +83,7 @@ $eumm =~ tr/_//d; if ($eumm >= 5.43) { $opts{AUTHOR} = 'Tim Bunce (dbi-users@perl.org)'; - $opts{ABSTRACT_FROM} = 'Oracle.pm'; + $opts{ABSTRACT_FROM} = 'lib/DBD/Oracle.pm'; $opts{PREREQ_PM} = { DBI => 1.51 }; $opts{CAPI} = 'TRUE' if $Config{archname} =~ /-object\b/i; } diff --git a/README b/README index fd2b28aa..55a6595b 100644 --- a/README +++ b/README @@ -1,301 +1,4183 @@ +NAME + DBD::Oracle - Oracle database driver for the DBI module -DBD::Oracle -- an Oracle interface for Perl 5. +VERSION + version 1.37_00 - Copyright (c) 1994-2006 Tim Bunce, Ireland. +SYNOPSIS + use DBI; - See the COPYRIGHT section in the Oracle.pm file for terms. - See also the MAINTAINER section in the Oracle.pm + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); - PLEASE READ THE ENTIRE README FILE CAREFULLY ! + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); - AND THEN READ ANY README.* FILES RELEVANT TO YOUR PLATFORM: + # See the DBI module documentation for full details - README.aix.txt - AIX - README.hpux.txt - HP-UX - README.java.txt - Java/thread problem on Solaris - README.macosx.txt - Mac OS/X - README.win32.txt - MS Windows - README.wingcc.txt - MS Windows using GCC - README.* - see if there's a file for your platform + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); - You may find these useful +DESCRIPTION + DBD::Oracle is a Perl module which works with the DBI module to provide + access to Oracle databases. - README.help.txt - Help and hints on build problems - README.sec.txt - Oracle security issues to be aware of - README.login.txt - Help on how to connect to Oracle - README.longs.txt - Help on handling LONGs - README.clients.txt - What Oracle client files you need installed + This documentation describes driver specific behaviour and restrictions. + It is not supposed to be used as the only reference for the user. In any + case consult the DBI documentation first! +CONSTANTS + :ora_session_modes + ORA_SYSDBA ORA_SYSOPER ORA_SYSASM -*** QUICK START GUIDE: + :ora_types + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN - The DBI requires one or more 'driver' modules to talk to databases. - Fetch, build and install the DBI module as per its README file. - You may then delete its source directory tree since it's no longer needed. - Use the 'perldoc DBI' command to read the DBI documentation. + SQLCS_IMPLICIT + SQLCS_NCHAR + SQLCS_IMPLICIT and SQLCS_NCHAR are *character set form* values. See + notes about Unicode elsewhere in this document. - Fetch this DBD::Oracle driver module and unpack it. - Follow the guidelines in this README file carefully. + SQLT_INT + SQLT_FLT + These types are used only internally, and may be specified as + internal bind type for ORA_NUMBER_TABLE. See notes about + ORA_NUMBER_TABLE elsewhere in this document + ORA_OCI + Oracle doesn't provide a formal API for determining the exact + version number of the OCI client library used, so DBD::Oracle has to + go digging (and sometimes has to more or less guess). The ORA_OCI + constant holds the result of that process. -*** *BEFORE* BUILDING, TESTING AND INSTALLING DBD::Oracle: + In string context ORA_OCI returns the full "A.B.C.D" version string. - Build, test and install Perl 5 (at least 5.6.1) - It is very important to TEST it and INSTALL it! + In numeric context ORA_OCI returns the major.minor version number + (8.1, 9.2, 10.0 etc). But note that version numbers are not actually + floating point and so if Oracle ever makes a release that has a two + digit minor version, such as 9.10 it will have a lower numeric value + than the preceding 9.9 release. So use with care. - Build, test and install the DBI module (at least DBI 1.51). - It is very important to TEST it and INSTALL it! + The contents and format of ORA_OCI are subject to change (it may, + for example, become a *version object* in later releases). I + recommend that you avoid checking for exact values. - Remember to *read* the DBI README file and this one CAREFULLY! + :ora_fetch_orient + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE - Install enough Oracle software to enable DBD::Oracle to build. + These constants are used to set the orientation of a fetch on a + scrollable cursor. - For Oracle Instant Client: that means install the following packages: - * The "Basic" package for the essential Oracle libraries. - * The "SDK" package for the headers and makefile. - * The "SQL*Plus" component is optional, but will help you check - your configuration and DBD::Oracle determine your Oracle version. + :ora_exe_modes + OCI_STMT_SCROLLABLE_READONLY - For full Oracle installs: that usually includes Pro*C and SQL*Net. - (That's not very specific because it varies between Oracle releases.). - As of release 1.22 support of Oracle clients before 9 was dropped. - The main reason for this is that next few versions of DBD::Oracle will introduce a number of new features - whicht will required a great deal of extra coding to make the OCI 8 work. - As well it is getting harder to find an Oracle client 8 to test against as well - Oracle no longer supports clients before 9. + :ora_fail_over + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL - The ORACLE_HOME environment variable must point to the Oracle Home - used to create DBD::Oracle. (Not essential under MS Windows). +DBI CLASS METHODS + connect + This method creates a database handle by connecting to a database, and + is the DBI equivalent of the "new" method. To open a connection to an + Oracle database you need to specify a database connection string (URL), + username and password. -*** MOST IMPORTANTLY: + The connection string is always of the form: "dbi:Oracle:" There are several ways to identify a database: - Make sure Oracle is working and you can use the Oracle sqlplus - command to talk to the database from the machine you - want to build DBD::Oracle on. This often involves setting - environment variables like PATH, LD_LIBRARY_PATH, TWO_TASK etc. - Consult Oracle documentation for more details. + 1 If the database is local, specifying the SID or service name will be + enough. - Only once you can connect to Oracle using sqlplus - should you try building and testing DBD::Oracle. + 2 If the database is defined in a TNSNAMES.ORA file, you can use the + service name given in the file -*** BUILDING: + 3 To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, + of the form: //host[:port][/service_name] -Execute: + If port name is not specified, 1521 is the default. If service name is + not specified, the hostname will be used as a service name. - perl Makefile.PL # use a perl that's in your PATH + The following examples show several ways a connection can be created: -Use the perl that is first on your PATH. Then execute: + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - make + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); -If you get an error like "make: not found" you need to find the -directory that has the make command installed in it (e.g. /usr/ccs/bin -on Solaris) and add that to your PATH environment variable. + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); -Don't worry about most warnings when make runs, specifically ones like -"end-of-loop code not reached", "... due to prototype", -"cast increases required alignment of target type", etc. + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); -If you have problems see the 'IF YOU HAVE PROBLEMS' section below. -If it builds without error you should then run 'make test'. For the -main tests to work they must be able to connect to an Oracle database. + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); -The tests default to using a DSN of "dbi:Oracle:" which means you'll be -connected to the default database based on your TWO_TASK or ORACLE_SID -environment variables. This default can be altered either by defining the -ORACLE_DSN environment variable or the DBI_DSN environment variable. -See the oracle_test_dsn() sub in t/nchar_test_lib.pl + OS authentication + To connect to a local database with a user which has been set up to + authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): -The supplied tests will connect to the database using the value of the -ORACLE_USERID environment variable to supply the username/password. -So you should set that to a valid user (e.g. 'scott/tiger') and ensure that -this user has sufficient privileges to create, insert into, select from and -drop a table, is also able to create, call and drop a procedure and is able to select from -systemtables like 'v$sessions'. Using 'system/manager' might work but is not -recommended! See also + $dbh = DBI->connect('dbi:Oracle:','/',''); -README.login.txt. + Note the lack of a connection name (use the ORACLE_SID environment + variable). If an explicit SID is used you will probably get an ORA-01004 + error. - make test + That only works for local databases. (Authentication to remote Oracle + databases using your Unix login name without a password is possible but + it is not secure and not recommended so not documented here. -If the all the formal tests pass then, finally, run: + Oracle Environment Variables + To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME + environment variable should be set correctly. In general, the value used + should match the version of Oracle that was used to build DBD::Oracle. + If using dynamic linking then ORACLE_HOME should match the version of + Oracle that will be used to load in the Oracle client libraries (via + LD_LIBRARY_PATH, ldconfig, or similar on Unix). - make install + Oracle can use two environment variables to specify default connections: + ORACLE_SID and TWO_TASK. + To use them, specify either a local SID or service name, or a service + name that is specified in the TNSNAMES.ORA file. -*** IF YOU HAVE PROBLEMS: + Note that if you have *both* local and remote databases, and you have + ORACLE_SID *and* TWO_TASK set, and you don't specify a fully qualified + connect string on the command line, TWO_TASK takes precedence over + ORACLE_SID (i.e. you get connected to remote system). -Make sure you are using a recent perl (5.6.1 or later) and make -sure it's on your PATH so you can say 'perl Makefile.PL' and not -'/path/to/perl Makefile.PL'. + It is highly recommended not to rely on environment variables and to + always explicitly specify the SID in the connection string. This can + prevent serious mistakes such as dropping a schema in the wrong + database, and generally makes debugging and troubleshooting easier. -If you get compiler errors refering to Perl's own header files -(.../CORE/*.h) then there is something wrong with your installation. -It is important to use a Perl that was built on the system you are using. -It's also important to use the same compiler that was used to build the -Perl you are using. + Also remember that depending on the operating system you are using the + differing "ORACLE" environment variables may be case sensitive, so if + you are not connecting as you should double check the case of both the + variable and its value. -If you have build/link or core dump problems try: - perl Makefile.PL -p -or - perl Makefile.PL -nob -If it helps then please let me know (and please include a copy -of the log from the failed default build, the log from the build that -worked, plus the output of the "perl -V" command). + Timezones + If the query is run through SQL*Net (mostly queries that are executed on + remote servers), Oracle will return the time zone based on the setting + of the UNIX environment variable "TZ" for the user who started the + listener. -Do not hand edit the generated Makefile unless you are completely sure -you understand the implications! Always try to make changes via the -Makefile.PL command line and/or editing the Makefile.PL. -You should not need to make any changes. If you do please let us -know so that I can try to make it automatic in a later release. + If the query is run locally, Oracle will return the time zone based on + the "TZ" environment variable setting of the user running the query. -If you just can't login or login takes a long time then read -README.login.txt + With local queries, you can change the time zone for a particular user + by simply changing the setting of "TZ". To check the current setting, + issue the UNIX "date" command. -If you have linking problems (errors related to libraries or functions) -then you could try forcing a 'static' build using: + Oracle DRCP + DBD::Oracle supports DRCP (Database Resident Connection Pool) so if you + have an 11.2 database and DRCP is enabled you can direct all of your + connections to it by adding ':POOLED' to the SID or setting a connection + attribute of ora_drcp, or set the SERVER=POOLED when using a TNSENTRY + style connection or even by setting an environment variable ORA_DRCP. + All of which are demonstrated below; - make realclean - perl Makefile.PL LINKTYPE=static - make - make perl (you'll need to use and install _this_ new perl binary) - make test - make -f Makefile.aperl inst_perl MAP_TARGET=perl (install new perl) - make install (install DBD::Oracle) + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') -But that's not recommended these days. + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') ->>> Also carefully read the README.help.txt file which is full of useful ->>> tips and workarounds for various problems of various systems. + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) -*** HOW TO REPORT PROBLEMS + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') -This software is supported via the dbi-users@perl.org mailing list. -(You don't need to subscribe to the list in order to post.) + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") -Please do NOT post problems to comp.lang.perl.*, perl5-porters@perl.org, -http://www.cpanforum.com/dist/DBD-Oracle, or google groups etc. + if the ORA_DRCP environment variable is set then just this -If you're *sure* the problem is a bug then you can post a bug report -to http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle -Problem reports that don't include sufficient detail (including the -information listed below and how to reproduce the problem) -are unlikely to get resolved. + $dbh = DBI->connect('dbi:Oracle:DB','username','password') -For more information and to keep informed about progress you can join the -mailing list. Send a message to dbi-users-help@perl.org for more information. + You can find a white paper on setting up DRCP and its advantages at + . -Please post details of any problems (or changes you needed to make) to -dbi-users@perl.org. - - -** IT IS IMPORTANT TO INCLUDE *ALL* THE FOLLOWING INFORMATION: + Please note that DRCP support in DBD::Oracle is relatively new so the + mechanics or its implementation are subject to change. -1. A complete log of all steps of the build, e.g.: + TAF (Transparent Application Failover) + Transparent Application Failover (TAF) is the feature in OCI that allows + for clients to automatically reconnect to an instance in the event of a + failure of the instance. The reconnect happens automatically from within + the OCI (Oracle Call Interface) library. DBD::Oracle now supports a + callback function that will fire when a TAF event takes place. The main + use of the callback is to give your program the opportunity to inform + the user that a failover is taking place. - (do a make realclean first) - perl Makefile.PL - make - make test + You will have to set up TAF on your instance before you can use this + callback. You can test your instance to see if you can use TAF callback + with - Make sure to include the 'stderr' output. The best way to do this is - to use the "script" command (man script). If that's not available - then "command > command.log 2>&1" (assuming you're not using csh). - The "2>&1" is required (after the stdout redirect) to redirect stderr - to the same place. + $dbh->ora_can_taf(); - If a test fails then also include the output of: + If you try to set up a callback without it being enabled DBD::Oracle + will croak. - perl -Mblib t/.t + It is outside the scope of this documents to go through all of the + possible TAF situations you might want to set up but here is a simple + example: -2. Full details of which version of Oracle client and server you're using - (if it wasn't automatically found and printed by "perl Makefile.PL") + The TNS entry for the instance has had the following added to the + CONNECT_DATA section -3. The output of perl -V (that's a capital V, not lowercase) + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) -4. If you get errors like "undefined symbol", "symbol not found", - "undefined reference", "Text relocation remains" or any similar - error then include the output of "perl Makefile.PL -s XXX" - where XXX is the name of one of the symbols. - Please don't send the entire output of this command, - just any obviously 'interesting' parts (if there are any). - See also the LINKTYPE=static notes above. + You will also have to create your own perl function that will be called + from the client. You can name it anything you want and it will always be + passed two parameters, the failover event value and the failover type. + You can also set a sleep value in case of failover error and the OCI + client will sleep for the specified seconds before it attempts another + event. -5. If you get a core dump, rebuild DBD::Oracle with debugging - enabled by executing: perl Makefile.PL -g (note the -g option) - then rerun the code to get a new core dump file, finally use a - debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. - NOTE: I may not be able to help you much without a stack trace! - It is worth fetching and building the GNU GDB debugger (>=4.15) if - you don't have a good debugger on your system. If desperate try: - make perl; ./perl script; echo '$c' | adb ./perl core - Also see the Devel::CoreStack module on CPAN. - -6. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun - make test after setting the environment variable PERL_DL_DEBUG to 2. - -7. If your installation succeeds, but your script does not behave - as you expect, the problem may be on your end. Before - sending to dbi-users, try writing a *small*, easy to use test case - to reproduce your problem. Also, use the DBI->trace method to - trace your database calls. + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants -It is important to check that you are using the latest version before -posting. If you're not then you're *very* likely to be told "upgrade to -the latest". You would do yourself a favour by upgrading beforehand. + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); -Try to help yourself first, then try to help others help you by following -these guidelines carefully. And remember, please don't mail developers -directly - use the dbi-users mailing list. + #create the perl TAF event function -Regards, -Tim. + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ -=============================================================================== -Examples and other info: + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); -README.help.txt -- READ IT FIRST IF YOU HAVE ANY PROBLEMS -README.win32.txt -- building DBD::Oracle under MS Windows -README.wingcc.txt -- building DBD::Oracle under MS Windows with gcc -README.macosx.txt -- building DBD::Oracle under MacOS X -README.clients.txt -- building/using DBD::Oracle on minimally configured systems -README.login.txt -- help for login problems -README.longs.txt -- examples dealing with LONG types (blobs) + } + return 0; + } -DBI 'home page': http://dbi.perl.org + The TAF types are as follows -Old archive site for Perl DB information: - ftp://ftp.demon.co.uk/pub/perl/db/ -Mailing list archive: /DBI/perldb-interest/ -Perl 4 Oraperl (v2.4) /perl4/oraperl/ - -Jeff Stander's stuff stands out for Oraperl: -Directories of interest might be - /pub/Oracle/sources - /pub/Oracle/sources/jstander - /pub/Oracle/sources/jstander/distrib - /pub/Oracle/sources/jstander/tsmlib - /pub/Oracle/sources/jstander/wdbex - /pub/Oracle/sources/web/scripts - /pub/Oracle/sources/dba - /pub/Oracle/sources/dba/imp2sql7 - /pub/Oracle/sources/Lonnroth - /pub/Oracle/sources/harrison - -http://www.bf.rmit.edu.au/~orafaq/perlish.html -ftp://ftp.bf.rmit.edu.au/pub/perl/db -ftp://ftp.bf.rmit.edu.au/pub/Oracle -ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources -ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip - -DBI and DBD::Oracle are very portable. If Perl and Oracle run on a platform -then the chances are that DBD::Oracle will as well. - -=============================================================================== - -See the large README.help.txt file for lots of hints and advice -about building and runtime issues. - -End. + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + + The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + + Connect Attributes + ora_ncs_buff_mtpl + You can customize the size of the buffer when selecting LOBs with the + built-in AUTO Lob. The default value is 4 which is probably excessive + for most situations but is needed for backward compatibility. If you not + converting between a NCS on the DB and the Client then you might want to + set this to 1 to reduce memory usage. + + This value can also be specified with the "ORA_DBD_NCS_BUFFER" + environment variable in which case it sets the value at the connect + stage. + + ora_drcp + For Oracle 11.2 or greater. + + Set to *1* to enable DRCP. Can also be set via the "ORA_DRCP" + environment variable. + + ora_drcp_class + If you are using DRCP, you can set a CONNECTION_CLASS for your pools as + well. As sessions from a DRCP cannot be shared by users, you can use + this setting to identify the same user across different applications. + OCI will ensure that sessions belonging to a 'class' are not shared + outside the class'. + + The values for ora_drcp_class cannot contain a '*' and must be less than + 1024 characters. + + This value can be also be specified with the "ORA_DRCP_CLASS" + environment variable. + + ora_drcp_min + This optional value specifies the minimum number of sessions that are + initially opened. New sessions are only opened after this value has been + reached. + + The default value is 4 and any value above 0 is valid. + + Generally, it should be set to the number of concurrent statements the + application is planning or expecting to run. + + This value can also be specified with the "ORA_DRCP_MIN" environment + variable. + + ora_drcp_max + This optional value specifies the maximum number of sessions that can be + open at one time. Once reached no more sessions can be opened until one + becomes free. The default value is 40 and any value above 1 is valid. + You should not set this value lower than ora_drcp_min as that will just + waste resources. + + This value can also be specified with the "ORA_DRCP_MAX" environment + variable. + + ora_drcp_incr + This optional value specifies the next increment for sessions to be + started if the current number of sessions are less than ora_drcp_max. + The default value is 2 and any value above 0 is valid as long as the + value of ora_drcp_min + ora_drcp_incr is not greater than ora_drcp_max. + + This value can also be specified with the "ORA_DRCP_INCR" environment + variable. + + ora_taf + If your Oracle instance has been configured to use TAF events you can + enable the TAF callback by setting this option to any *true* value. + + ora_taf_function + The name of the Perl subroutine that will be called from OCI when a TAF + event occurs. You must supply a perl function to use the callback and it + will always receive two parameters, the failover event value and the + failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + + ora_taf_sleep + The amount of time in seconds the OCI client will sleep between + attempting successive failover events when the event is OCI_FO_ERROR. + + ora_session_mode + The ora_session_mode attribute can be used to connect with SYSDBA, + SYSOPER and ORA_SYSASM authorization. The ORA_SYSDBA, ORA_SYSOPER and + ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + + This is one case where setting ORACLE_SID may be useful since connecting + as SYSDBA or SYSOPER via SQL*Net is frequently disabled for security + reasons. + + Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + + It has been reported that this only works if $dsn does not contain a SID + so that Oracle then uses the value of ORACLE_SID (not TWO_TASK) + environment variable to connect to a local instance. Also the username + and password should be empty, and the user executing the script needs to + be part of the dba group or osdba group. + + ora_oratab_orahome + Passing a true value for the ora_oratab_orahome attribute will make + DBD::Oracle change $ENV{ORACLE_HOME} to make the Oracle home directory + that specified in the "/etc/oratab" file *if* the database to connect to + is specified as a SID that exists in the oratab file, and DBD::Oracle + was built to use the Oracle 7 OCI API (not Oracle 8+). + + ora_module_name + After connecting to the database the value of this attribute is passed + to the SET_MODULE() function in the "DBMS_APPLICATION_INFO" PL/SQL + package. This can be used to identify the application to the DBA for + monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + + The maximum size is 48 bytes. + + ora_driver_name + For 11g and later you can now set the name of the driver layer using + OCI. Perl, Perl5, ApachePerl so on. Names starting with "ORA" are + reserved. You can enter up to 8 characters. If none is enter then this + will default to DBDOxxxx where xxxx is the current version number. This + value can be retrieved on the server side using V$SESSION_CONNECT_INFO + or GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + + ora_client_info + Allows you to add any value (up to 64 bytes) to your session and it can + be retrieved on the server side from the "V$SESSION"a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + + ora_client_identifier + Allows you to specify the user identifier in the session handle. + + Most useful for web applications as it can pass in the session user name + which might be different to the connection user name. Can be up to 64 + bytes long but do not to include the password for security reasons and + the first character of the identifier should not be ':'. This value can + be retrieved on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + + ora_action + Allows you to specify any string up to 32 bytes which may be retrieved + on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + + ora_dbh_share + Requires at least Perl 5.8.0 compiled with ithreads. + + Allows you to share database connections between threads. The first + connect will make the connection, all following calls to connect with + the same ora_dbh_share attribute will use the same database connection. + The value must be a reference to a already shared scalar which is + initialized to an empty string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + + ora_envhp + The first time a connection is made a new OCI 'environment' is created + by DBD::Oracle and stored in the driver handle. Subsequent connects + reuse (share) that same OCI environment by default. + + The ora_envhp attribute can be used to disable the reuse of the OCI + environment from a previous connect. If the value is 0 then a new OCI + environment is allocated and used for this connection. + + The OCI environment holds information about the client side context, + such as the local NLS environment. By altering %ENV and setting + ora_envhp to 0 you can create connections with different NLS settings. + This is most useful for testing. + + ora_charset, ora_ncharset + For oracle versions >= 9.2 you can specify the client charset and + ncharset with the ora_charset and ora_ncharset attributes. You still + need to pass "ora_envhp = 0" for all but the first connect. + + These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + + ora_verbose + Use this value to enable DBD::Oracle only tracing. Simply either set the + ora_verbose attribute on the connect() method to the trace level you + desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + + or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + + In both cases the DBD::Oracle trace level is set to 6, which is the + highest level tracing most of the calls to OCI. + + ora_oci_success_warn + Use this value to print otherwise silent OCI warnings that may happen + when an execute or fetch returns "Success With Info" or when you want to + tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + + ora_objects + Use this value to enable extended embedded oracle objects mode. In + extended: + + 1 Embedded objects are returned as instance + (including type-name etc.) instead of simple ARRAY. + + 2 Determine object type for each instance. All object attributes are + returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + + ora_ph_type + The default placeholder datatype for the database session. The "TYPE" or + "ora_type" attributes to "bind_param" in DBI and "bind_param_inout" in + DBI override the datatype for individual placeholders. The most frequent + reason for using this attribute is to permit trailing spaces in values + passed by placeholders. + + Constants for the values allowed for this attribute can be imported + using + + use DBD::Oracle qw(:ora_types); + + Only the following values are permitted for this attribute. + + ORA_VARCHAR2 + Oracle clients using OCI 8 will strip trailing spaces and allow + embedded \0 bytes. Oracle clients using OCI 9.2 do not strip + trailing spaces and allow embedded \0 bytes. This is the normal + default placeholder type. + + ORA_STRING + Do not strip trailing spaces and end the string at the first \0. + + ORA_CHAR + Do not strip trailing spaces and allow embedded \0. Force + 'blank-padded comparison semantics'. + + For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + + Will pad bloggs out to 8 characters and return the username. + + ora_parse_error_offset + If the previous error was from a failed "prepare" due to a syntax error, + this attribute gives the offset into the "Statement" attribute where the + error was found. + + ora_array_chunk_size + Due to OCI limitations, DBD::Oracle needs to buffer up rows of bind + values in its "execute_for_fetch" implementation. This attribute sets + the number of rows to buffer at a time (default value is 1000). + + The "execute_for_fetch" function will collect (at most) this many rows + in an array, send them off to the DB for execution, then go back to + collect the next chunk of rows and so on. This attribute can be used to + limit or extend the number of rows processed at a time. + + Note that this attribute also applies to "execute_array", since that + method is implemented using "execute_for_fetch". + + ora_connect_with_default_signals + Sometimes the Oracle client seems to change some of the signal handlers + of the process during the connect phase. For instance, some users have + observed Perl's default $SIG{INT} handler being ignored after connecting + to an Oracle database. If this causes problems in your application, set + this attribute to an array reference of signals you would like to be + localized during the connect process. Once the connect is complete, the + signal handlers should be returned to their previous state. + + For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + + NOTE disabling the signal handlers the OCI library sets up may affect + functionality in the OCI library. + + NOTE If you are using connect_cached then the above example will lead to + DBI thinking each connection is different as an anonymous array + reference is being used. To avoid this when using connect_cached you are + advised to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + + In more recent Perl versions you could possibly make use of new state + variables. + + connect_cached + Implemented by DBI, no driver-specific impact. Please note that + connect_cached as not been tested with DRCP. + + data_sources + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + + Returns a list of available databases. You will have to set either the + 'ORACLE_HOME' or 'TNS_ADMIN' environment value to retrieve this list. It + will read these values from TNSNAMES.ORA file entries. + +METHODS COMMON TO ALL HANDLES + For all of the methods below, $h can be either a database handle ($dbh) + or a statement handle ($sth). Note that *$dbh* and *$sth* can be + replaced with any variable name you choose: these are just the names + most often used. Another common variable used in this documentation is + $*rv*, which stands for "return value". + + err + $rv = $h->err; + + Returns the error code from the last method called. + + errstr + $str = $h->errstr; + + Returns the last error that was reported by Oracle. Starting with + "ORA-00000" code followed by the error message. + + state + $str = $h->state; + + Oracle hasn't supported SQLSTATE since the early versions OCI. It will + return empty when the command succeeds and 'S1000' (General Error) for + all other errors. + + While this method can be called as either "$sth->state" or + "$dbh->state", it is usually clearer to always use "$dbh->state". + + trace + Implemented by DBI, no driver-specific impact. + + trace_msg + Implemented by DBI, no driver-specific impact. + + parse_trace_flag and parse_trace_flags + Implemented by DBI, no driver-specific impact. + + func + DBD::Oracle uses the "func" method to support a variety of functions. + + Private database handle functions + Some of these functions are called through the method func() which is + described in the DBI documentation. Any function that begins with ora_ + can be called directly. + + plsql_errstr + This function returns a string which describes the errors from the most + recent PL/SQL function, procedure, package, or package body compile in a + format similar to the output of the SQL*Plus command 'show errors'. + + The function returns undef if the error string could not be retrieved + due to a database error. Look in $dbh->errstr for the cause of the + failure. + + If there are no compile errors, an empty string is returned. + + Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + + dbms_output_enable / dbms_output_put / dbms_output_get + These functions use the PL/SQL DBMS_OUTPUT package to store and retrieve + text using the DBMS_OUTPUT buffer. Text stored in this buffer by + dbms_output_put or any PL/SQL block can be retrieved by dbms_output_get + or any PL/SQL block connected to the same database session. + + Stored text is not available until after dbms_output_put or the PL/SQL + block that saved it completes its execution. This means you CAN NOT use + these functions to monitor long running PL/SQL procedures. + + Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + + Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + + dbms_output_enable ( [ buffer_size ] ) + This function calls DBMS_OUTPUT.ENABLE to enable calls to package + DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to these + procedures are ignored unless DBMS_OUTPUT.ENABLE is called first. + + The buffer_size is the maximum amount of text that can be saved in the + buffer and must be between 2000 and 1,000,000. If buffer_size is not + given, the default is 20,000 bytes. + + dbms_output_put ( [ @lines ] ) + This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + + If all lines were saved successfully the function returns 1. Depending + on the context, an empty list or undef is returned for failure. + + If any line causes buffer_size to be exceeded, a buffer overflow error + is raised and the function call fails. Some of the text might be in the + buffer. + + dbms_output_get + This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from + the buffer. + + In an array context, all complete lines are removed from the buffer and + returned as a list. If there are no complete lines, an empty list is + returned. + + In a scalar context, the first complete line is removed from the buffer + and returned. If there are no complete lines, undef is returned. + + Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or + DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, + DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + + reauthenticate ( $username, $password ) + Starts a new session against the current database using the credentials + supplied. + + private_attribute_info + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + + Returns a hash of all private attributes used by DBD::Oracle, for either + a database or a statement handle. Currently, all the hash values are + undef. + +ATTRIBUTES COMMON TO ALL HANDLES + InactiveDestroy (boolean) + Implemented by DBI, no driver-specific impact. + + RaiseError (boolean, inherited) + Forces errors to always raise an exception. Although it defaults to off, + it is recommended that this be turned on, as the alternative is to check + the return value of every method (prepare, execute, fetch, etc.) + manually, which is easy to forget to do. + + PrintError (boolean, inherited) + Forces database errors to also generate warnings, which can then be + filtered with methods such as locally redefining *$SIG{__WARN__}* or + using modules such as "CGI::Carp". This attribute is on by default. + + ShowErrorStatement (boolean, inherited) + Appends information about the current statement to error messages. If + placeholder information is available, adds that as well. Defaults to + true. + + Warn (boolean, inherited) + Enables warnings. This is on by default, and should only be turned off + in a local block for a short a time only when absolutely needed. + + Executed (boolean, read-only) + Indicates if a handle has been executed. For database handles, this + value is true after the "do" method has been called, or when one of the + child statement handles has issued an "execute". Issuing a "commit" or + "rollback" always resets the attribute to false for database handles. + For statement handles, any call to "execute" or its variants will flip + the value to true for the lifetime of the statement handle. + + TraceLevel (integer, inherited) + Sets the trace level, similar to the "trace" method. See the sections on + "trace" and "parse_trace_flag" for more details. + + Active (boolean, read-only) + Indicates if a handle is active or not. For database handles, this + indicates if the database has been disconnected or not. For statement + handles, it indicates if all the data has been fetched yet or not. Use + of this attribute is not encouraged. + + Kids (integer, read-only) + Returns the number of child processes created for each handle type. For + a driver handle, indicates the number of database handles created. For a + database handle, indicates the number of statement handles created. For + statement handles, it always returns zero, because statement handles do + not create kids. + + ActiveKids (integer, read-only) + Same as "Kids", but only returns those that are active. + + CachedKids (hash ref) + Returns a hashref of handles. If called on a database handle, returns + all statement handles created by use of the "prepare_cached" method. If + called on a driver handle, returns all database handles created by the + "connect_cached" method. + + ChildHandles (array ref) + Implemented by DBI, no driver-specific impact. + + PrintWarn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleError (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleSetErr (code ref, inherited) + Implemented by DBI, no driver-specific impact. + + ErrCount (unsigned integer) + Implemented by DBI, no driver-specific impact. + + FetchHashKeyName (string, inherited) + Implemented by DBI, no driver-specific impact. + + ChopBlanks (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Taint (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintIn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintOut (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Profile (inherited) + Implemented by DBI, no driver-specific impact. + + Type (scalar) + Returns "dr" for a driver handle, "db" for a database handle, and "st" + for a statement handle. Should be rarely needed. + + LongReadLen + Implemented by DBI, no driver-specific impact. + + LongTruncOk + Implemented by DBI, no driver-specific impact. + + CompatMode + Type: boolean, inherited + + The CompatMode attribute is used by emulation layers (such as Oraperl) + to enable compatible behaviour in the underlying driver (e.g., + DBD::Oracle) for this handle. Not normally set by application code. + + It also has the effect of disabling the 'quick FETCH' of attribute + values from the handles attribute cache. So all attribute values are + handled by the drivers own FETCH method. This makes them slightly slower + but is useful for special-purpose drivers like DBD::Multiplex. + +ORACLE-SPECIFIC DATABASE HANDLE METHODS + ora_can_unicode ( [ $refresh ] ) + Returns a number indicating whether either of the database character + sets is a Unicode encoding. Calls ora_nls_parameters() and passes the + optional $refresh parameter to it. + + 0 = Neither character set is a Unicode encoding. + + 1 = National character set is a Unicode encoding. + + 2 = Database character set is a Unicode encoding. + + 3 = Both character sets are Unicode encodings. + + ora_can_taf + Returns true if the current connection supports TAF events. False if + otherise. + + ora_nls_parameters ( [ $refresh ] ) + Returns a hash reference containing the current NLS parameters, as given + by the v$nls_parameters view. The values fetched are cached between + calls. To cause the latest values to be fetched, pass a true value to + the function. + +DATABASE HANDLE METHODS + selectall_arrayref + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the rows returned by + preparing and executing the SQL string. See the DBI documentation for + full details. + + selectall_hashref + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + + Returns a reference to a hash containing the rows returned by preparing + and executing the SQL string. See the DBI documentation for full + details. + + selectcol_arrayref + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the first column from each + rows returned by preparing and executing the SQL string. It is possible + to specify exactly which columns to return. See the DBI documentation + for full details. + + prepare + $sth = $dbh->prepare($statement, \%attr); + + Prepares a statement for later execution by the database engine and + returns a reference to a statement handle object. + + Prepare Attributes + These attributes may be used in the "\%attr" parameter of the "prepare" + in DBI database handle method. + + ora_placeholders + Set to false to disable processing of placeholders. Used mainly for + loading a PL/SQL package that has been *wrapped* with Oracle's + "wrap" utility. + + ora_auto_lob + If true (the default), fetching retrieves the contents of the CLOB + or BLOB column in most circumstances. If false, fetching retrieves + the Oracle "LOB Locator" of the CLOB or BLOB value. + + See "LOBs and LONGs" for more details. + + See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how + to use LOB Locators. + + ora_pers_lob + If true the "Simple Fetch for CLOBs and BLOBs" method for the "Data + Interface for Persistent LOBs" will be used for LOBs rather than the + default method "Data Interface for LOB Locators". + + ora_clbk_lob + If true the "Piecewise Fetch with Callback" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_lob + If true the "Piecewise Fetch with Polling" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_size + This is the max piece size for the "Piecewise Fetch with Callback" + and "Piecewise Fetch with Polling" methods, in chars for CLOBS, and + bytes for BLOBS. + + ora_check_sql + If 1 (default), force SELECT statements to be described in + prepare(). If 0, allow SELECT statements to defer describe until + execute(). + + See "Prepare Postponed Till Execute" for more information. + + ora_exe_mode + This will set the execute mode of the current statement. Presently + only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + + See "Scrollable Cursors" for more details. + + ora_prefetch_rows + Sets the number of rows to be prefetched. If it is not set, then the + default value is 1. See "Row Prefetching" for more details. + + ora_prefetch_memory + Sets the memory level for rows to be prefetched. The application + then fetches as many rows as will fit into that much memory. See + "Row Prefetching" for more details. + + ora_row_cache_off + By default DBD::Oracle will use a row cache when fetching to cut + down the number of round trips to the server. If you do not want to + use an array fetch set this value to any value other than 0; + + See "Row Prefetching" for more details. + + Placeholders + There are two types of placeholders that can be used in DBD::Oracle. The + first is the "question mark" type, in which each placeholder is + represented by a single question mark character. This is the method + recommended by the DBI specs and is the most portable. Each question + mark is internally replaced by a "dollar sign number" in the order in + which they appear in the query (important when using "bind_param"). + + The other placeholder type is "named parameters" in the format ":foo" + which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + + The different types of placeholders cannot be mixed within a statement, + but you may use different ones for each statement handle you have. This + is confusing at best, so stick to one style within your program. + + prepare_cached + $sth = $dbh->prepare_cached($statement, \%attr); + + Implemented by DBI, no driver-specific impact. This method is most + useful if the same query is used over and over as it will cut down round + trips to the server. + + do + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + + Prepare and execute a single statement. Returns the number of rows + affected if the query was successful, returns undef if an error + occurred, and returns -1 if the number of rows is unknown or not + available. Note that this method will return 0E0 instead of 0 for 'no + rows were affected', in order to always return a true value if no error + occurred. + + last_insert_id + Oracle does not implement auto_increment of serial type columns it uses + predefined sequences where the id numbers are either selected before + insert, at insert time with a trigger, or as part of the query. + + Below is an example of you to use the latter with the SQL returning + clause to get the ID number back on insert with the bind_param_inout + method. . + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + + commit + $rv = $dbh->commit; + + Issues a COMMIT to the server, indicating that the current transaction + is finished and that all changes made will be visible to other + processes. If AutoCommit is enabled, then a warning is given and no + COMMIT is issued. Returns true on success, false on error. + + rollback + $rv = $dbh->rollback; + + Issues a ROLLBACK to the server, which discards any changes made in the + current transaction. If AutoCommit is enabled, then a warning is given + and no ROLLBACK is issued. Returns true on success, and false on error. + + begin_work + This method turns on transactions until the next call to "commit" or + "rollback", if "AutoCommit" is currently enabled. If it is not enabled, + calling begin_work will issue an error. Note that the transaction will + not actually begin until the first statement after begin_work is called. + + disconnect + $rv = $dbh->disconnect; + + Disconnects from the Oracle database. Any uncommitted changes will be + rolled back upon disconnection. It's good policy to always explicitly + call commit or rollback at some point before disconnecting, rather than + relying on the default rollback behavior. + + If the script exits before disconnect is called (or, more precisely, if + the database handle is no longer referenced by anything), then the + database handle's DESTROY method will call the rollback() and + disconnect() methods automatically. It is best to explicitly disconnect + rather than rely on this behavior. + + ping + $rv = $dbh->ping; + + This "ping" method is used to check the validity of a database handle. + The value returned is either 0, indicating that the connection is no + longer valid, or 1, indicating the connection is valid. This function + does 1 round trip to the Oracle Server. + + get_info() + $value = $dbh->get_info($info_type); + + DBD::Oracle supports "get_info()", but (currently) only a few info + types. + + table_info() + DBD::Oracle supports attributes for "table_info()". + + In Oracle, the concept of *user* and *schema* is (currently) the same. + Because database objects are owned by an user, the owner names in the + data dictionary views correspond to schema names. Oracle does not + support catalogues so TABLE_CAT is ignored as selection criterion. + + Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + + TABLE_TYPE may contain a comma-separated list of table types. The + following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + + The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + + The special enumerations of catalogues, schemas and table types are + supported. However, TABLE_CAT is always NULL. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. "table_info()" performs a case-sensitive search. So, a + selection criterion should respect upper and lower case. Normally, an + identifier is case-insensitive. Oracle stores and returns it in upper + case. Sometimes, database objects are created with quoted identifiers + (for reserved words, mixed case, special characters, ...). Such an + identifier is case-sensitive (if not all upper case). Oracle stores and + returns it as given. "table_info()" has no special quote handling, + neither adds nor removes quotes. + + primary_key_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + If the primary key constraint was created without an identifier, PK_NAME + contains a system generated name with the form SYS_Cn. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + foreign_key_info() + This method (currently) supports the extended behaviour of SQL/CLI, i.e. + the result set contains foreign keys that refer to primary and alternate + keys. The field UNIQUE_OR_PRIMARY distinguishes these keys. + + Oracle does not support catalogues, so $pk_catalog and $fk_catalog are + ignored as selection criteria (in the new style interface). The + UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always NULL + (undef). See "table_info()" for more detailed information. + + If the primary or foreign key constraints were created without an + identifier, UK_NAME or FK_NAME contains a system generated name with the + form SYS_Cn. + + The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle + (currently) does not support other actions. + + The DELETE_RULE field may contain wrong values. This is a known Bug + (#1271663) in Oracle's data dictionary views. Currently (as of 8.1.7), + 'RESTRICT' and 'SET DEFAULT' are not supported, 'CASCADE' is mapped + correctly and all other actions (incl. 'SET NULL') appear as 'NO + ACTION'. + + The DEFERABILITY field is always NULL, because this columns is not + present in the ALL_CONSTRAINTS view of older Oracle releases. + + The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, + FK_TABLE_SCHEM, FK_TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + column_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + + Don't rely on the values of the BUFFER_LENGTH field! Especially the + length of FLOATs may be wrong. + + Datatype codes for non-standard types are subject to change. + + Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + It is possible with Oracle to make the names of the various DB objects + (table,column,index etc) case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + + So in the example the exact case "Bla_BLA" must be used to get it info + on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + + any case can be used to get info on the column. + + selectrow_array + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + + Returns an array of row information after preparing and executing the + provided SQL string. The rows are returned by calling "fetchrow_array". + The string can also be a statement handle generated by a previous + prepare. Note that only the first row of data is returned. If called in + a scalar context, only the first column of the first row is returned. + Because this is not portable, it is not recommended that you use this + method in that way. + + selectrow_arrayref + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an array, by internal use of the "fetchrow_arrayref" + method. + + selectrow_hashref + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an hash, by internal use of the "fetchrow_hashref" method. + + clone + $other_dbh = $dbh->clone(); + + Creates a copy of the database handle by connecting with the same + parameters as the original handle, then trying to merge the attributes. + See the DBI documentation for complete usage. + +DATABASE HANDLE ATTRIBUTES + AutoCommit (boolean) + Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is + on, but this may change in the future, so it is highly recommended that + you explicitly set it when calling "connect". + + ReadOnly (boolean) + $dbh->{ReadOnly} = 1; + + Specifies if the current database connection should be in read-only mode + or not. + + Please not that this method is not foolproof: there are still ways to + update the database. Consider this a safety net to catch applications + that should not be issuing commands such as INSERT, UPDATE, or DELETE. + + This method method requires DBI version 1.55 or better. + + Name (string, read-only) + Returns the name of the current database. This is the same as the DSN, + without the "dbi:Oracle:" part. + + Username (string, read-only) + Returns the name of the user connected to the database. + + Driver (handle, read-only) + Holds the handle of the parent driver. The only recommended use for this + is to find the name of the driver using: + + $dbh->{Driver}->{Name} + + RowCacheSize + DBD::Oracle supports both Server pre-fetch and Client side row caching. + By default both are turned on to give optimum performance. Most of the + time one can just let DBD::Oracle figure out the best optimization. + + Row Caching + Row caching occurs on the client side and the object of it is to cut + down the number of round trips made to the server when fetching rows. At + each fetch a set number of rows will be retrieved from the server and + stored locally. Further calls the server are made only when the end of + the local buffer(cache) is reached. + + Rows up to the specified top level row count "RowCacheSize" are fetched + if it occupies no more than the specified memory usage limit. The + default value is 0, which means that memory size is not included in + computing the number of rows to prefetch. If the "RowCacheSize" value is + set to a negative number then the positive value of RowCacheSize is used + to compute the number of rows to prefetch. + + By default "RowCacheSize" is automatically set. If you want to totally + turn off prefetching set this to 1. + + For any SQL statement that contains a LOB, Long or Object Type Row + Caching will be turned off. However server side caching still works. If + you are only selecting a LOB Locator then Row Caching will still work. + + Row Prefetching + Row prefetching occurs on the server side and uses the DBI database + handle attribute "RowCacheSize" and or the Prepare Attribute + 'ora_prefetch_memory'. Tweaking these values may yield improved + performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + + In the above example 10 rows will be prefetched up to a maximum of 10000 + bytes of data. The Oracle® Call Interface Programmer's Guide, suggests + a good row cache value for a scrollable cursor is about 20% of expected + size of the record set. + + The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) + when it needs to get new rows. This happens on the first fetch that sets + the current_positon to any value other than 0. In the above example if + we do a OCI_FETCH_FIRST the first 10 rows are loaded into the buffer and + DBD::Oracle will not have to go back to the server for more rows. When + record 11 is fetched DBD::Oracle fetches and returns this row and the + next 9 rows are loaded into the buffer. In this case if you fetch + backwards from 10 to 1 no server round trips are made. + + With large record sets it is best not to attempt to go to the last + record as this may take some time, A large buffer size might even slow + down the fetch. If you must get the number of rows in a large record set + you might try using an few large OCI_FETCH_ABSOLUTEs and then an + OCI_FETCH_LAST, this might save some time. So if you had a record set of + 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one + would fetch the first 5000 rows into the buffer then the next 5000 rows. + If one requires only the first few rows there is no need to set a large + prefetch value. + + If the ora_prefetch_memory less than 1 or not present then memory size + is not included in computing the number of rows to prefetch otherwise + the number of rows will be limited to memory size. Likewise if the + RowCacheSize is less than 1 it is not included in the computing of the + prefetch rows. + +ORACLE-SPECIFIC STATEMENT HANDLE METHODS + ora_stmt_type + Returns the OCI Statement Type number for the SQL of a statement handle. + + ora_stmt_type_name + Returns the OCI Statement Type name for the SQL of a statement handle. + +DBI STATEMENT HANDLE OBJECT METHODS + bind_param + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + + Allows the user to bind a value and/or a data type to a placeholder. + + The value of $param_num is a number if using the '?' or if using ":foo" + style placeholders, the complete name (e.g. ":foo") must be given. The + $bind_value argument is fairly self-explanatory. A value of "undef" will + bind a "NULL" to the placeholder. Using "undef" is useful when you want + to change just the type and will be overwriting the value later. (Any + value is actually usable, but "undef" is easy and efficient). + + The "\%attr" hash is used to indicate the data type of the placeholder. + The default value is "varchar". If you need something else, you must use + one of the values provided by DBI or by DBD::Pg. To use a SQL value, + modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + + This will import some constants into your script. You can plug those + directly into the "bind_param" call. Some common ones that you will + encounter are: + + SQL_INTEGER + + To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + + You can then set the data types by setting the value of the "ora_type" + key in the hash passed to "bind_param". The current list of Oracle data + types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + + Data types are "sticky," in that once a data type is set to a certain + placeholder, it will remain for that placeholder, unless it is + explicitly set to something else afterwards. If the statement has + already been prepared, and you switch the data type to something else, + DBD::Oracle will re-prepare the statement for you before doing the next + execute. + + Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + + These attributes may be used in the "\%attr" parameter of the + "bind_param" in DBI or "bind_param_inout" in DBI statement handle + methods. + + ora_type + Specify the placeholder's datatype using an Oracle datatype. A fatal + error is raised if "ora_type" and the DBI "TYPE" attribute are used + for the same placeholder. Some of these types are not supported by + the current version of DBD::Oracle and will cause a fatal error if + used. Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + + Potentially useful values when DBD::Oracle was built using OCI 7 and + later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + + Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + + Additional values when DBD::Oracle was built using OCI 9.2 and + later: + + SQLT_CHR, SQLT_BIN + + See "Binding Cursors" for the correct way to use ORA_RSET. + + See "LOBs and LONGs" for how to use ORA_CLOB and ORA_BLOB. + + See "SYS.DBMS_SQL datatypes" for ORA_VARCHAR2_TABLE, + ORA_NUMBER_TABLE. + + See "Data Interface for Persistent LOBs" for the correct way to use + SQLT_CHR and SQLT_BIN. + + See "Other Data Types" for more information. + + See also "Placeholders and Bind Values" in DBI. + + ora_csform + Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values + are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can + be imported from the DBD::Oracle module. Rarely needed. + + ora_csid + Specify the *integer* OCI_ATTR_CHARSET_ID for the bind value. + Character set names can't be used currently. + + ora_maxdata_size + Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. May be + needed if a character set conversion from client to server causes + the data to use more space and so fail with a truncation error. + + ora_maxarray_numentries + Specify the maximum number of array entries to allocate. Used with + ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of + array entries Oracle can pass back to you in OUT variable of type + TABLE OF ... . + + ora_internal_type + Specify internal data representation. Currently is supported only + for ORA_NUMBER_TABLE. + + Optimizing Results + Prepare Postponed Till Execute + The DBD::Oracle module can avoid an explicit 'describe' operation prior + to the execution of the statement unless the application requests + information about the results (such as $sth->{NAME}). This reduces + communication with the server and increases performance (reducing the + number of PARSE_CALLS inside the server). + + However, it also means that SQL errors are not detected until + "execute()" (or $sth->{NAME} etc) is called instead of when "prepare()" + is called. Note that if the describe is triggered by the use of + $sth->{NAME} or a similar attribute and the describe fails then *an + exception is thrown* even if "RaiseError" is false! + + Set "ora_check_sql" to 0 in prepare() to enable this behaviour. + + bind_param_inout + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + + DBD::Oracle fully supports bind_param_inout below are some uses for this + method. + + Returning A Value from an INSERT + Oracle supports an extended SQL insert syntax which will return one or + more of the values inserted. This can be particularly useful for + single-pass insertion of values with re-used sequence values (avoiding a + separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + + If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + + If you have many rows to insert you can take advantage of Oracle's built + in execute array feature with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + + Which will return all the ids into @out_values. + + Note: + This will only work for numbered (?) placeholders, + The third parameter of bind_param_inout_array, (0 in the example), + "maxlen" is required by DBI but not used by DBD::Oracle + The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + + Returning A Recordset + DBD::Oracle does not currently support binding a PL/SQL table (aka + array) as an IN OUT parameter to any Perl data structure. You cannot + therefore call a PL/SQL function or procedure from DBI that uses a + non-atomic datatype as either a parameter, or a return value. However, + if you are using Oracle 9.0.1 or later, you can make use of table (or + pipelined) functions. + + For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + + Currently, there is no way to directly call the function + Array_Example.Array_Func from DBI. However, by making the following + relatively painless additions, its not only possible, but extremely + efficient. + + First, you need to create database object types that correspond to the + record and table types in the package. From the above example, these + would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + + Now, assuming the existing function needs to remain unchanged (it is + probably being called from other PL/SQL code), we need to add a new + function to the package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + + As you can see, the new function is very simple. Now, it is a simple + matter of calling the function as a straight-forward SELECT from your + DBI code. From the above example, the code would look something like + this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + + SYS.DBMS_SQL datatypes + DBD::Oracle has built-in support for SYS.DBMS_SQL.VARCHAR2_TABLE and + SYS.DBMS_SQL.NUMBER_TABLE datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + Note: + Take careful note that we use '\\@arr' here because the + 'bind_param_inout' will only take a reference to a scalar. + + ORA_VARCHAR2_TABLE + SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. ( + in bind_param() and bind_param_inout() ). When you bind array, you need + to specify full buffer size for OUT data. So, there are two parameters: + *max_len* (specified as 3rd argument of bind_param_inout() ), and + *ora_maxarray_numentries*. They define maximum array entry length and + maximum rows, that can be passed to Oracle and back to you. In this + example we send array with 1 element with length=3, but allocate space + for 100 Oracle array entries with maximum length 10 of each. So, you can + get no more than 100 array entries with length <= 10. + + If you set *max_len* to zero, maximum array entry length is calculated + as maximum length of entry of array bound. If 0 < *max_len* < length( + $some_element ), truncation occur. + + If you set *ora_maxarray_numentries* to zero, current (at bind time) + bound array length is used as maximum. If 0 < *ora_maxarray_numentries* + < scalar(@array), not all array entries are bound. + + ORA_NUMBER_TABLE + SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike + ORA_VARCHAR2_TABLE. The main difference is internal data representation. + Currently 2 types of bind is allowed : as C-integer, or as C-double + type. To select one of them, you may specify additional bind parameter + *ora_internal_type* as either SQLT_INT or SQLT_FLT for C-integer and + C-double types. Integer size is architecture-specific and is usually 32 + or 64 bit. Double is standard IEEE 754 type. + + *ora_internal_type* defaults to double (SQLT_FLT). + + *max_len* is ignored for OCI_NUMBER_TABLE. + + Currently, you cannot bind full native Oracle NUMBER(38). If you really + need, send request to dbi-dev list. + + The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + + If you change bind type to SQLT_INT, like: + + ora_internal_type => SQLT_INT + + you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + + bind_param_inout_array + DBD::Oracle supports this undocumented feature of DBI. See "Returning A + Value from an INSERT" for an example. + + bind_param_array + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + + Binds an array of values to a placeholder, so that each is used in turn + by a call to the "execute_array" method. + + execute + $rv = $sth->execute(@bind_values); + + Perform whatever processing is necessary to execute the prepared + statement. + + execute_array + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + Execute a prepared statement once for each item in a passed-in hashref, + or items that were previously bound via the "bind_param_array" method. + See the DBI documentation for more details. + + DBD::Oracle takes full advantage of OCI's array interface so inserts and + updates using this interface will run very quickly. + + execute_for_fetch + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + Used internally by the "execute_array" method, and rarely used directly. + See the DBI documentation for more details. + + fetchrow_arrayref + $ary_ref = $sth->fetchrow_arrayref; + + Fetches the next row of data from the statement handle, and returns a + reference to an array holding the column values. Any columns that are + NULL are returned as undef within the array. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + Note that the same array reference is returned for each fetch, so don't + store the reference and then use it after a later fetch. Also, the + elements of the array are also reused for each row, so take care if you + want to take a reference to an element. See also "bind_columns". + + fetchrow_array + @ary = $sth->fetchrow_array; + + Similar to the "fetchrow_arrayref" method, but returns a list of column + information rather than a reference to a list. Do not use this in a + scalar context. + + fetchrow_hashref + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + + Fetches the next row of data and returns a hashref containing the name + of the columns as the keys and the data itself as the values. Any NULL + value is returned as as undef value. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + The optional $name argument should be either "NAME", "NAME_lc" or + "NAME_uc", and indicates what sort of transformation to make to the keys + in the hash. By default Oracle uses upper case. + + fetchall_arrayref + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + + Returns a reference to an array of arrays that contains all the + remaining rows to be fetched from the statement handle. If there are no + more rows, an empty arrayref will be returned. If an error occurs, the + data read in so far will be returned. Because of this, you should always + check "$sth->err" after calling this method, unless "RaiseError" has + been enabled. + + If $slice is an array reference, fetchall_arrayref uses the + "fetchrow_arrayref" method to fetch each row as an array ref. If the + $slice array is not empty then it is used as a slice to select + individual columns by perl array index number (starting at 0, unlike + column and parameter numbers which start at 1). + + With no parameters, or if $slice is undefined, fetchall_arrayref acts as + if passed an empty array ref. + + If $slice is a hash reference, fetchall_arrayref uses "fetchrow_hashref" + to fetch each row as a hash reference. + + See the DBI documentation for a complete discussion. + + fetchall_hashref + $hash_ref = $sth->fetchall_hashref( $key_field ); + + Returns a hashref containing all rows to be fetched from the statement + handle. See the DBI documentation for a full discussion. + + finish + $rv = $sth->finish; + + Indicates to DBI that you are finished with the statement handle and are + not going to use it again. Only needed when you have not fetched all the + possible rows. + + rows + $rv = $sth->rows; + + Returns the number of rows affected for updates, deletes and inserts and + -1 for selects. + + bind_col + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + + Binds a Perl variable and/or some attributes to an output column of a + SELECT statement. Column numbers count up from 1. You do not need to + bind output columns in order to fetch data. + + NOTE: DBD::Oracle does not use the $bind_type to determine how to bind + the column; it uses what Oracle says the data type is. You can however + set a numeric bind type with the bind attributes + StrictlyTyped/DiscardString as these attributes are applied after the + column is retrieved. + + See the DBI documentation for a discussion of the optional parameters + "\%attr" and $bind_type + + bind_columns + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + + Calls the "bind_col" method for each column in the SELECT statement, + using the supplied list. + + dump_results + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + + Fetches all the rows from the statement handle, calls "DBI::neat_list" + for each row, and prints the results to $fh (which defaults to STDOUT). + Rows are separated by $lsep (which defaults to a newline). Columns are + separated by $fsep (which defaults to a comma). The $maxlen controls how + wide the output can be, and defaults to 35. + + This method is designed as a handy utility for prototyping and testing + queries. Since it uses "neat_list" to format and edit the string for + reading by humans, it is not recommended for data transfer applications. + +STATEMENT HANDLE ATTRIBUTES + NUM_OF_FIELDS (integer, read-only) + Returns the number of columns returned by the current statement. A + number will only be returned for SELECT statements for INSERT, UPDATE, + and DELETE statements which contain a RETURNING clause. This method + returns undef if called before "execute()". + + NUM_OF_PARAMS (integer, read-only) + Returns the number of placeholders in the current statement. + + NAME (arrayref, read-only) + Returns an arrayref of column names for the current statement. This + method will only work for SELECT statements, for SHOW statements, and + for INSERT, UPDATE, and DELETE statements which contain a RETURNING + clause. This method returns undef if called before "execute()". + + NAME_lc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to lower case. + + NAME_uc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to upper case. + + NAME_hash (hashref, read-only) + Similar to the "NAME" attribute, but returns a hashref of column names + instead of an arrayref. The names of the columns are the keys of the + hash, and the values represent the order in which the columns are + returned, starting at 0. This method returns undef if called before + "execute()". + + NAME_lc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + NAME_uc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + TYPE (arrayref, read-only) + Returns an arrayref indicating the data type for each column in the + statement. This method returns undef if called before "execute()". + + PRECISION (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the precision for "NUMERIC" columns, the + size in number of characters for "CHAR" and "VARCHAR" columns, and for + all other types of columns it returns the number of *bytes*. This method + returns undef if called before "execute()". + + SCALE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the scale of the that column. The only + type that will return a value is "NUMERIC". This method returns undef if + called before "execute()". + + NULLABLE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates if the column is nullable or not. 0 = + not nullable, 1 = nullable, 2 = unknown. This method returns undef if + called before "execute()". + + Database (dbh, read-only) + Returns the database handle this statement handle was created from. + + ParamValues (hash ref, read-only) + Returns a reference to a hash containing the values currently bound to + placeholders. If the "named parameters" type of placeholders are being + used (such as ":foo"), then the keys of the hash will be the names of + the placeholders (without the colon). If the "dollar sign numbers" type + of placeholders are being used, the keys of the hash will be the + numbers, without the dollar signs. If the "question mark" type is used, + integer numbers will be returned, starting at one and increasing for + every placeholder. + + If this method is called before "execute", the literal values passed in + are returned. If called after "execute", then the quoted versions of the + values are returned. + + ParamTypes (hash ref, read-only) + Returns a reference to a hash containing the type names currently bound + to placeholders. The keys are the same as returned by the ParamValues + method. The values are hashrefs containing a single key value pair, in + which the key is either 'TYPE' if the type has a generic SQL equivalent, + and 'pg_type' if the type can only be expressed by a Postgres type. The + value is the internal number corresponding to the type originally passed + in. (Placeholders that have not yet been bound will return undef as the + value). This allows the output of ParamTypes to be passed back to the + "bind_param" method. + + Statement (string, read-only) + Returns the statement string passed to the most recent "prepare" method + called in this database handle, even if that method failed. This is + especially useful where "RaiseError" is enabled and the exception + handler checks $@ and sees that a "prepare" method call failed. + + RowsInCache + Returns the number of un-fetched rows in the cache for selects. + +SCROLLABLE CURSORS + Oracle supports the concept of a 'Scrollable Cursor' which is defined as + a 'Result Set' where the rows can be fetched either sequentially or + non-sequentially. One can fetch rows forward, backwards, from any given + position or the n-th row from the current position in the result set. + + Rows are numbered sequentially starting at one and client-side caching + of the partial or entire result set can improve performance by limiting + round trips to the server. + + Oracle does not support DML type operations with scrollable cursors so + you are limited to simple 'Select' operations only. As well you can not + use this functionality with remote mapped queries or if the LONG + datatype is part of the select list. + + However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, + and fetch methods. + + Only use scrollable cursors if you really have a good reason to. They do + use up considerable more server and client resources and have poorer + response times than non-scrolling cursors. + + Enabling Scrollable Cursors + To enable this functionality you must first import the 'Fetch + Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + + Next you will have to tell DBD::Oracle that you will be using scrolling + by setting the ora_exe_mode attribute on the statement handle to + 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + + When the statement is executed you will then be able to use + 'ora_fetch_scroll' method to get a row or you can still use any of the + other fetch methods but with a poorer response time than if you used a + non-scrolling cursor. As well scrollable cursors are compatible with any + applicable bind methods. + + Scrollable Cursor Methods + The following driver-specific methods are used with scrollable cursors. + + ora_scroll_position + $position = $sth->ora_scroll_position(); + + This method returns the current position (row number) attribute of + the result set. Prior to the first fetch this value is 0. This is + the only time this value will be 0 after the first fetch the value + will be set, so you can use this value to test if any rows have been + fetched. The minimum value will always be 1 after the first fetch. + The maximum value will always be the total number of rows in the + record set. + + ora_fetch_scroll + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + + Works the same as "fetchrow_arrayref", excepts one passes in a + 'Fetch Orientation' constant and a fetch_offset value which will + then determine the row that will be fetched. It returns the row as a + list containing the field values. Null fields are returned as + *undef* values in the list. + + The valid orientation constant and fetch offset values combination + are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + + The effect that a ora_fetch_scroll method call has on the + current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + + The effects of the differing orientation constants on the first + fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + + Scrollable Cursor Usage + Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + + and one assumes that the number of rows returned from the query is 20, + the code snippets below will illustrate the use of ora_fetch_scroll + method; + + Fetching the Last Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute to will be 20 after this snippet. This + is also a way to get the number of rows in the record set, however, + if the record set is large this could take some time. + + Fetching the Current Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will still be 20 after this snippet. + + Fetching the First Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the Next Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 5 after this snippet. + + Fetching the Prior Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the 10th Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 10th to 14th Row + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 14 after this snippet. + + Fetching the 14th to 10th Row + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 5th Row From the Present Position. + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 15 after this snippet. + + Fetching the 9th Row Prior From the Present Position + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 6 after this snippet. + + Use Finish + $sth->finish(); + + When using scrollable cursors it is required that you use the + $sth->finish() method when you are done with the cursor as this type + of cursor has to be explicitly cancelled on the server. If you do + not do this you may cause resource problems on your database. + +LOBS AND LONGS + The key to working with LOBs (CLOB, BLOBs) is to remember the value of + an Oracle LOB column is not the content of the LOB. It's a 'LOB Locator' + which, after being selected or inserted needs extra processing to read + or write the content of the LOB. There are also legacy LONG types (LONG, + LONG RAW, VARCHAR2) which are presently deprecated by Oracle but are + still in use. These LONG types do not utilize a 'LOB Locator' and also + are more limited in functionality than CLOB or BLOB fields. + + DBD::Oracle now offers three interfaces to LOB and LONG data, + + "Data Interface for Persistent LOBs" + With this interface DBD::Oracle handles your data directly utilizing + regular OCI calls, Oracle itself takes care of the LOB Locator + operations in the case of BLOBs and CLOBs treating them exactly as + if they were the same as the legacy LONG or LONG RAW types. + + "Data Interface for LOB Locators" + With this interface DBD::Oracle handles your data utilizing LOB + Locator OCI calls so it only works with CLOB and BLOB datatypes. + With this interface DBD::Oracle takes care of the LOB Locator + operations for you. + + "LOB Locator Method Interface" + This allows the user direct access to the LOB Locator methods, so + you have to take case of the LOB Locator operations yourself. + + Generally speaking the interface that you will chose will be dependent + on what end you are trying to achieve. All have their benefits and + drawbacks. + + One point to remember when working with LOBs (CLOBs, BLOBs) is if your + LOB column can be in one of three states; + + NULL + The table cell is created, but the cell holds no locator or value. + If your LOB field is in this state then there is no LOB Locator that + DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + + error when working with a LOB. + + You can correct this by using an SQL UPDATE statement to reset the + LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB + or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + + Empty + A LOB instance with a locator exists in the cell, but it has no + value. The length of the LOB is zero. In this case DBD::Oracle will + return 'undef' for the field. + + Populated + A LOB instance with a locator and a value exists in the cell. You + actually get the LOB value. + + Data Interface for Persistent LOBs + This is the original interface for LONG and LONG RAW datatypes and from + Oracle 9iR1 and later the OCI API was extended to work directly with the + other LOB datatypes. In other words you can treat all LOB type data + (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can + perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using + the same techniques you would use on other datatypes that store + character or binary data. In some cases there are fewer round trips to + the server as no 'LOB Locators' are used, normally one can get an entire + LOB is a single round trip. + + Simple Fetch for LONGs and LONG RAWs + As the name implies this is the simplest way to use this interface. + DBD::Oracle just attempts to get your LONG datatypes as a single large + piece. There are no special settings, simply set the database handle's + 'LongReadLen' attribute to a value that will be the larger than the + expected size of the LONG or LONG RAW. If the size of the LONG or LONG + RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A + Truncation' error. To stop this set the database handle's 'LongTruncOk' + attribute to '1'. The maximum value of 'LongReadLen' seems to be + dependent on the physical memory limits of the box that Oracle is + running on. You have most likely reached this limit if you run into an + 'ORA-01062: unable to allocate memory for define buffer' error. One + solution is to set the size of 'LongReadLen' to a lower value. + + For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select out all of the long1 fields in the table as long as they are + all under 2MB in length. A value in long1 longer than this will throw an + error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the long1 fields but they will be + truncated at 2MBs. + + Using ora_ncs_buff_mtpl + When getting CLOBs and NCLOBs in or out of Oracle, the Server will + translate from the Server's NCharSet to the Client's. If they happen to + be the same or at least compatible then all of these actions are a 1 + char to 1 char bases. Thus if you set your LongReadLen buffer to + 10_000_000 you will get up to 10_000_000 char. + + However if the Server has to translate from one NCharSet to another it + will use bytes for conversion. The buffer value is set to 4 * + LONG_READ_LEN which was very wasteful as you might only be asking for + 10_000_000 bytes but you were actually using 40_000_000 bytes of buffer + under the hood. You would still get 10_000_000 bytes (maybe less + characters though) but you are using allot more memory that you need. + + You can now customize the size of the buffer by setting the + 'ora_ncs_buff_mtpl' either on the connection or statement handle. You + can also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you + will have to go back and change all your code if you are getting into + trouble. + + The default value is still set to 4 for backward compatibility. You can + lower this value and thus increase the amount of data you can retrieve. + If the ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error + telling you to increase this buffer by one. + + If the error is not captured then you may get at some random point later + on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + + This is one of the more obscure ORA errors (have some fun and report it + to Meta-Link they will scratch their heads for hours) + + If you get this, simply increment the ora_ncs_buff_mtpl by one until it + goes away. + + This should greatly increase your ability to select very large CLOBs or + NCLOBs, by freeing up a large block of memory. + + You can tune this value by setting ora_oci_success_warn which will + display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + + In the case above the query Got 28 characters (well really only 20 + characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) + thus saving 40bytes of memory. + + Simple Fetch for CLOBs and BLOBs + To use this interface for CLOBs and LOBs datatypes set the + 'ora_pers_lob' attribute of the statement handle to '1' with the prepare + method, as well set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. If the + size of the LOB exceeds the 'LongReadLen' DBD::Oracle will return a + 'ORA-24345: A Truncation' error. To stop this set the database handle's + 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems + to be dependent on the physical memory limits of the box that Oracle is + running on in the same way that LONGs and LONG RAWs are. + + For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, + this is an internal OCI limit complain to them if you want it changed. + However if you CLOB is longer than this and also larger than the + 'LongReadLen' than the 'LongReadLen' in chars is returned. + + It seems with BLOBs you are not limited by the 64k. + + For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the lobs but they will be truncated + at 2MBs. + + Piecewise Fetch with Callback + With a piecewise callback fetch DBD::Oracle sets up a function that will + 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, + CLOB, BLOB) piece by piece. To use this interface set the 'ora_clbk_lob' + attribute of the statement handle to '1' with the prepare method. Next + set the 'ora_piece_size' to the size of the piece that you want to + return on the callback. Finally set the database handle's 'LongReadLen' + attribute to a value that will be the larger than the expected size of + the LOB. Like the "Simple Fetch for LONGs and LONG RAWs" and "Simple + Fetch for CLOBs and BLOBs" the if the size of the LOB exceeds the is + 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the + LOB or set the 'LongReadLen' to a higher value. With this interface the + value of 'ora_piece_size' seems to be constrained by the same memory + limit as found on the Simple Fetch interface. If you encounter an + 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller + value. The value for 'LongReadLen' is dependent on the version and + settings of the Oracle DB you are using. In theory it ranges from 8GBs + in 9iR1 up to 128 terabytes with 11g but you will also be limited by the + physical memory of your PERL instance. + + Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will + throw an error. + + Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 filed is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Piecewise Fetch with Polling + With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB + during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by + piece. To use this interface set the 'ora_piece_lob' attribute of the + statement handle to '1' with the prepare method. Next set the + 'ora_piece_size' to the size of the piece that you want to return on the + callback. Finally set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. Like + the "Piecewise Fetch with Callback" and Simple Fetches if the size of + the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' + attribute to truncate the LOB or set the 'LongReadLen' to a higher + value. With this interface the value of 'ora_piece_size' seems to be + constrained by the same memory limit as found on the "Piecewise Fetch + with Callback". + + Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will + throw an error. + + Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 field is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Binding for Updates and Inserts for CLOBs and BLOBs + To bind for updates and inserts all that is required to use this + interface is to set the statement handle's prepare method 'ora_type' + attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in + the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + + So far the only limit reached with this form of insert is the LOBs must + be under 2GB in size. + + Support for Remote LOBs; + Starting with Oracle 10gR2 the interface for Persistent LOBs was + expanded to support remote LOBs (access over a dblink). Given a database + called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + + to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Below are the limitations of Remote LOBs; + + Queries involving more than one database are not supported; + so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + + as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + + DDL commands are not supported; + so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + + Only binds and defines for data going into remote persistent LOBs are + supported. + so that parameter passing in PL/SQL where CHAR data is bound or + defined for remote LOBs is not allowed . + + These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + + If the remote object is a view such as + CREATE VIEW v AS SELECT foo() FROM ... + + the following would not work: + + SELECT * FROM v@dbs2; + + Limited PL/SQL parameter passing + PL/SQL parameter passing is not allowed where the actual argument is + a LOB type and the remote argument is one of VARCHAR2, NVARCHAR2, + CHAR, NCHAR, or RAW. + + RETURNING INTO does not support implicit conversions between CHAR and + CLOB. + so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + + Locator Data Interface + Simple Usage + When fetching LOBs with this interface a 'LOB Locator' is created then + used to get the lob with the LongReadLen and LongTruncOk attributes. The + value for 'LongReadLen' is dependent on the version and settings of the + Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 + terabytes with 11g but you will also be limited by the physical memory + of your PERL instance. + + When inserting or updating LOBs some *major* magic has to be performed + behind the scenes to make it transparent. Basically the driver has to + insert a 'LOB Locator' and then refetch the newly inserted LOB Locator + before being able to write the data into it. However, it works well most + of the time, and I've made it as fast as possible, just one extra + server-round-trip per insert or update after the first. For the time + being, only single-row LOB updates are supported. + + To insert or update a large LOB using a placeholder, DBD::Oracle has to + know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + + The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + + or use the corresponding integer values (112 and 113). + + One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has to + be able to tell which parameters relate to which table fields. In all + cases where it can possibly work it out for itself, it does, however, if + there are multiple LOB fields of the same type in the table then you + need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + + There are some limitations inherent in the way DBD::Oracle makes typical + LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + + The alternative is to disable the automatic LOB Locator processing. If + "ora_auto_lob" is 0 in prepare(), you can fetch the LOB Locators and do + all the work yourself using the ora_lob_*() methods. See the "Data + Interface for LOB Locators" section below. + + LOB support in PL/SQL + LOB Locators can be passed to PL/SQL calls by binding them to + placeholders with the proper "ora_type". If "ora_auto_lob" is true, + output LOB parameters will be automatically returned as strings. + + If the Oracle driver has support for temporary LOBs (Oracle 9i and + higher), strings can be bound to input LOB placeholders and will be + automatically converted to LOBs. + + Example: # Build a large XML document, bind it as a CLOB, # extract + elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + + If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + + error, while attempting to insert a LOB, this means the Oracle user has + insufficient space for LOB you are trying to insert. One solution it to + use "alter database datafile 'sss.ggg' resize Mnnn" to increase the + available memory for LOBs. + + Persistent & Locator Interface Caveats + Now that one has the option of using the Persistent or the Locator + interface for LOBs the questions arises which one to use. For starters, + if you want to access LOBs over a dblink you will have to use the + Persistent interface so that choice is simple. The question of which one + to use after that is a little more tricky. It basically boils down to a + choice between LOB size and speed. + + The Callback and Polling piecewise fetches are very very slow when + compared to the Simple and the Locator fetches but they can handle very + large blocks of data. Given a situation where a large LOB is to be read + the Locator fetch may time out while either of the piecewise fetches may + not. + + With the Simple fetch you are limited by physical memory of your server + but it runs a little faster than the Locator, as there are fewer round + trips to the server. So if you have small LOBs and need to save a little + bandwidth this is the one to use. It you are going after large LOBs then + the Locator interface is the one to use. + + If you need to update more than a single row of with LOB data then the + Persistent interface can do it while the Locator can't. + + If you encounter a situation where you have to access the legacy LOBs + (LONG, LONG RAW) and the values are to large for you system then you can + use the Callback or Polling piecewise fetches to get all of the data. + + Not all of the Persistent interface has been implemented yet, the + following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + + Most of the time you should just use the "Locator Data Interface" as + this is in one that has the best combination of speed and size. + + All this being said if you are doing some critical programming I would + use the "Data Interface for LOB Locators" as this gives you very fine + grain control of your LOBs, of course the code for this will be somewhat + more involved. + + Data Interface for LOB Locators + The following driver-specific methods let you manipulate "LOB Locators" + directly. To select a LOB locator directly set the if the "ora_auto_lob" + attribute to false, or alternatively they can be returned via PL/SQL + procedure calls. + + (If using a DBI version earlier than 1.36 they must be called via the + func() method. Note that methods called via func() don't honour + RaiseError etc, and so it's important to check $dbh->err after each + call. It's recommended that you upgrade to DBI 1.38 or later.) + + Note that LOB locators are only valid while the statement handle that + created them is valid. When all references to the original statement + handle are lost, the handle is destroyed and the locators are freed. + + ora_lob_read + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + + Read a portion of the LOB. $offset starts at 1. Uses the Oracle + OCILobRead function. + + ora_lob_write + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + + Write/overwrite a portion of the LOB. $offset starts at 1. Uses the + Oracle OCILobWrite function. + + ora_lob_append + $rc = $dbh->ora_lob_append($lob_locator, $data); + + Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + + ora_lob_trim + $rc = $dbh->ora_lob_trim($lob_locator, $length); + + Trims the length of the LOB to $length. Uses the Oracle OCILobTrim + function. + + ora_lob_length + $length = $dbh->ora_lob_length($lob_locator); + + Returns the length of the LOB. Uses the Oracle OCILobGetLength + function. + + ora_lob_is_init + $is_init = $dbh->ora_lob_is_init($lob_locator); + + Returns true(1) if the Lob Locator is initialized false(0) if it is + not, or 'undef' if there is an error. Uses the Oracle + OCILobLocatorIsInit function. + + ora_lob_chunk_size + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + + Returns the chunk size of the LOB. Uses the Oracle + OCILobGetChunkSize function. + + For optimal performance, Oracle recommends reading from and writing + to a LOB in batches using a multiple of the LOB chunk size. In + Oracle 10g and before, when all defaults are in place, this chunk + size defaults to 8k (8192). + + LOB Locator Method Examples + *Note:* Make sure you first read the note in the section above about + multi-byte character set issues with these methods. + + The following examples demonstrate the usage of LOB Locators to read, + write, and append data, and to query the size of large data. + + The following examples assume a table containing two large object + columns, one binary and one character, with a primary key column, + defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + + It also assumes a sequence for use in generating unique lob_id field + values, defined as follows: + + CREATE SEQUENCE lob_example_seq + + Example: Inserting a new row with large data + Unless enough memory is available to store and bind the entire LOB data + for insert all at once, the LOB columns must be written interactively, + piece by piece. In the case of a new row, this is performed by first + inserting a row, with empty values in the LOB columns, then modifying + the row by writing the large data interactively to the LOB columns using + their LOB locators as handles. + + The insert statement must create token values in the LOB columns. Here, + we use the empty string for both the binary and character large object + columns 'bindata' and 'chardata'. + + After the INSERT statement, a SELECT statement is used to acquire LOB + locators to the 'bindata' and 'chardata' fields of the newly inserted + row. Because these LOB locators are subsequently written, they must be + acquired from a select statement containing the clause 'FOR UPDATE' (LOB + locators are only valid within the transaction that fetched them, so + can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + + In this example we demonstrate the use of ora_lob_write() interactively + to append data to the columns 'bin_data' and 'char_data'. Had we used + ora_lob_append(), we could have saved ourselves the trouble of keeping + track of the offset into the lobs. The snippet of code beneath the + comment 'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + + The scalar variables $offset and $length are no longer needed, because + ora_lob_append() keeps track of the offset for us. + + Example: Updating an existing row with large data + In this example, we demonstrate a technique for overwriting a portion of + a blob field with new binary data. The blob data before and after the + section overwritten remains unchanged. Hence, this technique could be + used for updating fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + + After running this code, the row where lob_id = 5 will contain, starting + at position 100234 in the bin_data column, the string "This string will + overwrite a portion of the blob". + + Example: Streaming character data from the database + In this example, we demonstrate a technique for streaming data from the + database to a file handle, in this case STDOUT. This allows more data to + be read in and written out than could be stored in memory at a given + time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + + Notice that the select statement does not contain the phrase "FOR + UPDATE". Because we are only reading from the LOB Locator returned, and + not modifying the LOB it refers to, the select statement does not + require the "FOR UPDATE" clause. + + A word of caution when using the data returned from an ora_lob_read in a + conditional statement. for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + + was used with a chunk size of 4096 against a blob that requires more + than 1 chunk to return the data and the last chunk is one byte long and + contains a zero (ASCII 48) you will miss this last byte as $data will + contain 0 which PERL will see as false and not print it out. + + Example: Truncating existing large data + In this example, we truncate the data already present in a large object + column in the database. Specifically, for each row in the table, we + truncate the 'bindata' value to half its previous length. + + After acquiring a LOB Locator for the column, we query its length, then + we trim the length by half. Because we modify the large objects with the + call to ora_lob_trim(), we must select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +SPACES AND PADDING + Trailing Spaces + Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder + values and uses Nonpadded Comparison Semantics with the result. This + causes trouble if the spaces are needed for comparison with a CHAR value + or to prevent the value from becoming '' which Oracle treats as NULL. + Look for Blank-padded Comparison Semantics and Nonpadded Comparison + Semantics in Oracle's SQL Reference or Server SQL Reference for more + details. + + To preserve trailing spaces in placeholder values for Oracle clients + that use OCI 8, either change the default placeholder type with + "ora_ph_type" or the placeholder type for a particular call to "bind" in + DBI or "bind_param_inout" in DBI with "ora_type" or "TYPE". Using + ORA_CHAR with ora_type or "SQL_CHAR" with "TYPE" allows the placeholder + to be used with Padded Comparison Semantics if the value it is being + compared to is a CHAR, NCHAR, or literal. + + Please remember that using spaces as a value or at the end of a value + makes visually distinguishing values with different numbers of spaces + difficult and should be avoided. + + Oracle Clients that use OCI 9.2 do not strip trailing spaces. + + Padded Char Fields + Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder + values to the size of the CHAR. As the default placeholder type value in + DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will have to + change the default placeholder type with "ora_ph_type" or placeholder + type for a particular call with "bind" in DBI or "bind_param_inout" in + DBI with "ORA_CHAR". + +UNICODE + DBD::Oracle now supports Unicode UTF-8. There are, however, a number of + issues you should be aware of, so please read all this section + carefully. + + In this section we'll discuss "Perl and Unicode", then "Oracle and + Unicode", and finally "DBD::Oracle and Unicode". + + Information about Unicode in general can be found at: + . It is well worth reading because there are + many misconceptions about Unicode and you may be holding some of them. + + Perl and Unicode + Perl began implementing Unicode with version 5.6, but the implementation + did not mature until version 5.8 and later. If you plan to use Unicode + you are *strongly* urged to use Perl 5.8.2 or later and to *carefully* + read the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + + And then read it again. + + Perl's internal Unicode format is UTF-8 which corresponds to the Oracle + character set called AL32UTF8. + + Oracle and Unicode + Oracle supports many characters sets, including several different forms + of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + + When you create an Oracle database, you must specify the DATABASE + character set (used for DDL, DML and CHAR datatypes) and the NATIONAL + character set (used for NCHAR and NCLOB types). The character sets used + in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + + The Oracle 9.2 and later default for the national character set is + AL16UTF16. The default for the database character set is often US7ASCII. + Although many experienced DBAs will consider an 8bit character set like + WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other + than US7ASCII, requires that the NLS_LANG environment variable be set. + See the "Oracle UTF8 is not UTF-8" section below. + + You are strongly urged to read the Oracle Internationalization + documentation specifically with respect the choices and trade offs for + creating a databases for use with international character sets. + + Oracle uses the NLS_LANG environment variable to indicate what character + set is being used on the client. When fetching data Oracle will convert + from whatever the database character set is to the client character set + specified by NLS_LANG. Similarly, when sending data to the database + Oracle will convert from the character set specified by NLS_LANG to the + database character set. + + The NLS_NCHAR environment variable can be used to define a different + character set for 'national' (NCHAR) character types. + + Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. For + example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + + Oracle UTF8 is not UTF-8 + AL32UTF8 should be used in preference to UTF8 if it works for you, which + it should for Oracle 9.2 or later. If you're using an old version of + Oracle that doesn't support AL32UTF8 then you should avoid using any + Unicode characters that require surrogates, in other words characters + beyond the Unicode BMP (Basic Multilingual Plane). + + That's because the character set that Oracle calls "UTF8" doesn't + conform to the UTF-8 standard in its handling of surrogate characters. + Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". + Here are a couple of extracts from + : + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + + Oracle uses this internally because it collates (sorts) in the same + order as UTF16, which is the basis of Oracle's internal collation + definitions. + + Rather than change UTF8 for clients Oracle chose to define a new + character set called "AL32UTF8" which does conform to the UTF-8 + standard. (The AL32UTF8 character set can't be used on the server + because it would break collation.) + + Because of that, for the rest of this document we'll use "AL32UTF8". If + you're using an Oracle version below 9.2 you'll need to use "UTF8" until + you upgrade. + + DBD::Oracle and Unicode + DBD::Oracle Unicode support has been implemented for Oracle versions 9 + or greater, and Perl version 5.6 or greater (though we *strongly* + suggest that you use Perl 5.8.2 or later). + + You can check which Oracle version your DBD::Oracle was built with by + importing the "ORA_OCI" constant from DBD::Oracle. + + Fetching Data + + Any data returned from Oracle to DBD::Oracle in the AL32UTF8 character + set will be marked as UTF-8 to ensure correct handling by Perl. + + For Oracle to return data in the AL32UTF8 character set the NLS_LANG or + NLS_NCHAR environment variable *must* be set as described in the + previous section. + + When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle + will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR is + AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + + When fetching other character data from Oracle, DBD::Oracle will set the + Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + + Sending Data using Placeholders + + Data bound to a placeholder is assumed to be in the default client + character set (specified by NLS_LANG) except for a few special cases. + These are listed here with the highest precedence first: + + If the "ora_csid" attribute is given to bind_param() then that is passed + to Oracle and takes precedence. + + If the value is a Perl Unicode string (UTF-8) then DBD::Oracle ensures + that Oracle uses the Unicode character set, regardless of the NLS_LANG + and NLS_NCHAR settings. + + If the placeholder is for inserting an NCLOB then the client NLS_NCHAR + character set is used. (That's useful but inconsistent with the other + behaviour so may change. Best to be explicit by using the "ora_csform" + attribute.) + + If the "ora_csform" attribute is given to bind_param() then that + determines if the value should be assumed to be in the default + (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + Binding with bind_param_array and execute_array is also UTF-8 compatible + in the same way. If you attempt to insert UTF-8 data into a non UTF-8 + Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert will + still happen but a error code of 0 will be returned with the following + warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + + The warning will report the parameter number and the NCHAR setting that + the query is running. + + Sending Data using SQL + + Oracle assumes the SQL statement is in the default client character set + (as specified by NLS_LANG). So Unicode strings containing non-ASCII + characters should not be used unless the default client character set is + AL32UTF8. + + DBD::Oracle and Other Character Sets and Encodings + The only multi-byte Oracle character set supported by DBD::Oracle is + "AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +OBJECT & COLLECTION DATA TYPES + Oracle databases allow for the creation of object oriented like + user-defined types. There are two types of objects, Embedded--an object + stored in a column of a regular table and REF--an object that uses the + REF retrieval mechanism. + + DBD::Oracle supports only the 'selection' of embedded objects of the + following types OBJECT, VARRAY and TABLE in any combination. Support is + seamless and recursive, meaning you need only supply a simple SQL + statement to get all the values in an embedded object. You can either + get the values as an array of scalars or they can be returned into a + DBD::Oracle::Object. + + Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + + The code to access all the data in the table could be something like + this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + + Note that values in PHONE_NUMBERS are returned as an array reference + '@$phone'. + + As stated before DBD::Oracle will automatically drill into the embedded + object and extract all of the data as reference arrays of scalars. The + example below has OBJECT type embedded in a TABLE type embedded in an + SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + + The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + + Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + + The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + + So far DBD::Oracle has been tested on a table with 20 embedded Objects, + Varrays and Tables nested to 10 levels. + + Any NULL values found in the embedded object will be returned as + 'undef'. + +OTHER DATA TYPES + DBD::Oracle does not *explicitly* support most Oracle datatypes. It + simply asks Oracle to return them as strings and Oracle does so. Mostly. + Similarly when binding placeholder values DBD::Oracle binds them as + strings and Oracle converts them to the appropriate type, such as DATE, + when used. + + Some of these automatic conversions to and from strings use NLS settings + to control the formatting for output and the parsing for input. The most + common example is the DATE type. The default NLS format for DATE might + be DD-MON-YYYY and so when a DATE type is fetched that's how Oracle will + format the date. NLS settings also control the default parsing of + strings into DATE values. An error will be generated if the contents of + the string don't match the NLS format. If you're dealing in dates which + don't match the default NLS format then you can either change the + default NLS format or, more commonly, use TO_CHAR(field, "format") and + TO_DATE(?, "format") to explicitly specify formats for converting to and + from strings. + + A slightly more subtle problem can occur with NUMBER types. The default + NLS settings might format numbers with a fullstop (""."") to separate + thousands and a comma ("","") as the decimal point. Perl will generate + warnings and use incorrect values when numbers, returned and formatted + as strings in this way by Oracle, are used in a numeric context. You + could explicitly convert each numeric value using the TO_CHAR(...) + function but that gets tedious very quickly. The best fix is to change + the NLS settings. That can be done for an individual connection by + doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + + There are some types, like BOOLEAN, that Oracle does not automatically + convert to or from strings (pity). These need to be converted explicitly + using SQL or PL/SQL functions. + + Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + + Support for Insert of XMLType (ORA_XMLTYPE) + Inserting large XML data sets into tables with XMLType fields is now + supported by DBD::Oracle. The only special requirement is the use of + bind_param() with an attribute hash parameter that specifies ora_type as + ORA_XMLTYPE. For example with a table like this; + + create table books (book_id number, book_xml XMLType); + + one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + + In the above case we will assume that $xml has 10000 Book nodes and is + over 32k in size and is well formed XML. This will also work for XML + that is smaller than 32k as well. Attempting to insert malformed XML + will cause an error. + + Binding Cursors + Cursors can be returned from PL/SQL blocks, either from stored functions + (or procedures with OUT parameters) or from direct "OPEN" statements, as + shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + The only special requirement is the use of "bind_param_inout()" with an + attribute hash parameter that specifies "ora_type" as "ORA_RSET". If you + don't do that you'll get an error from the "execute()" like: "ORA-06550: + line X, column Y: PLS-00306: wrong number or types of arguments in call + to ...". + + Here's an alternative form using a function that returns a cursor. This + example uses the pre-defined weak (or generic) REF CURSOR type + SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + A cursor obtained from PL/SQL as above may be passed back to PL/SQL by + binding for input, as shown in this example, which explicitly closes a + cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + + It is not normally necessary to close a cursor explicitly in this way. + Oracle will close the cursor automatically at the first client-server + interaction after the cursor statement handle is destroyed. An explicit + close may be desirable if the reference to the cursor handle from the + PL/SQL statement handle delays the destruction of the cursor handle for + too long. This reference remains until the PL/SQL handle is re-bound, + re-executed or destroyed. + + See the "curref.pl" script in the Oracle.ex directory in the DBD::Oracle + source distribution for a complete working example. + + Fetching Nested Cursors + Oracle supports the use of select list expressions of type REF CURSOR. + These may be explicit cursor expressions - "CURSOR(SELECT ...)", or + calls to PL/SQL functions which return REF CURSOR values. The values of + these expressions are known as nested cursors. + + The value returned to a Perl program when a nested cursor is fetched is + a statement handle. This statement handle is ready to be fetched from. + It should not (indeed, must not) be executed. + + Oracle imposes a restriction on the order of fetching when nested + cursors are used. Suppose $sth1 is a handle for a select statement + involving nested cursors, and $sth2 is a nested cursor handle fetched + from $sth1. $sth2 can only be fetched from while $sth1 is still active, + and the row containing $sth2 is still current in $sth1. Any attempt to + fetch another row from $sth1 renders all nested cursor handles + previously fetched from $sth1 defunct. + + Fetching from such a defunct handle results in an error with the message + "ERROR nested cursor is defunct (parent row is no longer current)". + + This means that the "fetchall..." or "selectall..." methods are not + useful for queries returning nested cursors. By the time such a method + returns, all the nested cursor handles it has fetched will be defunct. + + It is necessary to use an explicit fetch loop, and to do all the + fetching of nested cursors within the loop, as the following example + shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + + The cursor returned by the function "sp_ListEmp" defined in the previous + section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + + Pre-fetching Nested Cursors + By default, DBD::Oracle pre-fetches rows in order to reduce the number + of round trips to the server. For queries which do not involve nested + cursors, the number of pre-fetched rows is controlled by the DBI + database handle attribute "RowCacheSize" (q.v.). + + In Oracle, server side open cursors are a controlled resource, limited + in number, on a per session basis, to the value of the initialization + parameter "OPEN_CURSORS". Nested cursors count towards this limit. Each + nested cursor in the current row counts 1, as does each nested cursor in + a pre-fetched row. Defunct nested cursors do not count. + + An Oracle specific database handle attribute, "ora_max_nested_cursors", + further controls pre-fetching for queries involving nested cursors. For + each statement handle, the total number of nested cursors in pre-fetched + rows is limited to the value of this parameter. The default value is 0, + which disables pre-fetching for queries involving nested cursors. + +PL/SQL Examples + Most of these PL/SQL examples come from: Eric Bartley + . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + + You can find more examples in the t/plsql.t file in the DBD::Oracle + source directory. + + Oracle 9.2 appears to have a bug where a variable bound with + bind_param_inout() that isn't assigned to by the executed PL/SQL block + may contain garbage. See + + + Avoid Using "SQL Call" + Avoid using the "SQL Call" statement with DBD:Oracle as you might find + that DBD::Oracle will not raise an exception in some case. Specifically + if you use "SQL Call" to run a procedure all "No data found" exceptions + will be quietly ignored and returned as null. According to Oracle + support this is part of the same mechanism where; + + select (select * from dual where 0=1) from dual + + returns a null value rather than an exception. + +CONTRIBUTING + If you'd like DBD::Oracle to do something new or different the best way + to make that happen is to do it yourself and email to dbi-dev@perl.org a + patch of the source code (using 'diff' - see below) that shows the + changes. + + How to create a patch using Subversion + The DBD::Oracle source code is maintained using Subversion (a + replacement for CVS, see ). To access the + source you'll need to install a Subversion client. Then, to get the + source code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + + If it prompts for a username and password use your perl.org account if + you have one, else just 'guest' and 'guest'. The source code will be in + a new subdirectory called "trunk". + + To keep informed about changes to the source you can send an empty email + to dbd-oracle-changes-subscribe@perl.org after which you'll get an email + with the change log message and diff of each change checked-in to the + source. + + After making your changes you can generate a patch file, but before you + do, make sure your source is still upto date using: + + svn update + + If you get any conflicts reported you'll need to fix them first. Then + generate the patch file from within the "trunk" directory using: + + svn diff > foo.patch + + Read the patch file, as a sanity check, and then email it to + dbi-dev@perl.org. + + How to create a patch without Subversion + Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + + Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + + Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you + want. + + Test your changes and then remove all temporary files: + + make test && make distclean + + Go back to the directory you originally unpacked the distribution: + + cd .. + + Unpack *another* copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + + Then create a patch file by performing a recursive "diff" on the two top + level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + + Speak before you patch + For anything non-trivial or possibly controversial it's a good idea to + discuss (on dbi-dev@perl.org) the changes you propose before actually + spending time working on them. Otherwise you run the risk of them being + rejected because they don't fit into some larger plans you may not be + aware of. + + GitHub repository + A git mirror of the subversion is also available at + `https://github.com/yanick/DBD-Oracle`. + +Oracle Related Links +WHICH VERSION OF DBD::ORACLE IS FOR ME? + From version 1.25 onwards DBD::Oracle only support Oracle clients 9.2 or + greater. Support for ProC connections was dropped in 1.29. + + If you are still stuck with an older version of Oracle or its client you + might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + + As there are dozens of different versions of Oracle's clients this list + does not include all of them, just the major released versions of + Oracle. + + Note that one can still connect to any Oracle version with the older + DBD::Oracle versions the only problem you will have is that some of the + newer OCI and Oracle features available in later DBD::Oracle releases + will not be available to you. + + So to make a short story a little longer: + + 1 If you are using Oracle 7 or early 8 DB and you can manage to get a + 9 client and you can use any DBD::Oracle version. + + 2 If you have to use an Oracle 7 client then DBD::Oracle 1.17 should + work + + 3 Same thing for 8 up to R2, use 1.17, if you are lucky and have the + right patch-set you might go with 1.18. + + 4 For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. + Again this depends on your patch-set, If you run into trouble go + with 1.19 + + 5 After 9.2 you can use any version you want. + + 6 It seems that the 10g client can only connect to 9 and 11 DBs while + the 9 can go back to 7 and even get to 10. I am not sure what the + 11g client can connect to. + +BUGS AND LIMITATIONS + There is a known problem with the 11.2g Oracle client and the + "DBMS_LOB.GETLENGTH()" PL/SQL function. See + for the details. + +SEE ALSO + DBI http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in + the DBD::Oracle source distribution including the examples in the + Oracle.ex directory + + DBD::Oracle Tutorial + http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-ora + cle.html + + Oracle Instant Client + http://www.oracle.com/technology/tech/oci/instantclient/index.html + + Oracle on Linux + http://www.ixora.com.au/ + + Free Oracle Tools and Links + ora_explain supplied and installed with DBD::Oracle. + + http://www.orafaq.com/ + + http://vonnieda.org/oracletool/ + + Commercial Oracle Tools and Links + Assorted tools and references for general information. No + recommendation implied. + + http://www.platinum.com + + http://www.SoftTreeTech.com + + Also PL/Vision from RevealNet and Steven Feuerstein, and "Q" from + Savant Corporation. + +AUTHORS + DBI by Tim Bunce . + + The original "DBD::Oracle" was by Tim Bunce. Maintained as of release + 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the + auspice of the Pythian Group (). + +ACKNOWLEDGEMENTS + A great many people have helped with DBD::Oracle over the 17 years + between 1994 and 2011. Far too many to name, but we thank them all. Many + are named in the Changes file. + +COPYRIGHT + The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. + The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The + Pythian Group). Canada. The DBD::Oracle module is Copyright (c) 2011 + John Scoles. Canada. + + The DBD::Oracle module is free open source software; you can + redistribute it and/or modify it under the same terms as Perl 5. + +AUTHORS + * Tim Bunce + + * John Scoles + + * Yanick Champoux + +COPYRIGHT AND LICENSE + This software is copyright (c) 1994 by Tim Bunce. + + This is free software; you can redistribute it and/or modify it under + the same terms as the Perl 5 programming language system itself. diff --git a/README.mkdn b/README.mkdn new file mode 100644 index 00000000..111d9c54 --- /dev/null +++ b/README.mkdn @@ -0,0 +1,4228 @@ +# NAME + +DBD::Oracle - Oracle database driver for the DBI module + +# VERSION + +version 1.37_00 + +# SYNOPSIS + + use DBI; + + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); + + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); + + # See the DBI module documentation for full details + + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); + +# DESCRIPTION + +DBD::Oracle is a Perl module which works with the DBI module to provide +access to Oracle databases. + +This documentation describes driver specific behaviour and restrictions. It is +not supposed to be used as the only reference for the user. In any case +consult the [DBI](http://search.cpan.org/perldoc?DBI) documentation first! + +# CONSTANTS + +- :ora_session_modes + +ORA_SYSDBA ORA_SYSOPER ORA_SYSASM + +- :ora_types + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +- SQLCS_IMPLICIT + +- SQLCS_NCHAR + +SQLCS_IMPLICIT and SQLCS_NCHAR are _character set form_ values. +See notes about Unicode elsewhere in this document. + +- SQLT_INT + +- SQLT_FLT + +These types are used only internally, and may be specified as internal +bind type for ORA_NUMBER_TABLE. See notes about ORA_NUMBER_TABLE elsewhere +in this document + +- ORA_OCI + +Oracle doesn't provide a formal API for determining the exact version +number of the OCI client library used, so DBD::Oracle has to go digging +(and sometimes has to more or less guess). The ORA_OCI constant +holds the result of that process. + +In string context ORA_OCI returns the full "A.B.C.D" version string. + +In numeric context ORA_OCI returns the major.minor version number +(8.1, 9.2, 10.0 etc). But note that version numbers are not actually +floating point and so if Oracle ever makes a release that has a two +digit minor version, such as `9.10` it will have a lower numeric +value than the preceding `9.9` release. So use with care. + +The contents and format of ORA_OCI are subject to change (it may, +for example, become a _version object_ in later releases). +I recommend that you avoid checking for exact values. + +- :ora_fetch_orient + + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE + +These constants are used to set the orientation of a fetch on a scrollable cursor. + +- :ora_exe_modes + + OCI_STMT_SCROLLABLE_READONLY + +- :ora_fail_over + + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + +# DBI CLASS METHODS + +## __connect__ + +This method creates a database handle by connecting to a database, and is the DBI equivalent of the "new" method. +To open a connection to an Oracle database you need to specify a database connection string (URL), username and password. + +The connection string is always of the form: "dbi:Oracle:" +There are several ways to identify a database: + +- 1 + +If the database is local, specifying the SID or service name will be enough. + +- 2 + +If the database is defined in a TNSNAMES.ORA file, you can use the service name given in the file + +- 3 + +To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: +//host[:port][/service_name] + +If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. + +The following examples show several ways a connection can be created: + + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); + + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); + + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); + + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); + +### OS authentication + +To connect to a local database with a user which has been set up to +authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): + + $dbh = DBI->connect('dbi:Oracle:','/',''); + +Note the lack of a connection name (use the ORACLE_SID environment +variable). If an explicit SID is used you will probably get an ORA-01004 error. + +That only works for local databases. (Authentication to remote Oracle +databases using your Unix login name without a password is possible +but it is not secure and not recommended so not documented here. + +### Oracle Environment Variables + +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). + +Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. + +To use them, specify either a local SID or service name, or a service name that is specified in the TNSNAMES.ORA file. + +Note that if you have *both* local and remote databases, and you have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO_TASK takes precedence over ORACLE_SID (i.e. you get connected to remote system). + +It is highly recommended not to rely on environment variables and to always explicitly specify the SID in the connection string. This can prevent serious mistakes such as dropping a schema in the wrong database, and generally makes debugging and troubleshooting easier. + +Also remember that depending on the operating system you are using the differing "ORACLE" environment variables may be case sensitive, so if you are not connecting as you should double check the case of both the variable and its value. + +### Timezones + +If the query is run through SQL*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. + +If the query is run locally, Oracle will return the time zone based on the "TZ" environment variable setting of the user running +the query. + +With local queries, you can change the time zone for a particular user by simply changing the setting of "TZ". To check the current setting, +issue the UNIX "date" command. + +### Oracle DRCP + +DBD::Oracle supports DRCP (Database Resident Connection Pool) so +if you have an 11.2 database and DRCP is enabled you can direct +all of your connections to it by adding ':POOLED' to the SID or +setting a connection attribute of ora_drcp, or set the SERVER=POOLED +when using a TNSENTRY style connection or even by setting an +environment variable ORA_DRCP. All of which are demonstrated below; + + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') + + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') + + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") + + if the ORA_DRCP environment variable is set then just this + + $dbh = DBI->connect('dbi:Oracle:DB','username','password') + +You can find a white paper on setting up DRCP and its advantages at [http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf](http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf). + +Please note that DRCP support in DBD::Oracle is relatively new so the +mechanics or its implementation are subject to change. + +### TAF (Transparent Application Failover) + +Transparent Application Failover (TAF) is the feature in OCI that +allows for clients to automatically reconnect to an instance in the +event of a failure of the instance. The reconnect happens +automatically from within the OCI (Oracle Call Interface) library. +DBD::Oracle now supports a callback function that will fire when a TAF +event takes place. The main use of the callback is to give your +program the opportunity to inform the user that a failover is taking +place. + +You will have to set up TAF on your instance before you can use this +callback. You can test your instance to see if you can use TAF +callback with + + $dbh->ora_can_taf(); + +If you try to set up a callback without it being enabled DBD::Oracle will croak. + +It is outside the scope of this documents to go through all of the +possible TAF situations you might want to set up but here is a simple +example: + +The TNS entry for the instance has had the following added to the +CONNECT_DATA section + + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) + +You will also have to create your own perl function that will be +called from the client. You can name it anything you want and it will +always be passed two parameters, the failover event value and the +failover type. You can also set a sleep value in case of failover +error and the OCI client will sleep for the specified seconds before it +attempts another event. + + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants + + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + + #create the perl TAF event function + + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ + + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); + + } + return 0; + } + +The TAF types are as follows + + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + +The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + +### Connect Attributes + +#### ora_ncs_buff_mtpl + +You can customize the size of the buffer when selecting LOBs with +the built-in AUTO Lob. The default value is 4 which is probably +excessive for most situations but is needed for backward +compatibility. If you not converting between a NCS on the DB and the +Client then you might want to set this to 1 to reduce memory usage. + +This value can also be specified with the `ORA_DBD_NCS_BUFFER` +environment variable in which case it sets the value at the connect +stage. + +#### ora_drcp + +For Oracle 11.2 or greater. + +Set to _1_ to enable DRCP. Can also be set via the `ORA_DRCP` environment variable. + +#### ora_drcp_class + +If you are using DRCP, you can set a CONNECTION_CLASS for your pools +as well. As sessions from a DRCP cannot be shared by users, you can +use this setting to identify the same user across different +applications. OCI will ensure that sessions belonging to a 'class' are +not shared outside the class'. + +The values for ora_drcp_class cannot contain a '*' and must be less +than 1024 characters. + +This value can be also be specified with the `ORA_DRCP_CLASS` +environment variable. + +#### ora_drcp_min + +This optional value specifies the minimum number of sessions that are +initially opened. New sessions are only opened after this value has +been reached. + +The default value is 4 and any value above 0 is valid. + +Generally, it should be set to the number of concurrent statements the +application is planning or expecting to run. + +This value can also be specified with the `ORA_DRCP_MIN` environment +variable. + +#### ora_drcp_max + +This optional value specifies the maximum number of sessions that can +be open at one time. Once reached no more sessions can be opened +until one becomes free. The default value is 40 and any value above 1 +is valid. You should not set this value lower than ora_drcp_min as +that will just waste resources. + +This value can also be specified with the `ORA_DRCP_MAX` environment +variable. + +#### ora_drcp_incr + +This optional value specifies the next increment for sessions to be +started if the current number of sessions are less than +ora_drcp_max. The default value is 2 and any value above 0 is +valid as long as the value of ora_drcp_min + ora_drcp_incr is not +greater than ora_drcp_max. + +This value can also be specified with the `ORA_DRCP_INCR` environment +variable. + +#### ora_taf + +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option to any _true_ value. + +#### ora_taf_function + +The name of the Perl subroutine that will be called from OCI when a +TAF event occurs. You must supply a perl function to use the callback +and it will always receive two parameters, the failover event value +and the failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + +#### ora_taf_sleep + +The amount of time in seconds the OCI client will sleep between attempting +successive failover events when the event is OCI_FO_ERROR. + +#### ora_session_mode + +The ora_session_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA_SYSASM authorization. +The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + +This is one case where setting ORACLE_SID may be useful since +connecting as SYSDBA or SYSOPER via SQL*Net is frequently disabled +for security reasons. + +Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + +It has been reported that this only works if `$dsn` does not contain +a SID so that Oracle then uses the value of ORACLE_SID (not +TWO_TASK) environment variable to connect to a local instance. Also +the username and password should be empty, and the user executing the +script needs to be part of the dba group or osdba group. + +#### ora_oratab_orahome + +Passing a true value for the ora_oratab_orahome attribute will make +DBD::Oracle change `$ENV{ORACLE_HOME}` to make the Oracle home directory +that specified in the `/etc/oratab` file _if_ the database to connect to +is specified as a SID that exists in the oratab file, and DBD::Oracle was +built to use the Oracle 7 OCI API (not Oracle 8+). + +#### ora_module_name + +After connecting to the database the value of this attribute is passed +to the SET_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL +package. This can be used to identify the application to the DBA for +monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + +The maximum size is 48 bytes. + +#### ora_driver_name + +For 11g and later you can now set the name of the driver layer using OCI. +Perl, Perl5, ApachePerl so on. Names starting with "ORA" are reserved. You +can enter up to 8 characters. If none is enter then this will default to +DBDOxxxx where xxxx is the current version number. This value can be +retrieved on the server side using V$SESSION_CONNECT_INFO or +GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + +#### ora_client_info + +Allows you to add any value (up to 64 bytes) to your session and it can be +retrieved on the server side from the `V$SESSION`a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + +#### ora_client_identifier + +Allows you to specify the user identifier in the session handle. + +Most useful for web applications as it can pass in the session user +name which might be different to the connection user name. Can be up +to 64 bytes long but do not to include the password for security +reasons and the first character of the identifier should not be +':'. This value can be retrieved on the server side using `V$SESSION` +view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + +#### ora_action + +Allows you to specify any string up to 32 bytes which may be retrieved +on the server side using `V$SESSION` view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + +#### ora_dbh_share + +Requires at least Perl 5.8.0 compiled with ithreads. + +Allows you to share +database connections between threads. The first connect will make the +connection, all following calls to connect with the same ora_dbh_share +attribute will use the same database connection. The value must be a +reference to a already shared scalar which is initialized to an empty +string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + +#### ora_envhp + +The first time a connection is made a new OCI 'environment' is +created by DBD::Oracle and stored in the driver handle. +Subsequent connects reuse (share) that same OCI environment +by default. + +The ora_envhp attribute can be used to disable the reuse of the OCI +environment from a previous connect. If the value is `0` then +a new OCI environment is allocated and used for this connection. + +The OCI environment holds information about the client side context, +such as the local NLS environment. By altering `%ENV` and setting +ora_envhp to 0 you can create connections with different NLS +settings. This is most useful for testing. + +#### ora_charset, ora_ncharset + +For oracle versions >= 9.2 you can specify the client charset and +ncharset with the ora_charset and ora_ncharset attributes. You +still need to pass `ora_envhp = 0` for all but the first connect. + +These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + +#### ora_verbose + +Use this value to enable DBD::Oracle only tracing. Simply either set +the ora_verbose attribute on the connect() method to the trace level +you desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + +or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + +In both cases the DBD::Oracle trace level is set to 6, which is the highest +level tracing most of the calls to OCI. + +#### ora_oci_success_warn + +Use this value to print otherwise silent OCI warnings that may happen +when an execute or fetch returns "Success With Info" or when you want +to tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + +#### ora_objects + +Use this value to enable extended embedded oracle objects mode. In extended: + +- 1 + +Embedded objects are returned as instance (including type-name etc.) instead of simple ARRAY. + +- 2 + +Determine object type for each instance. All object attributes are returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + +#### ora_ph_type + +The default placeholder datatype for the database session. +The `TYPE` or [ora_type](#pod_ora_type) attributes to L and +L override the datatype for individual placeholders. +The most frequent reason for using this attribute is to permit trailing spaces +in values passed by placeholders. + +Constants for the values allowed for this attribute can be imported using + + use DBD::Oracle qw(:ora_types); + +Only the following values are permitted for this attribute. + +- ORA_VARCHAR2 + +Oracle clients using OCI 8 will strip trailing spaces and allow embedded \0 bytes. +Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \0 bytes. +This is the normal default placeholder type. + +- ORA_STRING + +Do not strip trailing spaces and end the string at the first \0. + +- ORA_CHAR + +Do not strip trailing spaces and allow embedded \0. +Force 'blank-padded comparison semantics'. + +For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + +Will pad bloggs out to 8 characters and return the username. + +#### ora_parse_error_offset + +If the previous error was from a failed `prepare` due to a syntax error, +this attribute gives the offset into the `Statement` attribute where the +error was found. + +#### ora_array_chunk_size + +Due to OCI limitations, DBD::Oracle needs to buffer up rows of +bind values in its `execute_for_fetch` implementation. This attribute +sets the number of rows to buffer at a time (default value is 1000). + +The `execute_for_fetch` function will collect (at most) this many +rows in an array, send them off to the DB for execution, then go back +to collect the next chunk of rows and so on. This attribute can be +used to limit or extend the number of rows processed at a time. + +Note that this attribute also applies to `execute_array`, since that +method is implemented using `execute_for_fetch`. + +#### ora_connect_with_default_signals + +Sometimes the Oracle client seems to change some of the signal +handlers of the process during the connect phase. For instance, some +users have observed Perl's default `$SIG{INT}` handler being ignored +after connecting to an Oracle database. If this causes problems in +your application, set this attribute to an array reference of signals +you would like to be localized during the connect process. Once the +connect is complete, the signal handlers should be returned to their +previous state. + +For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + +NOTE disabling the signal handlers the OCI library sets up may affect +functionality in the OCI library. + +NOTE If you are using connect_cached then the above example will lead +to DBI thinking each connection is different as an anonymous array reference +is being used. To avoid this when using connect_cached you are advised +to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + +In more recent Perl versions you could possibly make use of new state +variables. + +## __connect_cached__ + +Implemented by DBI, no driver-specific impact. +Please note that connect_cached as not been tested with DRCP. + +## __data_sources__ + + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + +Returns a list of available databases. You will have to set either the 'ORACLE_HOME' or +'TNS_ADMIN' environment value to retrieve this list. It will read these values from +TNSNAMES.ORA file entries. + +# METHODS COMMON TO ALL HANDLES + +For all of the methods below, __$h__ can be either a database handle (__$dbh__) +or a statement handle (__$sth__). Note that _$dbh_ and _$sth_ can be replaced with +any variable name you choose: these are just the names most often used. Another +common variable used in this documentation is $_rv_, which stands for "return value". + +## __err__ + + $rv = $h->err; + +Returns the error code from the last method called. + +## __errstr__ + + $str = $h->errstr; + +Returns the last error that was reported by Oracle. Starting with "ORA-00000" code followed by the error message. + +## __state__ + + $str = $h->state; + +Oracle hasn't supported SQLSTATE since the early versions OCI. It will return empty when the command succeeds and +'S1000' (General Error) for all other errors. + +While this method can be called as either `$sth->state` or `$dbh->state`, it +is usually clearer to always use `$dbh->state`. + +## __trace__ + +Implemented by DBI, no driver-specific impact. + +## __trace_msg__ + +Implemented by DBI, no driver-specific impact. + +## __parse_trace_flag__ and __parse_trace_flags__ + +Implemented by DBI, no driver-specific impact. + +## __func__ + +DBD::Oracle uses the `func` method to support a variety of functions. + +## __Private database handle functions__ + +Some of these functions are called through the method func() +which is described in the DBI documentation. Any function that begins with ora_ +can be called directly. + +## __plsql_errstr__ + +This function returns a string which describes the errors +from the most recent PL/SQL function, procedure, package, +or package body compile in a format similar to the output +of the SQL*Plus command 'show errors'. + +The function returns undef if the error string could not +be retrieved due to a database error. +Look in $dbh->errstr for the cause of the failure. + +If there are no compile errors, an empty string is returned. + +Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + +## __dbms_output_enable / dbms_output_put / dbms_output_get__ + +These functions use the PL/SQL DBMS_OUTPUT package to store and +retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer +by dbms_output_put or any PL/SQL block can be retrieved by +dbms_output_get or any PL/SQL block connected to the same database +session. + +Stored text is not available until after dbms_output_put or the PL/SQL +block that saved it completes its execution. This means you __CAN NOT__ +use these functions to monitor long running PL/SQL procedures. + +Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + +Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + +## __dbms_output_enable ( [ buffer_size ] )__ + +This function calls DBMS_OUTPUT.ENABLE to enable calls to package +DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to +these procedures are ignored unless DBMS_OUTPUT.ENABLE is called +first. + +The buffer_size is the maximum amount of text that can be saved in the +buffer and must be between 2000 and 1,000,000. If buffer_size is not +given, the default is 20,000 bytes. + +## __dbms_output_put ( [ @lines ] )__ + +This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + +If all lines were saved successfully the function returns 1. Depending +on the context, an empty list or undef is returned for failure. + +If any line causes buffer_size to be exceeded, a buffer overflow error +is raised and the function call fails. Some of the text might be in +the buffer. + +## __dbms_output_get__ + +This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from +the buffer. + +In an array context, all complete lines are removed from the buffer and +returned as a list. If there are no complete lines, an empty list is +returned. + +In a scalar context, the first complete line is removed from the buffer +and returned. If there are no complete lines, undef is returned. + +Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or +DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, +DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + +## __reauthenticate ( $username, $password )__ + +Starts a new session against the current database using the credentials +supplied. + +## __private_attribute_info__ + + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + +Returns a hash of all private attributes used by DBD::Oracle, for either +a database or a statement handle. Currently, all the hash values are undef. + +# ATTRIBUTES COMMON TO ALL HANDLES + +## __InactiveDestroy__ (boolean) + +Implemented by DBI, no driver-specific impact. + +## __RaiseError__ (boolean, inherited) + +Forces errors to always raise an exception. Although it defaults to off, it is recommended that this +be turned on, as the alternative is to check the return value of every method (prepare, execute, fetch, etc.) +manually, which is easy to forget to do. + +## __PrintError__ (boolean, inherited) + +Forces database errors to also generate warnings, which can then be filtered with methods such as +locally redefining _$SIG{__WARN__}_ or using modules such as `CGI::Carp`. This attribute is on +by default. + +## __ShowErrorStatement__ (boolean, inherited) + +Appends information about the current statement to error messages. If placeholder information +is available, adds that as well. Defaults to true. + +## __Warn__ (boolean, inherited) + +Enables warnings. This is on by default, and should only be turned off in a local block +for a short a time only when absolutely needed. + +## __Executed__ (boolean, read-only) + +Indicates if a handle has been executed. For database handles, this value is true after the [do](#pod_do) method has been called, or +when one of the child statement handles has issued an [execute](#pod_execute). Issuing a [commit](#pod_commit) or [rollback](#pod_rollback) always resets the +attribute to false for database handles. For statement handles, any call to [execute](#pod_execute) or its variants will flip the value to +true for the lifetime of the statement handle. + +## __TraceLevel__ (integer, inherited) + +Sets the trace level, similar to the [trace](#pod_trace) method. See the sections on +[trace](#pod_trace) and [parse_trace_flag](#pod_parse_trace_flag) for more details. + +## __Active__ (boolean, read-only) + +Indicates if a handle is active or not. For database handles, this indicates if the database has +been disconnected or not. For statement handles, it indicates if all the data has been fetched yet +or not. Use of this attribute is not encouraged. + +## __Kids__ (integer, read-only) + +Returns the number of child processes created for each handle type. For a driver handle, indicates the number +of database handles created. For a database handle, indicates the number of statement handles created. For +statement handles, it always returns zero, because statement handles do not create kids. + +## __ActiveKids__ (integer, read-only) + +Same as `Kids`, but only returns those that are active. + +## __CachedKids__ (hash ref) + +Returns a hashref of handles. If called on a database handle, returns all statement handles created by use of the +`prepare_cached` method. If called on a driver handle, returns all database handles created by the [connect_cached](#pod_connect_cached) +method. + +## __ChildHandles__ (array ref) + +Implemented by DBI, no driver-specific impact. + +## __PrintWarn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleError__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleSetErr__ (code ref, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ErrCount__ (unsigned integer) + +Implemented by DBI, no driver-specific impact. + +## __FetchHashKeyName__ (string, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ChopBlanks__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Taint__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintIn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintOut__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Profile__ (inherited) + +Implemented by DBI, no driver-specific impact. + +## __Type__ (scalar) + +Returns `dr` for a driver handle, `db` for a database handle, and `st` for a statement handle. +Should be rarely needed. + +## __LongReadLen__ + +Implemented by DBI, no driver-specific impact. + +## __LongTruncOk__ + +Implemented by DBI, no driver-specific impact. + +## __CompatMode__ + +Type: boolean, inherited + +The CompatMode attribute is used by emulation layers (such as Oraperl) to enable compatible behaviour in the underlying driver (e.g., DBD::Oracle) for this handle. Not normally set by application code. + +It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. + +# ORACLE-SPECIFIC DATABASE HANDLE METHODS + +## __ora_can_unicode ( [ $refresh ] )__ + +Returns a number indicating whether either of the database character sets +is a Unicode encoding. Calls ora_nls_parameters() and passes the optional +$refresh parameter to it. + +0 = Neither character set is a Unicode encoding. + +1 = National character set is a Unicode encoding. + +2 = Database character set is a Unicode encoding. + +3 = Both character sets are Unicode encodings. + +## __ora_can_taf__ + +Returns true if the current connection supports TAF events. False if otherise. + +## __ora_nls_parameters ( [ $refresh ] )__ + +Returns a hash reference containing the current NLS parameters, as given +by the v$nls_parameters view. The values fetched are cached between calls. +To cause the latest values to be fetched, pass a true value to the function. + +# DATABASE HANDLE METHODS + +## __selectall_arrayref__ + + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectall_hashref__ + + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + +Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectcol_arrayref__ + + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the first column +from each rows returned by preparing and executing the SQL string. It is possible to specify exactly +which columns to return. See the DBI documentation for full details. + +## __prepare__ + + $sth = $dbh->prepare($statement, \%attr); + +Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. + +### __Prepare Attributes__ + +These attributes may be used in the `\%attr` parameter of the +L database handle method. + +- ora_placeholders + +Set to false to disable processing of placeholders. Used mainly for loading a +PL/SQL package that has been _wrapped_ with Oracle's `wrap` utility. + +- ora_auto_lob + +If true (the default), fetching retrieves the contents of the CLOB or +BLOB column in most circumstances. If false, fetching retrieves the +Oracle "LOB Locator" of the CLOB or BLOB value. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for more details. + +See also the LOB tests in 05dbi.t of Oracle::OCI for examples +of how to use LOB Locators. + +- ora_pers_lob + +If true the [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) method for the [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) will be +used for LOBs rather than the default method [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators). + +- ora_clbk_lob + +If true the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) method for the L will be used for LOBs. + +- ora_piece_lob + +If true the [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) method for the L will be used for LOBs. + +- ora_piece_size + +This is the max piece size for the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) +and [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) methods, in chars for CLOBS, and +bytes for BLOBS. + +- ora_check_sql + +If 1 (default), force SELECT statements to be described in prepare(). +If 0, allow SELECT statements to defer describe until execute(). + +See [Prepare Postponed Till Execute](#pod_Prepare Postponed Till Execute) for more information. + +- ora_exe_mode + +This will set the execute mode of the current statement. Presently +only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + +See [Scrollable Cursors](#pod_Scrollable Cursors) for more details. + +- ora_prefetch_rows + +Sets the number of rows to be prefetched. If it is not set, then the +default value is 1. See [Row Prefetching](#pod_Row Prefetching) for more details. + +- ora_prefetch_memory + +Sets the memory level for rows to be prefetched. The application then +fetches as many rows as will fit into that much memory. See L for more details. + +- ora_row_cache_off + +By default DBD::Oracle will use a row cache when fetching to cut down +the number of round trips to the server. If you do not want to use an +array fetch set this value to any value other than 0; + +See [Row Prefetching](#pod_Row Prefetching) for more details. + +### __Placeholders__ + +There are two types of placeholders that can be used in DBD::Oracle. The first is +the "question mark" type, in which each placeholder is represented by a single +question mark character. This is the method recommended by the DBI specs and is the most +portable. Each question mark is internally replaced by a "dollar sign number" in the order +in which they appear in the query (important when using [bind_param](#pod_bind_param)). + +The other placeholder type is "named parameters" in the format ":foo" which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + +The different types of placeholders cannot be mixed within a statement, but you may +use different ones for each statement handle you have. This is confusing at best, so +stick to one style within your program. + +## __prepare_cached__ + + $sth = $dbh->prepare_cached($statement, \%attr); + +Implemented by DBI, no driver-specific impact. This method is most useful +if the same query is used over and over as it will cut down round trips to the server. + +## __do__ + + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + +Prepare and execute a single statement. Returns the number of rows affected if the +query was successful, returns undef if an error occurred, and returns -1 if the +number of rows is unknown or not available. Note that this method will return __0E0__ instead +of 0 for 'no rows were affected', in order to always return a true value if no error occurred. + +## __last_insert_id__ + +Oracle does not implement auto_increment of serial type columns it uses predefined +sequences where the id numbers are either selected before insert, at insert time with a trigger, + or as part of the query. + +Below is an example of you to use the latter with the SQL returning clause to get the ID number back +on insert with the bind_param_inout method. +. + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + +## __commit__ + + $rv = $dbh->commit; + +Issues a COMMIT to the server, indicating that the current transaction is finished and that +all changes made will be visible to other processes. If AutoCommit is enabled, then +a warning is given and no COMMIT is issued. Returns true on success, false on error. + +## __rollback__ + + $rv = $dbh->rollback; + +Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit +is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and +false on error. + +## __begin_work__ + +This method turns on transactions until the next call to [commit](#pod_commit) or [rollback](#pod_rollback), if [AutoCommit](#pod_AutoCommit) is +currently enabled. If it is not enabled, calling begin_work will issue an error. Note that the +transaction will not actually begin until the first statement after begin_work is called. + +## __disconnect__ + + $rv = $dbh->disconnect; + +Disconnects from the Oracle database. Any uncommitted changes will be rolled back upon disconnection. It's +good policy to always explicitly call commit or rollback at some point before disconnecting, rather than +relying on the default rollback behavior. + +If the script exits before disconnect is called (or, more precisely, if the database handle is no longer +referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() +methods automatically. It is best to explicitly disconnect rather than rely on this behavior. + +## __ping__ + + $rv = $dbh->ping; + +This `ping` method is used to check the validity of a database handle. The value returned is +either 0, indicating that the connection is no longer valid, or 1, indicating the connection is valid. +This function does 1 round trip to the Oracle Server. + +## __get_info()__ + + $value = $dbh->get_info($info_type); + +DBD::Oracle supports `get_info()`, but (currently) only a few info types. + +## __table_info()__ + +DBD::Oracle supports attributes for `table_info()`. + +In Oracle, the concept of _user_ and _schema_ is (currently) the +same. Because database objects are owned by an user, the owner names +in the data dictionary views correspond to schema names. +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. + +Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + +TABLE_TYPE may contain a comma-separated list of table types. +The following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + +The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + +The special enumerations of catalogues, schemas and table types are +supported. However, TABLE_CAT is always NULL. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +`table_info()` performs a case-sensitive search. So, a selection +criterion should respect upper and lower case. +Normally, an identifier is case-insensitive. Oracle stores and +returns it in upper case. Sometimes, database objects are created +with quoted identifiers (for reserved words, mixed case, special +characters, ...). Such an identifier is case-sensitive (if not all +upper case). Oracle stores and returns it as given. +`table_info()` has no special quote handling, neither adds nor +removes quotes. + +## __primary_key_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary key constraint was created without an identifier, +PK_NAME contains a system generated name with the form SYS_Cn. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __foreign_key_info()__ + +This method (currently) supports the extended behaviour of SQL/CLI, i.e. the +result set contains foreign keys that refer to primary __and__ alternate keys. +The field UNIQUE_OR_PRIMARY distinguishes these keys. + +Oracle does not support catalogues, so `$pk_catalog` and `$fk_catalog` are +ignored as selection criteria (in the new style interface). +The UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always +NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary or foreign key constraints were created without an identifier, +UK_NAME or FK_NAME contains a system generated name with the form SYS_Cn. + +The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle (currently) +does not support other actions. + +The DELETE_RULE field may contain wrong values. This is a known Bug (#1271663) +in Oracle's data dictionary views. Currently (as of 8.1.7), 'RESTRICT' and +'SET DEFAULT' are not supported, 'CASCADE' is mapped correctly and all other +actions (incl. 'SET NULL') appear as 'NO ACTION'. + +The DEFERABILITY field is always NULL, because this columns is +not present in the ALL_CONSTRAINTS view of older Oracle releases. + +The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, +FK_TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __column_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + +Don't rely on the values of the BUFFER_LENGTH field! +Especially the length of FLOATs may be wrong. + +Datatype codes for non-standard types are subject to change. + +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +It is possible with Oracle to make the names of the various DB objects (table,column,index etc) +case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + +So in the example the exact case "Bla_BLA" must be used to get it info on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + +any case can be used to get info on the column. + +## __selectrow_array__ + + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + +Returns an array of row information after preparing and executing the provided SQL string. The rows are returned +by calling [fetchrow_array](#pod_fetchrow_array). The string can also be a statement handle generated by a previous prepare. Note that +only the first row of data is returned. If called in a scalar context, only the first column of the first row is +returned. Because this is not portable, it is not recommended that you use this method in that way. + +## __selectrow_arrayref__ + + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an array, by internal use of +the [fetchrow_arrayref](#pod_fetchrow_arrayref) method. + +## __selectrow_hashref__ + + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an hash, by internal use of +the [fetchrow_hashref](#pod_fetchrow_hashref) method. + +## __clone__ + + $other_dbh = $dbh->clone(); + +Creates a copy of the database handle by connecting with the same parameters as the original +handle, then trying to merge the attributes. See the DBI documentation for complete usage. + +# DATABASE HANDLE ATTRIBUTES + +## __AutoCommit__ (boolean) + +Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change +in the future, so it is highly recommended that you explicitly set it when +calling [connect](#pod_connect). + +## __ReadOnly__ (boolean) + + $dbh->{ReadOnly} = 1; + +Specifies if the current database connection should be in read-only mode or not. + +Please not that this method is not foolproof: there are still ways to update the +database. Consider this a safety net to catch applications that should not be +issuing commands such as INSERT, UPDATE, or DELETE. + +This method method requires DBI version 1.55 or better. + +## __Name__ (string, read-only) + +Returns the name of the current database. This is the same as the DSN, without the +"dbi:Oracle:" part. + +## __Username__ (string, read-only) + +Returns the name of the user connected to the database. + +## __Driver__ (handle, read-only) + +Holds the handle of the parent driver. The only recommended use for this is to find the name +of the driver using: + + $dbh->{Driver}->{Name} + +## __RowCacheSize__ + +DBD::Oracle supports both Server pre-fetch and Client side row caching. By default both +are turned on to give optimum performance. Most of the time one can just let DBD::Oracle +figure out the best optimization. + +### __Row Caching__ + +Row caching occurs on the client side and the object of it is to cut down the number of round +trips made to the server when fetching rows. At each fetch a set number of rows will be retrieved +from the server and stored locally. Further calls the server are made only when the end of the +local buffer(cache) is reached. + +Rows up to the specified top level row +count `RowCacheSize` are fetched if it occupies no more than the specified memory usage limit. +The default value is 0, which means that memory size is not included in computing the number of rows to prefetch. If +the `RowCacheSize` value is set to a negative number then the positive value of RowCacheSize is used +to compute the number of rows to prefetch. + +By default `RowCacheSize` is automatically set. If you want to totally turn off prefetching set this to 1. + +For any SQL statement that contains a LOB, Long or Object Type Row Caching will be turned off. However server side +caching still works. If you are only selecting a LOB Locator then Row Caching will still work. + +### Row Prefetching + +Row prefetching occurs on the server side and uses the DBI database handle attribute `RowCacheSize` and or the +Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improved performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. + +The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first +fetch that sets the current_positon to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are +loaded into the buffer and DBD::Oracle will not have to go back to the server for more rows. When record 11 is fetched DBD::Oracle +fetches and returns this row and the next 9 rows are loaded into the buffer. In this case if you fetch backwards from 10 to 1 +no server round trips are made. + +With large record sets it is best not to attempt to go to the last record as this may take some time, A large buffer size might even slow down +the fetch. If you must get the number of rows in a large record set you might try using an few large OCI_FETCH_ABSOLUTEs and then an OCI_FETCH_LAST, +this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. +If one requires only the first few rows there is no need to set a large prefetch value. + +If the ora_prefetch_memory less than 1 or not present then memory size is not included in computing the +number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it +is not included in the computing of the prefetch rows. + +# ORACLE-SPECIFIC STATEMENT HANDLE METHODS + +## __ora_stmt_type__ + +Returns the OCI Statement Type number for the SQL of a statement handle. + +## __ora_stmt_type_name__ + +Returns the OCI Statement Type name for the SQL of a statement handle. + +# DBI STATEMENT HANDLE OBJECT METHODS + +## __bind_param__ + + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + +Allows the user to bind a value and/or a data type to a placeholder. + +The value of `$param_num` is a number if using the '?' or if using ":foo" style placeholders, the complete name +(e.g. ":foo") must be given. +The `$bind_value` argument is fairly self-explanatory. A value of `undef` will +bind a `NULL` to the placeholder. Using `undef` is useful when you want +to change just the type and will be overwriting the value later. +(Any value is actually usable, but `undef` is easy and efficient). + +The `\%attr` hash is used to indicate the data type of the placeholder. +The default value is "varchar". If you need something else, you must +use one of the values provided by DBI or by DBD::Pg. To use a SQL value, +modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + +This will import some constants into your script. You can plug those +directly into the [bind_param](#pod_bind_param) call. Some common ones that you will +encounter are: + + SQL_INTEGER + +To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + +You can then set the data types by setting the value of the `ora_type` +key in the hash passed to [bind_param](#pod_bind_param). +The current list of Oracle data types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +Data types are "sticky," in that once a data type is set to a certain placeholder, +it will remain for that placeholder, unless it is explicitly set to something +else afterwards. If the statement has already been prepared, and you switch the +data type to something else, DBD::Oracle will re-prepare the statement for you before +doing the next execute. + +Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + +These attributes may be used in the `\%attr` parameter of the +L or L statement handle methods. + +- ora_type + +Specify the placeholder's datatype using an Oracle datatype. +A fatal error is raised if `ora_type` and the DBI `TYPE` attribute +are used for the same placeholder. +Some of these types are not supported by the current version of +DBD::Oracle and will cause a fatal error if used. +Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + +Potentially useful values when DBD::Oracle was built using OCI 7 and later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + +Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + +Additional values when DBD::Oracle was built using OCI 9.2 and later: + + SQLT_CHR, SQLT_BIN + +See [Binding Cursors](#pod_Binding Cursors) for the correct way to use ORA_RSET. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for how to use ORA_CLOB and ORA_BLOB. + +See [SYS.DBMS_SQL datatypes](#pod_SYS.DBMS_SQL datatypes) for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. + +See [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) for the correct way to use SQLT_CHR and SQLT_BIN. + +See [Other Data Types](#pod_Other Data Types) for more information. + +See also L. + +- ora_csform + +Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values +are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can +be imported from the DBD::Oracle module. Rarely needed. + +- ora_csid + +Specify the _integer_ OCI_ATTR_CHARSET_ID for the bind value. +Character set names can't be used currently. + +- ora_maxdata_size + +Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. +May be needed if a character set conversion from client to server +causes the data to use more space and so fail with a truncation error. + +- ora_maxarray_numentries + +Specify the maximum number of array entries to allocate. Used with +ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of +array entries Oracle can pass back to you in OUT variable of type +TABLE OF ... . + +- ora_internal_type + +Specify internal data representation. Currently is supported only for +ORA_NUMBER_TABLE. + +### Optimizing Results + +#### Prepare Postponed Till Execute + +The DBD::Oracle module can avoid an explicit 'describe' operation +prior to the execution of the statement unless the application requests +information about the results (such as $sth->{NAME}). This reduces +communication with the server and increases performance (reducing the +number of PARSE_CALLS inside the server). + +However, it also means that SQL errors are not detected until +`execute()` (or $sth->{NAME} etc) is called instead of when +`prepare()` is called. Note that if the describe is triggered by the +use of $sth->{NAME} or a similar attribute and the describe fails then +_an exception is thrown_ even if `RaiseError` is false! + +Set [ora_check_sql](#pod_ora_check_sql) to 0 in prepare() to enable this behaviour. + +## __bind_param_inout__ + + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + +DBD::Oracle fully supports bind_param_inout below are some uses for this method. + +### __Returning A Value from an INSERT__ + +Oracle supports an extended SQL insert syntax which will return one +or more of the values inserted. This can be particularly useful for +single-pass insertion of values with re-used sequence values +(avoiding a separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + +If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + +If you have many rows to insert you can take advantage of Oracle's built in execute array feature +with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + +Which will return all the ids into @out_values. + +- __Note:__ + +- This will only work for numbered (?) placeholders, + +- The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle + +- The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + +### Returning A Recordset + +DBD::Oracle does not currently support binding a PL/SQL table (aka array) +as an IN OUT parameter to any Perl data structure. You cannot therefore call +a PL/SQL function or procedure from DBI that uses a non-atomic datatype as +either a parameter, or a return value. However, if you are using Oracle 9.0.1 +or later, you can make use of table (or pipelined) functions. + +For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + +Currently, there is no way to directly call the function +Array_Example.Array_Func from DBI. However, by making the following relatively +painless additions, its not only possible, but extremely efficient. + +First, you need to create database object types that correspond to the record +and table types in the package. From the above example, these would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + +Now, assuming the existing function needs to remain unchanged (it is probably +being called from other PL/SQL code), we need to add a new function to the +package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + +As you can see, the new function is very simple. Now, it is a simple matter +of calling the function as a straight-forward SELECT from your DBI code. From +the above example, the code would look something like this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + +### __SYS.DBMS_SQL datatypes__ + +DBD::Oracle has built-in support for __SYS.DBMS_SQL.VARCHAR2_TABLE__ +and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +- __Note:__ + +- Take careful note that we use '\\@arr' here because the 'bind_param_inout' + will only take a reference to a scalar. + +### __ORA_VARCHAR2_TABLE__ + +SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. +( in bind_param() and bind_param_inout() ). When you bind array, you need +to specify full buffer size for OUT data. So, there are two parameters: +_max_len_ (specified as 3rd argument of bind_param_inout() ), +and _ora_maxarray_numentries_. They define maximum array entry length and +maximum rows, that can be passed to Oracle and back to you. In this +example we send array with 1 element with length=3, but allocate space for 100 +Oracle array entries with maximum length 10 of each. So, you can get no more +than 100 array entries with length <= 10. + +If you set _max_len_ to zero, maximum array entry length is calculated +as maximum length of entry of array bound. If 0 < _max_len_ < length( $some_element ), +truncation occur. + +If you set _ora_maxarray_numentries_ to zero, current (at bind time) bound +array length is used as maximum. If 0 < _ora_maxarray_numentries_ < scalar(@array), +not all array entries are bound. + +### __ORA_NUMBER_TABLE__ + +SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. +The main difference is internal data representation. Currently 2 types of +bind is allowed : as C-integer, or as C-double type. To select one of them, +you may specify additional bind parameter _ora_internal_type_ as either +__SQLT_INT__ or __SQLT_FLT__ for C-integer and C-double types. +Integer size is architecture-specific and is usually 32 or 64 bit. +Double is standard IEEE 754 type. + +_ora_internal_type_ defaults to double (SQLT_FLT). + +_max_len_ is ignored for OCI_NUMBER_TABLE. + +Currently, you cannot bind full native Oracle NUMBER(38). If you really need, +send request to dbi-dev list. + +The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + +If you change bind type to __SQLT_INT__, like: + + ora_internal_type => SQLT_INT + +you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + +## __bind_param_inout_array__ + +DBD::Oracle supports this undocumented feature of DBI. See [Returning A Value from an INSERT](#pod_Returning A Value from an INSERT) for an example. + +## __bind_param_array__ + + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + +Binds an array of values to a placeholder, so that each is used in turn by a call +to the [execute_array](#pod_execute_array) method. + +## __execute__ + + $rv = $sth->execute(@bind_values); + +Perform whatever processing is necessary to execute the prepared statement. + +## __execute_array__ + + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + +Execute a prepared statement once for each item in a passed-in hashref, or items that +were previously bound via the [bind_param_array](#pod_bind_param_array) method. See the DBI documentation +for more details. + +DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very +quickly. + +## __execute_for_fetch__ + + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + +Used internally by the [execute_array](#pod_execute_array) method, and rarely used directly. See the +DBI documentation for more details. + +## __fetchrow_arrayref__ + + $ary_ref = $sth->fetchrow_arrayref; + +Fetches the next row of data from the statement handle, and returns a reference to an array +holding the column values. Any columns that are NULL are returned as undef within the array. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +Note that the same array reference is returned for each fetch, so don't store the reference and +then use it after a later fetch. Also, the elements of the array are also reused for each row, +so take care if you want to take a reference to an element. See also [bind_columns](#pod_bind_columns). + +## __fetchrow_array__ + + @ary = $sth->fetchrow_array; + +Similar to the [fetchrow_arrayref](#pod_fetchrow_arrayref) method, but returns a list of column information rather than +a reference to a list. Do not use this in a scalar context. + +## __fetchrow_hashref__ + + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + +Fetches the next row of data and returns a hashref containing the name of the columns as the keys +and the data itself as the values. Any NULL value is returned as as undef value. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +The optional `$name` argument should be either `NAME`, `NAME_lc` or `NAME_uc`, and indicates +what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. + +## __fetchall_arrayref__ + + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + +Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the +statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, +the data read in so far will be returned. Because of this, you should always check `$sth->err` after +calling this method, unless [RaiseError](#pod_RaiseError) has been enabled. + +If `$slice` is an array reference, fetchall_arrayref uses the [fetchrow_arrayref](#pod_fetchrow_arrayref) method to fetch each +row as an array ref. If the `$slice` array is not empty then it is used as a slice to select individual +columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). + +With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. + +If `$slice` is a hash reference, fetchall_arrayref uses [fetchrow_hashref](#pod_fetchrow_hashref) to fetch each row as a hash reference. + +See the DBI documentation for a complete discussion. + +## __fetchall_hashref__ + + $hash_ref = $sth->fetchall_hashref( $key_field ); + +Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for +a full discussion. + +## __finish__ + + $rv = $sth->finish; + +Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed +when you have not fetched all the possible rows. + +## __rows__ + + $rv = $sth->rows; + +Returns the number of rows affected for updates, deletes and inserts and -1 for selects. + +## __bind_col__ + + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + +Binds a Perl variable and/or some attributes to an output column of a SELECT statement. +Column numbers count up from 1. You do not need to bind output columns in order to fetch data. + +NOTE: DBD::Oracle does not use the `$bind_type` to determine how to +bind the column; it uses what Oracle says the data type is. You can +however set a numeric bind type with the bind attributes +StrictlyTyped/DiscardString as these attributes are applied after the +column is retrieved. + +See the DBI documentation for a discussion of the optional parameters `\%attr` and `$bind_type` + +## __bind_columns__ + + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + +Calls the [bind_col](#pod_bind_col) method for each column in the SELECT statement, using the supplied list. + +## __dump_results__ + + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + +Fetches all the rows from the statement handle, calls `DBI::neat_list` for each row, and +prints the results to `$fh` (which defaults to `STDOUT`). Rows are separated by `$lsep` (which defaults +to a newline). Columns are separated by `$fsep` (which defaults to a comma). The `$maxlen` controls +how wide the output can be, and defaults to 35. + +This method is designed as a handy utility for prototyping and testing queries. Since it uses +"neat_list" to format and edit the string for reading by humans, it is not recommended +for data transfer applications. + +# STATEMENT HANDLE ATTRIBUTES + +## __NUM_OF_FIELDS__ (integer, read-only) + +Returns the number of columns returned by the current statement. A number will only be returned for +SELECT statements for INSERT, +UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NUM_OF_PARAMS__ (integer, read-only) + +Returns the number of placeholders in the current statement. + +## __NAME__ (arrayref, read-only) + +Returns an arrayref of column names for the current statement. This +method will only work for SELECT statements, for SHOW statements, and for +INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NAME_lc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to lower case. + +## __NAME_uc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to upper case. + +## __NAME_hash__ (hashref, read-only) + +Similar to the `NAME` attribute, but returns a hashref of column names instead of an arrayref. The names of the columns +are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. +This method returns undef if called before `execute()`. + +## __NAME_lc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __NAME_uc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __TYPE__ (arrayref, read-only) + +Returns an arrayref indicating the data type for each column in the statement. +This method returns undef if called before `execute()`. + +## __PRECISION__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. +The number indicates the precision for `NUMERIC` columns, the size in number of +characters for `CHAR` and `VARCHAR` columns, and for all other types of columns +it returns the number of _bytes_. +This method returns undef if called before `execute()`. + +## __SCALE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates the scale of the that column. The only type that will return a value is `NUMERIC`. +This method returns undef if called before `execute()`. + +## __NULLABLE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates if the column is nullable or not. 0 = not nullable, 1 = nullable, 2 = unknown. +This method returns undef if called before `execute()`. + +## __Database__ (dbh, read-only) + +Returns the database handle this statement handle was created from. + +## __ParamValues__ (hash ref, read-only) + +Returns a reference to a hash containing the values currently bound to placeholders. If the "named parameters" +type of placeholders are being used (such as ":foo"), then the keys of the hash will be the names of the +placeholders (without the colon). If the "dollar sign numbers" type of placeholders are being used, the keys of the hash will +be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, +starting at one and increasing for every placeholder. + +If this method is called before [execute](#pod_execute), the literal values passed in are returned. If called after +[execute](#pod_execute), then the quoted versions of the values are returned. + +## __ParamTypes__ (hash ref, read-only) + +Returns a reference to a hash containing the type names currently bound to placeholders. The keys +are the same as returned by the ParamValues method. The values are hashrefs containing a single key value +pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can +only be expressed by a Postgres type. The value is the internal number corresponding to the type originally +passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of +ParamTypes to be passed back to the [bind_param](#pod_bind_param) method. + +## __Statement__ (string, read-only) + +Returns the statement string passed to the most recent "prepare" method called in this database handle, even if that method +failed. This is especially useful where "RaiseError" is enabled and the exception handler checks $@ and sees that a `prepare` +method call failed. + +## __RowsInCache__ + +Returns the number of un-fetched rows in the cache for selects. + +# SCROLLABLE CURSORS + +Oracle supports the concept of a 'Scrollable Cursor' which is defined as a 'Result Set' where +the rows can be fetched either sequentially or non-sequentially. One can fetch rows forward, +backwards, from any given position or the n-th row from the current position in the result set. + +Rows are numbered sequentially starting at one and client-side caching of the partial or entire result set +can improve performance by limiting round trips to the server. + +Oracle does not support DML type operations with scrollable cursors so you are limited +to simple 'Select' operations only. As well you can not use this functionality with remote +mapped queries or if the LONG datatype is part of the select list. + +However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch methods. + +Only use scrollable cursors if you really have a good reason to. They do use up considerable +more server and client resources and have poorer response times than non-scrolling cursors. + +## Enabling Scrollable Cursors + +To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + +Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the +statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + +When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row +or you can still use any of the other fetch methods but with a poorer response time than if you used a +non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. + +## Scrollable Cursor Methods + +The following driver-specific methods are used with scrollable cursors. + +- ora_scroll_position + + $position = $sth->ora_scroll_position(); + +This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time +this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. +The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. + +- ora_fetch_scroll + + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + +Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset +value which will then determine the row that will be fetched. It returns the row as a list containing the field values. +Null fields are returned as _undef_ values in the list. + +The valid orientation constant and fetch offset values combination are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + +The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + +The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + +## Scrollable Cursor Usage + +Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + +and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll +method; + +- Fetching the Last Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +if the record set is large this could take some time. + +- Fetching the Current Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will still be 20 after this snippet. + +- Fetching the First Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the Next Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 5 after this snippet. + +- Fetching the Prior Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the 10th Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 10th to 14th Row + + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 14 after this snippet. + +- Fetching the 14th to 10th Row + + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 5th Row From the Present Position. + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 15 after this snippet. + +- Fetching the 9th Row Prior From the Present Position + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 6 after this snippet. + +- Use Finish + + $sth->finish(); + +When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of +cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. + +# LOBS AND LONGS + +The key to working with LOBs (CLOB, BLOBs) is to remember the value of an Oracle LOB column is not the content of the LOB. It's a +'LOB Locator' which, after being selected or inserted needs extra processing to read or write the content of the LOB. There are also legacy LONG types (LONG, LONG RAW, VARCHAR2) +which are presently deprecated by Oracle but are still in use. These LONG types do not utilize a 'LOB Locator' and also are more limited in +functionality than CLOB or BLOB fields. + +DBD::Oracle now offers three interfaces to LOB and LONG data, + +- [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) + +With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of +BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. + +- [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) + +With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. + +- [LOB Locator Method Interface](#pod_LOB Locator Method Interface) + +This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. + +Generally speaking the interface that you will chose will be dependent on what end you are trying to achieve. All have their benefits and +drawbacks. + +One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB column can be in one of three states; + +- NULL + +The table cell is created, but the cell holds no locator or value. +If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + +error when working with a LOB. + +You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + +- Empty + +A LOB instance with a locator exists in the cell, but it has no value. The length of the LOB is zero. In this case DBD::Oracle will return 'undef' for the field. + +- Populated + +A LOB instance with a locator and a value exists in the cell. You actually get the LOB value. + +## Data Interface for Persistent LOBs + +This is the original interface for LONG and LONG RAW datatypes and from Oracle 9iR1 and later the OCI API was extended to work directly with the other LOB datatypes. +In other words you can treat all LOB type data (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using the same techniques +you would use on other datatypes that store character or binary data. In some cases there are fewer round trips to the server as no 'LOB Locators' are +used, normally one can get an entire LOB is a single round trip. + +### Simple Fetch for LONGs and LONG RAWs + +As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG datatypes as a single large piece. +There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. +If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into +an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. + +For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the long1 fields but they will be truncated at 2MBs. + +### Using ora_ncs_buff_mtpl + +When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the +Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. +Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. + +However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer +value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes +but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes +(maybe less characters though) but you are using allot more memory that you need. + +You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can +also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. + +The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the +ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. + +If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + +This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) + +If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. + +This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. + +You can tune this value by setting ora_oci_success_warn which will display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + +In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. + +### Simple Fetch for CLOBs and BLOBs + +To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well +set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds +the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. + +For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this +and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. + +It seems with BLOBs you are not limited by the 64k. + +For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the lobs but they will be truncated at 2MBs. + +### Piecewise Fetch with Callback + +With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. +To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Simple Fetch for LONGs and LONG RAWs](#pod_Simple Fetch for LONGs and LONG RAWs) and [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is +dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. + +Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +#### Piecewise Fetch with Polling + +With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' +attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback). + +Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. + +Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +### Binding for Updates and Inserts for CLOBs and BLOBs + +To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method +'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + +So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. + +### Support for Remote LOBs; + +Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + +to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Below are the limitations of Remote LOBs; + +- Queries involving more than one database are not supported; + +so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + +as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + +- DDL commands are not supported; + +so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + +- Only binds and defines for data going into remote persistent LOBs are supported. + +so that parameter passing in PL/SQL where CHAR data is bound or defined for remote LOBs is not allowed . + +These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + +- If the remote object is a view such as + + CREATE VIEW v AS SELECT foo() FROM ... + +the following would not work: + + SELECT * FROM v@dbs2; + +- Limited PL/SQL parameter passing + +PL/SQL parameter passing is not allowed where the actual argument is a LOB type +and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. + +- RETURNING INTO does not support implicit conversions between CHAR and CLOB. + +so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + +## Locator Data Interface + +### Simple Usage + +When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob with the LongReadLen and LongTruncOk attributes. +The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +When inserting or updating LOBs some _major_ magic has to be performed +behind the scenes to make it transparent. Basically the driver has to +insert a 'LOB Locator' and then refetch the newly inserted LOB +Locator before being able to write the data into it. However, it works +well most of the time, and I've made it as fast as possible, just one +extra server-round-trip per insert or update after the first. For the +time being, only single-row LOB updates are supported. + +To insert or update a large LOB using a placeholder, DBD::Oracle has to +know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + +The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + +or use the corresponding integer values (112 and 113). + +One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has +to be able to tell which parameters relate to which table fields. +In all cases where it can possibly work it out for itself, it does, +however, if there are multiple LOB fields of the same type in the table +then you need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + +There are some limitations inherent in the way DBD::Oracle makes typical +LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + +The alternative is to disable the automatic LOB Locator processing. +If [ora_auto_lob](#pod_ora_auto_lob) is 0 in prepare(), you can fetch the LOB Locators and +do all the work yourself using the ora_lob_*() methods. +See the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) section below. + +### LOB support in PL/SQL + +LOB Locators can be passed to PL/SQL calls by binding them to placeholders +with the proper `ora_type`. If [ora_auto_lob](#pod_ora_auto_lob) is true, output LOB +parameters will be automatically returned as strings. + +If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), +strings can be bound to input LOB placeholders and will be automatically +converted to LOBs. + +Example: + # Build a large XML document, bind it as a CLOB, + # extract elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + +If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + +error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. +One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. + +## Persistent & Locator Interface Caveats + +Now that one has the option of using the Persistent or the Locator interface for LOBs the questions arises +which one to use. For starters, if you want to access LOBs over a dblink you will have to use the Persistent +interface so that choice is simple. The question of which one to use after that is a little more tricky. +It basically boils down to a choice between LOB size and speed. + +The Callback and Polling piecewise fetches are very very slow +when compared to the Simple and the Locator fetches but they can handle very large blocks of data. Given a situation where a +large LOB is to be read the Locator fetch may time out while either of the piecewise fetches may not. + +With the Simple fetch you are limited by physical memory of your server but it runs a little faster than the Locator, as there are fewer round trips +to the server. So if you have small LOBs and need to save a little bandwidth this is the one to use. It you are going after large LOBs then the Locator interface is the one to use. + +If you need to update more than a single row of with LOB data then the Persistent interface can do it while the Locator can't. + +If you encounter a situation where you have to access the legacy LOBs (LONG, LONG RAW) and the values are to large for you system then you can use +the Callback or Polling piecewise fetches to get all of the data. + +Not all of the Persistent interface has been implemented yet, the following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + +Most of the time you should just use the [Locator Data Interface](#pod_Locator Data Interface) as this is in one that has the best combination of speed and size. + +All this being said if you are doing some critical programming I would use the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) as this gives you very +fine grain control of your LOBs, of course the code for this will be somewhat more involved. + +## Data Interface for LOB Locators + +The following driver-specific methods let you manipulate "LOB Locators" directly. +To select a LOB locator directly set the if the `ora_auto_lob` +attribute to false, or alternatively they can be returned via PL/SQL procedure calls. + +(If using a DBI version earlier than 1.36 they must be called via the +func() method. Note that methods called via func() don't honour +RaiseError etc, and so it's important to check $dbh->err after each call. +It's recommended that you upgrade to DBI 1.38 or later.) + +Note that LOB locators are only valid while the statement handle that +created them is valid. When all references to the original statement +handle are lost, the handle is destroyed and the locators are freed. + +- ora_lob_read + + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + +Read a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobRead function. + +- ora_lob_write + + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + +Write/overwrite a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobWrite function. + +- ora_lob_append + + $rc = $dbh->ora_lob_append($lob_locator, $data); + +Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + +- ora_lob_trim + + $rc = $dbh->ora_lob_trim($lob_locator, $length); + +Trims the length of the LOB to $length. +Uses the Oracle OCILobTrim function. + +- ora_lob_length + + $length = $dbh->ora_lob_length($lob_locator); + +Returns the length of the LOB. +Uses the Oracle OCILobGetLength function. + +- ora_lob_is_init + + $is_init = $dbh->ora_lob_is_init($lob_locator); + +Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' +if there is an error. +Uses the Oracle OCILobLocatorIsInit function. + +- ora_lob_chunk_size + + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + +Returns the chunk size of the LOB. +Uses the Oracle OCILobGetChunkSize function. + +For optimal performance, Oracle recommends reading from and +writing to a LOB in batches using a multiple of the LOB chunk size. +In Oracle 10g and before, when all defaults are in place, this +chunk size defaults to 8k (8192). + +### LOB Locator Method Examples + +_Note:_ Make sure you first read the note in the section above about +multi-byte character set issues with these methods. + +The following examples demonstrate the usage of LOB Locators +to read, write, and append data, and to query the size of +large data. + +The following examples assume a table containing two large +object columns, one binary and one character, with a primary +key column, defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + +It also assumes a sequence for use in generating unique +lob_id field values, defined as follows: + + CREATE SEQUENCE lob_example_seq + +### Example: Inserting a new row with large data + +Unless enough memory is available to store and bind the +entire LOB data for insert all at once, the LOB columns must +be written interactively, piece by piece. In the case of a new row, +this is performed by first inserting a row, with empty values in +the LOB columns, then modifying the row by writing the large data +interactively to the LOB columns using their LOB locators as handles. + +The insert statement must create token values in the LOB +columns. Here, we use the empty string for both the binary +and character large object columns 'bindata' and 'chardata'. + +After the INSERT statement, a SELECT statement is used to +acquire LOB locators to the 'bindata' and 'chardata' fields +of the newly inserted row. Because these LOB locators are +subsequently written, they must be acquired from a select +statement containing the clause 'FOR UPDATE' (LOB locators +are only valid within the transaction that fetched them, so +can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + +In this example we demonstrate the use of ora_lob_write() +interactively to append data to the columns 'bin_data' and +'char_data'. Had we used ora_lob_append(), we could have +saved ourselves the trouble of keeping track of the offset +into the lobs. The snippet of code beneath the comment +'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + +The scalar variables $offset and $length are no longer +needed, because ora_lob_append() keeps track of the offset +for us. + +### Example: Updating an existing row with large data + +In this example, we demonstrate a technique for overwriting +a portion of a blob field with new binary data. The blob +data before and after the section overwritten remains +unchanged. Hence, this technique could be used for updating +fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + +After running this code, the row where lob_id = 5 will +contain, starting at position 100234 in the bin_data column, +the string "This string will overwrite a portion of the blob". + +### Example: Streaming character data from the database + +In this example, we demonstrate a technique for streaming +data from the database to a file handle, in this case +STDOUT. This allows more data to be read in and written out +than could be stored in memory at a given time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + +Notice that the select statement does not contain the phrase +"FOR UPDATE". Because we are only reading from the LOB +Locator returned, and not modifying the LOB it refers to, +the select statement does not require the "FOR UPDATE" +clause. + +A word of caution when using the data returned from an ora_lob_read in a conditional statement. +for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + +was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return +the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte +as $data will contain 0 which PERL will see as false and not print it out. + +### Example: Truncating existing large data + +In this example, we truncate the data already present in a +large object column in the database. Specifically, for each +row in the table, we truncate the 'bindata' value to half +its previous length. + +After acquiring a LOB Locator for the column, we query its +length, then we trim the length by half. Because we modify +the large objects with the call to ora_lob_trim(), we must +select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +# SPACES AND PADDING + +## Trailing Spaces + +Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder +values and uses Nonpadded Comparison Semantics with the result. +This causes trouble if the spaces are needed for +comparison with a CHAR value or to prevent the value from +becoming '' which Oracle treats as NULL. +Look for Blank-padded Comparison Semantics and Nonpadded +Comparison Semantics in Oracle's SQL Reference or Server +SQL Reference for more details. + +To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, +either change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or the placeholder +type for a particular call to L or L +with [ora_type](#pod_ora_type) or `TYPE`. +Using [ORA_CHAR](http://search.cpan.org/perldoc?ORA_CHAR) with [ora_type](http://search.cpan.org/perldoc?ora_type) or `SQL_CHAR` with `TYPE` +allows the placeholder to be used with Padded Comparison Semantics +if the value it is being compared to is a CHAR, NCHAR, or literal. + +Please remember that using spaces as a value or at the end of +a value makes visually distinguishing values with different +numbers of spaces difficult and should be avoided. + +Oracle Clients that use OCI 9.2 do not strip trailing spaces. + +## Padded Char Fields + +Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. +As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will +have to change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or placeholder +type for a particular call with L or L +with [ORA_CHAR](#pod_ORA_CHAR). + +# UNICODE + +DBD::Oracle now supports Unicode UTF-8. There are, however, a number +of issues you should be aware of, so please read all this section +carefully. + +In this section we'll discuss "Perl and Unicode", then "Oracle and +Unicode", and finally "DBD::Oracle and Unicode". + +Information about Unicode in general can be found at: +[http://www.unicode.org/](http://www.unicode.org/). It is well worth reading because there are +many misconceptions about Unicode and you may be holding some of them. + +## Perl and Unicode + +Perl began implementing Unicode with version 5.6, but the implementation +did not mature until version 5.8 and later. If you plan to use Unicode +you are _strongly_ urged to use Perl 5.8.2 or later and to _carefully_ read +the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + +And then read it again. + +Perl's internal Unicode format is UTF-8 +which corresponds to the Oracle character set called AL32UTF8. + +## Oracle and Unicode + +Oracle supports many characters sets, including several different forms +of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + +When you create an Oracle database, you must specify the DATABASE +character set (used for DDL, DML and CHAR datatypes) and the NATIONAL +character set (used for NCHAR and NCLOB types). +The character sets used in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + +The Oracle 9.2 and later default for the national character set is AL16UTF16. +The default for the database character set is often US7ASCII. +Although many experienced DBAs will consider an 8bit character set like +WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle +other than US7ASCII, requires that the NLS_LANG environment variable be set. +See the L<"Oracle UTF8 is not UTF-8"> section below. + +You are strongly urged to read the Oracle Internationalization documentation +specifically with respect the choices and trade offs for creating +a databases for use with international character sets. + +Oracle uses the NLS_LANG environment variable to indicate what +character set is being used on the client. When fetching data Oracle +will convert from whatever the database character set is to the client +character set specified by NLS_LANG. Similarly, when sending data to +the database Oracle will convert from the character set specified by +NLS_LANG to the database character set. + +The NLS_NCHAR environment variable can be used to define a different +character set for 'national' (NCHAR) character types. + +Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. +For example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + +## Oracle UTF8 is not UTF-8 + +AL32UTF8 should be used in preference to UTF8 if it works for you, +which it should for Oracle 9.2 or later. If you're using an old +version of Oracle that doesn't support AL32UTF8 then you should +avoid using any Unicode characters that require surrogates, in other +words characters beyond the Unicode BMP (Basic Multilingual Plane). + +That's because the character set that Oracle calls "UTF8" doesn't +conform to the UTF-8 standard in its handling of surrogate characters. +Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". +Here are a couple of extracts from [http://www.unicode.org/reports/tr26/](http://www.unicode.org/reports/tr26/): + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + +Oracle uses this internally because it collates (sorts) in the same order +as UTF16, which is the basis of Oracle's internal collation definitions. + +Rather than change UTF8 for clients Oracle chose to define a new character +set called "AL32UTF8" which does conform to the UTF-8 standard. +(The AL32UTF8 character set can't be used on the server because it +would break collation.) + +Because of that, for the rest of this document we'll use "AL32UTF8". +If you're using an Oracle version below 9.2 you'll need to use "UTF8" +until you upgrade. + +## DBD::Oracle and Unicode + +DBD::Oracle Unicode support has been implemented for Oracle versions 9 +or greater, and Perl version 5.6 or greater (though we _strongly_ +suggest that you use Perl 5.8.2 or later). + +You can check which Oracle version your DBD::Oracle was built with by +importing the `ORA_OCI` constant from DBD::Oracle. + +__Fetching Data__ + +Any data returned from Oracle to DBD::Oracle in the AL32UTF8 +character set will be marked as UTF-8 to ensure correct handling by Perl. + +For Oracle to return data in the AL32UTF8 character set the +NLS_LANG or NLS_NCHAR environment variable _must_ be set as described +in the previous section. + +When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR +is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + +When fetching other character data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + +__Sending Data using Placeholders__ + +Data bound to a placeholder is assumed to be in the default client +character set (specified by NLS_LANG) except for a few special +cases. These are listed here with the highest precedence first: + +If the `ora_csid` attribute is given to bind_param() then that +is passed to Oracle and takes precedence. + +If the value is a Perl Unicode string (UTF-8) then DBD::Oracle +ensures that Oracle uses the Unicode character set, regardless of +the NLS_LANG and NLS_NCHAR settings. + +If the placeholder is for inserting an NCLOB then the client NLS_NCHAR +character set is used. (That's useful but inconsistent with the other behaviour +so may change. Best to be explicit by using the `ora_csform` +attribute.) + +If the `ora_csform` attribute is given to bind_param() then that +determines if the value should be assumed to be in the default +(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + +or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + +Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to +insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert +will still happen but a error code of 0 will be returned with the following warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + +The warning will report the parameter number and the NCHAR setting that the query is running. + +__Sending Data using SQL__ + +Oracle assumes the SQL statement is in the default client character +set (as specified by NLS_LANG). So Unicode strings containing +non-ASCII characters should not be used unless the default client +character set is AL32UTF8. + +## DBD::Oracle and Other Character Sets and Encodings + +The only multi-byte Oracle character set supported by DBD::Oracle is +"AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +# OBJECT & COLLECTION DATA TYPES + +Oracle databases allow for the creation of object oriented like user-defined types. +There are two types of objects, Embedded--an object stored in a column of a regular table +and REF--an object that uses the REF retrieval mechanism. + +DBD::Oracle supports only the 'selection' of embedded objects of the following types OBJECT, VARRAY +and TABLE in any combination. Support is seamless and recursive, meaning you +need only supply a simple SQL statement to get all the values in an embedded object. +You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. + +Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + +The code to access all the data in the table could be something like this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + +Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. + +As stated before DBD::Oracle will automatically drill into the embedded object and extract +all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an +SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + +The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + +Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + +The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + +So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables +nested to 10 levels. + +Any NULL values found in the embedded object will be returned as 'undef'. + +# OTHER DATA TYPES + +DBD::Oracle does not _explicitly_ support most Oracle datatypes. +It simply asks Oracle to return them as strings and Oracle does so. +Mostly. Similarly when binding placeholder values DBD::Oracle binds +them as strings and Oracle converts them to the appropriate type, +such as DATE, when used. + +Some of these automatic conversions to and from strings use NLS +settings to control the formatting for output and the parsing for +input. The most common example is the DATE type. The default NLS +format for DATE might be DD-MON-YYYY and so when a DATE type is +fetched that's how Oracle will format the date. NLS settings also +control the default parsing of strings into DATE values. An error +will be generated if the contents of the string don't match the +NLS format. If you're dealing in dates which don't match the default +NLS format then you can either change the default NLS format or, more +commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") +to explicitly specify formats for converting to and from strings. + +A slightly more subtle problem can occur with NUMBER types. The +default NLS settings might format numbers with a fullstop ("`.`") +to separate thousands and a comma ("`,`") as the decimal point. +Perl will generate warnings and use incorrect values when numbers, +returned and formatted as strings in this way by Oracle, are used +in a numeric context. You could explicitly convert each numeric +value using the TO_CHAR(...) function but that gets tedious very +quickly. The best fix is to change the NLS settings. That can be +done for an individual connection by doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + +There are some types, like BOOLEAN, that Oracle does not automatically +convert to or from strings (pity). These need to be converted +explicitly using SQL or PL/SQL functions. + +Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + +#### Support for Insert of XMLType (ORA_XMLTYPE) + +Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special +requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For +example with a table like this; + + create table books (book_id number, book_xml XMLType); + +one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + +In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. +This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. + +#### Binding Cursors + +Cursors can be returned from PL/SQL blocks, either from stored +functions (or procedures with OUT parameters) or +from direct `OPEN` statements, as shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +The only special requirement is the use of `bind_param_inout()` with an +attribute hash parameter that specifies `ora_type` as `ORA_RSET`. +If you don't do that you'll get an error from the `execute()` like: +"ORA-06550: line X, column Y: PLS-00306: wrong number or types of +arguments in call to ...". + +Here's an alternative form using a function that returns a cursor. +This example uses the pre-defined weak (or generic) REF CURSOR type +SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +A cursor obtained from PL/SQL as above may be passed back to PL/SQL +by binding for input, as shown in this example, which explicitly +closes a cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + +It is not normally necessary to close a cursor +explicitly in this way. Oracle will close the cursor automatically +at the first client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to +the cursor handle from the PL/SQL statement handle delays the destruction +of the cursor handle for too long. This reference remains until the +PL/SQL handle is re-bound, re-executed or destroyed. + +See the `curref.pl` script in the Oracle.ex directory in the DBD::Oracle +source distribution for a complete working example. + +#### Fetching Nested Cursors + +Oracle supports the use of select list expressions of type REF CURSOR. +These may be explicit cursor expressions - `CURSOR(SELECT ...)`, or +calls to PL/SQL functions which return REF CURSOR values. The values +of these expressions are known as nested cursors. + +The value returned to a Perl program when a nested cursor is fetched +is a statement handle. This statement handle is ready to be fetched from. +It should not (indeed, must not) be executed. + +Oracle imposes a restriction on the order of fetching when nested +cursors are used. Suppose `$sth1` is a handle for a select statement +involving nested cursors, and `$sth2` is a nested cursor handle fetched +from `$sth1`. `$sth2` can only be fetched from while `$sth1` is +still active, and the row containing `$sth2` is still current in `$sth1`. +Any attempt to fetch another row from `$sth1` renders all nested cursor +handles previously fetched from `$sth1` defunct. + +Fetching from such a defunct handle results in an error with the message +`ERROR nested cursor is defunct (parent row is no longer current)`. + +This means that the `fetchall...` or `selectall...` methods are not useful +for queries returning nested cursors. By the time such a method returns, +all the nested cursor handles it has fetched will be defunct. + +It is necessary to use an explicit fetch loop, and to do all the +fetching of nested cursors within the loop, as the following example +shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + +The cursor returned by the function `sp_ListEmp` defined in the +previous section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + +#### Pre-fetching Nested Cursors + +By default, DBD::Oracle pre-fetches rows in order to reduce the number of +round trips to the server. For queries which do not involve nested cursors, +the number of pre-fetched rows is controlled by the DBI database handle +attribute `RowCacheSize` (q.v.). + +In Oracle, server side open cursors are a controlled resource, limited in +number, on a per session basis, to the value of the initialization +parameter `OPEN_CURSORS`. Nested cursors count towards this limit. +Each nested cursor in the current row counts 1, as does +each nested cursor in a pre-fetched row. Defunct nested cursors do not count. + +An Oracle specific database handle attribute, `ora_max_nested_cursors`, +further controls pre-fetching for queries involving nested cursors. For +each statement handle, the total number of nested cursors in pre-fetched +rows is limited to the value of this parameter. The default value +is 0, which disables pre-fetching for queries involving nested cursors. + +# PL/SQL Examples + +Most of these PL/SQL examples come from: Eric Bartley . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + +You can find more examples in the t/plsql.t file in the DBD::Oracle +source directory. + +Oracle 9.2 appears to have a bug where a variable bound +with bind_param_inout() that isn't assigned to by the executed +PL/SQL block may contain garbage. +See [http://www.mail-archive.com/dbi-users@perl.org/msg18835.html](http://www.mail-archive.com/dbi-users@perl.org/msg18835.html) + +## Avoid Using "SQL Call" + +Avoid using the "SQL Call" statement with DBD:Oracle as you might find that +DBD::Oracle will not raise an exception in some case. Specifically if you use +"SQL Call" to run a procedure all "No data found" exceptions will be quietly +ignored and returned as null. According to Oracle support this is part of the same +mechanism where; + + select (select * from dual where 0=1) from dual + +returns a null value rather than an exception. + +# CONTRIBUTING + +If you'd like DBD::Oracle to do something new or different the best way +to make that happen is to do it yourself and email to dbi-dev@perl.org a +patch of the source code (using 'diff' - see below) that shows the changes. + +## How to create a patch using Subversion + +The DBD::Oracle source code is maintained using Subversion (a replacement +for CVS, see [http://subversion.tigris.org/](http://subversion.tigris.org/)). To access the source +you'll need to install a Subversion client. Then, to get the source +code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + +If it prompts for a username and password use your perl.org account +if you have one, else just 'guest' and 'guest'. The source code will +be in a new subdirectory called `trunk`. + +To keep informed about changes to the source you can send an empty email +to dbd-oracle-changes-subscribe@perl.org after which you'll get an email with the +change log message and diff of each change checked-in to the source. + +After making your changes you can generate a patch file, but before +you do, make sure your source is still upto date using: + + svn update + +If you get any conflicts reported you'll need to fix them first. +Then generate the patch file from within the `trunk` directory using: + + svn diff > foo.patch + +Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. + +## How to create a patch without Subversion + +Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + +Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + +Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you want. + +Test your changes and then remove all temporary files: + + make test && make distclean + +Go back to the directory you originally unpacked the distribution: + + cd .. + +Unpack _another_ copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + +Then create a patch file by performing a recursive `diff` on the two +top level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + +## Speak before you patch + +For anything non-trivial or possibly controversial it's a good idea +to discuss (on dbi-dev@perl.org) the changes you propose before +actually spending time working on them. Otherwise you run the risk +of them being rejected because they don't fit into some larger plans +you may not be aware of. + +## GitHub repository + +A git mirror of the subversion is also available at +`https://github.com/yanick/DBD-Oracle`. + +# Oracle Related Links + +# WHICH VERSION OF DBD::ORACLE IS FOR ME? + +From version 1.25 onwards DBD::Oracle only support Oracle clients +9.2 or greater. Support for ProC connections was dropped in 1.29. + +If you are still stuck with an older version of Oracle or its client you might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + +As there are dozens of different versions of Oracle's clients this +list does not include all of them, just the major released versions of +Oracle. + +Note that one can still connect to any Oracle version with the older +DBD::Oracle versions the only problem you will have is that some of +the newer OCI and Oracle features available in later DBD::Oracle +releases will not be available to you. + +So to make a short story a little longer: + +- 1 + +If you are using Oracle 7 or early 8 DB and you can manage to get a 9 client and you can use +any DBD::Oracle version. + +- 2 + +If you have to use an Oracle 7 client then DBD::Oracle 1.17 should work + +- 3 + +Same thing for 8 up to R2, use 1.17, if you are lucky and have the right patch-set you might +go with 1.18. + +- 4 + +For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. Again this depends on your +patch-set, If you run into trouble go with 1.19 + +- 5 + +After 9.2 you can use any version you want. + +- 6 + +It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go back to 7 +and even get to 10. I am not sure what the 11g client can connect to. + +# BUGS AND LIMITATIONS + +There is a known problem with the 11.2g Oracle client and the +`DBMS_LOB.GETLENGTH()` PL/SQL function. +See [https://rt.cpan.org/Public/Bug/Display.html?id=69350](https://rt.cpan.org/Public/Bug/Display.html?id=69350) for the details. + +# SEE ALSO + +- [DBI](http://search.cpan.org/perldoc?DBI) + +http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in +the DBD::Oracle source distribution including the examples in the +Oracle.ex directory + +- DBD::Oracle Tutorial + +http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-oracle.html + +- Oracle Instant Client + +http://www.oracle.com/technology/tech/oci/instantclient/index.html + +- Oracle on Linux + +http://www.ixora.com.au/ + +- Free Oracle Tools and Links + +ora_explain supplied and installed with DBD::Oracle. + +http://www.orafaq.com/ + +http://vonnieda.org/oracletool/ + +- Commercial Oracle Tools and Links + +Assorted tools and references for general information. +No recommendation implied. + +http://www.platinum.com + +http://www.SoftTreeTech.com + +Also PL/Vision from RevealNet and Steven Feuerstein, and +"Q" from Savant Corporation. + +# AUTHORS + +DBI by Tim Bunce [http://www.tim.bunce.name](http://www.tim.bunce.name). + +The original `DBD::Oracle` was by Tim Bunce. +Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the +auspice of the Pythian Group ([http://www.pythian.com](http://www.pythian.com)). + +# ACKNOWLEDGEMENTS + +A great many people have helped with DBD::Oracle over the 17 years +between 1994 and 2011. Far too many to name, but we thank them all. +Many are named in the Changes file. + +# COPYRIGHT + +The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. +The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The Pythian Group). Canada. +The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. + +The DBD::Oracle module is free open source software; you can +redistribute it and/or modify it under the same terms as Perl 5. + +# AUTHORS + +- * + +Tim Bunce + +- * + +John Scoles + +- * + +Yanick Champoux + +# COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/err_bind/err_bind_param_inout_overrun_bug.msg b/err_bind/err_bind_param_inout_overrun_bug.msg deleted file mode 100644 index 83d9001f..00000000 --- a/err_bind/err_bind_param_inout_overrun_bug.msg +++ /dev/null @@ -1,108 +0,0 @@ -From dbi-users-return-215-Tim.Bunce=ig.co.uk@perl.org Mon Feb 5 23:03:29 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id XAA01289; Mon, 5 Feb 2001 23:03:27 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <06769-16@oink>; Fri, 6 Feb 1970 00:01:15 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 981413584:20:24069:0; Mon, 05 Feb 2001 22:53:04 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-2.mail.demon.net - id aa2024004; 5 Feb 2001 22:53 GMT -Received: (qmail 6267 invoked by uid 508); 5 Feb 2001 22:52:23 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6247 invoked from network); 5 Feb 2001 22:52:22 -0000 -Received: from seeme.dare.feddata.com (38.186.101.66) by tmtowtdi.perl.org - with SMTP; 5 Feb 2001 22:52:22 -0000 -Received: by seeme.dare.feddata.com; id OAA05466; - Mon, 5 Feb 2001 14:55:56 -0800 (PST) -Received: from ifyou.dare.feddata.com(38.186.101.111) by seeme.dare.feddata.com - via smap (4.1) id xma005448; Mon, 5 Feb 01 14:55:39 -0800 -Sender: oscar@dare.feddata.com -Message-ID: <3A7F2FB0.A1507582@pasadena.feddata.com> -Date: Mon, 05 Feb 2001 14:56:48 -0800 -From: Oscar DeMartino -Organization: Federal Data Corporation -X-Mailer: Mozilla 4.61 [en] (X11; U; SunOS 5.6 sun4u) -X-Accept-Language: en -MIME-Version: 1.0 -To: dbi-users@perl.org -Subject: Undetected error - Binding and Stored Procedures -Content-Type: multipart/alternative; - boundary="------------E1028F7A8304BE268EB8F67B" -Status: RO -Content-Length: 2042 -Lines: 66 - ---------------E1028F7A8304BE268EB8F67B -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -I am running Oracle 8.1.5 and am using many stored procedures. We -use returned cursors, and individual values. The problem is, when -a stored procedure is executed and the specified bound variable has not -be declared large enough to hold the returned value subsequent -bound variables do not get set and I cannot find any way to -automatically detect this. - -Example: - -The stored procedure takes 1-input value and returns three string -values. - -the stored procedure is prepared , so I get the statement handle. - -I bind the input variable, and then bind the three output variables (1, -2, & 3) -as 100 character strings. - -I then execute the statment handle. - -There do not appear to be any errors, after checking the returned value -(for the execute call), -and ->err and ->errstr are clean. - -variable 1 has the correct returned value. -BUT, output variable 2 & 3, have no value. - ------- -Executing the stored procedure using sqlplus (sql command line -interface) indicated: - -What really occured is that the returned output variables 1 & 3 were -under 100 characters long -output variable 2 was 120 characters long - ---------- - -I know I could make all output variables the max size allowed in the -database field -but this would seem to waste space in the perl code. Since the field in - -the database -is simply defined as a varchar2 with no size limitation (upto 32767). - ------ -Am I missing something about detecting that variables 2 & 3 did not get -stored correctly -by DBI::Oracle?? - - - --- -Oscar "Fred" DeMartino FFFFF DDDD CCC -320 N. Halstead Ave. Ste #160 F D D C C -Pasadena, CA 91107 FFF D D C -e-mail: Oscar.DeMartino@pasadena.feddata.com F D D C -Phone: (626)306-6649 F D D C C -Federal Data Corporation F DDDD CCC - - - ---------------E1028F7A8304BE268EB8F67B-- - diff --git a/err_bind/err_bindarrays.msg b/err_bind/err_bindarrays.msg deleted file mode 100644 index 8ca7a5d3..00000000 --- a/err_bind/err_bindarrays.msg +++ /dev/null @@ -1,241 +0,0 @@ -From cturner@redhat.com Tue Mar 27 06:01:56 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id GAA19714; Tue, 27 Mar 2001 06:01:56 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <13771-3@oink>; - Fri, 27 Mar 1970 06:00:50 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985668014:20:27605:3; Tue, 27 Mar 2001 04:40:14 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ab2125244; 27 Mar 2001 4:39 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id XAA32289 - for ; Mon, 26 Mar 2001 23:39:38 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2R4bvT12929; Mon, 26 Mar 2001 23:37:57 -0500 -Sender: cturner@redhat.com -To: Tim.Bunce@ig.co.uk -Subject: DBD::Oracle and OCI bound arrays -From: Chip Turner -Date: 26 Mar 2001 23:37:57 -0500 -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 980 -Lines: 29 - - -Hey Tim, - -The need to have true OCI bound arrays for DBD::Oracle has come up, -and it looks like I get the fun job of implementing them. Basically, -this will allow DBD::Oracle to do something the DCOracle python -library does. The idea is: - -my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -my @c1 = 'aa' .. 'zz'; -my @c2 = 'aaa' .. 'azz'; -$sth->execute(\@c1, \@c2); - -In other words, it populates the table with a single execute call, -passing two (or more) equally sized arrays in as references for bound -parameters. This has the potential to save a good amount of time, -especially for large datasets. - -This would pretty much be a proprietary extension for Oracle, though -similar uses could be done in other DBD's. - -Just thought I'd let you know what I was intending to do, and to see -if you had any interest in receiving it as a patch after I'm done. - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Tue Mar 27 09:29:48 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id JAA20809; Tue, 27 Mar 2001 09:29:42 +0100 (BST) -Date: Tue, 27 Mar 2001 09:29:41 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim.Bunce@ig.co.uk, dbi-dev@perl.org -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010327092941.D20616@ig.co.uk> -References: -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Mon, Mar 26, 2001 at 11:37:57PM -0500 -Content-Length: 1570 -Lines: 39 - -On Mon, Mar 26, 2001 at 11:37:57PM -0500, Chip Turner wrote: -> -> Hey Tim, -> -> The need to have true OCI bound arrays for DBD::Oracle has come up, -> and it looks like I get the fun job of implementing them. Basically, -> this will allow DBD::Oracle to do something the DCOracle python -> library does. The idea is: -> -> my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -> my @c1 = 'aa' .. 'zz'; -> my @c2 = 'aaa' .. 'azz'; -> $sth->execute(\@c1, \@c2); -> -> In other words, it populates the table with a single execute call, -> passing two (or more) equally sized arrays in as references for bound -> parameters. This has the potential to save a good amount of time, -> especially for large datasets. -> -> This would pretty much be a proprietary extension for Oracle, though -> similar uses could be done in other DBD's. -> -> Just thought I'd let you know what I was intending to do, and to see -> if you had any interest in receiving it as a patch after I'm done. - -I would *urge* you to discuss the implementation with me *before* -you get very far cutting code. - -And anyway, I think someone's already done much or all of the work. -Dig around in the dbi-dev archives. If you can't find the discussion -let me know. If you do, then ask them (via the dbi-dev list) what -the status is. - -I'm planning to make a DBI release next week and, hopefully, a -DBD::Oracle release the week after to cleare a backlog of patches I -have queued up. After that I'll be looking to add in the work of the -other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -Tim. - -From cturner@redhat.com Wed Mar 28 02:01:21 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id CAA27336; Wed, 28 Mar 2001 02:01:21 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <17151-9@oink>; - Sat, 28 Mar 1970 01:59:47 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985739868:20:27318:0; Wed, 28 Mar 2001 00:37:48 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ac2119835; 28 Mar 2001 0:37 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id TAA10445 - for ; Tue, 27 Mar 2001 19:37:35 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2S0ZoJ20115; Tue, 27 Mar 2001 19:35:50 -0500 -Sender: cturner@redhat.com -To: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -References: <20010327092941.D20616@ig.co.uk> -From: Chip Turner -Date: 27 Mar 2001 19:35:50 -0500 -In-Reply-To: <20010327092941.D20616@ig.co.uk> -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 1495 -Lines: 35 - -Tim Bunce writes: - -> I would *urge* you to discuss the implementation with me *before* -> you get very far cutting code. - -Unfortunately, it's a little late for this; I've mostly finished the -change (at least, enough for our needs), except for some review and -cleanups. It seems to work quite well (400 times faster than repeated -looping over a dataset) and passes all of DBD::Oracle's test suite. - -> And anyway, I think someone's already done much or all of the work. -> Dig around in the dbi-dev archives. If you can't find the discussion -> let me know. If you do, then ask them (via the dbi-dev list) what -> the status is. - -I checked as you suggest, but couldn't find any code, just discussion -of it. I'll check again, but it didn't seem that the person had put -it anywhere I could get at it. - -> I'm planning to make a DBI release next week and, hopefully, a -> DBD::Oracle release the week after to cleare a backlog of patches I -> have queued up. After that I'll be looking to add in the work of the -> other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -If you would like, the patch will probably be suitable for inclusion -by then, if you want it in by the next release. Should there be any -problems with it or its implementation, I'd be glad to clean it up if -you have interest in it (if not, that's cool too; we need it soon, -though, either way). - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Wed Mar 28 11:51:58 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id LAA00444; Wed, 28 Mar 2001 11:51:51 +0100 (BST) -Date: Wed, 28 Mar 2001 11:51:51 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010328115151.D29769@ig.co.uk> -References: <20010327092941.D20616@ig.co.uk> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Tue, Mar 27, 2001 at 07:35:50PM -0500 -Content-Length: 1786 -Lines: 40 - -On Tue, Mar 27, 2001 at 07:35:50PM -0500, Chip Turner wrote: -> Tim Bunce writes: -> -> > I would *urge* you to discuss the implementation with me *before* -> > you get very far cutting code. -> -> Unfortunately, it's a little late for this; I've mostly finished the -> change (at least, enough for our needs), except for some review and -> cleanups. It seems to work quite well (400 times faster than repeated -> looping over a dataset) and passes all of DBD::Oracle's test suite. - -I trust you've added some more tests for your new functionality! - -> > And anyway, I think someone's already done much or all of the work. -> > Dig around in the dbi-dev archives. If you can't find the discussion -> > let me know. If you do, then ask them (via the dbi-dev list) what -> > the status is. -> -> I checked as you suggest, but couldn't find any code, just discussion -> of it. I'll check again, but it didn't seem that the person had put -> it anywhere I could get at it. - -You could always ask them (CC me). - -> > I'm planning to make a DBI release next week and, hopefully, a -> > DBD::Oracle release the week after to cleare a backlog of patches I -> > have queued up. After that I'll be looking to add in the work of the -> > other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). -> -> If you would like, the patch will probably be suitable for inclusion -> by then, if you want it in by the next release. Should there be any -> problems with it or its implementation, I'd be glad to clean it up if -> you have interest in it (if not, that's cool too; we need it soon, -> though, either way). - -Thanks for the clean-up offer. Send it to me after I make the next -DBD::Oracle release (as a fresh patch over that version please - but -there shouldn't be too many changes). - -Tim. - diff --git a/err_bind/err_bindclobleak.msg b/err_bind/err_bindclobleak.msg deleted file mode 100644 index 1a31c760..00000000 --- a/err_bind/err_bindclobleak.msg +++ /dev/null @@ -1,58 +0,0 @@ -From PGWeiss@arity.com Thu Mar 9 09:51:45 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id JAA14948; Thu, 9 Mar 2000 09:51:43 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <27566-0@oink>; Mon, 9 Mar 1970 10:51:10 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 952595299:20:10439:68; Thu, 09 Mar 2000 09:48:19 GMT -Received: from image.arity.com ([140.239.104.130]) by punt-2.mail.demon.net - id aa2010598; 9 Mar 2000 9:47 GMT -Received: by image.arity.com with Internet Mail Service (5.5.2650.21) - id ; Thu, 9 Mar 2000 04:51:44 -0500 -Message-ID: -From: "Paul G. Weiss" -To: Perl-Win32-Database Mailing List , - "'Tim Bunce'" -Subject: Another CLOB related DBD::Oracle bug -Date: Thu, 9 Mar 2000 04:51:41 -0500 -MIME-Version: 1.0 -X-Mailer: Internet Mail Service (5.5.2650.21) -Content-Type: text/plain; charset="iso-8859-1" -Status: RO -Content-Length: 689 -Lines: 32 - -Binding a parameter to type ORA_CLOB causes a leak. -Consider: - -for (1..10000) -{ - for (1..100) - { - my $sth = $db->prepare('update item set descr = ? where id = ?'); - if ($leak) - { - $sth->bind_param(1, $descr, {ora_type => ORA_CLOB, -ora_field=>'DESCR'}); - $sth->bind_param(2, 12); - $sth->execute; - } - else - { - $sth->execute($descr,12); - } - } - sleep 1; -} - - -With $leak set to 1, i.e. binding the parameters explicitly the -program leaks. With $leak set to 0 it does not (but then I can't -set descr to anything greater than 4K nor can I set it to the -empty string). - -Is there a patch? - --P - diff --git a/err_bind/err_bindnullhash.msg b/err_bind/err_bindnullhash.msg deleted file mode 100644 index d9a98b9a..00000000 --- a/err_bind/err_bindnullhash.msg +++ /dev/null @@ -1,77 +0,0 @@ -From dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org Thu Jul 11 17:49:35 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g6BGnYH11008 - for ; Thu, 11 Jul 2002 17:49:34 +0100 (BST) - (envelope-from dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 11 Jul 2002 17:49:34 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1026401921:10:09249:41; Thu, 11 Jul 2002 15:38:41 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1124337; 11 Jul 2002 15:38 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id B567C2BF65 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 347792BF62 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Received: (qmail 95914 invoked by uid 1005); 11 Jul 2002 15:38:04 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 95896 invoked by uid 76); 11 Jul 2002 15:38:04 -0000 -Received: from ironmail1.cc.lehigh.edu (HELO ironmail1.cc.lehigh.edu) (128.180.39.26) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Thu Jul 11 15:38:04 2002 -0000 -Received: from ([128.180.39.20]) - by ironmail1.cc.lehigh.edu with ESMTP with TLS; - Thu, 11 Jul 2002 11:35:06 -0400 (EDT) -Received: from lawrencework (pc-lfn0.dept.Lehigh.EDU [128.180.52.51]) - by rain.CC.Lehigh.EDU (8.12.4/8.12.4) with SMTP id g6BFZ6rr022463 - for ; Thu, 11 Jul 2002 11:35:06 -0400 -Message-ID: <0a0401c228f0$93feda10$3334b480@lawrencework> -From: "Phil R Lawrence" -To: -References: <083b01c22824$70357340$3334b480@lawrencework> <20020711140937.A568@dansat.data-plan.com> -Subject: Re: error msg suggestion -Date: Thu, 11 Jul 2002 11:35:20 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2600.0000 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -X-Status: A -Content-Length: 636 -Lines: 21 - -Tim Bunce wrote: -> Binding an undef should work and be treated as a NULL. -> -> Probably a bug in your code or the driver. But you didn't -> say which driver. - -Hmmm. quite right, undefs do bind as NULL. However, in this case I am -binding $hash{non-existent-key}, which autoinstantiates to an undef, and looks -like this in the trace: - undef (magic-sg:y) - -Of course it was my dumb fault for having the wrong key for lookup, but -nonetheless, perhaps this should work the same as a normal undef. - -# $DBI::VERSION = "1.14"; -# $DBD::ODBC::VERSION = '0.28'; -$DSN = 'driver=Microsoft Access Driver (*.mdb);dbq=StudyManager.mdb'; - -Thanks, -Phil - - diff --git a/err_bind/err_trailingblank.msg b/err_bind/err_trailingblank.msg deleted file mode 100644 index cdf34a32..00000000 --- a/err_bind/err_trailingblank.msg +++ /dev/null @@ -1,345 +0,0 @@ -From dbi-users-bounce@isc.org Mon May 1 21:12:02 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id VAA16051; Mon, 1 May 2000 21:12:00 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <14295-42@oink>; Fri, 1 May 1970 21:06:08 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 957208278:10:19133:4; Mon, 01 May 2000 19:11:18 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1123094; 1 May 2000 19:11 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id B3CCF3FAA; - Mon, 1 May 2000 12:10:53 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Mon, 01 May 2000 12:05:42 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A70763E34 - for ; Mon, 1 May 2000 12:05:30 -0700 (PDT) -Received: from scotth.emsphone.com (scotth.emsphone.com [199.67.51.179]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA25897 - for ; - Mon, 1 May 2000 12:05:30 -0700 (PDT) env-from (shildret@scotth.emsphone.com) -Received: (from shildret@localhost) by scotth.emsphone.com (8.9.3/8.9.3) - id OAA50011 for dbi-users@isc.org; - Mon, 1 May 2000 14:05:48 -0500 (CDT) (envelope-from shildret) -Message-ID: -X-Mailer: XFMail 1.4.0 on FreeBSD -X-Priority: 3 (Normal) -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 8bit -MIME-Version: 1.0 -Resent-Date: Thu, 29 Jul 1999 22:07:08 +0100 -Resent-Message-Id: <19990729220708.G17723@ig.co.uk> -Resent-From: Tim Bunce -Resent-To: Tim Bunce -Date: Mon, 01 May 2000 14:05:48 -0500 (CDT) -Sender: shildret@scotth.emsphone.com -From: "Scott T. Hildreth" -To: "dbi-users@isc.org" -Subject: FW: Oracle & Trailing Blanks - possible change in DBD::Oracle -Resent-Sender: shildret@scotth.emsphone.com -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 3885 -Lines: 94 - - -Here is the help, I got regarding the trailing spaces. - ------FW: <19990729220708.G17723@ig.co.uk>----- - -Date: Thu, 29 Jul 1999 22:07:08 +0100 -From: Tim Bunce -To: Tim Bunce -Subject: Oracle & Trailing Blanks - possible change in DBD::Oracle -Cc: "Scott T. HIldreth" , - dbi-users@isc.org - - *** From dbi-users -- To unsubscribe, see the end of this message. *** - -On Thu, Jul 29, 1999 at 09:49:38PM +0100, Tim Bunce wrote: -> *** From dbi-users -- To unsubscribe, see the end of this message. *** -> -> On Thu, Jul 29, 1999 at 09:33:55AM -0500, Scott T. HIldreth wrote: -> > -> > Hi all, I wonder if someone can let me know if I got this right. -> > I have a key to match which can contain trailing blanks. The -> > field in the database is CHAR(18). If I match the key with -> > sqlplus, Oracle finds a match, with or without the trailing -> > blank. When I do an sth->execute( $key ), the key is not -> > found. I abstract the key with substr, so the trailing blank -> > is in the key, but no match is found. Do I need to place qoutes -> > around the value in $key? -> -> Somewhat hiddedn in the Oraperl.pm docs it says this: -> -> --- -> B Substitution variables are now bound as type 1 (VARCHAR2) -> and not type 5 (STRING) by default. This can alter the behaviour of -> SQL code which compares a char field with a substitution variable. -> See the String Comparison section in the Datatypes chapter of the -> Oracle OCI manual for more details. -> -> You can work around this by using DBD::Oracle's ability to specify -> the Oracle type to be used on a per field basis: -> -> $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) -> $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); -> $csr->bind_param(1, $value_x, $char_attrib); -> $csr->bind_param(2, $value_y, $char_attrib); -> ora_bind($csr); # bind with no parameters since we've done bind_param()'s -> --- -> -> Ignoring the Oraperl specifics there the key point is to use -> -> $csr->bind_param($idx, $value, { ora_type => 5 }); -> -> I'll add something to the DBD::Oracle docs. - -[You'll still need to blank-pad the string.] - -Looking at this issue again I've discovered that the key issue is that -type 1 strips trailing blanks whilst type 5 doesn't. - -I'rather m concerned by this. Since I'm against the DBI changing the -data in any way on principle and since Oraperl used to use type 5 -I'm strongly considering changing DBD::Oracle 'back' to using type 5. - -This would only affect anyone who relies on placeholders having -trailing blanks stripped off. (I'll provide a way to alter the -default with a single statement and/or env var for anyone affected). - -If that's you - speak up now! - -Tim. - ------------------------------------------------------------------------------- -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of -'unsubscribe'. ------------------------------------------------------------------------------- - - ---------------End of forwarded message------------------------- - ----------------------------------- -E-Mail: Scott T. Hildreth -Date: 01-May-00 -Time: 14:04:41 ----------------------------------- - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - -From joshua.horton@mail.tju.edu Fri May 23 07:43:09 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.6/8.12.6) with ESMTP id h4N6UY7T061880 - for ; Fri, 23 May 2003 07:43:09 +0100 (BST) - (envelope-from joshua.horton@mail.tju.edu) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 23 May 2003 07:43:09 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1053631164:10:02298:54; Thu, 22 May 2003 19:19:24 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116141; 22 May 2003 19:19 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id BD31E21C13C - for ; Thu, 22 May 2003 15:18:30 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail.tju.edu (fw-tr16.tju.edu [147.140.233.16]) - by dolly1.pobox.com (Postfix) with ESMTP id 615A521C06D - for ; Thu, 22 May 2003 15:18:22 -0400 (EDT) -Received: from PCSE447.tjh.tju.edu by mail.tju.edu for Tim.Bunce@pobox.com; Thu, 22 May 2003 15:17:54 -0400 -Message-Id: <031301c32096$de68f6f0$2310ae0a@PCSE447> -From: "Joshua Horton" -To: -Subject: Re: :Oracle and Oracle 9.2? -Date: Thu, 22 May 2003 15:18:03 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 5.50.4807.1700 -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 3511 -Lines: 99 - -Re: :Oracle and Oracle 9.2? - ----------------------------------------------------------------------------- ----- - - a.. From: Tim Bunce - b.. Subject: Re: :Oracle and Oracle 9.2? - c.. Date: Tue, 15 Apr 2003 07:36:55 -0700 - ----------------------------------------------------------------------------- ----- - -I'd appreciate it if other people with Oracle 9.2.x could let me -know if it passed or failed for them and what their exact oracle -version (four digits) and platform (operating system) is. - -Thanks. - -Tim. - -On Fri, Apr 04, 2003 at 01:48:36PM +0200, Smejkal Petr wrote: -> I have the same experience on Linux however on Windows all tests passes -(I'm not -> sure if it is related to different Oracle version - test of windows Perl -against -> Linux Oracle is OK). -> -> Linux Oracle: 9.2.0.2 -> Windows Oracle: 9.2.0.1 -> DBI: 1.35 -> DBD::Oracle: 1.14 -> -> -- Petr Smejkal -> -- Business Systems Analyst / Country IT Cz/Sk -> -- +420 284 059 639 -> -> > -----Original Message----- -> > From: Tom Malaher [mailto:[EMAIL PROTECTED] -> > Sent: Friday, April 04, 2003 1:35 AM -> > To: [EMAIL PROTECTED] -> > Subject: DBD::Oracle and Oracle 9.2? -> > -> > -> > My sysadmin is trying to install DBD::Oracle on a Solaris box running -> > Oracle 9.2. -> > -> > The ph_type.t test is failing with -> > -> > PERL_DL_NONLAZY=1 ./perl "-MExtUtils::Command::MM" "-e" -> > "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -> > t/base.......ok -> > t/cursor.....ok -> > t/general....ok -> > t/long.......ok -> > t/meta.......ok -> > t/ph_type....NOK 12 expected 'trailing' but got 'trailing ' -> > for VARCHAR2 -> > t/ph_type....FAILED test 12 -> > Failed 1/19 tests, 94.74% okay -> > t/plsql......ok -> > t/reauth.....skipped -> > all skipped: no reason given -> > t/select.....ok -> > Failed Test Stat Wstat Total Fail Failed List of Failed -> > -------------------------------------------------------------- -> > ----------------- -> > t/ph_type.t 19 1 5.26% 12 -> > 1 test skipped. -> > Failed 1/9 test scripts, 88.89% okay. 1/314 subtests failed, -> > 99.68% okay. -> > *** Error code 29 -> > make: Fatal error: Command failed for target `test_static' -> > -> > Is there a known problem with DBD::Oracle and Oracle 9.x? -> > Has Oracle changed the behavior of trailing spaces in VARCHAR2 fields? -> > -> > I've run the same test script on an oracle 8 installation -> > using DBD::Oracle 1.06 and DBI 1.14, and it works fine (no trailing -> > space is returned). -> > -> > Tom -> > -My config:HP-UX 11.11 (64-bit) on rp5470 2x733 5GB RAMOracle 9.2.0.2.0 -Enterprise Edition (64-bit)Perl 5.8.0 custom compiled with -./Configure -Duse64bitall -Ubincompat5005 -Duselargefiles -Dprefix=/opt/perl -5 ; all other options defaultDBI-1.32 all passed some skippedDBD-Oracle-1.14 -: PERL_DL_NONLAZY=1 /opt/perl5/bin/perl "-MExtUtils::Command::MM" -"-e" "test_harness(0, 'blib/lib', 'blib/arch')" -t/*.tt/base.......okt/cursor.....okt/general....okt/long.......okt/meta..... -..okt/ph_type....ok 11/19 expected 'trailing' but got 'trailing ' for -VARCHAR2t/ph_type....FAILED test 12 Failed 1/19 tests, 94.74% -okayt/plsql......okt/reauth.....skipped all skipped: no reason -givent/select.....okFailed Test Stat Wstat Total Fail Failed List of -Failed---------------------------------------------------------------------- --------------------------------------------------------t/ph_type.t -19 1 5.26% 121 test skipped.Failed 1/9 test scripts, 88.89% okay. -1/314 subtests failed, 99.68% okay.*** Error exit code 2Stop.Thanks,Josh -Horton - - -From nobody@fsck.com Tue Dec 30 14:33:50 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hBUEWNnP026077 - for ; Tue, 30 Dec 2003 14:33:50 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Dec 2003 14:33:50 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AbJwa-0003ua-H6; - Tue, 30 Dec 2003 13:29:56 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AbJwa-0003ua-H6 - for pobox@dbi.demon.co.uk; Tue, 30 Dec 2003 13:29:56 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 56DAD4C6 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3B3564C8 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 30 Dec 2003 08:29:54 -0500 (EST) -Received: (qmail 10988 invoked by uid 225); 30 Dec 2003 13:29:53 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 10984 invoked by alias); 30 Dec 2003 13:29:52 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 30 Dec 2003 05:29:41 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 8760D11153; Tue, 30 Dec 2003 08:29:37 -0500 (EST) -Subject: [cpan #4786] Oracle 9.2.0.0 fails a test in ph_types.t -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4786 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -To: "AdminCc of cpan Ticket #4786": ; -Date: Tue, 30 Dec 2003 08:29:37 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,SUPERLONG_LINE,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -Content-Length: 888 -Lines: 11 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -Assuming that ORA_OCI() gets set correctly when compiling against 9.2, the attached patch will work. I also tried this in SQL*Plus and was able to insert a trailing space into a VARCHAR2. (I replicated the test in ph_types.t). - -I did not test my patch as I installed DBD::Oracle 1.14 by setting the chops_spaces value in %test_info to 0. When I did that, everything installed fine. However, I didn't think that my solution was the best for the module, so I figured ORA_OCI should do the trick. - -I'm running Perl5.8.0 for Solaris2.9 going against the full Oracle build for 9.2. (I did not run into this issue, surprisingly, on Redhat9 running Perl 5.8.2, but I built against Oracle 9.1 there ...) - diff --git a/err_build/err_aix64.msg b/err_build/err_aix64.msg deleted file mode 100644 index f952e29e..00000000 --- a/err_build/err_aix64.msg +++ /dev/null @@ -1,142 +0,0 @@ -From SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com Fri Jan 7 16:11:33 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j07GAqfa044155 - for ; Fri, 7 Jan 2005 16:11:32 GMT - (envelope-from SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Fri, 07 Jan 2005 16:11:32 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CmvQB-0003Po-Kf; - Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CmvQB-0003Po-Kf - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CmvQA-0002zW-VM - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 49778102ACC; - Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 384E5FF808 - for ; Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Received-SPF: pass (boggle.pobox.com: domain of dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by boggle.pobox.com (Postfix) with SMTP id A74B8F4090 - for ; Fri, 7 Jan 2005 09:48:57 -0500 (EST) -Received: (qmail 2690 invoked by uid 514); 7 Jan 2005 14:48:56 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 2622 invoked from network); 7 Jan 2005 14:48:55 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 7 Jan 2005 14:48:55 -0000 -Received: (qmail 13078 invoked by uid 225); 7 Jan 2005 14:48:54 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 13048 invoked by alias); 7 Jan 2005 14:48:51 -0000 -X-Spam-Status: No, hits=-4.6 required=8.0 - tests=BAYES_00,HTML_MESSAGE,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: neutral (x1.develooper.com: local policy) -Received: from outmx020.isp.belgacom.be (HELO outmx020.isp.belgacom.be) (195.238.2.201) - by la.mx.develooper.com (qpsmtpd/0.28) with ESMTP; Fri, 07 Jan 2005 06:48:38 -0800 -Received: from outmx020.isp.belgacom.be (localhost [127.0.0.1]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmOgS020070 - for ; Fri, 7 Jan 2005 15:48:24 +0100 - (envelope-from ) -Received: from relaytwo.roularta.be (smtprelaytwo.roularta.be [194.78.177.23]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmMDA020034 - for ; Fri, 7 Jan 2005 15:48:22 +0100 - (envelope-from ) -Received: from rmgexch01.RMG.be ([89.0.35.150]) by roesfront3.RMG.be with Microsoft SMTPSVC(5.0.2195.6713); - Fri, 7 Jan 2005 15:47:50 +0100 -X-MimeOLE: Produced By Microsoft Exchange V6.5.7226.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----_=_NextPart_001_01C4F4C7.EE810087" -Subject: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Date: Fri, 7 Jan 2005 15:48:21 +0100 -Message-ID: -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Thread-Index: AcT0x+Y4G1R3vbX6Rh+QdPyNy/10eQ== -From: -To: -X-OriginalArrivalTime: 07 Jan 2005 14:47:50.0598 (UTC) FILETIME=[DC5D2E60:01C4F4C7] -Status: RO -Content-Length: 1678 -Lines: 62 - -------_=_NextPart_001_01C4F4C7.EE810087 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - -Hi,=20 -=20 -I finally succeeded in installing a 64bit build of Perl and its modules -for Oracle 64-bit. We were running in 32bit but integrating Proc and -cobols in our perl scripts only worked when we changed environments to -64bit causing problems for the oracle connections in perl. It's nothing -special, no editing of makefiles ... I can't believe I lost so much time -on this one ;) ( Now that I look back to my problems, they were probably -caused by using a wrong perl build for compiling the modules, Aix has -its default perl now under /bin.. stupid me )=20 -=20 -perl 5.8.6 64bit ----------------- -./Configure -de -Dcc=3Dgcc -Duse64bitall=20 -make -make test -make install -=20 -DBI 1.46 --------- -!!Make sure you are using the newly installed perl!! - check with perl -v it should show :=20 - This is perl, v5.8.6 built for aix-64all -perl Makefile.PL -make -make test -make install=20 -=20 -DBD-Oracle 1.16 ---------------- -!!Use correct perl like above mentioned!!=20 -export ORACLE_HOME=3D=20 -export LIBPATH=3D$ORACLE_HOME/lib -export LD_LIBRARY_PATH=3D$ORACLE_HOME/lib -=20 -perl Makefile.PL=20 -make -make test ( some test may still fail, I had 85% success on tests )=20 -make install=20 -=20 -Test -----=20 -=20 -test with :=20 - use DBI; - $dbh=3DDBI->connect("dbi:Oracle:","system","manager")|| die -$DBI::errstr; - $stmt=3D$dbh->prepare("select * from tab"); - $rc=3D$stmt->execute() || die $DBI::errstr; - while (my($record)=3D$stmt->fetchrow()) - { - print $record; - } -=20 -Happy 64-bit perling ;)=20 - -------_=_NextPart_001_01C4F4C7.EE810087-- - diff --git a/err_build/err_hpux_ld.msg b/err_build/err_hpux_ld.msg deleted file mode 100644 index 27f9cd07..00000000 --- a/err_build/err_hpux_ld.msg +++ /dev/null @@ -1,89 +0,0 @@ -From SRS0=JbZc=U3=lincolnbaxter.com=lab@bounce2.pobox.com Tue Jun 21 05:02:19 2005 -Return-Path: -X-Original-To: timbo@localhost -Delivered-To: timbo@localhost.data-plan.com -Received: from localhost (localhost [127.0.0.1]) - by timac.data-plan.com (Postfix) with ESMTP id B016F2A3D98 - for ; Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DkYXK-0003m5-Mr; - Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DkYXK-0003m5-Mr - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1DkYXJ-00006n-QE - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AF60172691; - Mon, 20 Jun 2005 22:29:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from ms-smtp-04-eri0.southeast.rr.com (ms-smtp-04-lbl.southeast.rr.com [24.25.9.103]) - by gold.pobox.com (Postfix) with ESMTP id A3C1E7272E - for ; Mon, 20 Jun 2005 22:29:11 -0400 (EDT) -Received: from lincolnbaxter.com (cpe-069-132-010-126.carolina.res.rr.com [69.132.10.126]) - by ms-smtp-04-eri0.southeast.rr.com (8.12.10/8.12.7) with ESMTP id j5L2TIL4001864 - for ; Mon, 20 Jun 2005 22:29:18 -0400 (EDT) -Received: (qmail 5171 invoked from network); 20 Jun 2005 22:29:07 -0400 -Received: from lws (192.168.0.25) - by lws with SMTP; 20 Jun 2005 22:29:07 -0400 -Subject: Re: gcc options when building DBD:Oracle -From: "Lincoln A. Baxter" -Reply-To: lab@lincolnbaxter.com -To: jriekenberg@everestkc.net -Cc: Tim Bunce -In-Reply-To: -References: -Content-Type: text/plain -Date: Mon, 20 Jun 2005 22:29:07 -0400 -Message-Id: <1119320947.17452.484.camel@lws> -Mime-Version: 1.0 -X-Mailer: Evolution 2.2.1.1 -Content-Transfer-Encoding: 7bit -X-Virus-Scanned: Symantec AntiVirus Scan Engine -Status: RO -Content-Length: 2011 -Lines: 38 - -Hi Jan, - -This looks like something that might be relatively easy to fix in -Makefile.PL. But I no longer have access to HPUX systems, and never -built DBD-Oracle with gcc on that platform. I could add your message to -the README.hpux file, but it is becoming less and less necessary to read -this file with newer versions of DBD-Oracle, in which Makefile.PL has -been made much smarter. - -Would you consider sending Tim or me a patch to Makefile.PL that -generates the right $(LD) command (only on HP rp8400, and only for your -version of gcc or later? - -Lincoln - -On Mon, 2005-06-20 at 15:36 -0500, jriekenberg@everestkc.net wrote: -> Lincoln, -> -> I recently built DBD:Oracle on an HP rp8400. Everything worked as expected until I actually issued the "make" command. Make proceeded as expected until it reached "MakeMaker dynamic_lib" section. The gcc line in that section failed with the error in the attached text file. Apparently gcc was not correctly passing the "+b" option to ld. Instead, it was attempting to interpret the option itself. It assumed the "+b" was a filename, and that failed because gcc could not find the file. I ended up adding the "-Xlinker" option before the "+b" and before the "$(LD_RUN_PATH)" in the line in Makefile. The line now looks like this: -> -> $(LD) -Xlinker +b -Xlinker "$(LD_RUN_PATH)" $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) -> -> Running "make" now works correctly. -> -> Also, "make test" returned the following error when attempting to build the various tests: -> -> /usr/lib/dld.sl: Can't shl_load() a library containing Thread Local Storage: /usr/lib/libcl.2 -> -> Setting LD_PRELOAD with "export LD_PRELOAD=/usr/lib/libcl.2" corrected this problem, and "make test" worked correctly. -> -> -> I didn't see DBD::Oracle documentation on exactly this, so I'm sending this to you. You may be aware of these items already. If so, please disregard this. -> -> Jon Riekenberg -> -> -> - - diff --git a/err_build/err_hpuxsuccess.msg b/err_build/err_hpuxsuccess.msg deleted file mode 100644 index c6edd79f..00000000 --- a/err_build/err_hpuxsuccess.msg +++ /dev/null @@ -1,279 +0,0 @@ -From dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org Tue Mar 23 17:00:25 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i2NGvAxX021862 - for ; Tue, 23 Mar 2004 17:00:23 GMT - (envelope-from dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 23 Mar 2004 17:00:23 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1B5oND-0000Ba-LH; - Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1B5oND-0000Ba-LH - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [208.210.124.70] (helo=majesty.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1B5oNC-00001d-92 - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:26 +0000 -Received: from majesty.pobox.com (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 18033954B4 - for ; Tue, 23 Mar 2004 11:03:24 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 3577D954BE - for ; Tue, 23 Mar 2004 11:03:21 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by majesty.pobox.com (Postfix) with SMTP - for ; Tue, 23 Mar 2004 11:02:41 -0500 (EST) -Received: (qmail 6527 invoked by uid 1005); 23 Mar 2004 16:02:21 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6510 invoked by uid 76); 23 Mar 2004 16:02:20 -0000 -Received: from x1.develooper.com (HELO x1.develooper.com) (63.251.223.170) - by onion.perl.org (qpsmtpd/0.27.1) with SMTP; Tue, 23 Mar 2004 08:02:20 -0800 -Received: (qmail 1985 invoked by uid 225); 23 Mar 2004 16:02:15 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 1893 invoked by alias); 23 Mar 2004 16:02:00 -0000 -X-Spam-Status: No, hits=0.0 required=7.0 - tests= -X-Spam-Check-By: la.mx.develooper.com -Received: from Unknown (HELO dundee.fpcc.net) (204.144.241.120) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Tue, 23 Mar 2004 08:01:44 -0800 -Received: from aberdeen.fpcc.net (aberdeen.fpcc.net [204.144.241.125]) - by dundee.fpcc.net (8.11.6/8.11.6) with ESMTP id i2NG1f111241; - Tue, 23 Mar 2004 09:01:41 -0700 -Received: from aberdeen.fpcc.net (localhost.localdomain [127.0.0.1]) - by aberdeen.fpcc.net (8.12.8/8.12.8) with ESMTP id i2NFrNOv024637; - Tue, 23 Mar 2004 08:53:23 -0700 -Received: (from laubster@localhost) - by aberdeen.fpcc.net (8.12.8/8.12.8/Submit) id i2NFrMOx024635; - Tue, 23 Mar 2004 08:53:22 -0700 -X-Authentication-Warning: aberdeen.fpcc.net: laubster set sender to dbiusers@laubster.org using -f -Date: Tue, 23 Mar 2004 08:53:22 -0700 -From: "J.D. Laub" -To: dbi-users@perl.org -Cc: lbaxter@fleetcc.com -Subject: SUCCESS: DBD::Oracle 1.15 on HP-UX 11.11 -Message-ID: <20040323155322.GA24576@aberdeen.fpcc.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -Organization: The Psychiatric Ward of Terrors -X-Virus-Checked: Checked -Status: RO -Content-Length: 9105 -Lines: 206 - -I've just had success building DBD::Oracle 1.15 on HP-UX 11.11 -(against both oracle 8.1.7 & oracle 9.2.0) & thought I'd share my -experience. - -Disclaimer: these instructions relate to our environment. It may be -that our sysadmins/dbas chose to configure/install things a certain -way (i.e., our install of $ORACLE_HOME/bin/sqlplus was *chosen* -to be 1.1/32), and/or that we're running old versions of software -(i.e., perhaps later releases of gcc don't ignore -mpa-risc-1-1). -In fact, there are probably some mistruths in here; rest assured -they're not intentional. :-) - -I'm unsure how (if?) I should go about getting this information into -the DBD::Oracle README.hpux. Lincoln, please contact me with any -thoughts you have. - - -### The summary ################################ - -Use the ansic compiler (~US$800/cpu). - -Shell variables I used: - PATH=/bin:$PATH # use 32bit ar & nm since using a 32bit cc - PERLDEST=/opt/perl_ora8 # or "perl_ora9" for an ora9 build - PATH=$PERLDEST/bin:$PATH # for build of DBI, pick up new perl - export LDLOADLIBS='+b : +s' # handy for ORACLE_SID connections to ora7 - unset PERLLIB # important to avoid outdated cruft - export ORACLE_USERID=scott/tiger # insecure - consider using "/" - ORACLE_SID=orcl - ORAENV_ASK=NO - . oraenv # sets LD_LIBRARY_PATH and SHLIB_PATH - -For ora8: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DAportable ' \ - -A prepend:ldflags='+z +DAportable ' - -For ora9: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DA2.0W ' \ - -A prepend:ldflags='+z +DA2.0W ' \ - -Dlibpth='/usr/lib/pa20_64 /usr/local/pa20_64/lib' - -After you use the above to install perl, DBI & DBD::Oracle will -build in the normal fashion. - - -### General Notes ################################ - -* During "make test", I received 1 failure (on -lib/ExtUtils/t/Constant) for ora8, and 3 failures (on -lib/ExtUtils/t/Constant, lib/ExtUtils/t/recurs, and t/op/write) for -ora9. Nevertheless, things seem mostly OK. - -* These are the various combinations possible for a given compiled -file on HP-UX 11.11 (the quoted description is what gets kicked out -by the "file" command): - - PA-RISC1.1/32bit ("PA-RISC1.1 relocatable object") - (I'll call this 1.1/32) - PA-RISC2.0/32bit ("PA-RISC2.0 relocatable object") - (I'll call this 2.0/32) - PA-RISC2.0/64bit ("ELF 64-bit MSB relocatable, PA-RISC 2.0 (LP64)") - (I'll call this 2.0/64) - -* "perl -v" lies about the RISC level: -$ file ./perl -./perl: PA-RISC1.1 shared executable dynamically linked -not stripped -$ ./perl -v | grep RISC -This is perl, v5.8.3 built for PA-RISC2.0 - -* If you'll be linking against 2.0/64 libraries, you'll have to -build all your object modules that way. I've not yet found a way -to link 32bit executables to 64bit libraries (and vice versa). Run -the "file" command on your Oracle libraries to find out which path -you'll have to take. - -* Two environment variables control where libraries are -searched. LD_LIBRARY_PATH and SHLIB_PATH (in that order) are -used for 64bit executables, while SHLIB_PATH is used for 32bit -executables. - -* I tried attempts using aCC as well as the default (free) cc that -comes with hpux; both avenues were too problematic to continue -pursuing. - -* The format of compiled objects is specified by compiler options. -According to the ansic compiler docs, the options are "+DAportable" -(for 1.1/32), "+DA2.0" (for 2.0/32), and "+DA2.0W" (for 2.0/64). -For gcc, the corresponding switches are -mpa-risc-1-1 (for 1.1/32) -and -mpa-risc-2-0 (for 2.0/64), but I've found that -mpa-risc-1-1 -is ineffective. (According to the "file" command, you *always* get -2.0/64.) - -* Our gcc displays the behavior described at -http://sources.redhat.com/ml/binutils/2002-10/msg00586.html and -http://aspn.activestate.com/ASPN/Mail/Message/perl5-porters/1641238 -, so is therefore unusable anytime '-lcl' is to be specified. -Unfortunately, that library is required for DBD::Oracle builds. -(The workaround of adding the 3 declarations does seem to work, -but littering those throughout perl's Configure, main.c, etc. -seems a big task.) Attempts to get gcc to use the hp ld instead -of the gnu ld (by specifying -mno-gnu-ld and -fno-gnu-linker) were -unsuccessful. The first html link shown above indicates you have -to rebuild gcc to use the hp linker, and that was not an incredibly -desirable path to pursue. - -* Our default PATH was set to put /usr/local/pa20_64/bin ahead of -/bin. This caused problems because (I think) the 64bit versions -of either ar (the archiver) or nm (the symbol lister) do not play -well with /bin/cc (the 32bit compiler). The tweak to put /bin at -the head of PATH, so we get the 32bit versions, takes care of the -problem. - -* I ran into an intermittent quirk during the build of perl in which -typing "make" (just after the Configure) did nothing. It turns out -that only dependencies were being written to "makefile", and that -removing "makefile" (so it could be automatically rebuilt) solved -the problem. - -* Most of my research on finding the right compiler/linker switches -was done with a "hello world" C program, trying the various -compilers and options, and trying to link it with the oracle -libraries. This proved to be a good choice, as trying to test -compilers/switches against the perl source distribution would have -proved quite difficult. - - -### DBD::Oracle specific ################################ - -* ora8 delivers its libraries in 2 formats: 1.1/32 (under -$ORACLE_HOME/lib) and 2.0/64 (under $ORACLE_HOME/lib64). ora7 -delivers only 1.1/32, while ora9 delivers only 2.0/64. It may seem -a bit inconsistent considering the ora8 setup, but ora9 libraries -are found under $ORACLE_HOME/lib and not $ORACLE_HOME/lib64. - -* Under ora8, oraenv incorrectly sets LD_LIBRARY_PATH to include -$ORACLE_HOME/lib instead of $ORACLE_HOME/lib64, so you've got to -make an override in oraenv_local if you want to use 2.0/64. It -doesn't harm anything, but oraenv unnecessarily sets LD_LIBRARY_PATH -for ora7 (a 64bit environment variable for a 32bit application). - -* If you use shared libraries AND you'll be upgrading Oracle, you -should expect you'll need to rebuild DBD::Oracle unless you'll keep -the old Oracle libraries available. - -* If you're building against ora8, the setting of LDLOADLIBS -is recommended so that when oraenv set SHLIB_PATH to the -$ORACLE_HOME/lib for ora7, the code will still find the ora8 -libraries. - -* We expect to need local (ORACLE_SID) connections for ora8 & -ora9. We could have gone with a single 2.0/64 perl coupled with -2 DBD::Oracle installs and PERLLIB twiddling in oraenv_local to -get to the right one. Instead, we chose to do 2 perl installs -(/opt/perl_ora8 and /opt/perl_ora9) because we can also connect -locally to ora7 by using the 1.1/32 ora8 version, something that -isn't possible with a 2.0/64 version. Also, we've some older 1.1/32 -machines into which we'd like to plop a tarball of the perl stuff, -so a 1.1/32 executable was desirable. - -* Some tests I ran were hinting that with 2.0/64, specifying "+b :" -on the build of DBD::Oracle correctly configured Oracle.sl as far as -the chatr program is concerned, but it seemed that LD_LIBRARY_PATH -*always* needed to be set correctly. (I.e., the embedded path in -the library seemed to be ignored.) I didn't pursue researching this -since there's no way to get the ora9 compiled code to connect to -ora8, meaning LD_LIBRARY_PATH had to be set correctly anyway. - -Testing local (ORACLE_SID) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora9 cannot connect to ora8 or ora7: "UNKNOWN - OCI STATUS 1804) OCIInitialize. Check ORACLE_HOME and NLS - settings etc." - -Testing remote (sqlnet) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 can connect to ora9 -builds against 2.0/64 ora9 can connect to ora8 -builds against 2.0/64 ora9 cannot connect to ora7: "OCI-21500: internal - error code" - - -### Versions ################################ - -perl: 5.8.3 -dbi: 1.41 -dbd-oracle: 1.15 -$ strings /bin/cc | grep Compiler -HP92453-01 B.11.11.08 HP C Compiler -$ strings /bin/ld | grep linker -$Revision: 92453-07 linker linker crt0.o B.11.16 000601 $ -@(#)92453-07 linker command s800.sgs ld PA64 B.11.18 REL 000922 -$ gcc -v -Reading specs from /usr/local/pa20_64/lib/gcc-lib/hppa64-hp-hpux11.11/3.3.1/specs -Configured with: ../src/configure --enable-languages=c,c++ --prefix=/usr/local/pa20_64 --with-local-prefix=/usr/local/pa20_64 --with-gnu-as --with-as=/usr/local/pa20_64/bin/as --with-gnu-ld --with-ld=/usr/local/pa20_64/bin/ld --disable-shared --disable-nls --host=hppa64-hp-hpux11.11 -Thread model: single -gcc version 3.3.1 - --- -J.D. Laub (Laubster) |"Your leg's too long / Your skull's too strong / -dbiusers@laubster.org| Suppose your nose is wrong." - Renaldo & the Loaf - diff --git a/err_build/err_instantclient.msg b/err_build/err_instantclient.msg deleted file mode 100644 index f0e549eb..00000000 --- a/err_build/err_instantclient.msg +++ /dev/null @@ -1,207 +0,0 @@ -From SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Feb 2 10:11:05 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j12AAUZ6055956 - for ; Wed, 2 Feb 2005 10:11:05 GMT - (envelope-from SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 02 Feb 2005 10:11:05 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwGaQ-0002Bn-H6; - Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwGaQ-0002Bn-H6 - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwGaP-00042G-Vb - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 9C3FB1E3946; - Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 879981E3958 - for ; Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Received-SPF: pass (kelvin.pobox.com: domain of dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by kelvin.pobox.com (Postfix) with SMTP id D0B001E3946 - for ; Wed, 2 Feb 2005 04:14:08 -0500 (EST) -Received: (qmail 7188 invoked by uid 514); 2 Feb 2005 09:14:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -List-Id: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 2531 invoked from network); 2 Feb 2005 04:10:16 -0000 -Delivered-To: dbi-users@perl.org -X-Spam-Status: No, hits=-2.6 required=8.0 - tests=BAYES_00,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: pass (x1.develooper.com: local policy) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgw.shina.sankyo.co.jp: iscan owned process doing -bs -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: Making DBD::Oracle with Instant Client 10.1.0.3 -Date: Wed, 2 Feb 2005 13:09:58 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBE9@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUI3Q64h9ykph8RSl6pF0OpBbTqJA== -To: -X-OriginalArrivalTime: 02 Feb 2005 04:09:59.0005 (UTC) FILETIME=[0F7508D0:01C508DD] -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 44 - -Hi all, - -Thanks to the devel package, I've got succeeded in making DBD::Oracle -with the Oracle Instant Client 10.1.0.3, no *.mk files, in my linux box. -My recipe is: - -1) install both basic- and devel-10.1.0.3 rpm packages -2) export ORALCE_HOME="/usr/lib/oracle/10.1.0.3/client" -3) export LD_LIBRARY_PATH="$ORACLE_HOME/lib:$LD_LIBRARY_PATH" -4) modify the Makefile.PL file to bypass the find_headers() routine and - to pass a correct -I flag to cc (the attached dirty patch is FYI) -5) execute the Makefile.PL * with the -l option *, perl Makefile.PL -l -6) make && make test && make install -# I got many errors in t/30long.t (retrieving blobs ?) -# but it seems to work fairly. - -I hope this could help those who are annoyed with the "Unable to locate an -oracle.mk,..." error. - -Happy DBing, - -Satoshi - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+# my @h_dirs = find_headers(); - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client"; - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -From SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com Thu Feb 3 08:10:48 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j138AMOi093146 - for ; Thu, 3 Feb 2005 08:10:48 GMT - (envelope-from SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Thu, 03 Feb 2005 08:10:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwboD-0005ug-LV; - Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwboD-0005ug-LV - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwboD-0000Wn-82 - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 70999102D9F; - Thu, 3 Feb 2005 02:53:48 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 5F45E102DCC - for ; Thu, 3 Feb 2005 02:53:48 -0500 (EST) -X-Pobox-Antispam: Require PTR Record returned DENY: 210.81.52.253 has no PTR record -X-Pobox-Antispam: country/Japan returned DENY: sender address snisim@sankyo.co.jp matches TLD .jp (Japan) -Received-SPF: none (boggle.pobox.com: domain of snisim@sankyo.co.jp does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for snisim@sankyo.co.jp to mail through 210.81.52.253) -Received: from mailgws.shina.sankyo.co.jp (unknown [210.81.52.253]) - by boggle.pobox.com (Postfix) with ESMTP id A38A5102E20 - for ; Thu, 3 Feb 2005 02:53:46 -0500 (EST) -Received: from es007.sankyo.co.jp (localhost [127.0.0.1]) - by mailgws.shina.sankyo.co.jp (8.9.3p2/3.7W) with ESMTP id LAA15117 - for ; Thu, 3 Feb 2005 11:45:39 +0900 (JST) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgws.shina.sankyo.co.jp: iscan owned process doing -bs -Received: from EVS001.sankyo.co.jp ([10.14.121.200]) by es007.sankyo.co.jp with Microsoft SMTPSVC(6.0.3790.0); - Thu, 3 Feb 2005 11:45:39 +0900 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: RE: Making DBD::Oracle with Instant Client 10.1.0.3 -Content-class: urn:content-classes:message -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Date: Thu, 3 Feb 2005 11:46:07 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBEC@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUJEc1pQuIX++g2S8y4AE9WqWRYtQAhsK+Q -To: -X-OriginalArrivalTime: 03 Feb 2005 02:45:39.0123 (UTC) FILETIME=[71F21030:01C5099A] -Status: RO -Content-Length: 1192 -Lines: 36 - -Hi Tim, - -Thank you for your kind reply. - -I found my patch will cause a compilation error for the local variable -@h_dirs gets into undefined after commenting out the line 279. -It should be corrected as following: - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+ my @h_dirs; - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client" - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -I'm not a dbi-users member so I can't reply my post... I wonder if you can do it. - -Thanks, - -Satoshi - - diff --git a/err_build/err_makefileundef.msg b/err_build/err_makefileundef.msg deleted file mode 100644 index b98d782a..00000000 --- a/err_build/err_makefileundef.msg +++ /dev/null @@ -1,87 +0,0 @@ -From timbo Tue Apr 26 09:19:54 2005 -Return-path: -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 26 Apr 2005 09:19:54 -0700 (PDT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DQSgy-0006AU-4c; - Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DQSgy-0006AU-4c - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1DQSgy-0003uM-1T - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 759703B902A; - Tue, 26 Apr 2005 12:13:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 80C0A39F279 - for ; Tue, 26 Apr 2005 12:13:42 -0400 (EDT) -Received-SPF: none (kelvin.pobox.com: domain of lembark@wrkhors.com does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 66.246.154.128(mail-out.pilosoft.net) -Received: from mail.pilosoft.net (mail-out.pilosoft.net [66.246.154.128]) - by kelvin.pobox.com (Postfix) with ESMTP id 2ED743AB75B - for ; Tue, 26 Apr 2005 12:12:30 -0400 (EDT) -Received: from [192.168.1.2] (dsl-69-31-90-94.pilosoft.com [69.31.90.94]) - by mail.pilosoft.net (8.12.8/8.12.8) with ESMTP id j3QGA3u1014203 - for ; Tue, 26 Apr 2005 12:10:03 -0400 -Date: Tue, 26 Apr 2005 12:14:22 -0400 -From: Steven Lembark -Reply-To: lembark@wrkhors.com -To: Tim Bunce -Subject: Possible glitch in DBD::Oracle-1.48 Makefile.pl -Message-ID: <269F0144DC99100E7C80975F@[192.168.1.2]> -X-Mailer: Mulberry/3.1.3 (Linux/x86) -X-Workhorse: lembark 1.1 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii; format=flowed -Content-Transfer-Encoding: 7bit -Content-Disposition: inline -X-Virus-Scanned: ClamAV version 0.83, clamav-milter version 0.83 on mail.pilosoft.net -X-Virus-Status: Clean -X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=failed version=3.0.2 -X-Spam-Level: 0.0 -X-Spam-Checker-Version: SpamAssassin 3.0.2 (2004-11-16) on cheeta.pilosoft.net -X-Status: A -Content-Length: 1342 -Lines: 36 - -Linking with OTHERLDFLAGS = -L/opt/oracle/product/9.2/lib/ --L/opt/oracle/product/9.2/rdbms/lib/ -lclntsh `cat -/opt/oracle/product/9.2/lib/sysliblist` -ldl -lm [from 'build' rule] - -Checking if your kit is complete... -Looks good -Use of uninitialized value in substitution (s///) at Makefile.PL line 1446. -LD_RUN_PATH=/opt/oracle/product/9.2/lib:/opt/oracle/product/9.2/rdbms/lib -Using DBD::Oracle 1.16. - - - sub const_loadlibs { - my $self = shift; - local($_) = $self->SUPER::const_loadlibs(@_); - # edit LD_RUN_PATH ... - my ($ldrp) = m/^LD_RUN_PATH\s*=\s*(.*)/m; - # remove redundant /lib or /usr/lib as it can cause problems --> $ldrp =~ s!:(/usr)?/lib$!!; - # if it's empty then set it manually - #Lincoln: if pick the right library path - my $libdir = main::ora_libdir(); - $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; - #print "ldrp=$ldrp\n"; - - # stitch it back in - s/^LD_RUN_PATH\s*=\s*(.*)/LD_RUN_PATH=$ldrp/m; - my $env = $ENV{LD_RUN_PATH}; - print "Ignoring LD_RUN_PATH='$env' in environment\n" if $env; - print "LD_RUN_PATH=$ldrp\n"; - return $_; - } - --- -Steven Lembark 85-09 90th Street -Workhorse Computing Woodhaven, NY 11421 -lembark@wrkhors.com 1 888 359 3508 - diff --git a/err_build/err_memleak.msg b/err_build/err_memleak.msg deleted file mode 100644 index d40913d7..00000000 --- a/err_build/err_memleak.msg +++ /dev/null @@ -1,95 +0,0 @@ -From SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com Wed Sep 1 16:31:37 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i81FRlpg021884 - for ; Wed, 1 Sep 2004 16:31:37 +0100 (BST) - (envelope-from SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 Sep 2004 16:31:37 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C2WYO-00034m-M1; - Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C2WYO-00034m-M1 - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1C2WYO-0005CR-FY - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 1C1D6A758C; - Wed, 1 Sep 2004 10:57:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 184C8A7214 - for ; Wed, 1 Sep 2004 10:57:32 -0400 (EDT) -Received-SPF: fail (boggle.pobox.com: domain of www-data@pallas.eruditorum.org does not designate 63.251.223.170 as permitted sender) -X-SPF-Override: pass (client 63.251.223.170 was found in trusted-forwarder.org, overrides regular SPF fail) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.170(x1.develooper.com) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP id 7A6C9A7555 - for ; Wed, 1 Sep 2004 10:57:06 -0400 (EDT) -Received: (qmail 5427 invoked by uid 225); 1 Sep 2004 14:57:04 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 5403 invoked by alias); 1 Sep 2004 14:57:02 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 01 Sep 2004 07:56:59 -0700 -Received: by pallas.eruditorum.org (Postfix, from userid 33) - id 1FDD784C0F5; Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -Subject: [cpan #6245] Confirmed memory leak -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #6245 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -Date: Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -To: undisclosed-recipients: ; -Status: RO -Content-Length: 937 -Lines: 38 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -I Using : -1. SunOS 5.6 Generic_105181-33 sun4u sparc SUNW,Ultra-Enterprise - Perl 5.005_03 - DBI 1.37 - DBD-Oracle 1.14 - Oracle Release 8.1.5.0.0 - - -2. Linux 2.4.18-17.7.xsmp #1 SMP i686 - Perl 5.6.1 - DBI 1.41 - DBD-Oracle 1.16 - Oracle Release 8.1.6.0.0 - -II The following code: - -use strict; -use DBI; - -foreach ( 1 .. 100 ) { - my $dbh = DBI->connect( 'dbi:Oracle:host=****', '***', '***' ); - $dbh->disconnect(); - sleep(1) -} - -III Leak about 4K every 10 seconds - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8724 8720 2760 S 1.3 3.4 0:01 perl - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8736 8732 2760 S 0.7 3.4 0:01 perl - diff --git a/err_build/err_solarisnotes.msg b/err_build/err_solarisnotes.msg deleted file mode 100644 index eaddc475..00000000 --- a/err_build/err_solarisnotes.msg +++ /dev/null @@ -1,482 +0,0 @@ -From SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com Wed Dec 22 08:11:00 2004 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id iBM8Aog0091816 - for ; Wed, 22 Dec 2004 08:11:00 GMT - (envelope-from SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 22 Dec 2004 08:11:00 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Ch0it-0001A5-Rv; - Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Ch0it-0001A5-Rv - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Ch0is-0000To-R8 - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id F0F0DFE10C; - Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 8B2AAFE1C3 - for ; Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Received-SPF: none (lime.pobox.com: domain of alexzar@zorranlabs.com does not designate permitted sender hosts) -Received: from penguin.nocdirect.com (penguin.nocdirect.com [69.73.160.206]) - by lime.pobox.com (Postfix) with ESMTP id 2B41BFE159 - for ; Wed, 22 Dec 2004 02:13:17 -0500 (EST) -Received: from localhost ([127.0.0.1]) - by penguin.nocdirect.com with esmtps (TLSv1:DES-CBC3-SHA:168) - (Exim 4.43) - id 1Cgz53-0000fj-Bx; Tue, 21 Dec 2004 23:30:37 -0600 -Date: Tue, 21 Dec 2004 23:30:35 -0600 (CST) -From: Alex Zarutin -X-X-Sender: zorranla@penguin.nocdirect.com -To: Tim Bunce -Cc: dbi-users-help@perl.org -Subject: Step-by-Step installation manual of DBD-Oracle-1.16 on Sparc Solaris - 9 with Oracle 9.2.0.1.0 client. -Message-ID: -MIME-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-AntiAbuse: This header was added to track abuse, please include it with any abuse report -X-AntiAbuse: Primary Hostname - penguin.nocdirect.com -X-AntiAbuse: Original Domain - pobox.com -X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] -X-AntiAbuse: Sender Address Domain - zorranlabs.com -X-Source: -X-Source-Args: -X-Source-Dir: -Status: RO -X-Status: A -Content-Length: 15603 -Lines: 426 - - -Hi Tim, - -I have spent a couple days trying to install DBD-Oracle-1.16 (all -required stuff, such as GCC, DBI, etc has been installed before ) on -Sun-Fire v240 running Spark Solaris 9 with the Oracle 9.2.0.1.0 client -installed. The installation takes a couple minutes ONLY after you spend -days trying to make it workable. - -I wrote the log of what I do, in order to do not waste my time in -future. I am pretty sure that this log will be very useful for people -installing DBD-Oracle on Solaris. I published it on my log page, and left -link on it at http://cpanratings.perl.org/d/DBD-Oracle review page. I -would recommend you to add this log to the readme file of your next -releases. Log is written very detailed (step-by-step) with highlighted -typical mistakes. - -Environment: -Hardware/OS: bash-2.05# uname -a -SunOS qadmz41 5.9 Generic_117171-08 sun4u sparc SUNW,Sun-Fire-V240 -OS is actually "standard" Solaris 9 installation came on the box from -SUN - -Oracle Client: Oracle 9.2.0.1.0 -GCC: gcc version 3.3.2, installed to /usr/local/bin as a package from -http://www.sunfreeware.com/programlistsparc9.html -PERL: perl v5.8.5 built for sun4-solaris, installed to /usr/local/bin as -a package from http://www.sunfreeware.com/programlistsparc9.html -DBI: DBI-1.45, installed from http://search.cpan.org/~timb/DBI-1.45/ - -Step-by-Step Manual: - -Step 1: In order to install "DBD-Oracle-1.16" you need to download it, -set all appropriate environment variables (see readme for details) and -run <>. -I got an error that is mostly typical for Solaris installation: - -// ************************ Error 1 ***********************/ - -.... -Found header files in rdbms/demo. - -********************************************************* -I can't find the header files I need in your Oracle installation. -You probably need to install some more Oracle components. -I'll keep going, but the compile will probably fail. -See README.clients for more information. -********************************************************* -Checking for functioning wait.ph - -System: perl5.008005 sunos 5.9 generic sun4u sparc sunw,ultra-5_10 -solaris -Compiler: gcc -B/usr/ccs/bin/ -O -fno-strict-aliasing -pipe --I/usr/local/include -I/opt/gnu/include -D_LARGEFILE_SOURCE --D_FILE_OFFSET_BITS=64 - -.... -// *****************************************************/ - -Investigating this problem, I found that error message is thrown by the -"find_headers" sub of Makefile.PL, especially in this "if -(!$h_file{'oratypes.h'} || !$h_file{'ocidfn.h'})" evaluation. -So I checked these files to make sure that they are installed, but did -not find them under $ORACLE_HOME/rdbms -In the same time, I found an article saying about the similar problem -with DBD-Oracle on Linux, -http://baroti.homedns.org/steve/lost+found/cpan-install-DBD-Oracle-9-2-l -inux.html -They mentioned about two files, and since I was not sure about second -one, ociapr.h I copied both files. You should find its public.1.1.jar -file on the Disk3 of Oracle 9i installation set. - -bash-2.05# pwd -/ora_orig/Disk3/stage/Components/oracle.rdbms.oci/9.2.0.1.0/1/DataFiles - -bash-2.05# ls -al -total 970 -drwxr-xr-x 2 2840 42424 512 Aug 21 2002 . -drwxr-xr-x 3 2840 42424 512 Aug 21 2002 .. --rwxr-xr-x 1 2840 42424 2047 May 9 2002 bin.1.1.jar --rwxr-xr-x 1 2840 42424 206 May 9 2002 build.1.1.jar --rwxr-xr-x 1 2840 42424 135034 May 9 2002 demo.1.1.jar --rwxr-xr-x 1 2840 42424 329814 May 9 2002 public.1.1.jar - -You should just (as dba:oracle) to create the directory called public, -copy public.1.1.jar there and extract all files, since I would not guess -if the rest of them are used or not - -bash-2.05# mkdir $ORACLE_HOME/rdbms/public - -bash-2.05# ls -al $ORACLE_HOME/rdbms/public -total 3404 -drwxr-xr-x 2 oracle dba 512 Dec 21 12:12 . -drwxr-xr-x 10 oracle dba 512 Dec 21 12:05 .. -... --rw-r--r-- 1 oracle dba 6055 Mar 9 2002 ociapr.h --rw-r--r-- 1 oracle dba 10694 Jun 29 2000 ocidfn.h -... - -After that run <> again, and I hope process passes -fine. At least, it was fine in my case - -Step 2: You should <> the module, and as it appears on Solaris, -you will get typical problem. See my error log: - -// ************************ Error 2 ***********************/ -.... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -ld: fatal: file -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib//libclntsh.so: -wrong ELF class: ELFCLASS64 -ld: fatal: File processing errors. No output written to -blib/arch/auto/DBD/Oracle/Oracle.so -collect2: ld returned 1 exit status -*** Error code 1 -make: Fatal error: Command failed for target -`blib/arch/auto/DBD/Oracle/Oracle.so' - -// *****************************************************/ - -So, as another set on Google' posts showed that it is a possibility of -missing libraries compiled with 64 bits and same libraries compiled with -32 bits suppoert. As I understood, all components of installation, such -as Oracle client, Perl, GCC should support only one type of libraries, -either 32 or 64 bits. I found that having all as 32 bits is easier to me -than recompile perl, gcc as 64 (may be I am wrong in this assumption). -In order to have all of them as 32 bits, I changed lib to lib32 in -Manifest file (not Manifest.PL). - -You should replace the following lines in the "MakeMaker const_loadlibs -section": - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -By their lib32 clones: - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -And replace this line in "MakeMaker dynamic_lib section" (~~ line 491) - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread - -By its lib32 clone: - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread - -I hope, that after that process passes without any errors. Here is last -part, that I got during <>: - -..... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/local/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL -ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/local/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" -blib/script/ora_explain -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oracle.3 -Manifying blib/man3/DBD::Oraperl.3 - -III. Once we build the module, we should test it, to make sure that it -works fine. You should run <> to do it: - -Check that you have ORACLE_HOME, ORACLE_USERID, ORACLE_SID environment -variables set, like this: - -ORACLE_HOME=="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0 -ORACLE_USERID=STARSHIP/STARSHIP -ORACLE_SID=COLORADO - -When you run <>, you will probably get this errors: - -// ************************ Error 3 ***********************/ - -bash-2.05# make test -PERL_DL_NONLAZY=1 /usr/local/bin/perl "-MExtUtils::Command::MM" "-e" -"test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............DBI connect('','STARSHIP/STARSHIP',...) failed: -ORA-12545: Connect failed because target host or object does not exist -(DBD ERROR: OCIServerAttach) at t/10general.t line 12 -Undefined subroutine &main::BAILOUT called at t/10general.t line 15. -# Looks like your test died before it could output anything. -t/10general.............dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-31 - Failed 31/31 tests, 0.00% okay -..... - -// *****************************************************/ - -One more brainstorm, and I figured out another way to set ORACLE_USERID: - -ORACLE_USERID=STARSHIP/STARSHIP@COLORADO -ORACLE_SID=COLORADO - -Later, when tests finished, I was confirmed that it was probably -preferred way of setting ORACLE_USERID. -Tests did found correct settings, and "main" set of them returned the -following report: - -All tests successful, 1 test and 122 subtests skipped. -Files=18, Tests=1020, 24 wallclock secs (11.27 cusr + 1.34 csys = 12.61 -CPU) - -For the Extra test, less formal, but test anyway, I just commented these -two lines in test.pl file - -$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -and set the same values in the same form to the $dbuser as it was in -ORACLE_USERID , and -left $dbname empty, - -$dbname = ''; -$dbuser = 'STARSHIP/STARSHIP@COLORADO'; - -and got pretty good report: - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - -recommended) - as 'STARSHIP/STARSHIP@COLORADO' (via ORACLE_USERID env var or default - -recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -Fields: 6 -Names: 'NUM_T' 'DATE_T' 'CHAR_T' 'ROWID_T' -'RAW_T' 'NULL_T' -Lengths: 172 76 121 21 3 1 -OraTypes: 2 12 1 104 23 1 -SQLTypes: 8 93 12 -9104 -2 12 -Scale: 0 0 0 0 0 0 -Precision: 126 75 120 20 2 0 -Nullable: 1 1 1 1 1 1 -Est row width: 32 -Data rows: - fetch: '7.2', '21-DEC-04', 'STARSHIP', 'AAAADeAABAAAAZSAAA', '7D', -undef - -ora_logoff... -lda out of scope... - -Testing repetitive connect/open/close/disconnect: -If this test hangs then read the README.help file. -Expect sequence of digits, no other messages: -1 2 3 4 5 - -Test interaction of explicit close/logoff and implicit DESTROYs -Expect just 'done.', no other messages: -done. - -Testing row cache (5). -Test completed in 0 seconds. - -Test complete (0 seconds). -If the tests above have produced the 'expected' output then they have -passed. - -IV. The last part is actually target of all steps above, installing -build module. < did not surprise me, and it it passed -smoothly. - -bash-2.05# make install -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/dbdimp -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/ocitra -ce.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/mk.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.so -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.bs -Files found in blib/arch: installing files in blib/lib into architecture -dependent library tree -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/oraperl.ph -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/Oraperl.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle/GetInfo.pm -Installing /usr/local/share/man/man1/ora_explain.1 -Installing /usr/local/share/man/man3/DBD::Oracle.3 -Installing /usr/local/share/man/man3/DBD::Oraperl.3 -Installing /usr/local/bin/ora_explain -Writing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/.packl -ist -Appending installation info to -/usr/local/lib/perl5/5.8.5/sun4-solaris/perllocal.pod - -V. This is actually it, and you do not need to do anything else. But -investigating different errors during the various steps, I found the -very simple "independent sanity" testdbi perl script written by Jeff -Hunter. This script is not related to standard process of -making/buildin/testing/installation. It just verifies that you can -access DB and run a couple queries against it. The code itself, -testdbi.pl can be found at -http://www.idevelopment.info/data/Oracle/DBA_tips/Programming/PROGRAMMIN -G_2.shtml - -You just should set connection information, similar to how I did it, - - $ORACLE_SID = "COLORADO"; - $ORACLE_USERID = "STARSHIP"; - $ORACLE_PASSWORD = "STARSHIP"; - - $ENV{'ORACLE_SID'} = "$ORACLE_SID"; - $ENV{'ORACLE_HOME'} = /u01/app/oracle/product/9.2.0.1.0"; - -run it as any perl script, <>, and see result: - -bash-2.05# perl testdbi.pl - -Running testdbi.pl... - - (*) Attempting Oracle Login ... - OK - (*) Creating table TEST_DBI ... - OK - (*) Insert into TEST_DBI ... - 1 rows inserted. - 1 rows inserted. - 1 rows inserted. - OK - (*) Select from TEST_DBI ... - - --> TEST_DBI_INTR_NO : 1000 - --> TEST_DBI_NAME : Jeff Hunter - - --> TEST_DBI_INTR_NO : 1001 - --> TEST_DBI_NAME : Melody Hunter - - --> TEST_DBI_INTR_NO : 1002 - --> TEST_DBI_NAME : Alex Hunter - OK - - (*) Delete from TEST_DBI ... - 3 rows deleted. - OK - - (*) Drop table TEST_DBI ... - OK - - (*) Select USER and SYSTEM ... - - --> USER : STARSHIP - --> SYSDATE : 21-DEC-2004 16:49:59 - OK - - (*) Attempting Oracle Logoff ... - OK - -Ending testdbi.pl... - -With the best regards, - -Alex Zarutin - -Software Engineer -4thpass A Motorola Company -Seattle, WA -www.4thpass.com - - - - diff --git a/err_build/err_testfailnotable.msg b/err_build/err_testfailnotable.msg deleted file mode 100644 index 687d5ed7..00000000 --- a/err_build/err_testfailnotable.msg +++ /dev/null @@ -1,97 +0,0 @@ -From SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 18:10:51 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RHAOAK026067 - for ; Wed, 27 Oct 2004 18:10:51 +0100 (BST) - (envelope-from SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 18:10:51 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMp30-0000e2-Hh; - Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMp30-0000e2-Hh - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMp30-0001QS-2p - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 87C155A7D; - Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 7779A59A1 - for ; Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Received-SPF: pass (gold.pobox.com: domain of dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by gold.pobox.com (Postfix) with SMTP id DC5795A4A - for ; Wed, 27 Oct 2004 10:45:07 -0400 (EDT) -Received: (qmail 18140 invoked by uid 514); 27 Oct 2004 14:45:04 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 18131 invoked from network); 27 Oct 2004 14:45:04 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 14:45:04 -0000 -Received: (qmail 8663 invoked by uid 225); 27 Oct 2004 14:45:03 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 8659 invoked by alias); 27 Oct 2004 14:45:03 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from ns2.aramiska.net (HELO dmzms01.aramiska.net) (80.242.32.2) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 07:45:01 -0700 -Received: from ip-80-242-36-115.aramiska-arc.aramiska.net (ip-80-242-36-115.aramiska-arc.aramiska.net [80.242.36.115]) - by dmzms01.aramiska.net (Postfix) with ESMTP - id 9F21E1100D9; Wed, 27 Oct 2004 14:44:55 +0000 (UTC) -Received: from localhost (localhost [127.0.0.1]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id E558E7C; Wed, 27 Oct 2004 14:44:52 +0000 (UTC) -Received: from dansat.data-plan.com (ip-192-168-0-3.internal.data-plan.aramiska.net [192.168.0.3]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id D8A5E71; Wed, 27 Oct 2004 14:44:50 +0000 (UTC) -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9REioAA023212; - Wed, 27 Oct 2004 15:44:50 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i9REinmW023211; - Wed, 27 Oct 2004 15:44:49 +0100 (BST) -Date: Wed, 27 Oct 2004 15:44:49 +0100 -From: Tim Bunce -To: "H.Merijn Brand" -Cc: Tim Bunce , DBI developers -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Message-ID: <20041027144449.GB19991@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> <20041027093516.D001.H.M.BRAND@hccnet.nl> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20041027093516.D001.H.M.BRAND@hccnet.nl> -User-Agent: Mutt/1.4i -X-Virus-Scanned: by Aramiska Arc -Status: RO -Content-Length: 634 -Lines: 14 - -On Wed, Oct 27, 2004 at 09:39:33AM +0200, H.Merijn Brand wrote: -> On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> > file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> > size: 235224 bytes -> > md5: 9711550ed0ebfc743920a6a357ed717c -> -> I know you can't blame the test for not being able to create a table for the -> reason this failure shows, but there might be a more user-friendly way to fail ... - -Yeap. Some tests behave better in that situation. Looks like those -two need improving. Patches welcome! (I'd happily not touch DBD::Oracle -for a few months after the pain of the last few months :) - -Tim. - diff --git a/err_docs/err_trace.msg b/err_docs/err_trace.msg deleted file mode 100644 index 3d7500fb..00000000 --- a/err_docs/err_trace.msg +++ /dev/null @@ -1,14 +0,0 @@ -Add this to the DBD::Oracle docs as a handy note: - -$dbh->do(q{alter session set events '65285 trace name errorstack level 3'}); - -A trace file should then be generated. - -Trace files are generated in the 'user_dump_destination' specified in init.ora. - -Try $ORACLE_BASE/admin/$ORACLE_SID/udump. - -or the location returned by -select value -from v$parameter -where name like '%user_dump%' diff --git a/err_lob/err_csr_clob.msg b/err_lob/err_csr_clob.msg deleted file mode 100644 index 397d53b3..00000000 --- a/err_lob/err_csr_clob.msg +++ /dev/null @@ -1,65 +0,0 @@ -From dbi-users-bounce@isc.org Thu Sep 21 20:27:21 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id UAA18945; Thu, 21 Sep 2000 20:27:20 +0100 (BST) -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <02709-1@oink>; Mon, 21 Sep 1970 20:26:40 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 969564156:20:26825:1; Thu, 21 Sep 2000 19:22:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-2.mail.demon.net - id aa2026778; 21 Sep 2000 19:22 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 28A613E5D; - Thu, 21 Sep 2000 12:22:17 -0700 (PDT) -Received: with LISTAR (v1.0.0; list dbi-users); - Thu, 21 Sep 2000 12:17:37 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A59853E42 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) -Received: from wheel.cs.wisc.edu (wheel.cs.wisc.edu [128.105.121.12]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA00855 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) env-from (horn@wheel.cs.wisc.edu) -Received: (from horn@localhost) by wheel.cs.wisc.edu (8.9.2/8.9.2) id OAA16413 - for dbi-users@isc.org; Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -Date: Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -From: Jeffrey Horn -Message-Id: <200009211917.OAA16413@wheel.cs.wisc.edu> -To: dbi-users@isc.org -Subject: Setting ORA_TYPE after the fact... -Sender: horn@wheel.cs.wisc.edu -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: horn@cs.wisc.edu -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -X-Status: A -Content-Length: 969 -Lines: 20 - -I have a situation where I would like to return a cursor that contains a -CLOB as one of it's attributes from a PL/SQL procedure. What I get back is -a LOB locator and DBD doesn't actually read the CLOB but instead returns an -error. - -If I go through a bind/prepare/execute/fetch on a similar SQL statement all -is well. Is there any way that I can tell DBD that a given attribute of -a cursor is a CLOB once the cursor is already opened so that DBD will do the -right thing? - --- Jeff Horn - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_lob/err_loblenwide.msg b/err_lob/err_loblenwide.msg deleted file mode 100644 index 08023e97..00000000 --- a/err_lob/err_loblenwide.msg +++ /dev/null @@ -1,95 +0,0 @@ -From nobody@fsck.com Thu Dec 4 07:36:20 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hB47Y2nE066844 - for ; Thu, 4 Dec 2003 07:36:20 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 04 Dec 2003 07:36:20 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1ARgrA-0005O4-5M; - Wed, 03 Dec 2003 23:56:32 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1ARgrA-0005O4-5M - for pobox@dbi.demon.co.uk; Wed, 03 Dec 2003 23:56:32 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 314AB9A28F - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 188369A287 - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com[63.251.223.170]) - by icicle.pobox.com (Postfix) with SMTP - for ; Wed, 3 Dec 2003 18:56:31 -0500 (EST) -Received: (qmail 3178 invoked by uid 225); 3 Dec 2003 23:56:30 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 3174 invoked by alias); 3 Dec 2003 23:56:29 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Wed, 03 Dec 2003 15:56:18 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 91512114F1; Wed, 3 Dec 2003 18:56:07 -0500 (EST) -Subject: [cpan #4564] Perl DBI bug handling CLOBs -From: "Jay Turner via RT" -Reply-To: bug-DBI@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4564 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: J.Turner@mdl.com -To: "AdminCc of cpan Ticket #4564": ; -Date: Wed, 3 Dec 2003 18:56:07 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -X-Status: A -Content-Length: 1853 -Lines: 46 - - -This message about DBI was sent to you by J.Turner@mdl.com via rt.cpan.org - -Full context and any attached attachments can be found at: - - - -Date: Fri, 28 Feb 2003 16:55:28 -0800 - -It has come to my attention that PERL DBI counts on OCILobGetLength -returning BYTES. It returns CHARACTERS instead, which is the count of -variable-width characters. For multi-byte character sets this results -in errors such as: - -DBD::Oracle::st fetch failed: ORA-03130: the buffer for the next piece -to be fetched is required (DBD ERROR: OCILobGetLength) at id rmsc01.pl -line 294. - -The correct way to read CLOBs is - -1) Query the LOB locator for the CSID and CSFRM (character set ID and -form). A character set >= 800 is a mulitbyte character set and csfrm -<> 0 is CLOB. - -2) Pass the CSID and CSFRM to OCILobRead with AMT=0 and pass your -buffer address and size. - -3) Your callback routine must either be capable of completing the I/O -by allocating additional buffers, or it must notify the caller of -OCILobRead to free the lob locator, since an incomplete read jams the -locator-you can't use it for anything else without finishing the read -(attempts to reuse the locator will result in errors). - -Likewise, with OCILobWrite, you have to pass the CSID and CSFRM, with -AMT=0 and the buffer size in bytes. The callback can just say it has -zero bytes and set piece=OCI_LAST_PIECE. - -You cannot use the return value of OCILobGetLength as the size of the -data that is being read. The actual size of the data is unknown for -variable-width characters, and the buffer has to be big enough to -accomplish the translation, so you can't just double or triple the -return value from OCILobGetLength (I have seen that approach fail). - -You can simulate the effects of a foreign character set by - -$ export NLS_LANG=Japanese - diff --git a/err_lob/err_lobtesttblfail.msg b/err_lob/err_lobtesttblfail.msg deleted file mode 100644 index 1333ee88..00000000 --- a/err_lob/err_lobtesttblfail.msg +++ /dev/null @@ -1,208 +0,0 @@ -From SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 15:22:22 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RELAAO018624 - for ; Wed, 27 Oct 2004 15:22:22 +0100 (BST) - (envelope-from SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 15:22:22 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMiQ8-0000Eo-FG; - Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMiQ8-0000Eo-FG - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMiQ8-0006dS-9n - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B3BB911C325; - Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9947911C2CE - for ; Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Received-SPF: pass (icicle.pobox.com: domain of dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by icicle.pobox.com (Postfix) with SMTP id 5033611C34F - for ; Wed, 27 Oct 2004 03:39:46 -0400 (EDT) -Received: (qmail 12004 invoked by uid 514); 27 Oct 2004 07:39:43 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 11995 invoked from network); 27 Oct 2004 07:39:43 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 07:39:43 -0000 -Received: (qmail 13565 invoked by uid 225); 27 Oct 2004 07:39:43 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 13560 invoked by alias); 27 Oct 2004 07:39:42 -0000 -X-Spam-Status: No, hits=-3.7 required=8.0 - tests=BAYES_00,LARGE_HEX -X-Spam-Check-By: la.mx.develooper.com -Received: from smtp-vbr15.xs4all.nl (HELO smtp-vbr15.xs4all.nl) (194.109.24.35) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 00:39:40 -0700 -Received: from [127.0.0.1] (procura.xs4all.nl [213.84.163.145]) - by smtp-vbr15.xs4all.nl (8.12.11/8.12.11) with ESMTP id i9R7dWHI013040; - Wed, 27 Oct 2004 09:39:34 +0200 (CEST) - (envelope-from h.m.brand@hccnet.nl) -Date: Wed, 27 Oct 2004 09:39:33 +0200 -From: "H.Merijn Brand" -To: Tim Bunce -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Cc: DBI developers -In-Reply-To: <20041022213625.GA22377@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> -Message-Id: <20041027093516.D001.H.M.BRAND@hccnet.nl> -MIME-Version: 1.0 -Content-Type: text/plain; charset="US-ASCII" -X-Mailer: Becky! ver. 2.11.02 [en] -X-Virus-Scanned: by XS4ALL Virus Scanner -X-Virus-Checked: Checked -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i9RELAAO018624 -Status: RO -X-Status: A -Content-Length: 7175 -Lines: 134 - -On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> size: 235224 bytes -> md5: 9711550ed0ebfc743920a6a357ed717c - -I know you can't blame the test for not being able to create a table for the -reason this failure shows, but there might be a more user-friendly way to fail ... - -I'll report back when the DBA has fixed the tablespace - -HP-UX 11.11/64 (11i) + Oracle-9.2.0/64 + perl-5.8.5-dor/64 - -PERL_DL_NONLAZY=1 /pro/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, -'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............ok -t/15nls.................ok -t/20select..............ok -t/21nchar............... Database and client versions and character sets: -Database 9.2.0.1.0 CHAR set is US7ASCII (Non-Unicode), NCHAR set is AL16UTF16 ( -nicode) -Client 9.2.0.1 NLS_LANG is '', NLS_NCHAR is '' -t/21nchar...............ok -t/22nchar_al32utf8......ok -t/22nchar_utf8..........ok -t/23wide_db.............skipped - all skipped: Database character set is not Unicode -t/23wide_db_8bit........skipped - all skipped: Database character set is not Unicode -t/23wide_db_al32utf8....skipped - all skipped: Database character set is not Unicode -t/24implicit_utf8.......ok -t/25plsql...............ok -t/30long................ok 188/470DBD::Oracle::db do failed: ORA-03237: Initial -Extent of specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: -OCIStmtExecute) [for Statement "create table dbd_ora__drop_me ( idx integer, ln - NCLOB, dt date )"] at t/nchar_test_lib.pl line 356. -t/30long................ok 189/470DBD::Oracle::st execute failed: ORA-00942: ta -le or view does not exist (DBD ERROR: error possibly near <*> indicator at char -12 in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statem -nt "insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1= -0, :p2='0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X...'] at t/30long.t line 153. -# Failed test (t/30long.t at line 153) -t/30long................NOK 190DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=41, -:p2='12345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -...'] at t/30long.t line 154. -# Failed test (t/30long.t at line 154) -t/30long................NOK 191DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=42, -:p2='2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -...'] at t/30long.t line 155. -t/30long................NOK 192# Failed test (t/30long.t at line 155) -DBD::Oracle::st execute failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 12 in 'insert into <*>dbd_ora__dr -p_me values (:p1, :p2, SYSDATE)') [for Statement "insert into dbd_ora__drop_me -alues (?, ?, SYSDATE)" with ParamValues: :p1=43, :p2=undef] at t/30long.t line -56. -# Failed test (t/30long.t at line 156) -t/30long................NOK 193DBD::Oracle::db prepare failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 14 -in 'select * from <*>dbd_ora__drop_me order by idx') [for Statement "select * f -om dbd_ora__drop_me order by idx"] at t/30long.t line 170. -# Failed test (t/30long.t at line 170) -Can't call method "trace" on an undefined value at t/30long.t line 171. -t/30long................NOK 194# Looks like you planned 470 tests but only ran -94. -# Looks like your test died just after 194. -t/30long................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 190-470 - Failed 281/470 tests, 40.21% okay (less 122 skipped tests: 67 okay, 14. -6%) -t/31lob.................DBD::Oracle::db do failed: ORA-03237: Initial Extent of -specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: OCIStmtEx -cute) [for Statement " - CREATE TABLE dbd_ora__drop_me ( - id INTEGER NOT NULL, - data BLOB - ) - "] at t/31lob.t line 21. -DBD::Oracle::db do failed: ORA-00942: table or view does not exist (DBD ERROR: -rror possibly near <*> indicator at char 12 in 'INSERT INTO <*>dbd_ora__drop_me -(id,data) VALUES (1, EMPTY_BLOB())') [for Statement "INSERT INTO dbd_ora__drop_ -e (id,data) VALUES (1, EMPTY_BLOB())"] at t/31lob.t line 31. -DBD::Oracle::db prepare failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 17 in 'SELECT data FROM <*>dbd_or -__drop_me WHERE id = :p1') [for Statement "SELECT data FROM dbd_ora__drop_me WH -RE id = ?"] at t/31lob.t line 34. -Can't call method "bind_param" on an undefined value at t/31lob.t line 36. -# Looks like your test died before it could output anything. -t/31lob.................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-2 - Failed 2/2 tests, 0.00% okay -t/40ph_type.............ok -t/50cursor..............ok -t/60reauth..............ORACLE_USERID_2 not defined. Tests skipped. -skipped - all skipped: no reason given -t/70meta................ok -Failed Test Stat Wstat Total Fail Failed List of Failed -------------------------------------------------------------------------------- -t/30long.t 255 65280 470 557 118.51% 190-470 -t/31lob.t 255 65280 2 4 200.00% 1-2 -4 tests and 122 subtests skipped. -Failed 2/18 test scripts, 88.89% okay. 283/1883 subtests failed, 84.97% okay. -make: *** [test_dynamic] Error 255 - --- -H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/) -using perl-5.6.1, 5.8.0 & 633 on HP-UX 10.20 & 11.00, AIX 4.2, AIX 4.3, - WinNT 4, Win2K pro & WinCE 2.11 often with Tk800.024 &/| DBD-Unify -ftp://ftp.funet.fi/pub/languages/perl/CPAN/authors/id/H/HM/HMBRAND/ - - - - diff --git a/err_lob/err_nclob_form.msg b/err_lob/err_nclob_form.msg deleted file mode 100644 index 05587693..00000000 --- a/err_lob/err_nclob_form.msg +++ /dev/null @@ -1,189 +0,0 @@ -From dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org Tue Jul 22 07:40:59 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6M6UUD7096422 - for ; Tue, 22 Jul 2003 07:40:58 +0100 (BST) - (envelope-from dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 22 Jul 2003 07:40:58 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058814697:11:26523:33; Mon, 21 Jul 2003 19:11:37 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1126786; 21 Jul 2003 19:11 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E855B21C37F - for ; Mon, 21 Jul 2003 15:11:18 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 9010121C236 - for ; Mon, 21 Jul 2003 15:11:17 -0400 (EDT) -Received: (qmail 66848 invoked by uid 1005); 21 Jul 2003 19:11:15 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 66832 invoked by uid 76); 21 Jul 2003 19:11:15 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 21 Jul 2003 12:11:15 -0700 -Received: (qmail 559 invoked by uid 225); 21 Jul 2003 19:11:08 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 552 invoked by uid 507); 21 Jul 2003 19:11:07 -0000 -Received-SPF: unknown -Received: from sneakemail.com (HELO monkey.sneakemail.com) (207.106.87.13) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Mon, 21 Jul 2003 12:11:03 -0700 -Received: (qmail 22505 invoked by uid 501); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #3); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #2); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #1); 21 Jul 2003 19:10:57 -0000 -Date: Mon, 21 Jul 2003 21:10:53 +0200 -From: "Wolfgang Weisselberg" -To: dbi-users@perl.org -Subject: DBD::Oracle and unicode-NCLOBs leads to ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) -Message-ID: <13502-46198@sneakemail.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.6 required=7.0 tests=CARRIAGE_RETURNS,FROM_ENDS_IN_NUMS,FROM_HAS_MIXED_NUMS,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_MUTT version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 6055 -Lines: 132 - -Hello all! - -Even after extensive googling and looking through the docs I fail -to fetch NCLOBs from an Oracle 9.2i database where the national -character set is unicode. - -I believe it has been done before, but I could not find anything ... -I would be grateful for any pointers. - - -NCLOBs work like CLOBs when the national character set is not -unicode, even with the old DBI 1.21 and DBD::Oracle 1.12 on an -Oracle 8 client. NVarchar2 and NChar work OK even with unicode. - -Setting NSL_LANG to AMERICAN_AMERICA.UTF8 or .AL32UTF8 does not -help, as I suspected. - -I tried using Oracle 9.2i (the DB is using 9.2i) on a Debian -Linux box. I upgraded DBI to 1.37 and DBD::Oracle to 1.14 (the -newest versions according to CPAN). I got zero errors on make -test with both. Perl is Debian's normal "perl5 (revision 5.0 -version 6 subversion 1)". - -A simple - select memo from unicode_test -(memo being the NCLOB field) fails (again, only with the national -charset being unicode). - -The relevant code snippet (RaiseError being set, of course): - -| $| = 1; -| print "DBI: $DBI::VERSION\n", -| "DBD::Oracle $DBD::Oracle::VERSION\n"; -| my $sth = $dbh->prepare("select memo from unicode_test"); -| $sth->execute(); -| -| while ( my ($memo) = $sth->fetchrow_array() ) { -| print Dumper $memo; -| } -| exit; - - -The output: - -| DBI: 1.37 -| DBD::Oracle 1.14 -| $VAR1 = ''; -| $VAR1 = ''; -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. - - - -Running with tracelevel 3: - [...] -| dbd_st_prepare'd sql SELECT -| dbd_describe SELECT (EXPLICIT, lb 99999999)... -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_execute SELECT (out0, lob0)... -| dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -| <- execute= '0E0' at nclobtest.pl line 79 via nclobtest.pl line 60 -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -| 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x82f8e28)~INNER 'ParamValues') -| error: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| 1 <- FETCH= HASH(0x831661c)0keys at nclobtest.pl line 81 via nclobtest.pl line 60 -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. - - - -Tracelevel 9 (yes, it's a bit verbose :-/ ) - -[...] -| OCIDescriptorAlloc(0x831c058,0x8395228,OCI_DTYPE_LOB,0,0) -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| OCIAttrSet(0x8335b34,OCI_HTYPE_STMT,0xbffff30c,4,11,0x832d5a4)=SUCCESS -| OCIDefineByPos(0x8335b34,0x8395224,0x832d5a4,1,0x8395228,-1,112,0x83414e0,0x83414f0,0x8341500,0)=SUCCESS -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -[...] -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| 0 (rc=0): '' -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead(0x832d530,0x832d5a4,0x832c69c,0xbffff318,1,0x8394da0,24,(nil),(nil),0,1)=ERROR -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| OCIErrorGet(0x832d5a4,1,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=SUCCESS -| OCIErrorGet after OCILobRead (er1:ok): -1, 24806: ORA-24806: LOB form mismatch -| -| OCIErrorGet(0x832d5a4,2,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=NO_DATA -| 0 (rc=0): undef -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -[gets and prints error message] - - -Any ideas anyone? - --Wolfgang - diff --git a/err_lob/err_nulllobsegv.msg b/err_lob/err_nulllobsegv.msg deleted file mode 100644 index 6de3c99b..00000000 --- a/err_lob/err_nulllobsegv.msg +++ /dev/null @@ -1,93 +0,0 @@ -From dbi-users-return-1743-Tim.Bunce=ig.co.uk@perl.org Wed Apr 11 04:00:48 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id EAA17912; Wed, 11 Apr 2001 04:00:48 +0100 (BST) -Received: from 194.217.242.36 by oink with SMTP (PP) id <02579-1@oink>; - Sat, 11 Apr 1970 04:00:28 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 986956750:10:04398:0; Wed, 11 Apr 2001 02:39:10 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-1.mail.demon.net - id aa1106187; 11 Apr 2001 2:39 GMT -Received: (qmail 32618 invoked by uid 508); 11 Apr 2001 02:39:06 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 32603 invoked from network); 11 Apr 2001 02:39:05 -0000 -Received: from owns.warpcore.org (216.81.249.18) by tmtowtdi.perl.org with SMTP; - 11 Apr 2001 02:39:05 -0000 -Received: (from thebrain@localhost) by owns.warpcore.org (8.11.1/8.11.1) - id f3B2cxH06298 for dbi-users@perl.org; - Tue, 10 Apr 2001 21:38:59 -0500 -Date: Tue, 10 Apr 2001 21:38:59 -0500 -From: Stephen Clouse -To: dbi-users@perl.org -Subject: Bizarre DBD::Oracle Segfault -Message-ID: <20010410213859.B2766@owns.warpcore.org> -Mail-Followup-To: dbi-users@perl.org -Mime-Version: 1.0 -Content-Type: text/plain -Content-Disposition: inline; filename="msg.pgp" -User-Agent: Mutt/1.2.5i -Status: RO -Content-Length: 1918 -Lines: 54 - ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -I sent an email to the dbi-users list about a number of DBD::Oracle CLOB -handling problems waaaaaaaaaaaaaaay back (end of January or so) that today -someone dug up and inquired if I had ever found fixes for what I had pointed -out. - -The problems outlined that day turned out to be the test script itself, which -was doing so much bizarre stuff on one statement that DBD::Oracle just went to -sleep instead (and so was the actual program that instigated the writing of the -test script). - -Well, all but one problem was the script. This, the most serious one, continues -to linger: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',undef); - -On Linux, DBI 1.15, Oracle 8.1.6, and DBD::Oracle 1.06, this segfaults on the -execute. Unfortunately this manifests itself too deep in Oracle for me to -debug. - -The bizarre part is, either of the two snippets below will work: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',''); -$st->execute('B','B',undef); - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',$lobvalue); -$st->execute('B','B',undef); - -It's only when binding undef as the LOB value in the very first execute of a -statement that the segfault occurs. At any other time, it's kosher. That -qualifies as bizarre in my book. - -Your guess is better than mine. - -- -- -Stephen Clouse -Senior Programmer, IQ Coordinator Project Lead -The IQ Group, Inc. - ------BEGIN PGP SIGNATURE----- -Version: PGP 6.5.8 - -iQA+AwUBOtPDwgOGqGs0PadnEQLmtgCeJHTStLu8Q8oFb9UQ4995f8vhZH8Al1p6 -RD5m0FEJH2tQiY0+b6542mQ= -=L0M+ ------END PGP SIGNATURE----- - diff --git a/err_lob/err_tmplobfree.msg b/err_lob/err_tmplobfree.msg deleted file mode 100644 index 0ec8f940..00000000 --- a/err_lob/err_tmplobfree.msg +++ /dev/null @@ -1,537 +0,0 @@ -From SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com Wed Aug 25 17:53:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PGpkpQ033405 - for ; Wed, 25 Aug 2004 17:53:57 +0100 (BST) - (envelope-from SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 17:53:57 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Bzyve-0007kY-Gp; - Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Bzyve-0007kY-Gp - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Bzyvd-0000zb-Lg - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id AA6D8B0635; - Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 9B2A1B0BB0 - for ; Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -Received: from natnoddy.rzone.de (natnoddy.rzone.de [81.169.145.166]) - by lime.pobox.com (Postfix) with ESMTP id 2AAB1B0635 - for ; Wed, 25 Aug 2004 10:39:06 -0400 (EDT) -Received: from genericom.de (pD95195AC.dip.t-dialin.net [217.81.149.172]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7PEc05w018990 - for ; Wed, 25 Aug 2004 16:38:01 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412CA445.FC2F9EF2@genericom.de> -Date: Wed, 25 Aug 2004 16:37:57 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim.Bunce@pobox.com -Subject: DBD::Oracle: Freeing a temporary blob -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms4BC2D4519D41A502BB06559C" -Status: RO -X-Status: A -Content-Length: 4985 -Lines: 122 - -This is a cryptographically signed message in MIME format. - ---------------ms4BC2D4519D41A502BB06559C -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Dear Tim, - -first, I would really like to thank you for the great work you have done -with your DBI/DBD work. We are using it extensively in several projects -and we are highly pleased. - -Unfortunately I have now encountered a problem we need to fix urgently, -since our customer's production is seriously affected. - -We tried for many days to find a solution (google, newsgroups, -trial-and-error...), without luck. So my last chance is to contact you -directly, although I assume you have a lot work yourself. - ---- - -The problem: - -Our database contains a stored function "ReadUnitBlob()" that returns a -temporary blob: - -function ReadUnitBlob(UnitID_IN in integer) return blob -is -... -begin - ... - dbms_lob.createtemporary(retBlob, false, dbms_lob.call); - dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); - ... - return retBlob; -end; - -We call this function in Perl in a big loop to fetch a lot of blobs (~ -100000) using something like: - -my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -ora_auto_lob => 0 }); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); -my ($loc) = $sth->fetchrow_array(); -$sth->finish(); -... -while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) - ... - -Although this works, it has a big disadvantage: Oracle does not -automaticaly free the temporary blob, so it shortly runs out of temp. -space. (confirmed with "select * from v$temporary_lobs"). - -Acording to the Oracle docs this can be we solved by implicitly freeing -the temp. blob, e.g. by calling the PLSQL method -"dbms_lob.freetemporary()". I tried differnt ways to do this with -DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -locator from the my stored procedure and to pass it to a call of -"dbms_lob.freetemporary()": - -my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -ora_auto_lob => 0 }); -my $bloc; -$sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); - -obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) - -Can you help me??? Do you know a way how to free the temp. blob using -DBD::Oracle (using Oracle::OCI is not possible, since the customer is -strinctly refusing to install it). - -Otherwise, would it be possible include an additional DBD::Oracle LOB -Locator Method "ora_lob_freetemporary()" that warps -"OCILobFreeTemporary" ? - -Any help is really appreciated! - -Greeting from Germany, - - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------ms4BC2D4519D41A502BB06559C -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjUxNDM3NThaMCMGCSqG -SIb3DQEJBDEWBBS+u38esQAv19TdNkv4jgxlzsRqSzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAJQgoN5ASnyjnB7bgrv1+V7Cu4ULKe1CkHs0IEZaB -KuJcm98U7kskRyC5g6YNopuJxFbr19K3q5rrJGoUscKjiw== ---------------ms4BC2D4519D41A502BB06559C-- - - -From SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com Wed Aug 25 22:47:05 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PLjxpJ037568 - for ; Wed, 25 Aug 2004 22:47:04 +0100 (BST) - (envelope-from SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 22:47:04 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C04j1-00038v-Pz; - Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C04j1-00038v-Pz - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C04j0-00002I-FU - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:30 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AD1815463; - Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 85FFF55E7 - for ; Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Received-SPF: none (gold.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail04.svc.cra.dublin.eircom.net (mail04.svc.cra.dublin.eircom.net [159.134.118.20]) - by gold.pobox.com (Postfix) with SMTP id 14C005463 - for ; Wed, 25 Aug 2004 16:50:25 -0400 (EDT) -Received: (qmail 5678 messnum 5046341 invoked from network[213.94.228.233/unknown]); 25 Aug 2004 20:50:23 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail04.svc.cra.dublin.eircom.net (qp 5678) with SMTP; 25 Aug 2004 20:50:23 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PKsrof034865; - Wed, 25 Aug 2004 21:54:53 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7PKsqas034864; - Wed, 25 Aug 2004 21:54:52 +0100 (BST) -Date: Wed, 25 Aug 2004 21:54:52 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim.Bunce@pobox.com -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040825205452.GC34655@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412CA445.FC2F9EF2@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 4674 -Lines: 124 - -On Wed, Aug 25, 2004 at 04:37:57PM +0200, Philipp Lang wrote: -> Dear Tim, -> -> first, I would really like to thank you for the great work you have done -> with your DBI/DBD work. We are using it extensively in several projects -> and we are highly pleased. - -Thanks Philipp! - -> Unfortunately I have now encountered a problem we need to fix urgently, -> since our customer's production is seriously affected. -> -> We tried for many days to find a solution (google, newsgroups, -> trial-and-error...), without luck. So my last chance is to contact you -> directly, although I assume you have a lot work yourself. - -I am very busy and what little spare time I have for DBD::Oracle -is going into trying to get 1.16 released (which is proving to be -hard as we're tripping over Oracle bugs when an Oracle 8 client -talks to an Oracle 9+ server.) It's a major release that will help -many people so I need to give that priority. - -Separately I am exploring ways to fund DBI and DBD::Oracle development -so I can devote more time to it. There's is much that needs to be -done and much more that could be done beyond that. - -The Perl Foundation (TPF) have setup a way for people and companies -to make donations for DBI development [as yet unannounced so please -keep to yourself]. A note on the contribution could indicate that the -donor would like it used for a particular purpose, such as DBD::Oracle. - -Anyway, to cut a long story short, it would be much easier to devote -time to this if it could be funded in some way. - -I think the TPF setup is working so it could be done that way. -Alternatively you could contract me to do the work for you. -That would be quicker and simpler for you as TPF's non-profit -status doesn't make a difference to European donors. - -My standard daily rate for add-hoc consulting is 1600 Euro. -I'd expect to be able to sort this out inside a day, and prefer -fixed-price quotes anyway, so would 1600 Euro be okay? - -Of course, if you feel your company would like to either -make a general contribution to DBI/DBD::Oracle development beyond -that, or to fund the development of specific functionality that -would be of extra value to you then I'd be happy to talk about that. - -I hate asking for money, and would much rather dig into the code and -reply with a patch, but it's just not practical for me now. Sorry. - -Tim. - -> --- -> -> The problem: -> -> Our database contains a stored function "ReadUnitBlob()" that returns a -> temporary blob: -> -> function ReadUnitBlob(UnitID_IN in integer) return blob -> is -> ... -> begin -> ... -> dbms_lob.createtemporary(retBlob, false, dbms_lob.call); -> dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); -> ... -> return retBlob; -> end; -> -> We call this function in Perl in a big loop to fetch a lot of blobs (~ -> 100000) using something like: -> -> my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -> ora_auto_lob => 0 }); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> my ($loc) = $sth->fetchrow_array(); -> $sth->finish(); -> ... -> while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) -> ... -> -> Although this works, it has a big disadvantage: Oracle does not -> automaticaly free the temporary blob, so it shortly runs out of temp. -> space. (confirmed with "select * from v$temporary_lobs"). -> -> Acording to the Oracle docs this can be we solved by implicitly freeing -> the temp. blob, e.g. by calling the PLSQL method -> "dbms_lob.freetemporary()". I tried differnt ways to do this with -> DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -> locator from the my stored procedure and to pass it to a call of -> "dbms_lob.freetemporary()": -> -> my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -> ora_auto_lob => 0 }); -> my $bloc; -> $sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> -> obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) -> -> Can you help me??? Do you know a way how to free the temp. blob using -> DBD::Oracle (using Oracle::OCI is not possible, since the customer is -> strinctly refusing to install it). -> -> Otherwise, would it be possible include an additional DBD::Oracle LOB -> Locator Method "ora_lob_freetemporary()" that warps -> "OCILobFreeTemporary" ? -> -> Any help is really appreciated! -> -> Greeting from Germany, -> -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - -From SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com Thu Aug 26 14:06:45 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QD6Som051890 - for ; Thu, 26 Aug 2004 14:06:45 +0100 (BST) - (envelope-from SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 14:06:45 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0HX2-0003PB-Sd; - Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0HX2-0003PB-Sd - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0HX2-0003BR-F8 - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id DC4BFB0D27; - Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id CE95AB0D7D - for ; Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 81.169.145.165(natsmtp00.rzone.de) -Received: from natsmtp00.rzone.de (natsmtp00.rzone.de [81.169.145.165]) - by lime.pobox.com (Postfix) with ESMTP id 71107B0D27 - for ; Thu, 26 Aug 2004 06:30:56 -0400 (EDT) -Received: from genericom.de (pD9E61E09.dip.t-dialin.net [217.230.30.9]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7QAUoTY009695 - for ; Thu, 26 Aug 2004 12:30:51 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412DBBD7.2C124831@genericom.de> -Date: Thu, 26 Aug 2004 12:30:47 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------msB92907D67E7D4C0121D50420" -Status: O -X-Status: A -Content-Length: 3040 -Lines: 58 - -This is a cryptographically signed message in MIME format. - ---------------msB92907D67E7D4C0121D50420 -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Tim Bunce wrote: -> -> I hate asking for money, and would much rather dig into the code and -> reply with a patch, but it's just not practical for me now. Sorry. - -Thanks for your quick reply. I can fully understand your position in -this issue. We will need to submit this issue to our customer, and -eventually it will be their decision, since a) the problem technically -originates in external components -and b) our work is payed on a time and material basis. - -Thanks again, - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------msB92907D67E7D4C0121D50420 -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjYxMDMwNDhaMCMGCSqG -SIb3DQEJBDEWBBQbWUdl+peoD/lHpzCOnuQfzAsbJzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAXzFame8ymLqgf+7nZ4V7L9e9J+aG6z5ipa+iv76v -EFAg5QObdHdvTnq5QEAjEnLKgeUGvdgpS6PA0h+beEIeIA== ---------------msB92907D67E7D4C0121D50420-- - - -From SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com Thu Aug 26 16:42:55 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QFgKp1054926 - for ; Thu, 26 Aug 2004 16:42:55 +0100 (BST) - (envelope-from SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 16:42:55 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0L1E-0005sL-5Z; - Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0L1E-0005sL-5Z - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0L1E-0001t1-Cm - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 541E8AFAD6; - Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 1C39FB0747 - for ; Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail01.svc.cra.dublin.eircom.net (mail01.svc.cra.dublin.eircom.net [159.134.118.17]) - by lime.pobox.com (Postfix) with SMTP id BFBB5AFAD6 - for ; Thu, 26 Aug 2004 10:14:19 -0400 (EDT) -Received: (qmail 12246 messnum 7731352 invoked from network[213.94.228.233/unknown]); 26 Aug 2004 14:14:17 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail01.svc.cra.dublin.eircom.net (qp 12246) with SMTP; 26 Aug 2004 14:14:17 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QEItof052863; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7QEItr3052862; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) -Date: Thu, 26 Aug 2004 15:18:55 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040826141855.GC52359@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> <412DBBD7.2C124831@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412DBBD7.2C124831@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 926 -Lines: 25 - -Okay. Thanks. Let me know how it turns out. - -Tim. - -On Thu, Aug 26, 2004 at 12:30:47PM +0200, Philipp Lang wrote: -> Tim Bunce wrote: -> > -> > I hate asking for money, and would much rather dig into the code and -> > reply with a patch, but it's just not practical for me now. Sorry. -> -> Thanks for your quick reply. I can fully understand your position in -> this issue. We will need to submit this issue to our customer, and -> eventually it will be their decision, since a) the problem technically -> originates in external components -> and b) our work is payed on a time and material basis. -> -> Thanks again, -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - diff --git a/err_unicode/err_char.msg b/err_unicode/err_char.msg deleted file mode 100644 index d2a7a4a3..00000000 --- a/err_unicode/err_char.msg +++ /dev/null @@ -1,129 +0,0 @@ -From dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org Fri May 31 15:39:50 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g4VEdno73229 - for ; Fri, 31 May 2002 15:39:49 +0100 (BST) - (envelope-from dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 31 May 2002 15:39:49 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1022854157:20:06570:1; Fri, 31 May 2002 14:09:17 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2005972; 31 May 2002 14:08 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 210F42BF43 - for ; Fri, 31 May 2002 10:08:39 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (unknown [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 8D88B2BF11 - for ; Fri, 31 May 2002 10:08:38 -0400 (EDT) -Received: (qmail 47355 invoked by uid 1005); 31 May 2002 14:07:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 47340 invoked by uid 76); 31 May 2002 14:07:41 -0000 -Received: from wsrgeh.wsr.ac.at (HELO wsrgeh.wsr.ac.at) (143.130.16.2) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Fri May 31 14:07:41 2002 -0000 -Received: from dialog.wsr.ac.at (dialog.wsr.ac.at [143.130.50.66]) - by wsrgeh.wsr.ac.at (8.11.6/8.11.6) with ESMTP id g4VE8Or11772 - for ; Fri, 31 May 2002 16:08:24 +0200 -Received: (from hjp@localhost) - by dialog.wsr.ac.at (8.11.6/8.11.6) id g4VE8Nf12538 - for dbi-users@perl.org; Fri, 31 May 2002 16:08:23 +0200 -Date: Fri, 31 May 2002 16:08:23 +0200 -From: "Peter J. Holzer" -To: dbi-users@perl.org -Subject: Re: Insert a blank value into Oracle -Message-ID: <20020531160823.F28779@wsr.ac.at> -Mail-Followup-To: "Peter J. Holzer" , - dbi-users@perl.org -References: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw> -Mime-Version: 1.0 -Content-Type: multipart/signed; micalg=pgp-md5; - protocol="application/pgp-signature"; boundary="aZoGpuMECXJckB41" -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -In-Reply-To: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw>; from larry_wu@mail.gss.com.tw on Fri, May 31, 2002 at 06:38:45PM +0800 -Status: RO -Content-Length: 2819 -Lines: 74 - ---aZoGpuMECXJckB41 -Content-Type: text/plain; charset=iso-8859-1 -Content-Disposition: inline -Content-Transfer-Encoding: quoted-printable - -On 2002-05-31 18:38:45 +0800, Larry Wu (=A7d=A4l=B7=D3) wrote: -> I encountered a problem to insert a space value ( like ' ' ) into Oracle -> database. -[...] -> Unfortunately, I have a table A contained a not allow null column -> NotNullCol. Now I want to insert a row like below: ->=20 -> $sth =3D $dbh->prepare( qq{ insert into A ( KeyCol, NotNullCol ) -> values (?,?)} ); -> $sth->bind_param(1, '1'); -> $sth->bind_param(2, ' '); -> $sth->execute; ->=20 -> When I executed this file I got an error from Oracle: Can't insert NULL -> value into ( "A"."NotNullCol") (DBD ERROR: OCIStmtExecute). -> I think the space value was truncated in the process. Could any one tell = -me -> how to keep a blank space in my bind_param ? - -use DBD::Oracle qw(:ora_types); -[...] -$sth->bind_param(2, ' ', { ora_type =3D> ORA_CHAR }); - -This is a frequently asked question here. The default type for strings, -ORA_VARCHAR2, strips trailing blanks from strings. A few months ago, -during one of the diskussuions about this feature, Tim said that he -might add a way to change the default in a future version of -DBD::Oracle. If he doesn't, maybe a paragraph like the following should -be added to the doc (not sure where - it fits below "Using DBD::Oracle -with Oracle 8 - Features and Issues" but it isn't Oracle 8 specific): - - =3Dhead2 Inserting strings with trailing spaces - - OCI provides several string types which behave differently. - Unfortunately, none of them can store arbitrary perl strings. - By default, DBD::Oracle binds string variables as ORA_VARCHAR2, - which allows embedded NUL characters but strips trailing spaces. If - you need trailing spaces, but don't need embedded NUL characters, - you can explicetly bind the param to type ORA_CHAR with: - - $sth->bind_param(($field_num, $string_value, - { ora_type =3D> ORA_CHAR }); - - =20 - hp - ---=20 - _ | Peter J. Holzer | Aeltere Sources (also solche, die schon -|_|_) | Sysadmin WSR / LUGA | aelter als 12 Stunden sind) sollte man -| | | hjp@wsr.ac.at | bei Linux generell nicht einsetzen - -__/ | http://www.hjp.at/ | Real Time Linux?? -- Gerhard Schneider - ---aZoGpuMECXJckB41 -Content-Type: application/pgp-signature -Content-Disposition: inline - ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.0.6 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -iQDQAwUBPPeD11LjemazOuKpAQEtNAXUC6rFL0C0v6MNW/K5ggXcSDY7Xvrj6Ed/ -jqjHq2Dx+h2rIMWXCDIGZVphSG74u4FL41AQF/rzGR/e56qH7aAxVmaiLdQE/DRi -zzsoOHoPEg96FhHljDtCZyxHzsz9sRJ1dfW1PELn5r2OSYPPsVzMoeR4iEXnVjvV -ZYH/OfbKRKhysIHjcNYKcyQL87GXdjzCEas3Xz+jyxW2vqzGAwUfTim4ySY9rF37 -c5vopwrTFCsi58r1LccFhQqEfw== -=Xe8d ------END PGP SIGNATURE----- - ---aZoGpuMECXJckB41-- - diff --git a/err_unicode/err_twolongstr.msg b/err_unicode/err_twolongstr.msg deleted file mode 100644 index 5d6c357d..00000000 --- a/err_unicode/err_twolongstr.msg +++ /dev/null @@ -1,1256 +0,0 @@ -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Wed Nov 17 19:08:49 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAHJ8F8P027204 - for ; Wed, 17 Nov 2004 19:08:48 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 17 Nov 2004 19:08:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUUU6-0001mQ-FU; - Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUUU6-0001mQ-FU - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUUU6-0000DF-68 - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9D10A120BFA; - Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 8C898120BEF - for ; Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Received-SPF: none (icicle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by icicle.pobox.com (Postfix) with ESMTP id 362C6120BEC - for ; Wed, 17 Nov 2004 13:24:46 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 9C0CC244379 - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 17196-06 for ; - Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 3131324406F - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 10:22:44 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_006A_01C4CC8F.60A4F6F0" -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117173321.GA6272@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTMy6HoelzJHh9WSPaTpCdfuF1C4gABpsZg -Message-Id: <20041117182444.3131324406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 16865 -Lines: 527 - -This is a multi-part message in MIME format. - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -I did - it is attached to the posting. However, I will attach it again -here. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 9:33 AM -> To: Susan Cassidy -> Cc: dbi-users@perl.org -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> If you can post a small self-contained example that demonstrates -> the problem then I'll take a look. -> -> Tim. -> -> On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > I never got any response to my question about this problem. I -> thought I'd try again. -> > -> > -> > -> > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> 5.8.5. -> > -> > -> > -> > Thanks, -> > -> > Susan -> > -> > -> > -> > --------------------------------------------------------------------- -> ----------------------------------- -> > -> > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > Sent: Friday, November 05, 2004 10:23 AM -> > To: 'dbi-users@perl.org' -> > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for -> > insert into a LONG column' when data not LONG -> > -> > -> > -> > I had an application that was processing a bunch of xml and inserting -> into a table with a bunch of -> > VARCHAR2(4000) columns. -> > -> > -> > -> > A couple of the entries I was processing caused the 'ORA-01461: can -> bind a LONG value only for insert -> > into a LONG column' error. -> > -> > -> > -> > I put checks in for the length of the data, and nothing approached -> 4000 bytes in length. -> > -> > -> > -> > I tracked down some of the entries causing problems, and on certain -> specific data, if 2 columns -> > containing specific data are inserted together, I get this error. If -> only one of the 2 is inserted, I -> > do not get the error, regardless of which one of the two I insert. -> > -> > -> > -> > The lengths of the pieces of data are 1399 and 1397 characters. -> > -> > -> > -> > The data is somewhat odd-looking (we suspect some odd data is in this -> file), but there is no reason for -> > the error message to appear. -> > -> > -> > -> > Trace shows nothing helpful - it thinks the data is the right length. -> > -> > -> > -> > We've successfully inserted thousands of other, similar entries with -> no trouble. -> > -> > -> > -> > The basics are: -> > -> > #create table test_table (item1 varchar2(4000), item2 -> varchar2(4000)); -> > -> > -> > -> > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, ?)"; -> > -> > -> > -> > $sth=$dbh->prepare($statement) || -> > -> > errexit("bad prepare for stmt $statement, error: $DBI::errstr"); -> > -> > my $rc=$sth->execute(@vals) || -> > -> > errexit("can't execute statement: error: $DBI::errstr\n"); -> > -> > -> > -> > Trace shows: -> > -> > -> > -> > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > -> > -> prepare for DBD::Oracle::db (DBI::db=HASH(0x82d4178)~0x82d6580 -> 'INSERT INTO test_table -> > (item1,item2) VALUES (?, ?) -> > -> > ') thr#8148ff0 -> > -> > dbd_preparse scanned 2 distinct placeholders -> > -> > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl line -> 40 -> > -> > -> execute for DBD::Oracle::st (DBI::st=HASH(0x82d6640)~0x8149dcc -> 'version 11.2no service -> > password-encryptionservice -> > -> > udp-small-serversservice tcp-small-servers!hostname router1!!no ip -> domain-lookupip inspect name mysite -> > ftpip inspect name -> > -> > mysite smtpip inspect name mysite tcp!interface Ethernet0ip address -> 10.10.10.2 255.255.255.0ip -> > access-group 101 inip ins -> > -> > pect mysite inip inspect mysite outno keepalive!interface Serial0no -> ip addressencapsulation -> > frame-relay...' 'version 11.2 -> > -> > no service password-encryptionservice udp-small-serversservice tcp- -> small-servers!hostname router1!!no ip -> > domain-lookupip -> > -> > inspect name mysite ftpip inspect name mysite smtpip inspect name -> mysite tcp!interface Ethernet0ip -> > address 10.10.10.2 255 -> > -> > .255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite -> outno keepalive!interface Serial0no -> > ip addressencaps -> > -> > ulation frame-relayn...') thr#8148ff0 -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (type 0) -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (size -> 1399/1400/0, ptype 4, otype 1) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (type 0) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (size -> 1397/1398/0, ptype 4, otype 1) -> > -> > dbd_st_execute INSERT (out0, lob0)... -> > -> > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > <- execute= undef at test_insert_large.pl line 42 -> > -> > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> 'ParamValues') thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line 42 -> > -> > -> $DBI::errstr (&) FETCH from lasth=HASH -> > -> > >> DBD::Oracle::st::errstr -> > -> > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' -> > -> > -- DBI::END -> > -> > -> disconnect_all for DBD::Oracle::dr -> (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > -> > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > -> > Connect done -> > -> > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > -> > Size of vals is 2 -> > -> > val 1 size 1399, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!i -> > -> > nterface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11 -> > -> > .2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 IETF!router eigrp 69network -> > 10.0.0.0no auto-summar -> > -> > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0. -> > -> > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permit icmp 10.10.10.0 -> > 0.0.0.255 anyaccess- -> > -> > list 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-rep -> > -> > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 ad -> > -> > ministratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp a -> > -> > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 0.0.0.255 -> > time-exceededaccess-list 102 permit tcp -> > -> > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > val 2 size 1397, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11. -> > -> > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci 200 -> IETF!router eigrp 69network -> > 10.0.0.0no auto-summary -> > -> > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 0.0.0.0 -> 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0.0 -> > -> > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permiticmp 10.10.10.0 -> > 0.0.0.255 anyaccess-li -> > -> > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess-list -> 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-reply -> > -> > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 admi -> > -> > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp any -> > -> > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 time-exceededaccess-list -> > 102 permit tcp an -> > -> > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > can't execute statement: error: ORA-01461: can bind a LONG value only -> for insert into a LONG column (DBD -> > ERROR: OCIStmtEx -> > -> > ecute) -> > -> > -> > -> > ! -> DESTROY for DBD::Oracle::db (DBI::db=HASH(0x82d6580)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#0) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > -> > -> > I will attach the test program. Somehow it seems to think the -> datatype is LONG instead of VARCHAR. -> > -> > -> > -> > -> > -> > Anyone with ideas? -> > -> > -> > -> > -> > -> > Thanks, -> > -> > Susan -> - - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: application/octet-stream; - name="test_insert_large.pl" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="test_insert_large.pl" - -#!/usr/local/bin/perl -w=0A= -=0A= -use DBI;=0A= -=0A= -our $dbh;=0A= -our $sth;=0A= -=0A= -$dbuser=3D"proj1";=0A= -$dbpasswd=3D"proj1";=0A= -=0A= -$dbserver=3D'oracledev';=0A= -$db_sid=3D'AL32UTF8';=0A= -=0A= -##=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D connect to database = -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=0A= -=0A= -$dbh=3D DBI->connect("dbi:Oracle:host=3D$dbserver;sid=3D$db_sid", = -$dbuser, $dbpasswd,=0A= - {PrintError =3D> 0, AutoCommit =3D> 1}) or=0A= - errexit( "Unable to connect to $dbserver: $DBI::errstr");=0A= -print "Connect done\n";=0A= -=0A= -#create table test_table (item1 varchar2(4000), item2 varchar2(4000));=0A= -=0A= -=0A= -my $statement=3D"INSERT INTO test_table (item1,item2) VALUES (?, ?)";=0A= -print "stmt: $statement\n";=0A= -=0A= -@vals=3D(=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysite inip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permit icmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permiticmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= -);=0A= -=0A= -print "Size of vals is ",scalar @vals,"\n";=0A= -my $z=3D0;=0A= -foreach my $x (@vals) {=0A= - my $len=3Dlength($x);=0A= - print "val ",++$z, " size $len, is: '$x'\n";=0A= -}=0A= -=0A= -DBI->trace(2);=0A= - $sth=3D$dbh->prepare($statement) ||=0A= - errexit("bad prepare for stmt $statement, error: $DBI::errstr");=0A= - my $rc=3D$sth->execute(@vals) ||=0A= - errexit("can't execute statement: error: $DBI::errstr\n");=0A= -=0A= -print "Done\n";=0A= -exit;=0A= -=0A= -=0A= -sub errexit {=0A= - my (@msg)=3D@_;=0A= - print @msg,"\n";=0A= - exit 1;=0A= -}=0A= -=0A= -=0A= -=0A= - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0-- - - -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 00:15:21 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI0FC8G049539 - for ; Thu, 18 Nov 2004 00:15:21 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 00:15:21 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUVdd-0002Nv-CF; - Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUVdd-0002Nv-CF - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CUVdc-0005lu-Rs - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 4A256ADD6F; - Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3D82CADD64 - for ; Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Received-SPF: none (boggle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by boggle.pobox.com (Postfix) with ESMTP id B23D4ADCF6 - for ; Wed, 17 Nov 2004 14:38:15 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 0C9DF24435B - for ; Wed, 17 Nov 2004 11:38:14 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 18475-01 for ; - Wed, 17 Nov 2004 11:38:13 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id ACF0424406F - for ; Wed, 17 Nov 2004 11:38:13 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 11:36:14 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117192902.GA31595@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTM27+9yfJDVs3WQIWAKc6DR3EgdQAAKfgw -Message-Id: <20041117193813.ACF0424406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -X-Status: A -Content-Length: 14671 -Lines: 489 - -NLS_LANG=.UTF8 -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORACLE_HOME=/home/oracle/product/9.2.0 -ORACLE_SID=AL32UTF8 -ORACLE_BASE=/home/oracle - -NLS_NCHAR is not set, because we are not using any NVARCHAR data item, and -haven't needed it. - -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 11:29 AM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > I did - it is attached to the posting. However, I will attach it again -> > here. -> > -> > Thanks, -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 9:33 AM -> > > To: Susan Cassidy -> > > Cc: dbi-users@perl.org -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > If you can post a small self-contained example that demonstrates -> > > the problem then I'll take a look. -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > > > I never got any response to my question about this problem. I -> > > thought I'd try again. -> > > > -> > > > -> > > > -> > > > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> > > 5.8.5. -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > > -> > > > -> > > > -> > > > ----------------------------------------------------------------- -> ---- -> > > ----------------------------------- -> > > > -> > > > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > > > Sent: Friday, November 05, 2004 10:23 AM -> > > > To: 'dbi-users@perl.org' -> > > > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> > > 01461: can bind a LONG value only for -> > > > insert into a LONG column' when data not LONG -> > > > -> > > > -> > > > -> > > > I had an application that was processing a bunch of xml and -> inserting -> > > into a table with a bunch of -> > > > VARCHAR2(4000) columns. -> > > > -> > > > -> > > > -> > > > A couple of the entries I was processing caused the 'ORA-01461: -> can -> > > bind a LONG value only for insert -> > > > into a LONG column' error. -> > > > -> > > > -> > > > -> > > > I put checks in for the length of the data, and nothing -> approached -> > > 4000 bytes in length. -> > > > -> > > > -> > > > -> > > > I tracked down some of the entries causing problems, and on -> certain -> > > specific data, if 2 columns -> > > > containing specific data are inserted together, I get this error. -> If -> > > only one of the 2 is inserted, I -> > > > do not get the error, regardless of which one of the two I -> insert. -> > > > -> > > > -> > > > -> > > > The lengths of the pieces of data are 1399 and 1397 characters. -> > > > -> > > > -> > > > -> > > > The data is somewhat odd-looking (we suspect some odd data is in -> this -> > > file), but there is no reason for -> > > > the error message to appear. -> > > > -> > > > -> > > > -> > > > Trace shows nothing helpful - it thinks the data is the right -> length. -> > > > -> > > > -> > > > -> > > > We've successfully inserted thousands of other, similar entries -> with -> > > no trouble. -> > > > -> > > > -> > > > -> > > > The basics are: -> > > > -> > > > #create table test_table (item1 varchar2(4000), item2 -> > > varchar2(4000)); -> > > > -> > > > -> > > > -> > > > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, -> ?)"; -> > > > -> > > > -> > > > -> > > > $sth=$dbh->prepare($statement) || -> > > > -> > > > errexit("bad prepare for stmt $statement, error: -> $DBI::errstr"); -> > > > -> > > > my $rc=$sth->execute(@vals) || -> > > > -> > > > errexit("can't execute statement: error: $DBI::errstr\n"); -> > > > -> > > > -> > > > -> > > > Trace shows: -> > > > -> > > > -> > > > -> > > > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > > > -> > > > -> prepare for DBD::Oracle::db -> (DBI::db=HASH(0x82d4178)~0x82d6580 -> > > 'INSERT INTO test_table -> > > > (item1,item2) VALUES (?, ?) -> > > > -> > > > ') thr#8148ff0 -> > > > -> > > > dbd_preparse scanned 2 distinct placeholders -> > > > -> > > > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl -> line -> > > 40 -> > > > -> > > > -> execute for DBD::Oracle::st -> (DBI::st=HASH(0x82d6640)~0x8149dcc -> > > 'version 11.2no service -> > > > password-encryptionservice -> > > > -> > > > udp-small-serversservice tcp-small-servers!hostname router1!!no -> ip -> > > domain-lookupip inspect name mysite -> > > > ftpip inspect name -> > > > -> > > > mysite smtpip inspect name mysite tcp!interface Ethernet0ip -> address -> > > 10.10.10.2 255.255.255.0ip -> > > > access-group 101 inip ins -> > > > -> > > > pect mysite inip inspect mysite outno keepalive!interface -> Serial0no -> > > ip addressencapsulation -> > > > frame-relay...' 'version 11.2 -> > > > -> > > > no service password-encryptionservice udp-small-serversservice -> tcp- -> > > small-servers!hostname router1!!no ip -> > > > domain-lookupip -> > > > -> > > > inspect name mysite ftpip inspect name mysite smtpip inspect name -> > > mysite tcp!interface Ethernet0ip -> > > > address 10.10.10.2 255 -> > > > -> > > > .255.255.0ip access-group 101 inip inspect mysiteinip inspect -> mysite -> > > outno keepalive!interface Serial0no -> > > > ip addressencaps -> > > > -> > > > ulation frame-relayn...') thr#8148ff0 -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (type -> 0) -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (size -> > > 1399/1400/0, ptype 4, otype 1) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (type -> 0) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (size -> > > 1397/1398/0, ptype 4, otype 1) -> > > > -> > > > dbd_st_execute INSERT (out0, lob0)... -> > > > -> > > > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > <- execute= undef at test_insert_large.pl line 42 -> > > > -> > > > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> > > 'ParamValues') thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line -> 42 -> > > > -> > > > -> $DBI::errstr (&) FETCH from lasth=HASH -> > > > -> > > > >> DBD::Oracle::st::errstr -> > > > -> > > > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' -> > > > -> > > > -- DBI::END -> > > > -> > > > -> disconnect_all for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > > > -> > > > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > > > -> > > > Connect done -> > > > -> > > > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > > > -> > > > Size of vals is 2 -> > > > -> > > > val 1 size 1399, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!i -> > > > -> > > > nterface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11 -> > > > -> > > > .2 255.255.255.252ip access-group 102 inframe-relay interface- -> dlci -> > > 200 IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summar -> > > > -> > > > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> > > 0.0.0.0 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0. -> > > > -> > > > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permit icmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess- -> > > > -> > > > list 101 deny ip any anyaccess-list 102 permit eigrp any -> anyaccess- -> > > list 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-rep -> > > > -> > > > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 ad -> > > > -> > > > ministratively-prohibitedaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp a -> > > > -> > > > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> > > 10.10.10.0 0.0.0.255 -> > > > time-exceededaccess-list 102 permit tcp -> > > > -> > > > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line -> con -> > > 0line vty 0 4login!end' -> > > > -> > > > val 2 size 1397, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11. -> > > > -> > > > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 -> > > IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summary -> > > > -> > > > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 -> > > 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0.0 -> > > > -> > > > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permiticmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess-li -> > > > -> > > > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list -> > > 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-reply -> > > > -> > > > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 admi -> > > > -> > > > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp any -> > > > -> > > > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 time-exceededaccess-list -> > > > 102 permit tcp an -> > > > -> > > > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> > > 0line vty 0 4login!end' -> > > > -> > > > can't execute statement: error: ORA-01461: can bind a LONG value -> only -> > > for insert into a LONG column (DBD -> > > > ERROR: OCIStmtEx -> > > > -> > > > ecute) -> > > > -> > > > -> > > > -> > > > ! -> DESTROY for DBD::Oracle::db -> (DBI::db=HASH(0x82d6580)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#0) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY for DBD::Oracle::st -> (DBI::st=HASH(0x8149dcc)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > -> > > > -> > > > I will attach the test program. Somehow it seems to think the -> > > datatype is LONG instead of VARCHAR. -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Anyone with ideas? -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > -> > -> - - - -From SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 07:11:03 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI7Ar8G057950 - for ; Thu, 18 Nov 2004 07:11:03 GMT - (envelope-from SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 07:11:03 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUaCR-0002mS-7P; - Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUaCR-0002mS-7P - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUaCQ-0004JQ-R5 - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 17ACAA3F35; - Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from integer (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 04F8DA3EAC - for ; Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Received-SPF: none (integer.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by integer.pobox.com (Postfix) with ESMTP id A9FC6A3F4D - for ; Wed, 17 Nov 2004 19:30:43 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id DEA102441A9 - for ; Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 22204-10 for ; - Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 7AD52244370 - for ; Wed, 17 Nov 2004 16:30:40 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 16:28:41 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041118001712.GB49519@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTNA/o7HZXghXaJRbyz8M5kVQMQmwAAUBjg -Message-Id: <20041118003040.7AD52244370@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 1789 -Lines: 63 - -Hi, - -I set NLS_LANG to .US7ASCII, ran it again, and I get the same error. - -Of course, I could not use that in production. - -The really strange part, to me, was that if I just insert one of the 2 -problematic columns, it worked, but both together failed. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 4:17 PM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> And does the problem go away if NLS_LANG is set to a non-unicode charset? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 11:36:14AM -0800, Susan Cassidy wrote: -> > NLS_LANG=.UTF8 -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORACLE_HOME=/home/oracle/product/9.2.0 -> > ORACLE_SID=AL32UTF8 -> > ORACLE_BASE=/home/oracle -> > -> > NLS_NCHAR is not set, because we are not using any NVARCHAR data item, -> and -> > haven't needed it. -> > -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 11:29 AM -> > > To: Susan Cassidy -> > > Cc: 'Tim Bunce' -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > > > I did - it is attached to the posting. However, I will attach it -> again -> > > > here. -> > > > -> > > > Thanks, -> > > > Susan -> > > > - - diff --git a/err_unsorted/err_etherreal.msg b/err_unsorted/err_etherreal.msg deleted file mode 100644 index 1ad5c78e..00000000 --- a/err_unsorted/err_etherreal.msg +++ /dev/null @@ -1,90 +0,0 @@ -From dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org Tue Apr 30 14:47:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UDliR22576 - for ; Tue, 30 Apr 2002 14:47:44 +0100 (BST) - (envelope-from dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.23] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 14:47:44 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020172466:10:24548:59; Tue, 30 Apr 2002 13:14:26 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1023391; 30 Apr 2002 13:13 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id A94562C075 - for ; Tue, 30 Apr 2002 09:12:33 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id F24B22BFBE - for ; Tue, 30 Apr 2002 09:12:32 -0400 (EDT) -Received: (qmail 36589 invoked by uid 1005); 30 Apr 2002 13:12:28 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 36168 invoked by uid 76); 30 Apr 2002 13:10:41 -0000 -Content-Type: text/plain; - charset="iso-8859-1" -From: Calin Medianu -To: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Date: Tue, 30 Apr 2002 16:04:47 +0300 -X-Mailer: KMail [version 1.3.2] -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> <20020429233138.E16831@dansat.data-plan.com> -In-Reply-To: <20020429233138.E16831@dansat.data-plan.com> -Cc: dbi-users@perl.org -MIME-Version: 1.0 -Message-Id: <20020430131233.F24B22BFBE@dolly1.pobox.com> -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id g3UDliR22576 -Status: RO -X-Status: A -Content-Length: 1213 -Lines: 38 - -[Add note to DBD::Oracle docs about using ethereal to sniff Oracle packets] -[Not sure if this bug got fixed yet. Maybe not.] - -Me again with the slow cursors. - -I modified both queries to only return 10 rows. -I ran a sniffer (ethereal) on the NIC. It is pretty cool, it also decodes TNS. - -when I am using the SQL, it works like this, there are about 7 packets -received by my workstation to set up the session, then all 10 rows are in the -same packet, then there is another packet probably saying goodbye. - -When I am using the REF cursor, each row comes in it's own TNS packet, that -is why it is so slow! - -Any idea how to fix it? - -thanks a lot, - -Calin - -> On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> > Hello, -> > -> > I did the following. Wrote a perl script that retreves -> > data via a straight select from the database. Then I -> > wrote a stored procedure returning a ref cursor open -> > on the same select statement and retrieved the data as -> > well. Using the REF CURSOR/ sotred procedure was about -> > 3 time slower, that is 40 seconds instead of around -> > 10. -> > -> > Is this normal? Is this a problem with oracle or with -> > DBD::Oracle? -> -> DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. -> -> Get a level 3 trace and look for the "dbd_describe'd" line for the -> ref cursor. -> -> Tim. - diff --git a/err_unsorted/err_memleak2.msg b/err_unsorted/err_memleak2.msg deleted file mode 100644 index 97501852..00000000 --- a/err_unsorted/err_memleak2.msg +++ /dev/null @@ -1,476 +0,0 @@ -From mike@boom.net Fri Nov 28 22:23:33 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hASMLLnY018698 - for ; Fri, 28 Nov 2003 22:23:33 GMT - (envelope-from mike@boom.net) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 28 Nov 2003 22:23:33 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1APmgW-0006iM-9g; - Fri, 28 Nov 2003 17:45:40 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1APmgW-0006iM-9g - for pobox@dbi.demon.co.uk; Fri, 28 Nov 2003 17:45:40 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id E82CD95E03 - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B1EE595DFB - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: from abort.boom.net (abort.boom.net[69.36.241.24]) - by icicle.pobox.com (Postfix) with ESMTP - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: by abort.boom.net (Postfix, from userid 530) - id E3C8B8517A; Fri, 28 Nov 2003 09:45:36 -0800 (PST) -Date: Fri, 28 Nov 2003 09:45:36 -0800 -From: Mike Hedlund -To: dbi-users@perl.org -Cc: Tim.Bunce@pobox.com -Subject: Memory leak in DBD::Oracle 1.14 ... ? -Message-ID: <20031128174536.GJ10609@boom.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.5.4i -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id hASMLLnY018698 -Content-Length: 24309 -Lines: 434 - -I've attached a little script which replicates the problem on my machine as well as the build session log for DBD::Oracle 1.14. - -I've tested it using DBI 1.38 and DBI 1.28 with both DBD::Oracle 1.12 and 1.14. - -Regardless of the DBI version, DBD::Oracle 1.14 leaks on my system and DBD::Oracle 1.12 does not. I've noticed the leak when calling connect_cached(), do() (or prepare()/execute()/commit/finish). - --mike - - --------------------- script --------------- -#!/usr/bin/perl -use strict; -use DBI; - -my($dbp) = "dbi:Oracle:host=weirdo.com;port=1521;sid=SID"; -my($dbu) = "username"; -my($dbpass) = "password"; - -while (1) { - my($sth); - my(@row); - my($dbh) = DBI->connect_cached($dbp,$dbu,$dbpass) || die "Couldn't connect to oracle db: $DBI::errstr\n"; - -## -## uncomment these and it just leaks faster. -## -# $sth = $dbh->prepare("SELECT * from FROM_STATS"); -# $sth->execute; -# while(@row = $sth->fetchrow_array) { - ##print "row: @row\n"; -# } -# $sth->finish; -} -exit; ------------------------- end script -------------------- - - ------------- log --------------------------------------- -Script started on Fri 28 Nov 2003 09:11:15 AM PST -[mike@commando DBD-Oracle-1.14]$ setenv ORACLE_HOME /home/orahome -[mike@commando DBD-Oracle-1.14]$ make realclean -rm -f blib/script/ora_explain -rm -rf Oracle.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm ./blib Makefile.aperl blib/arch/auto/DBD/Oracle/extralibs.all perlmain.c tmon.out mon.out so_locations pm_to_blib *.o *.a perl.exe perl perl Oracle.bs Oracle.bso Oracle.def libOracle.def Oracle.exp Oracle.x core core.*perl.*.? *perl.core -mv Makefile Makefile.old > /dev/null 2>&1 -rm -rf blib/lib/auto/DBD/Oracle blib/arch/auto/DBD/Oracle -rm -rf DBD-Oracle-1.14 -rm -f blib/arch/auto/DBD/Oracle/Oracle.so blib/arch/auto/DBD/Oracle/Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.a -rm -f blib/lib/DBD/Oracle.pm blib/arch/auto/DBD/Oracle/dbdimp.h blib/lib/oraperl.ph -rm -f blib/arch/auto/DBD/Oracle/ocitrace.h blib/lib/Oraperl.pm -rm -f blib/arch/auto/DBD/Oracle/Oracle.h blib/arch/auto/DBD/Oracle/mk.pm -rm -f blib/lib/DBD/Oracle/GetInfo.pm -rm -rf Makefile Makefile.old -[mike@commando DBD-Oracle-1.14]$ perl Makefile.PL -v -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI - - Configuring DBD::Oracle ... - ->>> Remember to actually *READ* the README file! - Especially if you have any problems. - -Using Oracle in /home/orahome - -WARNING: could not decode oracle version from -/home/orahome/orainst/inspdver, or /home/orahome/install/unix.rgs -or from ORACLE_HOME path /home/orahome. -Oracle version based logic in Makefile.PL may produce erroneous results. - -Found header files in rdbms/public rdbms/demo. -Found /home/orahome/rdbms/demo/demo_rdbms.mk -Found /home/orahome/otrace/demo/atmoci.mk -Found /home/orahome/precomp/demo/proc/demo_proc.mk -Using /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/lib/env_rdbms.mk -Read a total of 2202 lines from /home/orahome/rdbms/lib/env_rdbms.mk (including inclusions) -Read a total of 2493 lines from /home/orahome/rdbms/demo/demo_rdbms.mk (including inclusions) -Deleted SHELL definition: SHELL=/bin/sh -Deleted LIB_EXT definition: LIB_EXT=a -Deleted OBJ_EXT definition: OBJ_EXT=o -Deleted AR definition: AR=ar -Deleted AS definition: AS=as -Deleted CC definition: CC=cc -Deleted CHMOD definition: CHMOD=chmod -Deleted CPP definition: CPP=cpp -Deleted ECHO definition: ECHO=echo -Deleted LD definition: LD=ld -Deleted PERL definition: PERL=perl -Deleted CFLAGS definition: CFLAGS=$(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ -Deleted OPTIMIZE definition: OPTIMIZE=$(OPTIMIZE3) -Deleted AR definition: AR=/usr/bin/ar -Deleted AS definition: AS=/usr/bin/as -Deleted LD definition: LD=/usr/bin/ld -Deleted CPP definition: CPP=/lib/cpp -Deleted CHMOD definition: CHMOD=/bin/chmod -Deleted ASFLAGS definition: ASFLAGS= -Deleting ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS definition: ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Deleting ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS33 definition: ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Appending '/home/orahome/rdbms/lib/libskgxpd.a /home/orahome/rdbms/lib/libskgxpu.a /home/orahome/rdbms/lib/libskgxpt.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxp9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxp9.a' to LIBS -Appending '/home/orahome/rdbms/lib/libskgxns.a /home/orahome/rdbms/lib/libskgxnd.a /home/orahome/rdbms/lib/libskgxnr.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxn9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxn9.a' to LIBS -Evaluating `cat $(LIBHOME)sysliblist` - expanded `cat /home/orahome/lib/sysliblist` - returned '-ldl -lm -lpthread -lnsl ' - -Attempting to discover Oracle OCI build rules -gcc -c -o DBD_ORA_OBJ.o DBD_ORA_OBJ.c -by executing: (make -f /home/orahome/rdbms/demo/demo_rdbms.mk build ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh' CC=echo OPTIMIZE= CCFLAGS= EXE=DBD_ORA_EXE OBJS=DBD_ORA_OBJ.o) -returned: -[echo -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh `cat /home/orahome/lib/sysliblist` -ldl -lm - -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -reduced to: -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -Oracle oci build command: - + -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - - - -System: perl5.008 linux stripples.devel.redhat.com 2.4.21-1.1931.2.382.entsmp #1 smp wed aug 6 17:18:52 edt 2003 i686 i686 i386 gnulinux -Compiler: gcc -O2 -g -pipe -march=i386 -mcpu=i686 -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -Linker: /usr/bin/ld -Sysliblist: -ldl -lm -lpthread -lnsl -Oracle makefiles would have used these definitions but we override them: - CC: cc - - CFLAGS: $(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) - [$(GFLAG) -O3 $(CDEBUG) $(CCFLAGS) -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -DLINUX -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS $(LPFLAGS) $(USRFLAGS)] - - LDFLAGS: -o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ - [-o $@ -L/home/orahome/rdbms/lib/ -L$(LIBHOME) -L$(LIBHOME)stubs/] - - -Linking with OTHERLDFLAGS = -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - [from 'build' rule] - - -MakeMaker (v6.03) -Checking if your kit is complete... -Looks good - ABSTRACT_FROM => q[Oracle.pm] - AUTHOR => q[Tim Bunce (dbi-users@perl.org)] - DEFINE => q[ -DUTF8_SUPPORT] - DIR => [] - EXE_FILES => [q[ora_explain]] - INC => q[-I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI] - NAME => q[DBD::Oracle] - OBJECT => q[$(O_FILES)] - PREREQ_PM => { DBI=>q[0] } - VERSION_FROM => q[Oracle.pm] - clean => { FILES=>q[Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm] } - dist => { DIST_DEFAULT=>q[clean distcheck disttest ci tardist], COMPRESS=>q[gzip -v9], PREOP=>q[$(MAKE) -f Makefile.old distdir], SUFFIX=>q[gz] } - dynamic_lib => { OTHERLDFLAGS=>q[ -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] } -Using PERL=/usr/bin/perl -LD_RUN_PATH=/home/orahome/lib:/home/orahome/rdbms/lib -Using DBD::Oracle 1.14. -Using DBD::Oracle 1.14. -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -Writing Makefile for DBD::Oracle - -*** If you have problems... - read all the log printed above, and the README and README.help files. - (Of course, you have read README by now anyway, haven't you?) - -[mike@commando DBD-Oracle-1.14]$ make -cp Oracle.pm blib/lib/DBD/Oracle.pm -cp Oracle.h blib/arch/auto/DBD/Oracle/Oracle.h -cp dbdimp.h blib/arch/auto/DBD/Oracle/dbdimp.h -cp oraperl.ph blib/lib/oraperl.ph -cp ocitrace.h blib/arch/auto/DBD/Oracle/ocitrace.h -cp Oraperl.pm blib/lib/Oraperl.pm -cp mk.pm blib/arch/auto/DBD/Oracle/mk.pm -cp lib/DBD/Oracle/GetInfo.pm blib/lib/DBD/Oracle/GetInfo.pm -/usr/bin/perl -p -e "s/~DRIVER~/Oracle/g" /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI/Driver.xst > Oracle.xsi -/usr/bin/perl /usr/lib/perl5/5.8.0/ExtUtils/xsubpp -typemap /usr/lib/perl5/5.8.0/ExtUtils/typemap Oracle.xs > Oracle.xsc && mv Oracle.xsc Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT dbdimp.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci7.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci8.c -Running Mkbootstrap for DBD::Oracle () -chmod 644 Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/home/orahome/lib:/home/orahome/rdbms/lib" gcc -shared -L/usr/local/lib Oracle.o dbdimp.o oci7.o oci8.o -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" blib/script/ora_explain -Manifying blib/man3/DBD::Oracle.3pm -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oraperl.3pm -[mike@commando DBD-Oracle-1.14]$ make test -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/base....... t/base.......ok 1/5 t/base.......ok 2/5 t/base.......ok 3/5 t/base.......ok 4/5 t/base.......ok 5/5 t/base.......ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/reauth.....skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.82 cusr + 0.33 csys = 4.15 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ make test TEST_VERBOSE=1 -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1, 'blib/lib', 'blib/arch')" t/*.t -t/base.......1..5 -ok 1 -ok 2 -ok 3 -ok 4 -ok 5 -ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/reauth.....ORACLE_USERID_2 not defined. -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.85 cusr + 0.32 csys = 4.17 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ perl _V-V -Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: - Platform: - osname=linux, osvers=2.4.21-1.1931.2.382.entsmp, archname=i386-linux-thread-multi - uname='linux str' - config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Dotherlibdirs=/usr/lib/perl5/5.8.0 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr' - hint=recommended, useposix=true, d_sigaction=define - usethreads=define use5005threads=undef' - useithreads=define usemultiplicity= - useperlio= d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=un uselongdouble= - usemymalloc=, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', - optimize='', - cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm' - ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)', gccosandvers='' -gccversion='3.2.2 200302' - intsize=r, longsize=r, ptrsize=5, doublesize=8, byteorder=1234 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - ivtype='long' -k', ivsize=4' -ivtype='l, nvtype='double' -o_nonbl', nvsize=, Off_t='', lseeksize=8 - alignbytes=4, prototype=define - Linker and Libraries: - ld='gcc' -l', ldflags =' -L/u' - libpth=/usr/local/lib /lib /usr/lib - libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil - perllibs= - libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libper - gnulibc_version='2.3.2' - Dynamic Linking: - dlsrc=dl_dlopen.xs, dlext=so', d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE' - cccdlflags='-fPIC' -ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5', lddlflags='s Unicode/Normalize XS/A' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING MULTIPLICITY USE_ITHREADS USE_LARGE_FILES PERL_IMPLICIT_CONTEXT - Locally applied patches: - MAINT18379 - Built under linux - Compiled at Aug 13 2003 11:47:58 - @INC: - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/site_perl/5.8.0 - /usr/lib/perl5/site_perl - /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/vendor_perl/5.8.0 - /usr/lib/perl5/vendor_perl - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - . -[mike@commando DBD-Oracle-1.14]$ ^D -Script done on Fri 28 Nov 2003 09:16:43 AM PST ------------- end log ----------------------------------- - - diff --git a/err_unsorted/err_multiora.msg b/err_unsorted/err_multiora.msg deleted file mode 100644 index 9f7bcf6c..00000000 --- a/err_unsorted/err_multiora.msg +++ /dev/null @@ -1,470 +0,0 @@ -From dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org Mon Jan 5 10:12:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05ACYn1063537 - for ; Mon, 5 Jan 2004 10:12:58 GMT - (envelope-from dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 10:12:58 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdQXY-0007a7-IO; - Mon, 05 Jan 2004 09:18:18 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdQXY-0007a7-IO - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 08:56:48 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id C92F0282F - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id B344B2B84 - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: (qmail 58691 invoked by uid 1005); 5 Jan 2004 08:56:38 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 58674 invoked by uid 76); 5 Jan 2004 08:56:38 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 05 Jan 2004 00:56:38 -0800 -Received: (qmail 17937 invoked by uid 225); 5 Jan 2004 08:56:36 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 17930 invoked by uid 507); 5 Jan 2004 08:56:36 -0000 -Received: from stone.sifira.dk (HELO mail.int.sifira.dk) (217.157.24.2) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Mon, 05 Jan 2004 00:56:05 -0800 -Received: from ash.int.sifira.dk (ash.int.sifira.dk [192.168.1.7]) by mail.int.sifira.dk (Postfix) with ESMTP id F127674F58; Mon, 5 Jan 2004 09:55:58 +0100 (MET) -Sender: kn@sifira.dk -To: "Anniballi, Fran" -Cc: -Subject: Re: Help - multiple Oracle versions -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -From: Kristian Nielsen -Date: 05 Jan 2004 09:55:59 +0100 -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Message-ID: <7sllomsrj4.fsf@ash.int.sifira.dk> -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-2.5 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_GNUS_UA version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1223 -Lines: 40 - -[Add notes to docs covering what's in this thread] - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - -From dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org Mon Jan 5 14:47:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05Ejvo1064760 - for ; Mon, 5 Jan 2004 14:47:30 GMT - (envelope-from dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 14:47:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdVCS-0004w0-Is; - Mon, 05 Jan 2004 13:55:22 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdVCS-0004w0-Is - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 13:55:21 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 548DE2C87 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 417692C81 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 08:55:19 -0500 (EST) -Received: (qmail 91728 invoked by uid 1005); 5 Jan 2004 13:55:17 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 48614 invoked by uid 76); 5 Jan 2004 12:24:01 -0000 -Delivered-To: dbi-users@perl.org -X-MimeOLE: Produced By Microsoft Exchange V6.0.6487.1 -content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; charset="iso-8859-1" -Subject: RE: Help - multiple Oracle versions -Date: Mon, 5 Jan 2004 07:23:23 -0500 -Message-ID: <6B003D25ADBDE347B5542AFE6A55B42E04537A09@tayexc13.americas.cpqcorp.net> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Help - multiple Oracle versions -Thread-Index: AcPTac0nADA1C8LsTdSTxpcvyeSNCgAHQWGQ -From: "Anniballi, Fran" -To: -Cc: -X-OriginalArrivalTime: 05 Jan 2004 12:23:24.0525 (UTC) FILETIME=[B6F761D0:01C3D386] -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.3 required=7.0 tests=CARRIAGE_RETURNS,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i05Ejvo1064760 -Status: RO -Content-Length: 1465 -Lines: 52 - -Thanks. Looks like this is what I'll need. - ------Original Message----- -From: kn@sifira.dk [mailto:kn@sifira.dk] -Sent: Monday, January 05, 2004 3:56 AM -To: Anniballi, Fran -Cc: dbi-users@perl.org -Subject: Re: Help - multiple Oracle versions - - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - - -From dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org Tue Jan 6 17:00:29 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i06GxrnC075337 - for ; Tue, 6 Jan 2004 17:00:29 GMT - (envelope-from dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 06 Jan 2004 17:00:29 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Adu0c-0004RW-9d; - Tue, 06 Jan 2004 16:24:47 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Adu0c-0004RW-9d - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 16:24:47 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 21A79495C - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 08B12494B - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 6 Jan 2004 11:24:45 -0500 (EST) -Received: (qmail 25114 invoked by uid 1005); 6 Jan 2004 16:24:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 25095 invoked by uid 76); 6 Jan 2004 16:24:42 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Tue, 06 Jan 2004 08:24:42 -0800 -Received: (qmail 16535 invoked by uid 225); 6 Jan 2004 16:24:39 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16527 invoked by uid 507); 6 Jan 2004 16:24:39 -0000 -Received: from mail.cybcon.com (HELO mail.cybcon.com) (216.190.188.5) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 06 Jan 2004 08:24:08 -0800 -Received: from poirot (dsl2-6.cybcon.com [208.186.116.6]) by mail.cybcon.com (8.11.6/8.11.6) with ESMTP id i06GNhn08916; Tue, 6 Jan 2004 08:23:43 -0800 -Subject: RE: Help - multiple Oracle versions -From: Jared Still -To: "Anniballi, Fran" -Cc: DBI List -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 (1.0.8-11) -Date: 06 Jan 2004 08:25:59 -0800 -Message-Id: <1073406359.324.244.camel@poirot.jks.com> -Mime-Version: 1.0 -X-CyberConnectics-MailScanner2-Information: Spam/Virus Scanned at CyberConnectics -X-CyberConnectics-MailScanner2: Found to be clean -X-CyberConnectics-MailScanner2-SpamCheck: -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.2 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_05_08,SUPERLONG_LINE version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 4050 -Lines: 102 - -I read quickly through this thread, so my apologies if someone -already pointed this out. - -It doesn't matter which version of Oracle you compiled DBD with, -you can connect to all your 8i/9i databases on any platform with it. - -Assume you compiled with 9i libs, and you can connect to 9i db's with -no problem, but are unable to connect to 8i, getting the error you -mentioned previously. - -It appears that you are changing your Oracle environment via the -oraenv shell script to change your ORACLE_HOME to the 8i version -of Oracle. - -If so, stop doing that. Just leave your environment at 9i, and -connect to your 8i database. It will be fine. This is the way -my linux server is setup, and DBD is used to connect to Oracle -versions 7.3, 8.1.6, 8.1.7 and 9.2.0 every day. - -At our site DBD is compiled with 8i libs so that we can still -connect to the version 7 databases. If you compile with 9i libs, -you will be unable to connect to version 7 databases. - -HTH - -Jared - - -On Sun, 2004-01-04 at 05:12, Anniballi, Fran wrote: -> This is all done on one UNIX box. -> -> If I try option one, it doesn't work. I can't access an oracle8 instance with oracle9 sqlplus (or the other way around). That is the real problem. Since I can't do this I have to reassign the pointers before I access it. I can do this fine with sqlplus but with dbi/dbd I have to compile with one or the other. -> -> For option two, if I have two versions of DBD:Oracle, how do I tell Perl which one to use? My scripts just say "/usr/bin/perl" in the first line. -> -> -----Original Message----- -> From: kn@sifira.dk [mailto:kn@sifira.dk] -> Sent: Saturday, January 03, 2004 1:04 PM -> To: dbi-users@perl.org -> Cc: Anniballi, Fran -> Subject: Re: Help - multiple Oracle versions -> -> -> "Anniballi, Fran" writes: -> -> > As soon as I recompile the same DBI/DBD with it pointing to Oracle 9 -> > environment (libraries), it doesn't work. It is looking for Oracle9 -> > library files and I obviously don't have it pointing to oracle9 -> > libraries when I access an Oracle 8 instance. Oracle 9 is not -> > compatible with Oracle 8 so I have to redirect the environment -> > variables at run time. -> -> It sounds like you are confusing the Oracle client version and the -> Oracle server version. -> -> Eg. if you set ORACLE_HOME to /usr/local/oracle8 (or whatever) and use -> /usr/local/oracle8/bin/sqlplus you are using the Oracle 8 client, while -> if you set it to /usr/local/oracle9 and call -> /usr/local/oracle9/bin/sqlplus, you are using the Oracle 9 client. -> -> Which Oracle instance you access is selected by the connection string; -> for example "sqlplus scott/tiger@DB8" might access the Oracle 8 -> instance, and "scott/tiger@DB9" might access the Oracle 9 instance. -> -> What people are telling you is that you can choose client version -> independently of the server version. For example, it is possible to set -> ORACLE_HOME to /usr/local/oracle9 and call -> -> /usr/local/oracle9/bin/sqlplus scott/tiger@DB8 -> -> to access the Oracle 8 instance with the Oracle 9 client. This of course -> requires that the definition for DB8 is present in the file -> /usr/local/oracle-9.2/network/admin/tnsnames.ora. -> -> So you should either -> -> 1. Use only the Oracle 9 client, not change ORACLE_HOME, and access both -> instances with Oracle 9 sqlplus and DBD::Oracle compiled against -> Oracle 9 libraries. -> -> or -> -> 2. Compile DBD::Oracle twice (once against Oracle 8 libraries, once -> against Oracle 9 libraries, just as you have two versions of sqlplus) -> and use each one with the proper ORACLE_HOME setting. -> -> My guess is that you will find possibility 1. the easiest. -> -> > The tnsnames.ora are all set. I did what you said already. -> > -> > Example: DBI/DBD will work fine if I compile the DBI/DBD pointing to -> > Oracle 8 environment(libraries) and access an Oracle 8 instance. I -> > didn't have to change tnsnames.ora -> -> Yes you do: You need to have BOTH Oracle instances defined in EACH -> tnsnames.ora. -> -> Hope this helps, -> -> - Kristian. - - - -From andy@andyh.co.uk Wed Jan 7 07:31:57 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i077VPn8081048 - for ; Wed, 7 Jan 2004 07:31:57 GMT - (envelope-from andy@andyh.co.uk) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 07 Jan 2004 07:31:57 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Ae0Yb-0002lT-IA; - Tue, 06 Jan 2004 23:24:17 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Ae0Yb-0002lT-IA - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 23:24:17 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 00D7C3C15 - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id CB5813BEA - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from mta03-svc.ntlworld.com (mta03-svc.ntlworld.com [62.253.162.43]) - by integer.pobox.com (Postfix) with ESMTP - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from excession ([80.2.244.47]) by mta03-svc.ntlworld.com - (InterMail vM.4.01.03.37 201-229-121-137-20020806) with SMTP - id <20040106232403.NEKJ9852.mta03-svc.ntlworld.com@excession>; - Tue, 6 Jan 2004 23:24:03 +0000 -Message-ID: <00bd01c3d4ac$e5713190$6564a8c0@excession> -From: "Andy Hassall" -To: "Eric Lenio" , "Tim Bunce" -Cc: -References: <20040102143310.GC27273@lenio.net> <20040104204914.GB60357@dansat.data-plan.com> <20040105123653.GA31473@lenio.net> <20040105223121.GG66760@dansat.data-plan.com> <20040106222634.GG11531@lenio.net> <20040106223845.GE78360@dansat.data-plan.com> <20040106225722.GI11531@lenio.net> -Subject: Re: DBI primary_key tests fail: oracle 8 -Date: Tue, 6 Jan 2004 23:29:14 -0000 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2800.1158 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 43 - -Eric Lenio wrote: -> OK Tim. One other note -- after reading through oracle docs, I think -> you might want to substitute 'session_user' for 'current_schema' in -> 'select sys_context(...)'. The definition of session_user is -> "returns the database -> user name by which the current user is authenticated" while -> current_schema is "returns the name of the default schema being used -> in the current session". -> Maybe it doesn't matter, I'm not an oracle guru by any stretch of the -> imagination. - -There's several usernames in the USERENV context: - -CURRENT_SCHEMA - -The schema/user used for unqualified object name resolution; by default the -user you logged in as, but alterable with 'alter session set -current_schema=x'. Useful for avoiding having to maintain loads of synonyms. - -CURRENT_USER - -The user you're currently authenticated as. Doesn't change in SQL and -anonymous PL/SQL, but changes within definer-rights PL/SQL stored procedures -to the owner of the stored procedure, since stored procs by default run with -the privileges of the owner, not the invoker. - -SESSION_USER - -Who you originally logged in as, and never changes (but see below). Looks -like the appropriate one to use. - -PROXY_USER - -I don't think DBD::Oracle supports proxy authentication so don't need to -worry about that one yet. Possibly a bit of a grey area if it does support -it in the future, since this would hold the username in the DSN, but it'd -reauthenticate and change the SESSION_USER on connect (which would probably -have to be specified as an attribute to the $dbh). - --- -Andy Hassall (andy@andyh.co.uk) icq(5747695) (http://www.andyh.co.uk) -Space: disk usage analysis tool (http://www.andyhsoftware.co.uk/space) - - diff --git a/err_unsorted/err_ora9ir2oci.msg b/err_unsorted/err_ora9ir2oci.msg deleted file mode 100644 index 7ed476e4..00000000 --- a/err_unsorted/err_ora9ir2oci.msg +++ /dev/null @@ -1,27 +0,0 @@ -http://otn.oracle.com/tech/oci/htdocs/oci9ir2_new_features - -OCI Session Pooling -Session Pooling is a new feature in Oracle 9i Database Release 2. -An application can now maintain a pool of sessions and use a session -from the pool when it needs it. This saves the time consuming process -of initiating a connection and authentication every time the process -needs a new session. Session Pooling is useful, especially when a -large number of stateless sessions are required for a very short -time. In a web scenario, where many users are connected for a short -time, and the primary operation is accessing data, it is a costly -operation to start up a new session every time. In such a scenario, -session pooling could boost up the performance. - -OCI Statement caching -Client-side statement caching is also introduced in Oracle9i Database -Release 2. This feature can be enabled at the time of session -creation. It allows users to have a cache of statements per session. -On the server, this means having cursors that ready to be used, -without the need to parse the statements again, and thus improving -performance significantly. With this feature enabled, applications -do not have to keep a track of the statements themselves, as the -OCI layer will do it for them. In addition, a tagging feature is -provided, which users can use as a key to save and search for -statements. - - diff --git a/err_unsorted/err_ref_type.msg b/err_unsorted/err_ref_type.msg deleted file mode 100644 index 26d86e14..00000000 --- a/err_unsorted/err_ref_type.msg +++ /dev/null @@ -1,115 +0,0 @@ -From dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org Wed Jul 23 18:40:02 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6NHUUA0010501 - for ; Wed, 23 Jul 2003 18:40:02 +0100 (BST) - (envelope-from dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 23 Jul 2003 18:40:02 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058948095:10:09585:8; Wed, 23 Jul 2003 08:14:55 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116163; 23 Jul 2003 8:14 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 88C1B21C024 - for ; Wed, 23 Jul 2003 04:13:51 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id AA89B21C082 - for ; Wed, 23 Jul 2003 04:13:50 -0400 (EDT) -Received: (qmail 26606 invoked by uid 1005); 23 Jul 2003 08:13:44 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 26590 invoked by uid 76); 23 Jul 2003 08:13:43 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Wed, 23 Jul 2003 01:13:43 -0700 -Received: (qmail 16360 invoked by uid 225); 23 Jul 2003 08:13:41 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16355 invoked by uid 507); 23 Jul 2003 08:13:41 -0000 -Received-SPF: unknown -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Wed, 23 Jul 2003 01:13:41 -0700 -Received: (qmail 5378 invoked from network); 23 Jul 2003 08:54:08 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 23 Jul 2003 08:54:08 -0000 -Received: (qmail 8984 invoked from network); 23 Jul 2003 08:13:49 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 23 Jul 2003 08:13:49 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Wed, 23 Jul 2003 10:13:49 +0200 (CEST) -Subject: Re: binding to parameters of type REF -From: Hendrik =?ISO-8859-1?Q?Fu=DF?= -To: dbi-users@perl.org -In-Reply-To: <1058865345.1241.56.camel@mars> -References: <1058865345.1241.56.camel@mars> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 -Date: 23 Jul 2003 10:11:49 +0200 -Message-Id: <1058947909.6353.5.camel@mars> -Mime-Version: 1.0 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.3 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,LARGE_HEX,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1354 -Lines: 56 - -I've also found out, that DBD::Oracle does not support type SQL_REF: -When not using DBD::Proxy I get: - - SQL type 20 for ':p1' is not fully supported, - bound as SQL_VARCHAR instead - -I even get segmentation faults when trying to fetch REF columns. :-( - -Any ideas? - -> Hi, -> -> I'm trying to bind a perl variable to an Oracle table reference with -> Oracle 9.2.0.3, DBD::Proxy and Perl::DBI 1.37 without success. I -> could'nt find help on this in the docs or list archives. I hope this is -> the right place to post. -> -> In SQL*Plus: -> -> SQL> desc getReference -> FUNCTION getReference RETURNS REF OF TABLETYPE -> -> SQL> select getReference() from dual; -> -> GETREFERENCE() -> ---------------------------------------------------------------------- -> 0000280209C229D2216EF6A5F4E030010A8D086AD3C204FC6EE0E46501E030010A8D08 -> 2CE703C0000E0000 -> -> -> My code: -> -> my $ref = undef; -> my $sth = $dbh->prepare('BEGIN ? := getReference(); END;'); -> $sth->bind_param_inout(1, \$ref, 128, SQL_REF ); -> $sth->execute(); -> -> yields: -> -> PLS-00382: expression is of wrong type -> -> -> Even fetching a reference does not work: -> -> my $sth = $dbh->prepare('SELECT getReference() FROM DUAL'); -> $sth->execute(); -> ($ref) = $sth->fetchrow_array(); -> -> yields undef in $ref. -> -> I'd very much appreciate your help. -> cheers, -> Hendrik - - - - diff --git a/err_unsorted/err_refcsr_rowcache.msg b/err_unsorted/err_refcsr_rowcache.msg deleted file mode 100644 index 5101d2ae..00000000 --- a/err_unsorted/err_refcsr_rowcache.msg +++ /dev/null @@ -1,85 +0,0 @@ -From dbi-users-bounce@isc.org Tue May 16 22:53:12 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id WAA29547; Tue, 16 May 2000 22:53:11 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <04730-2@oink>; Sat, 16 May 1970 22:51:48 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 958512876:10:15786:0; Tue, 16 May 2000 21:34:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1122388; 16 May 2000 21:33 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 661E53EC8; - Tue, 16 May 2000 14:33:38 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Tue, 16 May 2000 14:28:31 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id 7192F3E20 - for ; - Tue, 16 May 2000 14:28:27 -0700 (PDT) -Received: from anchor-post-34.mail.demon.net (anchor-post-34.mail.demon.net [194.217.242.92]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id OAA27204 - for ; - Tue, 16 May 2000 14:28:26 -0700 (PDT) env-from (Tim.Bunce@ig.co.uk) -Received: from ignite.demon.co.uk ([158.152.8.99] helo=oink) - by anchor-post-34.mail.demon.net with smtp (Exim 2.12 #1) - id 12rot7-000Mp4-0Y; Tue, 16 May 2000 22:28:25 +0100 -Received: from toad by oink with SMTP (PP) id <04650-0@oink>; - Sat, 16 May 1970 22:23:55 +0100 -Received: by toad.ig.co.uk (SMI-8.6/SMI-SVR4) id WAA29289; - Tue, 16 May 2000 22:23:50 +0100 -Date: Tue, 16 May 2000 22:23:50 +0100 -From: Tim Bunce -To: peter_dev@talk21.com -Cc: dbi-users@isc.org -Subject: Re: Oracle Stored Procs take longer than embedded SQL -Message-ID: <20000516222350.F28435@ig.co.uk> -References: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs>; from peter_dev@talk21.com on Tue, May 16, 2000 at 06:48:22PM +0100 -Organization: Paul Ingram Group, Software Systems, +44 1 483 862800 -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 1372 -Lines: 30 - -On Tue, May 16, 2000 at 06:48:22PM +0100, peter_dev@talk21.com wrote: -> I have a problem with the fetching of data from an Oracle Ref Cursor taking longer than the same query in Embeded SQL. -> -> $ get_sp.pl -> Fetched in 0.00774896144866943 seconds -> Completed in 0.106827020645142 seconds -> -> $ get_sql.pl -> Fetched in 0.00138604640960693 seconds -> Completed in 0.380790948867798 seconds -> -> In this example (Using the SCOTT/TIGER tables), while the Stored Procedure completed first, the actual fetch of the data took considerably longer. In a real situation (e.g. bigger tables ), this is easily the longest part of the task and causes the overall execution time to increase hugely. -> -> Any Help would be appreciated -> thanks - -Possibly related to the lack of a row cache on that statement handle. -You, or some kind volunteer, could probably hack that in without too -much work. - -Tim. - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_unsorted/err_refcsr_slow.msg b/err_unsorted/err_refcsr_slow.msg deleted file mode 100644 index 790d267d..00000000 --- a/err_unsorted/err_refcsr_slow.msg +++ /dev/null @@ -1,347 +0,0 @@ -From dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org Mon Apr 29 23:12:51 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TMCpR17212 - for ; Mon, 29 Apr 2002 23:12:51 +0100 (BST) - (envelope-from dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 29 Apr 2002 23:12:51 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020117986:10:17770:92; Mon, 29 Apr 2002 22:06:26 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1017591; 29 Apr 2002 22:06 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id 975037274A - for ; Mon, 29 Apr 2002 18:01:37 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by wormwood.pobox.com (Postfix) with SMTP id ED2897273F - for ; Mon, 29 Apr 2002 18:01:34 -0400 (EDT) -Received: (qmail 70462 invoked by uid 1005); 29 Apr 2002 21:59:33 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 20335 invoked by uid 76); 29 Apr 2002 20:18:55 -0000 -Message-ID: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Date: Mon, 29 Apr 2002 13:18:53 -0700 (PDT) -From: Calin Medianu -Reply-To: cmedianu@sfu.ca -Subject: DBD::Oracle Slow cursors -To: dbi-users@perl.org -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 568 -Lines: 21 - -Hello, - -I did the following. Wrote a perl script that retreves -data via a straight select from the database. Then I -wrote a stored procedure returning a ref cursor open -on the same select statement and retrieved the data as -well. Using the REF CURSOR/ sotred procedure was about -3 time slower, that is 40 seconds instead of around -10. - -Is this normal? Is this a problem with oracle or with -DBD::Oracle? - -Thanks, - -Calin Medianu - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org Tue Apr 30 00:06:36 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TN6aR17980 - for ; Tue, 30 Apr 2002 00:06:36 +0100 (BST) - (envelope-from dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 00:06:36 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020119533:20:05733:4; Mon, 29 Apr 2002 22:32:13 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2005393; 29 Apr 2002 22:32 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 4E6B73E6BF - for ; Mon, 29 Apr 2002 18:32:00 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-1.pobox.com (Postfix) with SMTP id BF79C3E6A0 - for ; Mon, 29 Apr 2002 18:31:59 -0400 (EDT) -Received: (qmail 87860 invoked by uid 1005); 29 Apr 2002 22:31:59 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 87844 invoked by uid 76); 29 Apr 2002 22:31:58 -0000 -Received: from mail01.svc.cra.dublin.eircom.net (HELO mail01.svc.cra.dublin.eircom.net) (159.134.118.17) - by onion.perl.org (qpsmtpd/0.07) with SMTP; Mon Apr 29 22:31:58 2002 -0000 -Received: (qmail 21911 messnum 119827 invoked from network[159.134.167.97/p865.as1.limerick1.eircom.net]); 29 Apr 2002 22:31:29 -0000 -Received: from p865.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.97) - by mail01.svc.cra.dublin.eircom.net (qp 21911) with SMTP; 29 Apr 2002 22:31:29 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g3TMVcR17579; - Mon, 29 Apr 2002 23:31:38 +0100 (BST) - (envelope-from timbo) -Date: Mon, 29 Apr 2002 23:31:38 +0100 -From: Tim Bunce -To: cmedianu@sfu.ca -Cc: dbi-users@perl.org -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020429233138.E16831@dansat.data-plan.com> -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020429201853.52283.qmail@web10007.mail.yahoo.com>; from calinm@yahoo.com on Mon, Apr 29, 2002 at 01:18:53PM -0700 -Content-Length: 651 -Lines: 20 - -On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> Hello, -> -> I did the following. Wrote a perl script that retreves -> data via a straight select from the database. Then I -> wrote a stored procedure returning a ref cursor open -> on the same select statement and retrieved the data as -> well. Using the REF CURSOR/ sotred procedure was about -> 3 time slower, that is 40 seconds instead of around -> 10. -> -> Is this normal? Is this a problem with oracle or with -> DBD::Oracle? - -DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. - -Get a level 3 trace and look for the "dbd_describe'd" line for the -ref cursor. - -Tim. - -From calinm@yahoo.com Tue Apr 30 22:02:56 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL2tR26878 - for ; Tue, 30 Apr 2002 22:02:55 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:02:55 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020198219:10:21718:114; Tue, 30 Apr 2002 20:23:39 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101732; 30 Apr 2002 20:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C6B4A2BFB4 - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10004.mail.yahoo.com (web10004.mail.yahoo.com [216.136.130.40]) - by dolly1.pobox.com (Postfix) with SMTP id 527BD2BF3D - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Message-ID: <20020430202321.54825.qmail@web10004.mail.yahoo.com> -Received: from [213.157.171.169] by web10004.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 13:23:20 PDT -Date: Tue, 30 Apr 2002 13:23:20 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -Cc: dbi-users@perl.org -In-Reply-To: <20020430140517.P16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 425 -Lines: 18 - -I "Solved" the problem. For Now.. I did -perl Makefile.PL -8 - -hoping that the buggy code would be recently added, -and it was. Now both the select and the cursor return -the data at the same speed, meaning fast.. - -Am I am missing much by not using the code for Oracle -8? - -Thanks, - -Calin - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From timbo@dansat.data-plan.com Wed May 1 16:49:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g41FnsR33994 - for ; Wed, 1 May 2002 16:49:54 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 May 2002 16:49:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020265865:20:10671:66; Wed, 01 May 2002 15:11:05 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-2.mail.demon.net - id aa2122069; 1 May 2002 15:10 GMT -Received: from cali-3.pobox.com (cali-3.pobox.com [64.71.166.116]) - by silk.pobox.com (Postfix) with ESMTP id F29CC3FDF2 - for ; Wed, 1 May 2002 11:09:52 -0400 (EDT) -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id E3A943E689 - for ; Wed, 1 May 2002 10:57:15 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id D1F523E688 - for ; Wed, 1 May 2002 10:57:14 -0400 (EDT) -Received: (qmail 96042 messnum 564683 invoked from network[159.134.166.63/p575.as1.limerick1.eircom.net]); 1 May 2002 14:57:13 -0000 -Received: from p575.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.63) - by mail03.svc.cra.dublin.eircom.net (qp 96042) with SMTP; 1 May 2002 14:57:13 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g41EvIh33626; - Wed, 1 May 2002 15:57:18 +0100 (BST) - (envelope-from timbo) -Date: Wed, 1 May 2002 15:57:18 +0100 -From: Tim Bunce -To: Calin Medianu -Cc: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020501155718.S16831@dansat.data-plan.com> -References: <20020430151126.Q16831@dansat.data-plan.com> <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020430183429.33340.qmail@web10005.mail.yahoo.com>; from calinm@yahoo.com on Tue, Apr 30, 2002 at 11:34:29AM -0700 -Status: RO -Content-Length: 3111 -Lines: 111 - -Thanks. I'll take a look when I get to DBD::Oracle again. - -I think the last row of that table applies and it doesn't refer to OCIBindObject(): - REF CURSOR variables - SQLT_RSET - Allocate a statement handle, OCIStmt, and then bind its address - (OCIStmt **) using the SQLT_RSET datatype. -Note that SQLT_REF isn't the same as SQLT_RSET. - -You could always try patching it yourself! - -Tim. - - -On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin Medianu wrote: -> It says here: -> http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> -> that 2 calls are neede to bind a ref , the second is -> to OCIBindObject() which I don't see in dbdimp.c. -> -> Could this be a reason? -> -> Cheers, -> -> Calin -> -> --- Tim Bunce wrote: -> > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > Medianu wrote: -> > > Me again with the slow cursors. -> > > -> > > I modified both queries to only return 10 rows. -> > > I ran a sniffer (ethereal) on the NIC. It is -> > pretty cool, it also decodes TNS. -> > > -> > > when I am using the SQL, it works like this, there -> > are about 7 packets -> > > received by my workstation to set up the session, -> > then all 10 rows are in the -> > > same packet, then there is another packet probably -> > saying goodbye. -> > > -> > > When I am using the REF cursor, each row comes in -> > it's own TNS packet, that -> > > is why it is so slow! -> > > -> > > Any idea how to fix it? -> > -> > Do a level 9 trace to get a log of the OCI calls and -> > confirm that -> > the fragment I posted is being called (may be -> > helpful to also -> > add an extra print statement into that code since -> > parsing the -> > OCI trace can be painful). -> > -> > Assuming the code is being called then as far as I -> > can see the code is -> > doing the right thing and it's probably an Oracle -> > OCI issue. -> > -> > You'd need to talk to Oracle support. No need to -> > mention perl etc. -> > Just talk about your OCI application and provide the -> > OCI call trace. -> > -> > Let me know what you find out! -> > -> > Tim. -> > -> > > thanks a lot, -> > > -> > > Calin -> > > -> > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> > Medianu wrote: -> > > > > Hello, -> > > > > -> > > > > I did the following. Wrote a perl script that -> > retreves -> > > > > data via a straight select from the database. -> > Then I -> > > > > wrote a stored procedure returning a ref -> > cursor open -> > > > > on the same select statement and retrieved the -> > data as -> > > > > well. Using the REF CURSOR/ sotred procedure -> > was about -> > > > > 3 time slower, that is 40 seconds instead of -> > around -> > > > > 10. -> > > > > -> > > > > Is this normal? Is this a problem with oracle -> > or with -> > > > > DBD::Oracle? -> > > > -> > > > DBD::Oracle. It probably isn't setting up a row -> > cache for the ref cursor. -> > > > -> > > > Get a level 3 trace and look for the -> > "dbd_describe'd" line for the -> > > > ref cursor. -> > > > -> > > > Tim. -> -> -> __________________________________________________ -> Do You Yahoo!? -> Yahoo! Health - your guide to health and wellness -> http://health.yahoo.com - diff --git a/err_unsorted/err_slowcsr.msg b/err_unsorted/err_slowcsr.msg deleted file mode 100644 index 80c43350..00000000 --- a/err_unsorted/err_slowcsr.msg +++ /dev/null @@ -1,316 +0,0 @@ -From calinm@yahoo.com Tue Apr 30 22:03:11 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL3AR27018 - for ; Tue, 30 Apr 2002 22:03:10 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:03:10 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020196981:10:23493:39; Tue, 30 Apr 2002 20:03:01 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-1.mail.demon.net - id aa1108477; 30 Apr 2002 20:02 GMT -Received: from dolly1.pobox.com (dolly1.pobox.com [207.106.49.22]) - by silk.pobox.com (Postfix) with ESMTP id 915563FCE8 - for ; Tue, 30 Apr 2002 14:35:38 -0400 (EDT) -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 343702BFDD - for ; Tue, 30 Apr 2002 14:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10005.mail.yahoo.com (web10005.mail.yahoo.com [216.136.130.41]) - by dolly1.pobox.com (Postfix) with SMTP id 6AA822BFA3 - for ; Tue, 30 Apr 2002 14:34:37 -0400 (EDT) -Message-ID: <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Received: from [213.157.171.169] by web10005.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 11:34:29 PDT -Date: Tue, 30 Apr 2002 11:34:29 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020430151126.Q16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 2457 -Lines: 96 - -It says here: -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 - -that 2 calls are neede to bind a ref , the second is -to OCIBindObject() which I don't see in dbdimp.c. - -Could this be a reason? - -Cheers, - -Calin - ---- Tim Bunce wrote: -> On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> Medianu wrote: -> > Me again with the slow cursors. -> > -> > I modified both queries to only return 10 rows. -> > I ran a sniffer (ethereal) on the NIC. It is -> pretty cool, it also decodes TNS. -> > -> > when I am using the SQL, it works like this, there -> are about 7 packets -> > received by my workstation to set up the session, -> then all 10 rows are in the -> > same packet, then there is another packet probably -> saying goodbye. -> > -> > When I am using the REF cursor, each row comes in -> it's own TNS packet, that -> > is why it is so slow! -> > -> > Any idea how to fix it? -> -> Do a level 9 trace to get a log of the OCI calls and -> confirm that -> the fragment I posted is being called (may be -> helpful to also -> add an extra print statement into that code since -> parsing the -> OCI trace can be painful). -> -> Assuming the code is being called then as far as I -> can see the code is -> doing the right thing and it's probably an Oracle -> OCI issue. -> -> You'd need to talk to Oracle support. No need to -> mention perl etc. -> Just talk about your OCI application and provide the -> OCI call trace. -> -> Let me know what you find out! -> -> Tim. -> -> > thanks a lot, -> > -> > Calin -> > -> > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> Medianu wrote: -> > > > Hello, -> > > > -> > > > I did the following. Wrote a perl script that -> retreves -> > > > data via a straight select from the database. -> Then I -> > > > wrote a stored procedure returning a ref -> cursor open -> > > > on the same select statement and retrieved the -> data as -> > > > well. Using the REF CURSOR/ sotred procedure -> was about -> > > > 3 time slower, that is 40 seconds instead of -> around -> > > > 10. -> > > > -> > > > Is this normal? Is this a problem with oracle -> or with -> > > > DBD::Oracle? -> > > -> > > DBD::Oracle. It probably isn't setting up a row -> cache for the ref cursor. -> > > -> > > Get a level 3 trace and look for the -> "dbd_describe'd" line for the -> > > ref cursor. -> > > -> > > Tim. - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From calinm@yahoo.com Fri May 3 13:48:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g43Cm5R50489 - for ; Fri, 3 May 2002 13:48:05 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 03 May 2002 13:48:05 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020429421:10:02019:143; Fri, 03 May 2002 12:37:01 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1123562; 3 May 2002 12:36 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id D7BD1725A1 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10008.mail.yahoo.com (web10008.mail.yahoo.com [216.136.130.44]) - by wormwood.pobox.com (Postfix) with SMTP id 3088772674 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Message-ID: <20020503123640.19648.qmail@web10008.mail.yahoo.com> -Received: from [213.157.171.169] by web10008.mail.yahoo.com via HTTP; Fri, 03 May 2002 05:36:40 PDT -Date: Fri, 3 May 2002 05:36:40 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020501155718.S16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -Content-Length: 3619 -Lines: 150 - -Sure, - -I'll give it a try next week. - -Cheers, - -Calin ---- Tim Bunce wrote: -> Thanks. I'll take a look when I get to DBD::Oracle -> again. -> -> I think the last row of that table applies and it -> doesn't refer to OCIBindObject(): -> REF CURSOR variables -> SQLT_RSET -> Allocate a statement handle, OCIStmt, and then -> bind its address -> (OCIStmt **) using the SQLT_RSET datatype. -> Note that SQLT_REF isn't the same as SQLT_RSET. -> -> You could always try patching it yourself! -> -> Tim. -> -> -> On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin -> Medianu wrote: -> > It says here: -> > -> -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> > -> > that 2 calls are neede to bind a ref , the second -> is -> > to OCIBindObject() which I don't see in dbdimp.c. -> > -> > Could this be a reason? -> > -> > Cheers, -> > -> > Calin -> > -> > --- Tim Bunce wrote: -> > > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > > Medianu wrote: -> > > > Me again with the slow cursors. -> > > > -> > > > I modified both queries to only return 10 -> rows. -> > > > I ran a sniffer (ethereal) on the NIC. It is -> > > pretty cool, it also decodes TNS. -> > > > -> > > > when I am using the SQL, it works like this, -> there -> > > are about 7 packets -> > > > received by my workstation to set up the -> session, -> > > then all 10 rows are in the -> > > > same packet, then there is another packet -> probably -> > > saying goodbye. -> > > > -> > > > When I am using the REF cursor, each row comes -> in -> > > it's own TNS packet, that -> > > > is why it is so slow! -> > > > -> > > > Any idea how to fix it? -> > > -> > > Do a level 9 trace to get a log of the OCI calls -> and -> > > confirm that -> > > the fragment I posted is being called (may be -> > > helpful to also -> > > add an extra print statement into that code -> since -> > > parsing the -> > > OCI trace can be painful). -> > > -> > > Assuming the code is being called then as far as -> I -> > > can see the code is -> > > doing the right thing and it's probably an -> Oracle -> > > OCI issue. -> > > -> > > You'd need to talk to Oracle support. No need to -> > > mention perl etc. -> > > Just talk about your OCI application and provide -> the -> > > OCI call trace. -> > > -> > > Let me know what you find out! -> > > -> > > Tim. -> > > -> > > > thanks a lot, -> > > > -> > > > Calin -> > > > -> > > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, -> Calin -> > > Medianu wrote: -> > > > > > Hello, -> > > > > > -> > > > > > I did the following. Wrote a perl script -> that -> > > retreves -> > > > > > data via a straight select from the -> database. -> > > Then I -> > > > > > wrote a stored procedure returning a ref -> > > cursor open -> > > > > > on the same select statement and retrieved -> the -> > > data as -> > > > > > well. Using the REF CURSOR/ sotred -> procedure -> > > was about -> > > > > > 3 time slower, that is 40 seconds instead -> of -> > > around -> > > > > > 10. -> > > > > > -> > > > > > Is this normal? Is this a problem with -> oracle -> > > or with -> > > > > > DBD::Oracle? -> > > > > -> > > > > DBD::Oracle. It probably isn't setting up a -> row -> > > cache for the ref cursor. -> > > > > -> > > > > Get a level 3 trace and look for the -> > > "dbd_describe'd" line for the -> > > > > ref cursor. -> > > > > -> > > > > Tim. -> > -> > -> > __________________________________________________ -> > Do You Yahoo!? -> > Yahoo! Health - your guide to health and wellness -> > http://health.yahoo.com - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - diff --git a/err_unsorted/err_svrparse.msg b/err_unsorted/err_svrparse.msg deleted file mode 100644 index 16886ca8..00000000 --- a/err_unsorted/err_svrparse.msg +++ /dev/null @@ -1,4717 +0,0 @@ -From cary.millsap@hotsos.com Thu Sep 12 23:38:20 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8CMbgC02618 - for ; Thu, 12 Sep 2002 23:38:03 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 12 Sep 2002 23:38:03 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031869308:20:16258:30; Thu, 12 Sep 2002 22:21:48 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2108888; 12 Sep 2002 22:21 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id A32132F05C9 - for ; Thu, 12 Sep 2002 18:21:34 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-3.pobox.com (Postfix) with ESMTP id D71F62F056D - for ; Thu, 12 Sep 2002 18:21:31 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8CMLQn17849; - Thu, 12 Sep 2002 17:21:26 -0500 -From: "Cary Millsap" -To: -Subject: -Date: Thu, 12 Sep 2002 17:21:17 -0500 -Message-ID: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_016A_01C25A80.D1527130" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 64884 -Lines: 2025 - -This is a multi-part message in MIME format. - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: multipart/alternative; - boundary="----=_NextPart_001_016B_01C25A80.D1557E70" - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -How are you doing? I hope you've had a good two years since I saw you on -the Oracle Geek Cruise event. - - - -I've been working on a project this year to construct a book about -optimizing Oracle response time. In my research, I've discovered -something about the DBI that I didn't expect: it executes two Oracle -parse calls for every one that I would expect an efficient DBI layer to -make. I've included my Perl source (below), the Oracle level-12 trace -data that shows the sequence of calls it's receiving from the Perl -application (below), a level-9 DBI trace from the application -(attached), and our version information (below). - - - -The reason I'm bringing this to your attention in this way is that I'm -relying pretty heavily upon Perl for performance measurement tools, -examples, and simulators in the text. I love the language and I want for -the book to be an encouragement for more people to use Perl. However, -this extra-parse behavior is one of the things that the book highlights -as an important scalability barrier (some other tools do it too, -unfortunately). Of course, this is a speed bump on the road to my goal -of helping to promote Perl. - - - -I was hoping that by showing you this specific data, you could make the -problem go away. - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - -Listing [listing.sqltrace.pl]: a simple application that executes a -database query - -#!/usr/bin/perl - - - - - -# $Header: /home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 21:10:25 -cvm Exp $ - -# Cary Millsap (cary.millsap@hotsos.com) - - - - - -use strict; - -use warnings; - -use DBI; - -use DBD::Oracle; - -use Getopt::Long; - -use Term::ReadKey; - - - - - -my $sth; # Oracle statement handle - -my $hostname = ""; - -my $username = "/"; - -my $password = ""; - -my $logfile = "ex1.log"; - -my %attr = ( - - RaiseError => 1, - - AutoCommit => 0, - -); - -my %opt = ( - - pause => 0, - -); - - - - - -# Get command line options and arguments. - -GetOptions( - - "pause" => \$opt{pause}, - -); - -my $key = 37; # default query value - -$key = $ARGV[0] if $ARGV[0]; - - - - - -# Connect to Oracle. - -my $dbh = DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr); - -$dbh->trace(9, $logfile); - - - - - -# Activate tracing. - -$sth = $dbh->prepare(q(alter session set events '10046 trace name -context forever, level 12')); - -$sth->execute; - - - - - -# Allow the user to find the Oracle session and activate OS diagnostic - -# tools like strace(1) or lsof(8). - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Execute the query to trace. - -$sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -$sth->execute($key); - - - - - -# Print output header. - -my @cdefs = qw(%8d %8d %32s); # column definitions - -my @hdefs = qw(Key Fkey Value); # column headings - -my $bformat = join(" ", @cdefs) . "\n"; - -my $hformat; ($hformat = $bformat) =~ s/%(\d*)\S+/%$1s/g; - -printf $hformat, @hdefs; - -printf $hformat, do { my @h; push @h, "-" x (/(\d+)/?$1:10) for @cdefs; -@h }; - - - - - -# Print query results. - -for my $row (@{$sth->fetchall_arrayref}) { - - printf $bformat, @$row; - -} - - - - - -# Allow the user to do final OS diagnostic stuff. - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Disconnect from Oracle. - -$dbh->disconnect; - - - - - -Listing [listing:sqltrace.trc]: raw SQL trace output for an execution of -our program - -/usr/local/oracle/admin/V816/udump/ora_17349.trc - -Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production - -With the Partitioning option - -JServer Release 8.1.6.0.0 - Production - -ORACLE_HOME = /usr/local/oracle/product/8.1.6 - -System name: Linux - -Node name: www.hotsos.com - -Release: 2.2.16-22enterprise - -Version: #1 SMP Tue Aug 22 16:29:32 EDT 2000 - -Machine: i686 - -Instance name: V816 - -Redo thread mounted by this instance: 1 - -Oracle process number: 8 - -Unix process pid: 17349, image: oracle@www.hotsos.com (TNS V1-V3) - - - -*** SESSION ID:(7.9) 2002-09-12 16:14:01.582 - -===================== - -PARSING IN CURSOR #1 len=69 dep=0 uid=12 oct=42 lid=12 tim=107309054 -hv=1509700594 ad='54af5e14' - -alter session set events '10046 trace name context forever, level 12' - -END OF STMT - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107309054 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -*** 2002-09-12 16:14:31.226 - -WAIT #1: nam='SQL*Net message from client' ela= 2964 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -WAIT #2: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #2: nam='SQL*Net message from client' ela= 0 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -BINDS #1: - - bind 0: dty=1 mxl=32(04) mal=00 scl=00 pre=00 oacflg=25 oacfl2=10 -size=32 offset=0 - - bfp=0940e7f0 bln=32 avl=04 flg=05 - - value="8542" - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #1: nam='file open' ela= 0 p1=0 p2=0 p3=0 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6671 p3=1 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6678 p3=1 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - -*** 2002-09-12 16:14:56.200 - -WAIT #1: nam='SQL*Net message from client' ela= 2496 p1=1650815232 p2=1 -p3=0 - -XCTEND rlbk=0, rd_only=1 - -STAT #1 id=1 cnt=1 pid=0 pos=0 obj=5156 op='TABLE ACCESS BY INDEX ROWID -T ' - -STAT #1 id=2 cnt=2 pid=1 pos=1 obj=5157 op='INDEX UNIQUE SCAN ' - - - - - -$ perl -V - -Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration: - - Platform: - - osname=linux, osvers=2.2.5-22smp, archname=i386-linux - - uname='linux porky.devel.redhat.com 2.2.5-22smp #1 smp wed jun 2 -09:11:51 edt 1999 i686 unknown ' - - config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -Dcc=gcc --Dcccdlflags=-fPIC -Dinstallprefix=/usr -Dprefix=/usr --Darchname=i386-linux -Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm --Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Uuselargefiles' - - hint=recommended, useposix=true, d_sigaction=define - - usethreads=undef use5005threads=undef useithreads=undef -usemultiplicity=undef - - useperlio=undef d_sfio=undef uselargefiles=undef - - use64bitint=undef use64bitall=undef uselongdouble=undef -usesocks=undef - - Compiler: - - cc='gcc', optimize='-O2 -march=i386 -mcpu=i686', gccversion=2.96 -20000731 (experimental) - - cppflags='-fno-strict-aliasing' - - ccflags ='-fno-strict-aliasing' - - stdchar='char', d_stdstdio=define, usevfork=false - - intsize=4, longsize=4, ptrsize=4, doublesize=8 - - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', -lseeksize=4 - - alignbytes=4, usemymalloc=n, prototype=define - - Linker and Libraries: - - ld='gcc', ldflags =' -L/usr/local/lib' - - libpth=/usr/local/lib /lib /usr/lib - - libs=-lnsl -ldl -lm -lc -lcrypt - - libc=/lib/libc-2.1.92.so, so=so, useshrplib=false, libperl=libperl.a - - Dynamic Linking: - - dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' - - cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' - - - - - -Characteristics of this binary (from libperl): - - Compile-time options: - - Built under linux - - Compiled at Aug 7 2000 10:59:51 - - @INC: - - /usr/lib/perl5/5.6.0/i386-linux - - /usr/lib/perl5/5.6.0 - - /usr/lib/perl5/site_perl/5.6.0/i386-linux - - /usr/lib/perl5/site_perl/5.6.0 - - /usr/lib/perl5/site_perl - - . - - - - - -Other site information - -- Redhat Linux 7.0 - -- Oracle 8.1.6.1.0 - -- DBD-Oracle 1.12 - -- DBI 1.30 - - - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

How are you doing? I hope you’ve had a good two = -years -since I saw you on the Oracle Geek Cruise event.

- -

 

- -

I’ve been working on a project this year to = -construct -a book about optimizing Oracle response time. In my research, I’ve -discovered something about the DBI that I didn’t expect: it = -executes two -Oracle parse calls for every one that I would expect an efficient DBI = -layer to -make. I’ve included my Perl source (below), the Oracle level-12 = -trace -data that shows the sequence of calls it’s receiving from the Perl = -application -(below), a level-9 DBI trace from the application (attached), and our = -version information -(below).

- -

 

- -

The reason I’m bringing this to your attention = -in this -way is that I’m relying pretty heavily upon Perl for performance -measurement tools, examples, and simulators in the text. I love the = -language -and I want for the book to be an encouragement for more people to use = -Perl. -However, this extra-parse behavior is one of the things that the book = -highlights -as an important scalability barrier (some other tools do it too, = -unfortunately). -Of course, this is a speed bump on the road to my goal of helping to = -promote Perl.

- -

 

- -

I was hoping that by showing you this specific data, = -you -could make the problem go away.

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -
- -

Listing [listing.sqltrace.pl]: a simple = -application that -executes a database query

- -
- -
- -

#!/usr/bin/perl

- -

- -

- -

 

- -

 

- -

# = -$Header: -/home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 = -21:10:25 cvm Exp $

- -

- -

# = -Cary Millsap (cary.millsap@hotsos.com)

- -

- -

 

- -

 

- -

use = -strict;

- -

- -

use = -warnings;

- -

- -

use = -DBI;

- -

- -

use = -DBD::Oracle;

- -

- -

use = -Getopt::Long;

- -

- -

use = -Term::ReadKey;

- -

- -

 

- -

 

- -

my -$sth;           &n= -bsp;        -# Oracle statement handle

- -

- -

my = -$hostname =3D -"";

- -

- -

my = -$username =3D -"/";

- -

- -

my = -$password =3D -"";

- -

- -

my = -$logfile  -=3D "ex1.log";

- -

- -

my = -%attr =3D (

- -

- -

    -RaiseError =3D> 1,

- -

- -

    -AutoCommit =3D> 0,

- -

- -

);

- -

- -

my = -%opt =3D (

- -

- -

    -pause   =3D> 0,

- -

- -

);

- -

- -

 

- -

 

- -

# Get = -command line -options and arguments.

- -

- -

GetOptions(

- -

- -

    -"pause" =3D> \$opt{pause},

- -

- -

);

- -

- -

my = -$key =3D -37;           &nbs= -p;  - # default query value

- -

- -

$key = -=3D $ARGV[0] if -$ARGV[0];

- -

- -

 

- -

 

- -

# = -Connect to -Oracle.

- -

- -

my = -$dbh =3D -DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr);

- -

- -

$dbh->trace(9, -$logfile);

- -

- -

 

- -

 

- -

# = -Activate -tracing.

- -

- -

$sth = -=3D -$dbh->prepare(q(alter session set events '10046 trace name context = -forever, -level 12'));

- -

- -

$sth->execute;

- -

- -

 

- -

 

- -

# = -Allow the user -to find the Oracle session and activate OS diagnostic

- -

- -

# = -tools like -strace(1) or lsof(8).

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Execute the -query to trace.

- -

- -

$sth = -=3D -$dbh->prepare(q(select key, fkey, value from t where = -key=3D?));

- -

- -

$sth->execute($key);

- -

- -

 

- -

 

- -

# = -Print output -header.

- -

- -

my = -@cdefs =3D qw(%8d -%8d %32s);   # column definitions

- -

- -

my = -@hdefs =3D qw(Key -Fkey Value); # column headings

- -

- -

my = -$bformat =3D -join("  ", @cdefs) . "\n";

- -

- -

my = -$hformat; -($hformat =3D $bformat) =3D~ s/%(\d*)\S+/%$1s/g;

- -

- -

printf $hformat, -@hdefs;

- -

- -

printf $hformat, -do { my @h; push @h, "-" x (/(\d+)/?$1:10) for = -@cdefs; @h };

- -

- -

 

- -

 

- -

# = -Print query -results.

- -

- -

for = -my $row -(@{$sth->fetchall_arrayref}) {

- -

- -

    -printf $bformat, @$row;

- -

- -

}

- -

- -

- -

 

- -

 

- -

# = -Allow the user -to do final OS diagnostic stuff.

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Disconnect from -Oracle.

- -

- -

$dbh->disconnect;

- -
- -

 

- -

 

- -
- -

Listing [listing:sqltrace.trc]: raw SQL trace = -output for -an execution of our program

- -
- -
- -

/usr/local/oracle/admin/V816/udump/ora_17349.tr= -c

- -

Oracle8i Enterprise -Edition Release 8.1.6.1.0 - Production

- -

With = -the -Partitioning option

- -

JServer Release -8.1.6.0.0 - Production

- -

ORACLE_HOME =3D -/usr/local/oracle/product/8.1.6

- -

System -name:        Linux

- -

Node name:  = -www.hotsos.com

- -

Release:    = -2.2.16-22enterprise

- -

Version:    #1 -SMP Tue Aug 22 16:29:32 EDT 2000

- -

Machine:    = -i686

- -

Instance name: -V816

- -

Redo = -thread -mounted by this instance: 1

- -

Oracle process -number: 8

- -

Unix = -process pid: -17349, image: oracle@www.hotsos.com (TNS V1-V3)

- -

 

- -

*** = -SESSION -ID:(7.9) 2002-09-12 16:14:01.582

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D69 dep=3D0 uid=3D12 oct=3D42 lid=3D12 = -tim=3D107309054 hv=3D1509700594 -ad=3D'54af5e14'

- -

alter = -session set -events '10046 trace name context forever, level 12'

- -

END = -OF STMT

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -309054

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

*** = -2002-09-12 -16:14:31.226

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2964 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#2 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312018 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

WAIT = -#2: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#2: -nam=3D'SQL*Net message from client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312019 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

BINDS = -#1:

- -

 bind 0: -dty=3D1 mxl=3D32(04) mal=3D00 scl=3D00 pre=3D00 oacflg=3D25 oacfl2=3D10 = -size=3D32 offset=3D0

- -

   bfp=3D0940e7f0 bln=3D32 avl=3D04 flg=3D05

- -

   -value=3D"8542"

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#1: nam=3D'file -open' ela=3D 0 p1=3D0 p2=3D0 p3=3D0

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6671 p3=3D1

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6678 p3=3D1

- -

FETCH -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

*** = -2002-09-12 -16:14:56.200

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2496 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

XCTEND rlbk=3D0, -rd_only=3D1

- -

STAT = -#1 id=3D1 cnt=3D1 -pid=3D0 pos=3D0 obj=3D5156 op=3D'TABLE ACCESS BY INDEX ROWID T = -'

- -

STAT = -#1 id=3D2 cnt=3D2 -pid=3D1 pos=3D1 obj=3D5157 op=3D'INDEX UNIQUE SCAN '

- -
- -

 

- -

 

- -

$ perl -V

- -

Summary of my perl5 (revision 5.0 version 6 subversion 0) = -configuration:

- -

  Platform:

- -

    osname=3Dlinux, osvers=3D2.2.5-22smp, = -archname=3Di386-linux

- -

    uname=3D'linux porky.devel.redhat.com = -2.2.5-22smp #1 smp -wed jun 2 09:11:51 edt 1999 i686 unknown '

- -

    config_args=3D'-des -Doptimize=3D-O2 = --march=3Di386 -mcpu=3Di686 --Dcc=3Dgcc -Dcccdlflags=3D-fPIC -Dinstallprefix=3D/usr -Dprefix=3D/usr = --Darchname=3Di386-linux --Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm -Di_gdbm -Di_shadow = --Di_syslog -Dman3ext=3D3pm -Uuselargefiles'

- -

    hint=3Drecommended, useposix=3Dtrue, = -d_sigaction=3Ddefine

- -

    usethreads=3Dundef use5005threads=3Dundef = -useithreads=3Dundef -usemultiplicity=3Dundef

- -

    useperlio=3Dundef d_sfio=3Dundef = -uselargefiles=3Dundef

- -

    use64bitint=3Dundef use64bitall=3Dundef = -uselongdouble=3Dundef -usesocks=3Dundef

- -

  Compiler:

- -

    cc=3D'gcc', optimize=3D'-O2 -march=3Di386 = --mcpu=3Di686', gccversion=3D2.96 -20000731 (experimental)

- -

    = -cppflags=3D'-fno-strict-aliasing'

- -

    ccflags = -=3D'-fno-strict-aliasing'

- -

    stdchar=3D'char', d_stdstdio=3Ddefine, = -usevfork=3Dfalse

- -

    intsize=3D4, longsize=3D4, ptrsize=3D4, = -doublesize=3D8

- -

    d_longlong=3Ddefine, longlongsize=3D8, = -d_longdbl=3Ddefine, -longdblsize=3D12

- -

    ivtype=3D'long', ivsize=3D4, = -nvtype=3D'double', nvsize=3D8, Off_t=3D'off_t', -lseeksize=3D4

- -

    alignbytes=3D4, usemymalloc=3Dn, = -prototype=3Ddefine

- -

  Linker and Libraries:

- -

    ld=3D'gcc', ldflags =3D' = --L/usr/local/lib'

- -

    libpth=3D/usr/local/lib /lib = -/usr/lib

- -

    libs=3D-lnsl -ldl -lm -lc = --lcrypt

- -

    libc=3D/lib/libc-2.1.92.so, so=3Dso, = -useshrplib=3Dfalse, libperl=3Dlibperl.a

- -

  Dynamic Linking:

- -

    dlsrc=3Ddl_dlopen.xs, dlext=3Dso, = -d_dlsymun=3Dundef, ccdlflags=3D'-rdynamic'

- -

    cccdlflags=3D'-fPIC', lddlflags=3D'-shared = --L/usr/local/lib'

- -

 

- -

 

- -

Characteristics of this binary (from libperl): = -

- -

  Compile-time options:

- -

  Built under linux

- -

  Compiled at Aug  7 2000 10:59:51

- -

  @INC:

- -

    = -/usr/lib/perl5/5.6.0/i386-linux

- -

    /usr/lib/perl5/5.6.0

- -

    = -/usr/lib/perl5/site_perl/5.6.0/i386-linux

- -

    = -/usr/lib/perl5/site_perl/5.6.0

- -

    /usr/lib/perl5/site_perl

- -

    .

- -

 

- -

 

- -

Other site information

- -

- Redhat Linux 7.0

- -

- Oracle 8.1.6.1.0

- -

- DBD-Oracle 1.12

- -

- DBI 1.30

- -

 

- -
- - - - - -------=_NextPart_001_016B_01C25A80.D1557E70-- - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: application/octet-stream; - name="ex1.log" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="ex1.log" - - DBI::db=3DHASH(0x8235a74) trace level set to 9 in DBI 1.30-nothread=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'alter session set events '10046 trace name context forever, level 12'')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240f68)=3D>DBI::st=3DHASH(0x8240f98),= - DBD::Oracle::st, 8240f74, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= -OCIHandleAlloc(0x82465d8,0x826c948,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826bf48,0x82559ec,'alter session set events '10046 = -trace name context forever, level 12'',69,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0x826c94c,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql ALTER=0A= - dbd_describe skipped for ALTER=0A= - <- prepare=3D DBI::st=3DHASH(0x8240f68) at ex1.pl line 38=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240f68)~0x8240f98)=0A= - dbd_st_execute ALTER (out0, lob0)...=0A= -OCIStmtExecute(0x82557c4,0x826bf48,0x82559ec,1,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff654,(nil),9,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute ALTER returned (SUCCESS, rpc0, fn52, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 39=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'select key, fkey, value from t where key=3D?')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240fe0)=3D>DBI::st=3DHASH(0x8240fb0),= - DBD::Oracle::st, 8240fec, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= - dbd_preparse scanned 1 distinct placeholders=0A= -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where = -key=3D:p1',44,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql SELECT=0A= - dbd_describe SELECT (EXPLICIT, lb 80)...=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3DSUCCES= -S=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3dc,(nil),18,0x82559ec)=3DSUCC= -ESS=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d1c0,1)=3DSUCCESS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d6,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d4,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d8,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1da,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1db,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1e8,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 1: 'KEY' NO null , otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d200,2)=3DSUCCESS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d216,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d214,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d218,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d228,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 2: 'FKEY' NULLable, otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d240,3)=3DSUCCESS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d256,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d254,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d258,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d268,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 3: 'VALUE' NULLable, otype 1-> 5, dbsize 32/33, p32.s0=0A= -OCIAttrSet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3d4,4,11,0x82559ec)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d1c4,0x82559ec,1,0x826e8d0,134,5,0x826d438,= -0x826d448,0x826d458,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d204,0x82559ec,2,0x826eaf8,134,5,0x826ca28,= -0x826ca38,0x826ca48,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d244,0x82559ec,3,0x826cbb8,33,5,0x826ca58,0= -x826cbe0,0x826cbf0,0)=3DSUCCESS=0A= - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231)=0A= - <- prepare=3D DBI::st=3DHASH(0x8240fe0) at ex1.pl line 50=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240f98)~INNER)=0A= -OCIHandleFree(0x826bf48,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef at ex1.pl line 51=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240fe0)~0x8240fb0 = -'8542')=0A= - bind :p1 <=3D=3D '8542' (type 0)=0A= - bind :p1 <=3D=3D '8542' (size 4/5/0, ptype 7, otype 1)=0A= - bind :p1 <=3D=3D '8542' (size 4/4, otype 1, indp 0, at_exec 1)=0A= -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb= -6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS=0A= -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da= -090)=3DSUCCESS=0A= - bind :p1 done with ftype 1=0A= - dbd_st_execute SELECT (out0, lob0)...=0A= - in ':p1' [0,0]: len 4, ind 0=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 51=0A= - -> fetchall_arrayref for DBD::Oracle::st = -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0)=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DSUCCESS=0A= - dbih_setup_fbav for 3 fields =3D> 0x8240fbc=0A= - dbd_st_fetch 3 fields SUCCESS=0A= - 0 (rc=3D0): '8542'=0A= - 1 (rc=3D0): '8542'=0A= - 2 (rc=3D0): 'value'=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DNO_DATA=0A= - dbd_st_fetch no-more-data=0A= - <- fetchall_arrayref=3D [ ARRAY(0x82411f0) ] row1 at ex1.pl line 62=0A= - -> disconnect for DBD::Oracle::db = -(DBI::db=3DHASH(0x8235b34)~0x8235a74)=0A= -OCISessionEnd(0x82557c4,0x82559ec,0x826c384,0)=3DSUCCESS=0A= -OCIServerDetach(0x8255834,0x82559ec,0)=3DSUCCESS=0A= - <- disconnect=3D 1 at ex1.pl line 74=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240fb0)~INNER)=0A= -OCIHandleFree(0x826e4a0,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -> DESTROY for DBD::Oracle::db (DBI::db=3DHASH(0x8235a74)~INNER)=0A= -OCIHandleFree(0x826c384,OCI_HTYPE_SESSION)=3DSUCCESS=0A= -OCIHandleFree(0x8255834,OCI_HTYPE_SERVER)=3DSUCCESS=0A= -OCIHandleFree(0x82557c4,OCI_HTYPE_SVCCTX)=3DSUCCESS=0A= -OCIHandleFree(0x82559ec,OCI_HTYPE_ERROR)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -------=_NextPart_000_016A_01C25A80.D1527130-- - - -From timbo@dansat.data-plan.com Fri Sep 13 07:30:31 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6UUC04053 - for ; Fri, 13 Sep 2002 07:30:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:30:30 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031871608:20:03733:55; Thu, 12 Sep 2002 23:00:08 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id ab2122693; 12 Sep 2002 23:00 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id AE0642F0B8A - for ; Thu, 12 Sep 2002 18:58:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id 931D42F0D0A - for ; Thu, 12 Sep 2002 18:58:19 -0400 (EDT) -Received: (qmail 57270 messnum 519666 invoked from network[159.134.164.69/p69.as1.limerick1.eircom.net]); 12 Sep 2002 22:58:17 -0000 -Received: from p69.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.69) - by mail03.svc.cra.dublin.eircom.net (qp 57270) with SMTP; 12 Sep 2002 22:58:17 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8CMwEQ02798; - Thu, 12 Sep 2002 23:58:14 +0100 (BST) - (envelope-from timbo) -Date: Thu, 12 Sep 2002 23:58:14 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls -Message-ID: <20020912225814.GG539@dansat.data-plan.com> -References: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 3530 -Lines: 77 - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCESS - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 '8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCESS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - -From cary.millsap@hotsos.com Fri Sep 13 07:31:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6VsC04590 - for ; Fri, 13 Sep 2002 07:31:54 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:31:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031889643:20:09494:0; Fri, 13 Sep 2002 04:00:43 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-2.mail.demon.net - id aa2008866; 13 Sep 2002 4:00 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id C94C67264F - for ; Fri, 13 Sep 2002 00:00:07 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by wormwood.pobox.com (Postfix) with ESMTP id A821072676 - for ; Fri, 13 Sep 2002 00:00:06 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D405n19404 - for ; Thu, 12 Sep 2002 23:00:05 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 22:59:56 -0500 -Message-ID: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020912225814.GG539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4825 -Lines: 129 - -Tim, - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Thursday, September 12, 2002 5:58 PM -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you -on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer -to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make -the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I -can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect -that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - - -From timbo@dansat.data-plan.com Fri Sep 13 10:48:59 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D9mwC06022 - for ; Fri, 13 Sep 2002 10:48:58 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 10:48:58 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031907122:20:19599:21; Fri, 13 Sep 2002 08:52:02 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2129553; 13 Sep 2002 8:52 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 99E263E660 - for ; Fri, 13 Sep 2002 04:51:54 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-2.pobox.com (Postfix) with SMTP id 721613E637 - for ; Fri, 13 Sep 2002 04:51:53 -0400 (EDT) -Received: (qmail 29161 messnum 524631 invoked from network[159.134.167.5/p773.as1.limerick1.eircom.net]); 13 Sep 2002 08:51:51 -0000 -Received: from p773.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.5) - by mail03.svc.cra.dublin.eircom.net (qp 29161) with SMTP; 13 Sep 2002 08:51:51 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8D8prO05752; - Fri, 13 Sep 2002 09:51:53 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 09:51:53 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913085153.GJ539@dansat.data-plan.com> -References: <20020912225814.GG539@dansat.data-plan.com> <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 6172 -Lines: 154 - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more "official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -> key=:p1',44,1,0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - -From cary.millsap@hotsos.com Fri Sep 13 17:52:40 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DGqdC10778 - for ; Fri, 13 Sep 2002 17:52:39 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 17:52:39 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031932999:10:25604:102; Fri, 13 Sep 2002 16:03:19 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101673; 13 Sep 2002 16:03 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E4A692C078 - for ; Fri, 13 Sep 2002 12:02:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 1609E2C03F - for ; Fri, 13 Sep 2002 12:02:29 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DG2Sn24856 - for ; Fri, 13 Sep 2002 11:02:28 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Fri, 13 Sep 2002 11:02:20 -0500 -Message-ID: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913085153.GJ539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 9234 -Lines: 248 - -Tim, - -I think it's important for a developer to have the ability to turn this -on and off. But I would argue that 0 is the correct default. I think of -it as a probability times cost function. The cost of leaving the setting -at 1 accidentally in a production application is pretty high: if the app -doesn't scale (because it's parsing too much), then it jeopardizes the -business' ability to succeed with it. - -The probability of leaving the option set to 1 accidentally during -production is very high. A point in evidence is that I didn't find the -parameter until I corresponded personally with you. I in fact *still* -don't know where to find it. I've checked Descartes & Bunce, perldoc -DBI, and perldoc DBD::Oracle without finding it yet... - -If the default were 0, the probability of leaving the option set to 0 -accidentally during development would be much lower. A developer faced -with a SQL syntax problem he doesn't understand will do the research -necessary to fix that problem. He can't release his code until he does. - -The problem with the default of 1 is, in my opinion, that most -developers will never learn of the feature, and they'll accidentally -leave it turned on in production. The proportion of developers who -competently performance-test their code is, unfortunately, -microscopically small. But they all do some level of functional testing. - -I would recommend making the ora_check_sql feature a more prominently -documented feature, presumably in "perldoc DBD::Oracle". - -I did learn in a test that specifying the option in the DBI->connect() -call doesn't do anything. Is it possible that you could allow us to -specify it at the connection level? The workaround is to do something -like this: - - use Getopt::Long; - my %prepare_attr = (ora_check_sql=>0); - GetOptions("dev"=>\$dev); - $prepare_attr{ora_check_sql} = 1 if $dev; - # developer must specify the command-line flag to get the -unscalable - # behavior that's necessary for functional testing - ... - $sth = $dbh->prepare($sql, %prepare_attr); # MUST specify -%p..attr - -...But I doubt that most Oracle application developers would come up -with this without some coaching. - -I'll definitely keep an eye open for projects you might like. It would -be a hell of an opportunity for someone to have you, I think. It seems -that if you could make a list like Oracle-L (1,900 people) aware that -there's an opportunity, it would improve your chances of finding -something quickly. It's of course bad taste to advertise oneself overtly -on those lists, but there is almost always a clever way to do it anyway -without offending anyone. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:52 AM -To: Cary Millsap -Cc: 'Tim Bunce' -Subject: Re: two Oracle parse calls - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge -to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our -lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a -preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more -"official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw -you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 -trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret -them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t -where -> key=:p1',44,1,0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: -231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), -{ -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call -parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:37 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLbC13725 - for ; Fri, 13 Sep 2002 23:21:37 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:37 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031951069:20:15816:152; Fri, 13 Sep 2002 21:04:29 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2120669; 13 Sep 2002 21:04 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 544863E642 - for ; Fri, 13 Sep 2002 17:04:17 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id 0AE7C3E667 - for ; Fri, 13 Sep 2002 17:04:16 -0400 (EDT) -Received: (qmail 16221 messnum 355694 invoked from network[159.134.166.226/p738.as1.limerick1.eircom.net]); 13 Sep 2002 21:04:14 -0000 -Received: from p738.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.226) - by mail05.svc.cra.dublin.eircom.net (qp 16221) with SMTP; 13 Sep 2002 21:04:14 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DL4Lx12642; - Fri, 13 Sep 2002 22:04:21 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:04:21 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913210421.GR539@dansat.data-plan.com> -References: <20020913085153.GJ539@dansat.data-plan.com> <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 3078 -Lines: 70 - -On Fri, Sep 13, 2002 at 11:02:20AM -0500, Cary Millsap wrote: -> Tim, -> -> I think it's important for a developer to have the ability to turn this -> on and off. But I would argue that 0 is the correct default. I think of -> it as a probability times cost function. The cost of leaving the setting -> at 1 accidentally in a production application is pretty high: if the app -> doesn't scale (because it's parsing too much), then it jeopardizes the -> business' ability to succeed with it. -> -> The probability of leaving the option set to 1 accidentally during -> production is very high. A point in evidence is that I didn't find the -> parameter until I corresponded personally with you. I in fact *still* -> don't know where to find it. I've checked Descartes & Bunce, perldoc -> DBI, and perldoc DBD::Oracle without finding it yet... - -It's not documented. - -As I recall it... originally DBD::Oracle defered the describe as -long as possible. But people reported very slow select performance: - - http://www.faqchest.com/prgm/dbi-l/dbi-99/dbi-9910/dbi-991005/dbi99101218_28018.html - -Turned out that the row cache logic needed the describe to try to -work out an optimal row cache size. Without the describe the row -cache wasn't getting set up. - -At some point I added code that would just set OCI_ATTR_PREFETCH_MEMORY -to a set size if ora_check_sql was 0. But I can't remember now why -I left ora_check_sql=1. - -It was possibly in relation to wanting to be able to use the -OCI_ATTR_PARSE_ERROR_OFFSET attribute to be able to highlight the -point in a query where the error was detected. But I think execute() -needs to be able to do that anyway (to catch syntax errors in -non-select statements). - -There is another problem. If the describe has been defered and the -application uses $sth->{NAME} or other similar attribute then the -describe has to be done at that point. The code is thee to do that -but the problem is how should the DBI behave if there's an error -in the SQL? It currently always croaks (rather than return undef, -in order to give a useful error message), but that's rather surprising -behaviour to many people and very unhelpful to some. - -There may well be other subtle issues that I can't recall right now. - -> I would recommend making the ora_check_sql feature a more prominently -> documented feature, presumably in "perldoc DBD::Oracle". -> -> I did learn in a test that specifying the option in the DBI->connect() -> call doesn't do anything. Is it possible that you could allow us to -> specify it at the connection level? - -By making it a database handle attribute, yes, that would be my plan. - -> I'll definitely keep an eye open for projects you might like. It would -> be a hell of an opportunity for someone to have you, I think. - -Thanks. - -> It seems that if you could make a list like Oracle-L (1,900 people) aware -> that there's an opportunity, it would improve your chances of finding -> something quickly. It's of course bad taste to advertise oneself overtly -> on those lists, but there is almost always a clever way to do it anyway -> without offending anyone. - -:-) - -Tim. - -From cary.millsap@hotsos.com Fri Sep 13 07:32:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6W1C04656 - for ; Fri, 13 Sep 2002 07:32:01 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:32:01 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031891038:20:04710:44; Fri, 13 Sep 2002 04:23:58 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id ab2004623; 13 Sep 2002 4:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 942A82BF2C - for ; Fri, 13 Sep 2002 00:23:44 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 73C982BF33 - for ; Fri, 13 Sep 2002 00:23:42 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D4Ndn19584 - for ; Thu, 12 Sep 2002 23:23:39 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 23:23:30 -0500 -Message-ID: <019301c25add$53f5dfd0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0194_01C25AB3.6B1FD7D0" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -Content-Length: 36859 -Lines: 1209 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Well, that was easy. Setting ora_check_sql=>0 does solve the problem. - - - -I now shift into "Please make 0 the default" mode. - - - -Here are the Oracle trace files, by the way, with a splash of color to -illustrate how the Oracle kernel sees what's going on (I hope you have -an HTML mail reader)... - - - -With {ora_check_sql=>1} (or no setting at all), here's what Oracle does -for the application: - - - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - - - -The PARSING IN CURSOR section tells us what SQL it is that we're -executing. Each line beginning with "PARSE" is emitted only when Oracle -executes a parse call. There are two. The first is wasted. - - - -Here's the same application with {ora_check_sql=>1} (the official new -default value, I am sure :-)): - - - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=109776065 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -FETCH #1:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=109776065 - - - -One parse call; problem solved. - - - -Thank you sincerely for your help. - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- -From: Cary Millsap [mailto:cary.millsap@hotsos.com] -Sent: Thursday, September 12, 2002 11:00 PM -To: 'Tim Bunce' -Subject: RE: two Oracle parse calls - - - -Tim, - - - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - - - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- - -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] - -Sent: Thursday, September 12, 2002 5:58 PM - -To: Cary Millsap - -Cc: tim.bunce@pobox.com - -Subject: two Oracle parse calls - - - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: - -> Tim, - -> - -> How are you doing? I hope you've had a good two years since I saw you -on - -> the Oracle Geek Cruise event. - - - -Yes thanks. And you? - - - -> I've been working on a project this year to construct a book about - -> optimizing Oracle response time. In my research, I've discovered - -> something about the DBI that I didn't expect: it executes two Oracle - -> parse calls for every one that I would expect an efficient DBI layer -to - -> make. I've included my Perl source (below), the Oracle level-12 trace - -> data that shows the sequence of calls it's receiving from the Perl - -> application (below), a level-9 DBI trace from the application - -> (attached), and our version information (below). - -> - -> I was hoping that by showing you this specific data, you could make -the - -> problem go away. - - - -I can only do what OCI lets me do... but within that I'll do what I -can... - - - -I'm not familar with Oracle trace logs so I can't readily intrepret them - -and I'll take what you say at face value. - - - -But I am familar with DBD::Oracle :) and the logs it writes :) - - - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -> $sth->execute($key); - - - - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - - dbd_preparse scanned 1 distinct placeholders - -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS - -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - - dbd_st_prepare'd sql SELECT - - dbd_describe SELECT (EXPLICIT, lb 80)... - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') - -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS - -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - - bind :p1 done with ftype 1 - - dbd_st_execute SELECT (out0, lob0)... - - in ':p1' [0,0]: len 4, ind 0 - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - - <- execute= '0E0' at ex1.pl line 51 - - - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - - - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -call that prepare() does. - - - -It doesn't do that for non-select statements so you could check if - -non-selects also have two parse calls. - - - -Also try doing - - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - - - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the - -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -is possibly redundant and could be removed (but Oracle ought to detect -that - -anyway and not make a round-trip for it, and certainly not call parse). - - - -If non-selects only have one parse call but ora_check_sql=>0 doesn't - -fix selects, then I might be able to do a simple patch to avoid the - -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - - - -Then the issue will be: should ora_check_sql=>0 be the default... - - - -Tim. - - - -p.s. I'd love a copy of your book when it's ready! - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Well, that was easy. Setting ora_check_sql=3D>0 = -does solve the -problem.

- -

 

- -

I now shift into "Please make 0 the = -default" mode.

- -

 

- -

Here are the Oracle trace files, by the way, with a = -splash -of color to illustrate how the Oracle kernel sees what’s going on = -(I hope -you have an HTML mail reader)...

- -

 

- -

With {ora_check_sql=3D>1} (or no setting at all), = -here’s -what Oracle does for the application:

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #2 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312018 = -hv=3D1997601641 ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF STMT

- -

PARSE = -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312019 = -hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF = -STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

FETCH = -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

 

- -

The PARSING IN CURSOR section tells us what SQL it is = -that -we’re executing. Each line beginning with “PARSE” is = -emitted -only when Oracle executes a parse call. There are two. The first is = -wasted.

- -

 

- -

Here’s the same application with = -{ora_check_sql=3D>1} (the official new = -default value, I -am sure J):

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 = -dep=3D0 uid=3D12 -oct=3D3 lid=3D12 tim=3D109776065 hv=3D1997601641 = -ad=3D'54af1384'

- -

select key, fkey, value from = -t where -key=3D:p1

- -

END OF STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

FETCH = -#1:c=3D0,e=3D0,p=3D0,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D109= -776065

- -

 

- -

One parse call; problem solved.

- -

 

- -

Thank you sincerely for your help.

- -

 

- -

 

- -

Cary = -Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System = -Performance, -Feb 9-12 Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 = -Middelfart Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----
-From: Cary Millsap [mailto:cary.millsap@hotsos.com]
-Sent: Thursday, September 12, 2002 11:00 PM
-To: 'Tim Bunce'
-Subject: RE: two Oracle parse calls

- -

 

- -

Tim,

- -

 

- -

Thanks so very much. The attribute ora_check_sql=3D>0 is new = -knowledge -to me; this is a nice reward for having written to you. I will test it = -either -tonight or the first thing tomorrow and then inform you of the results -immediately after that. If it solves the problem, then I will lobby you = -to make -0 the default value and probably consider the issue "problem = -solved."

- -

 

- -

Things are very well, thank you. I've been at home with my = -family now -for over three straight weeks, and we're having a nice time of our lives = -these -days with the business settling into stride a bit. Tonight is a big = -night for -me. I've just crossed the line of accepting a preliminary offer from = -O'Reilly. -This book project has actually been underway for quite some time now, = -but as of -tonight it's quite a bit more "official."

- -

 

- -

 

- -

Cary Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec = -9-11 -Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System Performance, Feb = -9-12 -Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 Middelfart = -Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----

- -

From: Tim Bunce [mailto:Tim.Bunce@pobox.com]

- -

Sent: Thursday, September 12, 2002 5:58 PM

- -

To: Cary Millsap

- -

Cc: tim.bunce@pobox.com

- -

Subject: two Oracle parse calls

- -

 

- -

On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap = -wrote:

- -

> Tim,

- -

>

- -

> How are you doing? I hope you've had a good two years since = -I saw -you on

- -

> the Oracle Geek Cruise event.

- -

 

- -

Yes thanks. And you?

- -

 

- -

> I've been working on a project this year to construct a = -book about

- -

> optimizing Oracle response time. In my research, I've = -discovered

- -

> something about the DBI that I didn't expect: it executes = -two -Oracle

- -

> parse calls for every one that I would expect an efficient = -DBI -layer to

- -

> make. I've included my Perl source (below), the Oracle = -level-12 -trace

- -

> data that shows the sequence of calls it's receiving from = -the Perl

- -

> application (below), a level-9 DBI trace from the = -application

- -

> (attached), and our version information = -(below).

- -

>

- -

> I was hoping that by showing you this specific data, you = -could -make the

- -

> problem go away.

- -

 

- -

I can only do what OCI lets me do... but within that I'll do = -what I -can...

- -

 

- -

I'm not familar with Oracle trace logs so I can't readily = -intrepret -them

- -

and I'll take what you say at face value.

- -

 

- -

But I am familar with DBD::Oracle :) and the logs it writes = -:)

- -

 

- -

> $sth =3D $dbh->prepare(q(select key, fkey, value from t = -where -key=3D?));

- -

> $sth->execute($key);

- -

 

- -

 

- -

    -> prepare for DBD::Oracle::db -(DBI::db=3DHASH(0x8235b34)~0x8235a74 'select key, fkey, value from t = -where -key=3D?')

- -

    dbd_preparse scanned 1 distinct = -placeholders

- -

OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCC= -ESS

- -

OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from = -t -where key=3D:p1',44,1,0)=3DSUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)= -=3DSUCCESS

- -

    dbd_st_prepare'd sql SELECT

- -

    dbd_describe SELECT (EXPLICIT, lb = -80)...

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3D= -SUCCESS

- -

    dbd_describe'd 3 columns (row bytes: 76 max, = -40 est -avg, cache: 231)

- -

    <- prepare=3D DBI::st=3DHASH(0x8240fe0) at = -ex1.pl -line 50

- -

    -> execute for DBD::Oracle::st -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0 '8542')

- -

OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x8= -26cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS - -

OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40= -,0x401da090)=3DSUCCESS

- -

       bind :p1 done with ftype = -1

- -

    dbd_st_execute SELECT (out0, = -lob0)...

- -

       in  ':p1' [0,0]: = -len  4, -ind 0

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3D= -SUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec= -)=3DSUCCESS

- -

    dbd_st_execute SELECT returned (SUCCESS, = -rpc0, fn4, -out0)

- -

    <- execute=3D '0E0' at ex1.pl line = -51

- -

 

- -

Given those OCI calls, what is DBD::Oracle doing that it = -shouldn't?

- -

 

- -

I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

call that prepare() does.

- -

 

- -

It doesn't do that for non-select statements so you could check = -if

- -

non-selects also have two parse calls.

- -

 

- -

Also try doing

- -

  $sth =3D $dbh->prepare(q(select key, fkey, value from = -t where -key=3D?), { ora_check_sql=3D> 0 });

- -

 

- -

which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till = -after the

- -

main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

is possibly redundant and could be removed (but Oracle ought to = -detect -that

- -

anyway and not make a round-trip for it, and certainly not call = -parse).

- -

 

- -

If non-selects only have one parse call but = -ora_check_sql=3D>0 doesn't

- -

fix selects, then I might be able to do a simple patch to avoid = -the

- -

OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if = -ora_check_sql=3D>0.

- -

 

- -

Then the issue will be: should ora_check_sql=3D>0 be the = -default...

- -

 

- -

Tim.

- -

 

- -

p.s. I'd love a copy of your book when it's = -ready!

- -
- - - - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0-- - - -From cary.millsap@hotsos.com Fri Sep 13 21:17:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DKHhC12417 - for ; Fri, 13 Sep 2002 21:17:43 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 21:17:43 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031946929:20:18513:70; Fri, 13 Sep 2002 19:55:29 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2018248; 13 Sep 2002 19:55 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 7FC402C01F - for ; Fri, 13 Sep 2002 15:55:06 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 76A5E2BFE1 - for ; Fri, 13 Sep 2002 15:55:05 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DJt4n26736 - for ; Fri, 13 Sep 2002 14:55:04 -0500 -From: "Cary Millsap" -To: "Tim Bunce" -Subject: A little more data -Date: Fri, 13 Sep 2002 14:54:56 -0500 -Message-ID: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0203_01C25B35.89729F60" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4948 -Lines: 166 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -I hope this is helpful. I have noticed that I cannot produce the -extra-parse problem on my 8.1.7 laptop database, no matter what the -setting of ora_check_sql. All of the data I've sent you is from our -8.1.6 Linux database. If you really needed it, I could produce level-9 -DBI trace data from identical tests on both platforms, but I won't spend -the time doing that unless you say it will help... - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - - - - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

I hope this is helpful… I have noticed that I = -cannot -produce the extra-parse problem on my 8.1.7 laptop database, no matter = -what the -setting of ora_check_sql. All of the data I’ve sent you is from = -our 8.1.6 -Linux database. If you really needed it, I could produce level-9 DBI = -trace data -from identical tests on both platforms, but I won’t spend the time = -doing -that unless you say it will help...

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -

 

- -
- - - - - -------=_NextPart_000_0203_01C25B35.89729F60-- - - -From timbo@dansat.data-plan.com Fri Sep 13 22:05:30 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL5UC12942 - for ; Fri, 13 Sep 2002 22:05:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:05:30 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031948458:10:20432:5; Fri, 13 Sep 2002 20:20:58 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-1.mail.demon.net - id aa1020174; 13 Sep 2002 20:20 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 8A60E3E659 - for ; Fri, 13 Sep 2002 16:20:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id CAC663E685 - for ; Fri, 13 Sep 2002 16:20:36 -0400 (EDT) -Received: (qmail 37861 messnum 258096 invoked from network[159.134.164.124/p124.as1.limerick1.eircom.net]); 13 Sep 2002 20:20:35 -0000 -Received: from p124.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.124) - by mail05.svc.cra.dublin.eircom.net (qp 37861) with SMTP; 13 Sep 2002 20:20:35 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DKKhu12535; - Fri, 13 Sep 2002 21:20:43 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 21:20:43 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data -Message-ID: <20020913202043.GO539@dansat.data-plan.com> -References: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1098 -Lines: 34 - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - -From cary.millsap@hotsos.com Fri Sep 13 22:04:47 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL4kC12684 - for ; Fri, 13 Sep 2002 22:04:46 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:04:46 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031949629:20:13745:23; Fri, 13 Sep 2002 20:40:29 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2013849; 13 Sep 2002 20:40 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 7D90A3E650 - for ; Fri, 13 Sep 2002 16:40:20 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-1.pobox.com (Postfix) with ESMTP id 785AB3E642 - for ; Fri, 13 Sep 2002 16:40:19 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DKeIn27106 - for ; Fri, 13 Sep 2002 15:40:18 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: A little more data -Date: Fri, 13 Sep 2002 15:40:10 -0500 -Message-ID: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913202043.GO539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 1999 -Lines: 63 - -Well, it's 1.06 on my Windows machine (the most up-to-date version -available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -but interesting that (admitting now that there's a new degree of freedom -running loose amid the test) "the older version performs better than the -newer one." :) That's certainly not a fair statement if the diff between -8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:21 PM -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't -spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:32 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLWC13692 - for ; Fri, 13 Sep 2002 23:21:32 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:32 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031952887:10:13297:20; Fri, 13 Sep 2002 21:34:47 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1118141; 13 Sep 2002 21:34 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C7D482BF23 - for ; Fri, 13 Sep 2002 17:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail00.svc.cra.dublin.eircom.net (mail00.svc.cra.dublin.eircom.net [159.134.118.16]) - by dolly1.pobox.com (Postfix) with SMTP id 8352A2BF6C - for ; Fri, 13 Sep 2002 17:34:36 -0400 (EDT) -Received: (qmail 5093 messnum 521124 invoked from network[159.134.164.134/p134.as1.limerick1.eircom.net]); 13 Sep 2002 21:34:34 -0000 -Received: from p134.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.134) - by mail00.svc.cra.dublin.eircom.net (qp 5093) with SMTP; 13 Sep 2002 21:34:34 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DLYeI13070; - Fri, 13 Sep 2002 22:34:40 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:34:40 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: A little more data -Message-ID: <20020913213440.GS539@dansat.data-plan.com> -References: <20020913202043.GO539@dansat.data-plan.com> <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 2282 -Lines: 69 - -According my RCS the default for ora_check_sql changed from 0 to 1 -around version 1.03. - -Tim. - -On Fri, Sep 13, 2002 at 03:40:10PM -0500, Cary Millsap wrote: -> Well, it's 1.06 on my Windows machine (the most up-to-date version -> available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -> but interesting that (admitting now that there's a new degree of freedom -> running loose amid the test) "the older version performs better than the -> newer one." :) That's certainly not a fair statement if the diff between -> 8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Friday, September 13, 2002 3:21 PM -> To: Cary Millsap -> Cc: Tim Bunce -> Subject: Re: A little more data -> -> If they're using the same version of DBD::Oracle then -> the change must me on the sever side. Maybe Oracle's -> woken up to the fact they don't need a second parse! -> -> Tim. -> -> On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > -> > -> > I hope this is helpful. I have noticed that I cannot produce the -> > extra-parse problem on my 8.1.7 laptop database, no matter what the -> > setting of ora_check_sql. All of the data I've sent you is from our -> > 8.1.6 Linux database. If you really needed it, I could produce level-9 -> > DBI trace data from identical tests on both platforms, but I won't -> spend -> > the time doing that unless you say it will help... -> > -> > -> > -> > Cary Millsap -> > Hotsos Enterprises, Ltd. -> > http://www.hotsos.com -> > -> > Upcoming events: -> > - Hotsos Clinic , Oct 1-3 San -> > Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> > - 2003 Hotsos Symposium on -> > OracleR System Performance, Feb 9-12 Dallas -> > - Next event: Miracle Database Forum , Sep -> > 20-22 Middlefart Denmark -> > -> > -> > -> - diff --git a/err_unsorted/err_xml.msg b/err_unsorted/err_xml.msg deleted file mode 100644 index 7a60a0cb..00000000 --- a/err_unsorted/err_xml.msg +++ /dev/null @@ -1,118 +0,0 @@ -From dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org Fri Aug 15 14:41:14 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h7FDe3MA043557 - for ; Fri, 15 Aug 2003 14:41:13 +0100 (BST) - (envelope-from dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 15 Aug 2003 14:41:13 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 19nc4X-0006LQ-BC; - Fri, 15 Aug 2003 10:44:41 +0000 -Received: from [207.106.49.22] (helo=dolly1.pobox.com) - by punt-3.mail.demon.net with esmtp id 19nc4X-0006LQ-BC - for pobox@dbi.demon.co.uk; Fri, 15 Aug 2003 10:44:41 +0000 -Received: from dolly1.pobox.com (localhost[127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 16F6B21C13B - for ; Fri, 15 Aug 2003 06:44:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.develooper.com[63.251.223.166]) - by dolly1.pobox.com (Postfix) with SMTP id 021F121C36F - for ; Fri, 15 Aug 2003 06:44:40 -0400 (EDT) -Received: (qmail 78180 invoked by uid 1005); 15 Aug 2003 10:44:34 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 71287 invoked by uid 76); 15 Aug 2003 10:32:13 -0000 -Delivered-To: dbi-users@perl.org -Received-SPF: unknown (domain of sender andyhassall@yahoo.com does not designate mailers: NXDOMAIN) -Message-ID: <20030815103200.24313.qmail@web9605.mail.yahoo.com> -Date: Fri, 15 Aug 2003 11:32:00 +0100 (BST) -From: =?iso-8859-1?q?Andy=20Hassall?= -Reply-To: andy@andyh.co.uk -Subject: Re: ERROR OCIDefineObject call needed but not implemented yet using XMLElement function -To: Susan Cassidy , dbi-users@perl.org -In-Reply-To: -MIME-Version: 1.0 -Content-Type: text/plain; charset=iso-8859-1 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.8 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,SPAM_PHRASE_01_02 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id h7FDe3MA043557 -Status: RO -Content-Length: 2299 -Lines: 65 - - --- Susan Cassidy wrote: > I am using DBD::Oracle. -I was on version 1.12, then I installed version -> 1.14, with the same result. -> -> This is Oracle 9.2.0. -> -> I have this select statement that works fine from SQL*Plus: -> -> select XMLElement("Sequences", -> XMLElement("Sequence", -> XMLATTRIBUTES ( b.local_name AS "ic-acckey", -> b.mol_type AS "molecule", -> n.seq_name AS "title"))) -> from gcg_bioseq b, gcg_annot_seq_name a, gcg_seq_name n -> where -> b.local_name = 'K00306' and -> b.seq_status = 'D' and -> b.seq_oid = a.seq_oid and -> a.seq_name_oid = n.seq_name_oid and -> n.name_type = 'LOCUS' -> -> -> When I run it via DBI/DBD I get this (trace level 2): -> -> DBI 1.32-nothread dispatch trace level set to 2 -> Note: perl is running without the recommended perl -w option -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x1b2314)~0x122bec ' -[snip -> Field 1 has an Oracle type (108) which is not explicitly supported -> fbh 1: -> -'XMLELEMENT("SEQUENCES",XMLELEMENT("SEQUENCE",XMLATTRIBUTES(B.LOCAL_NAMEAS"IC-ACCKEY",B.MOL_TYPEAS"MOLECULE",N.SEQ_NAMEAS"TITLE")))' -[snip] -> Error: prepare failed -> at line 56, error: ERROR OCIDefineObject call needed but not -> implemented yet -> -> Is there any other workaround for this than wrapping this up in a PL/SQL -> function? - - Don't rely on the implicit conversion to a string type that is done when -SQL*Plus displays an XMLElement; add .getClobVal() to the end of the -statement to retrieve it as a CLOB rather than the XMLElement object type -(which DBD::Oracle doesn't accept). - - i.e. - -select XMLElement("Sequences", - XMLElement("Sequence", - XMLATTRIBUTES ( b.local_name AS "ic-acckey", - b.mol_type AS "molecule", - n.seq_name AS "title"))).getClobVal() - from ... - - (or getStringVal() for a VARCHAR2) - -===== --- -Andy Hassall (andy@andyh.org) icq(5747695) http://www.andyh.co.uk -http://www.andyhsoftware.co.uk/space | disk usage analysis tool - -________________________________________________________________________ -Want to chat instantly with your online friends? Get the FREE Yahoo! -Messenger http://uk.messenger.yahoo.com/ - - diff --git a/err_unsorted/err_xml2.msg b/err_unsorted/err_xml2.msg deleted file mode 100644 index 3bb291c5..00000000 --- a/err_unsorted/err_xml2.msg +++ /dev/null @@ -1,700 +0,0 @@ -From dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org Fri Jan 30 12:50:15 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UClt3q069307 - for ; Fri, 30 Jan 2004 12:50:14 GMT - (envelope-from dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 12:50:14 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmWGJ-00057X-AG; - Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmWGJ-00057X-AG - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [207.8.214.3] (helo=puzzle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmWGI-0007XK-P3 - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:34 +0000 -Received: from puzzle.pobox.com (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 029E8701C6 - for ; Fri, 30 Jan 2004 05:52:34 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 12ABF701C1 - for ; Fri, 30 Jan 2004 05:52:30 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by puzzle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 05:51:10 -0500 (EST) -Received: (qmail 33345 invoked by uid 1005); 30 Jan 2004 10:50:36 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 33175 invoked by uid 76); 30 Jan 2004 10:50:26 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Fri, 30 Jan 2004 02:50:25 -0800 -Received: (qmail 21117 invoked by uid 225); 30 Jan 2004 10:48:52 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 21080 invoked by uid 507); 30 Jan 2004 10:48:49 -0000 -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Fri, 30 Jan 2004 02:48:46 -0800 -Received: (qmail 31958 invoked from network); 30 Jan 2004 11:50:38 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 30 Jan 2004 11:50:38 -0000 -Received: (qmail 6921 invoked from network); 30 Jan 2004 10:49:58 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 30 Jan 2004 10:49:58 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Fri, 30 Jan 2004 11:49:58 +0100 (CET) -Subject: DBD-Oracle and XMLType -From: Hendrik Fuss -To: "dbi-dev@perl.org" -Content-Type: multipart/mixed; boundary="=-fkyM33WAvQ5xV0uCPeSD" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 11:41:31 +0100 -Message-Id: <1075459292.7305.46.camel@mars> -Mime-Version: 1.0 -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.5 required=7.0 tests=MIME_LONG_LINE_QP,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01,TO_ADDRESS_EQ_REAL version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 8148 -Lines: 302 - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -Hi everyone, - -It's been a while since I last posted here. In September 2003 I was -trying to add support for binding XMLType objects to DBD-Oracle, so that -you could easily insert large (ie >4k) XML data into an XMLType table. - -Unfortunately my employer fired me in October 2003 and in the remaining -time I had to work on other projects, so I wasn't able to complete the -DBD project. Since I won't have access to an oracle database from now -on, I thought the least I can do is to provide my code as it is to the -list. Blame German economy. :-( - -The attached patch (based on DBD-Oracle 1.15) enables you to upload -XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -I added a function dbd_rebind_ph_nty for that purpose. You need to -create that XMLType object first using the C function -createxmlfromstring in xml.c. - -The XMLType object is either created from an OCIString or from a -temporary CLOB depending on the length of the source string. Have a look -at the bottom of ociap.h, all the (undocumented) XMLType functions are -there, and there are also some constants in oci.h. - -I'm not sure if the CLOB code currently works. - -Here is another code fragment: - - my $xml =3D createxml($dbh, 'Test document'); - my $sth =3D $dbh->prepare('INSERT INTO xml_type VALUES (?)'); - $sth->bind_param(1, $xml, { ora_type =3D> 108 }); # SQLT_NTY - $sth->execute(); - -Please note that this code is really just early development, which I -wouldn't publish under normal circumstances. :) I just hope it might me -useful to someone. - -Well then, time to say goodbye -thanks to Tim and everyone who contributed to dbi for a great piece of -software - -Cheers, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Description: -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - -151a152 -> case 108: /* SQLT_NTY */ -992a994,996 -> case SQL_UDT: -> return 108; /* Oracle NTY */ ->=20 -1004a1009,1072 -> static int -> dbd_rebind_ph_nty(sth, imp_sth, phs) -> SV* sth; -> imp_sth_t *imp_sth; -> phs_t *phs; -> { -> OCIType *tdo =3D NULL; -> sword status; -> SV* ptr; ->=20 -> if (phs->is_inout) -> croak("OUT binding for NTY is currently unsupported"); ->=20 -> /* ensure that the value is a support named object type */ -> /* (currently only OCIXMLType*) */ -> if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -> OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -> (CONST text*)"SYS", 3, -> (CONST text*)"XMLTYPE", 7, -> (CONST text*)0, 0, -> OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -> &tdo); ->=20 -> ptr =3D SvRV(phs->sv); -> phs->progv =3D (void*) SvIV(ptr); -> phs->maxlen =3D sizeof(OCIXMLType*); -> } -> else -> croak("Unsupported named object type for bind parameter"); ->=20 ->=20 -> /* bind by name */ ->=20 -> OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -> (text*)phs->name, (sb4)strlen(phs->name), -> (dvoid *) NULL, /* value supplied in BindObject later */ -> 0, -> (ub2)phs->ftype, 0, -> NULL, -> 0, 0, -> NULL, -> (ub4)OCI_DEFAULT, -> status -> ); ->=20 -> if (status !=3D OCI_SUCCESS) { -> oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -> return 0; -> } -> if (DBIS->debug >=3D 3) -> PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); ->=20 ->=20 -> /* bind the object */ ->=20 -> OCIBindObject(phs->bndhp, imp_sth->errhp, -> (CONST OCIType*)tdo, -> (dvoid **)&phs->progv, -> (ub4*)NULL, -> (dvoid **)NULL, -> (ub4*)NULL); ->=20 -> return 2; -> } -1309a1378,1380 -> case 108: -> done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -> break; -1331c1403 -< int at_exec =3D (phs->desc_h =3D=3D NULL); ---- -> int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); -1419c1491 -< if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) ---- -> if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQL= -T_NTY)) -1420a1493 -> /* ref allowed for OCIXMLType* */ -2219a2293 -> case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Disposition: attachment; filename=xml.c -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; name=xml.c; charset=ISO-8859-1 - -#include "oci.h" -#include - -/* This helper function creates an XMLType object from a string source. - * - * The resulting object can be bound to a placeholder, if ora_type =3D> - * SQLT_NTY is specified. - */ - -static void checkerr(errhp, status) -OCIError *errhp; -sword status; -{ - text errbuf[512]; - ub4 buflen; - sb4 errcode; - - switch (status) - { - case OCI_SUCCESS: - break; - case OCI_SUCCESS_WITH_INFO: - printf("Error - OCI_SUCCESS_WITH_INFO\n"); - break; - case OCI_NEED_DATA: - printf("Error - OCI_NEED_DATA\n"); - break; - case OCI_NO_DATA: - printf("Error - OCI_NO_DATA\n"); - break; - case OCI_ERROR: - OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, - errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR); - printf("Error - %s\n", errbuf); - exit(1); - break; - case OCI_INVALID_HANDLE: - printf("Error - OCI_INVALID_HANDLE\n"); - break; - case OCI_STILL_EXECUTING: - printf("Error - OCI_STILL_EXECUTE\n"); - break; - case OCI_CONTINUE: - printf("Error - OCI_CONTINUE\n"); - break; - default: - break; - } -} - - -#define MAX_OCISTRING_LEN 32766 - -SV* createxmlfromstring(SV* dbh, char* source) { - OCIXMLType *xml =3D NULL; - ub4 len; - ub1 src_type; - dvoid* src_ptr =3D NULL; - D_imp_dbh(dbh); - SV* sv_dest; - - len =3D strlen(source); - if(len > MAX_OCISTRING_LEN) { - src_type =3D OCI_XMLTYPE_CREATE_CLOB; - - printf("OCIDescriptorAlloc\n"); - checkerr( imp_dbh->errhp, - OCIDescriptorAlloc((dvoid*)imp_dbh->envhp, - (dvoid **)&src_ptr, - (ub4)OCI_DTYPE_LOB, - (size_t)0, - (dvoid**)0) ); - - printf("OCILobCreateTemporary\n"); - checkerr( imp_dbh->errhp, - OCILobCreateTemporary(imp_dbh->svchp, - imp_dbh->errhp,=20 - (OCILobLocator*) src_ptr, - (ub2)0,=20 - SQLCS_IMPLICIT,=20 - OCI_TEMP_CLOB,=20 - OCI_ATTR_NOCACHE,=20 - OCI_DURATION_SESSION) ); - - printf("OCILobWrite\n"); - checkerr (imp_dbh->errhp, - OCILobWriteAppend(imp_dbh->svchp, - imp_dbh->errhp, - (OCILobLocator*) src_ptr, - &len,=20 - (ub1*)source, - len, - OCI_ONE_PIECE, - (dvoid *)0,=20 - (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, - 0, - SQLCS_IMPLICIT)); - - } else { - src_type =3D OCI_XMLTYPE_CREATE_OCISTRING; - - printf("OCIStringAssignText\n"); - checkerr( imp_dbh->errhp, - OCIStringAssignText(imp_dbh->envhp, - imp_dbh->errhp,=20 - (CONST text*) source,=20 - (ub2) strlen(source), - (OCIString **) &src_ptr) - ); - } - - printf("OCIXMLTypeCreateFromSrc\n"); - checkerr( imp_dbh->errhp, - OCIXMLTypeCreateFromSrc(imp_dbh->svchp, - imp_dbh->errhp, - (OCIDuration)OCI_DURATION_CALLOUT, - (ub1)src_type, - (dvoid *)src_ptr, - (sb4)OCI_IND_NOTNULL, - &xml) - ); - - - /* free temporary resources */ - if( src_type =3D=3D OCI_XMLTYPE_CREATE_CLOB ) { - checkerr( imp_dbh->errhp, - OCILobFreeTemporary(imp_dbh->svchp, imp_dbh->errhp, - (OCILobLocator*) src_ptr) ); - - checkerr( imp_dbh->errhp, - OCIDescriptorFree((dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB) ); - } - - - sv_dest =3D newSViv(0); - sv_setref_pv(sv_dest, "OCIXMLTypePtr", xml); - return sv_dest; -} - ---=-fkyM33WAvQ5xV0uCPeSD-- - - - -From hendrik.fuss@morphochem.de Fri Jan 30 16:56:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UGsO3v071338 - for ; Fri, 30 Jan 2004 16:56:27 GMT - (envelope-from hendrik.fuss@morphochem.de) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 16:56:27 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmZJF-0001wN-DK; - Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmZJF-0001wN-DK - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmZJE-0003GM-Bm - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:48 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 334DE30C57 - for ; Fri, 30 Jan 2004 09:07:47 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id E65B230C2C - for ; Fri, 30 Jan 2004 09:07:45 -0500 (EST) -Received: from babel.morphochem.de (unknown [212.89.121.1]) - by boggle.pobox.com (Postfix) with ESMTP - for ; Fri, 30 Jan 2004 09:07:04 -0500 (EST) -Received: (qmail 29768 invoked from network); 30 Jan 2004 15:10:09 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) - by 212.89.121.1 with SMTP; 30 Jan 2004 15:10:09 -0000 -Received: (qmail 11736 invoked from network); 30 Jan 2004 14:09:30 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) - (envelope-sender ) - by localhost.morphochem.de (qmail-ldap-1.03) with SMTP - for ; 30 Jan 2004 14:09:30 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) - by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; - Fri, 30 Jan 2004 15:09:30 +0100 (CET) -Subject: Re: DBD-Oracle and XMLType -From: Hendrik Fuss -To: Tim Bunce -Cc: "dbi-dev@perl.org" -In-Reply-To: <20040130133443.GC70215@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> - <20040130133443.GC70215@dansat.data-plan.com> -Content-Type: multipart/mixed; boundary="=-Sq1IOPDEhKoqxUKefiS3" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 15:01:03 +0100 -Message-Id: <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Status: RO -X-Status: A -Content-Length: 5585 -Lines: 196 - - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -> > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.= -c -> > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > create that XMLType object first using the C function -> > createxmlfromstring in xml.c. ->=20 -> I there any chance you could post that as a context diff (diff -u ideally -> or else diff -c)? It's much safer and more useful. Thanks. - -Good idea. Here's a diff -u of dbdimp.c. - -By the way: I have thougt about general support of named types, not just -XMLType, but you need to get the type description (TDO) from somewhere. -My code just checks if the perl variable is a blessed reference of -"OCIXMLTypePtr". - -Also note that my code can't handle downloading of XMLType objects yet. - -best wishes, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Description: Context diff for dbdimp.c -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - ---- dbdimp.c.orig 2004-01-30 14:48:55.000000000 +0100 -+++ dbdimp.c 2003-10-07 12:17:17.000000000 +0200 -@@ -1,5 +1,5 @@ - /* -- $Id: dbdimp.c,v 1.1.1.1 2003/10/02 10:45:20 hfuss Exp $ -+ $Id: dbdimp.c,v 1.3 2003/10/07 10:17:17 hfuss Exp $ -=20 - Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce -=20 -@@ -149,6 +149,7 @@ - case 97: /* CHARZ */ - case 106: /* MLSLABEL */ - case 102: /* SQLT_CUR OCI 7 cursor variable */ -+ case 108: /* SQLT_NTY */ - case 112: /* SQLT_CLOB / long */ - case 113: /* SQLT_BLOB / long */ - case 116: /* SQLT_RSET OCI 8 cursor variable */ -@@ -990,6 +991,9 @@ - case SQL_LONGVARCHAR: - return 8; /* Oracle LONG */ -=20 -+ case SQL_UDT: -+ return 108; /* Oracle NTY */ -+ - case SQL_DATE: - case SQL_TIME: - case SQL_TIMESTAMP: -@@ -1002,6 +1006,70 @@ - } -=20 -=20 -+static int -+dbd_rebind_ph_nty(sth, imp_sth, phs) -+ SV* sth; -+ imp_sth_t *imp_sth; -+ phs_t *phs; -+{ -+ OCIType *tdo =3D NULL; -+ sword status; -+ SV* ptr; -+ -+ if (phs->is_inout) -+ croak("OUT binding for NTY is currently unsupported"); -+ -+ /* ensure that the value is a support named object type */ -+ /* (currently only OCIXMLType*) */ -+ if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -+ OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -+ (CONST text*)"SYS", 3, -+ (CONST text*)"XMLTYPE", 7, -+ (CONST text*)0, 0, -+ OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -+ &tdo); -+ -+ ptr =3D SvRV(phs->sv); -+ phs->progv =3D (void*) SvIV(ptr); -+ phs->maxlen =3D sizeof(OCIXMLType*); -+ } -+ else -+ croak("Unsupported named object type for bind parameter"); -+ -+ -+ /* bind by name */ -+ -+ OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -+ (text*)phs->name, (sb4)strlen(phs->name), -+ (dvoid *) NULL, /* value supplied in BindObject later */ -+ 0, -+ (ub2)phs->ftype, 0, -+ NULL, -+ 0, 0, -+ NULL, -+ (ub4)OCI_DEFAULT, -+ status -+ ); -+ -+ if (status !=3D OCI_SUCCESS) { -+ oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -+ return 0; -+ } -+ if (DBIS->debug >=3D 3) -+ PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); -+ -+ -+ /* bind the object */ -+ -+ OCIBindObject(phs->bndhp, imp_sth->errhp, -+ (CONST OCIType*)tdo, -+ (dvoid **)&phs->progv, -+ (ub4*)NULL, -+ (dvoid **)NULL, -+ (ub4*)NULL); -+ -+ return 2; -+} -=20 - static int=20 - dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr)=20 -@@ -1307,6 +1375,9 @@ - case SQLT_RSET: - done =3D dbd_rebind_ph_rset(sth, imp_sth, phs); - break; -+ case 108: -+ done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -+ break; - #else - case 102: /* SQLT_CUR */ - done =3D dbd_rebind_ph_cursor(sth, imp_sth, phs); -@@ -1315,6 +1386,7 @@ - default: - done =3D dbd_rebind_ph_char(sth, imp_sth, phs, &alen_ptr); - } -+ - if (done !=3D 1) { - if (done =3D=3D 2) { /* the rebind did the OCI bind call itself successfu= -lly */ - if (DBIS->debug >=3D 3) -@@ -1328,7 +1400,7 @@ - #ifdef OCI_V8_SYNTAX - if (phs->maxlen > phs->maxlen_bound) { - sword status; -- int at_exec =3D (phs->desc_h =3D=3D NULL); -+ int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, (sb4)strlen(phs->name), - phs->progv, -@@ -1416,8 +1488,9 @@ - } - assert(name !=3D Nullch); -=20 -- if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) -+ if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQLT= -_NTY)) - /* dbi handle allowed for cursor variables */ -+ /* ref allowed for OCIXMLType* */ - croak("Can't bind a reference (%s)", neatsvpv(newvalue,0)); - if (SvTYPE(newvalue) > SVt_PVLV) /* hook for later array logic? */ - croak("Can't bind a non-scalar value (%s)", neatsvpv(newvalue,0)); -@@ -2217,6 +2290,7 @@ - #ifdef OCI_V8_SYNTAX - case SQLT_CLOB: sql_fbh.dbtype =3D SQL_CLOB; break; - case SQLT_BLOB: sql_fbh.dbtype =3D SQL_BLOB; break; -+ case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - #endif - #ifdef SQLT_TIMESTAMP_TZ - case SQLT_TIMESTAMP_TZ: sql_fbh.dbtype =3D SQL_TIMESTAMP; break; - ---=-Sq1IOPDEhKoqxUKefiS3-- - - - -From timbo@dansat.data-plan.com Fri Jan 30 18:32:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UIVK3f073353 - for ; Fri, 30 Jan 2004 18:32:30 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 18:32:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmceP-000603-GP; - Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmceP-000603-GP - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [208.210.124.73] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1AmceO-0006dQ-DB - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:52 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 25AEA3F13D - for ; Fri, 30 Jan 2004 12:41:51 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9FB863F16E - for ; Fri, 30 Jan 2004 12:41:49 -0500 (EST) -Received: from mail09.svc.cra.dublin.eircom.net (mail09.svc.cra.dublin.eircom.net [159.134.118.25]) - by icicle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 12:41:11 -0500 (EST) -Received: (qmail 9504 messnum 226571 invoked from network[213.94.228.233/unknown]); 30 Jan 2004 17:40:43 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail09.svc.cra.dublin.eircom.net (qp 9504) with SMTP; 30 Jan 2004 17:40:43 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UHf33A072739; - Fri, 30 Jan 2004 17:41:03 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i0UHf2Wr072738; - Fri, 30 Jan 2004 17:41:02 GMT -Date: Fri, 30 Jan 2004 17:41:02 +0000 -From: Tim Bunce -To: Hendrik Fuss -Cc: Tim Bunce , "dbi-dev@perl.org" -Subject: Re: DBD-Oracle and XMLType -Message-ID: <20040130174102.GB72657@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> <20040130133443.GC70215@dansat.data-plan.com> <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <1075471263.7305.73.camel@mars> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1129 -Lines: 29 - -On Fri, Jan 30, 2004 at 03:01:03PM +0100, Hendrik Fuss wrote: -> > > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -> > > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > > create that XMLType object first using the C function -> > > createxmlfromstring in xml.c. -> > -> > I there any chance you could post that as a context diff (diff -u ideally -> > or else diff -c)? It's much safer and more useful. Thanks. -> -> Good idea. Here's a diff -u of dbdimp.c. - -Thanks. - -> By the way: I have thougt about general support of named types, not just -> XMLType, but you need to get the type description (TDO) from somewhere. -> My code just checks if the perl variable is a blessed reference of -> "OCIXMLTypePtr". - -Doing the equivalent of m/^OCI(\w+)Ptr$/ and then calling OCITypeByName -with $1 uppercased might take us (or someone) a step further. - -> Also note that my code can't handle downloading of XMLType objects yet. - -I'll trust that some kind soul with an itch will send a patch :-) - -Thanks again Hendrik. - -Tim. - diff --git a/err_unsorted/err_xmltypebindplsql.msg b/err_unsorted/err_xmltypebindplsql.msg deleted file mode 100644 index 08faa725..00000000 --- a/err_unsorted/err_xmltypebindplsql.msg +++ /dev/null @@ -1,174 +0,0 @@ -From dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org Thu Apr 25 11:02:42 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3PA2gK34525 - for ; Thu, 25 Apr 2002 11:02:42 +0100 (BST) - (envelope-from dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 25 Apr 2002 11:02:42 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1019721492:10:18778:60; Thu, 25 Apr 2002 07:58:12 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1109782; 25 Apr 2002 7:58 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 791692BF11 - for ; Thu, 25 Apr 2002 03:58:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id 976FB2BEE4 - for ; Thu, 25 Apr 2002 03:58:07 -0400 (EDT) -Received: (qmail 84467 invoked by uid 1005); 25 Apr 2002 07:58:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 77923 invoked by uid 76); 24 Apr 2002 23:08:56 -0000 -Date: Wed, 24 Apr 2002 19:08:54 -0400 -From: Mark Stillwell -To: dbi-users-help@perl.org, dbi-users@perl.org -Subject: Oracle 9 XMLTYPE insert -Message-ID: <20020424190852.C22854@byrd.biostat.ufl.edu> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -Status: RO -Content-Length: 1469 -Lines: 43 - -I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -Here is my problem, I have a table named 'test' with three fields: eid -(integer), x (SYS.XMLTYPE) and formname (text) - -I create a database handler and connect to the database just fine. - -I create a new statement handler with the following command: - -$sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -SYS.XMLTYPE.CREATEXML(?), ?"); - -I loop over some data, $eid gets and integer, $xmlvalue gets a string, -and $formname gets a string. So long as $xmlvalue is relatively short -$sth->execute($eid, $xmlvalue, $formname); works great, but as soon as -it becomes long enough to force the use of clob's I have a problem. - -So I tried the following: - -$sth->bind_param(1, $i); -$sth->bind_param(2, $xmlvalue, { ora_type => ORA_CLOB }); -$sth->bind_param(3, $intable); -$sth->execute; - -This works great if column 'x' is a normal CLOB and I omit the -sys.xmltype.createxml statement above, but when 'x' is of type -sys.xmltype I get the following error: - -nvalid LOB locator specified -ORA-06512: at "SYS.XMLTYPE", line 0 - -Right now I've hacked the setup so there is a supplemental table called -'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE test SET x -= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem like the -right way to do this. - -Is there any way to do what I want in the current version of -DBI/OracleDBD? - --- -Mark Stillwell -marklee@ufl.edu -http://plaza.ufl.edu/marklee/ - -From dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org Wed May 8 16:11:46 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g48FBjo24814 - for ; Wed, 8 May 2002 16:11:45 +0100 (BST) - (envelope-from dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 08 May 2002 16:11:45 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020870336:20:08175:2; Wed, 08 May 2002 15:05:36 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2109147; 8 May 2002 15:05 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id 68FE23E6D4 - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-3.pobox.com (Postfix) with SMTP id 33A783E64D - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Received: (qmail 65232 invoked by uid 1005); 8 May 2002 15:01:47 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 60079 invoked by uid 76); 8 May 2002 14:50:53 -0000 -From: "Ben Middleton" -To: -Cc: -Subject: Re: Oracle 9 XMLTYPE insert -Date: Wed, 8 May 2002 15:50:47 +0100 -Message-ID: -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0) -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -Content-Length: 1311 -Lines: 39 - -Hi. - -Not sure if you ever resolved this: - -> I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -> Here is my problem, I have a table named 'test' with three fields: -> eid (integer), x (SYS.XMLTYPE) and formname (text) - -> I create a new statement handler with the following command: - -> $sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -> SYS.XMLTYPE.CREATEXML(?), ?"); - -.... - -> Invalid LOB locator specified -> ORA-06512: at "SYS.XMLTYPE", line 0 - -> Right now I've hacked the setup so there is a supplemental table -> called 'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE -> test SET x= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem -> like the right way to do this. - -> Is there any way to do what I want in the current version of -> DBI/OracleDBD? - -I don't think that the current DBI/DBD can bind a CLOB to a PL/SQL function -(which is all the CREATEXML function is) - hence you will have to go with -the intermediate CLOB table solution. - -Incidentally, if you are using Oracle9i - have you tried using a TEMPORARY -TABLE with a CLOB column (see SQL Reference Guide)? If setup correctly, this -is automatically truncated at the end of a transaction, is managed by the -Server, and provides some efficiency benefits. We use this here quite -effectively. - -Ben. - - diff --git a/Oracle.pm b/lib/DBD/Oracle.pm similarity index 99% rename from Oracle.pm rename to lib/DBD/Oracle.pm index 75d7f2a8..48127036 100644 --- a/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -7,12 +7,17 @@ require 5.006; -$DBD::Oracle::VERSION = '1.35_00'; - my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { - package DBD::Oracle; +package DBD::Oracle; +{ + $DBD::Oracle::VERSION = '1.37_00'; +} +BEGIN { + $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; +} +# ABSTRACT: Oracle database driver for the DBI module use DBI (); use DynaLoader (); @@ -110,7 +115,13 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; } -{ package DBD::Oracle::dr; # ====== DRIVER ====== +{ package DBD::Oracle::dr; +{ + $DBD::Oracle::dr::VERSION = '1.37_00'; +} +BEGIN { + $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DRIVER ====== use strict; my %dbnames = (); # holds list of known databases (oratab + tnsnames) @@ -309,7 +320,13 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; } -{ package DBD::Oracle::db; # ====== DATABASE ====== +{ package DBD::Oracle::db; +{ + $DBD::Oracle::db::VERSION = '1.37_00'; +} +BEGIN { + $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DATABASE ====== use strict; use DBI qw(:sql_types); @@ -1001,7 +1018,13 @@ SQL } # end of package DBD::Oracle::db -{ package DBD::Oracle::st; # ====== STATEMENT ====== +{ package DBD::Oracle::st; +{ + $DBD::Oracle::st::VERSION = '1.37_00'; +} +BEGIN { + $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== STATEMENT ====== sub bind_param_inout_array { @@ -1095,12 +1118,18 @@ SQL 1; -__END__ + + +=pod =head1 NAME DBD::Oracle - Oracle database driver for the DBI module +=head1 VERSION + +version 1.37_00 + =head1 SYNOPSIS use DBI; @@ -1114,7 +1143,6 @@ DBD::Oracle - Oracle database driver for the DBI module # for some advanced uses you may need Oracle type values: use DBD::Oracle qw(:ora_types); - =head1 DESCRIPTION DBD::Oracle is a Perl module which works with the DBI module to provide @@ -1222,7 +1250,6 @@ If port name is not specified, 1521 is the default. If service name is not speci The following examples show several ways a connection can be created: - $dbh = DBI->connect('dbi:Oracle:DB','username','password'); $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); @@ -1553,7 +1580,6 @@ DBDOxxxx where xxxx is the current version number. This value can be retrieved on the server side using V$SESSION_CONNECT_INFO or GV$SESSION_CONNECT_INFO - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); $dbh->{ora_driver_name} = $q; @@ -1724,7 +1750,6 @@ If the previous error was from a failed C due to a syntax error, this attribute gives the offset into the C attribute where the error was found. - =head4 ora_array_chunk_size Due to OCI limitations, DBD::Oracle needs to buffer up rows of @@ -1947,7 +1972,6 @@ DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. Starts a new session against the current database using the credentials supplied. - =head2 B $hashref = $dbh->private_attribute_info(); @@ -2075,7 +2099,6 @@ Implemented by DBI, no driver-specific impact. Implemented by DBI, no driver-specific impact. - =head2 B Type: boolean, inherited @@ -2084,7 +2107,6 @@ The CompatMode attribute is used by emulation layers (such as Oraperl) to enable It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. - =head1 ORACLE-SPECIFIC DATABASE HANDLE METHODS =head2 B @@ -2244,7 +2266,6 @@ The different types of placeholders cannot be mixed within a statement, but you use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. - =head2 B $sth = $dbh->prepare_cached($statement, \%attr); @@ -2263,7 +2284,6 @@ query was successful, returns undef if an error occurred, and returns -1 if the number of rows is unknown or not available. Note that this method will return B<0E0> instead of 0 for 'no rows were affected', in order to always return a true value if no error occurred. - =head2 B Oracle does not implement auto_increment of serial type columns it uses predefined @@ -2319,7 +2339,6 @@ If the script exits before disconnect is called (or, more precisely, if the data referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() methods automatically. It is best to explicitly disconnect rather than rely on this behavior. - =head2 B $rv = $dbh->ping; @@ -2668,7 +2687,6 @@ Examples: ## This executes the statement with 567 (integer) and "Zool" (varchar) $sth->execute(); - These attributes may be used in the C<\%attr> parameter of the L or L statement handle methods. @@ -2763,10 +2781,8 @@ Set L to 0 in prepare() to enable this behaviour. $rv = $sth->bind_param_inout($param_num, \$scalar, 0); - DBD::Oracle fully supports bind_param_inout below are some uses for this method. - =head3 B Oracle supports an extended SQL insert syntax which will return one @@ -2940,10 +2956,6 @@ the above example, the code would look something like this : ... } - - - - =head3 B DBD::Oracle has built-in support for B @@ -2978,13 +2990,11 @@ and B datatypes. The simple example is here: =item B -=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' +=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' will only take a reference to a scalar. =back - - =head3 B SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. @@ -3093,7 +3103,6 @@ you get: DBD::Oracle supports this undocumented feature of DBI. See L for an example. - =head2 B $rv = $sth->bind_param_array($param_num, $array_ref_or_value) @@ -3103,8 +3112,6 @@ DBD::Oracle supports this undocumented feature of DBI. See L method. - - =head2 B $rv = $sth->execute(@bind_values); @@ -3371,7 +3378,6 @@ However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch Only use scrollable cursors if you really have a good reason to. They do use up considerable more server and client resources and have poorer response times than non-scrolling cursors. - =head2 Enabling Scrollable Cursors To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; @@ -3387,7 +3393,6 @@ When the statement is executed you will then be able to use 'ora_fetch_scroll' m or you can still use any of the other fetch methods but with a poorer response time than if you used a non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. - =head2 Scrollable Cursor Methods The following driver-specific methods are used with scrollable cursors. @@ -3727,7 +3732,6 @@ You can tune this value by setting ora_oci_success_warn which will display the f In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. - =head3 Simple Fetch for CLOBs and BLOBs To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well @@ -4129,7 +4133,6 @@ Uses the Oracle OCILobTrim function. Returns the length of the LOB. Uses the Oracle OCILobGetLength function. - =item ora_lob_is_init $is_init = $dbh->ora_lob_is_init($lob_locator); @@ -4176,7 +4179,6 @@ lob_id field values, defined as follows: CREATE SEQUENCE lob_example_seq - =head3 Example: Inserting a new row with large data Unless enough memory is available to store and bind the @@ -4242,7 +4244,6 @@ can't be used effectively if AutoCommit is enabled). $offset += $length; } - In this example we demonstrate the use of ora_lob_write() interactively to append data to the columns 'bin_data' and 'char_data'. Had we used ora_lob_append(), we could have @@ -4259,7 +4260,6 @@ The scalar variables $offset and $length are no longer needed, because ora_lob_append() keeps track of the offset for us. - =head3 Example: Updating an existing row with large data In this example, we demonstrate a technique for overwriting @@ -4444,7 +4444,6 @@ WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other than US7ASCII, requires that the NLS_LANG environment variable be set. See the L<"Oracle UTF8 is not UTF-8"> section below. - You are strongly urged to read the Oracle Internationalization documentation specifically with respect the choices and trade offs for creating a databases for use with international character sets. @@ -4551,7 +4550,6 @@ If the C attribute is given to bind_param() then that determines if the value should be assumed to be in the default (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); ... $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); @@ -4592,7 +4590,6 @@ and TABLE in any combination. Support is seamless and recursive, meaning you need only supply a simple SQL statement to get all the values in an embedded object. You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. - Array example, given this type and table; CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); @@ -4745,7 +4742,6 @@ There are some types, like BOOLEAN, that Oracle does not automatically convert to or from strings (pity). These need to be converted explicitly using SQL or PL/SQL functions. - Examples: # DATE values @@ -4800,7 +4796,6 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" - =head4 Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special @@ -4948,7 +4943,6 @@ shows: } } - The cursor returned by the function C defined in the previous section can be fetched as a nested cursor as follows: @@ -5329,7 +5323,6 @@ There is a known problem with the 11.2g Oracle client and the C PL/SQL function. See L for the details. - =head1 SEE ALSO =over @@ -5397,4 +5390,34 @@ The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. The DBD::Oracle module is free open source software; you can redistribute it and/or modify it under the same terms as Perl 5. +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + + +__END__ + + diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index b1c088e3..49abb12d 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,4 +1,10 @@ package DBD::Oracle::GetInfo; +{ + $DBD::Oracle::GetInfo::VERSION = '1.37_00'; +} +BEGIN { + $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; +} use strict; use DBD::Oracle(); @@ -314,4 +320,44 @@ our %info = ( 1; + + +=pod + +=head1 NAME + +DBD::Oracle::GetInfo + +=head1 VERSION + +version 1.37_00 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + + __END__ diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 4af4cdbc..7075c84c 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,24 +1,70 @@ -package DBD::Oracle::Object; - -use strict; -use warnings; - -sub type_name { shift->{type_name} } - -sub attributes { @{shift->{attributes}} } - -sub attr_hash { - my $self = shift; - return $self->{attr_hash} ||= { $self->attributes }; -} - -sub attr { - my $self = shift; - if (@_) { - my $key = shift; - return $self->attr_hash->{$key}; - } - return $self->attr_hash; -} - -1; \ No newline at end of file +package DBD::Oracle::Object; +{ + $DBD::Oracle::Object::VERSION = '1.37_00'; +} +BEGIN { + $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; +} +# ABSTRACT: Wrapper for Oracle objects + +use strict; +use warnings; + +sub type_name { shift->{type_name} } + +sub attributes { @{shift->{attributes}} } + +sub attr_hash { + my $self = shift; + return $self->{attr_hash} ||= { $self->attributes }; +} + +sub attr { + my $self = shift; + if (@_) { + my $key = shift; + return $self->attr_hash->{$key}; + } + return $self->attr_hash; +} + +1; + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Object - Wrapper for Oracle objects + +=head1 VERSION + +version 1.37_00 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 7522d8c9..3a129ef4 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,9 +1,24 @@ +package DBD::Oracle::Troubleshooting; +{ + $DBD::Oracle::Troubleshooting::VERSION = '1.37_00'; +} +BEGIN { + $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; +} +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle + + +__END__ =pod =head1 NAME DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle +=head1 VERSION + +version 1.37_00 + =head1 CONNECTING TO ORACLE If you are reading this it is assumed that you have successfully @@ -30,7 +45,6 @@ For Windows the solution is to add this value to you PATH PATH=c:\app\oracle\product\xx.x.x;%PATH% - If you get past this stage and get a ORA-12154: TNS:could not resolve the connect identifier specified @@ -62,7 +76,6 @@ Protocol Adapter". If it generates any errors which look relevant then please talk to your Oracle technical support (and not the dbi-users mailing list). - =head1 USING THE LONG TYPES Some examples related to the use of LONG types are available in @@ -97,7 +110,6 @@ It turns out that now it is necessary to edit the same file and append this and then run "genclntsh", the libclntsh is properly generated and the linkage with DBD::Oracle proceeds properly. - =head2 cc1: invalid option `tune=pentium4'" error If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. @@ -154,7 +166,7 @@ To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY as you would for an install against 10g Standard Edition, Standard Edition One, or Enterprise Edition -=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 +=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 DBD::Oracle seems to hit some sort of bug with the above two versions of DB. The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also @@ -173,7 +185,6 @@ So far there is no patch for this but here are some work arounds or this way utf8::downgrade($parameter, 1); - =head1 CYGWIN @@ -336,4 +347,30 @@ oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + diff --git a/t/000-report-versions.t b/t/000-report-versions.t new file mode 100644 index 00000000..2d4a9a19 --- /dev/null +++ b/t/000-report-versions.t @@ -0,0 +1,446 @@ +#!perl +use warnings; +use strict; +use Test::More 0.94; + +# Include a cut-down version of YAML::Tiny so we don't introduce unnecessary +# dependencies ourselves. + +package Local::YAML::Tiny; + +use strict; +use Carp 'croak'; + +# UTF Support? +sub HAVE_UTF8 () { $] >= 5.007003 } +BEGIN { + if ( HAVE_UTF8 ) { + # The string eval helps hide this from Test::MinimumVersion + eval "require utf8;"; + die "Failed to load UTF-8 support" if $@; + } + + # Class structure + require 5.004; + $YAML::Tiny::VERSION = '1.40'; + + # Error storage + $YAML::Tiny::errstr = ''; +} + +# Printable characters for escapes +my %UNESCAPES = ( + z => "\x00", a => "\x07", t => "\x09", + n => "\x0a", v => "\x0b", f => "\x0c", + r => "\x0d", e => "\x1b", '\\' => '\\', +); + + +##################################################################### +# Implementation + +# Create an empty YAML::Tiny object +sub new { + my $class = shift; + bless [ @_ ], $class; +} + +# Create an object from a file +sub read { + my $class = ref $_[0] ? ref shift : shift; + + # Check the file + my $file = shift or return $class->_error( 'You did not specify a file name' ); + return $class->_error( "File '$file' does not exist" ) unless -e $file; + return $class->_error( "'$file' is a directory, not a file" ) unless -f _; + return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; + + # Slurp in the file + local $/ = undef; + local *CFG; + unless ( open(CFG, $file) ) { + return $class->_error("Failed to open file '$file': $!"); + } + my $contents = ; + unless ( close(CFG) ) { + return $class->_error("Failed to close file '$file': $!"); + } + + $class->read_string( $contents ); +} + +# Create an object from a string +sub read_string { + my $class = ref $_[0] ? ref shift : shift; + my $self = bless [], $class; + my $string = $_[0]; + unless ( defined $string ) { + return $self->_error("Did not provide a string to load"); + } + + # Byte order marks + # NOTE: Keeping this here to educate maintainers + # my %BOM = ( + # "\357\273\277" => 'UTF-8', + # "\376\377" => 'UTF-16BE', + # "\377\376" => 'UTF-16LE', + # "\377\376\0\0" => 'UTF-32LE' + # "\0\0\376\377" => 'UTF-32BE', + # ); + if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) { + return $self->_error("Stream has a non UTF-8 BOM"); + } else { + # Strip UTF-8 bom if found, we'll just ignore it + $string =~ s/^\357\273\277//; + } + + # Try to decode as utf8 + utf8::decode($string) if HAVE_UTF8; + + # Check for some special cases + return $self unless length $string; + unless ( $string =~ /[\012\015]+\z/ ) { + return $self->_error("Stream does not end with newline character"); + } + + # Split the file into lines + my @lines = grep { ! /^\s*(?:\#.*)?\z/ } + split /(?:\015{1,2}\012|\015|\012)/, $string; + + # Strip the initial YAML header + @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; + + # A nibbling parser + while ( @lines ) { + # Do we have a document header? + if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { + # Handle scalar documents + shift @lines; + if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { + push @$self, $self->_read_scalar( "$1", [ undef ], \@lines ); + next; + } + } + + if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { + # A naked document + push @$self, undef; + while ( @lines and $lines[0] !~ /^---/ ) { + shift @lines; + } + + } elsif ( $lines[0] =~ /^\s*\-/ ) { + # An array at the root + my $document = [ ]; + push @$self, $document; + $self->_read_array( $document, [ 0 ], \@lines ); + + } elsif ( $lines[0] =~ /^(\s*)\S/ ) { + # A hash at the root + my $document = { }; + push @$self, $document; + $self->_read_hash( $document, [ length($1) ], \@lines ); + + } else { + croak("YAML::Tiny failed to classify the line '$lines[0]'"); + } + } + + $self; +} + +# Deparse a scalar string to the actual scalar +sub _read_scalar { + my ($self, $string, $indent, $lines) = @_; + + # Trim trailing whitespace + $string =~ s/\s*\z//; + + # Explitic null/undef + return undef if $string eq '~'; + + # Quotes + if ( $string =~ /^\'(.*?)\'\z/ ) { + return '' unless defined $1; + $string = $1; + $string =~ s/\'\'/\'/g; + return $string; + } + if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) { + # Reusing the variable is a little ugly, + # but avoids a new variable and a string copy. + $string = $1; + $string =~ s/\\"/"/g; + $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; + return $string; + } + + # Special cases + if ( $string =~ /^[\'\"!&]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + return {} if $string eq '{}'; + return [] if $string eq '[]'; + + # Regular unquoted string + return $string unless $string =~ /^[>|]/; + + # Error + croak("YAML::Tiny failed to find multi-line scalar content") unless @$lines; + + # Check the indent depth + $lines->[0] =~ /^(\s*)/; + $indent->[-1] = length("$1"); + if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Pull the lines + my @multiline = (); + while ( @$lines ) { + $lines->[0] =~ /^(\s*)/; + last unless length($1) >= $indent->[-1]; + push @multiline, substr(shift(@$lines), length($1)); + } + + my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; + my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; + return join( $j, @multiline ) . $t; +} + +# Parse an array +sub _read_array { + my ($self, $array, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { + # Inline nested hash + my $indent2 = length("$1"); + $lines->[0] =~ s/-/ /; + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { + # Array entry with a value + shift @$lines; + push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { + shift @$lines; + unless ( @$lines ) { + push @$array, undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)\-/ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] == $indent2 ) { + # Null array entry + push @$array, undef; + } else { + # Naked indenter + push @$array, [ ]; + $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines ); + } + + } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines ); + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + + } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { + # This is probably a structure like the following... + # --- + # foo: + # - list + # bar: value + # + # ... so lets return and let the hash parser handle it + return 1; + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + } + + return 1; +} + +# Parse an array +sub _read_hash { + my ($self, $hash, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Get the key + unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { + if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + my $key = $1; + + # Do we have a value? + if ( length $lines->[0] ) { + # Yes + $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines ); + } else { + # An indent + shift @$lines; + unless ( @$lines ) { + $hash->{$key} = undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)-/ ) { + $hash->{$key} = []; + $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } elsif ( $lines->[0] =~ /^(\s*)./ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] >= $indent2 ) { + # Null hash entry + $hash->{$key} = undef; + } else { + $hash->{$key} = {}; + $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } + } + } + } + + return 1; +} + +# Set error +sub _error { + $YAML::Tiny::errstr = $_[1]; + undef; +} + +# Retrieve error +sub errstr { + $YAML::Tiny::errstr; +} + + + +##################################################################### +# Use Scalar::Util if possible, otherwise emulate it + +BEGIN { + eval { + require Scalar::Util; + }; + if ( $@ ) { + # Failed to load Scalar::Util + eval <<'END_PERL'; +sub refaddr { + my $pkg = ref($_[0]) or return undef; + if (!!UNIVERSAL::can($_[0], 'can')) { + bless $_[0], 'Scalar::Util::Fake'; + } else { + $pkg = undef; + } + "$_[0]" =~ /0x(\w+)/; + my $i = do { local $^W; hex $1 }; + bless $_[0], $pkg if defined $pkg; + $i; +} +END_PERL + } else { + Scalar::Util->import('refaddr'); + } +} + + +##################################################################### +# main test +##################################################################### + +package main; + +BEGIN { + + # Skip modules that either don't want to be loaded directly, such as + # Module::Install, or that mess with the test count, such as the Test::* + # modules listed here. + # + # Moose::Role conflicts if Moose is loaded as well, but Moose::Role is in + # the Moose distribution and it's certain that someone who uses + # Moose::Role also uses Moose somewhere, so if we disallow Moose::Role, + # we'll still get the relevant version number. + + my %skip = map { $_ => 1 } qw( + App::FatPacker + Class::Accessor::Classy + Devel::Cover + Module::Install + Moose::Role + POE::Loop::Tk + Template::Test + Test::Kwalitee + Test::Pod::Coverage + Test::Portability::Files + Test::YAML::Meta + ); + + my $Test = Test::Builder->new; + + $Test->plan(skip_all => "META.yml could not be found") + unless -f 'META.yml' and -r _; + + my $meta = (Local::YAML::Tiny->read('META.yml'))->[0]; + my %requires; + for my $require_key (grep { /requires/ } keys %$meta) { + my %h = %{ $meta->{$require_key} }; + $requires{$_}++ for keys %h; + } + delete $requires{perl}; + + diag("Testing with Perl $], $^X"); + for my $module (sort keys %requires) { + if ($skip{$module}) { + note "$module doesn't want to be loaded directly, skipping"; + next; + } + local $SIG{__WARN__} = sub { note "$module: $_[0]" }; + use_ok $module or BAIL_OUT("can't load $module"); + my $version = $module->VERSION; + $version = 'undefined' unless defined $version; + diag(" $module version is $version"); + } + done_testing; +} diff --git a/xt/changes.t b/xt/changes.t deleted file mode 100644 index 27a4808a..00000000 --- a/xt/changes.t +++ /dev/null @@ -1,8 +0,0 @@ -use strict; -use warnings; - -use Test::More; - -eval 'use Test::CPAN::Changes'; -plan skip_all => 'Test::CPAN::Changes required for this test' if $@; -changes_ok(); diff --git a/xt/manifest.t b/xt/manifest.t deleted file mode 100644 index 00df9957..00000000 --- a/xt/manifest.t +++ /dev/null @@ -1,21 +0,0 @@ -use strict; -use warnings; - -use ExtUtils::Manifest qw/ fullcheck /; - -use Test::More tests => 1; - -my ( $missing, $extra ) = do { - local *STDERR; - - # hush little baby, don't you cry - open STDERR, '>', \my $stderr; - - fullcheck(); -}; - -ok @$missing + @$extra == 0, 'manifest in sync' or do { - diag "missing files:\n", map { " \t $_\n " } @$missing if @$missing; - diag "extra files: \n", map { "\t$_\n" } @$extra if @$extra; -}; - diff --git a/xt/pod.t b/xt/pod.t deleted file mode 100644 index 66481225..00000000 --- a/xt/pod.t +++ /dev/null @@ -1,11 +0,0 @@ -use Test::More; - -eval "use Test::Pod"; - -plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; - -pod_file_ok( 'Oracle.pm' ); -pod_file_ok( 'lib/DBD/Oracle/Object.pm' ); -pod_file_ok( 'lib/DBD/Oracle/GetInfo.pm' ); - -done_testing; From 4485a74ba0bfc0b899ea01dc93cacf5a83be09f4 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sun, 8 Jan 2012 12:00:19 -0500 Subject: [PATCH 095/637] TAF support depends on OCI_ATTR_TAF_ENABLED --- Changes | 6 ++++++ Oracle.xs | 4 ++++ dbdimp.c | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/Changes b/Changes index e5a50cae..2cbbec47 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,12 @@ Revision history for DBD::Oracle {{$NEXT}} + [BUG FIXES] + - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED + [RT73798] + +1.37_00 2011-12-30 + [ENHANCEMENTS] - added SYSASM session mode. [RT651211] (patch from Anthony DeRobertis, reported by Julián Moreno Patiño) diff --git a/Oracle.xs b/Oracle.xs index fa79d0bf..1a1f3db2 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -358,9 +358,13 @@ ora_can_taf(dbh) sword status; ub4 can_taf = 0; CODE: +#ifdef OCI_ATTR_TAF_ENABLED OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { +# else + if ( 1 ) { +# endif oci_error(dbh, imp_dbh->errhp, status, "OCIAttrGet OCI_ATTR_TAF_ENABLED"); XSRETURN_IV(0); } diff --git a/dbdimp.c b/dbdimp.c index 84eb7054..9d4cc658 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -902,8 +902,12 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (imp_dbh->using_taf){ bool can_taf; + can_taf = 0; + +#ifdef OCI_ATTR_TAF_ENABLED OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); +#endif if (!can_taf){ croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); From 1e1642bc7a83d0bb9ac0ec4d3a9364407bb6cd2a Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 9 Jan 2012 20:45:46 +0000 Subject: [PATCH 096/637] TAF support depends on OCI_ATTR_TAF_ENABLED git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15079 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 ++++++ Oracle.xs | 4 ++++ dbdimp.c | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/Changes b/Changes index 63244b32..a3166a43 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,11 @@ Revision history for DBD::Oracle +1.37_00 2012-01-09 + + [BUG FIXES] + - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED + [RT73798] + 1.37_00 2011-12-30 [ENHANCEMENTS] diff --git a/Oracle.xs b/Oracle.xs index fa79d0bf..1a1f3db2 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -358,9 +358,13 @@ ora_can_taf(dbh) sword status; ub4 can_taf = 0; CODE: +#ifdef OCI_ATTR_TAF_ENABLED OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { +# else + if ( 1 ) { +# endif oci_error(dbh, imp_dbh->errhp, status, "OCIAttrGet OCI_ATTR_TAF_ENABLED"); XSRETURN_IV(0); } diff --git a/dbdimp.c b/dbdimp.c index 84eb7054..9d4cc658 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -902,8 +902,12 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (imp_dbh->using_taf){ bool can_taf; + can_taf = 0; + +#ifdef OCI_ATTR_TAF_ENABLED OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); +#endif if (!can_taf){ croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); From 1e806f2562a8657de8925b5717740ea4c94d782e Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 9 Jan 2012 20:45:46 +0000 Subject: [PATCH 097/637] TAF support depends on OCI_ATTR_TAF_ENABLED git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15079 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 ++++++ Oracle.xs | 4 ++++ dbdimp.c | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/Changes b/Changes index 63244b32..a3166a43 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,11 @@ Revision history for DBD::Oracle +1.37_00 2012-01-09 + + [BUG FIXES] + - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED + [RT73798] + 1.37_00 2011-12-30 [ENHANCEMENTS] diff --git a/Oracle.xs b/Oracle.xs index fa79d0bf..1a1f3db2 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -358,9 +358,13 @@ ora_can_taf(dbh) sword status; ub4 can_taf = 0; CODE: +#ifdef OCI_ATTR_TAF_ENABLED OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { +# else + if ( 1 ) { +# endif oci_error(dbh, imp_dbh->errhp, status, "OCIAttrGet OCI_ATTR_TAF_ENABLED"); XSRETURN_IV(0); } diff --git a/dbdimp.c b/dbdimp.c index 84eb7054..9d4cc658 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -902,8 +902,12 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (imp_dbh->using_taf){ bool can_taf; + can_taf = 0; + +#ifdef OCI_ATTR_TAF_ENABLED OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); +#endif if (!can_taf){ croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); From db73000a6ccbfa0259f3dc1261b32dfc3b0a2c8e Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 13 Jan 2012 13:15:47 -0500 Subject: [PATCH 098/637] preps for v1.38 --- Changes | 4 ++++ dist.ini | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index e5a50cae..1de25c34 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,10 @@ Revision history for DBD::Oracle {{$NEXT}} + - promote 1.37_00 to official release + +1.37_00 2011-12-30 + [ENHANCEMENTS] - added SYSASM session mode. [RT651211] (patch from Anthony DeRobertis, reported by Julián Moreno Patiño) diff --git a/dist.ini b/dist.ini index 148ecba4..013f79fc 100644 --- a/dist.ini +++ b/dist.ini @@ -6,7 +6,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.37_00 +version = 1.38 [Authority] authority=cpan:PYTHIAN From 20021c36bcd7dd6a2d8e20b5ae1bb0012b47d3a3 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 25 Jan 2012 09:27:28 +0000 Subject: [PATCH 099/637] Mention the release of Oracle Instant Client 64 bit which does not work on Lion. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15095 50811bd7-b8ce-0310-adc1-d9db26280581 --- README.macosx.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.macosx.txt b/README.macosx.txt index e854e4c6..57801dad 100644 --- a/README.macosx.txt +++ b/README.macosx.txt @@ -50,11 +50,12 @@ database server on your MacOSX box. See below (Instructions for ====================================================================== Instructions for 10.7.x (Lion) -Because the 64 bit instantclient is currently [incompatible with Lion][], -DBD::Oracle can only be compiled with the 32-bit instantclient libraries, and -therefore requires 32-bit Perl. If your Perl is 64-bit (which, by default, it -is on Mac OS X), you will not be able to build DBD::Oracle until an updated -64-bit instantclient is released. +Because the 64 bit instantclient (version 10gr2)is currently +[incompatible with Lion][], DBD::Oracle can only be compiled with the +32-bit instantclient libraries, and therefore requires 32-bit Perl. If +your Perl is 64-bit (which, by default, it is on Mac OS X), you will +not be able to build DBD::Oracle until an updated 64-bit instantclient +is released. [incompatible with Lion]: http://only4left.jpiwowar.com/2011/08/instant-client-osx-lion-32-bit-only/ From fcb59da7dadae7914157f8a50119bbea7dab7f86 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 25 Jan 2012 09:27:28 +0000 Subject: [PATCH 100/637] Mention the release of Oracle Instant Client 64 bit which does not work on Lion. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15095 50811bd7-b8ce-0310-adc1-d9db26280581 --- README.macosx.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.macosx.txt b/README.macosx.txt index e854e4c6..57801dad 100644 --- a/README.macosx.txt +++ b/README.macosx.txt @@ -50,11 +50,12 @@ database server on your MacOSX box. See below (Instructions for ====================================================================== Instructions for 10.7.x (Lion) -Because the 64 bit instantclient is currently [incompatible with Lion][], -DBD::Oracle can only be compiled with the 32-bit instantclient libraries, and -therefore requires 32-bit Perl. If your Perl is 64-bit (which, by default, it -is on Mac OS X), you will not be able to build DBD::Oracle until an updated -64-bit instantclient is released. +Because the 64 bit instantclient (version 10gr2)is currently +[incompatible with Lion][], DBD::Oracle can only be compiled with the +32-bit instantclient libraries, and therefore requires 32-bit Perl. If +your Perl is 64-bit (which, by default, it is on Mac OS X), you will +not be able to build DBD::Oracle until an updated 64-bit instantclient +is released. [incompatible with Lion]: http://only4left.jpiwowar.com/2011/08/instant-client-osx-lion-32-bit-only/ From 946ab8afa11858aa2ffa10f260ba9a9a3083956c Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 31 Jan 2012 17:23:17 +0000 Subject: [PATCH 101/637] Patch from Rafael Kitover (Caelum) for RT 74544 NOTE, Yanick, didn't change Changes file as the one in trunk is not the same as the one you released as 1.38 - could you fix and add a changelog please. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15113 50811bd7-b8ce-0310-adc1-d9db26280581 --- Makefile.PL | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 878be69d..e59a97f1 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -994,14 +994,14 @@ sub win32_oracle_home { eval { require Win32::TieRegistry; $Win32::TieRegistry::Registry->Delimiter("/"); - $req_ok = 1; - $hkey = $Win32::TieRegistry::Registry->{"LMachine/SOFTWARE/Oracle/"}; + $hkey = $Win32::TieRegistry::Registry->{"LMachine/SOFTWARE/Oracle/"} + and $req_ok = 1; }; eval { # older name of Win32::TieRegistry require Tie::Registry; $Tie::Registry::Registry->Delimiter("/"); - $req_ok = 1; - $hkey = $Tie::Registry::Registry->{"LMachine/SOFTWARE/Oracle/"}; + $hkey = $Tie::Registry::Registry->{"LMachine/SOFTWARE/Oracle/"} + and $req_ok = 1; } unless $req_ok; eval { $default_home = $hkey->{ORACLE_HOME} || ''; From eca569a8c9cd4adcdfe950df6a1715ea07a59b64 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 31 Jan 2012 17:23:17 +0000 Subject: [PATCH 102/637] Patch from Rafael Kitover (Caelum) for RT 74544 NOTE, Yanick, didn't change Changes file as the one in trunk is not the same as the one you released as 1.38 - could you fix and add a changelog please. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15113 50811bd7-b8ce-0310-adc1-d9db26280581 --- Makefile.PL | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 878be69d..e59a97f1 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -994,14 +994,14 @@ sub win32_oracle_home { eval { require Win32::TieRegistry; $Win32::TieRegistry::Registry->Delimiter("/"); - $req_ok = 1; - $hkey = $Win32::TieRegistry::Registry->{"LMachine/SOFTWARE/Oracle/"}; + $hkey = $Win32::TieRegistry::Registry->{"LMachine/SOFTWARE/Oracle/"} + and $req_ok = 1; }; eval { # older name of Win32::TieRegistry require Tie::Registry; $Tie::Registry::Registry->Delimiter("/"); - $req_ok = 1; - $hkey = $Tie::Registry::Registry->{"LMachine/SOFTWARE/Oracle/"}; + $hkey = $Tie::Registry::Registry->{"LMachine/SOFTWARE/Oracle/"} + and $req_ok = 1; } unless $req_ok; eval { $default_home = $hkey->{ORACLE_HOME} || ''; From 62893c492b7fae98196ac40f9045090be1f2d30f Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 2 Feb 2012 21:05:22 +0000 Subject: [PATCH 103/637] sync Changes with release git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15118 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index a3166a43..d6e07d76 100644 --- a/Changes +++ b/Changes @@ -1,11 +1,15 @@ Revision history for DBD::Oracle -1.37_00 2012-01-09 +{{$NEXT}} [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED [RT73798] +1.38 2012-01-13 + + - promote 1.37_00 to official release + 1.37_00 2011-12-30 [ENHANCEMENTS] From 325fc7f2953bb936f38edd86545c15b1e8c7c001 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 2 Feb 2012 21:05:22 +0000 Subject: [PATCH 104/637] sync Changes with release git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15118 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index a3166a43..d6e07d76 100644 --- a/Changes +++ b/Changes @@ -1,11 +1,15 @@ Revision history for DBD::Oracle -1.37_00 2012-01-09 +{{$NEXT}} [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED [RT73798] +1.38 2012-01-13 + + - promote 1.37_00 to official release + 1.37_00 2011-12-30 [ENHANCEMENTS] From 6bf81cd55f83392af66b59c066d881e2b8934ecc Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 2 Feb 2012 21:05:27 +0000 Subject: [PATCH 105/637] add new Changes for last 2 commits git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15119 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Changes b/Changes index d6e07d76..4684b052 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,12 @@ Revision history for DBD::Oracle [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED [RT73798] + - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) + [RT74544] + + [DOCUMENTATION] + - Mention the release of Oracle Instant Client 64 bit which does not work + on Lion. (Martin J. Evans) 1.38 2012-01-13 From 249e39277b8cc9b259790d651abdb269b42265b1 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 2 Feb 2012 21:05:27 +0000 Subject: [PATCH 106/637] add new Changes for last 2 commits git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15119 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Changes b/Changes index d6e07d76..4684b052 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,12 @@ Revision history for DBD::Oracle [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED [RT73798] + - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) + [RT74544] + + [DOCUMENTATION] + - Mention the release of Oracle Instant Client 64 bit which does not work + on Lion. (Martin J. Evans) 1.38 2012-01-13 From 0c388047c63c5fbcaefebd54755c1ddba20f3cfb Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 25 Jan 2012 09:27:28 +0000 Subject: [PATCH 107/637] Mention the release of Oracle Instant Client 64 bit which does not work on Lion. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15095 50811bd7-b8ce-0310-adc1-d9db26280581 --- README.macosx.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.macosx.txt b/README.macosx.txt index e854e4c6..57801dad 100644 --- a/README.macosx.txt +++ b/README.macosx.txt @@ -50,11 +50,12 @@ database server on your MacOSX box. See below (Instructions for ====================================================================== Instructions for 10.7.x (Lion) -Because the 64 bit instantclient is currently [incompatible with Lion][], -DBD::Oracle can only be compiled with the 32-bit instantclient libraries, and -therefore requires 32-bit Perl. If your Perl is 64-bit (which, by default, it -is on Mac OS X), you will not be able to build DBD::Oracle until an updated -64-bit instantclient is released. +Because the 64 bit instantclient (version 10gr2)is currently +[incompatible with Lion][], DBD::Oracle can only be compiled with the +32-bit instantclient libraries, and therefore requires 32-bit Perl. If +your Perl is 64-bit (which, by default, it is on Mac OS X), you will +not be able to build DBD::Oracle until an updated 64-bit instantclient +is released. [incompatible with Lion]: http://only4left.jpiwowar.com/2011/08/instant-client-osx-lion-32-bit-only/ From 5589b0a47faf0dd557adbb99459b92e56ee47c89 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 31 Jan 2012 17:23:17 +0000 Subject: [PATCH 108/637] Patch from Rafael Kitover (Caelum) for RT 74544 NOTE, Yanick, didn't change Changes file as the one in trunk is not the same as the one you released as 1.38 - could you fix and add a changelog please. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15113 50811bd7-b8ce-0310-adc1-d9db26280581 --- Makefile.PL | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 878be69d..e59a97f1 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -994,14 +994,14 @@ sub win32_oracle_home { eval { require Win32::TieRegistry; $Win32::TieRegistry::Registry->Delimiter("/"); - $req_ok = 1; - $hkey = $Win32::TieRegistry::Registry->{"LMachine/SOFTWARE/Oracle/"}; + $hkey = $Win32::TieRegistry::Registry->{"LMachine/SOFTWARE/Oracle/"} + and $req_ok = 1; }; eval { # older name of Win32::TieRegistry require Tie::Registry; $Tie::Registry::Registry->Delimiter("/"); - $req_ok = 1; - $hkey = $Tie::Registry::Registry->{"LMachine/SOFTWARE/Oracle/"}; + $hkey = $Tie::Registry::Registry->{"LMachine/SOFTWARE/Oracle/"} + and $req_ok = 1; } unless $req_ok; eval { $default_home = $hkey->{ORACLE_HOME} || ''; From 3e16778e9775043647ae40dd3f38c11b3bfc3dc2 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 2 Feb 2012 16:13:15 -0500 Subject: [PATCH 109/637] svn-side changes --- Changes | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Changes b/Changes index d6e07d76..4684b052 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,12 @@ Revision history for DBD::Oracle [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED [RT73798] + - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) + [RT74544] + + [DOCUMENTATION] + - Mention the release of Oracle Instant Client 64 bit which does not work + on Lion. (Martin J. Evans) 1.38 2012-01-13 From c2013f1439d00ae2445835567a1ab75d339af773 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 2 Feb 2012 16:26:32 -0500 Subject: [PATCH 110/637] change for the modern /usr/bin/env perl --- examples/bind.pl | 2 +- examples/commit.pl | 2 +- examples/curref.pl | 2 +- examples/ex.pl | 2 +- examples/inserting_longs.pl | 2 +- examples/mktable.pl | 2 +- examples/oradump.pl | 2 +- examples/proc.pl | 2 +- examples/read_long_via_blob_read.pl | 2 +- examples/tabinfo.pl | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/bind.pl b/examples/bind.pl index 303d96be..1a4f71dd 100755 --- a/examples/bind.pl +++ b/examples/bind.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # bind.pl # diff --git a/examples/commit.pl b/examples/commit.pl index e6e0da3c..bef60655 100755 --- a/examples/commit.pl +++ b/examples/commit.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # commit.pl # diff --git a/examples/curref.pl b/examples/curref.pl index 5ecb0b32..3c464aa4 100755 --- a/examples/curref.pl +++ b/examples/curref.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # curref.pl - by Geoffrey Young # diff --git a/examples/ex.pl b/examples/ex.pl index 95ffa322..bd2016a4 100755 --- a/examples/ex.pl +++ b/examples/ex.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # Short example using bind_columns() to list a table's values use DBI; diff --git a/examples/inserting_longs.pl b/examples/inserting_longs.pl index 191a0c3d..056ce18a 100644 --- a/examples/inserting_longs.pl +++ b/examples/inserting_longs.pl @@ -1,4 +1,4 @@ -#!perl +#!/usr/bin/env perl use strict; use warnings; diff --git a/examples/mktable.pl b/examples/mktable.pl index 28d01007..570a16db 100755 --- a/examples/mktable.pl +++ b/examples/mktable.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # Sample DBI program to create a new table and load data into it. # # Author: Kevin Stock (original oraperl script) diff --git a/examples/oradump.pl b/examples/oradump.pl index 5477c569..5b1109cf 100755 --- a/examples/oradump.pl +++ b/examples/oradump.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # Dump the contents of an Oracle table into a set of insert statements. # Quoting is controlled by the datatypes of each column. (new with DBI) diff --git a/examples/proc.pl b/examples/proc.pl index a8a65a14..48dedec6 100755 --- a/examples/proc.pl +++ b/examples/proc.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # Short examples of procedure calls from Oracle.pm # These PL/SQL examples come from: Eric Bartley . diff --git a/examples/read_long_via_blob_read.pl b/examples/read_long_via_blob_read.pl index 70631d8d..d5a011ae 100644 --- a/examples/read_long_via_blob_read.pl +++ b/examples/read_long_via_blob_read.pl @@ -1,4 +1,4 @@ -#!perl +#!/usr/bin/env perl use strict; use warnings; diff --git a/examples/tabinfo.pl b/examples/tabinfo.pl index 307bd6b1..82c7f2ba 100755 --- a/examples/tabinfo.pl +++ b/examples/tabinfo.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # tabinfo # From 10047cf8d957890432b22dd0c353df111378384a Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 2 Feb 2012 16:27:52 -0500 Subject: [PATCH 111/637] record in Changes --- Changes | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changes b/Changes index 4684b052..dd8ddb41 100644 --- a/Changes +++ b/Changes @@ -12,6 +12,10 @@ Revision history for DBD::Oracle - Mention the release of Oracle Instant Client 64 bit which does not work on Lion. (Martin J. Evans) + [OTHERS] + - change the shebang line of examples to the more modern '/usr/bin/env perl' + [RT74001] + 1.38 2012-01-13 - promote 1.37_00 to official release From ae853defe36aa06a3de13c4bf69bbaab36409f44 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 2 Feb 2012 16:32:49 -0500 Subject: [PATCH 112/637] Build results of 10047cf (on master) --- .gitignore | 14 - Changes | 2 +- INSTALL | 44 + LICENSE | 377 ++ MANIFEST.SKIP | 32 - META.json | 97 + META.yml | 63 + README | 4338 ++++++++++++++- README.mkdn | 4228 +++++++++++++++ dist.ini | 22 - err_bind/err_bind_param_inout_overrun_bug.msg | 108 - err_bind/err_bindarrays.msg | 241 - err_bind/err_bindclobleak.msg | 58 - err_bind/err_bindnullhash.msg | 77 - err_bind/err_trailingblank.msg | 345 -- err_build/err_aix64.msg | 142 - err_build/err_hpux_ld.msg | 89 - err_build/err_hpuxsuccess.msg | 279 - err_build/err_instantclient.msg | 207 - err_build/err_makefileundef.msg | 87 - err_build/err_memleak.msg | 95 - err_build/err_solarisnotes.msg | 482 -- err_build/err_testfailnotable.msg | 97 - err_docs/err_trace.msg | 14 - err_lob/err_csr_clob.msg | 65 - err_lob/err_loblenwide.msg | 95 - err_lob/err_lobtesttblfail.msg | 208 - err_lob/err_nclob_form.msg | 189 - err_lob/err_nulllobsegv.msg | 93 - err_lob/err_tmplobfree.msg | 537 -- err_unicode/err_char.msg | 129 - err_unicode/err_twolongstr.msg | 1256 ----- err_unsorted/err_etherreal.msg | 90 - err_unsorted/err_memleak2.msg | 476 -- err_unsorted/err_multiora.msg | 470 -- err_unsorted/err_ora9ir2oci.msg | 27 - err_unsorted/err_ref_type.msg | 115 - err_unsorted/err_refcsr_rowcache.msg | 85 - err_unsorted/err_refcsr_slow.msg | 347 -- err_unsorted/err_slowcsr.msg | 316 -- err_unsorted/err_svrparse.msg | 4717 ----------------- err_unsorted/err_xml.msg | 118 - err_unsorted/err_xml2.msg | 700 --- err_unsorted/err_xmltypebindplsql.msg | 174 - lib/DBD/Oracle.pm | 109 +- lib/DBD/Oracle/GetInfo.pm | 47 + lib/DBD/Oracle/Object.pm | 95 +- lib/DBD/Oracle/Troubleshooting.pm | 48 +- t/000-report-versions.t | 446 ++ xt/changes.t | 8 - xt/manifest.t | 21 - xt/pod.t | 11 - 52 files changed, 9594 insertions(+), 12936 deletions(-) delete mode 100644 .gitignore create mode 100644 INSTALL create mode 100644 LICENSE delete mode 100644 MANIFEST.SKIP create mode 100644 META.json create mode 100644 META.yml create mode 100644 README.mkdn delete mode 100644 dist.ini delete mode 100644 err_bind/err_bind_param_inout_overrun_bug.msg delete mode 100644 err_bind/err_bindarrays.msg delete mode 100644 err_bind/err_bindclobleak.msg delete mode 100644 err_bind/err_bindnullhash.msg delete mode 100644 err_bind/err_trailingblank.msg delete mode 100644 err_build/err_aix64.msg delete mode 100644 err_build/err_hpux_ld.msg delete mode 100644 err_build/err_hpuxsuccess.msg delete mode 100644 err_build/err_instantclient.msg delete mode 100644 err_build/err_makefileundef.msg delete mode 100644 err_build/err_memleak.msg delete mode 100644 err_build/err_solarisnotes.msg delete mode 100644 err_build/err_testfailnotable.msg delete mode 100644 err_docs/err_trace.msg delete mode 100644 err_lob/err_csr_clob.msg delete mode 100644 err_lob/err_loblenwide.msg delete mode 100644 err_lob/err_lobtesttblfail.msg delete mode 100644 err_lob/err_nclob_form.msg delete mode 100644 err_lob/err_nulllobsegv.msg delete mode 100644 err_lob/err_tmplobfree.msg delete mode 100644 err_unicode/err_char.msg delete mode 100644 err_unicode/err_twolongstr.msg delete mode 100644 err_unsorted/err_etherreal.msg delete mode 100644 err_unsorted/err_memleak2.msg delete mode 100644 err_unsorted/err_multiora.msg delete mode 100644 err_unsorted/err_ora9ir2oci.msg delete mode 100644 err_unsorted/err_ref_type.msg delete mode 100644 err_unsorted/err_refcsr_rowcache.msg delete mode 100644 err_unsorted/err_refcsr_slow.msg delete mode 100644 err_unsorted/err_slowcsr.msg delete mode 100644 err_unsorted/err_svrparse.msg delete mode 100644 err_unsorted/err_xml.msg delete mode 100644 err_unsorted/err_xml2.msg delete mode 100644 err_unsorted/err_xmltypebindplsql.msg create mode 100644 t/000-report-versions.t delete mode 100644 xt/changes.t delete mode 100644 xt/manifest.t delete mode 100644 xt/pod.t diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 15e927c8..00000000 --- a/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -pm_to_blib -MYMETA.yml -Makefile -Makefile.old -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -blib -MYMETA.json -dbdimp.o -mk.pm -oci8.o -DBD-Oracle* diff --git a/Changes b/Changes index dd8ddb41..7a3203c6 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.38 2012-02-02 [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..b5ab17a0 --- /dev/null +++ b/INSTALL @@ -0,0 +1,44 @@ + +This is the Perl distribution DBD-Oracle. + +Installing DBD-Oracle is straightforward. + +## Installation with cpanm + +If you have cpanm, you only need one line: + + % cpanm DBD::Oracle + +If you are installing into a system-wide directory, you may need to pass the +"-S" flag to cpanm, which uses sudo to install the module: + + % cpanm -S DBD::Oracle + +## Installing with the CPAN shell + +Alternatively, if your CPAN shell is set up, you should just be able to do: + + % cpan DBD::Oracle + +## Manual installation + +As a last resort, you can manually install it. Download the tarball, untar it, +then build it: + + % perl Makefile.PL + % make && make test + +Then install it: + + % make install + +If you are installing into a system-wide directory, you may need to run: + + % sudo make install + +## Documentation + +DBD-Oracle documentation is available as POD. +You can run perldoc from a shell to read the documentation: + + % perldoc DBD::Oracle diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..a6a371c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,377 @@ +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +Terms of the Perl programming language system itself + +a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or +b) the "Artistic License" + +--- The GNU General Public License, Version 1, February 1989 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The GNU General Public License, Version 1, February 1989 + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! + + +--- The Artistic License 1.0 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The Artistic License 1.0 + +The Artistic License + +Preamble + +The intent of this document is to state the conditions under which a Package +may be copied, such that the Copyright Holder maintains some semblance of +artistic control over the development of the package, while giving the users of +the package the right to use and distribute the Package in a more-or-less +customary fashion, plus the right to make reasonable modifications. + +Definitions: + + - "Package" refers to the collection of files distributed by the Copyright + Holder, and derivatives of that collection of files created through + textual modification. + - "Standard Version" refers to such a Package if it has not been modified, + or has been modified in accordance with the wishes of the Copyright + Holder. + - "Copyright Holder" is whoever is named in the copyright or copyrights for + the package. + - "You" is you, if you're thinking about copying or distributing this Package. + - "Reasonable copying fee" is whatever you can justify on the basis of media + cost, duplication charges, time of people involved, and so on. (You will + not be required to justify it to the Copyright Holder, but only to the + computing community at large as a market that must bear the fee.) + - "Freely Available" means that no fee is charged for the item itself, though + there may be fees involved in handling the item. It also means that + recipients of the item may redistribute it under the same conditions they + received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications derived +from the Public Domain or from the Copyright Holder. A Package modified in such +a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided that +you insert a prominent notice in each changed file stating how and when you +changed that file, and provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major archive site + such as ftp.uu.net, or by allowing the Copyright Holder to include your + modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict with + standard executables, which must also be provided, and provide a separate + manual page for each non-standard executable that clearly documents how it + differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or executable +form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where to + get the Standard Version. + + b) accompany the distribution with the machine-readable source of the Package + with your modifications. + + c) accompany any non-standard executables with their corresponding Standard + Version executables, giving the non-standard executables non-standard + names, and clearly documenting the differences in manual pages (or + equivalent), together with instructions on where to get the Standard + Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. You +may not charge a fee for this Package itself. However, you may distribute this +Package in aggregate with other (possibly commercial) programs as part of a +larger (possibly commercial) software distribution provided that you do not +advertise this Package as a product of your own. + +6. The scripts and library files supplied as input to or produced as output +from the programs of this Package do not automatically fall under the copyright +of this Package, but belong to whomever generated them, and may be sold +commercially, and may be aggregated with this Package. + +7. C or perl subroutines supplied by you and linked into this Package shall not +be considered part of this Package. + +8. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +The End + diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP deleted file mode 100644 index c7db4c66..00000000 --- a/MANIFEST.SKIP +++ /dev/null @@ -1,32 +0,0 @@ -^DBD-Oracle-.* -\.svn\b -\.orig$ -\..*.swp$ -^.pure -^DIST/ -^MANIFEST\. -^Makefile$ -^blib/ -^csr/ -^err[/_] -^old/ -^info/ -^oci8/ -^oracle/ -^tags$ -~$ -^\.git -^xt -dbdimp.o -Makefile.old -mk.pm -MYMETA.json -MYMETA.yml -oci8.o -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -pm_to_blib - -dist.ini diff --git a/META.json b/META.json new file mode 100644 index 00000000..3af05f40 --- /dev/null +++ b/META.json @@ -0,0 +1,97 @@ +{ + "abstract" : "Oracle database driver for the DBI module", + "author" : [ + "Tim Bunce ", + "John Scoles", + "Yanick Champoux " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "DBD-Oracle", + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "6.30" + } + }, + "runtime" : { + "requires" : { + "DBI" : 0, + "DynaLoader" : 0, + "Exporter" : 0, + "perl" : "5.006", + "strict" : 0, + "warnings" : 0 + } + }, + "test" : { + "requires" : { + "Carp" : 0, + "Config" : 0, + "Data::Dumper" : 0, + "Devel::Peek" : 0, + "Encode" : 0, + "Math::BigInt" : 0, + "Oraperl" : 0, + "Scalar::Util" : 0, + "Test::More" : "0.94", + "Thread::Semaphore" : 0, + "utf8" : 0, + "vars" : 0 + } + } + }, + "provides" : { + "DBD::Oracle" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::GetInfo" : { + "file" : "lib/DBD/Oracle/GetInfo.pm", + "version" : "1.38" + }, + "DBD::Oracle::Object" : { + "file" : "lib/DBD/Oracle/Object.pm", + "version" : "1.38" + }, + "DBD::Oracle::Troubleshooting" : { + "file" : "lib/DBD/Oracle/Troubleshooting.pm", + "version" : "1.38" + }, + "DBD::Oracle::db" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::dr" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::st" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "mailto" : "bug-dbd-oracle at rt.cpan.org", + "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle" + }, + "homepage" : "http://search.cpan.org/dist/DBD-Oracle/", + "repository" : { + "type" : "git", + "url" : "git://github.com/yanick/DBD-Oracle.git", + "web" : "http://github.com/yanick/DBD-Oracle/tree" + } + }, + "version" : "1.38", + "x_authority" : "cpan:PYTHIAN" +} + diff --git a/META.yml b/META.yml new file mode 100644 index 00000000..c1c09bd4 --- /dev/null +++ b/META.yml @@ -0,0 +1,63 @@ +--- +abstract: 'Oracle database driver for the DBI module' +author: + - 'Tim Bunce ' + - 'John Scoles' + - 'Yanick Champoux ' +build_requires: + Carp: 0 + Config: 0 + Data::Dumper: 0 + Devel::Peek: 0 + Encode: 0 + Math::BigInt: 0 + Oraperl: 0 + Scalar::Util: 0 + Test::More: 0.94 + Thread::Semaphore: 0 + utf8: 0 + vars: 0 +configure_requires: + ExtUtils::MakeMaker: 6.30 +dynamic_config: 0 +generated_by: 'Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: DBD-Oracle +provides: + DBD::Oracle: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::GetInfo: + file: lib/DBD/Oracle/GetInfo.pm + version: 1.38 + DBD::Oracle::Object: + file: lib/DBD/Oracle/Object.pm + version: 1.38 + DBD::Oracle::Troubleshooting: + file: lib/DBD/Oracle/Troubleshooting.pm + version: 1.38 + DBD::Oracle::db: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::dr: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::st: + file: lib/DBD/Oracle.pm + version: 1.38 +requires: + DBI: 0 + DynaLoader: 0 + Exporter: 0 + perl: 5.006 + strict: 0 + warnings: 0 +resources: + bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle + homepage: http://search.cpan.org/dist/DBD-Oracle/ + repository: git://github.com/yanick/DBD-Oracle.git +version: 1.38 +x_authority: cpan:PYTHIAN diff --git a/README b/README index fd2b28aa..bf8f7b60 100644 --- a/README +++ b/README @@ -1,301 +1,4183 @@ +NAME + DBD::Oracle - Oracle database driver for the DBI module -DBD::Oracle -- an Oracle interface for Perl 5. +VERSION + version 1.38 - Copyright (c) 1994-2006 Tim Bunce, Ireland. +SYNOPSIS + use DBI; - See the COPYRIGHT section in the Oracle.pm file for terms. - See also the MAINTAINER section in the Oracle.pm + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); - PLEASE READ THE ENTIRE README FILE CAREFULLY ! + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); - AND THEN READ ANY README.* FILES RELEVANT TO YOUR PLATFORM: + # See the DBI module documentation for full details - README.aix.txt - AIX - README.hpux.txt - HP-UX - README.java.txt - Java/thread problem on Solaris - README.macosx.txt - Mac OS/X - README.win32.txt - MS Windows - README.wingcc.txt - MS Windows using GCC - README.* - see if there's a file for your platform + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); - You may find these useful +DESCRIPTION + DBD::Oracle is a Perl module which works with the DBI module to provide + access to Oracle databases. - README.help.txt - Help and hints on build problems - README.sec.txt - Oracle security issues to be aware of - README.login.txt - Help on how to connect to Oracle - README.longs.txt - Help on handling LONGs - README.clients.txt - What Oracle client files you need installed + This documentation describes driver specific behaviour and restrictions. + It is not supposed to be used as the only reference for the user. In any + case consult the DBI documentation first! +CONSTANTS + :ora_session_modes + ORA_SYSDBA ORA_SYSOPER ORA_SYSASM -*** QUICK START GUIDE: + :ora_types + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN - The DBI requires one or more 'driver' modules to talk to databases. - Fetch, build and install the DBI module as per its README file. - You may then delete its source directory tree since it's no longer needed. - Use the 'perldoc DBI' command to read the DBI documentation. + SQLCS_IMPLICIT + SQLCS_NCHAR + SQLCS_IMPLICIT and SQLCS_NCHAR are *character set form* values. See + notes about Unicode elsewhere in this document. - Fetch this DBD::Oracle driver module and unpack it. - Follow the guidelines in this README file carefully. + SQLT_INT + SQLT_FLT + These types are used only internally, and may be specified as + internal bind type for ORA_NUMBER_TABLE. See notes about + ORA_NUMBER_TABLE elsewhere in this document + ORA_OCI + Oracle doesn't provide a formal API for determining the exact + version number of the OCI client library used, so DBD::Oracle has to + go digging (and sometimes has to more or less guess). The ORA_OCI + constant holds the result of that process. -*** *BEFORE* BUILDING, TESTING AND INSTALLING DBD::Oracle: + In string context ORA_OCI returns the full "A.B.C.D" version string. - Build, test and install Perl 5 (at least 5.6.1) - It is very important to TEST it and INSTALL it! + In numeric context ORA_OCI returns the major.minor version number + (8.1, 9.2, 10.0 etc). But note that version numbers are not actually + floating point and so if Oracle ever makes a release that has a two + digit minor version, such as 9.10 it will have a lower numeric value + than the preceding 9.9 release. So use with care. - Build, test and install the DBI module (at least DBI 1.51). - It is very important to TEST it and INSTALL it! + The contents and format of ORA_OCI are subject to change (it may, + for example, become a *version object* in later releases). I + recommend that you avoid checking for exact values. - Remember to *read* the DBI README file and this one CAREFULLY! + :ora_fetch_orient + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE - Install enough Oracle software to enable DBD::Oracle to build. + These constants are used to set the orientation of a fetch on a + scrollable cursor. - For Oracle Instant Client: that means install the following packages: - * The "Basic" package for the essential Oracle libraries. - * The "SDK" package for the headers and makefile. - * The "SQL*Plus" component is optional, but will help you check - your configuration and DBD::Oracle determine your Oracle version. + :ora_exe_modes + OCI_STMT_SCROLLABLE_READONLY - For full Oracle installs: that usually includes Pro*C and SQL*Net. - (That's not very specific because it varies between Oracle releases.). - As of release 1.22 support of Oracle clients before 9 was dropped. - The main reason for this is that next few versions of DBD::Oracle will introduce a number of new features - whicht will required a great deal of extra coding to make the OCI 8 work. - As well it is getting harder to find an Oracle client 8 to test against as well - Oracle no longer supports clients before 9. + :ora_fail_over + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL - The ORACLE_HOME environment variable must point to the Oracle Home - used to create DBD::Oracle. (Not essential under MS Windows). +DBI CLASS METHODS + connect + This method creates a database handle by connecting to a database, and + is the DBI equivalent of the "new" method. To open a connection to an + Oracle database you need to specify a database connection string (URL), + username and password. -*** MOST IMPORTANTLY: + The connection string is always of the form: "dbi:Oracle:" There are several ways to identify a database: - Make sure Oracle is working and you can use the Oracle sqlplus - command to talk to the database from the machine you - want to build DBD::Oracle on. This often involves setting - environment variables like PATH, LD_LIBRARY_PATH, TWO_TASK etc. - Consult Oracle documentation for more details. + 1 If the database is local, specifying the SID or service name will be + enough. - Only once you can connect to Oracle using sqlplus - should you try building and testing DBD::Oracle. + 2 If the database is defined in a TNSNAMES.ORA file, you can use the + service name given in the file -*** BUILDING: + 3 To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, + of the form: //host[:port][/service_name] -Execute: + If port name is not specified, 1521 is the default. If service name is + not specified, the hostname will be used as a service name. - perl Makefile.PL # use a perl that's in your PATH + The following examples show several ways a connection can be created: -Use the perl that is first on your PATH. Then execute: + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - make + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); -If you get an error like "make: not found" you need to find the -directory that has the make command installed in it (e.g. /usr/ccs/bin -on Solaris) and add that to your PATH environment variable. + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); -Don't worry about most warnings when make runs, specifically ones like -"end-of-loop code not reached", "... due to prototype", -"cast increases required alignment of target type", etc. + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); -If you have problems see the 'IF YOU HAVE PROBLEMS' section below. -If it builds without error you should then run 'make test'. For the -main tests to work they must be able to connect to an Oracle database. + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); -The tests default to using a DSN of "dbi:Oracle:" which means you'll be -connected to the default database based on your TWO_TASK or ORACLE_SID -environment variables. This default can be altered either by defining the -ORACLE_DSN environment variable or the DBI_DSN environment variable. -See the oracle_test_dsn() sub in t/nchar_test_lib.pl + OS authentication + To connect to a local database with a user which has been set up to + authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): -The supplied tests will connect to the database using the value of the -ORACLE_USERID environment variable to supply the username/password. -So you should set that to a valid user (e.g. 'scott/tiger') and ensure that -this user has sufficient privileges to create, insert into, select from and -drop a table, is also able to create, call and drop a procedure and is able to select from -systemtables like 'v$sessions'. Using 'system/manager' might work but is not -recommended! See also + $dbh = DBI->connect('dbi:Oracle:','/',''); -README.login.txt. + Note the lack of a connection name (use the ORACLE_SID environment + variable). If an explicit SID is used you will probably get an ORA-01004 + error. - make test + That only works for local databases. (Authentication to remote Oracle + databases using your Unix login name without a password is possible but + it is not secure and not recommended so not documented here. -If the all the formal tests pass then, finally, run: + Oracle Environment Variables + To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME + environment variable should be set correctly. In general, the value used + should match the version of Oracle that was used to build DBD::Oracle. + If using dynamic linking then ORACLE_HOME should match the version of + Oracle that will be used to load in the Oracle client libraries (via + LD_LIBRARY_PATH, ldconfig, or similar on Unix). - make install + Oracle can use two environment variables to specify default connections: + ORACLE_SID and TWO_TASK. + To use them, specify either a local SID or service name, or a service + name that is specified in the TNSNAMES.ORA file. -*** IF YOU HAVE PROBLEMS: + Note that if you have *both* local and remote databases, and you have + ORACLE_SID *and* TWO_TASK set, and you don't specify a fully qualified + connect string on the command line, TWO_TASK takes precedence over + ORACLE_SID (i.e. you get connected to remote system). -Make sure you are using a recent perl (5.6.1 or later) and make -sure it's on your PATH so you can say 'perl Makefile.PL' and not -'/path/to/perl Makefile.PL'. + It is highly recommended not to rely on environment variables and to + always explicitly specify the SID in the connection string. This can + prevent serious mistakes such as dropping a schema in the wrong + database, and generally makes debugging and troubleshooting easier. -If you get compiler errors refering to Perl's own header files -(.../CORE/*.h) then there is something wrong with your installation. -It is important to use a Perl that was built on the system you are using. -It's also important to use the same compiler that was used to build the -Perl you are using. + Also remember that depending on the operating system you are using the + differing "ORACLE" environment variables may be case sensitive, so if + you are not connecting as you should double check the case of both the + variable and its value. -If you have build/link or core dump problems try: - perl Makefile.PL -p -or - perl Makefile.PL -nob -If it helps then please let me know (and please include a copy -of the log from the failed default build, the log from the build that -worked, plus the output of the "perl -V" command). + Timezones + If the query is run through SQL*Net (mostly queries that are executed on + remote servers), Oracle will return the time zone based on the setting + of the UNIX environment variable "TZ" for the user who started the + listener. -Do not hand edit the generated Makefile unless you are completely sure -you understand the implications! Always try to make changes via the -Makefile.PL command line and/or editing the Makefile.PL. -You should not need to make any changes. If you do please let us -know so that I can try to make it automatic in a later release. + If the query is run locally, Oracle will return the time zone based on + the "TZ" environment variable setting of the user running the query. -If you just can't login or login takes a long time then read -README.login.txt + With local queries, you can change the time zone for a particular user + by simply changing the setting of "TZ". To check the current setting, + issue the UNIX "date" command. -If you have linking problems (errors related to libraries or functions) -then you could try forcing a 'static' build using: + Oracle DRCP + DBD::Oracle supports DRCP (Database Resident Connection Pool) so if you + have an 11.2 database and DRCP is enabled you can direct all of your + connections to it by adding ':POOLED' to the SID or setting a connection + attribute of ora_drcp, or set the SERVER=POOLED when using a TNSENTRY + style connection or even by setting an environment variable ORA_DRCP. + All of which are demonstrated below; - make realclean - perl Makefile.PL LINKTYPE=static - make - make perl (you'll need to use and install _this_ new perl binary) - make test - make -f Makefile.aperl inst_perl MAP_TARGET=perl (install new perl) - make install (install DBD::Oracle) + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') -But that's not recommended these days. + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') ->>> Also carefully read the README.help.txt file which is full of useful ->>> tips and workarounds for various problems of various systems. + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) -*** HOW TO REPORT PROBLEMS + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') -This software is supported via the dbi-users@perl.org mailing list. -(You don't need to subscribe to the list in order to post.) + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") -Please do NOT post problems to comp.lang.perl.*, perl5-porters@perl.org, -http://www.cpanforum.com/dist/DBD-Oracle, or google groups etc. + if the ORA_DRCP environment variable is set then just this -If you're *sure* the problem is a bug then you can post a bug report -to http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle -Problem reports that don't include sufficient detail (including the -information listed below and how to reproduce the problem) -are unlikely to get resolved. + $dbh = DBI->connect('dbi:Oracle:DB','username','password') -For more information and to keep informed about progress you can join the -mailing list. Send a message to dbi-users-help@perl.org for more information. + You can find a white paper on setting up DRCP and its advantages at + . -Please post details of any problems (or changes you needed to make) to -dbi-users@perl.org. - - -** IT IS IMPORTANT TO INCLUDE *ALL* THE FOLLOWING INFORMATION: + Please note that DRCP support in DBD::Oracle is relatively new so the + mechanics or its implementation are subject to change. -1. A complete log of all steps of the build, e.g.: + TAF (Transparent Application Failover) + Transparent Application Failover (TAF) is the feature in OCI that allows + for clients to automatically reconnect to an instance in the event of a + failure of the instance. The reconnect happens automatically from within + the OCI (Oracle Call Interface) library. DBD::Oracle now supports a + callback function that will fire when a TAF event takes place. The main + use of the callback is to give your program the opportunity to inform + the user that a failover is taking place. - (do a make realclean first) - perl Makefile.PL - make - make test + You will have to set up TAF on your instance before you can use this + callback. You can test your instance to see if you can use TAF callback + with - Make sure to include the 'stderr' output. The best way to do this is - to use the "script" command (man script). If that's not available - then "command > command.log 2>&1" (assuming you're not using csh). - The "2>&1" is required (after the stdout redirect) to redirect stderr - to the same place. + $dbh->ora_can_taf(); - If a test fails then also include the output of: + If you try to set up a callback without it being enabled DBD::Oracle + will croak. - perl -Mblib t/.t + It is outside the scope of this documents to go through all of the + possible TAF situations you might want to set up but here is a simple + example: -2. Full details of which version of Oracle client and server you're using - (if it wasn't automatically found and printed by "perl Makefile.PL") + The TNS entry for the instance has had the following added to the + CONNECT_DATA section -3. The output of perl -V (that's a capital V, not lowercase) + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) -4. If you get errors like "undefined symbol", "symbol not found", - "undefined reference", "Text relocation remains" or any similar - error then include the output of "perl Makefile.PL -s XXX" - where XXX is the name of one of the symbols. - Please don't send the entire output of this command, - just any obviously 'interesting' parts (if there are any). - See also the LINKTYPE=static notes above. + You will also have to create your own perl function that will be called + from the client. You can name it anything you want and it will always be + passed two parameters, the failover event value and the failover type. + You can also set a sleep value in case of failover error and the OCI + client will sleep for the specified seconds before it attempts another + event. -5. If you get a core dump, rebuild DBD::Oracle with debugging - enabled by executing: perl Makefile.PL -g (note the -g option) - then rerun the code to get a new core dump file, finally use a - debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. - NOTE: I may not be able to help you much without a stack trace! - It is worth fetching and building the GNU GDB debugger (>=4.15) if - you don't have a good debugger on your system. If desperate try: - make perl; ./perl script; echo '$c' | adb ./perl core - Also see the Devel::CoreStack module on CPAN. - -6. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun - make test after setting the environment variable PERL_DL_DEBUG to 2. - -7. If your installation succeeds, but your script does not behave - as you expect, the problem may be on your end. Before - sending to dbi-users, try writing a *small*, easy to use test case - to reproduce your problem. Also, use the DBI->trace method to - trace your database calls. + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants -It is important to check that you are using the latest version before -posting. If you're not then you're *very* likely to be told "upgrade to -the latest". You would do yourself a favour by upgrading beforehand. + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); -Try to help yourself first, then try to help others help you by following -these guidelines carefully. And remember, please don't mail developers -directly - use the dbi-users mailing list. + #create the perl TAF event function -Regards, -Tim. + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ -=============================================================================== -Examples and other info: + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); -README.help.txt -- READ IT FIRST IF YOU HAVE ANY PROBLEMS -README.win32.txt -- building DBD::Oracle under MS Windows -README.wingcc.txt -- building DBD::Oracle under MS Windows with gcc -README.macosx.txt -- building DBD::Oracle under MacOS X -README.clients.txt -- building/using DBD::Oracle on minimally configured systems -README.login.txt -- help for login problems -README.longs.txt -- examples dealing with LONG types (blobs) + } + return 0; + } -DBI 'home page': http://dbi.perl.org + The TAF types are as follows -Old archive site for Perl DB information: - ftp://ftp.demon.co.uk/pub/perl/db/ -Mailing list archive: /DBI/perldb-interest/ -Perl 4 Oraperl (v2.4) /perl4/oraperl/ - -Jeff Stander's stuff stands out for Oraperl: -Directories of interest might be - /pub/Oracle/sources - /pub/Oracle/sources/jstander - /pub/Oracle/sources/jstander/distrib - /pub/Oracle/sources/jstander/tsmlib - /pub/Oracle/sources/jstander/wdbex - /pub/Oracle/sources/web/scripts - /pub/Oracle/sources/dba - /pub/Oracle/sources/dba/imp2sql7 - /pub/Oracle/sources/Lonnroth - /pub/Oracle/sources/harrison - -http://www.bf.rmit.edu.au/~orafaq/perlish.html -ftp://ftp.bf.rmit.edu.au/pub/perl/db -ftp://ftp.bf.rmit.edu.au/pub/Oracle -ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources -ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip - -DBI and DBD::Oracle are very portable. If Perl and Oracle run on a platform -then the chances are that DBD::Oracle will as well. - -=============================================================================== - -See the large README.help.txt file for lots of hints and advice -about building and runtime issues. - -End. + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + + The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + + Connect Attributes + ora_ncs_buff_mtpl + You can customize the size of the buffer when selecting LOBs with the + built-in AUTO Lob. The default value is 4 which is probably excessive + for most situations but is needed for backward compatibility. If you not + converting between a NCS on the DB and the Client then you might want to + set this to 1 to reduce memory usage. + + This value can also be specified with the "ORA_DBD_NCS_BUFFER" + environment variable in which case it sets the value at the connect + stage. + + ora_drcp + For Oracle 11.2 or greater. + + Set to *1* to enable DRCP. Can also be set via the "ORA_DRCP" + environment variable. + + ora_drcp_class + If you are using DRCP, you can set a CONNECTION_CLASS for your pools as + well. As sessions from a DRCP cannot be shared by users, you can use + this setting to identify the same user across different applications. + OCI will ensure that sessions belonging to a 'class' are not shared + outside the class'. + + The values for ora_drcp_class cannot contain a '*' and must be less than + 1024 characters. + + This value can be also be specified with the "ORA_DRCP_CLASS" + environment variable. + + ora_drcp_min + This optional value specifies the minimum number of sessions that are + initially opened. New sessions are only opened after this value has been + reached. + + The default value is 4 and any value above 0 is valid. + + Generally, it should be set to the number of concurrent statements the + application is planning or expecting to run. + + This value can also be specified with the "ORA_DRCP_MIN" environment + variable. + + ora_drcp_max + This optional value specifies the maximum number of sessions that can be + open at one time. Once reached no more sessions can be opened until one + becomes free. The default value is 40 and any value above 1 is valid. + You should not set this value lower than ora_drcp_min as that will just + waste resources. + + This value can also be specified with the "ORA_DRCP_MAX" environment + variable. + + ora_drcp_incr + This optional value specifies the next increment for sessions to be + started if the current number of sessions are less than ora_drcp_max. + The default value is 2 and any value above 0 is valid as long as the + value of ora_drcp_min + ora_drcp_incr is not greater than ora_drcp_max. + + This value can also be specified with the "ORA_DRCP_INCR" environment + variable. + + ora_taf + If your Oracle instance has been configured to use TAF events you can + enable the TAF callback by setting this option to any *true* value. + + ora_taf_function + The name of the Perl subroutine that will be called from OCI when a TAF + event occurs. You must supply a perl function to use the callback and it + will always receive two parameters, the failover event value and the + failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + + ora_taf_sleep + The amount of time in seconds the OCI client will sleep between + attempting successive failover events when the event is OCI_FO_ERROR. + + ora_session_mode + The ora_session_mode attribute can be used to connect with SYSDBA, + SYSOPER and ORA_SYSASM authorization. The ORA_SYSDBA, ORA_SYSOPER and + ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + + This is one case where setting ORACLE_SID may be useful since connecting + as SYSDBA or SYSOPER via SQL*Net is frequently disabled for security + reasons. + + Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + + It has been reported that this only works if $dsn does not contain a SID + so that Oracle then uses the value of ORACLE_SID (not TWO_TASK) + environment variable to connect to a local instance. Also the username + and password should be empty, and the user executing the script needs to + be part of the dba group or osdba group. + + ora_oratab_orahome + Passing a true value for the ora_oratab_orahome attribute will make + DBD::Oracle change $ENV{ORACLE_HOME} to make the Oracle home directory + that specified in the "/etc/oratab" file *if* the database to connect to + is specified as a SID that exists in the oratab file, and DBD::Oracle + was built to use the Oracle 7 OCI API (not Oracle 8+). + + ora_module_name + After connecting to the database the value of this attribute is passed + to the SET_MODULE() function in the "DBMS_APPLICATION_INFO" PL/SQL + package. This can be used to identify the application to the DBA for + monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + + The maximum size is 48 bytes. + + ora_driver_name + For 11g and later you can now set the name of the driver layer using + OCI. Perl, Perl5, ApachePerl so on. Names starting with "ORA" are + reserved. You can enter up to 8 characters. If none is enter then this + will default to DBDOxxxx where xxxx is the current version number. This + value can be retrieved on the server side using V$SESSION_CONNECT_INFO + or GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + + ora_client_info + Allows you to add any value (up to 64 bytes) to your session and it can + be retrieved on the server side from the "V$SESSION"a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + + ora_client_identifier + Allows you to specify the user identifier in the session handle. + + Most useful for web applications as it can pass in the session user name + which might be different to the connection user name. Can be up to 64 + bytes long but do not to include the password for security reasons and + the first character of the identifier should not be ':'. This value can + be retrieved on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + + ora_action + Allows you to specify any string up to 32 bytes which may be retrieved + on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + + ora_dbh_share + Requires at least Perl 5.8.0 compiled with ithreads. + + Allows you to share database connections between threads. The first + connect will make the connection, all following calls to connect with + the same ora_dbh_share attribute will use the same database connection. + The value must be a reference to a already shared scalar which is + initialized to an empty string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + + ora_envhp + The first time a connection is made a new OCI 'environment' is created + by DBD::Oracle and stored in the driver handle. Subsequent connects + reuse (share) that same OCI environment by default. + + The ora_envhp attribute can be used to disable the reuse of the OCI + environment from a previous connect. If the value is 0 then a new OCI + environment is allocated and used for this connection. + + The OCI environment holds information about the client side context, + such as the local NLS environment. By altering %ENV and setting + ora_envhp to 0 you can create connections with different NLS settings. + This is most useful for testing. + + ora_charset, ora_ncharset + For oracle versions >= 9.2 you can specify the client charset and + ncharset with the ora_charset and ora_ncharset attributes. You still + need to pass "ora_envhp = 0" for all but the first connect. + + These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + + ora_verbose + Use this value to enable DBD::Oracle only tracing. Simply either set the + ora_verbose attribute on the connect() method to the trace level you + desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + + or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + + In both cases the DBD::Oracle trace level is set to 6, which is the + highest level tracing most of the calls to OCI. + + ora_oci_success_warn + Use this value to print otherwise silent OCI warnings that may happen + when an execute or fetch returns "Success With Info" or when you want to + tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + + ora_objects + Use this value to enable extended embedded oracle objects mode. In + extended: + + 1 Embedded objects are returned as instance + (including type-name etc.) instead of simple ARRAY. + + 2 Determine object type for each instance. All object attributes are + returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + + ora_ph_type + The default placeholder datatype for the database session. The "TYPE" or + "ora_type" attributes to "bind_param" in DBI and "bind_param_inout" in + DBI override the datatype for individual placeholders. The most frequent + reason for using this attribute is to permit trailing spaces in values + passed by placeholders. + + Constants for the values allowed for this attribute can be imported + using + + use DBD::Oracle qw(:ora_types); + + Only the following values are permitted for this attribute. + + ORA_VARCHAR2 + Oracle clients using OCI 8 will strip trailing spaces and allow + embedded \0 bytes. Oracle clients using OCI 9.2 do not strip + trailing spaces and allow embedded \0 bytes. This is the normal + default placeholder type. + + ORA_STRING + Do not strip trailing spaces and end the string at the first \0. + + ORA_CHAR + Do not strip trailing spaces and allow embedded \0. Force + 'blank-padded comparison semantics'. + + For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + + Will pad bloggs out to 8 characters and return the username. + + ora_parse_error_offset + If the previous error was from a failed "prepare" due to a syntax error, + this attribute gives the offset into the "Statement" attribute where the + error was found. + + ora_array_chunk_size + Due to OCI limitations, DBD::Oracle needs to buffer up rows of bind + values in its "execute_for_fetch" implementation. This attribute sets + the number of rows to buffer at a time (default value is 1000). + + The "execute_for_fetch" function will collect (at most) this many rows + in an array, send them off to the DB for execution, then go back to + collect the next chunk of rows and so on. This attribute can be used to + limit or extend the number of rows processed at a time. + + Note that this attribute also applies to "execute_array", since that + method is implemented using "execute_for_fetch". + + ora_connect_with_default_signals + Sometimes the Oracle client seems to change some of the signal handlers + of the process during the connect phase. For instance, some users have + observed Perl's default $SIG{INT} handler being ignored after connecting + to an Oracle database. If this causes problems in your application, set + this attribute to an array reference of signals you would like to be + localized during the connect process. Once the connect is complete, the + signal handlers should be returned to their previous state. + + For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + + NOTE disabling the signal handlers the OCI library sets up may affect + functionality in the OCI library. + + NOTE If you are using connect_cached then the above example will lead to + DBI thinking each connection is different as an anonymous array + reference is being used. To avoid this when using connect_cached you are + advised to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + + In more recent Perl versions you could possibly make use of new state + variables. + + connect_cached + Implemented by DBI, no driver-specific impact. Please note that + connect_cached as not been tested with DRCP. + + data_sources + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + + Returns a list of available databases. You will have to set either the + 'ORACLE_HOME' or 'TNS_ADMIN' environment value to retrieve this list. It + will read these values from TNSNAMES.ORA file entries. + +METHODS COMMON TO ALL HANDLES + For all of the methods below, $h can be either a database handle ($dbh) + or a statement handle ($sth). Note that *$dbh* and *$sth* can be + replaced with any variable name you choose: these are just the names + most often used. Another common variable used in this documentation is + $*rv*, which stands for "return value". + + err + $rv = $h->err; + + Returns the error code from the last method called. + + errstr + $str = $h->errstr; + + Returns the last error that was reported by Oracle. Starting with + "ORA-00000" code followed by the error message. + + state + $str = $h->state; + + Oracle hasn't supported SQLSTATE since the early versions OCI. It will + return empty when the command succeeds and 'S1000' (General Error) for + all other errors. + + While this method can be called as either "$sth->state" or + "$dbh->state", it is usually clearer to always use "$dbh->state". + + trace + Implemented by DBI, no driver-specific impact. + + trace_msg + Implemented by DBI, no driver-specific impact. + + parse_trace_flag and parse_trace_flags + Implemented by DBI, no driver-specific impact. + + func + DBD::Oracle uses the "func" method to support a variety of functions. + + Private database handle functions + Some of these functions are called through the method func() which is + described in the DBI documentation. Any function that begins with ora_ + can be called directly. + + plsql_errstr + This function returns a string which describes the errors from the most + recent PL/SQL function, procedure, package, or package body compile in a + format similar to the output of the SQL*Plus command 'show errors'. + + The function returns undef if the error string could not be retrieved + due to a database error. Look in $dbh->errstr for the cause of the + failure. + + If there are no compile errors, an empty string is returned. + + Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + + dbms_output_enable / dbms_output_put / dbms_output_get + These functions use the PL/SQL DBMS_OUTPUT package to store and retrieve + text using the DBMS_OUTPUT buffer. Text stored in this buffer by + dbms_output_put or any PL/SQL block can be retrieved by dbms_output_get + or any PL/SQL block connected to the same database session. + + Stored text is not available until after dbms_output_put or the PL/SQL + block that saved it completes its execution. This means you CAN NOT use + these functions to monitor long running PL/SQL procedures. + + Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + + Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + + dbms_output_enable ( [ buffer_size ] ) + This function calls DBMS_OUTPUT.ENABLE to enable calls to package + DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to these + procedures are ignored unless DBMS_OUTPUT.ENABLE is called first. + + The buffer_size is the maximum amount of text that can be saved in the + buffer and must be between 2000 and 1,000,000. If buffer_size is not + given, the default is 20,000 bytes. + + dbms_output_put ( [ @lines ] ) + This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + + If all lines were saved successfully the function returns 1. Depending + on the context, an empty list or undef is returned for failure. + + If any line causes buffer_size to be exceeded, a buffer overflow error + is raised and the function call fails. Some of the text might be in the + buffer. + + dbms_output_get + This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from + the buffer. + + In an array context, all complete lines are removed from the buffer and + returned as a list. If there are no complete lines, an empty list is + returned. + + In a scalar context, the first complete line is removed from the buffer + and returned. If there are no complete lines, undef is returned. + + Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or + DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, + DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + + reauthenticate ( $username, $password ) + Starts a new session against the current database using the credentials + supplied. + + private_attribute_info + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + + Returns a hash of all private attributes used by DBD::Oracle, for either + a database or a statement handle. Currently, all the hash values are + undef. + +ATTRIBUTES COMMON TO ALL HANDLES + InactiveDestroy (boolean) + Implemented by DBI, no driver-specific impact. + + RaiseError (boolean, inherited) + Forces errors to always raise an exception. Although it defaults to off, + it is recommended that this be turned on, as the alternative is to check + the return value of every method (prepare, execute, fetch, etc.) + manually, which is easy to forget to do. + + PrintError (boolean, inherited) + Forces database errors to also generate warnings, which can then be + filtered with methods such as locally redefining *$SIG{__WARN__}* or + using modules such as "CGI::Carp". This attribute is on by default. + + ShowErrorStatement (boolean, inherited) + Appends information about the current statement to error messages. If + placeholder information is available, adds that as well. Defaults to + true. + + Warn (boolean, inherited) + Enables warnings. This is on by default, and should only be turned off + in a local block for a short a time only when absolutely needed. + + Executed (boolean, read-only) + Indicates if a handle has been executed. For database handles, this + value is true after the "do" method has been called, or when one of the + child statement handles has issued an "execute". Issuing a "commit" or + "rollback" always resets the attribute to false for database handles. + For statement handles, any call to "execute" or its variants will flip + the value to true for the lifetime of the statement handle. + + TraceLevel (integer, inherited) + Sets the trace level, similar to the "trace" method. See the sections on + "trace" and "parse_trace_flag" for more details. + + Active (boolean, read-only) + Indicates if a handle is active or not. For database handles, this + indicates if the database has been disconnected or not. For statement + handles, it indicates if all the data has been fetched yet or not. Use + of this attribute is not encouraged. + + Kids (integer, read-only) + Returns the number of child processes created for each handle type. For + a driver handle, indicates the number of database handles created. For a + database handle, indicates the number of statement handles created. For + statement handles, it always returns zero, because statement handles do + not create kids. + + ActiveKids (integer, read-only) + Same as "Kids", but only returns those that are active. + + CachedKids (hash ref) + Returns a hashref of handles. If called on a database handle, returns + all statement handles created by use of the "prepare_cached" method. If + called on a driver handle, returns all database handles created by the + "connect_cached" method. + + ChildHandles (array ref) + Implemented by DBI, no driver-specific impact. + + PrintWarn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleError (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleSetErr (code ref, inherited) + Implemented by DBI, no driver-specific impact. + + ErrCount (unsigned integer) + Implemented by DBI, no driver-specific impact. + + FetchHashKeyName (string, inherited) + Implemented by DBI, no driver-specific impact. + + ChopBlanks (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Taint (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintIn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintOut (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Profile (inherited) + Implemented by DBI, no driver-specific impact. + + Type (scalar) + Returns "dr" for a driver handle, "db" for a database handle, and "st" + for a statement handle. Should be rarely needed. + + LongReadLen + Implemented by DBI, no driver-specific impact. + + LongTruncOk + Implemented by DBI, no driver-specific impact. + + CompatMode + Type: boolean, inherited + + The CompatMode attribute is used by emulation layers (such as Oraperl) + to enable compatible behaviour in the underlying driver (e.g., + DBD::Oracle) for this handle. Not normally set by application code. + + It also has the effect of disabling the 'quick FETCH' of attribute + values from the handles attribute cache. So all attribute values are + handled by the drivers own FETCH method. This makes them slightly slower + but is useful for special-purpose drivers like DBD::Multiplex. + +ORACLE-SPECIFIC DATABASE HANDLE METHODS + ora_can_unicode ( [ $refresh ] ) + Returns a number indicating whether either of the database character + sets is a Unicode encoding. Calls ora_nls_parameters() and passes the + optional $refresh parameter to it. + + 0 = Neither character set is a Unicode encoding. + + 1 = National character set is a Unicode encoding. + + 2 = Database character set is a Unicode encoding. + + 3 = Both character sets are Unicode encodings. + + ora_can_taf + Returns true if the current connection supports TAF events. False if + otherise. + + ora_nls_parameters ( [ $refresh ] ) + Returns a hash reference containing the current NLS parameters, as given + by the v$nls_parameters view. The values fetched are cached between + calls. To cause the latest values to be fetched, pass a true value to + the function. + +DATABASE HANDLE METHODS + selectall_arrayref + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the rows returned by + preparing and executing the SQL string. See the DBI documentation for + full details. + + selectall_hashref + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + + Returns a reference to a hash containing the rows returned by preparing + and executing the SQL string. See the DBI documentation for full + details. + + selectcol_arrayref + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the first column from each + rows returned by preparing and executing the SQL string. It is possible + to specify exactly which columns to return. See the DBI documentation + for full details. + + prepare + $sth = $dbh->prepare($statement, \%attr); + + Prepares a statement for later execution by the database engine and + returns a reference to a statement handle object. + + Prepare Attributes + These attributes may be used in the "\%attr" parameter of the "prepare" + in DBI database handle method. + + ora_placeholders + Set to false to disable processing of placeholders. Used mainly for + loading a PL/SQL package that has been *wrapped* with Oracle's + "wrap" utility. + + ora_auto_lob + If true (the default), fetching retrieves the contents of the CLOB + or BLOB column in most circumstances. If false, fetching retrieves + the Oracle "LOB Locator" of the CLOB or BLOB value. + + See "LOBs and LONGs" for more details. + + See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how + to use LOB Locators. + + ora_pers_lob + If true the "Simple Fetch for CLOBs and BLOBs" method for the "Data + Interface for Persistent LOBs" will be used for LOBs rather than the + default method "Data Interface for LOB Locators". + + ora_clbk_lob + If true the "Piecewise Fetch with Callback" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_lob + If true the "Piecewise Fetch with Polling" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_size + This is the max piece size for the "Piecewise Fetch with Callback" + and "Piecewise Fetch with Polling" methods, in chars for CLOBS, and + bytes for BLOBS. + + ora_check_sql + If 1 (default), force SELECT statements to be described in + prepare(). If 0, allow SELECT statements to defer describe until + execute(). + + See "Prepare Postponed Till Execute" for more information. + + ora_exe_mode + This will set the execute mode of the current statement. Presently + only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + + See "Scrollable Cursors" for more details. + + ora_prefetch_rows + Sets the number of rows to be prefetched. If it is not set, then the + default value is 1. See "Row Prefetching" for more details. + + ora_prefetch_memory + Sets the memory level for rows to be prefetched. The application + then fetches as many rows as will fit into that much memory. See + "Row Prefetching" for more details. + + ora_row_cache_off + By default DBD::Oracle will use a row cache when fetching to cut + down the number of round trips to the server. If you do not want to + use an array fetch set this value to any value other than 0; + + See "Row Prefetching" for more details. + + Placeholders + There are two types of placeholders that can be used in DBD::Oracle. The + first is the "question mark" type, in which each placeholder is + represented by a single question mark character. This is the method + recommended by the DBI specs and is the most portable. Each question + mark is internally replaced by a "dollar sign number" in the order in + which they appear in the query (important when using "bind_param"). + + The other placeholder type is "named parameters" in the format ":foo" + which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + + The different types of placeholders cannot be mixed within a statement, + but you may use different ones for each statement handle you have. This + is confusing at best, so stick to one style within your program. + + prepare_cached + $sth = $dbh->prepare_cached($statement, \%attr); + + Implemented by DBI, no driver-specific impact. This method is most + useful if the same query is used over and over as it will cut down round + trips to the server. + + do + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + + Prepare and execute a single statement. Returns the number of rows + affected if the query was successful, returns undef if an error + occurred, and returns -1 if the number of rows is unknown or not + available. Note that this method will return 0E0 instead of 0 for 'no + rows were affected', in order to always return a true value if no error + occurred. + + last_insert_id + Oracle does not implement auto_increment of serial type columns it uses + predefined sequences where the id numbers are either selected before + insert, at insert time with a trigger, or as part of the query. + + Below is an example of you to use the latter with the SQL returning + clause to get the ID number back on insert with the bind_param_inout + method. . + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + + commit + $rv = $dbh->commit; + + Issues a COMMIT to the server, indicating that the current transaction + is finished and that all changes made will be visible to other + processes. If AutoCommit is enabled, then a warning is given and no + COMMIT is issued. Returns true on success, false on error. + + rollback + $rv = $dbh->rollback; + + Issues a ROLLBACK to the server, which discards any changes made in the + current transaction. If AutoCommit is enabled, then a warning is given + and no ROLLBACK is issued. Returns true on success, and false on error. + + begin_work + This method turns on transactions until the next call to "commit" or + "rollback", if "AutoCommit" is currently enabled. If it is not enabled, + calling begin_work will issue an error. Note that the transaction will + not actually begin until the first statement after begin_work is called. + + disconnect + $rv = $dbh->disconnect; + + Disconnects from the Oracle database. Any uncommitted changes will be + rolled back upon disconnection. It's good policy to always explicitly + call commit or rollback at some point before disconnecting, rather than + relying on the default rollback behavior. + + If the script exits before disconnect is called (or, more precisely, if + the database handle is no longer referenced by anything), then the + database handle's DESTROY method will call the rollback() and + disconnect() methods automatically. It is best to explicitly disconnect + rather than rely on this behavior. + + ping + $rv = $dbh->ping; + + This "ping" method is used to check the validity of a database handle. + The value returned is either 0, indicating that the connection is no + longer valid, or 1, indicating the connection is valid. This function + does 1 round trip to the Oracle Server. + + get_info() + $value = $dbh->get_info($info_type); + + DBD::Oracle supports "get_info()", but (currently) only a few info + types. + + table_info() + DBD::Oracle supports attributes for "table_info()". + + In Oracle, the concept of *user* and *schema* is (currently) the same. + Because database objects are owned by an user, the owner names in the + data dictionary views correspond to schema names. Oracle does not + support catalogues so TABLE_CAT is ignored as selection criterion. + + Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + + TABLE_TYPE may contain a comma-separated list of table types. The + following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + + The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + + The special enumerations of catalogues, schemas and table types are + supported. However, TABLE_CAT is always NULL. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. "table_info()" performs a case-sensitive search. So, a + selection criterion should respect upper and lower case. Normally, an + identifier is case-insensitive. Oracle stores and returns it in upper + case. Sometimes, database objects are created with quoted identifiers + (for reserved words, mixed case, special characters, ...). Such an + identifier is case-sensitive (if not all upper case). Oracle stores and + returns it as given. "table_info()" has no special quote handling, + neither adds nor removes quotes. + + primary_key_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + If the primary key constraint was created without an identifier, PK_NAME + contains a system generated name with the form SYS_Cn. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + foreign_key_info() + This method (currently) supports the extended behaviour of SQL/CLI, i.e. + the result set contains foreign keys that refer to primary and alternate + keys. The field UNIQUE_OR_PRIMARY distinguishes these keys. + + Oracle does not support catalogues, so $pk_catalog and $fk_catalog are + ignored as selection criteria (in the new style interface). The + UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always NULL + (undef). See "table_info()" for more detailed information. + + If the primary or foreign key constraints were created without an + identifier, UK_NAME or FK_NAME contains a system generated name with the + form SYS_Cn. + + The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle + (currently) does not support other actions. + + The DELETE_RULE field may contain wrong values. This is a known Bug + (#1271663) in Oracle's data dictionary views. Currently (as of 8.1.7), + 'RESTRICT' and 'SET DEFAULT' are not supported, 'CASCADE' is mapped + correctly and all other actions (incl. 'SET NULL') appear as 'NO + ACTION'. + + The DEFERABILITY field is always NULL, because this columns is not + present in the ALL_CONSTRAINTS view of older Oracle releases. + + The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, + FK_TABLE_SCHEM, FK_TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + column_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + + Don't rely on the values of the BUFFER_LENGTH field! Especially the + length of FLOATs may be wrong. + + Datatype codes for non-standard types are subject to change. + + Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + It is possible with Oracle to make the names of the various DB objects + (table,column,index etc) case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + + So in the example the exact case "Bla_BLA" must be used to get it info + on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + + any case can be used to get info on the column. + + selectrow_array + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + + Returns an array of row information after preparing and executing the + provided SQL string. The rows are returned by calling "fetchrow_array". + The string can also be a statement handle generated by a previous + prepare. Note that only the first row of data is returned. If called in + a scalar context, only the first column of the first row is returned. + Because this is not portable, it is not recommended that you use this + method in that way. + + selectrow_arrayref + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an array, by internal use of the "fetchrow_arrayref" + method. + + selectrow_hashref + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an hash, by internal use of the "fetchrow_hashref" method. + + clone + $other_dbh = $dbh->clone(); + + Creates a copy of the database handle by connecting with the same + parameters as the original handle, then trying to merge the attributes. + See the DBI documentation for complete usage. + +DATABASE HANDLE ATTRIBUTES + AutoCommit (boolean) + Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is + on, but this may change in the future, so it is highly recommended that + you explicitly set it when calling "connect". + + ReadOnly (boolean) + $dbh->{ReadOnly} = 1; + + Specifies if the current database connection should be in read-only mode + or not. + + Please not that this method is not foolproof: there are still ways to + update the database. Consider this a safety net to catch applications + that should not be issuing commands such as INSERT, UPDATE, or DELETE. + + This method method requires DBI version 1.55 or better. + + Name (string, read-only) + Returns the name of the current database. This is the same as the DSN, + without the "dbi:Oracle:" part. + + Username (string, read-only) + Returns the name of the user connected to the database. + + Driver (handle, read-only) + Holds the handle of the parent driver. The only recommended use for this + is to find the name of the driver using: + + $dbh->{Driver}->{Name} + + RowCacheSize + DBD::Oracle supports both Server pre-fetch and Client side row caching. + By default both are turned on to give optimum performance. Most of the + time one can just let DBD::Oracle figure out the best optimization. + + Row Caching + Row caching occurs on the client side and the object of it is to cut + down the number of round trips made to the server when fetching rows. At + each fetch a set number of rows will be retrieved from the server and + stored locally. Further calls the server are made only when the end of + the local buffer(cache) is reached. + + Rows up to the specified top level row count "RowCacheSize" are fetched + if it occupies no more than the specified memory usage limit. The + default value is 0, which means that memory size is not included in + computing the number of rows to prefetch. If the "RowCacheSize" value is + set to a negative number then the positive value of RowCacheSize is used + to compute the number of rows to prefetch. + + By default "RowCacheSize" is automatically set. If you want to totally + turn off prefetching set this to 1. + + For any SQL statement that contains a LOB, Long or Object Type Row + Caching will be turned off. However server side caching still works. If + you are only selecting a LOB Locator then Row Caching will still work. + + Row Prefetching + Row prefetching occurs on the server side and uses the DBI database + handle attribute "RowCacheSize" and or the Prepare Attribute + 'ora_prefetch_memory'. Tweaking these values may yield improved + performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + + In the above example 10 rows will be prefetched up to a maximum of 10000 + bytes of data. The Oracle® Call Interface Programmer's Guide, suggests + a good row cache value for a scrollable cursor is about 20% of expected + size of the record set. + + The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) + when it needs to get new rows. This happens on the first fetch that sets + the current_positon to any value other than 0. In the above example if + we do a OCI_FETCH_FIRST the first 10 rows are loaded into the buffer and + DBD::Oracle will not have to go back to the server for more rows. When + record 11 is fetched DBD::Oracle fetches and returns this row and the + next 9 rows are loaded into the buffer. In this case if you fetch + backwards from 10 to 1 no server round trips are made. + + With large record sets it is best not to attempt to go to the last + record as this may take some time, A large buffer size might even slow + down the fetch. If you must get the number of rows in a large record set + you might try using an few large OCI_FETCH_ABSOLUTEs and then an + OCI_FETCH_LAST, this might save some time. So if you had a record set of + 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one + would fetch the first 5000 rows into the buffer then the next 5000 rows. + If one requires only the first few rows there is no need to set a large + prefetch value. + + If the ora_prefetch_memory less than 1 or not present then memory size + is not included in computing the number of rows to prefetch otherwise + the number of rows will be limited to memory size. Likewise if the + RowCacheSize is less than 1 it is not included in the computing of the + prefetch rows. + +ORACLE-SPECIFIC STATEMENT HANDLE METHODS + ora_stmt_type + Returns the OCI Statement Type number for the SQL of a statement handle. + + ora_stmt_type_name + Returns the OCI Statement Type name for the SQL of a statement handle. + +DBI STATEMENT HANDLE OBJECT METHODS + bind_param + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + + Allows the user to bind a value and/or a data type to a placeholder. + + The value of $param_num is a number if using the '?' or if using ":foo" + style placeholders, the complete name (e.g. ":foo") must be given. The + $bind_value argument is fairly self-explanatory. A value of "undef" will + bind a "NULL" to the placeholder. Using "undef" is useful when you want + to change just the type and will be overwriting the value later. (Any + value is actually usable, but "undef" is easy and efficient). + + The "\%attr" hash is used to indicate the data type of the placeholder. + The default value is "varchar". If you need something else, you must use + one of the values provided by DBI or by DBD::Pg. To use a SQL value, + modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + + This will import some constants into your script. You can plug those + directly into the "bind_param" call. Some common ones that you will + encounter are: + + SQL_INTEGER + + To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + + You can then set the data types by setting the value of the "ora_type" + key in the hash passed to "bind_param". The current list of Oracle data + types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + + Data types are "sticky," in that once a data type is set to a certain + placeholder, it will remain for that placeholder, unless it is + explicitly set to something else afterwards. If the statement has + already been prepared, and you switch the data type to something else, + DBD::Oracle will re-prepare the statement for you before doing the next + execute. + + Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + + These attributes may be used in the "\%attr" parameter of the + "bind_param" in DBI or "bind_param_inout" in DBI statement handle + methods. + + ora_type + Specify the placeholder's datatype using an Oracle datatype. A fatal + error is raised if "ora_type" and the DBI "TYPE" attribute are used + for the same placeholder. Some of these types are not supported by + the current version of DBD::Oracle and will cause a fatal error if + used. Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + + Potentially useful values when DBD::Oracle was built using OCI 7 and + later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + + Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + + Additional values when DBD::Oracle was built using OCI 9.2 and + later: + + SQLT_CHR, SQLT_BIN + + See "Binding Cursors" for the correct way to use ORA_RSET. + + See "LOBs and LONGs" for how to use ORA_CLOB and ORA_BLOB. + + See "SYS.DBMS_SQL datatypes" for ORA_VARCHAR2_TABLE, + ORA_NUMBER_TABLE. + + See "Data Interface for Persistent LOBs" for the correct way to use + SQLT_CHR and SQLT_BIN. + + See "Other Data Types" for more information. + + See also "Placeholders and Bind Values" in DBI. + + ora_csform + Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values + are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can + be imported from the DBD::Oracle module. Rarely needed. + + ora_csid + Specify the *integer* OCI_ATTR_CHARSET_ID for the bind value. + Character set names can't be used currently. + + ora_maxdata_size + Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. May be + needed if a character set conversion from client to server causes + the data to use more space and so fail with a truncation error. + + ora_maxarray_numentries + Specify the maximum number of array entries to allocate. Used with + ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of + array entries Oracle can pass back to you in OUT variable of type + TABLE OF ... . + + ora_internal_type + Specify internal data representation. Currently is supported only + for ORA_NUMBER_TABLE. + + Optimizing Results + Prepare Postponed Till Execute + The DBD::Oracle module can avoid an explicit 'describe' operation prior + to the execution of the statement unless the application requests + information about the results (such as $sth->{NAME}). This reduces + communication with the server and increases performance (reducing the + number of PARSE_CALLS inside the server). + + However, it also means that SQL errors are not detected until + "execute()" (or $sth->{NAME} etc) is called instead of when "prepare()" + is called. Note that if the describe is triggered by the use of + $sth->{NAME} or a similar attribute and the describe fails then *an + exception is thrown* even if "RaiseError" is false! + + Set "ora_check_sql" to 0 in prepare() to enable this behaviour. + + bind_param_inout + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + + DBD::Oracle fully supports bind_param_inout below are some uses for this + method. + + Returning A Value from an INSERT + Oracle supports an extended SQL insert syntax which will return one or + more of the values inserted. This can be particularly useful for + single-pass insertion of values with re-used sequence values (avoiding a + separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + + If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + + If you have many rows to insert you can take advantage of Oracle's built + in execute array feature with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + + Which will return all the ids into @out_values. + + Note: + This will only work for numbered (?) placeholders, + The third parameter of bind_param_inout_array, (0 in the example), + "maxlen" is required by DBI but not used by DBD::Oracle + The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + + Returning A Recordset + DBD::Oracle does not currently support binding a PL/SQL table (aka + array) as an IN OUT parameter to any Perl data structure. You cannot + therefore call a PL/SQL function or procedure from DBI that uses a + non-atomic datatype as either a parameter, or a return value. However, + if you are using Oracle 9.0.1 or later, you can make use of table (or + pipelined) functions. + + For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + + Currently, there is no way to directly call the function + Array_Example.Array_Func from DBI. However, by making the following + relatively painless additions, its not only possible, but extremely + efficient. + + First, you need to create database object types that correspond to the + record and table types in the package. From the above example, these + would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + + Now, assuming the existing function needs to remain unchanged (it is + probably being called from other PL/SQL code), we need to add a new + function to the package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + + As you can see, the new function is very simple. Now, it is a simple + matter of calling the function as a straight-forward SELECT from your + DBI code. From the above example, the code would look something like + this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + + SYS.DBMS_SQL datatypes + DBD::Oracle has built-in support for SYS.DBMS_SQL.VARCHAR2_TABLE and + SYS.DBMS_SQL.NUMBER_TABLE datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + Note: + Take careful note that we use '\\@arr' here because the + 'bind_param_inout' will only take a reference to a scalar. + + ORA_VARCHAR2_TABLE + SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. ( + in bind_param() and bind_param_inout() ). When you bind array, you need + to specify full buffer size for OUT data. So, there are two parameters: + *max_len* (specified as 3rd argument of bind_param_inout() ), and + *ora_maxarray_numentries*. They define maximum array entry length and + maximum rows, that can be passed to Oracle and back to you. In this + example we send array with 1 element with length=3, but allocate space + for 100 Oracle array entries with maximum length 10 of each. So, you can + get no more than 100 array entries with length <= 10. + + If you set *max_len* to zero, maximum array entry length is calculated + as maximum length of entry of array bound. If 0 < *max_len* < length( + $some_element ), truncation occur. + + If you set *ora_maxarray_numentries* to zero, current (at bind time) + bound array length is used as maximum. If 0 < *ora_maxarray_numentries* + < scalar(@array), not all array entries are bound. + + ORA_NUMBER_TABLE + SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike + ORA_VARCHAR2_TABLE. The main difference is internal data representation. + Currently 2 types of bind is allowed : as C-integer, or as C-double + type. To select one of them, you may specify additional bind parameter + *ora_internal_type* as either SQLT_INT or SQLT_FLT for C-integer and + C-double types. Integer size is architecture-specific and is usually 32 + or 64 bit. Double is standard IEEE 754 type. + + *ora_internal_type* defaults to double (SQLT_FLT). + + *max_len* is ignored for OCI_NUMBER_TABLE. + + Currently, you cannot bind full native Oracle NUMBER(38). If you really + need, send request to dbi-dev list. + + The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + + If you change bind type to SQLT_INT, like: + + ora_internal_type => SQLT_INT + + you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + + bind_param_inout_array + DBD::Oracle supports this undocumented feature of DBI. See "Returning A + Value from an INSERT" for an example. + + bind_param_array + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + + Binds an array of values to a placeholder, so that each is used in turn + by a call to the "execute_array" method. + + execute + $rv = $sth->execute(@bind_values); + + Perform whatever processing is necessary to execute the prepared + statement. + + execute_array + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + Execute a prepared statement once for each item in a passed-in hashref, + or items that were previously bound via the "bind_param_array" method. + See the DBI documentation for more details. + + DBD::Oracle takes full advantage of OCI's array interface so inserts and + updates using this interface will run very quickly. + + execute_for_fetch + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + Used internally by the "execute_array" method, and rarely used directly. + See the DBI documentation for more details. + + fetchrow_arrayref + $ary_ref = $sth->fetchrow_arrayref; + + Fetches the next row of data from the statement handle, and returns a + reference to an array holding the column values. Any columns that are + NULL are returned as undef within the array. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + Note that the same array reference is returned for each fetch, so don't + store the reference and then use it after a later fetch. Also, the + elements of the array are also reused for each row, so take care if you + want to take a reference to an element. See also "bind_columns". + + fetchrow_array + @ary = $sth->fetchrow_array; + + Similar to the "fetchrow_arrayref" method, but returns a list of column + information rather than a reference to a list. Do not use this in a + scalar context. + + fetchrow_hashref + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + + Fetches the next row of data and returns a hashref containing the name + of the columns as the keys and the data itself as the values. Any NULL + value is returned as as undef value. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + The optional $name argument should be either "NAME", "NAME_lc" or + "NAME_uc", and indicates what sort of transformation to make to the keys + in the hash. By default Oracle uses upper case. + + fetchall_arrayref + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + + Returns a reference to an array of arrays that contains all the + remaining rows to be fetched from the statement handle. If there are no + more rows, an empty arrayref will be returned. If an error occurs, the + data read in so far will be returned. Because of this, you should always + check "$sth->err" after calling this method, unless "RaiseError" has + been enabled. + + If $slice is an array reference, fetchall_arrayref uses the + "fetchrow_arrayref" method to fetch each row as an array ref. If the + $slice array is not empty then it is used as a slice to select + individual columns by perl array index number (starting at 0, unlike + column and parameter numbers which start at 1). + + With no parameters, or if $slice is undefined, fetchall_arrayref acts as + if passed an empty array ref. + + If $slice is a hash reference, fetchall_arrayref uses "fetchrow_hashref" + to fetch each row as a hash reference. + + See the DBI documentation for a complete discussion. + + fetchall_hashref + $hash_ref = $sth->fetchall_hashref( $key_field ); + + Returns a hashref containing all rows to be fetched from the statement + handle. See the DBI documentation for a full discussion. + + finish + $rv = $sth->finish; + + Indicates to DBI that you are finished with the statement handle and are + not going to use it again. Only needed when you have not fetched all the + possible rows. + + rows + $rv = $sth->rows; + + Returns the number of rows affected for updates, deletes and inserts and + -1 for selects. + + bind_col + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + + Binds a Perl variable and/or some attributes to an output column of a + SELECT statement. Column numbers count up from 1. You do not need to + bind output columns in order to fetch data. + + NOTE: DBD::Oracle does not use the $bind_type to determine how to bind + the column; it uses what Oracle says the data type is. You can however + set a numeric bind type with the bind attributes + StrictlyTyped/DiscardString as these attributes are applied after the + column is retrieved. + + See the DBI documentation for a discussion of the optional parameters + "\%attr" and $bind_type + + bind_columns + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + + Calls the "bind_col" method for each column in the SELECT statement, + using the supplied list. + + dump_results + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + + Fetches all the rows from the statement handle, calls "DBI::neat_list" + for each row, and prints the results to $fh (which defaults to STDOUT). + Rows are separated by $lsep (which defaults to a newline). Columns are + separated by $fsep (which defaults to a comma). The $maxlen controls how + wide the output can be, and defaults to 35. + + This method is designed as a handy utility for prototyping and testing + queries. Since it uses "neat_list" to format and edit the string for + reading by humans, it is not recommended for data transfer applications. + +STATEMENT HANDLE ATTRIBUTES + NUM_OF_FIELDS (integer, read-only) + Returns the number of columns returned by the current statement. A + number will only be returned for SELECT statements for INSERT, UPDATE, + and DELETE statements which contain a RETURNING clause. This method + returns undef if called before "execute()". + + NUM_OF_PARAMS (integer, read-only) + Returns the number of placeholders in the current statement. + + NAME (arrayref, read-only) + Returns an arrayref of column names for the current statement. This + method will only work for SELECT statements, for SHOW statements, and + for INSERT, UPDATE, and DELETE statements which contain a RETURNING + clause. This method returns undef if called before "execute()". + + NAME_lc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to lower case. + + NAME_uc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to upper case. + + NAME_hash (hashref, read-only) + Similar to the "NAME" attribute, but returns a hashref of column names + instead of an arrayref. The names of the columns are the keys of the + hash, and the values represent the order in which the columns are + returned, starting at 0. This method returns undef if called before + "execute()". + + NAME_lc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + NAME_uc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + TYPE (arrayref, read-only) + Returns an arrayref indicating the data type for each column in the + statement. This method returns undef if called before "execute()". + + PRECISION (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the precision for "NUMERIC" columns, the + size in number of characters for "CHAR" and "VARCHAR" columns, and for + all other types of columns it returns the number of *bytes*. This method + returns undef if called before "execute()". + + SCALE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the scale of the that column. The only + type that will return a value is "NUMERIC". This method returns undef if + called before "execute()". + + NULLABLE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates if the column is nullable or not. 0 = + not nullable, 1 = nullable, 2 = unknown. This method returns undef if + called before "execute()". + + Database (dbh, read-only) + Returns the database handle this statement handle was created from. + + ParamValues (hash ref, read-only) + Returns a reference to a hash containing the values currently bound to + placeholders. If the "named parameters" type of placeholders are being + used (such as ":foo"), then the keys of the hash will be the names of + the placeholders (without the colon). If the "dollar sign numbers" type + of placeholders are being used, the keys of the hash will be the + numbers, without the dollar signs. If the "question mark" type is used, + integer numbers will be returned, starting at one and increasing for + every placeholder. + + If this method is called before "execute", the literal values passed in + are returned. If called after "execute", then the quoted versions of the + values are returned. + + ParamTypes (hash ref, read-only) + Returns a reference to a hash containing the type names currently bound + to placeholders. The keys are the same as returned by the ParamValues + method. The values are hashrefs containing a single key value pair, in + which the key is either 'TYPE' if the type has a generic SQL equivalent, + and 'pg_type' if the type can only be expressed by a Postgres type. The + value is the internal number corresponding to the type originally passed + in. (Placeholders that have not yet been bound will return undef as the + value). This allows the output of ParamTypes to be passed back to the + "bind_param" method. + + Statement (string, read-only) + Returns the statement string passed to the most recent "prepare" method + called in this database handle, even if that method failed. This is + especially useful where "RaiseError" is enabled and the exception + handler checks $@ and sees that a "prepare" method call failed. + + RowsInCache + Returns the number of un-fetched rows in the cache for selects. + +SCROLLABLE CURSORS + Oracle supports the concept of a 'Scrollable Cursor' which is defined as + a 'Result Set' where the rows can be fetched either sequentially or + non-sequentially. One can fetch rows forward, backwards, from any given + position or the n-th row from the current position in the result set. + + Rows are numbered sequentially starting at one and client-side caching + of the partial or entire result set can improve performance by limiting + round trips to the server. + + Oracle does not support DML type operations with scrollable cursors so + you are limited to simple 'Select' operations only. As well you can not + use this functionality with remote mapped queries or if the LONG + datatype is part of the select list. + + However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, + and fetch methods. + + Only use scrollable cursors if you really have a good reason to. They do + use up considerable more server and client resources and have poorer + response times than non-scrolling cursors. + + Enabling Scrollable Cursors + To enable this functionality you must first import the 'Fetch + Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + + Next you will have to tell DBD::Oracle that you will be using scrolling + by setting the ora_exe_mode attribute on the statement handle to + 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + + When the statement is executed you will then be able to use + 'ora_fetch_scroll' method to get a row or you can still use any of the + other fetch methods but with a poorer response time than if you used a + non-scrolling cursor. As well scrollable cursors are compatible with any + applicable bind methods. + + Scrollable Cursor Methods + The following driver-specific methods are used with scrollable cursors. + + ora_scroll_position + $position = $sth->ora_scroll_position(); + + This method returns the current position (row number) attribute of + the result set. Prior to the first fetch this value is 0. This is + the only time this value will be 0 after the first fetch the value + will be set, so you can use this value to test if any rows have been + fetched. The minimum value will always be 1 after the first fetch. + The maximum value will always be the total number of rows in the + record set. + + ora_fetch_scroll + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + + Works the same as "fetchrow_arrayref", excepts one passes in a + 'Fetch Orientation' constant and a fetch_offset value which will + then determine the row that will be fetched. It returns the row as a + list containing the field values. Null fields are returned as + *undef* values in the list. + + The valid orientation constant and fetch offset values combination + are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + + The effect that a ora_fetch_scroll method call has on the + current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + + The effects of the differing orientation constants on the first + fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + + Scrollable Cursor Usage + Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + + and one assumes that the number of rows returned from the query is 20, + the code snippets below will illustrate the use of ora_fetch_scroll + method; + + Fetching the Last Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute to will be 20 after this snippet. This + is also a way to get the number of rows in the record set, however, + if the record set is large this could take some time. + + Fetching the Current Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will still be 20 after this snippet. + + Fetching the First Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the Next Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 5 after this snippet. + + Fetching the Prior Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the 10th Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 10th to 14th Row + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 14 after this snippet. + + Fetching the 14th to 10th Row + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 5th Row From the Present Position. + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 15 after this snippet. + + Fetching the 9th Row Prior From the Present Position + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 6 after this snippet. + + Use Finish + $sth->finish(); + + When using scrollable cursors it is required that you use the + $sth->finish() method when you are done with the cursor as this type + of cursor has to be explicitly cancelled on the server. If you do + not do this you may cause resource problems on your database. + +LOBS AND LONGS + The key to working with LOBs (CLOB, BLOBs) is to remember the value of + an Oracle LOB column is not the content of the LOB. It's a 'LOB Locator' + which, after being selected or inserted needs extra processing to read + or write the content of the LOB. There are also legacy LONG types (LONG, + LONG RAW, VARCHAR2) which are presently deprecated by Oracle but are + still in use. These LONG types do not utilize a 'LOB Locator' and also + are more limited in functionality than CLOB or BLOB fields. + + DBD::Oracle now offers three interfaces to LOB and LONG data, + + "Data Interface for Persistent LOBs" + With this interface DBD::Oracle handles your data directly utilizing + regular OCI calls, Oracle itself takes care of the LOB Locator + operations in the case of BLOBs and CLOBs treating them exactly as + if they were the same as the legacy LONG or LONG RAW types. + + "Data Interface for LOB Locators" + With this interface DBD::Oracle handles your data utilizing LOB + Locator OCI calls so it only works with CLOB and BLOB datatypes. + With this interface DBD::Oracle takes care of the LOB Locator + operations for you. + + "LOB Locator Method Interface" + This allows the user direct access to the LOB Locator methods, so + you have to take case of the LOB Locator operations yourself. + + Generally speaking the interface that you will chose will be dependent + on what end you are trying to achieve. All have their benefits and + drawbacks. + + One point to remember when working with LOBs (CLOBs, BLOBs) is if your + LOB column can be in one of three states; + + NULL + The table cell is created, but the cell holds no locator or value. + If your LOB field is in this state then there is no LOB Locator that + DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + + error when working with a LOB. + + You can correct this by using an SQL UPDATE statement to reset the + LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB + or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + + Empty + A LOB instance with a locator exists in the cell, but it has no + value. The length of the LOB is zero. In this case DBD::Oracle will + return 'undef' for the field. + + Populated + A LOB instance with a locator and a value exists in the cell. You + actually get the LOB value. + + Data Interface for Persistent LOBs + This is the original interface for LONG and LONG RAW datatypes and from + Oracle 9iR1 and later the OCI API was extended to work directly with the + other LOB datatypes. In other words you can treat all LOB type data + (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can + perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using + the same techniques you would use on other datatypes that store + character or binary data. In some cases there are fewer round trips to + the server as no 'LOB Locators' are used, normally one can get an entire + LOB is a single round trip. + + Simple Fetch for LONGs and LONG RAWs + As the name implies this is the simplest way to use this interface. + DBD::Oracle just attempts to get your LONG datatypes as a single large + piece. There are no special settings, simply set the database handle's + 'LongReadLen' attribute to a value that will be the larger than the + expected size of the LONG or LONG RAW. If the size of the LONG or LONG + RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A + Truncation' error. To stop this set the database handle's 'LongTruncOk' + attribute to '1'. The maximum value of 'LongReadLen' seems to be + dependent on the physical memory limits of the box that Oracle is + running on. You have most likely reached this limit if you run into an + 'ORA-01062: unable to allocate memory for define buffer' error. One + solution is to set the size of 'LongReadLen' to a lower value. + + For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select out all of the long1 fields in the table as long as they are + all under 2MB in length. A value in long1 longer than this will throw an + error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the long1 fields but they will be + truncated at 2MBs. + + Using ora_ncs_buff_mtpl + When getting CLOBs and NCLOBs in or out of Oracle, the Server will + translate from the Server's NCharSet to the Client's. If they happen to + be the same or at least compatible then all of these actions are a 1 + char to 1 char bases. Thus if you set your LongReadLen buffer to + 10_000_000 you will get up to 10_000_000 char. + + However if the Server has to translate from one NCharSet to another it + will use bytes for conversion. The buffer value is set to 4 * + LONG_READ_LEN which was very wasteful as you might only be asking for + 10_000_000 bytes but you were actually using 40_000_000 bytes of buffer + under the hood. You would still get 10_000_000 bytes (maybe less + characters though) but you are using allot more memory that you need. + + You can now customize the size of the buffer by setting the + 'ora_ncs_buff_mtpl' either on the connection or statement handle. You + can also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you + will have to go back and change all your code if you are getting into + trouble. + + The default value is still set to 4 for backward compatibility. You can + lower this value and thus increase the amount of data you can retrieve. + If the ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error + telling you to increase this buffer by one. + + If the error is not captured then you may get at some random point later + on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + + This is one of the more obscure ORA errors (have some fun and report it + to Meta-Link they will scratch their heads for hours) + + If you get this, simply increment the ora_ncs_buff_mtpl by one until it + goes away. + + This should greatly increase your ability to select very large CLOBs or + NCLOBs, by freeing up a large block of memory. + + You can tune this value by setting ora_oci_success_warn which will + display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + + In the case above the query Got 28 characters (well really only 20 + characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) + thus saving 40bytes of memory. + + Simple Fetch for CLOBs and BLOBs + To use this interface for CLOBs and LOBs datatypes set the + 'ora_pers_lob' attribute of the statement handle to '1' with the prepare + method, as well set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. If the + size of the LOB exceeds the 'LongReadLen' DBD::Oracle will return a + 'ORA-24345: A Truncation' error. To stop this set the database handle's + 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems + to be dependent on the physical memory limits of the box that Oracle is + running on in the same way that LONGs and LONG RAWs are. + + For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, + this is an internal OCI limit complain to them if you want it changed. + However if you CLOB is longer than this and also larger than the + 'LongReadLen' than the 'LongReadLen' in chars is returned. + + It seems with BLOBs you are not limited by the 64k. + + For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the lobs but they will be truncated + at 2MBs. + + Piecewise Fetch with Callback + With a piecewise callback fetch DBD::Oracle sets up a function that will + 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, + CLOB, BLOB) piece by piece. To use this interface set the 'ora_clbk_lob' + attribute of the statement handle to '1' with the prepare method. Next + set the 'ora_piece_size' to the size of the piece that you want to + return on the callback. Finally set the database handle's 'LongReadLen' + attribute to a value that will be the larger than the expected size of + the LOB. Like the "Simple Fetch for LONGs and LONG RAWs" and "Simple + Fetch for CLOBs and BLOBs" the if the size of the LOB exceeds the is + 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the + LOB or set the 'LongReadLen' to a higher value. With this interface the + value of 'ora_piece_size' seems to be constrained by the same memory + limit as found on the Simple Fetch interface. If you encounter an + 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller + value. The value for 'LongReadLen' is dependent on the version and + settings of the Oracle DB you are using. In theory it ranges from 8GBs + in 9iR1 up to 128 terabytes with 11g but you will also be limited by the + physical memory of your PERL instance. + + Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will + throw an error. + + Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 filed is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Piecewise Fetch with Polling + With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB + during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by + piece. To use this interface set the 'ora_piece_lob' attribute of the + statement handle to '1' with the prepare method. Next set the + 'ora_piece_size' to the size of the piece that you want to return on the + callback. Finally set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. Like + the "Piecewise Fetch with Callback" and Simple Fetches if the size of + the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' + attribute to truncate the LOB or set the 'LongReadLen' to a higher + value. With this interface the value of 'ora_piece_size' seems to be + constrained by the same memory limit as found on the "Piecewise Fetch + with Callback". + + Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will + throw an error. + + Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 field is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Binding for Updates and Inserts for CLOBs and BLOBs + To bind for updates and inserts all that is required to use this + interface is to set the statement handle's prepare method 'ora_type' + attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in + the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + + So far the only limit reached with this form of insert is the LOBs must + be under 2GB in size. + + Support for Remote LOBs; + Starting with Oracle 10gR2 the interface for Persistent LOBs was + expanded to support remote LOBs (access over a dblink). Given a database + called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + + to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Below are the limitations of Remote LOBs; + + Queries involving more than one database are not supported; + so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + + as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + + DDL commands are not supported; + so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + + Only binds and defines for data going into remote persistent LOBs are + supported. + so that parameter passing in PL/SQL where CHAR data is bound or + defined for remote LOBs is not allowed . + + These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + + If the remote object is a view such as + CREATE VIEW v AS SELECT foo() FROM ... + + the following would not work: + + SELECT * FROM v@dbs2; + + Limited PL/SQL parameter passing + PL/SQL parameter passing is not allowed where the actual argument is + a LOB type and the remote argument is one of VARCHAR2, NVARCHAR2, + CHAR, NCHAR, or RAW. + + RETURNING INTO does not support implicit conversions between CHAR and + CLOB. + so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + + Locator Data Interface + Simple Usage + When fetching LOBs with this interface a 'LOB Locator' is created then + used to get the lob with the LongReadLen and LongTruncOk attributes. The + value for 'LongReadLen' is dependent on the version and settings of the + Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 + terabytes with 11g but you will also be limited by the physical memory + of your PERL instance. + + When inserting or updating LOBs some *major* magic has to be performed + behind the scenes to make it transparent. Basically the driver has to + insert a 'LOB Locator' and then refetch the newly inserted LOB Locator + before being able to write the data into it. However, it works well most + of the time, and I've made it as fast as possible, just one extra + server-round-trip per insert or update after the first. For the time + being, only single-row LOB updates are supported. + + To insert or update a large LOB using a placeholder, DBD::Oracle has to + know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + + The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + + or use the corresponding integer values (112 and 113). + + One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has to + be able to tell which parameters relate to which table fields. In all + cases where it can possibly work it out for itself, it does, however, if + there are multiple LOB fields of the same type in the table then you + need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + + There are some limitations inherent in the way DBD::Oracle makes typical + LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + + The alternative is to disable the automatic LOB Locator processing. If + "ora_auto_lob" is 0 in prepare(), you can fetch the LOB Locators and do + all the work yourself using the ora_lob_*() methods. See the "Data + Interface for LOB Locators" section below. + + LOB support in PL/SQL + LOB Locators can be passed to PL/SQL calls by binding them to + placeholders with the proper "ora_type". If "ora_auto_lob" is true, + output LOB parameters will be automatically returned as strings. + + If the Oracle driver has support for temporary LOBs (Oracle 9i and + higher), strings can be bound to input LOB placeholders and will be + automatically converted to LOBs. + + Example: # Build a large XML document, bind it as a CLOB, # extract + elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + + If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + + error, while attempting to insert a LOB, this means the Oracle user has + insufficient space for LOB you are trying to insert. One solution it to + use "alter database datafile 'sss.ggg' resize Mnnn" to increase the + available memory for LOBs. + + Persistent & Locator Interface Caveats + Now that one has the option of using the Persistent or the Locator + interface for LOBs the questions arises which one to use. For starters, + if you want to access LOBs over a dblink you will have to use the + Persistent interface so that choice is simple. The question of which one + to use after that is a little more tricky. It basically boils down to a + choice between LOB size and speed. + + The Callback and Polling piecewise fetches are very very slow when + compared to the Simple and the Locator fetches but they can handle very + large blocks of data. Given a situation where a large LOB is to be read + the Locator fetch may time out while either of the piecewise fetches may + not. + + With the Simple fetch you are limited by physical memory of your server + but it runs a little faster than the Locator, as there are fewer round + trips to the server. So if you have small LOBs and need to save a little + bandwidth this is the one to use. It you are going after large LOBs then + the Locator interface is the one to use. + + If you need to update more than a single row of with LOB data then the + Persistent interface can do it while the Locator can't. + + If you encounter a situation where you have to access the legacy LOBs + (LONG, LONG RAW) and the values are to large for you system then you can + use the Callback or Polling piecewise fetches to get all of the data. + + Not all of the Persistent interface has been implemented yet, the + following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + + Most of the time you should just use the "Locator Data Interface" as + this is in one that has the best combination of speed and size. + + All this being said if you are doing some critical programming I would + use the "Data Interface for LOB Locators" as this gives you very fine + grain control of your LOBs, of course the code for this will be somewhat + more involved. + + Data Interface for LOB Locators + The following driver-specific methods let you manipulate "LOB Locators" + directly. To select a LOB locator directly set the if the "ora_auto_lob" + attribute to false, or alternatively they can be returned via PL/SQL + procedure calls. + + (If using a DBI version earlier than 1.36 they must be called via the + func() method. Note that methods called via func() don't honour + RaiseError etc, and so it's important to check $dbh->err after each + call. It's recommended that you upgrade to DBI 1.38 or later.) + + Note that LOB locators are only valid while the statement handle that + created them is valid. When all references to the original statement + handle are lost, the handle is destroyed and the locators are freed. + + ora_lob_read + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + + Read a portion of the LOB. $offset starts at 1. Uses the Oracle + OCILobRead function. + + ora_lob_write + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + + Write/overwrite a portion of the LOB. $offset starts at 1. Uses the + Oracle OCILobWrite function. + + ora_lob_append + $rc = $dbh->ora_lob_append($lob_locator, $data); + + Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + + ora_lob_trim + $rc = $dbh->ora_lob_trim($lob_locator, $length); + + Trims the length of the LOB to $length. Uses the Oracle OCILobTrim + function. + + ora_lob_length + $length = $dbh->ora_lob_length($lob_locator); + + Returns the length of the LOB. Uses the Oracle OCILobGetLength + function. + + ora_lob_is_init + $is_init = $dbh->ora_lob_is_init($lob_locator); + + Returns true(1) if the Lob Locator is initialized false(0) if it is + not, or 'undef' if there is an error. Uses the Oracle + OCILobLocatorIsInit function. + + ora_lob_chunk_size + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + + Returns the chunk size of the LOB. Uses the Oracle + OCILobGetChunkSize function. + + For optimal performance, Oracle recommends reading from and writing + to a LOB in batches using a multiple of the LOB chunk size. In + Oracle 10g and before, when all defaults are in place, this chunk + size defaults to 8k (8192). + + LOB Locator Method Examples + *Note:* Make sure you first read the note in the section above about + multi-byte character set issues with these methods. + + The following examples demonstrate the usage of LOB Locators to read, + write, and append data, and to query the size of large data. + + The following examples assume a table containing two large object + columns, one binary and one character, with a primary key column, + defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + + It also assumes a sequence for use in generating unique lob_id field + values, defined as follows: + + CREATE SEQUENCE lob_example_seq + + Example: Inserting a new row with large data + Unless enough memory is available to store and bind the entire LOB data + for insert all at once, the LOB columns must be written interactively, + piece by piece. In the case of a new row, this is performed by first + inserting a row, with empty values in the LOB columns, then modifying + the row by writing the large data interactively to the LOB columns using + their LOB locators as handles. + + The insert statement must create token values in the LOB columns. Here, + we use the empty string for both the binary and character large object + columns 'bindata' and 'chardata'. + + After the INSERT statement, a SELECT statement is used to acquire LOB + locators to the 'bindata' and 'chardata' fields of the newly inserted + row. Because these LOB locators are subsequently written, they must be + acquired from a select statement containing the clause 'FOR UPDATE' (LOB + locators are only valid within the transaction that fetched them, so + can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + + In this example we demonstrate the use of ora_lob_write() interactively + to append data to the columns 'bin_data' and 'char_data'. Had we used + ora_lob_append(), we could have saved ourselves the trouble of keeping + track of the offset into the lobs. The snippet of code beneath the + comment 'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + + The scalar variables $offset and $length are no longer needed, because + ora_lob_append() keeps track of the offset for us. + + Example: Updating an existing row with large data + In this example, we demonstrate a technique for overwriting a portion of + a blob field with new binary data. The blob data before and after the + section overwritten remains unchanged. Hence, this technique could be + used for updating fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + + After running this code, the row where lob_id = 5 will contain, starting + at position 100234 in the bin_data column, the string "This string will + overwrite a portion of the blob". + + Example: Streaming character data from the database + In this example, we demonstrate a technique for streaming data from the + database to a file handle, in this case STDOUT. This allows more data to + be read in and written out than could be stored in memory at a given + time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + + Notice that the select statement does not contain the phrase "FOR + UPDATE". Because we are only reading from the LOB Locator returned, and + not modifying the LOB it refers to, the select statement does not + require the "FOR UPDATE" clause. + + A word of caution when using the data returned from an ora_lob_read in a + conditional statement. for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + + was used with a chunk size of 4096 against a blob that requires more + than 1 chunk to return the data and the last chunk is one byte long and + contains a zero (ASCII 48) you will miss this last byte as $data will + contain 0 which PERL will see as false and not print it out. + + Example: Truncating existing large data + In this example, we truncate the data already present in a large object + column in the database. Specifically, for each row in the table, we + truncate the 'bindata' value to half its previous length. + + After acquiring a LOB Locator for the column, we query its length, then + we trim the length by half. Because we modify the large objects with the + call to ora_lob_trim(), we must select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +SPACES AND PADDING + Trailing Spaces + Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder + values and uses Nonpadded Comparison Semantics with the result. This + causes trouble if the spaces are needed for comparison with a CHAR value + or to prevent the value from becoming '' which Oracle treats as NULL. + Look for Blank-padded Comparison Semantics and Nonpadded Comparison + Semantics in Oracle's SQL Reference or Server SQL Reference for more + details. + + To preserve trailing spaces in placeholder values for Oracle clients + that use OCI 8, either change the default placeholder type with + "ora_ph_type" or the placeholder type for a particular call to "bind" in + DBI or "bind_param_inout" in DBI with "ora_type" or "TYPE". Using + ORA_CHAR with ora_type or "SQL_CHAR" with "TYPE" allows the placeholder + to be used with Padded Comparison Semantics if the value it is being + compared to is a CHAR, NCHAR, or literal. + + Please remember that using spaces as a value or at the end of a value + makes visually distinguishing values with different numbers of spaces + difficult and should be avoided. + + Oracle Clients that use OCI 9.2 do not strip trailing spaces. + + Padded Char Fields + Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder + values to the size of the CHAR. As the default placeholder type value in + DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will have to + change the default placeholder type with "ora_ph_type" or placeholder + type for a particular call with "bind" in DBI or "bind_param_inout" in + DBI with "ORA_CHAR". + +UNICODE + DBD::Oracle now supports Unicode UTF-8. There are, however, a number of + issues you should be aware of, so please read all this section + carefully. + + In this section we'll discuss "Perl and Unicode", then "Oracle and + Unicode", and finally "DBD::Oracle and Unicode". + + Information about Unicode in general can be found at: + . It is well worth reading because there are + many misconceptions about Unicode and you may be holding some of them. + + Perl and Unicode + Perl began implementing Unicode with version 5.6, but the implementation + did not mature until version 5.8 and later. If you plan to use Unicode + you are *strongly* urged to use Perl 5.8.2 or later and to *carefully* + read the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + + And then read it again. + + Perl's internal Unicode format is UTF-8 which corresponds to the Oracle + character set called AL32UTF8. + + Oracle and Unicode + Oracle supports many characters sets, including several different forms + of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + + When you create an Oracle database, you must specify the DATABASE + character set (used for DDL, DML and CHAR datatypes) and the NATIONAL + character set (used for NCHAR and NCLOB types). The character sets used + in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + + The Oracle 9.2 and later default for the national character set is + AL16UTF16. The default for the database character set is often US7ASCII. + Although many experienced DBAs will consider an 8bit character set like + WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other + than US7ASCII, requires that the NLS_LANG environment variable be set. + See the "Oracle UTF8 is not UTF-8" section below. + + You are strongly urged to read the Oracle Internationalization + documentation specifically with respect the choices and trade offs for + creating a databases for use with international character sets. + + Oracle uses the NLS_LANG environment variable to indicate what character + set is being used on the client. When fetching data Oracle will convert + from whatever the database character set is to the client character set + specified by NLS_LANG. Similarly, when sending data to the database + Oracle will convert from the character set specified by NLS_LANG to the + database character set. + + The NLS_NCHAR environment variable can be used to define a different + character set for 'national' (NCHAR) character types. + + Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. For + example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + + Oracle UTF8 is not UTF-8 + AL32UTF8 should be used in preference to UTF8 if it works for you, which + it should for Oracle 9.2 or later. If you're using an old version of + Oracle that doesn't support AL32UTF8 then you should avoid using any + Unicode characters that require surrogates, in other words characters + beyond the Unicode BMP (Basic Multilingual Plane). + + That's because the character set that Oracle calls "UTF8" doesn't + conform to the UTF-8 standard in its handling of surrogate characters. + Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". + Here are a couple of extracts from + : + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + + Oracle uses this internally because it collates (sorts) in the same + order as UTF16, which is the basis of Oracle's internal collation + definitions. + + Rather than change UTF8 for clients Oracle chose to define a new + character set called "AL32UTF8" which does conform to the UTF-8 + standard. (The AL32UTF8 character set can't be used on the server + because it would break collation.) + + Because of that, for the rest of this document we'll use "AL32UTF8". If + you're using an Oracle version below 9.2 you'll need to use "UTF8" until + you upgrade. + + DBD::Oracle and Unicode + DBD::Oracle Unicode support has been implemented for Oracle versions 9 + or greater, and Perl version 5.6 or greater (though we *strongly* + suggest that you use Perl 5.8.2 or later). + + You can check which Oracle version your DBD::Oracle was built with by + importing the "ORA_OCI" constant from DBD::Oracle. + + Fetching Data + + Any data returned from Oracle to DBD::Oracle in the AL32UTF8 character + set will be marked as UTF-8 to ensure correct handling by Perl. + + For Oracle to return data in the AL32UTF8 character set the NLS_LANG or + NLS_NCHAR environment variable *must* be set as described in the + previous section. + + When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle + will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR is + AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + + When fetching other character data from Oracle, DBD::Oracle will set the + Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + + Sending Data using Placeholders + + Data bound to a placeholder is assumed to be in the default client + character set (specified by NLS_LANG) except for a few special cases. + These are listed here with the highest precedence first: + + If the "ora_csid" attribute is given to bind_param() then that is passed + to Oracle and takes precedence. + + If the value is a Perl Unicode string (UTF-8) then DBD::Oracle ensures + that Oracle uses the Unicode character set, regardless of the NLS_LANG + and NLS_NCHAR settings. + + If the placeholder is for inserting an NCLOB then the client NLS_NCHAR + character set is used. (That's useful but inconsistent with the other + behaviour so may change. Best to be explicit by using the "ora_csform" + attribute.) + + If the "ora_csform" attribute is given to bind_param() then that + determines if the value should be assumed to be in the default + (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + Binding with bind_param_array and execute_array is also UTF-8 compatible + in the same way. If you attempt to insert UTF-8 data into a non UTF-8 + Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert will + still happen but a error code of 0 will be returned with the following + warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + + The warning will report the parameter number and the NCHAR setting that + the query is running. + + Sending Data using SQL + + Oracle assumes the SQL statement is in the default client character set + (as specified by NLS_LANG). So Unicode strings containing non-ASCII + characters should not be used unless the default client character set is + AL32UTF8. + + DBD::Oracle and Other Character Sets and Encodings + The only multi-byte Oracle character set supported by DBD::Oracle is + "AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +OBJECT & COLLECTION DATA TYPES + Oracle databases allow for the creation of object oriented like + user-defined types. There are two types of objects, Embedded--an object + stored in a column of a regular table and REF--an object that uses the + REF retrieval mechanism. + + DBD::Oracle supports only the 'selection' of embedded objects of the + following types OBJECT, VARRAY and TABLE in any combination. Support is + seamless and recursive, meaning you need only supply a simple SQL + statement to get all the values in an embedded object. You can either + get the values as an array of scalars or they can be returned into a + DBD::Oracle::Object. + + Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + + The code to access all the data in the table could be something like + this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + + Note that values in PHONE_NUMBERS are returned as an array reference + '@$phone'. + + As stated before DBD::Oracle will automatically drill into the embedded + object and extract all of the data as reference arrays of scalars. The + example below has OBJECT type embedded in a TABLE type embedded in an + SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + + The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + + Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + + The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + + So far DBD::Oracle has been tested on a table with 20 embedded Objects, + Varrays and Tables nested to 10 levels. + + Any NULL values found in the embedded object will be returned as + 'undef'. + +OTHER DATA TYPES + DBD::Oracle does not *explicitly* support most Oracle datatypes. It + simply asks Oracle to return them as strings and Oracle does so. Mostly. + Similarly when binding placeholder values DBD::Oracle binds them as + strings and Oracle converts them to the appropriate type, such as DATE, + when used. + + Some of these automatic conversions to and from strings use NLS settings + to control the formatting for output and the parsing for input. The most + common example is the DATE type. The default NLS format for DATE might + be DD-MON-YYYY and so when a DATE type is fetched that's how Oracle will + format the date. NLS settings also control the default parsing of + strings into DATE values. An error will be generated if the contents of + the string don't match the NLS format. If you're dealing in dates which + don't match the default NLS format then you can either change the + default NLS format or, more commonly, use TO_CHAR(field, "format") and + TO_DATE(?, "format") to explicitly specify formats for converting to and + from strings. + + A slightly more subtle problem can occur with NUMBER types. The default + NLS settings might format numbers with a fullstop (""."") to separate + thousands and a comma ("","") as the decimal point. Perl will generate + warnings and use incorrect values when numbers, returned and formatted + as strings in this way by Oracle, are used in a numeric context. You + could explicitly convert each numeric value using the TO_CHAR(...) + function but that gets tedious very quickly. The best fix is to change + the NLS settings. That can be done for an individual connection by + doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + + There are some types, like BOOLEAN, that Oracle does not automatically + convert to or from strings (pity). These need to be converted explicitly + using SQL or PL/SQL functions. + + Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + + Support for Insert of XMLType (ORA_XMLTYPE) + Inserting large XML data sets into tables with XMLType fields is now + supported by DBD::Oracle. The only special requirement is the use of + bind_param() with an attribute hash parameter that specifies ora_type as + ORA_XMLTYPE. For example with a table like this; + + create table books (book_id number, book_xml XMLType); + + one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + + In the above case we will assume that $xml has 10000 Book nodes and is + over 32k in size and is well formed XML. This will also work for XML + that is smaller than 32k as well. Attempting to insert malformed XML + will cause an error. + + Binding Cursors + Cursors can be returned from PL/SQL blocks, either from stored functions + (or procedures with OUT parameters) or from direct "OPEN" statements, as + shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + The only special requirement is the use of "bind_param_inout()" with an + attribute hash parameter that specifies "ora_type" as "ORA_RSET". If you + don't do that you'll get an error from the "execute()" like: "ORA-06550: + line X, column Y: PLS-00306: wrong number or types of arguments in call + to ...". + + Here's an alternative form using a function that returns a cursor. This + example uses the pre-defined weak (or generic) REF CURSOR type + SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + A cursor obtained from PL/SQL as above may be passed back to PL/SQL by + binding for input, as shown in this example, which explicitly closes a + cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + + It is not normally necessary to close a cursor explicitly in this way. + Oracle will close the cursor automatically at the first client-server + interaction after the cursor statement handle is destroyed. An explicit + close may be desirable if the reference to the cursor handle from the + PL/SQL statement handle delays the destruction of the cursor handle for + too long. This reference remains until the PL/SQL handle is re-bound, + re-executed or destroyed. + + See the "curref.pl" script in the Oracle.ex directory in the DBD::Oracle + source distribution for a complete working example. + + Fetching Nested Cursors + Oracle supports the use of select list expressions of type REF CURSOR. + These may be explicit cursor expressions - "CURSOR(SELECT ...)", or + calls to PL/SQL functions which return REF CURSOR values. The values of + these expressions are known as nested cursors. + + The value returned to a Perl program when a nested cursor is fetched is + a statement handle. This statement handle is ready to be fetched from. + It should not (indeed, must not) be executed. + + Oracle imposes a restriction on the order of fetching when nested + cursors are used. Suppose $sth1 is a handle for a select statement + involving nested cursors, and $sth2 is a nested cursor handle fetched + from $sth1. $sth2 can only be fetched from while $sth1 is still active, + and the row containing $sth2 is still current in $sth1. Any attempt to + fetch another row from $sth1 renders all nested cursor handles + previously fetched from $sth1 defunct. + + Fetching from such a defunct handle results in an error with the message + "ERROR nested cursor is defunct (parent row is no longer current)". + + This means that the "fetchall..." or "selectall..." methods are not + useful for queries returning nested cursors. By the time such a method + returns, all the nested cursor handles it has fetched will be defunct. + + It is necessary to use an explicit fetch loop, and to do all the + fetching of nested cursors within the loop, as the following example + shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + + The cursor returned by the function "sp_ListEmp" defined in the previous + section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + + Pre-fetching Nested Cursors + By default, DBD::Oracle pre-fetches rows in order to reduce the number + of round trips to the server. For queries which do not involve nested + cursors, the number of pre-fetched rows is controlled by the DBI + database handle attribute "RowCacheSize" (q.v.). + + In Oracle, server side open cursors are a controlled resource, limited + in number, on a per session basis, to the value of the initialization + parameter "OPEN_CURSORS". Nested cursors count towards this limit. Each + nested cursor in the current row counts 1, as does each nested cursor in + a pre-fetched row. Defunct nested cursors do not count. + + An Oracle specific database handle attribute, "ora_max_nested_cursors", + further controls pre-fetching for queries involving nested cursors. For + each statement handle, the total number of nested cursors in pre-fetched + rows is limited to the value of this parameter. The default value is 0, + which disables pre-fetching for queries involving nested cursors. + +PL/SQL Examples + Most of these PL/SQL examples come from: Eric Bartley + . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + + You can find more examples in the t/plsql.t file in the DBD::Oracle + source directory. + + Oracle 9.2 appears to have a bug where a variable bound with + bind_param_inout() that isn't assigned to by the executed PL/SQL block + may contain garbage. See + + + Avoid Using "SQL Call" + Avoid using the "SQL Call" statement with DBD:Oracle as you might find + that DBD::Oracle will not raise an exception in some case. Specifically + if you use "SQL Call" to run a procedure all "No data found" exceptions + will be quietly ignored and returned as null. According to Oracle + support this is part of the same mechanism where; + + select (select * from dual where 0=1) from dual + + returns a null value rather than an exception. + +CONTRIBUTING + If you'd like DBD::Oracle to do something new or different the best way + to make that happen is to do it yourself and email to dbi-dev@perl.org a + patch of the source code (using 'diff' - see below) that shows the + changes. + + How to create a patch using Subversion + The DBD::Oracle source code is maintained using Subversion (a + replacement for CVS, see ). To access the + source you'll need to install a Subversion client. Then, to get the + source code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + + If it prompts for a username and password use your perl.org account if + you have one, else just 'guest' and 'guest'. The source code will be in + a new subdirectory called "trunk". + + To keep informed about changes to the source you can send an empty email + to dbd-oracle-changes-subscribe@perl.org after which you'll get an email + with the change log message and diff of each change checked-in to the + source. + + After making your changes you can generate a patch file, but before you + do, make sure your source is still upto date using: + + svn update + + If you get any conflicts reported you'll need to fix them first. Then + generate the patch file from within the "trunk" directory using: + + svn diff > foo.patch + + Read the patch file, as a sanity check, and then email it to + dbi-dev@perl.org. + + How to create a patch without Subversion + Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + + Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + + Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you + want. + + Test your changes and then remove all temporary files: + + make test && make distclean + + Go back to the directory you originally unpacked the distribution: + + cd .. + + Unpack *another* copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + + Then create a patch file by performing a recursive "diff" on the two top + level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + + Speak before you patch + For anything non-trivial or possibly controversial it's a good idea to + discuss (on dbi-dev@perl.org) the changes you propose before actually + spending time working on them. Otherwise you run the risk of them being + rejected because they don't fit into some larger plans you may not be + aware of. + + GitHub repository + A git mirror of the subversion is also available at + `https://github.com/yanick/DBD-Oracle`. + +Oracle Related Links +WHICH VERSION OF DBD::ORACLE IS FOR ME? + From version 1.25 onwards DBD::Oracle only support Oracle clients 9.2 or + greater. Support for ProC connections was dropped in 1.29. + + If you are still stuck with an older version of Oracle or its client you + might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + + As there are dozens of different versions of Oracle's clients this list + does not include all of them, just the major released versions of + Oracle. + + Note that one can still connect to any Oracle version with the older + DBD::Oracle versions the only problem you will have is that some of the + newer OCI and Oracle features available in later DBD::Oracle releases + will not be available to you. + + So to make a short story a little longer: + + 1 If you are using Oracle 7 or early 8 DB and you can manage to get a + 9 client and you can use any DBD::Oracle version. + + 2 If you have to use an Oracle 7 client then DBD::Oracle 1.17 should + work + + 3 Same thing for 8 up to R2, use 1.17, if you are lucky and have the + right patch-set you might go with 1.18. + + 4 For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. + Again this depends on your patch-set, If you run into trouble go + with 1.19 + + 5 After 9.2 you can use any version you want. + + 6 It seems that the 10g client can only connect to 9 and 11 DBs while + the 9 can go back to 7 and even get to 10. I am not sure what the + 11g client can connect to. + +BUGS AND LIMITATIONS + There is a known problem with the 11.2g Oracle client and the + "DBMS_LOB.GETLENGTH()" PL/SQL function. See + for the details. + +SEE ALSO + DBI http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in + the DBD::Oracle source distribution including the examples in the + Oracle.ex directory + + DBD::Oracle Tutorial + http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-ora + cle.html + + Oracle Instant Client + http://www.oracle.com/technology/tech/oci/instantclient/index.html + + Oracle on Linux + http://www.ixora.com.au/ + + Free Oracle Tools and Links + ora_explain supplied and installed with DBD::Oracle. + + http://www.orafaq.com/ + + http://vonnieda.org/oracletool/ + + Commercial Oracle Tools and Links + Assorted tools and references for general information. No + recommendation implied. + + http://www.platinum.com + + http://www.SoftTreeTech.com + + Also PL/Vision from RevealNet and Steven Feuerstein, and "Q" from + Savant Corporation. + +AUTHORS + DBI by Tim Bunce . + + The original "DBD::Oracle" was by Tim Bunce. Maintained as of release + 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the + auspice of the Pythian Group (). + +ACKNOWLEDGEMENTS + A great many people have helped with DBD::Oracle over the 17 years + between 1994 and 2011. Far too many to name, but we thank them all. Many + are named in the Changes file. + +COPYRIGHT + The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. + The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The + Pythian Group). Canada. The DBD::Oracle module is Copyright (c) 2011 + John Scoles. Canada. + + The DBD::Oracle module is free open source software; you can + redistribute it and/or modify it under the same terms as Perl 5. + +AUTHORS + * Tim Bunce + + * John Scoles + + * Yanick Champoux + +COPYRIGHT AND LICENSE + This software is copyright (c) 1994 by Tim Bunce. + + This is free software; you can redistribute it and/or modify it under + the same terms as the Perl 5 programming language system itself. diff --git a/README.mkdn b/README.mkdn new file mode 100644 index 00000000..efd36615 --- /dev/null +++ b/README.mkdn @@ -0,0 +1,4228 @@ +# NAME + +DBD::Oracle - Oracle database driver for the DBI module + +# VERSION + +version 1.38 + +# SYNOPSIS + + use DBI; + + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); + + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); + + # See the DBI module documentation for full details + + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); + +# DESCRIPTION + +DBD::Oracle is a Perl module which works with the DBI module to provide +access to Oracle databases. + +This documentation describes driver specific behaviour and restrictions. It is +not supposed to be used as the only reference for the user. In any case +consult the [DBI](http://search.cpan.org/perldoc?DBI) documentation first! + +# CONSTANTS + +- :ora_session_modes + +ORA_SYSDBA ORA_SYSOPER ORA_SYSASM + +- :ora_types + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +- SQLCS_IMPLICIT + +- SQLCS_NCHAR + +SQLCS_IMPLICIT and SQLCS_NCHAR are _character set form_ values. +See notes about Unicode elsewhere in this document. + +- SQLT_INT + +- SQLT_FLT + +These types are used only internally, and may be specified as internal +bind type for ORA_NUMBER_TABLE. See notes about ORA_NUMBER_TABLE elsewhere +in this document + +- ORA_OCI + +Oracle doesn't provide a formal API for determining the exact version +number of the OCI client library used, so DBD::Oracle has to go digging +(and sometimes has to more or less guess). The ORA_OCI constant +holds the result of that process. + +In string context ORA_OCI returns the full "A.B.C.D" version string. + +In numeric context ORA_OCI returns the major.minor version number +(8.1, 9.2, 10.0 etc). But note that version numbers are not actually +floating point and so if Oracle ever makes a release that has a two +digit minor version, such as `9.10` it will have a lower numeric +value than the preceding `9.9` release. So use with care. + +The contents and format of ORA_OCI are subject to change (it may, +for example, become a _version object_ in later releases). +I recommend that you avoid checking for exact values. + +- :ora_fetch_orient + + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE + +These constants are used to set the orientation of a fetch on a scrollable cursor. + +- :ora_exe_modes + + OCI_STMT_SCROLLABLE_READONLY + +- :ora_fail_over + + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + +# DBI CLASS METHODS + +## __connect__ + +This method creates a database handle by connecting to a database, and is the DBI equivalent of the "new" method. +To open a connection to an Oracle database you need to specify a database connection string (URL), username and password. + +The connection string is always of the form: "dbi:Oracle:" +There are several ways to identify a database: + +- 1 + +If the database is local, specifying the SID or service name will be enough. + +- 2 + +If the database is defined in a TNSNAMES.ORA file, you can use the service name given in the file + +- 3 + +To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: +//host[:port][/service_name] + +If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. + +The following examples show several ways a connection can be created: + + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); + + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); + + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); + + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); + +### OS authentication + +To connect to a local database with a user which has been set up to +authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): + + $dbh = DBI->connect('dbi:Oracle:','/',''); + +Note the lack of a connection name (use the ORACLE_SID environment +variable). If an explicit SID is used you will probably get an ORA-01004 error. + +That only works for local databases. (Authentication to remote Oracle +databases using your Unix login name without a password is possible +but it is not secure and not recommended so not documented here. + +### Oracle Environment Variables + +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). + +Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. + +To use them, specify either a local SID or service name, or a service name that is specified in the TNSNAMES.ORA file. + +Note that if you have *both* local and remote databases, and you have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO_TASK takes precedence over ORACLE_SID (i.e. you get connected to remote system). + +It is highly recommended not to rely on environment variables and to always explicitly specify the SID in the connection string. This can prevent serious mistakes such as dropping a schema in the wrong database, and generally makes debugging and troubleshooting easier. + +Also remember that depending on the operating system you are using the differing "ORACLE" environment variables may be case sensitive, so if you are not connecting as you should double check the case of both the variable and its value. + +### Timezones + +If the query is run through SQL*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. + +If the query is run locally, Oracle will return the time zone based on the "TZ" environment variable setting of the user running +the query. + +With local queries, you can change the time zone for a particular user by simply changing the setting of "TZ". To check the current setting, +issue the UNIX "date" command. + +### Oracle DRCP + +DBD::Oracle supports DRCP (Database Resident Connection Pool) so +if you have an 11.2 database and DRCP is enabled you can direct +all of your connections to it by adding ':POOLED' to the SID or +setting a connection attribute of ora_drcp, or set the SERVER=POOLED +when using a TNSENTRY style connection or even by setting an +environment variable ORA_DRCP. All of which are demonstrated below; + + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') + + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') + + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") + + if the ORA_DRCP environment variable is set then just this + + $dbh = DBI->connect('dbi:Oracle:DB','username','password') + +You can find a white paper on setting up DRCP and its advantages at [http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf](http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf). + +Please note that DRCP support in DBD::Oracle is relatively new so the +mechanics or its implementation are subject to change. + +### TAF (Transparent Application Failover) + +Transparent Application Failover (TAF) is the feature in OCI that +allows for clients to automatically reconnect to an instance in the +event of a failure of the instance. The reconnect happens +automatically from within the OCI (Oracle Call Interface) library. +DBD::Oracle now supports a callback function that will fire when a TAF +event takes place. The main use of the callback is to give your +program the opportunity to inform the user that a failover is taking +place. + +You will have to set up TAF on your instance before you can use this +callback. You can test your instance to see if you can use TAF +callback with + + $dbh->ora_can_taf(); + +If you try to set up a callback without it being enabled DBD::Oracle will croak. + +It is outside the scope of this documents to go through all of the +possible TAF situations you might want to set up but here is a simple +example: + +The TNS entry for the instance has had the following added to the +CONNECT_DATA section + + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) + +You will also have to create your own perl function that will be +called from the client. You can name it anything you want and it will +always be passed two parameters, the failover event value and the +failover type. You can also set a sleep value in case of failover +error and the OCI client will sleep for the specified seconds before it +attempts another event. + + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants + + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + + #create the perl TAF event function + + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ + + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); + + } + return 0; + } + +The TAF types are as follows + + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + +The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + +### Connect Attributes + +#### ora_ncs_buff_mtpl + +You can customize the size of the buffer when selecting LOBs with +the built-in AUTO Lob. The default value is 4 which is probably +excessive for most situations but is needed for backward +compatibility. If you not converting between a NCS on the DB and the +Client then you might want to set this to 1 to reduce memory usage. + +This value can also be specified with the `ORA_DBD_NCS_BUFFER` +environment variable in which case it sets the value at the connect +stage. + +#### ora_drcp + +For Oracle 11.2 or greater. + +Set to _1_ to enable DRCP. Can also be set via the `ORA_DRCP` environment variable. + +#### ora_drcp_class + +If you are using DRCP, you can set a CONNECTION_CLASS for your pools +as well. As sessions from a DRCP cannot be shared by users, you can +use this setting to identify the same user across different +applications. OCI will ensure that sessions belonging to a 'class' are +not shared outside the class'. + +The values for ora_drcp_class cannot contain a '*' and must be less +than 1024 characters. + +This value can be also be specified with the `ORA_DRCP_CLASS` +environment variable. + +#### ora_drcp_min + +This optional value specifies the minimum number of sessions that are +initially opened. New sessions are only opened after this value has +been reached. + +The default value is 4 and any value above 0 is valid. + +Generally, it should be set to the number of concurrent statements the +application is planning or expecting to run. + +This value can also be specified with the `ORA_DRCP_MIN` environment +variable. + +#### ora_drcp_max + +This optional value specifies the maximum number of sessions that can +be open at one time. Once reached no more sessions can be opened +until one becomes free. The default value is 40 and any value above 1 +is valid. You should not set this value lower than ora_drcp_min as +that will just waste resources. + +This value can also be specified with the `ORA_DRCP_MAX` environment +variable. + +#### ora_drcp_incr + +This optional value specifies the next increment for sessions to be +started if the current number of sessions are less than +ora_drcp_max. The default value is 2 and any value above 0 is +valid as long as the value of ora_drcp_min + ora_drcp_incr is not +greater than ora_drcp_max. + +This value can also be specified with the `ORA_DRCP_INCR` environment +variable. + +#### ora_taf + +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option to any _true_ value. + +#### ora_taf_function + +The name of the Perl subroutine that will be called from OCI when a +TAF event occurs. You must supply a perl function to use the callback +and it will always receive two parameters, the failover event value +and the failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + +#### ora_taf_sleep + +The amount of time in seconds the OCI client will sleep between attempting +successive failover events when the event is OCI_FO_ERROR. + +#### ora_session_mode + +The ora_session_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA_SYSASM authorization. +The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + +This is one case where setting ORACLE_SID may be useful since +connecting as SYSDBA or SYSOPER via SQL*Net is frequently disabled +for security reasons. + +Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + +It has been reported that this only works if `$dsn` does not contain +a SID so that Oracle then uses the value of ORACLE_SID (not +TWO_TASK) environment variable to connect to a local instance. Also +the username and password should be empty, and the user executing the +script needs to be part of the dba group or osdba group. + +#### ora_oratab_orahome + +Passing a true value for the ora_oratab_orahome attribute will make +DBD::Oracle change `$ENV{ORACLE_HOME}` to make the Oracle home directory +that specified in the `/etc/oratab` file _if_ the database to connect to +is specified as a SID that exists in the oratab file, and DBD::Oracle was +built to use the Oracle 7 OCI API (not Oracle 8+). + +#### ora_module_name + +After connecting to the database the value of this attribute is passed +to the SET_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL +package. This can be used to identify the application to the DBA for +monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + +The maximum size is 48 bytes. + +#### ora_driver_name + +For 11g and later you can now set the name of the driver layer using OCI. +Perl, Perl5, ApachePerl so on. Names starting with "ORA" are reserved. You +can enter up to 8 characters. If none is enter then this will default to +DBDOxxxx where xxxx is the current version number. This value can be +retrieved on the server side using V$SESSION_CONNECT_INFO or +GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + +#### ora_client_info + +Allows you to add any value (up to 64 bytes) to your session and it can be +retrieved on the server side from the `V$SESSION`a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + +#### ora_client_identifier + +Allows you to specify the user identifier in the session handle. + +Most useful for web applications as it can pass in the session user +name which might be different to the connection user name. Can be up +to 64 bytes long but do not to include the password for security +reasons and the first character of the identifier should not be +':'. This value can be retrieved on the server side using `V$SESSION` +view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + +#### ora_action + +Allows you to specify any string up to 32 bytes which may be retrieved +on the server side using `V$SESSION` view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + +#### ora_dbh_share + +Requires at least Perl 5.8.0 compiled with ithreads. + +Allows you to share +database connections between threads. The first connect will make the +connection, all following calls to connect with the same ora_dbh_share +attribute will use the same database connection. The value must be a +reference to a already shared scalar which is initialized to an empty +string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + +#### ora_envhp + +The first time a connection is made a new OCI 'environment' is +created by DBD::Oracle and stored in the driver handle. +Subsequent connects reuse (share) that same OCI environment +by default. + +The ora_envhp attribute can be used to disable the reuse of the OCI +environment from a previous connect. If the value is `0` then +a new OCI environment is allocated and used for this connection. + +The OCI environment holds information about the client side context, +such as the local NLS environment. By altering `%ENV` and setting +ora_envhp to 0 you can create connections with different NLS +settings. This is most useful for testing. + +#### ora_charset, ora_ncharset + +For oracle versions >= 9.2 you can specify the client charset and +ncharset with the ora_charset and ora_ncharset attributes. You +still need to pass `ora_envhp = 0` for all but the first connect. + +These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + +#### ora_verbose + +Use this value to enable DBD::Oracle only tracing. Simply either set +the ora_verbose attribute on the connect() method to the trace level +you desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + +or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + +In both cases the DBD::Oracle trace level is set to 6, which is the highest +level tracing most of the calls to OCI. + +#### ora_oci_success_warn + +Use this value to print otherwise silent OCI warnings that may happen +when an execute or fetch returns "Success With Info" or when you want +to tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + +#### ora_objects + +Use this value to enable extended embedded oracle objects mode. In extended: + +- 1 + +Embedded objects are returned as instance (including type-name etc.) instead of simple ARRAY. + +- 2 + +Determine object type for each instance. All object attributes are returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + +#### ora_ph_type + +The default placeholder datatype for the database session. +The `TYPE` or [ora_type](#pod_ora_type) attributes to L and +L override the datatype for individual placeholders. +The most frequent reason for using this attribute is to permit trailing spaces +in values passed by placeholders. + +Constants for the values allowed for this attribute can be imported using + + use DBD::Oracle qw(:ora_types); + +Only the following values are permitted for this attribute. + +- ORA_VARCHAR2 + +Oracle clients using OCI 8 will strip trailing spaces and allow embedded \0 bytes. +Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \0 bytes. +This is the normal default placeholder type. + +- ORA_STRING + +Do not strip trailing spaces and end the string at the first \0. + +- ORA_CHAR + +Do not strip trailing spaces and allow embedded \0. +Force 'blank-padded comparison semantics'. + +For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + +Will pad bloggs out to 8 characters and return the username. + +#### ora_parse_error_offset + +If the previous error was from a failed `prepare` due to a syntax error, +this attribute gives the offset into the `Statement` attribute where the +error was found. + +#### ora_array_chunk_size + +Due to OCI limitations, DBD::Oracle needs to buffer up rows of +bind values in its `execute_for_fetch` implementation. This attribute +sets the number of rows to buffer at a time (default value is 1000). + +The `execute_for_fetch` function will collect (at most) this many +rows in an array, send them off to the DB for execution, then go back +to collect the next chunk of rows and so on. This attribute can be +used to limit or extend the number of rows processed at a time. + +Note that this attribute also applies to `execute_array`, since that +method is implemented using `execute_for_fetch`. + +#### ora_connect_with_default_signals + +Sometimes the Oracle client seems to change some of the signal +handlers of the process during the connect phase. For instance, some +users have observed Perl's default `$SIG{INT}` handler being ignored +after connecting to an Oracle database. If this causes problems in +your application, set this attribute to an array reference of signals +you would like to be localized during the connect process. Once the +connect is complete, the signal handlers should be returned to their +previous state. + +For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + +NOTE disabling the signal handlers the OCI library sets up may affect +functionality in the OCI library. + +NOTE If you are using connect_cached then the above example will lead +to DBI thinking each connection is different as an anonymous array reference +is being used. To avoid this when using connect_cached you are advised +to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + +In more recent Perl versions you could possibly make use of new state +variables. + +## __connect_cached__ + +Implemented by DBI, no driver-specific impact. +Please note that connect_cached as not been tested with DRCP. + +## __data_sources__ + + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + +Returns a list of available databases. You will have to set either the 'ORACLE_HOME' or +'TNS_ADMIN' environment value to retrieve this list. It will read these values from +TNSNAMES.ORA file entries. + +# METHODS COMMON TO ALL HANDLES + +For all of the methods below, __$h__ can be either a database handle (__$dbh__) +or a statement handle (__$sth__). Note that _$dbh_ and _$sth_ can be replaced with +any variable name you choose: these are just the names most often used. Another +common variable used in this documentation is $_rv_, which stands for "return value". + +## __err__ + + $rv = $h->err; + +Returns the error code from the last method called. + +## __errstr__ + + $str = $h->errstr; + +Returns the last error that was reported by Oracle. Starting with "ORA-00000" code followed by the error message. + +## __state__ + + $str = $h->state; + +Oracle hasn't supported SQLSTATE since the early versions OCI. It will return empty when the command succeeds and +'S1000' (General Error) for all other errors. + +While this method can be called as either `$sth->state` or `$dbh->state`, it +is usually clearer to always use `$dbh->state`. + +## __trace__ + +Implemented by DBI, no driver-specific impact. + +## __trace_msg__ + +Implemented by DBI, no driver-specific impact. + +## __parse_trace_flag__ and __parse_trace_flags__ + +Implemented by DBI, no driver-specific impact. + +## __func__ + +DBD::Oracle uses the `func` method to support a variety of functions. + +## __Private database handle functions__ + +Some of these functions are called through the method func() +which is described in the DBI documentation. Any function that begins with ora_ +can be called directly. + +## __plsql_errstr__ + +This function returns a string which describes the errors +from the most recent PL/SQL function, procedure, package, +or package body compile in a format similar to the output +of the SQL*Plus command 'show errors'. + +The function returns undef if the error string could not +be retrieved due to a database error. +Look in $dbh->errstr for the cause of the failure. + +If there are no compile errors, an empty string is returned. + +Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + +## __dbms_output_enable / dbms_output_put / dbms_output_get__ + +These functions use the PL/SQL DBMS_OUTPUT package to store and +retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer +by dbms_output_put or any PL/SQL block can be retrieved by +dbms_output_get or any PL/SQL block connected to the same database +session. + +Stored text is not available until after dbms_output_put or the PL/SQL +block that saved it completes its execution. This means you __CAN NOT__ +use these functions to monitor long running PL/SQL procedures. + +Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + +Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + +## __dbms_output_enable ( [ buffer_size ] )__ + +This function calls DBMS_OUTPUT.ENABLE to enable calls to package +DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to +these procedures are ignored unless DBMS_OUTPUT.ENABLE is called +first. + +The buffer_size is the maximum amount of text that can be saved in the +buffer and must be between 2000 and 1,000,000. If buffer_size is not +given, the default is 20,000 bytes. + +## __dbms_output_put ( [ @lines ] )__ + +This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + +If all lines were saved successfully the function returns 1. Depending +on the context, an empty list or undef is returned for failure. + +If any line causes buffer_size to be exceeded, a buffer overflow error +is raised and the function call fails. Some of the text might be in +the buffer. + +## __dbms_output_get__ + +This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from +the buffer. + +In an array context, all complete lines are removed from the buffer and +returned as a list. If there are no complete lines, an empty list is +returned. + +In a scalar context, the first complete line is removed from the buffer +and returned. If there are no complete lines, undef is returned. + +Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or +DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, +DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + +## __reauthenticate ( $username, $password )__ + +Starts a new session against the current database using the credentials +supplied. + +## __private_attribute_info__ + + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + +Returns a hash of all private attributes used by DBD::Oracle, for either +a database or a statement handle. Currently, all the hash values are undef. + +# ATTRIBUTES COMMON TO ALL HANDLES + +## __InactiveDestroy__ (boolean) + +Implemented by DBI, no driver-specific impact. + +## __RaiseError__ (boolean, inherited) + +Forces errors to always raise an exception. Although it defaults to off, it is recommended that this +be turned on, as the alternative is to check the return value of every method (prepare, execute, fetch, etc.) +manually, which is easy to forget to do. + +## __PrintError__ (boolean, inherited) + +Forces database errors to also generate warnings, which can then be filtered with methods such as +locally redefining _$SIG{__WARN__}_ or using modules such as `CGI::Carp`. This attribute is on +by default. + +## __ShowErrorStatement__ (boolean, inherited) + +Appends information about the current statement to error messages. If placeholder information +is available, adds that as well. Defaults to true. + +## __Warn__ (boolean, inherited) + +Enables warnings. This is on by default, and should only be turned off in a local block +for a short a time only when absolutely needed. + +## __Executed__ (boolean, read-only) + +Indicates if a handle has been executed. For database handles, this value is true after the [do](#pod_do) method has been called, or +when one of the child statement handles has issued an [execute](#pod_execute). Issuing a [commit](#pod_commit) or [rollback](#pod_rollback) always resets the +attribute to false for database handles. For statement handles, any call to [execute](#pod_execute) or its variants will flip the value to +true for the lifetime of the statement handle. + +## __TraceLevel__ (integer, inherited) + +Sets the trace level, similar to the [trace](#pod_trace) method. See the sections on +[trace](#pod_trace) and [parse_trace_flag](#pod_parse_trace_flag) for more details. + +## __Active__ (boolean, read-only) + +Indicates if a handle is active or not. For database handles, this indicates if the database has +been disconnected or not. For statement handles, it indicates if all the data has been fetched yet +or not. Use of this attribute is not encouraged. + +## __Kids__ (integer, read-only) + +Returns the number of child processes created for each handle type. For a driver handle, indicates the number +of database handles created. For a database handle, indicates the number of statement handles created. For +statement handles, it always returns zero, because statement handles do not create kids. + +## __ActiveKids__ (integer, read-only) + +Same as `Kids`, but only returns those that are active. + +## __CachedKids__ (hash ref) + +Returns a hashref of handles. If called on a database handle, returns all statement handles created by use of the +`prepare_cached` method. If called on a driver handle, returns all database handles created by the [connect_cached](#pod_connect_cached) +method. + +## __ChildHandles__ (array ref) + +Implemented by DBI, no driver-specific impact. + +## __PrintWarn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleError__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleSetErr__ (code ref, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ErrCount__ (unsigned integer) + +Implemented by DBI, no driver-specific impact. + +## __FetchHashKeyName__ (string, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ChopBlanks__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Taint__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintIn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintOut__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Profile__ (inherited) + +Implemented by DBI, no driver-specific impact. + +## __Type__ (scalar) + +Returns `dr` for a driver handle, `db` for a database handle, and `st` for a statement handle. +Should be rarely needed. + +## __LongReadLen__ + +Implemented by DBI, no driver-specific impact. + +## __LongTruncOk__ + +Implemented by DBI, no driver-specific impact. + +## __CompatMode__ + +Type: boolean, inherited + +The CompatMode attribute is used by emulation layers (such as Oraperl) to enable compatible behaviour in the underlying driver (e.g., DBD::Oracle) for this handle. Not normally set by application code. + +It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. + +# ORACLE-SPECIFIC DATABASE HANDLE METHODS + +## __ora_can_unicode ( [ $refresh ] )__ + +Returns a number indicating whether either of the database character sets +is a Unicode encoding. Calls ora_nls_parameters() and passes the optional +$refresh parameter to it. + +0 = Neither character set is a Unicode encoding. + +1 = National character set is a Unicode encoding. + +2 = Database character set is a Unicode encoding. + +3 = Both character sets are Unicode encodings. + +## __ora_can_taf__ + +Returns true if the current connection supports TAF events. False if otherise. + +## __ora_nls_parameters ( [ $refresh ] )__ + +Returns a hash reference containing the current NLS parameters, as given +by the v$nls_parameters view. The values fetched are cached between calls. +To cause the latest values to be fetched, pass a true value to the function. + +# DATABASE HANDLE METHODS + +## __selectall_arrayref__ + + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectall_hashref__ + + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + +Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectcol_arrayref__ + + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the first column +from each rows returned by preparing and executing the SQL string. It is possible to specify exactly +which columns to return. See the DBI documentation for full details. + +## __prepare__ + + $sth = $dbh->prepare($statement, \%attr); + +Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. + +### __Prepare Attributes__ + +These attributes may be used in the `\%attr` parameter of the +L database handle method. + +- ora_placeholders + +Set to false to disable processing of placeholders. Used mainly for loading a +PL/SQL package that has been _wrapped_ with Oracle's `wrap` utility. + +- ora_auto_lob + +If true (the default), fetching retrieves the contents of the CLOB or +BLOB column in most circumstances. If false, fetching retrieves the +Oracle "LOB Locator" of the CLOB or BLOB value. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for more details. + +See also the LOB tests in 05dbi.t of Oracle::OCI for examples +of how to use LOB Locators. + +- ora_pers_lob + +If true the [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) method for the [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) will be +used for LOBs rather than the default method [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators). + +- ora_clbk_lob + +If true the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) method for the L will be used for LOBs. + +- ora_piece_lob + +If true the [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) method for the L will be used for LOBs. + +- ora_piece_size + +This is the max piece size for the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) +and [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) methods, in chars for CLOBS, and +bytes for BLOBS. + +- ora_check_sql + +If 1 (default), force SELECT statements to be described in prepare(). +If 0, allow SELECT statements to defer describe until execute(). + +See [Prepare Postponed Till Execute](#pod_Prepare Postponed Till Execute) for more information. + +- ora_exe_mode + +This will set the execute mode of the current statement. Presently +only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + +See [Scrollable Cursors](#pod_Scrollable Cursors) for more details. + +- ora_prefetch_rows + +Sets the number of rows to be prefetched. If it is not set, then the +default value is 1. See [Row Prefetching](#pod_Row Prefetching) for more details. + +- ora_prefetch_memory + +Sets the memory level for rows to be prefetched. The application then +fetches as many rows as will fit into that much memory. See L for more details. + +- ora_row_cache_off + +By default DBD::Oracle will use a row cache when fetching to cut down +the number of round trips to the server. If you do not want to use an +array fetch set this value to any value other than 0; + +See [Row Prefetching](#pod_Row Prefetching) for more details. + +### __Placeholders__ + +There are two types of placeholders that can be used in DBD::Oracle. The first is +the "question mark" type, in which each placeholder is represented by a single +question mark character. This is the method recommended by the DBI specs and is the most +portable. Each question mark is internally replaced by a "dollar sign number" in the order +in which they appear in the query (important when using [bind_param](#pod_bind_param)). + +The other placeholder type is "named parameters" in the format ":foo" which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + +The different types of placeholders cannot be mixed within a statement, but you may +use different ones for each statement handle you have. This is confusing at best, so +stick to one style within your program. + +## __prepare_cached__ + + $sth = $dbh->prepare_cached($statement, \%attr); + +Implemented by DBI, no driver-specific impact. This method is most useful +if the same query is used over and over as it will cut down round trips to the server. + +## __do__ + + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + +Prepare and execute a single statement. Returns the number of rows affected if the +query was successful, returns undef if an error occurred, and returns -1 if the +number of rows is unknown or not available. Note that this method will return __0E0__ instead +of 0 for 'no rows were affected', in order to always return a true value if no error occurred. + +## __last_insert_id__ + +Oracle does not implement auto_increment of serial type columns it uses predefined +sequences where the id numbers are either selected before insert, at insert time with a trigger, + or as part of the query. + +Below is an example of you to use the latter with the SQL returning clause to get the ID number back +on insert with the bind_param_inout method. +. + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + +## __commit__ + + $rv = $dbh->commit; + +Issues a COMMIT to the server, indicating that the current transaction is finished and that +all changes made will be visible to other processes. If AutoCommit is enabled, then +a warning is given and no COMMIT is issued. Returns true on success, false on error. + +## __rollback__ + + $rv = $dbh->rollback; + +Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit +is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and +false on error. + +## __begin_work__ + +This method turns on transactions until the next call to [commit](#pod_commit) or [rollback](#pod_rollback), if [AutoCommit](#pod_AutoCommit) is +currently enabled. If it is not enabled, calling begin_work will issue an error. Note that the +transaction will not actually begin until the first statement after begin_work is called. + +## __disconnect__ + + $rv = $dbh->disconnect; + +Disconnects from the Oracle database. Any uncommitted changes will be rolled back upon disconnection. It's +good policy to always explicitly call commit or rollback at some point before disconnecting, rather than +relying on the default rollback behavior. + +If the script exits before disconnect is called (or, more precisely, if the database handle is no longer +referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() +methods automatically. It is best to explicitly disconnect rather than rely on this behavior. + +## __ping__ + + $rv = $dbh->ping; + +This `ping` method is used to check the validity of a database handle. The value returned is +either 0, indicating that the connection is no longer valid, or 1, indicating the connection is valid. +This function does 1 round trip to the Oracle Server. + +## __get_info()__ + + $value = $dbh->get_info($info_type); + +DBD::Oracle supports `get_info()`, but (currently) only a few info types. + +## __table_info()__ + +DBD::Oracle supports attributes for `table_info()`. + +In Oracle, the concept of _user_ and _schema_ is (currently) the +same. Because database objects are owned by an user, the owner names +in the data dictionary views correspond to schema names. +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. + +Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + +TABLE_TYPE may contain a comma-separated list of table types. +The following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + +The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + +The special enumerations of catalogues, schemas and table types are +supported. However, TABLE_CAT is always NULL. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +`table_info()` performs a case-sensitive search. So, a selection +criterion should respect upper and lower case. +Normally, an identifier is case-insensitive. Oracle stores and +returns it in upper case. Sometimes, database objects are created +with quoted identifiers (for reserved words, mixed case, special +characters, ...). Such an identifier is case-sensitive (if not all +upper case). Oracle stores and returns it as given. +`table_info()` has no special quote handling, neither adds nor +removes quotes. + +## __primary_key_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary key constraint was created without an identifier, +PK_NAME contains a system generated name with the form SYS_Cn. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __foreign_key_info()__ + +This method (currently) supports the extended behaviour of SQL/CLI, i.e. the +result set contains foreign keys that refer to primary __and__ alternate keys. +The field UNIQUE_OR_PRIMARY distinguishes these keys. + +Oracle does not support catalogues, so `$pk_catalog` and `$fk_catalog` are +ignored as selection criteria (in the new style interface). +The UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always +NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary or foreign key constraints were created without an identifier, +UK_NAME or FK_NAME contains a system generated name with the form SYS_Cn. + +The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle (currently) +does not support other actions. + +The DELETE_RULE field may contain wrong values. This is a known Bug (#1271663) +in Oracle's data dictionary views. Currently (as of 8.1.7), 'RESTRICT' and +'SET DEFAULT' are not supported, 'CASCADE' is mapped correctly and all other +actions (incl. 'SET NULL') appear as 'NO ACTION'. + +The DEFERABILITY field is always NULL, because this columns is +not present in the ALL_CONSTRAINTS view of older Oracle releases. + +The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, +FK_TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __column_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + +Don't rely on the values of the BUFFER_LENGTH field! +Especially the length of FLOATs may be wrong. + +Datatype codes for non-standard types are subject to change. + +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +It is possible with Oracle to make the names of the various DB objects (table,column,index etc) +case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + +So in the example the exact case "Bla_BLA" must be used to get it info on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + +any case can be used to get info on the column. + +## __selectrow_array__ + + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + +Returns an array of row information after preparing and executing the provided SQL string. The rows are returned +by calling [fetchrow_array](#pod_fetchrow_array). The string can also be a statement handle generated by a previous prepare. Note that +only the first row of data is returned. If called in a scalar context, only the first column of the first row is +returned. Because this is not portable, it is not recommended that you use this method in that way. + +## __selectrow_arrayref__ + + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an array, by internal use of +the [fetchrow_arrayref](#pod_fetchrow_arrayref) method. + +## __selectrow_hashref__ + + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an hash, by internal use of +the [fetchrow_hashref](#pod_fetchrow_hashref) method. + +## __clone__ + + $other_dbh = $dbh->clone(); + +Creates a copy of the database handle by connecting with the same parameters as the original +handle, then trying to merge the attributes. See the DBI documentation for complete usage. + +# DATABASE HANDLE ATTRIBUTES + +## __AutoCommit__ (boolean) + +Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change +in the future, so it is highly recommended that you explicitly set it when +calling [connect](#pod_connect). + +## __ReadOnly__ (boolean) + + $dbh->{ReadOnly} = 1; + +Specifies if the current database connection should be in read-only mode or not. + +Please not that this method is not foolproof: there are still ways to update the +database. Consider this a safety net to catch applications that should not be +issuing commands such as INSERT, UPDATE, or DELETE. + +This method method requires DBI version 1.55 or better. + +## __Name__ (string, read-only) + +Returns the name of the current database. This is the same as the DSN, without the +"dbi:Oracle:" part. + +## __Username__ (string, read-only) + +Returns the name of the user connected to the database. + +## __Driver__ (handle, read-only) + +Holds the handle of the parent driver. The only recommended use for this is to find the name +of the driver using: + + $dbh->{Driver}->{Name} + +## __RowCacheSize__ + +DBD::Oracle supports both Server pre-fetch and Client side row caching. By default both +are turned on to give optimum performance. Most of the time one can just let DBD::Oracle +figure out the best optimization. + +### __Row Caching__ + +Row caching occurs on the client side and the object of it is to cut down the number of round +trips made to the server when fetching rows. At each fetch a set number of rows will be retrieved +from the server and stored locally. Further calls the server are made only when the end of the +local buffer(cache) is reached. + +Rows up to the specified top level row +count `RowCacheSize` are fetched if it occupies no more than the specified memory usage limit. +The default value is 0, which means that memory size is not included in computing the number of rows to prefetch. If +the `RowCacheSize` value is set to a negative number then the positive value of RowCacheSize is used +to compute the number of rows to prefetch. + +By default `RowCacheSize` is automatically set. If you want to totally turn off prefetching set this to 1. + +For any SQL statement that contains a LOB, Long or Object Type Row Caching will be turned off. However server side +caching still works. If you are only selecting a LOB Locator then Row Caching will still work. + +### Row Prefetching + +Row prefetching occurs on the server side and uses the DBI database handle attribute `RowCacheSize` and or the +Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improved performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. + +The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first +fetch that sets the current_positon to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are +loaded into the buffer and DBD::Oracle will not have to go back to the server for more rows. When record 11 is fetched DBD::Oracle +fetches and returns this row and the next 9 rows are loaded into the buffer. In this case if you fetch backwards from 10 to 1 +no server round trips are made. + +With large record sets it is best not to attempt to go to the last record as this may take some time, A large buffer size might even slow down +the fetch. If you must get the number of rows in a large record set you might try using an few large OCI_FETCH_ABSOLUTEs and then an OCI_FETCH_LAST, +this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. +If one requires only the first few rows there is no need to set a large prefetch value. + +If the ora_prefetch_memory less than 1 or not present then memory size is not included in computing the +number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it +is not included in the computing of the prefetch rows. + +# ORACLE-SPECIFIC STATEMENT HANDLE METHODS + +## __ora_stmt_type__ + +Returns the OCI Statement Type number for the SQL of a statement handle. + +## __ora_stmt_type_name__ + +Returns the OCI Statement Type name for the SQL of a statement handle. + +# DBI STATEMENT HANDLE OBJECT METHODS + +## __bind_param__ + + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + +Allows the user to bind a value and/or a data type to a placeholder. + +The value of `$param_num` is a number if using the '?' or if using ":foo" style placeholders, the complete name +(e.g. ":foo") must be given. +The `$bind_value` argument is fairly self-explanatory. A value of `undef` will +bind a `NULL` to the placeholder. Using `undef` is useful when you want +to change just the type and will be overwriting the value later. +(Any value is actually usable, but `undef` is easy and efficient). + +The `\%attr` hash is used to indicate the data type of the placeholder. +The default value is "varchar". If you need something else, you must +use one of the values provided by DBI or by DBD::Pg. To use a SQL value, +modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + +This will import some constants into your script. You can plug those +directly into the [bind_param](#pod_bind_param) call. Some common ones that you will +encounter are: + + SQL_INTEGER + +To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + +You can then set the data types by setting the value of the `ora_type` +key in the hash passed to [bind_param](#pod_bind_param). +The current list of Oracle data types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +Data types are "sticky," in that once a data type is set to a certain placeholder, +it will remain for that placeholder, unless it is explicitly set to something +else afterwards. If the statement has already been prepared, and you switch the +data type to something else, DBD::Oracle will re-prepare the statement for you before +doing the next execute. + +Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + +These attributes may be used in the `\%attr` parameter of the +L or L statement handle methods. + +- ora_type + +Specify the placeholder's datatype using an Oracle datatype. +A fatal error is raised if `ora_type` and the DBI `TYPE` attribute +are used for the same placeholder. +Some of these types are not supported by the current version of +DBD::Oracle and will cause a fatal error if used. +Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + +Potentially useful values when DBD::Oracle was built using OCI 7 and later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + +Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + +Additional values when DBD::Oracle was built using OCI 9.2 and later: + + SQLT_CHR, SQLT_BIN + +See [Binding Cursors](#pod_Binding Cursors) for the correct way to use ORA_RSET. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for how to use ORA_CLOB and ORA_BLOB. + +See [SYS.DBMS_SQL datatypes](#pod_SYS.DBMS_SQL datatypes) for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. + +See [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) for the correct way to use SQLT_CHR and SQLT_BIN. + +See [Other Data Types](#pod_Other Data Types) for more information. + +See also L. + +- ora_csform + +Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values +are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can +be imported from the DBD::Oracle module. Rarely needed. + +- ora_csid + +Specify the _integer_ OCI_ATTR_CHARSET_ID for the bind value. +Character set names can't be used currently. + +- ora_maxdata_size + +Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. +May be needed if a character set conversion from client to server +causes the data to use more space and so fail with a truncation error. + +- ora_maxarray_numentries + +Specify the maximum number of array entries to allocate. Used with +ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of +array entries Oracle can pass back to you in OUT variable of type +TABLE OF ... . + +- ora_internal_type + +Specify internal data representation. Currently is supported only for +ORA_NUMBER_TABLE. + +### Optimizing Results + +#### Prepare Postponed Till Execute + +The DBD::Oracle module can avoid an explicit 'describe' operation +prior to the execution of the statement unless the application requests +information about the results (such as $sth->{NAME}). This reduces +communication with the server and increases performance (reducing the +number of PARSE_CALLS inside the server). + +However, it also means that SQL errors are not detected until +`execute()` (or $sth->{NAME} etc) is called instead of when +`prepare()` is called. Note that if the describe is triggered by the +use of $sth->{NAME} or a similar attribute and the describe fails then +_an exception is thrown_ even if `RaiseError` is false! + +Set [ora_check_sql](#pod_ora_check_sql) to 0 in prepare() to enable this behaviour. + +## __bind_param_inout__ + + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + +DBD::Oracle fully supports bind_param_inout below are some uses for this method. + +### __Returning A Value from an INSERT__ + +Oracle supports an extended SQL insert syntax which will return one +or more of the values inserted. This can be particularly useful for +single-pass insertion of values with re-used sequence values +(avoiding a separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + +If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + +If you have many rows to insert you can take advantage of Oracle's built in execute array feature +with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + +Which will return all the ids into @out_values. + +- __Note:__ + +- This will only work for numbered (?) placeholders, + +- The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle + +- The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + +### Returning A Recordset + +DBD::Oracle does not currently support binding a PL/SQL table (aka array) +as an IN OUT parameter to any Perl data structure. You cannot therefore call +a PL/SQL function or procedure from DBI that uses a non-atomic datatype as +either a parameter, or a return value. However, if you are using Oracle 9.0.1 +or later, you can make use of table (or pipelined) functions. + +For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + +Currently, there is no way to directly call the function +Array_Example.Array_Func from DBI. However, by making the following relatively +painless additions, its not only possible, but extremely efficient. + +First, you need to create database object types that correspond to the record +and table types in the package. From the above example, these would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + +Now, assuming the existing function needs to remain unchanged (it is probably +being called from other PL/SQL code), we need to add a new function to the +package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + +As you can see, the new function is very simple. Now, it is a simple matter +of calling the function as a straight-forward SELECT from your DBI code. From +the above example, the code would look something like this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + +### __SYS.DBMS_SQL datatypes__ + +DBD::Oracle has built-in support for __SYS.DBMS_SQL.VARCHAR2_TABLE__ +and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +- __Note:__ + +- Take careful note that we use '\\@arr' here because the 'bind_param_inout' + will only take a reference to a scalar. + +### __ORA_VARCHAR2_TABLE__ + +SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. +( in bind_param() and bind_param_inout() ). When you bind array, you need +to specify full buffer size for OUT data. So, there are two parameters: +_max_len_ (specified as 3rd argument of bind_param_inout() ), +and _ora_maxarray_numentries_. They define maximum array entry length and +maximum rows, that can be passed to Oracle and back to you. In this +example we send array with 1 element with length=3, but allocate space for 100 +Oracle array entries with maximum length 10 of each. So, you can get no more +than 100 array entries with length <= 10. + +If you set _max_len_ to zero, maximum array entry length is calculated +as maximum length of entry of array bound. If 0 < _max_len_ < length( $some_element ), +truncation occur. + +If you set _ora_maxarray_numentries_ to zero, current (at bind time) bound +array length is used as maximum. If 0 < _ora_maxarray_numentries_ < scalar(@array), +not all array entries are bound. + +### __ORA_NUMBER_TABLE__ + +SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. +The main difference is internal data representation. Currently 2 types of +bind is allowed : as C-integer, or as C-double type. To select one of them, +you may specify additional bind parameter _ora_internal_type_ as either +__SQLT_INT__ or __SQLT_FLT__ for C-integer and C-double types. +Integer size is architecture-specific and is usually 32 or 64 bit. +Double is standard IEEE 754 type. + +_ora_internal_type_ defaults to double (SQLT_FLT). + +_max_len_ is ignored for OCI_NUMBER_TABLE. + +Currently, you cannot bind full native Oracle NUMBER(38). If you really need, +send request to dbi-dev list. + +The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + +If you change bind type to __SQLT_INT__, like: + + ora_internal_type => SQLT_INT + +you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + +## __bind_param_inout_array__ + +DBD::Oracle supports this undocumented feature of DBI. See [Returning A Value from an INSERT](#pod_Returning A Value from an INSERT) for an example. + +## __bind_param_array__ + + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + +Binds an array of values to a placeholder, so that each is used in turn by a call +to the [execute_array](#pod_execute_array) method. + +## __execute__ + + $rv = $sth->execute(@bind_values); + +Perform whatever processing is necessary to execute the prepared statement. + +## __execute_array__ + + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + +Execute a prepared statement once for each item in a passed-in hashref, or items that +were previously bound via the [bind_param_array](#pod_bind_param_array) method. See the DBI documentation +for more details. + +DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very +quickly. + +## __execute_for_fetch__ + + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + +Used internally by the [execute_array](#pod_execute_array) method, and rarely used directly. See the +DBI documentation for more details. + +## __fetchrow_arrayref__ + + $ary_ref = $sth->fetchrow_arrayref; + +Fetches the next row of data from the statement handle, and returns a reference to an array +holding the column values. Any columns that are NULL are returned as undef within the array. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +Note that the same array reference is returned for each fetch, so don't store the reference and +then use it after a later fetch. Also, the elements of the array are also reused for each row, +so take care if you want to take a reference to an element. See also [bind_columns](#pod_bind_columns). + +## __fetchrow_array__ + + @ary = $sth->fetchrow_array; + +Similar to the [fetchrow_arrayref](#pod_fetchrow_arrayref) method, but returns a list of column information rather than +a reference to a list. Do not use this in a scalar context. + +## __fetchrow_hashref__ + + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + +Fetches the next row of data and returns a hashref containing the name of the columns as the keys +and the data itself as the values. Any NULL value is returned as as undef value. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +The optional `$name` argument should be either `NAME`, `NAME_lc` or `NAME_uc`, and indicates +what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. + +## __fetchall_arrayref__ + + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + +Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the +statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, +the data read in so far will be returned. Because of this, you should always check `$sth->err` after +calling this method, unless [RaiseError](#pod_RaiseError) has been enabled. + +If `$slice` is an array reference, fetchall_arrayref uses the [fetchrow_arrayref](#pod_fetchrow_arrayref) method to fetch each +row as an array ref. If the `$slice` array is not empty then it is used as a slice to select individual +columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). + +With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. + +If `$slice` is a hash reference, fetchall_arrayref uses [fetchrow_hashref](#pod_fetchrow_hashref) to fetch each row as a hash reference. + +See the DBI documentation for a complete discussion. + +## __fetchall_hashref__ + + $hash_ref = $sth->fetchall_hashref( $key_field ); + +Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for +a full discussion. + +## __finish__ + + $rv = $sth->finish; + +Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed +when you have not fetched all the possible rows. + +## __rows__ + + $rv = $sth->rows; + +Returns the number of rows affected for updates, deletes and inserts and -1 for selects. + +## __bind_col__ + + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + +Binds a Perl variable and/or some attributes to an output column of a SELECT statement. +Column numbers count up from 1. You do not need to bind output columns in order to fetch data. + +NOTE: DBD::Oracle does not use the `$bind_type` to determine how to +bind the column; it uses what Oracle says the data type is. You can +however set a numeric bind type with the bind attributes +StrictlyTyped/DiscardString as these attributes are applied after the +column is retrieved. + +See the DBI documentation for a discussion of the optional parameters `\%attr` and `$bind_type` + +## __bind_columns__ + + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + +Calls the [bind_col](#pod_bind_col) method for each column in the SELECT statement, using the supplied list. + +## __dump_results__ + + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + +Fetches all the rows from the statement handle, calls `DBI::neat_list` for each row, and +prints the results to `$fh` (which defaults to `STDOUT`). Rows are separated by `$lsep` (which defaults +to a newline). Columns are separated by `$fsep` (which defaults to a comma). The `$maxlen` controls +how wide the output can be, and defaults to 35. + +This method is designed as a handy utility for prototyping and testing queries. Since it uses +"neat_list" to format and edit the string for reading by humans, it is not recommended +for data transfer applications. + +# STATEMENT HANDLE ATTRIBUTES + +## __NUM_OF_FIELDS__ (integer, read-only) + +Returns the number of columns returned by the current statement. A number will only be returned for +SELECT statements for INSERT, +UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NUM_OF_PARAMS__ (integer, read-only) + +Returns the number of placeholders in the current statement. + +## __NAME__ (arrayref, read-only) + +Returns an arrayref of column names for the current statement. This +method will only work for SELECT statements, for SHOW statements, and for +INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NAME_lc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to lower case. + +## __NAME_uc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to upper case. + +## __NAME_hash__ (hashref, read-only) + +Similar to the `NAME` attribute, but returns a hashref of column names instead of an arrayref. The names of the columns +are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. +This method returns undef if called before `execute()`. + +## __NAME_lc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __NAME_uc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __TYPE__ (arrayref, read-only) + +Returns an arrayref indicating the data type for each column in the statement. +This method returns undef if called before `execute()`. + +## __PRECISION__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. +The number indicates the precision for `NUMERIC` columns, the size in number of +characters for `CHAR` and `VARCHAR` columns, and for all other types of columns +it returns the number of _bytes_. +This method returns undef if called before `execute()`. + +## __SCALE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates the scale of the that column. The only type that will return a value is `NUMERIC`. +This method returns undef if called before `execute()`. + +## __NULLABLE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates if the column is nullable or not. 0 = not nullable, 1 = nullable, 2 = unknown. +This method returns undef if called before `execute()`. + +## __Database__ (dbh, read-only) + +Returns the database handle this statement handle was created from. + +## __ParamValues__ (hash ref, read-only) + +Returns a reference to a hash containing the values currently bound to placeholders. If the "named parameters" +type of placeholders are being used (such as ":foo"), then the keys of the hash will be the names of the +placeholders (without the colon). If the "dollar sign numbers" type of placeholders are being used, the keys of the hash will +be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, +starting at one and increasing for every placeholder. + +If this method is called before [execute](#pod_execute), the literal values passed in are returned. If called after +[execute](#pod_execute), then the quoted versions of the values are returned. + +## __ParamTypes__ (hash ref, read-only) + +Returns a reference to a hash containing the type names currently bound to placeholders. The keys +are the same as returned by the ParamValues method. The values are hashrefs containing a single key value +pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can +only be expressed by a Postgres type. The value is the internal number corresponding to the type originally +passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of +ParamTypes to be passed back to the [bind_param](#pod_bind_param) method. + +## __Statement__ (string, read-only) + +Returns the statement string passed to the most recent "prepare" method called in this database handle, even if that method +failed. This is especially useful where "RaiseError" is enabled and the exception handler checks $@ and sees that a `prepare` +method call failed. + +## __RowsInCache__ + +Returns the number of un-fetched rows in the cache for selects. + +# SCROLLABLE CURSORS + +Oracle supports the concept of a 'Scrollable Cursor' which is defined as a 'Result Set' where +the rows can be fetched either sequentially or non-sequentially. One can fetch rows forward, +backwards, from any given position or the n-th row from the current position in the result set. + +Rows are numbered sequentially starting at one and client-side caching of the partial or entire result set +can improve performance by limiting round trips to the server. + +Oracle does not support DML type operations with scrollable cursors so you are limited +to simple 'Select' operations only. As well you can not use this functionality with remote +mapped queries or if the LONG datatype is part of the select list. + +However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch methods. + +Only use scrollable cursors if you really have a good reason to. They do use up considerable +more server and client resources and have poorer response times than non-scrolling cursors. + +## Enabling Scrollable Cursors + +To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + +Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the +statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + +When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row +or you can still use any of the other fetch methods but with a poorer response time than if you used a +non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. + +## Scrollable Cursor Methods + +The following driver-specific methods are used with scrollable cursors. + +- ora_scroll_position + + $position = $sth->ora_scroll_position(); + +This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time +this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. +The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. + +- ora_fetch_scroll + + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + +Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset +value which will then determine the row that will be fetched. It returns the row as a list containing the field values. +Null fields are returned as _undef_ values in the list. + +The valid orientation constant and fetch offset values combination are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + +The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + +The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + +## Scrollable Cursor Usage + +Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + +and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll +method; + +- Fetching the Last Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +if the record set is large this could take some time. + +- Fetching the Current Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will still be 20 after this snippet. + +- Fetching the First Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the Next Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 5 after this snippet. + +- Fetching the Prior Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the 10th Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 10th to 14th Row + + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 14 after this snippet. + +- Fetching the 14th to 10th Row + + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 5th Row From the Present Position. + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 15 after this snippet. + +- Fetching the 9th Row Prior From the Present Position + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 6 after this snippet. + +- Use Finish + + $sth->finish(); + +When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of +cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. + +# LOBS AND LONGS + +The key to working with LOBs (CLOB, BLOBs) is to remember the value of an Oracle LOB column is not the content of the LOB. It's a +'LOB Locator' which, after being selected or inserted needs extra processing to read or write the content of the LOB. There are also legacy LONG types (LONG, LONG RAW, VARCHAR2) +which are presently deprecated by Oracle but are still in use. These LONG types do not utilize a 'LOB Locator' and also are more limited in +functionality than CLOB or BLOB fields. + +DBD::Oracle now offers three interfaces to LOB and LONG data, + +- [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) + +With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of +BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. + +- [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) + +With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. + +- [LOB Locator Method Interface](#pod_LOB Locator Method Interface) + +This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. + +Generally speaking the interface that you will chose will be dependent on what end you are trying to achieve. All have their benefits and +drawbacks. + +One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB column can be in one of three states; + +- NULL + +The table cell is created, but the cell holds no locator or value. +If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + +error when working with a LOB. + +You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + +- Empty + +A LOB instance with a locator exists in the cell, but it has no value. The length of the LOB is zero. In this case DBD::Oracle will return 'undef' for the field. + +- Populated + +A LOB instance with a locator and a value exists in the cell. You actually get the LOB value. + +## Data Interface for Persistent LOBs + +This is the original interface for LONG and LONG RAW datatypes and from Oracle 9iR1 and later the OCI API was extended to work directly with the other LOB datatypes. +In other words you can treat all LOB type data (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using the same techniques +you would use on other datatypes that store character or binary data. In some cases there are fewer round trips to the server as no 'LOB Locators' are +used, normally one can get an entire LOB is a single round trip. + +### Simple Fetch for LONGs and LONG RAWs + +As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG datatypes as a single large piece. +There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. +If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into +an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. + +For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the long1 fields but they will be truncated at 2MBs. + +### Using ora_ncs_buff_mtpl + +When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the +Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. +Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. + +However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer +value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes +but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes +(maybe less characters though) but you are using allot more memory that you need. + +You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can +also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. + +The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the +ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. + +If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + +This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) + +If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. + +This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. + +You can tune this value by setting ora_oci_success_warn which will display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + +In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. + +### Simple Fetch for CLOBs and BLOBs + +To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well +set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds +the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. + +For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this +and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. + +It seems with BLOBs you are not limited by the 64k. + +For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the lobs but they will be truncated at 2MBs. + +### Piecewise Fetch with Callback + +With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. +To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Simple Fetch for LONGs and LONG RAWs](#pod_Simple Fetch for LONGs and LONG RAWs) and [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is +dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. + +Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +#### Piecewise Fetch with Polling + +With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' +attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback). + +Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. + +Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +### Binding for Updates and Inserts for CLOBs and BLOBs + +To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method +'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + +So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. + +### Support for Remote LOBs; + +Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + +to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Below are the limitations of Remote LOBs; + +- Queries involving more than one database are not supported; + +so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + +as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + +- DDL commands are not supported; + +so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + +- Only binds and defines for data going into remote persistent LOBs are supported. + +so that parameter passing in PL/SQL where CHAR data is bound or defined for remote LOBs is not allowed . + +These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + +- If the remote object is a view such as + + CREATE VIEW v AS SELECT foo() FROM ... + +the following would not work: + + SELECT * FROM v@dbs2; + +- Limited PL/SQL parameter passing + +PL/SQL parameter passing is not allowed where the actual argument is a LOB type +and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. + +- RETURNING INTO does not support implicit conversions between CHAR and CLOB. + +so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + +## Locator Data Interface + +### Simple Usage + +When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob with the LongReadLen and LongTruncOk attributes. +The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +When inserting or updating LOBs some _major_ magic has to be performed +behind the scenes to make it transparent. Basically the driver has to +insert a 'LOB Locator' and then refetch the newly inserted LOB +Locator before being able to write the data into it. However, it works +well most of the time, and I've made it as fast as possible, just one +extra server-round-trip per insert or update after the first. For the +time being, only single-row LOB updates are supported. + +To insert or update a large LOB using a placeholder, DBD::Oracle has to +know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + +The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + +or use the corresponding integer values (112 and 113). + +One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has +to be able to tell which parameters relate to which table fields. +In all cases where it can possibly work it out for itself, it does, +however, if there are multiple LOB fields of the same type in the table +then you need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + +There are some limitations inherent in the way DBD::Oracle makes typical +LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + +The alternative is to disable the automatic LOB Locator processing. +If [ora_auto_lob](#pod_ora_auto_lob) is 0 in prepare(), you can fetch the LOB Locators and +do all the work yourself using the ora_lob_*() methods. +See the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) section below. + +### LOB support in PL/SQL + +LOB Locators can be passed to PL/SQL calls by binding them to placeholders +with the proper `ora_type`. If [ora_auto_lob](#pod_ora_auto_lob) is true, output LOB +parameters will be automatically returned as strings. + +If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), +strings can be bound to input LOB placeholders and will be automatically +converted to LOBs. + +Example: + # Build a large XML document, bind it as a CLOB, + # extract elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + +If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + +error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. +One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. + +## Persistent & Locator Interface Caveats + +Now that one has the option of using the Persistent or the Locator interface for LOBs the questions arises +which one to use. For starters, if you want to access LOBs over a dblink you will have to use the Persistent +interface so that choice is simple. The question of which one to use after that is a little more tricky. +It basically boils down to a choice between LOB size and speed. + +The Callback and Polling piecewise fetches are very very slow +when compared to the Simple and the Locator fetches but they can handle very large blocks of data. Given a situation where a +large LOB is to be read the Locator fetch may time out while either of the piecewise fetches may not. + +With the Simple fetch you are limited by physical memory of your server but it runs a little faster than the Locator, as there are fewer round trips +to the server. So if you have small LOBs and need to save a little bandwidth this is the one to use. It you are going after large LOBs then the Locator interface is the one to use. + +If you need to update more than a single row of with LOB data then the Persistent interface can do it while the Locator can't. + +If you encounter a situation where you have to access the legacy LOBs (LONG, LONG RAW) and the values are to large for you system then you can use +the Callback or Polling piecewise fetches to get all of the data. + +Not all of the Persistent interface has been implemented yet, the following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + +Most of the time you should just use the [Locator Data Interface](#pod_Locator Data Interface) as this is in one that has the best combination of speed and size. + +All this being said if you are doing some critical programming I would use the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) as this gives you very +fine grain control of your LOBs, of course the code for this will be somewhat more involved. + +## Data Interface for LOB Locators + +The following driver-specific methods let you manipulate "LOB Locators" directly. +To select a LOB locator directly set the if the `ora_auto_lob` +attribute to false, or alternatively they can be returned via PL/SQL procedure calls. + +(If using a DBI version earlier than 1.36 they must be called via the +func() method. Note that methods called via func() don't honour +RaiseError etc, and so it's important to check $dbh->err after each call. +It's recommended that you upgrade to DBI 1.38 or later.) + +Note that LOB locators are only valid while the statement handle that +created them is valid. When all references to the original statement +handle are lost, the handle is destroyed and the locators are freed. + +- ora_lob_read + + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + +Read a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobRead function. + +- ora_lob_write + + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + +Write/overwrite a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobWrite function. + +- ora_lob_append + + $rc = $dbh->ora_lob_append($lob_locator, $data); + +Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + +- ora_lob_trim + + $rc = $dbh->ora_lob_trim($lob_locator, $length); + +Trims the length of the LOB to $length. +Uses the Oracle OCILobTrim function. + +- ora_lob_length + + $length = $dbh->ora_lob_length($lob_locator); + +Returns the length of the LOB. +Uses the Oracle OCILobGetLength function. + +- ora_lob_is_init + + $is_init = $dbh->ora_lob_is_init($lob_locator); + +Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' +if there is an error. +Uses the Oracle OCILobLocatorIsInit function. + +- ora_lob_chunk_size + + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + +Returns the chunk size of the LOB. +Uses the Oracle OCILobGetChunkSize function. + +For optimal performance, Oracle recommends reading from and +writing to a LOB in batches using a multiple of the LOB chunk size. +In Oracle 10g and before, when all defaults are in place, this +chunk size defaults to 8k (8192). + +### LOB Locator Method Examples + +_Note:_ Make sure you first read the note in the section above about +multi-byte character set issues with these methods. + +The following examples demonstrate the usage of LOB Locators +to read, write, and append data, and to query the size of +large data. + +The following examples assume a table containing two large +object columns, one binary and one character, with a primary +key column, defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + +It also assumes a sequence for use in generating unique +lob_id field values, defined as follows: + + CREATE SEQUENCE lob_example_seq + +### Example: Inserting a new row with large data + +Unless enough memory is available to store and bind the +entire LOB data for insert all at once, the LOB columns must +be written interactively, piece by piece. In the case of a new row, +this is performed by first inserting a row, with empty values in +the LOB columns, then modifying the row by writing the large data +interactively to the LOB columns using their LOB locators as handles. + +The insert statement must create token values in the LOB +columns. Here, we use the empty string for both the binary +and character large object columns 'bindata' and 'chardata'. + +After the INSERT statement, a SELECT statement is used to +acquire LOB locators to the 'bindata' and 'chardata' fields +of the newly inserted row. Because these LOB locators are +subsequently written, they must be acquired from a select +statement containing the clause 'FOR UPDATE' (LOB locators +are only valid within the transaction that fetched them, so +can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + +In this example we demonstrate the use of ora_lob_write() +interactively to append data to the columns 'bin_data' and +'char_data'. Had we used ora_lob_append(), we could have +saved ourselves the trouble of keeping track of the offset +into the lobs. The snippet of code beneath the comment +'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + +The scalar variables $offset and $length are no longer +needed, because ora_lob_append() keeps track of the offset +for us. + +### Example: Updating an existing row with large data + +In this example, we demonstrate a technique for overwriting +a portion of a blob field with new binary data. The blob +data before and after the section overwritten remains +unchanged. Hence, this technique could be used for updating +fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + +After running this code, the row where lob_id = 5 will +contain, starting at position 100234 in the bin_data column, +the string "This string will overwrite a portion of the blob". + +### Example: Streaming character data from the database + +In this example, we demonstrate a technique for streaming +data from the database to a file handle, in this case +STDOUT. This allows more data to be read in and written out +than could be stored in memory at a given time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + +Notice that the select statement does not contain the phrase +"FOR UPDATE". Because we are only reading from the LOB +Locator returned, and not modifying the LOB it refers to, +the select statement does not require the "FOR UPDATE" +clause. + +A word of caution when using the data returned from an ora_lob_read in a conditional statement. +for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + +was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return +the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte +as $data will contain 0 which PERL will see as false and not print it out. + +### Example: Truncating existing large data + +In this example, we truncate the data already present in a +large object column in the database. Specifically, for each +row in the table, we truncate the 'bindata' value to half +its previous length. + +After acquiring a LOB Locator for the column, we query its +length, then we trim the length by half. Because we modify +the large objects with the call to ora_lob_trim(), we must +select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +# SPACES AND PADDING + +## Trailing Spaces + +Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder +values and uses Nonpadded Comparison Semantics with the result. +This causes trouble if the spaces are needed for +comparison with a CHAR value or to prevent the value from +becoming '' which Oracle treats as NULL. +Look for Blank-padded Comparison Semantics and Nonpadded +Comparison Semantics in Oracle's SQL Reference or Server +SQL Reference for more details. + +To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, +either change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or the placeholder +type for a particular call to L or L +with [ora_type](#pod_ora_type) or `TYPE`. +Using [ORA_CHAR](http://search.cpan.org/perldoc?ORA_CHAR) with [ora_type](http://search.cpan.org/perldoc?ora_type) or `SQL_CHAR` with `TYPE` +allows the placeholder to be used with Padded Comparison Semantics +if the value it is being compared to is a CHAR, NCHAR, or literal. + +Please remember that using spaces as a value or at the end of +a value makes visually distinguishing values with different +numbers of spaces difficult and should be avoided. + +Oracle Clients that use OCI 9.2 do not strip trailing spaces. + +## Padded Char Fields + +Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. +As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will +have to change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or placeholder +type for a particular call with L or L +with [ORA_CHAR](#pod_ORA_CHAR). + +# UNICODE + +DBD::Oracle now supports Unicode UTF-8. There are, however, a number +of issues you should be aware of, so please read all this section +carefully. + +In this section we'll discuss "Perl and Unicode", then "Oracle and +Unicode", and finally "DBD::Oracle and Unicode". + +Information about Unicode in general can be found at: +[http://www.unicode.org/](http://www.unicode.org/). It is well worth reading because there are +many misconceptions about Unicode and you may be holding some of them. + +## Perl and Unicode + +Perl began implementing Unicode with version 5.6, but the implementation +did not mature until version 5.8 and later. If you plan to use Unicode +you are _strongly_ urged to use Perl 5.8.2 or later and to _carefully_ read +the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + +And then read it again. + +Perl's internal Unicode format is UTF-8 +which corresponds to the Oracle character set called AL32UTF8. + +## Oracle and Unicode + +Oracle supports many characters sets, including several different forms +of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + +When you create an Oracle database, you must specify the DATABASE +character set (used for DDL, DML and CHAR datatypes) and the NATIONAL +character set (used for NCHAR and NCLOB types). +The character sets used in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + +The Oracle 9.2 and later default for the national character set is AL16UTF16. +The default for the database character set is often US7ASCII. +Although many experienced DBAs will consider an 8bit character set like +WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle +other than US7ASCII, requires that the NLS_LANG environment variable be set. +See the L<"Oracle UTF8 is not UTF-8"> section below. + +You are strongly urged to read the Oracle Internationalization documentation +specifically with respect the choices and trade offs for creating +a databases for use with international character sets. + +Oracle uses the NLS_LANG environment variable to indicate what +character set is being used on the client. When fetching data Oracle +will convert from whatever the database character set is to the client +character set specified by NLS_LANG. Similarly, when sending data to +the database Oracle will convert from the character set specified by +NLS_LANG to the database character set. + +The NLS_NCHAR environment variable can be used to define a different +character set for 'national' (NCHAR) character types. + +Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. +For example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + +## Oracle UTF8 is not UTF-8 + +AL32UTF8 should be used in preference to UTF8 if it works for you, +which it should for Oracle 9.2 or later. If you're using an old +version of Oracle that doesn't support AL32UTF8 then you should +avoid using any Unicode characters that require surrogates, in other +words characters beyond the Unicode BMP (Basic Multilingual Plane). + +That's because the character set that Oracle calls "UTF8" doesn't +conform to the UTF-8 standard in its handling of surrogate characters. +Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". +Here are a couple of extracts from [http://www.unicode.org/reports/tr26/](http://www.unicode.org/reports/tr26/): + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + +Oracle uses this internally because it collates (sorts) in the same order +as UTF16, which is the basis of Oracle's internal collation definitions. + +Rather than change UTF8 for clients Oracle chose to define a new character +set called "AL32UTF8" which does conform to the UTF-8 standard. +(The AL32UTF8 character set can't be used on the server because it +would break collation.) + +Because of that, for the rest of this document we'll use "AL32UTF8". +If you're using an Oracle version below 9.2 you'll need to use "UTF8" +until you upgrade. + +## DBD::Oracle and Unicode + +DBD::Oracle Unicode support has been implemented for Oracle versions 9 +or greater, and Perl version 5.6 or greater (though we _strongly_ +suggest that you use Perl 5.8.2 or later). + +You can check which Oracle version your DBD::Oracle was built with by +importing the `ORA_OCI` constant from DBD::Oracle. + +__Fetching Data__ + +Any data returned from Oracle to DBD::Oracle in the AL32UTF8 +character set will be marked as UTF-8 to ensure correct handling by Perl. + +For Oracle to return data in the AL32UTF8 character set the +NLS_LANG or NLS_NCHAR environment variable _must_ be set as described +in the previous section. + +When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR +is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + +When fetching other character data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + +__Sending Data using Placeholders__ + +Data bound to a placeholder is assumed to be in the default client +character set (specified by NLS_LANG) except for a few special +cases. These are listed here with the highest precedence first: + +If the `ora_csid` attribute is given to bind_param() then that +is passed to Oracle and takes precedence. + +If the value is a Perl Unicode string (UTF-8) then DBD::Oracle +ensures that Oracle uses the Unicode character set, regardless of +the NLS_LANG and NLS_NCHAR settings. + +If the placeholder is for inserting an NCLOB then the client NLS_NCHAR +character set is used. (That's useful but inconsistent with the other behaviour +so may change. Best to be explicit by using the `ora_csform` +attribute.) + +If the `ora_csform` attribute is given to bind_param() then that +determines if the value should be assumed to be in the default +(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + +or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + +Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to +insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert +will still happen but a error code of 0 will be returned with the following warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + +The warning will report the parameter number and the NCHAR setting that the query is running. + +__Sending Data using SQL__ + +Oracle assumes the SQL statement is in the default client character +set (as specified by NLS_LANG). So Unicode strings containing +non-ASCII characters should not be used unless the default client +character set is AL32UTF8. + +## DBD::Oracle and Other Character Sets and Encodings + +The only multi-byte Oracle character set supported by DBD::Oracle is +"AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +# OBJECT & COLLECTION DATA TYPES + +Oracle databases allow for the creation of object oriented like user-defined types. +There are two types of objects, Embedded--an object stored in a column of a regular table +and REF--an object that uses the REF retrieval mechanism. + +DBD::Oracle supports only the 'selection' of embedded objects of the following types OBJECT, VARRAY +and TABLE in any combination. Support is seamless and recursive, meaning you +need only supply a simple SQL statement to get all the values in an embedded object. +You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. + +Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + +The code to access all the data in the table could be something like this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + +Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. + +As stated before DBD::Oracle will automatically drill into the embedded object and extract +all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an +SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + +The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + +Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + +The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + +So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables +nested to 10 levels. + +Any NULL values found in the embedded object will be returned as 'undef'. + +# OTHER DATA TYPES + +DBD::Oracle does not _explicitly_ support most Oracle datatypes. +It simply asks Oracle to return them as strings and Oracle does so. +Mostly. Similarly when binding placeholder values DBD::Oracle binds +them as strings and Oracle converts them to the appropriate type, +such as DATE, when used. + +Some of these automatic conversions to and from strings use NLS +settings to control the formatting for output and the parsing for +input. The most common example is the DATE type. The default NLS +format for DATE might be DD-MON-YYYY and so when a DATE type is +fetched that's how Oracle will format the date. NLS settings also +control the default parsing of strings into DATE values. An error +will be generated if the contents of the string don't match the +NLS format. If you're dealing in dates which don't match the default +NLS format then you can either change the default NLS format or, more +commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") +to explicitly specify formats for converting to and from strings. + +A slightly more subtle problem can occur with NUMBER types. The +default NLS settings might format numbers with a fullstop ("`.`") +to separate thousands and a comma ("`,`") as the decimal point. +Perl will generate warnings and use incorrect values when numbers, +returned and formatted as strings in this way by Oracle, are used +in a numeric context. You could explicitly convert each numeric +value using the TO_CHAR(...) function but that gets tedious very +quickly. The best fix is to change the NLS settings. That can be +done for an individual connection by doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + +There are some types, like BOOLEAN, that Oracle does not automatically +convert to or from strings (pity). These need to be converted +explicitly using SQL or PL/SQL functions. + +Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + +#### Support for Insert of XMLType (ORA_XMLTYPE) + +Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special +requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For +example with a table like this; + + create table books (book_id number, book_xml XMLType); + +one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + +In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. +This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. + +#### Binding Cursors + +Cursors can be returned from PL/SQL blocks, either from stored +functions (or procedures with OUT parameters) or +from direct `OPEN` statements, as shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +The only special requirement is the use of `bind_param_inout()` with an +attribute hash parameter that specifies `ora_type` as `ORA_RSET`. +If you don't do that you'll get an error from the `execute()` like: +"ORA-06550: line X, column Y: PLS-00306: wrong number or types of +arguments in call to ...". + +Here's an alternative form using a function that returns a cursor. +This example uses the pre-defined weak (or generic) REF CURSOR type +SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +A cursor obtained from PL/SQL as above may be passed back to PL/SQL +by binding for input, as shown in this example, which explicitly +closes a cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + +It is not normally necessary to close a cursor +explicitly in this way. Oracle will close the cursor automatically +at the first client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to +the cursor handle from the PL/SQL statement handle delays the destruction +of the cursor handle for too long. This reference remains until the +PL/SQL handle is re-bound, re-executed or destroyed. + +See the `curref.pl` script in the Oracle.ex directory in the DBD::Oracle +source distribution for a complete working example. + +#### Fetching Nested Cursors + +Oracle supports the use of select list expressions of type REF CURSOR. +These may be explicit cursor expressions - `CURSOR(SELECT ...)`, or +calls to PL/SQL functions which return REF CURSOR values. The values +of these expressions are known as nested cursors. + +The value returned to a Perl program when a nested cursor is fetched +is a statement handle. This statement handle is ready to be fetched from. +It should not (indeed, must not) be executed. + +Oracle imposes a restriction on the order of fetching when nested +cursors are used. Suppose `$sth1` is a handle for a select statement +involving nested cursors, and `$sth2` is a nested cursor handle fetched +from `$sth1`. `$sth2` can only be fetched from while `$sth1` is +still active, and the row containing `$sth2` is still current in `$sth1`. +Any attempt to fetch another row from `$sth1` renders all nested cursor +handles previously fetched from `$sth1` defunct. + +Fetching from such a defunct handle results in an error with the message +`ERROR nested cursor is defunct (parent row is no longer current)`. + +This means that the `fetchall...` or `selectall...` methods are not useful +for queries returning nested cursors. By the time such a method returns, +all the nested cursor handles it has fetched will be defunct. + +It is necessary to use an explicit fetch loop, and to do all the +fetching of nested cursors within the loop, as the following example +shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + +The cursor returned by the function `sp_ListEmp` defined in the +previous section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + +#### Pre-fetching Nested Cursors + +By default, DBD::Oracle pre-fetches rows in order to reduce the number of +round trips to the server. For queries which do not involve nested cursors, +the number of pre-fetched rows is controlled by the DBI database handle +attribute `RowCacheSize` (q.v.). + +In Oracle, server side open cursors are a controlled resource, limited in +number, on a per session basis, to the value of the initialization +parameter `OPEN_CURSORS`. Nested cursors count towards this limit. +Each nested cursor in the current row counts 1, as does +each nested cursor in a pre-fetched row. Defunct nested cursors do not count. + +An Oracle specific database handle attribute, `ora_max_nested_cursors`, +further controls pre-fetching for queries involving nested cursors. For +each statement handle, the total number of nested cursors in pre-fetched +rows is limited to the value of this parameter. The default value +is 0, which disables pre-fetching for queries involving nested cursors. + +# PL/SQL Examples + +Most of these PL/SQL examples come from: Eric Bartley . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + +You can find more examples in the t/plsql.t file in the DBD::Oracle +source directory. + +Oracle 9.2 appears to have a bug where a variable bound +with bind_param_inout() that isn't assigned to by the executed +PL/SQL block may contain garbage. +See [http://www.mail-archive.com/dbi-users@perl.org/msg18835.html](http://www.mail-archive.com/dbi-users@perl.org/msg18835.html) + +## Avoid Using "SQL Call" + +Avoid using the "SQL Call" statement with DBD:Oracle as you might find that +DBD::Oracle will not raise an exception in some case. Specifically if you use +"SQL Call" to run a procedure all "No data found" exceptions will be quietly +ignored and returned as null. According to Oracle support this is part of the same +mechanism where; + + select (select * from dual where 0=1) from dual + +returns a null value rather than an exception. + +# CONTRIBUTING + +If you'd like DBD::Oracle to do something new or different the best way +to make that happen is to do it yourself and email to dbi-dev@perl.org a +patch of the source code (using 'diff' - see below) that shows the changes. + +## How to create a patch using Subversion + +The DBD::Oracle source code is maintained using Subversion (a replacement +for CVS, see [http://subversion.tigris.org/](http://subversion.tigris.org/)). To access the source +you'll need to install a Subversion client. Then, to get the source +code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + +If it prompts for a username and password use your perl.org account +if you have one, else just 'guest' and 'guest'. The source code will +be in a new subdirectory called `trunk`. + +To keep informed about changes to the source you can send an empty email +to dbd-oracle-changes-subscribe@perl.org after which you'll get an email with the +change log message and diff of each change checked-in to the source. + +After making your changes you can generate a patch file, but before +you do, make sure your source is still upto date using: + + svn update + +If you get any conflicts reported you'll need to fix them first. +Then generate the patch file from within the `trunk` directory using: + + svn diff > foo.patch + +Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. + +## How to create a patch without Subversion + +Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + +Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + +Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you want. + +Test your changes and then remove all temporary files: + + make test && make distclean + +Go back to the directory you originally unpacked the distribution: + + cd .. + +Unpack _another_ copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + +Then create a patch file by performing a recursive `diff` on the two +top level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + +## Speak before you patch + +For anything non-trivial or possibly controversial it's a good idea +to discuss (on dbi-dev@perl.org) the changes you propose before +actually spending time working on them. Otherwise you run the risk +of them being rejected because they don't fit into some larger plans +you may not be aware of. + +## GitHub repository + +A git mirror of the subversion is also available at +`https://github.com/yanick/DBD-Oracle`. + +# Oracle Related Links + +# WHICH VERSION OF DBD::ORACLE IS FOR ME? + +From version 1.25 onwards DBD::Oracle only support Oracle clients +9.2 or greater. Support for ProC connections was dropped in 1.29. + +If you are still stuck with an older version of Oracle or its client you might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + +As there are dozens of different versions of Oracle's clients this +list does not include all of them, just the major released versions of +Oracle. + +Note that one can still connect to any Oracle version with the older +DBD::Oracle versions the only problem you will have is that some of +the newer OCI and Oracle features available in later DBD::Oracle +releases will not be available to you. + +So to make a short story a little longer: + +- 1 + +If you are using Oracle 7 or early 8 DB and you can manage to get a 9 client and you can use +any DBD::Oracle version. + +- 2 + +If you have to use an Oracle 7 client then DBD::Oracle 1.17 should work + +- 3 + +Same thing for 8 up to R2, use 1.17, if you are lucky and have the right patch-set you might +go with 1.18. + +- 4 + +For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. Again this depends on your +patch-set, If you run into trouble go with 1.19 + +- 5 + +After 9.2 you can use any version you want. + +- 6 + +It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go back to 7 +and even get to 10. I am not sure what the 11g client can connect to. + +# BUGS AND LIMITATIONS + +There is a known problem with the 11.2g Oracle client and the +`DBMS_LOB.GETLENGTH()` PL/SQL function. +See [https://rt.cpan.org/Public/Bug/Display.html?id=69350](https://rt.cpan.org/Public/Bug/Display.html?id=69350) for the details. + +# SEE ALSO + +- [DBI](http://search.cpan.org/perldoc?DBI) + +http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in +the DBD::Oracle source distribution including the examples in the +Oracle.ex directory + +- DBD::Oracle Tutorial + +http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-oracle.html + +- Oracle Instant Client + +http://www.oracle.com/technology/tech/oci/instantclient/index.html + +- Oracle on Linux + +http://www.ixora.com.au/ + +- Free Oracle Tools and Links + +ora_explain supplied and installed with DBD::Oracle. + +http://www.orafaq.com/ + +http://vonnieda.org/oracletool/ + +- Commercial Oracle Tools and Links + +Assorted tools and references for general information. +No recommendation implied. + +http://www.platinum.com + +http://www.SoftTreeTech.com + +Also PL/Vision from RevealNet and Steven Feuerstein, and +"Q" from Savant Corporation. + +# AUTHORS + +DBI by Tim Bunce [http://www.tim.bunce.name](http://www.tim.bunce.name). + +The original `DBD::Oracle` was by Tim Bunce. +Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the +auspice of the Pythian Group ([http://www.pythian.com](http://www.pythian.com)). + +# ACKNOWLEDGEMENTS + +A great many people have helped with DBD::Oracle over the 17 years +between 1994 and 2011. Far too many to name, but we thank them all. +Many are named in the Changes file. + +# COPYRIGHT + +The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. +The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The Pythian Group). Canada. +The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. + +The DBD::Oracle module is free open source software; you can +redistribute it and/or modify it under the same terms as Perl 5. + +# AUTHORS + +- * + +Tim Bunce + +- * + +John Scoles + +- * + +Yanick Champoux + +# COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/dist.ini b/dist.ini deleted file mode 100644 index 013f79fc..00000000 --- a/dist.ini +++ /dev/null @@ -1,22 +0,0 @@ -name = DBD-Oracle -author = Tim Bunce -author = John Scoles -author = Yanick Champoux -license = Perl_5 -copyright_holder = Tim Bunce -copyright_year = 1994 - -version = 1.38 - -[Authority] -authority=cpan:PYTHIAN - -[MakeMaker::Custom] - -[@Filter] --bundle=@YANICK --remove=Author::YANICK::NextSemanticVersion --remove=ModuleBuild --remove=Authority --remove=Signature - diff --git a/err_bind/err_bind_param_inout_overrun_bug.msg b/err_bind/err_bind_param_inout_overrun_bug.msg deleted file mode 100644 index 83d9001f..00000000 --- a/err_bind/err_bind_param_inout_overrun_bug.msg +++ /dev/null @@ -1,108 +0,0 @@ -From dbi-users-return-215-Tim.Bunce=ig.co.uk@perl.org Mon Feb 5 23:03:29 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id XAA01289; Mon, 5 Feb 2001 23:03:27 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <06769-16@oink>; Fri, 6 Feb 1970 00:01:15 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 981413584:20:24069:0; Mon, 05 Feb 2001 22:53:04 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-2.mail.demon.net - id aa2024004; 5 Feb 2001 22:53 GMT -Received: (qmail 6267 invoked by uid 508); 5 Feb 2001 22:52:23 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6247 invoked from network); 5 Feb 2001 22:52:22 -0000 -Received: from seeme.dare.feddata.com (38.186.101.66) by tmtowtdi.perl.org - with SMTP; 5 Feb 2001 22:52:22 -0000 -Received: by seeme.dare.feddata.com; id OAA05466; - Mon, 5 Feb 2001 14:55:56 -0800 (PST) -Received: from ifyou.dare.feddata.com(38.186.101.111) by seeme.dare.feddata.com - via smap (4.1) id xma005448; Mon, 5 Feb 01 14:55:39 -0800 -Sender: oscar@dare.feddata.com -Message-ID: <3A7F2FB0.A1507582@pasadena.feddata.com> -Date: Mon, 05 Feb 2001 14:56:48 -0800 -From: Oscar DeMartino -Organization: Federal Data Corporation -X-Mailer: Mozilla 4.61 [en] (X11; U; SunOS 5.6 sun4u) -X-Accept-Language: en -MIME-Version: 1.0 -To: dbi-users@perl.org -Subject: Undetected error - Binding and Stored Procedures -Content-Type: multipart/alternative; - boundary="------------E1028F7A8304BE268EB8F67B" -Status: RO -Content-Length: 2042 -Lines: 66 - ---------------E1028F7A8304BE268EB8F67B -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -I am running Oracle 8.1.5 and am using many stored procedures. We -use returned cursors, and individual values. The problem is, when -a stored procedure is executed and the specified bound variable has not -be declared large enough to hold the returned value subsequent -bound variables do not get set and I cannot find any way to -automatically detect this. - -Example: - -The stored procedure takes 1-input value and returns three string -values. - -the stored procedure is prepared , so I get the statement handle. - -I bind the input variable, and then bind the three output variables (1, -2, & 3) -as 100 character strings. - -I then execute the statment handle. - -There do not appear to be any errors, after checking the returned value -(for the execute call), -and ->err and ->errstr are clean. - -variable 1 has the correct returned value. -BUT, output variable 2 & 3, have no value. - ------- -Executing the stored procedure using sqlplus (sql command line -interface) indicated: - -What really occured is that the returned output variables 1 & 3 were -under 100 characters long -output variable 2 was 120 characters long - ---------- - -I know I could make all output variables the max size allowed in the -database field -but this would seem to waste space in the perl code. Since the field in - -the database -is simply defined as a varchar2 with no size limitation (upto 32767). - ------ -Am I missing something about detecting that variables 2 & 3 did not get -stored correctly -by DBI::Oracle?? - - - --- -Oscar "Fred" DeMartino FFFFF DDDD CCC -320 N. Halstead Ave. Ste #160 F D D C C -Pasadena, CA 91107 FFF D D C -e-mail: Oscar.DeMartino@pasadena.feddata.com F D D C -Phone: (626)306-6649 F D D C C -Federal Data Corporation F DDDD CCC - - - ---------------E1028F7A8304BE268EB8F67B-- - diff --git a/err_bind/err_bindarrays.msg b/err_bind/err_bindarrays.msg deleted file mode 100644 index 8ca7a5d3..00000000 --- a/err_bind/err_bindarrays.msg +++ /dev/null @@ -1,241 +0,0 @@ -From cturner@redhat.com Tue Mar 27 06:01:56 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id GAA19714; Tue, 27 Mar 2001 06:01:56 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <13771-3@oink>; - Fri, 27 Mar 1970 06:00:50 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985668014:20:27605:3; Tue, 27 Mar 2001 04:40:14 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ab2125244; 27 Mar 2001 4:39 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id XAA32289 - for ; Mon, 26 Mar 2001 23:39:38 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2R4bvT12929; Mon, 26 Mar 2001 23:37:57 -0500 -Sender: cturner@redhat.com -To: Tim.Bunce@ig.co.uk -Subject: DBD::Oracle and OCI bound arrays -From: Chip Turner -Date: 26 Mar 2001 23:37:57 -0500 -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 980 -Lines: 29 - - -Hey Tim, - -The need to have true OCI bound arrays for DBD::Oracle has come up, -and it looks like I get the fun job of implementing them. Basically, -this will allow DBD::Oracle to do something the DCOracle python -library does. The idea is: - -my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -my @c1 = 'aa' .. 'zz'; -my @c2 = 'aaa' .. 'azz'; -$sth->execute(\@c1, \@c2); - -In other words, it populates the table with a single execute call, -passing two (or more) equally sized arrays in as references for bound -parameters. This has the potential to save a good amount of time, -especially for large datasets. - -This would pretty much be a proprietary extension for Oracle, though -similar uses could be done in other DBD's. - -Just thought I'd let you know what I was intending to do, and to see -if you had any interest in receiving it as a patch after I'm done. - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Tue Mar 27 09:29:48 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id JAA20809; Tue, 27 Mar 2001 09:29:42 +0100 (BST) -Date: Tue, 27 Mar 2001 09:29:41 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim.Bunce@ig.co.uk, dbi-dev@perl.org -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010327092941.D20616@ig.co.uk> -References: -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Mon, Mar 26, 2001 at 11:37:57PM -0500 -Content-Length: 1570 -Lines: 39 - -On Mon, Mar 26, 2001 at 11:37:57PM -0500, Chip Turner wrote: -> -> Hey Tim, -> -> The need to have true OCI bound arrays for DBD::Oracle has come up, -> and it looks like I get the fun job of implementing them. Basically, -> this will allow DBD::Oracle to do something the DCOracle python -> library does. The idea is: -> -> my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -> my @c1 = 'aa' .. 'zz'; -> my @c2 = 'aaa' .. 'azz'; -> $sth->execute(\@c1, \@c2); -> -> In other words, it populates the table with a single execute call, -> passing two (or more) equally sized arrays in as references for bound -> parameters. This has the potential to save a good amount of time, -> especially for large datasets. -> -> This would pretty much be a proprietary extension for Oracle, though -> similar uses could be done in other DBD's. -> -> Just thought I'd let you know what I was intending to do, and to see -> if you had any interest in receiving it as a patch after I'm done. - -I would *urge* you to discuss the implementation with me *before* -you get very far cutting code. - -And anyway, I think someone's already done much or all of the work. -Dig around in the dbi-dev archives. If you can't find the discussion -let me know. If you do, then ask them (via the dbi-dev list) what -the status is. - -I'm planning to make a DBI release next week and, hopefully, a -DBD::Oracle release the week after to cleare a backlog of patches I -have queued up. After that I'll be looking to add in the work of the -other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -Tim. - -From cturner@redhat.com Wed Mar 28 02:01:21 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id CAA27336; Wed, 28 Mar 2001 02:01:21 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <17151-9@oink>; - Sat, 28 Mar 1970 01:59:47 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985739868:20:27318:0; Wed, 28 Mar 2001 00:37:48 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ac2119835; 28 Mar 2001 0:37 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id TAA10445 - for ; Tue, 27 Mar 2001 19:37:35 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2S0ZoJ20115; Tue, 27 Mar 2001 19:35:50 -0500 -Sender: cturner@redhat.com -To: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -References: <20010327092941.D20616@ig.co.uk> -From: Chip Turner -Date: 27 Mar 2001 19:35:50 -0500 -In-Reply-To: <20010327092941.D20616@ig.co.uk> -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 1495 -Lines: 35 - -Tim Bunce writes: - -> I would *urge* you to discuss the implementation with me *before* -> you get very far cutting code. - -Unfortunately, it's a little late for this; I've mostly finished the -change (at least, enough for our needs), except for some review and -cleanups. It seems to work quite well (400 times faster than repeated -looping over a dataset) and passes all of DBD::Oracle's test suite. - -> And anyway, I think someone's already done much or all of the work. -> Dig around in the dbi-dev archives. If you can't find the discussion -> let me know. If you do, then ask them (via the dbi-dev list) what -> the status is. - -I checked as you suggest, but couldn't find any code, just discussion -of it. I'll check again, but it didn't seem that the person had put -it anywhere I could get at it. - -> I'm planning to make a DBI release next week and, hopefully, a -> DBD::Oracle release the week after to cleare a backlog of patches I -> have queued up. After that I'll be looking to add in the work of the -> other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -If you would like, the patch will probably be suitable for inclusion -by then, if you want it in by the next release. Should there be any -problems with it or its implementation, I'd be glad to clean it up if -you have interest in it (if not, that's cool too; we need it soon, -though, either way). - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Wed Mar 28 11:51:58 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id LAA00444; Wed, 28 Mar 2001 11:51:51 +0100 (BST) -Date: Wed, 28 Mar 2001 11:51:51 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010328115151.D29769@ig.co.uk> -References: <20010327092941.D20616@ig.co.uk> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Tue, Mar 27, 2001 at 07:35:50PM -0500 -Content-Length: 1786 -Lines: 40 - -On Tue, Mar 27, 2001 at 07:35:50PM -0500, Chip Turner wrote: -> Tim Bunce writes: -> -> > I would *urge* you to discuss the implementation with me *before* -> > you get very far cutting code. -> -> Unfortunately, it's a little late for this; I've mostly finished the -> change (at least, enough for our needs), except for some review and -> cleanups. It seems to work quite well (400 times faster than repeated -> looping over a dataset) and passes all of DBD::Oracle's test suite. - -I trust you've added some more tests for your new functionality! - -> > And anyway, I think someone's already done much or all of the work. -> > Dig around in the dbi-dev archives. If you can't find the discussion -> > let me know. If you do, then ask them (via the dbi-dev list) what -> > the status is. -> -> I checked as you suggest, but couldn't find any code, just discussion -> of it. I'll check again, but it didn't seem that the person had put -> it anywhere I could get at it. - -You could always ask them (CC me). - -> > I'm planning to make a DBI release next week and, hopefully, a -> > DBD::Oracle release the week after to cleare a backlog of patches I -> > have queued up. After that I'll be looking to add in the work of the -> > other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). -> -> If you would like, the patch will probably be suitable for inclusion -> by then, if you want it in by the next release. Should there be any -> problems with it or its implementation, I'd be glad to clean it up if -> you have interest in it (if not, that's cool too; we need it soon, -> though, either way). - -Thanks for the clean-up offer. Send it to me after I make the next -DBD::Oracle release (as a fresh patch over that version please - but -there shouldn't be too many changes). - -Tim. - diff --git a/err_bind/err_bindclobleak.msg b/err_bind/err_bindclobleak.msg deleted file mode 100644 index 1a31c760..00000000 --- a/err_bind/err_bindclobleak.msg +++ /dev/null @@ -1,58 +0,0 @@ -From PGWeiss@arity.com Thu Mar 9 09:51:45 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id JAA14948; Thu, 9 Mar 2000 09:51:43 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <27566-0@oink>; Mon, 9 Mar 1970 10:51:10 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 952595299:20:10439:68; Thu, 09 Mar 2000 09:48:19 GMT -Received: from image.arity.com ([140.239.104.130]) by punt-2.mail.demon.net - id aa2010598; 9 Mar 2000 9:47 GMT -Received: by image.arity.com with Internet Mail Service (5.5.2650.21) - id ; Thu, 9 Mar 2000 04:51:44 -0500 -Message-ID: -From: "Paul G. Weiss" -To: Perl-Win32-Database Mailing List , - "'Tim Bunce'" -Subject: Another CLOB related DBD::Oracle bug -Date: Thu, 9 Mar 2000 04:51:41 -0500 -MIME-Version: 1.0 -X-Mailer: Internet Mail Service (5.5.2650.21) -Content-Type: text/plain; charset="iso-8859-1" -Status: RO -Content-Length: 689 -Lines: 32 - -Binding a parameter to type ORA_CLOB causes a leak. -Consider: - -for (1..10000) -{ - for (1..100) - { - my $sth = $db->prepare('update item set descr = ? where id = ?'); - if ($leak) - { - $sth->bind_param(1, $descr, {ora_type => ORA_CLOB, -ora_field=>'DESCR'}); - $sth->bind_param(2, 12); - $sth->execute; - } - else - { - $sth->execute($descr,12); - } - } - sleep 1; -} - - -With $leak set to 1, i.e. binding the parameters explicitly the -program leaks. With $leak set to 0 it does not (but then I can't -set descr to anything greater than 4K nor can I set it to the -empty string). - -Is there a patch? - --P - diff --git a/err_bind/err_bindnullhash.msg b/err_bind/err_bindnullhash.msg deleted file mode 100644 index d9a98b9a..00000000 --- a/err_bind/err_bindnullhash.msg +++ /dev/null @@ -1,77 +0,0 @@ -From dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org Thu Jul 11 17:49:35 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g6BGnYH11008 - for ; Thu, 11 Jul 2002 17:49:34 +0100 (BST) - (envelope-from dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 11 Jul 2002 17:49:34 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1026401921:10:09249:41; Thu, 11 Jul 2002 15:38:41 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1124337; 11 Jul 2002 15:38 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id B567C2BF65 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 347792BF62 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Received: (qmail 95914 invoked by uid 1005); 11 Jul 2002 15:38:04 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 95896 invoked by uid 76); 11 Jul 2002 15:38:04 -0000 -Received: from ironmail1.cc.lehigh.edu (HELO ironmail1.cc.lehigh.edu) (128.180.39.26) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Thu Jul 11 15:38:04 2002 -0000 -Received: from ([128.180.39.20]) - by ironmail1.cc.lehigh.edu with ESMTP with TLS; - Thu, 11 Jul 2002 11:35:06 -0400 (EDT) -Received: from lawrencework (pc-lfn0.dept.Lehigh.EDU [128.180.52.51]) - by rain.CC.Lehigh.EDU (8.12.4/8.12.4) with SMTP id g6BFZ6rr022463 - for ; Thu, 11 Jul 2002 11:35:06 -0400 -Message-ID: <0a0401c228f0$93feda10$3334b480@lawrencework> -From: "Phil R Lawrence" -To: -References: <083b01c22824$70357340$3334b480@lawrencework> <20020711140937.A568@dansat.data-plan.com> -Subject: Re: error msg suggestion -Date: Thu, 11 Jul 2002 11:35:20 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2600.0000 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -X-Status: A -Content-Length: 636 -Lines: 21 - -Tim Bunce wrote: -> Binding an undef should work and be treated as a NULL. -> -> Probably a bug in your code or the driver. But you didn't -> say which driver. - -Hmmm. quite right, undefs do bind as NULL. However, in this case I am -binding $hash{non-existent-key}, which autoinstantiates to an undef, and looks -like this in the trace: - undef (magic-sg:y) - -Of course it was my dumb fault for having the wrong key for lookup, but -nonetheless, perhaps this should work the same as a normal undef. - -# $DBI::VERSION = "1.14"; -# $DBD::ODBC::VERSION = '0.28'; -$DSN = 'driver=Microsoft Access Driver (*.mdb);dbq=StudyManager.mdb'; - -Thanks, -Phil - - diff --git a/err_bind/err_trailingblank.msg b/err_bind/err_trailingblank.msg deleted file mode 100644 index cdf34a32..00000000 --- a/err_bind/err_trailingblank.msg +++ /dev/null @@ -1,345 +0,0 @@ -From dbi-users-bounce@isc.org Mon May 1 21:12:02 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id VAA16051; Mon, 1 May 2000 21:12:00 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <14295-42@oink>; Fri, 1 May 1970 21:06:08 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 957208278:10:19133:4; Mon, 01 May 2000 19:11:18 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1123094; 1 May 2000 19:11 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id B3CCF3FAA; - Mon, 1 May 2000 12:10:53 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Mon, 01 May 2000 12:05:42 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A70763E34 - for ; Mon, 1 May 2000 12:05:30 -0700 (PDT) -Received: from scotth.emsphone.com (scotth.emsphone.com [199.67.51.179]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA25897 - for ; - Mon, 1 May 2000 12:05:30 -0700 (PDT) env-from (shildret@scotth.emsphone.com) -Received: (from shildret@localhost) by scotth.emsphone.com (8.9.3/8.9.3) - id OAA50011 for dbi-users@isc.org; - Mon, 1 May 2000 14:05:48 -0500 (CDT) (envelope-from shildret) -Message-ID: -X-Mailer: XFMail 1.4.0 on FreeBSD -X-Priority: 3 (Normal) -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 8bit -MIME-Version: 1.0 -Resent-Date: Thu, 29 Jul 1999 22:07:08 +0100 -Resent-Message-Id: <19990729220708.G17723@ig.co.uk> -Resent-From: Tim Bunce -Resent-To: Tim Bunce -Date: Mon, 01 May 2000 14:05:48 -0500 (CDT) -Sender: shildret@scotth.emsphone.com -From: "Scott T. Hildreth" -To: "dbi-users@isc.org" -Subject: FW: Oracle & Trailing Blanks - possible change in DBD::Oracle -Resent-Sender: shildret@scotth.emsphone.com -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 3885 -Lines: 94 - - -Here is the help, I got regarding the trailing spaces. - ------FW: <19990729220708.G17723@ig.co.uk>----- - -Date: Thu, 29 Jul 1999 22:07:08 +0100 -From: Tim Bunce -To: Tim Bunce -Subject: Oracle & Trailing Blanks - possible change in DBD::Oracle -Cc: "Scott T. HIldreth" , - dbi-users@isc.org - - *** From dbi-users -- To unsubscribe, see the end of this message. *** - -On Thu, Jul 29, 1999 at 09:49:38PM +0100, Tim Bunce wrote: -> *** From dbi-users -- To unsubscribe, see the end of this message. *** -> -> On Thu, Jul 29, 1999 at 09:33:55AM -0500, Scott T. HIldreth wrote: -> > -> > Hi all, I wonder if someone can let me know if I got this right. -> > I have a key to match which can contain trailing blanks. The -> > field in the database is CHAR(18). If I match the key with -> > sqlplus, Oracle finds a match, with or without the trailing -> > blank. When I do an sth->execute( $key ), the key is not -> > found. I abstract the key with substr, so the trailing blank -> > is in the key, but no match is found. Do I need to place qoutes -> > around the value in $key? -> -> Somewhat hiddedn in the Oraperl.pm docs it says this: -> -> --- -> B Substitution variables are now bound as type 1 (VARCHAR2) -> and not type 5 (STRING) by default. This can alter the behaviour of -> SQL code which compares a char field with a substitution variable. -> See the String Comparison section in the Datatypes chapter of the -> Oracle OCI manual for more details. -> -> You can work around this by using DBD::Oracle's ability to specify -> the Oracle type to be used on a per field basis: -> -> $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) -> $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); -> $csr->bind_param(1, $value_x, $char_attrib); -> $csr->bind_param(2, $value_y, $char_attrib); -> ora_bind($csr); # bind with no parameters since we've done bind_param()'s -> --- -> -> Ignoring the Oraperl specifics there the key point is to use -> -> $csr->bind_param($idx, $value, { ora_type => 5 }); -> -> I'll add something to the DBD::Oracle docs. - -[You'll still need to blank-pad the string.] - -Looking at this issue again I've discovered that the key issue is that -type 1 strips trailing blanks whilst type 5 doesn't. - -I'rather m concerned by this. Since I'm against the DBI changing the -data in any way on principle and since Oraperl used to use type 5 -I'm strongly considering changing DBD::Oracle 'back' to using type 5. - -This would only affect anyone who relies on placeholders having -trailing blanks stripped off. (I'll provide a way to alter the -default with a single statement and/or env var for anyone affected). - -If that's you - speak up now! - -Tim. - ------------------------------------------------------------------------------- -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of -'unsubscribe'. ------------------------------------------------------------------------------- - - ---------------End of forwarded message------------------------- - ----------------------------------- -E-Mail: Scott T. Hildreth -Date: 01-May-00 -Time: 14:04:41 ----------------------------------- - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - -From joshua.horton@mail.tju.edu Fri May 23 07:43:09 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.6/8.12.6) with ESMTP id h4N6UY7T061880 - for ; Fri, 23 May 2003 07:43:09 +0100 (BST) - (envelope-from joshua.horton@mail.tju.edu) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 23 May 2003 07:43:09 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1053631164:10:02298:54; Thu, 22 May 2003 19:19:24 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116141; 22 May 2003 19:19 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id BD31E21C13C - for ; Thu, 22 May 2003 15:18:30 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail.tju.edu (fw-tr16.tju.edu [147.140.233.16]) - by dolly1.pobox.com (Postfix) with ESMTP id 615A521C06D - for ; Thu, 22 May 2003 15:18:22 -0400 (EDT) -Received: from PCSE447.tjh.tju.edu by mail.tju.edu for Tim.Bunce@pobox.com; Thu, 22 May 2003 15:17:54 -0400 -Message-Id: <031301c32096$de68f6f0$2310ae0a@PCSE447> -From: "Joshua Horton" -To: -Subject: Re: :Oracle and Oracle 9.2? -Date: Thu, 22 May 2003 15:18:03 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 5.50.4807.1700 -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 3511 -Lines: 99 - -Re: :Oracle and Oracle 9.2? - ----------------------------------------------------------------------------- ----- - - a.. From: Tim Bunce - b.. Subject: Re: :Oracle and Oracle 9.2? - c.. Date: Tue, 15 Apr 2003 07:36:55 -0700 - ----------------------------------------------------------------------------- ----- - -I'd appreciate it if other people with Oracle 9.2.x could let me -know if it passed or failed for them and what their exact oracle -version (four digits) and platform (operating system) is. - -Thanks. - -Tim. - -On Fri, Apr 04, 2003 at 01:48:36PM +0200, Smejkal Petr wrote: -> I have the same experience on Linux however on Windows all tests passes -(I'm not -> sure if it is related to different Oracle version - test of windows Perl -against -> Linux Oracle is OK). -> -> Linux Oracle: 9.2.0.2 -> Windows Oracle: 9.2.0.1 -> DBI: 1.35 -> DBD::Oracle: 1.14 -> -> -- Petr Smejkal -> -- Business Systems Analyst / Country IT Cz/Sk -> -- +420 284 059 639 -> -> > -----Original Message----- -> > From: Tom Malaher [mailto:[EMAIL PROTECTED] -> > Sent: Friday, April 04, 2003 1:35 AM -> > To: [EMAIL PROTECTED] -> > Subject: DBD::Oracle and Oracle 9.2? -> > -> > -> > My sysadmin is trying to install DBD::Oracle on a Solaris box running -> > Oracle 9.2. -> > -> > The ph_type.t test is failing with -> > -> > PERL_DL_NONLAZY=1 ./perl "-MExtUtils::Command::MM" "-e" -> > "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -> > t/base.......ok -> > t/cursor.....ok -> > t/general....ok -> > t/long.......ok -> > t/meta.......ok -> > t/ph_type....NOK 12 expected 'trailing' but got 'trailing ' -> > for VARCHAR2 -> > t/ph_type....FAILED test 12 -> > Failed 1/19 tests, 94.74% okay -> > t/plsql......ok -> > t/reauth.....skipped -> > all skipped: no reason given -> > t/select.....ok -> > Failed Test Stat Wstat Total Fail Failed List of Failed -> > -------------------------------------------------------------- -> > ----------------- -> > t/ph_type.t 19 1 5.26% 12 -> > 1 test skipped. -> > Failed 1/9 test scripts, 88.89% okay. 1/314 subtests failed, -> > 99.68% okay. -> > *** Error code 29 -> > make: Fatal error: Command failed for target `test_static' -> > -> > Is there a known problem with DBD::Oracle and Oracle 9.x? -> > Has Oracle changed the behavior of trailing spaces in VARCHAR2 fields? -> > -> > I've run the same test script on an oracle 8 installation -> > using DBD::Oracle 1.06 and DBI 1.14, and it works fine (no trailing -> > space is returned). -> > -> > Tom -> > -My config:HP-UX 11.11 (64-bit) on rp5470 2x733 5GB RAMOracle 9.2.0.2.0 -Enterprise Edition (64-bit)Perl 5.8.0 custom compiled with -./Configure -Duse64bitall -Ubincompat5005 -Duselargefiles -Dprefix=/opt/perl -5 ; all other options defaultDBI-1.32 all passed some skippedDBD-Oracle-1.14 -: PERL_DL_NONLAZY=1 /opt/perl5/bin/perl "-MExtUtils::Command::MM" -"-e" "test_harness(0, 'blib/lib', 'blib/arch')" -t/*.tt/base.......okt/cursor.....okt/general....okt/long.......okt/meta..... -..okt/ph_type....ok 11/19 expected 'trailing' but got 'trailing ' for -VARCHAR2t/ph_type....FAILED test 12 Failed 1/19 tests, 94.74% -okayt/plsql......okt/reauth.....skipped all skipped: no reason -givent/select.....okFailed Test Stat Wstat Total Fail Failed List of -Failed---------------------------------------------------------------------- --------------------------------------------------------t/ph_type.t -19 1 5.26% 121 test skipped.Failed 1/9 test scripts, 88.89% okay. -1/314 subtests failed, 99.68% okay.*** Error exit code 2Stop.Thanks,Josh -Horton - - -From nobody@fsck.com Tue Dec 30 14:33:50 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hBUEWNnP026077 - for ; Tue, 30 Dec 2003 14:33:50 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Dec 2003 14:33:50 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AbJwa-0003ua-H6; - Tue, 30 Dec 2003 13:29:56 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AbJwa-0003ua-H6 - for pobox@dbi.demon.co.uk; Tue, 30 Dec 2003 13:29:56 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 56DAD4C6 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3B3564C8 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 30 Dec 2003 08:29:54 -0500 (EST) -Received: (qmail 10988 invoked by uid 225); 30 Dec 2003 13:29:53 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 10984 invoked by alias); 30 Dec 2003 13:29:52 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 30 Dec 2003 05:29:41 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 8760D11153; Tue, 30 Dec 2003 08:29:37 -0500 (EST) -Subject: [cpan #4786] Oracle 9.2.0.0 fails a test in ph_types.t -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4786 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -To: "AdminCc of cpan Ticket #4786": ; -Date: Tue, 30 Dec 2003 08:29:37 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,SUPERLONG_LINE,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -Content-Length: 888 -Lines: 11 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -Assuming that ORA_OCI() gets set correctly when compiling against 9.2, the attached patch will work. I also tried this in SQL*Plus and was able to insert a trailing space into a VARCHAR2. (I replicated the test in ph_types.t). - -I did not test my patch as I installed DBD::Oracle 1.14 by setting the chops_spaces value in %test_info to 0. When I did that, everything installed fine. However, I didn't think that my solution was the best for the module, so I figured ORA_OCI should do the trick. - -I'm running Perl5.8.0 for Solaris2.9 going against the full Oracle build for 9.2. (I did not run into this issue, surprisingly, on Redhat9 running Perl 5.8.2, but I built against Oracle 9.1 there ...) - diff --git a/err_build/err_aix64.msg b/err_build/err_aix64.msg deleted file mode 100644 index f952e29e..00000000 --- a/err_build/err_aix64.msg +++ /dev/null @@ -1,142 +0,0 @@ -From SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com Fri Jan 7 16:11:33 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j07GAqfa044155 - for ; Fri, 7 Jan 2005 16:11:32 GMT - (envelope-from SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Fri, 07 Jan 2005 16:11:32 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CmvQB-0003Po-Kf; - Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CmvQB-0003Po-Kf - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CmvQA-0002zW-VM - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 49778102ACC; - Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 384E5FF808 - for ; Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Received-SPF: pass (boggle.pobox.com: domain of dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by boggle.pobox.com (Postfix) with SMTP id A74B8F4090 - for ; Fri, 7 Jan 2005 09:48:57 -0500 (EST) -Received: (qmail 2690 invoked by uid 514); 7 Jan 2005 14:48:56 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 2622 invoked from network); 7 Jan 2005 14:48:55 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 7 Jan 2005 14:48:55 -0000 -Received: (qmail 13078 invoked by uid 225); 7 Jan 2005 14:48:54 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 13048 invoked by alias); 7 Jan 2005 14:48:51 -0000 -X-Spam-Status: No, hits=-4.6 required=8.0 - tests=BAYES_00,HTML_MESSAGE,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: neutral (x1.develooper.com: local policy) -Received: from outmx020.isp.belgacom.be (HELO outmx020.isp.belgacom.be) (195.238.2.201) - by la.mx.develooper.com (qpsmtpd/0.28) with ESMTP; Fri, 07 Jan 2005 06:48:38 -0800 -Received: from outmx020.isp.belgacom.be (localhost [127.0.0.1]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmOgS020070 - for ; Fri, 7 Jan 2005 15:48:24 +0100 - (envelope-from ) -Received: from relaytwo.roularta.be (smtprelaytwo.roularta.be [194.78.177.23]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmMDA020034 - for ; Fri, 7 Jan 2005 15:48:22 +0100 - (envelope-from ) -Received: from rmgexch01.RMG.be ([89.0.35.150]) by roesfront3.RMG.be with Microsoft SMTPSVC(5.0.2195.6713); - Fri, 7 Jan 2005 15:47:50 +0100 -X-MimeOLE: Produced By Microsoft Exchange V6.5.7226.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----_=_NextPart_001_01C4F4C7.EE810087" -Subject: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Date: Fri, 7 Jan 2005 15:48:21 +0100 -Message-ID: -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Thread-Index: AcT0x+Y4G1R3vbX6Rh+QdPyNy/10eQ== -From: -To: -X-OriginalArrivalTime: 07 Jan 2005 14:47:50.0598 (UTC) FILETIME=[DC5D2E60:01C4F4C7] -Status: RO -Content-Length: 1678 -Lines: 62 - -------_=_NextPart_001_01C4F4C7.EE810087 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - -Hi,=20 -=20 -I finally succeeded in installing a 64bit build of Perl and its modules -for Oracle 64-bit. We were running in 32bit but integrating Proc and -cobols in our perl scripts only worked when we changed environments to -64bit causing problems for the oracle connections in perl. It's nothing -special, no editing of makefiles ... I can't believe I lost so much time -on this one ;) ( Now that I look back to my problems, they were probably -caused by using a wrong perl build for compiling the modules, Aix has -its default perl now under /bin.. stupid me )=20 -=20 -perl 5.8.6 64bit ----------------- -./Configure -de -Dcc=3Dgcc -Duse64bitall=20 -make -make test -make install -=20 -DBI 1.46 --------- -!!Make sure you are using the newly installed perl!! - check with perl -v it should show :=20 - This is perl, v5.8.6 built for aix-64all -perl Makefile.PL -make -make test -make install=20 -=20 -DBD-Oracle 1.16 ---------------- -!!Use correct perl like above mentioned!!=20 -export ORACLE_HOME=3D=20 -export LIBPATH=3D$ORACLE_HOME/lib -export LD_LIBRARY_PATH=3D$ORACLE_HOME/lib -=20 -perl Makefile.PL=20 -make -make test ( some test may still fail, I had 85% success on tests )=20 -make install=20 -=20 -Test -----=20 -=20 -test with :=20 - use DBI; - $dbh=3DDBI->connect("dbi:Oracle:","system","manager")|| die -$DBI::errstr; - $stmt=3D$dbh->prepare("select * from tab"); - $rc=3D$stmt->execute() || die $DBI::errstr; - while (my($record)=3D$stmt->fetchrow()) - { - print $record; - } -=20 -Happy 64-bit perling ;)=20 - -------_=_NextPart_001_01C4F4C7.EE810087-- - diff --git a/err_build/err_hpux_ld.msg b/err_build/err_hpux_ld.msg deleted file mode 100644 index 27f9cd07..00000000 --- a/err_build/err_hpux_ld.msg +++ /dev/null @@ -1,89 +0,0 @@ -From SRS0=JbZc=U3=lincolnbaxter.com=lab@bounce2.pobox.com Tue Jun 21 05:02:19 2005 -Return-Path: -X-Original-To: timbo@localhost -Delivered-To: timbo@localhost.data-plan.com -Received: from localhost (localhost [127.0.0.1]) - by timac.data-plan.com (Postfix) with ESMTP id B016F2A3D98 - for ; Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DkYXK-0003m5-Mr; - Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DkYXK-0003m5-Mr - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1DkYXJ-00006n-QE - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AF60172691; - Mon, 20 Jun 2005 22:29:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from ms-smtp-04-eri0.southeast.rr.com (ms-smtp-04-lbl.southeast.rr.com [24.25.9.103]) - by gold.pobox.com (Postfix) with ESMTP id A3C1E7272E - for ; Mon, 20 Jun 2005 22:29:11 -0400 (EDT) -Received: from lincolnbaxter.com (cpe-069-132-010-126.carolina.res.rr.com [69.132.10.126]) - by ms-smtp-04-eri0.southeast.rr.com (8.12.10/8.12.7) with ESMTP id j5L2TIL4001864 - for ; Mon, 20 Jun 2005 22:29:18 -0400 (EDT) -Received: (qmail 5171 invoked from network); 20 Jun 2005 22:29:07 -0400 -Received: from lws (192.168.0.25) - by lws with SMTP; 20 Jun 2005 22:29:07 -0400 -Subject: Re: gcc options when building DBD:Oracle -From: "Lincoln A. Baxter" -Reply-To: lab@lincolnbaxter.com -To: jriekenberg@everestkc.net -Cc: Tim Bunce -In-Reply-To: -References: -Content-Type: text/plain -Date: Mon, 20 Jun 2005 22:29:07 -0400 -Message-Id: <1119320947.17452.484.camel@lws> -Mime-Version: 1.0 -X-Mailer: Evolution 2.2.1.1 -Content-Transfer-Encoding: 7bit -X-Virus-Scanned: Symantec AntiVirus Scan Engine -Status: RO -Content-Length: 2011 -Lines: 38 - -Hi Jan, - -This looks like something that might be relatively easy to fix in -Makefile.PL. But I no longer have access to HPUX systems, and never -built DBD-Oracle with gcc on that platform. I could add your message to -the README.hpux file, but it is becoming less and less necessary to read -this file with newer versions of DBD-Oracle, in which Makefile.PL has -been made much smarter. - -Would you consider sending Tim or me a patch to Makefile.PL that -generates the right $(LD) command (only on HP rp8400, and only for your -version of gcc or later? - -Lincoln - -On Mon, 2005-06-20 at 15:36 -0500, jriekenberg@everestkc.net wrote: -> Lincoln, -> -> I recently built DBD:Oracle on an HP rp8400. Everything worked as expected until I actually issued the "make" command. Make proceeded as expected until it reached "MakeMaker dynamic_lib" section. The gcc line in that section failed with the error in the attached text file. Apparently gcc was not correctly passing the "+b" option to ld. Instead, it was attempting to interpret the option itself. It assumed the "+b" was a filename, and that failed because gcc could not find the file. I ended up adding the "-Xlinker" option before the "+b" and before the "$(LD_RUN_PATH)" in the line in Makefile. The line now looks like this: -> -> $(LD) -Xlinker +b -Xlinker "$(LD_RUN_PATH)" $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) -> -> Running "make" now works correctly. -> -> Also, "make test" returned the following error when attempting to build the various tests: -> -> /usr/lib/dld.sl: Can't shl_load() a library containing Thread Local Storage: /usr/lib/libcl.2 -> -> Setting LD_PRELOAD with "export LD_PRELOAD=/usr/lib/libcl.2" corrected this problem, and "make test" worked correctly. -> -> -> I didn't see DBD::Oracle documentation on exactly this, so I'm sending this to you. You may be aware of these items already. If so, please disregard this. -> -> Jon Riekenberg -> -> -> - - diff --git a/err_build/err_hpuxsuccess.msg b/err_build/err_hpuxsuccess.msg deleted file mode 100644 index c6edd79f..00000000 --- a/err_build/err_hpuxsuccess.msg +++ /dev/null @@ -1,279 +0,0 @@ -From dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org Tue Mar 23 17:00:25 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i2NGvAxX021862 - for ; Tue, 23 Mar 2004 17:00:23 GMT - (envelope-from dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 23 Mar 2004 17:00:23 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1B5oND-0000Ba-LH; - Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1B5oND-0000Ba-LH - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [208.210.124.70] (helo=majesty.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1B5oNC-00001d-92 - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:26 +0000 -Received: from majesty.pobox.com (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 18033954B4 - for ; Tue, 23 Mar 2004 11:03:24 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 3577D954BE - for ; Tue, 23 Mar 2004 11:03:21 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by majesty.pobox.com (Postfix) with SMTP - for ; Tue, 23 Mar 2004 11:02:41 -0500 (EST) -Received: (qmail 6527 invoked by uid 1005); 23 Mar 2004 16:02:21 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6510 invoked by uid 76); 23 Mar 2004 16:02:20 -0000 -Received: from x1.develooper.com (HELO x1.develooper.com) (63.251.223.170) - by onion.perl.org (qpsmtpd/0.27.1) with SMTP; Tue, 23 Mar 2004 08:02:20 -0800 -Received: (qmail 1985 invoked by uid 225); 23 Mar 2004 16:02:15 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 1893 invoked by alias); 23 Mar 2004 16:02:00 -0000 -X-Spam-Status: No, hits=0.0 required=7.0 - tests= -X-Spam-Check-By: la.mx.develooper.com -Received: from Unknown (HELO dundee.fpcc.net) (204.144.241.120) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Tue, 23 Mar 2004 08:01:44 -0800 -Received: from aberdeen.fpcc.net (aberdeen.fpcc.net [204.144.241.125]) - by dundee.fpcc.net (8.11.6/8.11.6) with ESMTP id i2NG1f111241; - Tue, 23 Mar 2004 09:01:41 -0700 -Received: from aberdeen.fpcc.net (localhost.localdomain [127.0.0.1]) - by aberdeen.fpcc.net (8.12.8/8.12.8) with ESMTP id i2NFrNOv024637; - Tue, 23 Mar 2004 08:53:23 -0700 -Received: (from laubster@localhost) - by aberdeen.fpcc.net (8.12.8/8.12.8/Submit) id i2NFrMOx024635; - Tue, 23 Mar 2004 08:53:22 -0700 -X-Authentication-Warning: aberdeen.fpcc.net: laubster set sender to dbiusers@laubster.org using -f -Date: Tue, 23 Mar 2004 08:53:22 -0700 -From: "J.D. Laub" -To: dbi-users@perl.org -Cc: lbaxter@fleetcc.com -Subject: SUCCESS: DBD::Oracle 1.15 on HP-UX 11.11 -Message-ID: <20040323155322.GA24576@aberdeen.fpcc.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -Organization: The Psychiatric Ward of Terrors -X-Virus-Checked: Checked -Status: RO -Content-Length: 9105 -Lines: 206 - -I've just had success building DBD::Oracle 1.15 on HP-UX 11.11 -(against both oracle 8.1.7 & oracle 9.2.0) & thought I'd share my -experience. - -Disclaimer: these instructions relate to our environment. It may be -that our sysadmins/dbas chose to configure/install things a certain -way (i.e., our install of $ORACLE_HOME/bin/sqlplus was *chosen* -to be 1.1/32), and/or that we're running old versions of software -(i.e., perhaps later releases of gcc don't ignore -mpa-risc-1-1). -In fact, there are probably some mistruths in here; rest assured -they're not intentional. :-) - -I'm unsure how (if?) I should go about getting this information into -the DBD::Oracle README.hpux. Lincoln, please contact me with any -thoughts you have. - - -### The summary ################################ - -Use the ansic compiler (~US$800/cpu). - -Shell variables I used: - PATH=/bin:$PATH # use 32bit ar & nm since using a 32bit cc - PERLDEST=/opt/perl_ora8 # or "perl_ora9" for an ora9 build - PATH=$PERLDEST/bin:$PATH # for build of DBI, pick up new perl - export LDLOADLIBS='+b : +s' # handy for ORACLE_SID connections to ora7 - unset PERLLIB # important to avoid outdated cruft - export ORACLE_USERID=scott/tiger # insecure - consider using "/" - ORACLE_SID=orcl - ORAENV_ASK=NO - . oraenv # sets LD_LIBRARY_PATH and SHLIB_PATH - -For ora8: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DAportable ' \ - -A prepend:ldflags='+z +DAportable ' - -For ora9: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DA2.0W ' \ - -A prepend:ldflags='+z +DA2.0W ' \ - -Dlibpth='/usr/lib/pa20_64 /usr/local/pa20_64/lib' - -After you use the above to install perl, DBI & DBD::Oracle will -build in the normal fashion. - - -### General Notes ################################ - -* During "make test", I received 1 failure (on -lib/ExtUtils/t/Constant) for ora8, and 3 failures (on -lib/ExtUtils/t/Constant, lib/ExtUtils/t/recurs, and t/op/write) for -ora9. Nevertheless, things seem mostly OK. - -* These are the various combinations possible for a given compiled -file on HP-UX 11.11 (the quoted description is what gets kicked out -by the "file" command): - - PA-RISC1.1/32bit ("PA-RISC1.1 relocatable object") - (I'll call this 1.1/32) - PA-RISC2.0/32bit ("PA-RISC2.0 relocatable object") - (I'll call this 2.0/32) - PA-RISC2.0/64bit ("ELF 64-bit MSB relocatable, PA-RISC 2.0 (LP64)") - (I'll call this 2.0/64) - -* "perl -v" lies about the RISC level: -$ file ./perl -./perl: PA-RISC1.1 shared executable dynamically linked -not stripped -$ ./perl -v | grep RISC -This is perl, v5.8.3 built for PA-RISC2.0 - -* If you'll be linking against 2.0/64 libraries, you'll have to -build all your object modules that way. I've not yet found a way -to link 32bit executables to 64bit libraries (and vice versa). Run -the "file" command on your Oracle libraries to find out which path -you'll have to take. - -* Two environment variables control where libraries are -searched. LD_LIBRARY_PATH and SHLIB_PATH (in that order) are -used for 64bit executables, while SHLIB_PATH is used for 32bit -executables. - -* I tried attempts using aCC as well as the default (free) cc that -comes with hpux; both avenues were too problematic to continue -pursuing. - -* The format of compiled objects is specified by compiler options. -According to the ansic compiler docs, the options are "+DAportable" -(for 1.1/32), "+DA2.0" (for 2.0/32), and "+DA2.0W" (for 2.0/64). -For gcc, the corresponding switches are -mpa-risc-1-1 (for 1.1/32) -and -mpa-risc-2-0 (for 2.0/64), but I've found that -mpa-risc-1-1 -is ineffective. (According to the "file" command, you *always* get -2.0/64.) - -* Our gcc displays the behavior described at -http://sources.redhat.com/ml/binutils/2002-10/msg00586.html and -http://aspn.activestate.com/ASPN/Mail/Message/perl5-porters/1641238 -, so is therefore unusable anytime '-lcl' is to be specified. -Unfortunately, that library is required for DBD::Oracle builds. -(The workaround of adding the 3 declarations does seem to work, -but littering those throughout perl's Configure, main.c, etc. -seems a big task.) Attempts to get gcc to use the hp ld instead -of the gnu ld (by specifying -mno-gnu-ld and -fno-gnu-linker) were -unsuccessful. The first html link shown above indicates you have -to rebuild gcc to use the hp linker, and that was not an incredibly -desirable path to pursue. - -* Our default PATH was set to put /usr/local/pa20_64/bin ahead of -/bin. This caused problems because (I think) the 64bit versions -of either ar (the archiver) or nm (the symbol lister) do not play -well with /bin/cc (the 32bit compiler). The tweak to put /bin at -the head of PATH, so we get the 32bit versions, takes care of the -problem. - -* I ran into an intermittent quirk during the build of perl in which -typing "make" (just after the Configure) did nothing. It turns out -that only dependencies were being written to "makefile", and that -removing "makefile" (so it could be automatically rebuilt) solved -the problem. - -* Most of my research on finding the right compiler/linker switches -was done with a "hello world" C program, trying the various -compilers and options, and trying to link it with the oracle -libraries. This proved to be a good choice, as trying to test -compilers/switches against the perl source distribution would have -proved quite difficult. - - -### DBD::Oracle specific ################################ - -* ora8 delivers its libraries in 2 formats: 1.1/32 (under -$ORACLE_HOME/lib) and 2.0/64 (under $ORACLE_HOME/lib64). ora7 -delivers only 1.1/32, while ora9 delivers only 2.0/64. It may seem -a bit inconsistent considering the ora8 setup, but ora9 libraries -are found under $ORACLE_HOME/lib and not $ORACLE_HOME/lib64. - -* Under ora8, oraenv incorrectly sets LD_LIBRARY_PATH to include -$ORACLE_HOME/lib instead of $ORACLE_HOME/lib64, so you've got to -make an override in oraenv_local if you want to use 2.0/64. It -doesn't harm anything, but oraenv unnecessarily sets LD_LIBRARY_PATH -for ora7 (a 64bit environment variable for a 32bit application). - -* If you use shared libraries AND you'll be upgrading Oracle, you -should expect you'll need to rebuild DBD::Oracle unless you'll keep -the old Oracle libraries available. - -* If you're building against ora8, the setting of LDLOADLIBS -is recommended so that when oraenv set SHLIB_PATH to the -$ORACLE_HOME/lib for ora7, the code will still find the ora8 -libraries. - -* We expect to need local (ORACLE_SID) connections for ora8 & -ora9. We could have gone with a single 2.0/64 perl coupled with -2 DBD::Oracle installs and PERLLIB twiddling in oraenv_local to -get to the right one. Instead, we chose to do 2 perl installs -(/opt/perl_ora8 and /opt/perl_ora9) because we can also connect -locally to ora7 by using the 1.1/32 ora8 version, something that -isn't possible with a 2.0/64 version. Also, we've some older 1.1/32 -machines into which we'd like to plop a tarball of the perl stuff, -so a 1.1/32 executable was desirable. - -* Some tests I ran were hinting that with 2.0/64, specifying "+b :" -on the build of DBD::Oracle correctly configured Oracle.sl as far as -the chatr program is concerned, but it seemed that LD_LIBRARY_PATH -*always* needed to be set correctly. (I.e., the embedded path in -the library seemed to be ignored.) I didn't pursue researching this -since there's no way to get the ora9 compiled code to connect to -ora8, meaning LD_LIBRARY_PATH had to be set correctly anyway. - -Testing local (ORACLE_SID) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora9 cannot connect to ora8 or ora7: "UNKNOWN - OCI STATUS 1804) OCIInitialize. Check ORACLE_HOME and NLS - settings etc." - -Testing remote (sqlnet) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 can connect to ora9 -builds against 2.0/64 ora9 can connect to ora8 -builds against 2.0/64 ora9 cannot connect to ora7: "OCI-21500: internal - error code" - - -### Versions ################################ - -perl: 5.8.3 -dbi: 1.41 -dbd-oracle: 1.15 -$ strings /bin/cc | grep Compiler -HP92453-01 B.11.11.08 HP C Compiler -$ strings /bin/ld | grep linker -$Revision: 92453-07 linker linker crt0.o B.11.16 000601 $ -@(#)92453-07 linker command s800.sgs ld PA64 B.11.18 REL 000922 -$ gcc -v -Reading specs from /usr/local/pa20_64/lib/gcc-lib/hppa64-hp-hpux11.11/3.3.1/specs -Configured with: ../src/configure --enable-languages=c,c++ --prefix=/usr/local/pa20_64 --with-local-prefix=/usr/local/pa20_64 --with-gnu-as --with-as=/usr/local/pa20_64/bin/as --with-gnu-ld --with-ld=/usr/local/pa20_64/bin/ld --disable-shared --disable-nls --host=hppa64-hp-hpux11.11 -Thread model: single -gcc version 3.3.1 - --- -J.D. Laub (Laubster) |"Your leg's too long / Your skull's too strong / -dbiusers@laubster.org| Suppose your nose is wrong." - Renaldo & the Loaf - diff --git a/err_build/err_instantclient.msg b/err_build/err_instantclient.msg deleted file mode 100644 index f0e549eb..00000000 --- a/err_build/err_instantclient.msg +++ /dev/null @@ -1,207 +0,0 @@ -From SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Feb 2 10:11:05 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j12AAUZ6055956 - for ; Wed, 2 Feb 2005 10:11:05 GMT - (envelope-from SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 02 Feb 2005 10:11:05 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwGaQ-0002Bn-H6; - Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwGaQ-0002Bn-H6 - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwGaP-00042G-Vb - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 9C3FB1E3946; - Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 879981E3958 - for ; Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Received-SPF: pass (kelvin.pobox.com: domain of dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by kelvin.pobox.com (Postfix) with SMTP id D0B001E3946 - for ; Wed, 2 Feb 2005 04:14:08 -0500 (EST) -Received: (qmail 7188 invoked by uid 514); 2 Feb 2005 09:14:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -List-Id: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 2531 invoked from network); 2 Feb 2005 04:10:16 -0000 -Delivered-To: dbi-users@perl.org -X-Spam-Status: No, hits=-2.6 required=8.0 - tests=BAYES_00,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: pass (x1.develooper.com: local policy) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgw.shina.sankyo.co.jp: iscan owned process doing -bs -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: Making DBD::Oracle with Instant Client 10.1.0.3 -Date: Wed, 2 Feb 2005 13:09:58 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBE9@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUI3Q64h9ykph8RSl6pF0OpBbTqJA== -To: -X-OriginalArrivalTime: 02 Feb 2005 04:09:59.0005 (UTC) FILETIME=[0F7508D0:01C508DD] -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 44 - -Hi all, - -Thanks to the devel package, I've got succeeded in making DBD::Oracle -with the Oracle Instant Client 10.1.0.3, no *.mk files, in my linux box. -My recipe is: - -1) install both basic- and devel-10.1.0.3 rpm packages -2) export ORALCE_HOME="/usr/lib/oracle/10.1.0.3/client" -3) export LD_LIBRARY_PATH="$ORACLE_HOME/lib:$LD_LIBRARY_PATH" -4) modify the Makefile.PL file to bypass the find_headers() routine and - to pass a correct -I flag to cc (the attached dirty patch is FYI) -5) execute the Makefile.PL * with the -l option *, perl Makefile.PL -l -6) make && make test && make install -# I got many errors in t/30long.t (retrieving blobs ?) -# but it seems to work fairly. - -I hope this could help those who are annoyed with the "Unable to locate an -oracle.mk,..." error. - -Happy DBing, - -Satoshi - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+# my @h_dirs = find_headers(); - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client"; - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -From SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com Thu Feb 3 08:10:48 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j138AMOi093146 - for ; Thu, 3 Feb 2005 08:10:48 GMT - (envelope-from SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Thu, 03 Feb 2005 08:10:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwboD-0005ug-LV; - Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwboD-0005ug-LV - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwboD-0000Wn-82 - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 70999102D9F; - Thu, 3 Feb 2005 02:53:48 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 5F45E102DCC - for ; Thu, 3 Feb 2005 02:53:48 -0500 (EST) -X-Pobox-Antispam: Require PTR Record returned DENY: 210.81.52.253 has no PTR record -X-Pobox-Antispam: country/Japan returned DENY: sender address snisim@sankyo.co.jp matches TLD .jp (Japan) -Received-SPF: none (boggle.pobox.com: domain of snisim@sankyo.co.jp does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for snisim@sankyo.co.jp to mail through 210.81.52.253) -Received: from mailgws.shina.sankyo.co.jp (unknown [210.81.52.253]) - by boggle.pobox.com (Postfix) with ESMTP id A38A5102E20 - for ; Thu, 3 Feb 2005 02:53:46 -0500 (EST) -Received: from es007.sankyo.co.jp (localhost [127.0.0.1]) - by mailgws.shina.sankyo.co.jp (8.9.3p2/3.7W) with ESMTP id LAA15117 - for ; Thu, 3 Feb 2005 11:45:39 +0900 (JST) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgws.shina.sankyo.co.jp: iscan owned process doing -bs -Received: from EVS001.sankyo.co.jp ([10.14.121.200]) by es007.sankyo.co.jp with Microsoft SMTPSVC(6.0.3790.0); - Thu, 3 Feb 2005 11:45:39 +0900 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: RE: Making DBD::Oracle with Instant Client 10.1.0.3 -Content-class: urn:content-classes:message -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Date: Thu, 3 Feb 2005 11:46:07 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBEC@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUJEc1pQuIX++g2S8y4AE9WqWRYtQAhsK+Q -To: -X-OriginalArrivalTime: 03 Feb 2005 02:45:39.0123 (UTC) FILETIME=[71F21030:01C5099A] -Status: RO -Content-Length: 1192 -Lines: 36 - -Hi Tim, - -Thank you for your kind reply. - -I found my patch will cause a compilation error for the local variable -@h_dirs gets into undefined after commenting out the line 279. -It should be corrected as following: - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+ my @h_dirs; - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client" - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -I'm not a dbi-users member so I can't reply my post... I wonder if you can do it. - -Thanks, - -Satoshi - - diff --git a/err_build/err_makefileundef.msg b/err_build/err_makefileundef.msg deleted file mode 100644 index b98d782a..00000000 --- a/err_build/err_makefileundef.msg +++ /dev/null @@ -1,87 +0,0 @@ -From timbo Tue Apr 26 09:19:54 2005 -Return-path: -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 26 Apr 2005 09:19:54 -0700 (PDT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DQSgy-0006AU-4c; - Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DQSgy-0006AU-4c - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1DQSgy-0003uM-1T - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 759703B902A; - Tue, 26 Apr 2005 12:13:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 80C0A39F279 - for ; Tue, 26 Apr 2005 12:13:42 -0400 (EDT) -Received-SPF: none (kelvin.pobox.com: domain of lembark@wrkhors.com does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 66.246.154.128(mail-out.pilosoft.net) -Received: from mail.pilosoft.net (mail-out.pilosoft.net [66.246.154.128]) - by kelvin.pobox.com (Postfix) with ESMTP id 2ED743AB75B - for ; Tue, 26 Apr 2005 12:12:30 -0400 (EDT) -Received: from [192.168.1.2] (dsl-69-31-90-94.pilosoft.com [69.31.90.94]) - by mail.pilosoft.net (8.12.8/8.12.8) with ESMTP id j3QGA3u1014203 - for ; Tue, 26 Apr 2005 12:10:03 -0400 -Date: Tue, 26 Apr 2005 12:14:22 -0400 -From: Steven Lembark -Reply-To: lembark@wrkhors.com -To: Tim Bunce -Subject: Possible glitch in DBD::Oracle-1.48 Makefile.pl -Message-ID: <269F0144DC99100E7C80975F@[192.168.1.2]> -X-Mailer: Mulberry/3.1.3 (Linux/x86) -X-Workhorse: lembark 1.1 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii; format=flowed -Content-Transfer-Encoding: 7bit -Content-Disposition: inline -X-Virus-Scanned: ClamAV version 0.83, clamav-milter version 0.83 on mail.pilosoft.net -X-Virus-Status: Clean -X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=failed version=3.0.2 -X-Spam-Level: 0.0 -X-Spam-Checker-Version: SpamAssassin 3.0.2 (2004-11-16) on cheeta.pilosoft.net -X-Status: A -Content-Length: 1342 -Lines: 36 - -Linking with OTHERLDFLAGS = -L/opt/oracle/product/9.2/lib/ --L/opt/oracle/product/9.2/rdbms/lib/ -lclntsh `cat -/opt/oracle/product/9.2/lib/sysliblist` -ldl -lm [from 'build' rule] - -Checking if your kit is complete... -Looks good -Use of uninitialized value in substitution (s///) at Makefile.PL line 1446. -LD_RUN_PATH=/opt/oracle/product/9.2/lib:/opt/oracle/product/9.2/rdbms/lib -Using DBD::Oracle 1.16. - - - sub const_loadlibs { - my $self = shift; - local($_) = $self->SUPER::const_loadlibs(@_); - # edit LD_RUN_PATH ... - my ($ldrp) = m/^LD_RUN_PATH\s*=\s*(.*)/m; - # remove redundant /lib or /usr/lib as it can cause problems --> $ldrp =~ s!:(/usr)?/lib$!!; - # if it's empty then set it manually - #Lincoln: if pick the right library path - my $libdir = main::ora_libdir(); - $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; - #print "ldrp=$ldrp\n"; - - # stitch it back in - s/^LD_RUN_PATH\s*=\s*(.*)/LD_RUN_PATH=$ldrp/m; - my $env = $ENV{LD_RUN_PATH}; - print "Ignoring LD_RUN_PATH='$env' in environment\n" if $env; - print "LD_RUN_PATH=$ldrp\n"; - return $_; - } - --- -Steven Lembark 85-09 90th Street -Workhorse Computing Woodhaven, NY 11421 -lembark@wrkhors.com 1 888 359 3508 - diff --git a/err_build/err_memleak.msg b/err_build/err_memleak.msg deleted file mode 100644 index d40913d7..00000000 --- a/err_build/err_memleak.msg +++ /dev/null @@ -1,95 +0,0 @@ -From SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com Wed Sep 1 16:31:37 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i81FRlpg021884 - for ; Wed, 1 Sep 2004 16:31:37 +0100 (BST) - (envelope-from SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 Sep 2004 16:31:37 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C2WYO-00034m-M1; - Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C2WYO-00034m-M1 - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1C2WYO-0005CR-FY - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 1C1D6A758C; - Wed, 1 Sep 2004 10:57:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 184C8A7214 - for ; Wed, 1 Sep 2004 10:57:32 -0400 (EDT) -Received-SPF: fail (boggle.pobox.com: domain of www-data@pallas.eruditorum.org does not designate 63.251.223.170 as permitted sender) -X-SPF-Override: pass (client 63.251.223.170 was found in trusted-forwarder.org, overrides regular SPF fail) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.170(x1.develooper.com) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP id 7A6C9A7555 - for ; Wed, 1 Sep 2004 10:57:06 -0400 (EDT) -Received: (qmail 5427 invoked by uid 225); 1 Sep 2004 14:57:04 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 5403 invoked by alias); 1 Sep 2004 14:57:02 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 01 Sep 2004 07:56:59 -0700 -Received: by pallas.eruditorum.org (Postfix, from userid 33) - id 1FDD784C0F5; Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -Subject: [cpan #6245] Confirmed memory leak -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #6245 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -Date: Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -To: undisclosed-recipients: ; -Status: RO -Content-Length: 937 -Lines: 38 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -I Using : -1. SunOS 5.6 Generic_105181-33 sun4u sparc SUNW,Ultra-Enterprise - Perl 5.005_03 - DBI 1.37 - DBD-Oracle 1.14 - Oracle Release 8.1.5.0.0 - - -2. Linux 2.4.18-17.7.xsmp #1 SMP i686 - Perl 5.6.1 - DBI 1.41 - DBD-Oracle 1.16 - Oracle Release 8.1.6.0.0 - -II The following code: - -use strict; -use DBI; - -foreach ( 1 .. 100 ) { - my $dbh = DBI->connect( 'dbi:Oracle:host=****', '***', '***' ); - $dbh->disconnect(); - sleep(1) -} - -III Leak about 4K every 10 seconds - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8724 8720 2760 S 1.3 3.4 0:01 perl - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8736 8732 2760 S 0.7 3.4 0:01 perl - diff --git a/err_build/err_solarisnotes.msg b/err_build/err_solarisnotes.msg deleted file mode 100644 index eaddc475..00000000 --- a/err_build/err_solarisnotes.msg +++ /dev/null @@ -1,482 +0,0 @@ -From SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com Wed Dec 22 08:11:00 2004 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id iBM8Aog0091816 - for ; Wed, 22 Dec 2004 08:11:00 GMT - (envelope-from SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 22 Dec 2004 08:11:00 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Ch0it-0001A5-Rv; - Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Ch0it-0001A5-Rv - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Ch0is-0000To-R8 - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id F0F0DFE10C; - Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 8B2AAFE1C3 - for ; Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Received-SPF: none (lime.pobox.com: domain of alexzar@zorranlabs.com does not designate permitted sender hosts) -Received: from penguin.nocdirect.com (penguin.nocdirect.com [69.73.160.206]) - by lime.pobox.com (Postfix) with ESMTP id 2B41BFE159 - for ; Wed, 22 Dec 2004 02:13:17 -0500 (EST) -Received: from localhost ([127.0.0.1]) - by penguin.nocdirect.com with esmtps (TLSv1:DES-CBC3-SHA:168) - (Exim 4.43) - id 1Cgz53-0000fj-Bx; Tue, 21 Dec 2004 23:30:37 -0600 -Date: Tue, 21 Dec 2004 23:30:35 -0600 (CST) -From: Alex Zarutin -X-X-Sender: zorranla@penguin.nocdirect.com -To: Tim Bunce -Cc: dbi-users-help@perl.org -Subject: Step-by-Step installation manual of DBD-Oracle-1.16 on Sparc Solaris - 9 with Oracle 9.2.0.1.0 client. -Message-ID: -MIME-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-AntiAbuse: This header was added to track abuse, please include it with any abuse report -X-AntiAbuse: Primary Hostname - penguin.nocdirect.com -X-AntiAbuse: Original Domain - pobox.com -X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] -X-AntiAbuse: Sender Address Domain - zorranlabs.com -X-Source: -X-Source-Args: -X-Source-Dir: -Status: RO -X-Status: A -Content-Length: 15603 -Lines: 426 - - -Hi Tim, - -I have spent a couple days trying to install DBD-Oracle-1.16 (all -required stuff, such as GCC, DBI, etc has been installed before ) on -Sun-Fire v240 running Spark Solaris 9 with the Oracle 9.2.0.1.0 client -installed. The installation takes a couple minutes ONLY after you spend -days trying to make it workable. - -I wrote the log of what I do, in order to do not waste my time in -future. I am pretty sure that this log will be very useful for people -installing DBD-Oracle on Solaris. I published it on my log page, and left -link on it at http://cpanratings.perl.org/d/DBD-Oracle review page. I -would recommend you to add this log to the readme file of your next -releases. Log is written very detailed (step-by-step) with highlighted -typical mistakes. - -Environment: -Hardware/OS: bash-2.05# uname -a -SunOS qadmz41 5.9 Generic_117171-08 sun4u sparc SUNW,Sun-Fire-V240 -OS is actually "standard" Solaris 9 installation came on the box from -SUN - -Oracle Client: Oracle 9.2.0.1.0 -GCC: gcc version 3.3.2, installed to /usr/local/bin as a package from -http://www.sunfreeware.com/programlistsparc9.html -PERL: perl v5.8.5 built for sun4-solaris, installed to /usr/local/bin as -a package from http://www.sunfreeware.com/programlistsparc9.html -DBI: DBI-1.45, installed from http://search.cpan.org/~timb/DBI-1.45/ - -Step-by-Step Manual: - -Step 1: In order to install "DBD-Oracle-1.16" you need to download it, -set all appropriate environment variables (see readme for details) and -run <>. -I got an error that is mostly typical for Solaris installation: - -// ************************ Error 1 ***********************/ - -.... -Found header files in rdbms/demo. - -********************************************************* -I can't find the header files I need in your Oracle installation. -You probably need to install some more Oracle components. -I'll keep going, but the compile will probably fail. -See README.clients for more information. -********************************************************* -Checking for functioning wait.ph - -System: perl5.008005 sunos 5.9 generic sun4u sparc sunw,ultra-5_10 -solaris -Compiler: gcc -B/usr/ccs/bin/ -O -fno-strict-aliasing -pipe --I/usr/local/include -I/opt/gnu/include -D_LARGEFILE_SOURCE --D_FILE_OFFSET_BITS=64 - -.... -// *****************************************************/ - -Investigating this problem, I found that error message is thrown by the -"find_headers" sub of Makefile.PL, especially in this "if -(!$h_file{'oratypes.h'} || !$h_file{'ocidfn.h'})" evaluation. -So I checked these files to make sure that they are installed, but did -not find them under $ORACLE_HOME/rdbms -In the same time, I found an article saying about the similar problem -with DBD-Oracle on Linux, -http://baroti.homedns.org/steve/lost+found/cpan-install-DBD-Oracle-9-2-l -inux.html -They mentioned about two files, and since I was not sure about second -one, ociapr.h I copied both files. You should find its public.1.1.jar -file on the Disk3 of Oracle 9i installation set. - -bash-2.05# pwd -/ora_orig/Disk3/stage/Components/oracle.rdbms.oci/9.2.0.1.0/1/DataFiles - -bash-2.05# ls -al -total 970 -drwxr-xr-x 2 2840 42424 512 Aug 21 2002 . -drwxr-xr-x 3 2840 42424 512 Aug 21 2002 .. --rwxr-xr-x 1 2840 42424 2047 May 9 2002 bin.1.1.jar --rwxr-xr-x 1 2840 42424 206 May 9 2002 build.1.1.jar --rwxr-xr-x 1 2840 42424 135034 May 9 2002 demo.1.1.jar --rwxr-xr-x 1 2840 42424 329814 May 9 2002 public.1.1.jar - -You should just (as dba:oracle) to create the directory called public, -copy public.1.1.jar there and extract all files, since I would not guess -if the rest of them are used or not - -bash-2.05# mkdir $ORACLE_HOME/rdbms/public - -bash-2.05# ls -al $ORACLE_HOME/rdbms/public -total 3404 -drwxr-xr-x 2 oracle dba 512 Dec 21 12:12 . -drwxr-xr-x 10 oracle dba 512 Dec 21 12:05 .. -... --rw-r--r-- 1 oracle dba 6055 Mar 9 2002 ociapr.h --rw-r--r-- 1 oracle dba 10694 Jun 29 2000 ocidfn.h -... - -After that run <> again, and I hope process passes -fine. At least, it was fine in my case - -Step 2: You should <> the module, and as it appears on Solaris, -you will get typical problem. See my error log: - -// ************************ Error 2 ***********************/ -.... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -ld: fatal: file -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib//libclntsh.so: -wrong ELF class: ELFCLASS64 -ld: fatal: File processing errors. No output written to -blib/arch/auto/DBD/Oracle/Oracle.so -collect2: ld returned 1 exit status -*** Error code 1 -make: Fatal error: Command failed for target -`blib/arch/auto/DBD/Oracle/Oracle.so' - -// *****************************************************/ - -So, as another set on Google' posts showed that it is a possibility of -missing libraries compiled with 64 bits and same libraries compiled with -32 bits suppoert. As I understood, all components of installation, such -as Oracle client, Perl, GCC should support only one type of libraries, -either 32 or 64 bits. I found that having all as 32 bits is easier to me -than recompile perl, gcc as 64 (may be I am wrong in this assumption). -In order to have all of them as 32 bits, I changed lib to lib32 in -Manifest file (not Manifest.PL). - -You should replace the following lines in the "MakeMaker const_loadlibs -section": - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -By their lib32 clones: - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -And replace this line in "MakeMaker dynamic_lib section" (~~ line 491) - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread - -By its lib32 clone: - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread - -I hope, that after that process passes without any errors. Here is last -part, that I got during <>: - -..... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/local/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL -ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/local/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" -blib/script/ora_explain -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oracle.3 -Manifying blib/man3/DBD::Oraperl.3 - -III. Once we build the module, we should test it, to make sure that it -works fine. You should run <> to do it: - -Check that you have ORACLE_HOME, ORACLE_USERID, ORACLE_SID environment -variables set, like this: - -ORACLE_HOME=="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0 -ORACLE_USERID=STARSHIP/STARSHIP -ORACLE_SID=COLORADO - -When you run <>, you will probably get this errors: - -// ************************ Error 3 ***********************/ - -bash-2.05# make test -PERL_DL_NONLAZY=1 /usr/local/bin/perl "-MExtUtils::Command::MM" "-e" -"test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............DBI connect('','STARSHIP/STARSHIP',...) failed: -ORA-12545: Connect failed because target host or object does not exist -(DBD ERROR: OCIServerAttach) at t/10general.t line 12 -Undefined subroutine &main::BAILOUT called at t/10general.t line 15. -# Looks like your test died before it could output anything. -t/10general.............dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-31 - Failed 31/31 tests, 0.00% okay -..... - -// *****************************************************/ - -One more brainstorm, and I figured out another way to set ORACLE_USERID: - -ORACLE_USERID=STARSHIP/STARSHIP@COLORADO -ORACLE_SID=COLORADO - -Later, when tests finished, I was confirmed that it was probably -preferred way of setting ORACLE_USERID. -Tests did found correct settings, and "main" set of them returned the -following report: - -All tests successful, 1 test and 122 subtests skipped. -Files=18, Tests=1020, 24 wallclock secs (11.27 cusr + 1.34 csys = 12.61 -CPU) - -For the Extra test, less formal, but test anyway, I just commented these -two lines in test.pl file - -$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -and set the same values in the same form to the $dbuser as it was in -ORACLE_USERID , and -left $dbname empty, - -$dbname = ''; -$dbuser = 'STARSHIP/STARSHIP@COLORADO'; - -and got pretty good report: - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - -recommended) - as 'STARSHIP/STARSHIP@COLORADO' (via ORACLE_USERID env var or default - -recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -Fields: 6 -Names: 'NUM_T' 'DATE_T' 'CHAR_T' 'ROWID_T' -'RAW_T' 'NULL_T' -Lengths: 172 76 121 21 3 1 -OraTypes: 2 12 1 104 23 1 -SQLTypes: 8 93 12 -9104 -2 12 -Scale: 0 0 0 0 0 0 -Precision: 126 75 120 20 2 0 -Nullable: 1 1 1 1 1 1 -Est row width: 32 -Data rows: - fetch: '7.2', '21-DEC-04', 'STARSHIP', 'AAAADeAABAAAAZSAAA', '7D', -undef - -ora_logoff... -lda out of scope... - -Testing repetitive connect/open/close/disconnect: -If this test hangs then read the README.help file. -Expect sequence of digits, no other messages: -1 2 3 4 5 - -Test interaction of explicit close/logoff and implicit DESTROYs -Expect just 'done.', no other messages: -done. - -Testing row cache (5). -Test completed in 0 seconds. - -Test complete (0 seconds). -If the tests above have produced the 'expected' output then they have -passed. - -IV. The last part is actually target of all steps above, installing -build module. < did not surprise me, and it it passed -smoothly. - -bash-2.05# make install -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/dbdimp -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/ocitra -ce.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/mk.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.so -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.bs -Files found in blib/arch: installing files in blib/lib into architecture -dependent library tree -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/oraperl.ph -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/Oraperl.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle/GetInfo.pm -Installing /usr/local/share/man/man1/ora_explain.1 -Installing /usr/local/share/man/man3/DBD::Oracle.3 -Installing /usr/local/share/man/man3/DBD::Oraperl.3 -Installing /usr/local/bin/ora_explain -Writing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/.packl -ist -Appending installation info to -/usr/local/lib/perl5/5.8.5/sun4-solaris/perllocal.pod - -V. This is actually it, and you do not need to do anything else. But -investigating different errors during the various steps, I found the -very simple "independent sanity" testdbi perl script written by Jeff -Hunter. This script is not related to standard process of -making/buildin/testing/installation. It just verifies that you can -access DB and run a couple queries against it. The code itself, -testdbi.pl can be found at -http://www.idevelopment.info/data/Oracle/DBA_tips/Programming/PROGRAMMIN -G_2.shtml - -You just should set connection information, similar to how I did it, - - $ORACLE_SID = "COLORADO"; - $ORACLE_USERID = "STARSHIP"; - $ORACLE_PASSWORD = "STARSHIP"; - - $ENV{'ORACLE_SID'} = "$ORACLE_SID"; - $ENV{'ORACLE_HOME'} = /u01/app/oracle/product/9.2.0.1.0"; - -run it as any perl script, <>, and see result: - -bash-2.05# perl testdbi.pl - -Running testdbi.pl... - - (*) Attempting Oracle Login ... - OK - (*) Creating table TEST_DBI ... - OK - (*) Insert into TEST_DBI ... - 1 rows inserted. - 1 rows inserted. - 1 rows inserted. - OK - (*) Select from TEST_DBI ... - - --> TEST_DBI_INTR_NO : 1000 - --> TEST_DBI_NAME : Jeff Hunter - - --> TEST_DBI_INTR_NO : 1001 - --> TEST_DBI_NAME : Melody Hunter - - --> TEST_DBI_INTR_NO : 1002 - --> TEST_DBI_NAME : Alex Hunter - OK - - (*) Delete from TEST_DBI ... - 3 rows deleted. - OK - - (*) Drop table TEST_DBI ... - OK - - (*) Select USER and SYSTEM ... - - --> USER : STARSHIP - --> SYSDATE : 21-DEC-2004 16:49:59 - OK - - (*) Attempting Oracle Logoff ... - OK - -Ending testdbi.pl... - -With the best regards, - -Alex Zarutin - -Software Engineer -4thpass A Motorola Company -Seattle, WA -www.4thpass.com - - - - diff --git a/err_build/err_testfailnotable.msg b/err_build/err_testfailnotable.msg deleted file mode 100644 index 687d5ed7..00000000 --- a/err_build/err_testfailnotable.msg +++ /dev/null @@ -1,97 +0,0 @@ -From SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 18:10:51 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RHAOAK026067 - for ; Wed, 27 Oct 2004 18:10:51 +0100 (BST) - (envelope-from SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 18:10:51 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMp30-0000e2-Hh; - Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMp30-0000e2-Hh - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMp30-0001QS-2p - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 87C155A7D; - Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 7779A59A1 - for ; Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Received-SPF: pass (gold.pobox.com: domain of dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by gold.pobox.com (Postfix) with SMTP id DC5795A4A - for ; Wed, 27 Oct 2004 10:45:07 -0400 (EDT) -Received: (qmail 18140 invoked by uid 514); 27 Oct 2004 14:45:04 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 18131 invoked from network); 27 Oct 2004 14:45:04 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 14:45:04 -0000 -Received: (qmail 8663 invoked by uid 225); 27 Oct 2004 14:45:03 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 8659 invoked by alias); 27 Oct 2004 14:45:03 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from ns2.aramiska.net (HELO dmzms01.aramiska.net) (80.242.32.2) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 07:45:01 -0700 -Received: from ip-80-242-36-115.aramiska-arc.aramiska.net (ip-80-242-36-115.aramiska-arc.aramiska.net [80.242.36.115]) - by dmzms01.aramiska.net (Postfix) with ESMTP - id 9F21E1100D9; Wed, 27 Oct 2004 14:44:55 +0000 (UTC) -Received: from localhost (localhost [127.0.0.1]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id E558E7C; Wed, 27 Oct 2004 14:44:52 +0000 (UTC) -Received: from dansat.data-plan.com (ip-192-168-0-3.internal.data-plan.aramiska.net [192.168.0.3]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id D8A5E71; Wed, 27 Oct 2004 14:44:50 +0000 (UTC) -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9REioAA023212; - Wed, 27 Oct 2004 15:44:50 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i9REinmW023211; - Wed, 27 Oct 2004 15:44:49 +0100 (BST) -Date: Wed, 27 Oct 2004 15:44:49 +0100 -From: Tim Bunce -To: "H.Merijn Brand" -Cc: Tim Bunce , DBI developers -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Message-ID: <20041027144449.GB19991@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> <20041027093516.D001.H.M.BRAND@hccnet.nl> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20041027093516.D001.H.M.BRAND@hccnet.nl> -User-Agent: Mutt/1.4i -X-Virus-Scanned: by Aramiska Arc -Status: RO -Content-Length: 634 -Lines: 14 - -On Wed, Oct 27, 2004 at 09:39:33AM +0200, H.Merijn Brand wrote: -> On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> > file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> > size: 235224 bytes -> > md5: 9711550ed0ebfc743920a6a357ed717c -> -> I know you can't blame the test for not being able to create a table for the -> reason this failure shows, but there might be a more user-friendly way to fail ... - -Yeap. Some tests behave better in that situation. Looks like those -two need improving. Patches welcome! (I'd happily not touch DBD::Oracle -for a few months after the pain of the last few months :) - -Tim. - diff --git a/err_docs/err_trace.msg b/err_docs/err_trace.msg deleted file mode 100644 index 3d7500fb..00000000 --- a/err_docs/err_trace.msg +++ /dev/null @@ -1,14 +0,0 @@ -Add this to the DBD::Oracle docs as a handy note: - -$dbh->do(q{alter session set events '65285 trace name errorstack level 3'}); - -A trace file should then be generated. - -Trace files are generated in the 'user_dump_destination' specified in init.ora. - -Try $ORACLE_BASE/admin/$ORACLE_SID/udump. - -or the location returned by -select value -from v$parameter -where name like '%user_dump%' diff --git a/err_lob/err_csr_clob.msg b/err_lob/err_csr_clob.msg deleted file mode 100644 index 397d53b3..00000000 --- a/err_lob/err_csr_clob.msg +++ /dev/null @@ -1,65 +0,0 @@ -From dbi-users-bounce@isc.org Thu Sep 21 20:27:21 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id UAA18945; Thu, 21 Sep 2000 20:27:20 +0100 (BST) -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <02709-1@oink>; Mon, 21 Sep 1970 20:26:40 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 969564156:20:26825:1; Thu, 21 Sep 2000 19:22:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-2.mail.demon.net - id aa2026778; 21 Sep 2000 19:22 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 28A613E5D; - Thu, 21 Sep 2000 12:22:17 -0700 (PDT) -Received: with LISTAR (v1.0.0; list dbi-users); - Thu, 21 Sep 2000 12:17:37 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A59853E42 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) -Received: from wheel.cs.wisc.edu (wheel.cs.wisc.edu [128.105.121.12]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA00855 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) env-from (horn@wheel.cs.wisc.edu) -Received: (from horn@localhost) by wheel.cs.wisc.edu (8.9.2/8.9.2) id OAA16413 - for dbi-users@isc.org; Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -Date: Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -From: Jeffrey Horn -Message-Id: <200009211917.OAA16413@wheel.cs.wisc.edu> -To: dbi-users@isc.org -Subject: Setting ORA_TYPE after the fact... -Sender: horn@wheel.cs.wisc.edu -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: horn@cs.wisc.edu -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -X-Status: A -Content-Length: 969 -Lines: 20 - -I have a situation where I would like to return a cursor that contains a -CLOB as one of it's attributes from a PL/SQL procedure. What I get back is -a LOB locator and DBD doesn't actually read the CLOB but instead returns an -error. - -If I go through a bind/prepare/execute/fetch on a similar SQL statement all -is well. Is there any way that I can tell DBD that a given attribute of -a cursor is a CLOB once the cursor is already opened so that DBD will do the -right thing? - --- Jeff Horn - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_lob/err_loblenwide.msg b/err_lob/err_loblenwide.msg deleted file mode 100644 index 08023e97..00000000 --- a/err_lob/err_loblenwide.msg +++ /dev/null @@ -1,95 +0,0 @@ -From nobody@fsck.com Thu Dec 4 07:36:20 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hB47Y2nE066844 - for ; Thu, 4 Dec 2003 07:36:20 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 04 Dec 2003 07:36:20 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1ARgrA-0005O4-5M; - Wed, 03 Dec 2003 23:56:32 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1ARgrA-0005O4-5M - for pobox@dbi.demon.co.uk; Wed, 03 Dec 2003 23:56:32 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 314AB9A28F - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 188369A287 - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com[63.251.223.170]) - by icicle.pobox.com (Postfix) with SMTP - for ; Wed, 3 Dec 2003 18:56:31 -0500 (EST) -Received: (qmail 3178 invoked by uid 225); 3 Dec 2003 23:56:30 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 3174 invoked by alias); 3 Dec 2003 23:56:29 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Wed, 03 Dec 2003 15:56:18 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 91512114F1; Wed, 3 Dec 2003 18:56:07 -0500 (EST) -Subject: [cpan #4564] Perl DBI bug handling CLOBs -From: "Jay Turner via RT" -Reply-To: bug-DBI@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4564 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: J.Turner@mdl.com -To: "AdminCc of cpan Ticket #4564": ; -Date: Wed, 3 Dec 2003 18:56:07 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -X-Status: A -Content-Length: 1853 -Lines: 46 - - -This message about DBI was sent to you by J.Turner@mdl.com via rt.cpan.org - -Full context and any attached attachments can be found at: - - - -Date: Fri, 28 Feb 2003 16:55:28 -0800 - -It has come to my attention that PERL DBI counts on OCILobGetLength -returning BYTES. It returns CHARACTERS instead, which is the count of -variable-width characters. For multi-byte character sets this results -in errors such as: - -DBD::Oracle::st fetch failed: ORA-03130: the buffer for the next piece -to be fetched is required (DBD ERROR: OCILobGetLength) at id rmsc01.pl -line 294. - -The correct way to read CLOBs is - -1) Query the LOB locator for the CSID and CSFRM (character set ID and -form). A character set >= 800 is a mulitbyte character set and csfrm -<> 0 is CLOB. - -2) Pass the CSID and CSFRM to OCILobRead with AMT=0 and pass your -buffer address and size. - -3) Your callback routine must either be capable of completing the I/O -by allocating additional buffers, or it must notify the caller of -OCILobRead to free the lob locator, since an incomplete read jams the -locator-you can't use it for anything else without finishing the read -(attempts to reuse the locator will result in errors). - -Likewise, with OCILobWrite, you have to pass the CSID and CSFRM, with -AMT=0 and the buffer size in bytes. The callback can just say it has -zero bytes and set piece=OCI_LAST_PIECE. - -You cannot use the return value of OCILobGetLength as the size of the -data that is being read. The actual size of the data is unknown for -variable-width characters, and the buffer has to be big enough to -accomplish the translation, so you can't just double or triple the -return value from OCILobGetLength (I have seen that approach fail). - -You can simulate the effects of a foreign character set by - -$ export NLS_LANG=Japanese - diff --git a/err_lob/err_lobtesttblfail.msg b/err_lob/err_lobtesttblfail.msg deleted file mode 100644 index 1333ee88..00000000 --- a/err_lob/err_lobtesttblfail.msg +++ /dev/null @@ -1,208 +0,0 @@ -From SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 15:22:22 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RELAAO018624 - for ; Wed, 27 Oct 2004 15:22:22 +0100 (BST) - (envelope-from SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 15:22:22 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMiQ8-0000Eo-FG; - Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMiQ8-0000Eo-FG - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMiQ8-0006dS-9n - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B3BB911C325; - Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9947911C2CE - for ; Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Received-SPF: pass (icicle.pobox.com: domain of dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by icicle.pobox.com (Postfix) with SMTP id 5033611C34F - for ; Wed, 27 Oct 2004 03:39:46 -0400 (EDT) -Received: (qmail 12004 invoked by uid 514); 27 Oct 2004 07:39:43 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 11995 invoked from network); 27 Oct 2004 07:39:43 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 07:39:43 -0000 -Received: (qmail 13565 invoked by uid 225); 27 Oct 2004 07:39:43 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 13560 invoked by alias); 27 Oct 2004 07:39:42 -0000 -X-Spam-Status: No, hits=-3.7 required=8.0 - tests=BAYES_00,LARGE_HEX -X-Spam-Check-By: la.mx.develooper.com -Received: from smtp-vbr15.xs4all.nl (HELO smtp-vbr15.xs4all.nl) (194.109.24.35) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 00:39:40 -0700 -Received: from [127.0.0.1] (procura.xs4all.nl [213.84.163.145]) - by smtp-vbr15.xs4all.nl (8.12.11/8.12.11) with ESMTP id i9R7dWHI013040; - Wed, 27 Oct 2004 09:39:34 +0200 (CEST) - (envelope-from h.m.brand@hccnet.nl) -Date: Wed, 27 Oct 2004 09:39:33 +0200 -From: "H.Merijn Brand" -To: Tim Bunce -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Cc: DBI developers -In-Reply-To: <20041022213625.GA22377@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> -Message-Id: <20041027093516.D001.H.M.BRAND@hccnet.nl> -MIME-Version: 1.0 -Content-Type: text/plain; charset="US-ASCII" -X-Mailer: Becky! ver. 2.11.02 [en] -X-Virus-Scanned: by XS4ALL Virus Scanner -X-Virus-Checked: Checked -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i9RELAAO018624 -Status: RO -X-Status: A -Content-Length: 7175 -Lines: 134 - -On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> size: 235224 bytes -> md5: 9711550ed0ebfc743920a6a357ed717c - -I know you can't blame the test for not being able to create a table for the -reason this failure shows, but there might be a more user-friendly way to fail ... - -I'll report back when the DBA has fixed the tablespace - -HP-UX 11.11/64 (11i) + Oracle-9.2.0/64 + perl-5.8.5-dor/64 - -PERL_DL_NONLAZY=1 /pro/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, -'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............ok -t/15nls.................ok -t/20select..............ok -t/21nchar............... Database and client versions and character sets: -Database 9.2.0.1.0 CHAR set is US7ASCII (Non-Unicode), NCHAR set is AL16UTF16 ( -nicode) -Client 9.2.0.1 NLS_LANG is '', NLS_NCHAR is '' -t/21nchar...............ok -t/22nchar_al32utf8......ok -t/22nchar_utf8..........ok -t/23wide_db.............skipped - all skipped: Database character set is not Unicode -t/23wide_db_8bit........skipped - all skipped: Database character set is not Unicode -t/23wide_db_al32utf8....skipped - all skipped: Database character set is not Unicode -t/24implicit_utf8.......ok -t/25plsql...............ok -t/30long................ok 188/470DBD::Oracle::db do failed: ORA-03237: Initial -Extent of specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: -OCIStmtExecute) [for Statement "create table dbd_ora__drop_me ( idx integer, ln - NCLOB, dt date )"] at t/nchar_test_lib.pl line 356. -t/30long................ok 189/470DBD::Oracle::st execute failed: ORA-00942: ta -le or view does not exist (DBD ERROR: error possibly near <*> indicator at char -12 in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statem -nt "insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1= -0, :p2='0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X...'] at t/30long.t line 153. -# Failed test (t/30long.t at line 153) -t/30long................NOK 190DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=41, -:p2='12345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -...'] at t/30long.t line 154. -# Failed test (t/30long.t at line 154) -t/30long................NOK 191DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=42, -:p2='2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -...'] at t/30long.t line 155. -t/30long................NOK 192# Failed test (t/30long.t at line 155) -DBD::Oracle::st execute failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 12 in 'insert into <*>dbd_ora__dr -p_me values (:p1, :p2, SYSDATE)') [for Statement "insert into dbd_ora__drop_me -alues (?, ?, SYSDATE)" with ParamValues: :p1=43, :p2=undef] at t/30long.t line -56. -# Failed test (t/30long.t at line 156) -t/30long................NOK 193DBD::Oracle::db prepare failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 14 -in 'select * from <*>dbd_ora__drop_me order by idx') [for Statement "select * f -om dbd_ora__drop_me order by idx"] at t/30long.t line 170. -# Failed test (t/30long.t at line 170) -Can't call method "trace" on an undefined value at t/30long.t line 171. -t/30long................NOK 194# Looks like you planned 470 tests but only ran -94. -# Looks like your test died just after 194. -t/30long................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 190-470 - Failed 281/470 tests, 40.21% okay (less 122 skipped tests: 67 okay, 14. -6%) -t/31lob.................DBD::Oracle::db do failed: ORA-03237: Initial Extent of -specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: OCIStmtEx -cute) [for Statement " - CREATE TABLE dbd_ora__drop_me ( - id INTEGER NOT NULL, - data BLOB - ) - "] at t/31lob.t line 21. -DBD::Oracle::db do failed: ORA-00942: table or view does not exist (DBD ERROR: -rror possibly near <*> indicator at char 12 in 'INSERT INTO <*>dbd_ora__drop_me -(id,data) VALUES (1, EMPTY_BLOB())') [for Statement "INSERT INTO dbd_ora__drop_ -e (id,data) VALUES (1, EMPTY_BLOB())"] at t/31lob.t line 31. -DBD::Oracle::db prepare failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 17 in 'SELECT data FROM <*>dbd_or -__drop_me WHERE id = :p1') [for Statement "SELECT data FROM dbd_ora__drop_me WH -RE id = ?"] at t/31lob.t line 34. -Can't call method "bind_param" on an undefined value at t/31lob.t line 36. -# Looks like your test died before it could output anything. -t/31lob.................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-2 - Failed 2/2 tests, 0.00% okay -t/40ph_type.............ok -t/50cursor..............ok -t/60reauth..............ORACLE_USERID_2 not defined. Tests skipped. -skipped - all skipped: no reason given -t/70meta................ok -Failed Test Stat Wstat Total Fail Failed List of Failed -------------------------------------------------------------------------------- -t/30long.t 255 65280 470 557 118.51% 190-470 -t/31lob.t 255 65280 2 4 200.00% 1-2 -4 tests and 122 subtests skipped. -Failed 2/18 test scripts, 88.89% okay. 283/1883 subtests failed, 84.97% okay. -make: *** [test_dynamic] Error 255 - --- -H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/) -using perl-5.6.1, 5.8.0 & 633 on HP-UX 10.20 & 11.00, AIX 4.2, AIX 4.3, - WinNT 4, Win2K pro & WinCE 2.11 often with Tk800.024 &/| DBD-Unify -ftp://ftp.funet.fi/pub/languages/perl/CPAN/authors/id/H/HM/HMBRAND/ - - - - diff --git a/err_lob/err_nclob_form.msg b/err_lob/err_nclob_form.msg deleted file mode 100644 index 05587693..00000000 --- a/err_lob/err_nclob_form.msg +++ /dev/null @@ -1,189 +0,0 @@ -From dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org Tue Jul 22 07:40:59 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6M6UUD7096422 - for ; Tue, 22 Jul 2003 07:40:58 +0100 (BST) - (envelope-from dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 22 Jul 2003 07:40:58 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058814697:11:26523:33; Mon, 21 Jul 2003 19:11:37 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1126786; 21 Jul 2003 19:11 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E855B21C37F - for ; Mon, 21 Jul 2003 15:11:18 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 9010121C236 - for ; Mon, 21 Jul 2003 15:11:17 -0400 (EDT) -Received: (qmail 66848 invoked by uid 1005); 21 Jul 2003 19:11:15 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 66832 invoked by uid 76); 21 Jul 2003 19:11:15 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 21 Jul 2003 12:11:15 -0700 -Received: (qmail 559 invoked by uid 225); 21 Jul 2003 19:11:08 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 552 invoked by uid 507); 21 Jul 2003 19:11:07 -0000 -Received-SPF: unknown -Received: from sneakemail.com (HELO monkey.sneakemail.com) (207.106.87.13) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Mon, 21 Jul 2003 12:11:03 -0700 -Received: (qmail 22505 invoked by uid 501); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #3); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #2); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #1); 21 Jul 2003 19:10:57 -0000 -Date: Mon, 21 Jul 2003 21:10:53 +0200 -From: "Wolfgang Weisselberg" -To: dbi-users@perl.org -Subject: DBD::Oracle and unicode-NCLOBs leads to ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) -Message-ID: <13502-46198@sneakemail.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.6 required=7.0 tests=CARRIAGE_RETURNS,FROM_ENDS_IN_NUMS,FROM_HAS_MIXED_NUMS,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_MUTT version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 6055 -Lines: 132 - -Hello all! - -Even after extensive googling and looking through the docs I fail -to fetch NCLOBs from an Oracle 9.2i database where the national -character set is unicode. - -I believe it has been done before, but I could not find anything ... -I would be grateful for any pointers. - - -NCLOBs work like CLOBs when the national character set is not -unicode, even with the old DBI 1.21 and DBD::Oracle 1.12 on an -Oracle 8 client. NVarchar2 and NChar work OK even with unicode. - -Setting NSL_LANG to AMERICAN_AMERICA.UTF8 or .AL32UTF8 does not -help, as I suspected. - -I tried using Oracle 9.2i (the DB is using 9.2i) on a Debian -Linux box. I upgraded DBI to 1.37 and DBD::Oracle to 1.14 (the -newest versions according to CPAN). I got zero errors on make -test with both. Perl is Debian's normal "perl5 (revision 5.0 -version 6 subversion 1)". - -A simple - select memo from unicode_test -(memo being the NCLOB field) fails (again, only with the national -charset being unicode). - -The relevant code snippet (RaiseError being set, of course): - -| $| = 1; -| print "DBI: $DBI::VERSION\n", -| "DBD::Oracle $DBD::Oracle::VERSION\n"; -| my $sth = $dbh->prepare("select memo from unicode_test"); -| $sth->execute(); -| -| while ( my ($memo) = $sth->fetchrow_array() ) { -| print Dumper $memo; -| } -| exit; - - -The output: - -| DBI: 1.37 -| DBD::Oracle 1.14 -| $VAR1 = ''; -| $VAR1 = ''; -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. - - - -Running with tracelevel 3: - [...] -| dbd_st_prepare'd sql SELECT -| dbd_describe SELECT (EXPLICIT, lb 99999999)... -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_execute SELECT (out0, lob0)... -| dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -| <- execute= '0E0' at nclobtest.pl line 79 via nclobtest.pl line 60 -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -| 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x82f8e28)~INNER 'ParamValues') -| error: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| 1 <- FETCH= HASH(0x831661c)0keys at nclobtest.pl line 81 via nclobtest.pl line 60 -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. - - - -Tracelevel 9 (yes, it's a bit verbose :-/ ) - -[...] -| OCIDescriptorAlloc(0x831c058,0x8395228,OCI_DTYPE_LOB,0,0) -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| OCIAttrSet(0x8335b34,OCI_HTYPE_STMT,0xbffff30c,4,11,0x832d5a4)=SUCCESS -| OCIDefineByPos(0x8335b34,0x8395224,0x832d5a4,1,0x8395228,-1,112,0x83414e0,0x83414f0,0x8341500,0)=SUCCESS -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -[...] -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| 0 (rc=0): '' -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead(0x832d530,0x832d5a4,0x832c69c,0xbffff318,1,0x8394da0,24,(nil),(nil),0,1)=ERROR -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| OCIErrorGet(0x832d5a4,1,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=SUCCESS -| OCIErrorGet after OCILobRead (er1:ok): -1, 24806: ORA-24806: LOB form mismatch -| -| OCIErrorGet(0x832d5a4,2,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=NO_DATA -| 0 (rc=0): undef -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -[gets and prints error message] - - -Any ideas anyone? - --Wolfgang - diff --git a/err_lob/err_nulllobsegv.msg b/err_lob/err_nulllobsegv.msg deleted file mode 100644 index 6de3c99b..00000000 --- a/err_lob/err_nulllobsegv.msg +++ /dev/null @@ -1,93 +0,0 @@ -From dbi-users-return-1743-Tim.Bunce=ig.co.uk@perl.org Wed Apr 11 04:00:48 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id EAA17912; Wed, 11 Apr 2001 04:00:48 +0100 (BST) -Received: from 194.217.242.36 by oink with SMTP (PP) id <02579-1@oink>; - Sat, 11 Apr 1970 04:00:28 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 986956750:10:04398:0; Wed, 11 Apr 2001 02:39:10 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-1.mail.demon.net - id aa1106187; 11 Apr 2001 2:39 GMT -Received: (qmail 32618 invoked by uid 508); 11 Apr 2001 02:39:06 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 32603 invoked from network); 11 Apr 2001 02:39:05 -0000 -Received: from owns.warpcore.org (216.81.249.18) by tmtowtdi.perl.org with SMTP; - 11 Apr 2001 02:39:05 -0000 -Received: (from thebrain@localhost) by owns.warpcore.org (8.11.1/8.11.1) - id f3B2cxH06298 for dbi-users@perl.org; - Tue, 10 Apr 2001 21:38:59 -0500 -Date: Tue, 10 Apr 2001 21:38:59 -0500 -From: Stephen Clouse -To: dbi-users@perl.org -Subject: Bizarre DBD::Oracle Segfault -Message-ID: <20010410213859.B2766@owns.warpcore.org> -Mail-Followup-To: dbi-users@perl.org -Mime-Version: 1.0 -Content-Type: text/plain -Content-Disposition: inline; filename="msg.pgp" -User-Agent: Mutt/1.2.5i -Status: RO -Content-Length: 1918 -Lines: 54 - ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -I sent an email to the dbi-users list about a number of DBD::Oracle CLOB -handling problems waaaaaaaaaaaaaaay back (end of January or so) that today -someone dug up and inquired if I had ever found fixes for what I had pointed -out. - -The problems outlined that day turned out to be the test script itself, which -was doing so much bizarre stuff on one statement that DBD::Oracle just went to -sleep instead (and so was the actual program that instigated the writing of the -test script). - -Well, all but one problem was the script. This, the most serious one, continues -to linger: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',undef); - -On Linux, DBI 1.15, Oracle 8.1.6, and DBD::Oracle 1.06, this segfaults on the -execute. Unfortunately this manifests itself too deep in Oracle for me to -debug. - -The bizarre part is, either of the two snippets below will work: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',''); -$st->execute('B','B',undef); - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',$lobvalue); -$st->execute('B','B',undef); - -It's only when binding undef as the LOB value in the very first execute of a -statement that the segfault occurs. At any other time, it's kosher. That -qualifies as bizarre in my book. - -Your guess is better than mine. - -- -- -Stephen Clouse -Senior Programmer, IQ Coordinator Project Lead -The IQ Group, Inc. - ------BEGIN PGP SIGNATURE----- -Version: PGP 6.5.8 - -iQA+AwUBOtPDwgOGqGs0PadnEQLmtgCeJHTStLu8Q8oFb9UQ4995f8vhZH8Al1p6 -RD5m0FEJH2tQiY0+b6542mQ= -=L0M+ ------END PGP SIGNATURE----- - diff --git a/err_lob/err_tmplobfree.msg b/err_lob/err_tmplobfree.msg deleted file mode 100644 index 0ec8f940..00000000 --- a/err_lob/err_tmplobfree.msg +++ /dev/null @@ -1,537 +0,0 @@ -From SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com Wed Aug 25 17:53:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PGpkpQ033405 - for ; Wed, 25 Aug 2004 17:53:57 +0100 (BST) - (envelope-from SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 17:53:57 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Bzyve-0007kY-Gp; - Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Bzyve-0007kY-Gp - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Bzyvd-0000zb-Lg - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id AA6D8B0635; - Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 9B2A1B0BB0 - for ; Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -Received: from natnoddy.rzone.de (natnoddy.rzone.de [81.169.145.166]) - by lime.pobox.com (Postfix) with ESMTP id 2AAB1B0635 - for ; Wed, 25 Aug 2004 10:39:06 -0400 (EDT) -Received: from genericom.de (pD95195AC.dip.t-dialin.net [217.81.149.172]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7PEc05w018990 - for ; Wed, 25 Aug 2004 16:38:01 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412CA445.FC2F9EF2@genericom.de> -Date: Wed, 25 Aug 2004 16:37:57 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim.Bunce@pobox.com -Subject: DBD::Oracle: Freeing a temporary blob -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms4BC2D4519D41A502BB06559C" -Status: RO -X-Status: A -Content-Length: 4985 -Lines: 122 - -This is a cryptographically signed message in MIME format. - ---------------ms4BC2D4519D41A502BB06559C -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Dear Tim, - -first, I would really like to thank you for the great work you have done -with your DBI/DBD work. We are using it extensively in several projects -and we are highly pleased. - -Unfortunately I have now encountered a problem we need to fix urgently, -since our customer's production is seriously affected. - -We tried for many days to find a solution (google, newsgroups, -trial-and-error...), without luck. So my last chance is to contact you -directly, although I assume you have a lot work yourself. - ---- - -The problem: - -Our database contains a stored function "ReadUnitBlob()" that returns a -temporary blob: - -function ReadUnitBlob(UnitID_IN in integer) return blob -is -... -begin - ... - dbms_lob.createtemporary(retBlob, false, dbms_lob.call); - dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); - ... - return retBlob; -end; - -We call this function in Perl in a big loop to fetch a lot of blobs (~ -100000) using something like: - -my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -ora_auto_lob => 0 }); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); -my ($loc) = $sth->fetchrow_array(); -$sth->finish(); -... -while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) - ... - -Although this works, it has a big disadvantage: Oracle does not -automaticaly free the temporary blob, so it shortly runs out of temp. -space. (confirmed with "select * from v$temporary_lobs"). - -Acording to the Oracle docs this can be we solved by implicitly freeing -the temp. blob, e.g. by calling the PLSQL method -"dbms_lob.freetemporary()". I tried differnt ways to do this with -DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -locator from the my stored procedure and to pass it to a call of -"dbms_lob.freetemporary()": - -my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -ora_auto_lob => 0 }); -my $bloc; -$sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); - -obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) - -Can you help me??? Do you know a way how to free the temp. blob using -DBD::Oracle (using Oracle::OCI is not possible, since the customer is -strinctly refusing to install it). - -Otherwise, would it be possible include an additional DBD::Oracle LOB -Locator Method "ora_lob_freetemporary()" that warps -"OCILobFreeTemporary" ? - -Any help is really appreciated! - -Greeting from Germany, - - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------ms4BC2D4519D41A502BB06559C -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjUxNDM3NThaMCMGCSqG -SIb3DQEJBDEWBBS+u38esQAv19TdNkv4jgxlzsRqSzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAJQgoN5ASnyjnB7bgrv1+V7Cu4ULKe1CkHs0IEZaB -KuJcm98U7kskRyC5g6YNopuJxFbr19K3q5rrJGoUscKjiw== ---------------ms4BC2D4519D41A502BB06559C-- - - -From SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com Wed Aug 25 22:47:05 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PLjxpJ037568 - for ; Wed, 25 Aug 2004 22:47:04 +0100 (BST) - (envelope-from SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 22:47:04 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C04j1-00038v-Pz; - Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C04j1-00038v-Pz - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C04j0-00002I-FU - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:30 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AD1815463; - Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 85FFF55E7 - for ; Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Received-SPF: none (gold.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail04.svc.cra.dublin.eircom.net (mail04.svc.cra.dublin.eircom.net [159.134.118.20]) - by gold.pobox.com (Postfix) with SMTP id 14C005463 - for ; Wed, 25 Aug 2004 16:50:25 -0400 (EDT) -Received: (qmail 5678 messnum 5046341 invoked from network[213.94.228.233/unknown]); 25 Aug 2004 20:50:23 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail04.svc.cra.dublin.eircom.net (qp 5678) with SMTP; 25 Aug 2004 20:50:23 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PKsrof034865; - Wed, 25 Aug 2004 21:54:53 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7PKsqas034864; - Wed, 25 Aug 2004 21:54:52 +0100 (BST) -Date: Wed, 25 Aug 2004 21:54:52 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim.Bunce@pobox.com -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040825205452.GC34655@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412CA445.FC2F9EF2@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 4674 -Lines: 124 - -On Wed, Aug 25, 2004 at 04:37:57PM +0200, Philipp Lang wrote: -> Dear Tim, -> -> first, I would really like to thank you for the great work you have done -> with your DBI/DBD work. We are using it extensively in several projects -> and we are highly pleased. - -Thanks Philipp! - -> Unfortunately I have now encountered a problem we need to fix urgently, -> since our customer's production is seriously affected. -> -> We tried for many days to find a solution (google, newsgroups, -> trial-and-error...), without luck. So my last chance is to contact you -> directly, although I assume you have a lot work yourself. - -I am very busy and what little spare time I have for DBD::Oracle -is going into trying to get 1.16 released (which is proving to be -hard as we're tripping over Oracle bugs when an Oracle 8 client -talks to an Oracle 9+ server.) It's a major release that will help -many people so I need to give that priority. - -Separately I am exploring ways to fund DBI and DBD::Oracle development -so I can devote more time to it. There's is much that needs to be -done and much more that could be done beyond that. - -The Perl Foundation (TPF) have setup a way for people and companies -to make donations for DBI development [as yet unannounced so please -keep to yourself]. A note on the contribution could indicate that the -donor would like it used for a particular purpose, such as DBD::Oracle. - -Anyway, to cut a long story short, it would be much easier to devote -time to this if it could be funded in some way. - -I think the TPF setup is working so it could be done that way. -Alternatively you could contract me to do the work for you. -That would be quicker and simpler for you as TPF's non-profit -status doesn't make a difference to European donors. - -My standard daily rate for add-hoc consulting is 1600 Euro. -I'd expect to be able to sort this out inside a day, and prefer -fixed-price quotes anyway, so would 1600 Euro be okay? - -Of course, if you feel your company would like to either -make a general contribution to DBI/DBD::Oracle development beyond -that, or to fund the development of specific functionality that -would be of extra value to you then I'd be happy to talk about that. - -I hate asking for money, and would much rather dig into the code and -reply with a patch, but it's just not practical for me now. Sorry. - -Tim. - -> --- -> -> The problem: -> -> Our database contains a stored function "ReadUnitBlob()" that returns a -> temporary blob: -> -> function ReadUnitBlob(UnitID_IN in integer) return blob -> is -> ... -> begin -> ... -> dbms_lob.createtemporary(retBlob, false, dbms_lob.call); -> dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); -> ... -> return retBlob; -> end; -> -> We call this function in Perl in a big loop to fetch a lot of blobs (~ -> 100000) using something like: -> -> my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -> ora_auto_lob => 0 }); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> my ($loc) = $sth->fetchrow_array(); -> $sth->finish(); -> ... -> while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) -> ... -> -> Although this works, it has a big disadvantage: Oracle does not -> automaticaly free the temporary blob, so it shortly runs out of temp. -> space. (confirmed with "select * from v$temporary_lobs"). -> -> Acording to the Oracle docs this can be we solved by implicitly freeing -> the temp. blob, e.g. by calling the PLSQL method -> "dbms_lob.freetemporary()". I tried differnt ways to do this with -> DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -> locator from the my stored procedure and to pass it to a call of -> "dbms_lob.freetemporary()": -> -> my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -> ora_auto_lob => 0 }); -> my $bloc; -> $sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> -> obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) -> -> Can you help me??? Do you know a way how to free the temp. blob using -> DBD::Oracle (using Oracle::OCI is not possible, since the customer is -> strinctly refusing to install it). -> -> Otherwise, would it be possible include an additional DBD::Oracle LOB -> Locator Method "ora_lob_freetemporary()" that warps -> "OCILobFreeTemporary" ? -> -> Any help is really appreciated! -> -> Greeting from Germany, -> -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - -From SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com Thu Aug 26 14:06:45 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QD6Som051890 - for ; Thu, 26 Aug 2004 14:06:45 +0100 (BST) - (envelope-from SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 14:06:45 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0HX2-0003PB-Sd; - Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0HX2-0003PB-Sd - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0HX2-0003BR-F8 - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id DC4BFB0D27; - Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id CE95AB0D7D - for ; Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 81.169.145.165(natsmtp00.rzone.de) -Received: from natsmtp00.rzone.de (natsmtp00.rzone.de [81.169.145.165]) - by lime.pobox.com (Postfix) with ESMTP id 71107B0D27 - for ; Thu, 26 Aug 2004 06:30:56 -0400 (EDT) -Received: from genericom.de (pD9E61E09.dip.t-dialin.net [217.230.30.9]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7QAUoTY009695 - for ; Thu, 26 Aug 2004 12:30:51 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412DBBD7.2C124831@genericom.de> -Date: Thu, 26 Aug 2004 12:30:47 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------msB92907D67E7D4C0121D50420" -Status: O -X-Status: A -Content-Length: 3040 -Lines: 58 - -This is a cryptographically signed message in MIME format. - ---------------msB92907D67E7D4C0121D50420 -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Tim Bunce wrote: -> -> I hate asking for money, and would much rather dig into the code and -> reply with a patch, but it's just not practical for me now. Sorry. - -Thanks for your quick reply. I can fully understand your position in -this issue. We will need to submit this issue to our customer, and -eventually it will be their decision, since a) the problem technically -originates in external components -and b) our work is payed on a time and material basis. - -Thanks again, - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------msB92907D67E7D4C0121D50420 -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjYxMDMwNDhaMCMGCSqG -SIb3DQEJBDEWBBQbWUdl+peoD/lHpzCOnuQfzAsbJzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAXzFame8ymLqgf+7nZ4V7L9e9J+aG6z5ipa+iv76v -EFAg5QObdHdvTnq5QEAjEnLKgeUGvdgpS6PA0h+beEIeIA== ---------------msB92907D67E7D4C0121D50420-- - - -From SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com Thu Aug 26 16:42:55 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QFgKp1054926 - for ; Thu, 26 Aug 2004 16:42:55 +0100 (BST) - (envelope-from SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 16:42:55 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0L1E-0005sL-5Z; - Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0L1E-0005sL-5Z - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0L1E-0001t1-Cm - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 541E8AFAD6; - Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 1C39FB0747 - for ; Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail01.svc.cra.dublin.eircom.net (mail01.svc.cra.dublin.eircom.net [159.134.118.17]) - by lime.pobox.com (Postfix) with SMTP id BFBB5AFAD6 - for ; Thu, 26 Aug 2004 10:14:19 -0400 (EDT) -Received: (qmail 12246 messnum 7731352 invoked from network[213.94.228.233/unknown]); 26 Aug 2004 14:14:17 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail01.svc.cra.dublin.eircom.net (qp 12246) with SMTP; 26 Aug 2004 14:14:17 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QEItof052863; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7QEItr3052862; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) -Date: Thu, 26 Aug 2004 15:18:55 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040826141855.GC52359@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> <412DBBD7.2C124831@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412DBBD7.2C124831@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 926 -Lines: 25 - -Okay. Thanks. Let me know how it turns out. - -Tim. - -On Thu, Aug 26, 2004 at 12:30:47PM +0200, Philipp Lang wrote: -> Tim Bunce wrote: -> > -> > I hate asking for money, and would much rather dig into the code and -> > reply with a patch, but it's just not practical for me now. Sorry. -> -> Thanks for your quick reply. I can fully understand your position in -> this issue. We will need to submit this issue to our customer, and -> eventually it will be their decision, since a) the problem technically -> originates in external components -> and b) our work is payed on a time and material basis. -> -> Thanks again, -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - diff --git a/err_unicode/err_char.msg b/err_unicode/err_char.msg deleted file mode 100644 index d2a7a4a3..00000000 --- a/err_unicode/err_char.msg +++ /dev/null @@ -1,129 +0,0 @@ -From dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org Fri May 31 15:39:50 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g4VEdno73229 - for ; Fri, 31 May 2002 15:39:49 +0100 (BST) - (envelope-from dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 31 May 2002 15:39:49 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1022854157:20:06570:1; Fri, 31 May 2002 14:09:17 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2005972; 31 May 2002 14:08 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 210F42BF43 - for ; Fri, 31 May 2002 10:08:39 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (unknown [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 8D88B2BF11 - for ; Fri, 31 May 2002 10:08:38 -0400 (EDT) -Received: (qmail 47355 invoked by uid 1005); 31 May 2002 14:07:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 47340 invoked by uid 76); 31 May 2002 14:07:41 -0000 -Received: from wsrgeh.wsr.ac.at (HELO wsrgeh.wsr.ac.at) (143.130.16.2) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Fri May 31 14:07:41 2002 -0000 -Received: from dialog.wsr.ac.at (dialog.wsr.ac.at [143.130.50.66]) - by wsrgeh.wsr.ac.at (8.11.6/8.11.6) with ESMTP id g4VE8Or11772 - for ; Fri, 31 May 2002 16:08:24 +0200 -Received: (from hjp@localhost) - by dialog.wsr.ac.at (8.11.6/8.11.6) id g4VE8Nf12538 - for dbi-users@perl.org; Fri, 31 May 2002 16:08:23 +0200 -Date: Fri, 31 May 2002 16:08:23 +0200 -From: "Peter J. Holzer" -To: dbi-users@perl.org -Subject: Re: Insert a blank value into Oracle -Message-ID: <20020531160823.F28779@wsr.ac.at> -Mail-Followup-To: "Peter J. Holzer" , - dbi-users@perl.org -References: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw> -Mime-Version: 1.0 -Content-Type: multipart/signed; micalg=pgp-md5; - protocol="application/pgp-signature"; boundary="aZoGpuMECXJckB41" -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -In-Reply-To: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw>; from larry_wu@mail.gss.com.tw on Fri, May 31, 2002 at 06:38:45PM +0800 -Status: RO -Content-Length: 2819 -Lines: 74 - ---aZoGpuMECXJckB41 -Content-Type: text/plain; charset=iso-8859-1 -Content-Disposition: inline -Content-Transfer-Encoding: quoted-printable - -On 2002-05-31 18:38:45 +0800, Larry Wu (=A7d=A4l=B7=D3) wrote: -> I encountered a problem to insert a space value ( like ' ' ) into Oracle -> database. -[...] -> Unfortunately, I have a table A contained a not allow null column -> NotNullCol. Now I want to insert a row like below: ->=20 -> $sth =3D $dbh->prepare( qq{ insert into A ( KeyCol, NotNullCol ) -> values (?,?)} ); -> $sth->bind_param(1, '1'); -> $sth->bind_param(2, ' '); -> $sth->execute; ->=20 -> When I executed this file I got an error from Oracle: Can't insert NULL -> value into ( "A"."NotNullCol") (DBD ERROR: OCIStmtExecute). -> I think the space value was truncated in the process. Could any one tell = -me -> how to keep a blank space in my bind_param ? - -use DBD::Oracle qw(:ora_types); -[...] -$sth->bind_param(2, ' ', { ora_type =3D> ORA_CHAR }); - -This is a frequently asked question here. The default type for strings, -ORA_VARCHAR2, strips trailing blanks from strings. A few months ago, -during one of the diskussuions about this feature, Tim said that he -might add a way to change the default in a future version of -DBD::Oracle. If he doesn't, maybe a paragraph like the following should -be added to the doc (not sure where - it fits below "Using DBD::Oracle -with Oracle 8 - Features and Issues" but it isn't Oracle 8 specific): - - =3Dhead2 Inserting strings with trailing spaces - - OCI provides several string types which behave differently. - Unfortunately, none of them can store arbitrary perl strings. - By default, DBD::Oracle binds string variables as ORA_VARCHAR2, - which allows embedded NUL characters but strips trailing spaces. If - you need trailing spaces, but don't need embedded NUL characters, - you can explicetly bind the param to type ORA_CHAR with: - - $sth->bind_param(($field_num, $string_value, - { ora_type =3D> ORA_CHAR }); - - =20 - hp - ---=20 - _ | Peter J. Holzer | Aeltere Sources (also solche, die schon -|_|_) | Sysadmin WSR / LUGA | aelter als 12 Stunden sind) sollte man -| | | hjp@wsr.ac.at | bei Linux generell nicht einsetzen - -__/ | http://www.hjp.at/ | Real Time Linux?? -- Gerhard Schneider - ---aZoGpuMECXJckB41 -Content-Type: application/pgp-signature -Content-Disposition: inline - ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.0.6 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -iQDQAwUBPPeD11LjemazOuKpAQEtNAXUC6rFL0C0v6MNW/K5ggXcSDY7Xvrj6Ed/ -jqjHq2Dx+h2rIMWXCDIGZVphSG74u4FL41AQF/rzGR/e56qH7aAxVmaiLdQE/DRi -zzsoOHoPEg96FhHljDtCZyxHzsz9sRJ1dfW1PELn5r2OSYPPsVzMoeR4iEXnVjvV -ZYH/OfbKRKhysIHjcNYKcyQL87GXdjzCEas3Xz+jyxW2vqzGAwUfTim4ySY9rF37 -c5vopwrTFCsi58r1LccFhQqEfw== -=Xe8d ------END PGP SIGNATURE----- - ---aZoGpuMECXJckB41-- - diff --git a/err_unicode/err_twolongstr.msg b/err_unicode/err_twolongstr.msg deleted file mode 100644 index 5d6c357d..00000000 --- a/err_unicode/err_twolongstr.msg +++ /dev/null @@ -1,1256 +0,0 @@ -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Wed Nov 17 19:08:49 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAHJ8F8P027204 - for ; Wed, 17 Nov 2004 19:08:48 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 17 Nov 2004 19:08:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUUU6-0001mQ-FU; - Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUUU6-0001mQ-FU - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUUU6-0000DF-68 - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9D10A120BFA; - Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 8C898120BEF - for ; Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Received-SPF: none (icicle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by icicle.pobox.com (Postfix) with ESMTP id 362C6120BEC - for ; Wed, 17 Nov 2004 13:24:46 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 9C0CC244379 - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 17196-06 for ; - Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 3131324406F - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 10:22:44 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_006A_01C4CC8F.60A4F6F0" -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117173321.GA6272@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTMy6HoelzJHh9WSPaTpCdfuF1C4gABpsZg -Message-Id: <20041117182444.3131324406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 16865 -Lines: 527 - -This is a multi-part message in MIME format. - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -I did - it is attached to the posting. However, I will attach it again -here. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 9:33 AM -> To: Susan Cassidy -> Cc: dbi-users@perl.org -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> If you can post a small self-contained example that demonstrates -> the problem then I'll take a look. -> -> Tim. -> -> On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > I never got any response to my question about this problem. I -> thought I'd try again. -> > -> > -> > -> > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> 5.8.5. -> > -> > -> > -> > Thanks, -> > -> > Susan -> > -> > -> > -> > --------------------------------------------------------------------- -> ----------------------------------- -> > -> > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > Sent: Friday, November 05, 2004 10:23 AM -> > To: 'dbi-users@perl.org' -> > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for -> > insert into a LONG column' when data not LONG -> > -> > -> > -> > I had an application that was processing a bunch of xml and inserting -> into a table with a bunch of -> > VARCHAR2(4000) columns. -> > -> > -> > -> > A couple of the entries I was processing caused the 'ORA-01461: can -> bind a LONG value only for insert -> > into a LONG column' error. -> > -> > -> > -> > I put checks in for the length of the data, and nothing approached -> 4000 bytes in length. -> > -> > -> > -> > I tracked down some of the entries causing problems, and on certain -> specific data, if 2 columns -> > containing specific data are inserted together, I get this error. If -> only one of the 2 is inserted, I -> > do not get the error, regardless of which one of the two I insert. -> > -> > -> > -> > The lengths of the pieces of data are 1399 and 1397 characters. -> > -> > -> > -> > The data is somewhat odd-looking (we suspect some odd data is in this -> file), but there is no reason for -> > the error message to appear. -> > -> > -> > -> > Trace shows nothing helpful - it thinks the data is the right length. -> > -> > -> > -> > We've successfully inserted thousands of other, similar entries with -> no trouble. -> > -> > -> > -> > The basics are: -> > -> > #create table test_table (item1 varchar2(4000), item2 -> varchar2(4000)); -> > -> > -> > -> > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, ?)"; -> > -> > -> > -> > $sth=$dbh->prepare($statement) || -> > -> > errexit("bad prepare for stmt $statement, error: $DBI::errstr"); -> > -> > my $rc=$sth->execute(@vals) || -> > -> > errexit("can't execute statement: error: $DBI::errstr\n"); -> > -> > -> > -> > Trace shows: -> > -> > -> > -> > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > -> > -> prepare for DBD::Oracle::db (DBI::db=HASH(0x82d4178)~0x82d6580 -> 'INSERT INTO test_table -> > (item1,item2) VALUES (?, ?) -> > -> > ') thr#8148ff0 -> > -> > dbd_preparse scanned 2 distinct placeholders -> > -> > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl line -> 40 -> > -> > -> execute for DBD::Oracle::st (DBI::st=HASH(0x82d6640)~0x8149dcc -> 'version 11.2no service -> > password-encryptionservice -> > -> > udp-small-serversservice tcp-small-servers!hostname router1!!no ip -> domain-lookupip inspect name mysite -> > ftpip inspect name -> > -> > mysite smtpip inspect name mysite tcp!interface Ethernet0ip address -> 10.10.10.2 255.255.255.0ip -> > access-group 101 inip ins -> > -> > pect mysite inip inspect mysite outno keepalive!interface Serial0no -> ip addressencapsulation -> > frame-relay...' 'version 11.2 -> > -> > no service password-encryptionservice udp-small-serversservice tcp- -> small-servers!hostname router1!!no ip -> > domain-lookupip -> > -> > inspect name mysite ftpip inspect name mysite smtpip inspect name -> mysite tcp!interface Ethernet0ip -> > address 10.10.10.2 255 -> > -> > .255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite -> outno keepalive!interface Serial0no -> > ip addressencaps -> > -> > ulation frame-relayn...') thr#8148ff0 -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (type 0) -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (size -> 1399/1400/0, ptype 4, otype 1) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (type 0) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (size -> 1397/1398/0, ptype 4, otype 1) -> > -> > dbd_st_execute INSERT (out0, lob0)... -> > -> > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > <- execute= undef at test_insert_large.pl line 42 -> > -> > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> 'ParamValues') thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line 42 -> > -> > -> $DBI::errstr (&) FETCH from lasth=HASH -> > -> > >> DBD::Oracle::st::errstr -> > -> > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' -> > -> > -- DBI::END -> > -> > -> disconnect_all for DBD::Oracle::dr -> (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > -> > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > -> > Connect done -> > -> > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > -> > Size of vals is 2 -> > -> > val 1 size 1399, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!i -> > -> > nterface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11 -> > -> > .2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 IETF!router eigrp 69network -> > 10.0.0.0no auto-summar -> > -> > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0. -> > -> > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permit icmp 10.10.10.0 -> > 0.0.0.255 anyaccess- -> > -> > list 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-rep -> > -> > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 ad -> > -> > ministratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp a -> > -> > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 0.0.0.255 -> > time-exceededaccess-list 102 permit tcp -> > -> > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > val 2 size 1397, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11. -> > -> > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci 200 -> IETF!router eigrp 69network -> > 10.0.0.0no auto-summary -> > -> > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 0.0.0.0 -> 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0.0 -> > -> > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permiticmp 10.10.10.0 -> > 0.0.0.255 anyaccess-li -> > -> > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess-list -> 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-reply -> > -> > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 admi -> > -> > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp any -> > -> > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 time-exceededaccess-list -> > 102 permit tcp an -> > -> > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > can't execute statement: error: ORA-01461: can bind a LONG value only -> for insert into a LONG column (DBD -> > ERROR: OCIStmtEx -> > -> > ecute) -> > -> > -> > -> > ! -> DESTROY for DBD::Oracle::db (DBI::db=HASH(0x82d6580)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#0) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > -> > -> > I will attach the test program. Somehow it seems to think the -> datatype is LONG instead of VARCHAR. -> > -> > -> > -> > -> > -> > Anyone with ideas? -> > -> > -> > -> > -> > -> > Thanks, -> > -> > Susan -> - - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: application/octet-stream; - name="test_insert_large.pl" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="test_insert_large.pl" - -#!/usr/local/bin/perl -w=0A= -=0A= -use DBI;=0A= -=0A= -our $dbh;=0A= -our $sth;=0A= -=0A= -$dbuser=3D"proj1";=0A= -$dbpasswd=3D"proj1";=0A= -=0A= -$dbserver=3D'oracledev';=0A= -$db_sid=3D'AL32UTF8';=0A= -=0A= -##=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D connect to database = -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=0A= -=0A= -$dbh=3D DBI->connect("dbi:Oracle:host=3D$dbserver;sid=3D$db_sid", = -$dbuser, $dbpasswd,=0A= - {PrintError =3D> 0, AutoCommit =3D> 1}) or=0A= - errexit( "Unable to connect to $dbserver: $DBI::errstr");=0A= -print "Connect done\n";=0A= -=0A= -#create table test_table (item1 varchar2(4000), item2 varchar2(4000));=0A= -=0A= -=0A= -my $statement=3D"INSERT INTO test_table (item1,item2) VALUES (?, ?)";=0A= -print "stmt: $statement\n";=0A= -=0A= -@vals=3D(=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysite inip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permit icmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permiticmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= -);=0A= -=0A= -print "Size of vals is ",scalar @vals,"\n";=0A= -my $z=3D0;=0A= -foreach my $x (@vals) {=0A= - my $len=3Dlength($x);=0A= - print "val ",++$z, " size $len, is: '$x'\n";=0A= -}=0A= -=0A= -DBI->trace(2);=0A= - $sth=3D$dbh->prepare($statement) ||=0A= - errexit("bad prepare for stmt $statement, error: $DBI::errstr");=0A= - my $rc=3D$sth->execute(@vals) ||=0A= - errexit("can't execute statement: error: $DBI::errstr\n");=0A= -=0A= -print "Done\n";=0A= -exit;=0A= -=0A= -=0A= -sub errexit {=0A= - my (@msg)=3D@_;=0A= - print @msg,"\n";=0A= - exit 1;=0A= -}=0A= -=0A= -=0A= -=0A= - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0-- - - -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 00:15:21 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI0FC8G049539 - for ; Thu, 18 Nov 2004 00:15:21 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 00:15:21 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUVdd-0002Nv-CF; - Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUVdd-0002Nv-CF - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CUVdc-0005lu-Rs - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 4A256ADD6F; - Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3D82CADD64 - for ; Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Received-SPF: none (boggle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by boggle.pobox.com (Postfix) with ESMTP id B23D4ADCF6 - for ; Wed, 17 Nov 2004 14:38:15 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 0C9DF24435B - for ; Wed, 17 Nov 2004 11:38:14 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 18475-01 for ; - Wed, 17 Nov 2004 11:38:13 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id ACF0424406F - for ; Wed, 17 Nov 2004 11:38:13 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 11:36:14 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117192902.GA31595@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTM27+9yfJDVs3WQIWAKc6DR3EgdQAAKfgw -Message-Id: <20041117193813.ACF0424406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -X-Status: A -Content-Length: 14671 -Lines: 489 - -NLS_LANG=.UTF8 -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORACLE_HOME=/home/oracle/product/9.2.0 -ORACLE_SID=AL32UTF8 -ORACLE_BASE=/home/oracle - -NLS_NCHAR is not set, because we are not using any NVARCHAR data item, and -haven't needed it. - -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 11:29 AM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > I did - it is attached to the posting. However, I will attach it again -> > here. -> > -> > Thanks, -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 9:33 AM -> > > To: Susan Cassidy -> > > Cc: dbi-users@perl.org -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > If you can post a small self-contained example that demonstrates -> > > the problem then I'll take a look. -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > > > I never got any response to my question about this problem. I -> > > thought I'd try again. -> > > > -> > > > -> > > > -> > > > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> > > 5.8.5. -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > > -> > > > -> > > > -> > > > ----------------------------------------------------------------- -> ---- -> > > ----------------------------------- -> > > > -> > > > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > > > Sent: Friday, November 05, 2004 10:23 AM -> > > > To: 'dbi-users@perl.org' -> > > > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> > > 01461: can bind a LONG value only for -> > > > insert into a LONG column' when data not LONG -> > > > -> > > > -> > > > -> > > > I had an application that was processing a bunch of xml and -> inserting -> > > into a table with a bunch of -> > > > VARCHAR2(4000) columns. -> > > > -> > > > -> > > > -> > > > A couple of the entries I was processing caused the 'ORA-01461: -> can -> > > bind a LONG value only for insert -> > > > into a LONG column' error. -> > > > -> > > > -> > > > -> > > > I put checks in for the length of the data, and nothing -> approached -> > > 4000 bytes in length. -> > > > -> > > > -> > > > -> > > > I tracked down some of the entries causing problems, and on -> certain -> > > specific data, if 2 columns -> > > > containing specific data are inserted together, I get this error. -> If -> > > only one of the 2 is inserted, I -> > > > do not get the error, regardless of which one of the two I -> insert. -> > > > -> > > > -> > > > -> > > > The lengths of the pieces of data are 1399 and 1397 characters. -> > > > -> > > > -> > > > -> > > > The data is somewhat odd-looking (we suspect some odd data is in -> this -> > > file), but there is no reason for -> > > > the error message to appear. -> > > > -> > > > -> > > > -> > > > Trace shows nothing helpful - it thinks the data is the right -> length. -> > > > -> > > > -> > > > -> > > > We've successfully inserted thousands of other, similar entries -> with -> > > no trouble. -> > > > -> > > > -> > > > -> > > > The basics are: -> > > > -> > > > #create table test_table (item1 varchar2(4000), item2 -> > > varchar2(4000)); -> > > > -> > > > -> > > > -> > > > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, -> ?)"; -> > > > -> > > > -> > > > -> > > > $sth=$dbh->prepare($statement) || -> > > > -> > > > errexit("bad prepare for stmt $statement, error: -> $DBI::errstr"); -> > > > -> > > > my $rc=$sth->execute(@vals) || -> > > > -> > > > errexit("can't execute statement: error: $DBI::errstr\n"); -> > > > -> > > > -> > > > -> > > > Trace shows: -> > > > -> > > > -> > > > -> > > > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > > > -> > > > -> prepare for DBD::Oracle::db -> (DBI::db=HASH(0x82d4178)~0x82d6580 -> > > 'INSERT INTO test_table -> > > > (item1,item2) VALUES (?, ?) -> > > > -> > > > ') thr#8148ff0 -> > > > -> > > > dbd_preparse scanned 2 distinct placeholders -> > > > -> > > > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl -> line -> > > 40 -> > > > -> > > > -> execute for DBD::Oracle::st -> (DBI::st=HASH(0x82d6640)~0x8149dcc -> > > 'version 11.2no service -> > > > password-encryptionservice -> > > > -> > > > udp-small-serversservice tcp-small-servers!hostname router1!!no -> ip -> > > domain-lookupip inspect name mysite -> > > > ftpip inspect name -> > > > -> > > > mysite smtpip inspect name mysite tcp!interface Ethernet0ip -> address -> > > 10.10.10.2 255.255.255.0ip -> > > > access-group 101 inip ins -> > > > -> > > > pect mysite inip inspect mysite outno keepalive!interface -> Serial0no -> > > ip addressencapsulation -> > > > frame-relay...' 'version 11.2 -> > > > -> > > > no service password-encryptionservice udp-small-serversservice -> tcp- -> > > small-servers!hostname router1!!no ip -> > > > domain-lookupip -> > > > -> > > > inspect name mysite ftpip inspect name mysite smtpip inspect name -> > > mysite tcp!interface Ethernet0ip -> > > > address 10.10.10.2 255 -> > > > -> > > > .255.255.0ip access-group 101 inip inspect mysiteinip inspect -> mysite -> > > outno keepalive!interface Serial0no -> > > > ip addressencaps -> > > > -> > > > ulation frame-relayn...') thr#8148ff0 -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (type -> 0) -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (size -> > > 1399/1400/0, ptype 4, otype 1) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (type -> 0) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (size -> > > 1397/1398/0, ptype 4, otype 1) -> > > > -> > > > dbd_st_execute INSERT (out0, lob0)... -> > > > -> > > > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > <- execute= undef at test_insert_large.pl line 42 -> > > > -> > > > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> > > 'ParamValues') thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line -> 42 -> > > > -> > > > -> $DBI::errstr (&) FETCH from lasth=HASH -> > > > -> > > > >> DBD::Oracle::st::errstr -> > > > -> > > > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' -> > > > -> > > > -- DBI::END -> > > > -> > > > -> disconnect_all for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > > > -> > > > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > > > -> > > > Connect done -> > > > -> > > > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > > > -> > > > Size of vals is 2 -> > > > -> > > > val 1 size 1399, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!i -> > > > -> > > > nterface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11 -> > > > -> > > > .2 255.255.255.252ip access-group 102 inframe-relay interface- -> dlci -> > > 200 IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summar -> > > > -> > > > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> > > 0.0.0.0 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0. -> > > > -> > > > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permit icmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess- -> > > > -> > > > list 101 deny ip any anyaccess-list 102 permit eigrp any -> anyaccess- -> > > list 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-rep -> > > > -> > > > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 ad -> > > > -> > > > ministratively-prohibitedaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp a -> > > > -> > > > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> > > 10.10.10.0 0.0.0.255 -> > > > time-exceededaccess-list 102 permit tcp -> > > > -> > > > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line -> con -> > > 0line vty 0 4login!end' -> > > > -> > > > val 2 size 1397, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11. -> > > > -> > > > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 -> > > IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summary -> > > > -> > > > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 -> > > 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0.0 -> > > > -> > > > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permiticmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess-li -> > > > -> > > > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list -> > > 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-reply -> > > > -> > > > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 admi -> > > > -> > > > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp any -> > > > -> > > > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 time-exceededaccess-list -> > > > 102 permit tcp an -> > > > -> > > > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> > > 0line vty 0 4login!end' -> > > > -> > > > can't execute statement: error: ORA-01461: can bind a LONG value -> only -> > > for insert into a LONG column (DBD -> > > > ERROR: OCIStmtEx -> > > > -> > > > ecute) -> > > > -> > > > -> > > > -> > > > ! -> DESTROY for DBD::Oracle::db -> (DBI::db=HASH(0x82d6580)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#0) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY for DBD::Oracle::st -> (DBI::st=HASH(0x8149dcc)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > -> > > > -> > > > I will attach the test program. Somehow it seems to think the -> > > datatype is LONG instead of VARCHAR. -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Anyone with ideas? -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > -> > -> - - - -From SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 07:11:03 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI7Ar8G057950 - for ; Thu, 18 Nov 2004 07:11:03 GMT - (envelope-from SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 07:11:03 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUaCR-0002mS-7P; - Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUaCR-0002mS-7P - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUaCQ-0004JQ-R5 - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 17ACAA3F35; - Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from integer (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 04F8DA3EAC - for ; Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Received-SPF: none (integer.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by integer.pobox.com (Postfix) with ESMTP id A9FC6A3F4D - for ; Wed, 17 Nov 2004 19:30:43 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id DEA102441A9 - for ; Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 22204-10 for ; - Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 7AD52244370 - for ; Wed, 17 Nov 2004 16:30:40 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 16:28:41 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041118001712.GB49519@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTNA/o7HZXghXaJRbyz8M5kVQMQmwAAUBjg -Message-Id: <20041118003040.7AD52244370@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 1789 -Lines: 63 - -Hi, - -I set NLS_LANG to .US7ASCII, ran it again, and I get the same error. - -Of course, I could not use that in production. - -The really strange part, to me, was that if I just insert one of the 2 -problematic columns, it worked, but both together failed. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 4:17 PM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> And does the problem go away if NLS_LANG is set to a non-unicode charset? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 11:36:14AM -0800, Susan Cassidy wrote: -> > NLS_LANG=.UTF8 -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORACLE_HOME=/home/oracle/product/9.2.0 -> > ORACLE_SID=AL32UTF8 -> > ORACLE_BASE=/home/oracle -> > -> > NLS_NCHAR is not set, because we are not using any NVARCHAR data item, -> and -> > haven't needed it. -> > -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 11:29 AM -> > > To: Susan Cassidy -> > > Cc: 'Tim Bunce' -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > > > I did - it is attached to the posting. However, I will attach it -> again -> > > > here. -> > > > -> > > > Thanks, -> > > > Susan -> > > > - - diff --git a/err_unsorted/err_etherreal.msg b/err_unsorted/err_etherreal.msg deleted file mode 100644 index 1ad5c78e..00000000 --- a/err_unsorted/err_etherreal.msg +++ /dev/null @@ -1,90 +0,0 @@ -From dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org Tue Apr 30 14:47:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UDliR22576 - for ; Tue, 30 Apr 2002 14:47:44 +0100 (BST) - (envelope-from dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.23] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 14:47:44 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020172466:10:24548:59; Tue, 30 Apr 2002 13:14:26 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1023391; 30 Apr 2002 13:13 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id A94562C075 - for ; Tue, 30 Apr 2002 09:12:33 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id F24B22BFBE - for ; Tue, 30 Apr 2002 09:12:32 -0400 (EDT) -Received: (qmail 36589 invoked by uid 1005); 30 Apr 2002 13:12:28 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 36168 invoked by uid 76); 30 Apr 2002 13:10:41 -0000 -Content-Type: text/plain; - charset="iso-8859-1" -From: Calin Medianu -To: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Date: Tue, 30 Apr 2002 16:04:47 +0300 -X-Mailer: KMail [version 1.3.2] -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> <20020429233138.E16831@dansat.data-plan.com> -In-Reply-To: <20020429233138.E16831@dansat.data-plan.com> -Cc: dbi-users@perl.org -MIME-Version: 1.0 -Message-Id: <20020430131233.F24B22BFBE@dolly1.pobox.com> -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id g3UDliR22576 -Status: RO -X-Status: A -Content-Length: 1213 -Lines: 38 - -[Add note to DBD::Oracle docs about using ethereal to sniff Oracle packets] -[Not sure if this bug got fixed yet. Maybe not.] - -Me again with the slow cursors. - -I modified both queries to only return 10 rows. -I ran a sniffer (ethereal) on the NIC. It is pretty cool, it also decodes TNS. - -when I am using the SQL, it works like this, there are about 7 packets -received by my workstation to set up the session, then all 10 rows are in the -same packet, then there is another packet probably saying goodbye. - -When I am using the REF cursor, each row comes in it's own TNS packet, that -is why it is so slow! - -Any idea how to fix it? - -thanks a lot, - -Calin - -> On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> > Hello, -> > -> > I did the following. Wrote a perl script that retreves -> > data via a straight select from the database. Then I -> > wrote a stored procedure returning a ref cursor open -> > on the same select statement and retrieved the data as -> > well. Using the REF CURSOR/ sotred procedure was about -> > 3 time slower, that is 40 seconds instead of around -> > 10. -> > -> > Is this normal? Is this a problem with oracle or with -> > DBD::Oracle? -> -> DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. -> -> Get a level 3 trace and look for the "dbd_describe'd" line for the -> ref cursor. -> -> Tim. - diff --git a/err_unsorted/err_memleak2.msg b/err_unsorted/err_memleak2.msg deleted file mode 100644 index 97501852..00000000 --- a/err_unsorted/err_memleak2.msg +++ /dev/null @@ -1,476 +0,0 @@ -From mike@boom.net Fri Nov 28 22:23:33 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hASMLLnY018698 - for ; Fri, 28 Nov 2003 22:23:33 GMT - (envelope-from mike@boom.net) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 28 Nov 2003 22:23:33 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1APmgW-0006iM-9g; - Fri, 28 Nov 2003 17:45:40 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1APmgW-0006iM-9g - for pobox@dbi.demon.co.uk; Fri, 28 Nov 2003 17:45:40 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id E82CD95E03 - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B1EE595DFB - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: from abort.boom.net (abort.boom.net[69.36.241.24]) - by icicle.pobox.com (Postfix) with ESMTP - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: by abort.boom.net (Postfix, from userid 530) - id E3C8B8517A; Fri, 28 Nov 2003 09:45:36 -0800 (PST) -Date: Fri, 28 Nov 2003 09:45:36 -0800 -From: Mike Hedlund -To: dbi-users@perl.org -Cc: Tim.Bunce@pobox.com -Subject: Memory leak in DBD::Oracle 1.14 ... ? -Message-ID: <20031128174536.GJ10609@boom.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.5.4i -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id hASMLLnY018698 -Content-Length: 24309 -Lines: 434 - -I've attached a little script which replicates the problem on my machine as well as the build session log for DBD::Oracle 1.14. - -I've tested it using DBI 1.38 and DBI 1.28 with both DBD::Oracle 1.12 and 1.14. - -Regardless of the DBI version, DBD::Oracle 1.14 leaks on my system and DBD::Oracle 1.12 does not. I've noticed the leak when calling connect_cached(), do() (or prepare()/execute()/commit/finish). - --mike - - --------------------- script --------------- -#!/usr/bin/perl -use strict; -use DBI; - -my($dbp) = "dbi:Oracle:host=weirdo.com;port=1521;sid=SID"; -my($dbu) = "username"; -my($dbpass) = "password"; - -while (1) { - my($sth); - my(@row); - my($dbh) = DBI->connect_cached($dbp,$dbu,$dbpass) || die "Couldn't connect to oracle db: $DBI::errstr\n"; - -## -## uncomment these and it just leaks faster. -## -# $sth = $dbh->prepare("SELECT * from FROM_STATS"); -# $sth->execute; -# while(@row = $sth->fetchrow_array) { - ##print "row: @row\n"; -# } -# $sth->finish; -} -exit; ------------------------- end script -------------------- - - ------------- log --------------------------------------- -Script started on Fri 28 Nov 2003 09:11:15 AM PST -[mike@commando DBD-Oracle-1.14]$ setenv ORACLE_HOME /home/orahome -[mike@commando DBD-Oracle-1.14]$ make realclean -rm -f blib/script/ora_explain -rm -rf Oracle.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm ./blib Makefile.aperl blib/arch/auto/DBD/Oracle/extralibs.all perlmain.c tmon.out mon.out so_locations pm_to_blib *.o *.a perl.exe perl perl Oracle.bs Oracle.bso Oracle.def libOracle.def Oracle.exp Oracle.x core core.*perl.*.? *perl.core -mv Makefile Makefile.old > /dev/null 2>&1 -rm -rf blib/lib/auto/DBD/Oracle blib/arch/auto/DBD/Oracle -rm -rf DBD-Oracle-1.14 -rm -f blib/arch/auto/DBD/Oracle/Oracle.so blib/arch/auto/DBD/Oracle/Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.a -rm -f blib/lib/DBD/Oracle.pm blib/arch/auto/DBD/Oracle/dbdimp.h blib/lib/oraperl.ph -rm -f blib/arch/auto/DBD/Oracle/ocitrace.h blib/lib/Oraperl.pm -rm -f blib/arch/auto/DBD/Oracle/Oracle.h blib/arch/auto/DBD/Oracle/mk.pm -rm -f blib/lib/DBD/Oracle/GetInfo.pm -rm -rf Makefile Makefile.old -[mike@commando DBD-Oracle-1.14]$ perl Makefile.PL -v -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI - - Configuring DBD::Oracle ... - ->>> Remember to actually *READ* the README file! - Especially if you have any problems. - -Using Oracle in /home/orahome - -WARNING: could not decode oracle version from -/home/orahome/orainst/inspdver, or /home/orahome/install/unix.rgs -or from ORACLE_HOME path /home/orahome. -Oracle version based logic in Makefile.PL may produce erroneous results. - -Found header files in rdbms/public rdbms/demo. -Found /home/orahome/rdbms/demo/demo_rdbms.mk -Found /home/orahome/otrace/demo/atmoci.mk -Found /home/orahome/precomp/demo/proc/demo_proc.mk -Using /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/lib/env_rdbms.mk -Read a total of 2202 lines from /home/orahome/rdbms/lib/env_rdbms.mk (including inclusions) -Read a total of 2493 lines from /home/orahome/rdbms/demo/demo_rdbms.mk (including inclusions) -Deleted SHELL definition: SHELL=/bin/sh -Deleted LIB_EXT definition: LIB_EXT=a -Deleted OBJ_EXT definition: OBJ_EXT=o -Deleted AR definition: AR=ar -Deleted AS definition: AS=as -Deleted CC definition: CC=cc -Deleted CHMOD definition: CHMOD=chmod -Deleted CPP definition: CPP=cpp -Deleted ECHO definition: ECHO=echo -Deleted LD definition: LD=ld -Deleted PERL definition: PERL=perl -Deleted CFLAGS definition: CFLAGS=$(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ -Deleted OPTIMIZE definition: OPTIMIZE=$(OPTIMIZE3) -Deleted AR definition: AR=/usr/bin/ar -Deleted AS definition: AS=/usr/bin/as -Deleted LD definition: LD=/usr/bin/ld -Deleted CPP definition: CPP=/lib/cpp -Deleted CHMOD definition: CHMOD=/bin/chmod -Deleted ASFLAGS definition: ASFLAGS= -Deleting ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS definition: ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Deleting ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS33 definition: ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Appending '/home/orahome/rdbms/lib/libskgxpd.a /home/orahome/rdbms/lib/libskgxpu.a /home/orahome/rdbms/lib/libskgxpt.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxp9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxp9.a' to LIBS -Appending '/home/orahome/rdbms/lib/libskgxns.a /home/orahome/rdbms/lib/libskgxnd.a /home/orahome/rdbms/lib/libskgxnr.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxn9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxn9.a' to LIBS -Evaluating `cat $(LIBHOME)sysliblist` - expanded `cat /home/orahome/lib/sysliblist` - returned '-ldl -lm -lpthread -lnsl ' - -Attempting to discover Oracle OCI build rules -gcc -c -o DBD_ORA_OBJ.o DBD_ORA_OBJ.c -by executing: (make -f /home/orahome/rdbms/demo/demo_rdbms.mk build ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh' CC=echo OPTIMIZE= CCFLAGS= EXE=DBD_ORA_EXE OBJS=DBD_ORA_OBJ.o) -returned: -[echo -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh `cat /home/orahome/lib/sysliblist` -ldl -lm - -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -reduced to: -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -Oracle oci build command: - + -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - - - -System: perl5.008 linux stripples.devel.redhat.com 2.4.21-1.1931.2.382.entsmp #1 smp wed aug 6 17:18:52 edt 2003 i686 i686 i386 gnulinux -Compiler: gcc -O2 -g -pipe -march=i386 -mcpu=i686 -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -Linker: /usr/bin/ld -Sysliblist: -ldl -lm -lpthread -lnsl -Oracle makefiles would have used these definitions but we override them: - CC: cc - - CFLAGS: $(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) - [$(GFLAG) -O3 $(CDEBUG) $(CCFLAGS) -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -DLINUX -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS $(LPFLAGS) $(USRFLAGS)] - - LDFLAGS: -o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ - [-o $@ -L/home/orahome/rdbms/lib/ -L$(LIBHOME) -L$(LIBHOME)stubs/] - - -Linking with OTHERLDFLAGS = -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - [from 'build' rule] - - -MakeMaker (v6.03) -Checking if your kit is complete... -Looks good - ABSTRACT_FROM => q[Oracle.pm] - AUTHOR => q[Tim Bunce (dbi-users@perl.org)] - DEFINE => q[ -DUTF8_SUPPORT] - DIR => [] - EXE_FILES => [q[ora_explain]] - INC => q[-I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI] - NAME => q[DBD::Oracle] - OBJECT => q[$(O_FILES)] - PREREQ_PM => { DBI=>q[0] } - VERSION_FROM => q[Oracle.pm] - clean => { FILES=>q[Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm] } - dist => { DIST_DEFAULT=>q[clean distcheck disttest ci tardist], COMPRESS=>q[gzip -v9], PREOP=>q[$(MAKE) -f Makefile.old distdir], SUFFIX=>q[gz] } - dynamic_lib => { OTHERLDFLAGS=>q[ -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] } -Using PERL=/usr/bin/perl -LD_RUN_PATH=/home/orahome/lib:/home/orahome/rdbms/lib -Using DBD::Oracle 1.14. -Using DBD::Oracle 1.14. -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -Writing Makefile for DBD::Oracle - -*** If you have problems... - read all the log printed above, and the README and README.help files. - (Of course, you have read README by now anyway, haven't you?) - -[mike@commando DBD-Oracle-1.14]$ make -cp Oracle.pm blib/lib/DBD/Oracle.pm -cp Oracle.h blib/arch/auto/DBD/Oracle/Oracle.h -cp dbdimp.h blib/arch/auto/DBD/Oracle/dbdimp.h -cp oraperl.ph blib/lib/oraperl.ph -cp ocitrace.h blib/arch/auto/DBD/Oracle/ocitrace.h -cp Oraperl.pm blib/lib/Oraperl.pm -cp mk.pm blib/arch/auto/DBD/Oracle/mk.pm -cp lib/DBD/Oracle/GetInfo.pm blib/lib/DBD/Oracle/GetInfo.pm -/usr/bin/perl -p -e "s/~DRIVER~/Oracle/g" /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI/Driver.xst > Oracle.xsi -/usr/bin/perl /usr/lib/perl5/5.8.0/ExtUtils/xsubpp -typemap /usr/lib/perl5/5.8.0/ExtUtils/typemap Oracle.xs > Oracle.xsc && mv Oracle.xsc Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT dbdimp.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci7.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci8.c -Running Mkbootstrap for DBD::Oracle () -chmod 644 Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/home/orahome/lib:/home/orahome/rdbms/lib" gcc -shared -L/usr/local/lib Oracle.o dbdimp.o oci7.o oci8.o -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" blib/script/ora_explain -Manifying blib/man3/DBD::Oracle.3pm -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oraperl.3pm -[mike@commando DBD-Oracle-1.14]$ make test -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/base....... t/base.......ok 1/5 t/base.......ok 2/5 t/base.......ok 3/5 t/base.......ok 4/5 t/base.......ok 5/5 t/base.......ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/reauth.....skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.82 cusr + 0.33 csys = 4.15 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ make test TEST_VERBOSE=1 -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1, 'blib/lib', 'blib/arch')" t/*.t -t/base.......1..5 -ok 1 -ok 2 -ok 3 -ok 4 -ok 5 -ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/reauth.....ORACLE_USERID_2 not defined. -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.85 cusr + 0.32 csys = 4.17 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ perl _V-V -Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: - Platform: - osname=linux, osvers=2.4.21-1.1931.2.382.entsmp, archname=i386-linux-thread-multi - uname='linux str' - config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Dotherlibdirs=/usr/lib/perl5/5.8.0 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr' - hint=recommended, useposix=true, d_sigaction=define - usethreads=define use5005threads=undef' - useithreads=define usemultiplicity= - useperlio= d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=un uselongdouble= - usemymalloc=, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', - optimize='', - cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm' - ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)', gccosandvers='' -gccversion='3.2.2 200302' - intsize=r, longsize=r, ptrsize=5, doublesize=8, byteorder=1234 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - ivtype='long' -k', ivsize=4' -ivtype='l, nvtype='double' -o_nonbl', nvsize=, Off_t='', lseeksize=8 - alignbytes=4, prototype=define - Linker and Libraries: - ld='gcc' -l', ldflags =' -L/u' - libpth=/usr/local/lib /lib /usr/lib - libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil - perllibs= - libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libper - gnulibc_version='2.3.2' - Dynamic Linking: - dlsrc=dl_dlopen.xs, dlext=so', d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE' - cccdlflags='-fPIC' -ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5', lddlflags='s Unicode/Normalize XS/A' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING MULTIPLICITY USE_ITHREADS USE_LARGE_FILES PERL_IMPLICIT_CONTEXT - Locally applied patches: - MAINT18379 - Built under linux - Compiled at Aug 13 2003 11:47:58 - @INC: - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/site_perl/5.8.0 - /usr/lib/perl5/site_perl - /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/vendor_perl/5.8.0 - /usr/lib/perl5/vendor_perl - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - . -[mike@commando DBD-Oracle-1.14]$ ^D -Script done on Fri 28 Nov 2003 09:16:43 AM PST ------------- end log ----------------------------------- - - diff --git a/err_unsorted/err_multiora.msg b/err_unsorted/err_multiora.msg deleted file mode 100644 index 9f7bcf6c..00000000 --- a/err_unsorted/err_multiora.msg +++ /dev/null @@ -1,470 +0,0 @@ -From dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org Mon Jan 5 10:12:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05ACYn1063537 - for ; Mon, 5 Jan 2004 10:12:58 GMT - (envelope-from dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 10:12:58 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdQXY-0007a7-IO; - Mon, 05 Jan 2004 09:18:18 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdQXY-0007a7-IO - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 08:56:48 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id C92F0282F - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id B344B2B84 - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: (qmail 58691 invoked by uid 1005); 5 Jan 2004 08:56:38 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 58674 invoked by uid 76); 5 Jan 2004 08:56:38 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 05 Jan 2004 00:56:38 -0800 -Received: (qmail 17937 invoked by uid 225); 5 Jan 2004 08:56:36 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 17930 invoked by uid 507); 5 Jan 2004 08:56:36 -0000 -Received: from stone.sifira.dk (HELO mail.int.sifira.dk) (217.157.24.2) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Mon, 05 Jan 2004 00:56:05 -0800 -Received: from ash.int.sifira.dk (ash.int.sifira.dk [192.168.1.7]) by mail.int.sifira.dk (Postfix) with ESMTP id F127674F58; Mon, 5 Jan 2004 09:55:58 +0100 (MET) -Sender: kn@sifira.dk -To: "Anniballi, Fran" -Cc: -Subject: Re: Help - multiple Oracle versions -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -From: Kristian Nielsen -Date: 05 Jan 2004 09:55:59 +0100 -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Message-ID: <7sllomsrj4.fsf@ash.int.sifira.dk> -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-2.5 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_GNUS_UA version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1223 -Lines: 40 - -[Add notes to docs covering what's in this thread] - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - -From dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org Mon Jan 5 14:47:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05Ejvo1064760 - for ; Mon, 5 Jan 2004 14:47:30 GMT - (envelope-from dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 14:47:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdVCS-0004w0-Is; - Mon, 05 Jan 2004 13:55:22 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdVCS-0004w0-Is - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 13:55:21 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 548DE2C87 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 417692C81 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 08:55:19 -0500 (EST) -Received: (qmail 91728 invoked by uid 1005); 5 Jan 2004 13:55:17 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 48614 invoked by uid 76); 5 Jan 2004 12:24:01 -0000 -Delivered-To: dbi-users@perl.org -X-MimeOLE: Produced By Microsoft Exchange V6.0.6487.1 -content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; charset="iso-8859-1" -Subject: RE: Help - multiple Oracle versions -Date: Mon, 5 Jan 2004 07:23:23 -0500 -Message-ID: <6B003D25ADBDE347B5542AFE6A55B42E04537A09@tayexc13.americas.cpqcorp.net> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Help - multiple Oracle versions -Thread-Index: AcPTac0nADA1C8LsTdSTxpcvyeSNCgAHQWGQ -From: "Anniballi, Fran" -To: -Cc: -X-OriginalArrivalTime: 05 Jan 2004 12:23:24.0525 (UTC) FILETIME=[B6F761D0:01C3D386] -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.3 required=7.0 tests=CARRIAGE_RETURNS,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i05Ejvo1064760 -Status: RO -Content-Length: 1465 -Lines: 52 - -Thanks. Looks like this is what I'll need. - ------Original Message----- -From: kn@sifira.dk [mailto:kn@sifira.dk] -Sent: Monday, January 05, 2004 3:56 AM -To: Anniballi, Fran -Cc: dbi-users@perl.org -Subject: Re: Help - multiple Oracle versions - - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - - -From dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org Tue Jan 6 17:00:29 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i06GxrnC075337 - for ; Tue, 6 Jan 2004 17:00:29 GMT - (envelope-from dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 06 Jan 2004 17:00:29 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Adu0c-0004RW-9d; - Tue, 06 Jan 2004 16:24:47 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Adu0c-0004RW-9d - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 16:24:47 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 21A79495C - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 08B12494B - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 6 Jan 2004 11:24:45 -0500 (EST) -Received: (qmail 25114 invoked by uid 1005); 6 Jan 2004 16:24:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 25095 invoked by uid 76); 6 Jan 2004 16:24:42 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Tue, 06 Jan 2004 08:24:42 -0800 -Received: (qmail 16535 invoked by uid 225); 6 Jan 2004 16:24:39 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16527 invoked by uid 507); 6 Jan 2004 16:24:39 -0000 -Received: from mail.cybcon.com (HELO mail.cybcon.com) (216.190.188.5) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 06 Jan 2004 08:24:08 -0800 -Received: from poirot (dsl2-6.cybcon.com [208.186.116.6]) by mail.cybcon.com (8.11.6/8.11.6) with ESMTP id i06GNhn08916; Tue, 6 Jan 2004 08:23:43 -0800 -Subject: RE: Help - multiple Oracle versions -From: Jared Still -To: "Anniballi, Fran" -Cc: DBI List -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 (1.0.8-11) -Date: 06 Jan 2004 08:25:59 -0800 -Message-Id: <1073406359.324.244.camel@poirot.jks.com> -Mime-Version: 1.0 -X-CyberConnectics-MailScanner2-Information: Spam/Virus Scanned at CyberConnectics -X-CyberConnectics-MailScanner2: Found to be clean -X-CyberConnectics-MailScanner2-SpamCheck: -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.2 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_05_08,SUPERLONG_LINE version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 4050 -Lines: 102 - -I read quickly through this thread, so my apologies if someone -already pointed this out. - -It doesn't matter which version of Oracle you compiled DBD with, -you can connect to all your 8i/9i databases on any platform with it. - -Assume you compiled with 9i libs, and you can connect to 9i db's with -no problem, but are unable to connect to 8i, getting the error you -mentioned previously. - -It appears that you are changing your Oracle environment via the -oraenv shell script to change your ORACLE_HOME to the 8i version -of Oracle. - -If so, stop doing that. Just leave your environment at 9i, and -connect to your 8i database. It will be fine. This is the way -my linux server is setup, and DBD is used to connect to Oracle -versions 7.3, 8.1.6, 8.1.7 and 9.2.0 every day. - -At our site DBD is compiled with 8i libs so that we can still -connect to the version 7 databases. If you compile with 9i libs, -you will be unable to connect to version 7 databases. - -HTH - -Jared - - -On Sun, 2004-01-04 at 05:12, Anniballi, Fran wrote: -> This is all done on one UNIX box. -> -> If I try option one, it doesn't work. I can't access an oracle8 instance with oracle9 sqlplus (or the other way around). That is the real problem. Since I can't do this I have to reassign the pointers before I access it. I can do this fine with sqlplus but with dbi/dbd I have to compile with one or the other. -> -> For option two, if I have two versions of DBD:Oracle, how do I tell Perl which one to use? My scripts just say "/usr/bin/perl" in the first line. -> -> -----Original Message----- -> From: kn@sifira.dk [mailto:kn@sifira.dk] -> Sent: Saturday, January 03, 2004 1:04 PM -> To: dbi-users@perl.org -> Cc: Anniballi, Fran -> Subject: Re: Help - multiple Oracle versions -> -> -> "Anniballi, Fran" writes: -> -> > As soon as I recompile the same DBI/DBD with it pointing to Oracle 9 -> > environment (libraries), it doesn't work. It is looking for Oracle9 -> > library files and I obviously don't have it pointing to oracle9 -> > libraries when I access an Oracle 8 instance. Oracle 9 is not -> > compatible with Oracle 8 so I have to redirect the environment -> > variables at run time. -> -> It sounds like you are confusing the Oracle client version and the -> Oracle server version. -> -> Eg. if you set ORACLE_HOME to /usr/local/oracle8 (or whatever) and use -> /usr/local/oracle8/bin/sqlplus you are using the Oracle 8 client, while -> if you set it to /usr/local/oracle9 and call -> /usr/local/oracle9/bin/sqlplus, you are using the Oracle 9 client. -> -> Which Oracle instance you access is selected by the connection string; -> for example "sqlplus scott/tiger@DB8" might access the Oracle 8 -> instance, and "scott/tiger@DB9" might access the Oracle 9 instance. -> -> What people are telling you is that you can choose client version -> independently of the server version. For example, it is possible to set -> ORACLE_HOME to /usr/local/oracle9 and call -> -> /usr/local/oracle9/bin/sqlplus scott/tiger@DB8 -> -> to access the Oracle 8 instance with the Oracle 9 client. This of course -> requires that the definition for DB8 is present in the file -> /usr/local/oracle-9.2/network/admin/tnsnames.ora. -> -> So you should either -> -> 1. Use only the Oracle 9 client, not change ORACLE_HOME, and access both -> instances with Oracle 9 sqlplus and DBD::Oracle compiled against -> Oracle 9 libraries. -> -> or -> -> 2. Compile DBD::Oracle twice (once against Oracle 8 libraries, once -> against Oracle 9 libraries, just as you have two versions of sqlplus) -> and use each one with the proper ORACLE_HOME setting. -> -> My guess is that you will find possibility 1. the easiest. -> -> > The tnsnames.ora are all set. I did what you said already. -> > -> > Example: DBI/DBD will work fine if I compile the DBI/DBD pointing to -> > Oracle 8 environment(libraries) and access an Oracle 8 instance. I -> > didn't have to change tnsnames.ora -> -> Yes you do: You need to have BOTH Oracle instances defined in EACH -> tnsnames.ora. -> -> Hope this helps, -> -> - Kristian. - - - -From andy@andyh.co.uk Wed Jan 7 07:31:57 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i077VPn8081048 - for ; Wed, 7 Jan 2004 07:31:57 GMT - (envelope-from andy@andyh.co.uk) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 07 Jan 2004 07:31:57 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Ae0Yb-0002lT-IA; - Tue, 06 Jan 2004 23:24:17 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Ae0Yb-0002lT-IA - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 23:24:17 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 00D7C3C15 - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id CB5813BEA - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from mta03-svc.ntlworld.com (mta03-svc.ntlworld.com [62.253.162.43]) - by integer.pobox.com (Postfix) with ESMTP - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from excession ([80.2.244.47]) by mta03-svc.ntlworld.com - (InterMail vM.4.01.03.37 201-229-121-137-20020806) with SMTP - id <20040106232403.NEKJ9852.mta03-svc.ntlworld.com@excession>; - Tue, 6 Jan 2004 23:24:03 +0000 -Message-ID: <00bd01c3d4ac$e5713190$6564a8c0@excession> -From: "Andy Hassall" -To: "Eric Lenio" , "Tim Bunce" -Cc: -References: <20040102143310.GC27273@lenio.net> <20040104204914.GB60357@dansat.data-plan.com> <20040105123653.GA31473@lenio.net> <20040105223121.GG66760@dansat.data-plan.com> <20040106222634.GG11531@lenio.net> <20040106223845.GE78360@dansat.data-plan.com> <20040106225722.GI11531@lenio.net> -Subject: Re: DBI primary_key tests fail: oracle 8 -Date: Tue, 6 Jan 2004 23:29:14 -0000 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2800.1158 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 43 - -Eric Lenio wrote: -> OK Tim. One other note -- after reading through oracle docs, I think -> you might want to substitute 'session_user' for 'current_schema' in -> 'select sys_context(...)'. The definition of session_user is -> "returns the database -> user name by which the current user is authenticated" while -> current_schema is "returns the name of the default schema being used -> in the current session". -> Maybe it doesn't matter, I'm not an oracle guru by any stretch of the -> imagination. - -There's several usernames in the USERENV context: - -CURRENT_SCHEMA - -The schema/user used for unqualified object name resolution; by default the -user you logged in as, but alterable with 'alter session set -current_schema=x'. Useful for avoiding having to maintain loads of synonyms. - -CURRENT_USER - -The user you're currently authenticated as. Doesn't change in SQL and -anonymous PL/SQL, but changes within definer-rights PL/SQL stored procedures -to the owner of the stored procedure, since stored procs by default run with -the privileges of the owner, not the invoker. - -SESSION_USER - -Who you originally logged in as, and never changes (but see below). Looks -like the appropriate one to use. - -PROXY_USER - -I don't think DBD::Oracle supports proxy authentication so don't need to -worry about that one yet. Possibly a bit of a grey area if it does support -it in the future, since this would hold the username in the DSN, but it'd -reauthenticate and change the SESSION_USER on connect (which would probably -have to be specified as an attribute to the $dbh). - --- -Andy Hassall (andy@andyh.co.uk) icq(5747695) (http://www.andyh.co.uk) -Space: disk usage analysis tool (http://www.andyhsoftware.co.uk/space) - - diff --git a/err_unsorted/err_ora9ir2oci.msg b/err_unsorted/err_ora9ir2oci.msg deleted file mode 100644 index 7ed476e4..00000000 --- a/err_unsorted/err_ora9ir2oci.msg +++ /dev/null @@ -1,27 +0,0 @@ -http://otn.oracle.com/tech/oci/htdocs/oci9ir2_new_features - -OCI Session Pooling -Session Pooling is a new feature in Oracle 9i Database Release 2. -An application can now maintain a pool of sessions and use a session -from the pool when it needs it. This saves the time consuming process -of initiating a connection and authentication every time the process -needs a new session. Session Pooling is useful, especially when a -large number of stateless sessions are required for a very short -time. In a web scenario, where many users are connected for a short -time, and the primary operation is accessing data, it is a costly -operation to start up a new session every time. In such a scenario, -session pooling could boost up the performance. - -OCI Statement caching -Client-side statement caching is also introduced in Oracle9i Database -Release 2. This feature can be enabled at the time of session -creation. It allows users to have a cache of statements per session. -On the server, this means having cursors that ready to be used, -without the need to parse the statements again, and thus improving -performance significantly. With this feature enabled, applications -do not have to keep a track of the statements themselves, as the -OCI layer will do it for them. In addition, a tagging feature is -provided, which users can use as a key to save and search for -statements. - - diff --git a/err_unsorted/err_ref_type.msg b/err_unsorted/err_ref_type.msg deleted file mode 100644 index 26d86e14..00000000 --- a/err_unsorted/err_ref_type.msg +++ /dev/null @@ -1,115 +0,0 @@ -From dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org Wed Jul 23 18:40:02 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6NHUUA0010501 - for ; Wed, 23 Jul 2003 18:40:02 +0100 (BST) - (envelope-from dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 23 Jul 2003 18:40:02 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058948095:10:09585:8; Wed, 23 Jul 2003 08:14:55 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116163; 23 Jul 2003 8:14 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 88C1B21C024 - for ; Wed, 23 Jul 2003 04:13:51 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id AA89B21C082 - for ; Wed, 23 Jul 2003 04:13:50 -0400 (EDT) -Received: (qmail 26606 invoked by uid 1005); 23 Jul 2003 08:13:44 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 26590 invoked by uid 76); 23 Jul 2003 08:13:43 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Wed, 23 Jul 2003 01:13:43 -0700 -Received: (qmail 16360 invoked by uid 225); 23 Jul 2003 08:13:41 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16355 invoked by uid 507); 23 Jul 2003 08:13:41 -0000 -Received-SPF: unknown -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Wed, 23 Jul 2003 01:13:41 -0700 -Received: (qmail 5378 invoked from network); 23 Jul 2003 08:54:08 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 23 Jul 2003 08:54:08 -0000 -Received: (qmail 8984 invoked from network); 23 Jul 2003 08:13:49 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 23 Jul 2003 08:13:49 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Wed, 23 Jul 2003 10:13:49 +0200 (CEST) -Subject: Re: binding to parameters of type REF -From: Hendrik =?ISO-8859-1?Q?Fu=DF?= -To: dbi-users@perl.org -In-Reply-To: <1058865345.1241.56.camel@mars> -References: <1058865345.1241.56.camel@mars> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 -Date: 23 Jul 2003 10:11:49 +0200 -Message-Id: <1058947909.6353.5.camel@mars> -Mime-Version: 1.0 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.3 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,LARGE_HEX,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1354 -Lines: 56 - -I've also found out, that DBD::Oracle does not support type SQL_REF: -When not using DBD::Proxy I get: - - SQL type 20 for ':p1' is not fully supported, - bound as SQL_VARCHAR instead - -I even get segmentation faults when trying to fetch REF columns. :-( - -Any ideas? - -> Hi, -> -> I'm trying to bind a perl variable to an Oracle table reference with -> Oracle 9.2.0.3, DBD::Proxy and Perl::DBI 1.37 without success. I -> could'nt find help on this in the docs or list archives. I hope this is -> the right place to post. -> -> In SQL*Plus: -> -> SQL> desc getReference -> FUNCTION getReference RETURNS REF OF TABLETYPE -> -> SQL> select getReference() from dual; -> -> GETREFERENCE() -> ---------------------------------------------------------------------- -> 0000280209C229D2216EF6A5F4E030010A8D086AD3C204FC6EE0E46501E030010A8D08 -> 2CE703C0000E0000 -> -> -> My code: -> -> my $ref = undef; -> my $sth = $dbh->prepare('BEGIN ? := getReference(); END;'); -> $sth->bind_param_inout(1, \$ref, 128, SQL_REF ); -> $sth->execute(); -> -> yields: -> -> PLS-00382: expression is of wrong type -> -> -> Even fetching a reference does not work: -> -> my $sth = $dbh->prepare('SELECT getReference() FROM DUAL'); -> $sth->execute(); -> ($ref) = $sth->fetchrow_array(); -> -> yields undef in $ref. -> -> I'd very much appreciate your help. -> cheers, -> Hendrik - - - - diff --git a/err_unsorted/err_refcsr_rowcache.msg b/err_unsorted/err_refcsr_rowcache.msg deleted file mode 100644 index 5101d2ae..00000000 --- a/err_unsorted/err_refcsr_rowcache.msg +++ /dev/null @@ -1,85 +0,0 @@ -From dbi-users-bounce@isc.org Tue May 16 22:53:12 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id WAA29547; Tue, 16 May 2000 22:53:11 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <04730-2@oink>; Sat, 16 May 1970 22:51:48 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 958512876:10:15786:0; Tue, 16 May 2000 21:34:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1122388; 16 May 2000 21:33 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 661E53EC8; - Tue, 16 May 2000 14:33:38 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Tue, 16 May 2000 14:28:31 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id 7192F3E20 - for ; - Tue, 16 May 2000 14:28:27 -0700 (PDT) -Received: from anchor-post-34.mail.demon.net (anchor-post-34.mail.demon.net [194.217.242.92]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id OAA27204 - for ; - Tue, 16 May 2000 14:28:26 -0700 (PDT) env-from (Tim.Bunce@ig.co.uk) -Received: from ignite.demon.co.uk ([158.152.8.99] helo=oink) - by anchor-post-34.mail.demon.net with smtp (Exim 2.12 #1) - id 12rot7-000Mp4-0Y; Tue, 16 May 2000 22:28:25 +0100 -Received: from toad by oink with SMTP (PP) id <04650-0@oink>; - Sat, 16 May 1970 22:23:55 +0100 -Received: by toad.ig.co.uk (SMI-8.6/SMI-SVR4) id WAA29289; - Tue, 16 May 2000 22:23:50 +0100 -Date: Tue, 16 May 2000 22:23:50 +0100 -From: Tim Bunce -To: peter_dev@talk21.com -Cc: dbi-users@isc.org -Subject: Re: Oracle Stored Procs take longer than embedded SQL -Message-ID: <20000516222350.F28435@ig.co.uk> -References: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs>; from peter_dev@talk21.com on Tue, May 16, 2000 at 06:48:22PM +0100 -Organization: Paul Ingram Group, Software Systems, +44 1 483 862800 -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 1372 -Lines: 30 - -On Tue, May 16, 2000 at 06:48:22PM +0100, peter_dev@talk21.com wrote: -> I have a problem with the fetching of data from an Oracle Ref Cursor taking longer than the same query in Embeded SQL. -> -> $ get_sp.pl -> Fetched in 0.00774896144866943 seconds -> Completed in 0.106827020645142 seconds -> -> $ get_sql.pl -> Fetched in 0.00138604640960693 seconds -> Completed in 0.380790948867798 seconds -> -> In this example (Using the SCOTT/TIGER tables), while the Stored Procedure completed first, the actual fetch of the data took considerably longer. In a real situation (e.g. bigger tables ), this is easily the longest part of the task and causes the overall execution time to increase hugely. -> -> Any Help would be appreciated -> thanks - -Possibly related to the lack of a row cache on that statement handle. -You, or some kind volunteer, could probably hack that in without too -much work. - -Tim. - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_unsorted/err_refcsr_slow.msg b/err_unsorted/err_refcsr_slow.msg deleted file mode 100644 index 790d267d..00000000 --- a/err_unsorted/err_refcsr_slow.msg +++ /dev/null @@ -1,347 +0,0 @@ -From dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org Mon Apr 29 23:12:51 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TMCpR17212 - for ; Mon, 29 Apr 2002 23:12:51 +0100 (BST) - (envelope-from dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 29 Apr 2002 23:12:51 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020117986:10:17770:92; Mon, 29 Apr 2002 22:06:26 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1017591; 29 Apr 2002 22:06 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id 975037274A - for ; Mon, 29 Apr 2002 18:01:37 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by wormwood.pobox.com (Postfix) with SMTP id ED2897273F - for ; Mon, 29 Apr 2002 18:01:34 -0400 (EDT) -Received: (qmail 70462 invoked by uid 1005); 29 Apr 2002 21:59:33 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 20335 invoked by uid 76); 29 Apr 2002 20:18:55 -0000 -Message-ID: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Date: Mon, 29 Apr 2002 13:18:53 -0700 (PDT) -From: Calin Medianu -Reply-To: cmedianu@sfu.ca -Subject: DBD::Oracle Slow cursors -To: dbi-users@perl.org -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 568 -Lines: 21 - -Hello, - -I did the following. Wrote a perl script that retreves -data via a straight select from the database. Then I -wrote a stored procedure returning a ref cursor open -on the same select statement and retrieved the data as -well. Using the REF CURSOR/ sotred procedure was about -3 time slower, that is 40 seconds instead of around -10. - -Is this normal? Is this a problem with oracle or with -DBD::Oracle? - -Thanks, - -Calin Medianu - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org Tue Apr 30 00:06:36 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TN6aR17980 - for ; Tue, 30 Apr 2002 00:06:36 +0100 (BST) - (envelope-from dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 00:06:36 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020119533:20:05733:4; Mon, 29 Apr 2002 22:32:13 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2005393; 29 Apr 2002 22:32 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 4E6B73E6BF - for ; Mon, 29 Apr 2002 18:32:00 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-1.pobox.com (Postfix) with SMTP id BF79C3E6A0 - for ; Mon, 29 Apr 2002 18:31:59 -0400 (EDT) -Received: (qmail 87860 invoked by uid 1005); 29 Apr 2002 22:31:59 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 87844 invoked by uid 76); 29 Apr 2002 22:31:58 -0000 -Received: from mail01.svc.cra.dublin.eircom.net (HELO mail01.svc.cra.dublin.eircom.net) (159.134.118.17) - by onion.perl.org (qpsmtpd/0.07) with SMTP; Mon Apr 29 22:31:58 2002 -0000 -Received: (qmail 21911 messnum 119827 invoked from network[159.134.167.97/p865.as1.limerick1.eircom.net]); 29 Apr 2002 22:31:29 -0000 -Received: from p865.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.97) - by mail01.svc.cra.dublin.eircom.net (qp 21911) with SMTP; 29 Apr 2002 22:31:29 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g3TMVcR17579; - Mon, 29 Apr 2002 23:31:38 +0100 (BST) - (envelope-from timbo) -Date: Mon, 29 Apr 2002 23:31:38 +0100 -From: Tim Bunce -To: cmedianu@sfu.ca -Cc: dbi-users@perl.org -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020429233138.E16831@dansat.data-plan.com> -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020429201853.52283.qmail@web10007.mail.yahoo.com>; from calinm@yahoo.com on Mon, Apr 29, 2002 at 01:18:53PM -0700 -Content-Length: 651 -Lines: 20 - -On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> Hello, -> -> I did the following. Wrote a perl script that retreves -> data via a straight select from the database. Then I -> wrote a stored procedure returning a ref cursor open -> on the same select statement and retrieved the data as -> well. Using the REF CURSOR/ sotred procedure was about -> 3 time slower, that is 40 seconds instead of around -> 10. -> -> Is this normal? Is this a problem with oracle or with -> DBD::Oracle? - -DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. - -Get a level 3 trace and look for the "dbd_describe'd" line for the -ref cursor. - -Tim. - -From calinm@yahoo.com Tue Apr 30 22:02:56 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL2tR26878 - for ; Tue, 30 Apr 2002 22:02:55 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:02:55 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020198219:10:21718:114; Tue, 30 Apr 2002 20:23:39 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101732; 30 Apr 2002 20:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C6B4A2BFB4 - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10004.mail.yahoo.com (web10004.mail.yahoo.com [216.136.130.40]) - by dolly1.pobox.com (Postfix) with SMTP id 527BD2BF3D - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Message-ID: <20020430202321.54825.qmail@web10004.mail.yahoo.com> -Received: from [213.157.171.169] by web10004.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 13:23:20 PDT -Date: Tue, 30 Apr 2002 13:23:20 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -Cc: dbi-users@perl.org -In-Reply-To: <20020430140517.P16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 425 -Lines: 18 - -I "Solved" the problem. For Now.. I did -perl Makefile.PL -8 - -hoping that the buggy code would be recently added, -and it was. Now both the select and the cursor return -the data at the same speed, meaning fast.. - -Am I am missing much by not using the code for Oracle -8? - -Thanks, - -Calin - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From timbo@dansat.data-plan.com Wed May 1 16:49:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g41FnsR33994 - for ; Wed, 1 May 2002 16:49:54 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 May 2002 16:49:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020265865:20:10671:66; Wed, 01 May 2002 15:11:05 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-2.mail.demon.net - id aa2122069; 1 May 2002 15:10 GMT -Received: from cali-3.pobox.com (cali-3.pobox.com [64.71.166.116]) - by silk.pobox.com (Postfix) with ESMTP id F29CC3FDF2 - for ; Wed, 1 May 2002 11:09:52 -0400 (EDT) -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id E3A943E689 - for ; Wed, 1 May 2002 10:57:15 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id D1F523E688 - for ; Wed, 1 May 2002 10:57:14 -0400 (EDT) -Received: (qmail 96042 messnum 564683 invoked from network[159.134.166.63/p575.as1.limerick1.eircom.net]); 1 May 2002 14:57:13 -0000 -Received: from p575.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.63) - by mail03.svc.cra.dublin.eircom.net (qp 96042) with SMTP; 1 May 2002 14:57:13 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g41EvIh33626; - Wed, 1 May 2002 15:57:18 +0100 (BST) - (envelope-from timbo) -Date: Wed, 1 May 2002 15:57:18 +0100 -From: Tim Bunce -To: Calin Medianu -Cc: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020501155718.S16831@dansat.data-plan.com> -References: <20020430151126.Q16831@dansat.data-plan.com> <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020430183429.33340.qmail@web10005.mail.yahoo.com>; from calinm@yahoo.com on Tue, Apr 30, 2002 at 11:34:29AM -0700 -Status: RO -Content-Length: 3111 -Lines: 111 - -Thanks. I'll take a look when I get to DBD::Oracle again. - -I think the last row of that table applies and it doesn't refer to OCIBindObject(): - REF CURSOR variables - SQLT_RSET - Allocate a statement handle, OCIStmt, and then bind its address - (OCIStmt **) using the SQLT_RSET datatype. -Note that SQLT_REF isn't the same as SQLT_RSET. - -You could always try patching it yourself! - -Tim. - - -On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin Medianu wrote: -> It says here: -> http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> -> that 2 calls are neede to bind a ref , the second is -> to OCIBindObject() which I don't see in dbdimp.c. -> -> Could this be a reason? -> -> Cheers, -> -> Calin -> -> --- Tim Bunce wrote: -> > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > Medianu wrote: -> > > Me again with the slow cursors. -> > > -> > > I modified both queries to only return 10 rows. -> > > I ran a sniffer (ethereal) on the NIC. It is -> > pretty cool, it also decodes TNS. -> > > -> > > when I am using the SQL, it works like this, there -> > are about 7 packets -> > > received by my workstation to set up the session, -> > then all 10 rows are in the -> > > same packet, then there is another packet probably -> > saying goodbye. -> > > -> > > When I am using the REF cursor, each row comes in -> > it's own TNS packet, that -> > > is why it is so slow! -> > > -> > > Any idea how to fix it? -> > -> > Do a level 9 trace to get a log of the OCI calls and -> > confirm that -> > the fragment I posted is being called (may be -> > helpful to also -> > add an extra print statement into that code since -> > parsing the -> > OCI trace can be painful). -> > -> > Assuming the code is being called then as far as I -> > can see the code is -> > doing the right thing and it's probably an Oracle -> > OCI issue. -> > -> > You'd need to talk to Oracle support. No need to -> > mention perl etc. -> > Just talk about your OCI application and provide the -> > OCI call trace. -> > -> > Let me know what you find out! -> > -> > Tim. -> > -> > > thanks a lot, -> > > -> > > Calin -> > > -> > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> > Medianu wrote: -> > > > > Hello, -> > > > > -> > > > > I did the following. Wrote a perl script that -> > retreves -> > > > > data via a straight select from the database. -> > Then I -> > > > > wrote a stored procedure returning a ref -> > cursor open -> > > > > on the same select statement and retrieved the -> > data as -> > > > > well. Using the REF CURSOR/ sotred procedure -> > was about -> > > > > 3 time slower, that is 40 seconds instead of -> > around -> > > > > 10. -> > > > > -> > > > > Is this normal? Is this a problem with oracle -> > or with -> > > > > DBD::Oracle? -> > > > -> > > > DBD::Oracle. It probably isn't setting up a row -> > cache for the ref cursor. -> > > > -> > > > Get a level 3 trace and look for the -> > "dbd_describe'd" line for the -> > > > ref cursor. -> > > > -> > > > Tim. -> -> -> __________________________________________________ -> Do You Yahoo!? -> Yahoo! Health - your guide to health and wellness -> http://health.yahoo.com - diff --git a/err_unsorted/err_slowcsr.msg b/err_unsorted/err_slowcsr.msg deleted file mode 100644 index 80c43350..00000000 --- a/err_unsorted/err_slowcsr.msg +++ /dev/null @@ -1,316 +0,0 @@ -From calinm@yahoo.com Tue Apr 30 22:03:11 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL3AR27018 - for ; Tue, 30 Apr 2002 22:03:10 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:03:10 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020196981:10:23493:39; Tue, 30 Apr 2002 20:03:01 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-1.mail.demon.net - id aa1108477; 30 Apr 2002 20:02 GMT -Received: from dolly1.pobox.com (dolly1.pobox.com [207.106.49.22]) - by silk.pobox.com (Postfix) with ESMTP id 915563FCE8 - for ; Tue, 30 Apr 2002 14:35:38 -0400 (EDT) -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 343702BFDD - for ; Tue, 30 Apr 2002 14:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10005.mail.yahoo.com (web10005.mail.yahoo.com [216.136.130.41]) - by dolly1.pobox.com (Postfix) with SMTP id 6AA822BFA3 - for ; Tue, 30 Apr 2002 14:34:37 -0400 (EDT) -Message-ID: <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Received: from [213.157.171.169] by web10005.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 11:34:29 PDT -Date: Tue, 30 Apr 2002 11:34:29 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020430151126.Q16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 2457 -Lines: 96 - -It says here: -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 - -that 2 calls are neede to bind a ref , the second is -to OCIBindObject() which I don't see in dbdimp.c. - -Could this be a reason? - -Cheers, - -Calin - ---- Tim Bunce wrote: -> On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> Medianu wrote: -> > Me again with the slow cursors. -> > -> > I modified both queries to only return 10 rows. -> > I ran a sniffer (ethereal) on the NIC. It is -> pretty cool, it also decodes TNS. -> > -> > when I am using the SQL, it works like this, there -> are about 7 packets -> > received by my workstation to set up the session, -> then all 10 rows are in the -> > same packet, then there is another packet probably -> saying goodbye. -> > -> > When I am using the REF cursor, each row comes in -> it's own TNS packet, that -> > is why it is so slow! -> > -> > Any idea how to fix it? -> -> Do a level 9 trace to get a log of the OCI calls and -> confirm that -> the fragment I posted is being called (may be -> helpful to also -> add an extra print statement into that code since -> parsing the -> OCI trace can be painful). -> -> Assuming the code is being called then as far as I -> can see the code is -> doing the right thing and it's probably an Oracle -> OCI issue. -> -> You'd need to talk to Oracle support. No need to -> mention perl etc. -> Just talk about your OCI application and provide the -> OCI call trace. -> -> Let me know what you find out! -> -> Tim. -> -> > thanks a lot, -> > -> > Calin -> > -> > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> Medianu wrote: -> > > > Hello, -> > > > -> > > > I did the following. Wrote a perl script that -> retreves -> > > > data via a straight select from the database. -> Then I -> > > > wrote a stored procedure returning a ref -> cursor open -> > > > on the same select statement and retrieved the -> data as -> > > > well. Using the REF CURSOR/ sotred procedure -> was about -> > > > 3 time slower, that is 40 seconds instead of -> around -> > > > 10. -> > > > -> > > > Is this normal? Is this a problem with oracle -> or with -> > > > DBD::Oracle? -> > > -> > > DBD::Oracle. It probably isn't setting up a row -> cache for the ref cursor. -> > > -> > > Get a level 3 trace and look for the -> "dbd_describe'd" line for the -> > > ref cursor. -> > > -> > > Tim. - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From calinm@yahoo.com Fri May 3 13:48:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g43Cm5R50489 - for ; Fri, 3 May 2002 13:48:05 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 03 May 2002 13:48:05 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020429421:10:02019:143; Fri, 03 May 2002 12:37:01 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1123562; 3 May 2002 12:36 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id D7BD1725A1 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10008.mail.yahoo.com (web10008.mail.yahoo.com [216.136.130.44]) - by wormwood.pobox.com (Postfix) with SMTP id 3088772674 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Message-ID: <20020503123640.19648.qmail@web10008.mail.yahoo.com> -Received: from [213.157.171.169] by web10008.mail.yahoo.com via HTTP; Fri, 03 May 2002 05:36:40 PDT -Date: Fri, 3 May 2002 05:36:40 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020501155718.S16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -Content-Length: 3619 -Lines: 150 - -Sure, - -I'll give it a try next week. - -Cheers, - -Calin ---- Tim Bunce wrote: -> Thanks. I'll take a look when I get to DBD::Oracle -> again. -> -> I think the last row of that table applies and it -> doesn't refer to OCIBindObject(): -> REF CURSOR variables -> SQLT_RSET -> Allocate a statement handle, OCIStmt, and then -> bind its address -> (OCIStmt **) using the SQLT_RSET datatype. -> Note that SQLT_REF isn't the same as SQLT_RSET. -> -> You could always try patching it yourself! -> -> Tim. -> -> -> On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin -> Medianu wrote: -> > It says here: -> > -> -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> > -> > that 2 calls are neede to bind a ref , the second -> is -> > to OCIBindObject() which I don't see in dbdimp.c. -> > -> > Could this be a reason? -> > -> > Cheers, -> > -> > Calin -> > -> > --- Tim Bunce wrote: -> > > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > > Medianu wrote: -> > > > Me again with the slow cursors. -> > > > -> > > > I modified both queries to only return 10 -> rows. -> > > > I ran a sniffer (ethereal) on the NIC. It is -> > > pretty cool, it also decodes TNS. -> > > > -> > > > when I am using the SQL, it works like this, -> there -> > > are about 7 packets -> > > > received by my workstation to set up the -> session, -> > > then all 10 rows are in the -> > > > same packet, then there is another packet -> probably -> > > saying goodbye. -> > > > -> > > > When I am using the REF cursor, each row comes -> in -> > > it's own TNS packet, that -> > > > is why it is so slow! -> > > > -> > > > Any idea how to fix it? -> > > -> > > Do a level 9 trace to get a log of the OCI calls -> and -> > > confirm that -> > > the fragment I posted is being called (may be -> > > helpful to also -> > > add an extra print statement into that code -> since -> > > parsing the -> > > OCI trace can be painful). -> > > -> > > Assuming the code is being called then as far as -> I -> > > can see the code is -> > > doing the right thing and it's probably an -> Oracle -> > > OCI issue. -> > > -> > > You'd need to talk to Oracle support. No need to -> > > mention perl etc. -> > > Just talk about your OCI application and provide -> the -> > > OCI call trace. -> > > -> > > Let me know what you find out! -> > > -> > > Tim. -> > > -> > > > thanks a lot, -> > > > -> > > > Calin -> > > > -> > > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, -> Calin -> > > Medianu wrote: -> > > > > > Hello, -> > > > > > -> > > > > > I did the following. Wrote a perl script -> that -> > > retreves -> > > > > > data via a straight select from the -> database. -> > > Then I -> > > > > > wrote a stored procedure returning a ref -> > > cursor open -> > > > > > on the same select statement and retrieved -> the -> > > data as -> > > > > > well. Using the REF CURSOR/ sotred -> procedure -> > > was about -> > > > > > 3 time slower, that is 40 seconds instead -> of -> > > around -> > > > > > 10. -> > > > > > -> > > > > > Is this normal? Is this a problem with -> oracle -> > > or with -> > > > > > DBD::Oracle? -> > > > > -> > > > > DBD::Oracle. It probably isn't setting up a -> row -> > > cache for the ref cursor. -> > > > > -> > > > > Get a level 3 trace and look for the -> > > "dbd_describe'd" line for the -> > > > > ref cursor. -> > > > > -> > > > > Tim. -> > -> > -> > __________________________________________________ -> > Do You Yahoo!? -> > Yahoo! Health - your guide to health and wellness -> > http://health.yahoo.com - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - diff --git a/err_unsorted/err_svrparse.msg b/err_unsorted/err_svrparse.msg deleted file mode 100644 index 16886ca8..00000000 --- a/err_unsorted/err_svrparse.msg +++ /dev/null @@ -1,4717 +0,0 @@ -From cary.millsap@hotsos.com Thu Sep 12 23:38:20 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8CMbgC02618 - for ; Thu, 12 Sep 2002 23:38:03 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 12 Sep 2002 23:38:03 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031869308:20:16258:30; Thu, 12 Sep 2002 22:21:48 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2108888; 12 Sep 2002 22:21 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id A32132F05C9 - for ; Thu, 12 Sep 2002 18:21:34 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-3.pobox.com (Postfix) with ESMTP id D71F62F056D - for ; Thu, 12 Sep 2002 18:21:31 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8CMLQn17849; - Thu, 12 Sep 2002 17:21:26 -0500 -From: "Cary Millsap" -To: -Subject: -Date: Thu, 12 Sep 2002 17:21:17 -0500 -Message-ID: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_016A_01C25A80.D1527130" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 64884 -Lines: 2025 - -This is a multi-part message in MIME format. - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: multipart/alternative; - boundary="----=_NextPart_001_016B_01C25A80.D1557E70" - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -How are you doing? I hope you've had a good two years since I saw you on -the Oracle Geek Cruise event. - - - -I've been working on a project this year to construct a book about -optimizing Oracle response time. In my research, I've discovered -something about the DBI that I didn't expect: it executes two Oracle -parse calls for every one that I would expect an efficient DBI layer to -make. I've included my Perl source (below), the Oracle level-12 trace -data that shows the sequence of calls it's receiving from the Perl -application (below), a level-9 DBI trace from the application -(attached), and our version information (below). - - - -The reason I'm bringing this to your attention in this way is that I'm -relying pretty heavily upon Perl for performance measurement tools, -examples, and simulators in the text. I love the language and I want for -the book to be an encouragement for more people to use Perl. However, -this extra-parse behavior is one of the things that the book highlights -as an important scalability barrier (some other tools do it too, -unfortunately). Of course, this is a speed bump on the road to my goal -of helping to promote Perl. - - - -I was hoping that by showing you this specific data, you could make the -problem go away. - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - -Listing [listing.sqltrace.pl]: a simple application that executes a -database query - -#!/usr/bin/perl - - - - - -# $Header: /home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 21:10:25 -cvm Exp $ - -# Cary Millsap (cary.millsap@hotsos.com) - - - - - -use strict; - -use warnings; - -use DBI; - -use DBD::Oracle; - -use Getopt::Long; - -use Term::ReadKey; - - - - - -my $sth; # Oracle statement handle - -my $hostname = ""; - -my $username = "/"; - -my $password = ""; - -my $logfile = "ex1.log"; - -my %attr = ( - - RaiseError => 1, - - AutoCommit => 0, - -); - -my %opt = ( - - pause => 0, - -); - - - - - -# Get command line options and arguments. - -GetOptions( - - "pause" => \$opt{pause}, - -); - -my $key = 37; # default query value - -$key = $ARGV[0] if $ARGV[0]; - - - - - -# Connect to Oracle. - -my $dbh = DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr); - -$dbh->trace(9, $logfile); - - - - - -# Activate tracing. - -$sth = $dbh->prepare(q(alter session set events '10046 trace name -context forever, level 12')); - -$sth->execute; - - - - - -# Allow the user to find the Oracle session and activate OS diagnostic - -# tools like strace(1) or lsof(8). - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Execute the query to trace. - -$sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -$sth->execute($key); - - - - - -# Print output header. - -my @cdefs = qw(%8d %8d %32s); # column definitions - -my @hdefs = qw(Key Fkey Value); # column headings - -my $bformat = join(" ", @cdefs) . "\n"; - -my $hformat; ($hformat = $bformat) =~ s/%(\d*)\S+/%$1s/g; - -printf $hformat, @hdefs; - -printf $hformat, do { my @h; push @h, "-" x (/(\d+)/?$1:10) for @cdefs; -@h }; - - - - - -# Print query results. - -for my $row (@{$sth->fetchall_arrayref}) { - - printf $bformat, @$row; - -} - - - - - -# Allow the user to do final OS diagnostic stuff. - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Disconnect from Oracle. - -$dbh->disconnect; - - - - - -Listing [listing:sqltrace.trc]: raw SQL trace output for an execution of -our program - -/usr/local/oracle/admin/V816/udump/ora_17349.trc - -Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production - -With the Partitioning option - -JServer Release 8.1.6.0.0 - Production - -ORACLE_HOME = /usr/local/oracle/product/8.1.6 - -System name: Linux - -Node name: www.hotsos.com - -Release: 2.2.16-22enterprise - -Version: #1 SMP Tue Aug 22 16:29:32 EDT 2000 - -Machine: i686 - -Instance name: V816 - -Redo thread mounted by this instance: 1 - -Oracle process number: 8 - -Unix process pid: 17349, image: oracle@www.hotsos.com (TNS V1-V3) - - - -*** SESSION ID:(7.9) 2002-09-12 16:14:01.582 - -===================== - -PARSING IN CURSOR #1 len=69 dep=0 uid=12 oct=42 lid=12 tim=107309054 -hv=1509700594 ad='54af5e14' - -alter session set events '10046 trace name context forever, level 12' - -END OF STMT - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107309054 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -*** 2002-09-12 16:14:31.226 - -WAIT #1: nam='SQL*Net message from client' ela= 2964 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -WAIT #2: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #2: nam='SQL*Net message from client' ela= 0 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -BINDS #1: - - bind 0: dty=1 mxl=32(04) mal=00 scl=00 pre=00 oacflg=25 oacfl2=10 -size=32 offset=0 - - bfp=0940e7f0 bln=32 avl=04 flg=05 - - value="8542" - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #1: nam='file open' ela= 0 p1=0 p2=0 p3=0 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6671 p3=1 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6678 p3=1 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - -*** 2002-09-12 16:14:56.200 - -WAIT #1: nam='SQL*Net message from client' ela= 2496 p1=1650815232 p2=1 -p3=0 - -XCTEND rlbk=0, rd_only=1 - -STAT #1 id=1 cnt=1 pid=0 pos=0 obj=5156 op='TABLE ACCESS BY INDEX ROWID -T ' - -STAT #1 id=2 cnt=2 pid=1 pos=1 obj=5157 op='INDEX UNIQUE SCAN ' - - - - - -$ perl -V - -Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration: - - Platform: - - osname=linux, osvers=2.2.5-22smp, archname=i386-linux - - uname='linux porky.devel.redhat.com 2.2.5-22smp #1 smp wed jun 2 -09:11:51 edt 1999 i686 unknown ' - - config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -Dcc=gcc --Dcccdlflags=-fPIC -Dinstallprefix=/usr -Dprefix=/usr --Darchname=i386-linux -Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm --Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Uuselargefiles' - - hint=recommended, useposix=true, d_sigaction=define - - usethreads=undef use5005threads=undef useithreads=undef -usemultiplicity=undef - - useperlio=undef d_sfio=undef uselargefiles=undef - - use64bitint=undef use64bitall=undef uselongdouble=undef -usesocks=undef - - Compiler: - - cc='gcc', optimize='-O2 -march=i386 -mcpu=i686', gccversion=2.96 -20000731 (experimental) - - cppflags='-fno-strict-aliasing' - - ccflags ='-fno-strict-aliasing' - - stdchar='char', d_stdstdio=define, usevfork=false - - intsize=4, longsize=4, ptrsize=4, doublesize=8 - - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', -lseeksize=4 - - alignbytes=4, usemymalloc=n, prototype=define - - Linker and Libraries: - - ld='gcc', ldflags =' -L/usr/local/lib' - - libpth=/usr/local/lib /lib /usr/lib - - libs=-lnsl -ldl -lm -lc -lcrypt - - libc=/lib/libc-2.1.92.so, so=so, useshrplib=false, libperl=libperl.a - - Dynamic Linking: - - dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' - - cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' - - - - - -Characteristics of this binary (from libperl): - - Compile-time options: - - Built under linux - - Compiled at Aug 7 2000 10:59:51 - - @INC: - - /usr/lib/perl5/5.6.0/i386-linux - - /usr/lib/perl5/5.6.0 - - /usr/lib/perl5/site_perl/5.6.0/i386-linux - - /usr/lib/perl5/site_perl/5.6.0 - - /usr/lib/perl5/site_perl - - . - - - - - -Other site information - -- Redhat Linux 7.0 - -- Oracle 8.1.6.1.0 - -- DBD-Oracle 1.12 - -- DBI 1.30 - - - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

How are you doing? I hope you’ve had a good two = -years -since I saw you on the Oracle Geek Cruise event.

- -

 

- -

I’ve been working on a project this year to = -construct -a book about optimizing Oracle response time. In my research, I’ve -discovered something about the DBI that I didn’t expect: it = -executes two -Oracle parse calls for every one that I would expect an efficient DBI = -layer to -make. I’ve included my Perl source (below), the Oracle level-12 = -trace -data that shows the sequence of calls it’s receiving from the Perl = -application -(below), a level-9 DBI trace from the application (attached), and our = -version information -(below).

- -

 

- -

The reason I’m bringing this to your attention = -in this -way is that I’m relying pretty heavily upon Perl for performance -measurement tools, examples, and simulators in the text. I love the = -language -and I want for the book to be an encouragement for more people to use = -Perl. -However, this extra-parse behavior is one of the things that the book = -highlights -as an important scalability barrier (some other tools do it too, = -unfortunately). -Of course, this is a speed bump on the road to my goal of helping to = -promote Perl.

- -

 

- -

I was hoping that by showing you this specific data, = -you -could make the problem go away.

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -
- -

Listing [listing.sqltrace.pl]: a simple = -application that -executes a database query

- -
- -
- -

#!/usr/bin/perl

- -

- -

- -

 

- -

 

- -

# = -$Header: -/home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 = -21:10:25 cvm Exp $

- -

- -

# = -Cary Millsap (cary.millsap@hotsos.com)

- -

- -

 

- -

 

- -

use = -strict;

- -

- -

use = -warnings;

- -

- -

use = -DBI;

- -

- -

use = -DBD::Oracle;

- -

- -

use = -Getopt::Long;

- -

- -

use = -Term::ReadKey;

- -

- -

 

- -

 

- -

my -$sth;           &n= -bsp;        -# Oracle statement handle

- -

- -

my = -$hostname =3D -"";

- -

- -

my = -$username =3D -"/";

- -

- -

my = -$password =3D -"";

- -

- -

my = -$logfile  -=3D "ex1.log";

- -

- -

my = -%attr =3D (

- -

- -

    -RaiseError =3D> 1,

- -

- -

    -AutoCommit =3D> 0,

- -

- -

);

- -

- -

my = -%opt =3D (

- -

- -

    -pause   =3D> 0,

- -

- -

);

- -

- -

 

- -

 

- -

# Get = -command line -options and arguments.

- -

- -

GetOptions(

- -

- -

    -"pause" =3D> \$opt{pause},

- -

- -

);

- -

- -

my = -$key =3D -37;           &nbs= -p;  - # default query value

- -

- -

$key = -=3D $ARGV[0] if -$ARGV[0];

- -

- -

 

- -

 

- -

# = -Connect to -Oracle.

- -

- -

my = -$dbh =3D -DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr);

- -

- -

$dbh->trace(9, -$logfile);

- -

- -

 

- -

 

- -

# = -Activate -tracing.

- -

- -

$sth = -=3D -$dbh->prepare(q(alter session set events '10046 trace name context = -forever, -level 12'));

- -

- -

$sth->execute;

- -

- -

 

- -

 

- -

# = -Allow the user -to find the Oracle session and activate OS diagnostic

- -

- -

# = -tools like -strace(1) or lsof(8).

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Execute the -query to trace.

- -

- -

$sth = -=3D -$dbh->prepare(q(select key, fkey, value from t where = -key=3D?));

- -

- -

$sth->execute($key);

- -

- -

 

- -

 

- -

# = -Print output -header.

- -

- -

my = -@cdefs =3D qw(%8d -%8d %32s);   # column definitions

- -

- -

my = -@hdefs =3D qw(Key -Fkey Value); # column headings

- -

- -

my = -$bformat =3D -join("  ", @cdefs) . "\n";

- -

- -

my = -$hformat; -($hformat =3D $bformat) =3D~ s/%(\d*)\S+/%$1s/g;

- -

- -

printf $hformat, -@hdefs;

- -

- -

printf $hformat, -do { my @h; push @h, "-" x (/(\d+)/?$1:10) for = -@cdefs; @h };

- -

- -

 

- -

 

- -

# = -Print query -results.

- -

- -

for = -my $row -(@{$sth->fetchall_arrayref}) {

- -

- -

    -printf $bformat, @$row;

- -

- -

}

- -

- -

- -

 

- -

 

- -

# = -Allow the user -to do final OS diagnostic stuff.

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Disconnect from -Oracle.

- -

- -

$dbh->disconnect;

- -
- -

 

- -

 

- -
- -

Listing [listing:sqltrace.trc]: raw SQL trace = -output for -an execution of our program

- -
- -
- -

/usr/local/oracle/admin/V816/udump/ora_17349.tr= -c

- -

Oracle8i Enterprise -Edition Release 8.1.6.1.0 - Production

- -

With = -the -Partitioning option

- -

JServer Release -8.1.6.0.0 - Production

- -

ORACLE_HOME =3D -/usr/local/oracle/product/8.1.6

- -

System -name:        Linux

- -

Node name:  = -www.hotsos.com

- -

Release:    = -2.2.16-22enterprise

- -

Version:    #1 -SMP Tue Aug 22 16:29:32 EDT 2000

- -

Machine:    = -i686

- -

Instance name: -V816

- -

Redo = -thread -mounted by this instance: 1

- -

Oracle process -number: 8

- -

Unix = -process pid: -17349, image: oracle@www.hotsos.com (TNS V1-V3)

- -

 

- -

*** = -SESSION -ID:(7.9) 2002-09-12 16:14:01.582

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D69 dep=3D0 uid=3D12 oct=3D42 lid=3D12 = -tim=3D107309054 hv=3D1509700594 -ad=3D'54af5e14'

- -

alter = -session set -events '10046 trace name context forever, level 12'

- -

END = -OF STMT

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -309054

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

*** = -2002-09-12 -16:14:31.226

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2964 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#2 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312018 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

WAIT = -#2: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#2: -nam=3D'SQL*Net message from client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312019 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

BINDS = -#1:

- -

 bind 0: -dty=3D1 mxl=3D32(04) mal=3D00 scl=3D00 pre=3D00 oacflg=3D25 oacfl2=3D10 = -size=3D32 offset=3D0

- -

   bfp=3D0940e7f0 bln=3D32 avl=3D04 flg=3D05

- -

   -value=3D"8542"

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#1: nam=3D'file -open' ela=3D 0 p1=3D0 p2=3D0 p3=3D0

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6671 p3=3D1

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6678 p3=3D1

- -

FETCH -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

*** = -2002-09-12 -16:14:56.200

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2496 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

XCTEND rlbk=3D0, -rd_only=3D1

- -

STAT = -#1 id=3D1 cnt=3D1 -pid=3D0 pos=3D0 obj=3D5156 op=3D'TABLE ACCESS BY INDEX ROWID T = -'

- -

STAT = -#1 id=3D2 cnt=3D2 -pid=3D1 pos=3D1 obj=3D5157 op=3D'INDEX UNIQUE SCAN '

- -
- -

 

- -

 

- -

$ perl -V

- -

Summary of my perl5 (revision 5.0 version 6 subversion 0) = -configuration:

- -

  Platform:

- -

    osname=3Dlinux, osvers=3D2.2.5-22smp, = -archname=3Di386-linux

- -

    uname=3D'linux porky.devel.redhat.com = -2.2.5-22smp #1 smp -wed jun 2 09:11:51 edt 1999 i686 unknown '

- -

    config_args=3D'-des -Doptimize=3D-O2 = --march=3Di386 -mcpu=3Di686 --Dcc=3Dgcc -Dcccdlflags=3D-fPIC -Dinstallprefix=3D/usr -Dprefix=3D/usr = --Darchname=3Di386-linux --Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm -Di_gdbm -Di_shadow = --Di_syslog -Dman3ext=3D3pm -Uuselargefiles'

- -

    hint=3Drecommended, useposix=3Dtrue, = -d_sigaction=3Ddefine

- -

    usethreads=3Dundef use5005threads=3Dundef = -useithreads=3Dundef -usemultiplicity=3Dundef

- -

    useperlio=3Dundef d_sfio=3Dundef = -uselargefiles=3Dundef

- -

    use64bitint=3Dundef use64bitall=3Dundef = -uselongdouble=3Dundef -usesocks=3Dundef

- -

  Compiler:

- -

    cc=3D'gcc', optimize=3D'-O2 -march=3Di386 = --mcpu=3Di686', gccversion=3D2.96 -20000731 (experimental)

- -

    = -cppflags=3D'-fno-strict-aliasing'

- -

    ccflags = -=3D'-fno-strict-aliasing'

- -

    stdchar=3D'char', d_stdstdio=3Ddefine, = -usevfork=3Dfalse

- -

    intsize=3D4, longsize=3D4, ptrsize=3D4, = -doublesize=3D8

- -

    d_longlong=3Ddefine, longlongsize=3D8, = -d_longdbl=3Ddefine, -longdblsize=3D12

- -

    ivtype=3D'long', ivsize=3D4, = -nvtype=3D'double', nvsize=3D8, Off_t=3D'off_t', -lseeksize=3D4

- -

    alignbytes=3D4, usemymalloc=3Dn, = -prototype=3Ddefine

- -

  Linker and Libraries:

- -

    ld=3D'gcc', ldflags =3D' = --L/usr/local/lib'

- -

    libpth=3D/usr/local/lib /lib = -/usr/lib

- -

    libs=3D-lnsl -ldl -lm -lc = --lcrypt

- -

    libc=3D/lib/libc-2.1.92.so, so=3Dso, = -useshrplib=3Dfalse, libperl=3Dlibperl.a

- -

  Dynamic Linking:

- -

    dlsrc=3Ddl_dlopen.xs, dlext=3Dso, = -d_dlsymun=3Dundef, ccdlflags=3D'-rdynamic'

- -

    cccdlflags=3D'-fPIC', lddlflags=3D'-shared = --L/usr/local/lib'

- -

 

- -

 

- -

Characteristics of this binary (from libperl): = -

- -

  Compile-time options:

- -

  Built under linux

- -

  Compiled at Aug  7 2000 10:59:51

- -

  @INC:

- -

    = -/usr/lib/perl5/5.6.0/i386-linux

- -

    /usr/lib/perl5/5.6.0

- -

    = -/usr/lib/perl5/site_perl/5.6.0/i386-linux

- -

    = -/usr/lib/perl5/site_perl/5.6.0

- -

    /usr/lib/perl5/site_perl

- -

    .

- -

 

- -

 

- -

Other site information

- -

- Redhat Linux 7.0

- -

- Oracle 8.1.6.1.0

- -

- DBD-Oracle 1.12

- -

- DBI 1.30

- -

 

- -
- - - - - -------=_NextPart_001_016B_01C25A80.D1557E70-- - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: application/octet-stream; - name="ex1.log" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="ex1.log" - - DBI::db=3DHASH(0x8235a74) trace level set to 9 in DBI 1.30-nothread=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'alter session set events '10046 trace name context forever, level 12'')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240f68)=3D>DBI::st=3DHASH(0x8240f98),= - DBD::Oracle::st, 8240f74, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= -OCIHandleAlloc(0x82465d8,0x826c948,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826bf48,0x82559ec,'alter session set events '10046 = -trace name context forever, level 12'',69,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0x826c94c,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql ALTER=0A= - dbd_describe skipped for ALTER=0A= - <- prepare=3D DBI::st=3DHASH(0x8240f68) at ex1.pl line 38=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240f68)~0x8240f98)=0A= - dbd_st_execute ALTER (out0, lob0)...=0A= -OCIStmtExecute(0x82557c4,0x826bf48,0x82559ec,1,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff654,(nil),9,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute ALTER returned (SUCCESS, rpc0, fn52, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 39=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'select key, fkey, value from t where key=3D?')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240fe0)=3D>DBI::st=3DHASH(0x8240fb0),= - DBD::Oracle::st, 8240fec, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= - dbd_preparse scanned 1 distinct placeholders=0A= -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where = -key=3D:p1',44,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql SELECT=0A= - dbd_describe SELECT (EXPLICIT, lb 80)...=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3DSUCCES= -S=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3dc,(nil),18,0x82559ec)=3DSUCC= -ESS=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d1c0,1)=3DSUCCESS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d6,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d4,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d8,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1da,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1db,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1e8,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 1: 'KEY' NO null , otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d200,2)=3DSUCCESS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d216,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d214,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d218,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d228,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 2: 'FKEY' NULLable, otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d240,3)=3DSUCCESS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d256,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d254,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d258,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d268,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 3: 'VALUE' NULLable, otype 1-> 5, dbsize 32/33, p32.s0=0A= -OCIAttrSet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3d4,4,11,0x82559ec)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d1c4,0x82559ec,1,0x826e8d0,134,5,0x826d438,= -0x826d448,0x826d458,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d204,0x82559ec,2,0x826eaf8,134,5,0x826ca28,= -0x826ca38,0x826ca48,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d244,0x82559ec,3,0x826cbb8,33,5,0x826ca58,0= -x826cbe0,0x826cbf0,0)=3DSUCCESS=0A= - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231)=0A= - <- prepare=3D DBI::st=3DHASH(0x8240fe0) at ex1.pl line 50=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240f98)~INNER)=0A= -OCIHandleFree(0x826bf48,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef at ex1.pl line 51=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240fe0)~0x8240fb0 = -'8542')=0A= - bind :p1 <=3D=3D '8542' (type 0)=0A= - bind :p1 <=3D=3D '8542' (size 4/5/0, ptype 7, otype 1)=0A= - bind :p1 <=3D=3D '8542' (size 4/4, otype 1, indp 0, at_exec 1)=0A= -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb= -6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS=0A= -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da= -090)=3DSUCCESS=0A= - bind :p1 done with ftype 1=0A= - dbd_st_execute SELECT (out0, lob0)...=0A= - in ':p1' [0,0]: len 4, ind 0=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 51=0A= - -> fetchall_arrayref for DBD::Oracle::st = -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0)=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DSUCCESS=0A= - dbih_setup_fbav for 3 fields =3D> 0x8240fbc=0A= - dbd_st_fetch 3 fields SUCCESS=0A= - 0 (rc=3D0): '8542'=0A= - 1 (rc=3D0): '8542'=0A= - 2 (rc=3D0): 'value'=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DNO_DATA=0A= - dbd_st_fetch no-more-data=0A= - <- fetchall_arrayref=3D [ ARRAY(0x82411f0) ] row1 at ex1.pl line 62=0A= - -> disconnect for DBD::Oracle::db = -(DBI::db=3DHASH(0x8235b34)~0x8235a74)=0A= -OCISessionEnd(0x82557c4,0x82559ec,0x826c384,0)=3DSUCCESS=0A= -OCIServerDetach(0x8255834,0x82559ec,0)=3DSUCCESS=0A= - <- disconnect=3D 1 at ex1.pl line 74=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240fb0)~INNER)=0A= -OCIHandleFree(0x826e4a0,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -> DESTROY for DBD::Oracle::db (DBI::db=3DHASH(0x8235a74)~INNER)=0A= -OCIHandleFree(0x826c384,OCI_HTYPE_SESSION)=3DSUCCESS=0A= -OCIHandleFree(0x8255834,OCI_HTYPE_SERVER)=3DSUCCESS=0A= -OCIHandleFree(0x82557c4,OCI_HTYPE_SVCCTX)=3DSUCCESS=0A= -OCIHandleFree(0x82559ec,OCI_HTYPE_ERROR)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -------=_NextPart_000_016A_01C25A80.D1527130-- - - -From timbo@dansat.data-plan.com Fri Sep 13 07:30:31 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6UUC04053 - for ; Fri, 13 Sep 2002 07:30:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:30:30 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031871608:20:03733:55; Thu, 12 Sep 2002 23:00:08 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id ab2122693; 12 Sep 2002 23:00 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id AE0642F0B8A - for ; Thu, 12 Sep 2002 18:58:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id 931D42F0D0A - for ; Thu, 12 Sep 2002 18:58:19 -0400 (EDT) -Received: (qmail 57270 messnum 519666 invoked from network[159.134.164.69/p69.as1.limerick1.eircom.net]); 12 Sep 2002 22:58:17 -0000 -Received: from p69.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.69) - by mail03.svc.cra.dublin.eircom.net (qp 57270) with SMTP; 12 Sep 2002 22:58:17 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8CMwEQ02798; - Thu, 12 Sep 2002 23:58:14 +0100 (BST) - (envelope-from timbo) -Date: Thu, 12 Sep 2002 23:58:14 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls -Message-ID: <20020912225814.GG539@dansat.data-plan.com> -References: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 3530 -Lines: 77 - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCESS - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 '8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCESS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - -From cary.millsap@hotsos.com Fri Sep 13 07:31:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6VsC04590 - for ; Fri, 13 Sep 2002 07:31:54 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:31:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031889643:20:09494:0; Fri, 13 Sep 2002 04:00:43 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-2.mail.demon.net - id aa2008866; 13 Sep 2002 4:00 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id C94C67264F - for ; Fri, 13 Sep 2002 00:00:07 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by wormwood.pobox.com (Postfix) with ESMTP id A821072676 - for ; Fri, 13 Sep 2002 00:00:06 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D405n19404 - for ; Thu, 12 Sep 2002 23:00:05 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 22:59:56 -0500 -Message-ID: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020912225814.GG539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4825 -Lines: 129 - -Tim, - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Thursday, September 12, 2002 5:58 PM -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you -on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer -to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make -the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I -can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect -that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - - -From timbo@dansat.data-plan.com Fri Sep 13 10:48:59 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D9mwC06022 - for ; Fri, 13 Sep 2002 10:48:58 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 10:48:58 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031907122:20:19599:21; Fri, 13 Sep 2002 08:52:02 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2129553; 13 Sep 2002 8:52 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 99E263E660 - for ; Fri, 13 Sep 2002 04:51:54 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-2.pobox.com (Postfix) with SMTP id 721613E637 - for ; Fri, 13 Sep 2002 04:51:53 -0400 (EDT) -Received: (qmail 29161 messnum 524631 invoked from network[159.134.167.5/p773.as1.limerick1.eircom.net]); 13 Sep 2002 08:51:51 -0000 -Received: from p773.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.5) - by mail03.svc.cra.dublin.eircom.net (qp 29161) with SMTP; 13 Sep 2002 08:51:51 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8D8prO05752; - Fri, 13 Sep 2002 09:51:53 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 09:51:53 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913085153.GJ539@dansat.data-plan.com> -References: <20020912225814.GG539@dansat.data-plan.com> <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 6172 -Lines: 154 - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more "official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -> key=:p1',44,1,0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - -From cary.millsap@hotsos.com Fri Sep 13 17:52:40 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DGqdC10778 - for ; Fri, 13 Sep 2002 17:52:39 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 17:52:39 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031932999:10:25604:102; Fri, 13 Sep 2002 16:03:19 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101673; 13 Sep 2002 16:03 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E4A692C078 - for ; Fri, 13 Sep 2002 12:02:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 1609E2C03F - for ; Fri, 13 Sep 2002 12:02:29 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DG2Sn24856 - for ; Fri, 13 Sep 2002 11:02:28 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Fri, 13 Sep 2002 11:02:20 -0500 -Message-ID: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913085153.GJ539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 9234 -Lines: 248 - -Tim, - -I think it's important for a developer to have the ability to turn this -on and off. But I would argue that 0 is the correct default. I think of -it as a probability times cost function. The cost of leaving the setting -at 1 accidentally in a production application is pretty high: if the app -doesn't scale (because it's parsing too much), then it jeopardizes the -business' ability to succeed with it. - -The probability of leaving the option set to 1 accidentally during -production is very high. A point in evidence is that I didn't find the -parameter until I corresponded personally with you. I in fact *still* -don't know where to find it. I've checked Descartes & Bunce, perldoc -DBI, and perldoc DBD::Oracle without finding it yet... - -If the default were 0, the probability of leaving the option set to 0 -accidentally during development would be much lower. A developer faced -with a SQL syntax problem he doesn't understand will do the research -necessary to fix that problem. He can't release his code until he does. - -The problem with the default of 1 is, in my opinion, that most -developers will never learn of the feature, and they'll accidentally -leave it turned on in production. The proportion of developers who -competently performance-test their code is, unfortunately, -microscopically small. But they all do some level of functional testing. - -I would recommend making the ora_check_sql feature a more prominently -documented feature, presumably in "perldoc DBD::Oracle". - -I did learn in a test that specifying the option in the DBI->connect() -call doesn't do anything. Is it possible that you could allow us to -specify it at the connection level? The workaround is to do something -like this: - - use Getopt::Long; - my %prepare_attr = (ora_check_sql=>0); - GetOptions("dev"=>\$dev); - $prepare_attr{ora_check_sql} = 1 if $dev; - # developer must specify the command-line flag to get the -unscalable - # behavior that's necessary for functional testing - ... - $sth = $dbh->prepare($sql, %prepare_attr); # MUST specify -%p..attr - -...But I doubt that most Oracle application developers would come up -with this without some coaching. - -I'll definitely keep an eye open for projects you might like. It would -be a hell of an opportunity for someone to have you, I think. It seems -that if you could make a list like Oracle-L (1,900 people) aware that -there's an opportunity, it would improve your chances of finding -something quickly. It's of course bad taste to advertise oneself overtly -on those lists, but there is almost always a clever way to do it anyway -without offending anyone. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:52 AM -To: Cary Millsap -Cc: 'Tim Bunce' -Subject: Re: two Oracle parse calls - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge -to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our -lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a -preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more -"official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw -you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 -trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret -them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t -where -> key=:p1',44,1,0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: -231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), -{ -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call -parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:37 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLbC13725 - for ; Fri, 13 Sep 2002 23:21:37 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:37 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031951069:20:15816:152; Fri, 13 Sep 2002 21:04:29 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2120669; 13 Sep 2002 21:04 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 544863E642 - for ; Fri, 13 Sep 2002 17:04:17 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id 0AE7C3E667 - for ; Fri, 13 Sep 2002 17:04:16 -0400 (EDT) -Received: (qmail 16221 messnum 355694 invoked from network[159.134.166.226/p738.as1.limerick1.eircom.net]); 13 Sep 2002 21:04:14 -0000 -Received: from p738.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.226) - by mail05.svc.cra.dublin.eircom.net (qp 16221) with SMTP; 13 Sep 2002 21:04:14 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DL4Lx12642; - Fri, 13 Sep 2002 22:04:21 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:04:21 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913210421.GR539@dansat.data-plan.com> -References: <20020913085153.GJ539@dansat.data-plan.com> <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 3078 -Lines: 70 - -On Fri, Sep 13, 2002 at 11:02:20AM -0500, Cary Millsap wrote: -> Tim, -> -> I think it's important for a developer to have the ability to turn this -> on and off. But I would argue that 0 is the correct default. I think of -> it as a probability times cost function. The cost of leaving the setting -> at 1 accidentally in a production application is pretty high: if the app -> doesn't scale (because it's parsing too much), then it jeopardizes the -> business' ability to succeed with it. -> -> The probability of leaving the option set to 1 accidentally during -> production is very high. A point in evidence is that I didn't find the -> parameter until I corresponded personally with you. I in fact *still* -> don't know where to find it. I've checked Descartes & Bunce, perldoc -> DBI, and perldoc DBD::Oracle without finding it yet... - -It's not documented. - -As I recall it... originally DBD::Oracle defered the describe as -long as possible. But people reported very slow select performance: - - http://www.faqchest.com/prgm/dbi-l/dbi-99/dbi-9910/dbi-991005/dbi99101218_28018.html - -Turned out that the row cache logic needed the describe to try to -work out an optimal row cache size. Without the describe the row -cache wasn't getting set up. - -At some point I added code that would just set OCI_ATTR_PREFETCH_MEMORY -to a set size if ora_check_sql was 0. But I can't remember now why -I left ora_check_sql=1. - -It was possibly in relation to wanting to be able to use the -OCI_ATTR_PARSE_ERROR_OFFSET attribute to be able to highlight the -point in a query where the error was detected. But I think execute() -needs to be able to do that anyway (to catch syntax errors in -non-select statements). - -There is another problem. If the describe has been defered and the -application uses $sth->{NAME} or other similar attribute then the -describe has to be done at that point. The code is thee to do that -but the problem is how should the DBI behave if there's an error -in the SQL? It currently always croaks (rather than return undef, -in order to give a useful error message), but that's rather surprising -behaviour to many people and very unhelpful to some. - -There may well be other subtle issues that I can't recall right now. - -> I would recommend making the ora_check_sql feature a more prominently -> documented feature, presumably in "perldoc DBD::Oracle". -> -> I did learn in a test that specifying the option in the DBI->connect() -> call doesn't do anything. Is it possible that you could allow us to -> specify it at the connection level? - -By making it a database handle attribute, yes, that would be my plan. - -> I'll definitely keep an eye open for projects you might like. It would -> be a hell of an opportunity for someone to have you, I think. - -Thanks. - -> It seems that if you could make a list like Oracle-L (1,900 people) aware -> that there's an opportunity, it would improve your chances of finding -> something quickly. It's of course bad taste to advertise oneself overtly -> on those lists, but there is almost always a clever way to do it anyway -> without offending anyone. - -:-) - -Tim. - -From cary.millsap@hotsos.com Fri Sep 13 07:32:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6W1C04656 - for ; Fri, 13 Sep 2002 07:32:01 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:32:01 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031891038:20:04710:44; Fri, 13 Sep 2002 04:23:58 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id ab2004623; 13 Sep 2002 4:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 942A82BF2C - for ; Fri, 13 Sep 2002 00:23:44 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 73C982BF33 - for ; Fri, 13 Sep 2002 00:23:42 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D4Ndn19584 - for ; Thu, 12 Sep 2002 23:23:39 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 23:23:30 -0500 -Message-ID: <019301c25add$53f5dfd0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0194_01C25AB3.6B1FD7D0" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -Content-Length: 36859 -Lines: 1209 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Well, that was easy. Setting ora_check_sql=>0 does solve the problem. - - - -I now shift into "Please make 0 the default" mode. - - - -Here are the Oracle trace files, by the way, with a splash of color to -illustrate how the Oracle kernel sees what's going on (I hope you have -an HTML mail reader)... - - - -With {ora_check_sql=>1} (or no setting at all), here's what Oracle does -for the application: - - - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - - - -The PARSING IN CURSOR section tells us what SQL it is that we're -executing. Each line beginning with "PARSE" is emitted only when Oracle -executes a parse call. There are two. The first is wasted. - - - -Here's the same application with {ora_check_sql=>1} (the official new -default value, I am sure :-)): - - - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=109776065 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -FETCH #1:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=109776065 - - - -One parse call; problem solved. - - - -Thank you sincerely for your help. - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- -From: Cary Millsap [mailto:cary.millsap@hotsos.com] -Sent: Thursday, September 12, 2002 11:00 PM -To: 'Tim Bunce' -Subject: RE: two Oracle parse calls - - - -Tim, - - - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - - - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- - -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] - -Sent: Thursday, September 12, 2002 5:58 PM - -To: Cary Millsap - -Cc: tim.bunce@pobox.com - -Subject: two Oracle parse calls - - - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: - -> Tim, - -> - -> How are you doing? I hope you've had a good two years since I saw you -on - -> the Oracle Geek Cruise event. - - - -Yes thanks. And you? - - - -> I've been working on a project this year to construct a book about - -> optimizing Oracle response time. In my research, I've discovered - -> something about the DBI that I didn't expect: it executes two Oracle - -> parse calls for every one that I would expect an efficient DBI layer -to - -> make. I've included my Perl source (below), the Oracle level-12 trace - -> data that shows the sequence of calls it's receiving from the Perl - -> application (below), a level-9 DBI trace from the application - -> (attached), and our version information (below). - -> - -> I was hoping that by showing you this specific data, you could make -the - -> problem go away. - - - -I can only do what OCI lets me do... but within that I'll do what I -can... - - - -I'm not familar with Oracle trace logs so I can't readily intrepret them - -and I'll take what you say at face value. - - - -But I am familar with DBD::Oracle :) and the logs it writes :) - - - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -> $sth->execute($key); - - - - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - - dbd_preparse scanned 1 distinct placeholders - -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS - -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - - dbd_st_prepare'd sql SELECT - - dbd_describe SELECT (EXPLICIT, lb 80)... - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') - -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS - -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - - bind :p1 done with ftype 1 - - dbd_st_execute SELECT (out0, lob0)... - - in ':p1' [0,0]: len 4, ind 0 - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - - <- execute= '0E0' at ex1.pl line 51 - - - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - - - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -call that prepare() does. - - - -It doesn't do that for non-select statements so you could check if - -non-selects also have two parse calls. - - - -Also try doing - - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - - - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the - -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -is possibly redundant and could be removed (but Oracle ought to detect -that - -anyway and not make a round-trip for it, and certainly not call parse). - - - -If non-selects only have one parse call but ora_check_sql=>0 doesn't - -fix selects, then I might be able to do a simple patch to avoid the - -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - - - -Then the issue will be: should ora_check_sql=>0 be the default... - - - -Tim. - - - -p.s. I'd love a copy of your book when it's ready! - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Well, that was easy. Setting ora_check_sql=3D>0 = -does solve the -problem.

- -

 

- -

I now shift into "Please make 0 the = -default" mode.

- -

 

- -

Here are the Oracle trace files, by the way, with a = -splash -of color to illustrate how the Oracle kernel sees what’s going on = -(I hope -you have an HTML mail reader)...

- -

 

- -

With {ora_check_sql=3D>1} (or no setting at all), = -here’s -what Oracle does for the application:

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #2 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312018 = -hv=3D1997601641 ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF STMT

- -

PARSE = -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312019 = -hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF = -STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

FETCH = -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

 

- -

The PARSING IN CURSOR section tells us what SQL it is = -that -we’re executing. Each line beginning with “PARSE” is = -emitted -only when Oracle executes a parse call. There are two. The first is = -wasted.

- -

 

- -

Here’s the same application with = -{ora_check_sql=3D>1} (the official new = -default value, I -am sure J):

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 = -dep=3D0 uid=3D12 -oct=3D3 lid=3D12 tim=3D109776065 hv=3D1997601641 = -ad=3D'54af1384'

- -

select key, fkey, value from = -t where -key=3D:p1

- -

END OF STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

FETCH = -#1:c=3D0,e=3D0,p=3D0,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D109= -776065

- -

 

- -

One parse call; problem solved.

- -

 

- -

Thank you sincerely for your help.

- -

 

- -

 

- -

Cary = -Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System = -Performance, -Feb 9-12 Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 = -Middelfart Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----
-From: Cary Millsap [mailto:cary.millsap@hotsos.com]
-Sent: Thursday, September 12, 2002 11:00 PM
-To: 'Tim Bunce'
-Subject: RE: two Oracle parse calls

- -

 

- -

Tim,

- -

 

- -

Thanks so very much. The attribute ora_check_sql=3D>0 is new = -knowledge -to me; this is a nice reward for having written to you. I will test it = -either -tonight or the first thing tomorrow and then inform you of the results -immediately after that. If it solves the problem, then I will lobby you = -to make -0 the default value and probably consider the issue "problem = -solved."

- -

 

- -

Things are very well, thank you. I've been at home with my = -family now -for over three straight weeks, and we're having a nice time of our lives = -these -days with the business settling into stride a bit. Tonight is a big = -night for -me. I've just crossed the line of accepting a preliminary offer from = -O'Reilly. -This book project has actually been underway for quite some time now, = -but as of -tonight it's quite a bit more "official."

- -

 

- -

 

- -

Cary Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec = -9-11 -Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System Performance, Feb = -9-12 -Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 Middelfart = -Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----

- -

From: Tim Bunce [mailto:Tim.Bunce@pobox.com]

- -

Sent: Thursday, September 12, 2002 5:58 PM

- -

To: Cary Millsap

- -

Cc: tim.bunce@pobox.com

- -

Subject: two Oracle parse calls

- -

 

- -

On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap = -wrote:

- -

> Tim,

- -

>

- -

> How are you doing? I hope you've had a good two years since = -I saw -you on

- -

> the Oracle Geek Cruise event.

- -

 

- -

Yes thanks. And you?

- -

 

- -

> I've been working on a project this year to construct a = -book about

- -

> optimizing Oracle response time. In my research, I've = -discovered

- -

> something about the DBI that I didn't expect: it executes = -two -Oracle

- -

> parse calls for every one that I would expect an efficient = -DBI -layer to

- -

> make. I've included my Perl source (below), the Oracle = -level-12 -trace

- -

> data that shows the sequence of calls it's receiving from = -the Perl

- -

> application (below), a level-9 DBI trace from the = -application

- -

> (attached), and our version information = -(below).

- -

>

- -

> I was hoping that by showing you this specific data, you = -could -make the

- -

> problem go away.

- -

 

- -

I can only do what OCI lets me do... but within that I'll do = -what I -can...

- -

 

- -

I'm not familar with Oracle trace logs so I can't readily = -intrepret -them

- -

and I'll take what you say at face value.

- -

 

- -

But I am familar with DBD::Oracle :) and the logs it writes = -:)

- -

 

- -

> $sth =3D $dbh->prepare(q(select key, fkey, value from t = -where -key=3D?));

- -

> $sth->execute($key);

- -

 

- -

 

- -

    -> prepare for DBD::Oracle::db -(DBI::db=3DHASH(0x8235b34)~0x8235a74 'select key, fkey, value from t = -where -key=3D?')

- -

    dbd_preparse scanned 1 distinct = -placeholders

- -

OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCC= -ESS

- -

OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from = -t -where key=3D:p1',44,1,0)=3DSUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)= -=3DSUCCESS

- -

    dbd_st_prepare'd sql SELECT

- -

    dbd_describe SELECT (EXPLICIT, lb = -80)...

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3D= -SUCCESS

- -

    dbd_describe'd 3 columns (row bytes: 76 max, = -40 est -avg, cache: 231)

- -

    <- prepare=3D DBI::st=3DHASH(0x8240fe0) at = -ex1.pl -line 50

- -

    -> execute for DBD::Oracle::st -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0 '8542')

- -

OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x8= -26cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS - -

OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40= -,0x401da090)=3DSUCCESS

- -

       bind :p1 done with ftype = -1

- -

    dbd_st_execute SELECT (out0, = -lob0)...

- -

       in  ':p1' [0,0]: = -len  4, -ind 0

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3D= -SUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec= -)=3DSUCCESS

- -

    dbd_st_execute SELECT returned (SUCCESS, = -rpc0, fn4, -out0)

- -

    <- execute=3D '0E0' at ex1.pl line = -51

- -

 

- -

Given those OCI calls, what is DBD::Oracle doing that it = -shouldn't?

- -

 

- -

I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

call that prepare() does.

- -

 

- -

It doesn't do that for non-select statements so you could check = -if

- -

non-selects also have two parse calls.

- -

 

- -

Also try doing

- -

  $sth =3D $dbh->prepare(q(select key, fkey, value from = -t where -key=3D?), { ora_check_sql=3D> 0 });

- -

 

- -

which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till = -after the

- -

main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

is possibly redundant and could be removed (but Oracle ought to = -detect -that

- -

anyway and not make a round-trip for it, and certainly not call = -parse).

- -

 

- -

If non-selects only have one parse call but = -ora_check_sql=3D>0 doesn't

- -

fix selects, then I might be able to do a simple patch to avoid = -the

- -

OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if = -ora_check_sql=3D>0.

- -

 

- -

Then the issue will be: should ora_check_sql=3D>0 be the = -default...

- -

 

- -

Tim.

- -

 

- -

p.s. I'd love a copy of your book when it's = -ready!

- -
- - - - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0-- - - -From cary.millsap@hotsos.com Fri Sep 13 21:17:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DKHhC12417 - for ; Fri, 13 Sep 2002 21:17:43 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 21:17:43 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031946929:20:18513:70; Fri, 13 Sep 2002 19:55:29 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2018248; 13 Sep 2002 19:55 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 7FC402C01F - for ; Fri, 13 Sep 2002 15:55:06 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 76A5E2BFE1 - for ; Fri, 13 Sep 2002 15:55:05 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DJt4n26736 - for ; Fri, 13 Sep 2002 14:55:04 -0500 -From: "Cary Millsap" -To: "Tim Bunce" -Subject: A little more data -Date: Fri, 13 Sep 2002 14:54:56 -0500 -Message-ID: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0203_01C25B35.89729F60" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4948 -Lines: 166 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -I hope this is helpful. I have noticed that I cannot produce the -extra-parse problem on my 8.1.7 laptop database, no matter what the -setting of ora_check_sql. All of the data I've sent you is from our -8.1.6 Linux database. If you really needed it, I could produce level-9 -DBI trace data from identical tests on both platforms, but I won't spend -the time doing that unless you say it will help... - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - - - - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

I hope this is helpful… I have noticed that I = -cannot -produce the extra-parse problem on my 8.1.7 laptop database, no matter = -what the -setting of ora_check_sql. All of the data I’ve sent you is from = -our 8.1.6 -Linux database. If you really needed it, I could produce level-9 DBI = -trace data -from identical tests on both platforms, but I won’t spend the time = -doing -that unless you say it will help...

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -

 

- -
- - - - - -------=_NextPart_000_0203_01C25B35.89729F60-- - - -From timbo@dansat.data-plan.com Fri Sep 13 22:05:30 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL5UC12942 - for ; Fri, 13 Sep 2002 22:05:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:05:30 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031948458:10:20432:5; Fri, 13 Sep 2002 20:20:58 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-1.mail.demon.net - id aa1020174; 13 Sep 2002 20:20 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 8A60E3E659 - for ; Fri, 13 Sep 2002 16:20:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id CAC663E685 - for ; Fri, 13 Sep 2002 16:20:36 -0400 (EDT) -Received: (qmail 37861 messnum 258096 invoked from network[159.134.164.124/p124.as1.limerick1.eircom.net]); 13 Sep 2002 20:20:35 -0000 -Received: from p124.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.124) - by mail05.svc.cra.dublin.eircom.net (qp 37861) with SMTP; 13 Sep 2002 20:20:35 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DKKhu12535; - Fri, 13 Sep 2002 21:20:43 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 21:20:43 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data -Message-ID: <20020913202043.GO539@dansat.data-plan.com> -References: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1098 -Lines: 34 - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - -From cary.millsap@hotsos.com Fri Sep 13 22:04:47 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL4kC12684 - for ; Fri, 13 Sep 2002 22:04:46 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:04:46 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031949629:20:13745:23; Fri, 13 Sep 2002 20:40:29 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2013849; 13 Sep 2002 20:40 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 7D90A3E650 - for ; Fri, 13 Sep 2002 16:40:20 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-1.pobox.com (Postfix) with ESMTP id 785AB3E642 - for ; Fri, 13 Sep 2002 16:40:19 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DKeIn27106 - for ; Fri, 13 Sep 2002 15:40:18 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: A little more data -Date: Fri, 13 Sep 2002 15:40:10 -0500 -Message-ID: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913202043.GO539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 1999 -Lines: 63 - -Well, it's 1.06 on my Windows machine (the most up-to-date version -available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -but interesting that (admitting now that there's a new degree of freedom -running loose amid the test) "the older version performs better than the -newer one." :) That's certainly not a fair statement if the diff between -8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:21 PM -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't -spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:32 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLWC13692 - for ; Fri, 13 Sep 2002 23:21:32 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:32 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031952887:10:13297:20; Fri, 13 Sep 2002 21:34:47 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1118141; 13 Sep 2002 21:34 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C7D482BF23 - for ; Fri, 13 Sep 2002 17:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail00.svc.cra.dublin.eircom.net (mail00.svc.cra.dublin.eircom.net [159.134.118.16]) - by dolly1.pobox.com (Postfix) with SMTP id 8352A2BF6C - for ; Fri, 13 Sep 2002 17:34:36 -0400 (EDT) -Received: (qmail 5093 messnum 521124 invoked from network[159.134.164.134/p134.as1.limerick1.eircom.net]); 13 Sep 2002 21:34:34 -0000 -Received: from p134.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.134) - by mail00.svc.cra.dublin.eircom.net (qp 5093) with SMTP; 13 Sep 2002 21:34:34 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DLYeI13070; - Fri, 13 Sep 2002 22:34:40 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:34:40 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: A little more data -Message-ID: <20020913213440.GS539@dansat.data-plan.com> -References: <20020913202043.GO539@dansat.data-plan.com> <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 2282 -Lines: 69 - -According my RCS the default for ora_check_sql changed from 0 to 1 -around version 1.03. - -Tim. - -On Fri, Sep 13, 2002 at 03:40:10PM -0500, Cary Millsap wrote: -> Well, it's 1.06 on my Windows machine (the most up-to-date version -> available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -> but interesting that (admitting now that there's a new degree of freedom -> running loose amid the test) "the older version performs better than the -> newer one." :) That's certainly not a fair statement if the diff between -> 8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Friday, September 13, 2002 3:21 PM -> To: Cary Millsap -> Cc: Tim Bunce -> Subject: Re: A little more data -> -> If they're using the same version of DBD::Oracle then -> the change must me on the sever side. Maybe Oracle's -> woken up to the fact they don't need a second parse! -> -> Tim. -> -> On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > -> > -> > I hope this is helpful. I have noticed that I cannot produce the -> > extra-parse problem on my 8.1.7 laptop database, no matter what the -> > setting of ora_check_sql. All of the data I've sent you is from our -> > 8.1.6 Linux database. If you really needed it, I could produce level-9 -> > DBI trace data from identical tests on both platforms, but I won't -> spend -> > the time doing that unless you say it will help... -> > -> > -> > -> > Cary Millsap -> > Hotsos Enterprises, Ltd. -> > http://www.hotsos.com -> > -> > Upcoming events: -> > - Hotsos Clinic , Oct 1-3 San -> > Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> > - 2003 Hotsos Symposium on -> > OracleR System Performance, Feb 9-12 Dallas -> > - Next event: Miracle Database Forum , Sep -> > 20-22 Middlefart Denmark -> > -> > -> > -> - diff --git a/err_unsorted/err_xml.msg b/err_unsorted/err_xml.msg deleted file mode 100644 index 7a60a0cb..00000000 --- a/err_unsorted/err_xml.msg +++ /dev/null @@ -1,118 +0,0 @@ -From dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org Fri Aug 15 14:41:14 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h7FDe3MA043557 - for ; Fri, 15 Aug 2003 14:41:13 +0100 (BST) - (envelope-from dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 15 Aug 2003 14:41:13 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 19nc4X-0006LQ-BC; - Fri, 15 Aug 2003 10:44:41 +0000 -Received: from [207.106.49.22] (helo=dolly1.pobox.com) - by punt-3.mail.demon.net with esmtp id 19nc4X-0006LQ-BC - for pobox@dbi.demon.co.uk; Fri, 15 Aug 2003 10:44:41 +0000 -Received: from dolly1.pobox.com (localhost[127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 16F6B21C13B - for ; Fri, 15 Aug 2003 06:44:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.develooper.com[63.251.223.166]) - by dolly1.pobox.com (Postfix) with SMTP id 021F121C36F - for ; Fri, 15 Aug 2003 06:44:40 -0400 (EDT) -Received: (qmail 78180 invoked by uid 1005); 15 Aug 2003 10:44:34 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 71287 invoked by uid 76); 15 Aug 2003 10:32:13 -0000 -Delivered-To: dbi-users@perl.org -Received-SPF: unknown (domain of sender andyhassall@yahoo.com does not designate mailers: NXDOMAIN) -Message-ID: <20030815103200.24313.qmail@web9605.mail.yahoo.com> -Date: Fri, 15 Aug 2003 11:32:00 +0100 (BST) -From: =?iso-8859-1?q?Andy=20Hassall?= -Reply-To: andy@andyh.co.uk -Subject: Re: ERROR OCIDefineObject call needed but not implemented yet using XMLElement function -To: Susan Cassidy , dbi-users@perl.org -In-Reply-To: -MIME-Version: 1.0 -Content-Type: text/plain; charset=iso-8859-1 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.8 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,SPAM_PHRASE_01_02 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id h7FDe3MA043557 -Status: RO -Content-Length: 2299 -Lines: 65 - - --- Susan Cassidy wrote: > I am using DBD::Oracle. -I was on version 1.12, then I installed version -> 1.14, with the same result. -> -> This is Oracle 9.2.0. -> -> I have this select statement that works fine from SQL*Plus: -> -> select XMLElement("Sequences", -> XMLElement("Sequence", -> XMLATTRIBUTES ( b.local_name AS "ic-acckey", -> b.mol_type AS "molecule", -> n.seq_name AS "title"))) -> from gcg_bioseq b, gcg_annot_seq_name a, gcg_seq_name n -> where -> b.local_name = 'K00306' and -> b.seq_status = 'D' and -> b.seq_oid = a.seq_oid and -> a.seq_name_oid = n.seq_name_oid and -> n.name_type = 'LOCUS' -> -> -> When I run it via DBI/DBD I get this (trace level 2): -> -> DBI 1.32-nothread dispatch trace level set to 2 -> Note: perl is running without the recommended perl -w option -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x1b2314)~0x122bec ' -[snip -> Field 1 has an Oracle type (108) which is not explicitly supported -> fbh 1: -> -'XMLELEMENT("SEQUENCES",XMLELEMENT("SEQUENCE",XMLATTRIBUTES(B.LOCAL_NAMEAS"IC-ACCKEY",B.MOL_TYPEAS"MOLECULE",N.SEQ_NAMEAS"TITLE")))' -[snip] -> Error: prepare failed -> at line 56, error: ERROR OCIDefineObject call needed but not -> implemented yet -> -> Is there any other workaround for this than wrapping this up in a PL/SQL -> function? - - Don't rely on the implicit conversion to a string type that is done when -SQL*Plus displays an XMLElement; add .getClobVal() to the end of the -statement to retrieve it as a CLOB rather than the XMLElement object type -(which DBD::Oracle doesn't accept). - - i.e. - -select XMLElement("Sequences", - XMLElement("Sequence", - XMLATTRIBUTES ( b.local_name AS "ic-acckey", - b.mol_type AS "molecule", - n.seq_name AS "title"))).getClobVal() - from ... - - (or getStringVal() for a VARCHAR2) - -===== --- -Andy Hassall (andy@andyh.org) icq(5747695) http://www.andyh.co.uk -http://www.andyhsoftware.co.uk/space | disk usage analysis tool - -________________________________________________________________________ -Want to chat instantly with your online friends? Get the FREE Yahoo! -Messenger http://uk.messenger.yahoo.com/ - - diff --git a/err_unsorted/err_xml2.msg b/err_unsorted/err_xml2.msg deleted file mode 100644 index 3bb291c5..00000000 --- a/err_unsorted/err_xml2.msg +++ /dev/null @@ -1,700 +0,0 @@ -From dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org Fri Jan 30 12:50:15 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UClt3q069307 - for ; Fri, 30 Jan 2004 12:50:14 GMT - (envelope-from dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 12:50:14 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmWGJ-00057X-AG; - Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmWGJ-00057X-AG - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [207.8.214.3] (helo=puzzle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmWGI-0007XK-P3 - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:34 +0000 -Received: from puzzle.pobox.com (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 029E8701C6 - for ; Fri, 30 Jan 2004 05:52:34 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 12ABF701C1 - for ; Fri, 30 Jan 2004 05:52:30 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by puzzle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 05:51:10 -0500 (EST) -Received: (qmail 33345 invoked by uid 1005); 30 Jan 2004 10:50:36 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 33175 invoked by uid 76); 30 Jan 2004 10:50:26 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Fri, 30 Jan 2004 02:50:25 -0800 -Received: (qmail 21117 invoked by uid 225); 30 Jan 2004 10:48:52 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 21080 invoked by uid 507); 30 Jan 2004 10:48:49 -0000 -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Fri, 30 Jan 2004 02:48:46 -0800 -Received: (qmail 31958 invoked from network); 30 Jan 2004 11:50:38 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 30 Jan 2004 11:50:38 -0000 -Received: (qmail 6921 invoked from network); 30 Jan 2004 10:49:58 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 30 Jan 2004 10:49:58 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Fri, 30 Jan 2004 11:49:58 +0100 (CET) -Subject: DBD-Oracle and XMLType -From: Hendrik Fuss -To: "dbi-dev@perl.org" -Content-Type: multipart/mixed; boundary="=-fkyM33WAvQ5xV0uCPeSD" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 11:41:31 +0100 -Message-Id: <1075459292.7305.46.camel@mars> -Mime-Version: 1.0 -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.5 required=7.0 tests=MIME_LONG_LINE_QP,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01,TO_ADDRESS_EQ_REAL version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 8148 -Lines: 302 - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -Hi everyone, - -It's been a while since I last posted here. In September 2003 I was -trying to add support for binding XMLType objects to DBD-Oracle, so that -you could easily insert large (ie >4k) XML data into an XMLType table. - -Unfortunately my employer fired me in October 2003 and in the remaining -time I had to work on other projects, so I wasn't able to complete the -DBD project. Since I won't have access to an oracle database from now -on, I thought the least I can do is to provide my code as it is to the -list. Blame German economy. :-( - -The attached patch (based on DBD-Oracle 1.15) enables you to upload -XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -I added a function dbd_rebind_ph_nty for that purpose. You need to -create that XMLType object first using the C function -createxmlfromstring in xml.c. - -The XMLType object is either created from an OCIString or from a -temporary CLOB depending on the length of the source string. Have a look -at the bottom of ociap.h, all the (undocumented) XMLType functions are -there, and there are also some constants in oci.h. - -I'm not sure if the CLOB code currently works. - -Here is another code fragment: - - my $xml =3D createxml($dbh, 'Test document'); - my $sth =3D $dbh->prepare('INSERT INTO xml_type VALUES (?)'); - $sth->bind_param(1, $xml, { ora_type =3D> 108 }); # SQLT_NTY - $sth->execute(); - -Please note that this code is really just early development, which I -wouldn't publish under normal circumstances. :) I just hope it might me -useful to someone. - -Well then, time to say goodbye -thanks to Tim and everyone who contributed to dbi for a great piece of -software - -Cheers, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Description: -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - -151a152 -> case 108: /* SQLT_NTY */ -992a994,996 -> case SQL_UDT: -> return 108; /* Oracle NTY */ ->=20 -1004a1009,1072 -> static int -> dbd_rebind_ph_nty(sth, imp_sth, phs) -> SV* sth; -> imp_sth_t *imp_sth; -> phs_t *phs; -> { -> OCIType *tdo =3D NULL; -> sword status; -> SV* ptr; ->=20 -> if (phs->is_inout) -> croak("OUT binding for NTY is currently unsupported"); ->=20 -> /* ensure that the value is a support named object type */ -> /* (currently only OCIXMLType*) */ -> if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -> OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -> (CONST text*)"SYS", 3, -> (CONST text*)"XMLTYPE", 7, -> (CONST text*)0, 0, -> OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -> &tdo); ->=20 -> ptr =3D SvRV(phs->sv); -> phs->progv =3D (void*) SvIV(ptr); -> phs->maxlen =3D sizeof(OCIXMLType*); -> } -> else -> croak("Unsupported named object type for bind parameter"); ->=20 ->=20 -> /* bind by name */ ->=20 -> OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -> (text*)phs->name, (sb4)strlen(phs->name), -> (dvoid *) NULL, /* value supplied in BindObject later */ -> 0, -> (ub2)phs->ftype, 0, -> NULL, -> 0, 0, -> NULL, -> (ub4)OCI_DEFAULT, -> status -> ); ->=20 -> if (status !=3D OCI_SUCCESS) { -> oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -> return 0; -> } -> if (DBIS->debug >=3D 3) -> PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); ->=20 ->=20 -> /* bind the object */ ->=20 -> OCIBindObject(phs->bndhp, imp_sth->errhp, -> (CONST OCIType*)tdo, -> (dvoid **)&phs->progv, -> (ub4*)NULL, -> (dvoid **)NULL, -> (ub4*)NULL); ->=20 -> return 2; -> } -1309a1378,1380 -> case 108: -> done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -> break; -1331c1403 -< int at_exec =3D (phs->desc_h =3D=3D NULL); ---- -> int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); -1419c1491 -< if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) ---- -> if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQL= -T_NTY)) -1420a1493 -> /* ref allowed for OCIXMLType* */ -2219a2293 -> case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Disposition: attachment; filename=xml.c -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; name=xml.c; charset=ISO-8859-1 - -#include "oci.h" -#include - -/* This helper function creates an XMLType object from a string source. - * - * The resulting object can be bound to a placeholder, if ora_type =3D> - * SQLT_NTY is specified. - */ - -static void checkerr(errhp, status) -OCIError *errhp; -sword status; -{ - text errbuf[512]; - ub4 buflen; - sb4 errcode; - - switch (status) - { - case OCI_SUCCESS: - break; - case OCI_SUCCESS_WITH_INFO: - printf("Error - OCI_SUCCESS_WITH_INFO\n"); - break; - case OCI_NEED_DATA: - printf("Error - OCI_NEED_DATA\n"); - break; - case OCI_NO_DATA: - printf("Error - OCI_NO_DATA\n"); - break; - case OCI_ERROR: - OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, - errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR); - printf("Error - %s\n", errbuf); - exit(1); - break; - case OCI_INVALID_HANDLE: - printf("Error - OCI_INVALID_HANDLE\n"); - break; - case OCI_STILL_EXECUTING: - printf("Error - OCI_STILL_EXECUTE\n"); - break; - case OCI_CONTINUE: - printf("Error - OCI_CONTINUE\n"); - break; - default: - break; - } -} - - -#define MAX_OCISTRING_LEN 32766 - -SV* createxmlfromstring(SV* dbh, char* source) { - OCIXMLType *xml =3D NULL; - ub4 len; - ub1 src_type; - dvoid* src_ptr =3D NULL; - D_imp_dbh(dbh); - SV* sv_dest; - - len =3D strlen(source); - if(len > MAX_OCISTRING_LEN) { - src_type =3D OCI_XMLTYPE_CREATE_CLOB; - - printf("OCIDescriptorAlloc\n"); - checkerr( imp_dbh->errhp, - OCIDescriptorAlloc((dvoid*)imp_dbh->envhp, - (dvoid **)&src_ptr, - (ub4)OCI_DTYPE_LOB, - (size_t)0, - (dvoid**)0) ); - - printf("OCILobCreateTemporary\n"); - checkerr( imp_dbh->errhp, - OCILobCreateTemporary(imp_dbh->svchp, - imp_dbh->errhp,=20 - (OCILobLocator*) src_ptr, - (ub2)0,=20 - SQLCS_IMPLICIT,=20 - OCI_TEMP_CLOB,=20 - OCI_ATTR_NOCACHE,=20 - OCI_DURATION_SESSION) ); - - printf("OCILobWrite\n"); - checkerr (imp_dbh->errhp, - OCILobWriteAppend(imp_dbh->svchp, - imp_dbh->errhp, - (OCILobLocator*) src_ptr, - &len,=20 - (ub1*)source, - len, - OCI_ONE_PIECE, - (dvoid *)0,=20 - (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, - 0, - SQLCS_IMPLICIT)); - - } else { - src_type =3D OCI_XMLTYPE_CREATE_OCISTRING; - - printf("OCIStringAssignText\n"); - checkerr( imp_dbh->errhp, - OCIStringAssignText(imp_dbh->envhp, - imp_dbh->errhp,=20 - (CONST text*) source,=20 - (ub2) strlen(source), - (OCIString **) &src_ptr) - ); - } - - printf("OCIXMLTypeCreateFromSrc\n"); - checkerr( imp_dbh->errhp, - OCIXMLTypeCreateFromSrc(imp_dbh->svchp, - imp_dbh->errhp, - (OCIDuration)OCI_DURATION_CALLOUT, - (ub1)src_type, - (dvoid *)src_ptr, - (sb4)OCI_IND_NOTNULL, - &xml) - ); - - - /* free temporary resources */ - if( src_type =3D=3D OCI_XMLTYPE_CREATE_CLOB ) { - checkerr( imp_dbh->errhp, - OCILobFreeTemporary(imp_dbh->svchp, imp_dbh->errhp, - (OCILobLocator*) src_ptr) ); - - checkerr( imp_dbh->errhp, - OCIDescriptorFree((dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB) ); - } - - - sv_dest =3D newSViv(0); - sv_setref_pv(sv_dest, "OCIXMLTypePtr", xml); - return sv_dest; -} - ---=-fkyM33WAvQ5xV0uCPeSD-- - - - -From hendrik.fuss@morphochem.de Fri Jan 30 16:56:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UGsO3v071338 - for ; Fri, 30 Jan 2004 16:56:27 GMT - (envelope-from hendrik.fuss@morphochem.de) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 16:56:27 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmZJF-0001wN-DK; - Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmZJF-0001wN-DK - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmZJE-0003GM-Bm - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:48 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 334DE30C57 - for ; Fri, 30 Jan 2004 09:07:47 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id E65B230C2C - for ; Fri, 30 Jan 2004 09:07:45 -0500 (EST) -Received: from babel.morphochem.de (unknown [212.89.121.1]) - by boggle.pobox.com (Postfix) with ESMTP - for ; Fri, 30 Jan 2004 09:07:04 -0500 (EST) -Received: (qmail 29768 invoked from network); 30 Jan 2004 15:10:09 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) - by 212.89.121.1 with SMTP; 30 Jan 2004 15:10:09 -0000 -Received: (qmail 11736 invoked from network); 30 Jan 2004 14:09:30 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) - (envelope-sender ) - by localhost.morphochem.de (qmail-ldap-1.03) with SMTP - for ; 30 Jan 2004 14:09:30 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) - by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; - Fri, 30 Jan 2004 15:09:30 +0100 (CET) -Subject: Re: DBD-Oracle and XMLType -From: Hendrik Fuss -To: Tim Bunce -Cc: "dbi-dev@perl.org" -In-Reply-To: <20040130133443.GC70215@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> - <20040130133443.GC70215@dansat.data-plan.com> -Content-Type: multipart/mixed; boundary="=-Sq1IOPDEhKoqxUKefiS3" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 15:01:03 +0100 -Message-Id: <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Status: RO -X-Status: A -Content-Length: 5585 -Lines: 196 - - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -> > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.= -c -> > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > create that XMLType object first using the C function -> > createxmlfromstring in xml.c. ->=20 -> I there any chance you could post that as a context diff (diff -u ideally -> or else diff -c)? It's much safer and more useful. Thanks. - -Good idea. Here's a diff -u of dbdimp.c. - -By the way: I have thougt about general support of named types, not just -XMLType, but you need to get the type description (TDO) from somewhere. -My code just checks if the perl variable is a blessed reference of -"OCIXMLTypePtr". - -Also note that my code can't handle downloading of XMLType objects yet. - -best wishes, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Description: Context diff for dbdimp.c -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - ---- dbdimp.c.orig 2004-01-30 14:48:55.000000000 +0100 -+++ dbdimp.c 2003-10-07 12:17:17.000000000 +0200 -@@ -1,5 +1,5 @@ - /* -- $Id: dbdimp.c,v 1.1.1.1 2003/10/02 10:45:20 hfuss Exp $ -+ $Id: dbdimp.c,v 1.3 2003/10/07 10:17:17 hfuss Exp $ -=20 - Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce -=20 -@@ -149,6 +149,7 @@ - case 97: /* CHARZ */ - case 106: /* MLSLABEL */ - case 102: /* SQLT_CUR OCI 7 cursor variable */ -+ case 108: /* SQLT_NTY */ - case 112: /* SQLT_CLOB / long */ - case 113: /* SQLT_BLOB / long */ - case 116: /* SQLT_RSET OCI 8 cursor variable */ -@@ -990,6 +991,9 @@ - case SQL_LONGVARCHAR: - return 8; /* Oracle LONG */ -=20 -+ case SQL_UDT: -+ return 108; /* Oracle NTY */ -+ - case SQL_DATE: - case SQL_TIME: - case SQL_TIMESTAMP: -@@ -1002,6 +1006,70 @@ - } -=20 -=20 -+static int -+dbd_rebind_ph_nty(sth, imp_sth, phs) -+ SV* sth; -+ imp_sth_t *imp_sth; -+ phs_t *phs; -+{ -+ OCIType *tdo =3D NULL; -+ sword status; -+ SV* ptr; -+ -+ if (phs->is_inout) -+ croak("OUT binding for NTY is currently unsupported"); -+ -+ /* ensure that the value is a support named object type */ -+ /* (currently only OCIXMLType*) */ -+ if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -+ OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -+ (CONST text*)"SYS", 3, -+ (CONST text*)"XMLTYPE", 7, -+ (CONST text*)0, 0, -+ OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -+ &tdo); -+ -+ ptr =3D SvRV(phs->sv); -+ phs->progv =3D (void*) SvIV(ptr); -+ phs->maxlen =3D sizeof(OCIXMLType*); -+ } -+ else -+ croak("Unsupported named object type for bind parameter"); -+ -+ -+ /* bind by name */ -+ -+ OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -+ (text*)phs->name, (sb4)strlen(phs->name), -+ (dvoid *) NULL, /* value supplied in BindObject later */ -+ 0, -+ (ub2)phs->ftype, 0, -+ NULL, -+ 0, 0, -+ NULL, -+ (ub4)OCI_DEFAULT, -+ status -+ ); -+ -+ if (status !=3D OCI_SUCCESS) { -+ oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -+ return 0; -+ } -+ if (DBIS->debug >=3D 3) -+ PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); -+ -+ -+ /* bind the object */ -+ -+ OCIBindObject(phs->bndhp, imp_sth->errhp, -+ (CONST OCIType*)tdo, -+ (dvoid **)&phs->progv, -+ (ub4*)NULL, -+ (dvoid **)NULL, -+ (ub4*)NULL); -+ -+ return 2; -+} -=20 - static int=20 - dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr)=20 -@@ -1307,6 +1375,9 @@ - case SQLT_RSET: - done =3D dbd_rebind_ph_rset(sth, imp_sth, phs); - break; -+ case 108: -+ done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -+ break; - #else - case 102: /* SQLT_CUR */ - done =3D dbd_rebind_ph_cursor(sth, imp_sth, phs); -@@ -1315,6 +1386,7 @@ - default: - done =3D dbd_rebind_ph_char(sth, imp_sth, phs, &alen_ptr); - } -+ - if (done !=3D 1) { - if (done =3D=3D 2) { /* the rebind did the OCI bind call itself successfu= -lly */ - if (DBIS->debug >=3D 3) -@@ -1328,7 +1400,7 @@ - #ifdef OCI_V8_SYNTAX - if (phs->maxlen > phs->maxlen_bound) { - sword status; -- int at_exec =3D (phs->desc_h =3D=3D NULL); -+ int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, (sb4)strlen(phs->name), - phs->progv, -@@ -1416,8 +1488,9 @@ - } - assert(name !=3D Nullch); -=20 -- if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) -+ if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQLT= -_NTY)) - /* dbi handle allowed for cursor variables */ -+ /* ref allowed for OCIXMLType* */ - croak("Can't bind a reference (%s)", neatsvpv(newvalue,0)); - if (SvTYPE(newvalue) > SVt_PVLV) /* hook for later array logic? */ - croak("Can't bind a non-scalar value (%s)", neatsvpv(newvalue,0)); -@@ -2217,6 +2290,7 @@ - #ifdef OCI_V8_SYNTAX - case SQLT_CLOB: sql_fbh.dbtype =3D SQL_CLOB; break; - case SQLT_BLOB: sql_fbh.dbtype =3D SQL_BLOB; break; -+ case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - #endif - #ifdef SQLT_TIMESTAMP_TZ - case SQLT_TIMESTAMP_TZ: sql_fbh.dbtype =3D SQL_TIMESTAMP; break; - ---=-Sq1IOPDEhKoqxUKefiS3-- - - - -From timbo@dansat.data-plan.com Fri Jan 30 18:32:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UIVK3f073353 - for ; Fri, 30 Jan 2004 18:32:30 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 18:32:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmceP-000603-GP; - Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmceP-000603-GP - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [208.210.124.73] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1AmceO-0006dQ-DB - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:52 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 25AEA3F13D - for ; Fri, 30 Jan 2004 12:41:51 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9FB863F16E - for ; Fri, 30 Jan 2004 12:41:49 -0500 (EST) -Received: from mail09.svc.cra.dublin.eircom.net (mail09.svc.cra.dublin.eircom.net [159.134.118.25]) - by icicle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 12:41:11 -0500 (EST) -Received: (qmail 9504 messnum 226571 invoked from network[213.94.228.233/unknown]); 30 Jan 2004 17:40:43 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail09.svc.cra.dublin.eircom.net (qp 9504) with SMTP; 30 Jan 2004 17:40:43 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UHf33A072739; - Fri, 30 Jan 2004 17:41:03 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i0UHf2Wr072738; - Fri, 30 Jan 2004 17:41:02 GMT -Date: Fri, 30 Jan 2004 17:41:02 +0000 -From: Tim Bunce -To: Hendrik Fuss -Cc: Tim Bunce , "dbi-dev@perl.org" -Subject: Re: DBD-Oracle and XMLType -Message-ID: <20040130174102.GB72657@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> <20040130133443.GC70215@dansat.data-plan.com> <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <1075471263.7305.73.camel@mars> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1129 -Lines: 29 - -On Fri, Jan 30, 2004 at 03:01:03PM +0100, Hendrik Fuss wrote: -> > > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -> > > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > > create that XMLType object first using the C function -> > > createxmlfromstring in xml.c. -> > -> > I there any chance you could post that as a context diff (diff -u ideally -> > or else diff -c)? It's much safer and more useful. Thanks. -> -> Good idea. Here's a diff -u of dbdimp.c. - -Thanks. - -> By the way: I have thougt about general support of named types, not just -> XMLType, but you need to get the type description (TDO) from somewhere. -> My code just checks if the perl variable is a blessed reference of -> "OCIXMLTypePtr". - -Doing the equivalent of m/^OCI(\w+)Ptr$/ and then calling OCITypeByName -with $1 uppercased might take us (or someone) a step further. - -> Also note that my code can't handle downloading of XMLType objects yet. - -I'll trust that some kind soul with an itch will send a patch :-) - -Thanks again Hendrik. - -Tim. - diff --git a/err_unsorted/err_xmltypebindplsql.msg b/err_unsorted/err_xmltypebindplsql.msg deleted file mode 100644 index 08faa725..00000000 --- a/err_unsorted/err_xmltypebindplsql.msg +++ /dev/null @@ -1,174 +0,0 @@ -From dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org Thu Apr 25 11:02:42 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3PA2gK34525 - for ; Thu, 25 Apr 2002 11:02:42 +0100 (BST) - (envelope-from dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 25 Apr 2002 11:02:42 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1019721492:10:18778:60; Thu, 25 Apr 2002 07:58:12 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1109782; 25 Apr 2002 7:58 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 791692BF11 - for ; Thu, 25 Apr 2002 03:58:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id 976FB2BEE4 - for ; Thu, 25 Apr 2002 03:58:07 -0400 (EDT) -Received: (qmail 84467 invoked by uid 1005); 25 Apr 2002 07:58:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 77923 invoked by uid 76); 24 Apr 2002 23:08:56 -0000 -Date: Wed, 24 Apr 2002 19:08:54 -0400 -From: Mark Stillwell -To: dbi-users-help@perl.org, dbi-users@perl.org -Subject: Oracle 9 XMLTYPE insert -Message-ID: <20020424190852.C22854@byrd.biostat.ufl.edu> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -Status: RO -Content-Length: 1469 -Lines: 43 - -I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -Here is my problem, I have a table named 'test' with three fields: eid -(integer), x (SYS.XMLTYPE) and formname (text) - -I create a database handler and connect to the database just fine. - -I create a new statement handler with the following command: - -$sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -SYS.XMLTYPE.CREATEXML(?), ?"); - -I loop over some data, $eid gets and integer, $xmlvalue gets a string, -and $formname gets a string. So long as $xmlvalue is relatively short -$sth->execute($eid, $xmlvalue, $formname); works great, but as soon as -it becomes long enough to force the use of clob's I have a problem. - -So I tried the following: - -$sth->bind_param(1, $i); -$sth->bind_param(2, $xmlvalue, { ora_type => ORA_CLOB }); -$sth->bind_param(3, $intable); -$sth->execute; - -This works great if column 'x' is a normal CLOB and I omit the -sys.xmltype.createxml statement above, but when 'x' is of type -sys.xmltype I get the following error: - -nvalid LOB locator specified -ORA-06512: at "SYS.XMLTYPE", line 0 - -Right now I've hacked the setup so there is a supplemental table called -'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE test SET x -= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem like the -right way to do this. - -Is there any way to do what I want in the current version of -DBI/OracleDBD? - --- -Mark Stillwell -marklee@ufl.edu -http://plaza.ufl.edu/marklee/ - -From dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org Wed May 8 16:11:46 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g48FBjo24814 - for ; Wed, 8 May 2002 16:11:45 +0100 (BST) - (envelope-from dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 08 May 2002 16:11:45 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020870336:20:08175:2; Wed, 08 May 2002 15:05:36 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2109147; 8 May 2002 15:05 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id 68FE23E6D4 - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-3.pobox.com (Postfix) with SMTP id 33A783E64D - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Received: (qmail 65232 invoked by uid 1005); 8 May 2002 15:01:47 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 60079 invoked by uid 76); 8 May 2002 14:50:53 -0000 -From: "Ben Middleton" -To: -Cc: -Subject: Re: Oracle 9 XMLTYPE insert -Date: Wed, 8 May 2002 15:50:47 +0100 -Message-ID: -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0) -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -Content-Length: 1311 -Lines: 39 - -Hi. - -Not sure if you ever resolved this: - -> I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -> Here is my problem, I have a table named 'test' with three fields: -> eid (integer), x (SYS.XMLTYPE) and formname (text) - -> I create a new statement handler with the following command: - -> $sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -> SYS.XMLTYPE.CREATEXML(?), ?"); - -.... - -> Invalid LOB locator specified -> ORA-06512: at "SYS.XMLTYPE", line 0 - -> Right now I've hacked the setup so there is a supplemental table -> called 'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE -> test SET x= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem -> like the right way to do this. - -> Is there any way to do what I want in the current version of -> DBI/OracleDBD? - -I don't think that the current DBI/DBD can bind a CLOB to a PL/SQL function -(which is all the CREATEXML function is) - hence you will have to go with -the intermediate CLOB table solution. - -Incidentally, if you are using Oracle9i - have you tried using a TEMPORARY -TABLE with a CLOB column (see SQL Reference Guide)? If setup correctly, this -is automatically truncated at the end of a transaction, is managed by the -Server, and provides some efficiency benefits. We use this here quite -effectively. - -Ben. - - diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index cd863cd9..9e610a68 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -11,6 +11,12 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; +{ + $DBD::Oracle::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Oracle database driver for the DBI module use DBI (); @@ -109,7 +115,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::dr; # ====== DRIVER ====== +{ package DBD::Oracle::dr; +{ + $DBD::Oracle::dr::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DRIVER ====== use strict; my %dbnames = (); # holds list of known databases (oratab + tnsnames) @@ -308,7 +320,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::db; # ====== DATABASE ====== +{ package DBD::Oracle::db; +{ + $DBD::Oracle::db::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DATABASE ====== use strict; use DBI qw(:sql_types); @@ -1000,7 +1018,13 @@ SQL } # end of package DBD::Oracle::db -{ package DBD::Oracle::st; # ====== STATEMENT ====== +{ package DBD::Oracle::st; +{ + $DBD::Oracle::st::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== STATEMENT ====== sub bind_param_inout_array { @@ -1094,9 +1118,18 @@ SQL 1; -__END__ +=pod + +=head1 NAME + +DBD::Oracle - Oracle database driver for the DBI module + +=head1 VERSION + +version 1.38 + =head1 SYNOPSIS use DBI; @@ -1110,7 +1143,6 @@ __END__ # for some advanced uses you may need Oracle type values: use DBD::Oracle qw(:ora_types); - =head1 DESCRIPTION DBD::Oracle is a Perl module which works with the DBI module to provide @@ -1218,7 +1250,6 @@ If port name is not specified, 1521 is the default. If service name is not speci The following examples show several ways a connection can be created: - $dbh = DBI->connect('dbi:Oracle:DB','username','password'); $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); @@ -1549,7 +1580,6 @@ DBDOxxxx where xxxx is the current version number. This value can be retrieved on the server side using V$SESSION_CONNECT_INFO or GV$SESSION_CONNECT_INFO - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); $dbh->{ora_driver_name} = $q; @@ -1720,7 +1750,6 @@ If the previous error was from a failed C due to a syntax error, this attribute gives the offset into the C attribute where the error was found. - =head4 ora_array_chunk_size Due to OCI limitations, DBD::Oracle needs to buffer up rows of @@ -1943,7 +1972,6 @@ DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. Starts a new session against the current database using the credentials supplied. - =head2 B $hashref = $dbh->private_attribute_info(); @@ -2071,7 +2099,6 @@ Implemented by DBI, no driver-specific impact. Implemented by DBI, no driver-specific impact. - =head2 B Type: boolean, inherited @@ -2080,7 +2107,6 @@ The CompatMode attribute is used by emulation layers (such as Oraperl) to enable It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. - =head1 ORACLE-SPECIFIC DATABASE HANDLE METHODS =head2 B @@ -2240,7 +2266,6 @@ The different types of placeholders cannot be mixed within a statement, but you use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. - =head2 B $sth = $dbh->prepare_cached($statement, \%attr); @@ -2259,7 +2284,6 @@ query was successful, returns undef if an error occurred, and returns -1 if the number of rows is unknown or not available. Note that this method will return B<0E0> instead of 0 for 'no rows were affected', in order to always return a true value if no error occurred. - =head2 B Oracle does not implement auto_increment of serial type columns it uses predefined @@ -2315,7 +2339,6 @@ If the script exits before disconnect is called (or, more precisely, if the data referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() methods automatically. It is best to explicitly disconnect rather than rely on this behavior. - =head2 B $rv = $dbh->ping; @@ -2664,7 +2687,6 @@ Examples: ## This executes the statement with 567 (integer) and "Zool" (varchar) $sth->execute(); - These attributes may be used in the C<\%attr> parameter of the L or L statement handle methods. @@ -2759,10 +2781,8 @@ Set L to 0 in prepare() to enable this behaviour. $rv = $sth->bind_param_inout($param_num, \$scalar, 0); - DBD::Oracle fully supports bind_param_inout below are some uses for this method. - =head3 B Oracle supports an extended SQL insert syntax which will return one @@ -2936,10 +2956,6 @@ the above example, the code would look something like this : ... } - - - - =head3 B DBD::Oracle has built-in support for B @@ -2974,13 +2990,11 @@ and B datatypes. The simple example is here: =item B -=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' +=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' will only take a reference to a scalar. =back - - =head3 B SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. @@ -3089,7 +3103,6 @@ you get: DBD::Oracle supports this undocumented feature of DBI. See L for an example. - =head2 B $rv = $sth->bind_param_array($param_num, $array_ref_or_value) @@ -3099,8 +3112,6 @@ DBD::Oracle supports this undocumented feature of DBI. See L method. - - =head2 B $rv = $sth->execute(@bind_values); @@ -3367,7 +3378,6 @@ However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch Only use scrollable cursors if you really have a good reason to. They do use up considerable more server and client resources and have poorer response times than non-scrolling cursors. - =head2 Enabling Scrollable Cursors To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; @@ -3383,7 +3393,6 @@ When the statement is executed you will then be able to use 'ora_fetch_scroll' m or you can still use any of the other fetch methods but with a poorer response time than if you used a non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. - =head2 Scrollable Cursor Methods The following driver-specific methods are used with scrollable cursors. @@ -3723,7 +3732,6 @@ You can tune this value by setting ora_oci_success_warn which will display the f In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. - =head3 Simple Fetch for CLOBs and BLOBs To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well @@ -4125,7 +4133,6 @@ Uses the Oracle OCILobTrim function. Returns the length of the LOB. Uses the Oracle OCILobGetLength function. - =item ora_lob_is_init $is_init = $dbh->ora_lob_is_init($lob_locator); @@ -4172,7 +4179,6 @@ lob_id field values, defined as follows: CREATE SEQUENCE lob_example_seq - =head3 Example: Inserting a new row with large data Unless enough memory is available to store and bind the @@ -4238,7 +4244,6 @@ can't be used effectively if AutoCommit is enabled). $offset += $length; } - In this example we demonstrate the use of ora_lob_write() interactively to append data to the columns 'bin_data' and 'char_data'. Had we used ora_lob_append(), we could have @@ -4255,7 +4260,6 @@ The scalar variables $offset and $length are no longer needed, because ora_lob_append() keeps track of the offset for us. - =head3 Example: Updating an existing row with large data In this example, we demonstrate a technique for overwriting @@ -4440,7 +4444,6 @@ WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other than US7ASCII, requires that the NLS_LANG environment variable be set. See the L<"Oracle UTF8 is not UTF-8"> section below. - You are strongly urged to read the Oracle Internationalization documentation specifically with respect the choices and trade offs for creating a databases for use with international character sets. @@ -4547,7 +4550,6 @@ If the C attribute is given to bind_param() then that determines if the value should be assumed to be in the default (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); ... $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); @@ -4588,7 +4590,6 @@ and TABLE in any combination. Support is seamless and recursive, meaning you need only supply a simple SQL statement to get all the values in an embedded object. You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. - Array example, given this type and table; CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); @@ -4741,7 +4742,6 @@ There are some types, like BOOLEAN, that Oracle does not automatically convert to or from strings (pity). These need to be converted explicitly using SQL or PL/SQL functions. - Examples: # DATE values @@ -4796,7 +4796,6 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" - =head4 Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special @@ -4944,7 +4943,6 @@ shows: } } - The cursor returned by the function C defined in the previous section can be fetched as a nested cursor as follows: @@ -5325,7 +5323,6 @@ There is a known problem with the 11.2g Oracle client and the C PL/SQL function. See L for the details. - =head1 SEE ALSO =over @@ -5393,4 +5390,34 @@ The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. The DBD::Oracle module is free open source software; you can redistribute it and/or modify it under the same terms as Perl 5. +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + + +__END__ + + diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index b1c088e3..29ba9b1c 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,4 +1,11 @@ package DBD::Oracle::GetInfo; +{ + $DBD::Oracle::GetInfo::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; +} +# ABSTRACT: Wrapper to get Oracle information use strict; use DBD::Oracle(); @@ -314,4 +321,44 @@ our %info = ( 1; + + +=pod + +=head1 NAME + +DBD::Oracle::GetInfo - Wrapper to get Oracle information + +=head1 VERSION + +version 1.38 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + + __END__ diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 39a99498..f7a4850f 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,25 +1,70 @@ -package DBD::Oracle::Object; -# ABSTRACT: Wrapper for Oracle objects - -use strict; -use warnings; - -sub type_name { shift->{type_name} } - -sub attributes { @{shift->{attributes}} } - -sub attr_hash { - my $self = shift; - return $self->{attr_hash} ||= { $self->attributes }; -} - -sub attr { - my $self = shift; - if (@_) { - my $key = shift; - return $self->attr_hash->{$key}; - } - return $self->attr_hash; -} - -1; +package DBD::Oracle::Object; +{ + $DBD::Oracle::Object::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; +} +# ABSTRACT: Wrapper for Oracle objects + +use strict; +use warnings; + +sub type_name { shift->{type_name} } + +sub attributes { @{shift->{attributes}} } + +sub attr_hash { + my $self = shift; + return $self->{attr_hash} ||= { $self->attributes }; +} + +sub attr { + my $self = shift; + if (@_) { + my $key = shift; + return $self->attr_hash->{$key}; + } + return $self->attr_hash; +} + +1; + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Object - Wrapper for Oracle objects + +=head1 VERSION + +version 1.38 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 24855d20..c3c4b40a 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,8 +1,24 @@ package DBD::Oracle::Troubleshooting; +{ + $DBD::Oracle::Troubleshooting::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; +} #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle + +__END__ =pod +=head1 NAME + +DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle + +=head1 VERSION + +version 1.38 + =head1 CONNECTING TO ORACLE If you are reading this it is assumed that you have successfully @@ -29,7 +45,6 @@ For Windows the solution is to add this value to you PATH PATH=c:\app\oracle\product\xx.x.x;%PATH% - If you get past this stage and get a ORA-12154: TNS:could not resolve the connect identifier specified @@ -61,7 +76,6 @@ Protocol Adapter". If it generates any errors which look relevant then please talk to your Oracle technical support (and not the dbi-users mailing list). - =head1 USING THE LONG TYPES Some examples related to the use of LONG types are available in @@ -96,7 +110,6 @@ It turns out that now it is necessary to edit the same file and append this and then run "genclntsh", the libclntsh is properly generated and the linkage with DBD::Oracle proceeds properly. - =head2 cc1: invalid option `tune=pentium4'" error If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. @@ -153,7 +166,7 @@ To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY as you would for an install against 10g Standard Edition, Standard Edition One, or Enterprise Edition -=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 +=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 DBD::Oracle seems to hit some sort of bug with the above two versions of DB. The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also @@ -172,7 +185,6 @@ So far there is no patch for this but here are some work arounds or this way utf8::downgrade($parameter, 1); - =head1 CYGWIN @@ -335,4 +347,30 @@ oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + diff --git a/t/000-report-versions.t b/t/000-report-versions.t new file mode 100644 index 00000000..2d4a9a19 --- /dev/null +++ b/t/000-report-versions.t @@ -0,0 +1,446 @@ +#!perl +use warnings; +use strict; +use Test::More 0.94; + +# Include a cut-down version of YAML::Tiny so we don't introduce unnecessary +# dependencies ourselves. + +package Local::YAML::Tiny; + +use strict; +use Carp 'croak'; + +# UTF Support? +sub HAVE_UTF8 () { $] >= 5.007003 } +BEGIN { + if ( HAVE_UTF8 ) { + # The string eval helps hide this from Test::MinimumVersion + eval "require utf8;"; + die "Failed to load UTF-8 support" if $@; + } + + # Class structure + require 5.004; + $YAML::Tiny::VERSION = '1.40'; + + # Error storage + $YAML::Tiny::errstr = ''; +} + +# Printable characters for escapes +my %UNESCAPES = ( + z => "\x00", a => "\x07", t => "\x09", + n => "\x0a", v => "\x0b", f => "\x0c", + r => "\x0d", e => "\x1b", '\\' => '\\', +); + + +##################################################################### +# Implementation + +# Create an empty YAML::Tiny object +sub new { + my $class = shift; + bless [ @_ ], $class; +} + +# Create an object from a file +sub read { + my $class = ref $_[0] ? ref shift : shift; + + # Check the file + my $file = shift or return $class->_error( 'You did not specify a file name' ); + return $class->_error( "File '$file' does not exist" ) unless -e $file; + return $class->_error( "'$file' is a directory, not a file" ) unless -f _; + return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; + + # Slurp in the file + local $/ = undef; + local *CFG; + unless ( open(CFG, $file) ) { + return $class->_error("Failed to open file '$file': $!"); + } + my $contents = ; + unless ( close(CFG) ) { + return $class->_error("Failed to close file '$file': $!"); + } + + $class->read_string( $contents ); +} + +# Create an object from a string +sub read_string { + my $class = ref $_[0] ? ref shift : shift; + my $self = bless [], $class; + my $string = $_[0]; + unless ( defined $string ) { + return $self->_error("Did not provide a string to load"); + } + + # Byte order marks + # NOTE: Keeping this here to educate maintainers + # my %BOM = ( + # "\357\273\277" => 'UTF-8', + # "\376\377" => 'UTF-16BE', + # "\377\376" => 'UTF-16LE', + # "\377\376\0\0" => 'UTF-32LE' + # "\0\0\376\377" => 'UTF-32BE', + # ); + if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) { + return $self->_error("Stream has a non UTF-8 BOM"); + } else { + # Strip UTF-8 bom if found, we'll just ignore it + $string =~ s/^\357\273\277//; + } + + # Try to decode as utf8 + utf8::decode($string) if HAVE_UTF8; + + # Check for some special cases + return $self unless length $string; + unless ( $string =~ /[\012\015]+\z/ ) { + return $self->_error("Stream does not end with newline character"); + } + + # Split the file into lines + my @lines = grep { ! /^\s*(?:\#.*)?\z/ } + split /(?:\015{1,2}\012|\015|\012)/, $string; + + # Strip the initial YAML header + @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; + + # A nibbling parser + while ( @lines ) { + # Do we have a document header? + if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { + # Handle scalar documents + shift @lines; + if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { + push @$self, $self->_read_scalar( "$1", [ undef ], \@lines ); + next; + } + } + + if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { + # A naked document + push @$self, undef; + while ( @lines and $lines[0] !~ /^---/ ) { + shift @lines; + } + + } elsif ( $lines[0] =~ /^\s*\-/ ) { + # An array at the root + my $document = [ ]; + push @$self, $document; + $self->_read_array( $document, [ 0 ], \@lines ); + + } elsif ( $lines[0] =~ /^(\s*)\S/ ) { + # A hash at the root + my $document = { }; + push @$self, $document; + $self->_read_hash( $document, [ length($1) ], \@lines ); + + } else { + croak("YAML::Tiny failed to classify the line '$lines[0]'"); + } + } + + $self; +} + +# Deparse a scalar string to the actual scalar +sub _read_scalar { + my ($self, $string, $indent, $lines) = @_; + + # Trim trailing whitespace + $string =~ s/\s*\z//; + + # Explitic null/undef + return undef if $string eq '~'; + + # Quotes + if ( $string =~ /^\'(.*?)\'\z/ ) { + return '' unless defined $1; + $string = $1; + $string =~ s/\'\'/\'/g; + return $string; + } + if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) { + # Reusing the variable is a little ugly, + # but avoids a new variable and a string copy. + $string = $1; + $string =~ s/\\"/"/g; + $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; + return $string; + } + + # Special cases + if ( $string =~ /^[\'\"!&]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + return {} if $string eq '{}'; + return [] if $string eq '[]'; + + # Regular unquoted string + return $string unless $string =~ /^[>|]/; + + # Error + croak("YAML::Tiny failed to find multi-line scalar content") unless @$lines; + + # Check the indent depth + $lines->[0] =~ /^(\s*)/; + $indent->[-1] = length("$1"); + if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Pull the lines + my @multiline = (); + while ( @$lines ) { + $lines->[0] =~ /^(\s*)/; + last unless length($1) >= $indent->[-1]; + push @multiline, substr(shift(@$lines), length($1)); + } + + my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; + my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; + return join( $j, @multiline ) . $t; +} + +# Parse an array +sub _read_array { + my ($self, $array, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { + # Inline nested hash + my $indent2 = length("$1"); + $lines->[0] =~ s/-/ /; + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { + # Array entry with a value + shift @$lines; + push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { + shift @$lines; + unless ( @$lines ) { + push @$array, undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)\-/ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] == $indent2 ) { + # Null array entry + push @$array, undef; + } else { + # Naked indenter + push @$array, [ ]; + $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines ); + } + + } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines ); + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + + } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { + # This is probably a structure like the following... + # --- + # foo: + # - list + # bar: value + # + # ... so lets return and let the hash parser handle it + return 1; + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + } + + return 1; +} + +# Parse an array +sub _read_hash { + my ($self, $hash, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Get the key + unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { + if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + my $key = $1; + + # Do we have a value? + if ( length $lines->[0] ) { + # Yes + $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines ); + } else { + # An indent + shift @$lines; + unless ( @$lines ) { + $hash->{$key} = undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)-/ ) { + $hash->{$key} = []; + $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } elsif ( $lines->[0] =~ /^(\s*)./ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] >= $indent2 ) { + # Null hash entry + $hash->{$key} = undef; + } else { + $hash->{$key} = {}; + $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } + } + } + } + + return 1; +} + +# Set error +sub _error { + $YAML::Tiny::errstr = $_[1]; + undef; +} + +# Retrieve error +sub errstr { + $YAML::Tiny::errstr; +} + + + +##################################################################### +# Use Scalar::Util if possible, otherwise emulate it + +BEGIN { + eval { + require Scalar::Util; + }; + if ( $@ ) { + # Failed to load Scalar::Util + eval <<'END_PERL'; +sub refaddr { + my $pkg = ref($_[0]) or return undef; + if (!!UNIVERSAL::can($_[0], 'can')) { + bless $_[0], 'Scalar::Util::Fake'; + } else { + $pkg = undef; + } + "$_[0]" =~ /0x(\w+)/; + my $i = do { local $^W; hex $1 }; + bless $_[0], $pkg if defined $pkg; + $i; +} +END_PERL + } else { + Scalar::Util->import('refaddr'); + } +} + + +##################################################################### +# main test +##################################################################### + +package main; + +BEGIN { + + # Skip modules that either don't want to be loaded directly, such as + # Module::Install, or that mess with the test count, such as the Test::* + # modules listed here. + # + # Moose::Role conflicts if Moose is loaded as well, but Moose::Role is in + # the Moose distribution and it's certain that someone who uses + # Moose::Role also uses Moose somewhere, so if we disallow Moose::Role, + # we'll still get the relevant version number. + + my %skip = map { $_ => 1 } qw( + App::FatPacker + Class::Accessor::Classy + Devel::Cover + Module::Install + Moose::Role + POE::Loop::Tk + Template::Test + Test::Kwalitee + Test::Pod::Coverage + Test::Portability::Files + Test::YAML::Meta + ); + + my $Test = Test::Builder->new; + + $Test->plan(skip_all => "META.yml could not be found") + unless -f 'META.yml' and -r _; + + my $meta = (Local::YAML::Tiny->read('META.yml'))->[0]; + my %requires; + for my $require_key (grep { /requires/ } keys %$meta) { + my %h = %{ $meta->{$require_key} }; + $requires{$_}++ for keys %h; + } + delete $requires{perl}; + + diag("Testing with Perl $], $^X"); + for my $module (sort keys %requires) { + if ($skip{$module}) { + note "$module doesn't want to be loaded directly, skipping"; + next; + } + local $SIG{__WARN__} = sub { note "$module: $_[0]" }; + use_ok $module or BAIL_OUT("can't load $module"); + my $version = $module->VERSION; + $version = 'undefined' unless defined $version; + diag(" $module version is $version"); + } + done_testing; +} diff --git a/xt/changes.t b/xt/changes.t deleted file mode 100644 index 27a4808a..00000000 --- a/xt/changes.t +++ /dev/null @@ -1,8 +0,0 @@ -use strict; -use warnings; - -use Test::More; - -eval 'use Test::CPAN::Changes'; -plan skip_all => 'Test::CPAN::Changes required for this test' if $@; -changes_ok(); diff --git a/xt/manifest.t b/xt/manifest.t deleted file mode 100644 index 00df9957..00000000 --- a/xt/manifest.t +++ /dev/null @@ -1,21 +0,0 @@ -use strict; -use warnings; - -use ExtUtils::Manifest qw/ fullcheck /; - -use Test::More tests => 1; - -my ( $missing, $extra ) = do { - local *STDERR; - - # hush little baby, don't you cry - open STDERR, '>', \my $stderr; - - fullcheck(); -}; - -ok @$missing + @$extra == 0, 'manifest in sync' or do { - diag "missing files:\n", map { " \t $_\n " } @$missing if @$missing; - diag "extra files: \n", map { "\t$_\n" } @$extra if @$extra; -}; - diff --git a/xt/pod.t b/xt/pod.t deleted file mode 100644 index 66481225..00000000 --- a/xt/pod.t +++ /dev/null @@ -1,11 +0,0 @@ -use Test::More; - -eval "use Test::Pod"; - -plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; - -pod_file_ok( 'Oracle.pm' ); -pod_file_ok( 'lib/DBD/Oracle/Object.pm' ); -pod_file_ok( 'lib/DBD/Oracle/GetInfo.pm' ); - -done_testing; From 23a6005caff1f64860117da437c414dc0b3fcb22 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 2 Feb 2012 16:36:42 -0500 Subject: [PATCH 113/637] fix ::GetInfo NAME line --- Changes | 1 + lib/DBD/Oracle/GetInfo.pm | 1 + 2 files changed, 2 insertions(+) diff --git a/Changes b/Changes index dd8ddb41..dbd16803 100644 --- a/Changes +++ b/Changes @@ -11,6 +11,7 @@ Revision history for DBD::Oracle [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work on Lion. (Martin J. Evans) + - Fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt7400] [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index b1c088e3..43331655 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,4 +1,5 @@ package DBD::Oracle::GetInfo; +# ABSTRACT: Wrapper to get Oracle information use strict; use DBD::Oracle(); From 53f19454eac12b0b0150f7033e44148249359531 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 2 Feb 2012 16:42:32 -0500 Subject: [PATCH 114/637] typos --- Changes | 3 ++- lib/DBD/Oracle/Troubleshooting.pm | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index dbd16803..a5226ce2 100644 --- a/Changes +++ b/Changes @@ -11,7 +11,8 @@ Revision history for DBD::Oracle [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work on Lion. (Martin J. Evans) - - Fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt7400] + - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] + - fix typos. (patch by Julián Moreno Patiño) [rt73999] [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 24855d20..6e422308 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -292,11 +292,11 @@ in the first table in above list, and not as one would normally expect in the process table. Installing DBI and DBD::Oracle has influence upon this since in -both cases a few enviroment variables are read or set in the +both cases a few environment variables are read or set in the test phase. For DBI it is the logical SYS$SCRATCH, which is a JOB logical. For DBD-Oracle it is when testing a new feature in the Oracle -RDBMS: UTF8 and UTF16 character set functionallity, and in order +RDBMS: UTF8 and UTF16 character set functionality, and in order to do this it sets and unsets the related environment variables NLS_NCHAR and NLS_LANG. From 676c86fe6a3cfe1518987d19052d3eca9f876d74 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 2 Feb 2012 21:46:18 +0000 Subject: [PATCH 115/637] change for the modern /usr/bin/env perl git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15120 50811bd7-b8ce-0310-adc1-d9db26280581 --- examples/bind.pl | 2 +- examples/commit.pl | 2 +- examples/curref.pl | 2 +- examples/ex.pl | 2 +- examples/inserting_longs.pl | 2 +- examples/mktable.pl | 2 +- examples/oradump.pl | 2 +- examples/proc.pl | 2 +- examples/read_long_via_blob_read.pl | 2 +- examples/tabinfo.pl | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/bind.pl b/examples/bind.pl index 303d96be..1a4f71dd 100755 --- a/examples/bind.pl +++ b/examples/bind.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # bind.pl # diff --git a/examples/commit.pl b/examples/commit.pl index e6e0da3c..bef60655 100755 --- a/examples/commit.pl +++ b/examples/commit.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # commit.pl # diff --git a/examples/curref.pl b/examples/curref.pl index 5ecb0b32..3c464aa4 100755 --- a/examples/curref.pl +++ b/examples/curref.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # curref.pl - by Geoffrey Young # diff --git a/examples/ex.pl b/examples/ex.pl index 95ffa322..bd2016a4 100755 --- a/examples/ex.pl +++ b/examples/ex.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # Short example using bind_columns() to list a table's values use DBI; diff --git a/examples/inserting_longs.pl b/examples/inserting_longs.pl index 191a0c3d..056ce18a 100644 --- a/examples/inserting_longs.pl +++ b/examples/inserting_longs.pl @@ -1,4 +1,4 @@ -#!perl +#!/usr/bin/env perl use strict; use warnings; diff --git a/examples/mktable.pl b/examples/mktable.pl index 28d01007..570a16db 100755 --- a/examples/mktable.pl +++ b/examples/mktable.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # Sample DBI program to create a new table and load data into it. # # Author: Kevin Stock (original oraperl script) diff --git a/examples/oradump.pl b/examples/oradump.pl index 5477c569..5b1109cf 100755 --- a/examples/oradump.pl +++ b/examples/oradump.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # Dump the contents of an Oracle table into a set of insert statements. # Quoting is controlled by the datatypes of each column. (new with DBI) diff --git a/examples/proc.pl b/examples/proc.pl index a8a65a14..48dedec6 100755 --- a/examples/proc.pl +++ b/examples/proc.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # Short examples of procedure calls from Oracle.pm # These PL/SQL examples come from: Eric Bartley . diff --git a/examples/read_long_via_blob_read.pl b/examples/read_long_via_blob_read.pl index 70631d8d..d5a011ae 100644 --- a/examples/read_long_via_blob_read.pl +++ b/examples/read_long_via_blob_read.pl @@ -1,4 +1,4 @@ -#!perl +#!/usr/bin/env perl use strict; use warnings; diff --git a/examples/tabinfo.pl b/examples/tabinfo.pl index 307bd6b1..82c7f2ba 100755 --- a/examples/tabinfo.pl +++ b/examples/tabinfo.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # tabinfo # From 6622ad5059504039827f0072d2dda22ec6ecbb8c Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 2 Feb 2012 21:46:18 +0000 Subject: [PATCH 116/637] change for the modern /usr/bin/env perl git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15120 50811bd7-b8ce-0310-adc1-d9db26280581 --- examples/bind.pl | 2 +- examples/commit.pl | 2 +- examples/curref.pl | 2 +- examples/ex.pl | 2 +- examples/inserting_longs.pl | 2 +- examples/mktable.pl | 2 +- examples/oradump.pl | 2 +- examples/proc.pl | 2 +- examples/read_long_via_blob_read.pl | 2 +- examples/tabinfo.pl | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/bind.pl b/examples/bind.pl index 303d96be..1a4f71dd 100755 --- a/examples/bind.pl +++ b/examples/bind.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # bind.pl # diff --git a/examples/commit.pl b/examples/commit.pl index e6e0da3c..bef60655 100755 --- a/examples/commit.pl +++ b/examples/commit.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # commit.pl # diff --git a/examples/curref.pl b/examples/curref.pl index 5ecb0b32..3c464aa4 100755 --- a/examples/curref.pl +++ b/examples/curref.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # curref.pl - by Geoffrey Young # diff --git a/examples/ex.pl b/examples/ex.pl index 95ffa322..bd2016a4 100755 --- a/examples/ex.pl +++ b/examples/ex.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # Short example using bind_columns() to list a table's values use DBI; diff --git a/examples/inserting_longs.pl b/examples/inserting_longs.pl index 191a0c3d..056ce18a 100644 --- a/examples/inserting_longs.pl +++ b/examples/inserting_longs.pl @@ -1,4 +1,4 @@ -#!perl +#!/usr/bin/env perl use strict; use warnings; diff --git a/examples/mktable.pl b/examples/mktable.pl index 28d01007..570a16db 100755 --- a/examples/mktable.pl +++ b/examples/mktable.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # Sample DBI program to create a new table and load data into it. # # Author: Kevin Stock (original oraperl script) diff --git a/examples/oradump.pl b/examples/oradump.pl index 5477c569..5b1109cf 100755 --- a/examples/oradump.pl +++ b/examples/oradump.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # Dump the contents of an Oracle table into a set of insert statements. # Quoting is controlled by the datatypes of each column. (new with DBI) diff --git a/examples/proc.pl b/examples/proc.pl index a8a65a14..48dedec6 100755 --- a/examples/proc.pl +++ b/examples/proc.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # Short examples of procedure calls from Oracle.pm # These PL/SQL examples come from: Eric Bartley . diff --git a/examples/read_long_via_blob_read.pl b/examples/read_long_via_blob_read.pl index 70631d8d..d5a011ae 100644 --- a/examples/read_long_via_blob_read.pl +++ b/examples/read_long_via_blob_read.pl @@ -1,4 +1,4 @@ -#!perl +#!/usr/bin/env perl use strict; use warnings; diff --git a/examples/tabinfo.pl b/examples/tabinfo.pl index 307bd6b1..82c7f2ba 100755 --- a/examples/tabinfo.pl +++ b/examples/tabinfo.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl # # tabinfo # From f6850e824e89e5eaba63a45f0643363993226905 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 2 Feb 2012 21:46:22 +0000 Subject: [PATCH 117/637] record in Changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15121 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changes b/Changes index 4684b052..dd8ddb41 100644 --- a/Changes +++ b/Changes @@ -12,6 +12,10 @@ Revision history for DBD::Oracle - Mention the release of Oracle Instant Client 64 bit which does not work on Lion. (Martin J. Evans) + [OTHERS] + - change the shebang line of examples to the more modern '/usr/bin/env perl' + [RT74001] + 1.38 2012-01-13 - promote 1.37_00 to official release From 6a05f460c3e32a40163fc288fda69b0d96523047 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 2 Feb 2012 21:46:22 +0000 Subject: [PATCH 118/637] record in Changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15121 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changes b/Changes index 4684b052..dd8ddb41 100644 --- a/Changes +++ b/Changes @@ -12,6 +12,10 @@ Revision history for DBD::Oracle - Mention the release of Oracle Instant Client 64 bit which does not work on Lion. (Martin J. Evans) + [OTHERS] + - change the shebang line of examples to the more modern '/usr/bin/env perl' + [RT74001] + 1.38 2012-01-13 - promote 1.37_00 to official release From 046181ab6ba6ddd7ced8ec908cc88ff129bf7892 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 2 Feb 2012 16:47:11 -0500 Subject: [PATCH 119/637] Build results of 23a6005 (on foo) --- .gitignore | 14 - Changes | 2 +- INSTALL | 44 + LICENSE | 377 ++ MANIFEST.SKIP | 32 - META.json | 97 + META.yml | 63 + README | 4338 ++++++++++++++- README.mkdn | 4228 +++++++++++++++ dist.ini | 22 - err_bind/err_bind_param_inout_overrun_bug.msg | 108 - err_bind/err_bindarrays.msg | 241 - err_bind/err_bindclobleak.msg | 58 - err_bind/err_bindnullhash.msg | 77 - err_bind/err_trailingblank.msg | 345 -- err_build/err_aix64.msg | 142 - err_build/err_hpux_ld.msg | 89 - err_build/err_hpuxsuccess.msg | 279 - err_build/err_instantclient.msg | 207 - err_build/err_makefileundef.msg | 87 - err_build/err_memleak.msg | 95 - err_build/err_solarisnotes.msg | 482 -- err_build/err_testfailnotable.msg | 97 - err_docs/err_trace.msg | 14 - err_lob/err_csr_clob.msg | 65 - err_lob/err_loblenwide.msg | 95 - err_lob/err_lobtesttblfail.msg | 208 - err_lob/err_nclob_form.msg | 189 - err_lob/err_nulllobsegv.msg | 93 - err_lob/err_tmplobfree.msg | 537 -- err_unicode/err_char.msg | 129 - err_unicode/err_twolongstr.msg | 1256 ----- err_unsorted/err_etherreal.msg | 90 - err_unsorted/err_memleak2.msg | 476 -- err_unsorted/err_multiora.msg | 470 -- err_unsorted/err_ora9ir2oci.msg | 27 - err_unsorted/err_ref_type.msg | 115 - err_unsorted/err_refcsr_rowcache.msg | 85 - err_unsorted/err_refcsr_slow.msg | 347 -- err_unsorted/err_slowcsr.msg | 316 -- err_unsorted/err_svrparse.msg | 4717 ----------------- err_unsorted/err_xml.msg | 118 - err_unsorted/err_xml2.msg | 700 --- err_unsorted/err_xmltypebindplsql.msg | 174 - lib/DBD/Oracle.pm | 109 +- lib/DBD/Oracle/GetInfo.pm | 46 + lib/DBD/Oracle/Object.pm | 95 +- lib/DBD/Oracle/Troubleshooting.pm | 48 +- t/000-report-versions.t | 446 ++ xt/changes.t | 8 - xt/manifest.t | 21 - xt/pod.t | 11 - 52 files changed, 9593 insertions(+), 12936 deletions(-) delete mode 100644 .gitignore create mode 100644 INSTALL create mode 100644 LICENSE delete mode 100644 MANIFEST.SKIP create mode 100644 META.json create mode 100644 META.yml create mode 100644 README.mkdn delete mode 100644 dist.ini delete mode 100644 err_bind/err_bind_param_inout_overrun_bug.msg delete mode 100644 err_bind/err_bindarrays.msg delete mode 100644 err_bind/err_bindclobleak.msg delete mode 100644 err_bind/err_bindnullhash.msg delete mode 100644 err_bind/err_trailingblank.msg delete mode 100644 err_build/err_aix64.msg delete mode 100644 err_build/err_hpux_ld.msg delete mode 100644 err_build/err_hpuxsuccess.msg delete mode 100644 err_build/err_instantclient.msg delete mode 100644 err_build/err_makefileundef.msg delete mode 100644 err_build/err_memleak.msg delete mode 100644 err_build/err_solarisnotes.msg delete mode 100644 err_build/err_testfailnotable.msg delete mode 100644 err_docs/err_trace.msg delete mode 100644 err_lob/err_csr_clob.msg delete mode 100644 err_lob/err_loblenwide.msg delete mode 100644 err_lob/err_lobtesttblfail.msg delete mode 100644 err_lob/err_nclob_form.msg delete mode 100644 err_lob/err_nulllobsegv.msg delete mode 100644 err_lob/err_tmplobfree.msg delete mode 100644 err_unicode/err_char.msg delete mode 100644 err_unicode/err_twolongstr.msg delete mode 100644 err_unsorted/err_etherreal.msg delete mode 100644 err_unsorted/err_memleak2.msg delete mode 100644 err_unsorted/err_multiora.msg delete mode 100644 err_unsorted/err_ora9ir2oci.msg delete mode 100644 err_unsorted/err_ref_type.msg delete mode 100644 err_unsorted/err_refcsr_rowcache.msg delete mode 100644 err_unsorted/err_refcsr_slow.msg delete mode 100644 err_unsorted/err_slowcsr.msg delete mode 100644 err_unsorted/err_svrparse.msg delete mode 100644 err_unsorted/err_xml.msg delete mode 100644 err_unsorted/err_xml2.msg delete mode 100644 err_unsorted/err_xmltypebindplsql.msg create mode 100644 t/000-report-versions.t delete mode 100644 xt/changes.t delete mode 100644 xt/manifest.t delete mode 100644 xt/pod.t diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 15e927c8..00000000 --- a/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -pm_to_blib -MYMETA.yml -Makefile -Makefile.old -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -blib -MYMETA.json -dbdimp.o -mk.pm -oci8.o -DBD-Oracle* diff --git a/Changes b/Changes index dbd16803..5e86bd02 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.38 2012-02-02 [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..b5ab17a0 --- /dev/null +++ b/INSTALL @@ -0,0 +1,44 @@ + +This is the Perl distribution DBD-Oracle. + +Installing DBD-Oracle is straightforward. + +## Installation with cpanm + +If you have cpanm, you only need one line: + + % cpanm DBD::Oracle + +If you are installing into a system-wide directory, you may need to pass the +"-S" flag to cpanm, which uses sudo to install the module: + + % cpanm -S DBD::Oracle + +## Installing with the CPAN shell + +Alternatively, if your CPAN shell is set up, you should just be able to do: + + % cpan DBD::Oracle + +## Manual installation + +As a last resort, you can manually install it. Download the tarball, untar it, +then build it: + + % perl Makefile.PL + % make && make test + +Then install it: + + % make install + +If you are installing into a system-wide directory, you may need to run: + + % sudo make install + +## Documentation + +DBD-Oracle documentation is available as POD. +You can run perldoc from a shell to read the documentation: + + % perldoc DBD::Oracle diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..a6a371c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,377 @@ +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +Terms of the Perl programming language system itself + +a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or +b) the "Artistic License" + +--- The GNU General Public License, Version 1, February 1989 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The GNU General Public License, Version 1, February 1989 + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! + + +--- The Artistic License 1.0 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The Artistic License 1.0 + +The Artistic License + +Preamble + +The intent of this document is to state the conditions under which a Package +may be copied, such that the Copyright Holder maintains some semblance of +artistic control over the development of the package, while giving the users of +the package the right to use and distribute the Package in a more-or-less +customary fashion, plus the right to make reasonable modifications. + +Definitions: + + - "Package" refers to the collection of files distributed by the Copyright + Holder, and derivatives of that collection of files created through + textual modification. + - "Standard Version" refers to such a Package if it has not been modified, + or has been modified in accordance with the wishes of the Copyright + Holder. + - "Copyright Holder" is whoever is named in the copyright or copyrights for + the package. + - "You" is you, if you're thinking about copying or distributing this Package. + - "Reasonable copying fee" is whatever you can justify on the basis of media + cost, duplication charges, time of people involved, and so on. (You will + not be required to justify it to the Copyright Holder, but only to the + computing community at large as a market that must bear the fee.) + - "Freely Available" means that no fee is charged for the item itself, though + there may be fees involved in handling the item. It also means that + recipients of the item may redistribute it under the same conditions they + received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications derived +from the Public Domain or from the Copyright Holder. A Package modified in such +a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided that +you insert a prominent notice in each changed file stating how and when you +changed that file, and provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major archive site + such as ftp.uu.net, or by allowing the Copyright Holder to include your + modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict with + standard executables, which must also be provided, and provide a separate + manual page for each non-standard executable that clearly documents how it + differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or executable +form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where to + get the Standard Version. + + b) accompany the distribution with the machine-readable source of the Package + with your modifications. + + c) accompany any non-standard executables with their corresponding Standard + Version executables, giving the non-standard executables non-standard + names, and clearly documenting the differences in manual pages (or + equivalent), together with instructions on where to get the Standard + Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. You +may not charge a fee for this Package itself. However, you may distribute this +Package in aggregate with other (possibly commercial) programs as part of a +larger (possibly commercial) software distribution provided that you do not +advertise this Package as a product of your own. + +6. The scripts and library files supplied as input to or produced as output +from the programs of this Package do not automatically fall under the copyright +of this Package, but belong to whomever generated them, and may be sold +commercially, and may be aggregated with this Package. + +7. C or perl subroutines supplied by you and linked into this Package shall not +be considered part of this Package. + +8. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +The End + diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP deleted file mode 100644 index c7db4c66..00000000 --- a/MANIFEST.SKIP +++ /dev/null @@ -1,32 +0,0 @@ -^DBD-Oracle-.* -\.svn\b -\.orig$ -\..*.swp$ -^.pure -^DIST/ -^MANIFEST\. -^Makefile$ -^blib/ -^csr/ -^err[/_] -^old/ -^info/ -^oci8/ -^oracle/ -^tags$ -~$ -^\.git -^xt -dbdimp.o -Makefile.old -mk.pm -MYMETA.json -MYMETA.yml -oci8.o -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -pm_to_blib - -dist.ini diff --git a/META.json b/META.json new file mode 100644 index 00000000..3af05f40 --- /dev/null +++ b/META.json @@ -0,0 +1,97 @@ +{ + "abstract" : "Oracle database driver for the DBI module", + "author" : [ + "Tim Bunce ", + "John Scoles", + "Yanick Champoux " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "DBD-Oracle", + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "6.30" + } + }, + "runtime" : { + "requires" : { + "DBI" : 0, + "DynaLoader" : 0, + "Exporter" : 0, + "perl" : "5.006", + "strict" : 0, + "warnings" : 0 + } + }, + "test" : { + "requires" : { + "Carp" : 0, + "Config" : 0, + "Data::Dumper" : 0, + "Devel::Peek" : 0, + "Encode" : 0, + "Math::BigInt" : 0, + "Oraperl" : 0, + "Scalar::Util" : 0, + "Test::More" : "0.94", + "Thread::Semaphore" : 0, + "utf8" : 0, + "vars" : 0 + } + } + }, + "provides" : { + "DBD::Oracle" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::GetInfo" : { + "file" : "lib/DBD/Oracle/GetInfo.pm", + "version" : "1.38" + }, + "DBD::Oracle::Object" : { + "file" : "lib/DBD/Oracle/Object.pm", + "version" : "1.38" + }, + "DBD::Oracle::Troubleshooting" : { + "file" : "lib/DBD/Oracle/Troubleshooting.pm", + "version" : "1.38" + }, + "DBD::Oracle::db" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::dr" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::st" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "mailto" : "bug-dbd-oracle at rt.cpan.org", + "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle" + }, + "homepage" : "http://search.cpan.org/dist/DBD-Oracle/", + "repository" : { + "type" : "git", + "url" : "git://github.com/yanick/DBD-Oracle.git", + "web" : "http://github.com/yanick/DBD-Oracle/tree" + } + }, + "version" : "1.38", + "x_authority" : "cpan:PYTHIAN" +} + diff --git a/META.yml b/META.yml new file mode 100644 index 00000000..c1c09bd4 --- /dev/null +++ b/META.yml @@ -0,0 +1,63 @@ +--- +abstract: 'Oracle database driver for the DBI module' +author: + - 'Tim Bunce ' + - 'John Scoles' + - 'Yanick Champoux ' +build_requires: + Carp: 0 + Config: 0 + Data::Dumper: 0 + Devel::Peek: 0 + Encode: 0 + Math::BigInt: 0 + Oraperl: 0 + Scalar::Util: 0 + Test::More: 0.94 + Thread::Semaphore: 0 + utf8: 0 + vars: 0 +configure_requires: + ExtUtils::MakeMaker: 6.30 +dynamic_config: 0 +generated_by: 'Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: DBD-Oracle +provides: + DBD::Oracle: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::GetInfo: + file: lib/DBD/Oracle/GetInfo.pm + version: 1.38 + DBD::Oracle::Object: + file: lib/DBD/Oracle/Object.pm + version: 1.38 + DBD::Oracle::Troubleshooting: + file: lib/DBD/Oracle/Troubleshooting.pm + version: 1.38 + DBD::Oracle::db: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::dr: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::st: + file: lib/DBD/Oracle.pm + version: 1.38 +requires: + DBI: 0 + DynaLoader: 0 + Exporter: 0 + perl: 5.006 + strict: 0 + warnings: 0 +resources: + bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle + homepage: http://search.cpan.org/dist/DBD-Oracle/ + repository: git://github.com/yanick/DBD-Oracle.git +version: 1.38 +x_authority: cpan:PYTHIAN diff --git a/README b/README index fd2b28aa..bf8f7b60 100644 --- a/README +++ b/README @@ -1,301 +1,4183 @@ +NAME + DBD::Oracle - Oracle database driver for the DBI module -DBD::Oracle -- an Oracle interface for Perl 5. +VERSION + version 1.38 - Copyright (c) 1994-2006 Tim Bunce, Ireland. +SYNOPSIS + use DBI; - See the COPYRIGHT section in the Oracle.pm file for terms. - See also the MAINTAINER section in the Oracle.pm + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); - PLEASE READ THE ENTIRE README FILE CAREFULLY ! + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); - AND THEN READ ANY README.* FILES RELEVANT TO YOUR PLATFORM: + # See the DBI module documentation for full details - README.aix.txt - AIX - README.hpux.txt - HP-UX - README.java.txt - Java/thread problem on Solaris - README.macosx.txt - Mac OS/X - README.win32.txt - MS Windows - README.wingcc.txt - MS Windows using GCC - README.* - see if there's a file for your platform + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); - You may find these useful +DESCRIPTION + DBD::Oracle is a Perl module which works with the DBI module to provide + access to Oracle databases. - README.help.txt - Help and hints on build problems - README.sec.txt - Oracle security issues to be aware of - README.login.txt - Help on how to connect to Oracle - README.longs.txt - Help on handling LONGs - README.clients.txt - What Oracle client files you need installed + This documentation describes driver specific behaviour and restrictions. + It is not supposed to be used as the only reference for the user. In any + case consult the DBI documentation first! +CONSTANTS + :ora_session_modes + ORA_SYSDBA ORA_SYSOPER ORA_SYSASM -*** QUICK START GUIDE: + :ora_types + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN - The DBI requires one or more 'driver' modules to talk to databases. - Fetch, build and install the DBI module as per its README file. - You may then delete its source directory tree since it's no longer needed. - Use the 'perldoc DBI' command to read the DBI documentation. + SQLCS_IMPLICIT + SQLCS_NCHAR + SQLCS_IMPLICIT and SQLCS_NCHAR are *character set form* values. See + notes about Unicode elsewhere in this document. - Fetch this DBD::Oracle driver module and unpack it. - Follow the guidelines in this README file carefully. + SQLT_INT + SQLT_FLT + These types are used only internally, and may be specified as + internal bind type for ORA_NUMBER_TABLE. See notes about + ORA_NUMBER_TABLE elsewhere in this document + ORA_OCI + Oracle doesn't provide a formal API for determining the exact + version number of the OCI client library used, so DBD::Oracle has to + go digging (and sometimes has to more or less guess). The ORA_OCI + constant holds the result of that process. -*** *BEFORE* BUILDING, TESTING AND INSTALLING DBD::Oracle: + In string context ORA_OCI returns the full "A.B.C.D" version string. - Build, test and install Perl 5 (at least 5.6.1) - It is very important to TEST it and INSTALL it! + In numeric context ORA_OCI returns the major.minor version number + (8.1, 9.2, 10.0 etc). But note that version numbers are not actually + floating point and so if Oracle ever makes a release that has a two + digit minor version, such as 9.10 it will have a lower numeric value + than the preceding 9.9 release. So use with care. - Build, test and install the DBI module (at least DBI 1.51). - It is very important to TEST it and INSTALL it! + The contents and format of ORA_OCI are subject to change (it may, + for example, become a *version object* in later releases). I + recommend that you avoid checking for exact values. - Remember to *read* the DBI README file and this one CAREFULLY! + :ora_fetch_orient + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE - Install enough Oracle software to enable DBD::Oracle to build. + These constants are used to set the orientation of a fetch on a + scrollable cursor. - For Oracle Instant Client: that means install the following packages: - * The "Basic" package for the essential Oracle libraries. - * The "SDK" package for the headers and makefile. - * The "SQL*Plus" component is optional, but will help you check - your configuration and DBD::Oracle determine your Oracle version. + :ora_exe_modes + OCI_STMT_SCROLLABLE_READONLY - For full Oracle installs: that usually includes Pro*C and SQL*Net. - (That's not very specific because it varies between Oracle releases.). - As of release 1.22 support of Oracle clients before 9 was dropped. - The main reason for this is that next few versions of DBD::Oracle will introduce a number of new features - whicht will required a great deal of extra coding to make the OCI 8 work. - As well it is getting harder to find an Oracle client 8 to test against as well - Oracle no longer supports clients before 9. + :ora_fail_over + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL - The ORACLE_HOME environment variable must point to the Oracle Home - used to create DBD::Oracle. (Not essential under MS Windows). +DBI CLASS METHODS + connect + This method creates a database handle by connecting to a database, and + is the DBI equivalent of the "new" method. To open a connection to an + Oracle database you need to specify a database connection string (URL), + username and password. -*** MOST IMPORTANTLY: + The connection string is always of the form: "dbi:Oracle:" There are several ways to identify a database: - Make sure Oracle is working and you can use the Oracle sqlplus - command to talk to the database from the machine you - want to build DBD::Oracle on. This often involves setting - environment variables like PATH, LD_LIBRARY_PATH, TWO_TASK etc. - Consult Oracle documentation for more details. + 1 If the database is local, specifying the SID or service name will be + enough. - Only once you can connect to Oracle using sqlplus - should you try building and testing DBD::Oracle. + 2 If the database is defined in a TNSNAMES.ORA file, you can use the + service name given in the file -*** BUILDING: + 3 To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, + of the form: //host[:port][/service_name] -Execute: + If port name is not specified, 1521 is the default. If service name is + not specified, the hostname will be used as a service name. - perl Makefile.PL # use a perl that's in your PATH + The following examples show several ways a connection can be created: -Use the perl that is first on your PATH. Then execute: + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - make + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); -If you get an error like "make: not found" you need to find the -directory that has the make command installed in it (e.g. /usr/ccs/bin -on Solaris) and add that to your PATH environment variable. + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); -Don't worry about most warnings when make runs, specifically ones like -"end-of-loop code not reached", "... due to prototype", -"cast increases required alignment of target type", etc. + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); -If you have problems see the 'IF YOU HAVE PROBLEMS' section below. -If it builds without error you should then run 'make test'. For the -main tests to work they must be able to connect to an Oracle database. + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); -The tests default to using a DSN of "dbi:Oracle:" which means you'll be -connected to the default database based on your TWO_TASK or ORACLE_SID -environment variables. This default can be altered either by defining the -ORACLE_DSN environment variable or the DBI_DSN environment variable. -See the oracle_test_dsn() sub in t/nchar_test_lib.pl + OS authentication + To connect to a local database with a user which has been set up to + authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): -The supplied tests will connect to the database using the value of the -ORACLE_USERID environment variable to supply the username/password. -So you should set that to a valid user (e.g. 'scott/tiger') and ensure that -this user has sufficient privileges to create, insert into, select from and -drop a table, is also able to create, call and drop a procedure and is able to select from -systemtables like 'v$sessions'. Using 'system/manager' might work but is not -recommended! See also + $dbh = DBI->connect('dbi:Oracle:','/',''); -README.login.txt. + Note the lack of a connection name (use the ORACLE_SID environment + variable). If an explicit SID is used you will probably get an ORA-01004 + error. - make test + That only works for local databases. (Authentication to remote Oracle + databases using your Unix login name without a password is possible but + it is not secure and not recommended so not documented here. -If the all the formal tests pass then, finally, run: + Oracle Environment Variables + To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME + environment variable should be set correctly. In general, the value used + should match the version of Oracle that was used to build DBD::Oracle. + If using dynamic linking then ORACLE_HOME should match the version of + Oracle that will be used to load in the Oracle client libraries (via + LD_LIBRARY_PATH, ldconfig, or similar on Unix). - make install + Oracle can use two environment variables to specify default connections: + ORACLE_SID and TWO_TASK. + To use them, specify either a local SID or service name, or a service + name that is specified in the TNSNAMES.ORA file. -*** IF YOU HAVE PROBLEMS: + Note that if you have *both* local and remote databases, and you have + ORACLE_SID *and* TWO_TASK set, and you don't specify a fully qualified + connect string on the command line, TWO_TASK takes precedence over + ORACLE_SID (i.e. you get connected to remote system). -Make sure you are using a recent perl (5.6.1 or later) and make -sure it's on your PATH so you can say 'perl Makefile.PL' and not -'/path/to/perl Makefile.PL'. + It is highly recommended not to rely on environment variables and to + always explicitly specify the SID in the connection string. This can + prevent serious mistakes such as dropping a schema in the wrong + database, and generally makes debugging and troubleshooting easier. -If you get compiler errors refering to Perl's own header files -(.../CORE/*.h) then there is something wrong with your installation. -It is important to use a Perl that was built on the system you are using. -It's also important to use the same compiler that was used to build the -Perl you are using. + Also remember that depending on the operating system you are using the + differing "ORACLE" environment variables may be case sensitive, so if + you are not connecting as you should double check the case of both the + variable and its value. -If you have build/link or core dump problems try: - perl Makefile.PL -p -or - perl Makefile.PL -nob -If it helps then please let me know (and please include a copy -of the log from the failed default build, the log from the build that -worked, plus the output of the "perl -V" command). + Timezones + If the query is run through SQL*Net (mostly queries that are executed on + remote servers), Oracle will return the time zone based on the setting + of the UNIX environment variable "TZ" for the user who started the + listener. -Do not hand edit the generated Makefile unless you are completely sure -you understand the implications! Always try to make changes via the -Makefile.PL command line and/or editing the Makefile.PL. -You should not need to make any changes. If you do please let us -know so that I can try to make it automatic in a later release. + If the query is run locally, Oracle will return the time zone based on + the "TZ" environment variable setting of the user running the query. -If you just can't login or login takes a long time then read -README.login.txt + With local queries, you can change the time zone for a particular user + by simply changing the setting of "TZ". To check the current setting, + issue the UNIX "date" command. -If you have linking problems (errors related to libraries or functions) -then you could try forcing a 'static' build using: + Oracle DRCP + DBD::Oracle supports DRCP (Database Resident Connection Pool) so if you + have an 11.2 database and DRCP is enabled you can direct all of your + connections to it by adding ':POOLED' to the SID or setting a connection + attribute of ora_drcp, or set the SERVER=POOLED when using a TNSENTRY + style connection or even by setting an environment variable ORA_DRCP. + All of which are demonstrated below; - make realclean - perl Makefile.PL LINKTYPE=static - make - make perl (you'll need to use and install _this_ new perl binary) - make test - make -f Makefile.aperl inst_perl MAP_TARGET=perl (install new perl) - make install (install DBD::Oracle) + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') -But that's not recommended these days. + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') ->>> Also carefully read the README.help.txt file which is full of useful ->>> tips and workarounds for various problems of various systems. + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) -*** HOW TO REPORT PROBLEMS + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') -This software is supported via the dbi-users@perl.org mailing list. -(You don't need to subscribe to the list in order to post.) + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") -Please do NOT post problems to comp.lang.perl.*, perl5-porters@perl.org, -http://www.cpanforum.com/dist/DBD-Oracle, or google groups etc. + if the ORA_DRCP environment variable is set then just this -If you're *sure* the problem is a bug then you can post a bug report -to http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle -Problem reports that don't include sufficient detail (including the -information listed below and how to reproduce the problem) -are unlikely to get resolved. + $dbh = DBI->connect('dbi:Oracle:DB','username','password') -For more information and to keep informed about progress you can join the -mailing list. Send a message to dbi-users-help@perl.org for more information. + You can find a white paper on setting up DRCP and its advantages at + . -Please post details of any problems (or changes you needed to make) to -dbi-users@perl.org. - - -** IT IS IMPORTANT TO INCLUDE *ALL* THE FOLLOWING INFORMATION: + Please note that DRCP support in DBD::Oracle is relatively new so the + mechanics or its implementation are subject to change. -1. A complete log of all steps of the build, e.g.: + TAF (Transparent Application Failover) + Transparent Application Failover (TAF) is the feature in OCI that allows + for clients to automatically reconnect to an instance in the event of a + failure of the instance. The reconnect happens automatically from within + the OCI (Oracle Call Interface) library. DBD::Oracle now supports a + callback function that will fire when a TAF event takes place. The main + use of the callback is to give your program the opportunity to inform + the user that a failover is taking place. - (do a make realclean first) - perl Makefile.PL - make - make test + You will have to set up TAF on your instance before you can use this + callback. You can test your instance to see if you can use TAF callback + with - Make sure to include the 'stderr' output. The best way to do this is - to use the "script" command (man script). If that's not available - then "command > command.log 2>&1" (assuming you're not using csh). - The "2>&1" is required (after the stdout redirect) to redirect stderr - to the same place. + $dbh->ora_can_taf(); - If a test fails then also include the output of: + If you try to set up a callback without it being enabled DBD::Oracle + will croak. - perl -Mblib t/.t + It is outside the scope of this documents to go through all of the + possible TAF situations you might want to set up but here is a simple + example: -2. Full details of which version of Oracle client and server you're using - (if it wasn't automatically found and printed by "perl Makefile.PL") + The TNS entry for the instance has had the following added to the + CONNECT_DATA section -3. The output of perl -V (that's a capital V, not lowercase) + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) -4. If you get errors like "undefined symbol", "symbol not found", - "undefined reference", "Text relocation remains" or any similar - error then include the output of "perl Makefile.PL -s XXX" - where XXX is the name of one of the symbols. - Please don't send the entire output of this command, - just any obviously 'interesting' parts (if there are any). - See also the LINKTYPE=static notes above. + You will also have to create your own perl function that will be called + from the client. You can name it anything you want and it will always be + passed two parameters, the failover event value and the failover type. + You can also set a sleep value in case of failover error and the OCI + client will sleep for the specified seconds before it attempts another + event. -5. If you get a core dump, rebuild DBD::Oracle with debugging - enabled by executing: perl Makefile.PL -g (note the -g option) - then rerun the code to get a new core dump file, finally use a - debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. - NOTE: I may not be able to help you much without a stack trace! - It is worth fetching and building the GNU GDB debugger (>=4.15) if - you don't have a good debugger on your system. If desperate try: - make perl; ./perl script; echo '$c' | adb ./perl core - Also see the Devel::CoreStack module on CPAN. - -6. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun - make test after setting the environment variable PERL_DL_DEBUG to 2. - -7. If your installation succeeds, but your script does not behave - as you expect, the problem may be on your end. Before - sending to dbi-users, try writing a *small*, easy to use test case - to reproduce your problem. Also, use the DBI->trace method to - trace your database calls. + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants -It is important to check that you are using the latest version before -posting. If you're not then you're *very* likely to be told "upgrade to -the latest". You would do yourself a favour by upgrading beforehand. + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); -Try to help yourself first, then try to help others help you by following -these guidelines carefully. And remember, please don't mail developers -directly - use the dbi-users mailing list. + #create the perl TAF event function -Regards, -Tim. + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ -=============================================================================== -Examples and other info: + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); -README.help.txt -- READ IT FIRST IF YOU HAVE ANY PROBLEMS -README.win32.txt -- building DBD::Oracle under MS Windows -README.wingcc.txt -- building DBD::Oracle under MS Windows with gcc -README.macosx.txt -- building DBD::Oracle under MacOS X -README.clients.txt -- building/using DBD::Oracle on minimally configured systems -README.login.txt -- help for login problems -README.longs.txt -- examples dealing with LONG types (blobs) + } + return 0; + } -DBI 'home page': http://dbi.perl.org + The TAF types are as follows -Old archive site for Perl DB information: - ftp://ftp.demon.co.uk/pub/perl/db/ -Mailing list archive: /DBI/perldb-interest/ -Perl 4 Oraperl (v2.4) /perl4/oraperl/ - -Jeff Stander's stuff stands out for Oraperl: -Directories of interest might be - /pub/Oracle/sources - /pub/Oracle/sources/jstander - /pub/Oracle/sources/jstander/distrib - /pub/Oracle/sources/jstander/tsmlib - /pub/Oracle/sources/jstander/wdbex - /pub/Oracle/sources/web/scripts - /pub/Oracle/sources/dba - /pub/Oracle/sources/dba/imp2sql7 - /pub/Oracle/sources/Lonnroth - /pub/Oracle/sources/harrison - -http://www.bf.rmit.edu.au/~orafaq/perlish.html -ftp://ftp.bf.rmit.edu.au/pub/perl/db -ftp://ftp.bf.rmit.edu.au/pub/Oracle -ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources -ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip - -DBI and DBD::Oracle are very portable. If Perl and Oracle run on a platform -then the chances are that DBD::Oracle will as well. - -=============================================================================== - -See the large README.help.txt file for lots of hints and advice -about building and runtime issues. - -End. + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + + The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + + Connect Attributes + ora_ncs_buff_mtpl + You can customize the size of the buffer when selecting LOBs with the + built-in AUTO Lob. The default value is 4 which is probably excessive + for most situations but is needed for backward compatibility. If you not + converting between a NCS on the DB and the Client then you might want to + set this to 1 to reduce memory usage. + + This value can also be specified with the "ORA_DBD_NCS_BUFFER" + environment variable in which case it sets the value at the connect + stage. + + ora_drcp + For Oracle 11.2 or greater. + + Set to *1* to enable DRCP. Can also be set via the "ORA_DRCP" + environment variable. + + ora_drcp_class + If you are using DRCP, you can set a CONNECTION_CLASS for your pools as + well. As sessions from a DRCP cannot be shared by users, you can use + this setting to identify the same user across different applications. + OCI will ensure that sessions belonging to a 'class' are not shared + outside the class'. + + The values for ora_drcp_class cannot contain a '*' and must be less than + 1024 characters. + + This value can be also be specified with the "ORA_DRCP_CLASS" + environment variable. + + ora_drcp_min + This optional value specifies the minimum number of sessions that are + initially opened. New sessions are only opened after this value has been + reached. + + The default value is 4 and any value above 0 is valid. + + Generally, it should be set to the number of concurrent statements the + application is planning or expecting to run. + + This value can also be specified with the "ORA_DRCP_MIN" environment + variable. + + ora_drcp_max + This optional value specifies the maximum number of sessions that can be + open at one time. Once reached no more sessions can be opened until one + becomes free. The default value is 40 and any value above 1 is valid. + You should not set this value lower than ora_drcp_min as that will just + waste resources. + + This value can also be specified with the "ORA_DRCP_MAX" environment + variable. + + ora_drcp_incr + This optional value specifies the next increment for sessions to be + started if the current number of sessions are less than ora_drcp_max. + The default value is 2 and any value above 0 is valid as long as the + value of ora_drcp_min + ora_drcp_incr is not greater than ora_drcp_max. + + This value can also be specified with the "ORA_DRCP_INCR" environment + variable. + + ora_taf + If your Oracle instance has been configured to use TAF events you can + enable the TAF callback by setting this option to any *true* value. + + ora_taf_function + The name of the Perl subroutine that will be called from OCI when a TAF + event occurs. You must supply a perl function to use the callback and it + will always receive two parameters, the failover event value and the + failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + + ora_taf_sleep + The amount of time in seconds the OCI client will sleep between + attempting successive failover events when the event is OCI_FO_ERROR. + + ora_session_mode + The ora_session_mode attribute can be used to connect with SYSDBA, + SYSOPER and ORA_SYSASM authorization. The ORA_SYSDBA, ORA_SYSOPER and + ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + + This is one case where setting ORACLE_SID may be useful since connecting + as SYSDBA or SYSOPER via SQL*Net is frequently disabled for security + reasons. + + Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + + It has been reported that this only works if $dsn does not contain a SID + so that Oracle then uses the value of ORACLE_SID (not TWO_TASK) + environment variable to connect to a local instance. Also the username + and password should be empty, and the user executing the script needs to + be part of the dba group or osdba group. + + ora_oratab_orahome + Passing a true value for the ora_oratab_orahome attribute will make + DBD::Oracle change $ENV{ORACLE_HOME} to make the Oracle home directory + that specified in the "/etc/oratab" file *if* the database to connect to + is specified as a SID that exists in the oratab file, and DBD::Oracle + was built to use the Oracle 7 OCI API (not Oracle 8+). + + ora_module_name + After connecting to the database the value of this attribute is passed + to the SET_MODULE() function in the "DBMS_APPLICATION_INFO" PL/SQL + package. This can be used to identify the application to the DBA for + monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + + The maximum size is 48 bytes. + + ora_driver_name + For 11g and later you can now set the name of the driver layer using + OCI. Perl, Perl5, ApachePerl so on. Names starting with "ORA" are + reserved. You can enter up to 8 characters. If none is enter then this + will default to DBDOxxxx where xxxx is the current version number. This + value can be retrieved on the server side using V$SESSION_CONNECT_INFO + or GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + + ora_client_info + Allows you to add any value (up to 64 bytes) to your session and it can + be retrieved on the server side from the "V$SESSION"a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + + ora_client_identifier + Allows you to specify the user identifier in the session handle. + + Most useful for web applications as it can pass in the session user name + which might be different to the connection user name. Can be up to 64 + bytes long but do not to include the password for security reasons and + the first character of the identifier should not be ':'. This value can + be retrieved on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + + ora_action + Allows you to specify any string up to 32 bytes which may be retrieved + on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + + ora_dbh_share + Requires at least Perl 5.8.0 compiled with ithreads. + + Allows you to share database connections between threads. The first + connect will make the connection, all following calls to connect with + the same ora_dbh_share attribute will use the same database connection. + The value must be a reference to a already shared scalar which is + initialized to an empty string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + + ora_envhp + The first time a connection is made a new OCI 'environment' is created + by DBD::Oracle and stored in the driver handle. Subsequent connects + reuse (share) that same OCI environment by default. + + The ora_envhp attribute can be used to disable the reuse of the OCI + environment from a previous connect. If the value is 0 then a new OCI + environment is allocated and used for this connection. + + The OCI environment holds information about the client side context, + such as the local NLS environment. By altering %ENV and setting + ora_envhp to 0 you can create connections with different NLS settings. + This is most useful for testing. + + ora_charset, ora_ncharset + For oracle versions >= 9.2 you can specify the client charset and + ncharset with the ora_charset and ora_ncharset attributes. You still + need to pass "ora_envhp = 0" for all but the first connect. + + These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + + ora_verbose + Use this value to enable DBD::Oracle only tracing. Simply either set the + ora_verbose attribute on the connect() method to the trace level you + desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + + or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + + In both cases the DBD::Oracle trace level is set to 6, which is the + highest level tracing most of the calls to OCI. + + ora_oci_success_warn + Use this value to print otherwise silent OCI warnings that may happen + when an execute or fetch returns "Success With Info" or when you want to + tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + + ora_objects + Use this value to enable extended embedded oracle objects mode. In + extended: + + 1 Embedded objects are returned as instance + (including type-name etc.) instead of simple ARRAY. + + 2 Determine object type for each instance. All object attributes are + returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + + ora_ph_type + The default placeholder datatype for the database session. The "TYPE" or + "ora_type" attributes to "bind_param" in DBI and "bind_param_inout" in + DBI override the datatype for individual placeholders. The most frequent + reason for using this attribute is to permit trailing spaces in values + passed by placeholders. + + Constants for the values allowed for this attribute can be imported + using + + use DBD::Oracle qw(:ora_types); + + Only the following values are permitted for this attribute. + + ORA_VARCHAR2 + Oracle clients using OCI 8 will strip trailing spaces and allow + embedded \0 bytes. Oracle clients using OCI 9.2 do not strip + trailing spaces and allow embedded \0 bytes. This is the normal + default placeholder type. + + ORA_STRING + Do not strip trailing spaces and end the string at the first \0. + + ORA_CHAR + Do not strip trailing spaces and allow embedded \0. Force + 'blank-padded comparison semantics'. + + For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + + Will pad bloggs out to 8 characters and return the username. + + ora_parse_error_offset + If the previous error was from a failed "prepare" due to a syntax error, + this attribute gives the offset into the "Statement" attribute where the + error was found. + + ora_array_chunk_size + Due to OCI limitations, DBD::Oracle needs to buffer up rows of bind + values in its "execute_for_fetch" implementation. This attribute sets + the number of rows to buffer at a time (default value is 1000). + + The "execute_for_fetch" function will collect (at most) this many rows + in an array, send them off to the DB for execution, then go back to + collect the next chunk of rows and so on. This attribute can be used to + limit or extend the number of rows processed at a time. + + Note that this attribute also applies to "execute_array", since that + method is implemented using "execute_for_fetch". + + ora_connect_with_default_signals + Sometimes the Oracle client seems to change some of the signal handlers + of the process during the connect phase. For instance, some users have + observed Perl's default $SIG{INT} handler being ignored after connecting + to an Oracle database. If this causes problems in your application, set + this attribute to an array reference of signals you would like to be + localized during the connect process. Once the connect is complete, the + signal handlers should be returned to their previous state. + + For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + + NOTE disabling the signal handlers the OCI library sets up may affect + functionality in the OCI library. + + NOTE If you are using connect_cached then the above example will lead to + DBI thinking each connection is different as an anonymous array + reference is being used. To avoid this when using connect_cached you are + advised to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + + In more recent Perl versions you could possibly make use of new state + variables. + + connect_cached + Implemented by DBI, no driver-specific impact. Please note that + connect_cached as not been tested with DRCP. + + data_sources + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + + Returns a list of available databases. You will have to set either the + 'ORACLE_HOME' or 'TNS_ADMIN' environment value to retrieve this list. It + will read these values from TNSNAMES.ORA file entries. + +METHODS COMMON TO ALL HANDLES + For all of the methods below, $h can be either a database handle ($dbh) + or a statement handle ($sth). Note that *$dbh* and *$sth* can be + replaced with any variable name you choose: these are just the names + most often used. Another common variable used in this documentation is + $*rv*, which stands for "return value". + + err + $rv = $h->err; + + Returns the error code from the last method called. + + errstr + $str = $h->errstr; + + Returns the last error that was reported by Oracle. Starting with + "ORA-00000" code followed by the error message. + + state + $str = $h->state; + + Oracle hasn't supported SQLSTATE since the early versions OCI. It will + return empty when the command succeeds and 'S1000' (General Error) for + all other errors. + + While this method can be called as either "$sth->state" or + "$dbh->state", it is usually clearer to always use "$dbh->state". + + trace + Implemented by DBI, no driver-specific impact. + + trace_msg + Implemented by DBI, no driver-specific impact. + + parse_trace_flag and parse_trace_flags + Implemented by DBI, no driver-specific impact. + + func + DBD::Oracle uses the "func" method to support a variety of functions. + + Private database handle functions + Some of these functions are called through the method func() which is + described in the DBI documentation. Any function that begins with ora_ + can be called directly. + + plsql_errstr + This function returns a string which describes the errors from the most + recent PL/SQL function, procedure, package, or package body compile in a + format similar to the output of the SQL*Plus command 'show errors'. + + The function returns undef if the error string could not be retrieved + due to a database error. Look in $dbh->errstr for the cause of the + failure. + + If there are no compile errors, an empty string is returned. + + Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + + dbms_output_enable / dbms_output_put / dbms_output_get + These functions use the PL/SQL DBMS_OUTPUT package to store and retrieve + text using the DBMS_OUTPUT buffer. Text stored in this buffer by + dbms_output_put or any PL/SQL block can be retrieved by dbms_output_get + or any PL/SQL block connected to the same database session. + + Stored text is not available until after dbms_output_put or the PL/SQL + block that saved it completes its execution. This means you CAN NOT use + these functions to monitor long running PL/SQL procedures. + + Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + + Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + + dbms_output_enable ( [ buffer_size ] ) + This function calls DBMS_OUTPUT.ENABLE to enable calls to package + DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to these + procedures are ignored unless DBMS_OUTPUT.ENABLE is called first. + + The buffer_size is the maximum amount of text that can be saved in the + buffer and must be between 2000 and 1,000,000. If buffer_size is not + given, the default is 20,000 bytes. + + dbms_output_put ( [ @lines ] ) + This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + + If all lines were saved successfully the function returns 1. Depending + on the context, an empty list or undef is returned for failure. + + If any line causes buffer_size to be exceeded, a buffer overflow error + is raised and the function call fails. Some of the text might be in the + buffer. + + dbms_output_get + This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from + the buffer. + + In an array context, all complete lines are removed from the buffer and + returned as a list. If there are no complete lines, an empty list is + returned. + + In a scalar context, the first complete line is removed from the buffer + and returned. If there are no complete lines, undef is returned. + + Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or + DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, + DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + + reauthenticate ( $username, $password ) + Starts a new session against the current database using the credentials + supplied. + + private_attribute_info + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + + Returns a hash of all private attributes used by DBD::Oracle, for either + a database or a statement handle. Currently, all the hash values are + undef. + +ATTRIBUTES COMMON TO ALL HANDLES + InactiveDestroy (boolean) + Implemented by DBI, no driver-specific impact. + + RaiseError (boolean, inherited) + Forces errors to always raise an exception. Although it defaults to off, + it is recommended that this be turned on, as the alternative is to check + the return value of every method (prepare, execute, fetch, etc.) + manually, which is easy to forget to do. + + PrintError (boolean, inherited) + Forces database errors to also generate warnings, which can then be + filtered with methods such as locally redefining *$SIG{__WARN__}* or + using modules such as "CGI::Carp". This attribute is on by default. + + ShowErrorStatement (boolean, inherited) + Appends information about the current statement to error messages. If + placeholder information is available, adds that as well. Defaults to + true. + + Warn (boolean, inherited) + Enables warnings. This is on by default, and should only be turned off + in a local block for a short a time only when absolutely needed. + + Executed (boolean, read-only) + Indicates if a handle has been executed. For database handles, this + value is true after the "do" method has been called, or when one of the + child statement handles has issued an "execute". Issuing a "commit" or + "rollback" always resets the attribute to false for database handles. + For statement handles, any call to "execute" or its variants will flip + the value to true for the lifetime of the statement handle. + + TraceLevel (integer, inherited) + Sets the trace level, similar to the "trace" method. See the sections on + "trace" and "parse_trace_flag" for more details. + + Active (boolean, read-only) + Indicates if a handle is active or not. For database handles, this + indicates if the database has been disconnected or not. For statement + handles, it indicates if all the data has been fetched yet or not. Use + of this attribute is not encouraged. + + Kids (integer, read-only) + Returns the number of child processes created for each handle type. For + a driver handle, indicates the number of database handles created. For a + database handle, indicates the number of statement handles created. For + statement handles, it always returns zero, because statement handles do + not create kids. + + ActiveKids (integer, read-only) + Same as "Kids", but only returns those that are active. + + CachedKids (hash ref) + Returns a hashref of handles. If called on a database handle, returns + all statement handles created by use of the "prepare_cached" method. If + called on a driver handle, returns all database handles created by the + "connect_cached" method. + + ChildHandles (array ref) + Implemented by DBI, no driver-specific impact. + + PrintWarn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleError (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleSetErr (code ref, inherited) + Implemented by DBI, no driver-specific impact. + + ErrCount (unsigned integer) + Implemented by DBI, no driver-specific impact. + + FetchHashKeyName (string, inherited) + Implemented by DBI, no driver-specific impact. + + ChopBlanks (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Taint (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintIn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintOut (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Profile (inherited) + Implemented by DBI, no driver-specific impact. + + Type (scalar) + Returns "dr" for a driver handle, "db" for a database handle, and "st" + for a statement handle. Should be rarely needed. + + LongReadLen + Implemented by DBI, no driver-specific impact. + + LongTruncOk + Implemented by DBI, no driver-specific impact. + + CompatMode + Type: boolean, inherited + + The CompatMode attribute is used by emulation layers (such as Oraperl) + to enable compatible behaviour in the underlying driver (e.g., + DBD::Oracle) for this handle. Not normally set by application code. + + It also has the effect of disabling the 'quick FETCH' of attribute + values from the handles attribute cache. So all attribute values are + handled by the drivers own FETCH method. This makes them slightly slower + but is useful for special-purpose drivers like DBD::Multiplex. + +ORACLE-SPECIFIC DATABASE HANDLE METHODS + ora_can_unicode ( [ $refresh ] ) + Returns a number indicating whether either of the database character + sets is a Unicode encoding. Calls ora_nls_parameters() and passes the + optional $refresh parameter to it. + + 0 = Neither character set is a Unicode encoding. + + 1 = National character set is a Unicode encoding. + + 2 = Database character set is a Unicode encoding. + + 3 = Both character sets are Unicode encodings. + + ora_can_taf + Returns true if the current connection supports TAF events. False if + otherise. + + ora_nls_parameters ( [ $refresh ] ) + Returns a hash reference containing the current NLS parameters, as given + by the v$nls_parameters view. The values fetched are cached between + calls. To cause the latest values to be fetched, pass a true value to + the function. + +DATABASE HANDLE METHODS + selectall_arrayref + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the rows returned by + preparing and executing the SQL string. See the DBI documentation for + full details. + + selectall_hashref + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + + Returns a reference to a hash containing the rows returned by preparing + and executing the SQL string. See the DBI documentation for full + details. + + selectcol_arrayref + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the first column from each + rows returned by preparing and executing the SQL string. It is possible + to specify exactly which columns to return. See the DBI documentation + for full details. + + prepare + $sth = $dbh->prepare($statement, \%attr); + + Prepares a statement for later execution by the database engine and + returns a reference to a statement handle object. + + Prepare Attributes + These attributes may be used in the "\%attr" parameter of the "prepare" + in DBI database handle method. + + ora_placeholders + Set to false to disable processing of placeholders. Used mainly for + loading a PL/SQL package that has been *wrapped* with Oracle's + "wrap" utility. + + ora_auto_lob + If true (the default), fetching retrieves the contents of the CLOB + or BLOB column in most circumstances. If false, fetching retrieves + the Oracle "LOB Locator" of the CLOB or BLOB value. + + See "LOBs and LONGs" for more details. + + See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how + to use LOB Locators. + + ora_pers_lob + If true the "Simple Fetch for CLOBs and BLOBs" method for the "Data + Interface for Persistent LOBs" will be used for LOBs rather than the + default method "Data Interface for LOB Locators". + + ora_clbk_lob + If true the "Piecewise Fetch with Callback" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_lob + If true the "Piecewise Fetch with Polling" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_size + This is the max piece size for the "Piecewise Fetch with Callback" + and "Piecewise Fetch with Polling" methods, in chars for CLOBS, and + bytes for BLOBS. + + ora_check_sql + If 1 (default), force SELECT statements to be described in + prepare(). If 0, allow SELECT statements to defer describe until + execute(). + + See "Prepare Postponed Till Execute" for more information. + + ora_exe_mode + This will set the execute mode of the current statement. Presently + only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + + See "Scrollable Cursors" for more details. + + ora_prefetch_rows + Sets the number of rows to be prefetched. If it is not set, then the + default value is 1. See "Row Prefetching" for more details. + + ora_prefetch_memory + Sets the memory level for rows to be prefetched. The application + then fetches as many rows as will fit into that much memory. See + "Row Prefetching" for more details. + + ora_row_cache_off + By default DBD::Oracle will use a row cache when fetching to cut + down the number of round trips to the server. If you do not want to + use an array fetch set this value to any value other than 0; + + See "Row Prefetching" for more details. + + Placeholders + There are two types of placeholders that can be used in DBD::Oracle. The + first is the "question mark" type, in which each placeholder is + represented by a single question mark character. This is the method + recommended by the DBI specs and is the most portable. Each question + mark is internally replaced by a "dollar sign number" in the order in + which they appear in the query (important when using "bind_param"). + + The other placeholder type is "named parameters" in the format ":foo" + which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + + The different types of placeholders cannot be mixed within a statement, + but you may use different ones for each statement handle you have. This + is confusing at best, so stick to one style within your program. + + prepare_cached + $sth = $dbh->prepare_cached($statement, \%attr); + + Implemented by DBI, no driver-specific impact. This method is most + useful if the same query is used over and over as it will cut down round + trips to the server. + + do + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + + Prepare and execute a single statement. Returns the number of rows + affected if the query was successful, returns undef if an error + occurred, and returns -1 if the number of rows is unknown or not + available. Note that this method will return 0E0 instead of 0 for 'no + rows were affected', in order to always return a true value if no error + occurred. + + last_insert_id + Oracle does not implement auto_increment of serial type columns it uses + predefined sequences where the id numbers are either selected before + insert, at insert time with a trigger, or as part of the query. + + Below is an example of you to use the latter with the SQL returning + clause to get the ID number back on insert with the bind_param_inout + method. . + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + + commit + $rv = $dbh->commit; + + Issues a COMMIT to the server, indicating that the current transaction + is finished and that all changes made will be visible to other + processes. If AutoCommit is enabled, then a warning is given and no + COMMIT is issued. Returns true on success, false on error. + + rollback + $rv = $dbh->rollback; + + Issues a ROLLBACK to the server, which discards any changes made in the + current transaction. If AutoCommit is enabled, then a warning is given + and no ROLLBACK is issued. Returns true on success, and false on error. + + begin_work + This method turns on transactions until the next call to "commit" or + "rollback", if "AutoCommit" is currently enabled. If it is not enabled, + calling begin_work will issue an error. Note that the transaction will + not actually begin until the first statement after begin_work is called. + + disconnect + $rv = $dbh->disconnect; + + Disconnects from the Oracle database. Any uncommitted changes will be + rolled back upon disconnection. It's good policy to always explicitly + call commit or rollback at some point before disconnecting, rather than + relying on the default rollback behavior. + + If the script exits before disconnect is called (or, more precisely, if + the database handle is no longer referenced by anything), then the + database handle's DESTROY method will call the rollback() and + disconnect() methods automatically. It is best to explicitly disconnect + rather than rely on this behavior. + + ping + $rv = $dbh->ping; + + This "ping" method is used to check the validity of a database handle. + The value returned is either 0, indicating that the connection is no + longer valid, or 1, indicating the connection is valid. This function + does 1 round trip to the Oracle Server. + + get_info() + $value = $dbh->get_info($info_type); + + DBD::Oracle supports "get_info()", but (currently) only a few info + types. + + table_info() + DBD::Oracle supports attributes for "table_info()". + + In Oracle, the concept of *user* and *schema* is (currently) the same. + Because database objects are owned by an user, the owner names in the + data dictionary views correspond to schema names. Oracle does not + support catalogues so TABLE_CAT is ignored as selection criterion. + + Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + + TABLE_TYPE may contain a comma-separated list of table types. The + following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + + The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + + The special enumerations of catalogues, schemas and table types are + supported. However, TABLE_CAT is always NULL. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. "table_info()" performs a case-sensitive search. So, a + selection criterion should respect upper and lower case. Normally, an + identifier is case-insensitive. Oracle stores and returns it in upper + case. Sometimes, database objects are created with quoted identifiers + (for reserved words, mixed case, special characters, ...). Such an + identifier is case-sensitive (if not all upper case). Oracle stores and + returns it as given. "table_info()" has no special quote handling, + neither adds nor removes quotes. + + primary_key_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + If the primary key constraint was created without an identifier, PK_NAME + contains a system generated name with the form SYS_Cn. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + foreign_key_info() + This method (currently) supports the extended behaviour of SQL/CLI, i.e. + the result set contains foreign keys that refer to primary and alternate + keys. The field UNIQUE_OR_PRIMARY distinguishes these keys. + + Oracle does not support catalogues, so $pk_catalog and $fk_catalog are + ignored as selection criteria (in the new style interface). The + UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always NULL + (undef). See "table_info()" for more detailed information. + + If the primary or foreign key constraints were created without an + identifier, UK_NAME or FK_NAME contains a system generated name with the + form SYS_Cn. + + The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle + (currently) does not support other actions. + + The DELETE_RULE field may contain wrong values. This is a known Bug + (#1271663) in Oracle's data dictionary views. Currently (as of 8.1.7), + 'RESTRICT' and 'SET DEFAULT' are not supported, 'CASCADE' is mapped + correctly and all other actions (incl. 'SET NULL') appear as 'NO + ACTION'. + + The DEFERABILITY field is always NULL, because this columns is not + present in the ALL_CONSTRAINTS view of older Oracle releases. + + The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, + FK_TABLE_SCHEM, FK_TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + column_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + + Don't rely on the values of the BUFFER_LENGTH field! Especially the + length of FLOATs may be wrong. + + Datatype codes for non-standard types are subject to change. + + Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + It is possible with Oracle to make the names of the various DB objects + (table,column,index etc) case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + + So in the example the exact case "Bla_BLA" must be used to get it info + on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + + any case can be used to get info on the column. + + selectrow_array + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + + Returns an array of row information after preparing and executing the + provided SQL string. The rows are returned by calling "fetchrow_array". + The string can also be a statement handle generated by a previous + prepare. Note that only the first row of data is returned. If called in + a scalar context, only the first column of the first row is returned. + Because this is not portable, it is not recommended that you use this + method in that way. + + selectrow_arrayref + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an array, by internal use of the "fetchrow_arrayref" + method. + + selectrow_hashref + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an hash, by internal use of the "fetchrow_hashref" method. + + clone + $other_dbh = $dbh->clone(); + + Creates a copy of the database handle by connecting with the same + parameters as the original handle, then trying to merge the attributes. + See the DBI documentation for complete usage. + +DATABASE HANDLE ATTRIBUTES + AutoCommit (boolean) + Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is + on, but this may change in the future, so it is highly recommended that + you explicitly set it when calling "connect". + + ReadOnly (boolean) + $dbh->{ReadOnly} = 1; + + Specifies if the current database connection should be in read-only mode + or not. + + Please not that this method is not foolproof: there are still ways to + update the database. Consider this a safety net to catch applications + that should not be issuing commands such as INSERT, UPDATE, or DELETE. + + This method method requires DBI version 1.55 or better. + + Name (string, read-only) + Returns the name of the current database. This is the same as the DSN, + without the "dbi:Oracle:" part. + + Username (string, read-only) + Returns the name of the user connected to the database. + + Driver (handle, read-only) + Holds the handle of the parent driver. The only recommended use for this + is to find the name of the driver using: + + $dbh->{Driver}->{Name} + + RowCacheSize + DBD::Oracle supports both Server pre-fetch and Client side row caching. + By default both are turned on to give optimum performance. Most of the + time one can just let DBD::Oracle figure out the best optimization. + + Row Caching + Row caching occurs on the client side and the object of it is to cut + down the number of round trips made to the server when fetching rows. At + each fetch a set number of rows will be retrieved from the server and + stored locally. Further calls the server are made only when the end of + the local buffer(cache) is reached. + + Rows up to the specified top level row count "RowCacheSize" are fetched + if it occupies no more than the specified memory usage limit. The + default value is 0, which means that memory size is not included in + computing the number of rows to prefetch. If the "RowCacheSize" value is + set to a negative number then the positive value of RowCacheSize is used + to compute the number of rows to prefetch. + + By default "RowCacheSize" is automatically set. If you want to totally + turn off prefetching set this to 1. + + For any SQL statement that contains a LOB, Long or Object Type Row + Caching will be turned off. However server side caching still works. If + you are only selecting a LOB Locator then Row Caching will still work. + + Row Prefetching + Row prefetching occurs on the server side and uses the DBI database + handle attribute "RowCacheSize" and or the Prepare Attribute + 'ora_prefetch_memory'. Tweaking these values may yield improved + performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + + In the above example 10 rows will be prefetched up to a maximum of 10000 + bytes of data. The Oracle® Call Interface Programmer's Guide, suggests + a good row cache value for a scrollable cursor is about 20% of expected + size of the record set. + + The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) + when it needs to get new rows. This happens on the first fetch that sets + the current_positon to any value other than 0. In the above example if + we do a OCI_FETCH_FIRST the first 10 rows are loaded into the buffer and + DBD::Oracle will not have to go back to the server for more rows. When + record 11 is fetched DBD::Oracle fetches and returns this row and the + next 9 rows are loaded into the buffer. In this case if you fetch + backwards from 10 to 1 no server round trips are made. + + With large record sets it is best not to attempt to go to the last + record as this may take some time, A large buffer size might even slow + down the fetch. If you must get the number of rows in a large record set + you might try using an few large OCI_FETCH_ABSOLUTEs and then an + OCI_FETCH_LAST, this might save some time. So if you had a record set of + 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one + would fetch the first 5000 rows into the buffer then the next 5000 rows. + If one requires only the first few rows there is no need to set a large + prefetch value. + + If the ora_prefetch_memory less than 1 or not present then memory size + is not included in computing the number of rows to prefetch otherwise + the number of rows will be limited to memory size. Likewise if the + RowCacheSize is less than 1 it is not included in the computing of the + prefetch rows. + +ORACLE-SPECIFIC STATEMENT HANDLE METHODS + ora_stmt_type + Returns the OCI Statement Type number for the SQL of a statement handle. + + ora_stmt_type_name + Returns the OCI Statement Type name for the SQL of a statement handle. + +DBI STATEMENT HANDLE OBJECT METHODS + bind_param + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + + Allows the user to bind a value and/or a data type to a placeholder. + + The value of $param_num is a number if using the '?' or if using ":foo" + style placeholders, the complete name (e.g. ":foo") must be given. The + $bind_value argument is fairly self-explanatory. A value of "undef" will + bind a "NULL" to the placeholder. Using "undef" is useful when you want + to change just the type and will be overwriting the value later. (Any + value is actually usable, but "undef" is easy and efficient). + + The "\%attr" hash is used to indicate the data type of the placeholder. + The default value is "varchar". If you need something else, you must use + one of the values provided by DBI or by DBD::Pg. To use a SQL value, + modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + + This will import some constants into your script. You can plug those + directly into the "bind_param" call. Some common ones that you will + encounter are: + + SQL_INTEGER + + To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + + You can then set the data types by setting the value of the "ora_type" + key in the hash passed to "bind_param". The current list of Oracle data + types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + + Data types are "sticky," in that once a data type is set to a certain + placeholder, it will remain for that placeholder, unless it is + explicitly set to something else afterwards. If the statement has + already been prepared, and you switch the data type to something else, + DBD::Oracle will re-prepare the statement for you before doing the next + execute. + + Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + + These attributes may be used in the "\%attr" parameter of the + "bind_param" in DBI or "bind_param_inout" in DBI statement handle + methods. + + ora_type + Specify the placeholder's datatype using an Oracle datatype. A fatal + error is raised if "ora_type" and the DBI "TYPE" attribute are used + for the same placeholder. Some of these types are not supported by + the current version of DBD::Oracle and will cause a fatal error if + used. Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + + Potentially useful values when DBD::Oracle was built using OCI 7 and + later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + + Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + + Additional values when DBD::Oracle was built using OCI 9.2 and + later: + + SQLT_CHR, SQLT_BIN + + See "Binding Cursors" for the correct way to use ORA_RSET. + + See "LOBs and LONGs" for how to use ORA_CLOB and ORA_BLOB. + + See "SYS.DBMS_SQL datatypes" for ORA_VARCHAR2_TABLE, + ORA_NUMBER_TABLE. + + See "Data Interface for Persistent LOBs" for the correct way to use + SQLT_CHR and SQLT_BIN. + + See "Other Data Types" for more information. + + See also "Placeholders and Bind Values" in DBI. + + ora_csform + Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values + are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can + be imported from the DBD::Oracle module. Rarely needed. + + ora_csid + Specify the *integer* OCI_ATTR_CHARSET_ID for the bind value. + Character set names can't be used currently. + + ora_maxdata_size + Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. May be + needed if a character set conversion from client to server causes + the data to use more space and so fail with a truncation error. + + ora_maxarray_numentries + Specify the maximum number of array entries to allocate. Used with + ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of + array entries Oracle can pass back to you in OUT variable of type + TABLE OF ... . + + ora_internal_type + Specify internal data representation. Currently is supported only + for ORA_NUMBER_TABLE. + + Optimizing Results + Prepare Postponed Till Execute + The DBD::Oracle module can avoid an explicit 'describe' operation prior + to the execution of the statement unless the application requests + information about the results (such as $sth->{NAME}). This reduces + communication with the server and increases performance (reducing the + number of PARSE_CALLS inside the server). + + However, it also means that SQL errors are not detected until + "execute()" (or $sth->{NAME} etc) is called instead of when "prepare()" + is called. Note that if the describe is triggered by the use of + $sth->{NAME} or a similar attribute and the describe fails then *an + exception is thrown* even if "RaiseError" is false! + + Set "ora_check_sql" to 0 in prepare() to enable this behaviour. + + bind_param_inout + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + + DBD::Oracle fully supports bind_param_inout below are some uses for this + method. + + Returning A Value from an INSERT + Oracle supports an extended SQL insert syntax which will return one or + more of the values inserted. This can be particularly useful for + single-pass insertion of values with re-used sequence values (avoiding a + separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + + If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + + If you have many rows to insert you can take advantage of Oracle's built + in execute array feature with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + + Which will return all the ids into @out_values. + + Note: + This will only work for numbered (?) placeholders, + The third parameter of bind_param_inout_array, (0 in the example), + "maxlen" is required by DBI but not used by DBD::Oracle + The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + + Returning A Recordset + DBD::Oracle does not currently support binding a PL/SQL table (aka + array) as an IN OUT parameter to any Perl data structure. You cannot + therefore call a PL/SQL function or procedure from DBI that uses a + non-atomic datatype as either a parameter, or a return value. However, + if you are using Oracle 9.0.1 or later, you can make use of table (or + pipelined) functions. + + For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + + Currently, there is no way to directly call the function + Array_Example.Array_Func from DBI. However, by making the following + relatively painless additions, its not only possible, but extremely + efficient. + + First, you need to create database object types that correspond to the + record and table types in the package. From the above example, these + would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + + Now, assuming the existing function needs to remain unchanged (it is + probably being called from other PL/SQL code), we need to add a new + function to the package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + + As you can see, the new function is very simple. Now, it is a simple + matter of calling the function as a straight-forward SELECT from your + DBI code. From the above example, the code would look something like + this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + + SYS.DBMS_SQL datatypes + DBD::Oracle has built-in support for SYS.DBMS_SQL.VARCHAR2_TABLE and + SYS.DBMS_SQL.NUMBER_TABLE datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + Note: + Take careful note that we use '\\@arr' here because the + 'bind_param_inout' will only take a reference to a scalar. + + ORA_VARCHAR2_TABLE + SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. ( + in bind_param() and bind_param_inout() ). When you bind array, you need + to specify full buffer size for OUT data. So, there are two parameters: + *max_len* (specified as 3rd argument of bind_param_inout() ), and + *ora_maxarray_numentries*. They define maximum array entry length and + maximum rows, that can be passed to Oracle and back to you. In this + example we send array with 1 element with length=3, but allocate space + for 100 Oracle array entries with maximum length 10 of each. So, you can + get no more than 100 array entries with length <= 10. + + If you set *max_len* to zero, maximum array entry length is calculated + as maximum length of entry of array bound. If 0 < *max_len* < length( + $some_element ), truncation occur. + + If you set *ora_maxarray_numentries* to zero, current (at bind time) + bound array length is used as maximum. If 0 < *ora_maxarray_numentries* + < scalar(@array), not all array entries are bound. + + ORA_NUMBER_TABLE + SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike + ORA_VARCHAR2_TABLE. The main difference is internal data representation. + Currently 2 types of bind is allowed : as C-integer, or as C-double + type. To select one of them, you may specify additional bind parameter + *ora_internal_type* as either SQLT_INT or SQLT_FLT for C-integer and + C-double types. Integer size is architecture-specific and is usually 32 + or 64 bit. Double is standard IEEE 754 type. + + *ora_internal_type* defaults to double (SQLT_FLT). + + *max_len* is ignored for OCI_NUMBER_TABLE. + + Currently, you cannot bind full native Oracle NUMBER(38). If you really + need, send request to dbi-dev list. + + The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + + If you change bind type to SQLT_INT, like: + + ora_internal_type => SQLT_INT + + you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + + bind_param_inout_array + DBD::Oracle supports this undocumented feature of DBI. See "Returning A + Value from an INSERT" for an example. + + bind_param_array + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + + Binds an array of values to a placeholder, so that each is used in turn + by a call to the "execute_array" method. + + execute + $rv = $sth->execute(@bind_values); + + Perform whatever processing is necessary to execute the prepared + statement. + + execute_array + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + Execute a prepared statement once for each item in a passed-in hashref, + or items that were previously bound via the "bind_param_array" method. + See the DBI documentation for more details. + + DBD::Oracle takes full advantage of OCI's array interface so inserts and + updates using this interface will run very quickly. + + execute_for_fetch + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + Used internally by the "execute_array" method, and rarely used directly. + See the DBI documentation for more details. + + fetchrow_arrayref + $ary_ref = $sth->fetchrow_arrayref; + + Fetches the next row of data from the statement handle, and returns a + reference to an array holding the column values. Any columns that are + NULL are returned as undef within the array. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + Note that the same array reference is returned for each fetch, so don't + store the reference and then use it after a later fetch. Also, the + elements of the array are also reused for each row, so take care if you + want to take a reference to an element. See also "bind_columns". + + fetchrow_array + @ary = $sth->fetchrow_array; + + Similar to the "fetchrow_arrayref" method, but returns a list of column + information rather than a reference to a list. Do not use this in a + scalar context. + + fetchrow_hashref + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + + Fetches the next row of data and returns a hashref containing the name + of the columns as the keys and the data itself as the values. Any NULL + value is returned as as undef value. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + The optional $name argument should be either "NAME", "NAME_lc" or + "NAME_uc", and indicates what sort of transformation to make to the keys + in the hash. By default Oracle uses upper case. + + fetchall_arrayref + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + + Returns a reference to an array of arrays that contains all the + remaining rows to be fetched from the statement handle. If there are no + more rows, an empty arrayref will be returned. If an error occurs, the + data read in so far will be returned. Because of this, you should always + check "$sth->err" after calling this method, unless "RaiseError" has + been enabled. + + If $slice is an array reference, fetchall_arrayref uses the + "fetchrow_arrayref" method to fetch each row as an array ref. If the + $slice array is not empty then it is used as a slice to select + individual columns by perl array index number (starting at 0, unlike + column and parameter numbers which start at 1). + + With no parameters, or if $slice is undefined, fetchall_arrayref acts as + if passed an empty array ref. + + If $slice is a hash reference, fetchall_arrayref uses "fetchrow_hashref" + to fetch each row as a hash reference. + + See the DBI documentation for a complete discussion. + + fetchall_hashref + $hash_ref = $sth->fetchall_hashref( $key_field ); + + Returns a hashref containing all rows to be fetched from the statement + handle. See the DBI documentation for a full discussion. + + finish + $rv = $sth->finish; + + Indicates to DBI that you are finished with the statement handle and are + not going to use it again. Only needed when you have not fetched all the + possible rows. + + rows + $rv = $sth->rows; + + Returns the number of rows affected for updates, deletes and inserts and + -1 for selects. + + bind_col + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + + Binds a Perl variable and/or some attributes to an output column of a + SELECT statement. Column numbers count up from 1. You do not need to + bind output columns in order to fetch data. + + NOTE: DBD::Oracle does not use the $bind_type to determine how to bind + the column; it uses what Oracle says the data type is. You can however + set a numeric bind type with the bind attributes + StrictlyTyped/DiscardString as these attributes are applied after the + column is retrieved. + + See the DBI documentation for a discussion of the optional parameters + "\%attr" and $bind_type + + bind_columns + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + + Calls the "bind_col" method for each column in the SELECT statement, + using the supplied list. + + dump_results + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + + Fetches all the rows from the statement handle, calls "DBI::neat_list" + for each row, and prints the results to $fh (which defaults to STDOUT). + Rows are separated by $lsep (which defaults to a newline). Columns are + separated by $fsep (which defaults to a comma). The $maxlen controls how + wide the output can be, and defaults to 35. + + This method is designed as a handy utility for prototyping and testing + queries. Since it uses "neat_list" to format and edit the string for + reading by humans, it is not recommended for data transfer applications. + +STATEMENT HANDLE ATTRIBUTES + NUM_OF_FIELDS (integer, read-only) + Returns the number of columns returned by the current statement. A + number will only be returned for SELECT statements for INSERT, UPDATE, + and DELETE statements which contain a RETURNING clause. This method + returns undef if called before "execute()". + + NUM_OF_PARAMS (integer, read-only) + Returns the number of placeholders in the current statement. + + NAME (arrayref, read-only) + Returns an arrayref of column names for the current statement. This + method will only work for SELECT statements, for SHOW statements, and + for INSERT, UPDATE, and DELETE statements which contain a RETURNING + clause. This method returns undef if called before "execute()". + + NAME_lc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to lower case. + + NAME_uc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to upper case. + + NAME_hash (hashref, read-only) + Similar to the "NAME" attribute, but returns a hashref of column names + instead of an arrayref. The names of the columns are the keys of the + hash, and the values represent the order in which the columns are + returned, starting at 0. This method returns undef if called before + "execute()". + + NAME_lc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + NAME_uc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + TYPE (arrayref, read-only) + Returns an arrayref indicating the data type for each column in the + statement. This method returns undef if called before "execute()". + + PRECISION (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the precision for "NUMERIC" columns, the + size in number of characters for "CHAR" and "VARCHAR" columns, and for + all other types of columns it returns the number of *bytes*. This method + returns undef if called before "execute()". + + SCALE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the scale of the that column. The only + type that will return a value is "NUMERIC". This method returns undef if + called before "execute()". + + NULLABLE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates if the column is nullable or not. 0 = + not nullable, 1 = nullable, 2 = unknown. This method returns undef if + called before "execute()". + + Database (dbh, read-only) + Returns the database handle this statement handle was created from. + + ParamValues (hash ref, read-only) + Returns a reference to a hash containing the values currently bound to + placeholders. If the "named parameters" type of placeholders are being + used (such as ":foo"), then the keys of the hash will be the names of + the placeholders (without the colon). If the "dollar sign numbers" type + of placeholders are being used, the keys of the hash will be the + numbers, without the dollar signs. If the "question mark" type is used, + integer numbers will be returned, starting at one and increasing for + every placeholder. + + If this method is called before "execute", the literal values passed in + are returned. If called after "execute", then the quoted versions of the + values are returned. + + ParamTypes (hash ref, read-only) + Returns a reference to a hash containing the type names currently bound + to placeholders. The keys are the same as returned by the ParamValues + method. The values are hashrefs containing a single key value pair, in + which the key is either 'TYPE' if the type has a generic SQL equivalent, + and 'pg_type' if the type can only be expressed by a Postgres type. The + value is the internal number corresponding to the type originally passed + in. (Placeholders that have not yet been bound will return undef as the + value). This allows the output of ParamTypes to be passed back to the + "bind_param" method. + + Statement (string, read-only) + Returns the statement string passed to the most recent "prepare" method + called in this database handle, even if that method failed. This is + especially useful where "RaiseError" is enabled and the exception + handler checks $@ and sees that a "prepare" method call failed. + + RowsInCache + Returns the number of un-fetched rows in the cache for selects. + +SCROLLABLE CURSORS + Oracle supports the concept of a 'Scrollable Cursor' which is defined as + a 'Result Set' where the rows can be fetched either sequentially or + non-sequentially. One can fetch rows forward, backwards, from any given + position or the n-th row from the current position in the result set. + + Rows are numbered sequentially starting at one and client-side caching + of the partial or entire result set can improve performance by limiting + round trips to the server. + + Oracle does not support DML type operations with scrollable cursors so + you are limited to simple 'Select' operations only. As well you can not + use this functionality with remote mapped queries or if the LONG + datatype is part of the select list. + + However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, + and fetch methods. + + Only use scrollable cursors if you really have a good reason to. They do + use up considerable more server and client resources and have poorer + response times than non-scrolling cursors. + + Enabling Scrollable Cursors + To enable this functionality you must first import the 'Fetch + Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + + Next you will have to tell DBD::Oracle that you will be using scrolling + by setting the ora_exe_mode attribute on the statement handle to + 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + + When the statement is executed you will then be able to use + 'ora_fetch_scroll' method to get a row or you can still use any of the + other fetch methods but with a poorer response time than if you used a + non-scrolling cursor. As well scrollable cursors are compatible with any + applicable bind methods. + + Scrollable Cursor Methods + The following driver-specific methods are used with scrollable cursors. + + ora_scroll_position + $position = $sth->ora_scroll_position(); + + This method returns the current position (row number) attribute of + the result set. Prior to the first fetch this value is 0. This is + the only time this value will be 0 after the first fetch the value + will be set, so you can use this value to test if any rows have been + fetched. The minimum value will always be 1 after the first fetch. + The maximum value will always be the total number of rows in the + record set. + + ora_fetch_scroll + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + + Works the same as "fetchrow_arrayref", excepts one passes in a + 'Fetch Orientation' constant and a fetch_offset value which will + then determine the row that will be fetched. It returns the row as a + list containing the field values. Null fields are returned as + *undef* values in the list. + + The valid orientation constant and fetch offset values combination + are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + + The effect that a ora_fetch_scroll method call has on the + current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + + The effects of the differing orientation constants on the first + fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + + Scrollable Cursor Usage + Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + + and one assumes that the number of rows returned from the query is 20, + the code snippets below will illustrate the use of ora_fetch_scroll + method; + + Fetching the Last Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute to will be 20 after this snippet. This + is also a way to get the number of rows in the record set, however, + if the record set is large this could take some time. + + Fetching the Current Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will still be 20 after this snippet. + + Fetching the First Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the Next Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 5 after this snippet. + + Fetching the Prior Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the 10th Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 10th to 14th Row + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 14 after this snippet. + + Fetching the 14th to 10th Row + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 5th Row From the Present Position. + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 15 after this snippet. + + Fetching the 9th Row Prior From the Present Position + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 6 after this snippet. + + Use Finish + $sth->finish(); + + When using scrollable cursors it is required that you use the + $sth->finish() method when you are done with the cursor as this type + of cursor has to be explicitly cancelled on the server. If you do + not do this you may cause resource problems on your database. + +LOBS AND LONGS + The key to working with LOBs (CLOB, BLOBs) is to remember the value of + an Oracle LOB column is not the content of the LOB. It's a 'LOB Locator' + which, after being selected or inserted needs extra processing to read + or write the content of the LOB. There are also legacy LONG types (LONG, + LONG RAW, VARCHAR2) which are presently deprecated by Oracle but are + still in use. These LONG types do not utilize a 'LOB Locator' and also + are more limited in functionality than CLOB or BLOB fields. + + DBD::Oracle now offers three interfaces to LOB and LONG data, + + "Data Interface for Persistent LOBs" + With this interface DBD::Oracle handles your data directly utilizing + regular OCI calls, Oracle itself takes care of the LOB Locator + operations in the case of BLOBs and CLOBs treating them exactly as + if they were the same as the legacy LONG or LONG RAW types. + + "Data Interface for LOB Locators" + With this interface DBD::Oracle handles your data utilizing LOB + Locator OCI calls so it only works with CLOB and BLOB datatypes. + With this interface DBD::Oracle takes care of the LOB Locator + operations for you. + + "LOB Locator Method Interface" + This allows the user direct access to the LOB Locator methods, so + you have to take case of the LOB Locator operations yourself. + + Generally speaking the interface that you will chose will be dependent + on what end you are trying to achieve. All have their benefits and + drawbacks. + + One point to remember when working with LOBs (CLOBs, BLOBs) is if your + LOB column can be in one of three states; + + NULL + The table cell is created, but the cell holds no locator or value. + If your LOB field is in this state then there is no LOB Locator that + DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + + error when working with a LOB. + + You can correct this by using an SQL UPDATE statement to reset the + LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB + or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + + Empty + A LOB instance with a locator exists in the cell, but it has no + value. The length of the LOB is zero. In this case DBD::Oracle will + return 'undef' for the field. + + Populated + A LOB instance with a locator and a value exists in the cell. You + actually get the LOB value. + + Data Interface for Persistent LOBs + This is the original interface for LONG and LONG RAW datatypes and from + Oracle 9iR1 and later the OCI API was extended to work directly with the + other LOB datatypes. In other words you can treat all LOB type data + (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can + perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using + the same techniques you would use on other datatypes that store + character or binary data. In some cases there are fewer round trips to + the server as no 'LOB Locators' are used, normally one can get an entire + LOB is a single round trip. + + Simple Fetch for LONGs and LONG RAWs + As the name implies this is the simplest way to use this interface. + DBD::Oracle just attempts to get your LONG datatypes as a single large + piece. There are no special settings, simply set the database handle's + 'LongReadLen' attribute to a value that will be the larger than the + expected size of the LONG or LONG RAW. If the size of the LONG or LONG + RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A + Truncation' error. To stop this set the database handle's 'LongTruncOk' + attribute to '1'. The maximum value of 'LongReadLen' seems to be + dependent on the physical memory limits of the box that Oracle is + running on. You have most likely reached this limit if you run into an + 'ORA-01062: unable to allocate memory for define buffer' error. One + solution is to set the size of 'LongReadLen' to a lower value. + + For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select out all of the long1 fields in the table as long as they are + all under 2MB in length. A value in long1 longer than this will throw an + error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the long1 fields but they will be + truncated at 2MBs. + + Using ora_ncs_buff_mtpl + When getting CLOBs and NCLOBs in or out of Oracle, the Server will + translate from the Server's NCharSet to the Client's. If they happen to + be the same or at least compatible then all of these actions are a 1 + char to 1 char bases. Thus if you set your LongReadLen buffer to + 10_000_000 you will get up to 10_000_000 char. + + However if the Server has to translate from one NCharSet to another it + will use bytes for conversion. The buffer value is set to 4 * + LONG_READ_LEN which was very wasteful as you might only be asking for + 10_000_000 bytes but you were actually using 40_000_000 bytes of buffer + under the hood. You would still get 10_000_000 bytes (maybe less + characters though) but you are using allot more memory that you need. + + You can now customize the size of the buffer by setting the + 'ora_ncs_buff_mtpl' either on the connection or statement handle. You + can also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you + will have to go back and change all your code if you are getting into + trouble. + + The default value is still set to 4 for backward compatibility. You can + lower this value and thus increase the amount of data you can retrieve. + If the ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error + telling you to increase this buffer by one. + + If the error is not captured then you may get at some random point later + on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + + This is one of the more obscure ORA errors (have some fun and report it + to Meta-Link they will scratch their heads for hours) + + If you get this, simply increment the ora_ncs_buff_mtpl by one until it + goes away. + + This should greatly increase your ability to select very large CLOBs or + NCLOBs, by freeing up a large block of memory. + + You can tune this value by setting ora_oci_success_warn which will + display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + + In the case above the query Got 28 characters (well really only 20 + characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) + thus saving 40bytes of memory. + + Simple Fetch for CLOBs and BLOBs + To use this interface for CLOBs and LOBs datatypes set the + 'ora_pers_lob' attribute of the statement handle to '1' with the prepare + method, as well set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. If the + size of the LOB exceeds the 'LongReadLen' DBD::Oracle will return a + 'ORA-24345: A Truncation' error. To stop this set the database handle's + 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems + to be dependent on the physical memory limits of the box that Oracle is + running on in the same way that LONGs and LONG RAWs are. + + For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, + this is an internal OCI limit complain to them if you want it changed. + However if you CLOB is longer than this and also larger than the + 'LongReadLen' than the 'LongReadLen' in chars is returned. + + It seems with BLOBs you are not limited by the 64k. + + For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the lobs but they will be truncated + at 2MBs. + + Piecewise Fetch with Callback + With a piecewise callback fetch DBD::Oracle sets up a function that will + 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, + CLOB, BLOB) piece by piece. To use this interface set the 'ora_clbk_lob' + attribute of the statement handle to '1' with the prepare method. Next + set the 'ora_piece_size' to the size of the piece that you want to + return on the callback. Finally set the database handle's 'LongReadLen' + attribute to a value that will be the larger than the expected size of + the LOB. Like the "Simple Fetch for LONGs and LONG RAWs" and "Simple + Fetch for CLOBs and BLOBs" the if the size of the LOB exceeds the is + 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the + LOB or set the 'LongReadLen' to a higher value. With this interface the + value of 'ora_piece_size' seems to be constrained by the same memory + limit as found on the Simple Fetch interface. If you encounter an + 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller + value. The value for 'LongReadLen' is dependent on the version and + settings of the Oracle DB you are using. In theory it ranges from 8GBs + in 9iR1 up to 128 terabytes with 11g but you will also be limited by the + physical memory of your PERL instance. + + Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will + throw an error. + + Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 filed is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Piecewise Fetch with Polling + With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB + during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by + piece. To use this interface set the 'ora_piece_lob' attribute of the + statement handle to '1' with the prepare method. Next set the + 'ora_piece_size' to the size of the piece that you want to return on the + callback. Finally set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. Like + the "Piecewise Fetch with Callback" and Simple Fetches if the size of + the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' + attribute to truncate the LOB or set the 'LongReadLen' to a higher + value. With this interface the value of 'ora_piece_size' seems to be + constrained by the same memory limit as found on the "Piecewise Fetch + with Callback". + + Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will + throw an error. + + Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 field is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Binding for Updates and Inserts for CLOBs and BLOBs + To bind for updates and inserts all that is required to use this + interface is to set the statement handle's prepare method 'ora_type' + attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in + the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + + So far the only limit reached with this form of insert is the LOBs must + be under 2GB in size. + + Support for Remote LOBs; + Starting with Oracle 10gR2 the interface for Persistent LOBs was + expanded to support remote LOBs (access over a dblink). Given a database + called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + + to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Below are the limitations of Remote LOBs; + + Queries involving more than one database are not supported; + so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + + as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + + DDL commands are not supported; + so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + + Only binds and defines for data going into remote persistent LOBs are + supported. + so that parameter passing in PL/SQL where CHAR data is bound or + defined for remote LOBs is not allowed . + + These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + + If the remote object is a view such as + CREATE VIEW v AS SELECT foo() FROM ... + + the following would not work: + + SELECT * FROM v@dbs2; + + Limited PL/SQL parameter passing + PL/SQL parameter passing is not allowed where the actual argument is + a LOB type and the remote argument is one of VARCHAR2, NVARCHAR2, + CHAR, NCHAR, or RAW. + + RETURNING INTO does not support implicit conversions between CHAR and + CLOB. + so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + + Locator Data Interface + Simple Usage + When fetching LOBs with this interface a 'LOB Locator' is created then + used to get the lob with the LongReadLen and LongTruncOk attributes. The + value for 'LongReadLen' is dependent on the version and settings of the + Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 + terabytes with 11g but you will also be limited by the physical memory + of your PERL instance. + + When inserting or updating LOBs some *major* magic has to be performed + behind the scenes to make it transparent. Basically the driver has to + insert a 'LOB Locator' and then refetch the newly inserted LOB Locator + before being able to write the data into it. However, it works well most + of the time, and I've made it as fast as possible, just one extra + server-round-trip per insert or update after the first. For the time + being, only single-row LOB updates are supported. + + To insert or update a large LOB using a placeholder, DBD::Oracle has to + know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + + The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + + or use the corresponding integer values (112 and 113). + + One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has to + be able to tell which parameters relate to which table fields. In all + cases where it can possibly work it out for itself, it does, however, if + there are multiple LOB fields of the same type in the table then you + need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + + There are some limitations inherent in the way DBD::Oracle makes typical + LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + + The alternative is to disable the automatic LOB Locator processing. If + "ora_auto_lob" is 0 in prepare(), you can fetch the LOB Locators and do + all the work yourself using the ora_lob_*() methods. See the "Data + Interface for LOB Locators" section below. + + LOB support in PL/SQL + LOB Locators can be passed to PL/SQL calls by binding them to + placeholders with the proper "ora_type". If "ora_auto_lob" is true, + output LOB parameters will be automatically returned as strings. + + If the Oracle driver has support for temporary LOBs (Oracle 9i and + higher), strings can be bound to input LOB placeholders and will be + automatically converted to LOBs. + + Example: # Build a large XML document, bind it as a CLOB, # extract + elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + + If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + + error, while attempting to insert a LOB, this means the Oracle user has + insufficient space for LOB you are trying to insert. One solution it to + use "alter database datafile 'sss.ggg' resize Mnnn" to increase the + available memory for LOBs. + + Persistent & Locator Interface Caveats + Now that one has the option of using the Persistent or the Locator + interface for LOBs the questions arises which one to use. For starters, + if you want to access LOBs over a dblink you will have to use the + Persistent interface so that choice is simple. The question of which one + to use after that is a little more tricky. It basically boils down to a + choice between LOB size and speed. + + The Callback and Polling piecewise fetches are very very slow when + compared to the Simple and the Locator fetches but they can handle very + large blocks of data. Given a situation where a large LOB is to be read + the Locator fetch may time out while either of the piecewise fetches may + not. + + With the Simple fetch you are limited by physical memory of your server + but it runs a little faster than the Locator, as there are fewer round + trips to the server. So if you have small LOBs and need to save a little + bandwidth this is the one to use. It you are going after large LOBs then + the Locator interface is the one to use. + + If you need to update more than a single row of with LOB data then the + Persistent interface can do it while the Locator can't. + + If you encounter a situation where you have to access the legacy LOBs + (LONG, LONG RAW) and the values are to large for you system then you can + use the Callback or Polling piecewise fetches to get all of the data. + + Not all of the Persistent interface has been implemented yet, the + following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + + Most of the time you should just use the "Locator Data Interface" as + this is in one that has the best combination of speed and size. + + All this being said if you are doing some critical programming I would + use the "Data Interface for LOB Locators" as this gives you very fine + grain control of your LOBs, of course the code for this will be somewhat + more involved. + + Data Interface for LOB Locators + The following driver-specific methods let you manipulate "LOB Locators" + directly. To select a LOB locator directly set the if the "ora_auto_lob" + attribute to false, or alternatively they can be returned via PL/SQL + procedure calls. + + (If using a DBI version earlier than 1.36 they must be called via the + func() method. Note that methods called via func() don't honour + RaiseError etc, and so it's important to check $dbh->err after each + call. It's recommended that you upgrade to DBI 1.38 or later.) + + Note that LOB locators are only valid while the statement handle that + created them is valid. When all references to the original statement + handle are lost, the handle is destroyed and the locators are freed. + + ora_lob_read + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + + Read a portion of the LOB. $offset starts at 1. Uses the Oracle + OCILobRead function. + + ora_lob_write + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + + Write/overwrite a portion of the LOB. $offset starts at 1. Uses the + Oracle OCILobWrite function. + + ora_lob_append + $rc = $dbh->ora_lob_append($lob_locator, $data); + + Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + + ora_lob_trim + $rc = $dbh->ora_lob_trim($lob_locator, $length); + + Trims the length of the LOB to $length. Uses the Oracle OCILobTrim + function. + + ora_lob_length + $length = $dbh->ora_lob_length($lob_locator); + + Returns the length of the LOB. Uses the Oracle OCILobGetLength + function. + + ora_lob_is_init + $is_init = $dbh->ora_lob_is_init($lob_locator); + + Returns true(1) if the Lob Locator is initialized false(0) if it is + not, or 'undef' if there is an error. Uses the Oracle + OCILobLocatorIsInit function. + + ora_lob_chunk_size + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + + Returns the chunk size of the LOB. Uses the Oracle + OCILobGetChunkSize function. + + For optimal performance, Oracle recommends reading from and writing + to a LOB in batches using a multiple of the LOB chunk size. In + Oracle 10g and before, when all defaults are in place, this chunk + size defaults to 8k (8192). + + LOB Locator Method Examples + *Note:* Make sure you first read the note in the section above about + multi-byte character set issues with these methods. + + The following examples demonstrate the usage of LOB Locators to read, + write, and append data, and to query the size of large data. + + The following examples assume a table containing two large object + columns, one binary and one character, with a primary key column, + defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + + It also assumes a sequence for use in generating unique lob_id field + values, defined as follows: + + CREATE SEQUENCE lob_example_seq + + Example: Inserting a new row with large data + Unless enough memory is available to store and bind the entire LOB data + for insert all at once, the LOB columns must be written interactively, + piece by piece. In the case of a new row, this is performed by first + inserting a row, with empty values in the LOB columns, then modifying + the row by writing the large data interactively to the LOB columns using + their LOB locators as handles. + + The insert statement must create token values in the LOB columns. Here, + we use the empty string for both the binary and character large object + columns 'bindata' and 'chardata'. + + After the INSERT statement, a SELECT statement is used to acquire LOB + locators to the 'bindata' and 'chardata' fields of the newly inserted + row. Because these LOB locators are subsequently written, they must be + acquired from a select statement containing the clause 'FOR UPDATE' (LOB + locators are only valid within the transaction that fetched them, so + can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + + In this example we demonstrate the use of ora_lob_write() interactively + to append data to the columns 'bin_data' and 'char_data'. Had we used + ora_lob_append(), we could have saved ourselves the trouble of keeping + track of the offset into the lobs. The snippet of code beneath the + comment 'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + + The scalar variables $offset and $length are no longer needed, because + ora_lob_append() keeps track of the offset for us. + + Example: Updating an existing row with large data + In this example, we demonstrate a technique for overwriting a portion of + a blob field with new binary data. The blob data before and after the + section overwritten remains unchanged. Hence, this technique could be + used for updating fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + + After running this code, the row where lob_id = 5 will contain, starting + at position 100234 in the bin_data column, the string "This string will + overwrite a portion of the blob". + + Example: Streaming character data from the database + In this example, we demonstrate a technique for streaming data from the + database to a file handle, in this case STDOUT. This allows more data to + be read in and written out than could be stored in memory at a given + time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + + Notice that the select statement does not contain the phrase "FOR + UPDATE". Because we are only reading from the LOB Locator returned, and + not modifying the LOB it refers to, the select statement does not + require the "FOR UPDATE" clause. + + A word of caution when using the data returned from an ora_lob_read in a + conditional statement. for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + + was used with a chunk size of 4096 against a blob that requires more + than 1 chunk to return the data and the last chunk is one byte long and + contains a zero (ASCII 48) you will miss this last byte as $data will + contain 0 which PERL will see as false and not print it out. + + Example: Truncating existing large data + In this example, we truncate the data already present in a large object + column in the database. Specifically, for each row in the table, we + truncate the 'bindata' value to half its previous length. + + After acquiring a LOB Locator for the column, we query its length, then + we trim the length by half. Because we modify the large objects with the + call to ora_lob_trim(), we must select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +SPACES AND PADDING + Trailing Spaces + Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder + values and uses Nonpadded Comparison Semantics with the result. This + causes trouble if the spaces are needed for comparison with a CHAR value + or to prevent the value from becoming '' which Oracle treats as NULL. + Look for Blank-padded Comparison Semantics and Nonpadded Comparison + Semantics in Oracle's SQL Reference or Server SQL Reference for more + details. + + To preserve trailing spaces in placeholder values for Oracle clients + that use OCI 8, either change the default placeholder type with + "ora_ph_type" or the placeholder type for a particular call to "bind" in + DBI or "bind_param_inout" in DBI with "ora_type" or "TYPE". Using + ORA_CHAR with ora_type or "SQL_CHAR" with "TYPE" allows the placeholder + to be used with Padded Comparison Semantics if the value it is being + compared to is a CHAR, NCHAR, or literal. + + Please remember that using spaces as a value or at the end of a value + makes visually distinguishing values with different numbers of spaces + difficult and should be avoided. + + Oracle Clients that use OCI 9.2 do not strip trailing spaces. + + Padded Char Fields + Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder + values to the size of the CHAR. As the default placeholder type value in + DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will have to + change the default placeholder type with "ora_ph_type" or placeholder + type for a particular call with "bind" in DBI or "bind_param_inout" in + DBI with "ORA_CHAR". + +UNICODE + DBD::Oracle now supports Unicode UTF-8. There are, however, a number of + issues you should be aware of, so please read all this section + carefully. + + In this section we'll discuss "Perl and Unicode", then "Oracle and + Unicode", and finally "DBD::Oracle and Unicode". + + Information about Unicode in general can be found at: + . It is well worth reading because there are + many misconceptions about Unicode and you may be holding some of them. + + Perl and Unicode + Perl began implementing Unicode with version 5.6, but the implementation + did not mature until version 5.8 and later. If you plan to use Unicode + you are *strongly* urged to use Perl 5.8.2 or later and to *carefully* + read the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + + And then read it again. + + Perl's internal Unicode format is UTF-8 which corresponds to the Oracle + character set called AL32UTF8. + + Oracle and Unicode + Oracle supports many characters sets, including several different forms + of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + + When you create an Oracle database, you must specify the DATABASE + character set (used for DDL, DML and CHAR datatypes) and the NATIONAL + character set (used for NCHAR and NCLOB types). The character sets used + in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + + The Oracle 9.2 and later default for the national character set is + AL16UTF16. The default for the database character set is often US7ASCII. + Although many experienced DBAs will consider an 8bit character set like + WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other + than US7ASCII, requires that the NLS_LANG environment variable be set. + See the "Oracle UTF8 is not UTF-8" section below. + + You are strongly urged to read the Oracle Internationalization + documentation specifically with respect the choices and trade offs for + creating a databases for use with international character sets. + + Oracle uses the NLS_LANG environment variable to indicate what character + set is being used on the client. When fetching data Oracle will convert + from whatever the database character set is to the client character set + specified by NLS_LANG. Similarly, when sending data to the database + Oracle will convert from the character set specified by NLS_LANG to the + database character set. + + The NLS_NCHAR environment variable can be used to define a different + character set for 'national' (NCHAR) character types. + + Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. For + example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + + Oracle UTF8 is not UTF-8 + AL32UTF8 should be used in preference to UTF8 if it works for you, which + it should for Oracle 9.2 or later. If you're using an old version of + Oracle that doesn't support AL32UTF8 then you should avoid using any + Unicode characters that require surrogates, in other words characters + beyond the Unicode BMP (Basic Multilingual Plane). + + That's because the character set that Oracle calls "UTF8" doesn't + conform to the UTF-8 standard in its handling of surrogate characters. + Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". + Here are a couple of extracts from + : + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + + Oracle uses this internally because it collates (sorts) in the same + order as UTF16, which is the basis of Oracle's internal collation + definitions. + + Rather than change UTF8 for clients Oracle chose to define a new + character set called "AL32UTF8" which does conform to the UTF-8 + standard. (The AL32UTF8 character set can't be used on the server + because it would break collation.) + + Because of that, for the rest of this document we'll use "AL32UTF8". If + you're using an Oracle version below 9.2 you'll need to use "UTF8" until + you upgrade. + + DBD::Oracle and Unicode + DBD::Oracle Unicode support has been implemented for Oracle versions 9 + or greater, and Perl version 5.6 or greater (though we *strongly* + suggest that you use Perl 5.8.2 or later). + + You can check which Oracle version your DBD::Oracle was built with by + importing the "ORA_OCI" constant from DBD::Oracle. + + Fetching Data + + Any data returned from Oracle to DBD::Oracle in the AL32UTF8 character + set will be marked as UTF-8 to ensure correct handling by Perl. + + For Oracle to return data in the AL32UTF8 character set the NLS_LANG or + NLS_NCHAR environment variable *must* be set as described in the + previous section. + + When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle + will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR is + AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + + When fetching other character data from Oracle, DBD::Oracle will set the + Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + + Sending Data using Placeholders + + Data bound to a placeholder is assumed to be in the default client + character set (specified by NLS_LANG) except for a few special cases. + These are listed here with the highest precedence first: + + If the "ora_csid" attribute is given to bind_param() then that is passed + to Oracle and takes precedence. + + If the value is a Perl Unicode string (UTF-8) then DBD::Oracle ensures + that Oracle uses the Unicode character set, regardless of the NLS_LANG + and NLS_NCHAR settings. + + If the placeholder is for inserting an NCLOB then the client NLS_NCHAR + character set is used. (That's useful but inconsistent with the other + behaviour so may change. Best to be explicit by using the "ora_csform" + attribute.) + + If the "ora_csform" attribute is given to bind_param() then that + determines if the value should be assumed to be in the default + (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + Binding with bind_param_array and execute_array is also UTF-8 compatible + in the same way. If you attempt to insert UTF-8 data into a non UTF-8 + Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert will + still happen but a error code of 0 will be returned with the following + warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + + The warning will report the parameter number and the NCHAR setting that + the query is running. + + Sending Data using SQL + + Oracle assumes the SQL statement is in the default client character set + (as specified by NLS_LANG). So Unicode strings containing non-ASCII + characters should not be used unless the default client character set is + AL32UTF8. + + DBD::Oracle and Other Character Sets and Encodings + The only multi-byte Oracle character set supported by DBD::Oracle is + "AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +OBJECT & COLLECTION DATA TYPES + Oracle databases allow for the creation of object oriented like + user-defined types. There are two types of objects, Embedded--an object + stored in a column of a regular table and REF--an object that uses the + REF retrieval mechanism. + + DBD::Oracle supports only the 'selection' of embedded objects of the + following types OBJECT, VARRAY and TABLE in any combination. Support is + seamless and recursive, meaning you need only supply a simple SQL + statement to get all the values in an embedded object. You can either + get the values as an array of scalars or they can be returned into a + DBD::Oracle::Object. + + Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + + The code to access all the data in the table could be something like + this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + + Note that values in PHONE_NUMBERS are returned as an array reference + '@$phone'. + + As stated before DBD::Oracle will automatically drill into the embedded + object and extract all of the data as reference arrays of scalars. The + example below has OBJECT type embedded in a TABLE type embedded in an + SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + + The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + + Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + + The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + + So far DBD::Oracle has been tested on a table with 20 embedded Objects, + Varrays and Tables nested to 10 levels. + + Any NULL values found in the embedded object will be returned as + 'undef'. + +OTHER DATA TYPES + DBD::Oracle does not *explicitly* support most Oracle datatypes. It + simply asks Oracle to return them as strings and Oracle does so. Mostly. + Similarly when binding placeholder values DBD::Oracle binds them as + strings and Oracle converts them to the appropriate type, such as DATE, + when used. + + Some of these automatic conversions to and from strings use NLS settings + to control the formatting for output and the parsing for input. The most + common example is the DATE type. The default NLS format for DATE might + be DD-MON-YYYY and so when a DATE type is fetched that's how Oracle will + format the date. NLS settings also control the default parsing of + strings into DATE values. An error will be generated if the contents of + the string don't match the NLS format. If you're dealing in dates which + don't match the default NLS format then you can either change the + default NLS format or, more commonly, use TO_CHAR(field, "format") and + TO_DATE(?, "format") to explicitly specify formats for converting to and + from strings. + + A slightly more subtle problem can occur with NUMBER types. The default + NLS settings might format numbers with a fullstop (""."") to separate + thousands and a comma ("","") as the decimal point. Perl will generate + warnings and use incorrect values when numbers, returned and formatted + as strings in this way by Oracle, are used in a numeric context. You + could explicitly convert each numeric value using the TO_CHAR(...) + function but that gets tedious very quickly. The best fix is to change + the NLS settings. That can be done for an individual connection by + doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + + There are some types, like BOOLEAN, that Oracle does not automatically + convert to or from strings (pity). These need to be converted explicitly + using SQL or PL/SQL functions. + + Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + + Support for Insert of XMLType (ORA_XMLTYPE) + Inserting large XML data sets into tables with XMLType fields is now + supported by DBD::Oracle. The only special requirement is the use of + bind_param() with an attribute hash parameter that specifies ora_type as + ORA_XMLTYPE. For example with a table like this; + + create table books (book_id number, book_xml XMLType); + + one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + + In the above case we will assume that $xml has 10000 Book nodes and is + over 32k in size and is well formed XML. This will also work for XML + that is smaller than 32k as well. Attempting to insert malformed XML + will cause an error. + + Binding Cursors + Cursors can be returned from PL/SQL blocks, either from stored functions + (or procedures with OUT parameters) or from direct "OPEN" statements, as + shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + The only special requirement is the use of "bind_param_inout()" with an + attribute hash parameter that specifies "ora_type" as "ORA_RSET". If you + don't do that you'll get an error from the "execute()" like: "ORA-06550: + line X, column Y: PLS-00306: wrong number or types of arguments in call + to ...". + + Here's an alternative form using a function that returns a cursor. This + example uses the pre-defined weak (or generic) REF CURSOR type + SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + A cursor obtained from PL/SQL as above may be passed back to PL/SQL by + binding for input, as shown in this example, which explicitly closes a + cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + + It is not normally necessary to close a cursor explicitly in this way. + Oracle will close the cursor automatically at the first client-server + interaction after the cursor statement handle is destroyed. An explicit + close may be desirable if the reference to the cursor handle from the + PL/SQL statement handle delays the destruction of the cursor handle for + too long. This reference remains until the PL/SQL handle is re-bound, + re-executed or destroyed. + + See the "curref.pl" script in the Oracle.ex directory in the DBD::Oracle + source distribution for a complete working example. + + Fetching Nested Cursors + Oracle supports the use of select list expressions of type REF CURSOR. + These may be explicit cursor expressions - "CURSOR(SELECT ...)", or + calls to PL/SQL functions which return REF CURSOR values. The values of + these expressions are known as nested cursors. + + The value returned to a Perl program when a nested cursor is fetched is + a statement handle. This statement handle is ready to be fetched from. + It should not (indeed, must not) be executed. + + Oracle imposes a restriction on the order of fetching when nested + cursors are used. Suppose $sth1 is a handle for a select statement + involving nested cursors, and $sth2 is a nested cursor handle fetched + from $sth1. $sth2 can only be fetched from while $sth1 is still active, + and the row containing $sth2 is still current in $sth1. Any attempt to + fetch another row from $sth1 renders all nested cursor handles + previously fetched from $sth1 defunct. + + Fetching from such a defunct handle results in an error with the message + "ERROR nested cursor is defunct (parent row is no longer current)". + + This means that the "fetchall..." or "selectall..." methods are not + useful for queries returning nested cursors. By the time such a method + returns, all the nested cursor handles it has fetched will be defunct. + + It is necessary to use an explicit fetch loop, and to do all the + fetching of nested cursors within the loop, as the following example + shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + + The cursor returned by the function "sp_ListEmp" defined in the previous + section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + + Pre-fetching Nested Cursors + By default, DBD::Oracle pre-fetches rows in order to reduce the number + of round trips to the server. For queries which do not involve nested + cursors, the number of pre-fetched rows is controlled by the DBI + database handle attribute "RowCacheSize" (q.v.). + + In Oracle, server side open cursors are a controlled resource, limited + in number, on a per session basis, to the value of the initialization + parameter "OPEN_CURSORS". Nested cursors count towards this limit. Each + nested cursor in the current row counts 1, as does each nested cursor in + a pre-fetched row. Defunct nested cursors do not count. + + An Oracle specific database handle attribute, "ora_max_nested_cursors", + further controls pre-fetching for queries involving nested cursors. For + each statement handle, the total number of nested cursors in pre-fetched + rows is limited to the value of this parameter. The default value is 0, + which disables pre-fetching for queries involving nested cursors. + +PL/SQL Examples + Most of these PL/SQL examples come from: Eric Bartley + . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + + You can find more examples in the t/plsql.t file in the DBD::Oracle + source directory. + + Oracle 9.2 appears to have a bug where a variable bound with + bind_param_inout() that isn't assigned to by the executed PL/SQL block + may contain garbage. See + + + Avoid Using "SQL Call" + Avoid using the "SQL Call" statement with DBD:Oracle as you might find + that DBD::Oracle will not raise an exception in some case. Specifically + if you use "SQL Call" to run a procedure all "No data found" exceptions + will be quietly ignored and returned as null. According to Oracle + support this is part of the same mechanism where; + + select (select * from dual where 0=1) from dual + + returns a null value rather than an exception. + +CONTRIBUTING + If you'd like DBD::Oracle to do something new or different the best way + to make that happen is to do it yourself and email to dbi-dev@perl.org a + patch of the source code (using 'diff' - see below) that shows the + changes. + + How to create a patch using Subversion + The DBD::Oracle source code is maintained using Subversion (a + replacement for CVS, see ). To access the + source you'll need to install a Subversion client. Then, to get the + source code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + + If it prompts for a username and password use your perl.org account if + you have one, else just 'guest' and 'guest'. The source code will be in + a new subdirectory called "trunk". + + To keep informed about changes to the source you can send an empty email + to dbd-oracle-changes-subscribe@perl.org after which you'll get an email + with the change log message and diff of each change checked-in to the + source. + + After making your changes you can generate a patch file, but before you + do, make sure your source is still upto date using: + + svn update + + If you get any conflicts reported you'll need to fix them first. Then + generate the patch file from within the "trunk" directory using: + + svn diff > foo.patch + + Read the patch file, as a sanity check, and then email it to + dbi-dev@perl.org. + + How to create a patch without Subversion + Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + + Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + + Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you + want. + + Test your changes and then remove all temporary files: + + make test && make distclean + + Go back to the directory you originally unpacked the distribution: + + cd .. + + Unpack *another* copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + + Then create a patch file by performing a recursive "diff" on the two top + level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + + Speak before you patch + For anything non-trivial or possibly controversial it's a good idea to + discuss (on dbi-dev@perl.org) the changes you propose before actually + spending time working on them. Otherwise you run the risk of them being + rejected because they don't fit into some larger plans you may not be + aware of. + + GitHub repository + A git mirror of the subversion is also available at + `https://github.com/yanick/DBD-Oracle`. + +Oracle Related Links +WHICH VERSION OF DBD::ORACLE IS FOR ME? + From version 1.25 onwards DBD::Oracle only support Oracle clients 9.2 or + greater. Support for ProC connections was dropped in 1.29. + + If you are still stuck with an older version of Oracle or its client you + might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + + As there are dozens of different versions of Oracle's clients this list + does not include all of them, just the major released versions of + Oracle. + + Note that one can still connect to any Oracle version with the older + DBD::Oracle versions the only problem you will have is that some of the + newer OCI and Oracle features available in later DBD::Oracle releases + will not be available to you. + + So to make a short story a little longer: + + 1 If you are using Oracle 7 or early 8 DB and you can manage to get a + 9 client and you can use any DBD::Oracle version. + + 2 If you have to use an Oracle 7 client then DBD::Oracle 1.17 should + work + + 3 Same thing for 8 up to R2, use 1.17, if you are lucky and have the + right patch-set you might go with 1.18. + + 4 For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. + Again this depends on your patch-set, If you run into trouble go + with 1.19 + + 5 After 9.2 you can use any version you want. + + 6 It seems that the 10g client can only connect to 9 and 11 DBs while + the 9 can go back to 7 and even get to 10. I am not sure what the + 11g client can connect to. + +BUGS AND LIMITATIONS + There is a known problem with the 11.2g Oracle client and the + "DBMS_LOB.GETLENGTH()" PL/SQL function. See + for the details. + +SEE ALSO + DBI http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in + the DBD::Oracle source distribution including the examples in the + Oracle.ex directory + + DBD::Oracle Tutorial + http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-ora + cle.html + + Oracle Instant Client + http://www.oracle.com/technology/tech/oci/instantclient/index.html + + Oracle on Linux + http://www.ixora.com.au/ + + Free Oracle Tools and Links + ora_explain supplied and installed with DBD::Oracle. + + http://www.orafaq.com/ + + http://vonnieda.org/oracletool/ + + Commercial Oracle Tools and Links + Assorted tools and references for general information. No + recommendation implied. + + http://www.platinum.com + + http://www.SoftTreeTech.com + + Also PL/Vision from RevealNet and Steven Feuerstein, and "Q" from + Savant Corporation. + +AUTHORS + DBI by Tim Bunce . + + The original "DBD::Oracle" was by Tim Bunce. Maintained as of release + 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the + auspice of the Pythian Group (). + +ACKNOWLEDGEMENTS + A great many people have helped with DBD::Oracle over the 17 years + between 1994 and 2011. Far too many to name, but we thank them all. Many + are named in the Changes file. + +COPYRIGHT + The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. + The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The + Pythian Group). Canada. The DBD::Oracle module is Copyright (c) 2011 + John Scoles. Canada. + + The DBD::Oracle module is free open source software; you can + redistribute it and/or modify it under the same terms as Perl 5. + +AUTHORS + * Tim Bunce + + * John Scoles + + * Yanick Champoux + +COPYRIGHT AND LICENSE + This software is copyright (c) 1994 by Tim Bunce. + + This is free software; you can redistribute it and/or modify it under + the same terms as the Perl 5 programming language system itself. diff --git a/README.mkdn b/README.mkdn new file mode 100644 index 00000000..efd36615 --- /dev/null +++ b/README.mkdn @@ -0,0 +1,4228 @@ +# NAME + +DBD::Oracle - Oracle database driver for the DBI module + +# VERSION + +version 1.38 + +# SYNOPSIS + + use DBI; + + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); + + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); + + # See the DBI module documentation for full details + + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); + +# DESCRIPTION + +DBD::Oracle is a Perl module which works with the DBI module to provide +access to Oracle databases. + +This documentation describes driver specific behaviour and restrictions. It is +not supposed to be used as the only reference for the user. In any case +consult the [DBI](http://search.cpan.org/perldoc?DBI) documentation first! + +# CONSTANTS + +- :ora_session_modes + +ORA_SYSDBA ORA_SYSOPER ORA_SYSASM + +- :ora_types + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +- SQLCS_IMPLICIT + +- SQLCS_NCHAR + +SQLCS_IMPLICIT and SQLCS_NCHAR are _character set form_ values. +See notes about Unicode elsewhere in this document. + +- SQLT_INT + +- SQLT_FLT + +These types are used only internally, and may be specified as internal +bind type for ORA_NUMBER_TABLE. See notes about ORA_NUMBER_TABLE elsewhere +in this document + +- ORA_OCI + +Oracle doesn't provide a formal API for determining the exact version +number of the OCI client library used, so DBD::Oracle has to go digging +(and sometimes has to more or less guess). The ORA_OCI constant +holds the result of that process. + +In string context ORA_OCI returns the full "A.B.C.D" version string. + +In numeric context ORA_OCI returns the major.minor version number +(8.1, 9.2, 10.0 etc). But note that version numbers are not actually +floating point and so if Oracle ever makes a release that has a two +digit minor version, such as `9.10` it will have a lower numeric +value than the preceding `9.9` release. So use with care. + +The contents and format of ORA_OCI are subject to change (it may, +for example, become a _version object_ in later releases). +I recommend that you avoid checking for exact values. + +- :ora_fetch_orient + + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE + +These constants are used to set the orientation of a fetch on a scrollable cursor. + +- :ora_exe_modes + + OCI_STMT_SCROLLABLE_READONLY + +- :ora_fail_over + + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + +# DBI CLASS METHODS + +## __connect__ + +This method creates a database handle by connecting to a database, and is the DBI equivalent of the "new" method. +To open a connection to an Oracle database you need to specify a database connection string (URL), username and password. + +The connection string is always of the form: "dbi:Oracle:" +There are several ways to identify a database: + +- 1 + +If the database is local, specifying the SID or service name will be enough. + +- 2 + +If the database is defined in a TNSNAMES.ORA file, you can use the service name given in the file + +- 3 + +To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: +//host[:port][/service_name] + +If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. + +The following examples show several ways a connection can be created: + + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); + + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); + + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); + + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); + +### OS authentication + +To connect to a local database with a user which has been set up to +authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): + + $dbh = DBI->connect('dbi:Oracle:','/',''); + +Note the lack of a connection name (use the ORACLE_SID environment +variable). If an explicit SID is used you will probably get an ORA-01004 error. + +That only works for local databases. (Authentication to remote Oracle +databases using your Unix login name without a password is possible +but it is not secure and not recommended so not documented here. + +### Oracle Environment Variables + +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). + +Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. + +To use them, specify either a local SID or service name, or a service name that is specified in the TNSNAMES.ORA file. + +Note that if you have *both* local and remote databases, and you have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO_TASK takes precedence over ORACLE_SID (i.e. you get connected to remote system). + +It is highly recommended not to rely on environment variables and to always explicitly specify the SID in the connection string. This can prevent serious mistakes such as dropping a schema in the wrong database, and generally makes debugging and troubleshooting easier. + +Also remember that depending on the operating system you are using the differing "ORACLE" environment variables may be case sensitive, so if you are not connecting as you should double check the case of both the variable and its value. + +### Timezones + +If the query is run through SQL*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. + +If the query is run locally, Oracle will return the time zone based on the "TZ" environment variable setting of the user running +the query. + +With local queries, you can change the time zone for a particular user by simply changing the setting of "TZ". To check the current setting, +issue the UNIX "date" command. + +### Oracle DRCP + +DBD::Oracle supports DRCP (Database Resident Connection Pool) so +if you have an 11.2 database and DRCP is enabled you can direct +all of your connections to it by adding ':POOLED' to the SID or +setting a connection attribute of ora_drcp, or set the SERVER=POOLED +when using a TNSENTRY style connection or even by setting an +environment variable ORA_DRCP. All of which are demonstrated below; + + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') + + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') + + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") + + if the ORA_DRCP environment variable is set then just this + + $dbh = DBI->connect('dbi:Oracle:DB','username','password') + +You can find a white paper on setting up DRCP and its advantages at [http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf](http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf). + +Please note that DRCP support in DBD::Oracle is relatively new so the +mechanics or its implementation are subject to change. + +### TAF (Transparent Application Failover) + +Transparent Application Failover (TAF) is the feature in OCI that +allows for clients to automatically reconnect to an instance in the +event of a failure of the instance. The reconnect happens +automatically from within the OCI (Oracle Call Interface) library. +DBD::Oracle now supports a callback function that will fire when a TAF +event takes place. The main use of the callback is to give your +program the opportunity to inform the user that a failover is taking +place. + +You will have to set up TAF on your instance before you can use this +callback. You can test your instance to see if you can use TAF +callback with + + $dbh->ora_can_taf(); + +If you try to set up a callback without it being enabled DBD::Oracle will croak. + +It is outside the scope of this documents to go through all of the +possible TAF situations you might want to set up but here is a simple +example: + +The TNS entry for the instance has had the following added to the +CONNECT_DATA section + + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) + +You will also have to create your own perl function that will be +called from the client. You can name it anything you want and it will +always be passed two parameters, the failover event value and the +failover type. You can also set a sleep value in case of failover +error and the OCI client will sleep for the specified seconds before it +attempts another event. + + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants + + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + + #create the perl TAF event function + + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ + + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); + + } + return 0; + } + +The TAF types are as follows + + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + +The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + +### Connect Attributes + +#### ora_ncs_buff_mtpl + +You can customize the size of the buffer when selecting LOBs with +the built-in AUTO Lob. The default value is 4 which is probably +excessive for most situations but is needed for backward +compatibility. If you not converting between a NCS on the DB and the +Client then you might want to set this to 1 to reduce memory usage. + +This value can also be specified with the `ORA_DBD_NCS_BUFFER` +environment variable in which case it sets the value at the connect +stage. + +#### ora_drcp + +For Oracle 11.2 or greater. + +Set to _1_ to enable DRCP. Can also be set via the `ORA_DRCP` environment variable. + +#### ora_drcp_class + +If you are using DRCP, you can set a CONNECTION_CLASS for your pools +as well. As sessions from a DRCP cannot be shared by users, you can +use this setting to identify the same user across different +applications. OCI will ensure that sessions belonging to a 'class' are +not shared outside the class'. + +The values for ora_drcp_class cannot contain a '*' and must be less +than 1024 characters. + +This value can be also be specified with the `ORA_DRCP_CLASS` +environment variable. + +#### ora_drcp_min + +This optional value specifies the minimum number of sessions that are +initially opened. New sessions are only opened after this value has +been reached. + +The default value is 4 and any value above 0 is valid. + +Generally, it should be set to the number of concurrent statements the +application is planning or expecting to run. + +This value can also be specified with the `ORA_DRCP_MIN` environment +variable. + +#### ora_drcp_max + +This optional value specifies the maximum number of sessions that can +be open at one time. Once reached no more sessions can be opened +until one becomes free. The default value is 40 and any value above 1 +is valid. You should not set this value lower than ora_drcp_min as +that will just waste resources. + +This value can also be specified with the `ORA_DRCP_MAX` environment +variable. + +#### ora_drcp_incr + +This optional value specifies the next increment for sessions to be +started if the current number of sessions are less than +ora_drcp_max. The default value is 2 and any value above 0 is +valid as long as the value of ora_drcp_min + ora_drcp_incr is not +greater than ora_drcp_max. + +This value can also be specified with the `ORA_DRCP_INCR` environment +variable. + +#### ora_taf + +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option to any _true_ value. + +#### ora_taf_function + +The name of the Perl subroutine that will be called from OCI when a +TAF event occurs. You must supply a perl function to use the callback +and it will always receive two parameters, the failover event value +and the failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + +#### ora_taf_sleep + +The amount of time in seconds the OCI client will sleep between attempting +successive failover events when the event is OCI_FO_ERROR. + +#### ora_session_mode + +The ora_session_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA_SYSASM authorization. +The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + +This is one case where setting ORACLE_SID may be useful since +connecting as SYSDBA or SYSOPER via SQL*Net is frequently disabled +for security reasons. + +Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + +It has been reported that this only works if `$dsn` does not contain +a SID so that Oracle then uses the value of ORACLE_SID (not +TWO_TASK) environment variable to connect to a local instance. Also +the username and password should be empty, and the user executing the +script needs to be part of the dba group or osdba group. + +#### ora_oratab_orahome + +Passing a true value for the ora_oratab_orahome attribute will make +DBD::Oracle change `$ENV{ORACLE_HOME}` to make the Oracle home directory +that specified in the `/etc/oratab` file _if_ the database to connect to +is specified as a SID that exists in the oratab file, and DBD::Oracle was +built to use the Oracle 7 OCI API (not Oracle 8+). + +#### ora_module_name + +After connecting to the database the value of this attribute is passed +to the SET_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL +package. This can be used to identify the application to the DBA for +monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + +The maximum size is 48 bytes. + +#### ora_driver_name + +For 11g and later you can now set the name of the driver layer using OCI. +Perl, Perl5, ApachePerl so on. Names starting with "ORA" are reserved. You +can enter up to 8 characters. If none is enter then this will default to +DBDOxxxx where xxxx is the current version number. This value can be +retrieved on the server side using V$SESSION_CONNECT_INFO or +GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + +#### ora_client_info + +Allows you to add any value (up to 64 bytes) to your session and it can be +retrieved on the server side from the `V$SESSION`a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + +#### ora_client_identifier + +Allows you to specify the user identifier in the session handle. + +Most useful for web applications as it can pass in the session user +name which might be different to the connection user name. Can be up +to 64 bytes long but do not to include the password for security +reasons and the first character of the identifier should not be +':'. This value can be retrieved on the server side using `V$SESSION` +view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + +#### ora_action + +Allows you to specify any string up to 32 bytes which may be retrieved +on the server side using `V$SESSION` view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + +#### ora_dbh_share + +Requires at least Perl 5.8.0 compiled with ithreads. + +Allows you to share +database connections between threads. The first connect will make the +connection, all following calls to connect with the same ora_dbh_share +attribute will use the same database connection. The value must be a +reference to a already shared scalar which is initialized to an empty +string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + +#### ora_envhp + +The first time a connection is made a new OCI 'environment' is +created by DBD::Oracle and stored in the driver handle. +Subsequent connects reuse (share) that same OCI environment +by default. + +The ora_envhp attribute can be used to disable the reuse of the OCI +environment from a previous connect. If the value is `0` then +a new OCI environment is allocated and used for this connection. + +The OCI environment holds information about the client side context, +such as the local NLS environment. By altering `%ENV` and setting +ora_envhp to 0 you can create connections with different NLS +settings. This is most useful for testing. + +#### ora_charset, ora_ncharset + +For oracle versions >= 9.2 you can specify the client charset and +ncharset with the ora_charset and ora_ncharset attributes. You +still need to pass `ora_envhp = 0` for all but the first connect. + +These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + +#### ora_verbose + +Use this value to enable DBD::Oracle only tracing. Simply either set +the ora_verbose attribute on the connect() method to the trace level +you desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + +or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + +In both cases the DBD::Oracle trace level is set to 6, which is the highest +level tracing most of the calls to OCI. + +#### ora_oci_success_warn + +Use this value to print otherwise silent OCI warnings that may happen +when an execute or fetch returns "Success With Info" or when you want +to tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + +#### ora_objects + +Use this value to enable extended embedded oracle objects mode. In extended: + +- 1 + +Embedded objects are returned as instance (including type-name etc.) instead of simple ARRAY. + +- 2 + +Determine object type for each instance. All object attributes are returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + +#### ora_ph_type + +The default placeholder datatype for the database session. +The `TYPE` or [ora_type](#pod_ora_type) attributes to L and +L override the datatype for individual placeholders. +The most frequent reason for using this attribute is to permit trailing spaces +in values passed by placeholders. + +Constants for the values allowed for this attribute can be imported using + + use DBD::Oracle qw(:ora_types); + +Only the following values are permitted for this attribute. + +- ORA_VARCHAR2 + +Oracle clients using OCI 8 will strip trailing spaces and allow embedded \0 bytes. +Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \0 bytes. +This is the normal default placeholder type. + +- ORA_STRING + +Do not strip trailing spaces and end the string at the first \0. + +- ORA_CHAR + +Do not strip trailing spaces and allow embedded \0. +Force 'blank-padded comparison semantics'. + +For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + +Will pad bloggs out to 8 characters and return the username. + +#### ora_parse_error_offset + +If the previous error was from a failed `prepare` due to a syntax error, +this attribute gives the offset into the `Statement` attribute where the +error was found. + +#### ora_array_chunk_size + +Due to OCI limitations, DBD::Oracle needs to buffer up rows of +bind values in its `execute_for_fetch` implementation. This attribute +sets the number of rows to buffer at a time (default value is 1000). + +The `execute_for_fetch` function will collect (at most) this many +rows in an array, send them off to the DB for execution, then go back +to collect the next chunk of rows and so on. This attribute can be +used to limit or extend the number of rows processed at a time. + +Note that this attribute also applies to `execute_array`, since that +method is implemented using `execute_for_fetch`. + +#### ora_connect_with_default_signals + +Sometimes the Oracle client seems to change some of the signal +handlers of the process during the connect phase. For instance, some +users have observed Perl's default `$SIG{INT}` handler being ignored +after connecting to an Oracle database. If this causes problems in +your application, set this attribute to an array reference of signals +you would like to be localized during the connect process. Once the +connect is complete, the signal handlers should be returned to their +previous state. + +For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + +NOTE disabling the signal handlers the OCI library sets up may affect +functionality in the OCI library. + +NOTE If you are using connect_cached then the above example will lead +to DBI thinking each connection is different as an anonymous array reference +is being used. To avoid this when using connect_cached you are advised +to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + +In more recent Perl versions you could possibly make use of new state +variables. + +## __connect_cached__ + +Implemented by DBI, no driver-specific impact. +Please note that connect_cached as not been tested with DRCP. + +## __data_sources__ + + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + +Returns a list of available databases. You will have to set either the 'ORACLE_HOME' or +'TNS_ADMIN' environment value to retrieve this list. It will read these values from +TNSNAMES.ORA file entries. + +# METHODS COMMON TO ALL HANDLES + +For all of the methods below, __$h__ can be either a database handle (__$dbh__) +or a statement handle (__$sth__). Note that _$dbh_ and _$sth_ can be replaced with +any variable name you choose: these are just the names most often used. Another +common variable used in this documentation is $_rv_, which stands for "return value". + +## __err__ + + $rv = $h->err; + +Returns the error code from the last method called. + +## __errstr__ + + $str = $h->errstr; + +Returns the last error that was reported by Oracle. Starting with "ORA-00000" code followed by the error message. + +## __state__ + + $str = $h->state; + +Oracle hasn't supported SQLSTATE since the early versions OCI. It will return empty when the command succeeds and +'S1000' (General Error) for all other errors. + +While this method can be called as either `$sth->state` or `$dbh->state`, it +is usually clearer to always use `$dbh->state`. + +## __trace__ + +Implemented by DBI, no driver-specific impact. + +## __trace_msg__ + +Implemented by DBI, no driver-specific impact. + +## __parse_trace_flag__ and __parse_trace_flags__ + +Implemented by DBI, no driver-specific impact. + +## __func__ + +DBD::Oracle uses the `func` method to support a variety of functions. + +## __Private database handle functions__ + +Some of these functions are called through the method func() +which is described in the DBI documentation. Any function that begins with ora_ +can be called directly. + +## __plsql_errstr__ + +This function returns a string which describes the errors +from the most recent PL/SQL function, procedure, package, +or package body compile in a format similar to the output +of the SQL*Plus command 'show errors'. + +The function returns undef if the error string could not +be retrieved due to a database error. +Look in $dbh->errstr for the cause of the failure. + +If there are no compile errors, an empty string is returned. + +Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + +## __dbms_output_enable / dbms_output_put / dbms_output_get__ + +These functions use the PL/SQL DBMS_OUTPUT package to store and +retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer +by dbms_output_put or any PL/SQL block can be retrieved by +dbms_output_get or any PL/SQL block connected to the same database +session. + +Stored text is not available until after dbms_output_put or the PL/SQL +block that saved it completes its execution. This means you __CAN NOT__ +use these functions to monitor long running PL/SQL procedures. + +Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + +Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + +## __dbms_output_enable ( [ buffer_size ] )__ + +This function calls DBMS_OUTPUT.ENABLE to enable calls to package +DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to +these procedures are ignored unless DBMS_OUTPUT.ENABLE is called +first. + +The buffer_size is the maximum amount of text that can be saved in the +buffer and must be between 2000 and 1,000,000. If buffer_size is not +given, the default is 20,000 bytes. + +## __dbms_output_put ( [ @lines ] )__ + +This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + +If all lines were saved successfully the function returns 1. Depending +on the context, an empty list or undef is returned for failure. + +If any line causes buffer_size to be exceeded, a buffer overflow error +is raised and the function call fails. Some of the text might be in +the buffer. + +## __dbms_output_get__ + +This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from +the buffer. + +In an array context, all complete lines are removed from the buffer and +returned as a list. If there are no complete lines, an empty list is +returned. + +In a scalar context, the first complete line is removed from the buffer +and returned. If there are no complete lines, undef is returned. + +Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or +DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, +DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + +## __reauthenticate ( $username, $password )__ + +Starts a new session against the current database using the credentials +supplied. + +## __private_attribute_info__ + + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + +Returns a hash of all private attributes used by DBD::Oracle, for either +a database or a statement handle. Currently, all the hash values are undef. + +# ATTRIBUTES COMMON TO ALL HANDLES + +## __InactiveDestroy__ (boolean) + +Implemented by DBI, no driver-specific impact. + +## __RaiseError__ (boolean, inherited) + +Forces errors to always raise an exception. Although it defaults to off, it is recommended that this +be turned on, as the alternative is to check the return value of every method (prepare, execute, fetch, etc.) +manually, which is easy to forget to do. + +## __PrintError__ (boolean, inherited) + +Forces database errors to also generate warnings, which can then be filtered with methods such as +locally redefining _$SIG{__WARN__}_ or using modules such as `CGI::Carp`. This attribute is on +by default. + +## __ShowErrorStatement__ (boolean, inherited) + +Appends information about the current statement to error messages. If placeholder information +is available, adds that as well. Defaults to true. + +## __Warn__ (boolean, inherited) + +Enables warnings. This is on by default, and should only be turned off in a local block +for a short a time only when absolutely needed. + +## __Executed__ (boolean, read-only) + +Indicates if a handle has been executed. For database handles, this value is true after the [do](#pod_do) method has been called, or +when one of the child statement handles has issued an [execute](#pod_execute). Issuing a [commit](#pod_commit) or [rollback](#pod_rollback) always resets the +attribute to false for database handles. For statement handles, any call to [execute](#pod_execute) or its variants will flip the value to +true for the lifetime of the statement handle. + +## __TraceLevel__ (integer, inherited) + +Sets the trace level, similar to the [trace](#pod_trace) method. See the sections on +[trace](#pod_trace) and [parse_trace_flag](#pod_parse_trace_flag) for more details. + +## __Active__ (boolean, read-only) + +Indicates if a handle is active or not. For database handles, this indicates if the database has +been disconnected or not. For statement handles, it indicates if all the data has been fetched yet +or not. Use of this attribute is not encouraged. + +## __Kids__ (integer, read-only) + +Returns the number of child processes created for each handle type. For a driver handle, indicates the number +of database handles created. For a database handle, indicates the number of statement handles created. For +statement handles, it always returns zero, because statement handles do not create kids. + +## __ActiveKids__ (integer, read-only) + +Same as `Kids`, but only returns those that are active. + +## __CachedKids__ (hash ref) + +Returns a hashref of handles. If called on a database handle, returns all statement handles created by use of the +`prepare_cached` method. If called on a driver handle, returns all database handles created by the [connect_cached](#pod_connect_cached) +method. + +## __ChildHandles__ (array ref) + +Implemented by DBI, no driver-specific impact. + +## __PrintWarn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleError__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleSetErr__ (code ref, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ErrCount__ (unsigned integer) + +Implemented by DBI, no driver-specific impact. + +## __FetchHashKeyName__ (string, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ChopBlanks__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Taint__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintIn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintOut__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Profile__ (inherited) + +Implemented by DBI, no driver-specific impact. + +## __Type__ (scalar) + +Returns `dr` for a driver handle, `db` for a database handle, and `st` for a statement handle. +Should be rarely needed. + +## __LongReadLen__ + +Implemented by DBI, no driver-specific impact. + +## __LongTruncOk__ + +Implemented by DBI, no driver-specific impact. + +## __CompatMode__ + +Type: boolean, inherited + +The CompatMode attribute is used by emulation layers (such as Oraperl) to enable compatible behaviour in the underlying driver (e.g., DBD::Oracle) for this handle. Not normally set by application code. + +It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. + +# ORACLE-SPECIFIC DATABASE HANDLE METHODS + +## __ora_can_unicode ( [ $refresh ] )__ + +Returns a number indicating whether either of the database character sets +is a Unicode encoding. Calls ora_nls_parameters() and passes the optional +$refresh parameter to it. + +0 = Neither character set is a Unicode encoding. + +1 = National character set is a Unicode encoding. + +2 = Database character set is a Unicode encoding. + +3 = Both character sets are Unicode encodings. + +## __ora_can_taf__ + +Returns true if the current connection supports TAF events. False if otherise. + +## __ora_nls_parameters ( [ $refresh ] )__ + +Returns a hash reference containing the current NLS parameters, as given +by the v$nls_parameters view. The values fetched are cached between calls. +To cause the latest values to be fetched, pass a true value to the function. + +# DATABASE HANDLE METHODS + +## __selectall_arrayref__ + + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectall_hashref__ + + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + +Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectcol_arrayref__ + + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the first column +from each rows returned by preparing and executing the SQL string. It is possible to specify exactly +which columns to return. See the DBI documentation for full details. + +## __prepare__ + + $sth = $dbh->prepare($statement, \%attr); + +Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. + +### __Prepare Attributes__ + +These attributes may be used in the `\%attr` parameter of the +L database handle method. + +- ora_placeholders + +Set to false to disable processing of placeholders. Used mainly for loading a +PL/SQL package that has been _wrapped_ with Oracle's `wrap` utility. + +- ora_auto_lob + +If true (the default), fetching retrieves the contents of the CLOB or +BLOB column in most circumstances. If false, fetching retrieves the +Oracle "LOB Locator" of the CLOB or BLOB value. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for more details. + +See also the LOB tests in 05dbi.t of Oracle::OCI for examples +of how to use LOB Locators. + +- ora_pers_lob + +If true the [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) method for the [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) will be +used for LOBs rather than the default method [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators). + +- ora_clbk_lob + +If true the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) method for the L will be used for LOBs. + +- ora_piece_lob + +If true the [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) method for the L will be used for LOBs. + +- ora_piece_size + +This is the max piece size for the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) +and [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) methods, in chars for CLOBS, and +bytes for BLOBS. + +- ora_check_sql + +If 1 (default), force SELECT statements to be described in prepare(). +If 0, allow SELECT statements to defer describe until execute(). + +See [Prepare Postponed Till Execute](#pod_Prepare Postponed Till Execute) for more information. + +- ora_exe_mode + +This will set the execute mode of the current statement. Presently +only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + +See [Scrollable Cursors](#pod_Scrollable Cursors) for more details. + +- ora_prefetch_rows + +Sets the number of rows to be prefetched. If it is not set, then the +default value is 1. See [Row Prefetching](#pod_Row Prefetching) for more details. + +- ora_prefetch_memory + +Sets the memory level for rows to be prefetched. The application then +fetches as many rows as will fit into that much memory. See L for more details. + +- ora_row_cache_off + +By default DBD::Oracle will use a row cache when fetching to cut down +the number of round trips to the server. If you do not want to use an +array fetch set this value to any value other than 0; + +See [Row Prefetching](#pod_Row Prefetching) for more details. + +### __Placeholders__ + +There are two types of placeholders that can be used in DBD::Oracle. The first is +the "question mark" type, in which each placeholder is represented by a single +question mark character. This is the method recommended by the DBI specs and is the most +portable. Each question mark is internally replaced by a "dollar sign number" in the order +in which they appear in the query (important when using [bind_param](#pod_bind_param)). + +The other placeholder type is "named parameters" in the format ":foo" which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + +The different types of placeholders cannot be mixed within a statement, but you may +use different ones for each statement handle you have. This is confusing at best, so +stick to one style within your program. + +## __prepare_cached__ + + $sth = $dbh->prepare_cached($statement, \%attr); + +Implemented by DBI, no driver-specific impact. This method is most useful +if the same query is used over and over as it will cut down round trips to the server. + +## __do__ + + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + +Prepare and execute a single statement. Returns the number of rows affected if the +query was successful, returns undef if an error occurred, and returns -1 if the +number of rows is unknown or not available. Note that this method will return __0E0__ instead +of 0 for 'no rows were affected', in order to always return a true value if no error occurred. + +## __last_insert_id__ + +Oracle does not implement auto_increment of serial type columns it uses predefined +sequences where the id numbers are either selected before insert, at insert time with a trigger, + or as part of the query. + +Below is an example of you to use the latter with the SQL returning clause to get the ID number back +on insert with the bind_param_inout method. +. + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + +## __commit__ + + $rv = $dbh->commit; + +Issues a COMMIT to the server, indicating that the current transaction is finished and that +all changes made will be visible to other processes. If AutoCommit is enabled, then +a warning is given and no COMMIT is issued. Returns true on success, false on error. + +## __rollback__ + + $rv = $dbh->rollback; + +Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit +is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and +false on error. + +## __begin_work__ + +This method turns on transactions until the next call to [commit](#pod_commit) or [rollback](#pod_rollback), if [AutoCommit](#pod_AutoCommit) is +currently enabled. If it is not enabled, calling begin_work will issue an error. Note that the +transaction will not actually begin until the first statement after begin_work is called. + +## __disconnect__ + + $rv = $dbh->disconnect; + +Disconnects from the Oracle database. Any uncommitted changes will be rolled back upon disconnection. It's +good policy to always explicitly call commit or rollback at some point before disconnecting, rather than +relying on the default rollback behavior. + +If the script exits before disconnect is called (or, more precisely, if the database handle is no longer +referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() +methods automatically. It is best to explicitly disconnect rather than rely on this behavior. + +## __ping__ + + $rv = $dbh->ping; + +This `ping` method is used to check the validity of a database handle. The value returned is +either 0, indicating that the connection is no longer valid, or 1, indicating the connection is valid. +This function does 1 round trip to the Oracle Server. + +## __get_info()__ + + $value = $dbh->get_info($info_type); + +DBD::Oracle supports `get_info()`, but (currently) only a few info types. + +## __table_info()__ + +DBD::Oracle supports attributes for `table_info()`. + +In Oracle, the concept of _user_ and _schema_ is (currently) the +same. Because database objects are owned by an user, the owner names +in the data dictionary views correspond to schema names. +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. + +Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + +TABLE_TYPE may contain a comma-separated list of table types. +The following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + +The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + +The special enumerations of catalogues, schemas and table types are +supported. However, TABLE_CAT is always NULL. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +`table_info()` performs a case-sensitive search. So, a selection +criterion should respect upper and lower case. +Normally, an identifier is case-insensitive. Oracle stores and +returns it in upper case. Sometimes, database objects are created +with quoted identifiers (for reserved words, mixed case, special +characters, ...). Such an identifier is case-sensitive (if not all +upper case). Oracle stores and returns it as given. +`table_info()` has no special quote handling, neither adds nor +removes quotes. + +## __primary_key_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary key constraint was created without an identifier, +PK_NAME contains a system generated name with the form SYS_Cn. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __foreign_key_info()__ + +This method (currently) supports the extended behaviour of SQL/CLI, i.e. the +result set contains foreign keys that refer to primary __and__ alternate keys. +The field UNIQUE_OR_PRIMARY distinguishes these keys. + +Oracle does not support catalogues, so `$pk_catalog` and `$fk_catalog` are +ignored as selection criteria (in the new style interface). +The UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always +NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary or foreign key constraints were created without an identifier, +UK_NAME or FK_NAME contains a system generated name with the form SYS_Cn. + +The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle (currently) +does not support other actions. + +The DELETE_RULE field may contain wrong values. This is a known Bug (#1271663) +in Oracle's data dictionary views. Currently (as of 8.1.7), 'RESTRICT' and +'SET DEFAULT' are not supported, 'CASCADE' is mapped correctly and all other +actions (incl. 'SET NULL') appear as 'NO ACTION'. + +The DEFERABILITY field is always NULL, because this columns is +not present in the ALL_CONSTRAINTS view of older Oracle releases. + +The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, +FK_TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __column_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + +Don't rely on the values of the BUFFER_LENGTH field! +Especially the length of FLOATs may be wrong. + +Datatype codes for non-standard types are subject to change. + +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +It is possible with Oracle to make the names of the various DB objects (table,column,index etc) +case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + +So in the example the exact case "Bla_BLA" must be used to get it info on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + +any case can be used to get info on the column. + +## __selectrow_array__ + + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + +Returns an array of row information after preparing and executing the provided SQL string. The rows are returned +by calling [fetchrow_array](#pod_fetchrow_array). The string can also be a statement handle generated by a previous prepare. Note that +only the first row of data is returned. If called in a scalar context, only the first column of the first row is +returned. Because this is not portable, it is not recommended that you use this method in that way. + +## __selectrow_arrayref__ + + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an array, by internal use of +the [fetchrow_arrayref](#pod_fetchrow_arrayref) method. + +## __selectrow_hashref__ + + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an hash, by internal use of +the [fetchrow_hashref](#pod_fetchrow_hashref) method. + +## __clone__ + + $other_dbh = $dbh->clone(); + +Creates a copy of the database handle by connecting with the same parameters as the original +handle, then trying to merge the attributes. See the DBI documentation for complete usage. + +# DATABASE HANDLE ATTRIBUTES + +## __AutoCommit__ (boolean) + +Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change +in the future, so it is highly recommended that you explicitly set it when +calling [connect](#pod_connect). + +## __ReadOnly__ (boolean) + + $dbh->{ReadOnly} = 1; + +Specifies if the current database connection should be in read-only mode or not. + +Please not that this method is not foolproof: there are still ways to update the +database. Consider this a safety net to catch applications that should not be +issuing commands such as INSERT, UPDATE, or DELETE. + +This method method requires DBI version 1.55 or better. + +## __Name__ (string, read-only) + +Returns the name of the current database. This is the same as the DSN, without the +"dbi:Oracle:" part. + +## __Username__ (string, read-only) + +Returns the name of the user connected to the database. + +## __Driver__ (handle, read-only) + +Holds the handle of the parent driver. The only recommended use for this is to find the name +of the driver using: + + $dbh->{Driver}->{Name} + +## __RowCacheSize__ + +DBD::Oracle supports both Server pre-fetch and Client side row caching. By default both +are turned on to give optimum performance. Most of the time one can just let DBD::Oracle +figure out the best optimization. + +### __Row Caching__ + +Row caching occurs on the client side and the object of it is to cut down the number of round +trips made to the server when fetching rows. At each fetch a set number of rows will be retrieved +from the server and stored locally. Further calls the server are made only when the end of the +local buffer(cache) is reached. + +Rows up to the specified top level row +count `RowCacheSize` are fetched if it occupies no more than the specified memory usage limit. +The default value is 0, which means that memory size is not included in computing the number of rows to prefetch. If +the `RowCacheSize` value is set to a negative number then the positive value of RowCacheSize is used +to compute the number of rows to prefetch. + +By default `RowCacheSize` is automatically set. If you want to totally turn off prefetching set this to 1. + +For any SQL statement that contains a LOB, Long or Object Type Row Caching will be turned off. However server side +caching still works. If you are only selecting a LOB Locator then Row Caching will still work. + +### Row Prefetching + +Row prefetching occurs on the server side and uses the DBI database handle attribute `RowCacheSize` and or the +Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improved performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. + +The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first +fetch that sets the current_positon to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are +loaded into the buffer and DBD::Oracle will not have to go back to the server for more rows. When record 11 is fetched DBD::Oracle +fetches and returns this row and the next 9 rows are loaded into the buffer. In this case if you fetch backwards from 10 to 1 +no server round trips are made. + +With large record sets it is best not to attempt to go to the last record as this may take some time, A large buffer size might even slow down +the fetch. If you must get the number of rows in a large record set you might try using an few large OCI_FETCH_ABSOLUTEs and then an OCI_FETCH_LAST, +this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. +If one requires only the first few rows there is no need to set a large prefetch value. + +If the ora_prefetch_memory less than 1 or not present then memory size is not included in computing the +number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it +is not included in the computing of the prefetch rows. + +# ORACLE-SPECIFIC STATEMENT HANDLE METHODS + +## __ora_stmt_type__ + +Returns the OCI Statement Type number for the SQL of a statement handle. + +## __ora_stmt_type_name__ + +Returns the OCI Statement Type name for the SQL of a statement handle. + +# DBI STATEMENT HANDLE OBJECT METHODS + +## __bind_param__ + + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + +Allows the user to bind a value and/or a data type to a placeholder. + +The value of `$param_num` is a number if using the '?' or if using ":foo" style placeholders, the complete name +(e.g. ":foo") must be given. +The `$bind_value` argument is fairly self-explanatory. A value of `undef` will +bind a `NULL` to the placeholder. Using `undef` is useful when you want +to change just the type and will be overwriting the value later. +(Any value is actually usable, but `undef` is easy and efficient). + +The `\%attr` hash is used to indicate the data type of the placeholder. +The default value is "varchar". If you need something else, you must +use one of the values provided by DBI or by DBD::Pg. To use a SQL value, +modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + +This will import some constants into your script. You can plug those +directly into the [bind_param](#pod_bind_param) call. Some common ones that you will +encounter are: + + SQL_INTEGER + +To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + +You can then set the data types by setting the value of the `ora_type` +key in the hash passed to [bind_param](#pod_bind_param). +The current list of Oracle data types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +Data types are "sticky," in that once a data type is set to a certain placeholder, +it will remain for that placeholder, unless it is explicitly set to something +else afterwards. If the statement has already been prepared, and you switch the +data type to something else, DBD::Oracle will re-prepare the statement for you before +doing the next execute. + +Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + +These attributes may be used in the `\%attr` parameter of the +L or L statement handle methods. + +- ora_type + +Specify the placeholder's datatype using an Oracle datatype. +A fatal error is raised if `ora_type` and the DBI `TYPE` attribute +are used for the same placeholder. +Some of these types are not supported by the current version of +DBD::Oracle and will cause a fatal error if used. +Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + +Potentially useful values when DBD::Oracle was built using OCI 7 and later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + +Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + +Additional values when DBD::Oracle was built using OCI 9.2 and later: + + SQLT_CHR, SQLT_BIN + +See [Binding Cursors](#pod_Binding Cursors) for the correct way to use ORA_RSET. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for how to use ORA_CLOB and ORA_BLOB. + +See [SYS.DBMS_SQL datatypes](#pod_SYS.DBMS_SQL datatypes) for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. + +See [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) for the correct way to use SQLT_CHR and SQLT_BIN. + +See [Other Data Types](#pod_Other Data Types) for more information. + +See also L. + +- ora_csform + +Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values +are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can +be imported from the DBD::Oracle module. Rarely needed. + +- ora_csid + +Specify the _integer_ OCI_ATTR_CHARSET_ID for the bind value. +Character set names can't be used currently. + +- ora_maxdata_size + +Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. +May be needed if a character set conversion from client to server +causes the data to use more space and so fail with a truncation error. + +- ora_maxarray_numentries + +Specify the maximum number of array entries to allocate. Used with +ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of +array entries Oracle can pass back to you in OUT variable of type +TABLE OF ... . + +- ora_internal_type + +Specify internal data representation. Currently is supported only for +ORA_NUMBER_TABLE. + +### Optimizing Results + +#### Prepare Postponed Till Execute + +The DBD::Oracle module can avoid an explicit 'describe' operation +prior to the execution of the statement unless the application requests +information about the results (such as $sth->{NAME}). This reduces +communication with the server and increases performance (reducing the +number of PARSE_CALLS inside the server). + +However, it also means that SQL errors are not detected until +`execute()` (or $sth->{NAME} etc) is called instead of when +`prepare()` is called. Note that if the describe is triggered by the +use of $sth->{NAME} or a similar attribute and the describe fails then +_an exception is thrown_ even if `RaiseError` is false! + +Set [ora_check_sql](#pod_ora_check_sql) to 0 in prepare() to enable this behaviour. + +## __bind_param_inout__ + + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + +DBD::Oracle fully supports bind_param_inout below are some uses for this method. + +### __Returning A Value from an INSERT__ + +Oracle supports an extended SQL insert syntax which will return one +or more of the values inserted. This can be particularly useful for +single-pass insertion of values with re-used sequence values +(avoiding a separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + +If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + +If you have many rows to insert you can take advantage of Oracle's built in execute array feature +with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + +Which will return all the ids into @out_values. + +- __Note:__ + +- This will only work for numbered (?) placeholders, + +- The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle + +- The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + +### Returning A Recordset + +DBD::Oracle does not currently support binding a PL/SQL table (aka array) +as an IN OUT parameter to any Perl data structure. You cannot therefore call +a PL/SQL function or procedure from DBI that uses a non-atomic datatype as +either a parameter, or a return value. However, if you are using Oracle 9.0.1 +or later, you can make use of table (or pipelined) functions. + +For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + +Currently, there is no way to directly call the function +Array_Example.Array_Func from DBI. However, by making the following relatively +painless additions, its not only possible, but extremely efficient. + +First, you need to create database object types that correspond to the record +and table types in the package. From the above example, these would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + +Now, assuming the existing function needs to remain unchanged (it is probably +being called from other PL/SQL code), we need to add a new function to the +package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + +As you can see, the new function is very simple. Now, it is a simple matter +of calling the function as a straight-forward SELECT from your DBI code. From +the above example, the code would look something like this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + +### __SYS.DBMS_SQL datatypes__ + +DBD::Oracle has built-in support for __SYS.DBMS_SQL.VARCHAR2_TABLE__ +and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +- __Note:__ + +- Take careful note that we use '\\@arr' here because the 'bind_param_inout' + will only take a reference to a scalar. + +### __ORA_VARCHAR2_TABLE__ + +SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. +( in bind_param() and bind_param_inout() ). When you bind array, you need +to specify full buffer size for OUT data. So, there are two parameters: +_max_len_ (specified as 3rd argument of bind_param_inout() ), +and _ora_maxarray_numentries_. They define maximum array entry length and +maximum rows, that can be passed to Oracle and back to you. In this +example we send array with 1 element with length=3, but allocate space for 100 +Oracle array entries with maximum length 10 of each. So, you can get no more +than 100 array entries with length <= 10. + +If you set _max_len_ to zero, maximum array entry length is calculated +as maximum length of entry of array bound. If 0 < _max_len_ < length( $some_element ), +truncation occur. + +If you set _ora_maxarray_numentries_ to zero, current (at bind time) bound +array length is used as maximum. If 0 < _ora_maxarray_numentries_ < scalar(@array), +not all array entries are bound. + +### __ORA_NUMBER_TABLE__ + +SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. +The main difference is internal data representation. Currently 2 types of +bind is allowed : as C-integer, or as C-double type. To select one of them, +you may specify additional bind parameter _ora_internal_type_ as either +__SQLT_INT__ or __SQLT_FLT__ for C-integer and C-double types. +Integer size is architecture-specific and is usually 32 or 64 bit. +Double is standard IEEE 754 type. + +_ora_internal_type_ defaults to double (SQLT_FLT). + +_max_len_ is ignored for OCI_NUMBER_TABLE. + +Currently, you cannot bind full native Oracle NUMBER(38). If you really need, +send request to dbi-dev list. + +The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + +If you change bind type to __SQLT_INT__, like: + + ora_internal_type => SQLT_INT + +you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + +## __bind_param_inout_array__ + +DBD::Oracle supports this undocumented feature of DBI. See [Returning A Value from an INSERT](#pod_Returning A Value from an INSERT) for an example. + +## __bind_param_array__ + + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + +Binds an array of values to a placeholder, so that each is used in turn by a call +to the [execute_array](#pod_execute_array) method. + +## __execute__ + + $rv = $sth->execute(@bind_values); + +Perform whatever processing is necessary to execute the prepared statement. + +## __execute_array__ + + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + +Execute a prepared statement once for each item in a passed-in hashref, or items that +were previously bound via the [bind_param_array](#pod_bind_param_array) method. See the DBI documentation +for more details. + +DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very +quickly. + +## __execute_for_fetch__ + + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + +Used internally by the [execute_array](#pod_execute_array) method, and rarely used directly. See the +DBI documentation for more details. + +## __fetchrow_arrayref__ + + $ary_ref = $sth->fetchrow_arrayref; + +Fetches the next row of data from the statement handle, and returns a reference to an array +holding the column values. Any columns that are NULL are returned as undef within the array. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +Note that the same array reference is returned for each fetch, so don't store the reference and +then use it after a later fetch. Also, the elements of the array are also reused for each row, +so take care if you want to take a reference to an element. See also [bind_columns](#pod_bind_columns). + +## __fetchrow_array__ + + @ary = $sth->fetchrow_array; + +Similar to the [fetchrow_arrayref](#pod_fetchrow_arrayref) method, but returns a list of column information rather than +a reference to a list. Do not use this in a scalar context. + +## __fetchrow_hashref__ + + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + +Fetches the next row of data and returns a hashref containing the name of the columns as the keys +and the data itself as the values. Any NULL value is returned as as undef value. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +The optional `$name` argument should be either `NAME`, `NAME_lc` or `NAME_uc`, and indicates +what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. + +## __fetchall_arrayref__ + + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + +Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the +statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, +the data read in so far will be returned. Because of this, you should always check `$sth->err` after +calling this method, unless [RaiseError](#pod_RaiseError) has been enabled. + +If `$slice` is an array reference, fetchall_arrayref uses the [fetchrow_arrayref](#pod_fetchrow_arrayref) method to fetch each +row as an array ref. If the `$slice` array is not empty then it is used as a slice to select individual +columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). + +With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. + +If `$slice` is a hash reference, fetchall_arrayref uses [fetchrow_hashref](#pod_fetchrow_hashref) to fetch each row as a hash reference. + +See the DBI documentation for a complete discussion. + +## __fetchall_hashref__ + + $hash_ref = $sth->fetchall_hashref( $key_field ); + +Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for +a full discussion. + +## __finish__ + + $rv = $sth->finish; + +Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed +when you have not fetched all the possible rows. + +## __rows__ + + $rv = $sth->rows; + +Returns the number of rows affected for updates, deletes and inserts and -1 for selects. + +## __bind_col__ + + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + +Binds a Perl variable and/or some attributes to an output column of a SELECT statement. +Column numbers count up from 1. You do not need to bind output columns in order to fetch data. + +NOTE: DBD::Oracle does not use the `$bind_type` to determine how to +bind the column; it uses what Oracle says the data type is. You can +however set a numeric bind type with the bind attributes +StrictlyTyped/DiscardString as these attributes are applied after the +column is retrieved. + +See the DBI documentation for a discussion of the optional parameters `\%attr` and `$bind_type` + +## __bind_columns__ + + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + +Calls the [bind_col](#pod_bind_col) method for each column in the SELECT statement, using the supplied list. + +## __dump_results__ + + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + +Fetches all the rows from the statement handle, calls `DBI::neat_list` for each row, and +prints the results to `$fh` (which defaults to `STDOUT`). Rows are separated by `$lsep` (which defaults +to a newline). Columns are separated by `$fsep` (which defaults to a comma). The `$maxlen` controls +how wide the output can be, and defaults to 35. + +This method is designed as a handy utility for prototyping and testing queries. Since it uses +"neat_list" to format and edit the string for reading by humans, it is not recommended +for data transfer applications. + +# STATEMENT HANDLE ATTRIBUTES + +## __NUM_OF_FIELDS__ (integer, read-only) + +Returns the number of columns returned by the current statement. A number will only be returned for +SELECT statements for INSERT, +UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NUM_OF_PARAMS__ (integer, read-only) + +Returns the number of placeholders in the current statement. + +## __NAME__ (arrayref, read-only) + +Returns an arrayref of column names for the current statement. This +method will only work for SELECT statements, for SHOW statements, and for +INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NAME_lc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to lower case. + +## __NAME_uc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to upper case. + +## __NAME_hash__ (hashref, read-only) + +Similar to the `NAME` attribute, but returns a hashref of column names instead of an arrayref. The names of the columns +are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. +This method returns undef if called before `execute()`. + +## __NAME_lc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __NAME_uc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __TYPE__ (arrayref, read-only) + +Returns an arrayref indicating the data type for each column in the statement. +This method returns undef if called before `execute()`. + +## __PRECISION__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. +The number indicates the precision for `NUMERIC` columns, the size in number of +characters for `CHAR` and `VARCHAR` columns, and for all other types of columns +it returns the number of _bytes_. +This method returns undef if called before `execute()`. + +## __SCALE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates the scale of the that column. The only type that will return a value is `NUMERIC`. +This method returns undef if called before `execute()`. + +## __NULLABLE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates if the column is nullable or not. 0 = not nullable, 1 = nullable, 2 = unknown. +This method returns undef if called before `execute()`. + +## __Database__ (dbh, read-only) + +Returns the database handle this statement handle was created from. + +## __ParamValues__ (hash ref, read-only) + +Returns a reference to a hash containing the values currently bound to placeholders. If the "named parameters" +type of placeholders are being used (such as ":foo"), then the keys of the hash will be the names of the +placeholders (without the colon). If the "dollar sign numbers" type of placeholders are being used, the keys of the hash will +be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, +starting at one and increasing for every placeholder. + +If this method is called before [execute](#pod_execute), the literal values passed in are returned. If called after +[execute](#pod_execute), then the quoted versions of the values are returned. + +## __ParamTypes__ (hash ref, read-only) + +Returns a reference to a hash containing the type names currently bound to placeholders. The keys +are the same as returned by the ParamValues method. The values are hashrefs containing a single key value +pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can +only be expressed by a Postgres type. The value is the internal number corresponding to the type originally +passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of +ParamTypes to be passed back to the [bind_param](#pod_bind_param) method. + +## __Statement__ (string, read-only) + +Returns the statement string passed to the most recent "prepare" method called in this database handle, even if that method +failed. This is especially useful where "RaiseError" is enabled and the exception handler checks $@ and sees that a `prepare` +method call failed. + +## __RowsInCache__ + +Returns the number of un-fetched rows in the cache for selects. + +# SCROLLABLE CURSORS + +Oracle supports the concept of a 'Scrollable Cursor' which is defined as a 'Result Set' where +the rows can be fetched either sequentially or non-sequentially. One can fetch rows forward, +backwards, from any given position or the n-th row from the current position in the result set. + +Rows are numbered sequentially starting at one and client-side caching of the partial or entire result set +can improve performance by limiting round trips to the server. + +Oracle does not support DML type operations with scrollable cursors so you are limited +to simple 'Select' operations only. As well you can not use this functionality with remote +mapped queries or if the LONG datatype is part of the select list. + +However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch methods. + +Only use scrollable cursors if you really have a good reason to. They do use up considerable +more server and client resources and have poorer response times than non-scrolling cursors. + +## Enabling Scrollable Cursors + +To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + +Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the +statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + +When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row +or you can still use any of the other fetch methods but with a poorer response time than if you used a +non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. + +## Scrollable Cursor Methods + +The following driver-specific methods are used with scrollable cursors. + +- ora_scroll_position + + $position = $sth->ora_scroll_position(); + +This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time +this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. +The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. + +- ora_fetch_scroll + + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + +Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset +value which will then determine the row that will be fetched. It returns the row as a list containing the field values. +Null fields are returned as _undef_ values in the list. + +The valid orientation constant and fetch offset values combination are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + +The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + +The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + +## Scrollable Cursor Usage + +Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + +and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll +method; + +- Fetching the Last Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +if the record set is large this could take some time. + +- Fetching the Current Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will still be 20 after this snippet. + +- Fetching the First Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the Next Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 5 after this snippet. + +- Fetching the Prior Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the 10th Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 10th to 14th Row + + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 14 after this snippet. + +- Fetching the 14th to 10th Row + + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 5th Row From the Present Position. + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 15 after this snippet. + +- Fetching the 9th Row Prior From the Present Position + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 6 after this snippet. + +- Use Finish + + $sth->finish(); + +When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of +cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. + +# LOBS AND LONGS + +The key to working with LOBs (CLOB, BLOBs) is to remember the value of an Oracle LOB column is not the content of the LOB. It's a +'LOB Locator' which, after being selected or inserted needs extra processing to read or write the content of the LOB. There are also legacy LONG types (LONG, LONG RAW, VARCHAR2) +which are presently deprecated by Oracle but are still in use. These LONG types do not utilize a 'LOB Locator' and also are more limited in +functionality than CLOB or BLOB fields. + +DBD::Oracle now offers three interfaces to LOB and LONG data, + +- [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) + +With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of +BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. + +- [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) + +With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. + +- [LOB Locator Method Interface](#pod_LOB Locator Method Interface) + +This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. + +Generally speaking the interface that you will chose will be dependent on what end you are trying to achieve. All have their benefits and +drawbacks. + +One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB column can be in one of three states; + +- NULL + +The table cell is created, but the cell holds no locator or value. +If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + +error when working with a LOB. + +You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + +- Empty + +A LOB instance with a locator exists in the cell, but it has no value. The length of the LOB is zero. In this case DBD::Oracle will return 'undef' for the field. + +- Populated + +A LOB instance with a locator and a value exists in the cell. You actually get the LOB value. + +## Data Interface for Persistent LOBs + +This is the original interface for LONG and LONG RAW datatypes and from Oracle 9iR1 and later the OCI API was extended to work directly with the other LOB datatypes. +In other words you can treat all LOB type data (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using the same techniques +you would use on other datatypes that store character or binary data. In some cases there are fewer round trips to the server as no 'LOB Locators' are +used, normally one can get an entire LOB is a single round trip. + +### Simple Fetch for LONGs and LONG RAWs + +As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG datatypes as a single large piece. +There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. +If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into +an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. + +For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the long1 fields but they will be truncated at 2MBs. + +### Using ora_ncs_buff_mtpl + +When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the +Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. +Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. + +However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer +value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes +but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes +(maybe less characters though) but you are using allot more memory that you need. + +You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can +also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. + +The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the +ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. + +If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + +This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) + +If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. + +This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. + +You can tune this value by setting ora_oci_success_warn which will display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + +In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. + +### Simple Fetch for CLOBs and BLOBs + +To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well +set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds +the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. + +For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this +and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. + +It seems with BLOBs you are not limited by the 64k. + +For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the lobs but they will be truncated at 2MBs. + +### Piecewise Fetch with Callback + +With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. +To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Simple Fetch for LONGs and LONG RAWs](#pod_Simple Fetch for LONGs and LONG RAWs) and [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is +dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. + +Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +#### Piecewise Fetch with Polling + +With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' +attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback). + +Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. + +Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +### Binding for Updates and Inserts for CLOBs and BLOBs + +To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method +'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + +So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. + +### Support for Remote LOBs; + +Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + +to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Below are the limitations of Remote LOBs; + +- Queries involving more than one database are not supported; + +so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + +as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + +- DDL commands are not supported; + +so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + +- Only binds and defines for data going into remote persistent LOBs are supported. + +so that parameter passing in PL/SQL where CHAR data is bound or defined for remote LOBs is not allowed . + +These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + +- If the remote object is a view such as + + CREATE VIEW v AS SELECT foo() FROM ... + +the following would not work: + + SELECT * FROM v@dbs2; + +- Limited PL/SQL parameter passing + +PL/SQL parameter passing is not allowed where the actual argument is a LOB type +and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. + +- RETURNING INTO does not support implicit conversions between CHAR and CLOB. + +so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + +## Locator Data Interface + +### Simple Usage + +When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob with the LongReadLen and LongTruncOk attributes. +The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +When inserting or updating LOBs some _major_ magic has to be performed +behind the scenes to make it transparent. Basically the driver has to +insert a 'LOB Locator' and then refetch the newly inserted LOB +Locator before being able to write the data into it. However, it works +well most of the time, and I've made it as fast as possible, just one +extra server-round-trip per insert or update after the first. For the +time being, only single-row LOB updates are supported. + +To insert or update a large LOB using a placeholder, DBD::Oracle has to +know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + +The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + +or use the corresponding integer values (112 and 113). + +One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has +to be able to tell which parameters relate to which table fields. +In all cases where it can possibly work it out for itself, it does, +however, if there are multiple LOB fields of the same type in the table +then you need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + +There are some limitations inherent in the way DBD::Oracle makes typical +LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + +The alternative is to disable the automatic LOB Locator processing. +If [ora_auto_lob](#pod_ora_auto_lob) is 0 in prepare(), you can fetch the LOB Locators and +do all the work yourself using the ora_lob_*() methods. +See the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) section below. + +### LOB support in PL/SQL + +LOB Locators can be passed to PL/SQL calls by binding them to placeholders +with the proper `ora_type`. If [ora_auto_lob](#pod_ora_auto_lob) is true, output LOB +parameters will be automatically returned as strings. + +If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), +strings can be bound to input LOB placeholders and will be automatically +converted to LOBs. + +Example: + # Build a large XML document, bind it as a CLOB, + # extract elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + +If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + +error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. +One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. + +## Persistent & Locator Interface Caveats + +Now that one has the option of using the Persistent or the Locator interface for LOBs the questions arises +which one to use. For starters, if you want to access LOBs over a dblink you will have to use the Persistent +interface so that choice is simple. The question of which one to use after that is a little more tricky. +It basically boils down to a choice between LOB size and speed. + +The Callback and Polling piecewise fetches are very very slow +when compared to the Simple and the Locator fetches but they can handle very large blocks of data. Given a situation where a +large LOB is to be read the Locator fetch may time out while either of the piecewise fetches may not. + +With the Simple fetch you are limited by physical memory of your server but it runs a little faster than the Locator, as there are fewer round trips +to the server. So if you have small LOBs and need to save a little bandwidth this is the one to use. It you are going after large LOBs then the Locator interface is the one to use. + +If you need to update more than a single row of with LOB data then the Persistent interface can do it while the Locator can't. + +If you encounter a situation where you have to access the legacy LOBs (LONG, LONG RAW) and the values are to large for you system then you can use +the Callback or Polling piecewise fetches to get all of the data. + +Not all of the Persistent interface has been implemented yet, the following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + +Most of the time you should just use the [Locator Data Interface](#pod_Locator Data Interface) as this is in one that has the best combination of speed and size. + +All this being said if you are doing some critical programming I would use the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) as this gives you very +fine grain control of your LOBs, of course the code for this will be somewhat more involved. + +## Data Interface for LOB Locators + +The following driver-specific methods let you manipulate "LOB Locators" directly. +To select a LOB locator directly set the if the `ora_auto_lob` +attribute to false, or alternatively they can be returned via PL/SQL procedure calls. + +(If using a DBI version earlier than 1.36 they must be called via the +func() method. Note that methods called via func() don't honour +RaiseError etc, and so it's important to check $dbh->err after each call. +It's recommended that you upgrade to DBI 1.38 or later.) + +Note that LOB locators are only valid while the statement handle that +created them is valid. When all references to the original statement +handle are lost, the handle is destroyed and the locators are freed. + +- ora_lob_read + + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + +Read a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobRead function. + +- ora_lob_write + + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + +Write/overwrite a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobWrite function. + +- ora_lob_append + + $rc = $dbh->ora_lob_append($lob_locator, $data); + +Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + +- ora_lob_trim + + $rc = $dbh->ora_lob_trim($lob_locator, $length); + +Trims the length of the LOB to $length. +Uses the Oracle OCILobTrim function. + +- ora_lob_length + + $length = $dbh->ora_lob_length($lob_locator); + +Returns the length of the LOB. +Uses the Oracle OCILobGetLength function. + +- ora_lob_is_init + + $is_init = $dbh->ora_lob_is_init($lob_locator); + +Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' +if there is an error. +Uses the Oracle OCILobLocatorIsInit function. + +- ora_lob_chunk_size + + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + +Returns the chunk size of the LOB. +Uses the Oracle OCILobGetChunkSize function. + +For optimal performance, Oracle recommends reading from and +writing to a LOB in batches using a multiple of the LOB chunk size. +In Oracle 10g and before, when all defaults are in place, this +chunk size defaults to 8k (8192). + +### LOB Locator Method Examples + +_Note:_ Make sure you first read the note in the section above about +multi-byte character set issues with these methods. + +The following examples demonstrate the usage of LOB Locators +to read, write, and append data, and to query the size of +large data. + +The following examples assume a table containing two large +object columns, one binary and one character, with a primary +key column, defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + +It also assumes a sequence for use in generating unique +lob_id field values, defined as follows: + + CREATE SEQUENCE lob_example_seq + +### Example: Inserting a new row with large data + +Unless enough memory is available to store and bind the +entire LOB data for insert all at once, the LOB columns must +be written interactively, piece by piece. In the case of a new row, +this is performed by first inserting a row, with empty values in +the LOB columns, then modifying the row by writing the large data +interactively to the LOB columns using their LOB locators as handles. + +The insert statement must create token values in the LOB +columns. Here, we use the empty string for both the binary +and character large object columns 'bindata' and 'chardata'. + +After the INSERT statement, a SELECT statement is used to +acquire LOB locators to the 'bindata' and 'chardata' fields +of the newly inserted row. Because these LOB locators are +subsequently written, they must be acquired from a select +statement containing the clause 'FOR UPDATE' (LOB locators +are only valid within the transaction that fetched them, so +can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + +In this example we demonstrate the use of ora_lob_write() +interactively to append data to the columns 'bin_data' and +'char_data'. Had we used ora_lob_append(), we could have +saved ourselves the trouble of keeping track of the offset +into the lobs. The snippet of code beneath the comment +'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + +The scalar variables $offset and $length are no longer +needed, because ora_lob_append() keeps track of the offset +for us. + +### Example: Updating an existing row with large data + +In this example, we demonstrate a technique for overwriting +a portion of a blob field with new binary data. The blob +data before and after the section overwritten remains +unchanged. Hence, this technique could be used for updating +fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + +After running this code, the row where lob_id = 5 will +contain, starting at position 100234 in the bin_data column, +the string "This string will overwrite a portion of the blob". + +### Example: Streaming character data from the database + +In this example, we demonstrate a technique for streaming +data from the database to a file handle, in this case +STDOUT. This allows more data to be read in and written out +than could be stored in memory at a given time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + +Notice that the select statement does not contain the phrase +"FOR UPDATE". Because we are only reading from the LOB +Locator returned, and not modifying the LOB it refers to, +the select statement does not require the "FOR UPDATE" +clause. + +A word of caution when using the data returned from an ora_lob_read in a conditional statement. +for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + +was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return +the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte +as $data will contain 0 which PERL will see as false and not print it out. + +### Example: Truncating existing large data + +In this example, we truncate the data already present in a +large object column in the database. Specifically, for each +row in the table, we truncate the 'bindata' value to half +its previous length. + +After acquiring a LOB Locator for the column, we query its +length, then we trim the length by half. Because we modify +the large objects with the call to ora_lob_trim(), we must +select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +# SPACES AND PADDING + +## Trailing Spaces + +Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder +values and uses Nonpadded Comparison Semantics with the result. +This causes trouble if the spaces are needed for +comparison with a CHAR value or to prevent the value from +becoming '' which Oracle treats as NULL. +Look for Blank-padded Comparison Semantics and Nonpadded +Comparison Semantics in Oracle's SQL Reference or Server +SQL Reference for more details. + +To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, +either change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or the placeholder +type for a particular call to L or L +with [ora_type](#pod_ora_type) or `TYPE`. +Using [ORA_CHAR](http://search.cpan.org/perldoc?ORA_CHAR) with [ora_type](http://search.cpan.org/perldoc?ora_type) or `SQL_CHAR` with `TYPE` +allows the placeholder to be used with Padded Comparison Semantics +if the value it is being compared to is a CHAR, NCHAR, or literal. + +Please remember that using spaces as a value or at the end of +a value makes visually distinguishing values with different +numbers of spaces difficult and should be avoided. + +Oracle Clients that use OCI 9.2 do not strip trailing spaces. + +## Padded Char Fields + +Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. +As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will +have to change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or placeholder +type for a particular call with L or L +with [ORA_CHAR](#pod_ORA_CHAR). + +# UNICODE + +DBD::Oracle now supports Unicode UTF-8. There are, however, a number +of issues you should be aware of, so please read all this section +carefully. + +In this section we'll discuss "Perl and Unicode", then "Oracle and +Unicode", and finally "DBD::Oracle and Unicode". + +Information about Unicode in general can be found at: +[http://www.unicode.org/](http://www.unicode.org/). It is well worth reading because there are +many misconceptions about Unicode and you may be holding some of them. + +## Perl and Unicode + +Perl began implementing Unicode with version 5.6, but the implementation +did not mature until version 5.8 and later. If you plan to use Unicode +you are _strongly_ urged to use Perl 5.8.2 or later and to _carefully_ read +the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + +And then read it again. + +Perl's internal Unicode format is UTF-8 +which corresponds to the Oracle character set called AL32UTF8. + +## Oracle and Unicode + +Oracle supports many characters sets, including several different forms +of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + +When you create an Oracle database, you must specify the DATABASE +character set (used for DDL, DML and CHAR datatypes) and the NATIONAL +character set (used for NCHAR and NCLOB types). +The character sets used in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + +The Oracle 9.2 and later default for the national character set is AL16UTF16. +The default for the database character set is often US7ASCII. +Although many experienced DBAs will consider an 8bit character set like +WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle +other than US7ASCII, requires that the NLS_LANG environment variable be set. +See the L<"Oracle UTF8 is not UTF-8"> section below. + +You are strongly urged to read the Oracle Internationalization documentation +specifically with respect the choices and trade offs for creating +a databases for use with international character sets. + +Oracle uses the NLS_LANG environment variable to indicate what +character set is being used on the client. When fetching data Oracle +will convert from whatever the database character set is to the client +character set specified by NLS_LANG. Similarly, when sending data to +the database Oracle will convert from the character set specified by +NLS_LANG to the database character set. + +The NLS_NCHAR environment variable can be used to define a different +character set for 'national' (NCHAR) character types. + +Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. +For example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + +## Oracle UTF8 is not UTF-8 + +AL32UTF8 should be used in preference to UTF8 if it works for you, +which it should for Oracle 9.2 or later. If you're using an old +version of Oracle that doesn't support AL32UTF8 then you should +avoid using any Unicode characters that require surrogates, in other +words characters beyond the Unicode BMP (Basic Multilingual Plane). + +That's because the character set that Oracle calls "UTF8" doesn't +conform to the UTF-8 standard in its handling of surrogate characters. +Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". +Here are a couple of extracts from [http://www.unicode.org/reports/tr26/](http://www.unicode.org/reports/tr26/): + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + +Oracle uses this internally because it collates (sorts) in the same order +as UTF16, which is the basis of Oracle's internal collation definitions. + +Rather than change UTF8 for clients Oracle chose to define a new character +set called "AL32UTF8" which does conform to the UTF-8 standard. +(The AL32UTF8 character set can't be used on the server because it +would break collation.) + +Because of that, for the rest of this document we'll use "AL32UTF8". +If you're using an Oracle version below 9.2 you'll need to use "UTF8" +until you upgrade. + +## DBD::Oracle and Unicode + +DBD::Oracle Unicode support has been implemented for Oracle versions 9 +or greater, and Perl version 5.6 or greater (though we _strongly_ +suggest that you use Perl 5.8.2 or later). + +You can check which Oracle version your DBD::Oracle was built with by +importing the `ORA_OCI` constant from DBD::Oracle. + +__Fetching Data__ + +Any data returned from Oracle to DBD::Oracle in the AL32UTF8 +character set will be marked as UTF-8 to ensure correct handling by Perl. + +For Oracle to return data in the AL32UTF8 character set the +NLS_LANG or NLS_NCHAR environment variable _must_ be set as described +in the previous section. + +When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR +is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + +When fetching other character data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + +__Sending Data using Placeholders__ + +Data bound to a placeholder is assumed to be in the default client +character set (specified by NLS_LANG) except for a few special +cases. These are listed here with the highest precedence first: + +If the `ora_csid` attribute is given to bind_param() then that +is passed to Oracle and takes precedence. + +If the value is a Perl Unicode string (UTF-8) then DBD::Oracle +ensures that Oracle uses the Unicode character set, regardless of +the NLS_LANG and NLS_NCHAR settings. + +If the placeholder is for inserting an NCLOB then the client NLS_NCHAR +character set is used. (That's useful but inconsistent with the other behaviour +so may change. Best to be explicit by using the `ora_csform` +attribute.) + +If the `ora_csform` attribute is given to bind_param() then that +determines if the value should be assumed to be in the default +(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + +or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + +Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to +insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert +will still happen but a error code of 0 will be returned with the following warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + +The warning will report the parameter number and the NCHAR setting that the query is running. + +__Sending Data using SQL__ + +Oracle assumes the SQL statement is in the default client character +set (as specified by NLS_LANG). So Unicode strings containing +non-ASCII characters should not be used unless the default client +character set is AL32UTF8. + +## DBD::Oracle and Other Character Sets and Encodings + +The only multi-byte Oracle character set supported by DBD::Oracle is +"AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +# OBJECT & COLLECTION DATA TYPES + +Oracle databases allow for the creation of object oriented like user-defined types. +There are two types of objects, Embedded--an object stored in a column of a regular table +and REF--an object that uses the REF retrieval mechanism. + +DBD::Oracle supports only the 'selection' of embedded objects of the following types OBJECT, VARRAY +and TABLE in any combination. Support is seamless and recursive, meaning you +need only supply a simple SQL statement to get all the values in an embedded object. +You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. + +Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + +The code to access all the data in the table could be something like this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + +Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. + +As stated before DBD::Oracle will automatically drill into the embedded object and extract +all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an +SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + +The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + +Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + +The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + +So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables +nested to 10 levels. + +Any NULL values found in the embedded object will be returned as 'undef'. + +# OTHER DATA TYPES + +DBD::Oracle does not _explicitly_ support most Oracle datatypes. +It simply asks Oracle to return them as strings and Oracle does so. +Mostly. Similarly when binding placeholder values DBD::Oracle binds +them as strings and Oracle converts them to the appropriate type, +such as DATE, when used. + +Some of these automatic conversions to and from strings use NLS +settings to control the formatting for output and the parsing for +input. The most common example is the DATE type. The default NLS +format for DATE might be DD-MON-YYYY and so when a DATE type is +fetched that's how Oracle will format the date. NLS settings also +control the default parsing of strings into DATE values. An error +will be generated if the contents of the string don't match the +NLS format. If you're dealing in dates which don't match the default +NLS format then you can either change the default NLS format or, more +commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") +to explicitly specify formats for converting to and from strings. + +A slightly more subtle problem can occur with NUMBER types. The +default NLS settings might format numbers with a fullstop ("`.`") +to separate thousands and a comma ("`,`") as the decimal point. +Perl will generate warnings and use incorrect values when numbers, +returned and formatted as strings in this way by Oracle, are used +in a numeric context. You could explicitly convert each numeric +value using the TO_CHAR(...) function but that gets tedious very +quickly. The best fix is to change the NLS settings. That can be +done for an individual connection by doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + +There are some types, like BOOLEAN, that Oracle does not automatically +convert to or from strings (pity). These need to be converted +explicitly using SQL or PL/SQL functions. + +Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + +#### Support for Insert of XMLType (ORA_XMLTYPE) + +Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special +requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For +example with a table like this; + + create table books (book_id number, book_xml XMLType); + +one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + +In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. +This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. + +#### Binding Cursors + +Cursors can be returned from PL/SQL blocks, either from stored +functions (or procedures with OUT parameters) or +from direct `OPEN` statements, as shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +The only special requirement is the use of `bind_param_inout()` with an +attribute hash parameter that specifies `ora_type` as `ORA_RSET`. +If you don't do that you'll get an error from the `execute()` like: +"ORA-06550: line X, column Y: PLS-00306: wrong number or types of +arguments in call to ...". + +Here's an alternative form using a function that returns a cursor. +This example uses the pre-defined weak (or generic) REF CURSOR type +SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +A cursor obtained from PL/SQL as above may be passed back to PL/SQL +by binding for input, as shown in this example, which explicitly +closes a cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + +It is not normally necessary to close a cursor +explicitly in this way. Oracle will close the cursor automatically +at the first client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to +the cursor handle from the PL/SQL statement handle delays the destruction +of the cursor handle for too long. This reference remains until the +PL/SQL handle is re-bound, re-executed or destroyed. + +See the `curref.pl` script in the Oracle.ex directory in the DBD::Oracle +source distribution for a complete working example. + +#### Fetching Nested Cursors + +Oracle supports the use of select list expressions of type REF CURSOR. +These may be explicit cursor expressions - `CURSOR(SELECT ...)`, or +calls to PL/SQL functions which return REF CURSOR values. The values +of these expressions are known as nested cursors. + +The value returned to a Perl program when a nested cursor is fetched +is a statement handle. This statement handle is ready to be fetched from. +It should not (indeed, must not) be executed. + +Oracle imposes a restriction on the order of fetching when nested +cursors are used. Suppose `$sth1` is a handle for a select statement +involving nested cursors, and `$sth2` is a nested cursor handle fetched +from `$sth1`. `$sth2` can only be fetched from while `$sth1` is +still active, and the row containing `$sth2` is still current in `$sth1`. +Any attempt to fetch another row from `$sth1` renders all nested cursor +handles previously fetched from `$sth1` defunct. + +Fetching from such a defunct handle results in an error with the message +`ERROR nested cursor is defunct (parent row is no longer current)`. + +This means that the `fetchall...` or `selectall...` methods are not useful +for queries returning nested cursors. By the time such a method returns, +all the nested cursor handles it has fetched will be defunct. + +It is necessary to use an explicit fetch loop, and to do all the +fetching of nested cursors within the loop, as the following example +shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + +The cursor returned by the function `sp_ListEmp` defined in the +previous section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + +#### Pre-fetching Nested Cursors + +By default, DBD::Oracle pre-fetches rows in order to reduce the number of +round trips to the server. For queries which do not involve nested cursors, +the number of pre-fetched rows is controlled by the DBI database handle +attribute `RowCacheSize` (q.v.). + +In Oracle, server side open cursors are a controlled resource, limited in +number, on a per session basis, to the value of the initialization +parameter `OPEN_CURSORS`. Nested cursors count towards this limit. +Each nested cursor in the current row counts 1, as does +each nested cursor in a pre-fetched row. Defunct nested cursors do not count. + +An Oracle specific database handle attribute, `ora_max_nested_cursors`, +further controls pre-fetching for queries involving nested cursors. For +each statement handle, the total number of nested cursors in pre-fetched +rows is limited to the value of this parameter. The default value +is 0, which disables pre-fetching for queries involving nested cursors. + +# PL/SQL Examples + +Most of these PL/SQL examples come from: Eric Bartley . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + +You can find more examples in the t/plsql.t file in the DBD::Oracle +source directory. + +Oracle 9.2 appears to have a bug where a variable bound +with bind_param_inout() that isn't assigned to by the executed +PL/SQL block may contain garbage. +See [http://www.mail-archive.com/dbi-users@perl.org/msg18835.html](http://www.mail-archive.com/dbi-users@perl.org/msg18835.html) + +## Avoid Using "SQL Call" + +Avoid using the "SQL Call" statement with DBD:Oracle as you might find that +DBD::Oracle will not raise an exception in some case. Specifically if you use +"SQL Call" to run a procedure all "No data found" exceptions will be quietly +ignored and returned as null. According to Oracle support this is part of the same +mechanism where; + + select (select * from dual where 0=1) from dual + +returns a null value rather than an exception. + +# CONTRIBUTING + +If you'd like DBD::Oracle to do something new or different the best way +to make that happen is to do it yourself and email to dbi-dev@perl.org a +patch of the source code (using 'diff' - see below) that shows the changes. + +## How to create a patch using Subversion + +The DBD::Oracle source code is maintained using Subversion (a replacement +for CVS, see [http://subversion.tigris.org/](http://subversion.tigris.org/)). To access the source +you'll need to install a Subversion client. Then, to get the source +code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + +If it prompts for a username and password use your perl.org account +if you have one, else just 'guest' and 'guest'. The source code will +be in a new subdirectory called `trunk`. + +To keep informed about changes to the source you can send an empty email +to dbd-oracle-changes-subscribe@perl.org after which you'll get an email with the +change log message and diff of each change checked-in to the source. + +After making your changes you can generate a patch file, but before +you do, make sure your source is still upto date using: + + svn update + +If you get any conflicts reported you'll need to fix them first. +Then generate the patch file from within the `trunk` directory using: + + svn diff > foo.patch + +Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. + +## How to create a patch without Subversion + +Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + +Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + +Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you want. + +Test your changes and then remove all temporary files: + + make test && make distclean + +Go back to the directory you originally unpacked the distribution: + + cd .. + +Unpack _another_ copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + +Then create a patch file by performing a recursive `diff` on the two +top level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + +## Speak before you patch + +For anything non-trivial or possibly controversial it's a good idea +to discuss (on dbi-dev@perl.org) the changes you propose before +actually spending time working on them. Otherwise you run the risk +of them being rejected because they don't fit into some larger plans +you may not be aware of. + +## GitHub repository + +A git mirror of the subversion is also available at +`https://github.com/yanick/DBD-Oracle`. + +# Oracle Related Links + +# WHICH VERSION OF DBD::ORACLE IS FOR ME? + +From version 1.25 onwards DBD::Oracle only support Oracle clients +9.2 or greater. Support for ProC connections was dropped in 1.29. + +If you are still stuck with an older version of Oracle or its client you might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + +As there are dozens of different versions of Oracle's clients this +list does not include all of them, just the major released versions of +Oracle. + +Note that one can still connect to any Oracle version with the older +DBD::Oracle versions the only problem you will have is that some of +the newer OCI and Oracle features available in later DBD::Oracle +releases will not be available to you. + +So to make a short story a little longer: + +- 1 + +If you are using Oracle 7 or early 8 DB and you can manage to get a 9 client and you can use +any DBD::Oracle version. + +- 2 + +If you have to use an Oracle 7 client then DBD::Oracle 1.17 should work + +- 3 + +Same thing for 8 up to R2, use 1.17, if you are lucky and have the right patch-set you might +go with 1.18. + +- 4 + +For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. Again this depends on your +patch-set, If you run into trouble go with 1.19 + +- 5 + +After 9.2 you can use any version you want. + +- 6 + +It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go back to 7 +and even get to 10. I am not sure what the 11g client can connect to. + +# BUGS AND LIMITATIONS + +There is a known problem with the 11.2g Oracle client and the +`DBMS_LOB.GETLENGTH()` PL/SQL function. +See [https://rt.cpan.org/Public/Bug/Display.html?id=69350](https://rt.cpan.org/Public/Bug/Display.html?id=69350) for the details. + +# SEE ALSO + +- [DBI](http://search.cpan.org/perldoc?DBI) + +http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in +the DBD::Oracle source distribution including the examples in the +Oracle.ex directory + +- DBD::Oracle Tutorial + +http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-oracle.html + +- Oracle Instant Client + +http://www.oracle.com/technology/tech/oci/instantclient/index.html + +- Oracle on Linux + +http://www.ixora.com.au/ + +- Free Oracle Tools and Links + +ora_explain supplied and installed with DBD::Oracle. + +http://www.orafaq.com/ + +http://vonnieda.org/oracletool/ + +- Commercial Oracle Tools and Links + +Assorted tools and references for general information. +No recommendation implied. + +http://www.platinum.com + +http://www.SoftTreeTech.com + +Also PL/Vision from RevealNet and Steven Feuerstein, and +"Q" from Savant Corporation. + +# AUTHORS + +DBI by Tim Bunce [http://www.tim.bunce.name](http://www.tim.bunce.name). + +The original `DBD::Oracle` was by Tim Bunce. +Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the +auspice of the Pythian Group ([http://www.pythian.com](http://www.pythian.com)). + +# ACKNOWLEDGEMENTS + +A great many people have helped with DBD::Oracle over the 17 years +between 1994 and 2011. Far too many to name, but we thank them all. +Many are named in the Changes file. + +# COPYRIGHT + +The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. +The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The Pythian Group). Canada. +The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. + +The DBD::Oracle module is free open source software; you can +redistribute it and/or modify it under the same terms as Perl 5. + +# AUTHORS + +- * + +Tim Bunce + +- * + +John Scoles + +- * + +Yanick Champoux + +# COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/dist.ini b/dist.ini deleted file mode 100644 index 013f79fc..00000000 --- a/dist.ini +++ /dev/null @@ -1,22 +0,0 @@ -name = DBD-Oracle -author = Tim Bunce -author = John Scoles -author = Yanick Champoux -license = Perl_5 -copyright_holder = Tim Bunce -copyright_year = 1994 - -version = 1.38 - -[Authority] -authority=cpan:PYTHIAN - -[MakeMaker::Custom] - -[@Filter] --bundle=@YANICK --remove=Author::YANICK::NextSemanticVersion --remove=ModuleBuild --remove=Authority --remove=Signature - diff --git a/err_bind/err_bind_param_inout_overrun_bug.msg b/err_bind/err_bind_param_inout_overrun_bug.msg deleted file mode 100644 index 83d9001f..00000000 --- a/err_bind/err_bind_param_inout_overrun_bug.msg +++ /dev/null @@ -1,108 +0,0 @@ -From dbi-users-return-215-Tim.Bunce=ig.co.uk@perl.org Mon Feb 5 23:03:29 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id XAA01289; Mon, 5 Feb 2001 23:03:27 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <06769-16@oink>; Fri, 6 Feb 1970 00:01:15 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 981413584:20:24069:0; Mon, 05 Feb 2001 22:53:04 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-2.mail.demon.net - id aa2024004; 5 Feb 2001 22:53 GMT -Received: (qmail 6267 invoked by uid 508); 5 Feb 2001 22:52:23 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6247 invoked from network); 5 Feb 2001 22:52:22 -0000 -Received: from seeme.dare.feddata.com (38.186.101.66) by tmtowtdi.perl.org - with SMTP; 5 Feb 2001 22:52:22 -0000 -Received: by seeme.dare.feddata.com; id OAA05466; - Mon, 5 Feb 2001 14:55:56 -0800 (PST) -Received: from ifyou.dare.feddata.com(38.186.101.111) by seeme.dare.feddata.com - via smap (4.1) id xma005448; Mon, 5 Feb 01 14:55:39 -0800 -Sender: oscar@dare.feddata.com -Message-ID: <3A7F2FB0.A1507582@pasadena.feddata.com> -Date: Mon, 05 Feb 2001 14:56:48 -0800 -From: Oscar DeMartino -Organization: Federal Data Corporation -X-Mailer: Mozilla 4.61 [en] (X11; U; SunOS 5.6 sun4u) -X-Accept-Language: en -MIME-Version: 1.0 -To: dbi-users@perl.org -Subject: Undetected error - Binding and Stored Procedures -Content-Type: multipart/alternative; - boundary="------------E1028F7A8304BE268EB8F67B" -Status: RO -Content-Length: 2042 -Lines: 66 - ---------------E1028F7A8304BE268EB8F67B -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -I am running Oracle 8.1.5 and am using many stored procedures. We -use returned cursors, and individual values. The problem is, when -a stored procedure is executed and the specified bound variable has not -be declared large enough to hold the returned value subsequent -bound variables do not get set and I cannot find any way to -automatically detect this. - -Example: - -The stored procedure takes 1-input value and returns three string -values. - -the stored procedure is prepared , so I get the statement handle. - -I bind the input variable, and then bind the three output variables (1, -2, & 3) -as 100 character strings. - -I then execute the statment handle. - -There do not appear to be any errors, after checking the returned value -(for the execute call), -and ->err and ->errstr are clean. - -variable 1 has the correct returned value. -BUT, output variable 2 & 3, have no value. - ------- -Executing the stored procedure using sqlplus (sql command line -interface) indicated: - -What really occured is that the returned output variables 1 & 3 were -under 100 characters long -output variable 2 was 120 characters long - ---------- - -I know I could make all output variables the max size allowed in the -database field -but this would seem to waste space in the perl code. Since the field in - -the database -is simply defined as a varchar2 with no size limitation (upto 32767). - ------ -Am I missing something about detecting that variables 2 & 3 did not get -stored correctly -by DBI::Oracle?? - - - --- -Oscar "Fred" DeMartino FFFFF DDDD CCC -320 N. Halstead Ave. Ste #160 F D D C C -Pasadena, CA 91107 FFF D D C -e-mail: Oscar.DeMartino@pasadena.feddata.com F D D C -Phone: (626)306-6649 F D D C C -Federal Data Corporation F DDDD CCC - - - ---------------E1028F7A8304BE268EB8F67B-- - diff --git a/err_bind/err_bindarrays.msg b/err_bind/err_bindarrays.msg deleted file mode 100644 index 8ca7a5d3..00000000 --- a/err_bind/err_bindarrays.msg +++ /dev/null @@ -1,241 +0,0 @@ -From cturner@redhat.com Tue Mar 27 06:01:56 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id GAA19714; Tue, 27 Mar 2001 06:01:56 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <13771-3@oink>; - Fri, 27 Mar 1970 06:00:50 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985668014:20:27605:3; Tue, 27 Mar 2001 04:40:14 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ab2125244; 27 Mar 2001 4:39 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id XAA32289 - for ; Mon, 26 Mar 2001 23:39:38 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2R4bvT12929; Mon, 26 Mar 2001 23:37:57 -0500 -Sender: cturner@redhat.com -To: Tim.Bunce@ig.co.uk -Subject: DBD::Oracle and OCI bound arrays -From: Chip Turner -Date: 26 Mar 2001 23:37:57 -0500 -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 980 -Lines: 29 - - -Hey Tim, - -The need to have true OCI bound arrays for DBD::Oracle has come up, -and it looks like I get the fun job of implementing them. Basically, -this will allow DBD::Oracle to do something the DCOracle python -library does. The idea is: - -my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -my @c1 = 'aa' .. 'zz'; -my @c2 = 'aaa' .. 'azz'; -$sth->execute(\@c1, \@c2); - -In other words, it populates the table with a single execute call, -passing two (or more) equally sized arrays in as references for bound -parameters. This has the potential to save a good amount of time, -especially for large datasets. - -This would pretty much be a proprietary extension for Oracle, though -similar uses could be done in other DBD's. - -Just thought I'd let you know what I was intending to do, and to see -if you had any interest in receiving it as a patch after I'm done. - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Tue Mar 27 09:29:48 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id JAA20809; Tue, 27 Mar 2001 09:29:42 +0100 (BST) -Date: Tue, 27 Mar 2001 09:29:41 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim.Bunce@ig.co.uk, dbi-dev@perl.org -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010327092941.D20616@ig.co.uk> -References: -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Mon, Mar 26, 2001 at 11:37:57PM -0500 -Content-Length: 1570 -Lines: 39 - -On Mon, Mar 26, 2001 at 11:37:57PM -0500, Chip Turner wrote: -> -> Hey Tim, -> -> The need to have true OCI bound arrays for DBD::Oracle has come up, -> and it looks like I get the fun job of implementing them. Basically, -> this will allow DBD::Oracle to do something the DCOracle python -> library does. The idea is: -> -> my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -> my @c1 = 'aa' .. 'zz'; -> my @c2 = 'aaa' .. 'azz'; -> $sth->execute(\@c1, \@c2); -> -> In other words, it populates the table with a single execute call, -> passing two (or more) equally sized arrays in as references for bound -> parameters. This has the potential to save a good amount of time, -> especially for large datasets. -> -> This would pretty much be a proprietary extension for Oracle, though -> similar uses could be done in other DBD's. -> -> Just thought I'd let you know what I was intending to do, and to see -> if you had any interest in receiving it as a patch after I'm done. - -I would *urge* you to discuss the implementation with me *before* -you get very far cutting code. - -And anyway, I think someone's already done much or all of the work. -Dig around in the dbi-dev archives. If you can't find the discussion -let me know. If you do, then ask them (via the dbi-dev list) what -the status is. - -I'm planning to make a DBI release next week and, hopefully, a -DBD::Oracle release the week after to cleare a backlog of patches I -have queued up. After that I'll be looking to add in the work of the -other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -Tim. - -From cturner@redhat.com Wed Mar 28 02:01:21 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id CAA27336; Wed, 28 Mar 2001 02:01:21 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <17151-9@oink>; - Sat, 28 Mar 1970 01:59:47 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985739868:20:27318:0; Wed, 28 Mar 2001 00:37:48 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ac2119835; 28 Mar 2001 0:37 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id TAA10445 - for ; Tue, 27 Mar 2001 19:37:35 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2S0ZoJ20115; Tue, 27 Mar 2001 19:35:50 -0500 -Sender: cturner@redhat.com -To: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -References: <20010327092941.D20616@ig.co.uk> -From: Chip Turner -Date: 27 Mar 2001 19:35:50 -0500 -In-Reply-To: <20010327092941.D20616@ig.co.uk> -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 1495 -Lines: 35 - -Tim Bunce writes: - -> I would *urge* you to discuss the implementation with me *before* -> you get very far cutting code. - -Unfortunately, it's a little late for this; I've mostly finished the -change (at least, enough for our needs), except for some review and -cleanups. It seems to work quite well (400 times faster than repeated -looping over a dataset) and passes all of DBD::Oracle's test suite. - -> And anyway, I think someone's already done much or all of the work. -> Dig around in the dbi-dev archives. If you can't find the discussion -> let me know. If you do, then ask them (via the dbi-dev list) what -> the status is. - -I checked as you suggest, but couldn't find any code, just discussion -of it. I'll check again, but it didn't seem that the person had put -it anywhere I could get at it. - -> I'm planning to make a DBI release next week and, hopefully, a -> DBD::Oracle release the week after to cleare a backlog of patches I -> have queued up. After that I'll be looking to add in the work of the -> other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -If you would like, the patch will probably be suitable for inclusion -by then, if you want it in by the next release. Should there be any -problems with it or its implementation, I'd be glad to clean it up if -you have interest in it (if not, that's cool too; we need it soon, -though, either way). - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Wed Mar 28 11:51:58 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id LAA00444; Wed, 28 Mar 2001 11:51:51 +0100 (BST) -Date: Wed, 28 Mar 2001 11:51:51 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010328115151.D29769@ig.co.uk> -References: <20010327092941.D20616@ig.co.uk> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Tue, Mar 27, 2001 at 07:35:50PM -0500 -Content-Length: 1786 -Lines: 40 - -On Tue, Mar 27, 2001 at 07:35:50PM -0500, Chip Turner wrote: -> Tim Bunce writes: -> -> > I would *urge* you to discuss the implementation with me *before* -> > you get very far cutting code. -> -> Unfortunately, it's a little late for this; I've mostly finished the -> change (at least, enough for our needs), except for some review and -> cleanups. It seems to work quite well (400 times faster than repeated -> looping over a dataset) and passes all of DBD::Oracle's test suite. - -I trust you've added some more tests for your new functionality! - -> > And anyway, I think someone's already done much or all of the work. -> > Dig around in the dbi-dev archives. If you can't find the discussion -> > let me know. If you do, then ask them (via the dbi-dev list) what -> > the status is. -> -> I checked as you suggest, but couldn't find any code, just discussion -> of it. I'll check again, but it didn't seem that the person had put -> it anywhere I could get at it. - -You could always ask them (CC me). - -> > I'm planning to make a DBI release next week and, hopefully, a -> > DBD::Oracle release the week after to cleare a backlog of patches I -> > have queued up. After that I'll be looking to add in the work of the -> > other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). -> -> If you would like, the patch will probably be suitable for inclusion -> by then, if you want it in by the next release. Should there be any -> problems with it or its implementation, I'd be glad to clean it up if -> you have interest in it (if not, that's cool too; we need it soon, -> though, either way). - -Thanks for the clean-up offer. Send it to me after I make the next -DBD::Oracle release (as a fresh patch over that version please - but -there shouldn't be too many changes). - -Tim. - diff --git a/err_bind/err_bindclobleak.msg b/err_bind/err_bindclobleak.msg deleted file mode 100644 index 1a31c760..00000000 --- a/err_bind/err_bindclobleak.msg +++ /dev/null @@ -1,58 +0,0 @@ -From PGWeiss@arity.com Thu Mar 9 09:51:45 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id JAA14948; Thu, 9 Mar 2000 09:51:43 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <27566-0@oink>; Mon, 9 Mar 1970 10:51:10 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 952595299:20:10439:68; Thu, 09 Mar 2000 09:48:19 GMT -Received: from image.arity.com ([140.239.104.130]) by punt-2.mail.demon.net - id aa2010598; 9 Mar 2000 9:47 GMT -Received: by image.arity.com with Internet Mail Service (5.5.2650.21) - id ; Thu, 9 Mar 2000 04:51:44 -0500 -Message-ID: -From: "Paul G. Weiss" -To: Perl-Win32-Database Mailing List , - "'Tim Bunce'" -Subject: Another CLOB related DBD::Oracle bug -Date: Thu, 9 Mar 2000 04:51:41 -0500 -MIME-Version: 1.0 -X-Mailer: Internet Mail Service (5.5.2650.21) -Content-Type: text/plain; charset="iso-8859-1" -Status: RO -Content-Length: 689 -Lines: 32 - -Binding a parameter to type ORA_CLOB causes a leak. -Consider: - -for (1..10000) -{ - for (1..100) - { - my $sth = $db->prepare('update item set descr = ? where id = ?'); - if ($leak) - { - $sth->bind_param(1, $descr, {ora_type => ORA_CLOB, -ora_field=>'DESCR'}); - $sth->bind_param(2, 12); - $sth->execute; - } - else - { - $sth->execute($descr,12); - } - } - sleep 1; -} - - -With $leak set to 1, i.e. binding the parameters explicitly the -program leaks. With $leak set to 0 it does not (but then I can't -set descr to anything greater than 4K nor can I set it to the -empty string). - -Is there a patch? - --P - diff --git a/err_bind/err_bindnullhash.msg b/err_bind/err_bindnullhash.msg deleted file mode 100644 index d9a98b9a..00000000 --- a/err_bind/err_bindnullhash.msg +++ /dev/null @@ -1,77 +0,0 @@ -From dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org Thu Jul 11 17:49:35 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g6BGnYH11008 - for ; Thu, 11 Jul 2002 17:49:34 +0100 (BST) - (envelope-from dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 11 Jul 2002 17:49:34 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1026401921:10:09249:41; Thu, 11 Jul 2002 15:38:41 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1124337; 11 Jul 2002 15:38 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id B567C2BF65 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 347792BF62 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Received: (qmail 95914 invoked by uid 1005); 11 Jul 2002 15:38:04 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 95896 invoked by uid 76); 11 Jul 2002 15:38:04 -0000 -Received: from ironmail1.cc.lehigh.edu (HELO ironmail1.cc.lehigh.edu) (128.180.39.26) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Thu Jul 11 15:38:04 2002 -0000 -Received: from ([128.180.39.20]) - by ironmail1.cc.lehigh.edu with ESMTP with TLS; - Thu, 11 Jul 2002 11:35:06 -0400 (EDT) -Received: from lawrencework (pc-lfn0.dept.Lehigh.EDU [128.180.52.51]) - by rain.CC.Lehigh.EDU (8.12.4/8.12.4) with SMTP id g6BFZ6rr022463 - for ; Thu, 11 Jul 2002 11:35:06 -0400 -Message-ID: <0a0401c228f0$93feda10$3334b480@lawrencework> -From: "Phil R Lawrence" -To: -References: <083b01c22824$70357340$3334b480@lawrencework> <20020711140937.A568@dansat.data-plan.com> -Subject: Re: error msg suggestion -Date: Thu, 11 Jul 2002 11:35:20 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2600.0000 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -X-Status: A -Content-Length: 636 -Lines: 21 - -Tim Bunce wrote: -> Binding an undef should work and be treated as a NULL. -> -> Probably a bug in your code or the driver. But you didn't -> say which driver. - -Hmmm. quite right, undefs do bind as NULL. However, in this case I am -binding $hash{non-existent-key}, which autoinstantiates to an undef, and looks -like this in the trace: - undef (magic-sg:y) - -Of course it was my dumb fault for having the wrong key for lookup, but -nonetheless, perhaps this should work the same as a normal undef. - -# $DBI::VERSION = "1.14"; -# $DBD::ODBC::VERSION = '0.28'; -$DSN = 'driver=Microsoft Access Driver (*.mdb);dbq=StudyManager.mdb'; - -Thanks, -Phil - - diff --git a/err_bind/err_trailingblank.msg b/err_bind/err_trailingblank.msg deleted file mode 100644 index cdf34a32..00000000 --- a/err_bind/err_trailingblank.msg +++ /dev/null @@ -1,345 +0,0 @@ -From dbi-users-bounce@isc.org Mon May 1 21:12:02 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id VAA16051; Mon, 1 May 2000 21:12:00 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <14295-42@oink>; Fri, 1 May 1970 21:06:08 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 957208278:10:19133:4; Mon, 01 May 2000 19:11:18 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1123094; 1 May 2000 19:11 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id B3CCF3FAA; - Mon, 1 May 2000 12:10:53 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Mon, 01 May 2000 12:05:42 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A70763E34 - for ; Mon, 1 May 2000 12:05:30 -0700 (PDT) -Received: from scotth.emsphone.com (scotth.emsphone.com [199.67.51.179]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA25897 - for ; - Mon, 1 May 2000 12:05:30 -0700 (PDT) env-from (shildret@scotth.emsphone.com) -Received: (from shildret@localhost) by scotth.emsphone.com (8.9.3/8.9.3) - id OAA50011 for dbi-users@isc.org; - Mon, 1 May 2000 14:05:48 -0500 (CDT) (envelope-from shildret) -Message-ID: -X-Mailer: XFMail 1.4.0 on FreeBSD -X-Priority: 3 (Normal) -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 8bit -MIME-Version: 1.0 -Resent-Date: Thu, 29 Jul 1999 22:07:08 +0100 -Resent-Message-Id: <19990729220708.G17723@ig.co.uk> -Resent-From: Tim Bunce -Resent-To: Tim Bunce -Date: Mon, 01 May 2000 14:05:48 -0500 (CDT) -Sender: shildret@scotth.emsphone.com -From: "Scott T. Hildreth" -To: "dbi-users@isc.org" -Subject: FW: Oracle & Trailing Blanks - possible change in DBD::Oracle -Resent-Sender: shildret@scotth.emsphone.com -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 3885 -Lines: 94 - - -Here is the help, I got regarding the trailing spaces. - ------FW: <19990729220708.G17723@ig.co.uk>----- - -Date: Thu, 29 Jul 1999 22:07:08 +0100 -From: Tim Bunce -To: Tim Bunce -Subject: Oracle & Trailing Blanks - possible change in DBD::Oracle -Cc: "Scott T. HIldreth" , - dbi-users@isc.org - - *** From dbi-users -- To unsubscribe, see the end of this message. *** - -On Thu, Jul 29, 1999 at 09:49:38PM +0100, Tim Bunce wrote: -> *** From dbi-users -- To unsubscribe, see the end of this message. *** -> -> On Thu, Jul 29, 1999 at 09:33:55AM -0500, Scott T. HIldreth wrote: -> > -> > Hi all, I wonder if someone can let me know if I got this right. -> > I have a key to match which can contain trailing blanks. The -> > field in the database is CHAR(18). If I match the key with -> > sqlplus, Oracle finds a match, with or without the trailing -> > blank. When I do an sth->execute( $key ), the key is not -> > found. I abstract the key with substr, so the trailing blank -> > is in the key, but no match is found. Do I need to place qoutes -> > around the value in $key? -> -> Somewhat hiddedn in the Oraperl.pm docs it says this: -> -> --- -> B Substitution variables are now bound as type 1 (VARCHAR2) -> and not type 5 (STRING) by default. This can alter the behaviour of -> SQL code which compares a char field with a substitution variable. -> See the String Comparison section in the Datatypes chapter of the -> Oracle OCI manual for more details. -> -> You can work around this by using DBD::Oracle's ability to specify -> the Oracle type to be used on a per field basis: -> -> $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) -> $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); -> $csr->bind_param(1, $value_x, $char_attrib); -> $csr->bind_param(2, $value_y, $char_attrib); -> ora_bind($csr); # bind with no parameters since we've done bind_param()'s -> --- -> -> Ignoring the Oraperl specifics there the key point is to use -> -> $csr->bind_param($idx, $value, { ora_type => 5 }); -> -> I'll add something to the DBD::Oracle docs. - -[You'll still need to blank-pad the string.] - -Looking at this issue again I've discovered that the key issue is that -type 1 strips trailing blanks whilst type 5 doesn't. - -I'rather m concerned by this. Since I'm against the DBI changing the -data in any way on principle and since Oraperl used to use type 5 -I'm strongly considering changing DBD::Oracle 'back' to using type 5. - -This would only affect anyone who relies on placeholders having -trailing blanks stripped off. (I'll provide a way to alter the -default with a single statement and/or env var for anyone affected). - -If that's you - speak up now! - -Tim. - ------------------------------------------------------------------------------- -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of -'unsubscribe'. ------------------------------------------------------------------------------- - - ---------------End of forwarded message------------------------- - ----------------------------------- -E-Mail: Scott T. Hildreth -Date: 01-May-00 -Time: 14:04:41 ----------------------------------- - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - -From joshua.horton@mail.tju.edu Fri May 23 07:43:09 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.6/8.12.6) with ESMTP id h4N6UY7T061880 - for ; Fri, 23 May 2003 07:43:09 +0100 (BST) - (envelope-from joshua.horton@mail.tju.edu) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 23 May 2003 07:43:09 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1053631164:10:02298:54; Thu, 22 May 2003 19:19:24 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116141; 22 May 2003 19:19 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id BD31E21C13C - for ; Thu, 22 May 2003 15:18:30 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail.tju.edu (fw-tr16.tju.edu [147.140.233.16]) - by dolly1.pobox.com (Postfix) with ESMTP id 615A521C06D - for ; Thu, 22 May 2003 15:18:22 -0400 (EDT) -Received: from PCSE447.tjh.tju.edu by mail.tju.edu for Tim.Bunce@pobox.com; Thu, 22 May 2003 15:17:54 -0400 -Message-Id: <031301c32096$de68f6f0$2310ae0a@PCSE447> -From: "Joshua Horton" -To: -Subject: Re: :Oracle and Oracle 9.2? -Date: Thu, 22 May 2003 15:18:03 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 5.50.4807.1700 -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 3511 -Lines: 99 - -Re: :Oracle and Oracle 9.2? - ----------------------------------------------------------------------------- ----- - - a.. From: Tim Bunce - b.. Subject: Re: :Oracle and Oracle 9.2? - c.. Date: Tue, 15 Apr 2003 07:36:55 -0700 - ----------------------------------------------------------------------------- ----- - -I'd appreciate it if other people with Oracle 9.2.x could let me -know if it passed or failed for them and what their exact oracle -version (four digits) and platform (operating system) is. - -Thanks. - -Tim. - -On Fri, Apr 04, 2003 at 01:48:36PM +0200, Smejkal Petr wrote: -> I have the same experience on Linux however on Windows all tests passes -(I'm not -> sure if it is related to different Oracle version - test of windows Perl -against -> Linux Oracle is OK). -> -> Linux Oracle: 9.2.0.2 -> Windows Oracle: 9.2.0.1 -> DBI: 1.35 -> DBD::Oracle: 1.14 -> -> -- Petr Smejkal -> -- Business Systems Analyst / Country IT Cz/Sk -> -- +420 284 059 639 -> -> > -----Original Message----- -> > From: Tom Malaher [mailto:[EMAIL PROTECTED] -> > Sent: Friday, April 04, 2003 1:35 AM -> > To: [EMAIL PROTECTED] -> > Subject: DBD::Oracle and Oracle 9.2? -> > -> > -> > My sysadmin is trying to install DBD::Oracle on a Solaris box running -> > Oracle 9.2. -> > -> > The ph_type.t test is failing with -> > -> > PERL_DL_NONLAZY=1 ./perl "-MExtUtils::Command::MM" "-e" -> > "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -> > t/base.......ok -> > t/cursor.....ok -> > t/general....ok -> > t/long.......ok -> > t/meta.......ok -> > t/ph_type....NOK 12 expected 'trailing' but got 'trailing ' -> > for VARCHAR2 -> > t/ph_type....FAILED test 12 -> > Failed 1/19 tests, 94.74% okay -> > t/plsql......ok -> > t/reauth.....skipped -> > all skipped: no reason given -> > t/select.....ok -> > Failed Test Stat Wstat Total Fail Failed List of Failed -> > -------------------------------------------------------------- -> > ----------------- -> > t/ph_type.t 19 1 5.26% 12 -> > 1 test skipped. -> > Failed 1/9 test scripts, 88.89% okay. 1/314 subtests failed, -> > 99.68% okay. -> > *** Error code 29 -> > make: Fatal error: Command failed for target `test_static' -> > -> > Is there a known problem with DBD::Oracle and Oracle 9.x? -> > Has Oracle changed the behavior of trailing spaces in VARCHAR2 fields? -> > -> > I've run the same test script on an oracle 8 installation -> > using DBD::Oracle 1.06 and DBI 1.14, and it works fine (no trailing -> > space is returned). -> > -> > Tom -> > -My config:HP-UX 11.11 (64-bit) on rp5470 2x733 5GB RAMOracle 9.2.0.2.0 -Enterprise Edition (64-bit)Perl 5.8.0 custom compiled with -./Configure -Duse64bitall -Ubincompat5005 -Duselargefiles -Dprefix=/opt/perl -5 ; all other options defaultDBI-1.32 all passed some skippedDBD-Oracle-1.14 -: PERL_DL_NONLAZY=1 /opt/perl5/bin/perl "-MExtUtils::Command::MM" -"-e" "test_harness(0, 'blib/lib', 'blib/arch')" -t/*.tt/base.......okt/cursor.....okt/general....okt/long.......okt/meta..... -..okt/ph_type....ok 11/19 expected 'trailing' but got 'trailing ' for -VARCHAR2t/ph_type....FAILED test 12 Failed 1/19 tests, 94.74% -okayt/plsql......okt/reauth.....skipped all skipped: no reason -givent/select.....okFailed Test Stat Wstat Total Fail Failed List of -Failed---------------------------------------------------------------------- --------------------------------------------------------t/ph_type.t -19 1 5.26% 121 test skipped.Failed 1/9 test scripts, 88.89% okay. -1/314 subtests failed, 99.68% okay.*** Error exit code 2Stop.Thanks,Josh -Horton - - -From nobody@fsck.com Tue Dec 30 14:33:50 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hBUEWNnP026077 - for ; Tue, 30 Dec 2003 14:33:50 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Dec 2003 14:33:50 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AbJwa-0003ua-H6; - Tue, 30 Dec 2003 13:29:56 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AbJwa-0003ua-H6 - for pobox@dbi.demon.co.uk; Tue, 30 Dec 2003 13:29:56 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 56DAD4C6 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3B3564C8 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 30 Dec 2003 08:29:54 -0500 (EST) -Received: (qmail 10988 invoked by uid 225); 30 Dec 2003 13:29:53 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 10984 invoked by alias); 30 Dec 2003 13:29:52 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 30 Dec 2003 05:29:41 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 8760D11153; Tue, 30 Dec 2003 08:29:37 -0500 (EST) -Subject: [cpan #4786] Oracle 9.2.0.0 fails a test in ph_types.t -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4786 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -To: "AdminCc of cpan Ticket #4786": ; -Date: Tue, 30 Dec 2003 08:29:37 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,SUPERLONG_LINE,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -Content-Length: 888 -Lines: 11 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -Assuming that ORA_OCI() gets set correctly when compiling against 9.2, the attached patch will work. I also tried this in SQL*Plus and was able to insert a trailing space into a VARCHAR2. (I replicated the test in ph_types.t). - -I did not test my patch as I installed DBD::Oracle 1.14 by setting the chops_spaces value in %test_info to 0. When I did that, everything installed fine. However, I didn't think that my solution was the best for the module, so I figured ORA_OCI should do the trick. - -I'm running Perl5.8.0 for Solaris2.9 going against the full Oracle build for 9.2. (I did not run into this issue, surprisingly, on Redhat9 running Perl 5.8.2, but I built against Oracle 9.1 there ...) - diff --git a/err_build/err_aix64.msg b/err_build/err_aix64.msg deleted file mode 100644 index f952e29e..00000000 --- a/err_build/err_aix64.msg +++ /dev/null @@ -1,142 +0,0 @@ -From SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com Fri Jan 7 16:11:33 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j07GAqfa044155 - for ; Fri, 7 Jan 2005 16:11:32 GMT - (envelope-from SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Fri, 07 Jan 2005 16:11:32 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CmvQB-0003Po-Kf; - Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CmvQB-0003Po-Kf - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CmvQA-0002zW-VM - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 49778102ACC; - Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 384E5FF808 - for ; Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Received-SPF: pass (boggle.pobox.com: domain of dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by boggle.pobox.com (Postfix) with SMTP id A74B8F4090 - for ; Fri, 7 Jan 2005 09:48:57 -0500 (EST) -Received: (qmail 2690 invoked by uid 514); 7 Jan 2005 14:48:56 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 2622 invoked from network); 7 Jan 2005 14:48:55 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 7 Jan 2005 14:48:55 -0000 -Received: (qmail 13078 invoked by uid 225); 7 Jan 2005 14:48:54 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 13048 invoked by alias); 7 Jan 2005 14:48:51 -0000 -X-Spam-Status: No, hits=-4.6 required=8.0 - tests=BAYES_00,HTML_MESSAGE,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: neutral (x1.develooper.com: local policy) -Received: from outmx020.isp.belgacom.be (HELO outmx020.isp.belgacom.be) (195.238.2.201) - by la.mx.develooper.com (qpsmtpd/0.28) with ESMTP; Fri, 07 Jan 2005 06:48:38 -0800 -Received: from outmx020.isp.belgacom.be (localhost [127.0.0.1]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmOgS020070 - for ; Fri, 7 Jan 2005 15:48:24 +0100 - (envelope-from ) -Received: from relaytwo.roularta.be (smtprelaytwo.roularta.be [194.78.177.23]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmMDA020034 - for ; Fri, 7 Jan 2005 15:48:22 +0100 - (envelope-from ) -Received: from rmgexch01.RMG.be ([89.0.35.150]) by roesfront3.RMG.be with Microsoft SMTPSVC(5.0.2195.6713); - Fri, 7 Jan 2005 15:47:50 +0100 -X-MimeOLE: Produced By Microsoft Exchange V6.5.7226.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----_=_NextPart_001_01C4F4C7.EE810087" -Subject: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Date: Fri, 7 Jan 2005 15:48:21 +0100 -Message-ID: -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Thread-Index: AcT0x+Y4G1R3vbX6Rh+QdPyNy/10eQ== -From: -To: -X-OriginalArrivalTime: 07 Jan 2005 14:47:50.0598 (UTC) FILETIME=[DC5D2E60:01C4F4C7] -Status: RO -Content-Length: 1678 -Lines: 62 - -------_=_NextPart_001_01C4F4C7.EE810087 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - -Hi,=20 -=20 -I finally succeeded in installing a 64bit build of Perl and its modules -for Oracle 64-bit. We were running in 32bit but integrating Proc and -cobols in our perl scripts only worked when we changed environments to -64bit causing problems for the oracle connections in perl. It's nothing -special, no editing of makefiles ... I can't believe I lost so much time -on this one ;) ( Now that I look back to my problems, they were probably -caused by using a wrong perl build for compiling the modules, Aix has -its default perl now under /bin.. stupid me )=20 -=20 -perl 5.8.6 64bit ----------------- -./Configure -de -Dcc=3Dgcc -Duse64bitall=20 -make -make test -make install -=20 -DBI 1.46 --------- -!!Make sure you are using the newly installed perl!! - check with perl -v it should show :=20 - This is perl, v5.8.6 built for aix-64all -perl Makefile.PL -make -make test -make install=20 -=20 -DBD-Oracle 1.16 ---------------- -!!Use correct perl like above mentioned!!=20 -export ORACLE_HOME=3D=20 -export LIBPATH=3D$ORACLE_HOME/lib -export LD_LIBRARY_PATH=3D$ORACLE_HOME/lib -=20 -perl Makefile.PL=20 -make -make test ( some test may still fail, I had 85% success on tests )=20 -make install=20 -=20 -Test -----=20 -=20 -test with :=20 - use DBI; - $dbh=3DDBI->connect("dbi:Oracle:","system","manager")|| die -$DBI::errstr; - $stmt=3D$dbh->prepare("select * from tab"); - $rc=3D$stmt->execute() || die $DBI::errstr; - while (my($record)=3D$stmt->fetchrow()) - { - print $record; - } -=20 -Happy 64-bit perling ;)=20 - -------_=_NextPart_001_01C4F4C7.EE810087-- - diff --git a/err_build/err_hpux_ld.msg b/err_build/err_hpux_ld.msg deleted file mode 100644 index 27f9cd07..00000000 --- a/err_build/err_hpux_ld.msg +++ /dev/null @@ -1,89 +0,0 @@ -From SRS0=JbZc=U3=lincolnbaxter.com=lab@bounce2.pobox.com Tue Jun 21 05:02:19 2005 -Return-Path: -X-Original-To: timbo@localhost -Delivered-To: timbo@localhost.data-plan.com -Received: from localhost (localhost [127.0.0.1]) - by timac.data-plan.com (Postfix) with ESMTP id B016F2A3D98 - for ; Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DkYXK-0003m5-Mr; - Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DkYXK-0003m5-Mr - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1DkYXJ-00006n-QE - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AF60172691; - Mon, 20 Jun 2005 22:29:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from ms-smtp-04-eri0.southeast.rr.com (ms-smtp-04-lbl.southeast.rr.com [24.25.9.103]) - by gold.pobox.com (Postfix) with ESMTP id A3C1E7272E - for ; Mon, 20 Jun 2005 22:29:11 -0400 (EDT) -Received: from lincolnbaxter.com (cpe-069-132-010-126.carolina.res.rr.com [69.132.10.126]) - by ms-smtp-04-eri0.southeast.rr.com (8.12.10/8.12.7) with ESMTP id j5L2TIL4001864 - for ; Mon, 20 Jun 2005 22:29:18 -0400 (EDT) -Received: (qmail 5171 invoked from network); 20 Jun 2005 22:29:07 -0400 -Received: from lws (192.168.0.25) - by lws with SMTP; 20 Jun 2005 22:29:07 -0400 -Subject: Re: gcc options when building DBD:Oracle -From: "Lincoln A. Baxter" -Reply-To: lab@lincolnbaxter.com -To: jriekenberg@everestkc.net -Cc: Tim Bunce -In-Reply-To: -References: -Content-Type: text/plain -Date: Mon, 20 Jun 2005 22:29:07 -0400 -Message-Id: <1119320947.17452.484.camel@lws> -Mime-Version: 1.0 -X-Mailer: Evolution 2.2.1.1 -Content-Transfer-Encoding: 7bit -X-Virus-Scanned: Symantec AntiVirus Scan Engine -Status: RO -Content-Length: 2011 -Lines: 38 - -Hi Jan, - -This looks like something that might be relatively easy to fix in -Makefile.PL. But I no longer have access to HPUX systems, and never -built DBD-Oracle with gcc on that platform. I could add your message to -the README.hpux file, but it is becoming less and less necessary to read -this file with newer versions of DBD-Oracle, in which Makefile.PL has -been made much smarter. - -Would you consider sending Tim or me a patch to Makefile.PL that -generates the right $(LD) command (only on HP rp8400, and only for your -version of gcc or later? - -Lincoln - -On Mon, 2005-06-20 at 15:36 -0500, jriekenberg@everestkc.net wrote: -> Lincoln, -> -> I recently built DBD:Oracle on an HP rp8400. Everything worked as expected until I actually issued the "make" command. Make proceeded as expected until it reached "MakeMaker dynamic_lib" section. The gcc line in that section failed with the error in the attached text file. Apparently gcc was not correctly passing the "+b" option to ld. Instead, it was attempting to interpret the option itself. It assumed the "+b" was a filename, and that failed because gcc could not find the file. I ended up adding the "-Xlinker" option before the "+b" and before the "$(LD_RUN_PATH)" in the line in Makefile. The line now looks like this: -> -> $(LD) -Xlinker +b -Xlinker "$(LD_RUN_PATH)" $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) -> -> Running "make" now works correctly. -> -> Also, "make test" returned the following error when attempting to build the various tests: -> -> /usr/lib/dld.sl: Can't shl_load() a library containing Thread Local Storage: /usr/lib/libcl.2 -> -> Setting LD_PRELOAD with "export LD_PRELOAD=/usr/lib/libcl.2" corrected this problem, and "make test" worked correctly. -> -> -> I didn't see DBD::Oracle documentation on exactly this, so I'm sending this to you. You may be aware of these items already. If so, please disregard this. -> -> Jon Riekenberg -> -> -> - - diff --git a/err_build/err_hpuxsuccess.msg b/err_build/err_hpuxsuccess.msg deleted file mode 100644 index c6edd79f..00000000 --- a/err_build/err_hpuxsuccess.msg +++ /dev/null @@ -1,279 +0,0 @@ -From dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org Tue Mar 23 17:00:25 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i2NGvAxX021862 - for ; Tue, 23 Mar 2004 17:00:23 GMT - (envelope-from dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 23 Mar 2004 17:00:23 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1B5oND-0000Ba-LH; - Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1B5oND-0000Ba-LH - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [208.210.124.70] (helo=majesty.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1B5oNC-00001d-92 - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:26 +0000 -Received: from majesty.pobox.com (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 18033954B4 - for ; Tue, 23 Mar 2004 11:03:24 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 3577D954BE - for ; Tue, 23 Mar 2004 11:03:21 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by majesty.pobox.com (Postfix) with SMTP - for ; Tue, 23 Mar 2004 11:02:41 -0500 (EST) -Received: (qmail 6527 invoked by uid 1005); 23 Mar 2004 16:02:21 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6510 invoked by uid 76); 23 Mar 2004 16:02:20 -0000 -Received: from x1.develooper.com (HELO x1.develooper.com) (63.251.223.170) - by onion.perl.org (qpsmtpd/0.27.1) with SMTP; Tue, 23 Mar 2004 08:02:20 -0800 -Received: (qmail 1985 invoked by uid 225); 23 Mar 2004 16:02:15 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 1893 invoked by alias); 23 Mar 2004 16:02:00 -0000 -X-Spam-Status: No, hits=0.0 required=7.0 - tests= -X-Spam-Check-By: la.mx.develooper.com -Received: from Unknown (HELO dundee.fpcc.net) (204.144.241.120) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Tue, 23 Mar 2004 08:01:44 -0800 -Received: from aberdeen.fpcc.net (aberdeen.fpcc.net [204.144.241.125]) - by dundee.fpcc.net (8.11.6/8.11.6) with ESMTP id i2NG1f111241; - Tue, 23 Mar 2004 09:01:41 -0700 -Received: from aberdeen.fpcc.net (localhost.localdomain [127.0.0.1]) - by aberdeen.fpcc.net (8.12.8/8.12.8) with ESMTP id i2NFrNOv024637; - Tue, 23 Mar 2004 08:53:23 -0700 -Received: (from laubster@localhost) - by aberdeen.fpcc.net (8.12.8/8.12.8/Submit) id i2NFrMOx024635; - Tue, 23 Mar 2004 08:53:22 -0700 -X-Authentication-Warning: aberdeen.fpcc.net: laubster set sender to dbiusers@laubster.org using -f -Date: Tue, 23 Mar 2004 08:53:22 -0700 -From: "J.D. Laub" -To: dbi-users@perl.org -Cc: lbaxter@fleetcc.com -Subject: SUCCESS: DBD::Oracle 1.15 on HP-UX 11.11 -Message-ID: <20040323155322.GA24576@aberdeen.fpcc.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -Organization: The Psychiatric Ward of Terrors -X-Virus-Checked: Checked -Status: RO -Content-Length: 9105 -Lines: 206 - -I've just had success building DBD::Oracle 1.15 on HP-UX 11.11 -(against both oracle 8.1.7 & oracle 9.2.0) & thought I'd share my -experience. - -Disclaimer: these instructions relate to our environment. It may be -that our sysadmins/dbas chose to configure/install things a certain -way (i.e., our install of $ORACLE_HOME/bin/sqlplus was *chosen* -to be 1.1/32), and/or that we're running old versions of software -(i.e., perhaps later releases of gcc don't ignore -mpa-risc-1-1). -In fact, there are probably some mistruths in here; rest assured -they're not intentional. :-) - -I'm unsure how (if?) I should go about getting this information into -the DBD::Oracle README.hpux. Lincoln, please contact me with any -thoughts you have. - - -### The summary ################################ - -Use the ansic compiler (~US$800/cpu). - -Shell variables I used: - PATH=/bin:$PATH # use 32bit ar & nm since using a 32bit cc - PERLDEST=/opt/perl_ora8 # or "perl_ora9" for an ora9 build - PATH=$PERLDEST/bin:$PATH # for build of DBI, pick up new perl - export LDLOADLIBS='+b : +s' # handy for ORACLE_SID connections to ora7 - unset PERLLIB # important to avoid outdated cruft - export ORACLE_USERID=scott/tiger # insecure - consider using "/" - ORACLE_SID=orcl - ORAENV_ASK=NO - . oraenv # sets LD_LIBRARY_PATH and SHLIB_PATH - -For ora8: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DAportable ' \ - -A prepend:ldflags='+z +DAportable ' - -For ora9: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DA2.0W ' \ - -A prepend:ldflags='+z +DA2.0W ' \ - -Dlibpth='/usr/lib/pa20_64 /usr/local/pa20_64/lib' - -After you use the above to install perl, DBI & DBD::Oracle will -build in the normal fashion. - - -### General Notes ################################ - -* During "make test", I received 1 failure (on -lib/ExtUtils/t/Constant) for ora8, and 3 failures (on -lib/ExtUtils/t/Constant, lib/ExtUtils/t/recurs, and t/op/write) for -ora9. Nevertheless, things seem mostly OK. - -* These are the various combinations possible for a given compiled -file on HP-UX 11.11 (the quoted description is what gets kicked out -by the "file" command): - - PA-RISC1.1/32bit ("PA-RISC1.1 relocatable object") - (I'll call this 1.1/32) - PA-RISC2.0/32bit ("PA-RISC2.0 relocatable object") - (I'll call this 2.0/32) - PA-RISC2.0/64bit ("ELF 64-bit MSB relocatable, PA-RISC 2.0 (LP64)") - (I'll call this 2.0/64) - -* "perl -v" lies about the RISC level: -$ file ./perl -./perl: PA-RISC1.1 shared executable dynamically linked -not stripped -$ ./perl -v | grep RISC -This is perl, v5.8.3 built for PA-RISC2.0 - -* If you'll be linking against 2.0/64 libraries, you'll have to -build all your object modules that way. I've not yet found a way -to link 32bit executables to 64bit libraries (and vice versa). Run -the "file" command on your Oracle libraries to find out which path -you'll have to take. - -* Two environment variables control where libraries are -searched. LD_LIBRARY_PATH and SHLIB_PATH (in that order) are -used for 64bit executables, while SHLIB_PATH is used for 32bit -executables. - -* I tried attempts using aCC as well as the default (free) cc that -comes with hpux; both avenues were too problematic to continue -pursuing. - -* The format of compiled objects is specified by compiler options. -According to the ansic compiler docs, the options are "+DAportable" -(for 1.1/32), "+DA2.0" (for 2.0/32), and "+DA2.0W" (for 2.0/64). -For gcc, the corresponding switches are -mpa-risc-1-1 (for 1.1/32) -and -mpa-risc-2-0 (for 2.0/64), but I've found that -mpa-risc-1-1 -is ineffective. (According to the "file" command, you *always* get -2.0/64.) - -* Our gcc displays the behavior described at -http://sources.redhat.com/ml/binutils/2002-10/msg00586.html and -http://aspn.activestate.com/ASPN/Mail/Message/perl5-porters/1641238 -, so is therefore unusable anytime '-lcl' is to be specified. -Unfortunately, that library is required for DBD::Oracle builds. -(The workaround of adding the 3 declarations does seem to work, -but littering those throughout perl's Configure, main.c, etc. -seems a big task.) Attempts to get gcc to use the hp ld instead -of the gnu ld (by specifying -mno-gnu-ld and -fno-gnu-linker) were -unsuccessful. The first html link shown above indicates you have -to rebuild gcc to use the hp linker, and that was not an incredibly -desirable path to pursue. - -* Our default PATH was set to put /usr/local/pa20_64/bin ahead of -/bin. This caused problems because (I think) the 64bit versions -of either ar (the archiver) or nm (the symbol lister) do not play -well with /bin/cc (the 32bit compiler). The tweak to put /bin at -the head of PATH, so we get the 32bit versions, takes care of the -problem. - -* I ran into an intermittent quirk during the build of perl in which -typing "make" (just after the Configure) did nothing. It turns out -that only dependencies were being written to "makefile", and that -removing "makefile" (so it could be automatically rebuilt) solved -the problem. - -* Most of my research on finding the right compiler/linker switches -was done with a "hello world" C program, trying the various -compilers and options, and trying to link it with the oracle -libraries. This proved to be a good choice, as trying to test -compilers/switches against the perl source distribution would have -proved quite difficult. - - -### DBD::Oracle specific ################################ - -* ora8 delivers its libraries in 2 formats: 1.1/32 (under -$ORACLE_HOME/lib) and 2.0/64 (under $ORACLE_HOME/lib64). ora7 -delivers only 1.1/32, while ora9 delivers only 2.0/64. It may seem -a bit inconsistent considering the ora8 setup, but ora9 libraries -are found under $ORACLE_HOME/lib and not $ORACLE_HOME/lib64. - -* Under ora8, oraenv incorrectly sets LD_LIBRARY_PATH to include -$ORACLE_HOME/lib instead of $ORACLE_HOME/lib64, so you've got to -make an override in oraenv_local if you want to use 2.0/64. It -doesn't harm anything, but oraenv unnecessarily sets LD_LIBRARY_PATH -for ora7 (a 64bit environment variable for a 32bit application). - -* If you use shared libraries AND you'll be upgrading Oracle, you -should expect you'll need to rebuild DBD::Oracle unless you'll keep -the old Oracle libraries available. - -* If you're building against ora8, the setting of LDLOADLIBS -is recommended so that when oraenv set SHLIB_PATH to the -$ORACLE_HOME/lib for ora7, the code will still find the ora8 -libraries. - -* We expect to need local (ORACLE_SID) connections for ora8 & -ora9. We could have gone with a single 2.0/64 perl coupled with -2 DBD::Oracle installs and PERLLIB twiddling in oraenv_local to -get to the right one. Instead, we chose to do 2 perl installs -(/opt/perl_ora8 and /opt/perl_ora9) because we can also connect -locally to ora7 by using the 1.1/32 ora8 version, something that -isn't possible with a 2.0/64 version. Also, we've some older 1.1/32 -machines into which we'd like to plop a tarball of the perl stuff, -so a 1.1/32 executable was desirable. - -* Some tests I ran were hinting that with 2.0/64, specifying "+b :" -on the build of DBD::Oracle correctly configured Oracle.sl as far as -the chatr program is concerned, but it seemed that LD_LIBRARY_PATH -*always* needed to be set correctly. (I.e., the embedded path in -the library seemed to be ignored.) I didn't pursue researching this -since there's no way to get the ora9 compiled code to connect to -ora8, meaning LD_LIBRARY_PATH had to be set correctly anyway. - -Testing local (ORACLE_SID) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora9 cannot connect to ora8 or ora7: "UNKNOWN - OCI STATUS 1804) OCIInitialize. Check ORACLE_HOME and NLS - settings etc." - -Testing remote (sqlnet) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 can connect to ora9 -builds against 2.0/64 ora9 can connect to ora8 -builds against 2.0/64 ora9 cannot connect to ora7: "OCI-21500: internal - error code" - - -### Versions ################################ - -perl: 5.8.3 -dbi: 1.41 -dbd-oracle: 1.15 -$ strings /bin/cc | grep Compiler -HP92453-01 B.11.11.08 HP C Compiler -$ strings /bin/ld | grep linker -$Revision: 92453-07 linker linker crt0.o B.11.16 000601 $ -@(#)92453-07 linker command s800.sgs ld PA64 B.11.18 REL 000922 -$ gcc -v -Reading specs from /usr/local/pa20_64/lib/gcc-lib/hppa64-hp-hpux11.11/3.3.1/specs -Configured with: ../src/configure --enable-languages=c,c++ --prefix=/usr/local/pa20_64 --with-local-prefix=/usr/local/pa20_64 --with-gnu-as --with-as=/usr/local/pa20_64/bin/as --with-gnu-ld --with-ld=/usr/local/pa20_64/bin/ld --disable-shared --disable-nls --host=hppa64-hp-hpux11.11 -Thread model: single -gcc version 3.3.1 - --- -J.D. Laub (Laubster) |"Your leg's too long / Your skull's too strong / -dbiusers@laubster.org| Suppose your nose is wrong." - Renaldo & the Loaf - diff --git a/err_build/err_instantclient.msg b/err_build/err_instantclient.msg deleted file mode 100644 index f0e549eb..00000000 --- a/err_build/err_instantclient.msg +++ /dev/null @@ -1,207 +0,0 @@ -From SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Feb 2 10:11:05 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j12AAUZ6055956 - for ; Wed, 2 Feb 2005 10:11:05 GMT - (envelope-from SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 02 Feb 2005 10:11:05 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwGaQ-0002Bn-H6; - Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwGaQ-0002Bn-H6 - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwGaP-00042G-Vb - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 9C3FB1E3946; - Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 879981E3958 - for ; Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Received-SPF: pass (kelvin.pobox.com: domain of dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by kelvin.pobox.com (Postfix) with SMTP id D0B001E3946 - for ; Wed, 2 Feb 2005 04:14:08 -0500 (EST) -Received: (qmail 7188 invoked by uid 514); 2 Feb 2005 09:14:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -List-Id: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 2531 invoked from network); 2 Feb 2005 04:10:16 -0000 -Delivered-To: dbi-users@perl.org -X-Spam-Status: No, hits=-2.6 required=8.0 - tests=BAYES_00,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: pass (x1.develooper.com: local policy) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgw.shina.sankyo.co.jp: iscan owned process doing -bs -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: Making DBD::Oracle with Instant Client 10.1.0.3 -Date: Wed, 2 Feb 2005 13:09:58 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBE9@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUI3Q64h9ykph8RSl6pF0OpBbTqJA== -To: -X-OriginalArrivalTime: 02 Feb 2005 04:09:59.0005 (UTC) FILETIME=[0F7508D0:01C508DD] -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 44 - -Hi all, - -Thanks to the devel package, I've got succeeded in making DBD::Oracle -with the Oracle Instant Client 10.1.0.3, no *.mk files, in my linux box. -My recipe is: - -1) install both basic- and devel-10.1.0.3 rpm packages -2) export ORALCE_HOME="/usr/lib/oracle/10.1.0.3/client" -3) export LD_LIBRARY_PATH="$ORACLE_HOME/lib:$LD_LIBRARY_PATH" -4) modify the Makefile.PL file to bypass the find_headers() routine and - to pass a correct -I flag to cc (the attached dirty patch is FYI) -5) execute the Makefile.PL * with the -l option *, perl Makefile.PL -l -6) make && make test && make install -# I got many errors in t/30long.t (retrieving blobs ?) -# but it seems to work fairly. - -I hope this could help those who are annoyed with the "Unable to locate an -oracle.mk,..." error. - -Happy DBing, - -Satoshi - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+# my @h_dirs = find_headers(); - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client"; - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -From SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com Thu Feb 3 08:10:48 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j138AMOi093146 - for ; Thu, 3 Feb 2005 08:10:48 GMT - (envelope-from SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Thu, 03 Feb 2005 08:10:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwboD-0005ug-LV; - Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwboD-0005ug-LV - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwboD-0000Wn-82 - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 70999102D9F; - Thu, 3 Feb 2005 02:53:48 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 5F45E102DCC - for ; Thu, 3 Feb 2005 02:53:48 -0500 (EST) -X-Pobox-Antispam: Require PTR Record returned DENY: 210.81.52.253 has no PTR record -X-Pobox-Antispam: country/Japan returned DENY: sender address snisim@sankyo.co.jp matches TLD .jp (Japan) -Received-SPF: none (boggle.pobox.com: domain of snisim@sankyo.co.jp does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for snisim@sankyo.co.jp to mail through 210.81.52.253) -Received: from mailgws.shina.sankyo.co.jp (unknown [210.81.52.253]) - by boggle.pobox.com (Postfix) with ESMTP id A38A5102E20 - for ; Thu, 3 Feb 2005 02:53:46 -0500 (EST) -Received: from es007.sankyo.co.jp (localhost [127.0.0.1]) - by mailgws.shina.sankyo.co.jp (8.9.3p2/3.7W) with ESMTP id LAA15117 - for ; Thu, 3 Feb 2005 11:45:39 +0900 (JST) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgws.shina.sankyo.co.jp: iscan owned process doing -bs -Received: from EVS001.sankyo.co.jp ([10.14.121.200]) by es007.sankyo.co.jp with Microsoft SMTPSVC(6.0.3790.0); - Thu, 3 Feb 2005 11:45:39 +0900 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: RE: Making DBD::Oracle with Instant Client 10.1.0.3 -Content-class: urn:content-classes:message -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Date: Thu, 3 Feb 2005 11:46:07 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBEC@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUJEc1pQuIX++g2S8y4AE9WqWRYtQAhsK+Q -To: -X-OriginalArrivalTime: 03 Feb 2005 02:45:39.0123 (UTC) FILETIME=[71F21030:01C5099A] -Status: RO -Content-Length: 1192 -Lines: 36 - -Hi Tim, - -Thank you for your kind reply. - -I found my patch will cause a compilation error for the local variable -@h_dirs gets into undefined after commenting out the line 279. -It should be corrected as following: - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+ my @h_dirs; - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client" - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -I'm not a dbi-users member so I can't reply my post... I wonder if you can do it. - -Thanks, - -Satoshi - - diff --git a/err_build/err_makefileundef.msg b/err_build/err_makefileundef.msg deleted file mode 100644 index b98d782a..00000000 --- a/err_build/err_makefileundef.msg +++ /dev/null @@ -1,87 +0,0 @@ -From timbo Tue Apr 26 09:19:54 2005 -Return-path: -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 26 Apr 2005 09:19:54 -0700 (PDT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DQSgy-0006AU-4c; - Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DQSgy-0006AU-4c - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1DQSgy-0003uM-1T - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 759703B902A; - Tue, 26 Apr 2005 12:13:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 80C0A39F279 - for ; Tue, 26 Apr 2005 12:13:42 -0400 (EDT) -Received-SPF: none (kelvin.pobox.com: domain of lembark@wrkhors.com does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 66.246.154.128(mail-out.pilosoft.net) -Received: from mail.pilosoft.net (mail-out.pilosoft.net [66.246.154.128]) - by kelvin.pobox.com (Postfix) with ESMTP id 2ED743AB75B - for ; Tue, 26 Apr 2005 12:12:30 -0400 (EDT) -Received: from [192.168.1.2] (dsl-69-31-90-94.pilosoft.com [69.31.90.94]) - by mail.pilosoft.net (8.12.8/8.12.8) with ESMTP id j3QGA3u1014203 - for ; Tue, 26 Apr 2005 12:10:03 -0400 -Date: Tue, 26 Apr 2005 12:14:22 -0400 -From: Steven Lembark -Reply-To: lembark@wrkhors.com -To: Tim Bunce -Subject: Possible glitch in DBD::Oracle-1.48 Makefile.pl -Message-ID: <269F0144DC99100E7C80975F@[192.168.1.2]> -X-Mailer: Mulberry/3.1.3 (Linux/x86) -X-Workhorse: lembark 1.1 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii; format=flowed -Content-Transfer-Encoding: 7bit -Content-Disposition: inline -X-Virus-Scanned: ClamAV version 0.83, clamav-milter version 0.83 on mail.pilosoft.net -X-Virus-Status: Clean -X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=failed version=3.0.2 -X-Spam-Level: 0.0 -X-Spam-Checker-Version: SpamAssassin 3.0.2 (2004-11-16) on cheeta.pilosoft.net -X-Status: A -Content-Length: 1342 -Lines: 36 - -Linking with OTHERLDFLAGS = -L/opt/oracle/product/9.2/lib/ --L/opt/oracle/product/9.2/rdbms/lib/ -lclntsh `cat -/opt/oracle/product/9.2/lib/sysliblist` -ldl -lm [from 'build' rule] - -Checking if your kit is complete... -Looks good -Use of uninitialized value in substitution (s///) at Makefile.PL line 1446. -LD_RUN_PATH=/opt/oracle/product/9.2/lib:/opt/oracle/product/9.2/rdbms/lib -Using DBD::Oracle 1.16. - - - sub const_loadlibs { - my $self = shift; - local($_) = $self->SUPER::const_loadlibs(@_); - # edit LD_RUN_PATH ... - my ($ldrp) = m/^LD_RUN_PATH\s*=\s*(.*)/m; - # remove redundant /lib or /usr/lib as it can cause problems --> $ldrp =~ s!:(/usr)?/lib$!!; - # if it's empty then set it manually - #Lincoln: if pick the right library path - my $libdir = main::ora_libdir(); - $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; - #print "ldrp=$ldrp\n"; - - # stitch it back in - s/^LD_RUN_PATH\s*=\s*(.*)/LD_RUN_PATH=$ldrp/m; - my $env = $ENV{LD_RUN_PATH}; - print "Ignoring LD_RUN_PATH='$env' in environment\n" if $env; - print "LD_RUN_PATH=$ldrp\n"; - return $_; - } - --- -Steven Lembark 85-09 90th Street -Workhorse Computing Woodhaven, NY 11421 -lembark@wrkhors.com 1 888 359 3508 - diff --git a/err_build/err_memleak.msg b/err_build/err_memleak.msg deleted file mode 100644 index d40913d7..00000000 --- a/err_build/err_memleak.msg +++ /dev/null @@ -1,95 +0,0 @@ -From SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com Wed Sep 1 16:31:37 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i81FRlpg021884 - for ; Wed, 1 Sep 2004 16:31:37 +0100 (BST) - (envelope-from SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 Sep 2004 16:31:37 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C2WYO-00034m-M1; - Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C2WYO-00034m-M1 - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1C2WYO-0005CR-FY - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 1C1D6A758C; - Wed, 1 Sep 2004 10:57:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 184C8A7214 - for ; Wed, 1 Sep 2004 10:57:32 -0400 (EDT) -Received-SPF: fail (boggle.pobox.com: domain of www-data@pallas.eruditorum.org does not designate 63.251.223.170 as permitted sender) -X-SPF-Override: pass (client 63.251.223.170 was found in trusted-forwarder.org, overrides regular SPF fail) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.170(x1.develooper.com) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP id 7A6C9A7555 - for ; Wed, 1 Sep 2004 10:57:06 -0400 (EDT) -Received: (qmail 5427 invoked by uid 225); 1 Sep 2004 14:57:04 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 5403 invoked by alias); 1 Sep 2004 14:57:02 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 01 Sep 2004 07:56:59 -0700 -Received: by pallas.eruditorum.org (Postfix, from userid 33) - id 1FDD784C0F5; Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -Subject: [cpan #6245] Confirmed memory leak -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #6245 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -Date: Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -To: undisclosed-recipients: ; -Status: RO -Content-Length: 937 -Lines: 38 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -I Using : -1. SunOS 5.6 Generic_105181-33 sun4u sparc SUNW,Ultra-Enterprise - Perl 5.005_03 - DBI 1.37 - DBD-Oracle 1.14 - Oracle Release 8.1.5.0.0 - - -2. Linux 2.4.18-17.7.xsmp #1 SMP i686 - Perl 5.6.1 - DBI 1.41 - DBD-Oracle 1.16 - Oracle Release 8.1.6.0.0 - -II The following code: - -use strict; -use DBI; - -foreach ( 1 .. 100 ) { - my $dbh = DBI->connect( 'dbi:Oracle:host=****', '***', '***' ); - $dbh->disconnect(); - sleep(1) -} - -III Leak about 4K every 10 seconds - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8724 8720 2760 S 1.3 3.4 0:01 perl - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8736 8732 2760 S 0.7 3.4 0:01 perl - diff --git a/err_build/err_solarisnotes.msg b/err_build/err_solarisnotes.msg deleted file mode 100644 index eaddc475..00000000 --- a/err_build/err_solarisnotes.msg +++ /dev/null @@ -1,482 +0,0 @@ -From SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com Wed Dec 22 08:11:00 2004 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id iBM8Aog0091816 - for ; Wed, 22 Dec 2004 08:11:00 GMT - (envelope-from SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 22 Dec 2004 08:11:00 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Ch0it-0001A5-Rv; - Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Ch0it-0001A5-Rv - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Ch0is-0000To-R8 - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id F0F0DFE10C; - Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 8B2AAFE1C3 - for ; Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Received-SPF: none (lime.pobox.com: domain of alexzar@zorranlabs.com does not designate permitted sender hosts) -Received: from penguin.nocdirect.com (penguin.nocdirect.com [69.73.160.206]) - by lime.pobox.com (Postfix) with ESMTP id 2B41BFE159 - for ; Wed, 22 Dec 2004 02:13:17 -0500 (EST) -Received: from localhost ([127.0.0.1]) - by penguin.nocdirect.com with esmtps (TLSv1:DES-CBC3-SHA:168) - (Exim 4.43) - id 1Cgz53-0000fj-Bx; Tue, 21 Dec 2004 23:30:37 -0600 -Date: Tue, 21 Dec 2004 23:30:35 -0600 (CST) -From: Alex Zarutin -X-X-Sender: zorranla@penguin.nocdirect.com -To: Tim Bunce -Cc: dbi-users-help@perl.org -Subject: Step-by-Step installation manual of DBD-Oracle-1.16 on Sparc Solaris - 9 with Oracle 9.2.0.1.0 client. -Message-ID: -MIME-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-AntiAbuse: This header was added to track abuse, please include it with any abuse report -X-AntiAbuse: Primary Hostname - penguin.nocdirect.com -X-AntiAbuse: Original Domain - pobox.com -X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] -X-AntiAbuse: Sender Address Domain - zorranlabs.com -X-Source: -X-Source-Args: -X-Source-Dir: -Status: RO -X-Status: A -Content-Length: 15603 -Lines: 426 - - -Hi Tim, - -I have spent a couple days trying to install DBD-Oracle-1.16 (all -required stuff, such as GCC, DBI, etc has been installed before ) on -Sun-Fire v240 running Spark Solaris 9 with the Oracle 9.2.0.1.0 client -installed. The installation takes a couple minutes ONLY after you spend -days trying to make it workable. - -I wrote the log of what I do, in order to do not waste my time in -future. I am pretty sure that this log will be very useful for people -installing DBD-Oracle on Solaris. I published it on my log page, and left -link on it at http://cpanratings.perl.org/d/DBD-Oracle review page. I -would recommend you to add this log to the readme file of your next -releases. Log is written very detailed (step-by-step) with highlighted -typical mistakes. - -Environment: -Hardware/OS: bash-2.05# uname -a -SunOS qadmz41 5.9 Generic_117171-08 sun4u sparc SUNW,Sun-Fire-V240 -OS is actually "standard" Solaris 9 installation came on the box from -SUN - -Oracle Client: Oracle 9.2.0.1.0 -GCC: gcc version 3.3.2, installed to /usr/local/bin as a package from -http://www.sunfreeware.com/programlistsparc9.html -PERL: perl v5.8.5 built for sun4-solaris, installed to /usr/local/bin as -a package from http://www.sunfreeware.com/programlistsparc9.html -DBI: DBI-1.45, installed from http://search.cpan.org/~timb/DBI-1.45/ - -Step-by-Step Manual: - -Step 1: In order to install "DBD-Oracle-1.16" you need to download it, -set all appropriate environment variables (see readme for details) and -run <>. -I got an error that is mostly typical for Solaris installation: - -// ************************ Error 1 ***********************/ - -.... -Found header files in rdbms/demo. - -********************************************************* -I can't find the header files I need in your Oracle installation. -You probably need to install some more Oracle components. -I'll keep going, but the compile will probably fail. -See README.clients for more information. -********************************************************* -Checking for functioning wait.ph - -System: perl5.008005 sunos 5.9 generic sun4u sparc sunw,ultra-5_10 -solaris -Compiler: gcc -B/usr/ccs/bin/ -O -fno-strict-aliasing -pipe --I/usr/local/include -I/opt/gnu/include -D_LARGEFILE_SOURCE --D_FILE_OFFSET_BITS=64 - -.... -// *****************************************************/ - -Investigating this problem, I found that error message is thrown by the -"find_headers" sub of Makefile.PL, especially in this "if -(!$h_file{'oratypes.h'} || !$h_file{'ocidfn.h'})" evaluation. -So I checked these files to make sure that they are installed, but did -not find them under $ORACLE_HOME/rdbms -In the same time, I found an article saying about the similar problem -with DBD-Oracle on Linux, -http://baroti.homedns.org/steve/lost+found/cpan-install-DBD-Oracle-9-2-l -inux.html -They mentioned about two files, and since I was not sure about second -one, ociapr.h I copied both files. You should find its public.1.1.jar -file on the Disk3 of Oracle 9i installation set. - -bash-2.05# pwd -/ora_orig/Disk3/stage/Components/oracle.rdbms.oci/9.2.0.1.0/1/DataFiles - -bash-2.05# ls -al -total 970 -drwxr-xr-x 2 2840 42424 512 Aug 21 2002 . -drwxr-xr-x 3 2840 42424 512 Aug 21 2002 .. --rwxr-xr-x 1 2840 42424 2047 May 9 2002 bin.1.1.jar --rwxr-xr-x 1 2840 42424 206 May 9 2002 build.1.1.jar --rwxr-xr-x 1 2840 42424 135034 May 9 2002 demo.1.1.jar --rwxr-xr-x 1 2840 42424 329814 May 9 2002 public.1.1.jar - -You should just (as dba:oracle) to create the directory called public, -copy public.1.1.jar there and extract all files, since I would not guess -if the rest of them are used or not - -bash-2.05# mkdir $ORACLE_HOME/rdbms/public - -bash-2.05# ls -al $ORACLE_HOME/rdbms/public -total 3404 -drwxr-xr-x 2 oracle dba 512 Dec 21 12:12 . -drwxr-xr-x 10 oracle dba 512 Dec 21 12:05 .. -... --rw-r--r-- 1 oracle dba 6055 Mar 9 2002 ociapr.h --rw-r--r-- 1 oracle dba 10694 Jun 29 2000 ocidfn.h -... - -After that run <> again, and I hope process passes -fine. At least, it was fine in my case - -Step 2: You should <> the module, and as it appears on Solaris, -you will get typical problem. See my error log: - -// ************************ Error 2 ***********************/ -.... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -ld: fatal: file -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib//libclntsh.so: -wrong ELF class: ELFCLASS64 -ld: fatal: File processing errors. No output written to -blib/arch/auto/DBD/Oracle/Oracle.so -collect2: ld returned 1 exit status -*** Error code 1 -make: Fatal error: Command failed for target -`blib/arch/auto/DBD/Oracle/Oracle.so' - -// *****************************************************/ - -So, as another set on Google' posts showed that it is a possibility of -missing libraries compiled with 64 bits and same libraries compiled with -32 bits suppoert. As I understood, all components of installation, such -as Oracle client, Perl, GCC should support only one type of libraries, -either 32 or 64 bits. I found that having all as 32 bits is easier to me -than recompile perl, gcc as 64 (may be I am wrong in this assumption). -In order to have all of them as 32 bits, I changed lib to lib32 in -Manifest file (not Manifest.PL). - -You should replace the following lines in the "MakeMaker const_loadlibs -section": - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -By their lib32 clones: - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -And replace this line in "MakeMaker dynamic_lib section" (~~ line 491) - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread - -By its lib32 clone: - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread - -I hope, that after that process passes without any errors. Here is last -part, that I got during <>: - -..... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/local/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL -ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/local/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" -blib/script/ora_explain -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oracle.3 -Manifying blib/man3/DBD::Oraperl.3 - -III. Once we build the module, we should test it, to make sure that it -works fine. You should run <> to do it: - -Check that you have ORACLE_HOME, ORACLE_USERID, ORACLE_SID environment -variables set, like this: - -ORACLE_HOME=="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0 -ORACLE_USERID=STARSHIP/STARSHIP -ORACLE_SID=COLORADO - -When you run <>, you will probably get this errors: - -// ************************ Error 3 ***********************/ - -bash-2.05# make test -PERL_DL_NONLAZY=1 /usr/local/bin/perl "-MExtUtils::Command::MM" "-e" -"test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............DBI connect('','STARSHIP/STARSHIP',...) failed: -ORA-12545: Connect failed because target host or object does not exist -(DBD ERROR: OCIServerAttach) at t/10general.t line 12 -Undefined subroutine &main::BAILOUT called at t/10general.t line 15. -# Looks like your test died before it could output anything. -t/10general.............dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-31 - Failed 31/31 tests, 0.00% okay -..... - -// *****************************************************/ - -One more brainstorm, and I figured out another way to set ORACLE_USERID: - -ORACLE_USERID=STARSHIP/STARSHIP@COLORADO -ORACLE_SID=COLORADO - -Later, when tests finished, I was confirmed that it was probably -preferred way of setting ORACLE_USERID. -Tests did found correct settings, and "main" set of them returned the -following report: - -All tests successful, 1 test and 122 subtests skipped. -Files=18, Tests=1020, 24 wallclock secs (11.27 cusr + 1.34 csys = 12.61 -CPU) - -For the Extra test, less formal, but test anyway, I just commented these -two lines in test.pl file - -$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -and set the same values in the same form to the $dbuser as it was in -ORACLE_USERID , and -left $dbname empty, - -$dbname = ''; -$dbuser = 'STARSHIP/STARSHIP@COLORADO'; - -and got pretty good report: - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - -recommended) - as 'STARSHIP/STARSHIP@COLORADO' (via ORACLE_USERID env var or default - -recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -Fields: 6 -Names: 'NUM_T' 'DATE_T' 'CHAR_T' 'ROWID_T' -'RAW_T' 'NULL_T' -Lengths: 172 76 121 21 3 1 -OraTypes: 2 12 1 104 23 1 -SQLTypes: 8 93 12 -9104 -2 12 -Scale: 0 0 0 0 0 0 -Precision: 126 75 120 20 2 0 -Nullable: 1 1 1 1 1 1 -Est row width: 32 -Data rows: - fetch: '7.2', '21-DEC-04', 'STARSHIP', 'AAAADeAABAAAAZSAAA', '7D', -undef - -ora_logoff... -lda out of scope... - -Testing repetitive connect/open/close/disconnect: -If this test hangs then read the README.help file. -Expect sequence of digits, no other messages: -1 2 3 4 5 - -Test interaction of explicit close/logoff and implicit DESTROYs -Expect just 'done.', no other messages: -done. - -Testing row cache (5). -Test completed in 0 seconds. - -Test complete (0 seconds). -If the tests above have produced the 'expected' output then they have -passed. - -IV. The last part is actually target of all steps above, installing -build module. < did not surprise me, and it it passed -smoothly. - -bash-2.05# make install -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/dbdimp -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/ocitra -ce.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/mk.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.so -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.bs -Files found in blib/arch: installing files in blib/lib into architecture -dependent library tree -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/oraperl.ph -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/Oraperl.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle/GetInfo.pm -Installing /usr/local/share/man/man1/ora_explain.1 -Installing /usr/local/share/man/man3/DBD::Oracle.3 -Installing /usr/local/share/man/man3/DBD::Oraperl.3 -Installing /usr/local/bin/ora_explain -Writing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/.packl -ist -Appending installation info to -/usr/local/lib/perl5/5.8.5/sun4-solaris/perllocal.pod - -V. This is actually it, and you do not need to do anything else. But -investigating different errors during the various steps, I found the -very simple "independent sanity" testdbi perl script written by Jeff -Hunter. This script is not related to standard process of -making/buildin/testing/installation. It just verifies that you can -access DB and run a couple queries against it. The code itself, -testdbi.pl can be found at -http://www.idevelopment.info/data/Oracle/DBA_tips/Programming/PROGRAMMIN -G_2.shtml - -You just should set connection information, similar to how I did it, - - $ORACLE_SID = "COLORADO"; - $ORACLE_USERID = "STARSHIP"; - $ORACLE_PASSWORD = "STARSHIP"; - - $ENV{'ORACLE_SID'} = "$ORACLE_SID"; - $ENV{'ORACLE_HOME'} = /u01/app/oracle/product/9.2.0.1.0"; - -run it as any perl script, <>, and see result: - -bash-2.05# perl testdbi.pl - -Running testdbi.pl... - - (*) Attempting Oracle Login ... - OK - (*) Creating table TEST_DBI ... - OK - (*) Insert into TEST_DBI ... - 1 rows inserted. - 1 rows inserted. - 1 rows inserted. - OK - (*) Select from TEST_DBI ... - - --> TEST_DBI_INTR_NO : 1000 - --> TEST_DBI_NAME : Jeff Hunter - - --> TEST_DBI_INTR_NO : 1001 - --> TEST_DBI_NAME : Melody Hunter - - --> TEST_DBI_INTR_NO : 1002 - --> TEST_DBI_NAME : Alex Hunter - OK - - (*) Delete from TEST_DBI ... - 3 rows deleted. - OK - - (*) Drop table TEST_DBI ... - OK - - (*) Select USER and SYSTEM ... - - --> USER : STARSHIP - --> SYSDATE : 21-DEC-2004 16:49:59 - OK - - (*) Attempting Oracle Logoff ... - OK - -Ending testdbi.pl... - -With the best regards, - -Alex Zarutin - -Software Engineer -4thpass A Motorola Company -Seattle, WA -www.4thpass.com - - - - diff --git a/err_build/err_testfailnotable.msg b/err_build/err_testfailnotable.msg deleted file mode 100644 index 687d5ed7..00000000 --- a/err_build/err_testfailnotable.msg +++ /dev/null @@ -1,97 +0,0 @@ -From SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 18:10:51 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RHAOAK026067 - for ; Wed, 27 Oct 2004 18:10:51 +0100 (BST) - (envelope-from SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 18:10:51 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMp30-0000e2-Hh; - Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMp30-0000e2-Hh - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMp30-0001QS-2p - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 87C155A7D; - Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 7779A59A1 - for ; Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Received-SPF: pass (gold.pobox.com: domain of dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by gold.pobox.com (Postfix) with SMTP id DC5795A4A - for ; Wed, 27 Oct 2004 10:45:07 -0400 (EDT) -Received: (qmail 18140 invoked by uid 514); 27 Oct 2004 14:45:04 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 18131 invoked from network); 27 Oct 2004 14:45:04 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 14:45:04 -0000 -Received: (qmail 8663 invoked by uid 225); 27 Oct 2004 14:45:03 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 8659 invoked by alias); 27 Oct 2004 14:45:03 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from ns2.aramiska.net (HELO dmzms01.aramiska.net) (80.242.32.2) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 07:45:01 -0700 -Received: from ip-80-242-36-115.aramiska-arc.aramiska.net (ip-80-242-36-115.aramiska-arc.aramiska.net [80.242.36.115]) - by dmzms01.aramiska.net (Postfix) with ESMTP - id 9F21E1100D9; Wed, 27 Oct 2004 14:44:55 +0000 (UTC) -Received: from localhost (localhost [127.0.0.1]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id E558E7C; Wed, 27 Oct 2004 14:44:52 +0000 (UTC) -Received: from dansat.data-plan.com (ip-192-168-0-3.internal.data-plan.aramiska.net [192.168.0.3]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id D8A5E71; Wed, 27 Oct 2004 14:44:50 +0000 (UTC) -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9REioAA023212; - Wed, 27 Oct 2004 15:44:50 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i9REinmW023211; - Wed, 27 Oct 2004 15:44:49 +0100 (BST) -Date: Wed, 27 Oct 2004 15:44:49 +0100 -From: Tim Bunce -To: "H.Merijn Brand" -Cc: Tim Bunce , DBI developers -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Message-ID: <20041027144449.GB19991@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> <20041027093516.D001.H.M.BRAND@hccnet.nl> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20041027093516.D001.H.M.BRAND@hccnet.nl> -User-Agent: Mutt/1.4i -X-Virus-Scanned: by Aramiska Arc -Status: RO -Content-Length: 634 -Lines: 14 - -On Wed, Oct 27, 2004 at 09:39:33AM +0200, H.Merijn Brand wrote: -> On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> > file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> > size: 235224 bytes -> > md5: 9711550ed0ebfc743920a6a357ed717c -> -> I know you can't blame the test for not being able to create a table for the -> reason this failure shows, but there might be a more user-friendly way to fail ... - -Yeap. Some tests behave better in that situation. Looks like those -two need improving. Patches welcome! (I'd happily not touch DBD::Oracle -for a few months after the pain of the last few months :) - -Tim. - diff --git a/err_docs/err_trace.msg b/err_docs/err_trace.msg deleted file mode 100644 index 3d7500fb..00000000 --- a/err_docs/err_trace.msg +++ /dev/null @@ -1,14 +0,0 @@ -Add this to the DBD::Oracle docs as a handy note: - -$dbh->do(q{alter session set events '65285 trace name errorstack level 3'}); - -A trace file should then be generated. - -Trace files are generated in the 'user_dump_destination' specified in init.ora. - -Try $ORACLE_BASE/admin/$ORACLE_SID/udump. - -or the location returned by -select value -from v$parameter -where name like '%user_dump%' diff --git a/err_lob/err_csr_clob.msg b/err_lob/err_csr_clob.msg deleted file mode 100644 index 397d53b3..00000000 --- a/err_lob/err_csr_clob.msg +++ /dev/null @@ -1,65 +0,0 @@ -From dbi-users-bounce@isc.org Thu Sep 21 20:27:21 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id UAA18945; Thu, 21 Sep 2000 20:27:20 +0100 (BST) -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <02709-1@oink>; Mon, 21 Sep 1970 20:26:40 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 969564156:20:26825:1; Thu, 21 Sep 2000 19:22:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-2.mail.demon.net - id aa2026778; 21 Sep 2000 19:22 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 28A613E5D; - Thu, 21 Sep 2000 12:22:17 -0700 (PDT) -Received: with LISTAR (v1.0.0; list dbi-users); - Thu, 21 Sep 2000 12:17:37 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A59853E42 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) -Received: from wheel.cs.wisc.edu (wheel.cs.wisc.edu [128.105.121.12]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA00855 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) env-from (horn@wheel.cs.wisc.edu) -Received: (from horn@localhost) by wheel.cs.wisc.edu (8.9.2/8.9.2) id OAA16413 - for dbi-users@isc.org; Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -Date: Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -From: Jeffrey Horn -Message-Id: <200009211917.OAA16413@wheel.cs.wisc.edu> -To: dbi-users@isc.org -Subject: Setting ORA_TYPE after the fact... -Sender: horn@wheel.cs.wisc.edu -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: horn@cs.wisc.edu -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -X-Status: A -Content-Length: 969 -Lines: 20 - -I have a situation where I would like to return a cursor that contains a -CLOB as one of it's attributes from a PL/SQL procedure. What I get back is -a LOB locator and DBD doesn't actually read the CLOB but instead returns an -error. - -If I go through a bind/prepare/execute/fetch on a similar SQL statement all -is well. Is there any way that I can tell DBD that a given attribute of -a cursor is a CLOB once the cursor is already opened so that DBD will do the -right thing? - --- Jeff Horn - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_lob/err_loblenwide.msg b/err_lob/err_loblenwide.msg deleted file mode 100644 index 08023e97..00000000 --- a/err_lob/err_loblenwide.msg +++ /dev/null @@ -1,95 +0,0 @@ -From nobody@fsck.com Thu Dec 4 07:36:20 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hB47Y2nE066844 - for ; Thu, 4 Dec 2003 07:36:20 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 04 Dec 2003 07:36:20 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1ARgrA-0005O4-5M; - Wed, 03 Dec 2003 23:56:32 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1ARgrA-0005O4-5M - for pobox@dbi.demon.co.uk; Wed, 03 Dec 2003 23:56:32 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 314AB9A28F - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 188369A287 - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com[63.251.223.170]) - by icicle.pobox.com (Postfix) with SMTP - for ; Wed, 3 Dec 2003 18:56:31 -0500 (EST) -Received: (qmail 3178 invoked by uid 225); 3 Dec 2003 23:56:30 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 3174 invoked by alias); 3 Dec 2003 23:56:29 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Wed, 03 Dec 2003 15:56:18 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 91512114F1; Wed, 3 Dec 2003 18:56:07 -0500 (EST) -Subject: [cpan #4564] Perl DBI bug handling CLOBs -From: "Jay Turner via RT" -Reply-To: bug-DBI@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4564 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: J.Turner@mdl.com -To: "AdminCc of cpan Ticket #4564": ; -Date: Wed, 3 Dec 2003 18:56:07 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -X-Status: A -Content-Length: 1853 -Lines: 46 - - -This message about DBI was sent to you by J.Turner@mdl.com via rt.cpan.org - -Full context and any attached attachments can be found at: - - - -Date: Fri, 28 Feb 2003 16:55:28 -0800 - -It has come to my attention that PERL DBI counts on OCILobGetLength -returning BYTES. It returns CHARACTERS instead, which is the count of -variable-width characters. For multi-byte character sets this results -in errors such as: - -DBD::Oracle::st fetch failed: ORA-03130: the buffer for the next piece -to be fetched is required (DBD ERROR: OCILobGetLength) at id rmsc01.pl -line 294. - -The correct way to read CLOBs is - -1) Query the LOB locator for the CSID and CSFRM (character set ID and -form). A character set >= 800 is a mulitbyte character set and csfrm -<> 0 is CLOB. - -2) Pass the CSID and CSFRM to OCILobRead with AMT=0 and pass your -buffer address and size. - -3) Your callback routine must either be capable of completing the I/O -by allocating additional buffers, or it must notify the caller of -OCILobRead to free the lob locator, since an incomplete read jams the -locator-you can't use it for anything else without finishing the read -(attempts to reuse the locator will result in errors). - -Likewise, with OCILobWrite, you have to pass the CSID and CSFRM, with -AMT=0 and the buffer size in bytes. The callback can just say it has -zero bytes and set piece=OCI_LAST_PIECE. - -You cannot use the return value of OCILobGetLength as the size of the -data that is being read. The actual size of the data is unknown for -variable-width characters, and the buffer has to be big enough to -accomplish the translation, so you can't just double or triple the -return value from OCILobGetLength (I have seen that approach fail). - -You can simulate the effects of a foreign character set by - -$ export NLS_LANG=Japanese - diff --git a/err_lob/err_lobtesttblfail.msg b/err_lob/err_lobtesttblfail.msg deleted file mode 100644 index 1333ee88..00000000 --- a/err_lob/err_lobtesttblfail.msg +++ /dev/null @@ -1,208 +0,0 @@ -From SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 15:22:22 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RELAAO018624 - for ; Wed, 27 Oct 2004 15:22:22 +0100 (BST) - (envelope-from SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 15:22:22 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMiQ8-0000Eo-FG; - Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMiQ8-0000Eo-FG - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMiQ8-0006dS-9n - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B3BB911C325; - Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9947911C2CE - for ; Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Received-SPF: pass (icicle.pobox.com: domain of dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by icicle.pobox.com (Postfix) with SMTP id 5033611C34F - for ; Wed, 27 Oct 2004 03:39:46 -0400 (EDT) -Received: (qmail 12004 invoked by uid 514); 27 Oct 2004 07:39:43 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 11995 invoked from network); 27 Oct 2004 07:39:43 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 07:39:43 -0000 -Received: (qmail 13565 invoked by uid 225); 27 Oct 2004 07:39:43 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 13560 invoked by alias); 27 Oct 2004 07:39:42 -0000 -X-Spam-Status: No, hits=-3.7 required=8.0 - tests=BAYES_00,LARGE_HEX -X-Spam-Check-By: la.mx.develooper.com -Received: from smtp-vbr15.xs4all.nl (HELO smtp-vbr15.xs4all.nl) (194.109.24.35) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 00:39:40 -0700 -Received: from [127.0.0.1] (procura.xs4all.nl [213.84.163.145]) - by smtp-vbr15.xs4all.nl (8.12.11/8.12.11) with ESMTP id i9R7dWHI013040; - Wed, 27 Oct 2004 09:39:34 +0200 (CEST) - (envelope-from h.m.brand@hccnet.nl) -Date: Wed, 27 Oct 2004 09:39:33 +0200 -From: "H.Merijn Brand" -To: Tim Bunce -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Cc: DBI developers -In-Reply-To: <20041022213625.GA22377@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> -Message-Id: <20041027093516.D001.H.M.BRAND@hccnet.nl> -MIME-Version: 1.0 -Content-Type: text/plain; charset="US-ASCII" -X-Mailer: Becky! ver. 2.11.02 [en] -X-Virus-Scanned: by XS4ALL Virus Scanner -X-Virus-Checked: Checked -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i9RELAAO018624 -Status: RO -X-Status: A -Content-Length: 7175 -Lines: 134 - -On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> size: 235224 bytes -> md5: 9711550ed0ebfc743920a6a357ed717c - -I know you can't blame the test for not being able to create a table for the -reason this failure shows, but there might be a more user-friendly way to fail ... - -I'll report back when the DBA has fixed the tablespace - -HP-UX 11.11/64 (11i) + Oracle-9.2.0/64 + perl-5.8.5-dor/64 - -PERL_DL_NONLAZY=1 /pro/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, -'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............ok -t/15nls.................ok -t/20select..............ok -t/21nchar............... Database and client versions and character sets: -Database 9.2.0.1.0 CHAR set is US7ASCII (Non-Unicode), NCHAR set is AL16UTF16 ( -nicode) -Client 9.2.0.1 NLS_LANG is '', NLS_NCHAR is '' -t/21nchar...............ok -t/22nchar_al32utf8......ok -t/22nchar_utf8..........ok -t/23wide_db.............skipped - all skipped: Database character set is not Unicode -t/23wide_db_8bit........skipped - all skipped: Database character set is not Unicode -t/23wide_db_al32utf8....skipped - all skipped: Database character set is not Unicode -t/24implicit_utf8.......ok -t/25plsql...............ok -t/30long................ok 188/470DBD::Oracle::db do failed: ORA-03237: Initial -Extent of specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: -OCIStmtExecute) [for Statement "create table dbd_ora__drop_me ( idx integer, ln - NCLOB, dt date )"] at t/nchar_test_lib.pl line 356. -t/30long................ok 189/470DBD::Oracle::st execute failed: ORA-00942: ta -le or view does not exist (DBD ERROR: error possibly near <*> indicator at char -12 in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statem -nt "insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1= -0, :p2='0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X...'] at t/30long.t line 153. -# Failed test (t/30long.t at line 153) -t/30long................NOK 190DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=41, -:p2='12345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -...'] at t/30long.t line 154. -# Failed test (t/30long.t at line 154) -t/30long................NOK 191DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=42, -:p2='2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -...'] at t/30long.t line 155. -t/30long................NOK 192# Failed test (t/30long.t at line 155) -DBD::Oracle::st execute failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 12 in 'insert into <*>dbd_ora__dr -p_me values (:p1, :p2, SYSDATE)') [for Statement "insert into dbd_ora__drop_me -alues (?, ?, SYSDATE)" with ParamValues: :p1=43, :p2=undef] at t/30long.t line -56. -# Failed test (t/30long.t at line 156) -t/30long................NOK 193DBD::Oracle::db prepare failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 14 -in 'select * from <*>dbd_ora__drop_me order by idx') [for Statement "select * f -om dbd_ora__drop_me order by idx"] at t/30long.t line 170. -# Failed test (t/30long.t at line 170) -Can't call method "trace" on an undefined value at t/30long.t line 171. -t/30long................NOK 194# Looks like you planned 470 tests but only ran -94. -# Looks like your test died just after 194. -t/30long................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 190-470 - Failed 281/470 tests, 40.21% okay (less 122 skipped tests: 67 okay, 14. -6%) -t/31lob.................DBD::Oracle::db do failed: ORA-03237: Initial Extent of -specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: OCIStmtEx -cute) [for Statement " - CREATE TABLE dbd_ora__drop_me ( - id INTEGER NOT NULL, - data BLOB - ) - "] at t/31lob.t line 21. -DBD::Oracle::db do failed: ORA-00942: table or view does not exist (DBD ERROR: -rror possibly near <*> indicator at char 12 in 'INSERT INTO <*>dbd_ora__drop_me -(id,data) VALUES (1, EMPTY_BLOB())') [for Statement "INSERT INTO dbd_ora__drop_ -e (id,data) VALUES (1, EMPTY_BLOB())"] at t/31lob.t line 31. -DBD::Oracle::db prepare failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 17 in 'SELECT data FROM <*>dbd_or -__drop_me WHERE id = :p1') [for Statement "SELECT data FROM dbd_ora__drop_me WH -RE id = ?"] at t/31lob.t line 34. -Can't call method "bind_param" on an undefined value at t/31lob.t line 36. -# Looks like your test died before it could output anything. -t/31lob.................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-2 - Failed 2/2 tests, 0.00% okay -t/40ph_type.............ok -t/50cursor..............ok -t/60reauth..............ORACLE_USERID_2 not defined. Tests skipped. -skipped - all skipped: no reason given -t/70meta................ok -Failed Test Stat Wstat Total Fail Failed List of Failed -------------------------------------------------------------------------------- -t/30long.t 255 65280 470 557 118.51% 190-470 -t/31lob.t 255 65280 2 4 200.00% 1-2 -4 tests and 122 subtests skipped. -Failed 2/18 test scripts, 88.89% okay. 283/1883 subtests failed, 84.97% okay. -make: *** [test_dynamic] Error 255 - --- -H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/) -using perl-5.6.1, 5.8.0 & 633 on HP-UX 10.20 & 11.00, AIX 4.2, AIX 4.3, - WinNT 4, Win2K pro & WinCE 2.11 often with Tk800.024 &/| DBD-Unify -ftp://ftp.funet.fi/pub/languages/perl/CPAN/authors/id/H/HM/HMBRAND/ - - - - diff --git a/err_lob/err_nclob_form.msg b/err_lob/err_nclob_form.msg deleted file mode 100644 index 05587693..00000000 --- a/err_lob/err_nclob_form.msg +++ /dev/null @@ -1,189 +0,0 @@ -From dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org Tue Jul 22 07:40:59 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6M6UUD7096422 - for ; Tue, 22 Jul 2003 07:40:58 +0100 (BST) - (envelope-from dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 22 Jul 2003 07:40:58 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058814697:11:26523:33; Mon, 21 Jul 2003 19:11:37 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1126786; 21 Jul 2003 19:11 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E855B21C37F - for ; Mon, 21 Jul 2003 15:11:18 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 9010121C236 - for ; Mon, 21 Jul 2003 15:11:17 -0400 (EDT) -Received: (qmail 66848 invoked by uid 1005); 21 Jul 2003 19:11:15 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 66832 invoked by uid 76); 21 Jul 2003 19:11:15 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 21 Jul 2003 12:11:15 -0700 -Received: (qmail 559 invoked by uid 225); 21 Jul 2003 19:11:08 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 552 invoked by uid 507); 21 Jul 2003 19:11:07 -0000 -Received-SPF: unknown -Received: from sneakemail.com (HELO monkey.sneakemail.com) (207.106.87.13) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Mon, 21 Jul 2003 12:11:03 -0700 -Received: (qmail 22505 invoked by uid 501); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #3); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #2); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #1); 21 Jul 2003 19:10:57 -0000 -Date: Mon, 21 Jul 2003 21:10:53 +0200 -From: "Wolfgang Weisselberg" -To: dbi-users@perl.org -Subject: DBD::Oracle and unicode-NCLOBs leads to ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) -Message-ID: <13502-46198@sneakemail.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.6 required=7.0 tests=CARRIAGE_RETURNS,FROM_ENDS_IN_NUMS,FROM_HAS_MIXED_NUMS,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_MUTT version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 6055 -Lines: 132 - -Hello all! - -Even after extensive googling and looking through the docs I fail -to fetch NCLOBs from an Oracle 9.2i database where the national -character set is unicode. - -I believe it has been done before, but I could not find anything ... -I would be grateful for any pointers. - - -NCLOBs work like CLOBs when the national character set is not -unicode, even with the old DBI 1.21 and DBD::Oracle 1.12 on an -Oracle 8 client. NVarchar2 and NChar work OK even with unicode. - -Setting NSL_LANG to AMERICAN_AMERICA.UTF8 or .AL32UTF8 does not -help, as I suspected. - -I tried using Oracle 9.2i (the DB is using 9.2i) on a Debian -Linux box. I upgraded DBI to 1.37 and DBD::Oracle to 1.14 (the -newest versions according to CPAN). I got zero errors on make -test with both. Perl is Debian's normal "perl5 (revision 5.0 -version 6 subversion 1)". - -A simple - select memo from unicode_test -(memo being the NCLOB field) fails (again, only with the national -charset being unicode). - -The relevant code snippet (RaiseError being set, of course): - -| $| = 1; -| print "DBI: $DBI::VERSION\n", -| "DBD::Oracle $DBD::Oracle::VERSION\n"; -| my $sth = $dbh->prepare("select memo from unicode_test"); -| $sth->execute(); -| -| while ( my ($memo) = $sth->fetchrow_array() ) { -| print Dumper $memo; -| } -| exit; - - -The output: - -| DBI: 1.37 -| DBD::Oracle 1.14 -| $VAR1 = ''; -| $VAR1 = ''; -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. - - - -Running with tracelevel 3: - [...] -| dbd_st_prepare'd sql SELECT -| dbd_describe SELECT (EXPLICIT, lb 99999999)... -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_execute SELECT (out0, lob0)... -| dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -| <- execute= '0E0' at nclobtest.pl line 79 via nclobtest.pl line 60 -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -| 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x82f8e28)~INNER 'ParamValues') -| error: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| 1 <- FETCH= HASH(0x831661c)0keys at nclobtest.pl line 81 via nclobtest.pl line 60 -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. - - - -Tracelevel 9 (yes, it's a bit verbose :-/ ) - -[...] -| OCIDescriptorAlloc(0x831c058,0x8395228,OCI_DTYPE_LOB,0,0) -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| OCIAttrSet(0x8335b34,OCI_HTYPE_STMT,0xbffff30c,4,11,0x832d5a4)=SUCCESS -| OCIDefineByPos(0x8335b34,0x8395224,0x832d5a4,1,0x8395228,-1,112,0x83414e0,0x83414f0,0x8341500,0)=SUCCESS -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -[...] -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| 0 (rc=0): '' -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead(0x832d530,0x832d5a4,0x832c69c,0xbffff318,1,0x8394da0,24,(nil),(nil),0,1)=ERROR -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| OCIErrorGet(0x832d5a4,1,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=SUCCESS -| OCIErrorGet after OCILobRead (er1:ok): -1, 24806: ORA-24806: LOB form mismatch -| -| OCIErrorGet(0x832d5a4,2,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=NO_DATA -| 0 (rc=0): undef -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -[gets and prints error message] - - -Any ideas anyone? - --Wolfgang - diff --git a/err_lob/err_nulllobsegv.msg b/err_lob/err_nulllobsegv.msg deleted file mode 100644 index 6de3c99b..00000000 --- a/err_lob/err_nulllobsegv.msg +++ /dev/null @@ -1,93 +0,0 @@ -From dbi-users-return-1743-Tim.Bunce=ig.co.uk@perl.org Wed Apr 11 04:00:48 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id EAA17912; Wed, 11 Apr 2001 04:00:48 +0100 (BST) -Received: from 194.217.242.36 by oink with SMTP (PP) id <02579-1@oink>; - Sat, 11 Apr 1970 04:00:28 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 986956750:10:04398:0; Wed, 11 Apr 2001 02:39:10 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-1.mail.demon.net - id aa1106187; 11 Apr 2001 2:39 GMT -Received: (qmail 32618 invoked by uid 508); 11 Apr 2001 02:39:06 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 32603 invoked from network); 11 Apr 2001 02:39:05 -0000 -Received: from owns.warpcore.org (216.81.249.18) by tmtowtdi.perl.org with SMTP; - 11 Apr 2001 02:39:05 -0000 -Received: (from thebrain@localhost) by owns.warpcore.org (8.11.1/8.11.1) - id f3B2cxH06298 for dbi-users@perl.org; - Tue, 10 Apr 2001 21:38:59 -0500 -Date: Tue, 10 Apr 2001 21:38:59 -0500 -From: Stephen Clouse -To: dbi-users@perl.org -Subject: Bizarre DBD::Oracle Segfault -Message-ID: <20010410213859.B2766@owns.warpcore.org> -Mail-Followup-To: dbi-users@perl.org -Mime-Version: 1.0 -Content-Type: text/plain -Content-Disposition: inline; filename="msg.pgp" -User-Agent: Mutt/1.2.5i -Status: RO -Content-Length: 1918 -Lines: 54 - ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -I sent an email to the dbi-users list about a number of DBD::Oracle CLOB -handling problems waaaaaaaaaaaaaaay back (end of January or so) that today -someone dug up and inquired if I had ever found fixes for what I had pointed -out. - -The problems outlined that day turned out to be the test script itself, which -was doing so much bizarre stuff on one statement that DBD::Oracle just went to -sleep instead (and so was the actual program that instigated the writing of the -test script). - -Well, all but one problem was the script. This, the most serious one, continues -to linger: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',undef); - -On Linux, DBI 1.15, Oracle 8.1.6, and DBD::Oracle 1.06, this segfaults on the -execute. Unfortunately this manifests itself too deep in Oracle for me to -debug. - -The bizarre part is, either of the two snippets below will work: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',''); -$st->execute('B','B',undef); - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',$lobvalue); -$st->execute('B','B',undef); - -It's only when binding undef as the LOB value in the very first execute of a -statement that the segfault occurs. At any other time, it's kosher. That -qualifies as bizarre in my book. - -Your guess is better than mine. - -- -- -Stephen Clouse -Senior Programmer, IQ Coordinator Project Lead -The IQ Group, Inc. - ------BEGIN PGP SIGNATURE----- -Version: PGP 6.5.8 - -iQA+AwUBOtPDwgOGqGs0PadnEQLmtgCeJHTStLu8Q8oFb9UQ4995f8vhZH8Al1p6 -RD5m0FEJH2tQiY0+b6542mQ= -=L0M+ ------END PGP SIGNATURE----- - diff --git a/err_lob/err_tmplobfree.msg b/err_lob/err_tmplobfree.msg deleted file mode 100644 index 0ec8f940..00000000 --- a/err_lob/err_tmplobfree.msg +++ /dev/null @@ -1,537 +0,0 @@ -From SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com Wed Aug 25 17:53:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PGpkpQ033405 - for ; Wed, 25 Aug 2004 17:53:57 +0100 (BST) - (envelope-from SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 17:53:57 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Bzyve-0007kY-Gp; - Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Bzyve-0007kY-Gp - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Bzyvd-0000zb-Lg - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id AA6D8B0635; - Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 9B2A1B0BB0 - for ; Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -Received: from natnoddy.rzone.de (natnoddy.rzone.de [81.169.145.166]) - by lime.pobox.com (Postfix) with ESMTP id 2AAB1B0635 - for ; Wed, 25 Aug 2004 10:39:06 -0400 (EDT) -Received: from genericom.de (pD95195AC.dip.t-dialin.net [217.81.149.172]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7PEc05w018990 - for ; Wed, 25 Aug 2004 16:38:01 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412CA445.FC2F9EF2@genericom.de> -Date: Wed, 25 Aug 2004 16:37:57 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim.Bunce@pobox.com -Subject: DBD::Oracle: Freeing a temporary blob -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms4BC2D4519D41A502BB06559C" -Status: RO -X-Status: A -Content-Length: 4985 -Lines: 122 - -This is a cryptographically signed message in MIME format. - ---------------ms4BC2D4519D41A502BB06559C -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Dear Tim, - -first, I would really like to thank you for the great work you have done -with your DBI/DBD work. We are using it extensively in several projects -and we are highly pleased. - -Unfortunately I have now encountered a problem we need to fix urgently, -since our customer's production is seriously affected. - -We tried for many days to find a solution (google, newsgroups, -trial-and-error...), without luck. So my last chance is to contact you -directly, although I assume you have a lot work yourself. - ---- - -The problem: - -Our database contains a stored function "ReadUnitBlob()" that returns a -temporary blob: - -function ReadUnitBlob(UnitID_IN in integer) return blob -is -... -begin - ... - dbms_lob.createtemporary(retBlob, false, dbms_lob.call); - dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); - ... - return retBlob; -end; - -We call this function in Perl in a big loop to fetch a lot of blobs (~ -100000) using something like: - -my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -ora_auto_lob => 0 }); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); -my ($loc) = $sth->fetchrow_array(); -$sth->finish(); -... -while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) - ... - -Although this works, it has a big disadvantage: Oracle does not -automaticaly free the temporary blob, so it shortly runs out of temp. -space. (confirmed with "select * from v$temporary_lobs"). - -Acording to the Oracle docs this can be we solved by implicitly freeing -the temp. blob, e.g. by calling the PLSQL method -"dbms_lob.freetemporary()". I tried differnt ways to do this with -DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -locator from the my stored procedure and to pass it to a call of -"dbms_lob.freetemporary()": - -my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -ora_auto_lob => 0 }); -my $bloc; -$sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); - -obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) - -Can you help me??? Do you know a way how to free the temp. blob using -DBD::Oracle (using Oracle::OCI is not possible, since the customer is -strinctly refusing to install it). - -Otherwise, would it be possible include an additional DBD::Oracle LOB -Locator Method "ora_lob_freetemporary()" that warps -"OCILobFreeTemporary" ? - -Any help is really appreciated! - -Greeting from Germany, - - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------ms4BC2D4519D41A502BB06559C -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjUxNDM3NThaMCMGCSqG -SIb3DQEJBDEWBBS+u38esQAv19TdNkv4jgxlzsRqSzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAJQgoN5ASnyjnB7bgrv1+V7Cu4ULKe1CkHs0IEZaB -KuJcm98U7kskRyC5g6YNopuJxFbr19K3q5rrJGoUscKjiw== ---------------ms4BC2D4519D41A502BB06559C-- - - -From SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com Wed Aug 25 22:47:05 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PLjxpJ037568 - for ; Wed, 25 Aug 2004 22:47:04 +0100 (BST) - (envelope-from SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 22:47:04 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C04j1-00038v-Pz; - Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C04j1-00038v-Pz - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C04j0-00002I-FU - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:30 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AD1815463; - Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 85FFF55E7 - for ; Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Received-SPF: none (gold.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail04.svc.cra.dublin.eircom.net (mail04.svc.cra.dublin.eircom.net [159.134.118.20]) - by gold.pobox.com (Postfix) with SMTP id 14C005463 - for ; Wed, 25 Aug 2004 16:50:25 -0400 (EDT) -Received: (qmail 5678 messnum 5046341 invoked from network[213.94.228.233/unknown]); 25 Aug 2004 20:50:23 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail04.svc.cra.dublin.eircom.net (qp 5678) with SMTP; 25 Aug 2004 20:50:23 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PKsrof034865; - Wed, 25 Aug 2004 21:54:53 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7PKsqas034864; - Wed, 25 Aug 2004 21:54:52 +0100 (BST) -Date: Wed, 25 Aug 2004 21:54:52 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim.Bunce@pobox.com -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040825205452.GC34655@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412CA445.FC2F9EF2@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 4674 -Lines: 124 - -On Wed, Aug 25, 2004 at 04:37:57PM +0200, Philipp Lang wrote: -> Dear Tim, -> -> first, I would really like to thank you for the great work you have done -> with your DBI/DBD work. We are using it extensively in several projects -> and we are highly pleased. - -Thanks Philipp! - -> Unfortunately I have now encountered a problem we need to fix urgently, -> since our customer's production is seriously affected. -> -> We tried for many days to find a solution (google, newsgroups, -> trial-and-error...), without luck. So my last chance is to contact you -> directly, although I assume you have a lot work yourself. - -I am very busy and what little spare time I have for DBD::Oracle -is going into trying to get 1.16 released (which is proving to be -hard as we're tripping over Oracle bugs when an Oracle 8 client -talks to an Oracle 9+ server.) It's a major release that will help -many people so I need to give that priority. - -Separately I am exploring ways to fund DBI and DBD::Oracle development -so I can devote more time to it. There's is much that needs to be -done and much more that could be done beyond that. - -The Perl Foundation (TPF) have setup a way for people and companies -to make donations for DBI development [as yet unannounced so please -keep to yourself]. A note on the contribution could indicate that the -donor would like it used for a particular purpose, such as DBD::Oracle. - -Anyway, to cut a long story short, it would be much easier to devote -time to this if it could be funded in some way. - -I think the TPF setup is working so it could be done that way. -Alternatively you could contract me to do the work for you. -That would be quicker and simpler for you as TPF's non-profit -status doesn't make a difference to European donors. - -My standard daily rate for add-hoc consulting is 1600 Euro. -I'd expect to be able to sort this out inside a day, and prefer -fixed-price quotes anyway, so would 1600 Euro be okay? - -Of course, if you feel your company would like to either -make a general contribution to DBI/DBD::Oracle development beyond -that, or to fund the development of specific functionality that -would be of extra value to you then I'd be happy to talk about that. - -I hate asking for money, and would much rather dig into the code and -reply with a patch, but it's just not practical for me now. Sorry. - -Tim. - -> --- -> -> The problem: -> -> Our database contains a stored function "ReadUnitBlob()" that returns a -> temporary blob: -> -> function ReadUnitBlob(UnitID_IN in integer) return blob -> is -> ... -> begin -> ... -> dbms_lob.createtemporary(retBlob, false, dbms_lob.call); -> dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); -> ... -> return retBlob; -> end; -> -> We call this function in Perl in a big loop to fetch a lot of blobs (~ -> 100000) using something like: -> -> my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -> ora_auto_lob => 0 }); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> my ($loc) = $sth->fetchrow_array(); -> $sth->finish(); -> ... -> while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) -> ... -> -> Although this works, it has a big disadvantage: Oracle does not -> automaticaly free the temporary blob, so it shortly runs out of temp. -> space. (confirmed with "select * from v$temporary_lobs"). -> -> Acording to the Oracle docs this can be we solved by implicitly freeing -> the temp. blob, e.g. by calling the PLSQL method -> "dbms_lob.freetemporary()". I tried differnt ways to do this with -> DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -> locator from the my stored procedure and to pass it to a call of -> "dbms_lob.freetemporary()": -> -> my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -> ora_auto_lob => 0 }); -> my $bloc; -> $sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> -> obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) -> -> Can you help me??? Do you know a way how to free the temp. blob using -> DBD::Oracle (using Oracle::OCI is not possible, since the customer is -> strinctly refusing to install it). -> -> Otherwise, would it be possible include an additional DBD::Oracle LOB -> Locator Method "ora_lob_freetemporary()" that warps -> "OCILobFreeTemporary" ? -> -> Any help is really appreciated! -> -> Greeting from Germany, -> -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - -From SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com Thu Aug 26 14:06:45 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QD6Som051890 - for ; Thu, 26 Aug 2004 14:06:45 +0100 (BST) - (envelope-from SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 14:06:45 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0HX2-0003PB-Sd; - Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0HX2-0003PB-Sd - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0HX2-0003BR-F8 - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id DC4BFB0D27; - Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id CE95AB0D7D - for ; Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 81.169.145.165(natsmtp00.rzone.de) -Received: from natsmtp00.rzone.de (natsmtp00.rzone.de [81.169.145.165]) - by lime.pobox.com (Postfix) with ESMTP id 71107B0D27 - for ; Thu, 26 Aug 2004 06:30:56 -0400 (EDT) -Received: from genericom.de (pD9E61E09.dip.t-dialin.net [217.230.30.9]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7QAUoTY009695 - for ; Thu, 26 Aug 2004 12:30:51 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412DBBD7.2C124831@genericom.de> -Date: Thu, 26 Aug 2004 12:30:47 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------msB92907D67E7D4C0121D50420" -Status: O -X-Status: A -Content-Length: 3040 -Lines: 58 - -This is a cryptographically signed message in MIME format. - ---------------msB92907D67E7D4C0121D50420 -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Tim Bunce wrote: -> -> I hate asking for money, and would much rather dig into the code and -> reply with a patch, but it's just not practical for me now. Sorry. - -Thanks for your quick reply. I can fully understand your position in -this issue. We will need to submit this issue to our customer, and -eventually it will be their decision, since a) the problem technically -originates in external components -and b) our work is payed on a time and material basis. - -Thanks again, - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------msB92907D67E7D4C0121D50420 -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjYxMDMwNDhaMCMGCSqG -SIb3DQEJBDEWBBQbWUdl+peoD/lHpzCOnuQfzAsbJzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAXzFame8ymLqgf+7nZ4V7L9e9J+aG6z5ipa+iv76v -EFAg5QObdHdvTnq5QEAjEnLKgeUGvdgpS6PA0h+beEIeIA== ---------------msB92907D67E7D4C0121D50420-- - - -From SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com Thu Aug 26 16:42:55 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QFgKp1054926 - for ; Thu, 26 Aug 2004 16:42:55 +0100 (BST) - (envelope-from SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 16:42:55 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0L1E-0005sL-5Z; - Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0L1E-0005sL-5Z - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0L1E-0001t1-Cm - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 541E8AFAD6; - Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 1C39FB0747 - for ; Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail01.svc.cra.dublin.eircom.net (mail01.svc.cra.dublin.eircom.net [159.134.118.17]) - by lime.pobox.com (Postfix) with SMTP id BFBB5AFAD6 - for ; Thu, 26 Aug 2004 10:14:19 -0400 (EDT) -Received: (qmail 12246 messnum 7731352 invoked from network[213.94.228.233/unknown]); 26 Aug 2004 14:14:17 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail01.svc.cra.dublin.eircom.net (qp 12246) with SMTP; 26 Aug 2004 14:14:17 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QEItof052863; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7QEItr3052862; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) -Date: Thu, 26 Aug 2004 15:18:55 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040826141855.GC52359@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> <412DBBD7.2C124831@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412DBBD7.2C124831@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 926 -Lines: 25 - -Okay. Thanks. Let me know how it turns out. - -Tim. - -On Thu, Aug 26, 2004 at 12:30:47PM +0200, Philipp Lang wrote: -> Tim Bunce wrote: -> > -> > I hate asking for money, and would much rather dig into the code and -> > reply with a patch, but it's just not practical for me now. Sorry. -> -> Thanks for your quick reply. I can fully understand your position in -> this issue. We will need to submit this issue to our customer, and -> eventually it will be their decision, since a) the problem technically -> originates in external components -> and b) our work is payed on a time and material basis. -> -> Thanks again, -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - diff --git a/err_unicode/err_char.msg b/err_unicode/err_char.msg deleted file mode 100644 index d2a7a4a3..00000000 --- a/err_unicode/err_char.msg +++ /dev/null @@ -1,129 +0,0 @@ -From dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org Fri May 31 15:39:50 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g4VEdno73229 - for ; Fri, 31 May 2002 15:39:49 +0100 (BST) - (envelope-from dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 31 May 2002 15:39:49 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1022854157:20:06570:1; Fri, 31 May 2002 14:09:17 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2005972; 31 May 2002 14:08 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 210F42BF43 - for ; Fri, 31 May 2002 10:08:39 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (unknown [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 8D88B2BF11 - for ; Fri, 31 May 2002 10:08:38 -0400 (EDT) -Received: (qmail 47355 invoked by uid 1005); 31 May 2002 14:07:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 47340 invoked by uid 76); 31 May 2002 14:07:41 -0000 -Received: from wsrgeh.wsr.ac.at (HELO wsrgeh.wsr.ac.at) (143.130.16.2) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Fri May 31 14:07:41 2002 -0000 -Received: from dialog.wsr.ac.at (dialog.wsr.ac.at [143.130.50.66]) - by wsrgeh.wsr.ac.at (8.11.6/8.11.6) with ESMTP id g4VE8Or11772 - for ; Fri, 31 May 2002 16:08:24 +0200 -Received: (from hjp@localhost) - by dialog.wsr.ac.at (8.11.6/8.11.6) id g4VE8Nf12538 - for dbi-users@perl.org; Fri, 31 May 2002 16:08:23 +0200 -Date: Fri, 31 May 2002 16:08:23 +0200 -From: "Peter J. Holzer" -To: dbi-users@perl.org -Subject: Re: Insert a blank value into Oracle -Message-ID: <20020531160823.F28779@wsr.ac.at> -Mail-Followup-To: "Peter J. Holzer" , - dbi-users@perl.org -References: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw> -Mime-Version: 1.0 -Content-Type: multipart/signed; micalg=pgp-md5; - protocol="application/pgp-signature"; boundary="aZoGpuMECXJckB41" -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -In-Reply-To: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw>; from larry_wu@mail.gss.com.tw on Fri, May 31, 2002 at 06:38:45PM +0800 -Status: RO -Content-Length: 2819 -Lines: 74 - ---aZoGpuMECXJckB41 -Content-Type: text/plain; charset=iso-8859-1 -Content-Disposition: inline -Content-Transfer-Encoding: quoted-printable - -On 2002-05-31 18:38:45 +0800, Larry Wu (=A7d=A4l=B7=D3) wrote: -> I encountered a problem to insert a space value ( like ' ' ) into Oracle -> database. -[...] -> Unfortunately, I have a table A contained a not allow null column -> NotNullCol. Now I want to insert a row like below: ->=20 -> $sth =3D $dbh->prepare( qq{ insert into A ( KeyCol, NotNullCol ) -> values (?,?)} ); -> $sth->bind_param(1, '1'); -> $sth->bind_param(2, ' '); -> $sth->execute; ->=20 -> When I executed this file I got an error from Oracle: Can't insert NULL -> value into ( "A"."NotNullCol") (DBD ERROR: OCIStmtExecute). -> I think the space value was truncated in the process. Could any one tell = -me -> how to keep a blank space in my bind_param ? - -use DBD::Oracle qw(:ora_types); -[...] -$sth->bind_param(2, ' ', { ora_type =3D> ORA_CHAR }); - -This is a frequently asked question here. The default type for strings, -ORA_VARCHAR2, strips trailing blanks from strings. A few months ago, -during one of the diskussuions about this feature, Tim said that he -might add a way to change the default in a future version of -DBD::Oracle. If he doesn't, maybe a paragraph like the following should -be added to the doc (not sure where - it fits below "Using DBD::Oracle -with Oracle 8 - Features and Issues" but it isn't Oracle 8 specific): - - =3Dhead2 Inserting strings with trailing spaces - - OCI provides several string types which behave differently. - Unfortunately, none of them can store arbitrary perl strings. - By default, DBD::Oracle binds string variables as ORA_VARCHAR2, - which allows embedded NUL characters but strips trailing spaces. If - you need trailing spaces, but don't need embedded NUL characters, - you can explicetly bind the param to type ORA_CHAR with: - - $sth->bind_param(($field_num, $string_value, - { ora_type =3D> ORA_CHAR }); - - =20 - hp - ---=20 - _ | Peter J. Holzer | Aeltere Sources (also solche, die schon -|_|_) | Sysadmin WSR / LUGA | aelter als 12 Stunden sind) sollte man -| | | hjp@wsr.ac.at | bei Linux generell nicht einsetzen - -__/ | http://www.hjp.at/ | Real Time Linux?? -- Gerhard Schneider - ---aZoGpuMECXJckB41 -Content-Type: application/pgp-signature -Content-Disposition: inline - ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.0.6 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -iQDQAwUBPPeD11LjemazOuKpAQEtNAXUC6rFL0C0v6MNW/K5ggXcSDY7Xvrj6Ed/ -jqjHq2Dx+h2rIMWXCDIGZVphSG74u4FL41AQF/rzGR/e56qH7aAxVmaiLdQE/DRi -zzsoOHoPEg96FhHljDtCZyxHzsz9sRJ1dfW1PELn5r2OSYPPsVzMoeR4iEXnVjvV -ZYH/OfbKRKhysIHjcNYKcyQL87GXdjzCEas3Xz+jyxW2vqzGAwUfTim4ySY9rF37 -c5vopwrTFCsi58r1LccFhQqEfw== -=Xe8d ------END PGP SIGNATURE----- - ---aZoGpuMECXJckB41-- - diff --git a/err_unicode/err_twolongstr.msg b/err_unicode/err_twolongstr.msg deleted file mode 100644 index 5d6c357d..00000000 --- a/err_unicode/err_twolongstr.msg +++ /dev/null @@ -1,1256 +0,0 @@ -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Wed Nov 17 19:08:49 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAHJ8F8P027204 - for ; Wed, 17 Nov 2004 19:08:48 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 17 Nov 2004 19:08:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUUU6-0001mQ-FU; - Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUUU6-0001mQ-FU - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUUU6-0000DF-68 - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9D10A120BFA; - Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 8C898120BEF - for ; Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Received-SPF: none (icicle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by icicle.pobox.com (Postfix) with ESMTP id 362C6120BEC - for ; Wed, 17 Nov 2004 13:24:46 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 9C0CC244379 - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 17196-06 for ; - Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 3131324406F - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 10:22:44 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_006A_01C4CC8F.60A4F6F0" -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117173321.GA6272@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTMy6HoelzJHh9WSPaTpCdfuF1C4gABpsZg -Message-Id: <20041117182444.3131324406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 16865 -Lines: 527 - -This is a multi-part message in MIME format. - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -I did - it is attached to the posting. However, I will attach it again -here. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 9:33 AM -> To: Susan Cassidy -> Cc: dbi-users@perl.org -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> If you can post a small self-contained example that demonstrates -> the problem then I'll take a look. -> -> Tim. -> -> On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > I never got any response to my question about this problem. I -> thought I'd try again. -> > -> > -> > -> > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> 5.8.5. -> > -> > -> > -> > Thanks, -> > -> > Susan -> > -> > -> > -> > --------------------------------------------------------------------- -> ----------------------------------- -> > -> > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > Sent: Friday, November 05, 2004 10:23 AM -> > To: 'dbi-users@perl.org' -> > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for -> > insert into a LONG column' when data not LONG -> > -> > -> > -> > I had an application that was processing a bunch of xml and inserting -> into a table with a bunch of -> > VARCHAR2(4000) columns. -> > -> > -> > -> > A couple of the entries I was processing caused the 'ORA-01461: can -> bind a LONG value only for insert -> > into a LONG column' error. -> > -> > -> > -> > I put checks in for the length of the data, and nothing approached -> 4000 bytes in length. -> > -> > -> > -> > I tracked down some of the entries causing problems, and on certain -> specific data, if 2 columns -> > containing specific data are inserted together, I get this error. If -> only one of the 2 is inserted, I -> > do not get the error, regardless of which one of the two I insert. -> > -> > -> > -> > The lengths of the pieces of data are 1399 and 1397 characters. -> > -> > -> > -> > The data is somewhat odd-looking (we suspect some odd data is in this -> file), but there is no reason for -> > the error message to appear. -> > -> > -> > -> > Trace shows nothing helpful - it thinks the data is the right length. -> > -> > -> > -> > We've successfully inserted thousands of other, similar entries with -> no trouble. -> > -> > -> > -> > The basics are: -> > -> > #create table test_table (item1 varchar2(4000), item2 -> varchar2(4000)); -> > -> > -> > -> > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, ?)"; -> > -> > -> > -> > $sth=$dbh->prepare($statement) || -> > -> > errexit("bad prepare for stmt $statement, error: $DBI::errstr"); -> > -> > my $rc=$sth->execute(@vals) || -> > -> > errexit("can't execute statement: error: $DBI::errstr\n"); -> > -> > -> > -> > Trace shows: -> > -> > -> > -> > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > -> > -> prepare for DBD::Oracle::db (DBI::db=HASH(0x82d4178)~0x82d6580 -> 'INSERT INTO test_table -> > (item1,item2) VALUES (?, ?) -> > -> > ') thr#8148ff0 -> > -> > dbd_preparse scanned 2 distinct placeholders -> > -> > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl line -> 40 -> > -> > -> execute for DBD::Oracle::st (DBI::st=HASH(0x82d6640)~0x8149dcc -> 'version 11.2no service -> > password-encryptionservice -> > -> > udp-small-serversservice tcp-small-servers!hostname router1!!no ip -> domain-lookupip inspect name mysite -> > ftpip inspect name -> > -> > mysite smtpip inspect name mysite tcp!interface Ethernet0ip address -> 10.10.10.2 255.255.255.0ip -> > access-group 101 inip ins -> > -> > pect mysite inip inspect mysite outno keepalive!interface Serial0no -> ip addressencapsulation -> > frame-relay...' 'version 11.2 -> > -> > no service password-encryptionservice udp-small-serversservice tcp- -> small-servers!hostname router1!!no ip -> > domain-lookupip -> > -> > inspect name mysite ftpip inspect name mysite smtpip inspect name -> mysite tcp!interface Ethernet0ip -> > address 10.10.10.2 255 -> > -> > .255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite -> outno keepalive!interface Serial0no -> > ip addressencaps -> > -> > ulation frame-relayn...') thr#8148ff0 -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (type 0) -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (size -> 1399/1400/0, ptype 4, otype 1) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (type 0) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (size -> 1397/1398/0, ptype 4, otype 1) -> > -> > dbd_st_execute INSERT (out0, lob0)... -> > -> > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > <- execute= undef at test_insert_large.pl line 42 -> > -> > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> 'ParamValues') thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line 42 -> > -> > -> $DBI::errstr (&) FETCH from lasth=HASH -> > -> > >> DBD::Oracle::st::errstr -> > -> > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' -> > -> > -- DBI::END -> > -> > -> disconnect_all for DBD::Oracle::dr -> (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > -> > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > -> > Connect done -> > -> > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > -> > Size of vals is 2 -> > -> > val 1 size 1399, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!i -> > -> > nterface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11 -> > -> > .2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 IETF!router eigrp 69network -> > 10.0.0.0no auto-summar -> > -> > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0. -> > -> > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permit icmp 10.10.10.0 -> > 0.0.0.255 anyaccess- -> > -> > list 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-rep -> > -> > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 ad -> > -> > ministratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp a -> > -> > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 0.0.0.255 -> > time-exceededaccess-list 102 permit tcp -> > -> > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > val 2 size 1397, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11. -> > -> > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci 200 -> IETF!router eigrp 69network -> > 10.0.0.0no auto-summary -> > -> > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 0.0.0.0 -> 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0.0 -> > -> > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permiticmp 10.10.10.0 -> > 0.0.0.255 anyaccess-li -> > -> > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess-list -> 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-reply -> > -> > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 admi -> > -> > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp any -> > -> > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 time-exceededaccess-list -> > 102 permit tcp an -> > -> > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > can't execute statement: error: ORA-01461: can bind a LONG value only -> for insert into a LONG column (DBD -> > ERROR: OCIStmtEx -> > -> > ecute) -> > -> > -> > -> > ! -> DESTROY for DBD::Oracle::db (DBI::db=HASH(0x82d6580)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#0) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > -> > -> > I will attach the test program. Somehow it seems to think the -> datatype is LONG instead of VARCHAR. -> > -> > -> > -> > -> > -> > Anyone with ideas? -> > -> > -> > -> > -> > -> > Thanks, -> > -> > Susan -> - - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: application/octet-stream; - name="test_insert_large.pl" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="test_insert_large.pl" - -#!/usr/local/bin/perl -w=0A= -=0A= -use DBI;=0A= -=0A= -our $dbh;=0A= -our $sth;=0A= -=0A= -$dbuser=3D"proj1";=0A= -$dbpasswd=3D"proj1";=0A= -=0A= -$dbserver=3D'oracledev';=0A= -$db_sid=3D'AL32UTF8';=0A= -=0A= -##=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D connect to database = -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=0A= -=0A= -$dbh=3D DBI->connect("dbi:Oracle:host=3D$dbserver;sid=3D$db_sid", = -$dbuser, $dbpasswd,=0A= - {PrintError =3D> 0, AutoCommit =3D> 1}) or=0A= - errexit( "Unable to connect to $dbserver: $DBI::errstr");=0A= -print "Connect done\n";=0A= -=0A= -#create table test_table (item1 varchar2(4000), item2 varchar2(4000));=0A= -=0A= -=0A= -my $statement=3D"INSERT INTO test_table (item1,item2) VALUES (?, ?)";=0A= -print "stmt: $statement\n";=0A= -=0A= -@vals=3D(=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysite inip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permit icmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permiticmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= -);=0A= -=0A= -print "Size of vals is ",scalar @vals,"\n";=0A= -my $z=3D0;=0A= -foreach my $x (@vals) {=0A= - my $len=3Dlength($x);=0A= - print "val ",++$z, " size $len, is: '$x'\n";=0A= -}=0A= -=0A= -DBI->trace(2);=0A= - $sth=3D$dbh->prepare($statement) ||=0A= - errexit("bad prepare for stmt $statement, error: $DBI::errstr");=0A= - my $rc=3D$sth->execute(@vals) ||=0A= - errexit("can't execute statement: error: $DBI::errstr\n");=0A= -=0A= -print "Done\n";=0A= -exit;=0A= -=0A= -=0A= -sub errexit {=0A= - my (@msg)=3D@_;=0A= - print @msg,"\n";=0A= - exit 1;=0A= -}=0A= -=0A= -=0A= -=0A= - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0-- - - -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 00:15:21 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI0FC8G049539 - for ; Thu, 18 Nov 2004 00:15:21 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 00:15:21 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUVdd-0002Nv-CF; - Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUVdd-0002Nv-CF - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CUVdc-0005lu-Rs - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 4A256ADD6F; - Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3D82CADD64 - for ; Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Received-SPF: none (boggle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by boggle.pobox.com (Postfix) with ESMTP id B23D4ADCF6 - for ; Wed, 17 Nov 2004 14:38:15 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 0C9DF24435B - for ; Wed, 17 Nov 2004 11:38:14 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 18475-01 for ; - Wed, 17 Nov 2004 11:38:13 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id ACF0424406F - for ; Wed, 17 Nov 2004 11:38:13 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 11:36:14 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117192902.GA31595@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTM27+9yfJDVs3WQIWAKc6DR3EgdQAAKfgw -Message-Id: <20041117193813.ACF0424406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -X-Status: A -Content-Length: 14671 -Lines: 489 - -NLS_LANG=.UTF8 -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORACLE_HOME=/home/oracle/product/9.2.0 -ORACLE_SID=AL32UTF8 -ORACLE_BASE=/home/oracle - -NLS_NCHAR is not set, because we are not using any NVARCHAR data item, and -haven't needed it. - -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 11:29 AM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > I did - it is attached to the posting. However, I will attach it again -> > here. -> > -> > Thanks, -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 9:33 AM -> > > To: Susan Cassidy -> > > Cc: dbi-users@perl.org -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > If you can post a small self-contained example that demonstrates -> > > the problem then I'll take a look. -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > > > I never got any response to my question about this problem. I -> > > thought I'd try again. -> > > > -> > > > -> > > > -> > > > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> > > 5.8.5. -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > > -> > > > -> > > > -> > > > ----------------------------------------------------------------- -> ---- -> > > ----------------------------------- -> > > > -> > > > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > > > Sent: Friday, November 05, 2004 10:23 AM -> > > > To: 'dbi-users@perl.org' -> > > > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> > > 01461: can bind a LONG value only for -> > > > insert into a LONG column' when data not LONG -> > > > -> > > > -> > > > -> > > > I had an application that was processing a bunch of xml and -> inserting -> > > into a table with a bunch of -> > > > VARCHAR2(4000) columns. -> > > > -> > > > -> > > > -> > > > A couple of the entries I was processing caused the 'ORA-01461: -> can -> > > bind a LONG value only for insert -> > > > into a LONG column' error. -> > > > -> > > > -> > > > -> > > > I put checks in for the length of the data, and nothing -> approached -> > > 4000 bytes in length. -> > > > -> > > > -> > > > -> > > > I tracked down some of the entries causing problems, and on -> certain -> > > specific data, if 2 columns -> > > > containing specific data are inserted together, I get this error. -> If -> > > only one of the 2 is inserted, I -> > > > do not get the error, regardless of which one of the two I -> insert. -> > > > -> > > > -> > > > -> > > > The lengths of the pieces of data are 1399 and 1397 characters. -> > > > -> > > > -> > > > -> > > > The data is somewhat odd-looking (we suspect some odd data is in -> this -> > > file), but there is no reason for -> > > > the error message to appear. -> > > > -> > > > -> > > > -> > > > Trace shows nothing helpful - it thinks the data is the right -> length. -> > > > -> > > > -> > > > -> > > > We've successfully inserted thousands of other, similar entries -> with -> > > no trouble. -> > > > -> > > > -> > > > -> > > > The basics are: -> > > > -> > > > #create table test_table (item1 varchar2(4000), item2 -> > > varchar2(4000)); -> > > > -> > > > -> > > > -> > > > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, -> ?)"; -> > > > -> > > > -> > > > -> > > > $sth=$dbh->prepare($statement) || -> > > > -> > > > errexit("bad prepare for stmt $statement, error: -> $DBI::errstr"); -> > > > -> > > > my $rc=$sth->execute(@vals) || -> > > > -> > > > errexit("can't execute statement: error: $DBI::errstr\n"); -> > > > -> > > > -> > > > -> > > > Trace shows: -> > > > -> > > > -> > > > -> > > > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > > > -> > > > -> prepare for DBD::Oracle::db -> (DBI::db=HASH(0x82d4178)~0x82d6580 -> > > 'INSERT INTO test_table -> > > > (item1,item2) VALUES (?, ?) -> > > > -> > > > ') thr#8148ff0 -> > > > -> > > > dbd_preparse scanned 2 distinct placeholders -> > > > -> > > > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl -> line -> > > 40 -> > > > -> > > > -> execute for DBD::Oracle::st -> (DBI::st=HASH(0x82d6640)~0x8149dcc -> > > 'version 11.2no service -> > > > password-encryptionservice -> > > > -> > > > udp-small-serversservice tcp-small-servers!hostname router1!!no -> ip -> > > domain-lookupip inspect name mysite -> > > > ftpip inspect name -> > > > -> > > > mysite smtpip inspect name mysite tcp!interface Ethernet0ip -> address -> > > 10.10.10.2 255.255.255.0ip -> > > > access-group 101 inip ins -> > > > -> > > > pect mysite inip inspect mysite outno keepalive!interface -> Serial0no -> > > ip addressencapsulation -> > > > frame-relay...' 'version 11.2 -> > > > -> > > > no service password-encryptionservice udp-small-serversservice -> tcp- -> > > small-servers!hostname router1!!no ip -> > > > domain-lookupip -> > > > -> > > > inspect name mysite ftpip inspect name mysite smtpip inspect name -> > > mysite tcp!interface Ethernet0ip -> > > > address 10.10.10.2 255 -> > > > -> > > > .255.255.0ip access-group 101 inip inspect mysiteinip inspect -> mysite -> > > outno keepalive!interface Serial0no -> > > > ip addressencaps -> > > > -> > > > ulation frame-relayn...') thr#8148ff0 -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (type -> 0) -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (size -> > > 1399/1400/0, ptype 4, otype 1) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (type -> 0) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (size -> > > 1397/1398/0, ptype 4, otype 1) -> > > > -> > > > dbd_st_execute INSERT (out0, lob0)... -> > > > -> > > > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > <- execute= undef at test_insert_large.pl line 42 -> > > > -> > > > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> > > 'ParamValues') thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line -> 42 -> > > > -> > > > -> $DBI::errstr (&) FETCH from lasth=HASH -> > > > -> > > > >> DBD::Oracle::st::errstr -> > > > -> > > > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' -> > > > -> > > > -- DBI::END -> > > > -> > > > -> disconnect_all for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > > > -> > > > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > > > -> > > > Connect done -> > > > -> > > > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > > > -> > > > Size of vals is 2 -> > > > -> > > > val 1 size 1399, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!i -> > > > -> > > > nterface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11 -> > > > -> > > > .2 255.255.255.252ip access-group 102 inframe-relay interface- -> dlci -> > > 200 IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summar -> > > > -> > > > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> > > 0.0.0.0 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0. -> > > > -> > > > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permit icmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess- -> > > > -> > > > list 101 deny ip any anyaccess-list 102 permit eigrp any -> anyaccess- -> > > list 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-rep -> > > > -> > > > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 ad -> > > > -> > > > ministratively-prohibitedaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp a -> > > > -> > > > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> > > 10.10.10.0 0.0.0.255 -> > > > time-exceededaccess-list 102 permit tcp -> > > > -> > > > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line -> con -> > > 0line vty 0 4login!end' -> > > > -> > > > val 2 size 1397, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11. -> > > > -> > > > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 -> > > IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summary -> > > > -> > > > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 -> > > 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0.0 -> > > > -> > > > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permiticmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess-li -> > > > -> > > > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list -> > > 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-reply -> > > > -> > > > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 admi -> > > > -> > > > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp any -> > > > -> > > > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 time-exceededaccess-list -> > > > 102 permit tcp an -> > > > -> > > > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> > > 0line vty 0 4login!end' -> > > > -> > > > can't execute statement: error: ORA-01461: can bind a LONG value -> only -> > > for insert into a LONG column (DBD -> > > > ERROR: OCIStmtEx -> > > > -> > > > ecute) -> > > > -> > > > -> > > > -> > > > ! -> DESTROY for DBD::Oracle::db -> (DBI::db=HASH(0x82d6580)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#0) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY for DBD::Oracle::st -> (DBI::st=HASH(0x8149dcc)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > -> > > > -> > > > I will attach the test program. Somehow it seems to think the -> > > datatype is LONG instead of VARCHAR. -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Anyone with ideas? -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > -> > -> - - - -From SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 07:11:03 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI7Ar8G057950 - for ; Thu, 18 Nov 2004 07:11:03 GMT - (envelope-from SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 07:11:03 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUaCR-0002mS-7P; - Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUaCR-0002mS-7P - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUaCQ-0004JQ-R5 - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 17ACAA3F35; - Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from integer (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 04F8DA3EAC - for ; Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Received-SPF: none (integer.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by integer.pobox.com (Postfix) with ESMTP id A9FC6A3F4D - for ; Wed, 17 Nov 2004 19:30:43 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id DEA102441A9 - for ; Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 22204-10 for ; - Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 7AD52244370 - for ; Wed, 17 Nov 2004 16:30:40 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 16:28:41 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041118001712.GB49519@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTNA/o7HZXghXaJRbyz8M5kVQMQmwAAUBjg -Message-Id: <20041118003040.7AD52244370@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 1789 -Lines: 63 - -Hi, - -I set NLS_LANG to .US7ASCII, ran it again, and I get the same error. - -Of course, I could not use that in production. - -The really strange part, to me, was that if I just insert one of the 2 -problematic columns, it worked, but both together failed. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 4:17 PM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> And does the problem go away if NLS_LANG is set to a non-unicode charset? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 11:36:14AM -0800, Susan Cassidy wrote: -> > NLS_LANG=.UTF8 -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORACLE_HOME=/home/oracle/product/9.2.0 -> > ORACLE_SID=AL32UTF8 -> > ORACLE_BASE=/home/oracle -> > -> > NLS_NCHAR is not set, because we are not using any NVARCHAR data item, -> and -> > haven't needed it. -> > -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 11:29 AM -> > > To: Susan Cassidy -> > > Cc: 'Tim Bunce' -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > > > I did - it is attached to the posting. However, I will attach it -> again -> > > > here. -> > > > -> > > > Thanks, -> > > > Susan -> > > > - - diff --git a/err_unsorted/err_etherreal.msg b/err_unsorted/err_etherreal.msg deleted file mode 100644 index 1ad5c78e..00000000 --- a/err_unsorted/err_etherreal.msg +++ /dev/null @@ -1,90 +0,0 @@ -From dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org Tue Apr 30 14:47:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UDliR22576 - for ; Tue, 30 Apr 2002 14:47:44 +0100 (BST) - (envelope-from dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.23] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 14:47:44 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020172466:10:24548:59; Tue, 30 Apr 2002 13:14:26 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1023391; 30 Apr 2002 13:13 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id A94562C075 - for ; Tue, 30 Apr 2002 09:12:33 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id F24B22BFBE - for ; Tue, 30 Apr 2002 09:12:32 -0400 (EDT) -Received: (qmail 36589 invoked by uid 1005); 30 Apr 2002 13:12:28 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 36168 invoked by uid 76); 30 Apr 2002 13:10:41 -0000 -Content-Type: text/plain; - charset="iso-8859-1" -From: Calin Medianu -To: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Date: Tue, 30 Apr 2002 16:04:47 +0300 -X-Mailer: KMail [version 1.3.2] -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> <20020429233138.E16831@dansat.data-plan.com> -In-Reply-To: <20020429233138.E16831@dansat.data-plan.com> -Cc: dbi-users@perl.org -MIME-Version: 1.0 -Message-Id: <20020430131233.F24B22BFBE@dolly1.pobox.com> -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id g3UDliR22576 -Status: RO -X-Status: A -Content-Length: 1213 -Lines: 38 - -[Add note to DBD::Oracle docs about using ethereal to sniff Oracle packets] -[Not sure if this bug got fixed yet. Maybe not.] - -Me again with the slow cursors. - -I modified both queries to only return 10 rows. -I ran a sniffer (ethereal) on the NIC. It is pretty cool, it also decodes TNS. - -when I am using the SQL, it works like this, there are about 7 packets -received by my workstation to set up the session, then all 10 rows are in the -same packet, then there is another packet probably saying goodbye. - -When I am using the REF cursor, each row comes in it's own TNS packet, that -is why it is so slow! - -Any idea how to fix it? - -thanks a lot, - -Calin - -> On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> > Hello, -> > -> > I did the following. Wrote a perl script that retreves -> > data via a straight select from the database. Then I -> > wrote a stored procedure returning a ref cursor open -> > on the same select statement and retrieved the data as -> > well. Using the REF CURSOR/ sotred procedure was about -> > 3 time slower, that is 40 seconds instead of around -> > 10. -> > -> > Is this normal? Is this a problem with oracle or with -> > DBD::Oracle? -> -> DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. -> -> Get a level 3 trace and look for the "dbd_describe'd" line for the -> ref cursor. -> -> Tim. - diff --git a/err_unsorted/err_memleak2.msg b/err_unsorted/err_memleak2.msg deleted file mode 100644 index 97501852..00000000 --- a/err_unsorted/err_memleak2.msg +++ /dev/null @@ -1,476 +0,0 @@ -From mike@boom.net Fri Nov 28 22:23:33 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hASMLLnY018698 - for ; Fri, 28 Nov 2003 22:23:33 GMT - (envelope-from mike@boom.net) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 28 Nov 2003 22:23:33 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1APmgW-0006iM-9g; - Fri, 28 Nov 2003 17:45:40 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1APmgW-0006iM-9g - for pobox@dbi.demon.co.uk; Fri, 28 Nov 2003 17:45:40 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id E82CD95E03 - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B1EE595DFB - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: from abort.boom.net (abort.boom.net[69.36.241.24]) - by icicle.pobox.com (Postfix) with ESMTP - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: by abort.boom.net (Postfix, from userid 530) - id E3C8B8517A; Fri, 28 Nov 2003 09:45:36 -0800 (PST) -Date: Fri, 28 Nov 2003 09:45:36 -0800 -From: Mike Hedlund -To: dbi-users@perl.org -Cc: Tim.Bunce@pobox.com -Subject: Memory leak in DBD::Oracle 1.14 ... ? -Message-ID: <20031128174536.GJ10609@boom.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.5.4i -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id hASMLLnY018698 -Content-Length: 24309 -Lines: 434 - -I've attached a little script which replicates the problem on my machine as well as the build session log for DBD::Oracle 1.14. - -I've tested it using DBI 1.38 and DBI 1.28 with both DBD::Oracle 1.12 and 1.14. - -Regardless of the DBI version, DBD::Oracle 1.14 leaks on my system and DBD::Oracle 1.12 does not. I've noticed the leak when calling connect_cached(), do() (or prepare()/execute()/commit/finish). - --mike - - --------------------- script --------------- -#!/usr/bin/perl -use strict; -use DBI; - -my($dbp) = "dbi:Oracle:host=weirdo.com;port=1521;sid=SID"; -my($dbu) = "username"; -my($dbpass) = "password"; - -while (1) { - my($sth); - my(@row); - my($dbh) = DBI->connect_cached($dbp,$dbu,$dbpass) || die "Couldn't connect to oracle db: $DBI::errstr\n"; - -## -## uncomment these and it just leaks faster. -## -# $sth = $dbh->prepare("SELECT * from FROM_STATS"); -# $sth->execute; -# while(@row = $sth->fetchrow_array) { - ##print "row: @row\n"; -# } -# $sth->finish; -} -exit; ------------------------- end script -------------------- - - ------------- log --------------------------------------- -Script started on Fri 28 Nov 2003 09:11:15 AM PST -[mike@commando DBD-Oracle-1.14]$ setenv ORACLE_HOME /home/orahome -[mike@commando DBD-Oracle-1.14]$ make realclean -rm -f blib/script/ora_explain -rm -rf Oracle.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm ./blib Makefile.aperl blib/arch/auto/DBD/Oracle/extralibs.all perlmain.c tmon.out mon.out so_locations pm_to_blib *.o *.a perl.exe perl perl Oracle.bs Oracle.bso Oracle.def libOracle.def Oracle.exp Oracle.x core core.*perl.*.? *perl.core -mv Makefile Makefile.old > /dev/null 2>&1 -rm -rf blib/lib/auto/DBD/Oracle blib/arch/auto/DBD/Oracle -rm -rf DBD-Oracle-1.14 -rm -f blib/arch/auto/DBD/Oracle/Oracle.so blib/arch/auto/DBD/Oracle/Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.a -rm -f blib/lib/DBD/Oracle.pm blib/arch/auto/DBD/Oracle/dbdimp.h blib/lib/oraperl.ph -rm -f blib/arch/auto/DBD/Oracle/ocitrace.h blib/lib/Oraperl.pm -rm -f blib/arch/auto/DBD/Oracle/Oracle.h blib/arch/auto/DBD/Oracle/mk.pm -rm -f blib/lib/DBD/Oracle/GetInfo.pm -rm -rf Makefile Makefile.old -[mike@commando DBD-Oracle-1.14]$ perl Makefile.PL -v -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI - - Configuring DBD::Oracle ... - ->>> Remember to actually *READ* the README file! - Especially if you have any problems. - -Using Oracle in /home/orahome - -WARNING: could not decode oracle version from -/home/orahome/orainst/inspdver, or /home/orahome/install/unix.rgs -or from ORACLE_HOME path /home/orahome. -Oracle version based logic in Makefile.PL may produce erroneous results. - -Found header files in rdbms/public rdbms/demo. -Found /home/orahome/rdbms/demo/demo_rdbms.mk -Found /home/orahome/otrace/demo/atmoci.mk -Found /home/orahome/precomp/demo/proc/demo_proc.mk -Using /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/lib/env_rdbms.mk -Read a total of 2202 lines from /home/orahome/rdbms/lib/env_rdbms.mk (including inclusions) -Read a total of 2493 lines from /home/orahome/rdbms/demo/demo_rdbms.mk (including inclusions) -Deleted SHELL definition: SHELL=/bin/sh -Deleted LIB_EXT definition: LIB_EXT=a -Deleted OBJ_EXT definition: OBJ_EXT=o -Deleted AR definition: AR=ar -Deleted AS definition: AS=as -Deleted CC definition: CC=cc -Deleted CHMOD definition: CHMOD=chmod -Deleted CPP definition: CPP=cpp -Deleted ECHO definition: ECHO=echo -Deleted LD definition: LD=ld -Deleted PERL definition: PERL=perl -Deleted CFLAGS definition: CFLAGS=$(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ -Deleted OPTIMIZE definition: OPTIMIZE=$(OPTIMIZE3) -Deleted AR definition: AR=/usr/bin/ar -Deleted AS definition: AS=/usr/bin/as -Deleted LD definition: LD=/usr/bin/ld -Deleted CPP definition: CPP=/lib/cpp -Deleted CHMOD definition: CHMOD=/bin/chmod -Deleted ASFLAGS definition: ASFLAGS= -Deleting ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS definition: ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Deleting ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS33 definition: ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Appending '/home/orahome/rdbms/lib/libskgxpd.a /home/orahome/rdbms/lib/libskgxpu.a /home/orahome/rdbms/lib/libskgxpt.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxp9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxp9.a' to LIBS -Appending '/home/orahome/rdbms/lib/libskgxns.a /home/orahome/rdbms/lib/libskgxnd.a /home/orahome/rdbms/lib/libskgxnr.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxn9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxn9.a' to LIBS -Evaluating `cat $(LIBHOME)sysliblist` - expanded `cat /home/orahome/lib/sysliblist` - returned '-ldl -lm -lpthread -lnsl ' - -Attempting to discover Oracle OCI build rules -gcc -c -o DBD_ORA_OBJ.o DBD_ORA_OBJ.c -by executing: (make -f /home/orahome/rdbms/demo/demo_rdbms.mk build ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh' CC=echo OPTIMIZE= CCFLAGS= EXE=DBD_ORA_EXE OBJS=DBD_ORA_OBJ.o) -returned: -[echo -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh `cat /home/orahome/lib/sysliblist` -ldl -lm - -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -reduced to: -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -Oracle oci build command: - + -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - - - -System: perl5.008 linux stripples.devel.redhat.com 2.4.21-1.1931.2.382.entsmp #1 smp wed aug 6 17:18:52 edt 2003 i686 i686 i386 gnulinux -Compiler: gcc -O2 -g -pipe -march=i386 -mcpu=i686 -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -Linker: /usr/bin/ld -Sysliblist: -ldl -lm -lpthread -lnsl -Oracle makefiles would have used these definitions but we override them: - CC: cc - - CFLAGS: $(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) - [$(GFLAG) -O3 $(CDEBUG) $(CCFLAGS) -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -DLINUX -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS $(LPFLAGS) $(USRFLAGS)] - - LDFLAGS: -o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ - [-o $@ -L/home/orahome/rdbms/lib/ -L$(LIBHOME) -L$(LIBHOME)stubs/] - - -Linking with OTHERLDFLAGS = -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - [from 'build' rule] - - -MakeMaker (v6.03) -Checking if your kit is complete... -Looks good - ABSTRACT_FROM => q[Oracle.pm] - AUTHOR => q[Tim Bunce (dbi-users@perl.org)] - DEFINE => q[ -DUTF8_SUPPORT] - DIR => [] - EXE_FILES => [q[ora_explain]] - INC => q[-I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI] - NAME => q[DBD::Oracle] - OBJECT => q[$(O_FILES)] - PREREQ_PM => { DBI=>q[0] } - VERSION_FROM => q[Oracle.pm] - clean => { FILES=>q[Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm] } - dist => { DIST_DEFAULT=>q[clean distcheck disttest ci tardist], COMPRESS=>q[gzip -v9], PREOP=>q[$(MAKE) -f Makefile.old distdir], SUFFIX=>q[gz] } - dynamic_lib => { OTHERLDFLAGS=>q[ -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] } -Using PERL=/usr/bin/perl -LD_RUN_PATH=/home/orahome/lib:/home/orahome/rdbms/lib -Using DBD::Oracle 1.14. -Using DBD::Oracle 1.14. -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -Writing Makefile for DBD::Oracle - -*** If you have problems... - read all the log printed above, and the README and README.help files. - (Of course, you have read README by now anyway, haven't you?) - -[mike@commando DBD-Oracle-1.14]$ make -cp Oracle.pm blib/lib/DBD/Oracle.pm -cp Oracle.h blib/arch/auto/DBD/Oracle/Oracle.h -cp dbdimp.h blib/arch/auto/DBD/Oracle/dbdimp.h -cp oraperl.ph blib/lib/oraperl.ph -cp ocitrace.h blib/arch/auto/DBD/Oracle/ocitrace.h -cp Oraperl.pm blib/lib/Oraperl.pm -cp mk.pm blib/arch/auto/DBD/Oracle/mk.pm -cp lib/DBD/Oracle/GetInfo.pm blib/lib/DBD/Oracle/GetInfo.pm -/usr/bin/perl -p -e "s/~DRIVER~/Oracle/g" /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI/Driver.xst > Oracle.xsi -/usr/bin/perl /usr/lib/perl5/5.8.0/ExtUtils/xsubpp -typemap /usr/lib/perl5/5.8.0/ExtUtils/typemap Oracle.xs > Oracle.xsc && mv Oracle.xsc Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT dbdimp.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci7.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci8.c -Running Mkbootstrap for DBD::Oracle () -chmod 644 Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/home/orahome/lib:/home/orahome/rdbms/lib" gcc -shared -L/usr/local/lib Oracle.o dbdimp.o oci7.o oci8.o -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" blib/script/ora_explain -Manifying blib/man3/DBD::Oracle.3pm -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oraperl.3pm -[mike@commando DBD-Oracle-1.14]$ make test -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/base....... t/base.......ok 1/5 t/base.......ok 2/5 t/base.......ok 3/5 t/base.......ok 4/5 t/base.......ok 5/5 t/base.......ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/reauth.....skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.82 cusr + 0.33 csys = 4.15 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ make test TEST_VERBOSE=1 -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1, 'blib/lib', 'blib/arch')" t/*.t -t/base.......1..5 -ok 1 -ok 2 -ok 3 -ok 4 -ok 5 -ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/reauth.....ORACLE_USERID_2 not defined. -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.85 cusr + 0.32 csys = 4.17 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ perl _V-V -Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: - Platform: - osname=linux, osvers=2.4.21-1.1931.2.382.entsmp, archname=i386-linux-thread-multi - uname='linux str' - config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Dotherlibdirs=/usr/lib/perl5/5.8.0 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr' - hint=recommended, useposix=true, d_sigaction=define - usethreads=define use5005threads=undef' - useithreads=define usemultiplicity= - useperlio= d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=un uselongdouble= - usemymalloc=, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', - optimize='', - cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm' - ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)', gccosandvers='' -gccversion='3.2.2 200302' - intsize=r, longsize=r, ptrsize=5, doublesize=8, byteorder=1234 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - ivtype='long' -k', ivsize=4' -ivtype='l, nvtype='double' -o_nonbl', nvsize=, Off_t='', lseeksize=8 - alignbytes=4, prototype=define - Linker and Libraries: - ld='gcc' -l', ldflags =' -L/u' - libpth=/usr/local/lib /lib /usr/lib - libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil - perllibs= - libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libper - gnulibc_version='2.3.2' - Dynamic Linking: - dlsrc=dl_dlopen.xs, dlext=so', d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE' - cccdlflags='-fPIC' -ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5', lddlflags='s Unicode/Normalize XS/A' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING MULTIPLICITY USE_ITHREADS USE_LARGE_FILES PERL_IMPLICIT_CONTEXT - Locally applied patches: - MAINT18379 - Built under linux - Compiled at Aug 13 2003 11:47:58 - @INC: - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/site_perl/5.8.0 - /usr/lib/perl5/site_perl - /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/vendor_perl/5.8.0 - /usr/lib/perl5/vendor_perl - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - . -[mike@commando DBD-Oracle-1.14]$ ^D -Script done on Fri 28 Nov 2003 09:16:43 AM PST ------------- end log ----------------------------------- - - diff --git a/err_unsorted/err_multiora.msg b/err_unsorted/err_multiora.msg deleted file mode 100644 index 9f7bcf6c..00000000 --- a/err_unsorted/err_multiora.msg +++ /dev/null @@ -1,470 +0,0 @@ -From dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org Mon Jan 5 10:12:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05ACYn1063537 - for ; Mon, 5 Jan 2004 10:12:58 GMT - (envelope-from dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 10:12:58 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdQXY-0007a7-IO; - Mon, 05 Jan 2004 09:18:18 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdQXY-0007a7-IO - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 08:56:48 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id C92F0282F - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id B344B2B84 - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: (qmail 58691 invoked by uid 1005); 5 Jan 2004 08:56:38 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 58674 invoked by uid 76); 5 Jan 2004 08:56:38 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 05 Jan 2004 00:56:38 -0800 -Received: (qmail 17937 invoked by uid 225); 5 Jan 2004 08:56:36 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 17930 invoked by uid 507); 5 Jan 2004 08:56:36 -0000 -Received: from stone.sifira.dk (HELO mail.int.sifira.dk) (217.157.24.2) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Mon, 05 Jan 2004 00:56:05 -0800 -Received: from ash.int.sifira.dk (ash.int.sifira.dk [192.168.1.7]) by mail.int.sifira.dk (Postfix) with ESMTP id F127674F58; Mon, 5 Jan 2004 09:55:58 +0100 (MET) -Sender: kn@sifira.dk -To: "Anniballi, Fran" -Cc: -Subject: Re: Help - multiple Oracle versions -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -From: Kristian Nielsen -Date: 05 Jan 2004 09:55:59 +0100 -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Message-ID: <7sllomsrj4.fsf@ash.int.sifira.dk> -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-2.5 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_GNUS_UA version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1223 -Lines: 40 - -[Add notes to docs covering what's in this thread] - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - -From dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org Mon Jan 5 14:47:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05Ejvo1064760 - for ; Mon, 5 Jan 2004 14:47:30 GMT - (envelope-from dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 14:47:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdVCS-0004w0-Is; - Mon, 05 Jan 2004 13:55:22 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdVCS-0004w0-Is - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 13:55:21 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 548DE2C87 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 417692C81 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 08:55:19 -0500 (EST) -Received: (qmail 91728 invoked by uid 1005); 5 Jan 2004 13:55:17 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 48614 invoked by uid 76); 5 Jan 2004 12:24:01 -0000 -Delivered-To: dbi-users@perl.org -X-MimeOLE: Produced By Microsoft Exchange V6.0.6487.1 -content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; charset="iso-8859-1" -Subject: RE: Help - multiple Oracle versions -Date: Mon, 5 Jan 2004 07:23:23 -0500 -Message-ID: <6B003D25ADBDE347B5542AFE6A55B42E04537A09@tayexc13.americas.cpqcorp.net> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Help - multiple Oracle versions -Thread-Index: AcPTac0nADA1C8LsTdSTxpcvyeSNCgAHQWGQ -From: "Anniballi, Fran" -To: -Cc: -X-OriginalArrivalTime: 05 Jan 2004 12:23:24.0525 (UTC) FILETIME=[B6F761D0:01C3D386] -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.3 required=7.0 tests=CARRIAGE_RETURNS,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i05Ejvo1064760 -Status: RO -Content-Length: 1465 -Lines: 52 - -Thanks. Looks like this is what I'll need. - ------Original Message----- -From: kn@sifira.dk [mailto:kn@sifira.dk] -Sent: Monday, January 05, 2004 3:56 AM -To: Anniballi, Fran -Cc: dbi-users@perl.org -Subject: Re: Help - multiple Oracle versions - - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - - -From dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org Tue Jan 6 17:00:29 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i06GxrnC075337 - for ; Tue, 6 Jan 2004 17:00:29 GMT - (envelope-from dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 06 Jan 2004 17:00:29 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Adu0c-0004RW-9d; - Tue, 06 Jan 2004 16:24:47 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Adu0c-0004RW-9d - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 16:24:47 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 21A79495C - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 08B12494B - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 6 Jan 2004 11:24:45 -0500 (EST) -Received: (qmail 25114 invoked by uid 1005); 6 Jan 2004 16:24:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 25095 invoked by uid 76); 6 Jan 2004 16:24:42 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Tue, 06 Jan 2004 08:24:42 -0800 -Received: (qmail 16535 invoked by uid 225); 6 Jan 2004 16:24:39 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16527 invoked by uid 507); 6 Jan 2004 16:24:39 -0000 -Received: from mail.cybcon.com (HELO mail.cybcon.com) (216.190.188.5) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 06 Jan 2004 08:24:08 -0800 -Received: from poirot (dsl2-6.cybcon.com [208.186.116.6]) by mail.cybcon.com (8.11.6/8.11.6) with ESMTP id i06GNhn08916; Tue, 6 Jan 2004 08:23:43 -0800 -Subject: RE: Help - multiple Oracle versions -From: Jared Still -To: "Anniballi, Fran" -Cc: DBI List -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 (1.0.8-11) -Date: 06 Jan 2004 08:25:59 -0800 -Message-Id: <1073406359.324.244.camel@poirot.jks.com> -Mime-Version: 1.0 -X-CyberConnectics-MailScanner2-Information: Spam/Virus Scanned at CyberConnectics -X-CyberConnectics-MailScanner2: Found to be clean -X-CyberConnectics-MailScanner2-SpamCheck: -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.2 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_05_08,SUPERLONG_LINE version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 4050 -Lines: 102 - -I read quickly through this thread, so my apologies if someone -already pointed this out. - -It doesn't matter which version of Oracle you compiled DBD with, -you can connect to all your 8i/9i databases on any platform with it. - -Assume you compiled with 9i libs, and you can connect to 9i db's with -no problem, but are unable to connect to 8i, getting the error you -mentioned previously. - -It appears that you are changing your Oracle environment via the -oraenv shell script to change your ORACLE_HOME to the 8i version -of Oracle. - -If so, stop doing that. Just leave your environment at 9i, and -connect to your 8i database. It will be fine. This is the way -my linux server is setup, and DBD is used to connect to Oracle -versions 7.3, 8.1.6, 8.1.7 and 9.2.0 every day. - -At our site DBD is compiled with 8i libs so that we can still -connect to the version 7 databases. If you compile with 9i libs, -you will be unable to connect to version 7 databases. - -HTH - -Jared - - -On Sun, 2004-01-04 at 05:12, Anniballi, Fran wrote: -> This is all done on one UNIX box. -> -> If I try option one, it doesn't work. I can't access an oracle8 instance with oracle9 sqlplus (or the other way around). That is the real problem. Since I can't do this I have to reassign the pointers before I access it. I can do this fine with sqlplus but with dbi/dbd I have to compile with one or the other. -> -> For option two, if I have two versions of DBD:Oracle, how do I tell Perl which one to use? My scripts just say "/usr/bin/perl" in the first line. -> -> -----Original Message----- -> From: kn@sifira.dk [mailto:kn@sifira.dk] -> Sent: Saturday, January 03, 2004 1:04 PM -> To: dbi-users@perl.org -> Cc: Anniballi, Fran -> Subject: Re: Help - multiple Oracle versions -> -> -> "Anniballi, Fran" writes: -> -> > As soon as I recompile the same DBI/DBD with it pointing to Oracle 9 -> > environment (libraries), it doesn't work. It is looking for Oracle9 -> > library files and I obviously don't have it pointing to oracle9 -> > libraries when I access an Oracle 8 instance. Oracle 9 is not -> > compatible with Oracle 8 so I have to redirect the environment -> > variables at run time. -> -> It sounds like you are confusing the Oracle client version and the -> Oracle server version. -> -> Eg. if you set ORACLE_HOME to /usr/local/oracle8 (or whatever) and use -> /usr/local/oracle8/bin/sqlplus you are using the Oracle 8 client, while -> if you set it to /usr/local/oracle9 and call -> /usr/local/oracle9/bin/sqlplus, you are using the Oracle 9 client. -> -> Which Oracle instance you access is selected by the connection string; -> for example "sqlplus scott/tiger@DB8" might access the Oracle 8 -> instance, and "scott/tiger@DB9" might access the Oracle 9 instance. -> -> What people are telling you is that you can choose client version -> independently of the server version. For example, it is possible to set -> ORACLE_HOME to /usr/local/oracle9 and call -> -> /usr/local/oracle9/bin/sqlplus scott/tiger@DB8 -> -> to access the Oracle 8 instance with the Oracle 9 client. This of course -> requires that the definition for DB8 is present in the file -> /usr/local/oracle-9.2/network/admin/tnsnames.ora. -> -> So you should either -> -> 1. Use only the Oracle 9 client, not change ORACLE_HOME, and access both -> instances with Oracle 9 sqlplus and DBD::Oracle compiled against -> Oracle 9 libraries. -> -> or -> -> 2. Compile DBD::Oracle twice (once against Oracle 8 libraries, once -> against Oracle 9 libraries, just as you have two versions of sqlplus) -> and use each one with the proper ORACLE_HOME setting. -> -> My guess is that you will find possibility 1. the easiest. -> -> > The tnsnames.ora are all set. I did what you said already. -> > -> > Example: DBI/DBD will work fine if I compile the DBI/DBD pointing to -> > Oracle 8 environment(libraries) and access an Oracle 8 instance. I -> > didn't have to change tnsnames.ora -> -> Yes you do: You need to have BOTH Oracle instances defined in EACH -> tnsnames.ora. -> -> Hope this helps, -> -> - Kristian. - - - -From andy@andyh.co.uk Wed Jan 7 07:31:57 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i077VPn8081048 - for ; Wed, 7 Jan 2004 07:31:57 GMT - (envelope-from andy@andyh.co.uk) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 07 Jan 2004 07:31:57 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Ae0Yb-0002lT-IA; - Tue, 06 Jan 2004 23:24:17 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Ae0Yb-0002lT-IA - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 23:24:17 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 00D7C3C15 - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id CB5813BEA - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from mta03-svc.ntlworld.com (mta03-svc.ntlworld.com [62.253.162.43]) - by integer.pobox.com (Postfix) with ESMTP - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from excession ([80.2.244.47]) by mta03-svc.ntlworld.com - (InterMail vM.4.01.03.37 201-229-121-137-20020806) with SMTP - id <20040106232403.NEKJ9852.mta03-svc.ntlworld.com@excession>; - Tue, 6 Jan 2004 23:24:03 +0000 -Message-ID: <00bd01c3d4ac$e5713190$6564a8c0@excession> -From: "Andy Hassall" -To: "Eric Lenio" , "Tim Bunce" -Cc: -References: <20040102143310.GC27273@lenio.net> <20040104204914.GB60357@dansat.data-plan.com> <20040105123653.GA31473@lenio.net> <20040105223121.GG66760@dansat.data-plan.com> <20040106222634.GG11531@lenio.net> <20040106223845.GE78360@dansat.data-plan.com> <20040106225722.GI11531@lenio.net> -Subject: Re: DBI primary_key tests fail: oracle 8 -Date: Tue, 6 Jan 2004 23:29:14 -0000 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2800.1158 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 43 - -Eric Lenio wrote: -> OK Tim. One other note -- after reading through oracle docs, I think -> you might want to substitute 'session_user' for 'current_schema' in -> 'select sys_context(...)'. The definition of session_user is -> "returns the database -> user name by which the current user is authenticated" while -> current_schema is "returns the name of the default schema being used -> in the current session". -> Maybe it doesn't matter, I'm not an oracle guru by any stretch of the -> imagination. - -There's several usernames in the USERENV context: - -CURRENT_SCHEMA - -The schema/user used for unqualified object name resolution; by default the -user you logged in as, but alterable with 'alter session set -current_schema=x'. Useful for avoiding having to maintain loads of synonyms. - -CURRENT_USER - -The user you're currently authenticated as. Doesn't change in SQL and -anonymous PL/SQL, but changes within definer-rights PL/SQL stored procedures -to the owner of the stored procedure, since stored procs by default run with -the privileges of the owner, not the invoker. - -SESSION_USER - -Who you originally logged in as, and never changes (but see below). Looks -like the appropriate one to use. - -PROXY_USER - -I don't think DBD::Oracle supports proxy authentication so don't need to -worry about that one yet. Possibly a bit of a grey area if it does support -it in the future, since this would hold the username in the DSN, but it'd -reauthenticate and change the SESSION_USER on connect (which would probably -have to be specified as an attribute to the $dbh). - --- -Andy Hassall (andy@andyh.co.uk) icq(5747695) (http://www.andyh.co.uk) -Space: disk usage analysis tool (http://www.andyhsoftware.co.uk/space) - - diff --git a/err_unsorted/err_ora9ir2oci.msg b/err_unsorted/err_ora9ir2oci.msg deleted file mode 100644 index 7ed476e4..00000000 --- a/err_unsorted/err_ora9ir2oci.msg +++ /dev/null @@ -1,27 +0,0 @@ -http://otn.oracle.com/tech/oci/htdocs/oci9ir2_new_features - -OCI Session Pooling -Session Pooling is a new feature in Oracle 9i Database Release 2. -An application can now maintain a pool of sessions and use a session -from the pool when it needs it. This saves the time consuming process -of initiating a connection and authentication every time the process -needs a new session. Session Pooling is useful, especially when a -large number of stateless sessions are required for a very short -time. In a web scenario, where many users are connected for a short -time, and the primary operation is accessing data, it is a costly -operation to start up a new session every time. In such a scenario, -session pooling could boost up the performance. - -OCI Statement caching -Client-side statement caching is also introduced in Oracle9i Database -Release 2. This feature can be enabled at the time of session -creation. It allows users to have a cache of statements per session. -On the server, this means having cursors that ready to be used, -without the need to parse the statements again, and thus improving -performance significantly. With this feature enabled, applications -do not have to keep a track of the statements themselves, as the -OCI layer will do it for them. In addition, a tagging feature is -provided, which users can use as a key to save and search for -statements. - - diff --git a/err_unsorted/err_ref_type.msg b/err_unsorted/err_ref_type.msg deleted file mode 100644 index 26d86e14..00000000 --- a/err_unsorted/err_ref_type.msg +++ /dev/null @@ -1,115 +0,0 @@ -From dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org Wed Jul 23 18:40:02 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6NHUUA0010501 - for ; Wed, 23 Jul 2003 18:40:02 +0100 (BST) - (envelope-from dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 23 Jul 2003 18:40:02 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058948095:10:09585:8; Wed, 23 Jul 2003 08:14:55 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116163; 23 Jul 2003 8:14 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 88C1B21C024 - for ; Wed, 23 Jul 2003 04:13:51 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id AA89B21C082 - for ; Wed, 23 Jul 2003 04:13:50 -0400 (EDT) -Received: (qmail 26606 invoked by uid 1005); 23 Jul 2003 08:13:44 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 26590 invoked by uid 76); 23 Jul 2003 08:13:43 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Wed, 23 Jul 2003 01:13:43 -0700 -Received: (qmail 16360 invoked by uid 225); 23 Jul 2003 08:13:41 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16355 invoked by uid 507); 23 Jul 2003 08:13:41 -0000 -Received-SPF: unknown -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Wed, 23 Jul 2003 01:13:41 -0700 -Received: (qmail 5378 invoked from network); 23 Jul 2003 08:54:08 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 23 Jul 2003 08:54:08 -0000 -Received: (qmail 8984 invoked from network); 23 Jul 2003 08:13:49 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 23 Jul 2003 08:13:49 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Wed, 23 Jul 2003 10:13:49 +0200 (CEST) -Subject: Re: binding to parameters of type REF -From: Hendrik =?ISO-8859-1?Q?Fu=DF?= -To: dbi-users@perl.org -In-Reply-To: <1058865345.1241.56.camel@mars> -References: <1058865345.1241.56.camel@mars> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 -Date: 23 Jul 2003 10:11:49 +0200 -Message-Id: <1058947909.6353.5.camel@mars> -Mime-Version: 1.0 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.3 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,LARGE_HEX,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1354 -Lines: 56 - -I've also found out, that DBD::Oracle does not support type SQL_REF: -When not using DBD::Proxy I get: - - SQL type 20 for ':p1' is not fully supported, - bound as SQL_VARCHAR instead - -I even get segmentation faults when trying to fetch REF columns. :-( - -Any ideas? - -> Hi, -> -> I'm trying to bind a perl variable to an Oracle table reference with -> Oracle 9.2.0.3, DBD::Proxy and Perl::DBI 1.37 without success. I -> could'nt find help on this in the docs or list archives. I hope this is -> the right place to post. -> -> In SQL*Plus: -> -> SQL> desc getReference -> FUNCTION getReference RETURNS REF OF TABLETYPE -> -> SQL> select getReference() from dual; -> -> GETREFERENCE() -> ---------------------------------------------------------------------- -> 0000280209C229D2216EF6A5F4E030010A8D086AD3C204FC6EE0E46501E030010A8D08 -> 2CE703C0000E0000 -> -> -> My code: -> -> my $ref = undef; -> my $sth = $dbh->prepare('BEGIN ? := getReference(); END;'); -> $sth->bind_param_inout(1, \$ref, 128, SQL_REF ); -> $sth->execute(); -> -> yields: -> -> PLS-00382: expression is of wrong type -> -> -> Even fetching a reference does not work: -> -> my $sth = $dbh->prepare('SELECT getReference() FROM DUAL'); -> $sth->execute(); -> ($ref) = $sth->fetchrow_array(); -> -> yields undef in $ref. -> -> I'd very much appreciate your help. -> cheers, -> Hendrik - - - - diff --git a/err_unsorted/err_refcsr_rowcache.msg b/err_unsorted/err_refcsr_rowcache.msg deleted file mode 100644 index 5101d2ae..00000000 --- a/err_unsorted/err_refcsr_rowcache.msg +++ /dev/null @@ -1,85 +0,0 @@ -From dbi-users-bounce@isc.org Tue May 16 22:53:12 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id WAA29547; Tue, 16 May 2000 22:53:11 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <04730-2@oink>; Sat, 16 May 1970 22:51:48 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 958512876:10:15786:0; Tue, 16 May 2000 21:34:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1122388; 16 May 2000 21:33 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 661E53EC8; - Tue, 16 May 2000 14:33:38 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Tue, 16 May 2000 14:28:31 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id 7192F3E20 - for ; - Tue, 16 May 2000 14:28:27 -0700 (PDT) -Received: from anchor-post-34.mail.demon.net (anchor-post-34.mail.demon.net [194.217.242.92]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id OAA27204 - for ; - Tue, 16 May 2000 14:28:26 -0700 (PDT) env-from (Tim.Bunce@ig.co.uk) -Received: from ignite.demon.co.uk ([158.152.8.99] helo=oink) - by anchor-post-34.mail.demon.net with smtp (Exim 2.12 #1) - id 12rot7-000Mp4-0Y; Tue, 16 May 2000 22:28:25 +0100 -Received: from toad by oink with SMTP (PP) id <04650-0@oink>; - Sat, 16 May 1970 22:23:55 +0100 -Received: by toad.ig.co.uk (SMI-8.6/SMI-SVR4) id WAA29289; - Tue, 16 May 2000 22:23:50 +0100 -Date: Tue, 16 May 2000 22:23:50 +0100 -From: Tim Bunce -To: peter_dev@talk21.com -Cc: dbi-users@isc.org -Subject: Re: Oracle Stored Procs take longer than embedded SQL -Message-ID: <20000516222350.F28435@ig.co.uk> -References: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs>; from peter_dev@talk21.com on Tue, May 16, 2000 at 06:48:22PM +0100 -Organization: Paul Ingram Group, Software Systems, +44 1 483 862800 -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 1372 -Lines: 30 - -On Tue, May 16, 2000 at 06:48:22PM +0100, peter_dev@talk21.com wrote: -> I have a problem with the fetching of data from an Oracle Ref Cursor taking longer than the same query in Embeded SQL. -> -> $ get_sp.pl -> Fetched in 0.00774896144866943 seconds -> Completed in 0.106827020645142 seconds -> -> $ get_sql.pl -> Fetched in 0.00138604640960693 seconds -> Completed in 0.380790948867798 seconds -> -> In this example (Using the SCOTT/TIGER tables), while the Stored Procedure completed first, the actual fetch of the data took considerably longer. In a real situation (e.g. bigger tables ), this is easily the longest part of the task and causes the overall execution time to increase hugely. -> -> Any Help would be appreciated -> thanks - -Possibly related to the lack of a row cache on that statement handle. -You, or some kind volunteer, could probably hack that in without too -much work. - -Tim. - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_unsorted/err_refcsr_slow.msg b/err_unsorted/err_refcsr_slow.msg deleted file mode 100644 index 790d267d..00000000 --- a/err_unsorted/err_refcsr_slow.msg +++ /dev/null @@ -1,347 +0,0 @@ -From dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org Mon Apr 29 23:12:51 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TMCpR17212 - for ; Mon, 29 Apr 2002 23:12:51 +0100 (BST) - (envelope-from dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 29 Apr 2002 23:12:51 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020117986:10:17770:92; Mon, 29 Apr 2002 22:06:26 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1017591; 29 Apr 2002 22:06 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id 975037274A - for ; Mon, 29 Apr 2002 18:01:37 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by wormwood.pobox.com (Postfix) with SMTP id ED2897273F - for ; Mon, 29 Apr 2002 18:01:34 -0400 (EDT) -Received: (qmail 70462 invoked by uid 1005); 29 Apr 2002 21:59:33 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 20335 invoked by uid 76); 29 Apr 2002 20:18:55 -0000 -Message-ID: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Date: Mon, 29 Apr 2002 13:18:53 -0700 (PDT) -From: Calin Medianu -Reply-To: cmedianu@sfu.ca -Subject: DBD::Oracle Slow cursors -To: dbi-users@perl.org -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 568 -Lines: 21 - -Hello, - -I did the following. Wrote a perl script that retreves -data via a straight select from the database. Then I -wrote a stored procedure returning a ref cursor open -on the same select statement and retrieved the data as -well. Using the REF CURSOR/ sotred procedure was about -3 time slower, that is 40 seconds instead of around -10. - -Is this normal? Is this a problem with oracle or with -DBD::Oracle? - -Thanks, - -Calin Medianu - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org Tue Apr 30 00:06:36 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TN6aR17980 - for ; Tue, 30 Apr 2002 00:06:36 +0100 (BST) - (envelope-from dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 00:06:36 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020119533:20:05733:4; Mon, 29 Apr 2002 22:32:13 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2005393; 29 Apr 2002 22:32 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 4E6B73E6BF - for ; Mon, 29 Apr 2002 18:32:00 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-1.pobox.com (Postfix) with SMTP id BF79C3E6A0 - for ; Mon, 29 Apr 2002 18:31:59 -0400 (EDT) -Received: (qmail 87860 invoked by uid 1005); 29 Apr 2002 22:31:59 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 87844 invoked by uid 76); 29 Apr 2002 22:31:58 -0000 -Received: from mail01.svc.cra.dublin.eircom.net (HELO mail01.svc.cra.dublin.eircom.net) (159.134.118.17) - by onion.perl.org (qpsmtpd/0.07) with SMTP; Mon Apr 29 22:31:58 2002 -0000 -Received: (qmail 21911 messnum 119827 invoked from network[159.134.167.97/p865.as1.limerick1.eircom.net]); 29 Apr 2002 22:31:29 -0000 -Received: from p865.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.97) - by mail01.svc.cra.dublin.eircom.net (qp 21911) with SMTP; 29 Apr 2002 22:31:29 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g3TMVcR17579; - Mon, 29 Apr 2002 23:31:38 +0100 (BST) - (envelope-from timbo) -Date: Mon, 29 Apr 2002 23:31:38 +0100 -From: Tim Bunce -To: cmedianu@sfu.ca -Cc: dbi-users@perl.org -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020429233138.E16831@dansat.data-plan.com> -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020429201853.52283.qmail@web10007.mail.yahoo.com>; from calinm@yahoo.com on Mon, Apr 29, 2002 at 01:18:53PM -0700 -Content-Length: 651 -Lines: 20 - -On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> Hello, -> -> I did the following. Wrote a perl script that retreves -> data via a straight select from the database. Then I -> wrote a stored procedure returning a ref cursor open -> on the same select statement and retrieved the data as -> well. Using the REF CURSOR/ sotred procedure was about -> 3 time slower, that is 40 seconds instead of around -> 10. -> -> Is this normal? Is this a problem with oracle or with -> DBD::Oracle? - -DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. - -Get a level 3 trace and look for the "dbd_describe'd" line for the -ref cursor. - -Tim. - -From calinm@yahoo.com Tue Apr 30 22:02:56 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL2tR26878 - for ; Tue, 30 Apr 2002 22:02:55 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:02:55 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020198219:10:21718:114; Tue, 30 Apr 2002 20:23:39 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101732; 30 Apr 2002 20:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C6B4A2BFB4 - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10004.mail.yahoo.com (web10004.mail.yahoo.com [216.136.130.40]) - by dolly1.pobox.com (Postfix) with SMTP id 527BD2BF3D - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Message-ID: <20020430202321.54825.qmail@web10004.mail.yahoo.com> -Received: from [213.157.171.169] by web10004.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 13:23:20 PDT -Date: Tue, 30 Apr 2002 13:23:20 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -Cc: dbi-users@perl.org -In-Reply-To: <20020430140517.P16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 425 -Lines: 18 - -I "Solved" the problem. For Now.. I did -perl Makefile.PL -8 - -hoping that the buggy code would be recently added, -and it was. Now both the select and the cursor return -the data at the same speed, meaning fast.. - -Am I am missing much by not using the code for Oracle -8? - -Thanks, - -Calin - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From timbo@dansat.data-plan.com Wed May 1 16:49:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g41FnsR33994 - for ; Wed, 1 May 2002 16:49:54 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 May 2002 16:49:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020265865:20:10671:66; Wed, 01 May 2002 15:11:05 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-2.mail.demon.net - id aa2122069; 1 May 2002 15:10 GMT -Received: from cali-3.pobox.com (cali-3.pobox.com [64.71.166.116]) - by silk.pobox.com (Postfix) with ESMTP id F29CC3FDF2 - for ; Wed, 1 May 2002 11:09:52 -0400 (EDT) -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id E3A943E689 - for ; Wed, 1 May 2002 10:57:15 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id D1F523E688 - for ; Wed, 1 May 2002 10:57:14 -0400 (EDT) -Received: (qmail 96042 messnum 564683 invoked from network[159.134.166.63/p575.as1.limerick1.eircom.net]); 1 May 2002 14:57:13 -0000 -Received: from p575.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.63) - by mail03.svc.cra.dublin.eircom.net (qp 96042) with SMTP; 1 May 2002 14:57:13 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g41EvIh33626; - Wed, 1 May 2002 15:57:18 +0100 (BST) - (envelope-from timbo) -Date: Wed, 1 May 2002 15:57:18 +0100 -From: Tim Bunce -To: Calin Medianu -Cc: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020501155718.S16831@dansat.data-plan.com> -References: <20020430151126.Q16831@dansat.data-plan.com> <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020430183429.33340.qmail@web10005.mail.yahoo.com>; from calinm@yahoo.com on Tue, Apr 30, 2002 at 11:34:29AM -0700 -Status: RO -Content-Length: 3111 -Lines: 111 - -Thanks. I'll take a look when I get to DBD::Oracle again. - -I think the last row of that table applies and it doesn't refer to OCIBindObject(): - REF CURSOR variables - SQLT_RSET - Allocate a statement handle, OCIStmt, and then bind its address - (OCIStmt **) using the SQLT_RSET datatype. -Note that SQLT_REF isn't the same as SQLT_RSET. - -You could always try patching it yourself! - -Tim. - - -On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin Medianu wrote: -> It says here: -> http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> -> that 2 calls are neede to bind a ref , the second is -> to OCIBindObject() which I don't see in dbdimp.c. -> -> Could this be a reason? -> -> Cheers, -> -> Calin -> -> --- Tim Bunce wrote: -> > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > Medianu wrote: -> > > Me again with the slow cursors. -> > > -> > > I modified both queries to only return 10 rows. -> > > I ran a sniffer (ethereal) on the NIC. It is -> > pretty cool, it also decodes TNS. -> > > -> > > when I am using the SQL, it works like this, there -> > are about 7 packets -> > > received by my workstation to set up the session, -> > then all 10 rows are in the -> > > same packet, then there is another packet probably -> > saying goodbye. -> > > -> > > When I am using the REF cursor, each row comes in -> > it's own TNS packet, that -> > > is why it is so slow! -> > > -> > > Any idea how to fix it? -> > -> > Do a level 9 trace to get a log of the OCI calls and -> > confirm that -> > the fragment I posted is being called (may be -> > helpful to also -> > add an extra print statement into that code since -> > parsing the -> > OCI trace can be painful). -> > -> > Assuming the code is being called then as far as I -> > can see the code is -> > doing the right thing and it's probably an Oracle -> > OCI issue. -> > -> > You'd need to talk to Oracle support. No need to -> > mention perl etc. -> > Just talk about your OCI application and provide the -> > OCI call trace. -> > -> > Let me know what you find out! -> > -> > Tim. -> > -> > > thanks a lot, -> > > -> > > Calin -> > > -> > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> > Medianu wrote: -> > > > > Hello, -> > > > > -> > > > > I did the following. Wrote a perl script that -> > retreves -> > > > > data via a straight select from the database. -> > Then I -> > > > > wrote a stored procedure returning a ref -> > cursor open -> > > > > on the same select statement and retrieved the -> > data as -> > > > > well. Using the REF CURSOR/ sotred procedure -> > was about -> > > > > 3 time slower, that is 40 seconds instead of -> > around -> > > > > 10. -> > > > > -> > > > > Is this normal? Is this a problem with oracle -> > or with -> > > > > DBD::Oracle? -> > > > -> > > > DBD::Oracle. It probably isn't setting up a row -> > cache for the ref cursor. -> > > > -> > > > Get a level 3 trace and look for the -> > "dbd_describe'd" line for the -> > > > ref cursor. -> > > > -> > > > Tim. -> -> -> __________________________________________________ -> Do You Yahoo!? -> Yahoo! Health - your guide to health and wellness -> http://health.yahoo.com - diff --git a/err_unsorted/err_slowcsr.msg b/err_unsorted/err_slowcsr.msg deleted file mode 100644 index 80c43350..00000000 --- a/err_unsorted/err_slowcsr.msg +++ /dev/null @@ -1,316 +0,0 @@ -From calinm@yahoo.com Tue Apr 30 22:03:11 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL3AR27018 - for ; Tue, 30 Apr 2002 22:03:10 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:03:10 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020196981:10:23493:39; Tue, 30 Apr 2002 20:03:01 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-1.mail.demon.net - id aa1108477; 30 Apr 2002 20:02 GMT -Received: from dolly1.pobox.com (dolly1.pobox.com [207.106.49.22]) - by silk.pobox.com (Postfix) with ESMTP id 915563FCE8 - for ; Tue, 30 Apr 2002 14:35:38 -0400 (EDT) -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 343702BFDD - for ; Tue, 30 Apr 2002 14:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10005.mail.yahoo.com (web10005.mail.yahoo.com [216.136.130.41]) - by dolly1.pobox.com (Postfix) with SMTP id 6AA822BFA3 - for ; Tue, 30 Apr 2002 14:34:37 -0400 (EDT) -Message-ID: <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Received: from [213.157.171.169] by web10005.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 11:34:29 PDT -Date: Tue, 30 Apr 2002 11:34:29 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020430151126.Q16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 2457 -Lines: 96 - -It says here: -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 - -that 2 calls are neede to bind a ref , the second is -to OCIBindObject() which I don't see in dbdimp.c. - -Could this be a reason? - -Cheers, - -Calin - ---- Tim Bunce wrote: -> On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> Medianu wrote: -> > Me again with the slow cursors. -> > -> > I modified both queries to only return 10 rows. -> > I ran a sniffer (ethereal) on the NIC. It is -> pretty cool, it also decodes TNS. -> > -> > when I am using the SQL, it works like this, there -> are about 7 packets -> > received by my workstation to set up the session, -> then all 10 rows are in the -> > same packet, then there is another packet probably -> saying goodbye. -> > -> > When I am using the REF cursor, each row comes in -> it's own TNS packet, that -> > is why it is so slow! -> > -> > Any idea how to fix it? -> -> Do a level 9 trace to get a log of the OCI calls and -> confirm that -> the fragment I posted is being called (may be -> helpful to also -> add an extra print statement into that code since -> parsing the -> OCI trace can be painful). -> -> Assuming the code is being called then as far as I -> can see the code is -> doing the right thing and it's probably an Oracle -> OCI issue. -> -> You'd need to talk to Oracle support. No need to -> mention perl etc. -> Just talk about your OCI application and provide the -> OCI call trace. -> -> Let me know what you find out! -> -> Tim. -> -> > thanks a lot, -> > -> > Calin -> > -> > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> Medianu wrote: -> > > > Hello, -> > > > -> > > > I did the following. Wrote a perl script that -> retreves -> > > > data via a straight select from the database. -> Then I -> > > > wrote a stored procedure returning a ref -> cursor open -> > > > on the same select statement and retrieved the -> data as -> > > > well. Using the REF CURSOR/ sotred procedure -> was about -> > > > 3 time slower, that is 40 seconds instead of -> around -> > > > 10. -> > > > -> > > > Is this normal? Is this a problem with oracle -> or with -> > > > DBD::Oracle? -> > > -> > > DBD::Oracle. It probably isn't setting up a row -> cache for the ref cursor. -> > > -> > > Get a level 3 trace and look for the -> "dbd_describe'd" line for the -> > > ref cursor. -> > > -> > > Tim. - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From calinm@yahoo.com Fri May 3 13:48:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g43Cm5R50489 - for ; Fri, 3 May 2002 13:48:05 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 03 May 2002 13:48:05 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020429421:10:02019:143; Fri, 03 May 2002 12:37:01 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1123562; 3 May 2002 12:36 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id D7BD1725A1 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10008.mail.yahoo.com (web10008.mail.yahoo.com [216.136.130.44]) - by wormwood.pobox.com (Postfix) with SMTP id 3088772674 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Message-ID: <20020503123640.19648.qmail@web10008.mail.yahoo.com> -Received: from [213.157.171.169] by web10008.mail.yahoo.com via HTTP; Fri, 03 May 2002 05:36:40 PDT -Date: Fri, 3 May 2002 05:36:40 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020501155718.S16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -Content-Length: 3619 -Lines: 150 - -Sure, - -I'll give it a try next week. - -Cheers, - -Calin ---- Tim Bunce wrote: -> Thanks. I'll take a look when I get to DBD::Oracle -> again. -> -> I think the last row of that table applies and it -> doesn't refer to OCIBindObject(): -> REF CURSOR variables -> SQLT_RSET -> Allocate a statement handle, OCIStmt, and then -> bind its address -> (OCIStmt **) using the SQLT_RSET datatype. -> Note that SQLT_REF isn't the same as SQLT_RSET. -> -> You could always try patching it yourself! -> -> Tim. -> -> -> On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin -> Medianu wrote: -> > It says here: -> > -> -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> > -> > that 2 calls are neede to bind a ref , the second -> is -> > to OCIBindObject() which I don't see in dbdimp.c. -> > -> > Could this be a reason? -> > -> > Cheers, -> > -> > Calin -> > -> > --- Tim Bunce wrote: -> > > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > > Medianu wrote: -> > > > Me again with the slow cursors. -> > > > -> > > > I modified both queries to only return 10 -> rows. -> > > > I ran a sniffer (ethereal) on the NIC. It is -> > > pretty cool, it also decodes TNS. -> > > > -> > > > when I am using the SQL, it works like this, -> there -> > > are about 7 packets -> > > > received by my workstation to set up the -> session, -> > > then all 10 rows are in the -> > > > same packet, then there is another packet -> probably -> > > saying goodbye. -> > > > -> > > > When I am using the REF cursor, each row comes -> in -> > > it's own TNS packet, that -> > > > is why it is so slow! -> > > > -> > > > Any idea how to fix it? -> > > -> > > Do a level 9 trace to get a log of the OCI calls -> and -> > > confirm that -> > > the fragment I posted is being called (may be -> > > helpful to also -> > > add an extra print statement into that code -> since -> > > parsing the -> > > OCI trace can be painful). -> > > -> > > Assuming the code is being called then as far as -> I -> > > can see the code is -> > > doing the right thing and it's probably an -> Oracle -> > > OCI issue. -> > > -> > > You'd need to talk to Oracle support. No need to -> > > mention perl etc. -> > > Just talk about your OCI application and provide -> the -> > > OCI call trace. -> > > -> > > Let me know what you find out! -> > > -> > > Tim. -> > > -> > > > thanks a lot, -> > > > -> > > > Calin -> > > > -> > > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, -> Calin -> > > Medianu wrote: -> > > > > > Hello, -> > > > > > -> > > > > > I did the following. Wrote a perl script -> that -> > > retreves -> > > > > > data via a straight select from the -> database. -> > > Then I -> > > > > > wrote a stored procedure returning a ref -> > > cursor open -> > > > > > on the same select statement and retrieved -> the -> > > data as -> > > > > > well. Using the REF CURSOR/ sotred -> procedure -> > > was about -> > > > > > 3 time slower, that is 40 seconds instead -> of -> > > around -> > > > > > 10. -> > > > > > -> > > > > > Is this normal? Is this a problem with -> oracle -> > > or with -> > > > > > DBD::Oracle? -> > > > > -> > > > > DBD::Oracle. It probably isn't setting up a -> row -> > > cache for the ref cursor. -> > > > > -> > > > > Get a level 3 trace and look for the -> > > "dbd_describe'd" line for the -> > > > > ref cursor. -> > > > > -> > > > > Tim. -> > -> > -> > __________________________________________________ -> > Do You Yahoo!? -> > Yahoo! Health - your guide to health and wellness -> > http://health.yahoo.com - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - diff --git a/err_unsorted/err_svrparse.msg b/err_unsorted/err_svrparse.msg deleted file mode 100644 index 16886ca8..00000000 --- a/err_unsorted/err_svrparse.msg +++ /dev/null @@ -1,4717 +0,0 @@ -From cary.millsap@hotsos.com Thu Sep 12 23:38:20 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8CMbgC02618 - for ; Thu, 12 Sep 2002 23:38:03 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 12 Sep 2002 23:38:03 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031869308:20:16258:30; Thu, 12 Sep 2002 22:21:48 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2108888; 12 Sep 2002 22:21 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id A32132F05C9 - for ; Thu, 12 Sep 2002 18:21:34 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-3.pobox.com (Postfix) with ESMTP id D71F62F056D - for ; Thu, 12 Sep 2002 18:21:31 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8CMLQn17849; - Thu, 12 Sep 2002 17:21:26 -0500 -From: "Cary Millsap" -To: -Subject: -Date: Thu, 12 Sep 2002 17:21:17 -0500 -Message-ID: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_016A_01C25A80.D1527130" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 64884 -Lines: 2025 - -This is a multi-part message in MIME format. - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: multipart/alternative; - boundary="----=_NextPart_001_016B_01C25A80.D1557E70" - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -How are you doing? I hope you've had a good two years since I saw you on -the Oracle Geek Cruise event. - - - -I've been working on a project this year to construct a book about -optimizing Oracle response time. In my research, I've discovered -something about the DBI that I didn't expect: it executes two Oracle -parse calls for every one that I would expect an efficient DBI layer to -make. I've included my Perl source (below), the Oracle level-12 trace -data that shows the sequence of calls it's receiving from the Perl -application (below), a level-9 DBI trace from the application -(attached), and our version information (below). - - - -The reason I'm bringing this to your attention in this way is that I'm -relying pretty heavily upon Perl for performance measurement tools, -examples, and simulators in the text. I love the language and I want for -the book to be an encouragement for more people to use Perl. However, -this extra-parse behavior is one of the things that the book highlights -as an important scalability barrier (some other tools do it too, -unfortunately). Of course, this is a speed bump on the road to my goal -of helping to promote Perl. - - - -I was hoping that by showing you this specific data, you could make the -problem go away. - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - -Listing [listing.sqltrace.pl]: a simple application that executes a -database query - -#!/usr/bin/perl - - - - - -# $Header: /home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 21:10:25 -cvm Exp $ - -# Cary Millsap (cary.millsap@hotsos.com) - - - - - -use strict; - -use warnings; - -use DBI; - -use DBD::Oracle; - -use Getopt::Long; - -use Term::ReadKey; - - - - - -my $sth; # Oracle statement handle - -my $hostname = ""; - -my $username = "/"; - -my $password = ""; - -my $logfile = "ex1.log"; - -my %attr = ( - - RaiseError => 1, - - AutoCommit => 0, - -); - -my %opt = ( - - pause => 0, - -); - - - - - -# Get command line options and arguments. - -GetOptions( - - "pause" => \$opt{pause}, - -); - -my $key = 37; # default query value - -$key = $ARGV[0] if $ARGV[0]; - - - - - -# Connect to Oracle. - -my $dbh = DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr); - -$dbh->trace(9, $logfile); - - - - - -# Activate tracing. - -$sth = $dbh->prepare(q(alter session set events '10046 trace name -context forever, level 12')); - -$sth->execute; - - - - - -# Allow the user to find the Oracle session and activate OS diagnostic - -# tools like strace(1) or lsof(8). - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Execute the query to trace. - -$sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -$sth->execute($key); - - - - - -# Print output header. - -my @cdefs = qw(%8d %8d %32s); # column definitions - -my @hdefs = qw(Key Fkey Value); # column headings - -my $bformat = join(" ", @cdefs) . "\n"; - -my $hformat; ($hformat = $bformat) =~ s/%(\d*)\S+/%$1s/g; - -printf $hformat, @hdefs; - -printf $hformat, do { my @h; push @h, "-" x (/(\d+)/?$1:10) for @cdefs; -@h }; - - - - - -# Print query results. - -for my $row (@{$sth->fetchall_arrayref}) { - - printf $bformat, @$row; - -} - - - - - -# Allow the user to do final OS diagnostic stuff. - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Disconnect from Oracle. - -$dbh->disconnect; - - - - - -Listing [listing:sqltrace.trc]: raw SQL trace output for an execution of -our program - -/usr/local/oracle/admin/V816/udump/ora_17349.trc - -Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production - -With the Partitioning option - -JServer Release 8.1.6.0.0 - Production - -ORACLE_HOME = /usr/local/oracle/product/8.1.6 - -System name: Linux - -Node name: www.hotsos.com - -Release: 2.2.16-22enterprise - -Version: #1 SMP Tue Aug 22 16:29:32 EDT 2000 - -Machine: i686 - -Instance name: V816 - -Redo thread mounted by this instance: 1 - -Oracle process number: 8 - -Unix process pid: 17349, image: oracle@www.hotsos.com (TNS V1-V3) - - - -*** SESSION ID:(7.9) 2002-09-12 16:14:01.582 - -===================== - -PARSING IN CURSOR #1 len=69 dep=0 uid=12 oct=42 lid=12 tim=107309054 -hv=1509700594 ad='54af5e14' - -alter session set events '10046 trace name context forever, level 12' - -END OF STMT - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107309054 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -*** 2002-09-12 16:14:31.226 - -WAIT #1: nam='SQL*Net message from client' ela= 2964 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -WAIT #2: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #2: nam='SQL*Net message from client' ela= 0 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -BINDS #1: - - bind 0: dty=1 mxl=32(04) mal=00 scl=00 pre=00 oacflg=25 oacfl2=10 -size=32 offset=0 - - bfp=0940e7f0 bln=32 avl=04 flg=05 - - value="8542" - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #1: nam='file open' ela= 0 p1=0 p2=0 p3=0 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6671 p3=1 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6678 p3=1 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - -*** 2002-09-12 16:14:56.200 - -WAIT #1: nam='SQL*Net message from client' ela= 2496 p1=1650815232 p2=1 -p3=0 - -XCTEND rlbk=0, rd_only=1 - -STAT #1 id=1 cnt=1 pid=0 pos=0 obj=5156 op='TABLE ACCESS BY INDEX ROWID -T ' - -STAT #1 id=2 cnt=2 pid=1 pos=1 obj=5157 op='INDEX UNIQUE SCAN ' - - - - - -$ perl -V - -Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration: - - Platform: - - osname=linux, osvers=2.2.5-22smp, archname=i386-linux - - uname='linux porky.devel.redhat.com 2.2.5-22smp #1 smp wed jun 2 -09:11:51 edt 1999 i686 unknown ' - - config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -Dcc=gcc --Dcccdlflags=-fPIC -Dinstallprefix=/usr -Dprefix=/usr --Darchname=i386-linux -Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm --Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Uuselargefiles' - - hint=recommended, useposix=true, d_sigaction=define - - usethreads=undef use5005threads=undef useithreads=undef -usemultiplicity=undef - - useperlio=undef d_sfio=undef uselargefiles=undef - - use64bitint=undef use64bitall=undef uselongdouble=undef -usesocks=undef - - Compiler: - - cc='gcc', optimize='-O2 -march=i386 -mcpu=i686', gccversion=2.96 -20000731 (experimental) - - cppflags='-fno-strict-aliasing' - - ccflags ='-fno-strict-aliasing' - - stdchar='char', d_stdstdio=define, usevfork=false - - intsize=4, longsize=4, ptrsize=4, doublesize=8 - - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', -lseeksize=4 - - alignbytes=4, usemymalloc=n, prototype=define - - Linker and Libraries: - - ld='gcc', ldflags =' -L/usr/local/lib' - - libpth=/usr/local/lib /lib /usr/lib - - libs=-lnsl -ldl -lm -lc -lcrypt - - libc=/lib/libc-2.1.92.so, so=so, useshrplib=false, libperl=libperl.a - - Dynamic Linking: - - dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' - - cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' - - - - - -Characteristics of this binary (from libperl): - - Compile-time options: - - Built under linux - - Compiled at Aug 7 2000 10:59:51 - - @INC: - - /usr/lib/perl5/5.6.0/i386-linux - - /usr/lib/perl5/5.6.0 - - /usr/lib/perl5/site_perl/5.6.0/i386-linux - - /usr/lib/perl5/site_perl/5.6.0 - - /usr/lib/perl5/site_perl - - . - - - - - -Other site information - -- Redhat Linux 7.0 - -- Oracle 8.1.6.1.0 - -- DBD-Oracle 1.12 - -- DBI 1.30 - - - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

How are you doing? I hope you’ve had a good two = -years -since I saw you on the Oracle Geek Cruise event.

- -

 

- -

I’ve been working on a project this year to = -construct -a book about optimizing Oracle response time. In my research, I’ve -discovered something about the DBI that I didn’t expect: it = -executes two -Oracle parse calls for every one that I would expect an efficient DBI = -layer to -make. I’ve included my Perl source (below), the Oracle level-12 = -trace -data that shows the sequence of calls it’s receiving from the Perl = -application -(below), a level-9 DBI trace from the application (attached), and our = -version information -(below).

- -

 

- -

The reason I’m bringing this to your attention = -in this -way is that I’m relying pretty heavily upon Perl for performance -measurement tools, examples, and simulators in the text. I love the = -language -and I want for the book to be an encouragement for more people to use = -Perl. -However, this extra-parse behavior is one of the things that the book = -highlights -as an important scalability barrier (some other tools do it too, = -unfortunately). -Of course, this is a speed bump on the road to my goal of helping to = -promote Perl.

- -

 

- -

I was hoping that by showing you this specific data, = -you -could make the problem go away.

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -
- -

Listing [listing.sqltrace.pl]: a simple = -application that -executes a database query

- -
- -
- -

#!/usr/bin/perl

- -

- -

- -

 

- -

 

- -

# = -$Header: -/home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 = -21:10:25 cvm Exp $

- -

- -

# = -Cary Millsap (cary.millsap@hotsos.com)

- -

- -

 

- -

 

- -

use = -strict;

- -

- -

use = -warnings;

- -

- -

use = -DBI;

- -

- -

use = -DBD::Oracle;

- -

- -

use = -Getopt::Long;

- -

- -

use = -Term::ReadKey;

- -

- -

 

- -

 

- -

my -$sth;           &n= -bsp;        -# Oracle statement handle

- -

- -

my = -$hostname =3D -"";

- -

- -

my = -$username =3D -"/";

- -

- -

my = -$password =3D -"";

- -

- -

my = -$logfile  -=3D "ex1.log";

- -

- -

my = -%attr =3D (

- -

- -

    -RaiseError =3D> 1,

- -

- -

    -AutoCommit =3D> 0,

- -

- -

);

- -

- -

my = -%opt =3D (

- -

- -

    -pause   =3D> 0,

- -

- -

);

- -

- -

 

- -

 

- -

# Get = -command line -options and arguments.

- -

- -

GetOptions(

- -

- -

    -"pause" =3D> \$opt{pause},

- -

- -

);

- -

- -

my = -$key =3D -37;           &nbs= -p;  - # default query value

- -

- -

$key = -=3D $ARGV[0] if -$ARGV[0];

- -

- -

 

- -

 

- -

# = -Connect to -Oracle.

- -

- -

my = -$dbh =3D -DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr);

- -

- -

$dbh->trace(9, -$logfile);

- -

- -

 

- -

 

- -

# = -Activate -tracing.

- -

- -

$sth = -=3D -$dbh->prepare(q(alter session set events '10046 trace name context = -forever, -level 12'));

- -

- -

$sth->execute;

- -

- -

 

- -

 

- -

# = -Allow the user -to find the Oracle session and activate OS diagnostic

- -

- -

# = -tools like -strace(1) or lsof(8).

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Execute the -query to trace.

- -

- -

$sth = -=3D -$dbh->prepare(q(select key, fkey, value from t where = -key=3D?));

- -

- -

$sth->execute($key);

- -

- -

 

- -

 

- -

# = -Print output -header.

- -

- -

my = -@cdefs =3D qw(%8d -%8d %32s);   # column definitions

- -

- -

my = -@hdefs =3D qw(Key -Fkey Value); # column headings

- -

- -

my = -$bformat =3D -join("  ", @cdefs) . "\n";

- -

- -

my = -$hformat; -($hformat =3D $bformat) =3D~ s/%(\d*)\S+/%$1s/g;

- -

- -

printf $hformat, -@hdefs;

- -

- -

printf $hformat, -do { my @h; push @h, "-" x (/(\d+)/?$1:10) for = -@cdefs; @h };

- -

- -

 

- -

 

- -

# = -Print query -results.

- -

- -

for = -my $row -(@{$sth->fetchall_arrayref}) {

- -

- -

    -printf $bformat, @$row;

- -

- -

}

- -

- -

- -

 

- -

 

- -

# = -Allow the user -to do final OS diagnostic stuff.

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Disconnect from -Oracle.

- -

- -

$dbh->disconnect;

- -
- -

 

- -

 

- -
- -

Listing [listing:sqltrace.trc]: raw SQL trace = -output for -an execution of our program

- -
- -
- -

/usr/local/oracle/admin/V816/udump/ora_17349.tr= -c

- -

Oracle8i Enterprise -Edition Release 8.1.6.1.0 - Production

- -

With = -the -Partitioning option

- -

JServer Release -8.1.6.0.0 - Production

- -

ORACLE_HOME =3D -/usr/local/oracle/product/8.1.6

- -

System -name:        Linux

- -

Node name:  = -www.hotsos.com

- -

Release:    = -2.2.16-22enterprise

- -

Version:    #1 -SMP Tue Aug 22 16:29:32 EDT 2000

- -

Machine:    = -i686

- -

Instance name: -V816

- -

Redo = -thread -mounted by this instance: 1

- -

Oracle process -number: 8

- -

Unix = -process pid: -17349, image: oracle@www.hotsos.com (TNS V1-V3)

- -

 

- -

*** = -SESSION -ID:(7.9) 2002-09-12 16:14:01.582

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D69 dep=3D0 uid=3D12 oct=3D42 lid=3D12 = -tim=3D107309054 hv=3D1509700594 -ad=3D'54af5e14'

- -

alter = -session set -events '10046 trace name context forever, level 12'

- -

END = -OF STMT

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -309054

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

*** = -2002-09-12 -16:14:31.226

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2964 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#2 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312018 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

WAIT = -#2: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#2: -nam=3D'SQL*Net message from client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312019 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

BINDS = -#1:

- -

 bind 0: -dty=3D1 mxl=3D32(04) mal=3D00 scl=3D00 pre=3D00 oacflg=3D25 oacfl2=3D10 = -size=3D32 offset=3D0

- -

   bfp=3D0940e7f0 bln=3D32 avl=3D04 flg=3D05

- -

   -value=3D"8542"

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#1: nam=3D'file -open' ela=3D 0 p1=3D0 p2=3D0 p3=3D0

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6671 p3=3D1

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6678 p3=3D1

- -

FETCH -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

*** = -2002-09-12 -16:14:56.200

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2496 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

XCTEND rlbk=3D0, -rd_only=3D1

- -

STAT = -#1 id=3D1 cnt=3D1 -pid=3D0 pos=3D0 obj=3D5156 op=3D'TABLE ACCESS BY INDEX ROWID T = -'

- -

STAT = -#1 id=3D2 cnt=3D2 -pid=3D1 pos=3D1 obj=3D5157 op=3D'INDEX UNIQUE SCAN '

- -
- -

 

- -

 

- -

$ perl -V

- -

Summary of my perl5 (revision 5.0 version 6 subversion 0) = -configuration:

- -

  Platform:

- -

    osname=3Dlinux, osvers=3D2.2.5-22smp, = -archname=3Di386-linux

- -

    uname=3D'linux porky.devel.redhat.com = -2.2.5-22smp #1 smp -wed jun 2 09:11:51 edt 1999 i686 unknown '

- -

    config_args=3D'-des -Doptimize=3D-O2 = --march=3Di386 -mcpu=3Di686 --Dcc=3Dgcc -Dcccdlflags=3D-fPIC -Dinstallprefix=3D/usr -Dprefix=3D/usr = --Darchname=3Di386-linux --Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm -Di_gdbm -Di_shadow = --Di_syslog -Dman3ext=3D3pm -Uuselargefiles'

- -

    hint=3Drecommended, useposix=3Dtrue, = -d_sigaction=3Ddefine

- -

    usethreads=3Dundef use5005threads=3Dundef = -useithreads=3Dundef -usemultiplicity=3Dundef

- -

    useperlio=3Dundef d_sfio=3Dundef = -uselargefiles=3Dundef

- -

    use64bitint=3Dundef use64bitall=3Dundef = -uselongdouble=3Dundef -usesocks=3Dundef

- -

  Compiler:

- -

    cc=3D'gcc', optimize=3D'-O2 -march=3Di386 = --mcpu=3Di686', gccversion=3D2.96 -20000731 (experimental)

- -

    = -cppflags=3D'-fno-strict-aliasing'

- -

    ccflags = -=3D'-fno-strict-aliasing'

- -

    stdchar=3D'char', d_stdstdio=3Ddefine, = -usevfork=3Dfalse

- -

    intsize=3D4, longsize=3D4, ptrsize=3D4, = -doublesize=3D8

- -

    d_longlong=3Ddefine, longlongsize=3D8, = -d_longdbl=3Ddefine, -longdblsize=3D12

- -

    ivtype=3D'long', ivsize=3D4, = -nvtype=3D'double', nvsize=3D8, Off_t=3D'off_t', -lseeksize=3D4

- -

    alignbytes=3D4, usemymalloc=3Dn, = -prototype=3Ddefine

- -

  Linker and Libraries:

- -

    ld=3D'gcc', ldflags =3D' = --L/usr/local/lib'

- -

    libpth=3D/usr/local/lib /lib = -/usr/lib

- -

    libs=3D-lnsl -ldl -lm -lc = --lcrypt

- -

    libc=3D/lib/libc-2.1.92.so, so=3Dso, = -useshrplib=3Dfalse, libperl=3Dlibperl.a

- -

  Dynamic Linking:

- -

    dlsrc=3Ddl_dlopen.xs, dlext=3Dso, = -d_dlsymun=3Dundef, ccdlflags=3D'-rdynamic'

- -

    cccdlflags=3D'-fPIC', lddlflags=3D'-shared = --L/usr/local/lib'

- -

 

- -

 

- -

Characteristics of this binary (from libperl): = -

- -

  Compile-time options:

- -

  Built under linux

- -

  Compiled at Aug  7 2000 10:59:51

- -

  @INC:

- -

    = -/usr/lib/perl5/5.6.0/i386-linux

- -

    /usr/lib/perl5/5.6.0

- -

    = -/usr/lib/perl5/site_perl/5.6.0/i386-linux

- -

    = -/usr/lib/perl5/site_perl/5.6.0

- -

    /usr/lib/perl5/site_perl

- -

    .

- -

 

- -

 

- -

Other site information

- -

- Redhat Linux 7.0

- -

- Oracle 8.1.6.1.0

- -

- DBD-Oracle 1.12

- -

- DBI 1.30

- -

 

- -
- - - - - -------=_NextPart_001_016B_01C25A80.D1557E70-- - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: application/octet-stream; - name="ex1.log" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="ex1.log" - - DBI::db=3DHASH(0x8235a74) trace level set to 9 in DBI 1.30-nothread=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'alter session set events '10046 trace name context forever, level 12'')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240f68)=3D>DBI::st=3DHASH(0x8240f98),= - DBD::Oracle::st, 8240f74, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= -OCIHandleAlloc(0x82465d8,0x826c948,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826bf48,0x82559ec,'alter session set events '10046 = -trace name context forever, level 12'',69,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0x826c94c,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql ALTER=0A= - dbd_describe skipped for ALTER=0A= - <- prepare=3D DBI::st=3DHASH(0x8240f68) at ex1.pl line 38=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240f68)~0x8240f98)=0A= - dbd_st_execute ALTER (out0, lob0)...=0A= -OCIStmtExecute(0x82557c4,0x826bf48,0x82559ec,1,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff654,(nil),9,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute ALTER returned (SUCCESS, rpc0, fn52, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 39=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'select key, fkey, value from t where key=3D?')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240fe0)=3D>DBI::st=3DHASH(0x8240fb0),= - DBD::Oracle::st, 8240fec, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= - dbd_preparse scanned 1 distinct placeholders=0A= -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where = -key=3D:p1',44,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql SELECT=0A= - dbd_describe SELECT (EXPLICIT, lb 80)...=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3DSUCCES= -S=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3dc,(nil),18,0x82559ec)=3DSUCC= -ESS=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d1c0,1)=3DSUCCESS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d6,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d4,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d8,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1da,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1db,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1e8,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 1: 'KEY' NO null , otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d200,2)=3DSUCCESS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d216,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d214,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d218,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d228,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 2: 'FKEY' NULLable, otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d240,3)=3DSUCCESS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d256,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d254,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d258,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d268,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 3: 'VALUE' NULLable, otype 1-> 5, dbsize 32/33, p32.s0=0A= -OCIAttrSet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3d4,4,11,0x82559ec)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d1c4,0x82559ec,1,0x826e8d0,134,5,0x826d438,= -0x826d448,0x826d458,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d204,0x82559ec,2,0x826eaf8,134,5,0x826ca28,= -0x826ca38,0x826ca48,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d244,0x82559ec,3,0x826cbb8,33,5,0x826ca58,0= -x826cbe0,0x826cbf0,0)=3DSUCCESS=0A= - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231)=0A= - <- prepare=3D DBI::st=3DHASH(0x8240fe0) at ex1.pl line 50=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240f98)~INNER)=0A= -OCIHandleFree(0x826bf48,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef at ex1.pl line 51=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240fe0)~0x8240fb0 = -'8542')=0A= - bind :p1 <=3D=3D '8542' (type 0)=0A= - bind :p1 <=3D=3D '8542' (size 4/5/0, ptype 7, otype 1)=0A= - bind :p1 <=3D=3D '8542' (size 4/4, otype 1, indp 0, at_exec 1)=0A= -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb= -6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS=0A= -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da= -090)=3DSUCCESS=0A= - bind :p1 done with ftype 1=0A= - dbd_st_execute SELECT (out0, lob0)...=0A= - in ':p1' [0,0]: len 4, ind 0=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 51=0A= - -> fetchall_arrayref for DBD::Oracle::st = -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0)=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DSUCCESS=0A= - dbih_setup_fbav for 3 fields =3D> 0x8240fbc=0A= - dbd_st_fetch 3 fields SUCCESS=0A= - 0 (rc=3D0): '8542'=0A= - 1 (rc=3D0): '8542'=0A= - 2 (rc=3D0): 'value'=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DNO_DATA=0A= - dbd_st_fetch no-more-data=0A= - <- fetchall_arrayref=3D [ ARRAY(0x82411f0) ] row1 at ex1.pl line 62=0A= - -> disconnect for DBD::Oracle::db = -(DBI::db=3DHASH(0x8235b34)~0x8235a74)=0A= -OCISessionEnd(0x82557c4,0x82559ec,0x826c384,0)=3DSUCCESS=0A= -OCIServerDetach(0x8255834,0x82559ec,0)=3DSUCCESS=0A= - <- disconnect=3D 1 at ex1.pl line 74=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240fb0)~INNER)=0A= -OCIHandleFree(0x826e4a0,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -> DESTROY for DBD::Oracle::db (DBI::db=3DHASH(0x8235a74)~INNER)=0A= -OCIHandleFree(0x826c384,OCI_HTYPE_SESSION)=3DSUCCESS=0A= -OCIHandleFree(0x8255834,OCI_HTYPE_SERVER)=3DSUCCESS=0A= -OCIHandleFree(0x82557c4,OCI_HTYPE_SVCCTX)=3DSUCCESS=0A= -OCIHandleFree(0x82559ec,OCI_HTYPE_ERROR)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -------=_NextPart_000_016A_01C25A80.D1527130-- - - -From timbo@dansat.data-plan.com Fri Sep 13 07:30:31 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6UUC04053 - for ; Fri, 13 Sep 2002 07:30:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:30:30 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031871608:20:03733:55; Thu, 12 Sep 2002 23:00:08 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id ab2122693; 12 Sep 2002 23:00 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id AE0642F0B8A - for ; Thu, 12 Sep 2002 18:58:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id 931D42F0D0A - for ; Thu, 12 Sep 2002 18:58:19 -0400 (EDT) -Received: (qmail 57270 messnum 519666 invoked from network[159.134.164.69/p69.as1.limerick1.eircom.net]); 12 Sep 2002 22:58:17 -0000 -Received: from p69.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.69) - by mail03.svc.cra.dublin.eircom.net (qp 57270) with SMTP; 12 Sep 2002 22:58:17 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8CMwEQ02798; - Thu, 12 Sep 2002 23:58:14 +0100 (BST) - (envelope-from timbo) -Date: Thu, 12 Sep 2002 23:58:14 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls -Message-ID: <20020912225814.GG539@dansat.data-plan.com> -References: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 3530 -Lines: 77 - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCESS - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 '8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCESS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - -From cary.millsap@hotsos.com Fri Sep 13 07:31:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6VsC04590 - for ; Fri, 13 Sep 2002 07:31:54 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:31:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031889643:20:09494:0; Fri, 13 Sep 2002 04:00:43 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-2.mail.demon.net - id aa2008866; 13 Sep 2002 4:00 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id C94C67264F - for ; Fri, 13 Sep 2002 00:00:07 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by wormwood.pobox.com (Postfix) with ESMTP id A821072676 - for ; Fri, 13 Sep 2002 00:00:06 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D405n19404 - for ; Thu, 12 Sep 2002 23:00:05 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 22:59:56 -0500 -Message-ID: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020912225814.GG539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4825 -Lines: 129 - -Tim, - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Thursday, September 12, 2002 5:58 PM -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you -on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer -to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make -the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I -can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect -that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - - -From timbo@dansat.data-plan.com Fri Sep 13 10:48:59 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D9mwC06022 - for ; Fri, 13 Sep 2002 10:48:58 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 10:48:58 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031907122:20:19599:21; Fri, 13 Sep 2002 08:52:02 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2129553; 13 Sep 2002 8:52 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 99E263E660 - for ; Fri, 13 Sep 2002 04:51:54 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-2.pobox.com (Postfix) with SMTP id 721613E637 - for ; Fri, 13 Sep 2002 04:51:53 -0400 (EDT) -Received: (qmail 29161 messnum 524631 invoked from network[159.134.167.5/p773.as1.limerick1.eircom.net]); 13 Sep 2002 08:51:51 -0000 -Received: from p773.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.5) - by mail03.svc.cra.dublin.eircom.net (qp 29161) with SMTP; 13 Sep 2002 08:51:51 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8D8prO05752; - Fri, 13 Sep 2002 09:51:53 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 09:51:53 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913085153.GJ539@dansat.data-plan.com> -References: <20020912225814.GG539@dansat.data-plan.com> <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 6172 -Lines: 154 - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more "official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -> key=:p1',44,1,0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - -From cary.millsap@hotsos.com Fri Sep 13 17:52:40 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DGqdC10778 - for ; Fri, 13 Sep 2002 17:52:39 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 17:52:39 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031932999:10:25604:102; Fri, 13 Sep 2002 16:03:19 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101673; 13 Sep 2002 16:03 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E4A692C078 - for ; Fri, 13 Sep 2002 12:02:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 1609E2C03F - for ; Fri, 13 Sep 2002 12:02:29 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DG2Sn24856 - for ; Fri, 13 Sep 2002 11:02:28 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Fri, 13 Sep 2002 11:02:20 -0500 -Message-ID: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913085153.GJ539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 9234 -Lines: 248 - -Tim, - -I think it's important for a developer to have the ability to turn this -on and off. But I would argue that 0 is the correct default. I think of -it as a probability times cost function. The cost of leaving the setting -at 1 accidentally in a production application is pretty high: if the app -doesn't scale (because it's parsing too much), then it jeopardizes the -business' ability to succeed with it. - -The probability of leaving the option set to 1 accidentally during -production is very high. A point in evidence is that I didn't find the -parameter until I corresponded personally with you. I in fact *still* -don't know where to find it. I've checked Descartes & Bunce, perldoc -DBI, and perldoc DBD::Oracle without finding it yet... - -If the default were 0, the probability of leaving the option set to 0 -accidentally during development would be much lower. A developer faced -with a SQL syntax problem he doesn't understand will do the research -necessary to fix that problem. He can't release his code until he does. - -The problem with the default of 1 is, in my opinion, that most -developers will never learn of the feature, and they'll accidentally -leave it turned on in production. The proportion of developers who -competently performance-test their code is, unfortunately, -microscopically small. But they all do some level of functional testing. - -I would recommend making the ora_check_sql feature a more prominently -documented feature, presumably in "perldoc DBD::Oracle". - -I did learn in a test that specifying the option in the DBI->connect() -call doesn't do anything. Is it possible that you could allow us to -specify it at the connection level? The workaround is to do something -like this: - - use Getopt::Long; - my %prepare_attr = (ora_check_sql=>0); - GetOptions("dev"=>\$dev); - $prepare_attr{ora_check_sql} = 1 if $dev; - # developer must specify the command-line flag to get the -unscalable - # behavior that's necessary for functional testing - ... - $sth = $dbh->prepare($sql, %prepare_attr); # MUST specify -%p..attr - -...But I doubt that most Oracle application developers would come up -with this without some coaching. - -I'll definitely keep an eye open for projects you might like. It would -be a hell of an opportunity for someone to have you, I think. It seems -that if you could make a list like Oracle-L (1,900 people) aware that -there's an opportunity, it would improve your chances of finding -something quickly. It's of course bad taste to advertise oneself overtly -on those lists, but there is almost always a clever way to do it anyway -without offending anyone. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:52 AM -To: Cary Millsap -Cc: 'Tim Bunce' -Subject: Re: two Oracle parse calls - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge -to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our -lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a -preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more -"official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw -you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 -trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret -them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t -where -> key=:p1',44,1,0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: -231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), -{ -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call -parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:37 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLbC13725 - for ; Fri, 13 Sep 2002 23:21:37 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:37 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031951069:20:15816:152; Fri, 13 Sep 2002 21:04:29 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2120669; 13 Sep 2002 21:04 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 544863E642 - for ; Fri, 13 Sep 2002 17:04:17 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id 0AE7C3E667 - for ; Fri, 13 Sep 2002 17:04:16 -0400 (EDT) -Received: (qmail 16221 messnum 355694 invoked from network[159.134.166.226/p738.as1.limerick1.eircom.net]); 13 Sep 2002 21:04:14 -0000 -Received: from p738.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.226) - by mail05.svc.cra.dublin.eircom.net (qp 16221) with SMTP; 13 Sep 2002 21:04:14 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DL4Lx12642; - Fri, 13 Sep 2002 22:04:21 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:04:21 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913210421.GR539@dansat.data-plan.com> -References: <20020913085153.GJ539@dansat.data-plan.com> <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 3078 -Lines: 70 - -On Fri, Sep 13, 2002 at 11:02:20AM -0500, Cary Millsap wrote: -> Tim, -> -> I think it's important for a developer to have the ability to turn this -> on and off. But I would argue that 0 is the correct default. I think of -> it as a probability times cost function. The cost of leaving the setting -> at 1 accidentally in a production application is pretty high: if the app -> doesn't scale (because it's parsing too much), then it jeopardizes the -> business' ability to succeed with it. -> -> The probability of leaving the option set to 1 accidentally during -> production is very high. A point in evidence is that I didn't find the -> parameter until I corresponded personally with you. I in fact *still* -> don't know where to find it. I've checked Descartes & Bunce, perldoc -> DBI, and perldoc DBD::Oracle without finding it yet... - -It's not documented. - -As I recall it... originally DBD::Oracle defered the describe as -long as possible. But people reported very slow select performance: - - http://www.faqchest.com/prgm/dbi-l/dbi-99/dbi-9910/dbi-991005/dbi99101218_28018.html - -Turned out that the row cache logic needed the describe to try to -work out an optimal row cache size. Without the describe the row -cache wasn't getting set up. - -At some point I added code that would just set OCI_ATTR_PREFETCH_MEMORY -to a set size if ora_check_sql was 0. But I can't remember now why -I left ora_check_sql=1. - -It was possibly in relation to wanting to be able to use the -OCI_ATTR_PARSE_ERROR_OFFSET attribute to be able to highlight the -point in a query where the error was detected. But I think execute() -needs to be able to do that anyway (to catch syntax errors in -non-select statements). - -There is another problem. If the describe has been defered and the -application uses $sth->{NAME} or other similar attribute then the -describe has to be done at that point. The code is thee to do that -but the problem is how should the DBI behave if there's an error -in the SQL? It currently always croaks (rather than return undef, -in order to give a useful error message), but that's rather surprising -behaviour to many people and very unhelpful to some. - -There may well be other subtle issues that I can't recall right now. - -> I would recommend making the ora_check_sql feature a more prominently -> documented feature, presumably in "perldoc DBD::Oracle". -> -> I did learn in a test that specifying the option in the DBI->connect() -> call doesn't do anything. Is it possible that you could allow us to -> specify it at the connection level? - -By making it a database handle attribute, yes, that would be my plan. - -> I'll definitely keep an eye open for projects you might like. It would -> be a hell of an opportunity for someone to have you, I think. - -Thanks. - -> It seems that if you could make a list like Oracle-L (1,900 people) aware -> that there's an opportunity, it would improve your chances of finding -> something quickly. It's of course bad taste to advertise oneself overtly -> on those lists, but there is almost always a clever way to do it anyway -> without offending anyone. - -:-) - -Tim. - -From cary.millsap@hotsos.com Fri Sep 13 07:32:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6W1C04656 - for ; Fri, 13 Sep 2002 07:32:01 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:32:01 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031891038:20:04710:44; Fri, 13 Sep 2002 04:23:58 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id ab2004623; 13 Sep 2002 4:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 942A82BF2C - for ; Fri, 13 Sep 2002 00:23:44 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 73C982BF33 - for ; Fri, 13 Sep 2002 00:23:42 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D4Ndn19584 - for ; Thu, 12 Sep 2002 23:23:39 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 23:23:30 -0500 -Message-ID: <019301c25add$53f5dfd0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0194_01C25AB3.6B1FD7D0" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -Content-Length: 36859 -Lines: 1209 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Well, that was easy. Setting ora_check_sql=>0 does solve the problem. - - - -I now shift into "Please make 0 the default" mode. - - - -Here are the Oracle trace files, by the way, with a splash of color to -illustrate how the Oracle kernel sees what's going on (I hope you have -an HTML mail reader)... - - - -With {ora_check_sql=>1} (or no setting at all), here's what Oracle does -for the application: - - - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - - - -The PARSING IN CURSOR section tells us what SQL it is that we're -executing. Each line beginning with "PARSE" is emitted only when Oracle -executes a parse call. There are two. The first is wasted. - - - -Here's the same application with {ora_check_sql=>1} (the official new -default value, I am sure :-)): - - - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=109776065 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -FETCH #1:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=109776065 - - - -One parse call; problem solved. - - - -Thank you sincerely for your help. - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- -From: Cary Millsap [mailto:cary.millsap@hotsos.com] -Sent: Thursday, September 12, 2002 11:00 PM -To: 'Tim Bunce' -Subject: RE: two Oracle parse calls - - - -Tim, - - - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - - - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- - -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] - -Sent: Thursday, September 12, 2002 5:58 PM - -To: Cary Millsap - -Cc: tim.bunce@pobox.com - -Subject: two Oracle parse calls - - - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: - -> Tim, - -> - -> How are you doing? I hope you've had a good two years since I saw you -on - -> the Oracle Geek Cruise event. - - - -Yes thanks. And you? - - - -> I've been working on a project this year to construct a book about - -> optimizing Oracle response time. In my research, I've discovered - -> something about the DBI that I didn't expect: it executes two Oracle - -> parse calls for every one that I would expect an efficient DBI layer -to - -> make. I've included my Perl source (below), the Oracle level-12 trace - -> data that shows the sequence of calls it's receiving from the Perl - -> application (below), a level-9 DBI trace from the application - -> (attached), and our version information (below). - -> - -> I was hoping that by showing you this specific data, you could make -the - -> problem go away. - - - -I can only do what OCI lets me do... but within that I'll do what I -can... - - - -I'm not familar with Oracle trace logs so I can't readily intrepret them - -and I'll take what you say at face value. - - - -But I am familar with DBD::Oracle :) and the logs it writes :) - - - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -> $sth->execute($key); - - - - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - - dbd_preparse scanned 1 distinct placeholders - -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS - -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - - dbd_st_prepare'd sql SELECT - - dbd_describe SELECT (EXPLICIT, lb 80)... - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') - -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS - -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - - bind :p1 done with ftype 1 - - dbd_st_execute SELECT (out0, lob0)... - - in ':p1' [0,0]: len 4, ind 0 - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - - <- execute= '0E0' at ex1.pl line 51 - - - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - - - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -call that prepare() does. - - - -It doesn't do that for non-select statements so you could check if - -non-selects also have two parse calls. - - - -Also try doing - - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - - - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the - -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -is possibly redundant and could be removed (but Oracle ought to detect -that - -anyway and not make a round-trip for it, and certainly not call parse). - - - -If non-selects only have one parse call but ora_check_sql=>0 doesn't - -fix selects, then I might be able to do a simple patch to avoid the - -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - - - -Then the issue will be: should ora_check_sql=>0 be the default... - - - -Tim. - - - -p.s. I'd love a copy of your book when it's ready! - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Well, that was easy. Setting ora_check_sql=3D>0 = -does solve the -problem.

- -

 

- -

I now shift into "Please make 0 the = -default" mode.

- -

 

- -

Here are the Oracle trace files, by the way, with a = -splash -of color to illustrate how the Oracle kernel sees what’s going on = -(I hope -you have an HTML mail reader)...

- -

 

- -

With {ora_check_sql=3D>1} (or no setting at all), = -here’s -what Oracle does for the application:

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #2 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312018 = -hv=3D1997601641 ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF STMT

- -

PARSE = -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312019 = -hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF = -STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

FETCH = -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

 

- -

The PARSING IN CURSOR section tells us what SQL it is = -that -we’re executing. Each line beginning with “PARSE” is = -emitted -only when Oracle executes a parse call. There are two. The first is = -wasted.

- -

 

- -

Here’s the same application with = -{ora_check_sql=3D>1} (the official new = -default value, I -am sure J):

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 = -dep=3D0 uid=3D12 -oct=3D3 lid=3D12 tim=3D109776065 hv=3D1997601641 = -ad=3D'54af1384'

- -

select key, fkey, value from = -t where -key=3D:p1

- -

END OF STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

FETCH = -#1:c=3D0,e=3D0,p=3D0,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D109= -776065

- -

 

- -

One parse call; problem solved.

- -

 

- -

Thank you sincerely for your help.

- -

 

- -

 

- -

Cary = -Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System = -Performance, -Feb 9-12 Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 = -Middelfart Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----
-From: Cary Millsap [mailto:cary.millsap@hotsos.com]
-Sent: Thursday, September 12, 2002 11:00 PM
-To: 'Tim Bunce'
-Subject: RE: two Oracle parse calls

- -

 

- -

Tim,

- -

 

- -

Thanks so very much. The attribute ora_check_sql=3D>0 is new = -knowledge -to me; this is a nice reward for having written to you. I will test it = -either -tonight or the first thing tomorrow and then inform you of the results -immediately after that. If it solves the problem, then I will lobby you = -to make -0 the default value and probably consider the issue "problem = -solved."

- -

 

- -

Things are very well, thank you. I've been at home with my = -family now -for over three straight weeks, and we're having a nice time of our lives = -these -days with the business settling into stride a bit. Tonight is a big = -night for -me. I've just crossed the line of accepting a preliminary offer from = -O'Reilly. -This book project has actually been underway for quite some time now, = -but as of -tonight it's quite a bit more "official."

- -

 

- -

 

- -

Cary Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec = -9-11 -Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System Performance, Feb = -9-12 -Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 Middelfart = -Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----

- -

From: Tim Bunce [mailto:Tim.Bunce@pobox.com]

- -

Sent: Thursday, September 12, 2002 5:58 PM

- -

To: Cary Millsap

- -

Cc: tim.bunce@pobox.com

- -

Subject: two Oracle parse calls

- -

 

- -

On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap = -wrote:

- -

> Tim,

- -

>

- -

> How are you doing? I hope you've had a good two years since = -I saw -you on

- -

> the Oracle Geek Cruise event.

- -

 

- -

Yes thanks. And you?

- -

 

- -

> I've been working on a project this year to construct a = -book about

- -

> optimizing Oracle response time. In my research, I've = -discovered

- -

> something about the DBI that I didn't expect: it executes = -two -Oracle

- -

> parse calls for every one that I would expect an efficient = -DBI -layer to

- -

> make. I've included my Perl source (below), the Oracle = -level-12 -trace

- -

> data that shows the sequence of calls it's receiving from = -the Perl

- -

> application (below), a level-9 DBI trace from the = -application

- -

> (attached), and our version information = -(below).

- -

>

- -

> I was hoping that by showing you this specific data, you = -could -make the

- -

> problem go away.

- -

 

- -

I can only do what OCI lets me do... but within that I'll do = -what I -can...

- -

 

- -

I'm not familar with Oracle trace logs so I can't readily = -intrepret -them

- -

and I'll take what you say at face value.

- -

 

- -

But I am familar with DBD::Oracle :) and the logs it writes = -:)

- -

 

- -

> $sth =3D $dbh->prepare(q(select key, fkey, value from t = -where -key=3D?));

- -

> $sth->execute($key);

- -

 

- -

 

- -

    -> prepare for DBD::Oracle::db -(DBI::db=3DHASH(0x8235b34)~0x8235a74 'select key, fkey, value from t = -where -key=3D?')

- -

    dbd_preparse scanned 1 distinct = -placeholders

- -

OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCC= -ESS

- -

OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from = -t -where key=3D:p1',44,1,0)=3DSUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)= -=3DSUCCESS

- -

    dbd_st_prepare'd sql SELECT

- -

    dbd_describe SELECT (EXPLICIT, lb = -80)...

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3D= -SUCCESS

- -

    dbd_describe'd 3 columns (row bytes: 76 max, = -40 est -avg, cache: 231)

- -

    <- prepare=3D DBI::st=3DHASH(0x8240fe0) at = -ex1.pl -line 50

- -

    -> execute for DBD::Oracle::st -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0 '8542')

- -

OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x8= -26cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS - -

OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40= -,0x401da090)=3DSUCCESS

- -

       bind :p1 done with ftype = -1

- -

    dbd_st_execute SELECT (out0, = -lob0)...

- -

       in  ':p1' [0,0]: = -len  4, -ind 0

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3D= -SUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec= -)=3DSUCCESS

- -

    dbd_st_execute SELECT returned (SUCCESS, = -rpc0, fn4, -out0)

- -

    <- execute=3D '0E0' at ex1.pl line = -51

- -

 

- -

Given those OCI calls, what is DBD::Oracle doing that it = -shouldn't?

- -

 

- -

I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

call that prepare() does.

- -

 

- -

It doesn't do that for non-select statements so you could check = -if

- -

non-selects also have two parse calls.

- -

 

- -

Also try doing

- -

  $sth =3D $dbh->prepare(q(select key, fkey, value from = -t where -key=3D?), { ora_check_sql=3D> 0 });

- -

 

- -

which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till = -after the

- -

main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

is possibly redundant and could be removed (but Oracle ought to = -detect -that

- -

anyway and not make a round-trip for it, and certainly not call = -parse).

- -

 

- -

If non-selects only have one parse call but = -ora_check_sql=3D>0 doesn't

- -

fix selects, then I might be able to do a simple patch to avoid = -the

- -

OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if = -ora_check_sql=3D>0.

- -

 

- -

Then the issue will be: should ora_check_sql=3D>0 be the = -default...

- -

 

- -

Tim.

- -

 

- -

p.s. I'd love a copy of your book when it's = -ready!

- -
- - - - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0-- - - -From cary.millsap@hotsos.com Fri Sep 13 21:17:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DKHhC12417 - for ; Fri, 13 Sep 2002 21:17:43 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 21:17:43 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031946929:20:18513:70; Fri, 13 Sep 2002 19:55:29 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2018248; 13 Sep 2002 19:55 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 7FC402C01F - for ; Fri, 13 Sep 2002 15:55:06 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 76A5E2BFE1 - for ; Fri, 13 Sep 2002 15:55:05 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DJt4n26736 - for ; Fri, 13 Sep 2002 14:55:04 -0500 -From: "Cary Millsap" -To: "Tim Bunce" -Subject: A little more data -Date: Fri, 13 Sep 2002 14:54:56 -0500 -Message-ID: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0203_01C25B35.89729F60" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4948 -Lines: 166 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -I hope this is helpful. I have noticed that I cannot produce the -extra-parse problem on my 8.1.7 laptop database, no matter what the -setting of ora_check_sql. All of the data I've sent you is from our -8.1.6 Linux database. If you really needed it, I could produce level-9 -DBI trace data from identical tests on both platforms, but I won't spend -the time doing that unless you say it will help... - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - - - - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

I hope this is helpful… I have noticed that I = -cannot -produce the extra-parse problem on my 8.1.7 laptop database, no matter = -what the -setting of ora_check_sql. All of the data I’ve sent you is from = -our 8.1.6 -Linux database. If you really needed it, I could produce level-9 DBI = -trace data -from identical tests on both platforms, but I won’t spend the time = -doing -that unless you say it will help...

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -

 

- -
- - - - - -------=_NextPart_000_0203_01C25B35.89729F60-- - - -From timbo@dansat.data-plan.com Fri Sep 13 22:05:30 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL5UC12942 - for ; Fri, 13 Sep 2002 22:05:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:05:30 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031948458:10:20432:5; Fri, 13 Sep 2002 20:20:58 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-1.mail.demon.net - id aa1020174; 13 Sep 2002 20:20 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 8A60E3E659 - for ; Fri, 13 Sep 2002 16:20:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id CAC663E685 - for ; Fri, 13 Sep 2002 16:20:36 -0400 (EDT) -Received: (qmail 37861 messnum 258096 invoked from network[159.134.164.124/p124.as1.limerick1.eircom.net]); 13 Sep 2002 20:20:35 -0000 -Received: from p124.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.124) - by mail05.svc.cra.dublin.eircom.net (qp 37861) with SMTP; 13 Sep 2002 20:20:35 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DKKhu12535; - Fri, 13 Sep 2002 21:20:43 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 21:20:43 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data -Message-ID: <20020913202043.GO539@dansat.data-plan.com> -References: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1098 -Lines: 34 - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - -From cary.millsap@hotsos.com Fri Sep 13 22:04:47 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL4kC12684 - for ; Fri, 13 Sep 2002 22:04:46 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:04:46 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031949629:20:13745:23; Fri, 13 Sep 2002 20:40:29 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2013849; 13 Sep 2002 20:40 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 7D90A3E650 - for ; Fri, 13 Sep 2002 16:40:20 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-1.pobox.com (Postfix) with ESMTP id 785AB3E642 - for ; Fri, 13 Sep 2002 16:40:19 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DKeIn27106 - for ; Fri, 13 Sep 2002 15:40:18 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: A little more data -Date: Fri, 13 Sep 2002 15:40:10 -0500 -Message-ID: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913202043.GO539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 1999 -Lines: 63 - -Well, it's 1.06 on my Windows machine (the most up-to-date version -available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -but interesting that (admitting now that there's a new degree of freedom -running loose amid the test) "the older version performs better than the -newer one." :) That's certainly not a fair statement if the diff between -8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:21 PM -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't -spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:32 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLWC13692 - for ; Fri, 13 Sep 2002 23:21:32 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:32 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031952887:10:13297:20; Fri, 13 Sep 2002 21:34:47 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1118141; 13 Sep 2002 21:34 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C7D482BF23 - for ; Fri, 13 Sep 2002 17:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail00.svc.cra.dublin.eircom.net (mail00.svc.cra.dublin.eircom.net [159.134.118.16]) - by dolly1.pobox.com (Postfix) with SMTP id 8352A2BF6C - for ; Fri, 13 Sep 2002 17:34:36 -0400 (EDT) -Received: (qmail 5093 messnum 521124 invoked from network[159.134.164.134/p134.as1.limerick1.eircom.net]); 13 Sep 2002 21:34:34 -0000 -Received: from p134.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.134) - by mail00.svc.cra.dublin.eircom.net (qp 5093) with SMTP; 13 Sep 2002 21:34:34 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DLYeI13070; - Fri, 13 Sep 2002 22:34:40 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:34:40 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: A little more data -Message-ID: <20020913213440.GS539@dansat.data-plan.com> -References: <20020913202043.GO539@dansat.data-plan.com> <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 2282 -Lines: 69 - -According my RCS the default for ora_check_sql changed from 0 to 1 -around version 1.03. - -Tim. - -On Fri, Sep 13, 2002 at 03:40:10PM -0500, Cary Millsap wrote: -> Well, it's 1.06 on my Windows machine (the most up-to-date version -> available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -> but interesting that (admitting now that there's a new degree of freedom -> running loose amid the test) "the older version performs better than the -> newer one." :) That's certainly not a fair statement if the diff between -> 8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Friday, September 13, 2002 3:21 PM -> To: Cary Millsap -> Cc: Tim Bunce -> Subject: Re: A little more data -> -> If they're using the same version of DBD::Oracle then -> the change must me on the sever side. Maybe Oracle's -> woken up to the fact they don't need a second parse! -> -> Tim. -> -> On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > -> > -> > I hope this is helpful. I have noticed that I cannot produce the -> > extra-parse problem on my 8.1.7 laptop database, no matter what the -> > setting of ora_check_sql. All of the data I've sent you is from our -> > 8.1.6 Linux database. If you really needed it, I could produce level-9 -> > DBI trace data from identical tests on both platforms, but I won't -> spend -> > the time doing that unless you say it will help... -> > -> > -> > -> > Cary Millsap -> > Hotsos Enterprises, Ltd. -> > http://www.hotsos.com -> > -> > Upcoming events: -> > - Hotsos Clinic , Oct 1-3 San -> > Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> > - 2003 Hotsos Symposium on -> > OracleR System Performance, Feb 9-12 Dallas -> > - Next event: Miracle Database Forum , Sep -> > 20-22 Middlefart Denmark -> > -> > -> > -> - diff --git a/err_unsorted/err_xml.msg b/err_unsorted/err_xml.msg deleted file mode 100644 index 7a60a0cb..00000000 --- a/err_unsorted/err_xml.msg +++ /dev/null @@ -1,118 +0,0 @@ -From dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org Fri Aug 15 14:41:14 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h7FDe3MA043557 - for ; Fri, 15 Aug 2003 14:41:13 +0100 (BST) - (envelope-from dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 15 Aug 2003 14:41:13 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 19nc4X-0006LQ-BC; - Fri, 15 Aug 2003 10:44:41 +0000 -Received: from [207.106.49.22] (helo=dolly1.pobox.com) - by punt-3.mail.demon.net with esmtp id 19nc4X-0006LQ-BC - for pobox@dbi.demon.co.uk; Fri, 15 Aug 2003 10:44:41 +0000 -Received: from dolly1.pobox.com (localhost[127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 16F6B21C13B - for ; Fri, 15 Aug 2003 06:44:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.develooper.com[63.251.223.166]) - by dolly1.pobox.com (Postfix) with SMTP id 021F121C36F - for ; Fri, 15 Aug 2003 06:44:40 -0400 (EDT) -Received: (qmail 78180 invoked by uid 1005); 15 Aug 2003 10:44:34 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 71287 invoked by uid 76); 15 Aug 2003 10:32:13 -0000 -Delivered-To: dbi-users@perl.org -Received-SPF: unknown (domain of sender andyhassall@yahoo.com does not designate mailers: NXDOMAIN) -Message-ID: <20030815103200.24313.qmail@web9605.mail.yahoo.com> -Date: Fri, 15 Aug 2003 11:32:00 +0100 (BST) -From: =?iso-8859-1?q?Andy=20Hassall?= -Reply-To: andy@andyh.co.uk -Subject: Re: ERROR OCIDefineObject call needed but not implemented yet using XMLElement function -To: Susan Cassidy , dbi-users@perl.org -In-Reply-To: -MIME-Version: 1.0 -Content-Type: text/plain; charset=iso-8859-1 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.8 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,SPAM_PHRASE_01_02 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id h7FDe3MA043557 -Status: RO -Content-Length: 2299 -Lines: 65 - - --- Susan Cassidy wrote: > I am using DBD::Oracle. -I was on version 1.12, then I installed version -> 1.14, with the same result. -> -> This is Oracle 9.2.0. -> -> I have this select statement that works fine from SQL*Plus: -> -> select XMLElement("Sequences", -> XMLElement("Sequence", -> XMLATTRIBUTES ( b.local_name AS "ic-acckey", -> b.mol_type AS "molecule", -> n.seq_name AS "title"))) -> from gcg_bioseq b, gcg_annot_seq_name a, gcg_seq_name n -> where -> b.local_name = 'K00306' and -> b.seq_status = 'D' and -> b.seq_oid = a.seq_oid and -> a.seq_name_oid = n.seq_name_oid and -> n.name_type = 'LOCUS' -> -> -> When I run it via DBI/DBD I get this (trace level 2): -> -> DBI 1.32-nothread dispatch trace level set to 2 -> Note: perl is running without the recommended perl -w option -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x1b2314)~0x122bec ' -[snip -> Field 1 has an Oracle type (108) which is not explicitly supported -> fbh 1: -> -'XMLELEMENT("SEQUENCES",XMLELEMENT("SEQUENCE",XMLATTRIBUTES(B.LOCAL_NAMEAS"IC-ACCKEY",B.MOL_TYPEAS"MOLECULE",N.SEQ_NAMEAS"TITLE")))' -[snip] -> Error: prepare failed -> at line 56, error: ERROR OCIDefineObject call needed but not -> implemented yet -> -> Is there any other workaround for this than wrapping this up in a PL/SQL -> function? - - Don't rely on the implicit conversion to a string type that is done when -SQL*Plus displays an XMLElement; add .getClobVal() to the end of the -statement to retrieve it as a CLOB rather than the XMLElement object type -(which DBD::Oracle doesn't accept). - - i.e. - -select XMLElement("Sequences", - XMLElement("Sequence", - XMLATTRIBUTES ( b.local_name AS "ic-acckey", - b.mol_type AS "molecule", - n.seq_name AS "title"))).getClobVal() - from ... - - (or getStringVal() for a VARCHAR2) - -===== --- -Andy Hassall (andy@andyh.org) icq(5747695) http://www.andyh.co.uk -http://www.andyhsoftware.co.uk/space | disk usage analysis tool - -________________________________________________________________________ -Want to chat instantly with your online friends? Get the FREE Yahoo! -Messenger http://uk.messenger.yahoo.com/ - - diff --git a/err_unsorted/err_xml2.msg b/err_unsorted/err_xml2.msg deleted file mode 100644 index 3bb291c5..00000000 --- a/err_unsorted/err_xml2.msg +++ /dev/null @@ -1,700 +0,0 @@ -From dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org Fri Jan 30 12:50:15 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UClt3q069307 - for ; Fri, 30 Jan 2004 12:50:14 GMT - (envelope-from dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 12:50:14 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmWGJ-00057X-AG; - Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmWGJ-00057X-AG - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [207.8.214.3] (helo=puzzle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmWGI-0007XK-P3 - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:34 +0000 -Received: from puzzle.pobox.com (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 029E8701C6 - for ; Fri, 30 Jan 2004 05:52:34 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 12ABF701C1 - for ; Fri, 30 Jan 2004 05:52:30 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by puzzle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 05:51:10 -0500 (EST) -Received: (qmail 33345 invoked by uid 1005); 30 Jan 2004 10:50:36 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 33175 invoked by uid 76); 30 Jan 2004 10:50:26 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Fri, 30 Jan 2004 02:50:25 -0800 -Received: (qmail 21117 invoked by uid 225); 30 Jan 2004 10:48:52 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 21080 invoked by uid 507); 30 Jan 2004 10:48:49 -0000 -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Fri, 30 Jan 2004 02:48:46 -0800 -Received: (qmail 31958 invoked from network); 30 Jan 2004 11:50:38 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 30 Jan 2004 11:50:38 -0000 -Received: (qmail 6921 invoked from network); 30 Jan 2004 10:49:58 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 30 Jan 2004 10:49:58 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Fri, 30 Jan 2004 11:49:58 +0100 (CET) -Subject: DBD-Oracle and XMLType -From: Hendrik Fuss -To: "dbi-dev@perl.org" -Content-Type: multipart/mixed; boundary="=-fkyM33WAvQ5xV0uCPeSD" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 11:41:31 +0100 -Message-Id: <1075459292.7305.46.camel@mars> -Mime-Version: 1.0 -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.5 required=7.0 tests=MIME_LONG_LINE_QP,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01,TO_ADDRESS_EQ_REAL version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 8148 -Lines: 302 - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -Hi everyone, - -It's been a while since I last posted here. In September 2003 I was -trying to add support for binding XMLType objects to DBD-Oracle, so that -you could easily insert large (ie >4k) XML data into an XMLType table. - -Unfortunately my employer fired me in October 2003 and in the remaining -time I had to work on other projects, so I wasn't able to complete the -DBD project. Since I won't have access to an oracle database from now -on, I thought the least I can do is to provide my code as it is to the -list. Blame German economy. :-( - -The attached patch (based on DBD-Oracle 1.15) enables you to upload -XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -I added a function dbd_rebind_ph_nty for that purpose. You need to -create that XMLType object first using the C function -createxmlfromstring in xml.c. - -The XMLType object is either created from an OCIString or from a -temporary CLOB depending on the length of the source string. Have a look -at the bottom of ociap.h, all the (undocumented) XMLType functions are -there, and there are also some constants in oci.h. - -I'm not sure if the CLOB code currently works. - -Here is another code fragment: - - my $xml =3D createxml($dbh, 'Test document'); - my $sth =3D $dbh->prepare('INSERT INTO xml_type VALUES (?)'); - $sth->bind_param(1, $xml, { ora_type =3D> 108 }); # SQLT_NTY - $sth->execute(); - -Please note that this code is really just early development, which I -wouldn't publish under normal circumstances. :) I just hope it might me -useful to someone. - -Well then, time to say goodbye -thanks to Tim and everyone who contributed to dbi for a great piece of -software - -Cheers, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Description: -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - -151a152 -> case 108: /* SQLT_NTY */ -992a994,996 -> case SQL_UDT: -> return 108; /* Oracle NTY */ ->=20 -1004a1009,1072 -> static int -> dbd_rebind_ph_nty(sth, imp_sth, phs) -> SV* sth; -> imp_sth_t *imp_sth; -> phs_t *phs; -> { -> OCIType *tdo =3D NULL; -> sword status; -> SV* ptr; ->=20 -> if (phs->is_inout) -> croak("OUT binding for NTY is currently unsupported"); ->=20 -> /* ensure that the value is a support named object type */ -> /* (currently only OCIXMLType*) */ -> if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -> OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -> (CONST text*)"SYS", 3, -> (CONST text*)"XMLTYPE", 7, -> (CONST text*)0, 0, -> OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -> &tdo); ->=20 -> ptr =3D SvRV(phs->sv); -> phs->progv =3D (void*) SvIV(ptr); -> phs->maxlen =3D sizeof(OCIXMLType*); -> } -> else -> croak("Unsupported named object type for bind parameter"); ->=20 ->=20 -> /* bind by name */ ->=20 -> OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -> (text*)phs->name, (sb4)strlen(phs->name), -> (dvoid *) NULL, /* value supplied in BindObject later */ -> 0, -> (ub2)phs->ftype, 0, -> NULL, -> 0, 0, -> NULL, -> (ub4)OCI_DEFAULT, -> status -> ); ->=20 -> if (status !=3D OCI_SUCCESS) { -> oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -> return 0; -> } -> if (DBIS->debug >=3D 3) -> PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); ->=20 ->=20 -> /* bind the object */ ->=20 -> OCIBindObject(phs->bndhp, imp_sth->errhp, -> (CONST OCIType*)tdo, -> (dvoid **)&phs->progv, -> (ub4*)NULL, -> (dvoid **)NULL, -> (ub4*)NULL); ->=20 -> return 2; -> } -1309a1378,1380 -> case 108: -> done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -> break; -1331c1403 -< int at_exec =3D (phs->desc_h =3D=3D NULL); ---- -> int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); -1419c1491 -< if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) ---- -> if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQL= -T_NTY)) -1420a1493 -> /* ref allowed for OCIXMLType* */ -2219a2293 -> case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Disposition: attachment; filename=xml.c -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; name=xml.c; charset=ISO-8859-1 - -#include "oci.h" -#include - -/* This helper function creates an XMLType object from a string source. - * - * The resulting object can be bound to a placeholder, if ora_type =3D> - * SQLT_NTY is specified. - */ - -static void checkerr(errhp, status) -OCIError *errhp; -sword status; -{ - text errbuf[512]; - ub4 buflen; - sb4 errcode; - - switch (status) - { - case OCI_SUCCESS: - break; - case OCI_SUCCESS_WITH_INFO: - printf("Error - OCI_SUCCESS_WITH_INFO\n"); - break; - case OCI_NEED_DATA: - printf("Error - OCI_NEED_DATA\n"); - break; - case OCI_NO_DATA: - printf("Error - OCI_NO_DATA\n"); - break; - case OCI_ERROR: - OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, - errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR); - printf("Error - %s\n", errbuf); - exit(1); - break; - case OCI_INVALID_HANDLE: - printf("Error - OCI_INVALID_HANDLE\n"); - break; - case OCI_STILL_EXECUTING: - printf("Error - OCI_STILL_EXECUTE\n"); - break; - case OCI_CONTINUE: - printf("Error - OCI_CONTINUE\n"); - break; - default: - break; - } -} - - -#define MAX_OCISTRING_LEN 32766 - -SV* createxmlfromstring(SV* dbh, char* source) { - OCIXMLType *xml =3D NULL; - ub4 len; - ub1 src_type; - dvoid* src_ptr =3D NULL; - D_imp_dbh(dbh); - SV* sv_dest; - - len =3D strlen(source); - if(len > MAX_OCISTRING_LEN) { - src_type =3D OCI_XMLTYPE_CREATE_CLOB; - - printf("OCIDescriptorAlloc\n"); - checkerr( imp_dbh->errhp, - OCIDescriptorAlloc((dvoid*)imp_dbh->envhp, - (dvoid **)&src_ptr, - (ub4)OCI_DTYPE_LOB, - (size_t)0, - (dvoid**)0) ); - - printf("OCILobCreateTemporary\n"); - checkerr( imp_dbh->errhp, - OCILobCreateTemporary(imp_dbh->svchp, - imp_dbh->errhp,=20 - (OCILobLocator*) src_ptr, - (ub2)0,=20 - SQLCS_IMPLICIT,=20 - OCI_TEMP_CLOB,=20 - OCI_ATTR_NOCACHE,=20 - OCI_DURATION_SESSION) ); - - printf("OCILobWrite\n"); - checkerr (imp_dbh->errhp, - OCILobWriteAppend(imp_dbh->svchp, - imp_dbh->errhp, - (OCILobLocator*) src_ptr, - &len,=20 - (ub1*)source, - len, - OCI_ONE_PIECE, - (dvoid *)0,=20 - (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, - 0, - SQLCS_IMPLICIT)); - - } else { - src_type =3D OCI_XMLTYPE_CREATE_OCISTRING; - - printf("OCIStringAssignText\n"); - checkerr( imp_dbh->errhp, - OCIStringAssignText(imp_dbh->envhp, - imp_dbh->errhp,=20 - (CONST text*) source,=20 - (ub2) strlen(source), - (OCIString **) &src_ptr) - ); - } - - printf("OCIXMLTypeCreateFromSrc\n"); - checkerr( imp_dbh->errhp, - OCIXMLTypeCreateFromSrc(imp_dbh->svchp, - imp_dbh->errhp, - (OCIDuration)OCI_DURATION_CALLOUT, - (ub1)src_type, - (dvoid *)src_ptr, - (sb4)OCI_IND_NOTNULL, - &xml) - ); - - - /* free temporary resources */ - if( src_type =3D=3D OCI_XMLTYPE_CREATE_CLOB ) { - checkerr( imp_dbh->errhp, - OCILobFreeTemporary(imp_dbh->svchp, imp_dbh->errhp, - (OCILobLocator*) src_ptr) ); - - checkerr( imp_dbh->errhp, - OCIDescriptorFree((dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB) ); - } - - - sv_dest =3D newSViv(0); - sv_setref_pv(sv_dest, "OCIXMLTypePtr", xml); - return sv_dest; -} - ---=-fkyM33WAvQ5xV0uCPeSD-- - - - -From hendrik.fuss@morphochem.de Fri Jan 30 16:56:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UGsO3v071338 - for ; Fri, 30 Jan 2004 16:56:27 GMT - (envelope-from hendrik.fuss@morphochem.de) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 16:56:27 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmZJF-0001wN-DK; - Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmZJF-0001wN-DK - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmZJE-0003GM-Bm - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:48 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 334DE30C57 - for ; Fri, 30 Jan 2004 09:07:47 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id E65B230C2C - for ; Fri, 30 Jan 2004 09:07:45 -0500 (EST) -Received: from babel.morphochem.de (unknown [212.89.121.1]) - by boggle.pobox.com (Postfix) with ESMTP - for ; Fri, 30 Jan 2004 09:07:04 -0500 (EST) -Received: (qmail 29768 invoked from network); 30 Jan 2004 15:10:09 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) - by 212.89.121.1 with SMTP; 30 Jan 2004 15:10:09 -0000 -Received: (qmail 11736 invoked from network); 30 Jan 2004 14:09:30 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) - (envelope-sender ) - by localhost.morphochem.de (qmail-ldap-1.03) with SMTP - for ; 30 Jan 2004 14:09:30 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) - by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; - Fri, 30 Jan 2004 15:09:30 +0100 (CET) -Subject: Re: DBD-Oracle and XMLType -From: Hendrik Fuss -To: Tim Bunce -Cc: "dbi-dev@perl.org" -In-Reply-To: <20040130133443.GC70215@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> - <20040130133443.GC70215@dansat.data-plan.com> -Content-Type: multipart/mixed; boundary="=-Sq1IOPDEhKoqxUKefiS3" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 15:01:03 +0100 -Message-Id: <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Status: RO -X-Status: A -Content-Length: 5585 -Lines: 196 - - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -> > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.= -c -> > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > create that XMLType object first using the C function -> > createxmlfromstring in xml.c. ->=20 -> I there any chance you could post that as a context diff (diff -u ideally -> or else diff -c)? It's much safer and more useful. Thanks. - -Good idea. Here's a diff -u of dbdimp.c. - -By the way: I have thougt about general support of named types, not just -XMLType, but you need to get the type description (TDO) from somewhere. -My code just checks if the perl variable is a blessed reference of -"OCIXMLTypePtr". - -Also note that my code can't handle downloading of XMLType objects yet. - -best wishes, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Description: Context diff for dbdimp.c -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - ---- dbdimp.c.orig 2004-01-30 14:48:55.000000000 +0100 -+++ dbdimp.c 2003-10-07 12:17:17.000000000 +0200 -@@ -1,5 +1,5 @@ - /* -- $Id: dbdimp.c,v 1.1.1.1 2003/10/02 10:45:20 hfuss Exp $ -+ $Id: dbdimp.c,v 1.3 2003/10/07 10:17:17 hfuss Exp $ -=20 - Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce -=20 -@@ -149,6 +149,7 @@ - case 97: /* CHARZ */ - case 106: /* MLSLABEL */ - case 102: /* SQLT_CUR OCI 7 cursor variable */ -+ case 108: /* SQLT_NTY */ - case 112: /* SQLT_CLOB / long */ - case 113: /* SQLT_BLOB / long */ - case 116: /* SQLT_RSET OCI 8 cursor variable */ -@@ -990,6 +991,9 @@ - case SQL_LONGVARCHAR: - return 8; /* Oracle LONG */ -=20 -+ case SQL_UDT: -+ return 108; /* Oracle NTY */ -+ - case SQL_DATE: - case SQL_TIME: - case SQL_TIMESTAMP: -@@ -1002,6 +1006,70 @@ - } -=20 -=20 -+static int -+dbd_rebind_ph_nty(sth, imp_sth, phs) -+ SV* sth; -+ imp_sth_t *imp_sth; -+ phs_t *phs; -+{ -+ OCIType *tdo =3D NULL; -+ sword status; -+ SV* ptr; -+ -+ if (phs->is_inout) -+ croak("OUT binding for NTY is currently unsupported"); -+ -+ /* ensure that the value is a support named object type */ -+ /* (currently only OCIXMLType*) */ -+ if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -+ OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -+ (CONST text*)"SYS", 3, -+ (CONST text*)"XMLTYPE", 7, -+ (CONST text*)0, 0, -+ OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -+ &tdo); -+ -+ ptr =3D SvRV(phs->sv); -+ phs->progv =3D (void*) SvIV(ptr); -+ phs->maxlen =3D sizeof(OCIXMLType*); -+ } -+ else -+ croak("Unsupported named object type for bind parameter"); -+ -+ -+ /* bind by name */ -+ -+ OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -+ (text*)phs->name, (sb4)strlen(phs->name), -+ (dvoid *) NULL, /* value supplied in BindObject later */ -+ 0, -+ (ub2)phs->ftype, 0, -+ NULL, -+ 0, 0, -+ NULL, -+ (ub4)OCI_DEFAULT, -+ status -+ ); -+ -+ if (status !=3D OCI_SUCCESS) { -+ oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -+ return 0; -+ } -+ if (DBIS->debug >=3D 3) -+ PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); -+ -+ -+ /* bind the object */ -+ -+ OCIBindObject(phs->bndhp, imp_sth->errhp, -+ (CONST OCIType*)tdo, -+ (dvoid **)&phs->progv, -+ (ub4*)NULL, -+ (dvoid **)NULL, -+ (ub4*)NULL); -+ -+ return 2; -+} -=20 - static int=20 - dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr)=20 -@@ -1307,6 +1375,9 @@ - case SQLT_RSET: - done =3D dbd_rebind_ph_rset(sth, imp_sth, phs); - break; -+ case 108: -+ done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -+ break; - #else - case 102: /* SQLT_CUR */ - done =3D dbd_rebind_ph_cursor(sth, imp_sth, phs); -@@ -1315,6 +1386,7 @@ - default: - done =3D dbd_rebind_ph_char(sth, imp_sth, phs, &alen_ptr); - } -+ - if (done !=3D 1) { - if (done =3D=3D 2) { /* the rebind did the OCI bind call itself successfu= -lly */ - if (DBIS->debug >=3D 3) -@@ -1328,7 +1400,7 @@ - #ifdef OCI_V8_SYNTAX - if (phs->maxlen > phs->maxlen_bound) { - sword status; -- int at_exec =3D (phs->desc_h =3D=3D NULL); -+ int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, (sb4)strlen(phs->name), - phs->progv, -@@ -1416,8 +1488,9 @@ - } - assert(name !=3D Nullch); -=20 -- if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) -+ if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQLT= -_NTY)) - /* dbi handle allowed for cursor variables */ -+ /* ref allowed for OCIXMLType* */ - croak("Can't bind a reference (%s)", neatsvpv(newvalue,0)); - if (SvTYPE(newvalue) > SVt_PVLV) /* hook for later array logic? */ - croak("Can't bind a non-scalar value (%s)", neatsvpv(newvalue,0)); -@@ -2217,6 +2290,7 @@ - #ifdef OCI_V8_SYNTAX - case SQLT_CLOB: sql_fbh.dbtype =3D SQL_CLOB; break; - case SQLT_BLOB: sql_fbh.dbtype =3D SQL_BLOB; break; -+ case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - #endif - #ifdef SQLT_TIMESTAMP_TZ - case SQLT_TIMESTAMP_TZ: sql_fbh.dbtype =3D SQL_TIMESTAMP; break; - ---=-Sq1IOPDEhKoqxUKefiS3-- - - - -From timbo@dansat.data-plan.com Fri Jan 30 18:32:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UIVK3f073353 - for ; Fri, 30 Jan 2004 18:32:30 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 18:32:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmceP-000603-GP; - Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmceP-000603-GP - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [208.210.124.73] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1AmceO-0006dQ-DB - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:52 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 25AEA3F13D - for ; Fri, 30 Jan 2004 12:41:51 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9FB863F16E - for ; Fri, 30 Jan 2004 12:41:49 -0500 (EST) -Received: from mail09.svc.cra.dublin.eircom.net (mail09.svc.cra.dublin.eircom.net [159.134.118.25]) - by icicle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 12:41:11 -0500 (EST) -Received: (qmail 9504 messnum 226571 invoked from network[213.94.228.233/unknown]); 30 Jan 2004 17:40:43 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail09.svc.cra.dublin.eircom.net (qp 9504) with SMTP; 30 Jan 2004 17:40:43 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UHf33A072739; - Fri, 30 Jan 2004 17:41:03 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i0UHf2Wr072738; - Fri, 30 Jan 2004 17:41:02 GMT -Date: Fri, 30 Jan 2004 17:41:02 +0000 -From: Tim Bunce -To: Hendrik Fuss -Cc: Tim Bunce , "dbi-dev@perl.org" -Subject: Re: DBD-Oracle and XMLType -Message-ID: <20040130174102.GB72657@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> <20040130133443.GC70215@dansat.data-plan.com> <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <1075471263.7305.73.camel@mars> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1129 -Lines: 29 - -On Fri, Jan 30, 2004 at 03:01:03PM +0100, Hendrik Fuss wrote: -> > > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -> > > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > > create that XMLType object first using the C function -> > > createxmlfromstring in xml.c. -> > -> > I there any chance you could post that as a context diff (diff -u ideally -> > or else diff -c)? It's much safer and more useful. Thanks. -> -> Good idea. Here's a diff -u of dbdimp.c. - -Thanks. - -> By the way: I have thougt about general support of named types, not just -> XMLType, but you need to get the type description (TDO) from somewhere. -> My code just checks if the perl variable is a blessed reference of -> "OCIXMLTypePtr". - -Doing the equivalent of m/^OCI(\w+)Ptr$/ and then calling OCITypeByName -with $1 uppercased might take us (or someone) a step further. - -> Also note that my code can't handle downloading of XMLType objects yet. - -I'll trust that some kind soul with an itch will send a patch :-) - -Thanks again Hendrik. - -Tim. - diff --git a/err_unsorted/err_xmltypebindplsql.msg b/err_unsorted/err_xmltypebindplsql.msg deleted file mode 100644 index 08faa725..00000000 --- a/err_unsorted/err_xmltypebindplsql.msg +++ /dev/null @@ -1,174 +0,0 @@ -From dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org Thu Apr 25 11:02:42 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3PA2gK34525 - for ; Thu, 25 Apr 2002 11:02:42 +0100 (BST) - (envelope-from dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 25 Apr 2002 11:02:42 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1019721492:10:18778:60; Thu, 25 Apr 2002 07:58:12 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1109782; 25 Apr 2002 7:58 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 791692BF11 - for ; Thu, 25 Apr 2002 03:58:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id 976FB2BEE4 - for ; Thu, 25 Apr 2002 03:58:07 -0400 (EDT) -Received: (qmail 84467 invoked by uid 1005); 25 Apr 2002 07:58:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 77923 invoked by uid 76); 24 Apr 2002 23:08:56 -0000 -Date: Wed, 24 Apr 2002 19:08:54 -0400 -From: Mark Stillwell -To: dbi-users-help@perl.org, dbi-users@perl.org -Subject: Oracle 9 XMLTYPE insert -Message-ID: <20020424190852.C22854@byrd.biostat.ufl.edu> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -Status: RO -Content-Length: 1469 -Lines: 43 - -I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -Here is my problem, I have a table named 'test' with three fields: eid -(integer), x (SYS.XMLTYPE) and formname (text) - -I create a database handler and connect to the database just fine. - -I create a new statement handler with the following command: - -$sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -SYS.XMLTYPE.CREATEXML(?), ?"); - -I loop over some data, $eid gets and integer, $xmlvalue gets a string, -and $formname gets a string. So long as $xmlvalue is relatively short -$sth->execute($eid, $xmlvalue, $formname); works great, but as soon as -it becomes long enough to force the use of clob's I have a problem. - -So I tried the following: - -$sth->bind_param(1, $i); -$sth->bind_param(2, $xmlvalue, { ora_type => ORA_CLOB }); -$sth->bind_param(3, $intable); -$sth->execute; - -This works great if column 'x' is a normal CLOB and I omit the -sys.xmltype.createxml statement above, but when 'x' is of type -sys.xmltype I get the following error: - -nvalid LOB locator specified -ORA-06512: at "SYS.XMLTYPE", line 0 - -Right now I've hacked the setup so there is a supplemental table called -'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE test SET x -= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem like the -right way to do this. - -Is there any way to do what I want in the current version of -DBI/OracleDBD? - --- -Mark Stillwell -marklee@ufl.edu -http://plaza.ufl.edu/marklee/ - -From dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org Wed May 8 16:11:46 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g48FBjo24814 - for ; Wed, 8 May 2002 16:11:45 +0100 (BST) - (envelope-from dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 08 May 2002 16:11:45 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020870336:20:08175:2; Wed, 08 May 2002 15:05:36 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2109147; 8 May 2002 15:05 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id 68FE23E6D4 - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-3.pobox.com (Postfix) with SMTP id 33A783E64D - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Received: (qmail 65232 invoked by uid 1005); 8 May 2002 15:01:47 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 60079 invoked by uid 76); 8 May 2002 14:50:53 -0000 -From: "Ben Middleton" -To: -Cc: -Subject: Re: Oracle 9 XMLTYPE insert -Date: Wed, 8 May 2002 15:50:47 +0100 -Message-ID: -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0) -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -Content-Length: 1311 -Lines: 39 - -Hi. - -Not sure if you ever resolved this: - -> I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -> Here is my problem, I have a table named 'test' with three fields: -> eid (integer), x (SYS.XMLTYPE) and formname (text) - -> I create a new statement handler with the following command: - -> $sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -> SYS.XMLTYPE.CREATEXML(?), ?"); - -.... - -> Invalid LOB locator specified -> ORA-06512: at "SYS.XMLTYPE", line 0 - -> Right now I've hacked the setup so there is a supplemental table -> called 'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE -> test SET x= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem -> like the right way to do this. - -> Is there any way to do what I want in the current version of -> DBI/OracleDBD? - -I don't think that the current DBI/DBD can bind a CLOB to a PL/SQL function -(which is all the CREATEXML function is) - hence you will have to go with -the intermediate CLOB table solution. - -Incidentally, if you are using Oracle9i - have you tried using a TEMPORARY -TABLE with a CLOB column (see SQL Reference Guide)? If setup correctly, this -is automatically truncated at the end of a transaction, is managed by the -Server, and provides some efficiency benefits. We use this here quite -effectively. - -Ben. - - diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index cd863cd9..9e610a68 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -11,6 +11,12 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; +{ + $DBD::Oracle::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Oracle database driver for the DBI module use DBI (); @@ -109,7 +115,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::dr; # ====== DRIVER ====== +{ package DBD::Oracle::dr; +{ + $DBD::Oracle::dr::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DRIVER ====== use strict; my %dbnames = (); # holds list of known databases (oratab + tnsnames) @@ -308,7 +320,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::db; # ====== DATABASE ====== +{ package DBD::Oracle::db; +{ + $DBD::Oracle::db::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DATABASE ====== use strict; use DBI qw(:sql_types); @@ -1000,7 +1018,13 @@ SQL } # end of package DBD::Oracle::db -{ package DBD::Oracle::st; # ====== STATEMENT ====== +{ package DBD::Oracle::st; +{ + $DBD::Oracle::st::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== STATEMENT ====== sub bind_param_inout_array { @@ -1094,9 +1118,18 @@ SQL 1; -__END__ +=pod + +=head1 NAME + +DBD::Oracle - Oracle database driver for the DBI module + +=head1 VERSION + +version 1.38 + =head1 SYNOPSIS use DBI; @@ -1110,7 +1143,6 @@ __END__ # for some advanced uses you may need Oracle type values: use DBD::Oracle qw(:ora_types); - =head1 DESCRIPTION DBD::Oracle is a Perl module which works with the DBI module to provide @@ -1218,7 +1250,6 @@ If port name is not specified, 1521 is the default. If service name is not speci The following examples show several ways a connection can be created: - $dbh = DBI->connect('dbi:Oracle:DB','username','password'); $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); @@ -1549,7 +1580,6 @@ DBDOxxxx where xxxx is the current version number. This value can be retrieved on the server side using V$SESSION_CONNECT_INFO or GV$SESSION_CONNECT_INFO - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); $dbh->{ora_driver_name} = $q; @@ -1720,7 +1750,6 @@ If the previous error was from a failed C due to a syntax error, this attribute gives the offset into the C attribute where the error was found. - =head4 ora_array_chunk_size Due to OCI limitations, DBD::Oracle needs to buffer up rows of @@ -1943,7 +1972,6 @@ DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. Starts a new session against the current database using the credentials supplied. - =head2 B $hashref = $dbh->private_attribute_info(); @@ -2071,7 +2099,6 @@ Implemented by DBI, no driver-specific impact. Implemented by DBI, no driver-specific impact. - =head2 B Type: boolean, inherited @@ -2080,7 +2107,6 @@ The CompatMode attribute is used by emulation layers (such as Oraperl) to enable It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. - =head1 ORACLE-SPECIFIC DATABASE HANDLE METHODS =head2 B @@ -2240,7 +2266,6 @@ The different types of placeholders cannot be mixed within a statement, but you use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. - =head2 B $sth = $dbh->prepare_cached($statement, \%attr); @@ -2259,7 +2284,6 @@ query was successful, returns undef if an error occurred, and returns -1 if the number of rows is unknown or not available. Note that this method will return B<0E0> instead of 0 for 'no rows were affected', in order to always return a true value if no error occurred. - =head2 B Oracle does not implement auto_increment of serial type columns it uses predefined @@ -2315,7 +2339,6 @@ If the script exits before disconnect is called (or, more precisely, if the data referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() methods automatically. It is best to explicitly disconnect rather than rely on this behavior. - =head2 B $rv = $dbh->ping; @@ -2664,7 +2687,6 @@ Examples: ## This executes the statement with 567 (integer) and "Zool" (varchar) $sth->execute(); - These attributes may be used in the C<\%attr> parameter of the L or L statement handle methods. @@ -2759,10 +2781,8 @@ Set L to 0 in prepare() to enable this behaviour. $rv = $sth->bind_param_inout($param_num, \$scalar, 0); - DBD::Oracle fully supports bind_param_inout below are some uses for this method. - =head3 B Oracle supports an extended SQL insert syntax which will return one @@ -2936,10 +2956,6 @@ the above example, the code would look something like this : ... } - - - - =head3 B DBD::Oracle has built-in support for B @@ -2974,13 +2990,11 @@ and B datatypes. The simple example is here: =item B -=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' +=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' will only take a reference to a scalar. =back - - =head3 B SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. @@ -3089,7 +3103,6 @@ you get: DBD::Oracle supports this undocumented feature of DBI. See L for an example. - =head2 B $rv = $sth->bind_param_array($param_num, $array_ref_or_value) @@ -3099,8 +3112,6 @@ DBD::Oracle supports this undocumented feature of DBI. See L method. - - =head2 B $rv = $sth->execute(@bind_values); @@ -3367,7 +3378,6 @@ However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch Only use scrollable cursors if you really have a good reason to. They do use up considerable more server and client resources and have poorer response times than non-scrolling cursors. - =head2 Enabling Scrollable Cursors To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; @@ -3383,7 +3393,6 @@ When the statement is executed you will then be able to use 'ora_fetch_scroll' m or you can still use any of the other fetch methods but with a poorer response time than if you used a non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. - =head2 Scrollable Cursor Methods The following driver-specific methods are used with scrollable cursors. @@ -3723,7 +3732,6 @@ You can tune this value by setting ora_oci_success_warn which will display the f In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. - =head3 Simple Fetch for CLOBs and BLOBs To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well @@ -4125,7 +4133,6 @@ Uses the Oracle OCILobTrim function. Returns the length of the LOB. Uses the Oracle OCILobGetLength function. - =item ora_lob_is_init $is_init = $dbh->ora_lob_is_init($lob_locator); @@ -4172,7 +4179,6 @@ lob_id field values, defined as follows: CREATE SEQUENCE lob_example_seq - =head3 Example: Inserting a new row with large data Unless enough memory is available to store and bind the @@ -4238,7 +4244,6 @@ can't be used effectively if AutoCommit is enabled). $offset += $length; } - In this example we demonstrate the use of ora_lob_write() interactively to append data to the columns 'bin_data' and 'char_data'. Had we used ora_lob_append(), we could have @@ -4255,7 +4260,6 @@ The scalar variables $offset and $length are no longer needed, because ora_lob_append() keeps track of the offset for us. - =head3 Example: Updating an existing row with large data In this example, we demonstrate a technique for overwriting @@ -4440,7 +4444,6 @@ WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other than US7ASCII, requires that the NLS_LANG environment variable be set. See the L<"Oracle UTF8 is not UTF-8"> section below. - You are strongly urged to read the Oracle Internationalization documentation specifically with respect the choices and trade offs for creating a databases for use with international character sets. @@ -4547,7 +4550,6 @@ If the C attribute is given to bind_param() then that determines if the value should be assumed to be in the default (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); ... $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); @@ -4588,7 +4590,6 @@ and TABLE in any combination. Support is seamless and recursive, meaning you need only supply a simple SQL statement to get all the values in an embedded object. You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. - Array example, given this type and table; CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); @@ -4741,7 +4742,6 @@ There are some types, like BOOLEAN, that Oracle does not automatically convert to or from strings (pity). These need to be converted explicitly using SQL or PL/SQL functions. - Examples: # DATE values @@ -4796,7 +4796,6 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" - =head4 Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special @@ -4944,7 +4943,6 @@ shows: } } - The cursor returned by the function C defined in the previous section can be fetched as a nested cursor as follows: @@ -5325,7 +5323,6 @@ There is a known problem with the 11.2g Oracle client and the C PL/SQL function. See L for the details. - =head1 SEE ALSO =over @@ -5393,4 +5390,34 @@ The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. The DBD::Oracle module is free open source software; you can redistribute it and/or modify it under the same terms as Perl 5. +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + + +__END__ + + diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 43331655..29ba9b1c 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,4 +1,10 @@ package DBD::Oracle::GetInfo; +{ + $DBD::Oracle::GetInfo::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Wrapper to get Oracle information use strict; @@ -315,4 +321,44 @@ our %info = ( 1; + + +=pod + +=head1 NAME + +DBD::Oracle::GetInfo - Wrapper to get Oracle information + +=head1 VERSION + +version 1.38 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + + __END__ diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 39a99498..f7a4850f 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,25 +1,70 @@ -package DBD::Oracle::Object; -# ABSTRACT: Wrapper for Oracle objects - -use strict; -use warnings; - -sub type_name { shift->{type_name} } - -sub attributes { @{shift->{attributes}} } - -sub attr_hash { - my $self = shift; - return $self->{attr_hash} ||= { $self->attributes }; -} - -sub attr { - my $self = shift; - if (@_) { - my $key = shift; - return $self->attr_hash->{$key}; - } - return $self->attr_hash; -} - -1; +package DBD::Oracle::Object; +{ + $DBD::Oracle::Object::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; +} +# ABSTRACT: Wrapper for Oracle objects + +use strict; +use warnings; + +sub type_name { shift->{type_name} } + +sub attributes { @{shift->{attributes}} } + +sub attr_hash { + my $self = shift; + return $self->{attr_hash} ||= { $self->attributes }; +} + +sub attr { + my $self = shift; + if (@_) { + my $key = shift; + return $self->attr_hash->{$key}; + } + return $self->attr_hash; +} + +1; + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Object - Wrapper for Oracle objects + +=head1 VERSION + +version 1.38 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 24855d20..c3c4b40a 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,8 +1,24 @@ package DBD::Oracle::Troubleshooting; +{ + $DBD::Oracle::Troubleshooting::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; +} #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle + +__END__ =pod +=head1 NAME + +DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle + +=head1 VERSION + +version 1.38 + =head1 CONNECTING TO ORACLE If you are reading this it is assumed that you have successfully @@ -29,7 +45,6 @@ For Windows the solution is to add this value to you PATH PATH=c:\app\oracle\product\xx.x.x;%PATH% - If you get past this stage and get a ORA-12154: TNS:could not resolve the connect identifier specified @@ -61,7 +76,6 @@ Protocol Adapter". If it generates any errors which look relevant then please talk to your Oracle technical support (and not the dbi-users mailing list). - =head1 USING THE LONG TYPES Some examples related to the use of LONG types are available in @@ -96,7 +110,6 @@ It turns out that now it is necessary to edit the same file and append this and then run "genclntsh", the libclntsh is properly generated and the linkage with DBD::Oracle proceeds properly. - =head2 cc1: invalid option `tune=pentium4'" error If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. @@ -153,7 +166,7 @@ To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY as you would for an install against 10g Standard Edition, Standard Edition One, or Enterprise Edition -=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 +=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 DBD::Oracle seems to hit some sort of bug with the above two versions of DB. The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also @@ -172,7 +185,6 @@ So far there is no patch for this but here are some work arounds or this way utf8::downgrade($parameter, 1); - =head1 CYGWIN @@ -335,4 +347,30 @@ oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + diff --git a/t/000-report-versions.t b/t/000-report-versions.t new file mode 100644 index 00000000..2d4a9a19 --- /dev/null +++ b/t/000-report-versions.t @@ -0,0 +1,446 @@ +#!perl +use warnings; +use strict; +use Test::More 0.94; + +# Include a cut-down version of YAML::Tiny so we don't introduce unnecessary +# dependencies ourselves. + +package Local::YAML::Tiny; + +use strict; +use Carp 'croak'; + +# UTF Support? +sub HAVE_UTF8 () { $] >= 5.007003 } +BEGIN { + if ( HAVE_UTF8 ) { + # The string eval helps hide this from Test::MinimumVersion + eval "require utf8;"; + die "Failed to load UTF-8 support" if $@; + } + + # Class structure + require 5.004; + $YAML::Tiny::VERSION = '1.40'; + + # Error storage + $YAML::Tiny::errstr = ''; +} + +# Printable characters for escapes +my %UNESCAPES = ( + z => "\x00", a => "\x07", t => "\x09", + n => "\x0a", v => "\x0b", f => "\x0c", + r => "\x0d", e => "\x1b", '\\' => '\\', +); + + +##################################################################### +# Implementation + +# Create an empty YAML::Tiny object +sub new { + my $class = shift; + bless [ @_ ], $class; +} + +# Create an object from a file +sub read { + my $class = ref $_[0] ? ref shift : shift; + + # Check the file + my $file = shift or return $class->_error( 'You did not specify a file name' ); + return $class->_error( "File '$file' does not exist" ) unless -e $file; + return $class->_error( "'$file' is a directory, not a file" ) unless -f _; + return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; + + # Slurp in the file + local $/ = undef; + local *CFG; + unless ( open(CFG, $file) ) { + return $class->_error("Failed to open file '$file': $!"); + } + my $contents = ; + unless ( close(CFG) ) { + return $class->_error("Failed to close file '$file': $!"); + } + + $class->read_string( $contents ); +} + +# Create an object from a string +sub read_string { + my $class = ref $_[0] ? ref shift : shift; + my $self = bless [], $class; + my $string = $_[0]; + unless ( defined $string ) { + return $self->_error("Did not provide a string to load"); + } + + # Byte order marks + # NOTE: Keeping this here to educate maintainers + # my %BOM = ( + # "\357\273\277" => 'UTF-8', + # "\376\377" => 'UTF-16BE', + # "\377\376" => 'UTF-16LE', + # "\377\376\0\0" => 'UTF-32LE' + # "\0\0\376\377" => 'UTF-32BE', + # ); + if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) { + return $self->_error("Stream has a non UTF-8 BOM"); + } else { + # Strip UTF-8 bom if found, we'll just ignore it + $string =~ s/^\357\273\277//; + } + + # Try to decode as utf8 + utf8::decode($string) if HAVE_UTF8; + + # Check for some special cases + return $self unless length $string; + unless ( $string =~ /[\012\015]+\z/ ) { + return $self->_error("Stream does not end with newline character"); + } + + # Split the file into lines + my @lines = grep { ! /^\s*(?:\#.*)?\z/ } + split /(?:\015{1,2}\012|\015|\012)/, $string; + + # Strip the initial YAML header + @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; + + # A nibbling parser + while ( @lines ) { + # Do we have a document header? + if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { + # Handle scalar documents + shift @lines; + if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { + push @$self, $self->_read_scalar( "$1", [ undef ], \@lines ); + next; + } + } + + if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { + # A naked document + push @$self, undef; + while ( @lines and $lines[0] !~ /^---/ ) { + shift @lines; + } + + } elsif ( $lines[0] =~ /^\s*\-/ ) { + # An array at the root + my $document = [ ]; + push @$self, $document; + $self->_read_array( $document, [ 0 ], \@lines ); + + } elsif ( $lines[0] =~ /^(\s*)\S/ ) { + # A hash at the root + my $document = { }; + push @$self, $document; + $self->_read_hash( $document, [ length($1) ], \@lines ); + + } else { + croak("YAML::Tiny failed to classify the line '$lines[0]'"); + } + } + + $self; +} + +# Deparse a scalar string to the actual scalar +sub _read_scalar { + my ($self, $string, $indent, $lines) = @_; + + # Trim trailing whitespace + $string =~ s/\s*\z//; + + # Explitic null/undef + return undef if $string eq '~'; + + # Quotes + if ( $string =~ /^\'(.*?)\'\z/ ) { + return '' unless defined $1; + $string = $1; + $string =~ s/\'\'/\'/g; + return $string; + } + if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) { + # Reusing the variable is a little ugly, + # but avoids a new variable and a string copy. + $string = $1; + $string =~ s/\\"/"/g; + $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; + return $string; + } + + # Special cases + if ( $string =~ /^[\'\"!&]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + return {} if $string eq '{}'; + return [] if $string eq '[]'; + + # Regular unquoted string + return $string unless $string =~ /^[>|]/; + + # Error + croak("YAML::Tiny failed to find multi-line scalar content") unless @$lines; + + # Check the indent depth + $lines->[0] =~ /^(\s*)/; + $indent->[-1] = length("$1"); + if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Pull the lines + my @multiline = (); + while ( @$lines ) { + $lines->[0] =~ /^(\s*)/; + last unless length($1) >= $indent->[-1]; + push @multiline, substr(shift(@$lines), length($1)); + } + + my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; + my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; + return join( $j, @multiline ) . $t; +} + +# Parse an array +sub _read_array { + my ($self, $array, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { + # Inline nested hash + my $indent2 = length("$1"); + $lines->[0] =~ s/-/ /; + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { + # Array entry with a value + shift @$lines; + push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { + shift @$lines; + unless ( @$lines ) { + push @$array, undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)\-/ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] == $indent2 ) { + # Null array entry + push @$array, undef; + } else { + # Naked indenter + push @$array, [ ]; + $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines ); + } + + } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines ); + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + + } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { + # This is probably a structure like the following... + # --- + # foo: + # - list + # bar: value + # + # ... so lets return and let the hash parser handle it + return 1; + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + } + + return 1; +} + +# Parse an array +sub _read_hash { + my ($self, $hash, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Get the key + unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { + if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + my $key = $1; + + # Do we have a value? + if ( length $lines->[0] ) { + # Yes + $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines ); + } else { + # An indent + shift @$lines; + unless ( @$lines ) { + $hash->{$key} = undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)-/ ) { + $hash->{$key} = []; + $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } elsif ( $lines->[0] =~ /^(\s*)./ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] >= $indent2 ) { + # Null hash entry + $hash->{$key} = undef; + } else { + $hash->{$key} = {}; + $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } + } + } + } + + return 1; +} + +# Set error +sub _error { + $YAML::Tiny::errstr = $_[1]; + undef; +} + +# Retrieve error +sub errstr { + $YAML::Tiny::errstr; +} + + + +##################################################################### +# Use Scalar::Util if possible, otherwise emulate it + +BEGIN { + eval { + require Scalar::Util; + }; + if ( $@ ) { + # Failed to load Scalar::Util + eval <<'END_PERL'; +sub refaddr { + my $pkg = ref($_[0]) or return undef; + if (!!UNIVERSAL::can($_[0], 'can')) { + bless $_[0], 'Scalar::Util::Fake'; + } else { + $pkg = undef; + } + "$_[0]" =~ /0x(\w+)/; + my $i = do { local $^W; hex $1 }; + bless $_[0], $pkg if defined $pkg; + $i; +} +END_PERL + } else { + Scalar::Util->import('refaddr'); + } +} + + +##################################################################### +# main test +##################################################################### + +package main; + +BEGIN { + + # Skip modules that either don't want to be loaded directly, such as + # Module::Install, or that mess with the test count, such as the Test::* + # modules listed here. + # + # Moose::Role conflicts if Moose is loaded as well, but Moose::Role is in + # the Moose distribution and it's certain that someone who uses + # Moose::Role also uses Moose somewhere, so if we disallow Moose::Role, + # we'll still get the relevant version number. + + my %skip = map { $_ => 1 } qw( + App::FatPacker + Class::Accessor::Classy + Devel::Cover + Module::Install + Moose::Role + POE::Loop::Tk + Template::Test + Test::Kwalitee + Test::Pod::Coverage + Test::Portability::Files + Test::YAML::Meta + ); + + my $Test = Test::Builder->new; + + $Test->plan(skip_all => "META.yml could not be found") + unless -f 'META.yml' and -r _; + + my $meta = (Local::YAML::Tiny->read('META.yml'))->[0]; + my %requires; + for my $require_key (grep { /requires/ } keys %$meta) { + my %h = %{ $meta->{$require_key} }; + $requires{$_}++ for keys %h; + } + delete $requires{perl}; + + diag("Testing with Perl $], $^X"); + for my $module (sort keys %requires) { + if ($skip{$module}) { + note "$module doesn't want to be loaded directly, skipping"; + next; + } + local $SIG{__WARN__} = sub { note "$module: $_[0]" }; + use_ok $module or BAIL_OUT("can't load $module"); + my $version = $module->VERSION; + $version = 'undefined' unless defined $version; + diag(" $module version is $version"); + } + done_testing; +} diff --git a/xt/changes.t b/xt/changes.t deleted file mode 100644 index 27a4808a..00000000 --- a/xt/changes.t +++ /dev/null @@ -1,8 +0,0 @@ -use strict; -use warnings; - -use Test::More; - -eval 'use Test::CPAN::Changes'; -plan skip_all => 'Test::CPAN::Changes required for this test' if $@; -changes_ok(); diff --git a/xt/manifest.t b/xt/manifest.t deleted file mode 100644 index 00df9957..00000000 --- a/xt/manifest.t +++ /dev/null @@ -1,21 +0,0 @@ -use strict; -use warnings; - -use ExtUtils::Manifest qw/ fullcheck /; - -use Test::More tests => 1; - -my ( $missing, $extra ) = do { - local *STDERR; - - # hush little baby, don't you cry - open STDERR, '>', \my $stderr; - - fullcheck(); -}; - -ok @$missing + @$extra == 0, 'manifest in sync' or do { - diag "missing files:\n", map { " \t $_\n " } @$missing if @$missing; - diag "extra files: \n", map { "\t$_\n" } @$extra if @$extra; -}; - diff --git a/xt/pod.t b/xt/pod.t deleted file mode 100644 index 66481225..00000000 --- a/xt/pod.t +++ /dev/null @@ -1,11 +0,0 @@ -use Test::More; - -eval "use Test::Pod"; - -plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; - -pod_file_ok( 'Oracle.pm' ); -pod_file_ok( 'lib/DBD/Oracle/Object.pm' ); -pod_file_ok( 'lib/DBD/Oracle/GetInfo.pm' ); - -done_testing; From f1660e270afc4650015f1adae6b3cc6149f08a5e Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 2 Feb 2012 21:48:51 +0000 Subject: [PATCH 120/637] fix ::GetInfo NAME line git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15122 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 ++++++- META.json | 18 +++++++++--------- META.yml | 16 ++++++++-------- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 10 +++++----- lib/DBD/Oracle/GetInfo.pm | 7 ++++--- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pm | 4 ++-- 9 files changed, 38 insertions(+), 32 deletions(-) diff --git a/Changes b/Changes index dd8ddb41..3c4e27fb 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.38 2012-02-02 [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED @@ -11,6 +11,11 @@ Revision history for DBD::Oracle [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work on Lion. (Martin J. Evans) + - Fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt7400] + + [OTHERS] + - change the shebang line of examples to the more modern '/usr/bin/env perl' + [RT74001] [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' diff --git a/META.json b/META.json index 3ce64a33..3af05f40 100644 --- a/META.json +++ b/META.json @@ -51,34 +51,34 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.37_00" + "version" : "1.38" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.37_00" + "version" : "1.38" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.37_00" + "version" : "1.38" }, "DBD::Oracle::Troubleshooting" : { "file" : "lib/DBD/Oracle/Troubleshooting.pm", - "version" : "1.37_00" + "version" : "1.38" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.37_00" + "version" : "1.38" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.37_00" + "version" : "1.38" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.37_00" + "version" : "1.38" } }, - "release_status" : "testing", + "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -91,7 +91,7 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, - "version" : "1.37_00", + "version" : "1.38", "x_authority" : "cpan:PYTHIAN" } diff --git a/META.yml b/META.yml index 7247e13c..c1c09bd4 100644 --- a/META.yml +++ b/META.yml @@ -29,25 +29,25 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.37_00 + version: 1.38 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.37_00 + version: 1.38 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.37_00 + version: 1.38 DBD::Oracle::Troubleshooting: file: lib/DBD/Oracle/Troubleshooting.pm - version: 1.37_00 + version: 1.38 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.37_00 + version: 1.38 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.37_00 + version: 1.38 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.37_00 + version: 1.38 requires: DBI: 0 DynaLoader: 0 @@ -59,5 +59,5 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.37_00 +version: 1.38 x_authority: cpan:PYTHIAN diff --git a/README b/README index 55a6595b..bf8f7b60 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.37_00 + version 1.38 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index 111d9c54..efd36615 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.37_00 +version 1.38 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 48127036..9e610a68 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.37_00'; + $DBD::Oracle::VERSION = '1.38'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -117,7 +117,7 @@ BEGIN { { package DBD::Oracle::dr; { - $DBD::Oracle::dr::VERSION = '1.37_00'; + $DBD::Oracle::dr::VERSION = '1.38'; } BEGIN { $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; @@ -322,7 +322,7 @@ BEGIN { { package DBD::Oracle::db; { - $DBD::Oracle::db::VERSION = '1.37_00'; + $DBD::Oracle::db::VERSION = '1.38'; } BEGIN { $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; @@ -1020,7 +1020,7 @@ SQL { package DBD::Oracle::st; { - $DBD::Oracle::st::VERSION = '1.37_00'; + $DBD::Oracle::st::VERSION = '1.38'; } BEGIN { $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; @@ -1128,7 +1128,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.37_00 +version 1.38 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 49abb12d..29ba9b1c 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,10 +1,11 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.37_00'; + $DBD::Oracle::GetInfo::VERSION = '1.38'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; } +# ABSTRACT: Wrapper to get Oracle information use strict; use DBD::Oracle(); @@ -326,11 +327,11 @@ our %info = ( =head1 NAME -DBD::Oracle::GetInfo +DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.37_00 +version 1.38 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 7075c84c..f7a4850f 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.37_00'; + $DBD::Oracle::Object::VERSION = '1.38'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.37_00 +version 1.38 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 3a129ef4..c3c4b40a 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Troubleshooting; { - $DBD::Oracle::Troubleshooting::VERSION = '1.37_00'; + $DBD::Oracle::Troubleshooting::VERSION = '1.38'; } BEGIN { $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; @@ -17,7 +17,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.37_00 +version 1.38 =head1 CONNECTING TO ORACLE From e63e147f4fec1917b2b6dff8a0c87dc19e475476 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 2 Feb 2012 21:50:15 +0000 Subject: [PATCH 121/637] typos git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15123 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 ++- lib/DBD/Oracle/Troubleshooting.pm | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 3c4e27fb..7c3e8305 100644 --- a/Changes +++ b/Changes @@ -11,7 +11,8 @@ Revision history for DBD::Oracle [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work on Lion. (Martin J. Evans) - - Fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt7400] + - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] + - fix typos. (patch by Julián Moreno Patiño) [rt73999] [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index c3c4b40a..96f153ef 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -304,11 +304,11 @@ in the first table in above list, and not as one would normally expect in the process table. Installing DBI and DBD::Oracle has influence upon this since in -both cases a few enviroment variables are read or set in the +both cases a few environment variables are read or set in the test phase. For DBI it is the logical SYS$SCRATCH, which is a JOB logical. For DBD-Oracle it is when testing a new feature in the Oracle -RDBMS: UTF8 and UTF16 character set functionallity, and in order +RDBMS: UTF8 and UTF16 character set functionality, and in order to do this it sets and unsets the related environment variables NLS_NCHAR and NLS_LANG. From 4f526a667b1c4b69a04a84a716c4085822a026cb Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 8 Feb 2012 15:26:30 -0500 Subject: [PATCH 122/637] utf8 encoding for PL/SQL procs --- Changes | 2 + dbdimp.c | 7 ++++ t/rt74753-utf8-encoded.t | 86 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 t/rt74753-utf8-encoded.t diff --git a/Changes b/Changes index a5226ce2..b2a2b58c 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,8 @@ Revision history for DBD::Oracle [RT73798] - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) [RT74544] + - PL/SQL out values were not utf8 encoded [RT74753] + (Steve Baldwin + Martin J. Evans) [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work diff --git a/dbdimp.c b/dbdimp.c index 9d4cc658..87e36826 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3198,6 +3198,13 @@ dbd_phs_sv_complete(phs_t *phs, SV *sv, I32 debug) SvCUR_set(sv, phs->alen); *SvEND(sv) = '\0'; SvPOK_only_UTF8(sv); + if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { +#ifdef sv_utf8_decode + sv_utf8_decode(sv); +#else + SvUTF8_on(sv); +#endif + } } else { /* shouldn't happen */ debug = 2; diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t new file mode 100644 index 00000000..ae318ad2 --- /dev/null +++ b/t/rt74753-utf8-encoded.t @@ -0,0 +1,86 @@ +#!/usr/bin/perl -w + +use strict; +use warnings; + +use Test::More tests => 2; + +use DBI; +use Encode; + +unshift @INC ,'t'; +require 'nchar_test_lib.pl'; + +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; + +$ENV{NLS_LANG} = 'AMERICAN_AMERICA.UTF8'; +$ENV{NLS_NCHAR} = 'UTF8'; + +my $dbh = DBI->connect( $dsn, $dbuser, '', { + PrintError => 0, AutoCommit => 0, RaiseError => 1, +},); + +$dbh->do(q(alter session set nls_territory = 'GERMANY')); + +my $sth = $dbh->prepare(<<"END_SQL"); + SELECT ltrim(rtrim(to_char(0, 'L'))) FROM dual +END_SQL + +$sth->execute; + +my ($val); +$sth->bind_columns( \($val) ); + +$sth->fetch; + +is Encode::is_utf8($val) => 1, "utf8 encoded"; + +$sth->finish; + +$val = undef; + +$sth = $dbh->prepare(<<'END_SQL'); +declare + l_ret varchar2(10); +begin + select ltrim(rtrim(to_char(0, 'L'))) + into l_ret + from dual; + -- + :ret := l_ret; +end; +END_SQL + +$sth->bind_param_inout(':ret', \$val, 100); +$sth->execute; + +is Encode::is_utf8($val) => 1, "utf8 encoded"; + +$dbh->disconnect; + + +__END__ + +undef $val; + +$sth = $dbh->prepare(<<'END_SQL'); +declare + l_ret varchar2(10); +begin + select ltrim(rtrim(to_char(0, 'L'))) + into l_ret + from dual; + -- + :ret := l_ret; +end; +END_SQL + +$sth->bind_param_inout( ':ret', \$val, 100 ); +$sth->execute; + +diag "val=[$val] len=@{[ length($val) ]}" while $sth->fetch; + +diag "utf8 is ", Encode::is_utf8($val) ? 'on' : 'off'; + +$dbh->disconnect; From 2714d0ffe473d67fcc0a3db7a3f5eb69847d5b9a Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 8 Feb 2012 15:45:27 -0500 Subject: [PATCH 123/637] Build results of 4f526a6 (on master) --- .gitignore | 14 - Changes | 2 +- INSTALL | 44 + LICENSE | 377 ++ MANIFEST | 1 + MANIFEST.SKIP | 32 - META.json | 97 + META.yml | 63 + README | 4338 ++++++++++++++- README.mkdn | 4228 +++++++++++++++ dist.ini | 22 - err_bind/err_bind_param_inout_overrun_bug.msg | 108 - err_bind/err_bindarrays.msg | 241 - err_bind/err_bindclobleak.msg | 58 - err_bind/err_bindnullhash.msg | 77 - err_bind/err_trailingblank.msg | 345 -- err_build/err_aix64.msg | 142 - err_build/err_hpux_ld.msg | 89 - err_build/err_hpuxsuccess.msg | 279 - err_build/err_instantclient.msg | 207 - err_build/err_makefileundef.msg | 87 - err_build/err_memleak.msg | 95 - err_build/err_solarisnotes.msg | 482 -- err_build/err_testfailnotable.msg | 97 - err_docs/err_trace.msg | 14 - err_lob/err_csr_clob.msg | 65 - err_lob/err_loblenwide.msg | 95 - err_lob/err_lobtesttblfail.msg | 208 - err_lob/err_nclob_form.msg | 189 - err_lob/err_nulllobsegv.msg | 93 - err_lob/err_tmplobfree.msg | 537 -- err_unicode/err_char.msg | 129 - err_unicode/err_twolongstr.msg | 1256 ----- err_unsorted/err_etherreal.msg | 90 - err_unsorted/err_memleak2.msg | 476 -- err_unsorted/err_multiora.msg | 470 -- err_unsorted/err_ora9ir2oci.msg | 27 - err_unsorted/err_ref_type.msg | 115 - err_unsorted/err_refcsr_rowcache.msg | 85 - err_unsorted/err_refcsr_slow.msg | 347 -- err_unsorted/err_slowcsr.msg | 316 -- err_unsorted/err_svrparse.msg | 4717 ----------------- err_unsorted/err_xml.msg | 118 - err_unsorted/err_xml2.msg | 700 --- err_unsorted/err_xmltypebindplsql.msg | 174 - lib/DBD/Oracle.pm | 109 +- lib/DBD/Oracle/GetInfo.pm | 46 + lib/DBD/Oracle/Object.pm | 95 +- lib/DBD/Oracle/Troubleshooting.pm | 48 +- t/000-report-versions.t | 446 ++ xt/changes.t | 8 - xt/manifest.t | 21 - xt/pod.t | 11 - 53 files changed, 9594 insertions(+), 12936 deletions(-) delete mode 100644 .gitignore create mode 100644 INSTALL create mode 100644 LICENSE delete mode 100644 MANIFEST.SKIP create mode 100644 META.json create mode 100644 META.yml create mode 100644 README.mkdn delete mode 100644 dist.ini delete mode 100644 err_bind/err_bind_param_inout_overrun_bug.msg delete mode 100644 err_bind/err_bindarrays.msg delete mode 100644 err_bind/err_bindclobleak.msg delete mode 100644 err_bind/err_bindnullhash.msg delete mode 100644 err_bind/err_trailingblank.msg delete mode 100644 err_build/err_aix64.msg delete mode 100644 err_build/err_hpux_ld.msg delete mode 100644 err_build/err_hpuxsuccess.msg delete mode 100644 err_build/err_instantclient.msg delete mode 100644 err_build/err_makefileundef.msg delete mode 100644 err_build/err_memleak.msg delete mode 100644 err_build/err_solarisnotes.msg delete mode 100644 err_build/err_testfailnotable.msg delete mode 100644 err_docs/err_trace.msg delete mode 100644 err_lob/err_csr_clob.msg delete mode 100644 err_lob/err_loblenwide.msg delete mode 100644 err_lob/err_lobtesttblfail.msg delete mode 100644 err_lob/err_nclob_form.msg delete mode 100644 err_lob/err_nulllobsegv.msg delete mode 100644 err_lob/err_tmplobfree.msg delete mode 100644 err_unicode/err_char.msg delete mode 100644 err_unicode/err_twolongstr.msg delete mode 100644 err_unsorted/err_etherreal.msg delete mode 100644 err_unsorted/err_memleak2.msg delete mode 100644 err_unsorted/err_multiora.msg delete mode 100644 err_unsorted/err_ora9ir2oci.msg delete mode 100644 err_unsorted/err_ref_type.msg delete mode 100644 err_unsorted/err_refcsr_rowcache.msg delete mode 100644 err_unsorted/err_refcsr_slow.msg delete mode 100644 err_unsorted/err_slowcsr.msg delete mode 100644 err_unsorted/err_svrparse.msg delete mode 100644 err_unsorted/err_xml.msg delete mode 100644 err_unsorted/err_xml2.msg delete mode 100644 err_unsorted/err_xmltypebindplsql.msg create mode 100644 t/000-report-versions.t delete mode 100644 xt/changes.t delete mode 100644 xt/manifest.t delete mode 100644 xt/pod.t diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 15e927c8..00000000 --- a/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -pm_to_blib -MYMETA.yml -Makefile -Makefile.old -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -blib -MYMETA.json -dbdimp.o -mk.pm -oci8.o -DBD-Oracle* diff --git a/Changes b/Changes index b2a2b58c..45beb272 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.38 2012-02-08 [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..b5ab17a0 --- /dev/null +++ b/INSTALL @@ -0,0 +1,44 @@ + +This is the Perl distribution DBD-Oracle. + +Installing DBD-Oracle is straightforward. + +## Installation with cpanm + +If you have cpanm, you only need one line: + + % cpanm DBD::Oracle + +If you are installing into a system-wide directory, you may need to pass the +"-S" flag to cpanm, which uses sudo to install the module: + + % cpanm -S DBD::Oracle + +## Installing with the CPAN shell + +Alternatively, if your CPAN shell is set up, you should just be able to do: + + % cpan DBD::Oracle + +## Manual installation + +As a last resort, you can manually install it. Download the tarball, untar it, +then build it: + + % perl Makefile.PL + % make && make test + +Then install it: + + % make install + +If you are installing into a system-wide directory, you may need to run: + + % sudo make install + +## Documentation + +DBD-Oracle documentation is available as POD. +You can run perldoc from a shell to read the documentation: + + % perldoc DBD::Oracle diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..a6a371c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,377 @@ +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +Terms of the Perl programming language system itself + +a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or +b) the "Artistic License" + +--- The GNU General Public License, Version 1, February 1989 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The GNU General Public License, Version 1, February 1989 + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! + + +--- The Artistic License 1.0 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The Artistic License 1.0 + +The Artistic License + +Preamble + +The intent of this document is to state the conditions under which a Package +may be copied, such that the Copyright Holder maintains some semblance of +artistic control over the development of the package, while giving the users of +the package the right to use and distribute the Package in a more-or-less +customary fashion, plus the right to make reasonable modifications. + +Definitions: + + - "Package" refers to the collection of files distributed by the Copyright + Holder, and derivatives of that collection of files created through + textual modification. + - "Standard Version" refers to such a Package if it has not been modified, + or has been modified in accordance with the wishes of the Copyright + Holder. + - "Copyright Holder" is whoever is named in the copyright or copyrights for + the package. + - "You" is you, if you're thinking about copying or distributing this Package. + - "Reasonable copying fee" is whatever you can justify on the basis of media + cost, duplication charges, time of people involved, and so on. (You will + not be required to justify it to the Copyright Holder, but only to the + computing community at large as a market that must bear the fee.) + - "Freely Available" means that no fee is charged for the item itself, though + there may be fees involved in handling the item. It also means that + recipients of the item may redistribute it under the same conditions they + received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications derived +from the Public Domain or from the Copyright Holder. A Package modified in such +a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided that +you insert a prominent notice in each changed file stating how and when you +changed that file, and provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major archive site + such as ftp.uu.net, or by allowing the Copyright Holder to include your + modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict with + standard executables, which must also be provided, and provide a separate + manual page for each non-standard executable that clearly documents how it + differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or executable +form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where to + get the Standard Version. + + b) accompany the distribution with the machine-readable source of the Package + with your modifications. + + c) accompany any non-standard executables with their corresponding Standard + Version executables, giving the non-standard executables non-standard + names, and clearly documenting the differences in manual pages (or + equivalent), together with instructions on where to get the Standard + Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. You +may not charge a fee for this Package itself. However, you may distribute this +Package in aggregate with other (possibly commercial) programs as part of a +larger (possibly commercial) software distribution provided that you do not +advertise this Package as a product of your own. + +6. The scripts and library files supplied as input to or produced as output +from the programs of this Package do not automatically fall under the copyright +of this Package, but belong to whomever generated them, and may be sold +commercially, and may be aggregated with this Package. + +7. C or perl subroutines supplied by you and linked into this Package shall not +be considered part of this Package. + +8. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +The End + diff --git a/MANIFEST b/MANIFEST index 436c409e..34c7a9d4 100644 --- a/MANIFEST +++ b/MANIFEST @@ -89,5 +89,6 @@ t/70meta.t t/80ora_charset.t t/nchar_test_lib.pl t/rt13865.t +t/rt74753-utf8-encoded.t test.pl typemap diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP deleted file mode 100644 index c7db4c66..00000000 --- a/MANIFEST.SKIP +++ /dev/null @@ -1,32 +0,0 @@ -^DBD-Oracle-.* -\.svn\b -\.orig$ -\..*.swp$ -^.pure -^DIST/ -^MANIFEST\. -^Makefile$ -^blib/ -^csr/ -^err[/_] -^old/ -^info/ -^oci8/ -^oracle/ -^tags$ -~$ -^\.git -^xt -dbdimp.o -Makefile.old -mk.pm -MYMETA.json -MYMETA.yml -oci8.o -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -pm_to_blib - -dist.ini diff --git a/META.json b/META.json new file mode 100644 index 00000000..3af05f40 --- /dev/null +++ b/META.json @@ -0,0 +1,97 @@ +{ + "abstract" : "Oracle database driver for the DBI module", + "author" : [ + "Tim Bunce ", + "John Scoles", + "Yanick Champoux " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "DBD-Oracle", + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "6.30" + } + }, + "runtime" : { + "requires" : { + "DBI" : 0, + "DynaLoader" : 0, + "Exporter" : 0, + "perl" : "5.006", + "strict" : 0, + "warnings" : 0 + } + }, + "test" : { + "requires" : { + "Carp" : 0, + "Config" : 0, + "Data::Dumper" : 0, + "Devel::Peek" : 0, + "Encode" : 0, + "Math::BigInt" : 0, + "Oraperl" : 0, + "Scalar::Util" : 0, + "Test::More" : "0.94", + "Thread::Semaphore" : 0, + "utf8" : 0, + "vars" : 0 + } + } + }, + "provides" : { + "DBD::Oracle" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::GetInfo" : { + "file" : "lib/DBD/Oracle/GetInfo.pm", + "version" : "1.38" + }, + "DBD::Oracle::Object" : { + "file" : "lib/DBD/Oracle/Object.pm", + "version" : "1.38" + }, + "DBD::Oracle::Troubleshooting" : { + "file" : "lib/DBD/Oracle/Troubleshooting.pm", + "version" : "1.38" + }, + "DBD::Oracle::db" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::dr" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::st" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "mailto" : "bug-dbd-oracle at rt.cpan.org", + "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle" + }, + "homepage" : "http://search.cpan.org/dist/DBD-Oracle/", + "repository" : { + "type" : "git", + "url" : "git://github.com/yanick/DBD-Oracle.git", + "web" : "http://github.com/yanick/DBD-Oracle/tree" + } + }, + "version" : "1.38", + "x_authority" : "cpan:PYTHIAN" +} + diff --git a/META.yml b/META.yml new file mode 100644 index 00000000..c1c09bd4 --- /dev/null +++ b/META.yml @@ -0,0 +1,63 @@ +--- +abstract: 'Oracle database driver for the DBI module' +author: + - 'Tim Bunce ' + - 'John Scoles' + - 'Yanick Champoux ' +build_requires: + Carp: 0 + Config: 0 + Data::Dumper: 0 + Devel::Peek: 0 + Encode: 0 + Math::BigInt: 0 + Oraperl: 0 + Scalar::Util: 0 + Test::More: 0.94 + Thread::Semaphore: 0 + utf8: 0 + vars: 0 +configure_requires: + ExtUtils::MakeMaker: 6.30 +dynamic_config: 0 +generated_by: 'Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: DBD-Oracle +provides: + DBD::Oracle: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::GetInfo: + file: lib/DBD/Oracle/GetInfo.pm + version: 1.38 + DBD::Oracle::Object: + file: lib/DBD/Oracle/Object.pm + version: 1.38 + DBD::Oracle::Troubleshooting: + file: lib/DBD/Oracle/Troubleshooting.pm + version: 1.38 + DBD::Oracle::db: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::dr: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::st: + file: lib/DBD/Oracle.pm + version: 1.38 +requires: + DBI: 0 + DynaLoader: 0 + Exporter: 0 + perl: 5.006 + strict: 0 + warnings: 0 +resources: + bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle + homepage: http://search.cpan.org/dist/DBD-Oracle/ + repository: git://github.com/yanick/DBD-Oracle.git +version: 1.38 +x_authority: cpan:PYTHIAN diff --git a/README b/README index fd2b28aa..bf8f7b60 100644 --- a/README +++ b/README @@ -1,301 +1,4183 @@ +NAME + DBD::Oracle - Oracle database driver for the DBI module -DBD::Oracle -- an Oracle interface for Perl 5. +VERSION + version 1.38 - Copyright (c) 1994-2006 Tim Bunce, Ireland. +SYNOPSIS + use DBI; - See the COPYRIGHT section in the Oracle.pm file for terms. - See also the MAINTAINER section in the Oracle.pm + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); - PLEASE READ THE ENTIRE README FILE CAREFULLY ! + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); - AND THEN READ ANY README.* FILES RELEVANT TO YOUR PLATFORM: + # See the DBI module documentation for full details - README.aix.txt - AIX - README.hpux.txt - HP-UX - README.java.txt - Java/thread problem on Solaris - README.macosx.txt - Mac OS/X - README.win32.txt - MS Windows - README.wingcc.txt - MS Windows using GCC - README.* - see if there's a file for your platform + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); - You may find these useful +DESCRIPTION + DBD::Oracle is a Perl module which works with the DBI module to provide + access to Oracle databases. - README.help.txt - Help and hints on build problems - README.sec.txt - Oracle security issues to be aware of - README.login.txt - Help on how to connect to Oracle - README.longs.txt - Help on handling LONGs - README.clients.txt - What Oracle client files you need installed + This documentation describes driver specific behaviour and restrictions. + It is not supposed to be used as the only reference for the user. In any + case consult the DBI documentation first! +CONSTANTS + :ora_session_modes + ORA_SYSDBA ORA_SYSOPER ORA_SYSASM -*** QUICK START GUIDE: + :ora_types + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN - The DBI requires one or more 'driver' modules to talk to databases. - Fetch, build and install the DBI module as per its README file. - You may then delete its source directory tree since it's no longer needed. - Use the 'perldoc DBI' command to read the DBI documentation. + SQLCS_IMPLICIT + SQLCS_NCHAR + SQLCS_IMPLICIT and SQLCS_NCHAR are *character set form* values. See + notes about Unicode elsewhere in this document. - Fetch this DBD::Oracle driver module and unpack it. - Follow the guidelines in this README file carefully. + SQLT_INT + SQLT_FLT + These types are used only internally, and may be specified as + internal bind type for ORA_NUMBER_TABLE. See notes about + ORA_NUMBER_TABLE elsewhere in this document + ORA_OCI + Oracle doesn't provide a formal API for determining the exact + version number of the OCI client library used, so DBD::Oracle has to + go digging (and sometimes has to more or less guess). The ORA_OCI + constant holds the result of that process. -*** *BEFORE* BUILDING, TESTING AND INSTALLING DBD::Oracle: + In string context ORA_OCI returns the full "A.B.C.D" version string. - Build, test and install Perl 5 (at least 5.6.1) - It is very important to TEST it and INSTALL it! + In numeric context ORA_OCI returns the major.minor version number + (8.1, 9.2, 10.0 etc). But note that version numbers are not actually + floating point and so if Oracle ever makes a release that has a two + digit minor version, such as 9.10 it will have a lower numeric value + than the preceding 9.9 release. So use with care. - Build, test and install the DBI module (at least DBI 1.51). - It is very important to TEST it and INSTALL it! + The contents and format of ORA_OCI are subject to change (it may, + for example, become a *version object* in later releases). I + recommend that you avoid checking for exact values. - Remember to *read* the DBI README file and this one CAREFULLY! + :ora_fetch_orient + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE - Install enough Oracle software to enable DBD::Oracle to build. + These constants are used to set the orientation of a fetch on a + scrollable cursor. - For Oracle Instant Client: that means install the following packages: - * The "Basic" package for the essential Oracle libraries. - * The "SDK" package for the headers and makefile. - * The "SQL*Plus" component is optional, but will help you check - your configuration and DBD::Oracle determine your Oracle version. + :ora_exe_modes + OCI_STMT_SCROLLABLE_READONLY - For full Oracle installs: that usually includes Pro*C and SQL*Net. - (That's not very specific because it varies between Oracle releases.). - As of release 1.22 support of Oracle clients before 9 was dropped. - The main reason for this is that next few versions of DBD::Oracle will introduce a number of new features - whicht will required a great deal of extra coding to make the OCI 8 work. - As well it is getting harder to find an Oracle client 8 to test against as well - Oracle no longer supports clients before 9. + :ora_fail_over + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL - The ORACLE_HOME environment variable must point to the Oracle Home - used to create DBD::Oracle. (Not essential under MS Windows). +DBI CLASS METHODS + connect + This method creates a database handle by connecting to a database, and + is the DBI equivalent of the "new" method. To open a connection to an + Oracle database you need to specify a database connection string (URL), + username and password. -*** MOST IMPORTANTLY: + The connection string is always of the form: "dbi:Oracle:" There are several ways to identify a database: - Make sure Oracle is working and you can use the Oracle sqlplus - command to talk to the database from the machine you - want to build DBD::Oracle on. This often involves setting - environment variables like PATH, LD_LIBRARY_PATH, TWO_TASK etc. - Consult Oracle documentation for more details. + 1 If the database is local, specifying the SID or service name will be + enough. - Only once you can connect to Oracle using sqlplus - should you try building and testing DBD::Oracle. + 2 If the database is defined in a TNSNAMES.ORA file, you can use the + service name given in the file -*** BUILDING: + 3 To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, + of the form: //host[:port][/service_name] -Execute: + If port name is not specified, 1521 is the default. If service name is + not specified, the hostname will be used as a service name. - perl Makefile.PL # use a perl that's in your PATH + The following examples show several ways a connection can be created: -Use the perl that is first on your PATH. Then execute: + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - make + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); -If you get an error like "make: not found" you need to find the -directory that has the make command installed in it (e.g. /usr/ccs/bin -on Solaris) and add that to your PATH environment variable. + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); -Don't worry about most warnings when make runs, specifically ones like -"end-of-loop code not reached", "... due to prototype", -"cast increases required alignment of target type", etc. + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); -If you have problems see the 'IF YOU HAVE PROBLEMS' section below. -If it builds without error you should then run 'make test'. For the -main tests to work they must be able to connect to an Oracle database. + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); -The tests default to using a DSN of "dbi:Oracle:" which means you'll be -connected to the default database based on your TWO_TASK or ORACLE_SID -environment variables. This default can be altered either by defining the -ORACLE_DSN environment variable or the DBI_DSN environment variable. -See the oracle_test_dsn() sub in t/nchar_test_lib.pl + OS authentication + To connect to a local database with a user which has been set up to + authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): -The supplied tests will connect to the database using the value of the -ORACLE_USERID environment variable to supply the username/password. -So you should set that to a valid user (e.g. 'scott/tiger') and ensure that -this user has sufficient privileges to create, insert into, select from and -drop a table, is also able to create, call and drop a procedure and is able to select from -systemtables like 'v$sessions'. Using 'system/manager' might work but is not -recommended! See also + $dbh = DBI->connect('dbi:Oracle:','/',''); -README.login.txt. + Note the lack of a connection name (use the ORACLE_SID environment + variable). If an explicit SID is used you will probably get an ORA-01004 + error. - make test + That only works for local databases. (Authentication to remote Oracle + databases using your Unix login name without a password is possible but + it is not secure and not recommended so not documented here. -If the all the formal tests pass then, finally, run: + Oracle Environment Variables + To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME + environment variable should be set correctly. In general, the value used + should match the version of Oracle that was used to build DBD::Oracle. + If using dynamic linking then ORACLE_HOME should match the version of + Oracle that will be used to load in the Oracle client libraries (via + LD_LIBRARY_PATH, ldconfig, or similar on Unix). - make install + Oracle can use two environment variables to specify default connections: + ORACLE_SID and TWO_TASK. + To use them, specify either a local SID or service name, or a service + name that is specified in the TNSNAMES.ORA file. -*** IF YOU HAVE PROBLEMS: + Note that if you have *both* local and remote databases, and you have + ORACLE_SID *and* TWO_TASK set, and you don't specify a fully qualified + connect string on the command line, TWO_TASK takes precedence over + ORACLE_SID (i.e. you get connected to remote system). -Make sure you are using a recent perl (5.6.1 or later) and make -sure it's on your PATH so you can say 'perl Makefile.PL' and not -'/path/to/perl Makefile.PL'. + It is highly recommended not to rely on environment variables and to + always explicitly specify the SID in the connection string. This can + prevent serious mistakes such as dropping a schema in the wrong + database, and generally makes debugging and troubleshooting easier. -If you get compiler errors refering to Perl's own header files -(.../CORE/*.h) then there is something wrong with your installation. -It is important to use a Perl that was built on the system you are using. -It's also important to use the same compiler that was used to build the -Perl you are using. + Also remember that depending on the operating system you are using the + differing "ORACLE" environment variables may be case sensitive, so if + you are not connecting as you should double check the case of both the + variable and its value. -If you have build/link or core dump problems try: - perl Makefile.PL -p -or - perl Makefile.PL -nob -If it helps then please let me know (and please include a copy -of the log from the failed default build, the log from the build that -worked, plus the output of the "perl -V" command). + Timezones + If the query is run through SQL*Net (mostly queries that are executed on + remote servers), Oracle will return the time zone based on the setting + of the UNIX environment variable "TZ" for the user who started the + listener. -Do not hand edit the generated Makefile unless you are completely sure -you understand the implications! Always try to make changes via the -Makefile.PL command line and/or editing the Makefile.PL. -You should not need to make any changes. If you do please let us -know so that I can try to make it automatic in a later release. + If the query is run locally, Oracle will return the time zone based on + the "TZ" environment variable setting of the user running the query. -If you just can't login or login takes a long time then read -README.login.txt + With local queries, you can change the time zone for a particular user + by simply changing the setting of "TZ". To check the current setting, + issue the UNIX "date" command. -If you have linking problems (errors related to libraries or functions) -then you could try forcing a 'static' build using: + Oracle DRCP + DBD::Oracle supports DRCP (Database Resident Connection Pool) so if you + have an 11.2 database and DRCP is enabled you can direct all of your + connections to it by adding ':POOLED' to the SID or setting a connection + attribute of ora_drcp, or set the SERVER=POOLED when using a TNSENTRY + style connection or even by setting an environment variable ORA_DRCP. + All of which are demonstrated below; - make realclean - perl Makefile.PL LINKTYPE=static - make - make perl (you'll need to use and install _this_ new perl binary) - make test - make -f Makefile.aperl inst_perl MAP_TARGET=perl (install new perl) - make install (install DBD::Oracle) + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') -But that's not recommended these days. + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') ->>> Also carefully read the README.help.txt file which is full of useful ->>> tips and workarounds for various problems of various systems. + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) -*** HOW TO REPORT PROBLEMS + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') -This software is supported via the dbi-users@perl.org mailing list. -(You don't need to subscribe to the list in order to post.) + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") -Please do NOT post problems to comp.lang.perl.*, perl5-porters@perl.org, -http://www.cpanforum.com/dist/DBD-Oracle, or google groups etc. + if the ORA_DRCP environment variable is set then just this -If you're *sure* the problem is a bug then you can post a bug report -to http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle -Problem reports that don't include sufficient detail (including the -information listed below and how to reproduce the problem) -are unlikely to get resolved. + $dbh = DBI->connect('dbi:Oracle:DB','username','password') -For more information and to keep informed about progress you can join the -mailing list. Send a message to dbi-users-help@perl.org for more information. + You can find a white paper on setting up DRCP and its advantages at + . -Please post details of any problems (or changes you needed to make) to -dbi-users@perl.org. - - -** IT IS IMPORTANT TO INCLUDE *ALL* THE FOLLOWING INFORMATION: + Please note that DRCP support in DBD::Oracle is relatively new so the + mechanics or its implementation are subject to change. -1. A complete log of all steps of the build, e.g.: + TAF (Transparent Application Failover) + Transparent Application Failover (TAF) is the feature in OCI that allows + for clients to automatically reconnect to an instance in the event of a + failure of the instance. The reconnect happens automatically from within + the OCI (Oracle Call Interface) library. DBD::Oracle now supports a + callback function that will fire when a TAF event takes place. The main + use of the callback is to give your program the opportunity to inform + the user that a failover is taking place. - (do a make realclean first) - perl Makefile.PL - make - make test + You will have to set up TAF on your instance before you can use this + callback. You can test your instance to see if you can use TAF callback + with - Make sure to include the 'stderr' output. The best way to do this is - to use the "script" command (man script). If that's not available - then "command > command.log 2>&1" (assuming you're not using csh). - The "2>&1" is required (after the stdout redirect) to redirect stderr - to the same place. + $dbh->ora_can_taf(); - If a test fails then also include the output of: + If you try to set up a callback without it being enabled DBD::Oracle + will croak. - perl -Mblib t/.t + It is outside the scope of this documents to go through all of the + possible TAF situations you might want to set up but here is a simple + example: -2. Full details of which version of Oracle client and server you're using - (if it wasn't automatically found and printed by "perl Makefile.PL") + The TNS entry for the instance has had the following added to the + CONNECT_DATA section -3. The output of perl -V (that's a capital V, not lowercase) + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) -4. If you get errors like "undefined symbol", "symbol not found", - "undefined reference", "Text relocation remains" or any similar - error then include the output of "perl Makefile.PL -s XXX" - where XXX is the name of one of the symbols. - Please don't send the entire output of this command, - just any obviously 'interesting' parts (if there are any). - See also the LINKTYPE=static notes above. + You will also have to create your own perl function that will be called + from the client. You can name it anything you want and it will always be + passed two parameters, the failover event value and the failover type. + You can also set a sleep value in case of failover error and the OCI + client will sleep for the specified seconds before it attempts another + event. -5. If you get a core dump, rebuild DBD::Oracle with debugging - enabled by executing: perl Makefile.PL -g (note the -g option) - then rerun the code to get a new core dump file, finally use a - debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. - NOTE: I may not be able to help you much without a stack trace! - It is worth fetching and building the GNU GDB debugger (>=4.15) if - you don't have a good debugger on your system. If desperate try: - make perl; ./perl script; echo '$c' | adb ./perl core - Also see the Devel::CoreStack module on CPAN. - -6. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun - make test after setting the environment variable PERL_DL_DEBUG to 2. - -7. If your installation succeeds, but your script does not behave - as you expect, the problem may be on your end. Before - sending to dbi-users, try writing a *small*, easy to use test case - to reproduce your problem. Also, use the DBI->trace method to - trace your database calls. + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants -It is important to check that you are using the latest version before -posting. If you're not then you're *very* likely to be told "upgrade to -the latest". You would do yourself a favour by upgrading beforehand. + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); -Try to help yourself first, then try to help others help you by following -these guidelines carefully. And remember, please don't mail developers -directly - use the dbi-users mailing list. + #create the perl TAF event function -Regards, -Tim. + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ -=============================================================================== -Examples and other info: + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); -README.help.txt -- READ IT FIRST IF YOU HAVE ANY PROBLEMS -README.win32.txt -- building DBD::Oracle under MS Windows -README.wingcc.txt -- building DBD::Oracle under MS Windows with gcc -README.macosx.txt -- building DBD::Oracle under MacOS X -README.clients.txt -- building/using DBD::Oracle on minimally configured systems -README.login.txt -- help for login problems -README.longs.txt -- examples dealing with LONG types (blobs) + } + return 0; + } -DBI 'home page': http://dbi.perl.org + The TAF types are as follows -Old archive site for Perl DB information: - ftp://ftp.demon.co.uk/pub/perl/db/ -Mailing list archive: /DBI/perldb-interest/ -Perl 4 Oraperl (v2.4) /perl4/oraperl/ - -Jeff Stander's stuff stands out for Oraperl: -Directories of interest might be - /pub/Oracle/sources - /pub/Oracle/sources/jstander - /pub/Oracle/sources/jstander/distrib - /pub/Oracle/sources/jstander/tsmlib - /pub/Oracle/sources/jstander/wdbex - /pub/Oracle/sources/web/scripts - /pub/Oracle/sources/dba - /pub/Oracle/sources/dba/imp2sql7 - /pub/Oracle/sources/Lonnroth - /pub/Oracle/sources/harrison - -http://www.bf.rmit.edu.au/~orafaq/perlish.html -ftp://ftp.bf.rmit.edu.au/pub/perl/db -ftp://ftp.bf.rmit.edu.au/pub/Oracle -ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources -ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip - -DBI and DBD::Oracle are very portable. If Perl and Oracle run on a platform -then the chances are that DBD::Oracle will as well. - -=============================================================================== - -See the large README.help.txt file for lots of hints and advice -about building and runtime issues. - -End. + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + + The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + + Connect Attributes + ora_ncs_buff_mtpl + You can customize the size of the buffer when selecting LOBs with the + built-in AUTO Lob. The default value is 4 which is probably excessive + for most situations but is needed for backward compatibility. If you not + converting between a NCS on the DB and the Client then you might want to + set this to 1 to reduce memory usage. + + This value can also be specified with the "ORA_DBD_NCS_BUFFER" + environment variable in which case it sets the value at the connect + stage. + + ora_drcp + For Oracle 11.2 or greater. + + Set to *1* to enable DRCP. Can also be set via the "ORA_DRCP" + environment variable. + + ora_drcp_class + If you are using DRCP, you can set a CONNECTION_CLASS for your pools as + well. As sessions from a DRCP cannot be shared by users, you can use + this setting to identify the same user across different applications. + OCI will ensure that sessions belonging to a 'class' are not shared + outside the class'. + + The values for ora_drcp_class cannot contain a '*' and must be less than + 1024 characters. + + This value can be also be specified with the "ORA_DRCP_CLASS" + environment variable. + + ora_drcp_min + This optional value specifies the minimum number of sessions that are + initially opened. New sessions are only opened after this value has been + reached. + + The default value is 4 and any value above 0 is valid. + + Generally, it should be set to the number of concurrent statements the + application is planning or expecting to run. + + This value can also be specified with the "ORA_DRCP_MIN" environment + variable. + + ora_drcp_max + This optional value specifies the maximum number of sessions that can be + open at one time. Once reached no more sessions can be opened until one + becomes free. The default value is 40 and any value above 1 is valid. + You should not set this value lower than ora_drcp_min as that will just + waste resources. + + This value can also be specified with the "ORA_DRCP_MAX" environment + variable. + + ora_drcp_incr + This optional value specifies the next increment for sessions to be + started if the current number of sessions are less than ora_drcp_max. + The default value is 2 and any value above 0 is valid as long as the + value of ora_drcp_min + ora_drcp_incr is not greater than ora_drcp_max. + + This value can also be specified with the "ORA_DRCP_INCR" environment + variable. + + ora_taf + If your Oracle instance has been configured to use TAF events you can + enable the TAF callback by setting this option to any *true* value. + + ora_taf_function + The name of the Perl subroutine that will be called from OCI when a TAF + event occurs. You must supply a perl function to use the callback and it + will always receive two parameters, the failover event value and the + failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + + ora_taf_sleep + The amount of time in seconds the OCI client will sleep between + attempting successive failover events when the event is OCI_FO_ERROR. + + ora_session_mode + The ora_session_mode attribute can be used to connect with SYSDBA, + SYSOPER and ORA_SYSASM authorization. The ORA_SYSDBA, ORA_SYSOPER and + ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + + This is one case where setting ORACLE_SID may be useful since connecting + as SYSDBA or SYSOPER via SQL*Net is frequently disabled for security + reasons. + + Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + + It has been reported that this only works if $dsn does not contain a SID + so that Oracle then uses the value of ORACLE_SID (not TWO_TASK) + environment variable to connect to a local instance. Also the username + and password should be empty, and the user executing the script needs to + be part of the dba group or osdba group. + + ora_oratab_orahome + Passing a true value for the ora_oratab_orahome attribute will make + DBD::Oracle change $ENV{ORACLE_HOME} to make the Oracle home directory + that specified in the "/etc/oratab" file *if* the database to connect to + is specified as a SID that exists in the oratab file, and DBD::Oracle + was built to use the Oracle 7 OCI API (not Oracle 8+). + + ora_module_name + After connecting to the database the value of this attribute is passed + to the SET_MODULE() function in the "DBMS_APPLICATION_INFO" PL/SQL + package. This can be used to identify the application to the DBA for + monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + + The maximum size is 48 bytes. + + ora_driver_name + For 11g and later you can now set the name of the driver layer using + OCI. Perl, Perl5, ApachePerl so on. Names starting with "ORA" are + reserved. You can enter up to 8 characters. If none is enter then this + will default to DBDOxxxx where xxxx is the current version number. This + value can be retrieved on the server side using V$SESSION_CONNECT_INFO + or GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + + ora_client_info + Allows you to add any value (up to 64 bytes) to your session and it can + be retrieved on the server side from the "V$SESSION"a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + + ora_client_identifier + Allows you to specify the user identifier in the session handle. + + Most useful for web applications as it can pass in the session user name + which might be different to the connection user name. Can be up to 64 + bytes long but do not to include the password for security reasons and + the first character of the identifier should not be ':'. This value can + be retrieved on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + + ora_action + Allows you to specify any string up to 32 bytes which may be retrieved + on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + + ora_dbh_share + Requires at least Perl 5.8.0 compiled with ithreads. + + Allows you to share database connections between threads. The first + connect will make the connection, all following calls to connect with + the same ora_dbh_share attribute will use the same database connection. + The value must be a reference to a already shared scalar which is + initialized to an empty string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + + ora_envhp + The first time a connection is made a new OCI 'environment' is created + by DBD::Oracle and stored in the driver handle. Subsequent connects + reuse (share) that same OCI environment by default. + + The ora_envhp attribute can be used to disable the reuse of the OCI + environment from a previous connect. If the value is 0 then a new OCI + environment is allocated and used for this connection. + + The OCI environment holds information about the client side context, + such as the local NLS environment. By altering %ENV and setting + ora_envhp to 0 you can create connections with different NLS settings. + This is most useful for testing. + + ora_charset, ora_ncharset + For oracle versions >= 9.2 you can specify the client charset and + ncharset with the ora_charset and ora_ncharset attributes. You still + need to pass "ora_envhp = 0" for all but the first connect. + + These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + + ora_verbose + Use this value to enable DBD::Oracle only tracing. Simply either set the + ora_verbose attribute on the connect() method to the trace level you + desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + + or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + + In both cases the DBD::Oracle trace level is set to 6, which is the + highest level tracing most of the calls to OCI. + + ora_oci_success_warn + Use this value to print otherwise silent OCI warnings that may happen + when an execute or fetch returns "Success With Info" or when you want to + tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + + ora_objects + Use this value to enable extended embedded oracle objects mode. In + extended: + + 1 Embedded objects are returned as instance + (including type-name etc.) instead of simple ARRAY. + + 2 Determine object type for each instance. All object attributes are + returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + + ora_ph_type + The default placeholder datatype for the database session. The "TYPE" or + "ora_type" attributes to "bind_param" in DBI and "bind_param_inout" in + DBI override the datatype for individual placeholders. The most frequent + reason for using this attribute is to permit trailing spaces in values + passed by placeholders. + + Constants for the values allowed for this attribute can be imported + using + + use DBD::Oracle qw(:ora_types); + + Only the following values are permitted for this attribute. + + ORA_VARCHAR2 + Oracle clients using OCI 8 will strip trailing spaces and allow + embedded \0 bytes. Oracle clients using OCI 9.2 do not strip + trailing spaces and allow embedded \0 bytes. This is the normal + default placeholder type. + + ORA_STRING + Do not strip trailing spaces and end the string at the first \0. + + ORA_CHAR + Do not strip trailing spaces and allow embedded \0. Force + 'blank-padded comparison semantics'. + + For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + + Will pad bloggs out to 8 characters and return the username. + + ora_parse_error_offset + If the previous error was from a failed "prepare" due to a syntax error, + this attribute gives the offset into the "Statement" attribute where the + error was found. + + ora_array_chunk_size + Due to OCI limitations, DBD::Oracle needs to buffer up rows of bind + values in its "execute_for_fetch" implementation. This attribute sets + the number of rows to buffer at a time (default value is 1000). + + The "execute_for_fetch" function will collect (at most) this many rows + in an array, send them off to the DB for execution, then go back to + collect the next chunk of rows and so on. This attribute can be used to + limit or extend the number of rows processed at a time. + + Note that this attribute also applies to "execute_array", since that + method is implemented using "execute_for_fetch". + + ora_connect_with_default_signals + Sometimes the Oracle client seems to change some of the signal handlers + of the process during the connect phase. For instance, some users have + observed Perl's default $SIG{INT} handler being ignored after connecting + to an Oracle database. If this causes problems in your application, set + this attribute to an array reference of signals you would like to be + localized during the connect process. Once the connect is complete, the + signal handlers should be returned to their previous state. + + For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + + NOTE disabling the signal handlers the OCI library sets up may affect + functionality in the OCI library. + + NOTE If you are using connect_cached then the above example will lead to + DBI thinking each connection is different as an anonymous array + reference is being used. To avoid this when using connect_cached you are + advised to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + + In more recent Perl versions you could possibly make use of new state + variables. + + connect_cached + Implemented by DBI, no driver-specific impact. Please note that + connect_cached as not been tested with DRCP. + + data_sources + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + + Returns a list of available databases. You will have to set either the + 'ORACLE_HOME' or 'TNS_ADMIN' environment value to retrieve this list. It + will read these values from TNSNAMES.ORA file entries. + +METHODS COMMON TO ALL HANDLES + For all of the methods below, $h can be either a database handle ($dbh) + or a statement handle ($sth). Note that *$dbh* and *$sth* can be + replaced with any variable name you choose: these are just the names + most often used. Another common variable used in this documentation is + $*rv*, which stands for "return value". + + err + $rv = $h->err; + + Returns the error code from the last method called. + + errstr + $str = $h->errstr; + + Returns the last error that was reported by Oracle. Starting with + "ORA-00000" code followed by the error message. + + state + $str = $h->state; + + Oracle hasn't supported SQLSTATE since the early versions OCI. It will + return empty when the command succeeds and 'S1000' (General Error) for + all other errors. + + While this method can be called as either "$sth->state" or + "$dbh->state", it is usually clearer to always use "$dbh->state". + + trace + Implemented by DBI, no driver-specific impact. + + trace_msg + Implemented by DBI, no driver-specific impact. + + parse_trace_flag and parse_trace_flags + Implemented by DBI, no driver-specific impact. + + func + DBD::Oracle uses the "func" method to support a variety of functions. + + Private database handle functions + Some of these functions are called through the method func() which is + described in the DBI documentation. Any function that begins with ora_ + can be called directly. + + plsql_errstr + This function returns a string which describes the errors from the most + recent PL/SQL function, procedure, package, or package body compile in a + format similar to the output of the SQL*Plus command 'show errors'. + + The function returns undef if the error string could not be retrieved + due to a database error. Look in $dbh->errstr for the cause of the + failure. + + If there are no compile errors, an empty string is returned. + + Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + + dbms_output_enable / dbms_output_put / dbms_output_get + These functions use the PL/SQL DBMS_OUTPUT package to store and retrieve + text using the DBMS_OUTPUT buffer. Text stored in this buffer by + dbms_output_put or any PL/SQL block can be retrieved by dbms_output_get + or any PL/SQL block connected to the same database session. + + Stored text is not available until after dbms_output_put or the PL/SQL + block that saved it completes its execution. This means you CAN NOT use + these functions to monitor long running PL/SQL procedures. + + Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + + Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + + dbms_output_enable ( [ buffer_size ] ) + This function calls DBMS_OUTPUT.ENABLE to enable calls to package + DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to these + procedures are ignored unless DBMS_OUTPUT.ENABLE is called first. + + The buffer_size is the maximum amount of text that can be saved in the + buffer and must be between 2000 and 1,000,000. If buffer_size is not + given, the default is 20,000 bytes. + + dbms_output_put ( [ @lines ] ) + This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + + If all lines were saved successfully the function returns 1. Depending + on the context, an empty list or undef is returned for failure. + + If any line causes buffer_size to be exceeded, a buffer overflow error + is raised and the function call fails. Some of the text might be in the + buffer. + + dbms_output_get + This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from + the buffer. + + In an array context, all complete lines are removed from the buffer and + returned as a list. If there are no complete lines, an empty list is + returned. + + In a scalar context, the first complete line is removed from the buffer + and returned. If there are no complete lines, undef is returned. + + Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or + DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, + DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + + reauthenticate ( $username, $password ) + Starts a new session against the current database using the credentials + supplied. + + private_attribute_info + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + + Returns a hash of all private attributes used by DBD::Oracle, for either + a database or a statement handle. Currently, all the hash values are + undef. + +ATTRIBUTES COMMON TO ALL HANDLES + InactiveDestroy (boolean) + Implemented by DBI, no driver-specific impact. + + RaiseError (boolean, inherited) + Forces errors to always raise an exception. Although it defaults to off, + it is recommended that this be turned on, as the alternative is to check + the return value of every method (prepare, execute, fetch, etc.) + manually, which is easy to forget to do. + + PrintError (boolean, inherited) + Forces database errors to also generate warnings, which can then be + filtered with methods such as locally redefining *$SIG{__WARN__}* or + using modules such as "CGI::Carp". This attribute is on by default. + + ShowErrorStatement (boolean, inherited) + Appends information about the current statement to error messages. If + placeholder information is available, adds that as well. Defaults to + true. + + Warn (boolean, inherited) + Enables warnings. This is on by default, and should only be turned off + in a local block for a short a time only when absolutely needed. + + Executed (boolean, read-only) + Indicates if a handle has been executed. For database handles, this + value is true after the "do" method has been called, or when one of the + child statement handles has issued an "execute". Issuing a "commit" or + "rollback" always resets the attribute to false for database handles. + For statement handles, any call to "execute" or its variants will flip + the value to true for the lifetime of the statement handle. + + TraceLevel (integer, inherited) + Sets the trace level, similar to the "trace" method. See the sections on + "trace" and "parse_trace_flag" for more details. + + Active (boolean, read-only) + Indicates if a handle is active or not. For database handles, this + indicates if the database has been disconnected or not. For statement + handles, it indicates if all the data has been fetched yet or not. Use + of this attribute is not encouraged. + + Kids (integer, read-only) + Returns the number of child processes created for each handle type. For + a driver handle, indicates the number of database handles created. For a + database handle, indicates the number of statement handles created. For + statement handles, it always returns zero, because statement handles do + not create kids. + + ActiveKids (integer, read-only) + Same as "Kids", but only returns those that are active. + + CachedKids (hash ref) + Returns a hashref of handles. If called on a database handle, returns + all statement handles created by use of the "prepare_cached" method. If + called on a driver handle, returns all database handles created by the + "connect_cached" method. + + ChildHandles (array ref) + Implemented by DBI, no driver-specific impact. + + PrintWarn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleError (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleSetErr (code ref, inherited) + Implemented by DBI, no driver-specific impact. + + ErrCount (unsigned integer) + Implemented by DBI, no driver-specific impact. + + FetchHashKeyName (string, inherited) + Implemented by DBI, no driver-specific impact. + + ChopBlanks (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Taint (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintIn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintOut (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Profile (inherited) + Implemented by DBI, no driver-specific impact. + + Type (scalar) + Returns "dr" for a driver handle, "db" for a database handle, and "st" + for a statement handle. Should be rarely needed. + + LongReadLen + Implemented by DBI, no driver-specific impact. + + LongTruncOk + Implemented by DBI, no driver-specific impact. + + CompatMode + Type: boolean, inherited + + The CompatMode attribute is used by emulation layers (such as Oraperl) + to enable compatible behaviour in the underlying driver (e.g., + DBD::Oracle) for this handle. Not normally set by application code. + + It also has the effect of disabling the 'quick FETCH' of attribute + values from the handles attribute cache. So all attribute values are + handled by the drivers own FETCH method. This makes them slightly slower + but is useful for special-purpose drivers like DBD::Multiplex. + +ORACLE-SPECIFIC DATABASE HANDLE METHODS + ora_can_unicode ( [ $refresh ] ) + Returns a number indicating whether either of the database character + sets is a Unicode encoding. Calls ora_nls_parameters() and passes the + optional $refresh parameter to it. + + 0 = Neither character set is a Unicode encoding. + + 1 = National character set is a Unicode encoding. + + 2 = Database character set is a Unicode encoding. + + 3 = Both character sets are Unicode encodings. + + ora_can_taf + Returns true if the current connection supports TAF events. False if + otherise. + + ora_nls_parameters ( [ $refresh ] ) + Returns a hash reference containing the current NLS parameters, as given + by the v$nls_parameters view. The values fetched are cached between + calls. To cause the latest values to be fetched, pass a true value to + the function. + +DATABASE HANDLE METHODS + selectall_arrayref + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the rows returned by + preparing and executing the SQL string. See the DBI documentation for + full details. + + selectall_hashref + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + + Returns a reference to a hash containing the rows returned by preparing + and executing the SQL string. See the DBI documentation for full + details. + + selectcol_arrayref + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the first column from each + rows returned by preparing and executing the SQL string. It is possible + to specify exactly which columns to return. See the DBI documentation + for full details. + + prepare + $sth = $dbh->prepare($statement, \%attr); + + Prepares a statement for later execution by the database engine and + returns a reference to a statement handle object. + + Prepare Attributes + These attributes may be used in the "\%attr" parameter of the "prepare" + in DBI database handle method. + + ora_placeholders + Set to false to disable processing of placeholders. Used mainly for + loading a PL/SQL package that has been *wrapped* with Oracle's + "wrap" utility. + + ora_auto_lob + If true (the default), fetching retrieves the contents of the CLOB + or BLOB column in most circumstances. If false, fetching retrieves + the Oracle "LOB Locator" of the CLOB or BLOB value. + + See "LOBs and LONGs" for more details. + + See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how + to use LOB Locators. + + ora_pers_lob + If true the "Simple Fetch for CLOBs and BLOBs" method for the "Data + Interface for Persistent LOBs" will be used for LOBs rather than the + default method "Data Interface for LOB Locators". + + ora_clbk_lob + If true the "Piecewise Fetch with Callback" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_lob + If true the "Piecewise Fetch with Polling" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_size + This is the max piece size for the "Piecewise Fetch with Callback" + and "Piecewise Fetch with Polling" methods, in chars for CLOBS, and + bytes for BLOBS. + + ora_check_sql + If 1 (default), force SELECT statements to be described in + prepare(). If 0, allow SELECT statements to defer describe until + execute(). + + See "Prepare Postponed Till Execute" for more information. + + ora_exe_mode + This will set the execute mode of the current statement. Presently + only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + + See "Scrollable Cursors" for more details. + + ora_prefetch_rows + Sets the number of rows to be prefetched. If it is not set, then the + default value is 1. See "Row Prefetching" for more details. + + ora_prefetch_memory + Sets the memory level for rows to be prefetched. The application + then fetches as many rows as will fit into that much memory. See + "Row Prefetching" for more details. + + ora_row_cache_off + By default DBD::Oracle will use a row cache when fetching to cut + down the number of round trips to the server. If you do not want to + use an array fetch set this value to any value other than 0; + + See "Row Prefetching" for more details. + + Placeholders + There are two types of placeholders that can be used in DBD::Oracle. The + first is the "question mark" type, in which each placeholder is + represented by a single question mark character. This is the method + recommended by the DBI specs and is the most portable. Each question + mark is internally replaced by a "dollar sign number" in the order in + which they appear in the query (important when using "bind_param"). + + The other placeholder type is "named parameters" in the format ":foo" + which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + + The different types of placeholders cannot be mixed within a statement, + but you may use different ones for each statement handle you have. This + is confusing at best, so stick to one style within your program. + + prepare_cached + $sth = $dbh->prepare_cached($statement, \%attr); + + Implemented by DBI, no driver-specific impact. This method is most + useful if the same query is used over and over as it will cut down round + trips to the server. + + do + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + + Prepare and execute a single statement. Returns the number of rows + affected if the query was successful, returns undef if an error + occurred, and returns -1 if the number of rows is unknown or not + available. Note that this method will return 0E0 instead of 0 for 'no + rows were affected', in order to always return a true value if no error + occurred. + + last_insert_id + Oracle does not implement auto_increment of serial type columns it uses + predefined sequences where the id numbers are either selected before + insert, at insert time with a trigger, or as part of the query. + + Below is an example of you to use the latter with the SQL returning + clause to get the ID number back on insert with the bind_param_inout + method. . + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + + commit + $rv = $dbh->commit; + + Issues a COMMIT to the server, indicating that the current transaction + is finished and that all changes made will be visible to other + processes. If AutoCommit is enabled, then a warning is given and no + COMMIT is issued. Returns true on success, false on error. + + rollback + $rv = $dbh->rollback; + + Issues a ROLLBACK to the server, which discards any changes made in the + current transaction. If AutoCommit is enabled, then a warning is given + and no ROLLBACK is issued. Returns true on success, and false on error. + + begin_work + This method turns on transactions until the next call to "commit" or + "rollback", if "AutoCommit" is currently enabled. If it is not enabled, + calling begin_work will issue an error. Note that the transaction will + not actually begin until the first statement after begin_work is called. + + disconnect + $rv = $dbh->disconnect; + + Disconnects from the Oracle database. Any uncommitted changes will be + rolled back upon disconnection. It's good policy to always explicitly + call commit or rollback at some point before disconnecting, rather than + relying on the default rollback behavior. + + If the script exits before disconnect is called (or, more precisely, if + the database handle is no longer referenced by anything), then the + database handle's DESTROY method will call the rollback() and + disconnect() methods automatically. It is best to explicitly disconnect + rather than rely on this behavior. + + ping + $rv = $dbh->ping; + + This "ping" method is used to check the validity of a database handle. + The value returned is either 0, indicating that the connection is no + longer valid, or 1, indicating the connection is valid. This function + does 1 round trip to the Oracle Server. + + get_info() + $value = $dbh->get_info($info_type); + + DBD::Oracle supports "get_info()", but (currently) only a few info + types. + + table_info() + DBD::Oracle supports attributes for "table_info()". + + In Oracle, the concept of *user* and *schema* is (currently) the same. + Because database objects are owned by an user, the owner names in the + data dictionary views correspond to schema names. Oracle does not + support catalogues so TABLE_CAT is ignored as selection criterion. + + Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + + TABLE_TYPE may contain a comma-separated list of table types. The + following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + + The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + + The special enumerations of catalogues, schemas and table types are + supported. However, TABLE_CAT is always NULL. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. "table_info()" performs a case-sensitive search. So, a + selection criterion should respect upper and lower case. Normally, an + identifier is case-insensitive. Oracle stores and returns it in upper + case. Sometimes, database objects are created with quoted identifiers + (for reserved words, mixed case, special characters, ...). Such an + identifier is case-sensitive (if not all upper case). Oracle stores and + returns it as given. "table_info()" has no special quote handling, + neither adds nor removes quotes. + + primary_key_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + If the primary key constraint was created without an identifier, PK_NAME + contains a system generated name with the form SYS_Cn. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + foreign_key_info() + This method (currently) supports the extended behaviour of SQL/CLI, i.e. + the result set contains foreign keys that refer to primary and alternate + keys. The field UNIQUE_OR_PRIMARY distinguishes these keys. + + Oracle does not support catalogues, so $pk_catalog and $fk_catalog are + ignored as selection criteria (in the new style interface). The + UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always NULL + (undef). See "table_info()" for more detailed information. + + If the primary or foreign key constraints were created without an + identifier, UK_NAME or FK_NAME contains a system generated name with the + form SYS_Cn. + + The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle + (currently) does not support other actions. + + The DELETE_RULE field may contain wrong values. This is a known Bug + (#1271663) in Oracle's data dictionary views. Currently (as of 8.1.7), + 'RESTRICT' and 'SET DEFAULT' are not supported, 'CASCADE' is mapped + correctly and all other actions (incl. 'SET NULL') appear as 'NO + ACTION'. + + The DEFERABILITY field is always NULL, because this columns is not + present in the ALL_CONSTRAINTS view of older Oracle releases. + + The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, + FK_TABLE_SCHEM, FK_TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + column_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + + Don't rely on the values of the BUFFER_LENGTH field! Especially the + length of FLOATs may be wrong. + + Datatype codes for non-standard types are subject to change. + + Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + It is possible with Oracle to make the names of the various DB objects + (table,column,index etc) case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + + So in the example the exact case "Bla_BLA" must be used to get it info + on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + + any case can be used to get info on the column. + + selectrow_array + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + + Returns an array of row information after preparing and executing the + provided SQL string. The rows are returned by calling "fetchrow_array". + The string can also be a statement handle generated by a previous + prepare. Note that only the first row of data is returned. If called in + a scalar context, only the first column of the first row is returned. + Because this is not portable, it is not recommended that you use this + method in that way. + + selectrow_arrayref + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an array, by internal use of the "fetchrow_arrayref" + method. + + selectrow_hashref + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an hash, by internal use of the "fetchrow_hashref" method. + + clone + $other_dbh = $dbh->clone(); + + Creates a copy of the database handle by connecting with the same + parameters as the original handle, then trying to merge the attributes. + See the DBI documentation for complete usage. + +DATABASE HANDLE ATTRIBUTES + AutoCommit (boolean) + Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is + on, but this may change in the future, so it is highly recommended that + you explicitly set it when calling "connect". + + ReadOnly (boolean) + $dbh->{ReadOnly} = 1; + + Specifies if the current database connection should be in read-only mode + or not. + + Please not that this method is not foolproof: there are still ways to + update the database. Consider this a safety net to catch applications + that should not be issuing commands such as INSERT, UPDATE, or DELETE. + + This method method requires DBI version 1.55 or better. + + Name (string, read-only) + Returns the name of the current database. This is the same as the DSN, + without the "dbi:Oracle:" part. + + Username (string, read-only) + Returns the name of the user connected to the database. + + Driver (handle, read-only) + Holds the handle of the parent driver. The only recommended use for this + is to find the name of the driver using: + + $dbh->{Driver}->{Name} + + RowCacheSize + DBD::Oracle supports both Server pre-fetch and Client side row caching. + By default both are turned on to give optimum performance. Most of the + time one can just let DBD::Oracle figure out the best optimization. + + Row Caching + Row caching occurs on the client side and the object of it is to cut + down the number of round trips made to the server when fetching rows. At + each fetch a set number of rows will be retrieved from the server and + stored locally. Further calls the server are made only when the end of + the local buffer(cache) is reached. + + Rows up to the specified top level row count "RowCacheSize" are fetched + if it occupies no more than the specified memory usage limit. The + default value is 0, which means that memory size is not included in + computing the number of rows to prefetch. If the "RowCacheSize" value is + set to a negative number then the positive value of RowCacheSize is used + to compute the number of rows to prefetch. + + By default "RowCacheSize" is automatically set. If you want to totally + turn off prefetching set this to 1. + + For any SQL statement that contains a LOB, Long or Object Type Row + Caching will be turned off. However server side caching still works. If + you are only selecting a LOB Locator then Row Caching will still work. + + Row Prefetching + Row prefetching occurs on the server side and uses the DBI database + handle attribute "RowCacheSize" and or the Prepare Attribute + 'ora_prefetch_memory'. Tweaking these values may yield improved + performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + + In the above example 10 rows will be prefetched up to a maximum of 10000 + bytes of data. The Oracle® Call Interface Programmer's Guide, suggests + a good row cache value for a scrollable cursor is about 20% of expected + size of the record set. + + The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) + when it needs to get new rows. This happens on the first fetch that sets + the current_positon to any value other than 0. In the above example if + we do a OCI_FETCH_FIRST the first 10 rows are loaded into the buffer and + DBD::Oracle will not have to go back to the server for more rows. When + record 11 is fetched DBD::Oracle fetches and returns this row and the + next 9 rows are loaded into the buffer. In this case if you fetch + backwards from 10 to 1 no server round trips are made. + + With large record sets it is best not to attempt to go to the last + record as this may take some time, A large buffer size might even slow + down the fetch. If you must get the number of rows in a large record set + you might try using an few large OCI_FETCH_ABSOLUTEs and then an + OCI_FETCH_LAST, this might save some time. So if you had a record set of + 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one + would fetch the first 5000 rows into the buffer then the next 5000 rows. + If one requires only the first few rows there is no need to set a large + prefetch value. + + If the ora_prefetch_memory less than 1 or not present then memory size + is not included in computing the number of rows to prefetch otherwise + the number of rows will be limited to memory size. Likewise if the + RowCacheSize is less than 1 it is not included in the computing of the + prefetch rows. + +ORACLE-SPECIFIC STATEMENT HANDLE METHODS + ora_stmt_type + Returns the OCI Statement Type number for the SQL of a statement handle. + + ora_stmt_type_name + Returns the OCI Statement Type name for the SQL of a statement handle. + +DBI STATEMENT HANDLE OBJECT METHODS + bind_param + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + + Allows the user to bind a value and/or a data type to a placeholder. + + The value of $param_num is a number if using the '?' or if using ":foo" + style placeholders, the complete name (e.g. ":foo") must be given. The + $bind_value argument is fairly self-explanatory. A value of "undef" will + bind a "NULL" to the placeholder. Using "undef" is useful when you want + to change just the type and will be overwriting the value later. (Any + value is actually usable, but "undef" is easy and efficient). + + The "\%attr" hash is used to indicate the data type of the placeholder. + The default value is "varchar". If you need something else, you must use + one of the values provided by DBI or by DBD::Pg. To use a SQL value, + modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + + This will import some constants into your script. You can plug those + directly into the "bind_param" call. Some common ones that you will + encounter are: + + SQL_INTEGER + + To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + + You can then set the data types by setting the value of the "ora_type" + key in the hash passed to "bind_param". The current list of Oracle data + types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + + Data types are "sticky," in that once a data type is set to a certain + placeholder, it will remain for that placeholder, unless it is + explicitly set to something else afterwards. If the statement has + already been prepared, and you switch the data type to something else, + DBD::Oracle will re-prepare the statement for you before doing the next + execute. + + Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + + These attributes may be used in the "\%attr" parameter of the + "bind_param" in DBI or "bind_param_inout" in DBI statement handle + methods. + + ora_type + Specify the placeholder's datatype using an Oracle datatype. A fatal + error is raised if "ora_type" and the DBI "TYPE" attribute are used + for the same placeholder. Some of these types are not supported by + the current version of DBD::Oracle and will cause a fatal error if + used. Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + + Potentially useful values when DBD::Oracle was built using OCI 7 and + later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + + Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + + Additional values when DBD::Oracle was built using OCI 9.2 and + later: + + SQLT_CHR, SQLT_BIN + + See "Binding Cursors" for the correct way to use ORA_RSET. + + See "LOBs and LONGs" for how to use ORA_CLOB and ORA_BLOB. + + See "SYS.DBMS_SQL datatypes" for ORA_VARCHAR2_TABLE, + ORA_NUMBER_TABLE. + + See "Data Interface for Persistent LOBs" for the correct way to use + SQLT_CHR and SQLT_BIN. + + See "Other Data Types" for more information. + + See also "Placeholders and Bind Values" in DBI. + + ora_csform + Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values + are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can + be imported from the DBD::Oracle module. Rarely needed. + + ora_csid + Specify the *integer* OCI_ATTR_CHARSET_ID for the bind value. + Character set names can't be used currently. + + ora_maxdata_size + Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. May be + needed if a character set conversion from client to server causes + the data to use more space and so fail with a truncation error. + + ora_maxarray_numentries + Specify the maximum number of array entries to allocate. Used with + ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of + array entries Oracle can pass back to you in OUT variable of type + TABLE OF ... . + + ora_internal_type + Specify internal data representation. Currently is supported only + for ORA_NUMBER_TABLE. + + Optimizing Results + Prepare Postponed Till Execute + The DBD::Oracle module can avoid an explicit 'describe' operation prior + to the execution of the statement unless the application requests + information about the results (such as $sth->{NAME}). This reduces + communication with the server and increases performance (reducing the + number of PARSE_CALLS inside the server). + + However, it also means that SQL errors are not detected until + "execute()" (or $sth->{NAME} etc) is called instead of when "prepare()" + is called. Note that if the describe is triggered by the use of + $sth->{NAME} or a similar attribute and the describe fails then *an + exception is thrown* even if "RaiseError" is false! + + Set "ora_check_sql" to 0 in prepare() to enable this behaviour. + + bind_param_inout + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + + DBD::Oracle fully supports bind_param_inout below are some uses for this + method. + + Returning A Value from an INSERT + Oracle supports an extended SQL insert syntax which will return one or + more of the values inserted. This can be particularly useful for + single-pass insertion of values with re-used sequence values (avoiding a + separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + + If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + + If you have many rows to insert you can take advantage of Oracle's built + in execute array feature with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + + Which will return all the ids into @out_values. + + Note: + This will only work for numbered (?) placeholders, + The third parameter of bind_param_inout_array, (0 in the example), + "maxlen" is required by DBI but not used by DBD::Oracle + The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + + Returning A Recordset + DBD::Oracle does not currently support binding a PL/SQL table (aka + array) as an IN OUT parameter to any Perl data structure. You cannot + therefore call a PL/SQL function or procedure from DBI that uses a + non-atomic datatype as either a parameter, or a return value. However, + if you are using Oracle 9.0.1 or later, you can make use of table (or + pipelined) functions. + + For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + + Currently, there is no way to directly call the function + Array_Example.Array_Func from DBI. However, by making the following + relatively painless additions, its not only possible, but extremely + efficient. + + First, you need to create database object types that correspond to the + record and table types in the package. From the above example, these + would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + + Now, assuming the existing function needs to remain unchanged (it is + probably being called from other PL/SQL code), we need to add a new + function to the package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + + As you can see, the new function is very simple. Now, it is a simple + matter of calling the function as a straight-forward SELECT from your + DBI code. From the above example, the code would look something like + this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + + SYS.DBMS_SQL datatypes + DBD::Oracle has built-in support for SYS.DBMS_SQL.VARCHAR2_TABLE and + SYS.DBMS_SQL.NUMBER_TABLE datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + Note: + Take careful note that we use '\\@arr' here because the + 'bind_param_inout' will only take a reference to a scalar. + + ORA_VARCHAR2_TABLE + SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. ( + in bind_param() and bind_param_inout() ). When you bind array, you need + to specify full buffer size for OUT data. So, there are two parameters: + *max_len* (specified as 3rd argument of bind_param_inout() ), and + *ora_maxarray_numentries*. They define maximum array entry length and + maximum rows, that can be passed to Oracle and back to you. In this + example we send array with 1 element with length=3, but allocate space + for 100 Oracle array entries with maximum length 10 of each. So, you can + get no more than 100 array entries with length <= 10. + + If you set *max_len* to zero, maximum array entry length is calculated + as maximum length of entry of array bound. If 0 < *max_len* < length( + $some_element ), truncation occur. + + If you set *ora_maxarray_numentries* to zero, current (at bind time) + bound array length is used as maximum. If 0 < *ora_maxarray_numentries* + < scalar(@array), not all array entries are bound. + + ORA_NUMBER_TABLE + SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike + ORA_VARCHAR2_TABLE. The main difference is internal data representation. + Currently 2 types of bind is allowed : as C-integer, or as C-double + type. To select one of them, you may specify additional bind parameter + *ora_internal_type* as either SQLT_INT or SQLT_FLT for C-integer and + C-double types. Integer size is architecture-specific and is usually 32 + or 64 bit. Double is standard IEEE 754 type. + + *ora_internal_type* defaults to double (SQLT_FLT). + + *max_len* is ignored for OCI_NUMBER_TABLE. + + Currently, you cannot bind full native Oracle NUMBER(38). If you really + need, send request to dbi-dev list. + + The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + + If you change bind type to SQLT_INT, like: + + ora_internal_type => SQLT_INT + + you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + + bind_param_inout_array + DBD::Oracle supports this undocumented feature of DBI. See "Returning A + Value from an INSERT" for an example. + + bind_param_array + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + + Binds an array of values to a placeholder, so that each is used in turn + by a call to the "execute_array" method. + + execute + $rv = $sth->execute(@bind_values); + + Perform whatever processing is necessary to execute the prepared + statement. + + execute_array + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + Execute a prepared statement once for each item in a passed-in hashref, + or items that were previously bound via the "bind_param_array" method. + See the DBI documentation for more details. + + DBD::Oracle takes full advantage of OCI's array interface so inserts and + updates using this interface will run very quickly. + + execute_for_fetch + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + Used internally by the "execute_array" method, and rarely used directly. + See the DBI documentation for more details. + + fetchrow_arrayref + $ary_ref = $sth->fetchrow_arrayref; + + Fetches the next row of data from the statement handle, and returns a + reference to an array holding the column values. Any columns that are + NULL are returned as undef within the array. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + Note that the same array reference is returned for each fetch, so don't + store the reference and then use it after a later fetch. Also, the + elements of the array are also reused for each row, so take care if you + want to take a reference to an element. See also "bind_columns". + + fetchrow_array + @ary = $sth->fetchrow_array; + + Similar to the "fetchrow_arrayref" method, but returns a list of column + information rather than a reference to a list. Do not use this in a + scalar context. + + fetchrow_hashref + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + + Fetches the next row of data and returns a hashref containing the name + of the columns as the keys and the data itself as the values. Any NULL + value is returned as as undef value. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + The optional $name argument should be either "NAME", "NAME_lc" or + "NAME_uc", and indicates what sort of transformation to make to the keys + in the hash. By default Oracle uses upper case. + + fetchall_arrayref + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + + Returns a reference to an array of arrays that contains all the + remaining rows to be fetched from the statement handle. If there are no + more rows, an empty arrayref will be returned. If an error occurs, the + data read in so far will be returned. Because of this, you should always + check "$sth->err" after calling this method, unless "RaiseError" has + been enabled. + + If $slice is an array reference, fetchall_arrayref uses the + "fetchrow_arrayref" method to fetch each row as an array ref. If the + $slice array is not empty then it is used as a slice to select + individual columns by perl array index number (starting at 0, unlike + column and parameter numbers which start at 1). + + With no parameters, or if $slice is undefined, fetchall_arrayref acts as + if passed an empty array ref. + + If $slice is a hash reference, fetchall_arrayref uses "fetchrow_hashref" + to fetch each row as a hash reference. + + See the DBI documentation for a complete discussion. + + fetchall_hashref + $hash_ref = $sth->fetchall_hashref( $key_field ); + + Returns a hashref containing all rows to be fetched from the statement + handle. See the DBI documentation for a full discussion. + + finish + $rv = $sth->finish; + + Indicates to DBI that you are finished with the statement handle and are + not going to use it again. Only needed when you have not fetched all the + possible rows. + + rows + $rv = $sth->rows; + + Returns the number of rows affected for updates, deletes and inserts and + -1 for selects. + + bind_col + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + + Binds a Perl variable and/or some attributes to an output column of a + SELECT statement. Column numbers count up from 1. You do not need to + bind output columns in order to fetch data. + + NOTE: DBD::Oracle does not use the $bind_type to determine how to bind + the column; it uses what Oracle says the data type is. You can however + set a numeric bind type with the bind attributes + StrictlyTyped/DiscardString as these attributes are applied after the + column is retrieved. + + See the DBI documentation for a discussion of the optional parameters + "\%attr" and $bind_type + + bind_columns + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + + Calls the "bind_col" method for each column in the SELECT statement, + using the supplied list. + + dump_results + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + + Fetches all the rows from the statement handle, calls "DBI::neat_list" + for each row, and prints the results to $fh (which defaults to STDOUT). + Rows are separated by $lsep (which defaults to a newline). Columns are + separated by $fsep (which defaults to a comma). The $maxlen controls how + wide the output can be, and defaults to 35. + + This method is designed as a handy utility for prototyping and testing + queries. Since it uses "neat_list" to format and edit the string for + reading by humans, it is not recommended for data transfer applications. + +STATEMENT HANDLE ATTRIBUTES + NUM_OF_FIELDS (integer, read-only) + Returns the number of columns returned by the current statement. A + number will only be returned for SELECT statements for INSERT, UPDATE, + and DELETE statements which contain a RETURNING clause. This method + returns undef if called before "execute()". + + NUM_OF_PARAMS (integer, read-only) + Returns the number of placeholders in the current statement. + + NAME (arrayref, read-only) + Returns an arrayref of column names for the current statement. This + method will only work for SELECT statements, for SHOW statements, and + for INSERT, UPDATE, and DELETE statements which contain a RETURNING + clause. This method returns undef if called before "execute()". + + NAME_lc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to lower case. + + NAME_uc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to upper case. + + NAME_hash (hashref, read-only) + Similar to the "NAME" attribute, but returns a hashref of column names + instead of an arrayref. The names of the columns are the keys of the + hash, and the values represent the order in which the columns are + returned, starting at 0. This method returns undef if called before + "execute()". + + NAME_lc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + NAME_uc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + TYPE (arrayref, read-only) + Returns an arrayref indicating the data type for each column in the + statement. This method returns undef if called before "execute()". + + PRECISION (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the precision for "NUMERIC" columns, the + size in number of characters for "CHAR" and "VARCHAR" columns, and for + all other types of columns it returns the number of *bytes*. This method + returns undef if called before "execute()". + + SCALE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the scale of the that column. The only + type that will return a value is "NUMERIC". This method returns undef if + called before "execute()". + + NULLABLE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates if the column is nullable or not. 0 = + not nullable, 1 = nullable, 2 = unknown. This method returns undef if + called before "execute()". + + Database (dbh, read-only) + Returns the database handle this statement handle was created from. + + ParamValues (hash ref, read-only) + Returns a reference to a hash containing the values currently bound to + placeholders. If the "named parameters" type of placeholders are being + used (such as ":foo"), then the keys of the hash will be the names of + the placeholders (without the colon). If the "dollar sign numbers" type + of placeholders are being used, the keys of the hash will be the + numbers, without the dollar signs. If the "question mark" type is used, + integer numbers will be returned, starting at one and increasing for + every placeholder. + + If this method is called before "execute", the literal values passed in + are returned. If called after "execute", then the quoted versions of the + values are returned. + + ParamTypes (hash ref, read-only) + Returns a reference to a hash containing the type names currently bound + to placeholders. The keys are the same as returned by the ParamValues + method. The values are hashrefs containing a single key value pair, in + which the key is either 'TYPE' if the type has a generic SQL equivalent, + and 'pg_type' if the type can only be expressed by a Postgres type. The + value is the internal number corresponding to the type originally passed + in. (Placeholders that have not yet been bound will return undef as the + value). This allows the output of ParamTypes to be passed back to the + "bind_param" method. + + Statement (string, read-only) + Returns the statement string passed to the most recent "prepare" method + called in this database handle, even if that method failed. This is + especially useful where "RaiseError" is enabled and the exception + handler checks $@ and sees that a "prepare" method call failed. + + RowsInCache + Returns the number of un-fetched rows in the cache for selects. + +SCROLLABLE CURSORS + Oracle supports the concept of a 'Scrollable Cursor' which is defined as + a 'Result Set' where the rows can be fetched either sequentially or + non-sequentially. One can fetch rows forward, backwards, from any given + position or the n-th row from the current position in the result set. + + Rows are numbered sequentially starting at one and client-side caching + of the partial or entire result set can improve performance by limiting + round trips to the server. + + Oracle does not support DML type operations with scrollable cursors so + you are limited to simple 'Select' operations only. As well you can not + use this functionality with remote mapped queries or if the LONG + datatype is part of the select list. + + However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, + and fetch methods. + + Only use scrollable cursors if you really have a good reason to. They do + use up considerable more server and client resources and have poorer + response times than non-scrolling cursors. + + Enabling Scrollable Cursors + To enable this functionality you must first import the 'Fetch + Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + + Next you will have to tell DBD::Oracle that you will be using scrolling + by setting the ora_exe_mode attribute on the statement handle to + 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + + When the statement is executed you will then be able to use + 'ora_fetch_scroll' method to get a row or you can still use any of the + other fetch methods but with a poorer response time than if you used a + non-scrolling cursor. As well scrollable cursors are compatible with any + applicable bind methods. + + Scrollable Cursor Methods + The following driver-specific methods are used with scrollable cursors. + + ora_scroll_position + $position = $sth->ora_scroll_position(); + + This method returns the current position (row number) attribute of + the result set. Prior to the first fetch this value is 0. This is + the only time this value will be 0 after the first fetch the value + will be set, so you can use this value to test if any rows have been + fetched. The minimum value will always be 1 after the first fetch. + The maximum value will always be the total number of rows in the + record set. + + ora_fetch_scroll + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + + Works the same as "fetchrow_arrayref", excepts one passes in a + 'Fetch Orientation' constant and a fetch_offset value which will + then determine the row that will be fetched. It returns the row as a + list containing the field values. Null fields are returned as + *undef* values in the list. + + The valid orientation constant and fetch offset values combination + are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + + The effect that a ora_fetch_scroll method call has on the + current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + + The effects of the differing orientation constants on the first + fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + + Scrollable Cursor Usage + Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + + and one assumes that the number of rows returned from the query is 20, + the code snippets below will illustrate the use of ora_fetch_scroll + method; + + Fetching the Last Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute to will be 20 after this snippet. This + is also a way to get the number of rows in the record set, however, + if the record set is large this could take some time. + + Fetching the Current Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will still be 20 after this snippet. + + Fetching the First Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the Next Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 5 after this snippet. + + Fetching the Prior Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the 10th Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 10th to 14th Row + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 14 after this snippet. + + Fetching the 14th to 10th Row + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 5th Row From the Present Position. + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 15 after this snippet. + + Fetching the 9th Row Prior From the Present Position + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 6 after this snippet. + + Use Finish + $sth->finish(); + + When using scrollable cursors it is required that you use the + $sth->finish() method when you are done with the cursor as this type + of cursor has to be explicitly cancelled on the server. If you do + not do this you may cause resource problems on your database. + +LOBS AND LONGS + The key to working with LOBs (CLOB, BLOBs) is to remember the value of + an Oracle LOB column is not the content of the LOB. It's a 'LOB Locator' + which, after being selected or inserted needs extra processing to read + or write the content of the LOB. There are also legacy LONG types (LONG, + LONG RAW, VARCHAR2) which are presently deprecated by Oracle but are + still in use. These LONG types do not utilize a 'LOB Locator' and also + are more limited in functionality than CLOB or BLOB fields. + + DBD::Oracle now offers three interfaces to LOB and LONG data, + + "Data Interface for Persistent LOBs" + With this interface DBD::Oracle handles your data directly utilizing + regular OCI calls, Oracle itself takes care of the LOB Locator + operations in the case of BLOBs and CLOBs treating them exactly as + if they were the same as the legacy LONG or LONG RAW types. + + "Data Interface for LOB Locators" + With this interface DBD::Oracle handles your data utilizing LOB + Locator OCI calls so it only works with CLOB and BLOB datatypes. + With this interface DBD::Oracle takes care of the LOB Locator + operations for you. + + "LOB Locator Method Interface" + This allows the user direct access to the LOB Locator methods, so + you have to take case of the LOB Locator operations yourself. + + Generally speaking the interface that you will chose will be dependent + on what end you are trying to achieve. All have their benefits and + drawbacks. + + One point to remember when working with LOBs (CLOBs, BLOBs) is if your + LOB column can be in one of three states; + + NULL + The table cell is created, but the cell holds no locator or value. + If your LOB field is in this state then there is no LOB Locator that + DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + + error when working with a LOB. + + You can correct this by using an SQL UPDATE statement to reset the + LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB + or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + + Empty + A LOB instance with a locator exists in the cell, but it has no + value. The length of the LOB is zero. In this case DBD::Oracle will + return 'undef' for the field. + + Populated + A LOB instance with a locator and a value exists in the cell. You + actually get the LOB value. + + Data Interface for Persistent LOBs + This is the original interface for LONG and LONG RAW datatypes and from + Oracle 9iR1 and later the OCI API was extended to work directly with the + other LOB datatypes. In other words you can treat all LOB type data + (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can + perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using + the same techniques you would use on other datatypes that store + character or binary data. In some cases there are fewer round trips to + the server as no 'LOB Locators' are used, normally one can get an entire + LOB is a single round trip. + + Simple Fetch for LONGs and LONG RAWs + As the name implies this is the simplest way to use this interface. + DBD::Oracle just attempts to get your LONG datatypes as a single large + piece. There are no special settings, simply set the database handle's + 'LongReadLen' attribute to a value that will be the larger than the + expected size of the LONG or LONG RAW. If the size of the LONG or LONG + RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A + Truncation' error. To stop this set the database handle's 'LongTruncOk' + attribute to '1'. The maximum value of 'LongReadLen' seems to be + dependent on the physical memory limits of the box that Oracle is + running on. You have most likely reached this limit if you run into an + 'ORA-01062: unable to allocate memory for define buffer' error. One + solution is to set the size of 'LongReadLen' to a lower value. + + For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select out all of the long1 fields in the table as long as they are + all under 2MB in length. A value in long1 longer than this will throw an + error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the long1 fields but they will be + truncated at 2MBs. + + Using ora_ncs_buff_mtpl + When getting CLOBs and NCLOBs in or out of Oracle, the Server will + translate from the Server's NCharSet to the Client's. If they happen to + be the same or at least compatible then all of these actions are a 1 + char to 1 char bases. Thus if you set your LongReadLen buffer to + 10_000_000 you will get up to 10_000_000 char. + + However if the Server has to translate from one NCharSet to another it + will use bytes for conversion. The buffer value is set to 4 * + LONG_READ_LEN which was very wasteful as you might only be asking for + 10_000_000 bytes but you were actually using 40_000_000 bytes of buffer + under the hood. You would still get 10_000_000 bytes (maybe less + characters though) but you are using allot more memory that you need. + + You can now customize the size of the buffer by setting the + 'ora_ncs_buff_mtpl' either on the connection or statement handle. You + can also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you + will have to go back and change all your code if you are getting into + trouble. + + The default value is still set to 4 for backward compatibility. You can + lower this value and thus increase the amount of data you can retrieve. + If the ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error + telling you to increase this buffer by one. + + If the error is not captured then you may get at some random point later + on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + + This is one of the more obscure ORA errors (have some fun and report it + to Meta-Link they will scratch their heads for hours) + + If you get this, simply increment the ora_ncs_buff_mtpl by one until it + goes away. + + This should greatly increase your ability to select very large CLOBs or + NCLOBs, by freeing up a large block of memory. + + You can tune this value by setting ora_oci_success_warn which will + display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + + In the case above the query Got 28 characters (well really only 20 + characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) + thus saving 40bytes of memory. + + Simple Fetch for CLOBs and BLOBs + To use this interface for CLOBs and LOBs datatypes set the + 'ora_pers_lob' attribute of the statement handle to '1' with the prepare + method, as well set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. If the + size of the LOB exceeds the 'LongReadLen' DBD::Oracle will return a + 'ORA-24345: A Truncation' error. To stop this set the database handle's + 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems + to be dependent on the physical memory limits of the box that Oracle is + running on in the same way that LONGs and LONG RAWs are. + + For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, + this is an internal OCI limit complain to them if you want it changed. + However if you CLOB is longer than this and also larger than the + 'LongReadLen' than the 'LongReadLen' in chars is returned. + + It seems with BLOBs you are not limited by the 64k. + + For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the lobs but they will be truncated + at 2MBs. + + Piecewise Fetch with Callback + With a piecewise callback fetch DBD::Oracle sets up a function that will + 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, + CLOB, BLOB) piece by piece. To use this interface set the 'ora_clbk_lob' + attribute of the statement handle to '1' with the prepare method. Next + set the 'ora_piece_size' to the size of the piece that you want to + return on the callback. Finally set the database handle's 'LongReadLen' + attribute to a value that will be the larger than the expected size of + the LOB. Like the "Simple Fetch for LONGs and LONG RAWs" and "Simple + Fetch for CLOBs and BLOBs" the if the size of the LOB exceeds the is + 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the + LOB or set the 'LongReadLen' to a higher value. With this interface the + value of 'ora_piece_size' seems to be constrained by the same memory + limit as found on the Simple Fetch interface. If you encounter an + 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller + value. The value for 'LongReadLen' is dependent on the version and + settings of the Oracle DB you are using. In theory it ranges from 8GBs + in 9iR1 up to 128 terabytes with 11g but you will also be limited by the + physical memory of your PERL instance. + + Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will + throw an error. + + Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 filed is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Piecewise Fetch with Polling + With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB + during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by + piece. To use this interface set the 'ora_piece_lob' attribute of the + statement handle to '1' with the prepare method. Next set the + 'ora_piece_size' to the size of the piece that you want to return on the + callback. Finally set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. Like + the "Piecewise Fetch with Callback" and Simple Fetches if the size of + the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' + attribute to truncate the LOB or set the 'LongReadLen' to a higher + value. With this interface the value of 'ora_piece_size' seems to be + constrained by the same memory limit as found on the "Piecewise Fetch + with Callback". + + Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will + throw an error. + + Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 field is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Binding for Updates and Inserts for CLOBs and BLOBs + To bind for updates and inserts all that is required to use this + interface is to set the statement handle's prepare method 'ora_type' + attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in + the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + + So far the only limit reached with this form of insert is the LOBs must + be under 2GB in size. + + Support for Remote LOBs; + Starting with Oracle 10gR2 the interface for Persistent LOBs was + expanded to support remote LOBs (access over a dblink). Given a database + called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + + to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Below are the limitations of Remote LOBs; + + Queries involving more than one database are not supported; + so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + + as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + + DDL commands are not supported; + so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + + Only binds and defines for data going into remote persistent LOBs are + supported. + so that parameter passing in PL/SQL where CHAR data is bound or + defined for remote LOBs is not allowed . + + These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + + If the remote object is a view such as + CREATE VIEW v AS SELECT foo() FROM ... + + the following would not work: + + SELECT * FROM v@dbs2; + + Limited PL/SQL parameter passing + PL/SQL parameter passing is not allowed where the actual argument is + a LOB type and the remote argument is one of VARCHAR2, NVARCHAR2, + CHAR, NCHAR, or RAW. + + RETURNING INTO does not support implicit conversions between CHAR and + CLOB. + so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + + Locator Data Interface + Simple Usage + When fetching LOBs with this interface a 'LOB Locator' is created then + used to get the lob with the LongReadLen and LongTruncOk attributes. The + value for 'LongReadLen' is dependent on the version and settings of the + Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 + terabytes with 11g but you will also be limited by the physical memory + of your PERL instance. + + When inserting or updating LOBs some *major* magic has to be performed + behind the scenes to make it transparent. Basically the driver has to + insert a 'LOB Locator' and then refetch the newly inserted LOB Locator + before being able to write the data into it. However, it works well most + of the time, and I've made it as fast as possible, just one extra + server-round-trip per insert or update after the first. For the time + being, only single-row LOB updates are supported. + + To insert or update a large LOB using a placeholder, DBD::Oracle has to + know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + + The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + + or use the corresponding integer values (112 and 113). + + One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has to + be able to tell which parameters relate to which table fields. In all + cases where it can possibly work it out for itself, it does, however, if + there are multiple LOB fields of the same type in the table then you + need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + + There are some limitations inherent in the way DBD::Oracle makes typical + LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + + The alternative is to disable the automatic LOB Locator processing. If + "ora_auto_lob" is 0 in prepare(), you can fetch the LOB Locators and do + all the work yourself using the ora_lob_*() methods. See the "Data + Interface for LOB Locators" section below. + + LOB support in PL/SQL + LOB Locators can be passed to PL/SQL calls by binding them to + placeholders with the proper "ora_type". If "ora_auto_lob" is true, + output LOB parameters will be automatically returned as strings. + + If the Oracle driver has support for temporary LOBs (Oracle 9i and + higher), strings can be bound to input LOB placeholders and will be + automatically converted to LOBs. + + Example: # Build a large XML document, bind it as a CLOB, # extract + elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + + If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + + error, while attempting to insert a LOB, this means the Oracle user has + insufficient space for LOB you are trying to insert. One solution it to + use "alter database datafile 'sss.ggg' resize Mnnn" to increase the + available memory for LOBs. + + Persistent & Locator Interface Caveats + Now that one has the option of using the Persistent or the Locator + interface for LOBs the questions arises which one to use. For starters, + if you want to access LOBs over a dblink you will have to use the + Persistent interface so that choice is simple. The question of which one + to use after that is a little more tricky. It basically boils down to a + choice between LOB size and speed. + + The Callback and Polling piecewise fetches are very very slow when + compared to the Simple and the Locator fetches but they can handle very + large blocks of data. Given a situation where a large LOB is to be read + the Locator fetch may time out while either of the piecewise fetches may + not. + + With the Simple fetch you are limited by physical memory of your server + but it runs a little faster than the Locator, as there are fewer round + trips to the server. So if you have small LOBs and need to save a little + bandwidth this is the one to use. It you are going after large LOBs then + the Locator interface is the one to use. + + If you need to update more than a single row of with LOB data then the + Persistent interface can do it while the Locator can't. + + If you encounter a situation where you have to access the legacy LOBs + (LONG, LONG RAW) and the values are to large for you system then you can + use the Callback or Polling piecewise fetches to get all of the data. + + Not all of the Persistent interface has been implemented yet, the + following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + + Most of the time you should just use the "Locator Data Interface" as + this is in one that has the best combination of speed and size. + + All this being said if you are doing some critical programming I would + use the "Data Interface for LOB Locators" as this gives you very fine + grain control of your LOBs, of course the code for this will be somewhat + more involved. + + Data Interface for LOB Locators + The following driver-specific methods let you manipulate "LOB Locators" + directly. To select a LOB locator directly set the if the "ora_auto_lob" + attribute to false, or alternatively they can be returned via PL/SQL + procedure calls. + + (If using a DBI version earlier than 1.36 they must be called via the + func() method. Note that methods called via func() don't honour + RaiseError etc, and so it's important to check $dbh->err after each + call. It's recommended that you upgrade to DBI 1.38 or later.) + + Note that LOB locators are only valid while the statement handle that + created them is valid. When all references to the original statement + handle are lost, the handle is destroyed and the locators are freed. + + ora_lob_read + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + + Read a portion of the LOB. $offset starts at 1. Uses the Oracle + OCILobRead function. + + ora_lob_write + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + + Write/overwrite a portion of the LOB. $offset starts at 1. Uses the + Oracle OCILobWrite function. + + ora_lob_append + $rc = $dbh->ora_lob_append($lob_locator, $data); + + Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + + ora_lob_trim + $rc = $dbh->ora_lob_trim($lob_locator, $length); + + Trims the length of the LOB to $length. Uses the Oracle OCILobTrim + function. + + ora_lob_length + $length = $dbh->ora_lob_length($lob_locator); + + Returns the length of the LOB. Uses the Oracle OCILobGetLength + function. + + ora_lob_is_init + $is_init = $dbh->ora_lob_is_init($lob_locator); + + Returns true(1) if the Lob Locator is initialized false(0) if it is + not, or 'undef' if there is an error. Uses the Oracle + OCILobLocatorIsInit function. + + ora_lob_chunk_size + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + + Returns the chunk size of the LOB. Uses the Oracle + OCILobGetChunkSize function. + + For optimal performance, Oracle recommends reading from and writing + to a LOB in batches using a multiple of the LOB chunk size. In + Oracle 10g and before, when all defaults are in place, this chunk + size defaults to 8k (8192). + + LOB Locator Method Examples + *Note:* Make sure you first read the note in the section above about + multi-byte character set issues with these methods. + + The following examples demonstrate the usage of LOB Locators to read, + write, and append data, and to query the size of large data. + + The following examples assume a table containing two large object + columns, one binary and one character, with a primary key column, + defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + + It also assumes a sequence for use in generating unique lob_id field + values, defined as follows: + + CREATE SEQUENCE lob_example_seq + + Example: Inserting a new row with large data + Unless enough memory is available to store and bind the entire LOB data + for insert all at once, the LOB columns must be written interactively, + piece by piece. In the case of a new row, this is performed by first + inserting a row, with empty values in the LOB columns, then modifying + the row by writing the large data interactively to the LOB columns using + their LOB locators as handles. + + The insert statement must create token values in the LOB columns. Here, + we use the empty string for both the binary and character large object + columns 'bindata' and 'chardata'. + + After the INSERT statement, a SELECT statement is used to acquire LOB + locators to the 'bindata' and 'chardata' fields of the newly inserted + row. Because these LOB locators are subsequently written, they must be + acquired from a select statement containing the clause 'FOR UPDATE' (LOB + locators are only valid within the transaction that fetched them, so + can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + + In this example we demonstrate the use of ora_lob_write() interactively + to append data to the columns 'bin_data' and 'char_data'. Had we used + ora_lob_append(), we could have saved ourselves the trouble of keeping + track of the offset into the lobs. The snippet of code beneath the + comment 'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + + The scalar variables $offset and $length are no longer needed, because + ora_lob_append() keeps track of the offset for us. + + Example: Updating an existing row with large data + In this example, we demonstrate a technique for overwriting a portion of + a blob field with new binary data. The blob data before and after the + section overwritten remains unchanged. Hence, this technique could be + used for updating fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + + After running this code, the row where lob_id = 5 will contain, starting + at position 100234 in the bin_data column, the string "This string will + overwrite a portion of the blob". + + Example: Streaming character data from the database + In this example, we demonstrate a technique for streaming data from the + database to a file handle, in this case STDOUT. This allows more data to + be read in and written out than could be stored in memory at a given + time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + + Notice that the select statement does not contain the phrase "FOR + UPDATE". Because we are only reading from the LOB Locator returned, and + not modifying the LOB it refers to, the select statement does not + require the "FOR UPDATE" clause. + + A word of caution when using the data returned from an ora_lob_read in a + conditional statement. for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + + was used with a chunk size of 4096 against a blob that requires more + than 1 chunk to return the data and the last chunk is one byte long and + contains a zero (ASCII 48) you will miss this last byte as $data will + contain 0 which PERL will see as false and not print it out. + + Example: Truncating existing large data + In this example, we truncate the data already present in a large object + column in the database. Specifically, for each row in the table, we + truncate the 'bindata' value to half its previous length. + + After acquiring a LOB Locator for the column, we query its length, then + we trim the length by half. Because we modify the large objects with the + call to ora_lob_trim(), we must select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +SPACES AND PADDING + Trailing Spaces + Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder + values and uses Nonpadded Comparison Semantics with the result. This + causes trouble if the spaces are needed for comparison with a CHAR value + or to prevent the value from becoming '' which Oracle treats as NULL. + Look for Blank-padded Comparison Semantics and Nonpadded Comparison + Semantics in Oracle's SQL Reference or Server SQL Reference for more + details. + + To preserve trailing spaces in placeholder values for Oracle clients + that use OCI 8, either change the default placeholder type with + "ora_ph_type" or the placeholder type for a particular call to "bind" in + DBI or "bind_param_inout" in DBI with "ora_type" or "TYPE". Using + ORA_CHAR with ora_type or "SQL_CHAR" with "TYPE" allows the placeholder + to be used with Padded Comparison Semantics if the value it is being + compared to is a CHAR, NCHAR, or literal. + + Please remember that using spaces as a value or at the end of a value + makes visually distinguishing values with different numbers of spaces + difficult and should be avoided. + + Oracle Clients that use OCI 9.2 do not strip trailing spaces. + + Padded Char Fields + Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder + values to the size of the CHAR. As the default placeholder type value in + DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will have to + change the default placeholder type with "ora_ph_type" or placeholder + type for a particular call with "bind" in DBI or "bind_param_inout" in + DBI with "ORA_CHAR". + +UNICODE + DBD::Oracle now supports Unicode UTF-8. There are, however, a number of + issues you should be aware of, so please read all this section + carefully. + + In this section we'll discuss "Perl and Unicode", then "Oracle and + Unicode", and finally "DBD::Oracle and Unicode". + + Information about Unicode in general can be found at: + . It is well worth reading because there are + many misconceptions about Unicode and you may be holding some of them. + + Perl and Unicode + Perl began implementing Unicode with version 5.6, but the implementation + did not mature until version 5.8 and later. If you plan to use Unicode + you are *strongly* urged to use Perl 5.8.2 or later and to *carefully* + read the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + + And then read it again. + + Perl's internal Unicode format is UTF-8 which corresponds to the Oracle + character set called AL32UTF8. + + Oracle and Unicode + Oracle supports many characters sets, including several different forms + of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + + When you create an Oracle database, you must specify the DATABASE + character set (used for DDL, DML and CHAR datatypes) and the NATIONAL + character set (used for NCHAR and NCLOB types). The character sets used + in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + + The Oracle 9.2 and later default for the national character set is + AL16UTF16. The default for the database character set is often US7ASCII. + Although many experienced DBAs will consider an 8bit character set like + WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other + than US7ASCII, requires that the NLS_LANG environment variable be set. + See the "Oracle UTF8 is not UTF-8" section below. + + You are strongly urged to read the Oracle Internationalization + documentation specifically with respect the choices and trade offs for + creating a databases for use with international character sets. + + Oracle uses the NLS_LANG environment variable to indicate what character + set is being used on the client. When fetching data Oracle will convert + from whatever the database character set is to the client character set + specified by NLS_LANG. Similarly, when sending data to the database + Oracle will convert from the character set specified by NLS_LANG to the + database character set. + + The NLS_NCHAR environment variable can be used to define a different + character set for 'national' (NCHAR) character types. + + Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. For + example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + + Oracle UTF8 is not UTF-8 + AL32UTF8 should be used in preference to UTF8 if it works for you, which + it should for Oracle 9.2 or later. If you're using an old version of + Oracle that doesn't support AL32UTF8 then you should avoid using any + Unicode characters that require surrogates, in other words characters + beyond the Unicode BMP (Basic Multilingual Plane). + + That's because the character set that Oracle calls "UTF8" doesn't + conform to the UTF-8 standard in its handling of surrogate characters. + Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". + Here are a couple of extracts from + : + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + + Oracle uses this internally because it collates (sorts) in the same + order as UTF16, which is the basis of Oracle's internal collation + definitions. + + Rather than change UTF8 for clients Oracle chose to define a new + character set called "AL32UTF8" which does conform to the UTF-8 + standard. (The AL32UTF8 character set can't be used on the server + because it would break collation.) + + Because of that, for the rest of this document we'll use "AL32UTF8". If + you're using an Oracle version below 9.2 you'll need to use "UTF8" until + you upgrade. + + DBD::Oracle and Unicode + DBD::Oracle Unicode support has been implemented for Oracle versions 9 + or greater, and Perl version 5.6 or greater (though we *strongly* + suggest that you use Perl 5.8.2 or later). + + You can check which Oracle version your DBD::Oracle was built with by + importing the "ORA_OCI" constant from DBD::Oracle. + + Fetching Data + + Any data returned from Oracle to DBD::Oracle in the AL32UTF8 character + set will be marked as UTF-8 to ensure correct handling by Perl. + + For Oracle to return data in the AL32UTF8 character set the NLS_LANG or + NLS_NCHAR environment variable *must* be set as described in the + previous section. + + When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle + will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR is + AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + + When fetching other character data from Oracle, DBD::Oracle will set the + Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + + Sending Data using Placeholders + + Data bound to a placeholder is assumed to be in the default client + character set (specified by NLS_LANG) except for a few special cases. + These are listed here with the highest precedence first: + + If the "ora_csid" attribute is given to bind_param() then that is passed + to Oracle and takes precedence. + + If the value is a Perl Unicode string (UTF-8) then DBD::Oracle ensures + that Oracle uses the Unicode character set, regardless of the NLS_LANG + and NLS_NCHAR settings. + + If the placeholder is for inserting an NCLOB then the client NLS_NCHAR + character set is used. (That's useful but inconsistent with the other + behaviour so may change. Best to be explicit by using the "ora_csform" + attribute.) + + If the "ora_csform" attribute is given to bind_param() then that + determines if the value should be assumed to be in the default + (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + Binding with bind_param_array and execute_array is also UTF-8 compatible + in the same way. If you attempt to insert UTF-8 data into a non UTF-8 + Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert will + still happen but a error code of 0 will be returned with the following + warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + + The warning will report the parameter number and the NCHAR setting that + the query is running. + + Sending Data using SQL + + Oracle assumes the SQL statement is in the default client character set + (as specified by NLS_LANG). So Unicode strings containing non-ASCII + characters should not be used unless the default client character set is + AL32UTF8. + + DBD::Oracle and Other Character Sets and Encodings + The only multi-byte Oracle character set supported by DBD::Oracle is + "AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +OBJECT & COLLECTION DATA TYPES + Oracle databases allow for the creation of object oriented like + user-defined types. There are two types of objects, Embedded--an object + stored in a column of a regular table and REF--an object that uses the + REF retrieval mechanism. + + DBD::Oracle supports only the 'selection' of embedded objects of the + following types OBJECT, VARRAY and TABLE in any combination. Support is + seamless and recursive, meaning you need only supply a simple SQL + statement to get all the values in an embedded object. You can either + get the values as an array of scalars or they can be returned into a + DBD::Oracle::Object. + + Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + + The code to access all the data in the table could be something like + this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + + Note that values in PHONE_NUMBERS are returned as an array reference + '@$phone'. + + As stated before DBD::Oracle will automatically drill into the embedded + object and extract all of the data as reference arrays of scalars. The + example below has OBJECT type embedded in a TABLE type embedded in an + SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + + The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + + Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + + The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + + So far DBD::Oracle has been tested on a table with 20 embedded Objects, + Varrays and Tables nested to 10 levels. + + Any NULL values found in the embedded object will be returned as + 'undef'. + +OTHER DATA TYPES + DBD::Oracle does not *explicitly* support most Oracle datatypes. It + simply asks Oracle to return them as strings and Oracle does so. Mostly. + Similarly when binding placeholder values DBD::Oracle binds them as + strings and Oracle converts them to the appropriate type, such as DATE, + when used. + + Some of these automatic conversions to and from strings use NLS settings + to control the formatting for output and the parsing for input. The most + common example is the DATE type. The default NLS format for DATE might + be DD-MON-YYYY and so when a DATE type is fetched that's how Oracle will + format the date. NLS settings also control the default parsing of + strings into DATE values. An error will be generated if the contents of + the string don't match the NLS format. If you're dealing in dates which + don't match the default NLS format then you can either change the + default NLS format or, more commonly, use TO_CHAR(field, "format") and + TO_DATE(?, "format") to explicitly specify formats for converting to and + from strings. + + A slightly more subtle problem can occur with NUMBER types. The default + NLS settings might format numbers with a fullstop (""."") to separate + thousands and a comma ("","") as the decimal point. Perl will generate + warnings and use incorrect values when numbers, returned and formatted + as strings in this way by Oracle, are used in a numeric context. You + could explicitly convert each numeric value using the TO_CHAR(...) + function but that gets tedious very quickly. The best fix is to change + the NLS settings. That can be done for an individual connection by + doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + + There are some types, like BOOLEAN, that Oracle does not automatically + convert to or from strings (pity). These need to be converted explicitly + using SQL or PL/SQL functions. + + Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + + Support for Insert of XMLType (ORA_XMLTYPE) + Inserting large XML data sets into tables with XMLType fields is now + supported by DBD::Oracle. The only special requirement is the use of + bind_param() with an attribute hash parameter that specifies ora_type as + ORA_XMLTYPE. For example with a table like this; + + create table books (book_id number, book_xml XMLType); + + one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + + In the above case we will assume that $xml has 10000 Book nodes and is + over 32k in size and is well formed XML. This will also work for XML + that is smaller than 32k as well. Attempting to insert malformed XML + will cause an error. + + Binding Cursors + Cursors can be returned from PL/SQL blocks, either from stored functions + (or procedures with OUT parameters) or from direct "OPEN" statements, as + shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + The only special requirement is the use of "bind_param_inout()" with an + attribute hash parameter that specifies "ora_type" as "ORA_RSET". If you + don't do that you'll get an error from the "execute()" like: "ORA-06550: + line X, column Y: PLS-00306: wrong number or types of arguments in call + to ...". + + Here's an alternative form using a function that returns a cursor. This + example uses the pre-defined weak (or generic) REF CURSOR type + SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + A cursor obtained from PL/SQL as above may be passed back to PL/SQL by + binding for input, as shown in this example, which explicitly closes a + cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + + It is not normally necessary to close a cursor explicitly in this way. + Oracle will close the cursor automatically at the first client-server + interaction after the cursor statement handle is destroyed. An explicit + close may be desirable if the reference to the cursor handle from the + PL/SQL statement handle delays the destruction of the cursor handle for + too long. This reference remains until the PL/SQL handle is re-bound, + re-executed or destroyed. + + See the "curref.pl" script in the Oracle.ex directory in the DBD::Oracle + source distribution for a complete working example. + + Fetching Nested Cursors + Oracle supports the use of select list expressions of type REF CURSOR. + These may be explicit cursor expressions - "CURSOR(SELECT ...)", or + calls to PL/SQL functions which return REF CURSOR values. The values of + these expressions are known as nested cursors. + + The value returned to a Perl program when a nested cursor is fetched is + a statement handle. This statement handle is ready to be fetched from. + It should not (indeed, must not) be executed. + + Oracle imposes a restriction on the order of fetching when nested + cursors are used. Suppose $sth1 is a handle for a select statement + involving nested cursors, and $sth2 is a nested cursor handle fetched + from $sth1. $sth2 can only be fetched from while $sth1 is still active, + and the row containing $sth2 is still current in $sth1. Any attempt to + fetch another row from $sth1 renders all nested cursor handles + previously fetched from $sth1 defunct. + + Fetching from such a defunct handle results in an error with the message + "ERROR nested cursor is defunct (parent row is no longer current)". + + This means that the "fetchall..." or "selectall..." methods are not + useful for queries returning nested cursors. By the time such a method + returns, all the nested cursor handles it has fetched will be defunct. + + It is necessary to use an explicit fetch loop, and to do all the + fetching of nested cursors within the loop, as the following example + shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + + The cursor returned by the function "sp_ListEmp" defined in the previous + section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + + Pre-fetching Nested Cursors + By default, DBD::Oracle pre-fetches rows in order to reduce the number + of round trips to the server. For queries which do not involve nested + cursors, the number of pre-fetched rows is controlled by the DBI + database handle attribute "RowCacheSize" (q.v.). + + In Oracle, server side open cursors are a controlled resource, limited + in number, on a per session basis, to the value of the initialization + parameter "OPEN_CURSORS". Nested cursors count towards this limit. Each + nested cursor in the current row counts 1, as does each nested cursor in + a pre-fetched row. Defunct nested cursors do not count. + + An Oracle specific database handle attribute, "ora_max_nested_cursors", + further controls pre-fetching for queries involving nested cursors. For + each statement handle, the total number of nested cursors in pre-fetched + rows is limited to the value of this parameter. The default value is 0, + which disables pre-fetching for queries involving nested cursors. + +PL/SQL Examples + Most of these PL/SQL examples come from: Eric Bartley + . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + + You can find more examples in the t/plsql.t file in the DBD::Oracle + source directory. + + Oracle 9.2 appears to have a bug where a variable bound with + bind_param_inout() that isn't assigned to by the executed PL/SQL block + may contain garbage. See + + + Avoid Using "SQL Call" + Avoid using the "SQL Call" statement with DBD:Oracle as you might find + that DBD::Oracle will not raise an exception in some case. Specifically + if you use "SQL Call" to run a procedure all "No data found" exceptions + will be quietly ignored and returned as null. According to Oracle + support this is part of the same mechanism where; + + select (select * from dual where 0=1) from dual + + returns a null value rather than an exception. + +CONTRIBUTING + If you'd like DBD::Oracle to do something new or different the best way + to make that happen is to do it yourself and email to dbi-dev@perl.org a + patch of the source code (using 'diff' - see below) that shows the + changes. + + How to create a patch using Subversion + The DBD::Oracle source code is maintained using Subversion (a + replacement for CVS, see ). To access the + source you'll need to install a Subversion client. Then, to get the + source code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + + If it prompts for a username and password use your perl.org account if + you have one, else just 'guest' and 'guest'. The source code will be in + a new subdirectory called "trunk". + + To keep informed about changes to the source you can send an empty email + to dbd-oracle-changes-subscribe@perl.org after which you'll get an email + with the change log message and diff of each change checked-in to the + source. + + After making your changes you can generate a patch file, but before you + do, make sure your source is still upto date using: + + svn update + + If you get any conflicts reported you'll need to fix them first. Then + generate the patch file from within the "trunk" directory using: + + svn diff > foo.patch + + Read the patch file, as a sanity check, and then email it to + dbi-dev@perl.org. + + How to create a patch without Subversion + Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + + Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + + Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you + want. + + Test your changes and then remove all temporary files: + + make test && make distclean + + Go back to the directory you originally unpacked the distribution: + + cd .. + + Unpack *another* copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + + Then create a patch file by performing a recursive "diff" on the two top + level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + + Speak before you patch + For anything non-trivial or possibly controversial it's a good idea to + discuss (on dbi-dev@perl.org) the changes you propose before actually + spending time working on them. Otherwise you run the risk of them being + rejected because they don't fit into some larger plans you may not be + aware of. + + GitHub repository + A git mirror of the subversion is also available at + `https://github.com/yanick/DBD-Oracle`. + +Oracle Related Links +WHICH VERSION OF DBD::ORACLE IS FOR ME? + From version 1.25 onwards DBD::Oracle only support Oracle clients 9.2 or + greater. Support for ProC connections was dropped in 1.29. + + If you are still stuck with an older version of Oracle or its client you + might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + + As there are dozens of different versions of Oracle's clients this list + does not include all of them, just the major released versions of + Oracle. + + Note that one can still connect to any Oracle version with the older + DBD::Oracle versions the only problem you will have is that some of the + newer OCI and Oracle features available in later DBD::Oracle releases + will not be available to you. + + So to make a short story a little longer: + + 1 If you are using Oracle 7 or early 8 DB and you can manage to get a + 9 client and you can use any DBD::Oracle version. + + 2 If you have to use an Oracle 7 client then DBD::Oracle 1.17 should + work + + 3 Same thing for 8 up to R2, use 1.17, if you are lucky and have the + right patch-set you might go with 1.18. + + 4 For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. + Again this depends on your patch-set, If you run into trouble go + with 1.19 + + 5 After 9.2 you can use any version you want. + + 6 It seems that the 10g client can only connect to 9 and 11 DBs while + the 9 can go back to 7 and even get to 10. I am not sure what the + 11g client can connect to. + +BUGS AND LIMITATIONS + There is a known problem with the 11.2g Oracle client and the + "DBMS_LOB.GETLENGTH()" PL/SQL function. See + for the details. + +SEE ALSO + DBI http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in + the DBD::Oracle source distribution including the examples in the + Oracle.ex directory + + DBD::Oracle Tutorial + http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-ora + cle.html + + Oracle Instant Client + http://www.oracle.com/technology/tech/oci/instantclient/index.html + + Oracle on Linux + http://www.ixora.com.au/ + + Free Oracle Tools and Links + ora_explain supplied and installed with DBD::Oracle. + + http://www.orafaq.com/ + + http://vonnieda.org/oracletool/ + + Commercial Oracle Tools and Links + Assorted tools and references for general information. No + recommendation implied. + + http://www.platinum.com + + http://www.SoftTreeTech.com + + Also PL/Vision from RevealNet and Steven Feuerstein, and "Q" from + Savant Corporation. + +AUTHORS + DBI by Tim Bunce . + + The original "DBD::Oracle" was by Tim Bunce. Maintained as of release + 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the + auspice of the Pythian Group (). + +ACKNOWLEDGEMENTS + A great many people have helped with DBD::Oracle over the 17 years + between 1994 and 2011. Far too many to name, but we thank them all. Many + are named in the Changes file. + +COPYRIGHT + The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. + The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The + Pythian Group). Canada. The DBD::Oracle module is Copyright (c) 2011 + John Scoles. Canada. + + The DBD::Oracle module is free open source software; you can + redistribute it and/or modify it under the same terms as Perl 5. + +AUTHORS + * Tim Bunce + + * John Scoles + + * Yanick Champoux + +COPYRIGHT AND LICENSE + This software is copyright (c) 1994 by Tim Bunce. + + This is free software; you can redistribute it and/or modify it under + the same terms as the Perl 5 programming language system itself. diff --git a/README.mkdn b/README.mkdn new file mode 100644 index 00000000..efd36615 --- /dev/null +++ b/README.mkdn @@ -0,0 +1,4228 @@ +# NAME + +DBD::Oracle - Oracle database driver for the DBI module + +# VERSION + +version 1.38 + +# SYNOPSIS + + use DBI; + + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); + + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); + + # See the DBI module documentation for full details + + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); + +# DESCRIPTION + +DBD::Oracle is a Perl module which works with the DBI module to provide +access to Oracle databases. + +This documentation describes driver specific behaviour and restrictions. It is +not supposed to be used as the only reference for the user. In any case +consult the [DBI](http://search.cpan.org/perldoc?DBI) documentation first! + +# CONSTANTS + +- :ora_session_modes + +ORA_SYSDBA ORA_SYSOPER ORA_SYSASM + +- :ora_types + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +- SQLCS_IMPLICIT + +- SQLCS_NCHAR + +SQLCS_IMPLICIT and SQLCS_NCHAR are _character set form_ values. +See notes about Unicode elsewhere in this document. + +- SQLT_INT + +- SQLT_FLT + +These types are used only internally, and may be specified as internal +bind type for ORA_NUMBER_TABLE. See notes about ORA_NUMBER_TABLE elsewhere +in this document + +- ORA_OCI + +Oracle doesn't provide a formal API for determining the exact version +number of the OCI client library used, so DBD::Oracle has to go digging +(and sometimes has to more or less guess). The ORA_OCI constant +holds the result of that process. + +In string context ORA_OCI returns the full "A.B.C.D" version string. + +In numeric context ORA_OCI returns the major.minor version number +(8.1, 9.2, 10.0 etc). But note that version numbers are not actually +floating point and so if Oracle ever makes a release that has a two +digit minor version, such as `9.10` it will have a lower numeric +value than the preceding `9.9` release. So use with care. + +The contents and format of ORA_OCI are subject to change (it may, +for example, become a _version object_ in later releases). +I recommend that you avoid checking for exact values. + +- :ora_fetch_orient + + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE + +These constants are used to set the orientation of a fetch on a scrollable cursor. + +- :ora_exe_modes + + OCI_STMT_SCROLLABLE_READONLY + +- :ora_fail_over + + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + +# DBI CLASS METHODS + +## __connect__ + +This method creates a database handle by connecting to a database, and is the DBI equivalent of the "new" method. +To open a connection to an Oracle database you need to specify a database connection string (URL), username and password. + +The connection string is always of the form: "dbi:Oracle:" +There are several ways to identify a database: + +- 1 + +If the database is local, specifying the SID or service name will be enough. + +- 2 + +If the database is defined in a TNSNAMES.ORA file, you can use the service name given in the file + +- 3 + +To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: +//host[:port][/service_name] + +If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. + +The following examples show several ways a connection can be created: + + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); + + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); + + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); + + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); + +### OS authentication + +To connect to a local database with a user which has been set up to +authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): + + $dbh = DBI->connect('dbi:Oracle:','/',''); + +Note the lack of a connection name (use the ORACLE_SID environment +variable). If an explicit SID is used you will probably get an ORA-01004 error. + +That only works for local databases. (Authentication to remote Oracle +databases using your Unix login name without a password is possible +but it is not secure and not recommended so not documented here. + +### Oracle Environment Variables + +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). + +Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. + +To use them, specify either a local SID or service name, or a service name that is specified in the TNSNAMES.ORA file. + +Note that if you have *both* local and remote databases, and you have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO_TASK takes precedence over ORACLE_SID (i.e. you get connected to remote system). + +It is highly recommended not to rely on environment variables and to always explicitly specify the SID in the connection string. This can prevent serious mistakes such as dropping a schema in the wrong database, and generally makes debugging and troubleshooting easier. + +Also remember that depending on the operating system you are using the differing "ORACLE" environment variables may be case sensitive, so if you are not connecting as you should double check the case of both the variable and its value. + +### Timezones + +If the query is run through SQL*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. + +If the query is run locally, Oracle will return the time zone based on the "TZ" environment variable setting of the user running +the query. + +With local queries, you can change the time zone for a particular user by simply changing the setting of "TZ". To check the current setting, +issue the UNIX "date" command. + +### Oracle DRCP + +DBD::Oracle supports DRCP (Database Resident Connection Pool) so +if you have an 11.2 database and DRCP is enabled you can direct +all of your connections to it by adding ':POOLED' to the SID or +setting a connection attribute of ora_drcp, or set the SERVER=POOLED +when using a TNSENTRY style connection or even by setting an +environment variable ORA_DRCP. All of which are demonstrated below; + + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') + + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') + + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") + + if the ORA_DRCP environment variable is set then just this + + $dbh = DBI->connect('dbi:Oracle:DB','username','password') + +You can find a white paper on setting up DRCP and its advantages at [http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf](http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf). + +Please note that DRCP support in DBD::Oracle is relatively new so the +mechanics or its implementation are subject to change. + +### TAF (Transparent Application Failover) + +Transparent Application Failover (TAF) is the feature in OCI that +allows for clients to automatically reconnect to an instance in the +event of a failure of the instance. The reconnect happens +automatically from within the OCI (Oracle Call Interface) library. +DBD::Oracle now supports a callback function that will fire when a TAF +event takes place. The main use of the callback is to give your +program the opportunity to inform the user that a failover is taking +place. + +You will have to set up TAF on your instance before you can use this +callback. You can test your instance to see if you can use TAF +callback with + + $dbh->ora_can_taf(); + +If you try to set up a callback without it being enabled DBD::Oracle will croak. + +It is outside the scope of this documents to go through all of the +possible TAF situations you might want to set up but here is a simple +example: + +The TNS entry for the instance has had the following added to the +CONNECT_DATA section + + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) + +You will also have to create your own perl function that will be +called from the client. You can name it anything you want and it will +always be passed two parameters, the failover event value and the +failover type. You can also set a sleep value in case of failover +error and the OCI client will sleep for the specified seconds before it +attempts another event. + + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants + + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + + #create the perl TAF event function + + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ + + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); + + } + return 0; + } + +The TAF types are as follows + + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + +The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + +### Connect Attributes + +#### ora_ncs_buff_mtpl + +You can customize the size of the buffer when selecting LOBs with +the built-in AUTO Lob. The default value is 4 which is probably +excessive for most situations but is needed for backward +compatibility. If you not converting between a NCS on the DB and the +Client then you might want to set this to 1 to reduce memory usage. + +This value can also be specified with the `ORA_DBD_NCS_BUFFER` +environment variable in which case it sets the value at the connect +stage. + +#### ora_drcp + +For Oracle 11.2 or greater. + +Set to _1_ to enable DRCP. Can also be set via the `ORA_DRCP` environment variable. + +#### ora_drcp_class + +If you are using DRCP, you can set a CONNECTION_CLASS for your pools +as well. As sessions from a DRCP cannot be shared by users, you can +use this setting to identify the same user across different +applications. OCI will ensure that sessions belonging to a 'class' are +not shared outside the class'. + +The values for ora_drcp_class cannot contain a '*' and must be less +than 1024 characters. + +This value can be also be specified with the `ORA_DRCP_CLASS` +environment variable. + +#### ora_drcp_min + +This optional value specifies the minimum number of sessions that are +initially opened. New sessions are only opened after this value has +been reached. + +The default value is 4 and any value above 0 is valid. + +Generally, it should be set to the number of concurrent statements the +application is planning or expecting to run. + +This value can also be specified with the `ORA_DRCP_MIN` environment +variable. + +#### ora_drcp_max + +This optional value specifies the maximum number of sessions that can +be open at one time. Once reached no more sessions can be opened +until one becomes free. The default value is 40 and any value above 1 +is valid. You should not set this value lower than ora_drcp_min as +that will just waste resources. + +This value can also be specified with the `ORA_DRCP_MAX` environment +variable. + +#### ora_drcp_incr + +This optional value specifies the next increment for sessions to be +started if the current number of sessions are less than +ora_drcp_max. The default value is 2 and any value above 0 is +valid as long as the value of ora_drcp_min + ora_drcp_incr is not +greater than ora_drcp_max. + +This value can also be specified with the `ORA_DRCP_INCR` environment +variable. + +#### ora_taf + +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option to any _true_ value. + +#### ora_taf_function + +The name of the Perl subroutine that will be called from OCI when a +TAF event occurs. You must supply a perl function to use the callback +and it will always receive two parameters, the failover event value +and the failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + +#### ora_taf_sleep + +The amount of time in seconds the OCI client will sleep between attempting +successive failover events when the event is OCI_FO_ERROR. + +#### ora_session_mode + +The ora_session_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA_SYSASM authorization. +The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + +This is one case where setting ORACLE_SID may be useful since +connecting as SYSDBA or SYSOPER via SQL*Net is frequently disabled +for security reasons. + +Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + +It has been reported that this only works if `$dsn` does not contain +a SID so that Oracle then uses the value of ORACLE_SID (not +TWO_TASK) environment variable to connect to a local instance. Also +the username and password should be empty, and the user executing the +script needs to be part of the dba group or osdba group. + +#### ora_oratab_orahome + +Passing a true value for the ora_oratab_orahome attribute will make +DBD::Oracle change `$ENV{ORACLE_HOME}` to make the Oracle home directory +that specified in the `/etc/oratab` file _if_ the database to connect to +is specified as a SID that exists in the oratab file, and DBD::Oracle was +built to use the Oracle 7 OCI API (not Oracle 8+). + +#### ora_module_name + +After connecting to the database the value of this attribute is passed +to the SET_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL +package. This can be used to identify the application to the DBA for +monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + +The maximum size is 48 bytes. + +#### ora_driver_name + +For 11g and later you can now set the name of the driver layer using OCI. +Perl, Perl5, ApachePerl so on. Names starting with "ORA" are reserved. You +can enter up to 8 characters. If none is enter then this will default to +DBDOxxxx where xxxx is the current version number. This value can be +retrieved on the server side using V$SESSION_CONNECT_INFO or +GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + +#### ora_client_info + +Allows you to add any value (up to 64 bytes) to your session and it can be +retrieved on the server side from the `V$SESSION`a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + +#### ora_client_identifier + +Allows you to specify the user identifier in the session handle. + +Most useful for web applications as it can pass in the session user +name which might be different to the connection user name. Can be up +to 64 bytes long but do not to include the password for security +reasons and the first character of the identifier should not be +':'. This value can be retrieved on the server side using `V$SESSION` +view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + +#### ora_action + +Allows you to specify any string up to 32 bytes which may be retrieved +on the server side using `V$SESSION` view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + +#### ora_dbh_share + +Requires at least Perl 5.8.0 compiled with ithreads. + +Allows you to share +database connections between threads. The first connect will make the +connection, all following calls to connect with the same ora_dbh_share +attribute will use the same database connection. The value must be a +reference to a already shared scalar which is initialized to an empty +string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + +#### ora_envhp + +The first time a connection is made a new OCI 'environment' is +created by DBD::Oracle and stored in the driver handle. +Subsequent connects reuse (share) that same OCI environment +by default. + +The ora_envhp attribute can be used to disable the reuse of the OCI +environment from a previous connect. If the value is `0` then +a new OCI environment is allocated and used for this connection. + +The OCI environment holds information about the client side context, +such as the local NLS environment. By altering `%ENV` and setting +ora_envhp to 0 you can create connections with different NLS +settings. This is most useful for testing. + +#### ora_charset, ora_ncharset + +For oracle versions >= 9.2 you can specify the client charset and +ncharset with the ora_charset and ora_ncharset attributes. You +still need to pass `ora_envhp = 0` for all but the first connect. + +These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + +#### ora_verbose + +Use this value to enable DBD::Oracle only tracing. Simply either set +the ora_verbose attribute on the connect() method to the trace level +you desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + +or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + +In both cases the DBD::Oracle trace level is set to 6, which is the highest +level tracing most of the calls to OCI. + +#### ora_oci_success_warn + +Use this value to print otherwise silent OCI warnings that may happen +when an execute or fetch returns "Success With Info" or when you want +to tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + +#### ora_objects + +Use this value to enable extended embedded oracle objects mode. In extended: + +- 1 + +Embedded objects are returned as instance (including type-name etc.) instead of simple ARRAY. + +- 2 + +Determine object type for each instance. All object attributes are returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + +#### ora_ph_type + +The default placeholder datatype for the database session. +The `TYPE` or [ora_type](#pod_ora_type) attributes to L and +L override the datatype for individual placeholders. +The most frequent reason for using this attribute is to permit trailing spaces +in values passed by placeholders. + +Constants for the values allowed for this attribute can be imported using + + use DBD::Oracle qw(:ora_types); + +Only the following values are permitted for this attribute. + +- ORA_VARCHAR2 + +Oracle clients using OCI 8 will strip trailing spaces and allow embedded \0 bytes. +Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \0 bytes. +This is the normal default placeholder type. + +- ORA_STRING + +Do not strip trailing spaces and end the string at the first \0. + +- ORA_CHAR + +Do not strip trailing spaces and allow embedded \0. +Force 'blank-padded comparison semantics'. + +For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + +Will pad bloggs out to 8 characters and return the username. + +#### ora_parse_error_offset + +If the previous error was from a failed `prepare` due to a syntax error, +this attribute gives the offset into the `Statement` attribute where the +error was found. + +#### ora_array_chunk_size + +Due to OCI limitations, DBD::Oracle needs to buffer up rows of +bind values in its `execute_for_fetch` implementation. This attribute +sets the number of rows to buffer at a time (default value is 1000). + +The `execute_for_fetch` function will collect (at most) this many +rows in an array, send them off to the DB for execution, then go back +to collect the next chunk of rows and so on. This attribute can be +used to limit or extend the number of rows processed at a time. + +Note that this attribute also applies to `execute_array`, since that +method is implemented using `execute_for_fetch`. + +#### ora_connect_with_default_signals + +Sometimes the Oracle client seems to change some of the signal +handlers of the process during the connect phase. For instance, some +users have observed Perl's default `$SIG{INT}` handler being ignored +after connecting to an Oracle database. If this causes problems in +your application, set this attribute to an array reference of signals +you would like to be localized during the connect process. Once the +connect is complete, the signal handlers should be returned to their +previous state. + +For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + +NOTE disabling the signal handlers the OCI library sets up may affect +functionality in the OCI library. + +NOTE If you are using connect_cached then the above example will lead +to DBI thinking each connection is different as an anonymous array reference +is being used. To avoid this when using connect_cached you are advised +to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + +In more recent Perl versions you could possibly make use of new state +variables. + +## __connect_cached__ + +Implemented by DBI, no driver-specific impact. +Please note that connect_cached as not been tested with DRCP. + +## __data_sources__ + + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + +Returns a list of available databases. You will have to set either the 'ORACLE_HOME' or +'TNS_ADMIN' environment value to retrieve this list. It will read these values from +TNSNAMES.ORA file entries. + +# METHODS COMMON TO ALL HANDLES + +For all of the methods below, __$h__ can be either a database handle (__$dbh__) +or a statement handle (__$sth__). Note that _$dbh_ and _$sth_ can be replaced with +any variable name you choose: these are just the names most often used. Another +common variable used in this documentation is $_rv_, which stands for "return value". + +## __err__ + + $rv = $h->err; + +Returns the error code from the last method called. + +## __errstr__ + + $str = $h->errstr; + +Returns the last error that was reported by Oracle. Starting with "ORA-00000" code followed by the error message. + +## __state__ + + $str = $h->state; + +Oracle hasn't supported SQLSTATE since the early versions OCI. It will return empty when the command succeeds and +'S1000' (General Error) for all other errors. + +While this method can be called as either `$sth->state` or `$dbh->state`, it +is usually clearer to always use `$dbh->state`. + +## __trace__ + +Implemented by DBI, no driver-specific impact. + +## __trace_msg__ + +Implemented by DBI, no driver-specific impact. + +## __parse_trace_flag__ and __parse_trace_flags__ + +Implemented by DBI, no driver-specific impact. + +## __func__ + +DBD::Oracle uses the `func` method to support a variety of functions. + +## __Private database handle functions__ + +Some of these functions are called through the method func() +which is described in the DBI documentation. Any function that begins with ora_ +can be called directly. + +## __plsql_errstr__ + +This function returns a string which describes the errors +from the most recent PL/SQL function, procedure, package, +or package body compile in a format similar to the output +of the SQL*Plus command 'show errors'. + +The function returns undef if the error string could not +be retrieved due to a database error. +Look in $dbh->errstr for the cause of the failure. + +If there are no compile errors, an empty string is returned. + +Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + +## __dbms_output_enable / dbms_output_put / dbms_output_get__ + +These functions use the PL/SQL DBMS_OUTPUT package to store and +retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer +by dbms_output_put or any PL/SQL block can be retrieved by +dbms_output_get or any PL/SQL block connected to the same database +session. + +Stored text is not available until after dbms_output_put or the PL/SQL +block that saved it completes its execution. This means you __CAN NOT__ +use these functions to monitor long running PL/SQL procedures. + +Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + +Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + +## __dbms_output_enable ( [ buffer_size ] )__ + +This function calls DBMS_OUTPUT.ENABLE to enable calls to package +DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to +these procedures are ignored unless DBMS_OUTPUT.ENABLE is called +first. + +The buffer_size is the maximum amount of text that can be saved in the +buffer and must be between 2000 and 1,000,000. If buffer_size is not +given, the default is 20,000 bytes. + +## __dbms_output_put ( [ @lines ] )__ + +This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + +If all lines were saved successfully the function returns 1. Depending +on the context, an empty list or undef is returned for failure. + +If any line causes buffer_size to be exceeded, a buffer overflow error +is raised and the function call fails. Some of the text might be in +the buffer. + +## __dbms_output_get__ + +This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from +the buffer. + +In an array context, all complete lines are removed from the buffer and +returned as a list. If there are no complete lines, an empty list is +returned. + +In a scalar context, the first complete line is removed from the buffer +and returned. If there are no complete lines, undef is returned. + +Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or +DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, +DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + +## __reauthenticate ( $username, $password )__ + +Starts a new session against the current database using the credentials +supplied. + +## __private_attribute_info__ + + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + +Returns a hash of all private attributes used by DBD::Oracle, for either +a database or a statement handle. Currently, all the hash values are undef. + +# ATTRIBUTES COMMON TO ALL HANDLES + +## __InactiveDestroy__ (boolean) + +Implemented by DBI, no driver-specific impact. + +## __RaiseError__ (boolean, inherited) + +Forces errors to always raise an exception. Although it defaults to off, it is recommended that this +be turned on, as the alternative is to check the return value of every method (prepare, execute, fetch, etc.) +manually, which is easy to forget to do. + +## __PrintError__ (boolean, inherited) + +Forces database errors to also generate warnings, which can then be filtered with methods such as +locally redefining _$SIG{__WARN__}_ or using modules such as `CGI::Carp`. This attribute is on +by default. + +## __ShowErrorStatement__ (boolean, inherited) + +Appends information about the current statement to error messages. If placeholder information +is available, adds that as well. Defaults to true. + +## __Warn__ (boolean, inherited) + +Enables warnings. This is on by default, and should only be turned off in a local block +for a short a time only when absolutely needed. + +## __Executed__ (boolean, read-only) + +Indicates if a handle has been executed. For database handles, this value is true after the [do](#pod_do) method has been called, or +when one of the child statement handles has issued an [execute](#pod_execute). Issuing a [commit](#pod_commit) or [rollback](#pod_rollback) always resets the +attribute to false for database handles. For statement handles, any call to [execute](#pod_execute) or its variants will flip the value to +true for the lifetime of the statement handle. + +## __TraceLevel__ (integer, inherited) + +Sets the trace level, similar to the [trace](#pod_trace) method. See the sections on +[trace](#pod_trace) and [parse_trace_flag](#pod_parse_trace_flag) for more details. + +## __Active__ (boolean, read-only) + +Indicates if a handle is active or not. For database handles, this indicates if the database has +been disconnected or not. For statement handles, it indicates if all the data has been fetched yet +or not. Use of this attribute is not encouraged. + +## __Kids__ (integer, read-only) + +Returns the number of child processes created for each handle type. For a driver handle, indicates the number +of database handles created. For a database handle, indicates the number of statement handles created. For +statement handles, it always returns zero, because statement handles do not create kids. + +## __ActiveKids__ (integer, read-only) + +Same as `Kids`, but only returns those that are active. + +## __CachedKids__ (hash ref) + +Returns a hashref of handles. If called on a database handle, returns all statement handles created by use of the +`prepare_cached` method. If called on a driver handle, returns all database handles created by the [connect_cached](#pod_connect_cached) +method. + +## __ChildHandles__ (array ref) + +Implemented by DBI, no driver-specific impact. + +## __PrintWarn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleError__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleSetErr__ (code ref, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ErrCount__ (unsigned integer) + +Implemented by DBI, no driver-specific impact. + +## __FetchHashKeyName__ (string, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ChopBlanks__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Taint__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintIn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintOut__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Profile__ (inherited) + +Implemented by DBI, no driver-specific impact. + +## __Type__ (scalar) + +Returns `dr` for a driver handle, `db` for a database handle, and `st` for a statement handle. +Should be rarely needed. + +## __LongReadLen__ + +Implemented by DBI, no driver-specific impact. + +## __LongTruncOk__ + +Implemented by DBI, no driver-specific impact. + +## __CompatMode__ + +Type: boolean, inherited + +The CompatMode attribute is used by emulation layers (such as Oraperl) to enable compatible behaviour in the underlying driver (e.g., DBD::Oracle) for this handle. Not normally set by application code. + +It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. + +# ORACLE-SPECIFIC DATABASE HANDLE METHODS + +## __ora_can_unicode ( [ $refresh ] )__ + +Returns a number indicating whether either of the database character sets +is a Unicode encoding. Calls ora_nls_parameters() and passes the optional +$refresh parameter to it. + +0 = Neither character set is a Unicode encoding. + +1 = National character set is a Unicode encoding. + +2 = Database character set is a Unicode encoding. + +3 = Both character sets are Unicode encodings. + +## __ora_can_taf__ + +Returns true if the current connection supports TAF events. False if otherise. + +## __ora_nls_parameters ( [ $refresh ] )__ + +Returns a hash reference containing the current NLS parameters, as given +by the v$nls_parameters view. The values fetched are cached between calls. +To cause the latest values to be fetched, pass a true value to the function. + +# DATABASE HANDLE METHODS + +## __selectall_arrayref__ + + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectall_hashref__ + + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + +Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectcol_arrayref__ + + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the first column +from each rows returned by preparing and executing the SQL string. It is possible to specify exactly +which columns to return. See the DBI documentation for full details. + +## __prepare__ + + $sth = $dbh->prepare($statement, \%attr); + +Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. + +### __Prepare Attributes__ + +These attributes may be used in the `\%attr` parameter of the +L database handle method. + +- ora_placeholders + +Set to false to disable processing of placeholders. Used mainly for loading a +PL/SQL package that has been _wrapped_ with Oracle's `wrap` utility. + +- ora_auto_lob + +If true (the default), fetching retrieves the contents of the CLOB or +BLOB column in most circumstances. If false, fetching retrieves the +Oracle "LOB Locator" of the CLOB or BLOB value. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for more details. + +See also the LOB tests in 05dbi.t of Oracle::OCI for examples +of how to use LOB Locators. + +- ora_pers_lob + +If true the [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) method for the [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) will be +used for LOBs rather than the default method [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators). + +- ora_clbk_lob + +If true the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) method for the L will be used for LOBs. + +- ora_piece_lob + +If true the [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) method for the L will be used for LOBs. + +- ora_piece_size + +This is the max piece size for the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) +and [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) methods, in chars for CLOBS, and +bytes for BLOBS. + +- ora_check_sql + +If 1 (default), force SELECT statements to be described in prepare(). +If 0, allow SELECT statements to defer describe until execute(). + +See [Prepare Postponed Till Execute](#pod_Prepare Postponed Till Execute) for more information. + +- ora_exe_mode + +This will set the execute mode of the current statement. Presently +only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + +See [Scrollable Cursors](#pod_Scrollable Cursors) for more details. + +- ora_prefetch_rows + +Sets the number of rows to be prefetched. If it is not set, then the +default value is 1. See [Row Prefetching](#pod_Row Prefetching) for more details. + +- ora_prefetch_memory + +Sets the memory level for rows to be prefetched. The application then +fetches as many rows as will fit into that much memory. See L for more details. + +- ora_row_cache_off + +By default DBD::Oracle will use a row cache when fetching to cut down +the number of round trips to the server. If you do not want to use an +array fetch set this value to any value other than 0; + +See [Row Prefetching](#pod_Row Prefetching) for more details. + +### __Placeholders__ + +There are two types of placeholders that can be used in DBD::Oracle. The first is +the "question mark" type, in which each placeholder is represented by a single +question mark character. This is the method recommended by the DBI specs and is the most +portable. Each question mark is internally replaced by a "dollar sign number" in the order +in which they appear in the query (important when using [bind_param](#pod_bind_param)). + +The other placeholder type is "named parameters" in the format ":foo" which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + +The different types of placeholders cannot be mixed within a statement, but you may +use different ones for each statement handle you have. This is confusing at best, so +stick to one style within your program. + +## __prepare_cached__ + + $sth = $dbh->prepare_cached($statement, \%attr); + +Implemented by DBI, no driver-specific impact. This method is most useful +if the same query is used over and over as it will cut down round trips to the server. + +## __do__ + + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + +Prepare and execute a single statement. Returns the number of rows affected if the +query was successful, returns undef if an error occurred, and returns -1 if the +number of rows is unknown or not available. Note that this method will return __0E0__ instead +of 0 for 'no rows were affected', in order to always return a true value if no error occurred. + +## __last_insert_id__ + +Oracle does not implement auto_increment of serial type columns it uses predefined +sequences where the id numbers are either selected before insert, at insert time with a trigger, + or as part of the query. + +Below is an example of you to use the latter with the SQL returning clause to get the ID number back +on insert with the bind_param_inout method. +. + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + +## __commit__ + + $rv = $dbh->commit; + +Issues a COMMIT to the server, indicating that the current transaction is finished and that +all changes made will be visible to other processes. If AutoCommit is enabled, then +a warning is given and no COMMIT is issued. Returns true on success, false on error. + +## __rollback__ + + $rv = $dbh->rollback; + +Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit +is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and +false on error. + +## __begin_work__ + +This method turns on transactions until the next call to [commit](#pod_commit) or [rollback](#pod_rollback), if [AutoCommit](#pod_AutoCommit) is +currently enabled. If it is not enabled, calling begin_work will issue an error. Note that the +transaction will not actually begin until the first statement after begin_work is called. + +## __disconnect__ + + $rv = $dbh->disconnect; + +Disconnects from the Oracle database. Any uncommitted changes will be rolled back upon disconnection. It's +good policy to always explicitly call commit or rollback at some point before disconnecting, rather than +relying on the default rollback behavior. + +If the script exits before disconnect is called (or, more precisely, if the database handle is no longer +referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() +methods automatically. It is best to explicitly disconnect rather than rely on this behavior. + +## __ping__ + + $rv = $dbh->ping; + +This `ping` method is used to check the validity of a database handle. The value returned is +either 0, indicating that the connection is no longer valid, or 1, indicating the connection is valid. +This function does 1 round trip to the Oracle Server. + +## __get_info()__ + + $value = $dbh->get_info($info_type); + +DBD::Oracle supports `get_info()`, but (currently) only a few info types. + +## __table_info()__ + +DBD::Oracle supports attributes for `table_info()`. + +In Oracle, the concept of _user_ and _schema_ is (currently) the +same. Because database objects are owned by an user, the owner names +in the data dictionary views correspond to schema names. +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. + +Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + +TABLE_TYPE may contain a comma-separated list of table types. +The following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + +The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + +The special enumerations of catalogues, schemas and table types are +supported. However, TABLE_CAT is always NULL. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +`table_info()` performs a case-sensitive search. So, a selection +criterion should respect upper and lower case. +Normally, an identifier is case-insensitive. Oracle stores and +returns it in upper case. Sometimes, database objects are created +with quoted identifiers (for reserved words, mixed case, special +characters, ...). Such an identifier is case-sensitive (if not all +upper case). Oracle stores and returns it as given. +`table_info()` has no special quote handling, neither adds nor +removes quotes. + +## __primary_key_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary key constraint was created without an identifier, +PK_NAME contains a system generated name with the form SYS_Cn. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __foreign_key_info()__ + +This method (currently) supports the extended behaviour of SQL/CLI, i.e. the +result set contains foreign keys that refer to primary __and__ alternate keys. +The field UNIQUE_OR_PRIMARY distinguishes these keys. + +Oracle does not support catalogues, so `$pk_catalog` and `$fk_catalog` are +ignored as selection criteria (in the new style interface). +The UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always +NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary or foreign key constraints were created without an identifier, +UK_NAME or FK_NAME contains a system generated name with the form SYS_Cn. + +The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle (currently) +does not support other actions. + +The DELETE_RULE field may contain wrong values. This is a known Bug (#1271663) +in Oracle's data dictionary views. Currently (as of 8.1.7), 'RESTRICT' and +'SET DEFAULT' are not supported, 'CASCADE' is mapped correctly and all other +actions (incl. 'SET NULL') appear as 'NO ACTION'. + +The DEFERABILITY field is always NULL, because this columns is +not present in the ALL_CONSTRAINTS view of older Oracle releases. + +The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, +FK_TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __column_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + +Don't rely on the values of the BUFFER_LENGTH field! +Especially the length of FLOATs may be wrong. + +Datatype codes for non-standard types are subject to change. + +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +It is possible with Oracle to make the names of the various DB objects (table,column,index etc) +case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + +So in the example the exact case "Bla_BLA" must be used to get it info on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + +any case can be used to get info on the column. + +## __selectrow_array__ + + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + +Returns an array of row information after preparing and executing the provided SQL string. The rows are returned +by calling [fetchrow_array](#pod_fetchrow_array). The string can also be a statement handle generated by a previous prepare. Note that +only the first row of data is returned. If called in a scalar context, only the first column of the first row is +returned. Because this is not portable, it is not recommended that you use this method in that way. + +## __selectrow_arrayref__ + + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an array, by internal use of +the [fetchrow_arrayref](#pod_fetchrow_arrayref) method. + +## __selectrow_hashref__ + + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an hash, by internal use of +the [fetchrow_hashref](#pod_fetchrow_hashref) method. + +## __clone__ + + $other_dbh = $dbh->clone(); + +Creates a copy of the database handle by connecting with the same parameters as the original +handle, then trying to merge the attributes. See the DBI documentation for complete usage. + +# DATABASE HANDLE ATTRIBUTES + +## __AutoCommit__ (boolean) + +Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change +in the future, so it is highly recommended that you explicitly set it when +calling [connect](#pod_connect). + +## __ReadOnly__ (boolean) + + $dbh->{ReadOnly} = 1; + +Specifies if the current database connection should be in read-only mode or not. + +Please not that this method is not foolproof: there are still ways to update the +database. Consider this a safety net to catch applications that should not be +issuing commands such as INSERT, UPDATE, or DELETE. + +This method method requires DBI version 1.55 or better. + +## __Name__ (string, read-only) + +Returns the name of the current database. This is the same as the DSN, without the +"dbi:Oracle:" part. + +## __Username__ (string, read-only) + +Returns the name of the user connected to the database. + +## __Driver__ (handle, read-only) + +Holds the handle of the parent driver. The only recommended use for this is to find the name +of the driver using: + + $dbh->{Driver}->{Name} + +## __RowCacheSize__ + +DBD::Oracle supports both Server pre-fetch and Client side row caching. By default both +are turned on to give optimum performance. Most of the time one can just let DBD::Oracle +figure out the best optimization. + +### __Row Caching__ + +Row caching occurs on the client side and the object of it is to cut down the number of round +trips made to the server when fetching rows. At each fetch a set number of rows will be retrieved +from the server and stored locally. Further calls the server are made only when the end of the +local buffer(cache) is reached. + +Rows up to the specified top level row +count `RowCacheSize` are fetched if it occupies no more than the specified memory usage limit. +The default value is 0, which means that memory size is not included in computing the number of rows to prefetch. If +the `RowCacheSize` value is set to a negative number then the positive value of RowCacheSize is used +to compute the number of rows to prefetch. + +By default `RowCacheSize` is automatically set. If you want to totally turn off prefetching set this to 1. + +For any SQL statement that contains a LOB, Long or Object Type Row Caching will be turned off. However server side +caching still works. If you are only selecting a LOB Locator then Row Caching will still work. + +### Row Prefetching + +Row prefetching occurs on the server side and uses the DBI database handle attribute `RowCacheSize` and or the +Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improved performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. + +The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first +fetch that sets the current_positon to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are +loaded into the buffer and DBD::Oracle will not have to go back to the server for more rows. When record 11 is fetched DBD::Oracle +fetches and returns this row and the next 9 rows are loaded into the buffer. In this case if you fetch backwards from 10 to 1 +no server round trips are made. + +With large record sets it is best not to attempt to go to the last record as this may take some time, A large buffer size might even slow down +the fetch. If you must get the number of rows in a large record set you might try using an few large OCI_FETCH_ABSOLUTEs and then an OCI_FETCH_LAST, +this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. +If one requires only the first few rows there is no need to set a large prefetch value. + +If the ora_prefetch_memory less than 1 or not present then memory size is not included in computing the +number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it +is not included in the computing of the prefetch rows. + +# ORACLE-SPECIFIC STATEMENT HANDLE METHODS + +## __ora_stmt_type__ + +Returns the OCI Statement Type number for the SQL of a statement handle. + +## __ora_stmt_type_name__ + +Returns the OCI Statement Type name for the SQL of a statement handle. + +# DBI STATEMENT HANDLE OBJECT METHODS + +## __bind_param__ + + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + +Allows the user to bind a value and/or a data type to a placeholder. + +The value of `$param_num` is a number if using the '?' or if using ":foo" style placeholders, the complete name +(e.g. ":foo") must be given. +The `$bind_value` argument is fairly self-explanatory. A value of `undef` will +bind a `NULL` to the placeholder. Using `undef` is useful when you want +to change just the type and will be overwriting the value later. +(Any value is actually usable, but `undef` is easy and efficient). + +The `\%attr` hash is used to indicate the data type of the placeholder. +The default value is "varchar". If you need something else, you must +use one of the values provided by DBI or by DBD::Pg. To use a SQL value, +modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + +This will import some constants into your script. You can plug those +directly into the [bind_param](#pod_bind_param) call. Some common ones that you will +encounter are: + + SQL_INTEGER + +To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + +You can then set the data types by setting the value of the `ora_type` +key in the hash passed to [bind_param](#pod_bind_param). +The current list of Oracle data types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +Data types are "sticky," in that once a data type is set to a certain placeholder, +it will remain for that placeholder, unless it is explicitly set to something +else afterwards. If the statement has already been prepared, and you switch the +data type to something else, DBD::Oracle will re-prepare the statement for you before +doing the next execute. + +Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + +These attributes may be used in the `\%attr` parameter of the +L or L statement handle methods. + +- ora_type + +Specify the placeholder's datatype using an Oracle datatype. +A fatal error is raised if `ora_type` and the DBI `TYPE` attribute +are used for the same placeholder. +Some of these types are not supported by the current version of +DBD::Oracle and will cause a fatal error if used. +Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + +Potentially useful values when DBD::Oracle was built using OCI 7 and later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + +Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + +Additional values when DBD::Oracle was built using OCI 9.2 and later: + + SQLT_CHR, SQLT_BIN + +See [Binding Cursors](#pod_Binding Cursors) for the correct way to use ORA_RSET. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for how to use ORA_CLOB and ORA_BLOB. + +See [SYS.DBMS_SQL datatypes](#pod_SYS.DBMS_SQL datatypes) for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. + +See [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) for the correct way to use SQLT_CHR and SQLT_BIN. + +See [Other Data Types](#pod_Other Data Types) for more information. + +See also L. + +- ora_csform + +Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values +are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can +be imported from the DBD::Oracle module. Rarely needed. + +- ora_csid + +Specify the _integer_ OCI_ATTR_CHARSET_ID for the bind value. +Character set names can't be used currently. + +- ora_maxdata_size + +Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. +May be needed if a character set conversion from client to server +causes the data to use more space and so fail with a truncation error. + +- ora_maxarray_numentries + +Specify the maximum number of array entries to allocate. Used with +ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of +array entries Oracle can pass back to you in OUT variable of type +TABLE OF ... . + +- ora_internal_type + +Specify internal data representation. Currently is supported only for +ORA_NUMBER_TABLE. + +### Optimizing Results + +#### Prepare Postponed Till Execute + +The DBD::Oracle module can avoid an explicit 'describe' operation +prior to the execution of the statement unless the application requests +information about the results (such as $sth->{NAME}). This reduces +communication with the server and increases performance (reducing the +number of PARSE_CALLS inside the server). + +However, it also means that SQL errors are not detected until +`execute()` (or $sth->{NAME} etc) is called instead of when +`prepare()` is called. Note that if the describe is triggered by the +use of $sth->{NAME} or a similar attribute and the describe fails then +_an exception is thrown_ even if `RaiseError` is false! + +Set [ora_check_sql](#pod_ora_check_sql) to 0 in prepare() to enable this behaviour. + +## __bind_param_inout__ + + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + +DBD::Oracle fully supports bind_param_inout below are some uses for this method. + +### __Returning A Value from an INSERT__ + +Oracle supports an extended SQL insert syntax which will return one +or more of the values inserted. This can be particularly useful for +single-pass insertion of values with re-used sequence values +(avoiding a separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + +If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + +If you have many rows to insert you can take advantage of Oracle's built in execute array feature +with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + +Which will return all the ids into @out_values. + +- __Note:__ + +- This will only work for numbered (?) placeholders, + +- The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle + +- The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + +### Returning A Recordset + +DBD::Oracle does not currently support binding a PL/SQL table (aka array) +as an IN OUT parameter to any Perl data structure. You cannot therefore call +a PL/SQL function or procedure from DBI that uses a non-atomic datatype as +either a parameter, or a return value. However, if you are using Oracle 9.0.1 +or later, you can make use of table (or pipelined) functions. + +For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + +Currently, there is no way to directly call the function +Array_Example.Array_Func from DBI. However, by making the following relatively +painless additions, its not only possible, but extremely efficient. + +First, you need to create database object types that correspond to the record +and table types in the package. From the above example, these would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + +Now, assuming the existing function needs to remain unchanged (it is probably +being called from other PL/SQL code), we need to add a new function to the +package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + +As you can see, the new function is very simple. Now, it is a simple matter +of calling the function as a straight-forward SELECT from your DBI code. From +the above example, the code would look something like this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + +### __SYS.DBMS_SQL datatypes__ + +DBD::Oracle has built-in support for __SYS.DBMS_SQL.VARCHAR2_TABLE__ +and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +- __Note:__ + +- Take careful note that we use '\\@arr' here because the 'bind_param_inout' + will only take a reference to a scalar. + +### __ORA_VARCHAR2_TABLE__ + +SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. +( in bind_param() and bind_param_inout() ). When you bind array, you need +to specify full buffer size for OUT data. So, there are two parameters: +_max_len_ (specified as 3rd argument of bind_param_inout() ), +and _ora_maxarray_numentries_. They define maximum array entry length and +maximum rows, that can be passed to Oracle and back to you. In this +example we send array with 1 element with length=3, but allocate space for 100 +Oracle array entries with maximum length 10 of each. So, you can get no more +than 100 array entries with length <= 10. + +If you set _max_len_ to zero, maximum array entry length is calculated +as maximum length of entry of array bound. If 0 < _max_len_ < length( $some_element ), +truncation occur. + +If you set _ora_maxarray_numentries_ to zero, current (at bind time) bound +array length is used as maximum. If 0 < _ora_maxarray_numentries_ < scalar(@array), +not all array entries are bound. + +### __ORA_NUMBER_TABLE__ + +SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. +The main difference is internal data representation. Currently 2 types of +bind is allowed : as C-integer, or as C-double type. To select one of them, +you may specify additional bind parameter _ora_internal_type_ as either +__SQLT_INT__ or __SQLT_FLT__ for C-integer and C-double types. +Integer size is architecture-specific and is usually 32 or 64 bit. +Double is standard IEEE 754 type. + +_ora_internal_type_ defaults to double (SQLT_FLT). + +_max_len_ is ignored for OCI_NUMBER_TABLE. + +Currently, you cannot bind full native Oracle NUMBER(38). If you really need, +send request to dbi-dev list. + +The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + +If you change bind type to __SQLT_INT__, like: + + ora_internal_type => SQLT_INT + +you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + +## __bind_param_inout_array__ + +DBD::Oracle supports this undocumented feature of DBI. See [Returning A Value from an INSERT](#pod_Returning A Value from an INSERT) for an example. + +## __bind_param_array__ + + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + +Binds an array of values to a placeholder, so that each is used in turn by a call +to the [execute_array](#pod_execute_array) method. + +## __execute__ + + $rv = $sth->execute(@bind_values); + +Perform whatever processing is necessary to execute the prepared statement. + +## __execute_array__ + + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + +Execute a prepared statement once for each item in a passed-in hashref, or items that +were previously bound via the [bind_param_array](#pod_bind_param_array) method. See the DBI documentation +for more details. + +DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very +quickly. + +## __execute_for_fetch__ + + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + +Used internally by the [execute_array](#pod_execute_array) method, and rarely used directly. See the +DBI documentation for more details. + +## __fetchrow_arrayref__ + + $ary_ref = $sth->fetchrow_arrayref; + +Fetches the next row of data from the statement handle, and returns a reference to an array +holding the column values. Any columns that are NULL are returned as undef within the array. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +Note that the same array reference is returned for each fetch, so don't store the reference and +then use it after a later fetch. Also, the elements of the array are also reused for each row, +so take care if you want to take a reference to an element. See also [bind_columns](#pod_bind_columns). + +## __fetchrow_array__ + + @ary = $sth->fetchrow_array; + +Similar to the [fetchrow_arrayref](#pod_fetchrow_arrayref) method, but returns a list of column information rather than +a reference to a list. Do not use this in a scalar context. + +## __fetchrow_hashref__ + + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + +Fetches the next row of data and returns a hashref containing the name of the columns as the keys +and the data itself as the values. Any NULL value is returned as as undef value. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +The optional `$name` argument should be either `NAME`, `NAME_lc` or `NAME_uc`, and indicates +what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. + +## __fetchall_arrayref__ + + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + +Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the +statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, +the data read in so far will be returned. Because of this, you should always check `$sth->err` after +calling this method, unless [RaiseError](#pod_RaiseError) has been enabled. + +If `$slice` is an array reference, fetchall_arrayref uses the [fetchrow_arrayref](#pod_fetchrow_arrayref) method to fetch each +row as an array ref. If the `$slice` array is not empty then it is used as a slice to select individual +columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). + +With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. + +If `$slice` is a hash reference, fetchall_arrayref uses [fetchrow_hashref](#pod_fetchrow_hashref) to fetch each row as a hash reference. + +See the DBI documentation for a complete discussion. + +## __fetchall_hashref__ + + $hash_ref = $sth->fetchall_hashref( $key_field ); + +Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for +a full discussion. + +## __finish__ + + $rv = $sth->finish; + +Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed +when you have not fetched all the possible rows. + +## __rows__ + + $rv = $sth->rows; + +Returns the number of rows affected for updates, deletes and inserts and -1 for selects. + +## __bind_col__ + + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + +Binds a Perl variable and/or some attributes to an output column of a SELECT statement. +Column numbers count up from 1. You do not need to bind output columns in order to fetch data. + +NOTE: DBD::Oracle does not use the `$bind_type` to determine how to +bind the column; it uses what Oracle says the data type is. You can +however set a numeric bind type with the bind attributes +StrictlyTyped/DiscardString as these attributes are applied after the +column is retrieved. + +See the DBI documentation for a discussion of the optional parameters `\%attr` and `$bind_type` + +## __bind_columns__ + + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + +Calls the [bind_col](#pod_bind_col) method for each column in the SELECT statement, using the supplied list. + +## __dump_results__ + + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + +Fetches all the rows from the statement handle, calls `DBI::neat_list` for each row, and +prints the results to `$fh` (which defaults to `STDOUT`). Rows are separated by `$lsep` (which defaults +to a newline). Columns are separated by `$fsep` (which defaults to a comma). The `$maxlen` controls +how wide the output can be, and defaults to 35. + +This method is designed as a handy utility for prototyping and testing queries. Since it uses +"neat_list" to format and edit the string for reading by humans, it is not recommended +for data transfer applications. + +# STATEMENT HANDLE ATTRIBUTES + +## __NUM_OF_FIELDS__ (integer, read-only) + +Returns the number of columns returned by the current statement. A number will only be returned for +SELECT statements for INSERT, +UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NUM_OF_PARAMS__ (integer, read-only) + +Returns the number of placeholders in the current statement. + +## __NAME__ (arrayref, read-only) + +Returns an arrayref of column names for the current statement. This +method will only work for SELECT statements, for SHOW statements, and for +INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NAME_lc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to lower case. + +## __NAME_uc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to upper case. + +## __NAME_hash__ (hashref, read-only) + +Similar to the `NAME` attribute, but returns a hashref of column names instead of an arrayref. The names of the columns +are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. +This method returns undef if called before `execute()`. + +## __NAME_lc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __NAME_uc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __TYPE__ (arrayref, read-only) + +Returns an arrayref indicating the data type for each column in the statement. +This method returns undef if called before `execute()`. + +## __PRECISION__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. +The number indicates the precision for `NUMERIC` columns, the size in number of +characters for `CHAR` and `VARCHAR` columns, and for all other types of columns +it returns the number of _bytes_. +This method returns undef if called before `execute()`. + +## __SCALE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates the scale of the that column. The only type that will return a value is `NUMERIC`. +This method returns undef if called before `execute()`. + +## __NULLABLE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates if the column is nullable or not. 0 = not nullable, 1 = nullable, 2 = unknown. +This method returns undef if called before `execute()`. + +## __Database__ (dbh, read-only) + +Returns the database handle this statement handle was created from. + +## __ParamValues__ (hash ref, read-only) + +Returns a reference to a hash containing the values currently bound to placeholders. If the "named parameters" +type of placeholders are being used (such as ":foo"), then the keys of the hash will be the names of the +placeholders (without the colon). If the "dollar sign numbers" type of placeholders are being used, the keys of the hash will +be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, +starting at one and increasing for every placeholder. + +If this method is called before [execute](#pod_execute), the literal values passed in are returned. If called after +[execute](#pod_execute), then the quoted versions of the values are returned. + +## __ParamTypes__ (hash ref, read-only) + +Returns a reference to a hash containing the type names currently bound to placeholders. The keys +are the same as returned by the ParamValues method. The values are hashrefs containing a single key value +pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can +only be expressed by a Postgres type. The value is the internal number corresponding to the type originally +passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of +ParamTypes to be passed back to the [bind_param](#pod_bind_param) method. + +## __Statement__ (string, read-only) + +Returns the statement string passed to the most recent "prepare" method called in this database handle, even if that method +failed. This is especially useful where "RaiseError" is enabled and the exception handler checks $@ and sees that a `prepare` +method call failed. + +## __RowsInCache__ + +Returns the number of un-fetched rows in the cache for selects. + +# SCROLLABLE CURSORS + +Oracle supports the concept of a 'Scrollable Cursor' which is defined as a 'Result Set' where +the rows can be fetched either sequentially or non-sequentially. One can fetch rows forward, +backwards, from any given position or the n-th row from the current position in the result set. + +Rows are numbered sequentially starting at one and client-side caching of the partial or entire result set +can improve performance by limiting round trips to the server. + +Oracle does not support DML type operations with scrollable cursors so you are limited +to simple 'Select' operations only. As well you can not use this functionality with remote +mapped queries or if the LONG datatype is part of the select list. + +However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch methods. + +Only use scrollable cursors if you really have a good reason to. They do use up considerable +more server and client resources and have poorer response times than non-scrolling cursors. + +## Enabling Scrollable Cursors + +To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + +Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the +statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + +When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row +or you can still use any of the other fetch methods but with a poorer response time than if you used a +non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. + +## Scrollable Cursor Methods + +The following driver-specific methods are used with scrollable cursors. + +- ora_scroll_position + + $position = $sth->ora_scroll_position(); + +This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time +this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. +The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. + +- ora_fetch_scroll + + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + +Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset +value which will then determine the row that will be fetched. It returns the row as a list containing the field values. +Null fields are returned as _undef_ values in the list. + +The valid orientation constant and fetch offset values combination are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + +The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + +The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + +## Scrollable Cursor Usage + +Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + +and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll +method; + +- Fetching the Last Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +if the record set is large this could take some time. + +- Fetching the Current Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will still be 20 after this snippet. + +- Fetching the First Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the Next Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 5 after this snippet. + +- Fetching the Prior Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the 10th Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 10th to 14th Row + + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 14 after this snippet. + +- Fetching the 14th to 10th Row + + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 5th Row From the Present Position. + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 15 after this snippet. + +- Fetching the 9th Row Prior From the Present Position + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 6 after this snippet. + +- Use Finish + + $sth->finish(); + +When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of +cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. + +# LOBS AND LONGS + +The key to working with LOBs (CLOB, BLOBs) is to remember the value of an Oracle LOB column is not the content of the LOB. It's a +'LOB Locator' which, after being selected or inserted needs extra processing to read or write the content of the LOB. There are also legacy LONG types (LONG, LONG RAW, VARCHAR2) +which are presently deprecated by Oracle but are still in use. These LONG types do not utilize a 'LOB Locator' and also are more limited in +functionality than CLOB or BLOB fields. + +DBD::Oracle now offers three interfaces to LOB and LONG data, + +- [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) + +With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of +BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. + +- [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) + +With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. + +- [LOB Locator Method Interface](#pod_LOB Locator Method Interface) + +This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. + +Generally speaking the interface that you will chose will be dependent on what end you are trying to achieve. All have their benefits and +drawbacks. + +One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB column can be in one of three states; + +- NULL + +The table cell is created, but the cell holds no locator or value. +If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + +error when working with a LOB. + +You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + +- Empty + +A LOB instance with a locator exists in the cell, but it has no value. The length of the LOB is zero. In this case DBD::Oracle will return 'undef' for the field. + +- Populated + +A LOB instance with a locator and a value exists in the cell. You actually get the LOB value. + +## Data Interface for Persistent LOBs + +This is the original interface for LONG and LONG RAW datatypes and from Oracle 9iR1 and later the OCI API was extended to work directly with the other LOB datatypes. +In other words you can treat all LOB type data (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using the same techniques +you would use on other datatypes that store character or binary data. In some cases there are fewer round trips to the server as no 'LOB Locators' are +used, normally one can get an entire LOB is a single round trip. + +### Simple Fetch for LONGs and LONG RAWs + +As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG datatypes as a single large piece. +There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. +If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into +an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. + +For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the long1 fields but they will be truncated at 2MBs. + +### Using ora_ncs_buff_mtpl + +When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the +Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. +Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. + +However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer +value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes +but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes +(maybe less characters though) but you are using allot more memory that you need. + +You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can +also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. + +The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the +ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. + +If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + +This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) + +If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. + +This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. + +You can tune this value by setting ora_oci_success_warn which will display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + +In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. + +### Simple Fetch for CLOBs and BLOBs + +To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well +set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds +the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. + +For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this +and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. + +It seems with BLOBs you are not limited by the 64k. + +For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the lobs but they will be truncated at 2MBs. + +### Piecewise Fetch with Callback + +With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. +To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Simple Fetch for LONGs and LONG RAWs](#pod_Simple Fetch for LONGs and LONG RAWs) and [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is +dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. + +Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +#### Piecewise Fetch with Polling + +With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' +attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback). + +Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. + +Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +### Binding for Updates and Inserts for CLOBs and BLOBs + +To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method +'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + +So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. + +### Support for Remote LOBs; + +Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + +to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Below are the limitations of Remote LOBs; + +- Queries involving more than one database are not supported; + +so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + +as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + +- DDL commands are not supported; + +so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + +- Only binds and defines for data going into remote persistent LOBs are supported. + +so that parameter passing in PL/SQL where CHAR data is bound or defined for remote LOBs is not allowed . + +These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + +- If the remote object is a view such as + + CREATE VIEW v AS SELECT foo() FROM ... + +the following would not work: + + SELECT * FROM v@dbs2; + +- Limited PL/SQL parameter passing + +PL/SQL parameter passing is not allowed where the actual argument is a LOB type +and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. + +- RETURNING INTO does not support implicit conversions between CHAR and CLOB. + +so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + +## Locator Data Interface + +### Simple Usage + +When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob with the LongReadLen and LongTruncOk attributes. +The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +When inserting or updating LOBs some _major_ magic has to be performed +behind the scenes to make it transparent. Basically the driver has to +insert a 'LOB Locator' and then refetch the newly inserted LOB +Locator before being able to write the data into it. However, it works +well most of the time, and I've made it as fast as possible, just one +extra server-round-trip per insert or update after the first. For the +time being, only single-row LOB updates are supported. + +To insert or update a large LOB using a placeholder, DBD::Oracle has to +know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + +The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + +or use the corresponding integer values (112 and 113). + +One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has +to be able to tell which parameters relate to which table fields. +In all cases where it can possibly work it out for itself, it does, +however, if there are multiple LOB fields of the same type in the table +then you need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + +There are some limitations inherent in the way DBD::Oracle makes typical +LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + +The alternative is to disable the automatic LOB Locator processing. +If [ora_auto_lob](#pod_ora_auto_lob) is 0 in prepare(), you can fetch the LOB Locators and +do all the work yourself using the ora_lob_*() methods. +See the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) section below. + +### LOB support in PL/SQL + +LOB Locators can be passed to PL/SQL calls by binding them to placeholders +with the proper `ora_type`. If [ora_auto_lob](#pod_ora_auto_lob) is true, output LOB +parameters will be automatically returned as strings. + +If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), +strings can be bound to input LOB placeholders and will be automatically +converted to LOBs. + +Example: + # Build a large XML document, bind it as a CLOB, + # extract elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + +If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + +error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. +One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. + +## Persistent & Locator Interface Caveats + +Now that one has the option of using the Persistent or the Locator interface for LOBs the questions arises +which one to use. For starters, if you want to access LOBs over a dblink you will have to use the Persistent +interface so that choice is simple. The question of which one to use after that is a little more tricky. +It basically boils down to a choice between LOB size and speed. + +The Callback and Polling piecewise fetches are very very slow +when compared to the Simple and the Locator fetches but they can handle very large blocks of data. Given a situation where a +large LOB is to be read the Locator fetch may time out while either of the piecewise fetches may not. + +With the Simple fetch you are limited by physical memory of your server but it runs a little faster than the Locator, as there are fewer round trips +to the server. So if you have small LOBs and need to save a little bandwidth this is the one to use. It you are going after large LOBs then the Locator interface is the one to use. + +If you need to update more than a single row of with LOB data then the Persistent interface can do it while the Locator can't. + +If you encounter a situation where you have to access the legacy LOBs (LONG, LONG RAW) and the values are to large for you system then you can use +the Callback or Polling piecewise fetches to get all of the data. + +Not all of the Persistent interface has been implemented yet, the following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + +Most of the time you should just use the [Locator Data Interface](#pod_Locator Data Interface) as this is in one that has the best combination of speed and size. + +All this being said if you are doing some critical programming I would use the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) as this gives you very +fine grain control of your LOBs, of course the code for this will be somewhat more involved. + +## Data Interface for LOB Locators + +The following driver-specific methods let you manipulate "LOB Locators" directly. +To select a LOB locator directly set the if the `ora_auto_lob` +attribute to false, or alternatively they can be returned via PL/SQL procedure calls. + +(If using a DBI version earlier than 1.36 they must be called via the +func() method. Note that methods called via func() don't honour +RaiseError etc, and so it's important to check $dbh->err after each call. +It's recommended that you upgrade to DBI 1.38 or later.) + +Note that LOB locators are only valid while the statement handle that +created them is valid. When all references to the original statement +handle are lost, the handle is destroyed and the locators are freed. + +- ora_lob_read + + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + +Read a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobRead function. + +- ora_lob_write + + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + +Write/overwrite a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobWrite function. + +- ora_lob_append + + $rc = $dbh->ora_lob_append($lob_locator, $data); + +Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + +- ora_lob_trim + + $rc = $dbh->ora_lob_trim($lob_locator, $length); + +Trims the length of the LOB to $length. +Uses the Oracle OCILobTrim function. + +- ora_lob_length + + $length = $dbh->ora_lob_length($lob_locator); + +Returns the length of the LOB. +Uses the Oracle OCILobGetLength function. + +- ora_lob_is_init + + $is_init = $dbh->ora_lob_is_init($lob_locator); + +Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' +if there is an error. +Uses the Oracle OCILobLocatorIsInit function. + +- ora_lob_chunk_size + + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + +Returns the chunk size of the LOB. +Uses the Oracle OCILobGetChunkSize function. + +For optimal performance, Oracle recommends reading from and +writing to a LOB in batches using a multiple of the LOB chunk size. +In Oracle 10g and before, when all defaults are in place, this +chunk size defaults to 8k (8192). + +### LOB Locator Method Examples + +_Note:_ Make sure you first read the note in the section above about +multi-byte character set issues with these methods. + +The following examples demonstrate the usage of LOB Locators +to read, write, and append data, and to query the size of +large data. + +The following examples assume a table containing two large +object columns, one binary and one character, with a primary +key column, defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + +It also assumes a sequence for use in generating unique +lob_id field values, defined as follows: + + CREATE SEQUENCE lob_example_seq + +### Example: Inserting a new row with large data + +Unless enough memory is available to store and bind the +entire LOB data for insert all at once, the LOB columns must +be written interactively, piece by piece. In the case of a new row, +this is performed by first inserting a row, with empty values in +the LOB columns, then modifying the row by writing the large data +interactively to the LOB columns using their LOB locators as handles. + +The insert statement must create token values in the LOB +columns. Here, we use the empty string for both the binary +and character large object columns 'bindata' and 'chardata'. + +After the INSERT statement, a SELECT statement is used to +acquire LOB locators to the 'bindata' and 'chardata' fields +of the newly inserted row. Because these LOB locators are +subsequently written, they must be acquired from a select +statement containing the clause 'FOR UPDATE' (LOB locators +are only valid within the transaction that fetched them, so +can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + +In this example we demonstrate the use of ora_lob_write() +interactively to append data to the columns 'bin_data' and +'char_data'. Had we used ora_lob_append(), we could have +saved ourselves the trouble of keeping track of the offset +into the lobs. The snippet of code beneath the comment +'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + +The scalar variables $offset and $length are no longer +needed, because ora_lob_append() keeps track of the offset +for us. + +### Example: Updating an existing row with large data + +In this example, we demonstrate a technique for overwriting +a portion of a blob field with new binary data. The blob +data before and after the section overwritten remains +unchanged. Hence, this technique could be used for updating +fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + +After running this code, the row where lob_id = 5 will +contain, starting at position 100234 in the bin_data column, +the string "This string will overwrite a portion of the blob". + +### Example: Streaming character data from the database + +In this example, we demonstrate a technique for streaming +data from the database to a file handle, in this case +STDOUT. This allows more data to be read in and written out +than could be stored in memory at a given time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + +Notice that the select statement does not contain the phrase +"FOR UPDATE". Because we are only reading from the LOB +Locator returned, and not modifying the LOB it refers to, +the select statement does not require the "FOR UPDATE" +clause. + +A word of caution when using the data returned from an ora_lob_read in a conditional statement. +for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + +was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return +the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte +as $data will contain 0 which PERL will see as false and not print it out. + +### Example: Truncating existing large data + +In this example, we truncate the data already present in a +large object column in the database. Specifically, for each +row in the table, we truncate the 'bindata' value to half +its previous length. + +After acquiring a LOB Locator for the column, we query its +length, then we trim the length by half. Because we modify +the large objects with the call to ora_lob_trim(), we must +select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +# SPACES AND PADDING + +## Trailing Spaces + +Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder +values and uses Nonpadded Comparison Semantics with the result. +This causes trouble if the spaces are needed for +comparison with a CHAR value or to prevent the value from +becoming '' which Oracle treats as NULL. +Look for Blank-padded Comparison Semantics and Nonpadded +Comparison Semantics in Oracle's SQL Reference or Server +SQL Reference for more details. + +To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, +either change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or the placeholder +type for a particular call to L or L +with [ora_type](#pod_ora_type) or `TYPE`. +Using [ORA_CHAR](http://search.cpan.org/perldoc?ORA_CHAR) with [ora_type](http://search.cpan.org/perldoc?ora_type) or `SQL_CHAR` with `TYPE` +allows the placeholder to be used with Padded Comparison Semantics +if the value it is being compared to is a CHAR, NCHAR, or literal. + +Please remember that using spaces as a value or at the end of +a value makes visually distinguishing values with different +numbers of spaces difficult and should be avoided. + +Oracle Clients that use OCI 9.2 do not strip trailing spaces. + +## Padded Char Fields + +Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. +As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will +have to change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or placeholder +type for a particular call with L or L +with [ORA_CHAR](#pod_ORA_CHAR). + +# UNICODE + +DBD::Oracle now supports Unicode UTF-8. There are, however, a number +of issues you should be aware of, so please read all this section +carefully. + +In this section we'll discuss "Perl and Unicode", then "Oracle and +Unicode", and finally "DBD::Oracle and Unicode". + +Information about Unicode in general can be found at: +[http://www.unicode.org/](http://www.unicode.org/). It is well worth reading because there are +many misconceptions about Unicode and you may be holding some of them. + +## Perl and Unicode + +Perl began implementing Unicode with version 5.6, but the implementation +did not mature until version 5.8 and later. If you plan to use Unicode +you are _strongly_ urged to use Perl 5.8.2 or later and to _carefully_ read +the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + +And then read it again. + +Perl's internal Unicode format is UTF-8 +which corresponds to the Oracle character set called AL32UTF8. + +## Oracle and Unicode + +Oracle supports many characters sets, including several different forms +of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + +When you create an Oracle database, you must specify the DATABASE +character set (used for DDL, DML and CHAR datatypes) and the NATIONAL +character set (used for NCHAR and NCLOB types). +The character sets used in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + +The Oracle 9.2 and later default for the national character set is AL16UTF16. +The default for the database character set is often US7ASCII. +Although many experienced DBAs will consider an 8bit character set like +WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle +other than US7ASCII, requires that the NLS_LANG environment variable be set. +See the L<"Oracle UTF8 is not UTF-8"> section below. + +You are strongly urged to read the Oracle Internationalization documentation +specifically with respect the choices and trade offs for creating +a databases for use with international character sets. + +Oracle uses the NLS_LANG environment variable to indicate what +character set is being used on the client. When fetching data Oracle +will convert from whatever the database character set is to the client +character set specified by NLS_LANG. Similarly, when sending data to +the database Oracle will convert from the character set specified by +NLS_LANG to the database character set. + +The NLS_NCHAR environment variable can be used to define a different +character set for 'national' (NCHAR) character types. + +Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. +For example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + +## Oracle UTF8 is not UTF-8 + +AL32UTF8 should be used in preference to UTF8 if it works for you, +which it should for Oracle 9.2 or later. If you're using an old +version of Oracle that doesn't support AL32UTF8 then you should +avoid using any Unicode characters that require surrogates, in other +words characters beyond the Unicode BMP (Basic Multilingual Plane). + +That's because the character set that Oracle calls "UTF8" doesn't +conform to the UTF-8 standard in its handling of surrogate characters. +Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". +Here are a couple of extracts from [http://www.unicode.org/reports/tr26/](http://www.unicode.org/reports/tr26/): + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + +Oracle uses this internally because it collates (sorts) in the same order +as UTF16, which is the basis of Oracle's internal collation definitions. + +Rather than change UTF8 for clients Oracle chose to define a new character +set called "AL32UTF8" which does conform to the UTF-8 standard. +(The AL32UTF8 character set can't be used on the server because it +would break collation.) + +Because of that, for the rest of this document we'll use "AL32UTF8". +If you're using an Oracle version below 9.2 you'll need to use "UTF8" +until you upgrade. + +## DBD::Oracle and Unicode + +DBD::Oracle Unicode support has been implemented for Oracle versions 9 +or greater, and Perl version 5.6 or greater (though we _strongly_ +suggest that you use Perl 5.8.2 or later). + +You can check which Oracle version your DBD::Oracle was built with by +importing the `ORA_OCI` constant from DBD::Oracle. + +__Fetching Data__ + +Any data returned from Oracle to DBD::Oracle in the AL32UTF8 +character set will be marked as UTF-8 to ensure correct handling by Perl. + +For Oracle to return data in the AL32UTF8 character set the +NLS_LANG or NLS_NCHAR environment variable _must_ be set as described +in the previous section. + +When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR +is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + +When fetching other character data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + +__Sending Data using Placeholders__ + +Data bound to a placeholder is assumed to be in the default client +character set (specified by NLS_LANG) except for a few special +cases. These are listed here with the highest precedence first: + +If the `ora_csid` attribute is given to bind_param() then that +is passed to Oracle and takes precedence. + +If the value is a Perl Unicode string (UTF-8) then DBD::Oracle +ensures that Oracle uses the Unicode character set, regardless of +the NLS_LANG and NLS_NCHAR settings. + +If the placeholder is for inserting an NCLOB then the client NLS_NCHAR +character set is used. (That's useful but inconsistent with the other behaviour +so may change. Best to be explicit by using the `ora_csform` +attribute.) + +If the `ora_csform` attribute is given to bind_param() then that +determines if the value should be assumed to be in the default +(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + +or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + +Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to +insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert +will still happen but a error code of 0 will be returned with the following warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + +The warning will report the parameter number and the NCHAR setting that the query is running. + +__Sending Data using SQL__ + +Oracle assumes the SQL statement is in the default client character +set (as specified by NLS_LANG). So Unicode strings containing +non-ASCII characters should not be used unless the default client +character set is AL32UTF8. + +## DBD::Oracle and Other Character Sets and Encodings + +The only multi-byte Oracle character set supported by DBD::Oracle is +"AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +# OBJECT & COLLECTION DATA TYPES + +Oracle databases allow for the creation of object oriented like user-defined types. +There are two types of objects, Embedded--an object stored in a column of a regular table +and REF--an object that uses the REF retrieval mechanism. + +DBD::Oracle supports only the 'selection' of embedded objects of the following types OBJECT, VARRAY +and TABLE in any combination. Support is seamless and recursive, meaning you +need only supply a simple SQL statement to get all the values in an embedded object. +You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. + +Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + +The code to access all the data in the table could be something like this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + +Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. + +As stated before DBD::Oracle will automatically drill into the embedded object and extract +all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an +SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + +The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + +Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + +The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + +So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables +nested to 10 levels. + +Any NULL values found in the embedded object will be returned as 'undef'. + +# OTHER DATA TYPES + +DBD::Oracle does not _explicitly_ support most Oracle datatypes. +It simply asks Oracle to return them as strings and Oracle does so. +Mostly. Similarly when binding placeholder values DBD::Oracle binds +them as strings and Oracle converts them to the appropriate type, +such as DATE, when used. + +Some of these automatic conversions to and from strings use NLS +settings to control the formatting for output and the parsing for +input. The most common example is the DATE type. The default NLS +format for DATE might be DD-MON-YYYY and so when a DATE type is +fetched that's how Oracle will format the date. NLS settings also +control the default parsing of strings into DATE values. An error +will be generated if the contents of the string don't match the +NLS format. If you're dealing in dates which don't match the default +NLS format then you can either change the default NLS format or, more +commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") +to explicitly specify formats for converting to and from strings. + +A slightly more subtle problem can occur with NUMBER types. The +default NLS settings might format numbers with a fullstop ("`.`") +to separate thousands and a comma ("`,`") as the decimal point. +Perl will generate warnings and use incorrect values when numbers, +returned and formatted as strings in this way by Oracle, are used +in a numeric context. You could explicitly convert each numeric +value using the TO_CHAR(...) function but that gets tedious very +quickly. The best fix is to change the NLS settings. That can be +done for an individual connection by doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + +There are some types, like BOOLEAN, that Oracle does not automatically +convert to or from strings (pity). These need to be converted +explicitly using SQL or PL/SQL functions. + +Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + +#### Support for Insert of XMLType (ORA_XMLTYPE) + +Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special +requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For +example with a table like this; + + create table books (book_id number, book_xml XMLType); + +one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + +In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. +This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. + +#### Binding Cursors + +Cursors can be returned from PL/SQL blocks, either from stored +functions (or procedures with OUT parameters) or +from direct `OPEN` statements, as shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +The only special requirement is the use of `bind_param_inout()` with an +attribute hash parameter that specifies `ora_type` as `ORA_RSET`. +If you don't do that you'll get an error from the `execute()` like: +"ORA-06550: line X, column Y: PLS-00306: wrong number or types of +arguments in call to ...". + +Here's an alternative form using a function that returns a cursor. +This example uses the pre-defined weak (or generic) REF CURSOR type +SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +A cursor obtained from PL/SQL as above may be passed back to PL/SQL +by binding for input, as shown in this example, which explicitly +closes a cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + +It is not normally necessary to close a cursor +explicitly in this way. Oracle will close the cursor automatically +at the first client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to +the cursor handle from the PL/SQL statement handle delays the destruction +of the cursor handle for too long. This reference remains until the +PL/SQL handle is re-bound, re-executed or destroyed. + +See the `curref.pl` script in the Oracle.ex directory in the DBD::Oracle +source distribution for a complete working example. + +#### Fetching Nested Cursors + +Oracle supports the use of select list expressions of type REF CURSOR. +These may be explicit cursor expressions - `CURSOR(SELECT ...)`, or +calls to PL/SQL functions which return REF CURSOR values. The values +of these expressions are known as nested cursors. + +The value returned to a Perl program when a nested cursor is fetched +is a statement handle. This statement handle is ready to be fetched from. +It should not (indeed, must not) be executed. + +Oracle imposes a restriction on the order of fetching when nested +cursors are used. Suppose `$sth1` is a handle for a select statement +involving nested cursors, and `$sth2` is a nested cursor handle fetched +from `$sth1`. `$sth2` can only be fetched from while `$sth1` is +still active, and the row containing `$sth2` is still current in `$sth1`. +Any attempt to fetch another row from `$sth1` renders all nested cursor +handles previously fetched from `$sth1` defunct. + +Fetching from such a defunct handle results in an error with the message +`ERROR nested cursor is defunct (parent row is no longer current)`. + +This means that the `fetchall...` or `selectall...` methods are not useful +for queries returning nested cursors. By the time such a method returns, +all the nested cursor handles it has fetched will be defunct. + +It is necessary to use an explicit fetch loop, and to do all the +fetching of nested cursors within the loop, as the following example +shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + +The cursor returned by the function `sp_ListEmp` defined in the +previous section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + +#### Pre-fetching Nested Cursors + +By default, DBD::Oracle pre-fetches rows in order to reduce the number of +round trips to the server. For queries which do not involve nested cursors, +the number of pre-fetched rows is controlled by the DBI database handle +attribute `RowCacheSize` (q.v.). + +In Oracle, server side open cursors are a controlled resource, limited in +number, on a per session basis, to the value of the initialization +parameter `OPEN_CURSORS`. Nested cursors count towards this limit. +Each nested cursor in the current row counts 1, as does +each nested cursor in a pre-fetched row. Defunct nested cursors do not count. + +An Oracle specific database handle attribute, `ora_max_nested_cursors`, +further controls pre-fetching for queries involving nested cursors. For +each statement handle, the total number of nested cursors in pre-fetched +rows is limited to the value of this parameter. The default value +is 0, which disables pre-fetching for queries involving nested cursors. + +# PL/SQL Examples + +Most of these PL/SQL examples come from: Eric Bartley . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + +You can find more examples in the t/plsql.t file in the DBD::Oracle +source directory. + +Oracle 9.2 appears to have a bug where a variable bound +with bind_param_inout() that isn't assigned to by the executed +PL/SQL block may contain garbage. +See [http://www.mail-archive.com/dbi-users@perl.org/msg18835.html](http://www.mail-archive.com/dbi-users@perl.org/msg18835.html) + +## Avoid Using "SQL Call" + +Avoid using the "SQL Call" statement with DBD:Oracle as you might find that +DBD::Oracle will not raise an exception in some case. Specifically if you use +"SQL Call" to run a procedure all "No data found" exceptions will be quietly +ignored and returned as null. According to Oracle support this is part of the same +mechanism where; + + select (select * from dual where 0=1) from dual + +returns a null value rather than an exception. + +# CONTRIBUTING + +If you'd like DBD::Oracle to do something new or different the best way +to make that happen is to do it yourself and email to dbi-dev@perl.org a +patch of the source code (using 'diff' - see below) that shows the changes. + +## How to create a patch using Subversion + +The DBD::Oracle source code is maintained using Subversion (a replacement +for CVS, see [http://subversion.tigris.org/](http://subversion.tigris.org/)). To access the source +you'll need to install a Subversion client. Then, to get the source +code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + +If it prompts for a username and password use your perl.org account +if you have one, else just 'guest' and 'guest'. The source code will +be in a new subdirectory called `trunk`. + +To keep informed about changes to the source you can send an empty email +to dbd-oracle-changes-subscribe@perl.org after which you'll get an email with the +change log message and diff of each change checked-in to the source. + +After making your changes you can generate a patch file, but before +you do, make sure your source is still upto date using: + + svn update + +If you get any conflicts reported you'll need to fix them first. +Then generate the patch file from within the `trunk` directory using: + + svn diff > foo.patch + +Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. + +## How to create a patch without Subversion + +Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + +Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + +Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you want. + +Test your changes and then remove all temporary files: + + make test && make distclean + +Go back to the directory you originally unpacked the distribution: + + cd .. + +Unpack _another_ copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + +Then create a patch file by performing a recursive `diff` on the two +top level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + +## Speak before you patch + +For anything non-trivial or possibly controversial it's a good idea +to discuss (on dbi-dev@perl.org) the changes you propose before +actually spending time working on them. Otherwise you run the risk +of them being rejected because they don't fit into some larger plans +you may not be aware of. + +## GitHub repository + +A git mirror of the subversion is also available at +`https://github.com/yanick/DBD-Oracle`. + +# Oracle Related Links + +# WHICH VERSION OF DBD::ORACLE IS FOR ME? + +From version 1.25 onwards DBD::Oracle only support Oracle clients +9.2 or greater. Support for ProC connections was dropped in 1.29. + +If you are still stuck with an older version of Oracle or its client you might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + +As there are dozens of different versions of Oracle's clients this +list does not include all of them, just the major released versions of +Oracle. + +Note that one can still connect to any Oracle version with the older +DBD::Oracle versions the only problem you will have is that some of +the newer OCI and Oracle features available in later DBD::Oracle +releases will not be available to you. + +So to make a short story a little longer: + +- 1 + +If you are using Oracle 7 or early 8 DB and you can manage to get a 9 client and you can use +any DBD::Oracle version. + +- 2 + +If you have to use an Oracle 7 client then DBD::Oracle 1.17 should work + +- 3 + +Same thing for 8 up to R2, use 1.17, if you are lucky and have the right patch-set you might +go with 1.18. + +- 4 + +For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. Again this depends on your +patch-set, If you run into trouble go with 1.19 + +- 5 + +After 9.2 you can use any version you want. + +- 6 + +It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go back to 7 +and even get to 10. I am not sure what the 11g client can connect to. + +# BUGS AND LIMITATIONS + +There is a known problem with the 11.2g Oracle client and the +`DBMS_LOB.GETLENGTH()` PL/SQL function. +See [https://rt.cpan.org/Public/Bug/Display.html?id=69350](https://rt.cpan.org/Public/Bug/Display.html?id=69350) for the details. + +# SEE ALSO + +- [DBI](http://search.cpan.org/perldoc?DBI) + +http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in +the DBD::Oracle source distribution including the examples in the +Oracle.ex directory + +- DBD::Oracle Tutorial + +http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-oracle.html + +- Oracle Instant Client + +http://www.oracle.com/technology/tech/oci/instantclient/index.html + +- Oracle on Linux + +http://www.ixora.com.au/ + +- Free Oracle Tools and Links + +ora_explain supplied and installed with DBD::Oracle. + +http://www.orafaq.com/ + +http://vonnieda.org/oracletool/ + +- Commercial Oracle Tools and Links + +Assorted tools and references for general information. +No recommendation implied. + +http://www.platinum.com + +http://www.SoftTreeTech.com + +Also PL/Vision from RevealNet and Steven Feuerstein, and +"Q" from Savant Corporation. + +# AUTHORS + +DBI by Tim Bunce [http://www.tim.bunce.name](http://www.tim.bunce.name). + +The original `DBD::Oracle` was by Tim Bunce. +Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the +auspice of the Pythian Group ([http://www.pythian.com](http://www.pythian.com)). + +# ACKNOWLEDGEMENTS + +A great many people have helped with DBD::Oracle over the 17 years +between 1994 and 2011. Far too many to name, but we thank them all. +Many are named in the Changes file. + +# COPYRIGHT + +The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. +The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The Pythian Group). Canada. +The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. + +The DBD::Oracle module is free open source software; you can +redistribute it and/or modify it under the same terms as Perl 5. + +# AUTHORS + +- * + +Tim Bunce + +- * + +John Scoles + +- * + +Yanick Champoux + +# COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/dist.ini b/dist.ini deleted file mode 100644 index 013f79fc..00000000 --- a/dist.ini +++ /dev/null @@ -1,22 +0,0 @@ -name = DBD-Oracle -author = Tim Bunce -author = John Scoles -author = Yanick Champoux -license = Perl_5 -copyright_holder = Tim Bunce -copyright_year = 1994 - -version = 1.38 - -[Authority] -authority=cpan:PYTHIAN - -[MakeMaker::Custom] - -[@Filter] --bundle=@YANICK --remove=Author::YANICK::NextSemanticVersion --remove=ModuleBuild --remove=Authority --remove=Signature - diff --git a/err_bind/err_bind_param_inout_overrun_bug.msg b/err_bind/err_bind_param_inout_overrun_bug.msg deleted file mode 100644 index 83d9001f..00000000 --- a/err_bind/err_bind_param_inout_overrun_bug.msg +++ /dev/null @@ -1,108 +0,0 @@ -From dbi-users-return-215-Tim.Bunce=ig.co.uk@perl.org Mon Feb 5 23:03:29 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id XAA01289; Mon, 5 Feb 2001 23:03:27 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <06769-16@oink>; Fri, 6 Feb 1970 00:01:15 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 981413584:20:24069:0; Mon, 05 Feb 2001 22:53:04 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-2.mail.demon.net - id aa2024004; 5 Feb 2001 22:53 GMT -Received: (qmail 6267 invoked by uid 508); 5 Feb 2001 22:52:23 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6247 invoked from network); 5 Feb 2001 22:52:22 -0000 -Received: from seeme.dare.feddata.com (38.186.101.66) by tmtowtdi.perl.org - with SMTP; 5 Feb 2001 22:52:22 -0000 -Received: by seeme.dare.feddata.com; id OAA05466; - Mon, 5 Feb 2001 14:55:56 -0800 (PST) -Received: from ifyou.dare.feddata.com(38.186.101.111) by seeme.dare.feddata.com - via smap (4.1) id xma005448; Mon, 5 Feb 01 14:55:39 -0800 -Sender: oscar@dare.feddata.com -Message-ID: <3A7F2FB0.A1507582@pasadena.feddata.com> -Date: Mon, 05 Feb 2001 14:56:48 -0800 -From: Oscar DeMartino -Organization: Federal Data Corporation -X-Mailer: Mozilla 4.61 [en] (X11; U; SunOS 5.6 sun4u) -X-Accept-Language: en -MIME-Version: 1.0 -To: dbi-users@perl.org -Subject: Undetected error - Binding and Stored Procedures -Content-Type: multipart/alternative; - boundary="------------E1028F7A8304BE268EB8F67B" -Status: RO -Content-Length: 2042 -Lines: 66 - ---------------E1028F7A8304BE268EB8F67B -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -I am running Oracle 8.1.5 and am using many stored procedures. We -use returned cursors, and individual values. The problem is, when -a stored procedure is executed and the specified bound variable has not -be declared large enough to hold the returned value subsequent -bound variables do not get set and I cannot find any way to -automatically detect this. - -Example: - -The stored procedure takes 1-input value and returns three string -values. - -the stored procedure is prepared , so I get the statement handle. - -I bind the input variable, and then bind the three output variables (1, -2, & 3) -as 100 character strings. - -I then execute the statment handle. - -There do not appear to be any errors, after checking the returned value -(for the execute call), -and ->err and ->errstr are clean. - -variable 1 has the correct returned value. -BUT, output variable 2 & 3, have no value. - ------- -Executing the stored procedure using sqlplus (sql command line -interface) indicated: - -What really occured is that the returned output variables 1 & 3 were -under 100 characters long -output variable 2 was 120 characters long - ---------- - -I know I could make all output variables the max size allowed in the -database field -but this would seem to waste space in the perl code. Since the field in - -the database -is simply defined as a varchar2 with no size limitation (upto 32767). - ------ -Am I missing something about detecting that variables 2 & 3 did not get -stored correctly -by DBI::Oracle?? - - - --- -Oscar "Fred" DeMartino FFFFF DDDD CCC -320 N. Halstead Ave. Ste #160 F D D C C -Pasadena, CA 91107 FFF D D C -e-mail: Oscar.DeMartino@pasadena.feddata.com F D D C -Phone: (626)306-6649 F D D C C -Federal Data Corporation F DDDD CCC - - - ---------------E1028F7A8304BE268EB8F67B-- - diff --git a/err_bind/err_bindarrays.msg b/err_bind/err_bindarrays.msg deleted file mode 100644 index 8ca7a5d3..00000000 --- a/err_bind/err_bindarrays.msg +++ /dev/null @@ -1,241 +0,0 @@ -From cturner@redhat.com Tue Mar 27 06:01:56 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id GAA19714; Tue, 27 Mar 2001 06:01:56 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <13771-3@oink>; - Fri, 27 Mar 1970 06:00:50 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985668014:20:27605:3; Tue, 27 Mar 2001 04:40:14 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ab2125244; 27 Mar 2001 4:39 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id XAA32289 - for ; Mon, 26 Mar 2001 23:39:38 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2R4bvT12929; Mon, 26 Mar 2001 23:37:57 -0500 -Sender: cturner@redhat.com -To: Tim.Bunce@ig.co.uk -Subject: DBD::Oracle and OCI bound arrays -From: Chip Turner -Date: 26 Mar 2001 23:37:57 -0500 -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 980 -Lines: 29 - - -Hey Tim, - -The need to have true OCI bound arrays for DBD::Oracle has come up, -and it looks like I get the fun job of implementing them. Basically, -this will allow DBD::Oracle to do something the DCOracle python -library does. The idea is: - -my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -my @c1 = 'aa' .. 'zz'; -my @c2 = 'aaa' .. 'azz'; -$sth->execute(\@c1, \@c2); - -In other words, it populates the table with a single execute call, -passing two (or more) equally sized arrays in as references for bound -parameters. This has the potential to save a good amount of time, -especially for large datasets. - -This would pretty much be a proprietary extension for Oracle, though -similar uses could be done in other DBD's. - -Just thought I'd let you know what I was intending to do, and to see -if you had any interest in receiving it as a patch after I'm done. - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Tue Mar 27 09:29:48 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id JAA20809; Tue, 27 Mar 2001 09:29:42 +0100 (BST) -Date: Tue, 27 Mar 2001 09:29:41 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim.Bunce@ig.co.uk, dbi-dev@perl.org -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010327092941.D20616@ig.co.uk> -References: -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Mon, Mar 26, 2001 at 11:37:57PM -0500 -Content-Length: 1570 -Lines: 39 - -On Mon, Mar 26, 2001 at 11:37:57PM -0500, Chip Turner wrote: -> -> Hey Tim, -> -> The need to have true OCI bound arrays for DBD::Oracle has come up, -> and it looks like I get the fun job of implementing them. Basically, -> this will allow DBD::Oracle to do something the DCOracle python -> library does. The idea is: -> -> my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -> my @c1 = 'aa' .. 'zz'; -> my @c2 = 'aaa' .. 'azz'; -> $sth->execute(\@c1, \@c2); -> -> In other words, it populates the table with a single execute call, -> passing two (or more) equally sized arrays in as references for bound -> parameters. This has the potential to save a good amount of time, -> especially for large datasets. -> -> This would pretty much be a proprietary extension for Oracle, though -> similar uses could be done in other DBD's. -> -> Just thought I'd let you know what I was intending to do, and to see -> if you had any interest in receiving it as a patch after I'm done. - -I would *urge* you to discuss the implementation with me *before* -you get very far cutting code. - -And anyway, I think someone's already done much or all of the work. -Dig around in the dbi-dev archives. If you can't find the discussion -let me know. If you do, then ask them (via the dbi-dev list) what -the status is. - -I'm planning to make a DBI release next week and, hopefully, a -DBD::Oracle release the week after to cleare a backlog of patches I -have queued up. After that I'll be looking to add in the work of the -other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -Tim. - -From cturner@redhat.com Wed Mar 28 02:01:21 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id CAA27336; Wed, 28 Mar 2001 02:01:21 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <17151-9@oink>; - Sat, 28 Mar 1970 01:59:47 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985739868:20:27318:0; Wed, 28 Mar 2001 00:37:48 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ac2119835; 28 Mar 2001 0:37 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id TAA10445 - for ; Tue, 27 Mar 2001 19:37:35 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2S0ZoJ20115; Tue, 27 Mar 2001 19:35:50 -0500 -Sender: cturner@redhat.com -To: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -References: <20010327092941.D20616@ig.co.uk> -From: Chip Turner -Date: 27 Mar 2001 19:35:50 -0500 -In-Reply-To: <20010327092941.D20616@ig.co.uk> -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 1495 -Lines: 35 - -Tim Bunce writes: - -> I would *urge* you to discuss the implementation with me *before* -> you get very far cutting code. - -Unfortunately, it's a little late for this; I've mostly finished the -change (at least, enough for our needs), except for some review and -cleanups. It seems to work quite well (400 times faster than repeated -looping over a dataset) and passes all of DBD::Oracle's test suite. - -> And anyway, I think someone's already done much or all of the work. -> Dig around in the dbi-dev archives. If you can't find the discussion -> let me know. If you do, then ask them (via the dbi-dev list) what -> the status is. - -I checked as you suggest, but couldn't find any code, just discussion -of it. I'll check again, but it didn't seem that the person had put -it anywhere I could get at it. - -> I'm planning to make a DBI release next week and, hopefully, a -> DBD::Oracle release the week after to cleare a backlog of patches I -> have queued up. After that I'll be looking to add in the work of the -> other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -If you would like, the patch will probably be suitable for inclusion -by then, if you want it in by the next release. Should there be any -problems with it or its implementation, I'd be glad to clean it up if -you have interest in it (if not, that's cool too; we need it soon, -though, either way). - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Wed Mar 28 11:51:58 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id LAA00444; Wed, 28 Mar 2001 11:51:51 +0100 (BST) -Date: Wed, 28 Mar 2001 11:51:51 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010328115151.D29769@ig.co.uk> -References: <20010327092941.D20616@ig.co.uk> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Tue, Mar 27, 2001 at 07:35:50PM -0500 -Content-Length: 1786 -Lines: 40 - -On Tue, Mar 27, 2001 at 07:35:50PM -0500, Chip Turner wrote: -> Tim Bunce writes: -> -> > I would *urge* you to discuss the implementation with me *before* -> > you get very far cutting code. -> -> Unfortunately, it's a little late for this; I've mostly finished the -> change (at least, enough for our needs), except for some review and -> cleanups. It seems to work quite well (400 times faster than repeated -> looping over a dataset) and passes all of DBD::Oracle's test suite. - -I trust you've added some more tests for your new functionality! - -> > And anyway, I think someone's already done much or all of the work. -> > Dig around in the dbi-dev archives. If you can't find the discussion -> > let me know. If you do, then ask them (via the dbi-dev list) what -> > the status is. -> -> I checked as you suggest, but couldn't find any code, just discussion -> of it. I'll check again, but it didn't seem that the person had put -> it anywhere I could get at it. - -You could always ask them (CC me). - -> > I'm planning to make a DBI release next week and, hopefully, a -> > DBD::Oracle release the week after to cleare a backlog of patches I -> > have queued up. After that I'll be looking to add in the work of the -> > other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). -> -> If you would like, the patch will probably be suitable for inclusion -> by then, if you want it in by the next release. Should there be any -> problems with it or its implementation, I'd be glad to clean it up if -> you have interest in it (if not, that's cool too; we need it soon, -> though, either way). - -Thanks for the clean-up offer. Send it to me after I make the next -DBD::Oracle release (as a fresh patch over that version please - but -there shouldn't be too many changes). - -Tim. - diff --git a/err_bind/err_bindclobleak.msg b/err_bind/err_bindclobleak.msg deleted file mode 100644 index 1a31c760..00000000 --- a/err_bind/err_bindclobleak.msg +++ /dev/null @@ -1,58 +0,0 @@ -From PGWeiss@arity.com Thu Mar 9 09:51:45 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id JAA14948; Thu, 9 Mar 2000 09:51:43 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <27566-0@oink>; Mon, 9 Mar 1970 10:51:10 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 952595299:20:10439:68; Thu, 09 Mar 2000 09:48:19 GMT -Received: from image.arity.com ([140.239.104.130]) by punt-2.mail.demon.net - id aa2010598; 9 Mar 2000 9:47 GMT -Received: by image.arity.com with Internet Mail Service (5.5.2650.21) - id ; Thu, 9 Mar 2000 04:51:44 -0500 -Message-ID: -From: "Paul G. Weiss" -To: Perl-Win32-Database Mailing List , - "'Tim Bunce'" -Subject: Another CLOB related DBD::Oracle bug -Date: Thu, 9 Mar 2000 04:51:41 -0500 -MIME-Version: 1.0 -X-Mailer: Internet Mail Service (5.5.2650.21) -Content-Type: text/plain; charset="iso-8859-1" -Status: RO -Content-Length: 689 -Lines: 32 - -Binding a parameter to type ORA_CLOB causes a leak. -Consider: - -for (1..10000) -{ - for (1..100) - { - my $sth = $db->prepare('update item set descr = ? where id = ?'); - if ($leak) - { - $sth->bind_param(1, $descr, {ora_type => ORA_CLOB, -ora_field=>'DESCR'}); - $sth->bind_param(2, 12); - $sth->execute; - } - else - { - $sth->execute($descr,12); - } - } - sleep 1; -} - - -With $leak set to 1, i.e. binding the parameters explicitly the -program leaks. With $leak set to 0 it does not (but then I can't -set descr to anything greater than 4K nor can I set it to the -empty string). - -Is there a patch? - --P - diff --git a/err_bind/err_bindnullhash.msg b/err_bind/err_bindnullhash.msg deleted file mode 100644 index d9a98b9a..00000000 --- a/err_bind/err_bindnullhash.msg +++ /dev/null @@ -1,77 +0,0 @@ -From dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org Thu Jul 11 17:49:35 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g6BGnYH11008 - for ; Thu, 11 Jul 2002 17:49:34 +0100 (BST) - (envelope-from dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 11 Jul 2002 17:49:34 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1026401921:10:09249:41; Thu, 11 Jul 2002 15:38:41 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1124337; 11 Jul 2002 15:38 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id B567C2BF65 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 347792BF62 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Received: (qmail 95914 invoked by uid 1005); 11 Jul 2002 15:38:04 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 95896 invoked by uid 76); 11 Jul 2002 15:38:04 -0000 -Received: from ironmail1.cc.lehigh.edu (HELO ironmail1.cc.lehigh.edu) (128.180.39.26) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Thu Jul 11 15:38:04 2002 -0000 -Received: from ([128.180.39.20]) - by ironmail1.cc.lehigh.edu with ESMTP with TLS; - Thu, 11 Jul 2002 11:35:06 -0400 (EDT) -Received: from lawrencework (pc-lfn0.dept.Lehigh.EDU [128.180.52.51]) - by rain.CC.Lehigh.EDU (8.12.4/8.12.4) with SMTP id g6BFZ6rr022463 - for ; Thu, 11 Jul 2002 11:35:06 -0400 -Message-ID: <0a0401c228f0$93feda10$3334b480@lawrencework> -From: "Phil R Lawrence" -To: -References: <083b01c22824$70357340$3334b480@lawrencework> <20020711140937.A568@dansat.data-plan.com> -Subject: Re: error msg suggestion -Date: Thu, 11 Jul 2002 11:35:20 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2600.0000 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -X-Status: A -Content-Length: 636 -Lines: 21 - -Tim Bunce wrote: -> Binding an undef should work and be treated as a NULL. -> -> Probably a bug in your code or the driver. But you didn't -> say which driver. - -Hmmm. quite right, undefs do bind as NULL. However, in this case I am -binding $hash{non-existent-key}, which autoinstantiates to an undef, and looks -like this in the trace: - undef (magic-sg:y) - -Of course it was my dumb fault for having the wrong key for lookup, but -nonetheless, perhaps this should work the same as a normal undef. - -# $DBI::VERSION = "1.14"; -# $DBD::ODBC::VERSION = '0.28'; -$DSN = 'driver=Microsoft Access Driver (*.mdb);dbq=StudyManager.mdb'; - -Thanks, -Phil - - diff --git a/err_bind/err_trailingblank.msg b/err_bind/err_trailingblank.msg deleted file mode 100644 index cdf34a32..00000000 --- a/err_bind/err_trailingblank.msg +++ /dev/null @@ -1,345 +0,0 @@ -From dbi-users-bounce@isc.org Mon May 1 21:12:02 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id VAA16051; Mon, 1 May 2000 21:12:00 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <14295-42@oink>; Fri, 1 May 1970 21:06:08 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 957208278:10:19133:4; Mon, 01 May 2000 19:11:18 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1123094; 1 May 2000 19:11 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id B3CCF3FAA; - Mon, 1 May 2000 12:10:53 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Mon, 01 May 2000 12:05:42 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A70763E34 - for ; Mon, 1 May 2000 12:05:30 -0700 (PDT) -Received: from scotth.emsphone.com (scotth.emsphone.com [199.67.51.179]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA25897 - for ; - Mon, 1 May 2000 12:05:30 -0700 (PDT) env-from (shildret@scotth.emsphone.com) -Received: (from shildret@localhost) by scotth.emsphone.com (8.9.3/8.9.3) - id OAA50011 for dbi-users@isc.org; - Mon, 1 May 2000 14:05:48 -0500 (CDT) (envelope-from shildret) -Message-ID: -X-Mailer: XFMail 1.4.0 on FreeBSD -X-Priority: 3 (Normal) -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 8bit -MIME-Version: 1.0 -Resent-Date: Thu, 29 Jul 1999 22:07:08 +0100 -Resent-Message-Id: <19990729220708.G17723@ig.co.uk> -Resent-From: Tim Bunce -Resent-To: Tim Bunce -Date: Mon, 01 May 2000 14:05:48 -0500 (CDT) -Sender: shildret@scotth.emsphone.com -From: "Scott T. Hildreth" -To: "dbi-users@isc.org" -Subject: FW: Oracle & Trailing Blanks - possible change in DBD::Oracle -Resent-Sender: shildret@scotth.emsphone.com -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 3885 -Lines: 94 - - -Here is the help, I got regarding the trailing spaces. - ------FW: <19990729220708.G17723@ig.co.uk>----- - -Date: Thu, 29 Jul 1999 22:07:08 +0100 -From: Tim Bunce -To: Tim Bunce -Subject: Oracle & Trailing Blanks - possible change in DBD::Oracle -Cc: "Scott T. HIldreth" , - dbi-users@isc.org - - *** From dbi-users -- To unsubscribe, see the end of this message. *** - -On Thu, Jul 29, 1999 at 09:49:38PM +0100, Tim Bunce wrote: -> *** From dbi-users -- To unsubscribe, see the end of this message. *** -> -> On Thu, Jul 29, 1999 at 09:33:55AM -0500, Scott T. HIldreth wrote: -> > -> > Hi all, I wonder if someone can let me know if I got this right. -> > I have a key to match which can contain trailing blanks. The -> > field in the database is CHAR(18). If I match the key with -> > sqlplus, Oracle finds a match, with or without the trailing -> > blank. When I do an sth->execute( $key ), the key is not -> > found. I abstract the key with substr, so the trailing blank -> > is in the key, but no match is found. Do I need to place qoutes -> > around the value in $key? -> -> Somewhat hiddedn in the Oraperl.pm docs it says this: -> -> --- -> B Substitution variables are now bound as type 1 (VARCHAR2) -> and not type 5 (STRING) by default. This can alter the behaviour of -> SQL code which compares a char field with a substitution variable. -> See the String Comparison section in the Datatypes chapter of the -> Oracle OCI manual for more details. -> -> You can work around this by using DBD::Oracle's ability to specify -> the Oracle type to be used on a per field basis: -> -> $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) -> $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); -> $csr->bind_param(1, $value_x, $char_attrib); -> $csr->bind_param(2, $value_y, $char_attrib); -> ora_bind($csr); # bind with no parameters since we've done bind_param()'s -> --- -> -> Ignoring the Oraperl specifics there the key point is to use -> -> $csr->bind_param($idx, $value, { ora_type => 5 }); -> -> I'll add something to the DBD::Oracle docs. - -[You'll still need to blank-pad the string.] - -Looking at this issue again I've discovered that the key issue is that -type 1 strips trailing blanks whilst type 5 doesn't. - -I'rather m concerned by this. Since I'm against the DBI changing the -data in any way on principle and since Oraperl used to use type 5 -I'm strongly considering changing DBD::Oracle 'back' to using type 5. - -This would only affect anyone who relies on placeholders having -trailing blanks stripped off. (I'll provide a way to alter the -default with a single statement and/or env var for anyone affected). - -If that's you - speak up now! - -Tim. - ------------------------------------------------------------------------------- -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of -'unsubscribe'. ------------------------------------------------------------------------------- - - ---------------End of forwarded message------------------------- - ----------------------------------- -E-Mail: Scott T. Hildreth -Date: 01-May-00 -Time: 14:04:41 ----------------------------------- - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - -From joshua.horton@mail.tju.edu Fri May 23 07:43:09 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.6/8.12.6) with ESMTP id h4N6UY7T061880 - for ; Fri, 23 May 2003 07:43:09 +0100 (BST) - (envelope-from joshua.horton@mail.tju.edu) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 23 May 2003 07:43:09 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1053631164:10:02298:54; Thu, 22 May 2003 19:19:24 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116141; 22 May 2003 19:19 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id BD31E21C13C - for ; Thu, 22 May 2003 15:18:30 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail.tju.edu (fw-tr16.tju.edu [147.140.233.16]) - by dolly1.pobox.com (Postfix) with ESMTP id 615A521C06D - for ; Thu, 22 May 2003 15:18:22 -0400 (EDT) -Received: from PCSE447.tjh.tju.edu by mail.tju.edu for Tim.Bunce@pobox.com; Thu, 22 May 2003 15:17:54 -0400 -Message-Id: <031301c32096$de68f6f0$2310ae0a@PCSE447> -From: "Joshua Horton" -To: -Subject: Re: :Oracle and Oracle 9.2? -Date: Thu, 22 May 2003 15:18:03 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 5.50.4807.1700 -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 3511 -Lines: 99 - -Re: :Oracle and Oracle 9.2? - ----------------------------------------------------------------------------- ----- - - a.. From: Tim Bunce - b.. Subject: Re: :Oracle and Oracle 9.2? - c.. Date: Tue, 15 Apr 2003 07:36:55 -0700 - ----------------------------------------------------------------------------- ----- - -I'd appreciate it if other people with Oracle 9.2.x could let me -know if it passed or failed for them and what their exact oracle -version (four digits) and platform (operating system) is. - -Thanks. - -Tim. - -On Fri, Apr 04, 2003 at 01:48:36PM +0200, Smejkal Petr wrote: -> I have the same experience on Linux however on Windows all tests passes -(I'm not -> sure if it is related to different Oracle version - test of windows Perl -against -> Linux Oracle is OK). -> -> Linux Oracle: 9.2.0.2 -> Windows Oracle: 9.2.0.1 -> DBI: 1.35 -> DBD::Oracle: 1.14 -> -> -- Petr Smejkal -> -- Business Systems Analyst / Country IT Cz/Sk -> -- +420 284 059 639 -> -> > -----Original Message----- -> > From: Tom Malaher [mailto:[EMAIL PROTECTED] -> > Sent: Friday, April 04, 2003 1:35 AM -> > To: [EMAIL PROTECTED] -> > Subject: DBD::Oracle and Oracle 9.2? -> > -> > -> > My sysadmin is trying to install DBD::Oracle on a Solaris box running -> > Oracle 9.2. -> > -> > The ph_type.t test is failing with -> > -> > PERL_DL_NONLAZY=1 ./perl "-MExtUtils::Command::MM" "-e" -> > "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -> > t/base.......ok -> > t/cursor.....ok -> > t/general....ok -> > t/long.......ok -> > t/meta.......ok -> > t/ph_type....NOK 12 expected 'trailing' but got 'trailing ' -> > for VARCHAR2 -> > t/ph_type....FAILED test 12 -> > Failed 1/19 tests, 94.74% okay -> > t/plsql......ok -> > t/reauth.....skipped -> > all skipped: no reason given -> > t/select.....ok -> > Failed Test Stat Wstat Total Fail Failed List of Failed -> > -------------------------------------------------------------- -> > ----------------- -> > t/ph_type.t 19 1 5.26% 12 -> > 1 test skipped. -> > Failed 1/9 test scripts, 88.89% okay. 1/314 subtests failed, -> > 99.68% okay. -> > *** Error code 29 -> > make: Fatal error: Command failed for target `test_static' -> > -> > Is there a known problem with DBD::Oracle and Oracle 9.x? -> > Has Oracle changed the behavior of trailing spaces in VARCHAR2 fields? -> > -> > I've run the same test script on an oracle 8 installation -> > using DBD::Oracle 1.06 and DBI 1.14, and it works fine (no trailing -> > space is returned). -> > -> > Tom -> > -My config:HP-UX 11.11 (64-bit) on rp5470 2x733 5GB RAMOracle 9.2.0.2.0 -Enterprise Edition (64-bit)Perl 5.8.0 custom compiled with -./Configure -Duse64bitall -Ubincompat5005 -Duselargefiles -Dprefix=/opt/perl -5 ; all other options defaultDBI-1.32 all passed some skippedDBD-Oracle-1.14 -: PERL_DL_NONLAZY=1 /opt/perl5/bin/perl "-MExtUtils::Command::MM" -"-e" "test_harness(0, 'blib/lib', 'blib/arch')" -t/*.tt/base.......okt/cursor.....okt/general....okt/long.......okt/meta..... -..okt/ph_type....ok 11/19 expected 'trailing' but got 'trailing ' for -VARCHAR2t/ph_type....FAILED test 12 Failed 1/19 tests, 94.74% -okayt/plsql......okt/reauth.....skipped all skipped: no reason -givent/select.....okFailed Test Stat Wstat Total Fail Failed List of -Failed---------------------------------------------------------------------- --------------------------------------------------------t/ph_type.t -19 1 5.26% 121 test skipped.Failed 1/9 test scripts, 88.89% okay. -1/314 subtests failed, 99.68% okay.*** Error exit code 2Stop.Thanks,Josh -Horton - - -From nobody@fsck.com Tue Dec 30 14:33:50 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hBUEWNnP026077 - for ; Tue, 30 Dec 2003 14:33:50 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Dec 2003 14:33:50 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AbJwa-0003ua-H6; - Tue, 30 Dec 2003 13:29:56 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AbJwa-0003ua-H6 - for pobox@dbi.demon.co.uk; Tue, 30 Dec 2003 13:29:56 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 56DAD4C6 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3B3564C8 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 30 Dec 2003 08:29:54 -0500 (EST) -Received: (qmail 10988 invoked by uid 225); 30 Dec 2003 13:29:53 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 10984 invoked by alias); 30 Dec 2003 13:29:52 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 30 Dec 2003 05:29:41 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 8760D11153; Tue, 30 Dec 2003 08:29:37 -0500 (EST) -Subject: [cpan #4786] Oracle 9.2.0.0 fails a test in ph_types.t -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4786 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -To: "AdminCc of cpan Ticket #4786": ; -Date: Tue, 30 Dec 2003 08:29:37 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,SUPERLONG_LINE,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -Content-Length: 888 -Lines: 11 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -Assuming that ORA_OCI() gets set correctly when compiling against 9.2, the attached patch will work. I also tried this in SQL*Plus and was able to insert a trailing space into a VARCHAR2. (I replicated the test in ph_types.t). - -I did not test my patch as I installed DBD::Oracle 1.14 by setting the chops_spaces value in %test_info to 0. When I did that, everything installed fine. However, I didn't think that my solution was the best for the module, so I figured ORA_OCI should do the trick. - -I'm running Perl5.8.0 for Solaris2.9 going against the full Oracle build for 9.2. (I did not run into this issue, surprisingly, on Redhat9 running Perl 5.8.2, but I built against Oracle 9.1 there ...) - diff --git a/err_build/err_aix64.msg b/err_build/err_aix64.msg deleted file mode 100644 index f952e29e..00000000 --- a/err_build/err_aix64.msg +++ /dev/null @@ -1,142 +0,0 @@ -From SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com Fri Jan 7 16:11:33 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j07GAqfa044155 - for ; Fri, 7 Jan 2005 16:11:32 GMT - (envelope-from SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Fri, 07 Jan 2005 16:11:32 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CmvQB-0003Po-Kf; - Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CmvQB-0003Po-Kf - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CmvQA-0002zW-VM - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 49778102ACC; - Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 384E5FF808 - for ; Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Received-SPF: pass (boggle.pobox.com: domain of dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by boggle.pobox.com (Postfix) with SMTP id A74B8F4090 - for ; Fri, 7 Jan 2005 09:48:57 -0500 (EST) -Received: (qmail 2690 invoked by uid 514); 7 Jan 2005 14:48:56 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 2622 invoked from network); 7 Jan 2005 14:48:55 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 7 Jan 2005 14:48:55 -0000 -Received: (qmail 13078 invoked by uid 225); 7 Jan 2005 14:48:54 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 13048 invoked by alias); 7 Jan 2005 14:48:51 -0000 -X-Spam-Status: No, hits=-4.6 required=8.0 - tests=BAYES_00,HTML_MESSAGE,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: neutral (x1.develooper.com: local policy) -Received: from outmx020.isp.belgacom.be (HELO outmx020.isp.belgacom.be) (195.238.2.201) - by la.mx.develooper.com (qpsmtpd/0.28) with ESMTP; Fri, 07 Jan 2005 06:48:38 -0800 -Received: from outmx020.isp.belgacom.be (localhost [127.0.0.1]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmOgS020070 - for ; Fri, 7 Jan 2005 15:48:24 +0100 - (envelope-from ) -Received: from relaytwo.roularta.be (smtprelaytwo.roularta.be [194.78.177.23]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmMDA020034 - for ; Fri, 7 Jan 2005 15:48:22 +0100 - (envelope-from ) -Received: from rmgexch01.RMG.be ([89.0.35.150]) by roesfront3.RMG.be with Microsoft SMTPSVC(5.0.2195.6713); - Fri, 7 Jan 2005 15:47:50 +0100 -X-MimeOLE: Produced By Microsoft Exchange V6.5.7226.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----_=_NextPart_001_01C4F4C7.EE810087" -Subject: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Date: Fri, 7 Jan 2005 15:48:21 +0100 -Message-ID: -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Thread-Index: AcT0x+Y4G1R3vbX6Rh+QdPyNy/10eQ== -From: -To: -X-OriginalArrivalTime: 07 Jan 2005 14:47:50.0598 (UTC) FILETIME=[DC5D2E60:01C4F4C7] -Status: RO -Content-Length: 1678 -Lines: 62 - -------_=_NextPart_001_01C4F4C7.EE810087 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - -Hi,=20 -=20 -I finally succeeded in installing a 64bit build of Perl and its modules -for Oracle 64-bit. We were running in 32bit but integrating Proc and -cobols in our perl scripts only worked when we changed environments to -64bit causing problems for the oracle connections in perl. It's nothing -special, no editing of makefiles ... I can't believe I lost so much time -on this one ;) ( Now that I look back to my problems, they were probably -caused by using a wrong perl build for compiling the modules, Aix has -its default perl now under /bin.. stupid me )=20 -=20 -perl 5.8.6 64bit ----------------- -./Configure -de -Dcc=3Dgcc -Duse64bitall=20 -make -make test -make install -=20 -DBI 1.46 --------- -!!Make sure you are using the newly installed perl!! - check with perl -v it should show :=20 - This is perl, v5.8.6 built for aix-64all -perl Makefile.PL -make -make test -make install=20 -=20 -DBD-Oracle 1.16 ---------------- -!!Use correct perl like above mentioned!!=20 -export ORACLE_HOME=3D=20 -export LIBPATH=3D$ORACLE_HOME/lib -export LD_LIBRARY_PATH=3D$ORACLE_HOME/lib -=20 -perl Makefile.PL=20 -make -make test ( some test may still fail, I had 85% success on tests )=20 -make install=20 -=20 -Test -----=20 -=20 -test with :=20 - use DBI; - $dbh=3DDBI->connect("dbi:Oracle:","system","manager")|| die -$DBI::errstr; - $stmt=3D$dbh->prepare("select * from tab"); - $rc=3D$stmt->execute() || die $DBI::errstr; - while (my($record)=3D$stmt->fetchrow()) - { - print $record; - } -=20 -Happy 64-bit perling ;)=20 - -------_=_NextPart_001_01C4F4C7.EE810087-- - diff --git a/err_build/err_hpux_ld.msg b/err_build/err_hpux_ld.msg deleted file mode 100644 index 27f9cd07..00000000 --- a/err_build/err_hpux_ld.msg +++ /dev/null @@ -1,89 +0,0 @@ -From SRS0=JbZc=U3=lincolnbaxter.com=lab@bounce2.pobox.com Tue Jun 21 05:02:19 2005 -Return-Path: -X-Original-To: timbo@localhost -Delivered-To: timbo@localhost.data-plan.com -Received: from localhost (localhost [127.0.0.1]) - by timac.data-plan.com (Postfix) with ESMTP id B016F2A3D98 - for ; Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DkYXK-0003m5-Mr; - Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DkYXK-0003m5-Mr - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1DkYXJ-00006n-QE - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AF60172691; - Mon, 20 Jun 2005 22:29:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from ms-smtp-04-eri0.southeast.rr.com (ms-smtp-04-lbl.southeast.rr.com [24.25.9.103]) - by gold.pobox.com (Postfix) with ESMTP id A3C1E7272E - for ; Mon, 20 Jun 2005 22:29:11 -0400 (EDT) -Received: from lincolnbaxter.com (cpe-069-132-010-126.carolina.res.rr.com [69.132.10.126]) - by ms-smtp-04-eri0.southeast.rr.com (8.12.10/8.12.7) with ESMTP id j5L2TIL4001864 - for ; Mon, 20 Jun 2005 22:29:18 -0400 (EDT) -Received: (qmail 5171 invoked from network); 20 Jun 2005 22:29:07 -0400 -Received: from lws (192.168.0.25) - by lws with SMTP; 20 Jun 2005 22:29:07 -0400 -Subject: Re: gcc options when building DBD:Oracle -From: "Lincoln A. Baxter" -Reply-To: lab@lincolnbaxter.com -To: jriekenberg@everestkc.net -Cc: Tim Bunce -In-Reply-To: -References: -Content-Type: text/plain -Date: Mon, 20 Jun 2005 22:29:07 -0400 -Message-Id: <1119320947.17452.484.camel@lws> -Mime-Version: 1.0 -X-Mailer: Evolution 2.2.1.1 -Content-Transfer-Encoding: 7bit -X-Virus-Scanned: Symantec AntiVirus Scan Engine -Status: RO -Content-Length: 2011 -Lines: 38 - -Hi Jan, - -This looks like something that might be relatively easy to fix in -Makefile.PL. But I no longer have access to HPUX systems, and never -built DBD-Oracle with gcc on that platform. I could add your message to -the README.hpux file, but it is becoming less and less necessary to read -this file with newer versions of DBD-Oracle, in which Makefile.PL has -been made much smarter. - -Would you consider sending Tim or me a patch to Makefile.PL that -generates the right $(LD) command (only on HP rp8400, and only for your -version of gcc or later? - -Lincoln - -On Mon, 2005-06-20 at 15:36 -0500, jriekenberg@everestkc.net wrote: -> Lincoln, -> -> I recently built DBD:Oracle on an HP rp8400. Everything worked as expected until I actually issued the "make" command. Make proceeded as expected until it reached "MakeMaker dynamic_lib" section. The gcc line in that section failed with the error in the attached text file. Apparently gcc was not correctly passing the "+b" option to ld. Instead, it was attempting to interpret the option itself. It assumed the "+b" was a filename, and that failed because gcc could not find the file. I ended up adding the "-Xlinker" option before the "+b" and before the "$(LD_RUN_PATH)" in the line in Makefile. The line now looks like this: -> -> $(LD) -Xlinker +b -Xlinker "$(LD_RUN_PATH)" $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) -> -> Running "make" now works correctly. -> -> Also, "make test" returned the following error when attempting to build the various tests: -> -> /usr/lib/dld.sl: Can't shl_load() a library containing Thread Local Storage: /usr/lib/libcl.2 -> -> Setting LD_PRELOAD with "export LD_PRELOAD=/usr/lib/libcl.2" corrected this problem, and "make test" worked correctly. -> -> -> I didn't see DBD::Oracle documentation on exactly this, so I'm sending this to you. You may be aware of these items already. If so, please disregard this. -> -> Jon Riekenberg -> -> -> - - diff --git a/err_build/err_hpuxsuccess.msg b/err_build/err_hpuxsuccess.msg deleted file mode 100644 index c6edd79f..00000000 --- a/err_build/err_hpuxsuccess.msg +++ /dev/null @@ -1,279 +0,0 @@ -From dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org Tue Mar 23 17:00:25 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i2NGvAxX021862 - for ; Tue, 23 Mar 2004 17:00:23 GMT - (envelope-from dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 23 Mar 2004 17:00:23 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1B5oND-0000Ba-LH; - Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1B5oND-0000Ba-LH - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [208.210.124.70] (helo=majesty.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1B5oNC-00001d-92 - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:26 +0000 -Received: from majesty.pobox.com (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 18033954B4 - for ; Tue, 23 Mar 2004 11:03:24 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 3577D954BE - for ; Tue, 23 Mar 2004 11:03:21 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by majesty.pobox.com (Postfix) with SMTP - for ; Tue, 23 Mar 2004 11:02:41 -0500 (EST) -Received: (qmail 6527 invoked by uid 1005); 23 Mar 2004 16:02:21 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6510 invoked by uid 76); 23 Mar 2004 16:02:20 -0000 -Received: from x1.develooper.com (HELO x1.develooper.com) (63.251.223.170) - by onion.perl.org (qpsmtpd/0.27.1) with SMTP; Tue, 23 Mar 2004 08:02:20 -0800 -Received: (qmail 1985 invoked by uid 225); 23 Mar 2004 16:02:15 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 1893 invoked by alias); 23 Mar 2004 16:02:00 -0000 -X-Spam-Status: No, hits=0.0 required=7.0 - tests= -X-Spam-Check-By: la.mx.develooper.com -Received: from Unknown (HELO dundee.fpcc.net) (204.144.241.120) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Tue, 23 Mar 2004 08:01:44 -0800 -Received: from aberdeen.fpcc.net (aberdeen.fpcc.net [204.144.241.125]) - by dundee.fpcc.net (8.11.6/8.11.6) with ESMTP id i2NG1f111241; - Tue, 23 Mar 2004 09:01:41 -0700 -Received: from aberdeen.fpcc.net (localhost.localdomain [127.0.0.1]) - by aberdeen.fpcc.net (8.12.8/8.12.8) with ESMTP id i2NFrNOv024637; - Tue, 23 Mar 2004 08:53:23 -0700 -Received: (from laubster@localhost) - by aberdeen.fpcc.net (8.12.8/8.12.8/Submit) id i2NFrMOx024635; - Tue, 23 Mar 2004 08:53:22 -0700 -X-Authentication-Warning: aberdeen.fpcc.net: laubster set sender to dbiusers@laubster.org using -f -Date: Tue, 23 Mar 2004 08:53:22 -0700 -From: "J.D. Laub" -To: dbi-users@perl.org -Cc: lbaxter@fleetcc.com -Subject: SUCCESS: DBD::Oracle 1.15 on HP-UX 11.11 -Message-ID: <20040323155322.GA24576@aberdeen.fpcc.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -Organization: The Psychiatric Ward of Terrors -X-Virus-Checked: Checked -Status: RO -Content-Length: 9105 -Lines: 206 - -I've just had success building DBD::Oracle 1.15 on HP-UX 11.11 -(against both oracle 8.1.7 & oracle 9.2.0) & thought I'd share my -experience. - -Disclaimer: these instructions relate to our environment. It may be -that our sysadmins/dbas chose to configure/install things a certain -way (i.e., our install of $ORACLE_HOME/bin/sqlplus was *chosen* -to be 1.1/32), and/or that we're running old versions of software -(i.e., perhaps later releases of gcc don't ignore -mpa-risc-1-1). -In fact, there are probably some mistruths in here; rest assured -they're not intentional. :-) - -I'm unsure how (if?) I should go about getting this information into -the DBD::Oracle README.hpux. Lincoln, please contact me with any -thoughts you have. - - -### The summary ################################ - -Use the ansic compiler (~US$800/cpu). - -Shell variables I used: - PATH=/bin:$PATH # use 32bit ar & nm since using a 32bit cc - PERLDEST=/opt/perl_ora8 # or "perl_ora9" for an ora9 build - PATH=$PERLDEST/bin:$PATH # for build of DBI, pick up new perl - export LDLOADLIBS='+b : +s' # handy for ORACLE_SID connections to ora7 - unset PERLLIB # important to avoid outdated cruft - export ORACLE_USERID=scott/tiger # insecure - consider using "/" - ORACLE_SID=orcl - ORAENV_ASK=NO - . oraenv # sets LD_LIBRARY_PATH and SHLIB_PATH - -For ora8: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DAportable ' \ - -A prepend:ldflags='+z +DAportable ' - -For ora9: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DA2.0W ' \ - -A prepend:ldflags='+z +DA2.0W ' \ - -Dlibpth='/usr/lib/pa20_64 /usr/local/pa20_64/lib' - -After you use the above to install perl, DBI & DBD::Oracle will -build in the normal fashion. - - -### General Notes ################################ - -* During "make test", I received 1 failure (on -lib/ExtUtils/t/Constant) for ora8, and 3 failures (on -lib/ExtUtils/t/Constant, lib/ExtUtils/t/recurs, and t/op/write) for -ora9. Nevertheless, things seem mostly OK. - -* These are the various combinations possible for a given compiled -file on HP-UX 11.11 (the quoted description is what gets kicked out -by the "file" command): - - PA-RISC1.1/32bit ("PA-RISC1.1 relocatable object") - (I'll call this 1.1/32) - PA-RISC2.0/32bit ("PA-RISC2.0 relocatable object") - (I'll call this 2.0/32) - PA-RISC2.0/64bit ("ELF 64-bit MSB relocatable, PA-RISC 2.0 (LP64)") - (I'll call this 2.0/64) - -* "perl -v" lies about the RISC level: -$ file ./perl -./perl: PA-RISC1.1 shared executable dynamically linked -not stripped -$ ./perl -v | grep RISC -This is perl, v5.8.3 built for PA-RISC2.0 - -* If you'll be linking against 2.0/64 libraries, you'll have to -build all your object modules that way. I've not yet found a way -to link 32bit executables to 64bit libraries (and vice versa). Run -the "file" command on your Oracle libraries to find out which path -you'll have to take. - -* Two environment variables control where libraries are -searched. LD_LIBRARY_PATH and SHLIB_PATH (in that order) are -used for 64bit executables, while SHLIB_PATH is used for 32bit -executables. - -* I tried attempts using aCC as well as the default (free) cc that -comes with hpux; both avenues were too problematic to continue -pursuing. - -* The format of compiled objects is specified by compiler options. -According to the ansic compiler docs, the options are "+DAportable" -(for 1.1/32), "+DA2.0" (for 2.0/32), and "+DA2.0W" (for 2.0/64). -For gcc, the corresponding switches are -mpa-risc-1-1 (for 1.1/32) -and -mpa-risc-2-0 (for 2.0/64), but I've found that -mpa-risc-1-1 -is ineffective. (According to the "file" command, you *always* get -2.0/64.) - -* Our gcc displays the behavior described at -http://sources.redhat.com/ml/binutils/2002-10/msg00586.html and -http://aspn.activestate.com/ASPN/Mail/Message/perl5-porters/1641238 -, so is therefore unusable anytime '-lcl' is to be specified. -Unfortunately, that library is required for DBD::Oracle builds. -(The workaround of adding the 3 declarations does seem to work, -but littering those throughout perl's Configure, main.c, etc. -seems a big task.) Attempts to get gcc to use the hp ld instead -of the gnu ld (by specifying -mno-gnu-ld and -fno-gnu-linker) were -unsuccessful. The first html link shown above indicates you have -to rebuild gcc to use the hp linker, and that was not an incredibly -desirable path to pursue. - -* Our default PATH was set to put /usr/local/pa20_64/bin ahead of -/bin. This caused problems because (I think) the 64bit versions -of either ar (the archiver) or nm (the symbol lister) do not play -well with /bin/cc (the 32bit compiler). The tweak to put /bin at -the head of PATH, so we get the 32bit versions, takes care of the -problem. - -* I ran into an intermittent quirk during the build of perl in which -typing "make" (just after the Configure) did nothing. It turns out -that only dependencies were being written to "makefile", and that -removing "makefile" (so it could be automatically rebuilt) solved -the problem. - -* Most of my research on finding the right compiler/linker switches -was done with a "hello world" C program, trying the various -compilers and options, and trying to link it with the oracle -libraries. This proved to be a good choice, as trying to test -compilers/switches against the perl source distribution would have -proved quite difficult. - - -### DBD::Oracle specific ################################ - -* ora8 delivers its libraries in 2 formats: 1.1/32 (under -$ORACLE_HOME/lib) and 2.0/64 (under $ORACLE_HOME/lib64). ora7 -delivers only 1.1/32, while ora9 delivers only 2.0/64. It may seem -a bit inconsistent considering the ora8 setup, but ora9 libraries -are found under $ORACLE_HOME/lib and not $ORACLE_HOME/lib64. - -* Under ora8, oraenv incorrectly sets LD_LIBRARY_PATH to include -$ORACLE_HOME/lib instead of $ORACLE_HOME/lib64, so you've got to -make an override in oraenv_local if you want to use 2.0/64. It -doesn't harm anything, but oraenv unnecessarily sets LD_LIBRARY_PATH -for ora7 (a 64bit environment variable for a 32bit application). - -* If you use shared libraries AND you'll be upgrading Oracle, you -should expect you'll need to rebuild DBD::Oracle unless you'll keep -the old Oracle libraries available. - -* If you're building against ora8, the setting of LDLOADLIBS -is recommended so that when oraenv set SHLIB_PATH to the -$ORACLE_HOME/lib for ora7, the code will still find the ora8 -libraries. - -* We expect to need local (ORACLE_SID) connections for ora8 & -ora9. We could have gone with a single 2.0/64 perl coupled with -2 DBD::Oracle installs and PERLLIB twiddling in oraenv_local to -get to the right one. Instead, we chose to do 2 perl installs -(/opt/perl_ora8 and /opt/perl_ora9) because we can also connect -locally to ora7 by using the 1.1/32 ora8 version, something that -isn't possible with a 2.0/64 version. Also, we've some older 1.1/32 -machines into which we'd like to plop a tarball of the perl stuff, -so a 1.1/32 executable was desirable. - -* Some tests I ran were hinting that with 2.0/64, specifying "+b :" -on the build of DBD::Oracle correctly configured Oracle.sl as far as -the chatr program is concerned, but it seemed that LD_LIBRARY_PATH -*always* needed to be set correctly. (I.e., the embedded path in -the library seemed to be ignored.) I didn't pursue researching this -since there's no way to get the ora9 compiled code to connect to -ora8, meaning LD_LIBRARY_PATH had to be set correctly anyway. - -Testing local (ORACLE_SID) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora9 cannot connect to ora8 or ora7: "UNKNOWN - OCI STATUS 1804) OCIInitialize. Check ORACLE_HOME and NLS - settings etc." - -Testing remote (sqlnet) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 can connect to ora9 -builds against 2.0/64 ora9 can connect to ora8 -builds against 2.0/64 ora9 cannot connect to ora7: "OCI-21500: internal - error code" - - -### Versions ################################ - -perl: 5.8.3 -dbi: 1.41 -dbd-oracle: 1.15 -$ strings /bin/cc | grep Compiler -HP92453-01 B.11.11.08 HP C Compiler -$ strings /bin/ld | grep linker -$Revision: 92453-07 linker linker crt0.o B.11.16 000601 $ -@(#)92453-07 linker command s800.sgs ld PA64 B.11.18 REL 000922 -$ gcc -v -Reading specs from /usr/local/pa20_64/lib/gcc-lib/hppa64-hp-hpux11.11/3.3.1/specs -Configured with: ../src/configure --enable-languages=c,c++ --prefix=/usr/local/pa20_64 --with-local-prefix=/usr/local/pa20_64 --with-gnu-as --with-as=/usr/local/pa20_64/bin/as --with-gnu-ld --with-ld=/usr/local/pa20_64/bin/ld --disable-shared --disable-nls --host=hppa64-hp-hpux11.11 -Thread model: single -gcc version 3.3.1 - --- -J.D. Laub (Laubster) |"Your leg's too long / Your skull's too strong / -dbiusers@laubster.org| Suppose your nose is wrong." - Renaldo & the Loaf - diff --git a/err_build/err_instantclient.msg b/err_build/err_instantclient.msg deleted file mode 100644 index f0e549eb..00000000 --- a/err_build/err_instantclient.msg +++ /dev/null @@ -1,207 +0,0 @@ -From SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Feb 2 10:11:05 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j12AAUZ6055956 - for ; Wed, 2 Feb 2005 10:11:05 GMT - (envelope-from SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 02 Feb 2005 10:11:05 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwGaQ-0002Bn-H6; - Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwGaQ-0002Bn-H6 - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwGaP-00042G-Vb - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 9C3FB1E3946; - Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 879981E3958 - for ; Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Received-SPF: pass (kelvin.pobox.com: domain of dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by kelvin.pobox.com (Postfix) with SMTP id D0B001E3946 - for ; Wed, 2 Feb 2005 04:14:08 -0500 (EST) -Received: (qmail 7188 invoked by uid 514); 2 Feb 2005 09:14:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -List-Id: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 2531 invoked from network); 2 Feb 2005 04:10:16 -0000 -Delivered-To: dbi-users@perl.org -X-Spam-Status: No, hits=-2.6 required=8.0 - tests=BAYES_00,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: pass (x1.develooper.com: local policy) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgw.shina.sankyo.co.jp: iscan owned process doing -bs -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: Making DBD::Oracle with Instant Client 10.1.0.3 -Date: Wed, 2 Feb 2005 13:09:58 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBE9@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUI3Q64h9ykph8RSl6pF0OpBbTqJA== -To: -X-OriginalArrivalTime: 02 Feb 2005 04:09:59.0005 (UTC) FILETIME=[0F7508D0:01C508DD] -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 44 - -Hi all, - -Thanks to the devel package, I've got succeeded in making DBD::Oracle -with the Oracle Instant Client 10.1.0.3, no *.mk files, in my linux box. -My recipe is: - -1) install both basic- and devel-10.1.0.3 rpm packages -2) export ORALCE_HOME="/usr/lib/oracle/10.1.0.3/client" -3) export LD_LIBRARY_PATH="$ORACLE_HOME/lib:$LD_LIBRARY_PATH" -4) modify the Makefile.PL file to bypass the find_headers() routine and - to pass a correct -I flag to cc (the attached dirty patch is FYI) -5) execute the Makefile.PL * with the -l option *, perl Makefile.PL -l -6) make && make test && make install -# I got many errors in t/30long.t (retrieving blobs ?) -# but it seems to work fairly. - -I hope this could help those who are annoyed with the "Unable to locate an -oracle.mk,..." error. - -Happy DBing, - -Satoshi - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+# my @h_dirs = find_headers(); - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client"; - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -From SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com Thu Feb 3 08:10:48 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j138AMOi093146 - for ; Thu, 3 Feb 2005 08:10:48 GMT - (envelope-from SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Thu, 03 Feb 2005 08:10:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwboD-0005ug-LV; - Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwboD-0005ug-LV - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwboD-0000Wn-82 - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 70999102D9F; - Thu, 3 Feb 2005 02:53:48 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 5F45E102DCC - for ; Thu, 3 Feb 2005 02:53:48 -0500 (EST) -X-Pobox-Antispam: Require PTR Record returned DENY: 210.81.52.253 has no PTR record -X-Pobox-Antispam: country/Japan returned DENY: sender address snisim@sankyo.co.jp matches TLD .jp (Japan) -Received-SPF: none (boggle.pobox.com: domain of snisim@sankyo.co.jp does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for snisim@sankyo.co.jp to mail through 210.81.52.253) -Received: from mailgws.shina.sankyo.co.jp (unknown [210.81.52.253]) - by boggle.pobox.com (Postfix) with ESMTP id A38A5102E20 - for ; Thu, 3 Feb 2005 02:53:46 -0500 (EST) -Received: from es007.sankyo.co.jp (localhost [127.0.0.1]) - by mailgws.shina.sankyo.co.jp (8.9.3p2/3.7W) with ESMTP id LAA15117 - for ; Thu, 3 Feb 2005 11:45:39 +0900 (JST) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgws.shina.sankyo.co.jp: iscan owned process doing -bs -Received: from EVS001.sankyo.co.jp ([10.14.121.200]) by es007.sankyo.co.jp with Microsoft SMTPSVC(6.0.3790.0); - Thu, 3 Feb 2005 11:45:39 +0900 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: RE: Making DBD::Oracle with Instant Client 10.1.0.3 -Content-class: urn:content-classes:message -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Date: Thu, 3 Feb 2005 11:46:07 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBEC@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUJEc1pQuIX++g2S8y4AE9WqWRYtQAhsK+Q -To: -X-OriginalArrivalTime: 03 Feb 2005 02:45:39.0123 (UTC) FILETIME=[71F21030:01C5099A] -Status: RO -Content-Length: 1192 -Lines: 36 - -Hi Tim, - -Thank you for your kind reply. - -I found my patch will cause a compilation error for the local variable -@h_dirs gets into undefined after commenting out the line 279. -It should be corrected as following: - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+ my @h_dirs; - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client" - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -I'm not a dbi-users member so I can't reply my post... I wonder if you can do it. - -Thanks, - -Satoshi - - diff --git a/err_build/err_makefileundef.msg b/err_build/err_makefileundef.msg deleted file mode 100644 index b98d782a..00000000 --- a/err_build/err_makefileundef.msg +++ /dev/null @@ -1,87 +0,0 @@ -From timbo Tue Apr 26 09:19:54 2005 -Return-path: -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 26 Apr 2005 09:19:54 -0700 (PDT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DQSgy-0006AU-4c; - Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DQSgy-0006AU-4c - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1DQSgy-0003uM-1T - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 759703B902A; - Tue, 26 Apr 2005 12:13:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 80C0A39F279 - for ; Tue, 26 Apr 2005 12:13:42 -0400 (EDT) -Received-SPF: none (kelvin.pobox.com: domain of lembark@wrkhors.com does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 66.246.154.128(mail-out.pilosoft.net) -Received: from mail.pilosoft.net (mail-out.pilosoft.net [66.246.154.128]) - by kelvin.pobox.com (Postfix) with ESMTP id 2ED743AB75B - for ; Tue, 26 Apr 2005 12:12:30 -0400 (EDT) -Received: from [192.168.1.2] (dsl-69-31-90-94.pilosoft.com [69.31.90.94]) - by mail.pilosoft.net (8.12.8/8.12.8) with ESMTP id j3QGA3u1014203 - for ; Tue, 26 Apr 2005 12:10:03 -0400 -Date: Tue, 26 Apr 2005 12:14:22 -0400 -From: Steven Lembark -Reply-To: lembark@wrkhors.com -To: Tim Bunce -Subject: Possible glitch in DBD::Oracle-1.48 Makefile.pl -Message-ID: <269F0144DC99100E7C80975F@[192.168.1.2]> -X-Mailer: Mulberry/3.1.3 (Linux/x86) -X-Workhorse: lembark 1.1 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii; format=flowed -Content-Transfer-Encoding: 7bit -Content-Disposition: inline -X-Virus-Scanned: ClamAV version 0.83, clamav-milter version 0.83 on mail.pilosoft.net -X-Virus-Status: Clean -X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=failed version=3.0.2 -X-Spam-Level: 0.0 -X-Spam-Checker-Version: SpamAssassin 3.0.2 (2004-11-16) on cheeta.pilosoft.net -X-Status: A -Content-Length: 1342 -Lines: 36 - -Linking with OTHERLDFLAGS = -L/opt/oracle/product/9.2/lib/ --L/opt/oracle/product/9.2/rdbms/lib/ -lclntsh `cat -/opt/oracle/product/9.2/lib/sysliblist` -ldl -lm [from 'build' rule] - -Checking if your kit is complete... -Looks good -Use of uninitialized value in substitution (s///) at Makefile.PL line 1446. -LD_RUN_PATH=/opt/oracle/product/9.2/lib:/opt/oracle/product/9.2/rdbms/lib -Using DBD::Oracle 1.16. - - - sub const_loadlibs { - my $self = shift; - local($_) = $self->SUPER::const_loadlibs(@_); - # edit LD_RUN_PATH ... - my ($ldrp) = m/^LD_RUN_PATH\s*=\s*(.*)/m; - # remove redundant /lib or /usr/lib as it can cause problems --> $ldrp =~ s!:(/usr)?/lib$!!; - # if it's empty then set it manually - #Lincoln: if pick the right library path - my $libdir = main::ora_libdir(); - $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; - #print "ldrp=$ldrp\n"; - - # stitch it back in - s/^LD_RUN_PATH\s*=\s*(.*)/LD_RUN_PATH=$ldrp/m; - my $env = $ENV{LD_RUN_PATH}; - print "Ignoring LD_RUN_PATH='$env' in environment\n" if $env; - print "LD_RUN_PATH=$ldrp\n"; - return $_; - } - --- -Steven Lembark 85-09 90th Street -Workhorse Computing Woodhaven, NY 11421 -lembark@wrkhors.com 1 888 359 3508 - diff --git a/err_build/err_memleak.msg b/err_build/err_memleak.msg deleted file mode 100644 index d40913d7..00000000 --- a/err_build/err_memleak.msg +++ /dev/null @@ -1,95 +0,0 @@ -From SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com Wed Sep 1 16:31:37 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i81FRlpg021884 - for ; Wed, 1 Sep 2004 16:31:37 +0100 (BST) - (envelope-from SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 Sep 2004 16:31:37 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C2WYO-00034m-M1; - Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C2WYO-00034m-M1 - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1C2WYO-0005CR-FY - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 1C1D6A758C; - Wed, 1 Sep 2004 10:57:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 184C8A7214 - for ; Wed, 1 Sep 2004 10:57:32 -0400 (EDT) -Received-SPF: fail (boggle.pobox.com: domain of www-data@pallas.eruditorum.org does not designate 63.251.223.170 as permitted sender) -X-SPF-Override: pass (client 63.251.223.170 was found in trusted-forwarder.org, overrides regular SPF fail) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.170(x1.develooper.com) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP id 7A6C9A7555 - for ; Wed, 1 Sep 2004 10:57:06 -0400 (EDT) -Received: (qmail 5427 invoked by uid 225); 1 Sep 2004 14:57:04 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 5403 invoked by alias); 1 Sep 2004 14:57:02 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 01 Sep 2004 07:56:59 -0700 -Received: by pallas.eruditorum.org (Postfix, from userid 33) - id 1FDD784C0F5; Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -Subject: [cpan #6245] Confirmed memory leak -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #6245 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -Date: Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -To: undisclosed-recipients: ; -Status: RO -Content-Length: 937 -Lines: 38 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -I Using : -1. SunOS 5.6 Generic_105181-33 sun4u sparc SUNW,Ultra-Enterprise - Perl 5.005_03 - DBI 1.37 - DBD-Oracle 1.14 - Oracle Release 8.1.5.0.0 - - -2. Linux 2.4.18-17.7.xsmp #1 SMP i686 - Perl 5.6.1 - DBI 1.41 - DBD-Oracle 1.16 - Oracle Release 8.1.6.0.0 - -II The following code: - -use strict; -use DBI; - -foreach ( 1 .. 100 ) { - my $dbh = DBI->connect( 'dbi:Oracle:host=****', '***', '***' ); - $dbh->disconnect(); - sleep(1) -} - -III Leak about 4K every 10 seconds - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8724 8720 2760 S 1.3 3.4 0:01 perl - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8736 8732 2760 S 0.7 3.4 0:01 perl - diff --git a/err_build/err_solarisnotes.msg b/err_build/err_solarisnotes.msg deleted file mode 100644 index eaddc475..00000000 --- a/err_build/err_solarisnotes.msg +++ /dev/null @@ -1,482 +0,0 @@ -From SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com Wed Dec 22 08:11:00 2004 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id iBM8Aog0091816 - for ; Wed, 22 Dec 2004 08:11:00 GMT - (envelope-from SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 22 Dec 2004 08:11:00 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Ch0it-0001A5-Rv; - Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Ch0it-0001A5-Rv - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Ch0is-0000To-R8 - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id F0F0DFE10C; - Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 8B2AAFE1C3 - for ; Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Received-SPF: none (lime.pobox.com: domain of alexzar@zorranlabs.com does not designate permitted sender hosts) -Received: from penguin.nocdirect.com (penguin.nocdirect.com [69.73.160.206]) - by lime.pobox.com (Postfix) with ESMTP id 2B41BFE159 - for ; Wed, 22 Dec 2004 02:13:17 -0500 (EST) -Received: from localhost ([127.0.0.1]) - by penguin.nocdirect.com with esmtps (TLSv1:DES-CBC3-SHA:168) - (Exim 4.43) - id 1Cgz53-0000fj-Bx; Tue, 21 Dec 2004 23:30:37 -0600 -Date: Tue, 21 Dec 2004 23:30:35 -0600 (CST) -From: Alex Zarutin -X-X-Sender: zorranla@penguin.nocdirect.com -To: Tim Bunce -Cc: dbi-users-help@perl.org -Subject: Step-by-Step installation manual of DBD-Oracle-1.16 on Sparc Solaris - 9 with Oracle 9.2.0.1.0 client. -Message-ID: -MIME-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-AntiAbuse: This header was added to track abuse, please include it with any abuse report -X-AntiAbuse: Primary Hostname - penguin.nocdirect.com -X-AntiAbuse: Original Domain - pobox.com -X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] -X-AntiAbuse: Sender Address Domain - zorranlabs.com -X-Source: -X-Source-Args: -X-Source-Dir: -Status: RO -X-Status: A -Content-Length: 15603 -Lines: 426 - - -Hi Tim, - -I have spent a couple days trying to install DBD-Oracle-1.16 (all -required stuff, such as GCC, DBI, etc has been installed before ) on -Sun-Fire v240 running Spark Solaris 9 with the Oracle 9.2.0.1.0 client -installed. The installation takes a couple minutes ONLY after you spend -days trying to make it workable. - -I wrote the log of what I do, in order to do not waste my time in -future. I am pretty sure that this log will be very useful for people -installing DBD-Oracle on Solaris. I published it on my log page, and left -link on it at http://cpanratings.perl.org/d/DBD-Oracle review page. I -would recommend you to add this log to the readme file of your next -releases. Log is written very detailed (step-by-step) with highlighted -typical mistakes. - -Environment: -Hardware/OS: bash-2.05# uname -a -SunOS qadmz41 5.9 Generic_117171-08 sun4u sparc SUNW,Sun-Fire-V240 -OS is actually "standard" Solaris 9 installation came on the box from -SUN - -Oracle Client: Oracle 9.2.0.1.0 -GCC: gcc version 3.3.2, installed to /usr/local/bin as a package from -http://www.sunfreeware.com/programlistsparc9.html -PERL: perl v5.8.5 built for sun4-solaris, installed to /usr/local/bin as -a package from http://www.sunfreeware.com/programlistsparc9.html -DBI: DBI-1.45, installed from http://search.cpan.org/~timb/DBI-1.45/ - -Step-by-Step Manual: - -Step 1: In order to install "DBD-Oracle-1.16" you need to download it, -set all appropriate environment variables (see readme for details) and -run <>. -I got an error that is mostly typical for Solaris installation: - -// ************************ Error 1 ***********************/ - -.... -Found header files in rdbms/demo. - -********************************************************* -I can't find the header files I need in your Oracle installation. -You probably need to install some more Oracle components. -I'll keep going, but the compile will probably fail. -See README.clients for more information. -********************************************************* -Checking for functioning wait.ph - -System: perl5.008005 sunos 5.9 generic sun4u sparc sunw,ultra-5_10 -solaris -Compiler: gcc -B/usr/ccs/bin/ -O -fno-strict-aliasing -pipe --I/usr/local/include -I/opt/gnu/include -D_LARGEFILE_SOURCE --D_FILE_OFFSET_BITS=64 - -.... -// *****************************************************/ - -Investigating this problem, I found that error message is thrown by the -"find_headers" sub of Makefile.PL, especially in this "if -(!$h_file{'oratypes.h'} || !$h_file{'ocidfn.h'})" evaluation. -So I checked these files to make sure that they are installed, but did -not find them under $ORACLE_HOME/rdbms -In the same time, I found an article saying about the similar problem -with DBD-Oracle on Linux, -http://baroti.homedns.org/steve/lost+found/cpan-install-DBD-Oracle-9-2-l -inux.html -They mentioned about two files, and since I was not sure about second -one, ociapr.h I copied both files. You should find its public.1.1.jar -file on the Disk3 of Oracle 9i installation set. - -bash-2.05# pwd -/ora_orig/Disk3/stage/Components/oracle.rdbms.oci/9.2.0.1.0/1/DataFiles - -bash-2.05# ls -al -total 970 -drwxr-xr-x 2 2840 42424 512 Aug 21 2002 . -drwxr-xr-x 3 2840 42424 512 Aug 21 2002 .. --rwxr-xr-x 1 2840 42424 2047 May 9 2002 bin.1.1.jar --rwxr-xr-x 1 2840 42424 206 May 9 2002 build.1.1.jar --rwxr-xr-x 1 2840 42424 135034 May 9 2002 demo.1.1.jar --rwxr-xr-x 1 2840 42424 329814 May 9 2002 public.1.1.jar - -You should just (as dba:oracle) to create the directory called public, -copy public.1.1.jar there and extract all files, since I would not guess -if the rest of them are used or not - -bash-2.05# mkdir $ORACLE_HOME/rdbms/public - -bash-2.05# ls -al $ORACLE_HOME/rdbms/public -total 3404 -drwxr-xr-x 2 oracle dba 512 Dec 21 12:12 . -drwxr-xr-x 10 oracle dba 512 Dec 21 12:05 .. -... --rw-r--r-- 1 oracle dba 6055 Mar 9 2002 ociapr.h --rw-r--r-- 1 oracle dba 10694 Jun 29 2000 ocidfn.h -... - -After that run <> again, and I hope process passes -fine. At least, it was fine in my case - -Step 2: You should <> the module, and as it appears on Solaris, -you will get typical problem. See my error log: - -// ************************ Error 2 ***********************/ -.... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -ld: fatal: file -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib//libclntsh.so: -wrong ELF class: ELFCLASS64 -ld: fatal: File processing errors. No output written to -blib/arch/auto/DBD/Oracle/Oracle.so -collect2: ld returned 1 exit status -*** Error code 1 -make: Fatal error: Command failed for target -`blib/arch/auto/DBD/Oracle/Oracle.so' - -// *****************************************************/ - -So, as another set on Google' posts showed that it is a possibility of -missing libraries compiled with 64 bits and same libraries compiled with -32 bits suppoert. As I understood, all components of installation, such -as Oracle client, Perl, GCC should support only one type of libraries, -either 32 or 64 bits. I found that having all as 32 bits is easier to me -than recompile perl, gcc as 64 (may be I am wrong in this assumption). -In order to have all of them as 32 bits, I changed lib to lib32 in -Manifest file (not Manifest.PL). - -You should replace the following lines in the "MakeMaker const_loadlibs -section": - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -By their lib32 clones: - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -And replace this line in "MakeMaker dynamic_lib section" (~~ line 491) - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread - -By its lib32 clone: - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread - -I hope, that after that process passes without any errors. Here is last -part, that I got during <>: - -..... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/local/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL -ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/local/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" -blib/script/ora_explain -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oracle.3 -Manifying blib/man3/DBD::Oraperl.3 - -III. Once we build the module, we should test it, to make sure that it -works fine. You should run <> to do it: - -Check that you have ORACLE_HOME, ORACLE_USERID, ORACLE_SID environment -variables set, like this: - -ORACLE_HOME=="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0 -ORACLE_USERID=STARSHIP/STARSHIP -ORACLE_SID=COLORADO - -When you run <>, you will probably get this errors: - -// ************************ Error 3 ***********************/ - -bash-2.05# make test -PERL_DL_NONLAZY=1 /usr/local/bin/perl "-MExtUtils::Command::MM" "-e" -"test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............DBI connect('','STARSHIP/STARSHIP',...) failed: -ORA-12545: Connect failed because target host or object does not exist -(DBD ERROR: OCIServerAttach) at t/10general.t line 12 -Undefined subroutine &main::BAILOUT called at t/10general.t line 15. -# Looks like your test died before it could output anything. -t/10general.............dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-31 - Failed 31/31 tests, 0.00% okay -..... - -// *****************************************************/ - -One more brainstorm, and I figured out another way to set ORACLE_USERID: - -ORACLE_USERID=STARSHIP/STARSHIP@COLORADO -ORACLE_SID=COLORADO - -Later, when tests finished, I was confirmed that it was probably -preferred way of setting ORACLE_USERID. -Tests did found correct settings, and "main" set of them returned the -following report: - -All tests successful, 1 test and 122 subtests skipped. -Files=18, Tests=1020, 24 wallclock secs (11.27 cusr + 1.34 csys = 12.61 -CPU) - -For the Extra test, less formal, but test anyway, I just commented these -two lines in test.pl file - -$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -and set the same values in the same form to the $dbuser as it was in -ORACLE_USERID , and -left $dbname empty, - -$dbname = ''; -$dbuser = 'STARSHIP/STARSHIP@COLORADO'; - -and got pretty good report: - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - -recommended) - as 'STARSHIP/STARSHIP@COLORADO' (via ORACLE_USERID env var or default - -recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -Fields: 6 -Names: 'NUM_T' 'DATE_T' 'CHAR_T' 'ROWID_T' -'RAW_T' 'NULL_T' -Lengths: 172 76 121 21 3 1 -OraTypes: 2 12 1 104 23 1 -SQLTypes: 8 93 12 -9104 -2 12 -Scale: 0 0 0 0 0 0 -Precision: 126 75 120 20 2 0 -Nullable: 1 1 1 1 1 1 -Est row width: 32 -Data rows: - fetch: '7.2', '21-DEC-04', 'STARSHIP', 'AAAADeAABAAAAZSAAA', '7D', -undef - -ora_logoff... -lda out of scope... - -Testing repetitive connect/open/close/disconnect: -If this test hangs then read the README.help file. -Expect sequence of digits, no other messages: -1 2 3 4 5 - -Test interaction of explicit close/logoff and implicit DESTROYs -Expect just 'done.', no other messages: -done. - -Testing row cache (5). -Test completed in 0 seconds. - -Test complete (0 seconds). -If the tests above have produced the 'expected' output then they have -passed. - -IV. The last part is actually target of all steps above, installing -build module. < did not surprise me, and it it passed -smoothly. - -bash-2.05# make install -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/dbdimp -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/ocitra -ce.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/mk.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.so -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.bs -Files found in blib/arch: installing files in blib/lib into architecture -dependent library tree -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/oraperl.ph -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/Oraperl.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle/GetInfo.pm -Installing /usr/local/share/man/man1/ora_explain.1 -Installing /usr/local/share/man/man3/DBD::Oracle.3 -Installing /usr/local/share/man/man3/DBD::Oraperl.3 -Installing /usr/local/bin/ora_explain -Writing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/.packl -ist -Appending installation info to -/usr/local/lib/perl5/5.8.5/sun4-solaris/perllocal.pod - -V. This is actually it, and you do not need to do anything else. But -investigating different errors during the various steps, I found the -very simple "independent sanity" testdbi perl script written by Jeff -Hunter. This script is not related to standard process of -making/buildin/testing/installation. It just verifies that you can -access DB and run a couple queries against it. The code itself, -testdbi.pl can be found at -http://www.idevelopment.info/data/Oracle/DBA_tips/Programming/PROGRAMMIN -G_2.shtml - -You just should set connection information, similar to how I did it, - - $ORACLE_SID = "COLORADO"; - $ORACLE_USERID = "STARSHIP"; - $ORACLE_PASSWORD = "STARSHIP"; - - $ENV{'ORACLE_SID'} = "$ORACLE_SID"; - $ENV{'ORACLE_HOME'} = /u01/app/oracle/product/9.2.0.1.0"; - -run it as any perl script, <>, and see result: - -bash-2.05# perl testdbi.pl - -Running testdbi.pl... - - (*) Attempting Oracle Login ... - OK - (*) Creating table TEST_DBI ... - OK - (*) Insert into TEST_DBI ... - 1 rows inserted. - 1 rows inserted. - 1 rows inserted. - OK - (*) Select from TEST_DBI ... - - --> TEST_DBI_INTR_NO : 1000 - --> TEST_DBI_NAME : Jeff Hunter - - --> TEST_DBI_INTR_NO : 1001 - --> TEST_DBI_NAME : Melody Hunter - - --> TEST_DBI_INTR_NO : 1002 - --> TEST_DBI_NAME : Alex Hunter - OK - - (*) Delete from TEST_DBI ... - 3 rows deleted. - OK - - (*) Drop table TEST_DBI ... - OK - - (*) Select USER and SYSTEM ... - - --> USER : STARSHIP - --> SYSDATE : 21-DEC-2004 16:49:59 - OK - - (*) Attempting Oracle Logoff ... - OK - -Ending testdbi.pl... - -With the best regards, - -Alex Zarutin - -Software Engineer -4thpass A Motorola Company -Seattle, WA -www.4thpass.com - - - - diff --git a/err_build/err_testfailnotable.msg b/err_build/err_testfailnotable.msg deleted file mode 100644 index 687d5ed7..00000000 --- a/err_build/err_testfailnotable.msg +++ /dev/null @@ -1,97 +0,0 @@ -From SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 18:10:51 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RHAOAK026067 - for ; Wed, 27 Oct 2004 18:10:51 +0100 (BST) - (envelope-from SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 18:10:51 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMp30-0000e2-Hh; - Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMp30-0000e2-Hh - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMp30-0001QS-2p - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 87C155A7D; - Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 7779A59A1 - for ; Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Received-SPF: pass (gold.pobox.com: domain of dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by gold.pobox.com (Postfix) with SMTP id DC5795A4A - for ; Wed, 27 Oct 2004 10:45:07 -0400 (EDT) -Received: (qmail 18140 invoked by uid 514); 27 Oct 2004 14:45:04 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 18131 invoked from network); 27 Oct 2004 14:45:04 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 14:45:04 -0000 -Received: (qmail 8663 invoked by uid 225); 27 Oct 2004 14:45:03 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 8659 invoked by alias); 27 Oct 2004 14:45:03 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from ns2.aramiska.net (HELO dmzms01.aramiska.net) (80.242.32.2) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 07:45:01 -0700 -Received: from ip-80-242-36-115.aramiska-arc.aramiska.net (ip-80-242-36-115.aramiska-arc.aramiska.net [80.242.36.115]) - by dmzms01.aramiska.net (Postfix) with ESMTP - id 9F21E1100D9; Wed, 27 Oct 2004 14:44:55 +0000 (UTC) -Received: from localhost (localhost [127.0.0.1]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id E558E7C; Wed, 27 Oct 2004 14:44:52 +0000 (UTC) -Received: from dansat.data-plan.com (ip-192-168-0-3.internal.data-plan.aramiska.net [192.168.0.3]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id D8A5E71; Wed, 27 Oct 2004 14:44:50 +0000 (UTC) -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9REioAA023212; - Wed, 27 Oct 2004 15:44:50 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i9REinmW023211; - Wed, 27 Oct 2004 15:44:49 +0100 (BST) -Date: Wed, 27 Oct 2004 15:44:49 +0100 -From: Tim Bunce -To: "H.Merijn Brand" -Cc: Tim Bunce , DBI developers -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Message-ID: <20041027144449.GB19991@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> <20041027093516.D001.H.M.BRAND@hccnet.nl> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20041027093516.D001.H.M.BRAND@hccnet.nl> -User-Agent: Mutt/1.4i -X-Virus-Scanned: by Aramiska Arc -Status: RO -Content-Length: 634 -Lines: 14 - -On Wed, Oct 27, 2004 at 09:39:33AM +0200, H.Merijn Brand wrote: -> On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> > file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> > size: 235224 bytes -> > md5: 9711550ed0ebfc743920a6a357ed717c -> -> I know you can't blame the test for not being able to create a table for the -> reason this failure shows, but there might be a more user-friendly way to fail ... - -Yeap. Some tests behave better in that situation. Looks like those -two need improving. Patches welcome! (I'd happily not touch DBD::Oracle -for a few months after the pain of the last few months :) - -Tim. - diff --git a/err_docs/err_trace.msg b/err_docs/err_trace.msg deleted file mode 100644 index 3d7500fb..00000000 --- a/err_docs/err_trace.msg +++ /dev/null @@ -1,14 +0,0 @@ -Add this to the DBD::Oracle docs as a handy note: - -$dbh->do(q{alter session set events '65285 trace name errorstack level 3'}); - -A trace file should then be generated. - -Trace files are generated in the 'user_dump_destination' specified in init.ora. - -Try $ORACLE_BASE/admin/$ORACLE_SID/udump. - -or the location returned by -select value -from v$parameter -where name like '%user_dump%' diff --git a/err_lob/err_csr_clob.msg b/err_lob/err_csr_clob.msg deleted file mode 100644 index 397d53b3..00000000 --- a/err_lob/err_csr_clob.msg +++ /dev/null @@ -1,65 +0,0 @@ -From dbi-users-bounce@isc.org Thu Sep 21 20:27:21 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id UAA18945; Thu, 21 Sep 2000 20:27:20 +0100 (BST) -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <02709-1@oink>; Mon, 21 Sep 1970 20:26:40 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 969564156:20:26825:1; Thu, 21 Sep 2000 19:22:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-2.mail.demon.net - id aa2026778; 21 Sep 2000 19:22 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 28A613E5D; - Thu, 21 Sep 2000 12:22:17 -0700 (PDT) -Received: with LISTAR (v1.0.0; list dbi-users); - Thu, 21 Sep 2000 12:17:37 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A59853E42 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) -Received: from wheel.cs.wisc.edu (wheel.cs.wisc.edu [128.105.121.12]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA00855 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) env-from (horn@wheel.cs.wisc.edu) -Received: (from horn@localhost) by wheel.cs.wisc.edu (8.9.2/8.9.2) id OAA16413 - for dbi-users@isc.org; Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -Date: Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -From: Jeffrey Horn -Message-Id: <200009211917.OAA16413@wheel.cs.wisc.edu> -To: dbi-users@isc.org -Subject: Setting ORA_TYPE after the fact... -Sender: horn@wheel.cs.wisc.edu -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: horn@cs.wisc.edu -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -X-Status: A -Content-Length: 969 -Lines: 20 - -I have a situation where I would like to return a cursor that contains a -CLOB as one of it's attributes from a PL/SQL procedure. What I get back is -a LOB locator and DBD doesn't actually read the CLOB but instead returns an -error. - -If I go through a bind/prepare/execute/fetch on a similar SQL statement all -is well. Is there any way that I can tell DBD that a given attribute of -a cursor is a CLOB once the cursor is already opened so that DBD will do the -right thing? - --- Jeff Horn - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_lob/err_loblenwide.msg b/err_lob/err_loblenwide.msg deleted file mode 100644 index 08023e97..00000000 --- a/err_lob/err_loblenwide.msg +++ /dev/null @@ -1,95 +0,0 @@ -From nobody@fsck.com Thu Dec 4 07:36:20 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hB47Y2nE066844 - for ; Thu, 4 Dec 2003 07:36:20 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 04 Dec 2003 07:36:20 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1ARgrA-0005O4-5M; - Wed, 03 Dec 2003 23:56:32 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1ARgrA-0005O4-5M - for pobox@dbi.demon.co.uk; Wed, 03 Dec 2003 23:56:32 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 314AB9A28F - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 188369A287 - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com[63.251.223.170]) - by icicle.pobox.com (Postfix) with SMTP - for ; Wed, 3 Dec 2003 18:56:31 -0500 (EST) -Received: (qmail 3178 invoked by uid 225); 3 Dec 2003 23:56:30 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 3174 invoked by alias); 3 Dec 2003 23:56:29 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Wed, 03 Dec 2003 15:56:18 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 91512114F1; Wed, 3 Dec 2003 18:56:07 -0500 (EST) -Subject: [cpan #4564] Perl DBI bug handling CLOBs -From: "Jay Turner via RT" -Reply-To: bug-DBI@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4564 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: J.Turner@mdl.com -To: "AdminCc of cpan Ticket #4564": ; -Date: Wed, 3 Dec 2003 18:56:07 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -X-Status: A -Content-Length: 1853 -Lines: 46 - - -This message about DBI was sent to you by J.Turner@mdl.com via rt.cpan.org - -Full context and any attached attachments can be found at: - - - -Date: Fri, 28 Feb 2003 16:55:28 -0800 - -It has come to my attention that PERL DBI counts on OCILobGetLength -returning BYTES. It returns CHARACTERS instead, which is the count of -variable-width characters. For multi-byte character sets this results -in errors such as: - -DBD::Oracle::st fetch failed: ORA-03130: the buffer for the next piece -to be fetched is required (DBD ERROR: OCILobGetLength) at id rmsc01.pl -line 294. - -The correct way to read CLOBs is - -1) Query the LOB locator for the CSID and CSFRM (character set ID and -form). A character set >= 800 is a mulitbyte character set and csfrm -<> 0 is CLOB. - -2) Pass the CSID and CSFRM to OCILobRead with AMT=0 and pass your -buffer address and size. - -3) Your callback routine must either be capable of completing the I/O -by allocating additional buffers, or it must notify the caller of -OCILobRead to free the lob locator, since an incomplete read jams the -locator-you can't use it for anything else without finishing the read -(attempts to reuse the locator will result in errors). - -Likewise, with OCILobWrite, you have to pass the CSID and CSFRM, with -AMT=0 and the buffer size in bytes. The callback can just say it has -zero bytes and set piece=OCI_LAST_PIECE. - -You cannot use the return value of OCILobGetLength as the size of the -data that is being read. The actual size of the data is unknown for -variable-width characters, and the buffer has to be big enough to -accomplish the translation, so you can't just double or triple the -return value from OCILobGetLength (I have seen that approach fail). - -You can simulate the effects of a foreign character set by - -$ export NLS_LANG=Japanese - diff --git a/err_lob/err_lobtesttblfail.msg b/err_lob/err_lobtesttblfail.msg deleted file mode 100644 index 1333ee88..00000000 --- a/err_lob/err_lobtesttblfail.msg +++ /dev/null @@ -1,208 +0,0 @@ -From SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 15:22:22 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RELAAO018624 - for ; Wed, 27 Oct 2004 15:22:22 +0100 (BST) - (envelope-from SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 15:22:22 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMiQ8-0000Eo-FG; - Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMiQ8-0000Eo-FG - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMiQ8-0006dS-9n - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B3BB911C325; - Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9947911C2CE - for ; Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Received-SPF: pass (icicle.pobox.com: domain of dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by icicle.pobox.com (Postfix) with SMTP id 5033611C34F - for ; Wed, 27 Oct 2004 03:39:46 -0400 (EDT) -Received: (qmail 12004 invoked by uid 514); 27 Oct 2004 07:39:43 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 11995 invoked from network); 27 Oct 2004 07:39:43 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 07:39:43 -0000 -Received: (qmail 13565 invoked by uid 225); 27 Oct 2004 07:39:43 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 13560 invoked by alias); 27 Oct 2004 07:39:42 -0000 -X-Spam-Status: No, hits=-3.7 required=8.0 - tests=BAYES_00,LARGE_HEX -X-Spam-Check-By: la.mx.develooper.com -Received: from smtp-vbr15.xs4all.nl (HELO smtp-vbr15.xs4all.nl) (194.109.24.35) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 00:39:40 -0700 -Received: from [127.0.0.1] (procura.xs4all.nl [213.84.163.145]) - by smtp-vbr15.xs4all.nl (8.12.11/8.12.11) with ESMTP id i9R7dWHI013040; - Wed, 27 Oct 2004 09:39:34 +0200 (CEST) - (envelope-from h.m.brand@hccnet.nl) -Date: Wed, 27 Oct 2004 09:39:33 +0200 -From: "H.Merijn Brand" -To: Tim Bunce -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Cc: DBI developers -In-Reply-To: <20041022213625.GA22377@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> -Message-Id: <20041027093516.D001.H.M.BRAND@hccnet.nl> -MIME-Version: 1.0 -Content-Type: text/plain; charset="US-ASCII" -X-Mailer: Becky! ver. 2.11.02 [en] -X-Virus-Scanned: by XS4ALL Virus Scanner -X-Virus-Checked: Checked -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i9RELAAO018624 -Status: RO -X-Status: A -Content-Length: 7175 -Lines: 134 - -On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> size: 235224 bytes -> md5: 9711550ed0ebfc743920a6a357ed717c - -I know you can't blame the test for not being able to create a table for the -reason this failure shows, but there might be a more user-friendly way to fail ... - -I'll report back when the DBA has fixed the tablespace - -HP-UX 11.11/64 (11i) + Oracle-9.2.0/64 + perl-5.8.5-dor/64 - -PERL_DL_NONLAZY=1 /pro/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, -'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............ok -t/15nls.................ok -t/20select..............ok -t/21nchar............... Database and client versions and character sets: -Database 9.2.0.1.0 CHAR set is US7ASCII (Non-Unicode), NCHAR set is AL16UTF16 ( -nicode) -Client 9.2.0.1 NLS_LANG is '', NLS_NCHAR is '' -t/21nchar...............ok -t/22nchar_al32utf8......ok -t/22nchar_utf8..........ok -t/23wide_db.............skipped - all skipped: Database character set is not Unicode -t/23wide_db_8bit........skipped - all skipped: Database character set is not Unicode -t/23wide_db_al32utf8....skipped - all skipped: Database character set is not Unicode -t/24implicit_utf8.......ok -t/25plsql...............ok -t/30long................ok 188/470DBD::Oracle::db do failed: ORA-03237: Initial -Extent of specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: -OCIStmtExecute) [for Statement "create table dbd_ora__drop_me ( idx integer, ln - NCLOB, dt date )"] at t/nchar_test_lib.pl line 356. -t/30long................ok 189/470DBD::Oracle::st execute failed: ORA-00942: ta -le or view does not exist (DBD ERROR: error possibly near <*> indicator at char -12 in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statem -nt "insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1= -0, :p2='0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X...'] at t/30long.t line 153. -# Failed test (t/30long.t at line 153) -t/30long................NOK 190DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=41, -:p2='12345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -...'] at t/30long.t line 154. -# Failed test (t/30long.t at line 154) -t/30long................NOK 191DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=42, -:p2='2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -...'] at t/30long.t line 155. -t/30long................NOK 192# Failed test (t/30long.t at line 155) -DBD::Oracle::st execute failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 12 in 'insert into <*>dbd_ora__dr -p_me values (:p1, :p2, SYSDATE)') [for Statement "insert into dbd_ora__drop_me -alues (?, ?, SYSDATE)" with ParamValues: :p1=43, :p2=undef] at t/30long.t line -56. -# Failed test (t/30long.t at line 156) -t/30long................NOK 193DBD::Oracle::db prepare failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 14 -in 'select * from <*>dbd_ora__drop_me order by idx') [for Statement "select * f -om dbd_ora__drop_me order by idx"] at t/30long.t line 170. -# Failed test (t/30long.t at line 170) -Can't call method "trace" on an undefined value at t/30long.t line 171. -t/30long................NOK 194# Looks like you planned 470 tests but only ran -94. -# Looks like your test died just after 194. -t/30long................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 190-470 - Failed 281/470 tests, 40.21% okay (less 122 skipped tests: 67 okay, 14. -6%) -t/31lob.................DBD::Oracle::db do failed: ORA-03237: Initial Extent of -specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: OCIStmtEx -cute) [for Statement " - CREATE TABLE dbd_ora__drop_me ( - id INTEGER NOT NULL, - data BLOB - ) - "] at t/31lob.t line 21. -DBD::Oracle::db do failed: ORA-00942: table or view does not exist (DBD ERROR: -rror possibly near <*> indicator at char 12 in 'INSERT INTO <*>dbd_ora__drop_me -(id,data) VALUES (1, EMPTY_BLOB())') [for Statement "INSERT INTO dbd_ora__drop_ -e (id,data) VALUES (1, EMPTY_BLOB())"] at t/31lob.t line 31. -DBD::Oracle::db prepare failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 17 in 'SELECT data FROM <*>dbd_or -__drop_me WHERE id = :p1') [for Statement "SELECT data FROM dbd_ora__drop_me WH -RE id = ?"] at t/31lob.t line 34. -Can't call method "bind_param" on an undefined value at t/31lob.t line 36. -# Looks like your test died before it could output anything. -t/31lob.................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-2 - Failed 2/2 tests, 0.00% okay -t/40ph_type.............ok -t/50cursor..............ok -t/60reauth..............ORACLE_USERID_2 not defined. Tests skipped. -skipped - all skipped: no reason given -t/70meta................ok -Failed Test Stat Wstat Total Fail Failed List of Failed -------------------------------------------------------------------------------- -t/30long.t 255 65280 470 557 118.51% 190-470 -t/31lob.t 255 65280 2 4 200.00% 1-2 -4 tests and 122 subtests skipped. -Failed 2/18 test scripts, 88.89% okay. 283/1883 subtests failed, 84.97% okay. -make: *** [test_dynamic] Error 255 - --- -H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/) -using perl-5.6.1, 5.8.0 & 633 on HP-UX 10.20 & 11.00, AIX 4.2, AIX 4.3, - WinNT 4, Win2K pro & WinCE 2.11 often with Tk800.024 &/| DBD-Unify -ftp://ftp.funet.fi/pub/languages/perl/CPAN/authors/id/H/HM/HMBRAND/ - - - - diff --git a/err_lob/err_nclob_form.msg b/err_lob/err_nclob_form.msg deleted file mode 100644 index 05587693..00000000 --- a/err_lob/err_nclob_form.msg +++ /dev/null @@ -1,189 +0,0 @@ -From dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org Tue Jul 22 07:40:59 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6M6UUD7096422 - for ; Tue, 22 Jul 2003 07:40:58 +0100 (BST) - (envelope-from dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 22 Jul 2003 07:40:58 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058814697:11:26523:33; Mon, 21 Jul 2003 19:11:37 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1126786; 21 Jul 2003 19:11 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E855B21C37F - for ; Mon, 21 Jul 2003 15:11:18 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 9010121C236 - for ; Mon, 21 Jul 2003 15:11:17 -0400 (EDT) -Received: (qmail 66848 invoked by uid 1005); 21 Jul 2003 19:11:15 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 66832 invoked by uid 76); 21 Jul 2003 19:11:15 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 21 Jul 2003 12:11:15 -0700 -Received: (qmail 559 invoked by uid 225); 21 Jul 2003 19:11:08 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 552 invoked by uid 507); 21 Jul 2003 19:11:07 -0000 -Received-SPF: unknown -Received: from sneakemail.com (HELO monkey.sneakemail.com) (207.106.87.13) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Mon, 21 Jul 2003 12:11:03 -0700 -Received: (qmail 22505 invoked by uid 501); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #3); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #2); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #1); 21 Jul 2003 19:10:57 -0000 -Date: Mon, 21 Jul 2003 21:10:53 +0200 -From: "Wolfgang Weisselberg" -To: dbi-users@perl.org -Subject: DBD::Oracle and unicode-NCLOBs leads to ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) -Message-ID: <13502-46198@sneakemail.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.6 required=7.0 tests=CARRIAGE_RETURNS,FROM_ENDS_IN_NUMS,FROM_HAS_MIXED_NUMS,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_MUTT version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 6055 -Lines: 132 - -Hello all! - -Even after extensive googling and looking through the docs I fail -to fetch NCLOBs from an Oracle 9.2i database where the national -character set is unicode. - -I believe it has been done before, but I could not find anything ... -I would be grateful for any pointers. - - -NCLOBs work like CLOBs when the national character set is not -unicode, even with the old DBI 1.21 and DBD::Oracle 1.12 on an -Oracle 8 client. NVarchar2 and NChar work OK even with unicode. - -Setting NSL_LANG to AMERICAN_AMERICA.UTF8 or .AL32UTF8 does not -help, as I suspected. - -I tried using Oracle 9.2i (the DB is using 9.2i) on a Debian -Linux box. I upgraded DBI to 1.37 and DBD::Oracle to 1.14 (the -newest versions according to CPAN). I got zero errors on make -test with both. Perl is Debian's normal "perl5 (revision 5.0 -version 6 subversion 1)". - -A simple - select memo from unicode_test -(memo being the NCLOB field) fails (again, only with the national -charset being unicode). - -The relevant code snippet (RaiseError being set, of course): - -| $| = 1; -| print "DBI: $DBI::VERSION\n", -| "DBD::Oracle $DBD::Oracle::VERSION\n"; -| my $sth = $dbh->prepare("select memo from unicode_test"); -| $sth->execute(); -| -| while ( my ($memo) = $sth->fetchrow_array() ) { -| print Dumper $memo; -| } -| exit; - - -The output: - -| DBI: 1.37 -| DBD::Oracle 1.14 -| $VAR1 = ''; -| $VAR1 = ''; -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. - - - -Running with tracelevel 3: - [...] -| dbd_st_prepare'd sql SELECT -| dbd_describe SELECT (EXPLICIT, lb 99999999)... -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_execute SELECT (out0, lob0)... -| dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -| <- execute= '0E0' at nclobtest.pl line 79 via nclobtest.pl line 60 -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -| 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x82f8e28)~INNER 'ParamValues') -| error: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| 1 <- FETCH= HASH(0x831661c)0keys at nclobtest.pl line 81 via nclobtest.pl line 60 -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. - - - -Tracelevel 9 (yes, it's a bit verbose :-/ ) - -[...] -| OCIDescriptorAlloc(0x831c058,0x8395228,OCI_DTYPE_LOB,0,0) -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| OCIAttrSet(0x8335b34,OCI_HTYPE_STMT,0xbffff30c,4,11,0x832d5a4)=SUCCESS -| OCIDefineByPos(0x8335b34,0x8395224,0x832d5a4,1,0x8395228,-1,112,0x83414e0,0x83414f0,0x8341500,0)=SUCCESS -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -[...] -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| 0 (rc=0): '' -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead(0x832d530,0x832d5a4,0x832c69c,0xbffff318,1,0x8394da0,24,(nil),(nil),0,1)=ERROR -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| OCIErrorGet(0x832d5a4,1,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=SUCCESS -| OCIErrorGet after OCILobRead (er1:ok): -1, 24806: ORA-24806: LOB form mismatch -| -| OCIErrorGet(0x832d5a4,2,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=NO_DATA -| 0 (rc=0): undef -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -[gets and prints error message] - - -Any ideas anyone? - --Wolfgang - diff --git a/err_lob/err_nulllobsegv.msg b/err_lob/err_nulllobsegv.msg deleted file mode 100644 index 6de3c99b..00000000 --- a/err_lob/err_nulllobsegv.msg +++ /dev/null @@ -1,93 +0,0 @@ -From dbi-users-return-1743-Tim.Bunce=ig.co.uk@perl.org Wed Apr 11 04:00:48 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id EAA17912; Wed, 11 Apr 2001 04:00:48 +0100 (BST) -Received: from 194.217.242.36 by oink with SMTP (PP) id <02579-1@oink>; - Sat, 11 Apr 1970 04:00:28 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 986956750:10:04398:0; Wed, 11 Apr 2001 02:39:10 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-1.mail.demon.net - id aa1106187; 11 Apr 2001 2:39 GMT -Received: (qmail 32618 invoked by uid 508); 11 Apr 2001 02:39:06 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 32603 invoked from network); 11 Apr 2001 02:39:05 -0000 -Received: from owns.warpcore.org (216.81.249.18) by tmtowtdi.perl.org with SMTP; - 11 Apr 2001 02:39:05 -0000 -Received: (from thebrain@localhost) by owns.warpcore.org (8.11.1/8.11.1) - id f3B2cxH06298 for dbi-users@perl.org; - Tue, 10 Apr 2001 21:38:59 -0500 -Date: Tue, 10 Apr 2001 21:38:59 -0500 -From: Stephen Clouse -To: dbi-users@perl.org -Subject: Bizarre DBD::Oracle Segfault -Message-ID: <20010410213859.B2766@owns.warpcore.org> -Mail-Followup-To: dbi-users@perl.org -Mime-Version: 1.0 -Content-Type: text/plain -Content-Disposition: inline; filename="msg.pgp" -User-Agent: Mutt/1.2.5i -Status: RO -Content-Length: 1918 -Lines: 54 - ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -I sent an email to the dbi-users list about a number of DBD::Oracle CLOB -handling problems waaaaaaaaaaaaaaay back (end of January or so) that today -someone dug up and inquired if I had ever found fixes for what I had pointed -out. - -The problems outlined that day turned out to be the test script itself, which -was doing so much bizarre stuff on one statement that DBD::Oracle just went to -sleep instead (and so was the actual program that instigated the writing of the -test script). - -Well, all but one problem was the script. This, the most serious one, continues -to linger: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',undef); - -On Linux, DBI 1.15, Oracle 8.1.6, and DBD::Oracle 1.06, this segfaults on the -execute. Unfortunately this manifests itself too deep in Oracle for me to -debug. - -The bizarre part is, either of the two snippets below will work: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',''); -$st->execute('B','B',undef); - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',$lobvalue); -$st->execute('B','B',undef); - -It's only when binding undef as the LOB value in the very first execute of a -statement that the segfault occurs. At any other time, it's kosher. That -qualifies as bizarre in my book. - -Your guess is better than mine. - -- -- -Stephen Clouse -Senior Programmer, IQ Coordinator Project Lead -The IQ Group, Inc. - ------BEGIN PGP SIGNATURE----- -Version: PGP 6.5.8 - -iQA+AwUBOtPDwgOGqGs0PadnEQLmtgCeJHTStLu8Q8oFb9UQ4995f8vhZH8Al1p6 -RD5m0FEJH2tQiY0+b6542mQ= -=L0M+ ------END PGP SIGNATURE----- - diff --git a/err_lob/err_tmplobfree.msg b/err_lob/err_tmplobfree.msg deleted file mode 100644 index 0ec8f940..00000000 --- a/err_lob/err_tmplobfree.msg +++ /dev/null @@ -1,537 +0,0 @@ -From SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com Wed Aug 25 17:53:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PGpkpQ033405 - for ; Wed, 25 Aug 2004 17:53:57 +0100 (BST) - (envelope-from SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 17:53:57 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Bzyve-0007kY-Gp; - Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Bzyve-0007kY-Gp - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Bzyvd-0000zb-Lg - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id AA6D8B0635; - Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 9B2A1B0BB0 - for ; Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -Received: from natnoddy.rzone.de (natnoddy.rzone.de [81.169.145.166]) - by lime.pobox.com (Postfix) with ESMTP id 2AAB1B0635 - for ; Wed, 25 Aug 2004 10:39:06 -0400 (EDT) -Received: from genericom.de (pD95195AC.dip.t-dialin.net [217.81.149.172]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7PEc05w018990 - for ; Wed, 25 Aug 2004 16:38:01 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412CA445.FC2F9EF2@genericom.de> -Date: Wed, 25 Aug 2004 16:37:57 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim.Bunce@pobox.com -Subject: DBD::Oracle: Freeing a temporary blob -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms4BC2D4519D41A502BB06559C" -Status: RO -X-Status: A -Content-Length: 4985 -Lines: 122 - -This is a cryptographically signed message in MIME format. - ---------------ms4BC2D4519D41A502BB06559C -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Dear Tim, - -first, I would really like to thank you for the great work you have done -with your DBI/DBD work. We are using it extensively in several projects -and we are highly pleased. - -Unfortunately I have now encountered a problem we need to fix urgently, -since our customer's production is seriously affected. - -We tried for many days to find a solution (google, newsgroups, -trial-and-error...), without luck. So my last chance is to contact you -directly, although I assume you have a lot work yourself. - ---- - -The problem: - -Our database contains a stored function "ReadUnitBlob()" that returns a -temporary blob: - -function ReadUnitBlob(UnitID_IN in integer) return blob -is -... -begin - ... - dbms_lob.createtemporary(retBlob, false, dbms_lob.call); - dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); - ... - return retBlob; -end; - -We call this function in Perl in a big loop to fetch a lot of blobs (~ -100000) using something like: - -my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -ora_auto_lob => 0 }); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); -my ($loc) = $sth->fetchrow_array(); -$sth->finish(); -... -while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) - ... - -Although this works, it has a big disadvantage: Oracle does not -automaticaly free the temporary blob, so it shortly runs out of temp. -space. (confirmed with "select * from v$temporary_lobs"). - -Acording to the Oracle docs this can be we solved by implicitly freeing -the temp. blob, e.g. by calling the PLSQL method -"dbms_lob.freetemporary()". I tried differnt ways to do this with -DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -locator from the my stored procedure and to pass it to a call of -"dbms_lob.freetemporary()": - -my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -ora_auto_lob => 0 }); -my $bloc; -$sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); - -obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) - -Can you help me??? Do you know a way how to free the temp. blob using -DBD::Oracle (using Oracle::OCI is not possible, since the customer is -strinctly refusing to install it). - -Otherwise, would it be possible include an additional DBD::Oracle LOB -Locator Method "ora_lob_freetemporary()" that warps -"OCILobFreeTemporary" ? - -Any help is really appreciated! - -Greeting from Germany, - - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------ms4BC2D4519D41A502BB06559C -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjUxNDM3NThaMCMGCSqG -SIb3DQEJBDEWBBS+u38esQAv19TdNkv4jgxlzsRqSzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAJQgoN5ASnyjnB7bgrv1+V7Cu4ULKe1CkHs0IEZaB -KuJcm98U7kskRyC5g6YNopuJxFbr19K3q5rrJGoUscKjiw== ---------------ms4BC2D4519D41A502BB06559C-- - - -From SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com Wed Aug 25 22:47:05 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PLjxpJ037568 - for ; Wed, 25 Aug 2004 22:47:04 +0100 (BST) - (envelope-from SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 22:47:04 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C04j1-00038v-Pz; - Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C04j1-00038v-Pz - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C04j0-00002I-FU - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:30 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AD1815463; - Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 85FFF55E7 - for ; Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Received-SPF: none (gold.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail04.svc.cra.dublin.eircom.net (mail04.svc.cra.dublin.eircom.net [159.134.118.20]) - by gold.pobox.com (Postfix) with SMTP id 14C005463 - for ; Wed, 25 Aug 2004 16:50:25 -0400 (EDT) -Received: (qmail 5678 messnum 5046341 invoked from network[213.94.228.233/unknown]); 25 Aug 2004 20:50:23 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail04.svc.cra.dublin.eircom.net (qp 5678) with SMTP; 25 Aug 2004 20:50:23 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PKsrof034865; - Wed, 25 Aug 2004 21:54:53 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7PKsqas034864; - Wed, 25 Aug 2004 21:54:52 +0100 (BST) -Date: Wed, 25 Aug 2004 21:54:52 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim.Bunce@pobox.com -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040825205452.GC34655@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412CA445.FC2F9EF2@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 4674 -Lines: 124 - -On Wed, Aug 25, 2004 at 04:37:57PM +0200, Philipp Lang wrote: -> Dear Tim, -> -> first, I would really like to thank you for the great work you have done -> with your DBI/DBD work. We are using it extensively in several projects -> and we are highly pleased. - -Thanks Philipp! - -> Unfortunately I have now encountered a problem we need to fix urgently, -> since our customer's production is seriously affected. -> -> We tried for many days to find a solution (google, newsgroups, -> trial-and-error...), without luck. So my last chance is to contact you -> directly, although I assume you have a lot work yourself. - -I am very busy and what little spare time I have for DBD::Oracle -is going into trying to get 1.16 released (which is proving to be -hard as we're tripping over Oracle bugs when an Oracle 8 client -talks to an Oracle 9+ server.) It's a major release that will help -many people so I need to give that priority. - -Separately I am exploring ways to fund DBI and DBD::Oracle development -so I can devote more time to it. There's is much that needs to be -done and much more that could be done beyond that. - -The Perl Foundation (TPF) have setup a way for people and companies -to make donations for DBI development [as yet unannounced so please -keep to yourself]. A note on the contribution could indicate that the -donor would like it used for a particular purpose, such as DBD::Oracle. - -Anyway, to cut a long story short, it would be much easier to devote -time to this if it could be funded in some way. - -I think the TPF setup is working so it could be done that way. -Alternatively you could contract me to do the work for you. -That would be quicker and simpler for you as TPF's non-profit -status doesn't make a difference to European donors. - -My standard daily rate for add-hoc consulting is 1600 Euro. -I'd expect to be able to sort this out inside a day, and prefer -fixed-price quotes anyway, so would 1600 Euro be okay? - -Of course, if you feel your company would like to either -make a general contribution to DBI/DBD::Oracle development beyond -that, or to fund the development of specific functionality that -would be of extra value to you then I'd be happy to talk about that. - -I hate asking for money, and would much rather dig into the code and -reply with a patch, but it's just not practical for me now. Sorry. - -Tim. - -> --- -> -> The problem: -> -> Our database contains a stored function "ReadUnitBlob()" that returns a -> temporary blob: -> -> function ReadUnitBlob(UnitID_IN in integer) return blob -> is -> ... -> begin -> ... -> dbms_lob.createtemporary(retBlob, false, dbms_lob.call); -> dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); -> ... -> return retBlob; -> end; -> -> We call this function in Perl in a big loop to fetch a lot of blobs (~ -> 100000) using something like: -> -> my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -> ora_auto_lob => 0 }); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> my ($loc) = $sth->fetchrow_array(); -> $sth->finish(); -> ... -> while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) -> ... -> -> Although this works, it has a big disadvantage: Oracle does not -> automaticaly free the temporary blob, so it shortly runs out of temp. -> space. (confirmed with "select * from v$temporary_lobs"). -> -> Acording to the Oracle docs this can be we solved by implicitly freeing -> the temp. blob, e.g. by calling the PLSQL method -> "dbms_lob.freetemporary()". I tried differnt ways to do this with -> DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -> locator from the my stored procedure and to pass it to a call of -> "dbms_lob.freetemporary()": -> -> my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -> ora_auto_lob => 0 }); -> my $bloc; -> $sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> -> obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) -> -> Can you help me??? Do you know a way how to free the temp. blob using -> DBD::Oracle (using Oracle::OCI is not possible, since the customer is -> strinctly refusing to install it). -> -> Otherwise, would it be possible include an additional DBD::Oracle LOB -> Locator Method "ora_lob_freetemporary()" that warps -> "OCILobFreeTemporary" ? -> -> Any help is really appreciated! -> -> Greeting from Germany, -> -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - -From SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com Thu Aug 26 14:06:45 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QD6Som051890 - for ; Thu, 26 Aug 2004 14:06:45 +0100 (BST) - (envelope-from SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 14:06:45 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0HX2-0003PB-Sd; - Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0HX2-0003PB-Sd - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0HX2-0003BR-F8 - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id DC4BFB0D27; - Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id CE95AB0D7D - for ; Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 81.169.145.165(natsmtp00.rzone.de) -Received: from natsmtp00.rzone.de (natsmtp00.rzone.de [81.169.145.165]) - by lime.pobox.com (Postfix) with ESMTP id 71107B0D27 - for ; Thu, 26 Aug 2004 06:30:56 -0400 (EDT) -Received: from genericom.de (pD9E61E09.dip.t-dialin.net [217.230.30.9]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7QAUoTY009695 - for ; Thu, 26 Aug 2004 12:30:51 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412DBBD7.2C124831@genericom.de> -Date: Thu, 26 Aug 2004 12:30:47 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------msB92907D67E7D4C0121D50420" -Status: O -X-Status: A -Content-Length: 3040 -Lines: 58 - -This is a cryptographically signed message in MIME format. - ---------------msB92907D67E7D4C0121D50420 -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Tim Bunce wrote: -> -> I hate asking for money, and would much rather dig into the code and -> reply with a patch, but it's just not practical for me now. Sorry. - -Thanks for your quick reply. I can fully understand your position in -this issue. We will need to submit this issue to our customer, and -eventually it will be their decision, since a) the problem technically -originates in external components -and b) our work is payed on a time and material basis. - -Thanks again, - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------msB92907D67E7D4C0121D50420 -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjYxMDMwNDhaMCMGCSqG -SIb3DQEJBDEWBBQbWUdl+peoD/lHpzCOnuQfzAsbJzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAXzFame8ymLqgf+7nZ4V7L9e9J+aG6z5ipa+iv76v -EFAg5QObdHdvTnq5QEAjEnLKgeUGvdgpS6PA0h+beEIeIA== ---------------msB92907D67E7D4C0121D50420-- - - -From SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com Thu Aug 26 16:42:55 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QFgKp1054926 - for ; Thu, 26 Aug 2004 16:42:55 +0100 (BST) - (envelope-from SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 16:42:55 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0L1E-0005sL-5Z; - Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0L1E-0005sL-5Z - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0L1E-0001t1-Cm - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 541E8AFAD6; - Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 1C39FB0747 - for ; Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail01.svc.cra.dublin.eircom.net (mail01.svc.cra.dublin.eircom.net [159.134.118.17]) - by lime.pobox.com (Postfix) with SMTP id BFBB5AFAD6 - for ; Thu, 26 Aug 2004 10:14:19 -0400 (EDT) -Received: (qmail 12246 messnum 7731352 invoked from network[213.94.228.233/unknown]); 26 Aug 2004 14:14:17 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail01.svc.cra.dublin.eircom.net (qp 12246) with SMTP; 26 Aug 2004 14:14:17 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QEItof052863; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7QEItr3052862; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) -Date: Thu, 26 Aug 2004 15:18:55 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040826141855.GC52359@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> <412DBBD7.2C124831@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412DBBD7.2C124831@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 926 -Lines: 25 - -Okay. Thanks. Let me know how it turns out. - -Tim. - -On Thu, Aug 26, 2004 at 12:30:47PM +0200, Philipp Lang wrote: -> Tim Bunce wrote: -> > -> > I hate asking for money, and would much rather dig into the code and -> > reply with a patch, but it's just not practical for me now. Sorry. -> -> Thanks for your quick reply. I can fully understand your position in -> this issue. We will need to submit this issue to our customer, and -> eventually it will be their decision, since a) the problem technically -> originates in external components -> and b) our work is payed on a time and material basis. -> -> Thanks again, -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - diff --git a/err_unicode/err_char.msg b/err_unicode/err_char.msg deleted file mode 100644 index d2a7a4a3..00000000 --- a/err_unicode/err_char.msg +++ /dev/null @@ -1,129 +0,0 @@ -From dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org Fri May 31 15:39:50 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g4VEdno73229 - for ; Fri, 31 May 2002 15:39:49 +0100 (BST) - (envelope-from dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 31 May 2002 15:39:49 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1022854157:20:06570:1; Fri, 31 May 2002 14:09:17 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2005972; 31 May 2002 14:08 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 210F42BF43 - for ; Fri, 31 May 2002 10:08:39 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (unknown [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 8D88B2BF11 - for ; Fri, 31 May 2002 10:08:38 -0400 (EDT) -Received: (qmail 47355 invoked by uid 1005); 31 May 2002 14:07:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 47340 invoked by uid 76); 31 May 2002 14:07:41 -0000 -Received: from wsrgeh.wsr.ac.at (HELO wsrgeh.wsr.ac.at) (143.130.16.2) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Fri May 31 14:07:41 2002 -0000 -Received: from dialog.wsr.ac.at (dialog.wsr.ac.at [143.130.50.66]) - by wsrgeh.wsr.ac.at (8.11.6/8.11.6) with ESMTP id g4VE8Or11772 - for ; Fri, 31 May 2002 16:08:24 +0200 -Received: (from hjp@localhost) - by dialog.wsr.ac.at (8.11.6/8.11.6) id g4VE8Nf12538 - for dbi-users@perl.org; Fri, 31 May 2002 16:08:23 +0200 -Date: Fri, 31 May 2002 16:08:23 +0200 -From: "Peter J. Holzer" -To: dbi-users@perl.org -Subject: Re: Insert a blank value into Oracle -Message-ID: <20020531160823.F28779@wsr.ac.at> -Mail-Followup-To: "Peter J. Holzer" , - dbi-users@perl.org -References: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw> -Mime-Version: 1.0 -Content-Type: multipart/signed; micalg=pgp-md5; - protocol="application/pgp-signature"; boundary="aZoGpuMECXJckB41" -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -In-Reply-To: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw>; from larry_wu@mail.gss.com.tw on Fri, May 31, 2002 at 06:38:45PM +0800 -Status: RO -Content-Length: 2819 -Lines: 74 - ---aZoGpuMECXJckB41 -Content-Type: text/plain; charset=iso-8859-1 -Content-Disposition: inline -Content-Transfer-Encoding: quoted-printable - -On 2002-05-31 18:38:45 +0800, Larry Wu (=A7d=A4l=B7=D3) wrote: -> I encountered a problem to insert a space value ( like ' ' ) into Oracle -> database. -[...] -> Unfortunately, I have a table A contained a not allow null column -> NotNullCol. Now I want to insert a row like below: ->=20 -> $sth =3D $dbh->prepare( qq{ insert into A ( KeyCol, NotNullCol ) -> values (?,?)} ); -> $sth->bind_param(1, '1'); -> $sth->bind_param(2, ' '); -> $sth->execute; ->=20 -> When I executed this file I got an error from Oracle: Can't insert NULL -> value into ( "A"."NotNullCol") (DBD ERROR: OCIStmtExecute). -> I think the space value was truncated in the process. Could any one tell = -me -> how to keep a blank space in my bind_param ? - -use DBD::Oracle qw(:ora_types); -[...] -$sth->bind_param(2, ' ', { ora_type =3D> ORA_CHAR }); - -This is a frequently asked question here. The default type for strings, -ORA_VARCHAR2, strips trailing blanks from strings. A few months ago, -during one of the diskussuions about this feature, Tim said that he -might add a way to change the default in a future version of -DBD::Oracle. If he doesn't, maybe a paragraph like the following should -be added to the doc (not sure where - it fits below "Using DBD::Oracle -with Oracle 8 - Features and Issues" but it isn't Oracle 8 specific): - - =3Dhead2 Inserting strings with trailing spaces - - OCI provides several string types which behave differently. - Unfortunately, none of them can store arbitrary perl strings. - By default, DBD::Oracle binds string variables as ORA_VARCHAR2, - which allows embedded NUL characters but strips trailing spaces. If - you need trailing spaces, but don't need embedded NUL characters, - you can explicetly bind the param to type ORA_CHAR with: - - $sth->bind_param(($field_num, $string_value, - { ora_type =3D> ORA_CHAR }); - - =20 - hp - ---=20 - _ | Peter J. Holzer | Aeltere Sources (also solche, die schon -|_|_) | Sysadmin WSR / LUGA | aelter als 12 Stunden sind) sollte man -| | | hjp@wsr.ac.at | bei Linux generell nicht einsetzen - -__/ | http://www.hjp.at/ | Real Time Linux?? -- Gerhard Schneider - ---aZoGpuMECXJckB41 -Content-Type: application/pgp-signature -Content-Disposition: inline - ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.0.6 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -iQDQAwUBPPeD11LjemazOuKpAQEtNAXUC6rFL0C0v6MNW/K5ggXcSDY7Xvrj6Ed/ -jqjHq2Dx+h2rIMWXCDIGZVphSG74u4FL41AQF/rzGR/e56qH7aAxVmaiLdQE/DRi -zzsoOHoPEg96FhHljDtCZyxHzsz9sRJ1dfW1PELn5r2OSYPPsVzMoeR4iEXnVjvV -ZYH/OfbKRKhysIHjcNYKcyQL87GXdjzCEas3Xz+jyxW2vqzGAwUfTim4ySY9rF37 -c5vopwrTFCsi58r1LccFhQqEfw== -=Xe8d ------END PGP SIGNATURE----- - ---aZoGpuMECXJckB41-- - diff --git a/err_unicode/err_twolongstr.msg b/err_unicode/err_twolongstr.msg deleted file mode 100644 index 5d6c357d..00000000 --- a/err_unicode/err_twolongstr.msg +++ /dev/null @@ -1,1256 +0,0 @@ -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Wed Nov 17 19:08:49 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAHJ8F8P027204 - for ; Wed, 17 Nov 2004 19:08:48 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 17 Nov 2004 19:08:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUUU6-0001mQ-FU; - Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUUU6-0001mQ-FU - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUUU6-0000DF-68 - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9D10A120BFA; - Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 8C898120BEF - for ; Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Received-SPF: none (icicle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by icicle.pobox.com (Postfix) with ESMTP id 362C6120BEC - for ; Wed, 17 Nov 2004 13:24:46 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 9C0CC244379 - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 17196-06 for ; - Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 3131324406F - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 10:22:44 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_006A_01C4CC8F.60A4F6F0" -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117173321.GA6272@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTMy6HoelzJHh9WSPaTpCdfuF1C4gABpsZg -Message-Id: <20041117182444.3131324406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 16865 -Lines: 527 - -This is a multi-part message in MIME format. - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -I did - it is attached to the posting. However, I will attach it again -here. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 9:33 AM -> To: Susan Cassidy -> Cc: dbi-users@perl.org -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> If you can post a small self-contained example that demonstrates -> the problem then I'll take a look. -> -> Tim. -> -> On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > I never got any response to my question about this problem. I -> thought I'd try again. -> > -> > -> > -> > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> 5.8.5. -> > -> > -> > -> > Thanks, -> > -> > Susan -> > -> > -> > -> > --------------------------------------------------------------------- -> ----------------------------------- -> > -> > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > Sent: Friday, November 05, 2004 10:23 AM -> > To: 'dbi-users@perl.org' -> > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for -> > insert into a LONG column' when data not LONG -> > -> > -> > -> > I had an application that was processing a bunch of xml and inserting -> into a table with a bunch of -> > VARCHAR2(4000) columns. -> > -> > -> > -> > A couple of the entries I was processing caused the 'ORA-01461: can -> bind a LONG value only for insert -> > into a LONG column' error. -> > -> > -> > -> > I put checks in for the length of the data, and nothing approached -> 4000 bytes in length. -> > -> > -> > -> > I tracked down some of the entries causing problems, and on certain -> specific data, if 2 columns -> > containing specific data are inserted together, I get this error. If -> only one of the 2 is inserted, I -> > do not get the error, regardless of which one of the two I insert. -> > -> > -> > -> > The lengths of the pieces of data are 1399 and 1397 characters. -> > -> > -> > -> > The data is somewhat odd-looking (we suspect some odd data is in this -> file), but there is no reason for -> > the error message to appear. -> > -> > -> > -> > Trace shows nothing helpful - it thinks the data is the right length. -> > -> > -> > -> > We've successfully inserted thousands of other, similar entries with -> no trouble. -> > -> > -> > -> > The basics are: -> > -> > #create table test_table (item1 varchar2(4000), item2 -> varchar2(4000)); -> > -> > -> > -> > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, ?)"; -> > -> > -> > -> > $sth=$dbh->prepare($statement) || -> > -> > errexit("bad prepare for stmt $statement, error: $DBI::errstr"); -> > -> > my $rc=$sth->execute(@vals) || -> > -> > errexit("can't execute statement: error: $DBI::errstr\n"); -> > -> > -> > -> > Trace shows: -> > -> > -> > -> > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > -> > -> prepare for DBD::Oracle::db (DBI::db=HASH(0x82d4178)~0x82d6580 -> 'INSERT INTO test_table -> > (item1,item2) VALUES (?, ?) -> > -> > ') thr#8148ff0 -> > -> > dbd_preparse scanned 2 distinct placeholders -> > -> > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl line -> 40 -> > -> > -> execute for DBD::Oracle::st (DBI::st=HASH(0x82d6640)~0x8149dcc -> 'version 11.2no service -> > password-encryptionservice -> > -> > udp-small-serversservice tcp-small-servers!hostname router1!!no ip -> domain-lookupip inspect name mysite -> > ftpip inspect name -> > -> > mysite smtpip inspect name mysite tcp!interface Ethernet0ip address -> 10.10.10.2 255.255.255.0ip -> > access-group 101 inip ins -> > -> > pect mysite inip inspect mysite outno keepalive!interface Serial0no -> ip addressencapsulation -> > frame-relay...' 'version 11.2 -> > -> > no service password-encryptionservice udp-small-serversservice tcp- -> small-servers!hostname router1!!no ip -> > domain-lookupip -> > -> > inspect name mysite ftpip inspect name mysite smtpip inspect name -> mysite tcp!interface Ethernet0ip -> > address 10.10.10.2 255 -> > -> > .255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite -> outno keepalive!interface Serial0no -> > ip addressencaps -> > -> > ulation frame-relayn...') thr#8148ff0 -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (type 0) -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (size -> 1399/1400/0, ptype 4, otype 1) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (type 0) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (size -> 1397/1398/0, ptype 4, otype 1) -> > -> > dbd_st_execute INSERT (out0, lob0)... -> > -> > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > <- execute= undef at test_insert_large.pl line 42 -> > -> > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> 'ParamValues') thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line 42 -> > -> > -> $DBI::errstr (&) FETCH from lasth=HASH -> > -> > >> DBD::Oracle::st::errstr -> > -> > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' -> > -> > -- DBI::END -> > -> > -> disconnect_all for DBD::Oracle::dr -> (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > -> > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > -> > Connect done -> > -> > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > -> > Size of vals is 2 -> > -> > val 1 size 1399, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!i -> > -> > nterface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11 -> > -> > .2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 IETF!router eigrp 69network -> > 10.0.0.0no auto-summar -> > -> > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0. -> > -> > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permit icmp 10.10.10.0 -> > 0.0.0.255 anyaccess- -> > -> > list 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-rep -> > -> > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 ad -> > -> > ministratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp a -> > -> > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 0.0.0.255 -> > time-exceededaccess-list 102 permit tcp -> > -> > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > val 2 size 1397, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11. -> > -> > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci 200 -> IETF!router eigrp 69network -> > 10.0.0.0no auto-summary -> > -> > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 0.0.0.0 -> 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0.0 -> > -> > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permiticmp 10.10.10.0 -> > 0.0.0.255 anyaccess-li -> > -> > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess-list -> 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-reply -> > -> > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 admi -> > -> > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp any -> > -> > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 time-exceededaccess-list -> > 102 permit tcp an -> > -> > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > can't execute statement: error: ORA-01461: can bind a LONG value only -> for insert into a LONG column (DBD -> > ERROR: OCIStmtEx -> > -> > ecute) -> > -> > -> > -> > ! -> DESTROY for DBD::Oracle::db (DBI::db=HASH(0x82d6580)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#0) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > -> > -> > I will attach the test program. Somehow it seems to think the -> datatype is LONG instead of VARCHAR. -> > -> > -> > -> > -> > -> > Anyone with ideas? -> > -> > -> > -> > -> > -> > Thanks, -> > -> > Susan -> - - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: application/octet-stream; - name="test_insert_large.pl" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="test_insert_large.pl" - -#!/usr/local/bin/perl -w=0A= -=0A= -use DBI;=0A= -=0A= -our $dbh;=0A= -our $sth;=0A= -=0A= -$dbuser=3D"proj1";=0A= -$dbpasswd=3D"proj1";=0A= -=0A= -$dbserver=3D'oracledev';=0A= -$db_sid=3D'AL32UTF8';=0A= -=0A= -##=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D connect to database = -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=0A= -=0A= -$dbh=3D DBI->connect("dbi:Oracle:host=3D$dbserver;sid=3D$db_sid", = -$dbuser, $dbpasswd,=0A= - {PrintError =3D> 0, AutoCommit =3D> 1}) or=0A= - errexit( "Unable to connect to $dbserver: $DBI::errstr");=0A= -print "Connect done\n";=0A= -=0A= -#create table test_table (item1 varchar2(4000), item2 varchar2(4000));=0A= -=0A= -=0A= -my $statement=3D"INSERT INTO test_table (item1,item2) VALUES (?, ?)";=0A= -print "stmt: $statement\n";=0A= -=0A= -@vals=3D(=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysite inip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permit icmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permiticmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= -);=0A= -=0A= -print "Size of vals is ",scalar @vals,"\n";=0A= -my $z=3D0;=0A= -foreach my $x (@vals) {=0A= - my $len=3Dlength($x);=0A= - print "val ",++$z, " size $len, is: '$x'\n";=0A= -}=0A= -=0A= -DBI->trace(2);=0A= - $sth=3D$dbh->prepare($statement) ||=0A= - errexit("bad prepare for stmt $statement, error: $DBI::errstr");=0A= - my $rc=3D$sth->execute(@vals) ||=0A= - errexit("can't execute statement: error: $DBI::errstr\n");=0A= -=0A= -print "Done\n";=0A= -exit;=0A= -=0A= -=0A= -sub errexit {=0A= - my (@msg)=3D@_;=0A= - print @msg,"\n";=0A= - exit 1;=0A= -}=0A= -=0A= -=0A= -=0A= - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0-- - - -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 00:15:21 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI0FC8G049539 - for ; Thu, 18 Nov 2004 00:15:21 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 00:15:21 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUVdd-0002Nv-CF; - Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUVdd-0002Nv-CF - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CUVdc-0005lu-Rs - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 4A256ADD6F; - Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3D82CADD64 - for ; Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Received-SPF: none (boggle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by boggle.pobox.com (Postfix) with ESMTP id B23D4ADCF6 - for ; Wed, 17 Nov 2004 14:38:15 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 0C9DF24435B - for ; Wed, 17 Nov 2004 11:38:14 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 18475-01 for ; - Wed, 17 Nov 2004 11:38:13 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id ACF0424406F - for ; Wed, 17 Nov 2004 11:38:13 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 11:36:14 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117192902.GA31595@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTM27+9yfJDVs3WQIWAKc6DR3EgdQAAKfgw -Message-Id: <20041117193813.ACF0424406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -X-Status: A -Content-Length: 14671 -Lines: 489 - -NLS_LANG=.UTF8 -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORACLE_HOME=/home/oracle/product/9.2.0 -ORACLE_SID=AL32UTF8 -ORACLE_BASE=/home/oracle - -NLS_NCHAR is not set, because we are not using any NVARCHAR data item, and -haven't needed it. - -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 11:29 AM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > I did - it is attached to the posting. However, I will attach it again -> > here. -> > -> > Thanks, -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 9:33 AM -> > > To: Susan Cassidy -> > > Cc: dbi-users@perl.org -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > If you can post a small self-contained example that demonstrates -> > > the problem then I'll take a look. -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > > > I never got any response to my question about this problem. I -> > > thought I'd try again. -> > > > -> > > > -> > > > -> > > > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> > > 5.8.5. -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > > -> > > > -> > > > -> > > > ----------------------------------------------------------------- -> ---- -> > > ----------------------------------- -> > > > -> > > > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > > > Sent: Friday, November 05, 2004 10:23 AM -> > > > To: 'dbi-users@perl.org' -> > > > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> > > 01461: can bind a LONG value only for -> > > > insert into a LONG column' when data not LONG -> > > > -> > > > -> > > > -> > > > I had an application that was processing a bunch of xml and -> inserting -> > > into a table with a bunch of -> > > > VARCHAR2(4000) columns. -> > > > -> > > > -> > > > -> > > > A couple of the entries I was processing caused the 'ORA-01461: -> can -> > > bind a LONG value only for insert -> > > > into a LONG column' error. -> > > > -> > > > -> > > > -> > > > I put checks in for the length of the data, and nothing -> approached -> > > 4000 bytes in length. -> > > > -> > > > -> > > > -> > > > I tracked down some of the entries causing problems, and on -> certain -> > > specific data, if 2 columns -> > > > containing specific data are inserted together, I get this error. -> If -> > > only one of the 2 is inserted, I -> > > > do not get the error, regardless of which one of the two I -> insert. -> > > > -> > > > -> > > > -> > > > The lengths of the pieces of data are 1399 and 1397 characters. -> > > > -> > > > -> > > > -> > > > The data is somewhat odd-looking (we suspect some odd data is in -> this -> > > file), but there is no reason for -> > > > the error message to appear. -> > > > -> > > > -> > > > -> > > > Trace shows nothing helpful - it thinks the data is the right -> length. -> > > > -> > > > -> > > > -> > > > We've successfully inserted thousands of other, similar entries -> with -> > > no trouble. -> > > > -> > > > -> > > > -> > > > The basics are: -> > > > -> > > > #create table test_table (item1 varchar2(4000), item2 -> > > varchar2(4000)); -> > > > -> > > > -> > > > -> > > > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, -> ?)"; -> > > > -> > > > -> > > > -> > > > $sth=$dbh->prepare($statement) || -> > > > -> > > > errexit("bad prepare for stmt $statement, error: -> $DBI::errstr"); -> > > > -> > > > my $rc=$sth->execute(@vals) || -> > > > -> > > > errexit("can't execute statement: error: $DBI::errstr\n"); -> > > > -> > > > -> > > > -> > > > Trace shows: -> > > > -> > > > -> > > > -> > > > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > > > -> > > > -> prepare for DBD::Oracle::db -> (DBI::db=HASH(0x82d4178)~0x82d6580 -> > > 'INSERT INTO test_table -> > > > (item1,item2) VALUES (?, ?) -> > > > -> > > > ') thr#8148ff0 -> > > > -> > > > dbd_preparse scanned 2 distinct placeholders -> > > > -> > > > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl -> line -> > > 40 -> > > > -> > > > -> execute for DBD::Oracle::st -> (DBI::st=HASH(0x82d6640)~0x8149dcc -> > > 'version 11.2no service -> > > > password-encryptionservice -> > > > -> > > > udp-small-serversservice tcp-small-servers!hostname router1!!no -> ip -> > > domain-lookupip inspect name mysite -> > > > ftpip inspect name -> > > > -> > > > mysite smtpip inspect name mysite tcp!interface Ethernet0ip -> address -> > > 10.10.10.2 255.255.255.0ip -> > > > access-group 101 inip ins -> > > > -> > > > pect mysite inip inspect mysite outno keepalive!interface -> Serial0no -> > > ip addressencapsulation -> > > > frame-relay...' 'version 11.2 -> > > > -> > > > no service password-encryptionservice udp-small-serversservice -> tcp- -> > > small-servers!hostname router1!!no ip -> > > > domain-lookupip -> > > > -> > > > inspect name mysite ftpip inspect name mysite smtpip inspect name -> > > mysite tcp!interface Ethernet0ip -> > > > address 10.10.10.2 255 -> > > > -> > > > .255.255.0ip access-group 101 inip inspect mysiteinip inspect -> mysite -> > > outno keepalive!interface Serial0no -> > > > ip addressencaps -> > > > -> > > > ulation frame-relayn...') thr#8148ff0 -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (type -> 0) -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (size -> > > 1399/1400/0, ptype 4, otype 1) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (type -> 0) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (size -> > > 1397/1398/0, ptype 4, otype 1) -> > > > -> > > > dbd_st_execute INSERT (out0, lob0)... -> > > > -> > > > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > <- execute= undef at test_insert_large.pl line 42 -> > > > -> > > > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> > > 'ParamValues') thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line -> 42 -> > > > -> > > > -> $DBI::errstr (&) FETCH from lasth=HASH -> > > > -> > > > >> DBD::Oracle::st::errstr -> > > > -> > > > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' -> > > > -> > > > -- DBI::END -> > > > -> > > > -> disconnect_all for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > > > -> > > > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > > > -> > > > Connect done -> > > > -> > > > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > > > -> > > > Size of vals is 2 -> > > > -> > > > val 1 size 1399, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!i -> > > > -> > > > nterface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11 -> > > > -> > > > .2 255.255.255.252ip access-group 102 inframe-relay interface- -> dlci -> > > 200 IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summar -> > > > -> > > > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> > > 0.0.0.0 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0. -> > > > -> > > > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permit icmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess- -> > > > -> > > > list 101 deny ip any anyaccess-list 102 permit eigrp any -> anyaccess- -> > > list 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-rep -> > > > -> > > > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 ad -> > > > -> > > > ministratively-prohibitedaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp a -> > > > -> > > > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> > > 10.10.10.0 0.0.0.255 -> > > > time-exceededaccess-list 102 permit tcp -> > > > -> > > > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line -> con -> > > 0line vty 0 4login!end' -> > > > -> > > > val 2 size 1397, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11. -> > > > -> > > > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 -> > > IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summary -> > > > -> > > > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 -> > > 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0.0 -> > > > -> > > > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permiticmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess-li -> > > > -> > > > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list -> > > 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-reply -> > > > -> > > > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 admi -> > > > -> > > > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp any -> > > > -> > > > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 time-exceededaccess-list -> > > > 102 permit tcp an -> > > > -> > > > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> > > 0line vty 0 4login!end' -> > > > -> > > > can't execute statement: error: ORA-01461: can bind a LONG value -> only -> > > for insert into a LONG column (DBD -> > > > ERROR: OCIStmtEx -> > > > -> > > > ecute) -> > > > -> > > > -> > > > -> > > > ! -> DESTROY for DBD::Oracle::db -> (DBI::db=HASH(0x82d6580)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#0) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY for DBD::Oracle::st -> (DBI::st=HASH(0x8149dcc)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > -> > > > -> > > > I will attach the test program. Somehow it seems to think the -> > > datatype is LONG instead of VARCHAR. -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Anyone with ideas? -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > -> > -> - - - -From SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 07:11:03 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI7Ar8G057950 - for ; Thu, 18 Nov 2004 07:11:03 GMT - (envelope-from SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 07:11:03 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUaCR-0002mS-7P; - Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUaCR-0002mS-7P - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUaCQ-0004JQ-R5 - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 17ACAA3F35; - Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from integer (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 04F8DA3EAC - for ; Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Received-SPF: none (integer.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by integer.pobox.com (Postfix) with ESMTP id A9FC6A3F4D - for ; Wed, 17 Nov 2004 19:30:43 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id DEA102441A9 - for ; Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 22204-10 for ; - Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 7AD52244370 - for ; Wed, 17 Nov 2004 16:30:40 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 16:28:41 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041118001712.GB49519@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTNA/o7HZXghXaJRbyz8M5kVQMQmwAAUBjg -Message-Id: <20041118003040.7AD52244370@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 1789 -Lines: 63 - -Hi, - -I set NLS_LANG to .US7ASCII, ran it again, and I get the same error. - -Of course, I could not use that in production. - -The really strange part, to me, was that if I just insert one of the 2 -problematic columns, it worked, but both together failed. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 4:17 PM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> And does the problem go away if NLS_LANG is set to a non-unicode charset? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 11:36:14AM -0800, Susan Cassidy wrote: -> > NLS_LANG=.UTF8 -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORACLE_HOME=/home/oracle/product/9.2.0 -> > ORACLE_SID=AL32UTF8 -> > ORACLE_BASE=/home/oracle -> > -> > NLS_NCHAR is not set, because we are not using any NVARCHAR data item, -> and -> > haven't needed it. -> > -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 11:29 AM -> > > To: Susan Cassidy -> > > Cc: 'Tim Bunce' -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > > > I did - it is attached to the posting. However, I will attach it -> again -> > > > here. -> > > > -> > > > Thanks, -> > > > Susan -> > > > - - diff --git a/err_unsorted/err_etherreal.msg b/err_unsorted/err_etherreal.msg deleted file mode 100644 index 1ad5c78e..00000000 --- a/err_unsorted/err_etherreal.msg +++ /dev/null @@ -1,90 +0,0 @@ -From dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org Tue Apr 30 14:47:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UDliR22576 - for ; Tue, 30 Apr 2002 14:47:44 +0100 (BST) - (envelope-from dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.23] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 14:47:44 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020172466:10:24548:59; Tue, 30 Apr 2002 13:14:26 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1023391; 30 Apr 2002 13:13 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id A94562C075 - for ; Tue, 30 Apr 2002 09:12:33 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id F24B22BFBE - for ; Tue, 30 Apr 2002 09:12:32 -0400 (EDT) -Received: (qmail 36589 invoked by uid 1005); 30 Apr 2002 13:12:28 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 36168 invoked by uid 76); 30 Apr 2002 13:10:41 -0000 -Content-Type: text/plain; - charset="iso-8859-1" -From: Calin Medianu -To: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Date: Tue, 30 Apr 2002 16:04:47 +0300 -X-Mailer: KMail [version 1.3.2] -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> <20020429233138.E16831@dansat.data-plan.com> -In-Reply-To: <20020429233138.E16831@dansat.data-plan.com> -Cc: dbi-users@perl.org -MIME-Version: 1.0 -Message-Id: <20020430131233.F24B22BFBE@dolly1.pobox.com> -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id g3UDliR22576 -Status: RO -X-Status: A -Content-Length: 1213 -Lines: 38 - -[Add note to DBD::Oracle docs about using ethereal to sniff Oracle packets] -[Not sure if this bug got fixed yet. Maybe not.] - -Me again with the slow cursors. - -I modified both queries to only return 10 rows. -I ran a sniffer (ethereal) on the NIC. It is pretty cool, it also decodes TNS. - -when I am using the SQL, it works like this, there are about 7 packets -received by my workstation to set up the session, then all 10 rows are in the -same packet, then there is another packet probably saying goodbye. - -When I am using the REF cursor, each row comes in it's own TNS packet, that -is why it is so slow! - -Any idea how to fix it? - -thanks a lot, - -Calin - -> On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> > Hello, -> > -> > I did the following. Wrote a perl script that retreves -> > data via a straight select from the database. Then I -> > wrote a stored procedure returning a ref cursor open -> > on the same select statement and retrieved the data as -> > well. Using the REF CURSOR/ sotred procedure was about -> > 3 time slower, that is 40 seconds instead of around -> > 10. -> > -> > Is this normal? Is this a problem with oracle or with -> > DBD::Oracle? -> -> DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. -> -> Get a level 3 trace and look for the "dbd_describe'd" line for the -> ref cursor. -> -> Tim. - diff --git a/err_unsorted/err_memleak2.msg b/err_unsorted/err_memleak2.msg deleted file mode 100644 index 97501852..00000000 --- a/err_unsorted/err_memleak2.msg +++ /dev/null @@ -1,476 +0,0 @@ -From mike@boom.net Fri Nov 28 22:23:33 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hASMLLnY018698 - for ; Fri, 28 Nov 2003 22:23:33 GMT - (envelope-from mike@boom.net) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 28 Nov 2003 22:23:33 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1APmgW-0006iM-9g; - Fri, 28 Nov 2003 17:45:40 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1APmgW-0006iM-9g - for pobox@dbi.demon.co.uk; Fri, 28 Nov 2003 17:45:40 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id E82CD95E03 - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B1EE595DFB - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: from abort.boom.net (abort.boom.net[69.36.241.24]) - by icicle.pobox.com (Postfix) with ESMTP - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: by abort.boom.net (Postfix, from userid 530) - id E3C8B8517A; Fri, 28 Nov 2003 09:45:36 -0800 (PST) -Date: Fri, 28 Nov 2003 09:45:36 -0800 -From: Mike Hedlund -To: dbi-users@perl.org -Cc: Tim.Bunce@pobox.com -Subject: Memory leak in DBD::Oracle 1.14 ... ? -Message-ID: <20031128174536.GJ10609@boom.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.5.4i -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id hASMLLnY018698 -Content-Length: 24309 -Lines: 434 - -I've attached a little script which replicates the problem on my machine as well as the build session log for DBD::Oracle 1.14. - -I've tested it using DBI 1.38 and DBI 1.28 with both DBD::Oracle 1.12 and 1.14. - -Regardless of the DBI version, DBD::Oracle 1.14 leaks on my system and DBD::Oracle 1.12 does not. I've noticed the leak when calling connect_cached(), do() (or prepare()/execute()/commit/finish). - --mike - - --------------------- script --------------- -#!/usr/bin/perl -use strict; -use DBI; - -my($dbp) = "dbi:Oracle:host=weirdo.com;port=1521;sid=SID"; -my($dbu) = "username"; -my($dbpass) = "password"; - -while (1) { - my($sth); - my(@row); - my($dbh) = DBI->connect_cached($dbp,$dbu,$dbpass) || die "Couldn't connect to oracle db: $DBI::errstr\n"; - -## -## uncomment these and it just leaks faster. -## -# $sth = $dbh->prepare("SELECT * from FROM_STATS"); -# $sth->execute; -# while(@row = $sth->fetchrow_array) { - ##print "row: @row\n"; -# } -# $sth->finish; -} -exit; ------------------------- end script -------------------- - - ------------- log --------------------------------------- -Script started on Fri 28 Nov 2003 09:11:15 AM PST -[mike@commando DBD-Oracle-1.14]$ setenv ORACLE_HOME /home/orahome -[mike@commando DBD-Oracle-1.14]$ make realclean -rm -f blib/script/ora_explain -rm -rf Oracle.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm ./blib Makefile.aperl blib/arch/auto/DBD/Oracle/extralibs.all perlmain.c tmon.out mon.out so_locations pm_to_blib *.o *.a perl.exe perl perl Oracle.bs Oracle.bso Oracle.def libOracle.def Oracle.exp Oracle.x core core.*perl.*.? *perl.core -mv Makefile Makefile.old > /dev/null 2>&1 -rm -rf blib/lib/auto/DBD/Oracle blib/arch/auto/DBD/Oracle -rm -rf DBD-Oracle-1.14 -rm -f blib/arch/auto/DBD/Oracle/Oracle.so blib/arch/auto/DBD/Oracle/Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.a -rm -f blib/lib/DBD/Oracle.pm blib/arch/auto/DBD/Oracle/dbdimp.h blib/lib/oraperl.ph -rm -f blib/arch/auto/DBD/Oracle/ocitrace.h blib/lib/Oraperl.pm -rm -f blib/arch/auto/DBD/Oracle/Oracle.h blib/arch/auto/DBD/Oracle/mk.pm -rm -f blib/lib/DBD/Oracle/GetInfo.pm -rm -rf Makefile Makefile.old -[mike@commando DBD-Oracle-1.14]$ perl Makefile.PL -v -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI - - Configuring DBD::Oracle ... - ->>> Remember to actually *READ* the README file! - Especially if you have any problems. - -Using Oracle in /home/orahome - -WARNING: could not decode oracle version from -/home/orahome/orainst/inspdver, or /home/orahome/install/unix.rgs -or from ORACLE_HOME path /home/orahome. -Oracle version based logic in Makefile.PL may produce erroneous results. - -Found header files in rdbms/public rdbms/demo. -Found /home/orahome/rdbms/demo/demo_rdbms.mk -Found /home/orahome/otrace/demo/atmoci.mk -Found /home/orahome/precomp/demo/proc/demo_proc.mk -Using /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/lib/env_rdbms.mk -Read a total of 2202 lines from /home/orahome/rdbms/lib/env_rdbms.mk (including inclusions) -Read a total of 2493 lines from /home/orahome/rdbms/demo/demo_rdbms.mk (including inclusions) -Deleted SHELL definition: SHELL=/bin/sh -Deleted LIB_EXT definition: LIB_EXT=a -Deleted OBJ_EXT definition: OBJ_EXT=o -Deleted AR definition: AR=ar -Deleted AS definition: AS=as -Deleted CC definition: CC=cc -Deleted CHMOD definition: CHMOD=chmod -Deleted CPP definition: CPP=cpp -Deleted ECHO definition: ECHO=echo -Deleted LD definition: LD=ld -Deleted PERL definition: PERL=perl -Deleted CFLAGS definition: CFLAGS=$(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ -Deleted OPTIMIZE definition: OPTIMIZE=$(OPTIMIZE3) -Deleted AR definition: AR=/usr/bin/ar -Deleted AS definition: AS=/usr/bin/as -Deleted LD definition: LD=/usr/bin/ld -Deleted CPP definition: CPP=/lib/cpp -Deleted CHMOD definition: CHMOD=/bin/chmod -Deleted ASFLAGS definition: ASFLAGS= -Deleting ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS definition: ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Deleting ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS33 definition: ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Appending '/home/orahome/rdbms/lib/libskgxpd.a /home/orahome/rdbms/lib/libskgxpu.a /home/orahome/rdbms/lib/libskgxpt.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxp9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxp9.a' to LIBS -Appending '/home/orahome/rdbms/lib/libskgxns.a /home/orahome/rdbms/lib/libskgxnd.a /home/orahome/rdbms/lib/libskgxnr.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxn9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxn9.a' to LIBS -Evaluating `cat $(LIBHOME)sysliblist` - expanded `cat /home/orahome/lib/sysliblist` - returned '-ldl -lm -lpthread -lnsl ' - -Attempting to discover Oracle OCI build rules -gcc -c -o DBD_ORA_OBJ.o DBD_ORA_OBJ.c -by executing: (make -f /home/orahome/rdbms/demo/demo_rdbms.mk build ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh' CC=echo OPTIMIZE= CCFLAGS= EXE=DBD_ORA_EXE OBJS=DBD_ORA_OBJ.o) -returned: -[echo -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh `cat /home/orahome/lib/sysliblist` -ldl -lm - -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -reduced to: -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -Oracle oci build command: - + -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - - - -System: perl5.008 linux stripples.devel.redhat.com 2.4.21-1.1931.2.382.entsmp #1 smp wed aug 6 17:18:52 edt 2003 i686 i686 i386 gnulinux -Compiler: gcc -O2 -g -pipe -march=i386 -mcpu=i686 -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -Linker: /usr/bin/ld -Sysliblist: -ldl -lm -lpthread -lnsl -Oracle makefiles would have used these definitions but we override them: - CC: cc - - CFLAGS: $(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) - [$(GFLAG) -O3 $(CDEBUG) $(CCFLAGS) -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -DLINUX -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS $(LPFLAGS) $(USRFLAGS)] - - LDFLAGS: -o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ - [-o $@ -L/home/orahome/rdbms/lib/ -L$(LIBHOME) -L$(LIBHOME)stubs/] - - -Linking with OTHERLDFLAGS = -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - [from 'build' rule] - - -MakeMaker (v6.03) -Checking if your kit is complete... -Looks good - ABSTRACT_FROM => q[Oracle.pm] - AUTHOR => q[Tim Bunce (dbi-users@perl.org)] - DEFINE => q[ -DUTF8_SUPPORT] - DIR => [] - EXE_FILES => [q[ora_explain]] - INC => q[-I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI] - NAME => q[DBD::Oracle] - OBJECT => q[$(O_FILES)] - PREREQ_PM => { DBI=>q[0] } - VERSION_FROM => q[Oracle.pm] - clean => { FILES=>q[Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm] } - dist => { DIST_DEFAULT=>q[clean distcheck disttest ci tardist], COMPRESS=>q[gzip -v9], PREOP=>q[$(MAKE) -f Makefile.old distdir], SUFFIX=>q[gz] } - dynamic_lib => { OTHERLDFLAGS=>q[ -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] } -Using PERL=/usr/bin/perl -LD_RUN_PATH=/home/orahome/lib:/home/orahome/rdbms/lib -Using DBD::Oracle 1.14. -Using DBD::Oracle 1.14. -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -Writing Makefile for DBD::Oracle - -*** If you have problems... - read all the log printed above, and the README and README.help files. - (Of course, you have read README by now anyway, haven't you?) - -[mike@commando DBD-Oracle-1.14]$ make -cp Oracle.pm blib/lib/DBD/Oracle.pm -cp Oracle.h blib/arch/auto/DBD/Oracle/Oracle.h -cp dbdimp.h blib/arch/auto/DBD/Oracle/dbdimp.h -cp oraperl.ph blib/lib/oraperl.ph -cp ocitrace.h blib/arch/auto/DBD/Oracle/ocitrace.h -cp Oraperl.pm blib/lib/Oraperl.pm -cp mk.pm blib/arch/auto/DBD/Oracle/mk.pm -cp lib/DBD/Oracle/GetInfo.pm blib/lib/DBD/Oracle/GetInfo.pm -/usr/bin/perl -p -e "s/~DRIVER~/Oracle/g" /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI/Driver.xst > Oracle.xsi -/usr/bin/perl /usr/lib/perl5/5.8.0/ExtUtils/xsubpp -typemap /usr/lib/perl5/5.8.0/ExtUtils/typemap Oracle.xs > Oracle.xsc && mv Oracle.xsc Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT dbdimp.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci7.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci8.c -Running Mkbootstrap for DBD::Oracle () -chmod 644 Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/home/orahome/lib:/home/orahome/rdbms/lib" gcc -shared -L/usr/local/lib Oracle.o dbdimp.o oci7.o oci8.o -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" blib/script/ora_explain -Manifying blib/man3/DBD::Oracle.3pm -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oraperl.3pm -[mike@commando DBD-Oracle-1.14]$ make test -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/base....... t/base.......ok 1/5 t/base.......ok 2/5 t/base.......ok 3/5 t/base.......ok 4/5 t/base.......ok 5/5 t/base.......ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/reauth.....skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.82 cusr + 0.33 csys = 4.15 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ make test TEST_VERBOSE=1 -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1, 'blib/lib', 'blib/arch')" t/*.t -t/base.......1..5 -ok 1 -ok 2 -ok 3 -ok 4 -ok 5 -ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/reauth.....ORACLE_USERID_2 not defined. -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.85 cusr + 0.32 csys = 4.17 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ perl _V-V -Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: - Platform: - osname=linux, osvers=2.4.21-1.1931.2.382.entsmp, archname=i386-linux-thread-multi - uname='linux str' - config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Dotherlibdirs=/usr/lib/perl5/5.8.0 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr' - hint=recommended, useposix=true, d_sigaction=define - usethreads=define use5005threads=undef' - useithreads=define usemultiplicity= - useperlio= d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=un uselongdouble= - usemymalloc=, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', - optimize='', - cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm' - ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)', gccosandvers='' -gccversion='3.2.2 200302' - intsize=r, longsize=r, ptrsize=5, doublesize=8, byteorder=1234 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - ivtype='long' -k', ivsize=4' -ivtype='l, nvtype='double' -o_nonbl', nvsize=, Off_t='', lseeksize=8 - alignbytes=4, prototype=define - Linker and Libraries: - ld='gcc' -l', ldflags =' -L/u' - libpth=/usr/local/lib /lib /usr/lib - libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil - perllibs= - libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libper - gnulibc_version='2.3.2' - Dynamic Linking: - dlsrc=dl_dlopen.xs, dlext=so', d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE' - cccdlflags='-fPIC' -ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5', lddlflags='s Unicode/Normalize XS/A' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING MULTIPLICITY USE_ITHREADS USE_LARGE_FILES PERL_IMPLICIT_CONTEXT - Locally applied patches: - MAINT18379 - Built under linux - Compiled at Aug 13 2003 11:47:58 - @INC: - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/site_perl/5.8.0 - /usr/lib/perl5/site_perl - /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/vendor_perl/5.8.0 - /usr/lib/perl5/vendor_perl - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - . -[mike@commando DBD-Oracle-1.14]$ ^D -Script done on Fri 28 Nov 2003 09:16:43 AM PST ------------- end log ----------------------------------- - - diff --git a/err_unsorted/err_multiora.msg b/err_unsorted/err_multiora.msg deleted file mode 100644 index 9f7bcf6c..00000000 --- a/err_unsorted/err_multiora.msg +++ /dev/null @@ -1,470 +0,0 @@ -From dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org Mon Jan 5 10:12:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05ACYn1063537 - for ; Mon, 5 Jan 2004 10:12:58 GMT - (envelope-from dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 10:12:58 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdQXY-0007a7-IO; - Mon, 05 Jan 2004 09:18:18 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdQXY-0007a7-IO - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 08:56:48 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id C92F0282F - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id B344B2B84 - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: (qmail 58691 invoked by uid 1005); 5 Jan 2004 08:56:38 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 58674 invoked by uid 76); 5 Jan 2004 08:56:38 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 05 Jan 2004 00:56:38 -0800 -Received: (qmail 17937 invoked by uid 225); 5 Jan 2004 08:56:36 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 17930 invoked by uid 507); 5 Jan 2004 08:56:36 -0000 -Received: from stone.sifira.dk (HELO mail.int.sifira.dk) (217.157.24.2) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Mon, 05 Jan 2004 00:56:05 -0800 -Received: from ash.int.sifira.dk (ash.int.sifira.dk [192.168.1.7]) by mail.int.sifira.dk (Postfix) with ESMTP id F127674F58; Mon, 5 Jan 2004 09:55:58 +0100 (MET) -Sender: kn@sifira.dk -To: "Anniballi, Fran" -Cc: -Subject: Re: Help - multiple Oracle versions -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -From: Kristian Nielsen -Date: 05 Jan 2004 09:55:59 +0100 -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Message-ID: <7sllomsrj4.fsf@ash.int.sifira.dk> -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-2.5 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_GNUS_UA version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1223 -Lines: 40 - -[Add notes to docs covering what's in this thread] - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - -From dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org Mon Jan 5 14:47:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05Ejvo1064760 - for ; Mon, 5 Jan 2004 14:47:30 GMT - (envelope-from dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 14:47:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdVCS-0004w0-Is; - Mon, 05 Jan 2004 13:55:22 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdVCS-0004w0-Is - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 13:55:21 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 548DE2C87 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 417692C81 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 08:55:19 -0500 (EST) -Received: (qmail 91728 invoked by uid 1005); 5 Jan 2004 13:55:17 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 48614 invoked by uid 76); 5 Jan 2004 12:24:01 -0000 -Delivered-To: dbi-users@perl.org -X-MimeOLE: Produced By Microsoft Exchange V6.0.6487.1 -content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; charset="iso-8859-1" -Subject: RE: Help - multiple Oracle versions -Date: Mon, 5 Jan 2004 07:23:23 -0500 -Message-ID: <6B003D25ADBDE347B5542AFE6A55B42E04537A09@tayexc13.americas.cpqcorp.net> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Help - multiple Oracle versions -Thread-Index: AcPTac0nADA1C8LsTdSTxpcvyeSNCgAHQWGQ -From: "Anniballi, Fran" -To: -Cc: -X-OriginalArrivalTime: 05 Jan 2004 12:23:24.0525 (UTC) FILETIME=[B6F761D0:01C3D386] -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.3 required=7.0 tests=CARRIAGE_RETURNS,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i05Ejvo1064760 -Status: RO -Content-Length: 1465 -Lines: 52 - -Thanks. Looks like this is what I'll need. - ------Original Message----- -From: kn@sifira.dk [mailto:kn@sifira.dk] -Sent: Monday, January 05, 2004 3:56 AM -To: Anniballi, Fran -Cc: dbi-users@perl.org -Subject: Re: Help - multiple Oracle versions - - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - - -From dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org Tue Jan 6 17:00:29 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i06GxrnC075337 - for ; Tue, 6 Jan 2004 17:00:29 GMT - (envelope-from dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 06 Jan 2004 17:00:29 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Adu0c-0004RW-9d; - Tue, 06 Jan 2004 16:24:47 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Adu0c-0004RW-9d - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 16:24:47 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 21A79495C - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 08B12494B - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 6 Jan 2004 11:24:45 -0500 (EST) -Received: (qmail 25114 invoked by uid 1005); 6 Jan 2004 16:24:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 25095 invoked by uid 76); 6 Jan 2004 16:24:42 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Tue, 06 Jan 2004 08:24:42 -0800 -Received: (qmail 16535 invoked by uid 225); 6 Jan 2004 16:24:39 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16527 invoked by uid 507); 6 Jan 2004 16:24:39 -0000 -Received: from mail.cybcon.com (HELO mail.cybcon.com) (216.190.188.5) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 06 Jan 2004 08:24:08 -0800 -Received: from poirot (dsl2-6.cybcon.com [208.186.116.6]) by mail.cybcon.com (8.11.6/8.11.6) with ESMTP id i06GNhn08916; Tue, 6 Jan 2004 08:23:43 -0800 -Subject: RE: Help - multiple Oracle versions -From: Jared Still -To: "Anniballi, Fran" -Cc: DBI List -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 (1.0.8-11) -Date: 06 Jan 2004 08:25:59 -0800 -Message-Id: <1073406359.324.244.camel@poirot.jks.com> -Mime-Version: 1.0 -X-CyberConnectics-MailScanner2-Information: Spam/Virus Scanned at CyberConnectics -X-CyberConnectics-MailScanner2: Found to be clean -X-CyberConnectics-MailScanner2-SpamCheck: -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.2 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_05_08,SUPERLONG_LINE version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 4050 -Lines: 102 - -I read quickly through this thread, so my apologies if someone -already pointed this out. - -It doesn't matter which version of Oracle you compiled DBD with, -you can connect to all your 8i/9i databases on any platform with it. - -Assume you compiled with 9i libs, and you can connect to 9i db's with -no problem, but are unable to connect to 8i, getting the error you -mentioned previously. - -It appears that you are changing your Oracle environment via the -oraenv shell script to change your ORACLE_HOME to the 8i version -of Oracle. - -If so, stop doing that. Just leave your environment at 9i, and -connect to your 8i database. It will be fine. This is the way -my linux server is setup, and DBD is used to connect to Oracle -versions 7.3, 8.1.6, 8.1.7 and 9.2.0 every day. - -At our site DBD is compiled with 8i libs so that we can still -connect to the version 7 databases. If you compile with 9i libs, -you will be unable to connect to version 7 databases. - -HTH - -Jared - - -On Sun, 2004-01-04 at 05:12, Anniballi, Fran wrote: -> This is all done on one UNIX box. -> -> If I try option one, it doesn't work. I can't access an oracle8 instance with oracle9 sqlplus (or the other way around). That is the real problem. Since I can't do this I have to reassign the pointers before I access it. I can do this fine with sqlplus but with dbi/dbd I have to compile with one or the other. -> -> For option two, if I have two versions of DBD:Oracle, how do I tell Perl which one to use? My scripts just say "/usr/bin/perl" in the first line. -> -> -----Original Message----- -> From: kn@sifira.dk [mailto:kn@sifira.dk] -> Sent: Saturday, January 03, 2004 1:04 PM -> To: dbi-users@perl.org -> Cc: Anniballi, Fran -> Subject: Re: Help - multiple Oracle versions -> -> -> "Anniballi, Fran" writes: -> -> > As soon as I recompile the same DBI/DBD with it pointing to Oracle 9 -> > environment (libraries), it doesn't work. It is looking for Oracle9 -> > library files and I obviously don't have it pointing to oracle9 -> > libraries when I access an Oracle 8 instance. Oracle 9 is not -> > compatible with Oracle 8 so I have to redirect the environment -> > variables at run time. -> -> It sounds like you are confusing the Oracle client version and the -> Oracle server version. -> -> Eg. if you set ORACLE_HOME to /usr/local/oracle8 (or whatever) and use -> /usr/local/oracle8/bin/sqlplus you are using the Oracle 8 client, while -> if you set it to /usr/local/oracle9 and call -> /usr/local/oracle9/bin/sqlplus, you are using the Oracle 9 client. -> -> Which Oracle instance you access is selected by the connection string; -> for example "sqlplus scott/tiger@DB8" might access the Oracle 8 -> instance, and "scott/tiger@DB9" might access the Oracle 9 instance. -> -> What people are telling you is that you can choose client version -> independently of the server version. For example, it is possible to set -> ORACLE_HOME to /usr/local/oracle9 and call -> -> /usr/local/oracle9/bin/sqlplus scott/tiger@DB8 -> -> to access the Oracle 8 instance with the Oracle 9 client. This of course -> requires that the definition for DB8 is present in the file -> /usr/local/oracle-9.2/network/admin/tnsnames.ora. -> -> So you should either -> -> 1. Use only the Oracle 9 client, not change ORACLE_HOME, and access both -> instances with Oracle 9 sqlplus and DBD::Oracle compiled against -> Oracle 9 libraries. -> -> or -> -> 2. Compile DBD::Oracle twice (once against Oracle 8 libraries, once -> against Oracle 9 libraries, just as you have two versions of sqlplus) -> and use each one with the proper ORACLE_HOME setting. -> -> My guess is that you will find possibility 1. the easiest. -> -> > The tnsnames.ora are all set. I did what you said already. -> > -> > Example: DBI/DBD will work fine if I compile the DBI/DBD pointing to -> > Oracle 8 environment(libraries) and access an Oracle 8 instance. I -> > didn't have to change tnsnames.ora -> -> Yes you do: You need to have BOTH Oracle instances defined in EACH -> tnsnames.ora. -> -> Hope this helps, -> -> - Kristian. - - - -From andy@andyh.co.uk Wed Jan 7 07:31:57 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i077VPn8081048 - for ; Wed, 7 Jan 2004 07:31:57 GMT - (envelope-from andy@andyh.co.uk) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 07 Jan 2004 07:31:57 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Ae0Yb-0002lT-IA; - Tue, 06 Jan 2004 23:24:17 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Ae0Yb-0002lT-IA - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 23:24:17 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 00D7C3C15 - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id CB5813BEA - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from mta03-svc.ntlworld.com (mta03-svc.ntlworld.com [62.253.162.43]) - by integer.pobox.com (Postfix) with ESMTP - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from excession ([80.2.244.47]) by mta03-svc.ntlworld.com - (InterMail vM.4.01.03.37 201-229-121-137-20020806) with SMTP - id <20040106232403.NEKJ9852.mta03-svc.ntlworld.com@excession>; - Tue, 6 Jan 2004 23:24:03 +0000 -Message-ID: <00bd01c3d4ac$e5713190$6564a8c0@excession> -From: "Andy Hassall" -To: "Eric Lenio" , "Tim Bunce" -Cc: -References: <20040102143310.GC27273@lenio.net> <20040104204914.GB60357@dansat.data-plan.com> <20040105123653.GA31473@lenio.net> <20040105223121.GG66760@dansat.data-plan.com> <20040106222634.GG11531@lenio.net> <20040106223845.GE78360@dansat.data-plan.com> <20040106225722.GI11531@lenio.net> -Subject: Re: DBI primary_key tests fail: oracle 8 -Date: Tue, 6 Jan 2004 23:29:14 -0000 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2800.1158 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 43 - -Eric Lenio wrote: -> OK Tim. One other note -- after reading through oracle docs, I think -> you might want to substitute 'session_user' for 'current_schema' in -> 'select sys_context(...)'. The definition of session_user is -> "returns the database -> user name by which the current user is authenticated" while -> current_schema is "returns the name of the default schema being used -> in the current session". -> Maybe it doesn't matter, I'm not an oracle guru by any stretch of the -> imagination. - -There's several usernames in the USERENV context: - -CURRENT_SCHEMA - -The schema/user used for unqualified object name resolution; by default the -user you logged in as, but alterable with 'alter session set -current_schema=x'. Useful for avoiding having to maintain loads of synonyms. - -CURRENT_USER - -The user you're currently authenticated as. Doesn't change in SQL and -anonymous PL/SQL, but changes within definer-rights PL/SQL stored procedures -to the owner of the stored procedure, since stored procs by default run with -the privileges of the owner, not the invoker. - -SESSION_USER - -Who you originally logged in as, and never changes (but see below). Looks -like the appropriate one to use. - -PROXY_USER - -I don't think DBD::Oracle supports proxy authentication so don't need to -worry about that one yet. Possibly a bit of a grey area if it does support -it in the future, since this would hold the username in the DSN, but it'd -reauthenticate and change the SESSION_USER on connect (which would probably -have to be specified as an attribute to the $dbh). - --- -Andy Hassall (andy@andyh.co.uk) icq(5747695) (http://www.andyh.co.uk) -Space: disk usage analysis tool (http://www.andyhsoftware.co.uk/space) - - diff --git a/err_unsorted/err_ora9ir2oci.msg b/err_unsorted/err_ora9ir2oci.msg deleted file mode 100644 index 7ed476e4..00000000 --- a/err_unsorted/err_ora9ir2oci.msg +++ /dev/null @@ -1,27 +0,0 @@ -http://otn.oracle.com/tech/oci/htdocs/oci9ir2_new_features - -OCI Session Pooling -Session Pooling is a new feature in Oracle 9i Database Release 2. -An application can now maintain a pool of sessions and use a session -from the pool when it needs it. This saves the time consuming process -of initiating a connection and authentication every time the process -needs a new session. Session Pooling is useful, especially when a -large number of stateless sessions are required for a very short -time. In a web scenario, where many users are connected for a short -time, and the primary operation is accessing data, it is a costly -operation to start up a new session every time. In such a scenario, -session pooling could boost up the performance. - -OCI Statement caching -Client-side statement caching is also introduced in Oracle9i Database -Release 2. This feature can be enabled at the time of session -creation. It allows users to have a cache of statements per session. -On the server, this means having cursors that ready to be used, -without the need to parse the statements again, and thus improving -performance significantly. With this feature enabled, applications -do not have to keep a track of the statements themselves, as the -OCI layer will do it for them. In addition, a tagging feature is -provided, which users can use as a key to save and search for -statements. - - diff --git a/err_unsorted/err_ref_type.msg b/err_unsorted/err_ref_type.msg deleted file mode 100644 index 26d86e14..00000000 --- a/err_unsorted/err_ref_type.msg +++ /dev/null @@ -1,115 +0,0 @@ -From dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org Wed Jul 23 18:40:02 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6NHUUA0010501 - for ; Wed, 23 Jul 2003 18:40:02 +0100 (BST) - (envelope-from dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 23 Jul 2003 18:40:02 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058948095:10:09585:8; Wed, 23 Jul 2003 08:14:55 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116163; 23 Jul 2003 8:14 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 88C1B21C024 - for ; Wed, 23 Jul 2003 04:13:51 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id AA89B21C082 - for ; Wed, 23 Jul 2003 04:13:50 -0400 (EDT) -Received: (qmail 26606 invoked by uid 1005); 23 Jul 2003 08:13:44 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 26590 invoked by uid 76); 23 Jul 2003 08:13:43 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Wed, 23 Jul 2003 01:13:43 -0700 -Received: (qmail 16360 invoked by uid 225); 23 Jul 2003 08:13:41 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16355 invoked by uid 507); 23 Jul 2003 08:13:41 -0000 -Received-SPF: unknown -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Wed, 23 Jul 2003 01:13:41 -0700 -Received: (qmail 5378 invoked from network); 23 Jul 2003 08:54:08 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 23 Jul 2003 08:54:08 -0000 -Received: (qmail 8984 invoked from network); 23 Jul 2003 08:13:49 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 23 Jul 2003 08:13:49 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Wed, 23 Jul 2003 10:13:49 +0200 (CEST) -Subject: Re: binding to parameters of type REF -From: Hendrik =?ISO-8859-1?Q?Fu=DF?= -To: dbi-users@perl.org -In-Reply-To: <1058865345.1241.56.camel@mars> -References: <1058865345.1241.56.camel@mars> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 -Date: 23 Jul 2003 10:11:49 +0200 -Message-Id: <1058947909.6353.5.camel@mars> -Mime-Version: 1.0 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.3 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,LARGE_HEX,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1354 -Lines: 56 - -I've also found out, that DBD::Oracle does not support type SQL_REF: -When not using DBD::Proxy I get: - - SQL type 20 for ':p1' is not fully supported, - bound as SQL_VARCHAR instead - -I even get segmentation faults when trying to fetch REF columns. :-( - -Any ideas? - -> Hi, -> -> I'm trying to bind a perl variable to an Oracle table reference with -> Oracle 9.2.0.3, DBD::Proxy and Perl::DBI 1.37 without success. I -> could'nt find help on this in the docs or list archives. I hope this is -> the right place to post. -> -> In SQL*Plus: -> -> SQL> desc getReference -> FUNCTION getReference RETURNS REF OF TABLETYPE -> -> SQL> select getReference() from dual; -> -> GETREFERENCE() -> ---------------------------------------------------------------------- -> 0000280209C229D2216EF6A5F4E030010A8D086AD3C204FC6EE0E46501E030010A8D08 -> 2CE703C0000E0000 -> -> -> My code: -> -> my $ref = undef; -> my $sth = $dbh->prepare('BEGIN ? := getReference(); END;'); -> $sth->bind_param_inout(1, \$ref, 128, SQL_REF ); -> $sth->execute(); -> -> yields: -> -> PLS-00382: expression is of wrong type -> -> -> Even fetching a reference does not work: -> -> my $sth = $dbh->prepare('SELECT getReference() FROM DUAL'); -> $sth->execute(); -> ($ref) = $sth->fetchrow_array(); -> -> yields undef in $ref. -> -> I'd very much appreciate your help. -> cheers, -> Hendrik - - - - diff --git a/err_unsorted/err_refcsr_rowcache.msg b/err_unsorted/err_refcsr_rowcache.msg deleted file mode 100644 index 5101d2ae..00000000 --- a/err_unsorted/err_refcsr_rowcache.msg +++ /dev/null @@ -1,85 +0,0 @@ -From dbi-users-bounce@isc.org Tue May 16 22:53:12 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id WAA29547; Tue, 16 May 2000 22:53:11 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <04730-2@oink>; Sat, 16 May 1970 22:51:48 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 958512876:10:15786:0; Tue, 16 May 2000 21:34:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1122388; 16 May 2000 21:33 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 661E53EC8; - Tue, 16 May 2000 14:33:38 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Tue, 16 May 2000 14:28:31 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id 7192F3E20 - for ; - Tue, 16 May 2000 14:28:27 -0700 (PDT) -Received: from anchor-post-34.mail.demon.net (anchor-post-34.mail.demon.net [194.217.242.92]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id OAA27204 - for ; - Tue, 16 May 2000 14:28:26 -0700 (PDT) env-from (Tim.Bunce@ig.co.uk) -Received: from ignite.demon.co.uk ([158.152.8.99] helo=oink) - by anchor-post-34.mail.demon.net with smtp (Exim 2.12 #1) - id 12rot7-000Mp4-0Y; Tue, 16 May 2000 22:28:25 +0100 -Received: from toad by oink with SMTP (PP) id <04650-0@oink>; - Sat, 16 May 1970 22:23:55 +0100 -Received: by toad.ig.co.uk (SMI-8.6/SMI-SVR4) id WAA29289; - Tue, 16 May 2000 22:23:50 +0100 -Date: Tue, 16 May 2000 22:23:50 +0100 -From: Tim Bunce -To: peter_dev@talk21.com -Cc: dbi-users@isc.org -Subject: Re: Oracle Stored Procs take longer than embedded SQL -Message-ID: <20000516222350.F28435@ig.co.uk> -References: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs>; from peter_dev@talk21.com on Tue, May 16, 2000 at 06:48:22PM +0100 -Organization: Paul Ingram Group, Software Systems, +44 1 483 862800 -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 1372 -Lines: 30 - -On Tue, May 16, 2000 at 06:48:22PM +0100, peter_dev@talk21.com wrote: -> I have a problem with the fetching of data from an Oracle Ref Cursor taking longer than the same query in Embeded SQL. -> -> $ get_sp.pl -> Fetched in 0.00774896144866943 seconds -> Completed in 0.106827020645142 seconds -> -> $ get_sql.pl -> Fetched in 0.00138604640960693 seconds -> Completed in 0.380790948867798 seconds -> -> In this example (Using the SCOTT/TIGER tables), while the Stored Procedure completed first, the actual fetch of the data took considerably longer. In a real situation (e.g. bigger tables ), this is easily the longest part of the task and causes the overall execution time to increase hugely. -> -> Any Help would be appreciated -> thanks - -Possibly related to the lack of a row cache on that statement handle. -You, or some kind volunteer, could probably hack that in without too -much work. - -Tim. - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_unsorted/err_refcsr_slow.msg b/err_unsorted/err_refcsr_slow.msg deleted file mode 100644 index 790d267d..00000000 --- a/err_unsorted/err_refcsr_slow.msg +++ /dev/null @@ -1,347 +0,0 @@ -From dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org Mon Apr 29 23:12:51 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TMCpR17212 - for ; Mon, 29 Apr 2002 23:12:51 +0100 (BST) - (envelope-from dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 29 Apr 2002 23:12:51 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020117986:10:17770:92; Mon, 29 Apr 2002 22:06:26 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1017591; 29 Apr 2002 22:06 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id 975037274A - for ; Mon, 29 Apr 2002 18:01:37 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by wormwood.pobox.com (Postfix) with SMTP id ED2897273F - for ; Mon, 29 Apr 2002 18:01:34 -0400 (EDT) -Received: (qmail 70462 invoked by uid 1005); 29 Apr 2002 21:59:33 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 20335 invoked by uid 76); 29 Apr 2002 20:18:55 -0000 -Message-ID: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Date: Mon, 29 Apr 2002 13:18:53 -0700 (PDT) -From: Calin Medianu -Reply-To: cmedianu@sfu.ca -Subject: DBD::Oracle Slow cursors -To: dbi-users@perl.org -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 568 -Lines: 21 - -Hello, - -I did the following. Wrote a perl script that retreves -data via a straight select from the database. Then I -wrote a stored procedure returning a ref cursor open -on the same select statement and retrieved the data as -well. Using the REF CURSOR/ sotred procedure was about -3 time slower, that is 40 seconds instead of around -10. - -Is this normal? Is this a problem with oracle or with -DBD::Oracle? - -Thanks, - -Calin Medianu - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org Tue Apr 30 00:06:36 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TN6aR17980 - for ; Tue, 30 Apr 2002 00:06:36 +0100 (BST) - (envelope-from dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 00:06:36 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020119533:20:05733:4; Mon, 29 Apr 2002 22:32:13 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2005393; 29 Apr 2002 22:32 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 4E6B73E6BF - for ; Mon, 29 Apr 2002 18:32:00 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-1.pobox.com (Postfix) with SMTP id BF79C3E6A0 - for ; Mon, 29 Apr 2002 18:31:59 -0400 (EDT) -Received: (qmail 87860 invoked by uid 1005); 29 Apr 2002 22:31:59 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 87844 invoked by uid 76); 29 Apr 2002 22:31:58 -0000 -Received: from mail01.svc.cra.dublin.eircom.net (HELO mail01.svc.cra.dublin.eircom.net) (159.134.118.17) - by onion.perl.org (qpsmtpd/0.07) with SMTP; Mon Apr 29 22:31:58 2002 -0000 -Received: (qmail 21911 messnum 119827 invoked from network[159.134.167.97/p865.as1.limerick1.eircom.net]); 29 Apr 2002 22:31:29 -0000 -Received: from p865.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.97) - by mail01.svc.cra.dublin.eircom.net (qp 21911) with SMTP; 29 Apr 2002 22:31:29 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g3TMVcR17579; - Mon, 29 Apr 2002 23:31:38 +0100 (BST) - (envelope-from timbo) -Date: Mon, 29 Apr 2002 23:31:38 +0100 -From: Tim Bunce -To: cmedianu@sfu.ca -Cc: dbi-users@perl.org -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020429233138.E16831@dansat.data-plan.com> -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020429201853.52283.qmail@web10007.mail.yahoo.com>; from calinm@yahoo.com on Mon, Apr 29, 2002 at 01:18:53PM -0700 -Content-Length: 651 -Lines: 20 - -On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> Hello, -> -> I did the following. Wrote a perl script that retreves -> data via a straight select from the database. Then I -> wrote a stored procedure returning a ref cursor open -> on the same select statement and retrieved the data as -> well. Using the REF CURSOR/ sotred procedure was about -> 3 time slower, that is 40 seconds instead of around -> 10. -> -> Is this normal? Is this a problem with oracle or with -> DBD::Oracle? - -DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. - -Get a level 3 trace and look for the "dbd_describe'd" line for the -ref cursor. - -Tim. - -From calinm@yahoo.com Tue Apr 30 22:02:56 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL2tR26878 - for ; Tue, 30 Apr 2002 22:02:55 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:02:55 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020198219:10:21718:114; Tue, 30 Apr 2002 20:23:39 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101732; 30 Apr 2002 20:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C6B4A2BFB4 - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10004.mail.yahoo.com (web10004.mail.yahoo.com [216.136.130.40]) - by dolly1.pobox.com (Postfix) with SMTP id 527BD2BF3D - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Message-ID: <20020430202321.54825.qmail@web10004.mail.yahoo.com> -Received: from [213.157.171.169] by web10004.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 13:23:20 PDT -Date: Tue, 30 Apr 2002 13:23:20 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -Cc: dbi-users@perl.org -In-Reply-To: <20020430140517.P16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 425 -Lines: 18 - -I "Solved" the problem. For Now.. I did -perl Makefile.PL -8 - -hoping that the buggy code would be recently added, -and it was. Now both the select and the cursor return -the data at the same speed, meaning fast.. - -Am I am missing much by not using the code for Oracle -8? - -Thanks, - -Calin - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From timbo@dansat.data-plan.com Wed May 1 16:49:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g41FnsR33994 - for ; Wed, 1 May 2002 16:49:54 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 May 2002 16:49:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020265865:20:10671:66; Wed, 01 May 2002 15:11:05 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-2.mail.demon.net - id aa2122069; 1 May 2002 15:10 GMT -Received: from cali-3.pobox.com (cali-3.pobox.com [64.71.166.116]) - by silk.pobox.com (Postfix) with ESMTP id F29CC3FDF2 - for ; Wed, 1 May 2002 11:09:52 -0400 (EDT) -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id E3A943E689 - for ; Wed, 1 May 2002 10:57:15 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id D1F523E688 - for ; Wed, 1 May 2002 10:57:14 -0400 (EDT) -Received: (qmail 96042 messnum 564683 invoked from network[159.134.166.63/p575.as1.limerick1.eircom.net]); 1 May 2002 14:57:13 -0000 -Received: from p575.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.63) - by mail03.svc.cra.dublin.eircom.net (qp 96042) with SMTP; 1 May 2002 14:57:13 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g41EvIh33626; - Wed, 1 May 2002 15:57:18 +0100 (BST) - (envelope-from timbo) -Date: Wed, 1 May 2002 15:57:18 +0100 -From: Tim Bunce -To: Calin Medianu -Cc: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020501155718.S16831@dansat.data-plan.com> -References: <20020430151126.Q16831@dansat.data-plan.com> <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020430183429.33340.qmail@web10005.mail.yahoo.com>; from calinm@yahoo.com on Tue, Apr 30, 2002 at 11:34:29AM -0700 -Status: RO -Content-Length: 3111 -Lines: 111 - -Thanks. I'll take a look when I get to DBD::Oracle again. - -I think the last row of that table applies and it doesn't refer to OCIBindObject(): - REF CURSOR variables - SQLT_RSET - Allocate a statement handle, OCIStmt, and then bind its address - (OCIStmt **) using the SQLT_RSET datatype. -Note that SQLT_REF isn't the same as SQLT_RSET. - -You could always try patching it yourself! - -Tim. - - -On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin Medianu wrote: -> It says here: -> http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> -> that 2 calls are neede to bind a ref , the second is -> to OCIBindObject() which I don't see in dbdimp.c. -> -> Could this be a reason? -> -> Cheers, -> -> Calin -> -> --- Tim Bunce wrote: -> > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > Medianu wrote: -> > > Me again with the slow cursors. -> > > -> > > I modified both queries to only return 10 rows. -> > > I ran a sniffer (ethereal) on the NIC. It is -> > pretty cool, it also decodes TNS. -> > > -> > > when I am using the SQL, it works like this, there -> > are about 7 packets -> > > received by my workstation to set up the session, -> > then all 10 rows are in the -> > > same packet, then there is another packet probably -> > saying goodbye. -> > > -> > > When I am using the REF cursor, each row comes in -> > it's own TNS packet, that -> > > is why it is so slow! -> > > -> > > Any idea how to fix it? -> > -> > Do a level 9 trace to get a log of the OCI calls and -> > confirm that -> > the fragment I posted is being called (may be -> > helpful to also -> > add an extra print statement into that code since -> > parsing the -> > OCI trace can be painful). -> > -> > Assuming the code is being called then as far as I -> > can see the code is -> > doing the right thing and it's probably an Oracle -> > OCI issue. -> > -> > You'd need to talk to Oracle support. No need to -> > mention perl etc. -> > Just talk about your OCI application and provide the -> > OCI call trace. -> > -> > Let me know what you find out! -> > -> > Tim. -> > -> > > thanks a lot, -> > > -> > > Calin -> > > -> > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> > Medianu wrote: -> > > > > Hello, -> > > > > -> > > > > I did the following. Wrote a perl script that -> > retreves -> > > > > data via a straight select from the database. -> > Then I -> > > > > wrote a stored procedure returning a ref -> > cursor open -> > > > > on the same select statement and retrieved the -> > data as -> > > > > well. Using the REF CURSOR/ sotred procedure -> > was about -> > > > > 3 time slower, that is 40 seconds instead of -> > around -> > > > > 10. -> > > > > -> > > > > Is this normal? Is this a problem with oracle -> > or with -> > > > > DBD::Oracle? -> > > > -> > > > DBD::Oracle. It probably isn't setting up a row -> > cache for the ref cursor. -> > > > -> > > > Get a level 3 trace and look for the -> > "dbd_describe'd" line for the -> > > > ref cursor. -> > > > -> > > > Tim. -> -> -> __________________________________________________ -> Do You Yahoo!? -> Yahoo! Health - your guide to health and wellness -> http://health.yahoo.com - diff --git a/err_unsorted/err_slowcsr.msg b/err_unsorted/err_slowcsr.msg deleted file mode 100644 index 80c43350..00000000 --- a/err_unsorted/err_slowcsr.msg +++ /dev/null @@ -1,316 +0,0 @@ -From calinm@yahoo.com Tue Apr 30 22:03:11 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL3AR27018 - for ; Tue, 30 Apr 2002 22:03:10 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:03:10 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020196981:10:23493:39; Tue, 30 Apr 2002 20:03:01 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-1.mail.demon.net - id aa1108477; 30 Apr 2002 20:02 GMT -Received: from dolly1.pobox.com (dolly1.pobox.com [207.106.49.22]) - by silk.pobox.com (Postfix) with ESMTP id 915563FCE8 - for ; Tue, 30 Apr 2002 14:35:38 -0400 (EDT) -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 343702BFDD - for ; Tue, 30 Apr 2002 14:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10005.mail.yahoo.com (web10005.mail.yahoo.com [216.136.130.41]) - by dolly1.pobox.com (Postfix) with SMTP id 6AA822BFA3 - for ; Tue, 30 Apr 2002 14:34:37 -0400 (EDT) -Message-ID: <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Received: from [213.157.171.169] by web10005.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 11:34:29 PDT -Date: Tue, 30 Apr 2002 11:34:29 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020430151126.Q16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 2457 -Lines: 96 - -It says here: -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 - -that 2 calls are neede to bind a ref , the second is -to OCIBindObject() which I don't see in dbdimp.c. - -Could this be a reason? - -Cheers, - -Calin - ---- Tim Bunce wrote: -> On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> Medianu wrote: -> > Me again with the slow cursors. -> > -> > I modified both queries to only return 10 rows. -> > I ran a sniffer (ethereal) on the NIC. It is -> pretty cool, it also decodes TNS. -> > -> > when I am using the SQL, it works like this, there -> are about 7 packets -> > received by my workstation to set up the session, -> then all 10 rows are in the -> > same packet, then there is another packet probably -> saying goodbye. -> > -> > When I am using the REF cursor, each row comes in -> it's own TNS packet, that -> > is why it is so slow! -> > -> > Any idea how to fix it? -> -> Do a level 9 trace to get a log of the OCI calls and -> confirm that -> the fragment I posted is being called (may be -> helpful to also -> add an extra print statement into that code since -> parsing the -> OCI trace can be painful). -> -> Assuming the code is being called then as far as I -> can see the code is -> doing the right thing and it's probably an Oracle -> OCI issue. -> -> You'd need to talk to Oracle support. No need to -> mention perl etc. -> Just talk about your OCI application and provide the -> OCI call trace. -> -> Let me know what you find out! -> -> Tim. -> -> > thanks a lot, -> > -> > Calin -> > -> > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> Medianu wrote: -> > > > Hello, -> > > > -> > > > I did the following. Wrote a perl script that -> retreves -> > > > data via a straight select from the database. -> Then I -> > > > wrote a stored procedure returning a ref -> cursor open -> > > > on the same select statement and retrieved the -> data as -> > > > well. Using the REF CURSOR/ sotred procedure -> was about -> > > > 3 time slower, that is 40 seconds instead of -> around -> > > > 10. -> > > > -> > > > Is this normal? Is this a problem with oracle -> or with -> > > > DBD::Oracle? -> > > -> > > DBD::Oracle. It probably isn't setting up a row -> cache for the ref cursor. -> > > -> > > Get a level 3 trace and look for the -> "dbd_describe'd" line for the -> > > ref cursor. -> > > -> > > Tim. - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From calinm@yahoo.com Fri May 3 13:48:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g43Cm5R50489 - for ; Fri, 3 May 2002 13:48:05 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 03 May 2002 13:48:05 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020429421:10:02019:143; Fri, 03 May 2002 12:37:01 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1123562; 3 May 2002 12:36 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id D7BD1725A1 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10008.mail.yahoo.com (web10008.mail.yahoo.com [216.136.130.44]) - by wormwood.pobox.com (Postfix) with SMTP id 3088772674 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Message-ID: <20020503123640.19648.qmail@web10008.mail.yahoo.com> -Received: from [213.157.171.169] by web10008.mail.yahoo.com via HTTP; Fri, 03 May 2002 05:36:40 PDT -Date: Fri, 3 May 2002 05:36:40 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020501155718.S16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -Content-Length: 3619 -Lines: 150 - -Sure, - -I'll give it a try next week. - -Cheers, - -Calin ---- Tim Bunce wrote: -> Thanks. I'll take a look when I get to DBD::Oracle -> again. -> -> I think the last row of that table applies and it -> doesn't refer to OCIBindObject(): -> REF CURSOR variables -> SQLT_RSET -> Allocate a statement handle, OCIStmt, and then -> bind its address -> (OCIStmt **) using the SQLT_RSET datatype. -> Note that SQLT_REF isn't the same as SQLT_RSET. -> -> You could always try patching it yourself! -> -> Tim. -> -> -> On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin -> Medianu wrote: -> > It says here: -> > -> -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> > -> > that 2 calls are neede to bind a ref , the second -> is -> > to OCIBindObject() which I don't see in dbdimp.c. -> > -> > Could this be a reason? -> > -> > Cheers, -> > -> > Calin -> > -> > --- Tim Bunce wrote: -> > > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > > Medianu wrote: -> > > > Me again with the slow cursors. -> > > > -> > > > I modified both queries to only return 10 -> rows. -> > > > I ran a sniffer (ethereal) on the NIC. It is -> > > pretty cool, it also decodes TNS. -> > > > -> > > > when I am using the SQL, it works like this, -> there -> > > are about 7 packets -> > > > received by my workstation to set up the -> session, -> > > then all 10 rows are in the -> > > > same packet, then there is another packet -> probably -> > > saying goodbye. -> > > > -> > > > When I am using the REF cursor, each row comes -> in -> > > it's own TNS packet, that -> > > > is why it is so slow! -> > > > -> > > > Any idea how to fix it? -> > > -> > > Do a level 9 trace to get a log of the OCI calls -> and -> > > confirm that -> > > the fragment I posted is being called (may be -> > > helpful to also -> > > add an extra print statement into that code -> since -> > > parsing the -> > > OCI trace can be painful). -> > > -> > > Assuming the code is being called then as far as -> I -> > > can see the code is -> > > doing the right thing and it's probably an -> Oracle -> > > OCI issue. -> > > -> > > You'd need to talk to Oracle support. No need to -> > > mention perl etc. -> > > Just talk about your OCI application and provide -> the -> > > OCI call trace. -> > > -> > > Let me know what you find out! -> > > -> > > Tim. -> > > -> > > > thanks a lot, -> > > > -> > > > Calin -> > > > -> > > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, -> Calin -> > > Medianu wrote: -> > > > > > Hello, -> > > > > > -> > > > > > I did the following. Wrote a perl script -> that -> > > retreves -> > > > > > data via a straight select from the -> database. -> > > Then I -> > > > > > wrote a stored procedure returning a ref -> > > cursor open -> > > > > > on the same select statement and retrieved -> the -> > > data as -> > > > > > well. Using the REF CURSOR/ sotred -> procedure -> > > was about -> > > > > > 3 time slower, that is 40 seconds instead -> of -> > > around -> > > > > > 10. -> > > > > > -> > > > > > Is this normal? Is this a problem with -> oracle -> > > or with -> > > > > > DBD::Oracle? -> > > > > -> > > > > DBD::Oracle. It probably isn't setting up a -> row -> > > cache for the ref cursor. -> > > > > -> > > > > Get a level 3 trace and look for the -> > > "dbd_describe'd" line for the -> > > > > ref cursor. -> > > > > -> > > > > Tim. -> > -> > -> > __________________________________________________ -> > Do You Yahoo!? -> > Yahoo! Health - your guide to health and wellness -> > http://health.yahoo.com - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - diff --git a/err_unsorted/err_svrparse.msg b/err_unsorted/err_svrparse.msg deleted file mode 100644 index 16886ca8..00000000 --- a/err_unsorted/err_svrparse.msg +++ /dev/null @@ -1,4717 +0,0 @@ -From cary.millsap@hotsos.com Thu Sep 12 23:38:20 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8CMbgC02618 - for ; Thu, 12 Sep 2002 23:38:03 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 12 Sep 2002 23:38:03 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031869308:20:16258:30; Thu, 12 Sep 2002 22:21:48 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2108888; 12 Sep 2002 22:21 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id A32132F05C9 - for ; Thu, 12 Sep 2002 18:21:34 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-3.pobox.com (Postfix) with ESMTP id D71F62F056D - for ; Thu, 12 Sep 2002 18:21:31 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8CMLQn17849; - Thu, 12 Sep 2002 17:21:26 -0500 -From: "Cary Millsap" -To: -Subject: -Date: Thu, 12 Sep 2002 17:21:17 -0500 -Message-ID: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_016A_01C25A80.D1527130" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 64884 -Lines: 2025 - -This is a multi-part message in MIME format. - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: multipart/alternative; - boundary="----=_NextPart_001_016B_01C25A80.D1557E70" - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -How are you doing? I hope you've had a good two years since I saw you on -the Oracle Geek Cruise event. - - - -I've been working on a project this year to construct a book about -optimizing Oracle response time. In my research, I've discovered -something about the DBI that I didn't expect: it executes two Oracle -parse calls for every one that I would expect an efficient DBI layer to -make. I've included my Perl source (below), the Oracle level-12 trace -data that shows the sequence of calls it's receiving from the Perl -application (below), a level-9 DBI trace from the application -(attached), and our version information (below). - - - -The reason I'm bringing this to your attention in this way is that I'm -relying pretty heavily upon Perl for performance measurement tools, -examples, and simulators in the text. I love the language and I want for -the book to be an encouragement for more people to use Perl. However, -this extra-parse behavior is one of the things that the book highlights -as an important scalability barrier (some other tools do it too, -unfortunately). Of course, this is a speed bump on the road to my goal -of helping to promote Perl. - - - -I was hoping that by showing you this specific data, you could make the -problem go away. - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - -Listing [listing.sqltrace.pl]: a simple application that executes a -database query - -#!/usr/bin/perl - - - - - -# $Header: /home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 21:10:25 -cvm Exp $ - -# Cary Millsap (cary.millsap@hotsos.com) - - - - - -use strict; - -use warnings; - -use DBI; - -use DBD::Oracle; - -use Getopt::Long; - -use Term::ReadKey; - - - - - -my $sth; # Oracle statement handle - -my $hostname = ""; - -my $username = "/"; - -my $password = ""; - -my $logfile = "ex1.log"; - -my %attr = ( - - RaiseError => 1, - - AutoCommit => 0, - -); - -my %opt = ( - - pause => 0, - -); - - - - - -# Get command line options and arguments. - -GetOptions( - - "pause" => \$opt{pause}, - -); - -my $key = 37; # default query value - -$key = $ARGV[0] if $ARGV[0]; - - - - - -# Connect to Oracle. - -my $dbh = DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr); - -$dbh->trace(9, $logfile); - - - - - -# Activate tracing. - -$sth = $dbh->prepare(q(alter session set events '10046 trace name -context forever, level 12')); - -$sth->execute; - - - - - -# Allow the user to find the Oracle session and activate OS diagnostic - -# tools like strace(1) or lsof(8). - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Execute the query to trace. - -$sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -$sth->execute($key); - - - - - -# Print output header. - -my @cdefs = qw(%8d %8d %32s); # column definitions - -my @hdefs = qw(Key Fkey Value); # column headings - -my $bformat = join(" ", @cdefs) . "\n"; - -my $hformat; ($hformat = $bformat) =~ s/%(\d*)\S+/%$1s/g; - -printf $hformat, @hdefs; - -printf $hformat, do { my @h; push @h, "-" x (/(\d+)/?$1:10) for @cdefs; -@h }; - - - - - -# Print query results. - -for my $row (@{$sth->fetchall_arrayref}) { - - printf $bformat, @$row; - -} - - - - - -# Allow the user to do final OS diagnostic stuff. - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Disconnect from Oracle. - -$dbh->disconnect; - - - - - -Listing [listing:sqltrace.trc]: raw SQL trace output for an execution of -our program - -/usr/local/oracle/admin/V816/udump/ora_17349.trc - -Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production - -With the Partitioning option - -JServer Release 8.1.6.0.0 - Production - -ORACLE_HOME = /usr/local/oracle/product/8.1.6 - -System name: Linux - -Node name: www.hotsos.com - -Release: 2.2.16-22enterprise - -Version: #1 SMP Tue Aug 22 16:29:32 EDT 2000 - -Machine: i686 - -Instance name: V816 - -Redo thread mounted by this instance: 1 - -Oracle process number: 8 - -Unix process pid: 17349, image: oracle@www.hotsos.com (TNS V1-V3) - - - -*** SESSION ID:(7.9) 2002-09-12 16:14:01.582 - -===================== - -PARSING IN CURSOR #1 len=69 dep=0 uid=12 oct=42 lid=12 tim=107309054 -hv=1509700594 ad='54af5e14' - -alter session set events '10046 trace name context forever, level 12' - -END OF STMT - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107309054 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -*** 2002-09-12 16:14:31.226 - -WAIT #1: nam='SQL*Net message from client' ela= 2964 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -WAIT #2: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #2: nam='SQL*Net message from client' ela= 0 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -BINDS #1: - - bind 0: dty=1 mxl=32(04) mal=00 scl=00 pre=00 oacflg=25 oacfl2=10 -size=32 offset=0 - - bfp=0940e7f0 bln=32 avl=04 flg=05 - - value="8542" - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #1: nam='file open' ela= 0 p1=0 p2=0 p3=0 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6671 p3=1 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6678 p3=1 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - -*** 2002-09-12 16:14:56.200 - -WAIT #1: nam='SQL*Net message from client' ela= 2496 p1=1650815232 p2=1 -p3=0 - -XCTEND rlbk=0, rd_only=1 - -STAT #1 id=1 cnt=1 pid=0 pos=0 obj=5156 op='TABLE ACCESS BY INDEX ROWID -T ' - -STAT #1 id=2 cnt=2 pid=1 pos=1 obj=5157 op='INDEX UNIQUE SCAN ' - - - - - -$ perl -V - -Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration: - - Platform: - - osname=linux, osvers=2.2.5-22smp, archname=i386-linux - - uname='linux porky.devel.redhat.com 2.2.5-22smp #1 smp wed jun 2 -09:11:51 edt 1999 i686 unknown ' - - config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -Dcc=gcc --Dcccdlflags=-fPIC -Dinstallprefix=/usr -Dprefix=/usr --Darchname=i386-linux -Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm --Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Uuselargefiles' - - hint=recommended, useposix=true, d_sigaction=define - - usethreads=undef use5005threads=undef useithreads=undef -usemultiplicity=undef - - useperlio=undef d_sfio=undef uselargefiles=undef - - use64bitint=undef use64bitall=undef uselongdouble=undef -usesocks=undef - - Compiler: - - cc='gcc', optimize='-O2 -march=i386 -mcpu=i686', gccversion=2.96 -20000731 (experimental) - - cppflags='-fno-strict-aliasing' - - ccflags ='-fno-strict-aliasing' - - stdchar='char', d_stdstdio=define, usevfork=false - - intsize=4, longsize=4, ptrsize=4, doublesize=8 - - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', -lseeksize=4 - - alignbytes=4, usemymalloc=n, prototype=define - - Linker and Libraries: - - ld='gcc', ldflags =' -L/usr/local/lib' - - libpth=/usr/local/lib /lib /usr/lib - - libs=-lnsl -ldl -lm -lc -lcrypt - - libc=/lib/libc-2.1.92.so, so=so, useshrplib=false, libperl=libperl.a - - Dynamic Linking: - - dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' - - cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' - - - - - -Characteristics of this binary (from libperl): - - Compile-time options: - - Built under linux - - Compiled at Aug 7 2000 10:59:51 - - @INC: - - /usr/lib/perl5/5.6.0/i386-linux - - /usr/lib/perl5/5.6.0 - - /usr/lib/perl5/site_perl/5.6.0/i386-linux - - /usr/lib/perl5/site_perl/5.6.0 - - /usr/lib/perl5/site_perl - - . - - - - - -Other site information - -- Redhat Linux 7.0 - -- Oracle 8.1.6.1.0 - -- DBD-Oracle 1.12 - -- DBI 1.30 - - - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

How are you doing? I hope you’ve had a good two = -years -since I saw you on the Oracle Geek Cruise event.

- -

 

- -

I’ve been working on a project this year to = -construct -a book about optimizing Oracle response time. In my research, I’ve -discovered something about the DBI that I didn’t expect: it = -executes two -Oracle parse calls for every one that I would expect an efficient DBI = -layer to -make. I’ve included my Perl source (below), the Oracle level-12 = -trace -data that shows the sequence of calls it’s receiving from the Perl = -application -(below), a level-9 DBI trace from the application (attached), and our = -version information -(below).

- -

 

- -

The reason I’m bringing this to your attention = -in this -way is that I’m relying pretty heavily upon Perl for performance -measurement tools, examples, and simulators in the text. I love the = -language -and I want for the book to be an encouragement for more people to use = -Perl. -However, this extra-parse behavior is one of the things that the book = -highlights -as an important scalability barrier (some other tools do it too, = -unfortunately). -Of course, this is a speed bump on the road to my goal of helping to = -promote Perl.

- -

 

- -

I was hoping that by showing you this specific data, = -you -could make the problem go away.

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -
- -

Listing [listing.sqltrace.pl]: a simple = -application that -executes a database query

- -
- -
- -

#!/usr/bin/perl

- -

- -

- -

 

- -

 

- -

# = -$Header: -/home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 = -21:10:25 cvm Exp $

- -

- -

# = -Cary Millsap (cary.millsap@hotsos.com)

- -

- -

 

- -

 

- -

use = -strict;

- -

- -

use = -warnings;

- -

- -

use = -DBI;

- -

- -

use = -DBD::Oracle;

- -

- -

use = -Getopt::Long;

- -

- -

use = -Term::ReadKey;

- -

- -

 

- -

 

- -

my -$sth;           &n= -bsp;        -# Oracle statement handle

- -

- -

my = -$hostname =3D -"";

- -

- -

my = -$username =3D -"/";

- -

- -

my = -$password =3D -"";

- -

- -

my = -$logfile  -=3D "ex1.log";

- -

- -

my = -%attr =3D (

- -

- -

    -RaiseError =3D> 1,

- -

- -

    -AutoCommit =3D> 0,

- -

- -

);

- -

- -

my = -%opt =3D (

- -

- -

    -pause   =3D> 0,

- -

- -

);

- -

- -

 

- -

 

- -

# Get = -command line -options and arguments.

- -

- -

GetOptions(

- -

- -

    -"pause" =3D> \$opt{pause},

- -

- -

);

- -

- -

my = -$key =3D -37;           &nbs= -p;  - # default query value

- -

- -

$key = -=3D $ARGV[0] if -$ARGV[0];

- -

- -

 

- -

 

- -

# = -Connect to -Oracle.

- -

- -

my = -$dbh =3D -DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr);

- -

- -

$dbh->trace(9, -$logfile);

- -

- -

 

- -

 

- -

# = -Activate -tracing.

- -

- -

$sth = -=3D -$dbh->prepare(q(alter session set events '10046 trace name context = -forever, -level 12'));

- -

- -

$sth->execute;

- -

- -

 

- -

 

- -

# = -Allow the user -to find the Oracle session and activate OS diagnostic

- -

- -

# = -tools like -strace(1) or lsof(8).

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Execute the -query to trace.

- -

- -

$sth = -=3D -$dbh->prepare(q(select key, fkey, value from t where = -key=3D?));

- -

- -

$sth->execute($key);

- -

- -

 

- -

 

- -

# = -Print output -header.

- -

- -

my = -@cdefs =3D qw(%8d -%8d %32s);   # column definitions

- -

- -

my = -@hdefs =3D qw(Key -Fkey Value); # column headings

- -

- -

my = -$bformat =3D -join("  ", @cdefs) . "\n";

- -

- -

my = -$hformat; -($hformat =3D $bformat) =3D~ s/%(\d*)\S+/%$1s/g;

- -

- -

printf $hformat, -@hdefs;

- -

- -

printf $hformat, -do { my @h; push @h, "-" x (/(\d+)/?$1:10) for = -@cdefs; @h };

- -

- -

 

- -

 

- -

# = -Print query -results.

- -

- -

for = -my $row -(@{$sth->fetchall_arrayref}) {

- -

- -

    -printf $bformat, @$row;

- -

- -

}

- -

- -

- -

 

- -

 

- -

# = -Allow the user -to do final OS diagnostic stuff.

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Disconnect from -Oracle.

- -

- -

$dbh->disconnect;

- -
- -

 

- -

 

- -
- -

Listing [listing:sqltrace.trc]: raw SQL trace = -output for -an execution of our program

- -
- -
- -

/usr/local/oracle/admin/V816/udump/ora_17349.tr= -c

- -

Oracle8i Enterprise -Edition Release 8.1.6.1.0 - Production

- -

With = -the -Partitioning option

- -

JServer Release -8.1.6.0.0 - Production

- -

ORACLE_HOME =3D -/usr/local/oracle/product/8.1.6

- -

System -name:        Linux

- -

Node name:  = -www.hotsos.com

- -

Release:    = -2.2.16-22enterprise

- -

Version:    #1 -SMP Tue Aug 22 16:29:32 EDT 2000

- -

Machine:    = -i686

- -

Instance name: -V816

- -

Redo = -thread -mounted by this instance: 1

- -

Oracle process -number: 8

- -

Unix = -process pid: -17349, image: oracle@www.hotsos.com (TNS V1-V3)

- -

 

- -

*** = -SESSION -ID:(7.9) 2002-09-12 16:14:01.582

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D69 dep=3D0 uid=3D12 oct=3D42 lid=3D12 = -tim=3D107309054 hv=3D1509700594 -ad=3D'54af5e14'

- -

alter = -session set -events '10046 trace name context forever, level 12'

- -

END = -OF STMT

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -309054

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

*** = -2002-09-12 -16:14:31.226

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2964 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#2 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312018 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

WAIT = -#2: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#2: -nam=3D'SQL*Net message from client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312019 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

BINDS = -#1:

- -

 bind 0: -dty=3D1 mxl=3D32(04) mal=3D00 scl=3D00 pre=3D00 oacflg=3D25 oacfl2=3D10 = -size=3D32 offset=3D0

- -

   bfp=3D0940e7f0 bln=3D32 avl=3D04 flg=3D05

- -

   -value=3D"8542"

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#1: nam=3D'file -open' ela=3D 0 p1=3D0 p2=3D0 p3=3D0

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6671 p3=3D1

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6678 p3=3D1

- -

FETCH -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

*** = -2002-09-12 -16:14:56.200

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2496 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

XCTEND rlbk=3D0, -rd_only=3D1

- -

STAT = -#1 id=3D1 cnt=3D1 -pid=3D0 pos=3D0 obj=3D5156 op=3D'TABLE ACCESS BY INDEX ROWID T = -'

- -

STAT = -#1 id=3D2 cnt=3D2 -pid=3D1 pos=3D1 obj=3D5157 op=3D'INDEX UNIQUE SCAN '

- -
- -

 

- -

 

- -

$ perl -V

- -

Summary of my perl5 (revision 5.0 version 6 subversion 0) = -configuration:

- -

  Platform:

- -

    osname=3Dlinux, osvers=3D2.2.5-22smp, = -archname=3Di386-linux

- -

    uname=3D'linux porky.devel.redhat.com = -2.2.5-22smp #1 smp -wed jun 2 09:11:51 edt 1999 i686 unknown '

- -

    config_args=3D'-des -Doptimize=3D-O2 = --march=3Di386 -mcpu=3Di686 --Dcc=3Dgcc -Dcccdlflags=3D-fPIC -Dinstallprefix=3D/usr -Dprefix=3D/usr = --Darchname=3Di386-linux --Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm -Di_gdbm -Di_shadow = --Di_syslog -Dman3ext=3D3pm -Uuselargefiles'

- -

    hint=3Drecommended, useposix=3Dtrue, = -d_sigaction=3Ddefine

- -

    usethreads=3Dundef use5005threads=3Dundef = -useithreads=3Dundef -usemultiplicity=3Dundef

- -

    useperlio=3Dundef d_sfio=3Dundef = -uselargefiles=3Dundef

- -

    use64bitint=3Dundef use64bitall=3Dundef = -uselongdouble=3Dundef -usesocks=3Dundef

- -

  Compiler:

- -

    cc=3D'gcc', optimize=3D'-O2 -march=3Di386 = --mcpu=3Di686', gccversion=3D2.96 -20000731 (experimental)

- -

    = -cppflags=3D'-fno-strict-aliasing'

- -

    ccflags = -=3D'-fno-strict-aliasing'

- -

    stdchar=3D'char', d_stdstdio=3Ddefine, = -usevfork=3Dfalse

- -

    intsize=3D4, longsize=3D4, ptrsize=3D4, = -doublesize=3D8

- -

    d_longlong=3Ddefine, longlongsize=3D8, = -d_longdbl=3Ddefine, -longdblsize=3D12

- -

    ivtype=3D'long', ivsize=3D4, = -nvtype=3D'double', nvsize=3D8, Off_t=3D'off_t', -lseeksize=3D4

- -

    alignbytes=3D4, usemymalloc=3Dn, = -prototype=3Ddefine

- -

  Linker and Libraries:

- -

    ld=3D'gcc', ldflags =3D' = --L/usr/local/lib'

- -

    libpth=3D/usr/local/lib /lib = -/usr/lib

- -

    libs=3D-lnsl -ldl -lm -lc = --lcrypt

- -

    libc=3D/lib/libc-2.1.92.so, so=3Dso, = -useshrplib=3Dfalse, libperl=3Dlibperl.a

- -

  Dynamic Linking:

- -

    dlsrc=3Ddl_dlopen.xs, dlext=3Dso, = -d_dlsymun=3Dundef, ccdlflags=3D'-rdynamic'

- -

    cccdlflags=3D'-fPIC', lddlflags=3D'-shared = --L/usr/local/lib'

- -

 

- -

 

- -

Characteristics of this binary (from libperl): = -

- -

  Compile-time options:

- -

  Built under linux

- -

  Compiled at Aug  7 2000 10:59:51

- -

  @INC:

- -

    = -/usr/lib/perl5/5.6.0/i386-linux

- -

    /usr/lib/perl5/5.6.0

- -

    = -/usr/lib/perl5/site_perl/5.6.0/i386-linux

- -

    = -/usr/lib/perl5/site_perl/5.6.0

- -

    /usr/lib/perl5/site_perl

- -

    .

- -

 

- -

 

- -

Other site information

- -

- Redhat Linux 7.0

- -

- Oracle 8.1.6.1.0

- -

- DBD-Oracle 1.12

- -

- DBI 1.30

- -

 

- -
- - - - - -------=_NextPart_001_016B_01C25A80.D1557E70-- - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: application/octet-stream; - name="ex1.log" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="ex1.log" - - DBI::db=3DHASH(0x8235a74) trace level set to 9 in DBI 1.30-nothread=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'alter session set events '10046 trace name context forever, level 12'')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240f68)=3D>DBI::st=3DHASH(0x8240f98),= - DBD::Oracle::st, 8240f74, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= -OCIHandleAlloc(0x82465d8,0x826c948,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826bf48,0x82559ec,'alter session set events '10046 = -trace name context forever, level 12'',69,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0x826c94c,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql ALTER=0A= - dbd_describe skipped for ALTER=0A= - <- prepare=3D DBI::st=3DHASH(0x8240f68) at ex1.pl line 38=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240f68)~0x8240f98)=0A= - dbd_st_execute ALTER (out0, lob0)...=0A= -OCIStmtExecute(0x82557c4,0x826bf48,0x82559ec,1,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff654,(nil),9,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute ALTER returned (SUCCESS, rpc0, fn52, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 39=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'select key, fkey, value from t where key=3D?')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240fe0)=3D>DBI::st=3DHASH(0x8240fb0),= - DBD::Oracle::st, 8240fec, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= - dbd_preparse scanned 1 distinct placeholders=0A= -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where = -key=3D:p1',44,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql SELECT=0A= - dbd_describe SELECT (EXPLICIT, lb 80)...=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3DSUCCES= -S=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3dc,(nil),18,0x82559ec)=3DSUCC= -ESS=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d1c0,1)=3DSUCCESS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d6,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d4,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d8,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1da,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1db,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1e8,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 1: 'KEY' NO null , otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d200,2)=3DSUCCESS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d216,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d214,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d218,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d228,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 2: 'FKEY' NULLable, otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d240,3)=3DSUCCESS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d256,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d254,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d258,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d268,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 3: 'VALUE' NULLable, otype 1-> 5, dbsize 32/33, p32.s0=0A= -OCIAttrSet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3d4,4,11,0x82559ec)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d1c4,0x82559ec,1,0x826e8d0,134,5,0x826d438,= -0x826d448,0x826d458,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d204,0x82559ec,2,0x826eaf8,134,5,0x826ca28,= -0x826ca38,0x826ca48,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d244,0x82559ec,3,0x826cbb8,33,5,0x826ca58,0= -x826cbe0,0x826cbf0,0)=3DSUCCESS=0A= - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231)=0A= - <- prepare=3D DBI::st=3DHASH(0x8240fe0) at ex1.pl line 50=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240f98)~INNER)=0A= -OCIHandleFree(0x826bf48,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef at ex1.pl line 51=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240fe0)~0x8240fb0 = -'8542')=0A= - bind :p1 <=3D=3D '8542' (type 0)=0A= - bind :p1 <=3D=3D '8542' (size 4/5/0, ptype 7, otype 1)=0A= - bind :p1 <=3D=3D '8542' (size 4/4, otype 1, indp 0, at_exec 1)=0A= -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb= -6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS=0A= -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da= -090)=3DSUCCESS=0A= - bind :p1 done with ftype 1=0A= - dbd_st_execute SELECT (out0, lob0)...=0A= - in ':p1' [0,0]: len 4, ind 0=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 51=0A= - -> fetchall_arrayref for DBD::Oracle::st = -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0)=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DSUCCESS=0A= - dbih_setup_fbav for 3 fields =3D> 0x8240fbc=0A= - dbd_st_fetch 3 fields SUCCESS=0A= - 0 (rc=3D0): '8542'=0A= - 1 (rc=3D0): '8542'=0A= - 2 (rc=3D0): 'value'=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DNO_DATA=0A= - dbd_st_fetch no-more-data=0A= - <- fetchall_arrayref=3D [ ARRAY(0x82411f0) ] row1 at ex1.pl line 62=0A= - -> disconnect for DBD::Oracle::db = -(DBI::db=3DHASH(0x8235b34)~0x8235a74)=0A= -OCISessionEnd(0x82557c4,0x82559ec,0x826c384,0)=3DSUCCESS=0A= -OCIServerDetach(0x8255834,0x82559ec,0)=3DSUCCESS=0A= - <- disconnect=3D 1 at ex1.pl line 74=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240fb0)~INNER)=0A= -OCIHandleFree(0x826e4a0,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -> DESTROY for DBD::Oracle::db (DBI::db=3DHASH(0x8235a74)~INNER)=0A= -OCIHandleFree(0x826c384,OCI_HTYPE_SESSION)=3DSUCCESS=0A= -OCIHandleFree(0x8255834,OCI_HTYPE_SERVER)=3DSUCCESS=0A= -OCIHandleFree(0x82557c4,OCI_HTYPE_SVCCTX)=3DSUCCESS=0A= -OCIHandleFree(0x82559ec,OCI_HTYPE_ERROR)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -------=_NextPart_000_016A_01C25A80.D1527130-- - - -From timbo@dansat.data-plan.com Fri Sep 13 07:30:31 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6UUC04053 - for ; Fri, 13 Sep 2002 07:30:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:30:30 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031871608:20:03733:55; Thu, 12 Sep 2002 23:00:08 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id ab2122693; 12 Sep 2002 23:00 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id AE0642F0B8A - for ; Thu, 12 Sep 2002 18:58:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id 931D42F0D0A - for ; Thu, 12 Sep 2002 18:58:19 -0400 (EDT) -Received: (qmail 57270 messnum 519666 invoked from network[159.134.164.69/p69.as1.limerick1.eircom.net]); 12 Sep 2002 22:58:17 -0000 -Received: from p69.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.69) - by mail03.svc.cra.dublin.eircom.net (qp 57270) with SMTP; 12 Sep 2002 22:58:17 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8CMwEQ02798; - Thu, 12 Sep 2002 23:58:14 +0100 (BST) - (envelope-from timbo) -Date: Thu, 12 Sep 2002 23:58:14 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls -Message-ID: <20020912225814.GG539@dansat.data-plan.com> -References: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 3530 -Lines: 77 - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCESS - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 '8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCESS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - -From cary.millsap@hotsos.com Fri Sep 13 07:31:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6VsC04590 - for ; Fri, 13 Sep 2002 07:31:54 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:31:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031889643:20:09494:0; Fri, 13 Sep 2002 04:00:43 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-2.mail.demon.net - id aa2008866; 13 Sep 2002 4:00 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id C94C67264F - for ; Fri, 13 Sep 2002 00:00:07 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by wormwood.pobox.com (Postfix) with ESMTP id A821072676 - for ; Fri, 13 Sep 2002 00:00:06 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D405n19404 - for ; Thu, 12 Sep 2002 23:00:05 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 22:59:56 -0500 -Message-ID: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020912225814.GG539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4825 -Lines: 129 - -Tim, - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Thursday, September 12, 2002 5:58 PM -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you -on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer -to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make -the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I -can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect -that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - - -From timbo@dansat.data-plan.com Fri Sep 13 10:48:59 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D9mwC06022 - for ; Fri, 13 Sep 2002 10:48:58 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 10:48:58 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031907122:20:19599:21; Fri, 13 Sep 2002 08:52:02 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2129553; 13 Sep 2002 8:52 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 99E263E660 - for ; Fri, 13 Sep 2002 04:51:54 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-2.pobox.com (Postfix) with SMTP id 721613E637 - for ; Fri, 13 Sep 2002 04:51:53 -0400 (EDT) -Received: (qmail 29161 messnum 524631 invoked from network[159.134.167.5/p773.as1.limerick1.eircom.net]); 13 Sep 2002 08:51:51 -0000 -Received: from p773.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.5) - by mail03.svc.cra.dublin.eircom.net (qp 29161) with SMTP; 13 Sep 2002 08:51:51 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8D8prO05752; - Fri, 13 Sep 2002 09:51:53 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 09:51:53 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913085153.GJ539@dansat.data-plan.com> -References: <20020912225814.GG539@dansat.data-plan.com> <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 6172 -Lines: 154 - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more "official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -> key=:p1',44,1,0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - -From cary.millsap@hotsos.com Fri Sep 13 17:52:40 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DGqdC10778 - for ; Fri, 13 Sep 2002 17:52:39 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 17:52:39 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031932999:10:25604:102; Fri, 13 Sep 2002 16:03:19 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101673; 13 Sep 2002 16:03 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E4A692C078 - for ; Fri, 13 Sep 2002 12:02:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 1609E2C03F - for ; Fri, 13 Sep 2002 12:02:29 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DG2Sn24856 - for ; Fri, 13 Sep 2002 11:02:28 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Fri, 13 Sep 2002 11:02:20 -0500 -Message-ID: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913085153.GJ539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 9234 -Lines: 248 - -Tim, - -I think it's important for a developer to have the ability to turn this -on and off. But I would argue that 0 is the correct default. I think of -it as a probability times cost function. The cost of leaving the setting -at 1 accidentally in a production application is pretty high: if the app -doesn't scale (because it's parsing too much), then it jeopardizes the -business' ability to succeed with it. - -The probability of leaving the option set to 1 accidentally during -production is very high. A point in evidence is that I didn't find the -parameter until I corresponded personally with you. I in fact *still* -don't know where to find it. I've checked Descartes & Bunce, perldoc -DBI, and perldoc DBD::Oracle without finding it yet... - -If the default were 0, the probability of leaving the option set to 0 -accidentally during development would be much lower. A developer faced -with a SQL syntax problem he doesn't understand will do the research -necessary to fix that problem. He can't release his code until he does. - -The problem with the default of 1 is, in my opinion, that most -developers will never learn of the feature, and they'll accidentally -leave it turned on in production. The proportion of developers who -competently performance-test their code is, unfortunately, -microscopically small. But they all do some level of functional testing. - -I would recommend making the ora_check_sql feature a more prominently -documented feature, presumably in "perldoc DBD::Oracle". - -I did learn in a test that specifying the option in the DBI->connect() -call doesn't do anything. Is it possible that you could allow us to -specify it at the connection level? The workaround is to do something -like this: - - use Getopt::Long; - my %prepare_attr = (ora_check_sql=>0); - GetOptions("dev"=>\$dev); - $prepare_attr{ora_check_sql} = 1 if $dev; - # developer must specify the command-line flag to get the -unscalable - # behavior that's necessary for functional testing - ... - $sth = $dbh->prepare($sql, %prepare_attr); # MUST specify -%p..attr - -...But I doubt that most Oracle application developers would come up -with this without some coaching. - -I'll definitely keep an eye open for projects you might like. It would -be a hell of an opportunity for someone to have you, I think. It seems -that if you could make a list like Oracle-L (1,900 people) aware that -there's an opportunity, it would improve your chances of finding -something quickly. It's of course bad taste to advertise oneself overtly -on those lists, but there is almost always a clever way to do it anyway -without offending anyone. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:52 AM -To: Cary Millsap -Cc: 'Tim Bunce' -Subject: Re: two Oracle parse calls - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge -to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our -lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a -preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more -"official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw -you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 -trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret -them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t -where -> key=:p1',44,1,0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: -231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), -{ -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call -parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:37 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLbC13725 - for ; Fri, 13 Sep 2002 23:21:37 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:37 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031951069:20:15816:152; Fri, 13 Sep 2002 21:04:29 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2120669; 13 Sep 2002 21:04 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 544863E642 - for ; Fri, 13 Sep 2002 17:04:17 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id 0AE7C3E667 - for ; Fri, 13 Sep 2002 17:04:16 -0400 (EDT) -Received: (qmail 16221 messnum 355694 invoked from network[159.134.166.226/p738.as1.limerick1.eircom.net]); 13 Sep 2002 21:04:14 -0000 -Received: from p738.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.226) - by mail05.svc.cra.dublin.eircom.net (qp 16221) with SMTP; 13 Sep 2002 21:04:14 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DL4Lx12642; - Fri, 13 Sep 2002 22:04:21 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:04:21 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913210421.GR539@dansat.data-plan.com> -References: <20020913085153.GJ539@dansat.data-plan.com> <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 3078 -Lines: 70 - -On Fri, Sep 13, 2002 at 11:02:20AM -0500, Cary Millsap wrote: -> Tim, -> -> I think it's important for a developer to have the ability to turn this -> on and off. But I would argue that 0 is the correct default. I think of -> it as a probability times cost function. The cost of leaving the setting -> at 1 accidentally in a production application is pretty high: if the app -> doesn't scale (because it's parsing too much), then it jeopardizes the -> business' ability to succeed with it. -> -> The probability of leaving the option set to 1 accidentally during -> production is very high. A point in evidence is that I didn't find the -> parameter until I corresponded personally with you. I in fact *still* -> don't know where to find it. I've checked Descartes & Bunce, perldoc -> DBI, and perldoc DBD::Oracle without finding it yet... - -It's not documented. - -As I recall it... originally DBD::Oracle defered the describe as -long as possible. But people reported very slow select performance: - - http://www.faqchest.com/prgm/dbi-l/dbi-99/dbi-9910/dbi-991005/dbi99101218_28018.html - -Turned out that the row cache logic needed the describe to try to -work out an optimal row cache size. Without the describe the row -cache wasn't getting set up. - -At some point I added code that would just set OCI_ATTR_PREFETCH_MEMORY -to a set size if ora_check_sql was 0. But I can't remember now why -I left ora_check_sql=1. - -It was possibly in relation to wanting to be able to use the -OCI_ATTR_PARSE_ERROR_OFFSET attribute to be able to highlight the -point in a query where the error was detected. But I think execute() -needs to be able to do that anyway (to catch syntax errors in -non-select statements). - -There is another problem. If the describe has been defered and the -application uses $sth->{NAME} or other similar attribute then the -describe has to be done at that point. The code is thee to do that -but the problem is how should the DBI behave if there's an error -in the SQL? It currently always croaks (rather than return undef, -in order to give a useful error message), but that's rather surprising -behaviour to many people and very unhelpful to some. - -There may well be other subtle issues that I can't recall right now. - -> I would recommend making the ora_check_sql feature a more prominently -> documented feature, presumably in "perldoc DBD::Oracle". -> -> I did learn in a test that specifying the option in the DBI->connect() -> call doesn't do anything. Is it possible that you could allow us to -> specify it at the connection level? - -By making it a database handle attribute, yes, that would be my plan. - -> I'll definitely keep an eye open for projects you might like. It would -> be a hell of an opportunity for someone to have you, I think. - -Thanks. - -> It seems that if you could make a list like Oracle-L (1,900 people) aware -> that there's an opportunity, it would improve your chances of finding -> something quickly. It's of course bad taste to advertise oneself overtly -> on those lists, but there is almost always a clever way to do it anyway -> without offending anyone. - -:-) - -Tim. - -From cary.millsap@hotsos.com Fri Sep 13 07:32:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6W1C04656 - for ; Fri, 13 Sep 2002 07:32:01 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:32:01 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031891038:20:04710:44; Fri, 13 Sep 2002 04:23:58 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id ab2004623; 13 Sep 2002 4:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 942A82BF2C - for ; Fri, 13 Sep 2002 00:23:44 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 73C982BF33 - for ; Fri, 13 Sep 2002 00:23:42 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D4Ndn19584 - for ; Thu, 12 Sep 2002 23:23:39 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 23:23:30 -0500 -Message-ID: <019301c25add$53f5dfd0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0194_01C25AB3.6B1FD7D0" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -Content-Length: 36859 -Lines: 1209 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Well, that was easy. Setting ora_check_sql=>0 does solve the problem. - - - -I now shift into "Please make 0 the default" mode. - - - -Here are the Oracle trace files, by the way, with a splash of color to -illustrate how the Oracle kernel sees what's going on (I hope you have -an HTML mail reader)... - - - -With {ora_check_sql=>1} (or no setting at all), here's what Oracle does -for the application: - - - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - - - -The PARSING IN CURSOR section tells us what SQL it is that we're -executing. Each line beginning with "PARSE" is emitted only when Oracle -executes a parse call. There are two. The first is wasted. - - - -Here's the same application with {ora_check_sql=>1} (the official new -default value, I am sure :-)): - - - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=109776065 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -FETCH #1:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=109776065 - - - -One parse call; problem solved. - - - -Thank you sincerely for your help. - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- -From: Cary Millsap [mailto:cary.millsap@hotsos.com] -Sent: Thursday, September 12, 2002 11:00 PM -To: 'Tim Bunce' -Subject: RE: two Oracle parse calls - - - -Tim, - - - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - - - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- - -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] - -Sent: Thursday, September 12, 2002 5:58 PM - -To: Cary Millsap - -Cc: tim.bunce@pobox.com - -Subject: two Oracle parse calls - - - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: - -> Tim, - -> - -> How are you doing? I hope you've had a good two years since I saw you -on - -> the Oracle Geek Cruise event. - - - -Yes thanks. And you? - - - -> I've been working on a project this year to construct a book about - -> optimizing Oracle response time. In my research, I've discovered - -> something about the DBI that I didn't expect: it executes two Oracle - -> parse calls for every one that I would expect an efficient DBI layer -to - -> make. I've included my Perl source (below), the Oracle level-12 trace - -> data that shows the sequence of calls it's receiving from the Perl - -> application (below), a level-9 DBI trace from the application - -> (attached), and our version information (below). - -> - -> I was hoping that by showing you this specific data, you could make -the - -> problem go away. - - - -I can only do what OCI lets me do... but within that I'll do what I -can... - - - -I'm not familar with Oracle trace logs so I can't readily intrepret them - -and I'll take what you say at face value. - - - -But I am familar with DBD::Oracle :) and the logs it writes :) - - - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -> $sth->execute($key); - - - - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - - dbd_preparse scanned 1 distinct placeholders - -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS - -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - - dbd_st_prepare'd sql SELECT - - dbd_describe SELECT (EXPLICIT, lb 80)... - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') - -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS - -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - - bind :p1 done with ftype 1 - - dbd_st_execute SELECT (out0, lob0)... - - in ':p1' [0,0]: len 4, ind 0 - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - - <- execute= '0E0' at ex1.pl line 51 - - - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - - - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -call that prepare() does. - - - -It doesn't do that for non-select statements so you could check if - -non-selects also have two parse calls. - - - -Also try doing - - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - - - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the - -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -is possibly redundant and could be removed (but Oracle ought to detect -that - -anyway and not make a round-trip for it, and certainly not call parse). - - - -If non-selects only have one parse call but ora_check_sql=>0 doesn't - -fix selects, then I might be able to do a simple patch to avoid the - -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - - - -Then the issue will be: should ora_check_sql=>0 be the default... - - - -Tim. - - - -p.s. I'd love a copy of your book when it's ready! - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Well, that was easy. Setting ora_check_sql=3D>0 = -does solve the -problem.

- -

 

- -

I now shift into "Please make 0 the = -default" mode.

- -

 

- -

Here are the Oracle trace files, by the way, with a = -splash -of color to illustrate how the Oracle kernel sees what’s going on = -(I hope -you have an HTML mail reader)...

- -

 

- -

With {ora_check_sql=3D>1} (or no setting at all), = -here’s -what Oracle does for the application:

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #2 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312018 = -hv=3D1997601641 ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF STMT

- -

PARSE = -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312019 = -hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF = -STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

FETCH = -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

 

- -

The PARSING IN CURSOR section tells us what SQL it is = -that -we’re executing. Each line beginning with “PARSE” is = -emitted -only when Oracle executes a parse call. There are two. The first is = -wasted.

- -

 

- -

Here’s the same application with = -{ora_check_sql=3D>1} (the official new = -default value, I -am sure J):

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 = -dep=3D0 uid=3D12 -oct=3D3 lid=3D12 tim=3D109776065 hv=3D1997601641 = -ad=3D'54af1384'

- -

select key, fkey, value from = -t where -key=3D:p1

- -

END OF STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

FETCH = -#1:c=3D0,e=3D0,p=3D0,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D109= -776065

- -

 

- -

One parse call; problem solved.

- -

 

- -

Thank you sincerely for your help.

- -

 

- -

 

- -

Cary = -Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System = -Performance, -Feb 9-12 Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 = -Middelfart Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----
-From: Cary Millsap [mailto:cary.millsap@hotsos.com]
-Sent: Thursday, September 12, 2002 11:00 PM
-To: 'Tim Bunce'
-Subject: RE: two Oracle parse calls

- -

 

- -

Tim,

- -

 

- -

Thanks so very much. The attribute ora_check_sql=3D>0 is new = -knowledge -to me; this is a nice reward for having written to you. I will test it = -either -tonight or the first thing tomorrow and then inform you of the results -immediately after that. If it solves the problem, then I will lobby you = -to make -0 the default value and probably consider the issue "problem = -solved."

- -

 

- -

Things are very well, thank you. I've been at home with my = -family now -for over three straight weeks, and we're having a nice time of our lives = -these -days with the business settling into stride a bit. Tonight is a big = -night for -me. I've just crossed the line of accepting a preliminary offer from = -O'Reilly. -This book project has actually been underway for quite some time now, = -but as of -tonight it's quite a bit more "official."

- -

 

- -

 

- -

Cary Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec = -9-11 -Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System Performance, Feb = -9-12 -Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 Middelfart = -Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----

- -

From: Tim Bunce [mailto:Tim.Bunce@pobox.com]

- -

Sent: Thursday, September 12, 2002 5:58 PM

- -

To: Cary Millsap

- -

Cc: tim.bunce@pobox.com

- -

Subject: two Oracle parse calls

- -

 

- -

On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap = -wrote:

- -

> Tim,

- -

>

- -

> How are you doing? I hope you've had a good two years since = -I saw -you on

- -

> the Oracle Geek Cruise event.

- -

 

- -

Yes thanks. And you?

- -

 

- -

> I've been working on a project this year to construct a = -book about

- -

> optimizing Oracle response time. In my research, I've = -discovered

- -

> something about the DBI that I didn't expect: it executes = -two -Oracle

- -

> parse calls for every one that I would expect an efficient = -DBI -layer to

- -

> make. I've included my Perl source (below), the Oracle = -level-12 -trace

- -

> data that shows the sequence of calls it's receiving from = -the Perl

- -

> application (below), a level-9 DBI trace from the = -application

- -

> (attached), and our version information = -(below).

- -

>

- -

> I was hoping that by showing you this specific data, you = -could -make the

- -

> problem go away.

- -

 

- -

I can only do what OCI lets me do... but within that I'll do = -what I -can...

- -

 

- -

I'm not familar with Oracle trace logs so I can't readily = -intrepret -them

- -

and I'll take what you say at face value.

- -

 

- -

But I am familar with DBD::Oracle :) and the logs it writes = -:)

- -

 

- -

> $sth =3D $dbh->prepare(q(select key, fkey, value from t = -where -key=3D?));

- -

> $sth->execute($key);

- -

 

- -

 

- -

    -> prepare for DBD::Oracle::db -(DBI::db=3DHASH(0x8235b34)~0x8235a74 'select key, fkey, value from t = -where -key=3D?')

- -

    dbd_preparse scanned 1 distinct = -placeholders

- -

OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCC= -ESS

- -

OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from = -t -where key=3D:p1',44,1,0)=3DSUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)= -=3DSUCCESS

- -

    dbd_st_prepare'd sql SELECT

- -

    dbd_describe SELECT (EXPLICIT, lb = -80)...

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3D= -SUCCESS

- -

    dbd_describe'd 3 columns (row bytes: 76 max, = -40 est -avg, cache: 231)

- -

    <- prepare=3D DBI::st=3DHASH(0x8240fe0) at = -ex1.pl -line 50

- -

    -> execute for DBD::Oracle::st -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0 '8542')

- -

OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x8= -26cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS - -

OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40= -,0x401da090)=3DSUCCESS

- -

       bind :p1 done with ftype = -1

- -

    dbd_st_execute SELECT (out0, = -lob0)...

- -

       in  ':p1' [0,0]: = -len  4, -ind 0

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3D= -SUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec= -)=3DSUCCESS

- -

    dbd_st_execute SELECT returned (SUCCESS, = -rpc0, fn4, -out0)

- -

    <- execute=3D '0E0' at ex1.pl line = -51

- -

 

- -

Given those OCI calls, what is DBD::Oracle doing that it = -shouldn't?

- -

 

- -

I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

call that prepare() does.

- -

 

- -

It doesn't do that for non-select statements so you could check = -if

- -

non-selects also have two parse calls.

- -

 

- -

Also try doing

- -

  $sth =3D $dbh->prepare(q(select key, fkey, value from = -t where -key=3D?), { ora_check_sql=3D> 0 });

- -

 

- -

which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till = -after the

- -

main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

is possibly redundant and could be removed (but Oracle ought to = -detect -that

- -

anyway and not make a round-trip for it, and certainly not call = -parse).

- -

 

- -

If non-selects only have one parse call but = -ora_check_sql=3D>0 doesn't

- -

fix selects, then I might be able to do a simple patch to avoid = -the

- -

OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if = -ora_check_sql=3D>0.

- -

 

- -

Then the issue will be: should ora_check_sql=3D>0 be the = -default...

- -

 

- -

Tim.

- -

 

- -

p.s. I'd love a copy of your book when it's = -ready!

- -
- - - - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0-- - - -From cary.millsap@hotsos.com Fri Sep 13 21:17:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DKHhC12417 - for ; Fri, 13 Sep 2002 21:17:43 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 21:17:43 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031946929:20:18513:70; Fri, 13 Sep 2002 19:55:29 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2018248; 13 Sep 2002 19:55 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 7FC402C01F - for ; Fri, 13 Sep 2002 15:55:06 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 76A5E2BFE1 - for ; Fri, 13 Sep 2002 15:55:05 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DJt4n26736 - for ; Fri, 13 Sep 2002 14:55:04 -0500 -From: "Cary Millsap" -To: "Tim Bunce" -Subject: A little more data -Date: Fri, 13 Sep 2002 14:54:56 -0500 -Message-ID: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0203_01C25B35.89729F60" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4948 -Lines: 166 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -I hope this is helpful. I have noticed that I cannot produce the -extra-parse problem on my 8.1.7 laptop database, no matter what the -setting of ora_check_sql. All of the data I've sent you is from our -8.1.6 Linux database. If you really needed it, I could produce level-9 -DBI trace data from identical tests on both platforms, but I won't spend -the time doing that unless you say it will help... - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - - - - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

I hope this is helpful… I have noticed that I = -cannot -produce the extra-parse problem on my 8.1.7 laptop database, no matter = -what the -setting of ora_check_sql. All of the data I’ve sent you is from = -our 8.1.6 -Linux database. If you really needed it, I could produce level-9 DBI = -trace data -from identical tests on both platforms, but I won’t spend the time = -doing -that unless you say it will help...

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -

 

- -
- - - - - -------=_NextPart_000_0203_01C25B35.89729F60-- - - -From timbo@dansat.data-plan.com Fri Sep 13 22:05:30 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL5UC12942 - for ; Fri, 13 Sep 2002 22:05:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:05:30 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031948458:10:20432:5; Fri, 13 Sep 2002 20:20:58 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-1.mail.demon.net - id aa1020174; 13 Sep 2002 20:20 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 8A60E3E659 - for ; Fri, 13 Sep 2002 16:20:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id CAC663E685 - for ; Fri, 13 Sep 2002 16:20:36 -0400 (EDT) -Received: (qmail 37861 messnum 258096 invoked from network[159.134.164.124/p124.as1.limerick1.eircom.net]); 13 Sep 2002 20:20:35 -0000 -Received: from p124.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.124) - by mail05.svc.cra.dublin.eircom.net (qp 37861) with SMTP; 13 Sep 2002 20:20:35 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DKKhu12535; - Fri, 13 Sep 2002 21:20:43 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 21:20:43 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data -Message-ID: <20020913202043.GO539@dansat.data-plan.com> -References: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1098 -Lines: 34 - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - -From cary.millsap@hotsos.com Fri Sep 13 22:04:47 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL4kC12684 - for ; Fri, 13 Sep 2002 22:04:46 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:04:46 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031949629:20:13745:23; Fri, 13 Sep 2002 20:40:29 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2013849; 13 Sep 2002 20:40 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 7D90A3E650 - for ; Fri, 13 Sep 2002 16:40:20 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-1.pobox.com (Postfix) with ESMTP id 785AB3E642 - for ; Fri, 13 Sep 2002 16:40:19 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DKeIn27106 - for ; Fri, 13 Sep 2002 15:40:18 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: A little more data -Date: Fri, 13 Sep 2002 15:40:10 -0500 -Message-ID: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913202043.GO539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 1999 -Lines: 63 - -Well, it's 1.06 on my Windows machine (the most up-to-date version -available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -but interesting that (admitting now that there's a new degree of freedom -running loose amid the test) "the older version performs better than the -newer one." :) That's certainly not a fair statement if the diff between -8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:21 PM -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't -spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:32 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLWC13692 - for ; Fri, 13 Sep 2002 23:21:32 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:32 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031952887:10:13297:20; Fri, 13 Sep 2002 21:34:47 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1118141; 13 Sep 2002 21:34 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C7D482BF23 - for ; Fri, 13 Sep 2002 17:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail00.svc.cra.dublin.eircom.net (mail00.svc.cra.dublin.eircom.net [159.134.118.16]) - by dolly1.pobox.com (Postfix) with SMTP id 8352A2BF6C - for ; Fri, 13 Sep 2002 17:34:36 -0400 (EDT) -Received: (qmail 5093 messnum 521124 invoked from network[159.134.164.134/p134.as1.limerick1.eircom.net]); 13 Sep 2002 21:34:34 -0000 -Received: from p134.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.134) - by mail00.svc.cra.dublin.eircom.net (qp 5093) with SMTP; 13 Sep 2002 21:34:34 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DLYeI13070; - Fri, 13 Sep 2002 22:34:40 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:34:40 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: A little more data -Message-ID: <20020913213440.GS539@dansat.data-plan.com> -References: <20020913202043.GO539@dansat.data-plan.com> <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 2282 -Lines: 69 - -According my RCS the default for ora_check_sql changed from 0 to 1 -around version 1.03. - -Tim. - -On Fri, Sep 13, 2002 at 03:40:10PM -0500, Cary Millsap wrote: -> Well, it's 1.06 on my Windows machine (the most up-to-date version -> available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -> but interesting that (admitting now that there's a new degree of freedom -> running loose amid the test) "the older version performs better than the -> newer one." :) That's certainly not a fair statement if the diff between -> 8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Friday, September 13, 2002 3:21 PM -> To: Cary Millsap -> Cc: Tim Bunce -> Subject: Re: A little more data -> -> If they're using the same version of DBD::Oracle then -> the change must me on the sever side. Maybe Oracle's -> woken up to the fact they don't need a second parse! -> -> Tim. -> -> On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > -> > -> > I hope this is helpful. I have noticed that I cannot produce the -> > extra-parse problem on my 8.1.7 laptop database, no matter what the -> > setting of ora_check_sql. All of the data I've sent you is from our -> > 8.1.6 Linux database. If you really needed it, I could produce level-9 -> > DBI trace data from identical tests on both platforms, but I won't -> spend -> > the time doing that unless you say it will help... -> > -> > -> > -> > Cary Millsap -> > Hotsos Enterprises, Ltd. -> > http://www.hotsos.com -> > -> > Upcoming events: -> > - Hotsos Clinic , Oct 1-3 San -> > Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> > - 2003 Hotsos Symposium on -> > OracleR System Performance, Feb 9-12 Dallas -> > - Next event: Miracle Database Forum , Sep -> > 20-22 Middlefart Denmark -> > -> > -> > -> - diff --git a/err_unsorted/err_xml.msg b/err_unsorted/err_xml.msg deleted file mode 100644 index 7a60a0cb..00000000 --- a/err_unsorted/err_xml.msg +++ /dev/null @@ -1,118 +0,0 @@ -From dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org Fri Aug 15 14:41:14 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h7FDe3MA043557 - for ; Fri, 15 Aug 2003 14:41:13 +0100 (BST) - (envelope-from dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 15 Aug 2003 14:41:13 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 19nc4X-0006LQ-BC; - Fri, 15 Aug 2003 10:44:41 +0000 -Received: from [207.106.49.22] (helo=dolly1.pobox.com) - by punt-3.mail.demon.net with esmtp id 19nc4X-0006LQ-BC - for pobox@dbi.demon.co.uk; Fri, 15 Aug 2003 10:44:41 +0000 -Received: from dolly1.pobox.com (localhost[127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 16F6B21C13B - for ; Fri, 15 Aug 2003 06:44:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.develooper.com[63.251.223.166]) - by dolly1.pobox.com (Postfix) with SMTP id 021F121C36F - for ; Fri, 15 Aug 2003 06:44:40 -0400 (EDT) -Received: (qmail 78180 invoked by uid 1005); 15 Aug 2003 10:44:34 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 71287 invoked by uid 76); 15 Aug 2003 10:32:13 -0000 -Delivered-To: dbi-users@perl.org -Received-SPF: unknown (domain of sender andyhassall@yahoo.com does not designate mailers: NXDOMAIN) -Message-ID: <20030815103200.24313.qmail@web9605.mail.yahoo.com> -Date: Fri, 15 Aug 2003 11:32:00 +0100 (BST) -From: =?iso-8859-1?q?Andy=20Hassall?= -Reply-To: andy@andyh.co.uk -Subject: Re: ERROR OCIDefineObject call needed but not implemented yet using XMLElement function -To: Susan Cassidy , dbi-users@perl.org -In-Reply-To: -MIME-Version: 1.0 -Content-Type: text/plain; charset=iso-8859-1 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.8 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,SPAM_PHRASE_01_02 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id h7FDe3MA043557 -Status: RO -Content-Length: 2299 -Lines: 65 - - --- Susan Cassidy wrote: > I am using DBD::Oracle. -I was on version 1.12, then I installed version -> 1.14, with the same result. -> -> This is Oracle 9.2.0. -> -> I have this select statement that works fine from SQL*Plus: -> -> select XMLElement("Sequences", -> XMLElement("Sequence", -> XMLATTRIBUTES ( b.local_name AS "ic-acckey", -> b.mol_type AS "molecule", -> n.seq_name AS "title"))) -> from gcg_bioseq b, gcg_annot_seq_name a, gcg_seq_name n -> where -> b.local_name = 'K00306' and -> b.seq_status = 'D' and -> b.seq_oid = a.seq_oid and -> a.seq_name_oid = n.seq_name_oid and -> n.name_type = 'LOCUS' -> -> -> When I run it via DBI/DBD I get this (trace level 2): -> -> DBI 1.32-nothread dispatch trace level set to 2 -> Note: perl is running without the recommended perl -w option -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x1b2314)~0x122bec ' -[snip -> Field 1 has an Oracle type (108) which is not explicitly supported -> fbh 1: -> -'XMLELEMENT("SEQUENCES",XMLELEMENT("SEQUENCE",XMLATTRIBUTES(B.LOCAL_NAMEAS"IC-ACCKEY",B.MOL_TYPEAS"MOLECULE",N.SEQ_NAMEAS"TITLE")))' -[snip] -> Error: prepare failed -> at line 56, error: ERROR OCIDefineObject call needed but not -> implemented yet -> -> Is there any other workaround for this than wrapping this up in a PL/SQL -> function? - - Don't rely on the implicit conversion to a string type that is done when -SQL*Plus displays an XMLElement; add .getClobVal() to the end of the -statement to retrieve it as a CLOB rather than the XMLElement object type -(which DBD::Oracle doesn't accept). - - i.e. - -select XMLElement("Sequences", - XMLElement("Sequence", - XMLATTRIBUTES ( b.local_name AS "ic-acckey", - b.mol_type AS "molecule", - n.seq_name AS "title"))).getClobVal() - from ... - - (or getStringVal() for a VARCHAR2) - -===== --- -Andy Hassall (andy@andyh.org) icq(5747695) http://www.andyh.co.uk -http://www.andyhsoftware.co.uk/space | disk usage analysis tool - -________________________________________________________________________ -Want to chat instantly with your online friends? Get the FREE Yahoo! -Messenger http://uk.messenger.yahoo.com/ - - diff --git a/err_unsorted/err_xml2.msg b/err_unsorted/err_xml2.msg deleted file mode 100644 index 3bb291c5..00000000 --- a/err_unsorted/err_xml2.msg +++ /dev/null @@ -1,700 +0,0 @@ -From dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org Fri Jan 30 12:50:15 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UClt3q069307 - for ; Fri, 30 Jan 2004 12:50:14 GMT - (envelope-from dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 12:50:14 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmWGJ-00057X-AG; - Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmWGJ-00057X-AG - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [207.8.214.3] (helo=puzzle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmWGI-0007XK-P3 - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:34 +0000 -Received: from puzzle.pobox.com (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 029E8701C6 - for ; Fri, 30 Jan 2004 05:52:34 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 12ABF701C1 - for ; Fri, 30 Jan 2004 05:52:30 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by puzzle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 05:51:10 -0500 (EST) -Received: (qmail 33345 invoked by uid 1005); 30 Jan 2004 10:50:36 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 33175 invoked by uid 76); 30 Jan 2004 10:50:26 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Fri, 30 Jan 2004 02:50:25 -0800 -Received: (qmail 21117 invoked by uid 225); 30 Jan 2004 10:48:52 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 21080 invoked by uid 507); 30 Jan 2004 10:48:49 -0000 -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Fri, 30 Jan 2004 02:48:46 -0800 -Received: (qmail 31958 invoked from network); 30 Jan 2004 11:50:38 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 30 Jan 2004 11:50:38 -0000 -Received: (qmail 6921 invoked from network); 30 Jan 2004 10:49:58 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 30 Jan 2004 10:49:58 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Fri, 30 Jan 2004 11:49:58 +0100 (CET) -Subject: DBD-Oracle and XMLType -From: Hendrik Fuss -To: "dbi-dev@perl.org" -Content-Type: multipart/mixed; boundary="=-fkyM33WAvQ5xV0uCPeSD" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 11:41:31 +0100 -Message-Id: <1075459292.7305.46.camel@mars> -Mime-Version: 1.0 -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.5 required=7.0 tests=MIME_LONG_LINE_QP,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01,TO_ADDRESS_EQ_REAL version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 8148 -Lines: 302 - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -Hi everyone, - -It's been a while since I last posted here. In September 2003 I was -trying to add support for binding XMLType objects to DBD-Oracle, so that -you could easily insert large (ie >4k) XML data into an XMLType table. - -Unfortunately my employer fired me in October 2003 and in the remaining -time I had to work on other projects, so I wasn't able to complete the -DBD project. Since I won't have access to an oracle database from now -on, I thought the least I can do is to provide my code as it is to the -list. Blame German economy. :-( - -The attached patch (based on DBD-Oracle 1.15) enables you to upload -XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -I added a function dbd_rebind_ph_nty for that purpose. You need to -create that XMLType object first using the C function -createxmlfromstring in xml.c. - -The XMLType object is either created from an OCIString or from a -temporary CLOB depending on the length of the source string. Have a look -at the bottom of ociap.h, all the (undocumented) XMLType functions are -there, and there are also some constants in oci.h. - -I'm not sure if the CLOB code currently works. - -Here is another code fragment: - - my $xml =3D createxml($dbh, 'Test document'); - my $sth =3D $dbh->prepare('INSERT INTO xml_type VALUES (?)'); - $sth->bind_param(1, $xml, { ora_type =3D> 108 }); # SQLT_NTY - $sth->execute(); - -Please note that this code is really just early development, which I -wouldn't publish under normal circumstances. :) I just hope it might me -useful to someone. - -Well then, time to say goodbye -thanks to Tim and everyone who contributed to dbi for a great piece of -software - -Cheers, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Description: -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - -151a152 -> case 108: /* SQLT_NTY */ -992a994,996 -> case SQL_UDT: -> return 108; /* Oracle NTY */ ->=20 -1004a1009,1072 -> static int -> dbd_rebind_ph_nty(sth, imp_sth, phs) -> SV* sth; -> imp_sth_t *imp_sth; -> phs_t *phs; -> { -> OCIType *tdo =3D NULL; -> sword status; -> SV* ptr; ->=20 -> if (phs->is_inout) -> croak("OUT binding for NTY is currently unsupported"); ->=20 -> /* ensure that the value is a support named object type */ -> /* (currently only OCIXMLType*) */ -> if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -> OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -> (CONST text*)"SYS", 3, -> (CONST text*)"XMLTYPE", 7, -> (CONST text*)0, 0, -> OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -> &tdo); ->=20 -> ptr =3D SvRV(phs->sv); -> phs->progv =3D (void*) SvIV(ptr); -> phs->maxlen =3D sizeof(OCIXMLType*); -> } -> else -> croak("Unsupported named object type for bind parameter"); ->=20 ->=20 -> /* bind by name */ ->=20 -> OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -> (text*)phs->name, (sb4)strlen(phs->name), -> (dvoid *) NULL, /* value supplied in BindObject later */ -> 0, -> (ub2)phs->ftype, 0, -> NULL, -> 0, 0, -> NULL, -> (ub4)OCI_DEFAULT, -> status -> ); ->=20 -> if (status !=3D OCI_SUCCESS) { -> oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -> return 0; -> } -> if (DBIS->debug >=3D 3) -> PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); ->=20 ->=20 -> /* bind the object */ ->=20 -> OCIBindObject(phs->bndhp, imp_sth->errhp, -> (CONST OCIType*)tdo, -> (dvoid **)&phs->progv, -> (ub4*)NULL, -> (dvoid **)NULL, -> (ub4*)NULL); ->=20 -> return 2; -> } -1309a1378,1380 -> case 108: -> done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -> break; -1331c1403 -< int at_exec =3D (phs->desc_h =3D=3D NULL); ---- -> int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); -1419c1491 -< if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) ---- -> if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQL= -T_NTY)) -1420a1493 -> /* ref allowed for OCIXMLType* */ -2219a2293 -> case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Disposition: attachment; filename=xml.c -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; name=xml.c; charset=ISO-8859-1 - -#include "oci.h" -#include - -/* This helper function creates an XMLType object from a string source. - * - * The resulting object can be bound to a placeholder, if ora_type =3D> - * SQLT_NTY is specified. - */ - -static void checkerr(errhp, status) -OCIError *errhp; -sword status; -{ - text errbuf[512]; - ub4 buflen; - sb4 errcode; - - switch (status) - { - case OCI_SUCCESS: - break; - case OCI_SUCCESS_WITH_INFO: - printf("Error - OCI_SUCCESS_WITH_INFO\n"); - break; - case OCI_NEED_DATA: - printf("Error - OCI_NEED_DATA\n"); - break; - case OCI_NO_DATA: - printf("Error - OCI_NO_DATA\n"); - break; - case OCI_ERROR: - OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, - errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR); - printf("Error - %s\n", errbuf); - exit(1); - break; - case OCI_INVALID_HANDLE: - printf("Error - OCI_INVALID_HANDLE\n"); - break; - case OCI_STILL_EXECUTING: - printf("Error - OCI_STILL_EXECUTE\n"); - break; - case OCI_CONTINUE: - printf("Error - OCI_CONTINUE\n"); - break; - default: - break; - } -} - - -#define MAX_OCISTRING_LEN 32766 - -SV* createxmlfromstring(SV* dbh, char* source) { - OCIXMLType *xml =3D NULL; - ub4 len; - ub1 src_type; - dvoid* src_ptr =3D NULL; - D_imp_dbh(dbh); - SV* sv_dest; - - len =3D strlen(source); - if(len > MAX_OCISTRING_LEN) { - src_type =3D OCI_XMLTYPE_CREATE_CLOB; - - printf("OCIDescriptorAlloc\n"); - checkerr( imp_dbh->errhp, - OCIDescriptorAlloc((dvoid*)imp_dbh->envhp, - (dvoid **)&src_ptr, - (ub4)OCI_DTYPE_LOB, - (size_t)0, - (dvoid**)0) ); - - printf("OCILobCreateTemporary\n"); - checkerr( imp_dbh->errhp, - OCILobCreateTemporary(imp_dbh->svchp, - imp_dbh->errhp,=20 - (OCILobLocator*) src_ptr, - (ub2)0,=20 - SQLCS_IMPLICIT,=20 - OCI_TEMP_CLOB,=20 - OCI_ATTR_NOCACHE,=20 - OCI_DURATION_SESSION) ); - - printf("OCILobWrite\n"); - checkerr (imp_dbh->errhp, - OCILobWriteAppend(imp_dbh->svchp, - imp_dbh->errhp, - (OCILobLocator*) src_ptr, - &len,=20 - (ub1*)source, - len, - OCI_ONE_PIECE, - (dvoid *)0,=20 - (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, - 0, - SQLCS_IMPLICIT)); - - } else { - src_type =3D OCI_XMLTYPE_CREATE_OCISTRING; - - printf("OCIStringAssignText\n"); - checkerr( imp_dbh->errhp, - OCIStringAssignText(imp_dbh->envhp, - imp_dbh->errhp,=20 - (CONST text*) source,=20 - (ub2) strlen(source), - (OCIString **) &src_ptr) - ); - } - - printf("OCIXMLTypeCreateFromSrc\n"); - checkerr( imp_dbh->errhp, - OCIXMLTypeCreateFromSrc(imp_dbh->svchp, - imp_dbh->errhp, - (OCIDuration)OCI_DURATION_CALLOUT, - (ub1)src_type, - (dvoid *)src_ptr, - (sb4)OCI_IND_NOTNULL, - &xml) - ); - - - /* free temporary resources */ - if( src_type =3D=3D OCI_XMLTYPE_CREATE_CLOB ) { - checkerr( imp_dbh->errhp, - OCILobFreeTemporary(imp_dbh->svchp, imp_dbh->errhp, - (OCILobLocator*) src_ptr) ); - - checkerr( imp_dbh->errhp, - OCIDescriptorFree((dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB) ); - } - - - sv_dest =3D newSViv(0); - sv_setref_pv(sv_dest, "OCIXMLTypePtr", xml); - return sv_dest; -} - ---=-fkyM33WAvQ5xV0uCPeSD-- - - - -From hendrik.fuss@morphochem.de Fri Jan 30 16:56:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UGsO3v071338 - for ; Fri, 30 Jan 2004 16:56:27 GMT - (envelope-from hendrik.fuss@morphochem.de) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 16:56:27 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmZJF-0001wN-DK; - Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmZJF-0001wN-DK - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmZJE-0003GM-Bm - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:48 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 334DE30C57 - for ; Fri, 30 Jan 2004 09:07:47 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id E65B230C2C - for ; Fri, 30 Jan 2004 09:07:45 -0500 (EST) -Received: from babel.morphochem.de (unknown [212.89.121.1]) - by boggle.pobox.com (Postfix) with ESMTP - for ; Fri, 30 Jan 2004 09:07:04 -0500 (EST) -Received: (qmail 29768 invoked from network); 30 Jan 2004 15:10:09 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) - by 212.89.121.1 with SMTP; 30 Jan 2004 15:10:09 -0000 -Received: (qmail 11736 invoked from network); 30 Jan 2004 14:09:30 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) - (envelope-sender ) - by localhost.morphochem.de (qmail-ldap-1.03) with SMTP - for ; 30 Jan 2004 14:09:30 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) - by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; - Fri, 30 Jan 2004 15:09:30 +0100 (CET) -Subject: Re: DBD-Oracle and XMLType -From: Hendrik Fuss -To: Tim Bunce -Cc: "dbi-dev@perl.org" -In-Reply-To: <20040130133443.GC70215@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> - <20040130133443.GC70215@dansat.data-plan.com> -Content-Type: multipart/mixed; boundary="=-Sq1IOPDEhKoqxUKefiS3" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 15:01:03 +0100 -Message-Id: <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Status: RO -X-Status: A -Content-Length: 5585 -Lines: 196 - - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -> > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.= -c -> > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > create that XMLType object first using the C function -> > createxmlfromstring in xml.c. ->=20 -> I there any chance you could post that as a context diff (diff -u ideally -> or else diff -c)? It's much safer and more useful. Thanks. - -Good idea. Here's a diff -u of dbdimp.c. - -By the way: I have thougt about general support of named types, not just -XMLType, but you need to get the type description (TDO) from somewhere. -My code just checks if the perl variable is a blessed reference of -"OCIXMLTypePtr". - -Also note that my code can't handle downloading of XMLType objects yet. - -best wishes, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Description: Context diff for dbdimp.c -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - ---- dbdimp.c.orig 2004-01-30 14:48:55.000000000 +0100 -+++ dbdimp.c 2003-10-07 12:17:17.000000000 +0200 -@@ -1,5 +1,5 @@ - /* -- $Id: dbdimp.c,v 1.1.1.1 2003/10/02 10:45:20 hfuss Exp $ -+ $Id: dbdimp.c,v 1.3 2003/10/07 10:17:17 hfuss Exp $ -=20 - Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce -=20 -@@ -149,6 +149,7 @@ - case 97: /* CHARZ */ - case 106: /* MLSLABEL */ - case 102: /* SQLT_CUR OCI 7 cursor variable */ -+ case 108: /* SQLT_NTY */ - case 112: /* SQLT_CLOB / long */ - case 113: /* SQLT_BLOB / long */ - case 116: /* SQLT_RSET OCI 8 cursor variable */ -@@ -990,6 +991,9 @@ - case SQL_LONGVARCHAR: - return 8; /* Oracle LONG */ -=20 -+ case SQL_UDT: -+ return 108; /* Oracle NTY */ -+ - case SQL_DATE: - case SQL_TIME: - case SQL_TIMESTAMP: -@@ -1002,6 +1006,70 @@ - } -=20 -=20 -+static int -+dbd_rebind_ph_nty(sth, imp_sth, phs) -+ SV* sth; -+ imp_sth_t *imp_sth; -+ phs_t *phs; -+{ -+ OCIType *tdo =3D NULL; -+ sword status; -+ SV* ptr; -+ -+ if (phs->is_inout) -+ croak("OUT binding for NTY is currently unsupported"); -+ -+ /* ensure that the value is a support named object type */ -+ /* (currently only OCIXMLType*) */ -+ if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -+ OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -+ (CONST text*)"SYS", 3, -+ (CONST text*)"XMLTYPE", 7, -+ (CONST text*)0, 0, -+ OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -+ &tdo); -+ -+ ptr =3D SvRV(phs->sv); -+ phs->progv =3D (void*) SvIV(ptr); -+ phs->maxlen =3D sizeof(OCIXMLType*); -+ } -+ else -+ croak("Unsupported named object type for bind parameter"); -+ -+ -+ /* bind by name */ -+ -+ OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -+ (text*)phs->name, (sb4)strlen(phs->name), -+ (dvoid *) NULL, /* value supplied in BindObject later */ -+ 0, -+ (ub2)phs->ftype, 0, -+ NULL, -+ 0, 0, -+ NULL, -+ (ub4)OCI_DEFAULT, -+ status -+ ); -+ -+ if (status !=3D OCI_SUCCESS) { -+ oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -+ return 0; -+ } -+ if (DBIS->debug >=3D 3) -+ PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); -+ -+ -+ /* bind the object */ -+ -+ OCIBindObject(phs->bndhp, imp_sth->errhp, -+ (CONST OCIType*)tdo, -+ (dvoid **)&phs->progv, -+ (ub4*)NULL, -+ (dvoid **)NULL, -+ (ub4*)NULL); -+ -+ return 2; -+} -=20 - static int=20 - dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr)=20 -@@ -1307,6 +1375,9 @@ - case SQLT_RSET: - done =3D dbd_rebind_ph_rset(sth, imp_sth, phs); - break; -+ case 108: -+ done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -+ break; - #else - case 102: /* SQLT_CUR */ - done =3D dbd_rebind_ph_cursor(sth, imp_sth, phs); -@@ -1315,6 +1386,7 @@ - default: - done =3D dbd_rebind_ph_char(sth, imp_sth, phs, &alen_ptr); - } -+ - if (done !=3D 1) { - if (done =3D=3D 2) { /* the rebind did the OCI bind call itself successfu= -lly */ - if (DBIS->debug >=3D 3) -@@ -1328,7 +1400,7 @@ - #ifdef OCI_V8_SYNTAX - if (phs->maxlen > phs->maxlen_bound) { - sword status; -- int at_exec =3D (phs->desc_h =3D=3D NULL); -+ int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, (sb4)strlen(phs->name), - phs->progv, -@@ -1416,8 +1488,9 @@ - } - assert(name !=3D Nullch); -=20 -- if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) -+ if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQLT= -_NTY)) - /* dbi handle allowed for cursor variables */ -+ /* ref allowed for OCIXMLType* */ - croak("Can't bind a reference (%s)", neatsvpv(newvalue,0)); - if (SvTYPE(newvalue) > SVt_PVLV) /* hook for later array logic? */ - croak("Can't bind a non-scalar value (%s)", neatsvpv(newvalue,0)); -@@ -2217,6 +2290,7 @@ - #ifdef OCI_V8_SYNTAX - case SQLT_CLOB: sql_fbh.dbtype =3D SQL_CLOB; break; - case SQLT_BLOB: sql_fbh.dbtype =3D SQL_BLOB; break; -+ case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - #endif - #ifdef SQLT_TIMESTAMP_TZ - case SQLT_TIMESTAMP_TZ: sql_fbh.dbtype =3D SQL_TIMESTAMP; break; - ---=-Sq1IOPDEhKoqxUKefiS3-- - - - -From timbo@dansat.data-plan.com Fri Jan 30 18:32:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UIVK3f073353 - for ; Fri, 30 Jan 2004 18:32:30 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 18:32:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmceP-000603-GP; - Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmceP-000603-GP - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [208.210.124.73] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1AmceO-0006dQ-DB - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:52 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 25AEA3F13D - for ; Fri, 30 Jan 2004 12:41:51 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9FB863F16E - for ; Fri, 30 Jan 2004 12:41:49 -0500 (EST) -Received: from mail09.svc.cra.dublin.eircom.net (mail09.svc.cra.dublin.eircom.net [159.134.118.25]) - by icicle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 12:41:11 -0500 (EST) -Received: (qmail 9504 messnum 226571 invoked from network[213.94.228.233/unknown]); 30 Jan 2004 17:40:43 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail09.svc.cra.dublin.eircom.net (qp 9504) with SMTP; 30 Jan 2004 17:40:43 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UHf33A072739; - Fri, 30 Jan 2004 17:41:03 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i0UHf2Wr072738; - Fri, 30 Jan 2004 17:41:02 GMT -Date: Fri, 30 Jan 2004 17:41:02 +0000 -From: Tim Bunce -To: Hendrik Fuss -Cc: Tim Bunce , "dbi-dev@perl.org" -Subject: Re: DBD-Oracle and XMLType -Message-ID: <20040130174102.GB72657@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> <20040130133443.GC70215@dansat.data-plan.com> <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <1075471263.7305.73.camel@mars> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1129 -Lines: 29 - -On Fri, Jan 30, 2004 at 03:01:03PM +0100, Hendrik Fuss wrote: -> > > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -> > > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > > create that XMLType object first using the C function -> > > createxmlfromstring in xml.c. -> > -> > I there any chance you could post that as a context diff (diff -u ideally -> > or else diff -c)? It's much safer and more useful. Thanks. -> -> Good idea. Here's a diff -u of dbdimp.c. - -Thanks. - -> By the way: I have thougt about general support of named types, not just -> XMLType, but you need to get the type description (TDO) from somewhere. -> My code just checks if the perl variable is a blessed reference of -> "OCIXMLTypePtr". - -Doing the equivalent of m/^OCI(\w+)Ptr$/ and then calling OCITypeByName -with $1 uppercased might take us (or someone) a step further. - -> Also note that my code can't handle downloading of XMLType objects yet. - -I'll trust that some kind soul with an itch will send a patch :-) - -Thanks again Hendrik. - -Tim. - diff --git a/err_unsorted/err_xmltypebindplsql.msg b/err_unsorted/err_xmltypebindplsql.msg deleted file mode 100644 index 08faa725..00000000 --- a/err_unsorted/err_xmltypebindplsql.msg +++ /dev/null @@ -1,174 +0,0 @@ -From dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org Thu Apr 25 11:02:42 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3PA2gK34525 - for ; Thu, 25 Apr 2002 11:02:42 +0100 (BST) - (envelope-from dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 25 Apr 2002 11:02:42 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1019721492:10:18778:60; Thu, 25 Apr 2002 07:58:12 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1109782; 25 Apr 2002 7:58 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 791692BF11 - for ; Thu, 25 Apr 2002 03:58:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id 976FB2BEE4 - for ; Thu, 25 Apr 2002 03:58:07 -0400 (EDT) -Received: (qmail 84467 invoked by uid 1005); 25 Apr 2002 07:58:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 77923 invoked by uid 76); 24 Apr 2002 23:08:56 -0000 -Date: Wed, 24 Apr 2002 19:08:54 -0400 -From: Mark Stillwell -To: dbi-users-help@perl.org, dbi-users@perl.org -Subject: Oracle 9 XMLTYPE insert -Message-ID: <20020424190852.C22854@byrd.biostat.ufl.edu> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -Status: RO -Content-Length: 1469 -Lines: 43 - -I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -Here is my problem, I have a table named 'test' with three fields: eid -(integer), x (SYS.XMLTYPE) and formname (text) - -I create a database handler and connect to the database just fine. - -I create a new statement handler with the following command: - -$sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -SYS.XMLTYPE.CREATEXML(?), ?"); - -I loop over some data, $eid gets and integer, $xmlvalue gets a string, -and $formname gets a string. So long as $xmlvalue is relatively short -$sth->execute($eid, $xmlvalue, $formname); works great, but as soon as -it becomes long enough to force the use of clob's I have a problem. - -So I tried the following: - -$sth->bind_param(1, $i); -$sth->bind_param(2, $xmlvalue, { ora_type => ORA_CLOB }); -$sth->bind_param(3, $intable); -$sth->execute; - -This works great if column 'x' is a normal CLOB and I omit the -sys.xmltype.createxml statement above, but when 'x' is of type -sys.xmltype I get the following error: - -nvalid LOB locator specified -ORA-06512: at "SYS.XMLTYPE", line 0 - -Right now I've hacked the setup so there is a supplemental table called -'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE test SET x -= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem like the -right way to do this. - -Is there any way to do what I want in the current version of -DBI/OracleDBD? - --- -Mark Stillwell -marklee@ufl.edu -http://plaza.ufl.edu/marklee/ - -From dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org Wed May 8 16:11:46 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g48FBjo24814 - for ; Wed, 8 May 2002 16:11:45 +0100 (BST) - (envelope-from dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 08 May 2002 16:11:45 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020870336:20:08175:2; Wed, 08 May 2002 15:05:36 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2109147; 8 May 2002 15:05 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id 68FE23E6D4 - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-3.pobox.com (Postfix) with SMTP id 33A783E64D - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Received: (qmail 65232 invoked by uid 1005); 8 May 2002 15:01:47 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 60079 invoked by uid 76); 8 May 2002 14:50:53 -0000 -From: "Ben Middleton" -To: -Cc: -Subject: Re: Oracle 9 XMLTYPE insert -Date: Wed, 8 May 2002 15:50:47 +0100 -Message-ID: -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0) -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -Content-Length: 1311 -Lines: 39 - -Hi. - -Not sure if you ever resolved this: - -> I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -> Here is my problem, I have a table named 'test' with three fields: -> eid (integer), x (SYS.XMLTYPE) and formname (text) - -> I create a new statement handler with the following command: - -> $sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -> SYS.XMLTYPE.CREATEXML(?), ?"); - -.... - -> Invalid LOB locator specified -> ORA-06512: at "SYS.XMLTYPE", line 0 - -> Right now I've hacked the setup so there is a supplemental table -> called 'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE -> test SET x= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem -> like the right way to do this. - -> Is there any way to do what I want in the current version of -> DBI/OracleDBD? - -I don't think that the current DBI/DBD can bind a CLOB to a PL/SQL function -(which is all the CREATEXML function is) - hence you will have to go with -the intermediate CLOB table solution. - -Incidentally, if you are using Oracle9i - have you tried using a TEMPORARY -TABLE with a CLOB column (see SQL Reference Guide)? If setup correctly, this -is automatically truncated at the end of a transaction, is managed by the -Server, and provides some efficiency benefits. We use this here quite -effectively. - -Ben. - - diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index cd863cd9..9e610a68 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -11,6 +11,12 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; +{ + $DBD::Oracle::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Oracle database driver for the DBI module use DBI (); @@ -109,7 +115,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::dr; # ====== DRIVER ====== +{ package DBD::Oracle::dr; +{ + $DBD::Oracle::dr::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DRIVER ====== use strict; my %dbnames = (); # holds list of known databases (oratab + tnsnames) @@ -308,7 +320,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::db; # ====== DATABASE ====== +{ package DBD::Oracle::db; +{ + $DBD::Oracle::db::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DATABASE ====== use strict; use DBI qw(:sql_types); @@ -1000,7 +1018,13 @@ SQL } # end of package DBD::Oracle::db -{ package DBD::Oracle::st; # ====== STATEMENT ====== +{ package DBD::Oracle::st; +{ + $DBD::Oracle::st::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== STATEMENT ====== sub bind_param_inout_array { @@ -1094,9 +1118,18 @@ SQL 1; -__END__ +=pod + +=head1 NAME + +DBD::Oracle - Oracle database driver for the DBI module + +=head1 VERSION + +version 1.38 + =head1 SYNOPSIS use DBI; @@ -1110,7 +1143,6 @@ __END__ # for some advanced uses you may need Oracle type values: use DBD::Oracle qw(:ora_types); - =head1 DESCRIPTION DBD::Oracle is a Perl module which works with the DBI module to provide @@ -1218,7 +1250,6 @@ If port name is not specified, 1521 is the default. If service name is not speci The following examples show several ways a connection can be created: - $dbh = DBI->connect('dbi:Oracle:DB','username','password'); $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); @@ -1549,7 +1580,6 @@ DBDOxxxx where xxxx is the current version number. This value can be retrieved on the server side using V$SESSION_CONNECT_INFO or GV$SESSION_CONNECT_INFO - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); $dbh->{ora_driver_name} = $q; @@ -1720,7 +1750,6 @@ If the previous error was from a failed C due to a syntax error, this attribute gives the offset into the C attribute where the error was found. - =head4 ora_array_chunk_size Due to OCI limitations, DBD::Oracle needs to buffer up rows of @@ -1943,7 +1972,6 @@ DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. Starts a new session against the current database using the credentials supplied. - =head2 B $hashref = $dbh->private_attribute_info(); @@ -2071,7 +2099,6 @@ Implemented by DBI, no driver-specific impact. Implemented by DBI, no driver-specific impact. - =head2 B Type: boolean, inherited @@ -2080,7 +2107,6 @@ The CompatMode attribute is used by emulation layers (such as Oraperl) to enable It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. - =head1 ORACLE-SPECIFIC DATABASE HANDLE METHODS =head2 B @@ -2240,7 +2266,6 @@ The different types of placeholders cannot be mixed within a statement, but you use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. - =head2 B $sth = $dbh->prepare_cached($statement, \%attr); @@ -2259,7 +2284,6 @@ query was successful, returns undef if an error occurred, and returns -1 if the number of rows is unknown or not available. Note that this method will return B<0E0> instead of 0 for 'no rows were affected', in order to always return a true value if no error occurred. - =head2 B Oracle does not implement auto_increment of serial type columns it uses predefined @@ -2315,7 +2339,6 @@ If the script exits before disconnect is called (or, more precisely, if the data referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() methods automatically. It is best to explicitly disconnect rather than rely on this behavior. - =head2 B $rv = $dbh->ping; @@ -2664,7 +2687,6 @@ Examples: ## This executes the statement with 567 (integer) and "Zool" (varchar) $sth->execute(); - These attributes may be used in the C<\%attr> parameter of the L or L statement handle methods. @@ -2759,10 +2781,8 @@ Set L to 0 in prepare() to enable this behaviour. $rv = $sth->bind_param_inout($param_num, \$scalar, 0); - DBD::Oracle fully supports bind_param_inout below are some uses for this method. - =head3 B Oracle supports an extended SQL insert syntax which will return one @@ -2936,10 +2956,6 @@ the above example, the code would look something like this : ... } - - - - =head3 B DBD::Oracle has built-in support for B @@ -2974,13 +2990,11 @@ and B datatypes. The simple example is here: =item B -=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' +=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' will only take a reference to a scalar. =back - - =head3 B SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. @@ -3089,7 +3103,6 @@ you get: DBD::Oracle supports this undocumented feature of DBI. See L for an example. - =head2 B $rv = $sth->bind_param_array($param_num, $array_ref_or_value) @@ -3099,8 +3112,6 @@ DBD::Oracle supports this undocumented feature of DBI. See L method. - - =head2 B $rv = $sth->execute(@bind_values); @@ -3367,7 +3378,6 @@ However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch Only use scrollable cursors if you really have a good reason to. They do use up considerable more server and client resources and have poorer response times than non-scrolling cursors. - =head2 Enabling Scrollable Cursors To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; @@ -3383,7 +3393,6 @@ When the statement is executed you will then be able to use 'ora_fetch_scroll' m or you can still use any of the other fetch methods but with a poorer response time than if you used a non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. - =head2 Scrollable Cursor Methods The following driver-specific methods are used with scrollable cursors. @@ -3723,7 +3732,6 @@ You can tune this value by setting ora_oci_success_warn which will display the f In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. - =head3 Simple Fetch for CLOBs and BLOBs To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well @@ -4125,7 +4133,6 @@ Uses the Oracle OCILobTrim function. Returns the length of the LOB. Uses the Oracle OCILobGetLength function. - =item ora_lob_is_init $is_init = $dbh->ora_lob_is_init($lob_locator); @@ -4172,7 +4179,6 @@ lob_id field values, defined as follows: CREATE SEQUENCE lob_example_seq - =head3 Example: Inserting a new row with large data Unless enough memory is available to store and bind the @@ -4238,7 +4244,6 @@ can't be used effectively if AutoCommit is enabled). $offset += $length; } - In this example we demonstrate the use of ora_lob_write() interactively to append data to the columns 'bin_data' and 'char_data'. Had we used ora_lob_append(), we could have @@ -4255,7 +4260,6 @@ The scalar variables $offset and $length are no longer needed, because ora_lob_append() keeps track of the offset for us. - =head3 Example: Updating an existing row with large data In this example, we demonstrate a technique for overwriting @@ -4440,7 +4444,6 @@ WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other than US7ASCII, requires that the NLS_LANG environment variable be set. See the L<"Oracle UTF8 is not UTF-8"> section below. - You are strongly urged to read the Oracle Internationalization documentation specifically with respect the choices and trade offs for creating a databases for use with international character sets. @@ -4547,7 +4550,6 @@ If the C attribute is given to bind_param() then that determines if the value should be assumed to be in the default (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); ... $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); @@ -4588,7 +4590,6 @@ and TABLE in any combination. Support is seamless and recursive, meaning you need only supply a simple SQL statement to get all the values in an embedded object. You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. - Array example, given this type and table; CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); @@ -4741,7 +4742,6 @@ There are some types, like BOOLEAN, that Oracle does not automatically convert to or from strings (pity). These need to be converted explicitly using SQL or PL/SQL functions. - Examples: # DATE values @@ -4796,7 +4796,6 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" - =head4 Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special @@ -4944,7 +4943,6 @@ shows: } } - The cursor returned by the function C defined in the previous section can be fetched as a nested cursor as follows: @@ -5325,7 +5323,6 @@ There is a known problem with the 11.2g Oracle client and the C PL/SQL function. See L for the details. - =head1 SEE ALSO =over @@ -5393,4 +5390,34 @@ The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. The DBD::Oracle module is free open source software; you can redistribute it and/or modify it under the same terms as Perl 5. +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + + +__END__ + + diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 43331655..29ba9b1c 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,4 +1,10 @@ package DBD::Oracle::GetInfo; +{ + $DBD::Oracle::GetInfo::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Wrapper to get Oracle information use strict; @@ -315,4 +321,44 @@ our %info = ( 1; + + +=pod + +=head1 NAME + +DBD::Oracle::GetInfo - Wrapper to get Oracle information + +=head1 VERSION + +version 1.38 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + + __END__ diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 39a99498..f7a4850f 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,25 +1,70 @@ -package DBD::Oracle::Object; -# ABSTRACT: Wrapper for Oracle objects - -use strict; -use warnings; - -sub type_name { shift->{type_name} } - -sub attributes { @{shift->{attributes}} } - -sub attr_hash { - my $self = shift; - return $self->{attr_hash} ||= { $self->attributes }; -} - -sub attr { - my $self = shift; - if (@_) { - my $key = shift; - return $self->attr_hash->{$key}; - } - return $self->attr_hash; -} - -1; +package DBD::Oracle::Object; +{ + $DBD::Oracle::Object::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; +} +# ABSTRACT: Wrapper for Oracle objects + +use strict; +use warnings; + +sub type_name { shift->{type_name} } + +sub attributes { @{shift->{attributes}} } + +sub attr_hash { + my $self = shift; + return $self->{attr_hash} ||= { $self->attributes }; +} + +sub attr { + my $self = shift; + if (@_) { + my $key = shift; + return $self->attr_hash->{$key}; + } + return $self->attr_hash; +} + +1; + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Object - Wrapper for Oracle objects + +=head1 VERSION + +version 1.38 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 6e422308..96f153ef 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,8 +1,24 @@ package DBD::Oracle::Troubleshooting; +{ + $DBD::Oracle::Troubleshooting::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; +} #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle + +__END__ =pod +=head1 NAME + +DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle + +=head1 VERSION + +version 1.38 + =head1 CONNECTING TO ORACLE If you are reading this it is assumed that you have successfully @@ -29,7 +45,6 @@ For Windows the solution is to add this value to you PATH PATH=c:\app\oracle\product\xx.x.x;%PATH% - If you get past this stage and get a ORA-12154: TNS:could not resolve the connect identifier specified @@ -61,7 +76,6 @@ Protocol Adapter". If it generates any errors which look relevant then please talk to your Oracle technical support (and not the dbi-users mailing list). - =head1 USING THE LONG TYPES Some examples related to the use of LONG types are available in @@ -96,7 +110,6 @@ It turns out that now it is necessary to edit the same file and append this and then run "genclntsh", the libclntsh is properly generated and the linkage with DBD::Oracle proceeds properly. - =head2 cc1: invalid option `tune=pentium4'" error If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. @@ -153,7 +166,7 @@ To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY as you would for an install against 10g Standard Edition, Standard Edition One, or Enterprise Edition -=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 +=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 DBD::Oracle seems to hit some sort of bug with the above two versions of DB. The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also @@ -172,7 +185,6 @@ So far there is no patch for this but here are some work arounds or this way utf8::downgrade($parameter, 1); - =head1 CYGWIN @@ -335,4 +347,30 @@ oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + diff --git a/t/000-report-versions.t b/t/000-report-versions.t new file mode 100644 index 00000000..2d4a9a19 --- /dev/null +++ b/t/000-report-versions.t @@ -0,0 +1,446 @@ +#!perl +use warnings; +use strict; +use Test::More 0.94; + +# Include a cut-down version of YAML::Tiny so we don't introduce unnecessary +# dependencies ourselves. + +package Local::YAML::Tiny; + +use strict; +use Carp 'croak'; + +# UTF Support? +sub HAVE_UTF8 () { $] >= 5.007003 } +BEGIN { + if ( HAVE_UTF8 ) { + # The string eval helps hide this from Test::MinimumVersion + eval "require utf8;"; + die "Failed to load UTF-8 support" if $@; + } + + # Class structure + require 5.004; + $YAML::Tiny::VERSION = '1.40'; + + # Error storage + $YAML::Tiny::errstr = ''; +} + +# Printable characters for escapes +my %UNESCAPES = ( + z => "\x00", a => "\x07", t => "\x09", + n => "\x0a", v => "\x0b", f => "\x0c", + r => "\x0d", e => "\x1b", '\\' => '\\', +); + + +##################################################################### +# Implementation + +# Create an empty YAML::Tiny object +sub new { + my $class = shift; + bless [ @_ ], $class; +} + +# Create an object from a file +sub read { + my $class = ref $_[0] ? ref shift : shift; + + # Check the file + my $file = shift or return $class->_error( 'You did not specify a file name' ); + return $class->_error( "File '$file' does not exist" ) unless -e $file; + return $class->_error( "'$file' is a directory, not a file" ) unless -f _; + return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; + + # Slurp in the file + local $/ = undef; + local *CFG; + unless ( open(CFG, $file) ) { + return $class->_error("Failed to open file '$file': $!"); + } + my $contents = ; + unless ( close(CFG) ) { + return $class->_error("Failed to close file '$file': $!"); + } + + $class->read_string( $contents ); +} + +# Create an object from a string +sub read_string { + my $class = ref $_[0] ? ref shift : shift; + my $self = bless [], $class; + my $string = $_[0]; + unless ( defined $string ) { + return $self->_error("Did not provide a string to load"); + } + + # Byte order marks + # NOTE: Keeping this here to educate maintainers + # my %BOM = ( + # "\357\273\277" => 'UTF-8', + # "\376\377" => 'UTF-16BE', + # "\377\376" => 'UTF-16LE', + # "\377\376\0\0" => 'UTF-32LE' + # "\0\0\376\377" => 'UTF-32BE', + # ); + if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) { + return $self->_error("Stream has a non UTF-8 BOM"); + } else { + # Strip UTF-8 bom if found, we'll just ignore it + $string =~ s/^\357\273\277//; + } + + # Try to decode as utf8 + utf8::decode($string) if HAVE_UTF8; + + # Check for some special cases + return $self unless length $string; + unless ( $string =~ /[\012\015]+\z/ ) { + return $self->_error("Stream does not end with newline character"); + } + + # Split the file into lines + my @lines = grep { ! /^\s*(?:\#.*)?\z/ } + split /(?:\015{1,2}\012|\015|\012)/, $string; + + # Strip the initial YAML header + @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; + + # A nibbling parser + while ( @lines ) { + # Do we have a document header? + if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { + # Handle scalar documents + shift @lines; + if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { + push @$self, $self->_read_scalar( "$1", [ undef ], \@lines ); + next; + } + } + + if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { + # A naked document + push @$self, undef; + while ( @lines and $lines[0] !~ /^---/ ) { + shift @lines; + } + + } elsif ( $lines[0] =~ /^\s*\-/ ) { + # An array at the root + my $document = [ ]; + push @$self, $document; + $self->_read_array( $document, [ 0 ], \@lines ); + + } elsif ( $lines[0] =~ /^(\s*)\S/ ) { + # A hash at the root + my $document = { }; + push @$self, $document; + $self->_read_hash( $document, [ length($1) ], \@lines ); + + } else { + croak("YAML::Tiny failed to classify the line '$lines[0]'"); + } + } + + $self; +} + +# Deparse a scalar string to the actual scalar +sub _read_scalar { + my ($self, $string, $indent, $lines) = @_; + + # Trim trailing whitespace + $string =~ s/\s*\z//; + + # Explitic null/undef + return undef if $string eq '~'; + + # Quotes + if ( $string =~ /^\'(.*?)\'\z/ ) { + return '' unless defined $1; + $string = $1; + $string =~ s/\'\'/\'/g; + return $string; + } + if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) { + # Reusing the variable is a little ugly, + # but avoids a new variable and a string copy. + $string = $1; + $string =~ s/\\"/"/g; + $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; + return $string; + } + + # Special cases + if ( $string =~ /^[\'\"!&]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + return {} if $string eq '{}'; + return [] if $string eq '[]'; + + # Regular unquoted string + return $string unless $string =~ /^[>|]/; + + # Error + croak("YAML::Tiny failed to find multi-line scalar content") unless @$lines; + + # Check the indent depth + $lines->[0] =~ /^(\s*)/; + $indent->[-1] = length("$1"); + if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Pull the lines + my @multiline = (); + while ( @$lines ) { + $lines->[0] =~ /^(\s*)/; + last unless length($1) >= $indent->[-1]; + push @multiline, substr(shift(@$lines), length($1)); + } + + my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; + my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; + return join( $j, @multiline ) . $t; +} + +# Parse an array +sub _read_array { + my ($self, $array, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { + # Inline nested hash + my $indent2 = length("$1"); + $lines->[0] =~ s/-/ /; + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { + # Array entry with a value + shift @$lines; + push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { + shift @$lines; + unless ( @$lines ) { + push @$array, undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)\-/ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] == $indent2 ) { + # Null array entry + push @$array, undef; + } else { + # Naked indenter + push @$array, [ ]; + $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines ); + } + + } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines ); + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + + } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { + # This is probably a structure like the following... + # --- + # foo: + # - list + # bar: value + # + # ... so lets return and let the hash parser handle it + return 1; + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + } + + return 1; +} + +# Parse an array +sub _read_hash { + my ($self, $hash, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Get the key + unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { + if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + my $key = $1; + + # Do we have a value? + if ( length $lines->[0] ) { + # Yes + $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines ); + } else { + # An indent + shift @$lines; + unless ( @$lines ) { + $hash->{$key} = undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)-/ ) { + $hash->{$key} = []; + $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } elsif ( $lines->[0] =~ /^(\s*)./ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] >= $indent2 ) { + # Null hash entry + $hash->{$key} = undef; + } else { + $hash->{$key} = {}; + $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } + } + } + } + + return 1; +} + +# Set error +sub _error { + $YAML::Tiny::errstr = $_[1]; + undef; +} + +# Retrieve error +sub errstr { + $YAML::Tiny::errstr; +} + + + +##################################################################### +# Use Scalar::Util if possible, otherwise emulate it + +BEGIN { + eval { + require Scalar::Util; + }; + if ( $@ ) { + # Failed to load Scalar::Util + eval <<'END_PERL'; +sub refaddr { + my $pkg = ref($_[0]) or return undef; + if (!!UNIVERSAL::can($_[0], 'can')) { + bless $_[0], 'Scalar::Util::Fake'; + } else { + $pkg = undef; + } + "$_[0]" =~ /0x(\w+)/; + my $i = do { local $^W; hex $1 }; + bless $_[0], $pkg if defined $pkg; + $i; +} +END_PERL + } else { + Scalar::Util->import('refaddr'); + } +} + + +##################################################################### +# main test +##################################################################### + +package main; + +BEGIN { + + # Skip modules that either don't want to be loaded directly, such as + # Module::Install, or that mess with the test count, such as the Test::* + # modules listed here. + # + # Moose::Role conflicts if Moose is loaded as well, but Moose::Role is in + # the Moose distribution and it's certain that someone who uses + # Moose::Role also uses Moose somewhere, so if we disallow Moose::Role, + # we'll still get the relevant version number. + + my %skip = map { $_ => 1 } qw( + App::FatPacker + Class::Accessor::Classy + Devel::Cover + Module::Install + Moose::Role + POE::Loop::Tk + Template::Test + Test::Kwalitee + Test::Pod::Coverage + Test::Portability::Files + Test::YAML::Meta + ); + + my $Test = Test::Builder->new; + + $Test->plan(skip_all => "META.yml could not be found") + unless -f 'META.yml' and -r _; + + my $meta = (Local::YAML::Tiny->read('META.yml'))->[0]; + my %requires; + for my $require_key (grep { /requires/ } keys %$meta) { + my %h = %{ $meta->{$require_key} }; + $requires{$_}++ for keys %h; + } + delete $requires{perl}; + + diag("Testing with Perl $], $^X"); + for my $module (sort keys %requires) { + if ($skip{$module}) { + note "$module doesn't want to be loaded directly, skipping"; + next; + } + local $SIG{__WARN__} = sub { note "$module: $_[0]" }; + use_ok $module or BAIL_OUT("can't load $module"); + my $version = $module->VERSION; + $version = 'undefined' unless defined $version; + diag(" $module version is $version"); + } + done_testing; +} diff --git a/xt/changes.t b/xt/changes.t deleted file mode 100644 index 27a4808a..00000000 --- a/xt/changes.t +++ /dev/null @@ -1,8 +0,0 @@ -use strict; -use warnings; - -use Test::More; - -eval 'use Test::CPAN::Changes'; -plan skip_all => 'Test::CPAN::Changes required for this test' if $@; -changes_ok(); diff --git a/xt/manifest.t b/xt/manifest.t deleted file mode 100644 index 00df9957..00000000 --- a/xt/manifest.t +++ /dev/null @@ -1,21 +0,0 @@ -use strict; -use warnings; - -use ExtUtils::Manifest qw/ fullcheck /; - -use Test::More tests => 1; - -my ( $missing, $extra ) = do { - local *STDERR; - - # hush little baby, don't you cry - open STDERR, '>', \my $stderr; - - fullcheck(); -}; - -ok @$missing + @$extra == 0, 'manifest in sync' or do { - diag "missing files:\n", map { " \t $_\n " } @$missing if @$missing; - diag "extra files: \n", map { "\t$_\n" } @$extra if @$extra; -}; - diff --git a/xt/pod.t b/xt/pod.t deleted file mode 100644 index 66481225..00000000 --- a/xt/pod.t +++ /dev/null @@ -1,11 +0,0 @@ -use Test::More; - -eval "use Test::Pod"; - -plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; - -pod_file_ok( 'Oracle.pm' ); -pod_file_ok( 'lib/DBD/Oracle/Object.pm' ); -pod_file_ok( 'lib/DBD/Oracle/GetInfo.pm' ); - -done_testing; From 69918405d021959c821f492deb0d362cb4e67641 Mon Sep 17 00:00:00 2001 From: yanick Date: Wed, 8 Feb 2012 20:48:55 +0000 Subject: [PATCH 124/637] PL/SQL out values are utf8 encoded Conflicts: Changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15135 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 +- MANIFEST | 1 + dbdimp.c | 7 ++++ t/rt74753-utf8-encoded.t | 86 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 t/rt74753-utf8-encoded.t diff --git a/Changes b/Changes index 7c3e8305..b14e1680 100644 --- a/Changes +++ b/Changes @@ -1,12 +1,14 @@ Revision history for DBD::Oracle -1.38 2012-02-02 +NEXT 2012-02-08 [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED [RT73798] - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) [RT74544] + - PL/SQL out values were not utf8 encoded [RT74753] + (Steve Baldwin + Martin J. Evans) [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work diff --git a/MANIFEST b/MANIFEST index 436c409e..34c7a9d4 100644 --- a/MANIFEST +++ b/MANIFEST @@ -89,5 +89,6 @@ t/70meta.t t/80ora_charset.t t/nchar_test_lib.pl t/rt13865.t +t/rt74753-utf8-encoded.t test.pl typemap diff --git a/dbdimp.c b/dbdimp.c index 9d4cc658..87e36826 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3198,6 +3198,13 @@ dbd_phs_sv_complete(phs_t *phs, SV *sv, I32 debug) SvCUR_set(sv, phs->alen); *SvEND(sv) = '\0'; SvPOK_only_UTF8(sv); + if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { +#ifdef sv_utf8_decode + sv_utf8_decode(sv); +#else + SvUTF8_on(sv); +#endif + } } else { /* shouldn't happen */ debug = 2; diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t new file mode 100644 index 00000000..ae318ad2 --- /dev/null +++ b/t/rt74753-utf8-encoded.t @@ -0,0 +1,86 @@ +#!/usr/bin/perl -w + +use strict; +use warnings; + +use Test::More tests => 2; + +use DBI; +use Encode; + +unshift @INC ,'t'; +require 'nchar_test_lib.pl'; + +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; + +$ENV{NLS_LANG} = 'AMERICAN_AMERICA.UTF8'; +$ENV{NLS_NCHAR} = 'UTF8'; + +my $dbh = DBI->connect( $dsn, $dbuser, '', { + PrintError => 0, AutoCommit => 0, RaiseError => 1, +},); + +$dbh->do(q(alter session set nls_territory = 'GERMANY')); + +my $sth = $dbh->prepare(<<"END_SQL"); + SELECT ltrim(rtrim(to_char(0, 'L'))) FROM dual +END_SQL + +$sth->execute; + +my ($val); +$sth->bind_columns( \($val) ); + +$sth->fetch; + +is Encode::is_utf8($val) => 1, "utf8 encoded"; + +$sth->finish; + +$val = undef; + +$sth = $dbh->prepare(<<'END_SQL'); +declare + l_ret varchar2(10); +begin + select ltrim(rtrim(to_char(0, 'L'))) + into l_ret + from dual; + -- + :ret := l_ret; +end; +END_SQL + +$sth->bind_param_inout(':ret', \$val, 100); +$sth->execute; + +is Encode::is_utf8($val) => 1, "utf8 encoded"; + +$dbh->disconnect; + + +__END__ + +undef $val; + +$sth = $dbh->prepare(<<'END_SQL'); +declare + l_ret varchar2(10); +begin + select ltrim(rtrim(to_char(0, 'L'))) + into l_ret + from dual; + -- + :ret := l_ret; +end; +END_SQL + +$sth->bind_param_inout( ':ret', \$val, 100 ); +$sth->execute; + +diag "val=[$val] len=@{[ length($val) ]}" while $sth->fetch; + +diag "utf8 is ", Encode::is_utf8($val) ? 'on' : 'off'; + +$dbh->disconnect; From 90bca8df7a393c10f886e956e059d323618df1b9 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 9 Feb 2012 14:35:23 -0500 Subject: [PATCH 125/637] code cleaning --- lib/DBD/Oracle.pm | 105 ++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index cd863cd9..ff71f86b 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -53,42 +53,50 @@ package DBD::Oracle; } sub driver{ - return $drh if $drh; - my($class, $attr) = @_; - my $oci = DBD::Oracle::ORA_OCI(); - - $class .= "::dr"; - - # not a 'my' since we use it above to prevent multiple drivers - - $drh = DBI::_new_drh($class, { - 'Name' => 'Oracle', - 'Version' => $VERSION, - 'Err' => \my $err, - 'Errstr' => \my $errstr, - 'Attribution' => "DBD::Oracle $VERSION using OCI$oci by Tim Bunce", - }); - DBD::Oracle::dr::init_oci($drh) ; - $drh->STORE('ShowErrorStatement', 1); - DBD::Oracle::db->install_method("ora_lob_read"); - DBD::Oracle::db->install_method("ora_lob_write"); - DBD::Oracle::db->install_method("ora_lob_append"); - DBD::Oracle::db->install_method("ora_lob_trim"); - DBD::Oracle::db->install_method("ora_lob_length"); - DBD::Oracle::db->install_method("ora_lob_chunk_size"); - DBD::Oracle::db->install_method("ora_lob_is_init"); - DBD::Oracle::db->install_method("ora_nls_parameters"); - DBD::Oracle::db->install_method("ora_can_unicode"); - DBD::Oracle::db->install_method("ora_can_taf"); - DBD::Oracle::db->install_method("ora_db_startup"); - DBD::Oracle::db->install_method("ora_db_shutdown"); - DBD::Oracle::st->install_method("ora_fetch_scroll"); - DBD::Oracle::st->install_method("ora_scroll_position"); - DBD::Oracle::st->install_method("ora_ping"); - DBD::Oracle::st->install_method("ora_stmt_type_name"); - DBD::Oracle::st->install_method("ora_stmt_type"); - $drh; - + return $drh if $drh; + + my($class, $attr) = @_; + my $oci = DBD::Oracle::ORA_OCI(); + + $class .= "::dr"; + + # not a 'my' since we use it above to prevent multiple drivers + + $drh = DBI::_new_drh($class, { + 'Name' => 'Oracle', + 'Version' => $VERSION, + 'Err' => \my $err, + 'Errstr' => \my $errstr, + 'Attribution' => "DBD::Oracle $VERSION using OCI$oci by Tim Bunce", + }); + + DBD::Oracle::dr::init_oci($drh) ; + $drh->STORE('ShowErrorStatement', 1); + + DBD::Oracle::db->install_method($_) for qw/ + ora_lob_read + ora_lob_write + ora_lob_append + ora_lob_trim + ora_lob_length + ora_lob_chunk_size + ora_lob_is_init + ora_nls_parameters + ora_can_unicode + ora_can_taf + ora_db_startup + ora_db_shutdown + /; + + DBD::Oracle::st->install_method($_) for qw/ + ora_fetch_scroll + ora_scroll_position + ora_ping + ora_stmt_type_name + ora_stmt_type + /; + + $drh; } @@ -1071,24 +1079,21 @@ SQL return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_count errors") if $err_count; - if (!wantarray) { - return $tuple_count; - } - - return ($tuple_count, defined $row_count ? $row_count : undef); - - + return wantarray + ? ($tuple_count, defined $row_count ? $row_count : undef) + : $tuple_count; } sub private_attribute_info { - return {ora_lengths => undef, - ora_types => undef, - ora_rowid => undef, - ora_est_row_width => undef, - ora_type => undef, - ora_fail_over => undef, - }; + return { map { $_ => undef } qw/ + ora_lengths + ora_types + ora_rowid + ora_est_row_width + ora_type + ora_fail_over + / }; } } From 80aef82299ffec7e3d0d0a84eb80c1d0b4060cec Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 9 Feb 2012 16:02:31 -0500 Subject: [PATCH 126/637] order the constants and remove dupes --- lib/DBD/Oracle/GetInfo.pm | 274 +++++++++++++++++--------------------- 1 file changed, 119 insertions(+), 155 deletions(-) diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 43331655..edacde25 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -90,27 +90,59 @@ sub sql_user_name { our %info = ( - 20 => 'Y', # SQL_ACCESSIBLE_PROCEDURES + 0 => 0, # SQL_MAX_DRIVER_CONNECTIONS + 1 => 0, # SQL_MAX_CONCURRENT_ACTIVITIES + 2 => \&sql_data_source_name, # SQL_DATA_SOURCE_NAME + 3 => 147209344, # SQL_DRIVER_HDBC + 4 => 147212776, # SQL_DRIVER_HENV +# 5 => undef, # SQL_DRIVER_HSTMT + 6 => $INC{'DBD/Oracle.pm'}, # SQL_DRIVER_NAME + 7 => $sql_driver_ver, # SQL_DRIVER_VER + 8 => 191, # SQL_FETCH_DIRECTION + 9 => 1, # SQL_ODBC_API_CONFORMANCE + 10 => '03.52', # SQL_ODBC_VER + 11 => 'Y', # SQL_ROW_UPDATES + 12 => 0, # SQL_ODBC_SAG_CLI_CONFORMANCE + 13 => sub {"$_[0]->{Name}"}, # SQL_SERVER_NAME + 14 => '\\', # SQL_SEARCH_PATTERN_ESCAPE + 15 => 1, # SQL_ODBC_SQL_CONFORMANCE + 16 => 'DEVEL', # SQL_DATABASE_NAME + 17 => 'Oracle', # SQL_DBMS_NAME + 18 => \&sql_dbms_version, # SQL_DBMS_VERSION 19 => 'Y', # SQL_ACCESSIBLE_TABLES - 0 => 0, # SQL_ACTIVE_CONNECTIONS - 116 => 0, # SQL_ACTIVE_ENVIRONMENTS - 1 => 0, # SQL_ACTIVE_STATEMENTS - 169 => 64, # SQL_AGGREGATE_FUNCTIONS - 117 => 0, # SQL_ALTER_DOMAIN - 86 => 1029739, # SQL_ALTER_TABLE - 10021 => 2, # SQL_ASYNC_MODE - 120 => 0, # SQL_BATCH_ROW_COUNT - 121 => 0, # SQL_BATCH_SUPPORT - 82 => 88, # SQL_BOOKMARK_PERSISTENCE - 114 => 2, # SQL_CATALOG_LOCATION - 10003 => 'N', # SQL_CATALOG_NAME - 41 => '@', # SQL_CATALOG_NAME_SEPARATOR - 42 => 'Database Link', # SQL_CATALOG_TERM - 92 => 3, # SQL_CATALOG_USAGE - 10004 => '', # SQL_COLLATING_SEQUENCE - 10004 => '', # SQL_COLLATION_SEQ - 87 => 'Y', # SQL_COLUMN_ALIAS + 20 => 'Y', # SQL_ACCESSIBLE_PROCEDURES + 21 => 'Y', # SQL_PROCEDURES 22 => 1, # SQL_CONCAT_NULL_BEHAVIOR + 23 => 2, # SQL_CURSOR_COMMIT_BEHAVIOR + 24 => 2, # SQL_CURSOR_ROLLBACK_BEHAVIOR + 25 => 'N', # SQL_DATA_SOURCE_READ_ONLY + 26 => 8, # SQL_DEFAULT_TRANSACTION_ISOLATION + 27 => 'Y', # SQL_EXPRESSIONS_IN_ORDERBY + 28 => 1, # SQL_IDENTIFIER_CASE + 29 => '"', # SQL_IDENTIFIER_QUOTE_CHAR + 30 => 30, # SQL_MAXIMUM_COLUMN_NAME_LENGTH + 31 => 30, # SQL_MAXIMUM_CURSOR_NAME_LENGTH + 32 => 30, # SQL_MAXIMUM_SCHEMA_NAME_LENGTH + 33 => 92, # SQL_MAX_PROCEDURE_NAME_LEN + 34 => 0, # SQL_MAXIMUM_CATALOG_NAME_LENGTH + 35 => 30, # SQL_MAXIMUM_TABLE_NAME_LENGTH + 36 => 'Y', # SQL_MULT_RESULT_SETS + 37 => 'Y', # SQL_MULTIPLE_ACTIVE_TXN + 38 => 'Y', # SQL_OUTER_JOINS + 39 => 'Owner', # SQL_SCHEMA_TERM + 40 => 'Procedure', # SQL_PROCEDURE_TERM + 41 => '@', # SQL_QUALIFIER_NAME_SEPARATOR + 42 => 'Database Link', # SQL_QUALIFIER_TERM + 43 => 7, # SQL_SCROLL_CONCURRENCY + 44 => 19, # SQL_SCROLL_OPTIONS + 45 => 'Table', # SQL_TABLE_TERM + 46 => 3, # SQL_TRANSACTION_CAPABLE + 47 => \&sql_user_name, # SQL_USER_NAME + 48 => 1, # SQL_CONVERT_FUNCTIONS + 49 => 16646015, # SQL_NUMERIC_FUNCTIONS + 50 => 8355839, # SQL_STRING_FUNCTIONS + 51 => 7, # SQL_SYSTEM_FUNCTIONS + 52 => 1023999, # SQL_TIMEDATE_FUNCTIONS 53 => 10518015, # SQL_CONVERT_BIGINT 54 => 10775839, # SQL_CONVERT_BINARY 55 => 10518015, # SQL_CONVERT_BIT @@ -119,12 +151,7 @@ our %info = ( 58 => 10518015, # SQL_CONVERT_DECIMAL 59 => 10514943, # SQL_CONVERT_DOUBLE 60 => 10514943, # SQL_CONVERT_FLOAT - 48 => 1, # SQL_CONVERT_FUNCTIONS - 173 => 0, # SQL_CONVERT_GUID 61 => 10518015, # SQL_CONVERT_INTEGER - 123 => 0, # SQL_CONVERT_INTERVAL_DAY_TIME - 124 => 0, # SQL_CONVERT_INTERVAL_YEAR_MONTH - 71 => 265216, # SQL_CONVERT_LONGVARBINARY 62 => 14680833, # SQL_CONVERT_LONGVARCHAR 63 => 10518015, # SQL_CONVERT_NUMERIC 64 => 10514943, # SQL_CONVERT_REAL @@ -134,10 +161,62 @@ our %info = ( 68 => 10518015, # SQL_CONVERT_TINYINT 69 => 10775839, # SQL_CONVERT_VARBINARY 70 => 15204351, # SQL_CONVERT_VARCHAR + 71 => 265216, # SQL_CONVERT_LONGVARBINARY + 72 => 10, # SQL_TRANSACTION_ISOLATION_OPTION + 73 => 'N', # SQL_ODBC_SQL_OPT_IEF + 74 => 2, # SQL_CORRELATION_NAME + 75 => 1, # SQL_NON_NULLABLE_COLUMNS +# 76 => undef, # SQL_DRIVER_HLIB + 77 => '03.52', # SQL_DRIVER_ODBC_VER + 78 => 1, # SQL_LOCK_TYPES + 79 => 1, # SQL_POS_OPERATIONS + 80 => 7, # SQL_POSITIONED_STATEMENTS + 81 => 15, # SQL_GETDATA_EXTENSIONS + 82 => 88, # SQL_BOOKMARK_PERSISTENCE + 83 => 0, # SQL_STATIC_SENSITIVITY + 84 => 0, # SQL_FILE_USAGE + 85 => 1, # SQL_NULL_COLLATION + 86 => 1029739, # SQL_ALTER_TABLE + 87 => 'Y', # SQL_COLUMN_ALIAS + 88 => 2, # SQL_GROUP_BY + 89 => \&sql_keywords, # SQL_KEYWORDS + 90 => 'N', # SQL_ORDER_BY_COLUMNS_IN_SELECT + 91 => 31, # SQL_SCHEMA_USAGE + 92 => 3, # SQL_QUALIFIER_USAGE + 93 => 3, # SQL_QUOTED_IDENTIFIER_CASE + 94 => '$#', # SQL_SPECIAL_CHARACTERS + 95 => 31, # SQL_SUBQUERIES + 96 => 3, # SQL_UNION_STATEMENT + 97 => 0, # SQL_MAXIMUM_COLUMNS_IN_GROUP_BY + 98 => 0, # SQL_MAXIMUM_COLUMNS_IN_INDEX + 99 => 0, # SQL_MAXIMUM_COLUMNS_IN_ORDER_BY + 100 => 1000, # SQL_MAXIMUM_COLUMNS_IN_SELECT + 101 => 1000, # SQL_MAXIMUM_COLUMNS_IN_TABLE + 102 => 0, # SQL_MAXIMUM_INDEX_SIZE + 103 => 'N', # SQL_MAX_ROW_SIZE_INCLUDES_LONG + 104 => 0, # SQL_MAXIMUM_ROW_SIZE + 105 => 0, # SQL_MAXIMUM_STATEMENT_LENGTH + 106 => 0, # SQL_MAXIMUM_TABLES_IN_SELECT + 107 => 30, # SQL_MAXIMUM_USER_NAME_LENGTH + 108 => 0, # SQL_MAX_CHAR_LITERAL_LEN + 109 => 0, # SQL_TIMEDATE_ADD_INTERVALS + 110 => 0, # SQL_TIMEDATE_DIFF_INTERVALS + 111 => 'N', # SQL_NEED_LONG_DATA_LEN + 112 => 0, # SQL_MAX_BINARY_LITERAL_LEN + 113 => 'Y', # SQL_LIKE_ESCAPE_CLAUSE + 114 => 2, # SQL_QUALIFIER_LOCATION + 115 => 127, # SQL_OUTER_JOIN_CAPABILITIES + 116 => 0, # SQL_ACTIVE_ENVIRONMENTS + 117 => 0, # SQL_ALTER_DOMAIN + 118 => 1, # SQL_SQL_CONFORMANCE + 119 => 0, # SQL_DATETIME_LITERALS + 120 => 0, # SQL_BATCH_ROW_COUNT + 121 => 0, # SQL_BATCH_SUPPORT 122 => 15106047, # SQL_CONVERT_WCHAR + 123 => 0, # SQL_CONVERT_INTERVAL_DAY_TIME + 124 => 0, # SQL_CONVERT_INTERVAL_YEAR_MONTH 125 => 14680833, # SQL_CONVERT_WLONGVARCHAR 126 => 15106047, # SQL_CONVERT_WVARCHAR - 74 => 2, # SQL_CORRELATION_NAME 127 => 0, # SQL_CREATE_ASSERTION 128 => 0, # SQL_CREATE_CHARACTER_SET 129 => 0, # SQL_CREATE_COLLATION @@ -146,29 +225,7 @@ our %info = ( 132 => 14305, # SQL_CREATE_TABLE 133 => 0, # SQL_CREATE_TRANSLATION 134 => 3, # SQL_CREATE_VIEW - 23 => 2, # SQL_CURSOR_COMMIT_BEHAVIOR - 24 => 2, # SQL_CURSOR_ROLLBACK_BEHAVIOR - 10001 => 1, # SQL_CURSOR_SENSITIVITY - 16 => 'DEVEL', # SQL_DATABASE_NAME - 2 => \&sql_data_source_name, # SQL_DATA_SOURCE_NAME - 25 => 'N', # SQL_DATA_SOURCE_READ_ONLY - 119 => 0, # SQL_DATETIME_LITERALS - 17 => 'Oracle', # SQL_DBMS_NAME - 18 => \&sql_dbms_version, # SQL_DBMS_VER - 18 => \&sql_dbms_version, # SQL_DBMS_VERSION - 170 => 3, # SQL_DDL_INDEX - 26 => 8, # SQL_DEFAULT_TRANSACTION_ISOLATION - 26 => 8, # SQL_DEFAULT_TXN_ISOLATION - 10002 => 'Y', # SQL_DESCRIBE_PARAMETER - 171 => '03.52.0002.0002', # SQL_DM_VER - 3 => 147209344, # SQL_DRIVER_HDBC # 135 => undef, # SQL_DRIVER_HDESC - 4 => 147212776, # SQL_DRIVER_HENV -# 76 => undef, # SQL_DRIVER_HLIB -# 5 => undef, # SQL_DRIVER_HSTMT - 6 => $INC{'DBD/Oracle.pm'}, # SQL_DRIVER_NAME - 77 => '03.52', # SQL_DRIVER_ODBC_VER - 7 => $sql_driver_ver, # SQL_DRIVER_VER 136 => 0, # SQL_DROP_ASSERTION 137 => 0, # SQL_DROP_CHARACTER_SET 138 => 0, # SQL_DROP_COLLATION @@ -179,107 +236,15 @@ our %info = ( 143 => 1, # SQL_DROP_VIEW 144 => 0, # SQL_DYNAMIC_CURSOR_ATTRIBUTES1 145 => 0, # SQL_DYNAMIC_CURSOR_ATTRIBUTES2 - 27 => 'Y', # SQL_EXPRESSIONS_IN_ORDERBY - 8 => 191, # SQL_FETCH_DIRECTION - 84 => 0, # SQL_FILE_USAGE 146 => 57345, # SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1 147 => 2183, # SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2 - 81 => 15, # SQL_GETDATA_EXTENSIONS - 88 => 2, # SQL_GROUP_BY - 28 => 1, # SQL_IDENTIFIER_CASE - 29 => '"', # SQL_IDENTIFIER_QUOTE_CHAR 148 => 3, # SQL_INDEX_KEYWORDS 149 => 65568, # SQL_INFO_SCHEMA_VIEWS - 172 => 7, # SQL_INSERT_STATEMENT - 73 => 'N', # SQL_INTEGRITY 150 => 0, # SQL_KEYSET_CURSOR_ATTRIBUTES1 151 => 0, # SQL_KEYSET_CURSOR_ATTRIBUTES2 - 89 => \&sql_keywords, # SQL_KEYWORDS - 113 => 'Y', # SQL_LIKE_ESCAPE_CLAUSE - 78 => 1, # SQL_LOCK_TYPES - 34 => 0, # SQL_MAXIMUM_CATALOG_NAME_LENGTH - 97 => 0, # SQL_MAXIMUM_COLUMNS_IN_GROUP_BY - 98 => 0, # SQL_MAXIMUM_COLUMNS_IN_INDEX - 99 => 0, # SQL_MAXIMUM_COLUMNS_IN_ORDER_BY - 100 => 1000, # SQL_MAXIMUM_COLUMNS_IN_SELECT - 101 => 1000, # SQL_MAXIMUM_COLUMNS_IN_TABLE - 30 => 30, # SQL_MAXIMUM_COLUMN_NAME_LENGTH - 1 => 0, # SQL_MAXIMUM_CONCURRENT_ACTIVITIES - 31 => 30, # SQL_MAXIMUM_CURSOR_NAME_LENGTH - 0 => 0, # SQL_MAXIMUM_DRIVER_CONNECTIONS - 10005 => 30, # SQL_MAXIMUM_IDENTIFIER_LENGTH - 102 => 0, # SQL_MAXIMUM_INDEX_SIZE - 104 => 0, # SQL_MAXIMUM_ROW_SIZE - 32 => 30, # SQL_MAXIMUM_SCHEMA_NAME_LENGTH - 105 => 0, # SQL_MAXIMUM_STATEMENT_LENGTH -# 20000 => undef, # SQL_MAXIMUM_STMT_OCTETS -# 20001 => undef, # SQL_MAXIMUM_STMT_OCTETS_DATA -# 20002 => undef, # SQL_MAXIMUM_STMT_OCTETS_SCHEMA - 106 => 0, # SQL_MAXIMUM_TABLES_IN_SELECT - 35 => 30, # SQL_MAXIMUM_TABLE_NAME_LENGTH - 107 => 30, # SQL_MAXIMUM_USER_NAME_LENGTH - 10022 => 0, # SQL_MAX_ASYNC_CONCURRENT_STATEMENTS - 112 => 0, # SQL_MAX_BINARY_LITERAL_LEN - 34 => 0, # SQL_MAX_CATALOG_NAME_LEN - 108 => 0, # SQL_MAX_CHAR_LITERAL_LEN - 97 => 0, # SQL_MAX_COLUMNS_IN_GROUP_BY - 98 => 0, # SQL_MAX_COLUMNS_IN_INDEX - 99 => 0, # SQL_MAX_COLUMNS_IN_ORDER_BY - 100 => 1000, # SQL_MAX_COLUMNS_IN_SELECT - 101 => 1000, # SQL_MAX_COLUMNS_IN_TABLE - 30 => 30, # SQL_MAX_COLUMN_NAME_LEN - 1 => 0, # SQL_MAX_CONCURRENT_ACTIVITIES - 31 => 30, # SQL_MAX_CURSOR_NAME_LEN - 0 => 0, # SQL_MAX_DRIVER_CONNECTIONS - 10005 => 30, # SQL_MAX_IDENTIFIER_LEN - 102 => 0, # SQL_MAX_INDEX_SIZE - 32 => 30, # SQL_MAX_OWNER_NAME_LEN - 33 => 92, # SQL_MAX_PROCEDURE_NAME_LEN - 34 => 0, # SQL_MAX_QUALIFIER_NAME_LEN - 104 => 0, # SQL_MAX_ROW_SIZE - 103 => 'N', # SQL_MAX_ROW_SIZE_INCLUDES_LONG - 32 => 30, # SQL_MAX_SCHEMA_NAME_LEN - 105 => 0, # SQL_MAX_STATEMENT_LEN - 106 => 0, # SQL_MAX_TABLES_IN_SELECT - 35 => 30, # SQL_MAX_TABLE_NAME_LEN - 107 => 30, # SQL_MAX_USER_NAME_LEN - 37 => 'Y', # SQL_MULTIPLE_ACTIVE_TXN - 36 => 'Y', # SQL_MULT_RESULT_SETS - 111 => 'N', # SQL_NEED_LONG_DATA_LEN - 75 => 1, # SQL_NON_NULLABLE_COLUMNS - 85 => 1, # SQL_NULL_COLLATION - 49 => 16646015, # SQL_NUMERIC_FUNCTIONS - 9 => 1, # SQL_ODBC_API_CONFORMANCE 152 => 3, # SQL_ODBC_INTERFACE_CONFORMANCE - 12 => 0, # SQL_ODBC_SAG_CLI_CONFORMANCE - 15 => 1, # SQL_ODBC_SQL_CONFORMANCE - 73 => 'N', # SQL_ODBC_SQL_OPT_IEF - 10 => '03.52', # SQL_ODBC_VER - 115 => 127, # SQL_OJ_CAPABILITIES - 90 => 'N', # SQL_ORDER_BY_COLUMNS_IN_SELECT - 38 => 'Y', # SQL_OUTER_JOINS - 115 => 127, # SQL_OUTER_JOIN_CAPABILITIES - 39 => 'Owner', # SQL_OWNER_TERM - 91 => 31, # SQL_OWNER_USAGE 153 => 2, # SQL_PARAM_ARRAY_ROW_COUNTS 154 => 3, # SQL_PARAM_ARRAY_SELECTS - 80 => 7, # SQL_POSITIONED_STATEMENTS - 79 => 1, # SQL_POS_OPERATIONS - 21 => 'Y', # SQL_PROCEDURES - 40 => 'Procedure', # SQL_PROCEDURE_TERM - 114 => 2, # SQL_QUALIFIER_LOCATION - 41 => '@', # SQL_QUALIFIER_NAME_SEPARATOR - 42 => 'Database Link', # SQL_QUALIFIER_TERM - 92 => 3, # SQL_QUALIFIER_USAGE - 93 => 3, # SQL_QUOTED_IDENTIFIER_CASE - 11 => 'Y', # SQL_ROW_UPDATES - 39 => 'Owner', # SQL_SCHEMA_TERM - 91 => 31, # SQL_SCHEMA_USAGE - 43 => 7, # SQL_SCROLL_CONCURRENCY - 44 => 19, # SQL_SCROLL_OPTIONS - 14 => '\\', # SQL_SEARCH_PATTERN_ESCAPE - 13 => sub {"$_[0]->{Name}"}, # SQL_SERVER_NAME - 94 => '$#', # SQL_SPECIAL_CHARACTERS 155 => 0, # SQL_SQL92_DATETIME_FUNCTIONS 156 => 0, # SQL_SQL92_FOREIGN_KEY_DELETE_RULE 157 => 0, # SQL_SQL92_FOREIGN_KEY_UPDATE_RULE @@ -291,26 +256,25 @@ our %info = ( 163 => 0, # SQL_SQL92_ROW_VALUE_CONSTRUCTOR 164 => 0, # SQL_SQL92_STRING_FUNCTIONS 165 => 1, # SQL_SQL92_VALUE_EXPRESSIONS - 118 => 1, # SQL_SQL_CONFORMANCE 166 => 3, # SQL_STANDARD_CLI_CONFORMANCE 167 => 57935, # SQL_STATIC_CURSOR_ATTRIBUTES1 168 => 4231, # SQL_STATIC_CURSOR_ATTRIBUTES2 - 83 => 0, # SQL_STATIC_SENSITIVITY - 50 => 8355839, # SQL_STRING_FUNCTIONS - 95 => 31, # SQL_SUBQUERIES - 51 => 7, # SQL_SYSTEM_FUNCTIONS - 45 => 'Table', # SQL_TABLE_TERM - 109 => 0, # SQL_TIMEDATE_ADD_INTERVALS - 110 => 0, # SQL_TIMEDATE_DIFF_INTERVALS - 52 => 1023999, # SQL_TIMEDATE_FUNCTIONS - 46 => 3, # SQL_TRANSACTION_CAPABLE - 72 => 10, # SQL_TRANSACTION_ISOLATION_OPTION - 46 => 3, # SQL_TXN_CAPABLE - 72 => 10, # SQL_TXN_ISOLATION_OPTION - 96 => 3, # SQL_UNION - 96 => 3, # SQL_UNION_STATEMENT - 47 => \&sql_user_name, # SQL_USER_NAME + 169 => 64, # SQL_AGGREGATE_FUNCTIONS + 170 => 3, # SQL_DDL_INDEX + 171 => '03.52.0002.0002', # SQL_DM_VER + 172 => 7, # SQL_INSERT_STATEMENT + 173 => 0, # SQL_CONVERT_GUID 10000 => 1995, # SQL_XOPEN_CLI_YEAR + 10001 => 1, # SQL_CURSOR_SENSITIVITY + 10002 => 'Y', # SQL_DESCRIBE_PARAMETER + 10003 => 'N', # SQL_CATALOG_NAME + 10004 => '', # SQL_COLLATING_SEQUENCE + 10005 => 30, # SQL_MAXIMUM_IDENTIFIER_LENGTH + 10021 => 2, # SQL_ASYNC_MODE + 10022 => 0, # SQL_MAX_ASYNC_CONCURRENT_STATEMENTS +# 20000 => undef, # SQL_MAXIMUM_STMT_OCTETS +# 20001 => undef, # SQL_MAXIMUM_STMT_OCTETS_DATA +# 20002 => undef, # SQL_MAXIMUM_STMT_OCTETS_SCHEMA ); 1; From 9f78661685d47fa319f1c6bf2dc33012bb261699 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 10 Feb 2012 13:38:38 -0500 Subject: [PATCH 127/637] rt74753, for truncated strings --- dbdimp.c | 7 +++++++ t/rt74753-utf8-encoded.t | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/dbdimp.c b/dbdimp.c index 87e36826..f60989b8 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3222,6 +3222,13 @@ dbd_phs_sv_complete(phs_t *phs, SV *sv, I32 debug) SvCUR_set(sv, phs->alen); *SvEND(sv) = '\0'; SvPOK_only_UTF8(sv); + if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { +#ifdef sv_utf8_decode + sv_utf8_decode(sv); +#else + SvUTF8_on(sv); +#endif + } } else { /* shouldn't happen */ debug = 2; diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index ae318ad2..2491a785 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -57,6 +57,25 @@ $sth->execute; is Encode::is_utf8($val) => 1, "utf8 encoded"; +$sth = $dbh->prepare(<<'END_SQL'); +declare + l_ret varchar2(10); +begin + select ltrim(rtrim(to_char(0, 'L'))) + || ltrim(rtrim(to_char(0, 'L'))) + || ltrim(rtrim(to_char(0, 'L'))) + into l_ret + from dual; + -- + :ret := l_ret; +end; +END_SQL + +$sth->bind_param_inout(':ret', \$val, 1); +$sth->execute; + +is Encode::is_utf8($val) => 1, "truncated, yet utf8 encoded"; + $dbh->disconnect; From 8cecadeeb7fa8b244cfa3bb6475baccb98a8af8b Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 10 Feb 2012 13:39:18 -0500 Subject: [PATCH 128/637] Build results of 9f78661 (on master) --- .gitignore | 14 - Changes | 2 +- INSTALL | 44 + LICENSE | 377 ++ MANIFEST | 1 + MANIFEST.SKIP | 32 - META.json | 97 + META.yml | 63 + README | 4338 ++++++++++++++- README.mkdn | 4228 +++++++++++++++ dist.ini | 22 - err_bind/err_bind_param_inout_overrun_bug.msg | 108 - err_bind/err_bindarrays.msg | 241 - err_bind/err_bindclobleak.msg | 58 - err_bind/err_bindnullhash.msg | 77 - err_bind/err_trailingblank.msg | 345 -- err_build/err_aix64.msg | 142 - err_build/err_hpux_ld.msg | 89 - err_build/err_hpuxsuccess.msg | 279 - err_build/err_instantclient.msg | 207 - err_build/err_makefileundef.msg | 87 - err_build/err_memleak.msg | 95 - err_build/err_solarisnotes.msg | 482 -- err_build/err_testfailnotable.msg | 97 - err_docs/err_trace.msg | 14 - err_lob/err_csr_clob.msg | 65 - err_lob/err_loblenwide.msg | 95 - err_lob/err_lobtesttblfail.msg | 208 - err_lob/err_nclob_form.msg | 189 - err_lob/err_nulllobsegv.msg | 93 - err_lob/err_tmplobfree.msg | 537 -- err_unicode/err_char.msg | 129 - err_unicode/err_twolongstr.msg | 1256 ----- err_unsorted/err_etherreal.msg | 90 - err_unsorted/err_memleak2.msg | 476 -- err_unsorted/err_multiora.msg | 470 -- err_unsorted/err_ora9ir2oci.msg | 27 - err_unsorted/err_ref_type.msg | 115 - err_unsorted/err_refcsr_rowcache.msg | 85 - err_unsorted/err_refcsr_slow.msg | 347 -- err_unsorted/err_slowcsr.msg | 316 -- err_unsorted/err_svrparse.msg | 4717 ----------------- err_unsorted/err_xml.msg | 118 - err_unsorted/err_xml2.msg | 700 --- err_unsorted/err_xmltypebindplsql.msg | 174 - lib/DBD/Oracle.pm | 109 +- lib/DBD/Oracle/GetInfo.pm | 46 + lib/DBD/Oracle/Object.pm | 95 +- lib/DBD/Oracle/Troubleshooting.pm | 48 +- t/000-report-versions.t | 446 ++ xt/changes.t | 8 - xt/manifest.t | 21 - xt/pod.t | 11 - 53 files changed, 9594 insertions(+), 12936 deletions(-) delete mode 100644 .gitignore create mode 100644 INSTALL create mode 100644 LICENSE delete mode 100644 MANIFEST.SKIP create mode 100644 META.json create mode 100644 META.yml create mode 100644 README.mkdn delete mode 100644 dist.ini delete mode 100644 err_bind/err_bind_param_inout_overrun_bug.msg delete mode 100644 err_bind/err_bindarrays.msg delete mode 100644 err_bind/err_bindclobleak.msg delete mode 100644 err_bind/err_bindnullhash.msg delete mode 100644 err_bind/err_trailingblank.msg delete mode 100644 err_build/err_aix64.msg delete mode 100644 err_build/err_hpux_ld.msg delete mode 100644 err_build/err_hpuxsuccess.msg delete mode 100644 err_build/err_instantclient.msg delete mode 100644 err_build/err_makefileundef.msg delete mode 100644 err_build/err_memleak.msg delete mode 100644 err_build/err_solarisnotes.msg delete mode 100644 err_build/err_testfailnotable.msg delete mode 100644 err_docs/err_trace.msg delete mode 100644 err_lob/err_csr_clob.msg delete mode 100644 err_lob/err_loblenwide.msg delete mode 100644 err_lob/err_lobtesttblfail.msg delete mode 100644 err_lob/err_nclob_form.msg delete mode 100644 err_lob/err_nulllobsegv.msg delete mode 100644 err_lob/err_tmplobfree.msg delete mode 100644 err_unicode/err_char.msg delete mode 100644 err_unicode/err_twolongstr.msg delete mode 100644 err_unsorted/err_etherreal.msg delete mode 100644 err_unsorted/err_memleak2.msg delete mode 100644 err_unsorted/err_multiora.msg delete mode 100644 err_unsorted/err_ora9ir2oci.msg delete mode 100644 err_unsorted/err_ref_type.msg delete mode 100644 err_unsorted/err_refcsr_rowcache.msg delete mode 100644 err_unsorted/err_refcsr_slow.msg delete mode 100644 err_unsorted/err_slowcsr.msg delete mode 100644 err_unsorted/err_svrparse.msg delete mode 100644 err_unsorted/err_xml.msg delete mode 100644 err_unsorted/err_xml2.msg delete mode 100644 err_unsorted/err_xmltypebindplsql.msg create mode 100644 t/000-report-versions.t delete mode 100644 xt/changes.t delete mode 100644 xt/manifest.t delete mode 100644 xt/pod.t diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 15e927c8..00000000 --- a/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -pm_to_blib -MYMETA.yml -Makefile -Makefile.old -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -blib -MYMETA.json -dbdimp.o -mk.pm -oci8.o -DBD-Oracle* diff --git a/Changes b/Changes index b2a2b58c..acc65f36 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.38 2012-02-10 [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..b5ab17a0 --- /dev/null +++ b/INSTALL @@ -0,0 +1,44 @@ + +This is the Perl distribution DBD-Oracle. + +Installing DBD-Oracle is straightforward. + +## Installation with cpanm + +If you have cpanm, you only need one line: + + % cpanm DBD::Oracle + +If you are installing into a system-wide directory, you may need to pass the +"-S" flag to cpanm, which uses sudo to install the module: + + % cpanm -S DBD::Oracle + +## Installing with the CPAN shell + +Alternatively, if your CPAN shell is set up, you should just be able to do: + + % cpan DBD::Oracle + +## Manual installation + +As a last resort, you can manually install it. Download the tarball, untar it, +then build it: + + % perl Makefile.PL + % make && make test + +Then install it: + + % make install + +If you are installing into a system-wide directory, you may need to run: + + % sudo make install + +## Documentation + +DBD-Oracle documentation is available as POD. +You can run perldoc from a shell to read the documentation: + + % perldoc DBD::Oracle diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..a6a371c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,377 @@ +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +Terms of the Perl programming language system itself + +a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or +b) the "Artistic License" + +--- The GNU General Public License, Version 1, February 1989 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The GNU General Public License, Version 1, February 1989 + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! + + +--- The Artistic License 1.0 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The Artistic License 1.0 + +The Artistic License + +Preamble + +The intent of this document is to state the conditions under which a Package +may be copied, such that the Copyright Holder maintains some semblance of +artistic control over the development of the package, while giving the users of +the package the right to use and distribute the Package in a more-or-less +customary fashion, plus the right to make reasonable modifications. + +Definitions: + + - "Package" refers to the collection of files distributed by the Copyright + Holder, and derivatives of that collection of files created through + textual modification. + - "Standard Version" refers to such a Package if it has not been modified, + or has been modified in accordance with the wishes of the Copyright + Holder. + - "Copyright Holder" is whoever is named in the copyright or copyrights for + the package. + - "You" is you, if you're thinking about copying or distributing this Package. + - "Reasonable copying fee" is whatever you can justify on the basis of media + cost, duplication charges, time of people involved, and so on. (You will + not be required to justify it to the Copyright Holder, but only to the + computing community at large as a market that must bear the fee.) + - "Freely Available" means that no fee is charged for the item itself, though + there may be fees involved in handling the item. It also means that + recipients of the item may redistribute it under the same conditions they + received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications derived +from the Public Domain or from the Copyright Holder. A Package modified in such +a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided that +you insert a prominent notice in each changed file stating how and when you +changed that file, and provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major archive site + such as ftp.uu.net, or by allowing the Copyright Holder to include your + modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict with + standard executables, which must also be provided, and provide a separate + manual page for each non-standard executable that clearly documents how it + differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or executable +form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where to + get the Standard Version. + + b) accompany the distribution with the machine-readable source of the Package + with your modifications. + + c) accompany any non-standard executables with their corresponding Standard + Version executables, giving the non-standard executables non-standard + names, and clearly documenting the differences in manual pages (or + equivalent), together with instructions on where to get the Standard + Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. You +may not charge a fee for this Package itself. However, you may distribute this +Package in aggregate with other (possibly commercial) programs as part of a +larger (possibly commercial) software distribution provided that you do not +advertise this Package as a product of your own. + +6. The scripts and library files supplied as input to or produced as output +from the programs of this Package do not automatically fall under the copyright +of this Package, but belong to whomever generated them, and may be sold +commercially, and may be aggregated with this Package. + +7. C or perl subroutines supplied by you and linked into this Package shall not +be considered part of this Package. + +8. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +The End + diff --git a/MANIFEST b/MANIFEST index 436c409e..34c7a9d4 100644 --- a/MANIFEST +++ b/MANIFEST @@ -89,5 +89,6 @@ t/70meta.t t/80ora_charset.t t/nchar_test_lib.pl t/rt13865.t +t/rt74753-utf8-encoded.t test.pl typemap diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP deleted file mode 100644 index c7db4c66..00000000 --- a/MANIFEST.SKIP +++ /dev/null @@ -1,32 +0,0 @@ -^DBD-Oracle-.* -\.svn\b -\.orig$ -\..*.swp$ -^.pure -^DIST/ -^MANIFEST\. -^Makefile$ -^blib/ -^csr/ -^err[/_] -^old/ -^info/ -^oci8/ -^oracle/ -^tags$ -~$ -^\.git -^xt -dbdimp.o -Makefile.old -mk.pm -MYMETA.json -MYMETA.yml -oci8.o -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -pm_to_blib - -dist.ini diff --git a/META.json b/META.json new file mode 100644 index 00000000..3af05f40 --- /dev/null +++ b/META.json @@ -0,0 +1,97 @@ +{ + "abstract" : "Oracle database driver for the DBI module", + "author" : [ + "Tim Bunce ", + "John Scoles", + "Yanick Champoux " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "DBD-Oracle", + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "6.30" + } + }, + "runtime" : { + "requires" : { + "DBI" : 0, + "DynaLoader" : 0, + "Exporter" : 0, + "perl" : "5.006", + "strict" : 0, + "warnings" : 0 + } + }, + "test" : { + "requires" : { + "Carp" : 0, + "Config" : 0, + "Data::Dumper" : 0, + "Devel::Peek" : 0, + "Encode" : 0, + "Math::BigInt" : 0, + "Oraperl" : 0, + "Scalar::Util" : 0, + "Test::More" : "0.94", + "Thread::Semaphore" : 0, + "utf8" : 0, + "vars" : 0 + } + } + }, + "provides" : { + "DBD::Oracle" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::GetInfo" : { + "file" : "lib/DBD/Oracle/GetInfo.pm", + "version" : "1.38" + }, + "DBD::Oracle::Object" : { + "file" : "lib/DBD/Oracle/Object.pm", + "version" : "1.38" + }, + "DBD::Oracle::Troubleshooting" : { + "file" : "lib/DBD/Oracle/Troubleshooting.pm", + "version" : "1.38" + }, + "DBD::Oracle::db" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::dr" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + }, + "DBD::Oracle::st" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.38" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "mailto" : "bug-dbd-oracle at rt.cpan.org", + "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle" + }, + "homepage" : "http://search.cpan.org/dist/DBD-Oracle/", + "repository" : { + "type" : "git", + "url" : "git://github.com/yanick/DBD-Oracle.git", + "web" : "http://github.com/yanick/DBD-Oracle/tree" + } + }, + "version" : "1.38", + "x_authority" : "cpan:PYTHIAN" +} + diff --git a/META.yml b/META.yml new file mode 100644 index 00000000..c1c09bd4 --- /dev/null +++ b/META.yml @@ -0,0 +1,63 @@ +--- +abstract: 'Oracle database driver for the DBI module' +author: + - 'Tim Bunce ' + - 'John Scoles' + - 'Yanick Champoux ' +build_requires: + Carp: 0 + Config: 0 + Data::Dumper: 0 + Devel::Peek: 0 + Encode: 0 + Math::BigInt: 0 + Oraperl: 0 + Scalar::Util: 0 + Test::More: 0.94 + Thread::Semaphore: 0 + utf8: 0 + vars: 0 +configure_requires: + ExtUtils::MakeMaker: 6.30 +dynamic_config: 0 +generated_by: 'Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: DBD-Oracle +provides: + DBD::Oracle: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::GetInfo: + file: lib/DBD/Oracle/GetInfo.pm + version: 1.38 + DBD::Oracle::Object: + file: lib/DBD/Oracle/Object.pm + version: 1.38 + DBD::Oracle::Troubleshooting: + file: lib/DBD/Oracle/Troubleshooting.pm + version: 1.38 + DBD::Oracle::db: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::dr: + file: lib/DBD/Oracle.pm + version: 1.38 + DBD::Oracle::st: + file: lib/DBD/Oracle.pm + version: 1.38 +requires: + DBI: 0 + DynaLoader: 0 + Exporter: 0 + perl: 5.006 + strict: 0 + warnings: 0 +resources: + bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle + homepage: http://search.cpan.org/dist/DBD-Oracle/ + repository: git://github.com/yanick/DBD-Oracle.git +version: 1.38 +x_authority: cpan:PYTHIAN diff --git a/README b/README index fd2b28aa..bf8f7b60 100644 --- a/README +++ b/README @@ -1,301 +1,4183 @@ +NAME + DBD::Oracle - Oracle database driver for the DBI module -DBD::Oracle -- an Oracle interface for Perl 5. +VERSION + version 1.38 - Copyright (c) 1994-2006 Tim Bunce, Ireland. +SYNOPSIS + use DBI; - See the COPYRIGHT section in the Oracle.pm file for terms. - See also the MAINTAINER section in the Oracle.pm + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); - PLEASE READ THE ENTIRE README FILE CAREFULLY ! + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); - AND THEN READ ANY README.* FILES RELEVANT TO YOUR PLATFORM: + # See the DBI module documentation for full details - README.aix.txt - AIX - README.hpux.txt - HP-UX - README.java.txt - Java/thread problem on Solaris - README.macosx.txt - Mac OS/X - README.win32.txt - MS Windows - README.wingcc.txt - MS Windows using GCC - README.* - see if there's a file for your platform + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); - You may find these useful +DESCRIPTION + DBD::Oracle is a Perl module which works with the DBI module to provide + access to Oracle databases. - README.help.txt - Help and hints on build problems - README.sec.txt - Oracle security issues to be aware of - README.login.txt - Help on how to connect to Oracle - README.longs.txt - Help on handling LONGs - README.clients.txt - What Oracle client files you need installed + This documentation describes driver specific behaviour and restrictions. + It is not supposed to be used as the only reference for the user. In any + case consult the DBI documentation first! +CONSTANTS + :ora_session_modes + ORA_SYSDBA ORA_SYSOPER ORA_SYSASM -*** QUICK START GUIDE: + :ora_types + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN - The DBI requires one or more 'driver' modules to talk to databases. - Fetch, build and install the DBI module as per its README file. - You may then delete its source directory tree since it's no longer needed. - Use the 'perldoc DBI' command to read the DBI documentation. + SQLCS_IMPLICIT + SQLCS_NCHAR + SQLCS_IMPLICIT and SQLCS_NCHAR are *character set form* values. See + notes about Unicode elsewhere in this document. - Fetch this DBD::Oracle driver module and unpack it. - Follow the guidelines in this README file carefully. + SQLT_INT + SQLT_FLT + These types are used only internally, and may be specified as + internal bind type for ORA_NUMBER_TABLE. See notes about + ORA_NUMBER_TABLE elsewhere in this document + ORA_OCI + Oracle doesn't provide a formal API for determining the exact + version number of the OCI client library used, so DBD::Oracle has to + go digging (and sometimes has to more or less guess). The ORA_OCI + constant holds the result of that process. -*** *BEFORE* BUILDING, TESTING AND INSTALLING DBD::Oracle: + In string context ORA_OCI returns the full "A.B.C.D" version string. - Build, test and install Perl 5 (at least 5.6.1) - It is very important to TEST it and INSTALL it! + In numeric context ORA_OCI returns the major.minor version number + (8.1, 9.2, 10.0 etc). But note that version numbers are not actually + floating point and so if Oracle ever makes a release that has a two + digit minor version, such as 9.10 it will have a lower numeric value + than the preceding 9.9 release. So use with care. - Build, test and install the DBI module (at least DBI 1.51). - It is very important to TEST it and INSTALL it! + The contents and format of ORA_OCI are subject to change (it may, + for example, become a *version object* in later releases). I + recommend that you avoid checking for exact values. - Remember to *read* the DBI README file and this one CAREFULLY! + :ora_fetch_orient + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE - Install enough Oracle software to enable DBD::Oracle to build. + These constants are used to set the orientation of a fetch on a + scrollable cursor. - For Oracle Instant Client: that means install the following packages: - * The "Basic" package for the essential Oracle libraries. - * The "SDK" package for the headers and makefile. - * The "SQL*Plus" component is optional, but will help you check - your configuration and DBD::Oracle determine your Oracle version. + :ora_exe_modes + OCI_STMT_SCROLLABLE_READONLY - For full Oracle installs: that usually includes Pro*C and SQL*Net. - (That's not very specific because it varies between Oracle releases.). - As of release 1.22 support of Oracle clients before 9 was dropped. - The main reason for this is that next few versions of DBD::Oracle will introduce a number of new features - whicht will required a great deal of extra coding to make the OCI 8 work. - As well it is getting harder to find an Oracle client 8 to test against as well - Oracle no longer supports clients before 9. + :ora_fail_over + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL - The ORACLE_HOME environment variable must point to the Oracle Home - used to create DBD::Oracle. (Not essential under MS Windows). +DBI CLASS METHODS + connect + This method creates a database handle by connecting to a database, and + is the DBI equivalent of the "new" method. To open a connection to an + Oracle database you need to specify a database connection string (URL), + username and password. -*** MOST IMPORTANTLY: + The connection string is always of the form: "dbi:Oracle:" There are several ways to identify a database: - Make sure Oracle is working and you can use the Oracle sqlplus - command to talk to the database from the machine you - want to build DBD::Oracle on. This often involves setting - environment variables like PATH, LD_LIBRARY_PATH, TWO_TASK etc. - Consult Oracle documentation for more details. + 1 If the database is local, specifying the SID or service name will be + enough. - Only once you can connect to Oracle using sqlplus - should you try building and testing DBD::Oracle. + 2 If the database is defined in a TNSNAMES.ORA file, you can use the + service name given in the file -*** BUILDING: + 3 To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, + of the form: //host[:port][/service_name] -Execute: + If port name is not specified, 1521 is the default. If service name is + not specified, the hostname will be used as a service name. - perl Makefile.PL # use a perl that's in your PATH + The following examples show several ways a connection can be created: -Use the perl that is first on your PATH. Then execute: + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - make + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); -If you get an error like "make: not found" you need to find the -directory that has the make command installed in it (e.g. /usr/ccs/bin -on Solaris) and add that to your PATH environment variable. + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); -Don't worry about most warnings when make runs, specifically ones like -"end-of-loop code not reached", "... due to prototype", -"cast increases required alignment of target type", etc. + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); -If you have problems see the 'IF YOU HAVE PROBLEMS' section below. -If it builds without error you should then run 'make test'. For the -main tests to work they must be able to connect to an Oracle database. + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); -The tests default to using a DSN of "dbi:Oracle:" which means you'll be -connected to the default database based on your TWO_TASK or ORACLE_SID -environment variables. This default can be altered either by defining the -ORACLE_DSN environment variable or the DBI_DSN environment variable. -See the oracle_test_dsn() sub in t/nchar_test_lib.pl + OS authentication + To connect to a local database with a user which has been set up to + authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): -The supplied tests will connect to the database using the value of the -ORACLE_USERID environment variable to supply the username/password. -So you should set that to a valid user (e.g. 'scott/tiger') and ensure that -this user has sufficient privileges to create, insert into, select from and -drop a table, is also able to create, call and drop a procedure and is able to select from -systemtables like 'v$sessions'. Using 'system/manager' might work but is not -recommended! See also + $dbh = DBI->connect('dbi:Oracle:','/',''); -README.login.txt. + Note the lack of a connection name (use the ORACLE_SID environment + variable). If an explicit SID is used you will probably get an ORA-01004 + error. - make test + That only works for local databases. (Authentication to remote Oracle + databases using your Unix login name without a password is possible but + it is not secure and not recommended so not documented here. -If the all the formal tests pass then, finally, run: + Oracle Environment Variables + To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME + environment variable should be set correctly. In general, the value used + should match the version of Oracle that was used to build DBD::Oracle. + If using dynamic linking then ORACLE_HOME should match the version of + Oracle that will be used to load in the Oracle client libraries (via + LD_LIBRARY_PATH, ldconfig, or similar on Unix). - make install + Oracle can use two environment variables to specify default connections: + ORACLE_SID and TWO_TASK. + To use them, specify either a local SID or service name, or a service + name that is specified in the TNSNAMES.ORA file. -*** IF YOU HAVE PROBLEMS: + Note that if you have *both* local and remote databases, and you have + ORACLE_SID *and* TWO_TASK set, and you don't specify a fully qualified + connect string on the command line, TWO_TASK takes precedence over + ORACLE_SID (i.e. you get connected to remote system). -Make sure you are using a recent perl (5.6.1 or later) and make -sure it's on your PATH so you can say 'perl Makefile.PL' and not -'/path/to/perl Makefile.PL'. + It is highly recommended not to rely on environment variables and to + always explicitly specify the SID in the connection string. This can + prevent serious mistakes such as dropping a schema in the wrong + database, and generally makes debugging and troubleshooting easier. -If you get compiler errors refering to Perl's own header files -(.../CORE/*.h) then there is something wrong with your installation. -It is important to use a Perl that was built on the system you are using. -It's also important to use the same compiler that was used to build the -Perl you are using. + Also remember that depending on the operating system you are using the + differing "ORACLE" environment variables may be case sensitive, so if + you are not connecting as you should double check the case of both the + variable and its value. -If you have build/link or core dump problems try: - perl Makefile.PL -p -or - perl Makefile.PL -nob -If it helps then please let me know (and please include a copy -of the log from the failed default build, the log from the build that -worked, plus the output of the "perl -V" command). + Timezones + If the query is run through SQL*Net (mostly queries that are executed on + remote servers), Oracle will return the time zone based on the setting + of the UNIX environment variable "TZ" for the user who started the + listener. -Do not hand edit the generated Makefile unless you are completely sure -you understand the implications! Always try to make changes via the -Makefile.PL command line and/or editing the Makefile.PL. -You should not need to make any changes. If you do please let us -know so that I can try to make it automatic in a later release. + If the query is run locally, Oracle will return the time zone based on + the "TZ" environment variable setting of the user running the query. -If you just can't login or login takes a long time then read -README.login.txt + With local queries, you can change the time zone for a particular user + by simply changing the setting of "TZ". To check the current setting, + issue the UNIX "date" command. -If you have linking problems (errors related to libraries or functions) -then you could try forcing a 'static' build using: + Oracle DRCP + DBD::Oracle supports DRCP (Database Resident Connection Pool) so if you + have an 11.2 database and DRCP is enabled you can direct all of your + connections to it by adding ':POOLED' to the SID or setting a connection + attribute of ora_drcp, or set the SERVER=POOLED when using a TNSENTRY + style connection or even by setting an environment variable ORA_DRCP. + All of which are demonstrated below; - make realclean - perl Makefile.PL LINKTYPE=static - make - make perl (you'll need to use and install _this_ new perl binary) - make test - make -f Makefile.aperl inst_perl MAP_TARGET=perl (install new perl) - make install (install DBD::Oracle) + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') -But that's not recommended these days. + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') ->>> Also carefully read the README.help.txt file which is full of useful ->>> tips and workarounds for various problems of various systems. + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) -*** HOW TO REPORT PROBLEMS + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') -This software is supported via the dbi-users@perl.org mailing list. -(You don't need to subscribe to the list in order to post.) + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") -Please do NOT post problems to comp.lang.perl.*, perl5-porters@perl.org, -http://www.cpanforum.com/dist/DBD-Oracle, or google groups etc. + if the ORA_DRCP environment variable is set then just this -If you're *sure* the problem is a bug then you can post a bug report -to http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle -Problem reports that don't include sufficient detail (including the -information listed below and how to reproduce the problem) -are unlikely to get resolved. + $dbh = DBI->connect('dbi:Oracle:DB','username','password') -For more information and to keep informed about progress you can join the -mailing list. Send a message to dbi-users-help@perl.org for more information. + You can find a white paper on setting up DRCP and its advantages at + . -Please post details of any problems (or changes you needed to make) to -dbi-users@perl.org. - - -** IT IS IMPORTANT TO INCLUDE *ALL* THE FOLLOWING INFORMATION: + Please note that DRCP support in DBD::Oracle is relatively new so the + mechanics or its implementation are subject to change. -1. A complete log of all steps of the build, e.g.: + TAF (Transparent Application Failover) + Transparent Application Failover (TAF) is the feature in OCI that allows + for clients to automatically reconnect to an instance in the event of a + failure of the instance. The reconnect happens automatically from within + the OCI (Oracle Call Interface) library. DBD::Oracle now supports a + callback function that will fire when a TAF event takes place. The main + use of the callback is to give your program the opportunity to inform + the user that a failover is taking place. - (do a make realclean first) - perl Makefile.PL - make - make test + You will have to set up TAF on your instance before you can use this + callback. You can test your instance to see if you can use TAF callback + with - Make sure to include the 'stderr' output. The best way to do this is - to use the "script" command (man script). If that's not available - then "command > command.log 2>&1" (assuming you're not using csh). - The "2>&1" is required (after the stdout redirect) to redirect stderr - to the same place. + $dbh->ora_can_taf(); - If a test fails then also include the output of: + If you try to set up a callback without it being enabled DBD::Oracle + will croak. - perl -Mblib t/.t + It is outside the scope of this documents to go through all of the + possible TAF situations you might want to set up but here is a simple + example: -2. Full details of which version of Oracle client and server you're using - (if it wasn't automatically found and printed by "perl Makefile.PL") + The TNS entry for the instance has had the following added to the + CONNECT_DATA section -3. The output of perl -V (that's a capital V, not lowercase) + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) -4. If you get errors like "undefined symbol", "symbol not found", - "undefined reference", "Text relocation remains" or any similar - error then include the output of "perl Makefile.PL -s XXX" - where XXX is the name of one of the symbols. - Please don't send the entire output of this command, - just any obviously 'interesting' parts (if there are any). - See also the LINKTYPE=static notes above. + You will also have to create your own perl function that will be called + from the client. You can name it anything you want and it will always be + passed two parameters, the failover event value and the failover type. + You can also set a sleep value in case of failover error and the OCI + client will sleep for the specified seconds before it attempts another + event. -5. If you get a core dump, rebuild DBD::Oracle with debugging - enabled by executing: perl Makefile.PL -g (note the -g option) - then rerun the code to get a new core dump file, finally use a - debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. - NOTE: I may not be able to help you much without a stack trace! - It is worth fetching and building the GNU GDB debugger (>=4.15) if - you don't have a good debugger on your system. If desperate try: - make perl; ./perl script; echo '$c' | adb ./perl core - Also see the Devel::CoreStack module on CPAN. - -6. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun - make test after setting the environment variable PERL_DL_DEBUG to 2. - -7. If your installation succeeds, but your script does not behave - as you expect, the problem may be on your end. Before - sending to dbi-users, try writing a *small*, easy to use test case - to reproduce your problem. Also, use the DBI->trace method to - trace your database calls. + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants -It is important to check that you are using the latest version before -posting. If you're not then you're *very* likely to be told "upgrade to -the latest". You would do yourself a favour by upgrading beforehand. + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); -Try to help yourself first, then try to help others help you by following -these guidelines carefully. And remember, please don't mail developers -directly - use the dbi-users mailing list. + #create the perl TAF event function -Regards, -Tim. + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ -=============================================================================== -Examples and other info: + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); -README.help.txt -- READ IT FIRST IF YOU HAVE ANY PROBLEMS -README.win32.txt -- building DBD::Oracle under MS Windows -README.wingcc.txt -- building DBD::Oracle under MS Windows with gcc -README.macosx.txt -- building DBD::Oracle under MacOS X -README.clients.txt -- building/using DBD::Oracle on minimally configured systems -README.login.txt -- help for login problems -README.longs.txt -- examples dealing with LONG types (blobs) + } + return 0; + } -DBI 'home page': http://dbi.perl.org + The TAF types are as follows -Old archive site for Perl DB information: - ftp://ftp.demon.co.uk/pub/perl/db/ -Mailing list archive: /DBI/perldb-interest/ -Perl 4 Oraperl (v2.4) /perl4/oraperl/ - -Jeff Stander's stuff stands out for Oraperl: -Directories of interest might be - /pub/Oracle/sources - /pub/Oracle/sources/jstander - /pub/Oracle/sources/jstander/distrib - /pub/Oracle/sources/jstander/tsmlib - /pub/Oracle/sources/jstander/wdbex - /pub/Oracle/sources/web/scripts - /pub/Oracle/sources/dba - /pub/Oracle/sources/dba/imp2sql7 - /pub/Oracle/sources/Lonnroth - /pub/Oracle/sources/harrison - -http://www.bf.rmit.edu.au/~orafaq/perlish.html -ftp://ftp.bf.rmit.edu.au/pub/perl/db -ftp://ftp.bf.rmit.edu.au/pub/Oracle -ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources -ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip - -DBI and DBD::Oracle are very portable. If Perl and Oracle run on a platform -then the chances are that DBD::Oracle will as well. - -=============================================================================== - -See the large README.help.txt file for lots of hints and advice -about building and runtime issues. - -End. + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + + The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + + Connect Attributes + ora_ncs_buff_mtpl + You can customize the size of the buffer when selecting LOBs with the + built-in AUTO Lob. The default value is 4 which is probably excessive + for most situations but is needed for backward compatibility. If you not + converting between a NCS on the DB and the Client then you might want to + set this to 1 to reduce memory usage. + + This value can also be specified with the "ORA_DBD_NCS_BUFFER" + environment variable in which case it sets the value at the connect + stage. + + ora_drcp + For Oracle 11.2 or greater. + + Set to *1* to enable DRCP. Can also be set via the "ORA_DRCP" + environment variable. + + ora_drcp_class + If you are using DRCP, you can set a CONNECTION_CLASS for your pools as + well. As sessions from a DRCP cannot be shared by users, you can use + this setting to identify the same user across different applications. + OCI will ensure that sessions belonging to a 'class' are not shared + outside the class'. + + The values for ora_drcp_class cannot contain a '*' and must be less than + 1024 characters. + + This value can be also be specified with the "ORA_DRCP_CLASS" + environment variable. + + ora_drcp_min + This optional value specifies the minimum number of sessions that are + initially opened. New sessions are only opened after this value has been + reached. + + The default value is 4 and any value above 0 is valid. + + Generally, it should be set to the number of concurrent statements the + application is planning or expecting to run. + + This value can also be specified with the "ORA_DRCP_MIN" environment + variable. + + ora_drcp_max + This optional value specifies the maximum number of sessions that can be + open at one time. Once reached no more sessions can be opened until one + becomes free. The default value is 40 and any value above 1 is valid. + You should not set this value lower than ora_drcp_min as that will just + waste resources. + + This value can also be specified with the "ORA_DRCP_MAX" environment + variable. + + ora_drcp_incr + This optional value specifies the next increment for sessions to be + started if the current number of sessions are less than ora_drcp_max. + The default value is 2 and any value above 0 is valid as long as the + value of ora_drcp_min + ora_drcp_incr is not greater than ora_drcp_max. + + This value can also be specified with the "ORA_DRCP_INCR" environment + variable. + + ora_taf + If your Oracle instance has been configured to use TAF events you can + enable the TAF callback by setting this option to any *true* value. + + ora_taf_function + The name of the Perl subroutine that will be called from OCI when a TAF + event occurs. You must supply a perl function to use the callback and it + will always receive two parameters, the failover event value and the + failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + + ora_taf_sleep + The amount of time in seconds the OCI client will sleep between + attempting successive failover events when the event is OCI_FO_ERROR. + + ora_session_mode + The ora_session_mode attribute can be used to connect with SYSDBA, + SYSOPER and ORA_SYSASM authorization. The ORA_SYSDBA, ORA_SYSOPER and + ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + + This is one case where setting ORACLE_SID may be useful since connecting + as SYSDBA or SYSOPER via SQL*Net is frequently disabled for security + reasons. + + Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + + It has been reported that this only works if $dsn does not contain a SID + so that Oracle then uses the value of ORACLE_SID (not TWO_TASK) + environment variable to connect to a local instance. Also the username + and password should be empty, and the user executing the script needs to + be part of the dba group or osdba group. + + ora_oratab_orahome + Passing a true value for the ora_oratab_orahome attribute will make + DBD::Oracle change $ENV{ORACLE_HOME} to make the Oracle home directory + that specified in the "/etc/oratab" file *if* the database to connect to + is specified as a SID that exists in the oratab file, and DBD::Oracle + was built to use the Oracle 7 OCI API (not Oracle 8+). + + ora_module_name + After connecting to the database the value of this attribute is passed + to the SET_MODULE() function in the "DBMS_APPLICATION_INFO" PL/SQL + package. This can be used to identify the application to the DBA for + monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + + The maximum size is 48 bytes. + + ora_driver_name + For 11g and later you can now set the name of the driver layer using + OCI. Perl, Perl5, ApachePerl so on. Names starting with "ORA" are + reserved. You can enter up to 8 characters. If none is enter then this + will default to DBDOxxxx where xxxx is the current version number. This + value can be retrieved on the server side using V$SESSION_CONNECT_INFO + or GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + + ora_client_info + Allows you to add any value (up to 64 bytes) to your session and it can + be retrieved on the server side from the "V$SESSION"a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + + ora_client_identifier + Allows you to specify the user identifier in the session handle. + + Most useful for web applications as it can pass in the session user name + which might be different to the connection user name. Can be up to 64 + bytes long but do not to include the password for security reasons and + the first character of the identifier should not be ':'. This value can + be retrieved on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + + ora_action + Allows you to specify any string up to 32 bytes which may be retrieved + on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + + ora_dbh_share + Requires at least Perl 5.8.0 compiled with ithreads. + + Allows you to share database connections between threads. The first + connect will make the connection, all following calls to connect with + the same ora_dbh_share attribute will use the same database connection. + The value must be a reference to a already shared scalar which is + initialized to an empty string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + + ora_envhp + The first time a connection is made a new OCI 'environment' is created + by DBD::Oracle and stored in the driver handle. Subsequent connects + reuse (share) that same OCI environment by default. + + The ora_envhp attribute can be used to disable the reuse of the OCI + environment from a previous connect. If the value is 0 then a new OCI + environment is allocated and used for this connection. + + The OCI environment holds information about the client side context, + such as the local NLS environment. By altering %ENV and setting + ora_envhp to 0 you can create connections with different NLS settings. + This is most useful for testing. + + ora_charset, ora_ncharset + For oracle versions >= 9.2 you can specify the client charset and + ncharset with the ora_charset and ora_ncharset attributes. You still + need to pass "ora_envhp = 0" for all but the first connect. + + These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + + ora_verbose + Use this value to enable DBD::Oracle only tracing. Simply either set the + ora_verbose attribute on the connect() method to the trace level you + desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + + or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + + In both cases the DBD::Oracle trace level is set to 6, which is the + highest level tracing most of the calls to OCI. + + ora_oci_success_warn + Use this value to print otherwise silent OCI warnings that may happen + when an execute or fetch returns "Success With Info" or when you want to + tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + + ora_objects + Use this value to enable extended embedded oracle objects mode. In + extended: + + 1 Embedded objects are returned as instance + (including type-name etc.) instead of simple ARRAY. + + 2 Determine object type for each instance. All object attributes are + returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + + ora_ph_type + The default placeholder datatype for the database session. The "TYPE" or + "ora_type" attributes to "bind_param" in DBI and "bind_param_inout" in + DBI override the datatype for individual placeholders. The most frequent + reason for using this attribute is to permit trailing spaces in values + passed by placeholders. + + Constants for the values allowed for this attribute can be imported + using + + use DBD::Oracle qw(:ora_types); + + Only the following values are permitted for this attribute. + + ORA_VARCHAR2 + Oracle clients using OCI 8 will strip trailing spaces and allow + embedded \0 bytes. Oracle clients using OCI 9.2 do not strip + trailing spaces and allow embedded \0 bytes. This is the normal + default placeholder type. + + ORA_STRING + Do not strip trailing spaces and end the string at the first \0. + + ORA_CHAR + Do not strip trailing spaces and allow embedded \0. Force + 'blank-padded comparison semantics'. + + For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + + Will pad bloggs out to 8 characters and return the username. + + ora_parse_error_offset + If the previous error was from a failed "prepare" due to a syntax error, + this attribute gives the offset into the "Statement" attribute where the + error was found. + + ora_array_chunk_size + Due to OCI limitations, DBD::Oracle needs to buffer up rows of bind + values in its "execute_for_fetch" implementation. This attribute sets + the number of rows to buffer at a time (default value is 1000). + + The "execute_for_fetch" function will collect (at most) this many rows + in an array, send them off to the DB for execution, then go back to + collect the next chunk of rows and so on. This attribute can be used to + limit or extend the number of rows processed at a time. + + Note that this attribute also applies to "execute_array", since that + method is implemented using "execute_for_fetch". + + ora_connect_with_default_signals + Sometimes the Oracle client seems to change some of the signal handlers + of the process during the connect phase. For instance, some users have + observed Perl's default $SIG{INT} handler being ignored after connecting + to an Oracle database. If this causes problems in your application, set + this attribute to an array reference of signals you would like to be + localized during the connect process. Once the connect is complete, the + signal handlers should be returned to their previous state. + + For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + + NOTE disabling the signal handlers the OCI library sets up may affect + functionality in the OCI library. + + NOTE If you are using connect_cached then the above example will lead to + DBI thinking each connection is different as an anonymous array + reference is being used. To avoid this when using connect_cached you are + advised to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + + In more recent Perl versions you could possibly make use of new state + variables. + + connect_cached + Implemented by DBI, no driver-specific impact. Please note that + connect_cached as not been tested with DRCP. + + data_sources + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + + Returns a list of available databases. You will have to set either the + 'ORACLE_HOME' or 'TNS_ADMIN' environment value to retrieve this list. It + will read these values from TNSNAMES.ORA file entries. + +METHODS COMMON TO ALL HANDLES + For all of the methods below, $h can be either a database handle ($dbh) + or a statement handle ($sth). Note that *$dbh* and *$sth* can be + replaced with any variable name you choose: these are just the names + most often used. Another common variable used in this documentation is + $*rv*, which stands for "return value". + + err + $rv = $h->err; + + Returns the error code from the last method called. + + errstr + $str = $h->errstr; + + Returns the last error that was reported by Oracle. Starting with + "ORA-00000" code followed by the error message. + + state + $str = $h->state; + + Oracle hasn't supported SQLSTATE since the early versions OCI. It will + return empty when the command succeeds and 'S1000' (General Error) for + all other errors. + + While this method can be called as either "$sth->state" or + "$dbh->state", it is usually clearer to always use "$dbh->state". + + trace + Implemented by DBI, no driver-specific impact. + + trace_msg + Implemented by DBI, no driver-specific impact. + + parse_trace_flag and parse_trace_flags + Implemented by DBI, no driver-specific impact. + + func + DBD::Oracle uses the "func" method to support a variety of functions. + + Private database handle functions + Some of these functions are called through the method func() which is + described in the DBI documentation. Any function that begins with ora_ + can be called directly. + + plsql_errstr + This function returns a string which describes the errors from the most + recent PL/SQL function, procedure, package, or package body compile in a + format similar to the output of the SQL*Plus command 'show errors'. + + The function returns undef if the error string could not be retrieved + due to a database error. Look in $dbh->errstr for the cause of the + failure. + + If there are no compile errors, an empty string is returned. + + Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + + dbms_output_enable / dbms_output_put / dbms_output_get + These functions use the PL/SQL DBMS_OUTPUT package to store and retrieve + text using the DBMS_OUTPUT buffer. Text stored in this buffer by + dbms_output_put or any PL/SQL block can be retrieved by dbms_output_get + or any PL/SQL block connected to the same database session. + + Stored text is not available until after dbms_output_put or the PL/SQL + block that saved it completes its execution. This means you CAN NOT use + these functions to monitor long running PL/SQL procedures. + + Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + + Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + + dbms_output_enable ( [ buffer_size ] ) + This function calls DBMS_OUTPUT.ENABLE to enable calls to package + DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to these + procedures are ignored unless DBMS_OUTPUT.ENABLE is called first. + + The buffer_size is the maximum amount of text that can be saved in the + buffer and must be between 2000 and 1,000,000. If buffer_size is not + given, the default is 20,000 bytes. + + dbms_output_put ( [ @lines ] ) + This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + + If all lines were saved successfully the function returns 1. Depending + on the context, an empty list or undef is returned for failure. + + If any line causes buffer_size to be exceeded, a buffer overflow error + is raised and the function call fails. Some of the text might be in the + buffer. + + dbms_output_get + This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from + the buffer. + + In an array context, all complete lines are removed from the buffer and + returned as a list. If there are no complete lines, an empty list is + returned. + + In a scalar context, the first complete line is removed from the buffer + and returned. If there are no complete lines, undef is returned. + + Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or + DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, + DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + + reauthenticate ( $username, $password ) + Starts a new session against the current database using the credentials + supplied. + + private_attribute_info + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + + Returns a hash of all private attributes used by DBD::Oracle, for either + a database or a statement handle. Currently, all the hash values are + undef. + +ATTRIBUTES COMMON TO ALL HANDLES + InactiveDestroy (boolean) + Implemented by DBI, no driver-specific impact. + + RaiseError (boolean, inherited) + Forces errors to always raise an exception. Although it defaults to off, + it is recommended that this be turned on, as the alternative is to check + the return value of every method (prepare, execute, fetch, etc.) + manually, which is easy to forget to do. + + PrintError (boolean, inherited) + Forces database errors to also generate warnings, which can then be + filtered with methods such as locally redefining *$SIG{__WARN__}* or + using modules such as "CGI::Carp". This attribute is on by default. + + ShowErrorStatement (boolean, inherited) + Appends information about the current statement to error messages. If + placeholder information is available, adds that as well. Defaults to + true. + + Warn (boolean, inherited) + Enables warnings. This is on by default, and should only be turned off + in a local block for a short a time only when absolutely needed. + + Executed (boolean, read-only) + Indicates if a handle has been executed. For database handles, this + value is true after the "do" method has been called, or when one of the + child statement handles has issued an "execute". Issuing a "commit" or + "rollback" always resets the attribute to false for database handles. + For statement handles, any call to "execute" or its variants will flip + the value to true for the lifetime of the statement handle. + + TraceLevel (integer, inherited) + Sets the trace level, similar to the "trace" method. See the sections on + "trace" and "parse_trace_flag" for more details. + + Active (boolean, read-only) + Indicates if a handle is active or not. For database handles, this + indicates if the database has been disconnected or not. For statement + handles, it indicates if all the data has been fetched yet or not. Use + of this attribute is not encouraged. + + Kids (integer, read-only) + Returns the number of child processes created for each handle type. For + a driver handle, indicates the number of database handles created. For a + database handle, indicates the number of statement handles created. For + statement handles, it always returns zero, because statement handles do + not create kids. + + ActiveKids (integer, read-only) + Same as "Kids", but only returns those that are active. + + CachedKids (hash ref) + Returns a hashref of handles. If called on a database handle, returns + all statement handles created by use of the "prepare_cached" method. If + called on a driver handle, returns all database handles created by the + "connect_cached" method. + + ChildHandles (array ref) + Implemented by DBI, no driver-specific impact. + + PrintWarn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleError (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleSetErr (code ref, inherited) + Implemented by DBI, no driver-specific impact. + + ErrCount (unsigned integer) + Implemented by DBI, no driver-specific impact. + + FetchHashKeyName (string, inherited) + Implemented by DBI, no driver-specific impact. + + ChopBlanks (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Taint (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintIn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintOut (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Profile (inherited) + Implemented by DBI, no driver-specific impact. + + Type (scalar) + Returns "dr" for a driver handle, "db" for a database handle, and "st" + for a statement handle. Should be rarely needed. + + LongReadLen + Implemented by DBI, no driver-specific impact. + + LongTruncOk + Implemented by DBI, no driver-specific impact. + + CompatMode + Type: boolean, inherited + + The CompatMode attribute is used by emulation layers (such as Oraperl) + to enable compatible behaviour in the underlying driver (e.g., + DBD::Oracle) for this handle. Not normally set by application code. + + It also has the effect of disabling the 'quick FETCH' of attribute + values from the handles attribute cache. So all attribute values are + handled by the drivers own FETCH method. This makes them slightly slower + but is useful for special-purpose drivers like DBD::Multiplex. + +ORACLE-SPECIFIC DATABASE HANDLE METHODS + ora_can_unicode ( [ $refresh ] ) + Returns a number indicating whether either of the database character + sets is a Unicode encoding. Calls ora_nls_parameters() and passes the + optional $refresh parameter to it. + + 0 = Neither character set is a Unicode encoding. + + 1 = National character set is a Unicode encoding. + + 2 = Database character set is a Unicode encoding. + + 3 = Both character sets are Unicode encodings. + + ora_can_taf + Returns true if the current connection supports TAF events. False if + otherise. + + ora_nls_parameters ( [ $refresh ] ) + Returns a hash reference containing the current NLS parameters, as given + by the v$nls_parameters view. The values fetched are cached between + calls. To cause the latest values to be fetched, pass a true value to + the function. + +DATABASE HANDLE METHODS + selectall_arrayref + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the rows returned by + preparing and executing the SQL string. See the DBI documentation for + full details. + + selectall_hashref + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + + Returns a reference to a hash containing the rows returned by preparing + and executing the SQL string. See the DBI documentation for full + details. + + selectcol_arrayref + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the first column from each + rows returned by preparing and executing the SQL string. It is possible + to specify exactly which columns to return. See the DBI documentation + for full details. + + prepare + $sth = $dbh->prepare($statement, \%attr); + + Prepares a statement for later execution by the database engine and + returns a reference to a statement handle object. + + Prepare Attributes + These attributes may be used in the "\%attr" parameter of the "prepare" + in DBI database handle method. + + ora_placeholders + Set to false to disable processing of placeholders. Used mainly for + loading a PL/SQL package that has been *wrapped* with Oracle's + "wrap" utility. + + ora_auto_lob + If true (the default), fetching retrieves the contents of the CLOB + or BLOB column in most circumstances. If false, fetching retrieves + the Oracle "LOB Locator" of the CLOB or BLOB value. + + See "LOBs and LONGs" for more details. + + See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how + to use LOB Locators. + + ora_pers_lob + If true the "Simple Fetch for CLOBs and BLOBs" method for the "Data + Interface for Persistent LOBs" will be used for LOBs rather than the + default method "Data Interface for LOB Locators". + + ora_clbk_lob + If true the "Piecewise Fetch with Callback" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_lob + If true the "Piecewise Fetch with Polling" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_size + This is the max piece size for the "Piecewise Fetch with Callback" + and "Piecewise Fetch with Polling" methods, in chars for CLOBS, and + bytes for BLOBS. + + ora_check_sql + If 1 (default), force SELECT statements to be described in + prepare(). If 0, allow SELECT statements to defer describe until + execute(). + + See "Prepare Postponed Till Execute" for more information. + + ora_exe_mode + This will set the execute mode of the current statement. Presently + only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + + See "Scrollable Cursors" for more details. + + ora_prefetch_rows + Sets the number of rows to be prefetched. If it is not set, then the + default value is 1. See "Row Prefetching" for more details. + + ora_prefetch_memory + Sets the memory level for rows to be prefetched. The application + then fetches as many rows as will fit into that much memory. See + "Row Prefetching" for more details. + + ora_row_cache_off + By default DBD::Oracle will use a row cache when fetching to cut + down the number of round trips to the server. If you do not want to + use an array fetch set this value to any value other than 0; + + See "Row Prefetching" for more details. + + Placeholders + There are two types of placeholders that can be used in DBD::Oracle. The + first is the "question mark" type, in which each placeholder is + represented by a single question mark character. This is the method + recommended by the DBI specs and is the most portable. Each question + mark is internally replaced by a "dollar sign number" in the order in + which they appear in the query (important when using "bind_param"). + + The other placeholder type is "named parameters" in the format ":foo" + which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + + The different types of placeholders cannot be mixed within a statement, + but you may use different ones for each statement handle you have. This + is confusing at best, so stick to one style within your program. + + prepare_cached + $sth = $dbh->prepare_cached($statement, \%attr); + + Implemented by DBI, no driver-specific impact. This method is most + useful if the same query is used over and over as it will cut down round + trips to the server. + + do + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + + Prepare and execute a single statement. Returns the number of rows + affected if the query was successful, returns undef if an error + occurred, and returns -1 if the number of rows is unknown or not + available. Note that this method will return 0E0 instead of 0 for 'no + rows were affected', in order to always return a true value if no error + occurred. + + last_insert_id + Oracle does not implement auto_increment of serial type columns it uses + predefined sequences where the id numbers are either selected before + insert, at insert time with a trigger, or as part of the query. + + Below is an example of you to use the latter with the SQL returning + clause to get the ID number back on insert with the bind_param_inout + method. . + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + + commit + $rv = $dbh->commit; + + Issues a COMMIT to the server, indicating that the current transaction + is finished and that all changes made will be visible to other + processes. If AutoCommit is enabled, then a warning is given and no + COMMIT is issued. Returns true on success, false on error. + + rollback + $rv = $dbh->rollback; + + Issues a ROLLBACK to the server, which discards any changes made in the + current transaction. If AutoCommit is enabled, then a warning is given + and no ROLLBACK is issued. Returns true on success, and false on error. + + begin_work + This method turns on transactions until the next call to "commit" or + "rollback", if "AutoCommit" is currently enabled. If it is not enabled, + calling begin_work will issue an error. Note that the transaction will + not actually begin until the first statement after begin_work is called. + + disconnect + $rv = $dbh->disconnect; + + Disconnects from the Oracle database. Any uncommitted changes will be + rolled back upon disconnection. It's good policy to always explicitly + call commit or rollback at some point before disconnecting, rather than + relying on the default rollback behavior. + + If the script exits before disconnect is called (or, more precisely, if + the database handle is no longer referenced by anything), then the + database handle's DESTROY method will call the rollback() and + disconnect() methods automatically. It is best to explicitly disconnect + rather than rely on this behavior. + + ping + $rv = $dbh->ping; + + This "ping" method is used to check the validity of a database handle. + The value returned is either 0, indicating that the connection is no + longer valid, or 1, indicating the connection is valid. This function + does 1 round trip to the Oracle Server. + + get_info() + $value = $dbh->get_info($info_type); + + DBD::Oracle supports "get_info()", but (currently) only a few info + types. + + table_info() + DBD::Oracle supports attributes for "table_info()". + + In Oracle, the concept of *user* and *schema* is (currently) the same. + Because database objects are owned by an user, the owner names in the + data dictionary views correspond to schema names. Oracle does not + support catalogues so TABLE_CAT is ignored as selection criterion. + + Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + + TABLE_TYPE may contain a comma-separated list of table types. The + following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + + The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + + The special enumerations of catalogues, schemas and table types are + supported. However, TABLE_CAT is always NULL. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. "table_info()" performs a case-sensitive search. So, a + selection criterion should respect upper and lower case. Normally, an + identifier is case-insensitive. Oracle stores and returns it in upper + case. Sometimes, database objects are created with quoted identifiers + (for reserved words, mixed case, special characters, ...). Such an + identifier is case-sensitive (if not all upper case). Oracle stores and + returns it as given. "table_info()" has no special quote handling, + neither adds nor removes quotes. + + primary_key_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + If the primary key constraint was created without an identifier, PK_NAME + contains a system generated name with the form SYS_Cn. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + foreign_key_info() + This method (currently) supports the extended behaviour of SQL/CLI, i.e. + the result set contains foreign keys that refer to primary and alternate + keys. The field UNIQUE_OR_PRIMARY distinguishes these keys. + + Oracle does not support catalogues, so $pk_catalog and $fk_catalog are + ignored as selection criteria (in the new style interface). The + UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always NULL + (undef). See "table_info()" for more detailed information. + + If the primary or foreign key constraints were created without an + identifier, UK_NAME or FK_NAME contains a system generated name with the + form SYS_Cn. + + The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle + (currently) does not support other actions. + + The DELETE_RULE field may contain wrong values. This is a known Bug + (#1271663) in Oracle's data dictionary views. Currently (as of 8.1.7), + 'RESTRICT' and 'SET DEFAULT' are not supported, 'CASCADE' is mapped + correctly and all other actions (incl. 'SET NULL') appear as 'NO + ACTION'. + + The DEFERABILITY field is always NULL, because this columns is not + present in the ALL_CONSTRAINTS view of older Oracle releases. + + The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, + FK_TABLE_SCHEM, FK_TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + column_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + + Don't rely on the values of the BUFFER_LENGTH field! Especially the + length of FLOATs may be wrong. + + Datatype codes for non-standard types are subject to change. + + Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + It is possible with Oracle to make the names of the various DB objects + (table,column,index etc) case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + + So in the example the exact case "Bla_BLA" must be used to get it info + on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + + any case can be used to get info on the column. + + selectrow_array + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + + Returns an array of row information after preparing and executing the + provided SQL string. The rows are returned by calling "fetchrow_array". + The string can also be a statement handle generated by a previous + prepare. Note that only the first row of data is returned. If called in + a scalar context, only the first column of the first row is returned. + Because this is not portable, it is not recommended that you use this + method in that way. + + selectrow_arrayref + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an array, by internal use of the "fetchrow_arrayref" + method. + + selectrow_hashref + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an hash, by internal use of the "fetchrow_hashref" method. + + clone + $other_dbh = $dbh->clone(); + + Creates a copy of the database handle by connecting with the same + parameters as the original handle, then trying to merge the attributes. + See the DBI documentation for complete usage. + +DATABASE HANDLE ATTRIBUTES + AutoCommit (boolean) + Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is + on, but this may change in the future, so it is highly recommended that + you explicitly set it when calling "connect". + + ReadOnly (boolean) + $dbh->{ReadOnly} = 1; + + Specifies if the current database connection should be in read-only mode + or not. + + Please not that this method is not foolproof: there are still ways to + update the database. Consider this a safety net to catch applications + that should not be issuing commands such as INSERT, UPDATE, or DELETE. + + This method method requires DBI version 1.55 or better. + + Name (string, read-only) + Returns the name of the current database. This is the same as the DSN, + without the "dbi:Oracle:" part. + + Username (string, read-only) + Returns the name of the user connected to the database. + + Driver (handle, read-only) + Holds the handle of the parent driver. The only recommended use for this + is to find the name of the driver using: + + $dbh->{Driver}->{Name} + + RowCacheSize + DBD::Oracle supports both Server pre-fetch and Client side row caching. + By default both are turned on to give optimum performance. Most of the + time one can just let DBD::Oracle figure out the best optimization. + + Row Caching + Row caching occurs on the client side and the object of it is to cut + down the number of round trips made to the server when fetching rows. At + each fetch a set number of rows will be retrieved from the server and + stored locally. Further calls the server are made only when the end of + the local buffer(cache) is reached. + + Rows up to the specified top level row count "RowCacheSize" are fetched + if it occupies no more than the specified memory usage limit. The + default value is 0, which means that memory size is not included in + computing the number of rows to prefetch. If the "RowCacheSize" value is + set to a negative number then the positive value of RowCacheSize is used + to compute the number of rows to prefetch. + + By default "RowCacheSize" is automatically set. If you want to totally + turn off prefetching set this to 1. + + For any SQL statement that contains a LOB, Long or Object Type Row + Caching will be turned off. However server side caching still works. If + you are only selecting a LOB Locator then Row Caching will still work. + + Row Prefetching + Row prefetching occurs on the server side and uses the DBI database + handle attribute "RowCacheSize" and or the Prepare Attribute + 'ora_prefetch_memory'. Tweaking these values may yield improved + performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + + In the above example 10 rows will be prefetched up to a maximum of 10000 + bytes of data. The Oracle® Call Interface Programmer's Guide, suggests + a good row cache value for a scrollable cursor is about 20% of expected + size of the record set. + + The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) + when it needs to get new rows. This happens on the first fetch that sets + the current_positon to any value other than 0. In the above example if + we do a OCI_FETCH_FIRST the first 10 rows are loaded into the buffer and + DBD::Oracle will not have to go back to the server for more rows. When + record 11 is fetched DBD::Oracle fetches and returns this row and the + next 9 rows are loaded into the buffer. In this case if you fetch + backwards from 10 to 1 no server round trips are made. + + With large record sets it is best not to attempt to go to the last + record as this may take some time, A large buffer size might even slow + down the fetch. If you must get the number of rows in a large record set + you might try using an few large OCI_FETCH_ABSOLUTEs and then an + OCI_FETCH_LAST, this might save some time. So if you had a record set of + 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one + would fetch the first 5000 rows into the buffer then the next 5000 rows. + If one requires only the first few rows there is no need to set a large + prefetch value. + + If the ora_prefetch_memory less than 1 or not present then memory size + is not included in computing the number of rows to prefetch otherwise + the number of rows will be limited to memory size. Likewise if the + RowCacheSize is less than 1 it is not included in the computing of the + prefetch rows. + +ORACLE-SPECIFIC STATEMENT HANDLE METHODS + ora_stmt_type + Returns the OCI Statement Type number for the SQL of a statement handle. + + ora_stmt_type_name + Returns the OCI Statement Type name for the SQL of a statement handle. + +DBI STATEMENT HANDLE OBJECT METHODS + bind_param + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + + Allows the user to bind a value and/or a data type to a placeholder. + + The value of $param_num is a number if using the '?' or if using ":foo" + style placeholders, the complete name (e.g. ":foo") must be given. The + $bind_value argument is fairly self-explanatory. A value of "undef" will + bind a "NULL" to the placeholder. Using "undef" is useful when you want + to change just the type and will be overwriting the value later. (Any + value is actually usable, but "undef" is easy and efficient). + + The "\%attr" hash is used to indicate the data type of the placeholder. + The default value is "varchar". If you need something else, you must use + one of the values provided by DBI or by DBD::Pg. To use a SQL value, + modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + + This will import some constants into your script. You can plug those + directly into the "bind_param" call. Some common ones that you will + encounter are: + + SQL_INTEGER + + To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + + You can then set the data types by setting the value of the "ora_type" + key in the hash passed to "bind_param". The current list of Oracle data + types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + + Data types are "sticky," in that once a data type is set to a certain + placeholder, it will remain for that placeholder, unless it is + explicitly set to something else afterwards. If the statement has + already been prepared, and you switch the data type to something else, + DBD::Oracle will re-prepare the statement for you before doing the next + execute. + + Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + + These attributes may be used in the "\%attr" parameter of the + "bind_param" in DBI or "bind_param_inout" in DBI statement handle + methods. + + ora_type + Specify the placeholder's datatype using an Oracle datatype. A fatal + error is raised if "ora_type" and the DBI "TYPE" attribute are used + for the same placeholder. Some of these types are not supported by + the current version of DBD::Oracle and will cause a fatal error if + used. Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + + Potentially useful values when DBD::Oracle was built using OCI 7 and + later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + + Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + + Additional values when DBD::Oracle was built using OCI 9.2 and + later: + + SQLT_CHR, SQLT_BIN + + See "Binding Cursors" for the correct way to use ORA_RSET. + + See "LOBs and LONGs" for how to use ORA_CLOB and ORA_BLOB. + + See "SYS.DBMS_SQL datatypes" for ORA_VARCHAR2_TABLE, + ORA_NUMBER_TABLE. + + See "Data Interface for Persistent LOBs" for the correct way to use + SQLT_CHR and SQLT_BIN. + + See "Other Data Types" for more information. + + See also "Placeholders and Bind Values" in DBI. + + ora_csform + Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values + are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can + be imported from the DBD::Oracle module. Rarely needed. + + ora_csid + Specify the *integer* OCI_ATTR_CHARSET_ID for the bind value. + Character set names can't be used currently. + + ora_maxdata_size + Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. May be + needed if a character set conversion from client to server causes + the data to use more space and so fail with a truncation error. + + ora_maxarray_numentries + Specify the maximum number of array entries to allocate. Used with + ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of + array entries Oracle can pass back to you in OUT variable of type + TABLE OF ... . + + ora_internal_type + Specify internal data representation. Currently is supported only + for ORA_NUMBER_TABLE. + + Optimizing Results + Prepare Postponed Till Execute + The DBD::Oracle module can avoid an explicit 'describe' operation prior + to the execution of the statement unless the application requests + information about the results (such as $sth->{NAME}). This reduces + communication with the server and increases performance (reducing the + number of PARSE_CALLS inside the server). + + However, it also means that SQL errors are not detected until + "execute()" (or $sth->{NAME} etc) is called instead of when "prepare()" + is called. Note that if the describe is triggered by the use of + $sth->{NAME} or a similar attribute and the describe fails then *an + exception is thrown* even if "RaiseError" is false! + + Set "ora_check_sql" to 0 in prepare() to enable this behaviour. + + bind_param_inout + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + + DBD::Oracle fully supports bind_param_inout below are some uses for this + method. + + Returning A Value from an INSERT + Oracle supports an extended SQL insert syntax which will return one or + more of the values inserted. This can be particularly useful for + single-pass insertion of values with re-used sequence values (avoiding a + separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + + If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + + If you have many rows to insert you can take advantage of Oracle's built + in execute array feature with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + + Which will return all the ids into @out_values. + + Note: + This will only work for numbered (?) placeholders, + The third parameter of bind_param_inout_array, (0 in the example), + "maxlen" is required by DBI but not used by DBD::Oracle + The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + + Returning A Recordset + DBD::Oracle does not currently support binding a PL/SQL table (aka + array) as an IN OUT parameter to any Perl data structure. You cannot + therefore call a PL/SQL function or procedure from DBI that uses a + non-atomic datatype as either a parameter, or a return value. However, + if you are using Oracle 9.0.1 or later, you can make use of table (or + pipelined) functions. + + For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + + Currently, there is no way to directly call the function + Array_Example.Array_Func from DBI. However, by making the following + relatively painless additions, its not only possible, but extremely + efficient. + + First, you need to create database object types that correspond to the + record and table types in the package. From the above example, these + would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + + Now, assuming the existing function needs to remain unchanged (it is + probably being called from other PL/SQL code), we need to add a new + function to the package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + + As you can see, the new function is very simple. Now, it is a simple + matter of calling the function as a straight-forward SELECT from your + DBI code. From the above example, the code would look something like + this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + + SYS.DBMS_SQL datatypes + DBD::Oracle has built-in support for SYS.DBMS_SQL.VARCHAR2_TABLE and + SYS.DBMS_SQL.NUMBER_TABLE datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + Note: + Take careful note that we use '\\@arr' here because the + 'bind_param_inout' will only take a reference to a scalar. + + ORA_VARCHAR2_TABLE + SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. ( + in bind_param() and bind_param_inout() ). When you bind array, you need + to specify full buffer size for OUT data. So, there are two parameters: + *max_len* (specified as 3rd argument of bind_param_inout() ), and + *ora_maxarray_numentries*. They define maximum array entry length and + maximum rows, that can be passed to Oracle and back to you. In this + example we send array with 1 element with length=3, but allocate space + for 100 Oracle array entries with maximum length 10 of each. So, you can + get no more than 100 array entries with length <= 10. + + If you set *max_len* to zero, maximum array entry length is calculated + as maximum length of entry of array bound. If 0 < *max_len* < length( + $some_element ), truncation occur. + + If you set *ora_maxarray_numentries* to zero, current (at bind time) + bound array length is used as maximum. If 0 < *ora_maxarray_numentries* + < scalar(@array), not all array entries are bound. + + ORA_NUMBER_TABLE + SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike + ORA_VARCHAR2_TABLE. The main difference is internal data representation. + Currently 2 types of bind is allowed : as C-integer, or as C-double + type. To select one of them, you may specify additional bind parameter + *ora_internal_type* as either SQLT_INT or SQLT_FLT for C-integer and + C-double types. Integer size is architecture-specific and is usually 32 + or 64 bit. Double is standard IEEE 754 type. + + *ora_internal_type* defaults to double (SQLT_FLT). + + *max_len* is ignored for OCI_NUMBER_TABLE. + + Currently, you cannot bind full native Oracle NUMBER(38). If you really + need, send request to dbi-dev list. + + The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + + If you change bind type to SQLT_INT, like: + + ora_internal_type => SQLT_INT + + you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + + bind_param_inout_array + DBD::Oracle supports this undocumented feature of DBI. See "Returning A + Value from an INSERT" for an example. + + bind_param_array + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + + Binds an array of values to a placeholder, so that each is used in turn + by a call to the "execute_array" method. + + execute + $rv = $sth->execute(@bind_values); + + Perform whatever processing is necessary to execute the prepared + statement. + + execute_array + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + Execute a prepared statement once for each item in a passed-in hashref, + or items that were previously bound via the "bind_param_array" method. + See the DBI documentation for more details. + + DBD::Oracle takes full advantage of OCI's array interface so inserts and + updates using this interface will run very quickly. + + execute_for_fetch + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + Used internally by the "execute_array" method, and rarely used directly. + See the DBI documentation for more details. + + fetchrow_arrayref + $ary_ref = $sth->fetchrow_arrayref; + + Fetches the next row of data from the statement handle, and returns a + reference to an array holding the column values. Any columns that are + NULL are returned as undef within the array. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + Note that the same array reference is returned for each fetch, so don't + store the reference and then use it after a later fetch. Also, the + elements of the array are also reused for each row, so take care if you + want to take a reference to an element. See also "bind_columns". + + fetchrow_array + @ary = $sth->fetchrow_array; + + Similar to the "fetchrow_arrayref" method, but returns a list of column + information rather than a reference to a list. Do not use this in a + scalar context. + + fetchrow_hashref + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + + Fetches the next row of data and returns a hashref containing the name + of the columns as the keys and the data itself as the values. Any NULL + value is returned as as undef value. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + The optional $name argument should be either "NAME", "NAME_lc" or + "NAME_uc", and indicates what sort of transformation to make to the keys + in the hash. By default Oracle uses upper case. + + fetchall_arrayref + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + + Returns a reference to an array of arrays that contains all the + remaining rows to be fetched from the statement handle. If there are no + more rows, an empty arrayref will be returned. If an error occurs, the + data read in so far will be returned. Because of this, you should always + check "$sth->err" after calling this method, unless "RaiseError" has + been enabled. + + If $slice is an array reference, fetchall_arrayref uses the + "fetchrow_arrayref" method to fetch each row as an array ref. If the + $slice array is not empty then it is used as a slice to select + individual columns by perl array index number (starting at 0, unlike + column and parameter numbers which start at 1). + + With no parameters, or if $slice is undefined, fetchall_arrayref acts as + if passed an empty array ref. + + If $slice is a hash reference, fetchall_arrayref uses "fetchrow_hashref" + to fetch each row as a hash reference. + + See the DBI documentation for a complete discussion. + + fetchall_hashref + $hash_ref = $sth->fetchall_hashref( $key_field ); + + Returns a hashref containing all rows to be fetched from the statement + handle. See the DBI documentation for a full discussion. + + finish + $rv = $sth->finish; + + Indicates to DBI that you are finished with the statement handle and are + not going to use it again. Only needed when you have not fetched all the + possible rows. + + rows + $rv = $sth->rows; + + Returns the number of rows affected for updates, deletes and inserts and + -1 for selects. + + bind_col + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + + Binds a Perl variable and/or some attributes to an output column of a + SELECT statement. Column numbers count up from 1. You do not need to + bind output columns in order to fetch data. + + NOTE: DBD::Oracle does not use the $bind_type to determine how to bind + the column; it uses what Oracle says the data type is. You can however + set a numeric bind type with the bind attributes + StrictlyTyped/DiscardString as these attributes are applied after the + column is retrieved. + + See the DBI documentation for a discussion of the optional parameters + "\%attr" and $bind_type + + bind_columns + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + + Calls the "bind_col" method for each column in the SELECT statement, + using the supplied list. + + dump_results + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + + Fetches all the rows from the statement handle, calls "DBI::neat_list" + for each row, and prints the results to $fh (which defaults to STDOUT). + Rows are separated by $lsep (which defaults to a newline). Columns are + separated by $fsep (which defaults to a comma). The $maxlen controls how + wide the output can be, and defaults to 35. + + This method is designed as a handy utility for prototyping and testing + queries. Since it uses "neat_list" to format and edit the string for + reading by humans, it is not recommended for data transfer applications. + +STATEMENT HANDLE ATTRIBUTES + NUM_OF_FIELDS (integer, read-only) + Returns the number of columns returned by the current statement. A + number will only be returned for SELECT statements for INSERT, UPDATE, + and DELETE statements which contain a RETURNING clause. This method + returns undef if called before "execute()". + + NUM_OF_PARAMS (integer, read-only) + Returns the number of placeholders in the current statement. + + NAME (arrayref, read-only) + Returns an arrayref of column names for the current statement. This + method will only work for SELECT statements, for SHOW statements, and + for INSERT, UPDATE, and DELETE statements which contain a RETURNING + clause. This method returns undef if called before "execute()". + + NAME_lc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to lower case. + + NAME_uc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to upper case. + + NAME_hash (hashref, read-only) + Similar to the "NAME" attribute, but returns a hashref of column names + instead of an arrayref. The names of the columns are the keys of the + hash, and the values represent the order in which the columns are + returned, starting at 0. This method returns undef if called before + "execute()". + + NAME_lc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + NAME_uc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + TYPE (arrayref, read-only) + Returns an arrayref indicating the data type for each column in the + statement. This method returns undef if called before "execute()". + + PRECISION (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the precision for "NUMERIC" columns, the + size in number of characters for "CHAR" and "VARCHAR" columns, and for + all other types of columns it returns the number of *bytes*. This method + returns undef if called before "execute()". + + SCALE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the scale of the that column. The only + type that will return a value is "NUMERIC". This method returns undef if + called before "execute()". + + NULLABLE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates if the column is nullable or not. 0 = + not nullable, 1 = nullable, 2 = unknown. This method returns undef if + called before "execute()". + + Database (dbh, read-only) + Returns the database handle this statement handle was created from. + + ParamValues (hash ref, read-only) + Returns a reference to a hash containing the values currently bound to + placeholders. If the "named parameters" type of placeholders are being + used (such as ":foo"), then the keys of the hash will be the names of + the placeholders (without the colon). If the "dollar sign numbers" type + of placeholders are being used, the keys of the hash will be the + numbers, without the dollar signs. If the "question mark" type is used, + integer numbers will be returned, starting at one and increasing for + every placeholder. + + If this method is called before "execute", the literal values passed in + are returned. If called after "execute", then the quoted versions of the + values are returned. + + ParamTypes (hash ref, read-only) + Returns a reference to a hash containing the type names currently bound + to placeholders. The keys are the same as returned by the ParamValues + method. The values are hashrefs containing a single key value pair, in + which the key is either 'TYPE' if the type has a generic SQL equivalent, + and 'pg_type' if the type can only be expressed by a Postgres type. The + value is the internal number corresponding to the type originally passed + in. (Placeholders that have not yet been bound will return undef as the + value). This allows the output of ParamTypes to be passed back to the + "bind_param" method. + + Statement (string, read-only) + Returns the statement string passed to the most recent "prepare" method + called in this database handle, even if that method failed. This is + especially useful where "RaiseError" is enabled and the exception + handler checks $@ and sees that a "prepare" method call failed. + + RowsInCache + Returns the number of un-fetched rows in the cache for selects. + +SCROLLABLE CURSORS + Oracle supports the concept of a 'Scrollable Cursor' which is defined as + a 'Result Set' where the rows can be fetched either sequentially or + non-sequentially. One can fetch rows forward, backwards, from any given + position or the n-th row from the current position in the result set. + + Rows are numbered sequentially starting at one and client-side caching + of the partial or entire result set can improve performance by limiting + round trips to the server. + + Oracle does not support DML type operations with scrollable cursors so + you are limited to simple 'Select' operations only. As well you can not + use this functionality with remote mapped queries or if the LONG + datatype is part of the select list. + + However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, + and fetch methods. + + Only use scrollable cursors if you really have a good reason to. They do + use up considerable more server and client resources and have poorer + response times than non-scrolling cursors. + + Enabling Scrollable Cursors + To enable this functionality you must first import the 'Fetch + Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + + Next you will have to tell DBD::Oracle that you will be using scrolling + by setting the ora_exe_mode attribute on the statement handle to + 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + + When the statement is executed you will then be able to use + 'ora_fetch_scroll' method to get a row or you can still use any of the + other fetch methods but with a poorer response time than if you used a + non-scrolling cursor. As well scrollable cursors are compatible with any + applicable bind methods. + + Scrollable Cursor Methods + The following driver-specific methods are used with scrollable cursors. + + ora_scroll_position + $position = $sth->ora_scroll_position(); + + This method returns the current position (row number) attribute of + the result set. Prior to the first fetch this value is 0. This is + the only time this value will be 0 after the first fetch the value + will be set, so you can use this value to test if any rows have been + fetched. The minimum value will always be 1 after the first fetch. + The maximum value will always be the total number of rows in the + record set. + + ora_fetch_scroll + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + + Works the same as "fetchrow_arrayref", excepts one passes in a + 'Fetch Orientation' constant and a fetch_offset value which will + then determine the row that will be fetched. It returns the row as a + list containing the field values. Null fields are returned as + *undef* values in the list. + + The valid orientation constant and fetch offset values combination + are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + + The effect that a ora_fetch_scroll method call has on the + current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + + The effects of the differing orientation constants on the first + fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + + Scrollable Cursor Usage + Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + + and one assumes that the number of rows returned from the query is 20, + the code snippets below will illustrate the use of ora_fetch_scroll + method; + + Fetching the Last Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute to will be 20 after this snippet. This + is also a way to get the number of rows in the record set, however, + if the record set is large this could take some time. + + Fetching the Current Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will still be 20 after this snippet. + + Fetching the First Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the Next Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 5 after this snippet. + + Fetching the Prior Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the 10th Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 10th to 14th Row + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 14 after this snippet. + + Fetching the 14th to 10th Row + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 5th Row From the Present Position. + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 15 after this snippet. + + Fetching the 9th Row Prior From the Present Position + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 6 after this snippet. + + Use Finish + $sth->finish(); + + When using scrollable cursors it is required that you use the + $sth->finish() method when you are done with the cursor as this type + of cursor has to be explicitly cancelled on the server. If you do + not do this you may cause resource problems on your database. + +LOBS AND LONGS + The key to working with LOBs (CLOB, BLOBs) is to remember the value of + an Oracle LOB column is not the content of the LOB. It's a 'LOB Locator' + which, after being selected or inserted needs extra processing to read + or write the content of the LOB. There are also legacy LONG types (LONG, + LONG RAW, VARCHAR2) which are presently deprecated by Oracle but are + still in use. These LONG types do not utilize a 'LOB Locator' and also + are more limited in functionality than CLOB or BLOB fields. + + DBD::Oracle now offers three interfaces to LOB and LONG data, + + "Data Interface for Persistent LOBs" + With this interface DBD::Oracle handles your data directly utilizing + regular OCI calls, Oracle itself takes care of the LOB Locator + operations in the case of BLOBs and CLOBs treating them exactly as + if they were the same as the legacy LONG or LONG RAW types. + + "Data Interface for LOB Locators" + With this interface DBD::Oracle handles your data utilizing LOB + Locator OCI calls so it only works with CLOB and BLOB datatypes. + With this interface DBD::Oracle takes care of the LOB Locator + operations for you. + + "LOB Locator Method Interface" + This allows the user direct access to the LOB Locator methods, so + you have to take case of the LOB Locator operations yourself. + + Generally speaking the interface that you will chose will be dependent + on what end you are trying to achieve. All have their benefits and + drawbacks. + + One point to remember when working with LOBs (CLOBs, BLOBs) is if your + LOB column can be in one of three states; + + NULL + The table cell is created, but the cell holds no locator or value. + If your LOB field is in this state then there is no LOB Locator that + DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + + error when working with a LOB. + + You can correct this by using an SQL UPDATE statement to reset the + LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB + or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + + Empty + A LOB instance with a locator exists in the cell, but it has no + value. The length of the LOB is zero. In this case DBD::Oracle will + return 'undef' for the field. + + Populated + A LOB instance with a locator and a value exists in the cell. You + actually get the LOB value. + + Data Interface for Persistent LOBs + This is the original interface for LONG and LONG RAW datatypes and from + Oracle 9iR1 and later the OCI API was extended to work directly with the + other LOB datatypes. In other words you can treat all LOB type data + (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can + perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using + the same techniques you would use on other datatypes that store + character or binary data. In some cases there are fewer round trips to + the server as no 'LOB Locators' are used, normally one can get an entire + LOB is a single round trip. + + Simple Fetch for LONGs and LONG RAWs + As the name implies this is the simplest way to use this interface. + DBD::Oracle just attempts to get your LONG datatypes as a single large + piece. There are no special settings, simply set the database handle's + 'LongReadLen' attribute to a value that will be the larger than the + expected size of the LONG or LONG RAW. If the size of the LONG or LONG + RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A + Truncation' error. To stop this set the database handle's 'LongTruncOk' + attribute to '1'. The maximum value of 'LongReadLen' seems to be + dependent on the physical memory limits of the box that Oracle is + running on. You have most likely reached this limit if you run into an + 'ORA-01062: unable to allocate memory for define buffer' error. One + solution is to set the size of 'LongReadLen' to a lower value. + + For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select out all of the long1 fields in the table as long as they are + all under 2MB in length. A value in long1 longer than this will throw an + error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the long1 fields but they will be + truncated at 2MBs. + + Using ora_ncs_buff_mtpl + When getting CLOBs and NCLOBs in or out of Oracle, the Server will + translate from the Server's NCharSet to the Client's. If they happen to + be the same or at least compatible then all of these actions are a 1 + char to 1 char bases. Thus if you set your LongReadLen buffer to + 10_000_000 you will get up to 10_000_000 char. + + However if the Server has to translate from one NCharSet to another it + will use bytes for conversion. The buffer value is set to 4 * + LONG_READ_LEN which was very wasteful as you might only be asking for + 10_000_000 bytes but you were actually using 40_000_000 bytes of buffer + under the hood. You would still get 10_000_000 bytes (maybe less + characters though) but you are using allot more memory that you need. + + You can now customize the size of the buffer by setting the + 'ora_ncs_buff_mtpl' either on the connection or statement handle. You + can also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you + will have to go back and change all your code if you are getting into + trouble. + + The default value is still set to 4 for backward compatibility. You can + lower this value and thus increase the amount of data you can retrieve. + If the ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error + telling you to increase this buffer by one. + + If the error is not captured then you may get at some random point later + on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + + This is one of the more obscure ORA errors (have some fun and report it + to Meta-Link they will scratch their heads for hours) + + If you get this, simply increment the ora_ncs_buff_mtpl by one until it + goes away. + + This should greatly increase your ability to select very large CLOBs or + NCLOBs, by freeing up a large block of memory. + + You can tune this value by setting ora_oci_success_warn which will + display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + + In the case above the query Got 28 characters (well really only 20 + characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) + thus saving 40bytes of memory. + + Simple Fetch for CLOBs and BLOBs + To use this interface for CLOBs and LOBs datatypes set the + 'ora_pers_lob' attribute of the statement handle to '1' with the prepare + method, as well set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. If the + size of the LOB exceeds the 'LongReadLen' DBD::Oracle will return a + 'ORA-24345: A Truncation' error. To stop this set the database handle's + 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems + to be dependent on the physical memory limits of the box that Oracle is + running on in the same way that LONGs and LONG RAWs are. + + For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, + this is an internal OCI limit complain to them if you want it changed. + However if you CLOB is longer than this and also larger than the + 'LongReadLen' than the 'LongReadLen' in chars is returned. + + It seems with BLOBs you are not limited by the 64k. + + For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the lobs but they will be truncated + at 2MBs. + + Piecewise Fetch with Callback + With a piecewise callback fetch DBD::Oracle sets up a function that will + 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, + CLOB, BLOB) piece by piece. To use this interface set the 'ora_clbk_lob' + attribute of the statement handle to '1' with the prepare method. Next + set the 'ora_piece_size' to the size of the piece that you want to + return on the callback. Finally set the database handle's 'LongReadLen' + attribute to a value that will be the larger than the expected size of + the LOB. Like the "Simple Fetch for LONGs and LONG RAWs" and "Simple + Fetch for CLOBs and BLOBs" the if the size of the LOB exceeds the is + 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the + LOB or set the 'LongReadLen' to a higher value. With this interface the + value of 'ora_piece_size' seems to be constrained by the same memory + limit as found on the Simple Fetch interface. If you encounter an + 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller + value. The value for 'LongReadLen' is dependent on the version and + settings of the Oracle DB you are using. In theory it ranges from 8GBs + in 9iR1 up to 128 terabytes with 11g but you will also be limited by the + physical memory of your PERL instance. + + Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will + throw an error. + + Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 filed is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Piecewise Fetch with Polling + With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB + during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by + piece. To use this interface set the 'ora_piece_lob' attribute of the + statement handle to '1' with the prepare method. Next set the + 'ora_piece_size' to the size of the piece that you want to return on the + callback. Finally set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. Like + the "Piecewise Fetch with Callback" and Simple Fetches if the size of + the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' + attribute to truncate the LOB or set the 'LongReadLen' to a higher + value. With this interface the value of 'ora_piece_size' seems to be + constrained by the same memory limit as found on the "Piecewise Fetch + with Callback". + + Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will + throw an error. + + Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 field is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Binding for Updates and Inserts for CLOBs and BLOBs + To bind for updates and inserts all that is required to use this + interface is to set the statement handle's prepare method 'ora_type' + attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in + the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + + So far the only limit reached with this form of insert is the LOBs must + be under 2GB in size. + + Support for Remote LOBs; + Starting with Oracle 10gR2 the interface for Persistent LOBs was + expanded to support remote LOBs (access over a dblink). Given a database + called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + + to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Below are the limitations of Remote LOBs; + + Queries involving more than one database are not supported; + so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + + as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + + DDL commands are not supported; + so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + + Only binds and defines for data going into remote persistent LOBs are + supported. + so that parameter passing in PL/SQL where CHAR data is bound or + defined for remote LOBs is not allowed . + + These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + + If the remote object is a view such as + CREATE VIEW v AS SELECT foo() FROM ... + + the following would not work: + + SELECT * FROM v@dbs2; + + Limited PL/SQL parameter passing + PL/SQL parameter passing is not allowed where the actual argument is + a LOB type and the remote argument is one of VARCHAR2, NVARCHAR2, + CHAR, NCHAR, or RAW. + + RETURNING INTO does not support implicit conversions between CHAR and + CLOB. + so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + + Locator Data Interface + Simple Usage + When fetching LOBs with this interface a 'LOB Locator' is created then + used to get the lob with the LongReadLen and LongTruncOk attributes. The + value for 'LongReadLen' is dependent on the version and settings of the + Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 + terabytes with 11g but you will also be limited by the physical memory + of your PERL instance. + + When inserting or updating LOBs some *major* magic has to be performed + behind the scenes to make it transparent. Basically the driver has to + insert a 'LOB Locator' and then refetch the newly inserted LOB Locator + before being able to write the data into it. However, it works well most + of the time, and I've made it as fast as possible, just one extra + server-round-trip per insert or update after the first. For the time + being, only single-row LOB updates are supported. + + To insert or update a large LOB using a placeholder, DBD::Oracle has to + know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + + The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + + or use the corresponding integer values (112 and 113). + + One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has to + be able to tell which parameters relate to which table fields. In all + cases where it can possibly work it out for itself, it does, however, if + there are multiple LOB fields of the same type in the table then you + need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + + There are some limitations inherent in the way DBD::Oracle makes typical + LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + + The alternative is to disable the automatic LOB Locator processing. If + "ora_auto_lob" is 0 in prepare(), you can fetch the LOB Locators and do + all the work yourself using the ora_lob_*() methods. See the "Data + Interface for LOB Locators" section below. + + LOB support in PL/SQL + LOB Locators can be passed to PL/SQL calls by binding them to + placeholders with the proper "ora_type". If "ora_auto_lob" is true, + output LOB parameters will be automatically returned as strings. + + If the Oracle driver has support for temporary LOBs (Oracle 9i and + higher), strings can be bound to input LOB placeholders and will be + automatically converted to LOBs. + + Example: # Build a large XML document, bind it as a CLOB, # extract + elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + + If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + + error, while attempting to insert a LOB, this means the Oracle user has + insufficient space for LOB you are trying to insert. One solution it to + use "alter database datafile 'sss.ggg' resize Mnnn" to increase the + available memory for LOBs. + + Persistent & Locator Interface Caveats + Now that one has the option of using the Persistent or the Locator + interface for LOBs the questions arises which one to use. For starters, + if you want to access LOBs over a dblink you will have to use the + Persistent interface so that choice is simple. The question of which one + to use after that is a little more tricky. It basically boils down to a + choice between LOB size and speed. + + The Callback and Polling piecewise fetches are very very slow when + compared to the Simple and the Locator fetches but they can handle very + large blocks of data. Given a situation where a large LOB is to be read + the Locator fetch may time out while either of the piecewise fetches may + not. + + With the Simple fetch you are limited by physical memory of your server + but it runs a little faster than the Locator, as there are fewer round + trips to the server. So if you have small LOBs and need to save a little + bandwidth this is the one to use. It you are going after large LOBs then + the Locator interface is the one to use. + + If you need to update more than a single row of with LOB data then the + Persistent interface can do it while the Locator can't. + + If you encounter a situation where you have to access the legacy LOBs + (LONG, LONG RAW) and the values are to large for you system then you can + use the Callback or Polling piecewise fetches to get all of the data. + + Not all of the Persistent interface has been implemented yet, the + following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + + Most of the time you should just use the "Locator Data Interface" as + this is in one that has the best combination of speed and size. + + All this being said if you are doing some critical programming I would + use the "Data Interface for LOB Locators" as this gives you very fine + grain control of your LOBs, of course the code for this will be somewhat + more involved. + + Data Interface for LOB Locators + The following driver-specific methods let you manipulate "LOB Locators" + directly. To select a LOB locator directly set the if the "ora_auto_lob" + attribute to false, or alternatively they can be returned via PL/SQL + procedure calls. + + (If using a DBI version earlier than 1.36 they must be called via the + func() method. Note that methods called via func() don't honour + RaiseError etc, and so it's important to check $dbh->err after each + call. It's recommended that you upgrade to DBI 1.38 or later.) + + Note that LOB locators are only valid while the statement handle that + created them is valid. When all references to the original statement + handle are lost, the handle is destroyed and the locators are freed. + + ora_lob_read + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + + Read a portion of the LOB. $offset starts at 1. Uses the Oracle + OCILobRead function. + + ora_lob_write + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + + Write/overwrite a portion of the LOB. $offset starts at 1. Uses the + Oracle OCILobWrite function. + + ora_lob_append + $rc = $dbh->ora_lob_append($lob_locator, $data); + + Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + + ora_lob_trim + $rc = $dbh->ora_lob_trim($lob_locator, $length); + + Trims the length of the LOB to $length. Uses the Oracle OCILobTrim + function. + + ora_lob_length + $length = $dbh->ora_lob_length($lob_locator); + + Returns the length of the LOB. Uses the Oracle OCILobGetLength + function. + + ora_lob_is_init + $is_init = $dbh->ora_lob_is_init($lob_locator); + + Returns true(1) if the Lob Locator is initialized false(0) if it is + not, or 'undef' if there is an error. Uses the Oracle + OCILobLocatorIsInit function. + + ora_lob_chunk_size + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + + Returns the chunk size of the LOB. Uses the Oracle + OCILobGetChunkSize function. + + For optimal performance, Oracle recommends reading from and writing + to a LOB in batches using a multiple of the LOB chunk size. In + Oracle 10g and before, when all defaults are in place, this chunk + size defaults to 8k (8192). + + LOB Locator Method Examples + *Note:* Make sure you first read the note in the section above about + multi-byte character set issues with these methods. + + The following examples demonstrate the usage of LOB Locators to read, + write, and append data, and to query the size of large data. + + The following examples assume a table containing two large object + columns, one binary and one character, with a primary key column, + defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + + It also assumes a sequence for use in generating unique lob_id field + values, defined as follows: + + CREATE SEQUENCE lob_example_seq + + Example: Inserting a new row with large data + Unless enough memory is available to store and bind the entire LOB data + for insert all at once, the LOB columns must be written interactively, + piece by piece. In the case of a new row, this is performed by first + inserting a row, with empty values in the LOB columns, then modifying + the row by writing the large data interactively to the LOB columns using + their LOB locators as handles. + + The insert statement must create token values in the LOB columns. Here, + we use the empty string for both the binary and character large object + columns 'bindata' and 'chardata'. + + After the INSERT statement, a SELECT statement is used to acquire LOB + locators to the 'bindata' and 'chardata' fields of the newly inserted + row. Because these LOB locators are subsequently written, they must be + acquired from a select statement containing the clause 'FOR UPDATE' (LOB + locators are only valid within the transaction that fetched them, so + can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + + In this example we demonstrate the use of ora_lob_write() interactively + to append data to the columns 'bin_data' and 'char_data'. Had we used + ora_lob_append(), we could have saved ourselves the trouble of keeping + track of the offset into the lobs. The snippet of code beneath the + comment 'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + + The scalar variables $offset and $length are no longer needed, because + ora_lob_append() keeps track of the offset for us. + + Example: Updating an existing row with large data + In this example, we demonstrate a technique for overwriting a portion of + a blob field with new binary data. The blob data before and after the + section overwritten remains unchanged. Hence, this technique could be + used for updating fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + + After running this code, the row where lob_id = 5 will contain, starting + at position 100234 in the bin_data column, the string "This string will + overwrite a portion of the blob". + + Example: Streaming character data from the database + In this example, we demonstrate a technique for streaming data from the + database to a file handle, in this case STDOUT. This allows more data to + be read in and written out than could be stored in memory at a given + time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + + Notice that the select statement does not contain the phrase "FOR + UPDATE". Because we are only reading from the LOB Locator returned, and + not modifying the LOB it refers to, the select statement does not + require the "FOR UPDATE" clause. + + A word of caution when using the data returned from an ora_lob_read in a + conditional statement. for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + + was used with a chunk size of 4096 against a blob that requires more + than 1 chunk to return the data and the last chunk is one byte long and + contains a zero (ASCII 48) you will miss this last byte as $data will + contain 0 which PERL will see as false and not print it out. + + Example: Truncating existing large data + In this example, we truncate the data already present in a large object + column in the database. Specifically, for each row in the table, we + truncate the 'bindata' value to half its previous length. + + After acquiring a LOB Locator for the column, we query its length, then + we trim the length by half. Because we modify the large objects with the + call to ora_lob_trim(), we must select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +SPACES AND PADDING + Trailing Spaces + Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder + values and uses Nonpadded Comparison Semantics with the result. This + causes trouble if the spaces are needed for comparison with a CHAR value + or to prevent the value from becoming '' which Oracle treats as NULL. + Look for Blank-padded Comparison Semantics and Nonpadded Comparison + Semantics in Oracle's SQL Reference or Server SQL Reference for more + details. + + To preserve trailing spaces in placeholder values for Oracle clients + that use OCI 8, either change the default placeholder type with + "ora_ph_type" or the placeholder type for a particular call to "bind" in + DBI or "bind_param_inout" in DBI with "ora_type" or "TYPE". Using + ORA_CHAR with ora_type or "SQL_CHAR" with "TYPE" allows the placeholder + to be used with Padded Comparison Semantics if the value it is being + compared to is a CHAR, NCHAR, or literal. + + Please remember that using spaces as a value or at the end of a value + makes visually distinguishing values with different numbers of spaces + difficult and should be avoided. + + Oracle Clients that use OCI 9.2 do not strip trailing spaces. + + Padded Char Fields + Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder + values to the size of the CHAR. As the default placeholder type value in + DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will have to + change the default placeholder type with "ora_ph_type" or placeholder + type for a particular call with "bind" in DBI or "bind_param_inout" in + DBI with "ORA_CHAR". + +UNICODE + DBD::Oracle now supports Unicode UTF-8. There are, however, a number of + issues you should be aware of, so please read all this section + carefully. + + In this section we'll discuss "Perl and Unicode", then "Oracle and + Unicode", and finally "DBD::Oracle and Unicode". + + Information about Unicode in general can be found at: + . It is well worth reading because there are + many misconceptions about Unicode and you may be holding some of them. + + Perl and Unicode + Perl began implementing Unicode with version 5.6, but the implementation + did not mature until version 5.8 and later. If you plan to use Unicode + you are *strongly* urged to use Perl 5.8.2 or later and to *carefully* + read the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + + And then read it again. + + Perl's internal Unicode format is UTF-8 which corresponds to the Oracle + character set called AL32UTF8. + + Oracle and Unicode + Oracle supports many characters sets, including several different forms + of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + + When you create an Oracle database, you must specify the DATABASE + character set (used for DDL, DML and CHAR datatypes) and the NATIONAL + character set (used for NCHAR and NCLOB types). The character sets used + in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + + The Oracle 9.2 and later default for the national character set is + AL16UTF16. The default for the database character set is often US7ASCII. + Although many experienced DBAs will consider an 8bit character set like + WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other + than US7ASCII, requires that the NLS_LANG environment variable be set. + See the "Oracle UTF8 is not UTF-8" section below. + + You are strongly urged to read the Oracle Internationalization + documentation specifically with respect the choices and trade offs for + creating a databases for use with international character sets. + + Oracle uses the NLS_LANG environment variable to indicate what character + set is being used on the client. When fetching data Oracle will convert + from whatever the database character set is to the client character set + specified by NLS_LANG. Similarly, when sending data to the database + Oracle will convert from the character set specified by NLS_LANG to the + database character set. + + The NLS_NCHAR environment variable can be used to define a different + character set for 'national' (NCHAR) character types. + + Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. For + example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + + Oracle UTF8 is not UTF-8 + AL32UTF8 should be used in preference to UTF8 if it works for you, which + it should for Oracle 9.2 or later. If you're using an old version of + Oracle that doesn't support AL32UTF8 then you should avoid using any + Unicode characters that require surrogates, in other words characters + beyond the Unicode BMP (Basic Multilingual Plane). + + That's because the character set that Oracle calls "UTF8" doesn't + conform to the UTF-8 standard in its handling of surrogate characters. + Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". + Here are a couple of extracts from + : + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + + Oracle uses this internally because it collates (sorts) in the same + order as UTF16, which is the basis of Oracle's internal collation + definitions. + + Rather than change UTF8 for clients Oracle chose to define a new + character set called "AL32UTF8" which does conform to the UTF-8 + standard. (The AL32UTF8 character set can't be used on the server + because it would break collation.) + + Because of that, for the rest of this document we'll use "AL32UTF8". If + you're using an Oracle version below 9.2 you'll need to use "UTF8" until + you upgrade. + + DBD::Oracle and Unicode + DBD::Oracle Unicode support has been implemented for Oracle versions 9 + or greater, and Perl version 5.6 or greater (though we *strongly* + suggest that you use Perl 5.8.2 or later). + + You can check which Oracle version your DBD::Oracle was built with by + importing the "ORA_OCI" constant from DBD::Oracle. + + Fetching Data + + Any data returned from Oracle to DBD::Oracle in the AL32UTF8 character + set will be marked as UTF-8 to ensure correct handling by Perl. + + For Oracle to return data in the AL32UTF8 character set the NLS_LANG or + NLS_NCHAR environment variable *must* be set as described in the + previous section. + + When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle + will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR is + AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + + When fetching other character data from Oracle, DBD::Oracle will set the + Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + + Sending Data using Placeholders + + Data bound to a placeholder is assumed to be in the default client + character set (specified by NLS_LANG) except for a few special cases. + These are listed here with the highest precedence first: + + If the "ora_csid" attribute is given to bind_param() then that is passed + to Oracle and takes precedence. + + If the value is a Perl Unicode string (UTF-8) then DBD::Oracle ensures + that Oracle uses the Unicode character set, regardless of the NLS_LANG + and NLS_NCHAR settings. + + If the placeholder is for inserting an NCLOB then the client NLS_NCHAR + character set is used. (That's useful but inconsistent with the other + behaviour so may change. Best to be explicit by using the "ora_csform" + attribute.) + + If the "ora_csform" attribute is given to bind_param() then that + determines if the value should be assumed to be in the default + (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + Binding with bind_param_array and execute_array is also UTF-8 compatible + in the same way. If you attempt to insert UTF-8 data into a non UTF-8 + Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert will + still happen but a error code of 0 will be returned with the following + warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + + The warning will report the parameter number and the NCHAR setting that + the query is running. + + Sending Data using SQL + + Oracle assumes the SQL statement is in the default client character set + (as specified by NLS_LANG). So Unicode strings containing non-ASCII + characters should not be used unless the default client character set is + AL32UTF8. + + DBD::Oracle and Other Character Sets and Encodings + The only multi-byte Oracle character set supported by DBD::Oracle is + "AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +OBJECT & COLLECTION DATA TYPES + Oracle databases allow for the creation of object oriented like + user-defined types. There are two types of objects, Embedded--an object + stored in a column of a regular table and REF--an object that uses the + REF retrieval mechanism. + + DBD::Oracle supports only the 'selection' of embedded objects of the + following types OBJECT, VARRAY and TABLE in any combination. Support is + seamless and recursive, meaning you need only supply a simple SQL + statement to get all the values in an embedded object. You can either + get the values as an array of scalars or they can be returned into a + DBD::Oracle::Object. + + Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + + The code to access all the data in the table could be something like + this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + + Note that values in PHONE_NUMBERS are returned as an array reference + '@$phone'. + + As stated before DBD::Oracle will automatically drill into the embedded + object and extract all of the data as reference arrays of scalars. The + example below has OBJECT type embedded in a TABLE type embedded in an + SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + + The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + + Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + + The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + + So far DBD::Oracle has been tested on a table with 20 embedded Objects, + Varrays and Tables nested to 10 levels. + + Any NULL values found in the embedded object will be returned as + 'undef'. + +OTHER DATA TYPES + DBD::Oracle does not *explicitly* support most Oracle datatypes. It + simply asks Oracle to return them as strings and Oracle does so. Mostly. + Similarly when binding placeholder values DBD::Oracle binds them as + strings and Oracle converts them to the appropriate type, such as DATE, + when used. + + Some of these automatic conversions to and from strings use NLS settings + to control the formatting for output and the parsing for input. The most + common example is the DATE type. The default NLS format for DATE might + be DD-MON-YYYY and so when a DATE type is fetched that's how Oracle will + format the date. NLS settings also control the default parsing of + strings into DATE values. An error will be generated if the contents of + the string don't match the NLS format. If you're dealing in dates which + don't match the default NLS format then you can either change the + default NLS format or, more commonly, use TO_CHAR(field, "format") and + TO_DATE(?, "format") to explicitly specify formats for converting to and + from strings. + + A slightly more subtle problem can occur with NUMBER types. The default + NLS settings might format numbers with a fullstop (""."") to separate + thousands and a comma ("","") as the decimal point. Perl will generate + warnings and use incorrect values when numbers, returned and formatted + as strings in this way by Oracle, are used in a numeric context. You + could explicitly convert each numeric value using the TO_CHAR(...) + function but that gets tedious very quickly. The best fix is to change + the NLS settings. That can be done for an individual connection by + doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + + There are some types, like BOOLEAN, that Oracle does not automatically + convert to or from strings (pity). These need to be converted explicitly + using SQL or PL/SQL functions. + + Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + + Support for Insert of XMLType (ORA_XMLTYPE) + Inserting large XML data sets into tables with XMLType fields is now + supported by DBD::Oracle. The only special requirement is the use of + bind_param() with an attribute hash parameter that specifies ora_type as + ORA_XMLTYPE. For example with a table like this; + + create table books (book_id number, book_xml XMLType); + + one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + + In the above case we will assume that $xml has 10000 Book nodes and is + over 32k in size and is well formed XML. This will also work for XML + that is smaller than 32k as well. Attempting to insert malformed XML + will cause an error. + + Binding Cursors + Cursors can be returned from PL/SQL blocks, either from stored functions + (or procedures with OUT parameters) or from direct "OPEN" statements, as + shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + The only special requirement is the use of "bind_param_inout()" with an + attribute hash parameter that specifies "ora_type" as "ORA_RSET". If you + don't do that you'll get an error from the "execute()" like: "ORA-06550: + line X, column Y: PLS-00306: wrong number or types of arguments in call + to ...". + + Here's an alternative form using a function that returns a cursor. This + example uses the pre-defined weak (or generic) REF CURSOR type + SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + A cursor obtained from PL/SQL as above may be passed back to PL/SQL by + binding for input, as shown in this example, which explicitly closes a + cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + + It is not normally necessary to close a cursor explicitly in this way. + Oracle will close the cursor automatically at the first client-server + interaction after the cursor statement handle is destroyed. An explicit + close may be desirable if the reference to the cursor handle from the + PL/SQL statement handle delays the destruction of the cursor handle for + too long. This reference remains until the PL/SQL handle is re-bound, + re-executed or destroyed. + + See the "curref.pl" script in the Oracle.ex directory in the DBD::Oracle + source distribution for a complete working example. + + Fetching Nested Cursors + Oracle supports the use of select list expressions of type REF CURSOR. + These may be explicit cursor expressions - "CURSOR(SELECT ...)", or + calls to PL/SQL functions which return REF CURSOR values. The values of + these expressions are known as nested cursors. + + The value returned to a Perl program when a nested cursor is fetched is + a statement handle. This statement handle is ready to be fetched from. + It should not (indeed, must not) be executed. + + Oracle imposes a restriction on the order of fetching when nested + cursors are used. Suppose $sth1 is a handle for a select statement + involving nested cursors, and $sth2 is a nested cursor handle fetched + from $sth1. $sth2 can only be fetched from while $sth1 is still active, + and the row containing $sth2 is still current in $sth1. Any attempt to + fetch another row from $sth1 renders all nested cursor handles + previously fetched from $sth1 defunct. + + Fetching from such a defunct handle results in an error with the message + "ERROR nested cursor is defunct (parent row is no longer current)". + + This means that the "fetchall..." or "selectall..." methods are not + useful for queries returning nested cursors. By the time such a method + returns, all the nested cursor handles it has fetched will be defunct. + + It is necessary to use an explicit fetch loop, and to do all the + fetching of nested cursors within the loop, as the following example + shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + + The cursor returned by the function "sp_ListEmp" defined in the previous + section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + + Pre-fetching Nested Cursors + By default, DBD::Oracle pre-fetches rows in order to reduce the number + of round trips to the server. For queries which do not involve nested + cursors, the number of pre-fetched rows is controlled by the DBI + database handle attribute "RowCacheSize" (q.v.). + + In Oracle, server side open cursors are a controlled resource, limited + in number, on a per session basis, to the value of the initialization + parameter "OPEN_CURSORS". Nested cursors count towards this limit. Each + nested cursor in the current row counts 1, as does each nested cursor in + a pre-fetched row. Defunct nested cursors do not count. + + An Oracle specific database handle attribute, "ora_max_nested_cursors", + further controls pre-fetching for queries involving nested cursors. For + each statement handle, the total number of nested cursors in pre-fetched + rows is limited to the value of this parameter. The default value is 0, + which disables pre-fetching for queries involving nested cursors. + +PL/SQL Examples + Most of these PL/SQL examples come from: Eric Bartley + . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + + You can find more examples in the t/plsql.t file in the DBD::Oracle + source directory. + + Oracle 9.2 appears to have a bug where a variable bound with + bind_param_inout() that isn't assigned to by the executed PL/SQL block + may contain garbage. See + + + Avoid Using "SQL Call" + Avoid using the "SQL Call" statement with DBD:Oracle as you might find + that DBD::Oracle will not raise an exception in some case. Specifically + if you use "SQL Call" to run a procedure all "No data found" exceptions + will be quietly ignored and returned as null. According to Oracle + support this is part of the same mechanism where; + + select (select * from dual where 0=1) from dual + + returns a null value rather than an exception. + +CONTRIBUTING + If you'd like DBD::Oracle to do something new or different the best way + to make that happen is to do it yourself and email to dbi-dev@perl.org a + patch of the source code (using 'diff' - see below) that shows the + changes. + + How to create a patch using Subversion + The DBD::Oracle source code is maintained using Subversion (a + replacement for CVS, see ). To access the + source you'll need to install a Subversion client. Then, to get the + source code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + + If it prompts for a username and password use your perl.org account if + you have one, else just 'guest' and 'guest'. The source code will be in + a new subdirectory called "trunk". + + To keep informed about changes to the source you can send an empty email + to dbd-oracle-changes-subscribe@perl.org after which you'll get an email + with the change log message and diff of each change checked-in to the + source. + + After making your changes you can generate a patch file, but before you + do, make sure your source is still upto date using: + + svn update + + If you get any conflicts reported you'll need to fix them first. Then + generate the patch file from within the "trunk" directory using: + + svn diff > foo.patch + + Read the patch file, as a sanity check, and then email it to + dbi-dev@perl.org. + + How to create a patch without Subversion + Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + + Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + + Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you + want. + + Test your changes and then remove all temporary files: + + make test && make distclean + + Go back to the directory you originally unpacked the distribution: + + cd .. + + Unpack *another* copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + + Then create a patch file by performing a recursive "diff" on the two top + level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + + Speak before you patch + For anything non-trivial or possibly controversial it's a good idea to + discuss (on dbi-dev@perl.org) the changes you propose before actually + spending time working on them. Otherwise you run the risk of them being + rejected because they don't fit into some larger plans you may not be + aware of. + + GitHub repository + A git mirror of the subversion is also available at + `https://github.com/yanick/DBD-Oracle`. + +Oracle Related Links +WHICH VERSION OF DBD::ORACLE IS FOR ME? + From version 1.25 onwards DBD::Oracle only support Oracle clients 9.2 or + greater. Support for ProC connections was dropped in 1.29. + + If you are still stuck with an older version of Oracle or its client you + might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + + As there are dozens of different versions of Oracle's clients this list + does not include all of them, just the major released versions of + Oracle. + + Note that one can still connect to any Oracle version with the older + DBD::Oracle versions the only problem you will have is that some of the + newer OCI and Oracle features available in later DBD::Oracle releases + will not be available to you. + + So to make a short story a little longer: + + 1 If you are using Oracle 7 or early 8 DB and you can manage to get a + 9 client and you can use any DBD::Oracle version. + + 2 If you have to use an Oracle 7 client then DBD::Oracle 1.17 should + work + + 3 Same thing for 8 up to R2, use 1.17, if you are lucky and have the + right patch-set you might go with 1.18. + + 4 For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. + Again this depends on your patch-set, If you run into trouble go + with 1.19 + + 5 After 9.2 you can use any version you want. + + 6 It seems that the 10g client can only connect to 9 and 11 DBs while + the 9 can go back to 7 and even get to 10. I am not sure what the + 11g client can connect to. + +BUGS AND LIMITATIONS + There is a known problem with the 11.2g Oracle client and the + "DBMS_LOB.GETLENGTH()" PL/SQL function. See + for the details. + +SEE ALSO + DBI http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in + the DBD::Oracle source distribution including the examples in the + Oracle.ex directory + + DBD::Oracle Tutorial + http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-ora + cle.html + + Oracle Instant Client + http://www.oracle.com/technology/tech/oci/instantclient/index.html + + Oracle on Linux + http://www.ixora.com.au/ + + Free Oracle Tools and Links + ora_explain supplied and installed with DBD::Oracle. + + http://www.orafaq.com/ + + http://vonnieda.org/oracletool/ + + Commercial Oracle Tools and Links + Assorted tools and references for general information. No + recommendation implied. + + http://www.platinum.com + + http://www.SoftTreeTech.com + + Also PL/Vision from RevealNet and Steven Feuerstein, and "Q" from + Savant Corporation. + +AUTHORS + DBI by Tim Bunce . + + The original "DBD::Oracle" was by Tim Bunce. Maintained as of release + 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the + auspice of the Pythian Group (). + +ACKNOWLEDGEMENTS + A great many people have helped with DBD::Oracle over the 17 years + between 1994 and 2011. Far too many to name, but we thank them all. Many + are named in the Changes file. + +COPYRIGHT + The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. + The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The + Pythian Group). Canada. The DBD::Oracle module is Copyright (c) 2011 + John Scoles. Canada. + + The DBD::Oracle module is free open source software; you can + redistribute it and/or modify it under the same terms as Perl 5. + +AUTHORS + * Tim Bunce + + * John Scoles + + * Yanick Champoux + +COPYRIGHT AND LICENSE + This software is copyright (c) 1994 by Tim Bunce. + + This is free software; you can redistribute it and/or modify it under + the same terms as the Perl 5 programming language system itself. diff --git a/README.mkdn b/README.mkdn new file mode 100644 index 00000000..efd36615 --- /dev/null +++ b/README.mkdn @@ -0,0 +1,4228 @@ +# NAME + +DBD::Oracle - Oracle database driver for the DBI module + +# VERSION + +version 1.38 + +# SYNOPSIS + + use DBI; + + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); + + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); + + # See the DBI module documentation for full details + + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); + +# DESCRIPTION + +DBD::Oracle is a Perl module which works with the DBI module to provide +access to Oracle databases. + +This documentation describes driver specific behaviour and restrictions. It is +not supposed to be used as the only reference for the user. In any case +consult the [DBI](http://search.cpan.org/perldoc?DBI) documentation first! + +# CONSTANTS + +- :ora_session_modes + +ORA_SYSDBA ORA_SYSOPER ORA_SYSASM + +- :ora_types + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +- SQLCS_IMPLICIT + +- SQLCS_NCHAR + +SQLCS_IMPLICIT and SQLCS_NCHAR are _character set form_ values. +See notes about Unicode elsewhere in this document. + +- SQLT_INT + +- SQLT_FLT + +These types are used only internally, and may be specified as internal +bind type for ORA_NUMBER_TABLE. See notes about ORA_NUMBER_TABLE elsewhere +in this document + +- ORA_OCI + +Oracle doesn't provide a formal API for determining the exact version +number of the OCI client library used, so DBD::Oracle has to go digging +(and sometimes has to more or less guess). The ORA_OCI constant +holds the result of that process. + +In string context ORA_OCI returns the full "A.B.C.D" version string. + +In numeric context ORA_OCI returns the major.minor version number +(8.1, 9.2, 10.0 etc). But note that version numbers are not actually +floating point and so if Oracle ever makes a release that has a two +digit minor version, such as `9.10` it will have a lower numeric +value than the preceding `9.9` release. So use with care. + +The contents and format of ORA_OCI are subject to change (it may, +for example, become a _version object_ in later releases). +I recommend that you avoid checking for exact values. + +- :ora_fetch_orient + + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE + +These constants are used to set the orientation of a fetch on a scrollable cursor. + +- :ora_exe_modes + + OCI_STMT_SCROLLABLE_READONLY + +- :ora_fail_over + + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + +# DBI CLASS METHODS + +## __connect__ + +This method creates a database handle by connecting to a database, and is the DBI equivalent of the "new" method. +To open a connection to an Oracle database you need to specify a database connection string (URL), username and password. + +The connection string is always of the form: "dbi:Oracle:" +There are several ways to identify a database: + +- 1 + +If the database is local, specifying the SID or service name will be enough. + +- 2 + +If the database is defined in a TNSNAMES.ORA file, you can use the service name given in the file + +- 3 + +To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: +//host[:port][/service_name] + +If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. + +The following examples show several ways a connection can be created: + + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); + + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); + + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); + + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); + +### OS authentication + +To connect to a local database with a user which has been set up to +authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): + + $dbh = DBI->connect('dbi:Oracle:','/',''); + +Note the lack of a connection name (use the ORACLE_SID environment +variable). If an explicit SID is used you will probably get an ORA-01004 error. + +That only works for local databases. (Authentication to remote Oracle +databases using your Unix login name without a password is possible +but it is not secure and not recommended so not documented here. + +### Oracle Environment Variables + +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). + +Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. + +To use them, specify either a local SID or service name, or a service name that is specified in the TNSNAMES.ORA file. + +Note that if you have *both* local and remote databases, and you have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO_TASK takes precedence over ORACLE_SID (i.e. you get connected to remote system). + +It is highly recommended not to rely on environment variables and to always explicitly specify the SID in the connection string. This can prevent serious mistakes such as dropping a schema in the wrong database, and generally makes debugging and troubleshooting easier. + +Also remember that depending on the operating system you are using the differing "ORACLE" environment variables may be case sensitive, so if you are not connecting as you should double check the case of both the variable and its value. + +### Timezones + +If the query is run through SQL*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. + +If the query is run locally, Oracle will return the time zone based on the "TZ" environment variable setting of the user running +the query. + +With local queries, you can change the time zone for a particular user by simply changing the setting of "TZ". To check the current setting, +issue the UNIX "date" command. + +### Oracle DRCP + +DBD::Oracle supports DRCP (Database Resident Connection Pool) so +if you have an 11.2 database and DRCP is enabled you can direct +all of your connections to it by adding ':POOLED' to the SID or +setting a connection attribute of ora_drcp, or set the SERVER=POOLED +when using a TNSENTRY style connection or even by setting an +environment variable ORA_DRCP. All of which are demonstrated below; + + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') + + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') + + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") + + if the ORA_DRCP environment variable is set then just this + + $dbh = DBI->connect('dbi:Oracle:DB','username','password') + +You can find a white paper on setting up DRCP and its advantages at [http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf](http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf). + +Please note that DRCP support in DBD::Oracle is relatively new so the +mechanics or its implementation are subject to change. + +### TAF (Transparent Application Failover) + +Transparent Application Failover (TAF) is the feature in OCI that +allows for clients to automatically reconnect to an instance in the +event of a failure of the instance. The reconnect happens +automatically from within the OCI (Oracle Call Interface) library. +DBD::Oracle now supports a callback function that will fire when a TAF +event takes place. The main use of the callback is to give your +program the opportunity to inform the user that a failover is taking +place. + +You will have to set up TAF on your instance before you can use this +callback. You can test your instance to see if you can use TAF +callback with + + $dbh->ora_can_taf(); + +If you try to set up a callback without it being enabled DBD::Oracle will croak. + +It is outside the scope of this documents to go through all of the +possible TAF situations you might want to set up but here is a simple +example: + +The TNS entry for the instance has had the following added to the +CONNECT_DATA section + + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) + +You will also have to create your own perl function that will be +called from the client. You can name it anything you want and it will +always be passed two parameters, the failover event value and the +failover type. You can also set a sleep value in case of failover +error and the OCI client will sleep for the specified seconds before it +attempts another event. + + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants + + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + + #create the perl TAF event function + + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ + + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); + + } + return 0; + } + +The TAF types are as follows + + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + +The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + +### Connect Attributes + +#### ora_ncs_buff_mtpl + +You can customize the size of the buffer when selecting LOBs with +the built-in AUTO Lob. The default value is 4 which is probably +excessive for most situations but is needed for backward +compatibility. If you not converting between a NCS on the DB and the +Client then you might want to set this to 1 to reduce memory usage. + +This value can also be specified with the `ORA_DBD_NCS_BUFFER` +environment variable in which case it sets the value at the connect +stage. + +#### ora_drcp + +For Oracle 11.2 or greater. + +Set to _1_ to enable DRCP. Can also be set via the `ORA_DRCP` environment variable. + +#### ora_drcp_class + +If you are using DRCP, you can set a CONNECTION_CLASS for your pools +as well. As sessions from a DRCP cannot be shared by users, you can +use this setting to identify the same user across different +applications. OCI will ensure that sessions belonging to a 'class' are +not shared outside the class'. + +The values for ora_drcp_class cannot contain a '*' and must be less +than 1024 characters. + +This value can be also be specified with the `ORA_DRCP_CLASS` +environment variable. + +#### ora_drcp_min + +This optional value specifies the minimum number of sessions that are +initially opened. New sessions are only opened after this value has +been reached. + +The default value is 4 and any value above 0 is valid. + +Generally, it should be set to the number of concurrent statements the +application is planning or expecting to run. + +This value can also be specified with the `ORA_DRCP_MIN` environment +variable. + +#### ora_drcp_max + +This optional value specifies the maximum number of sessions that can +be open at one time. Once reached no more sessions can be opened +until one becomes free. The default value is 40 and any value above 1 +is valid. You should not set this value lower than ora_drcp_min as +that will just waste resources. + +This value can also be specified with the `ORA_DRCP_MAX` environment +variable. + +#### ora_drcp_incr + +This optional value specifies the next increment for sessions to be +started if the current number of sessions are less than +ora_drcp_max. The default value is 2 and any value above 0 is +valid as long as the value of ora_drcp_min + ora_drcp_incr is not +greater than ora_drcp_max. + +This value can also be specified with the `ORA_DRCP_INCR` environment +variable. + +#### ora_taf + +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option to any _true_ value. + +#### ora_taf_function + +The name of the Perl subroutine that will be called from OCI when a +TAF event occurs. You must supply a perl function to use the callback +and it will always receive two parameters, the failover event value +and the failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + +#### ora_taf_sleep + +The amount of time in seconds the OCI client will sleep between attempting +successive failover events when the event is OCI_FO_ERROR. + +#### ora_session_mode + +The ora_session_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA_SYSASM authorization. +The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + +This is one case where setting ORACLE_SID may be useful since +connecting as SYSDBA or SYSOPER via SQL*Net is frequently disabled +for security reasons. + +Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + +It has been reported that this only works if `$dsn` does not contain +a SID so that Oracle then uses the value of ORACLE_SID (not +TWO_TASK) environment variable to connect to a local instance. Also +the username and password should be empty, and the user executing the +script needs to be part of the dba group or osdba group. + +#### ora_oratab_orahome + +Passing a true value for the ora_oratab_orahome attribute will make +DBD::Oracle change `$ENV{ORACLE_HOME}` to make the Oracle home directory +that specified in the `/etc/oratab` file _if_ the database to connect to +is specified as a SID that exists in the oratab file, and DBD::Oracle was +built to use the Oracle 7 OCI API (not Oracle 8+). + +#### ora_module_name + +After connecting to the database the value of this attribute is passed +to the SET_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL +package. This can be used to identify the application to the DBA for +monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + +The maximum size is 48 bytes. + +#### ora_driver_name + +For 11g and later you can now set the name of the driver layer using OCI. +Perl, Perl5, ApachePerl so on. Names starting with "ORA" are reserved. You +can enter up to 8 characters. If none is enter then this will default to +DBDOxxxx where xxxx is the current version number. This value can be +retrieved on the server side using V$SESSION_CONNECT_INFO or +GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + +#### ora_client_info + +Allows you to add any value (up to 64 bytes) to your session and it can be +retrieved on the server side from the `V$SESSION`a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + +#### ora_client_identifier + +Allows you to specify the user identifier in the session handle. + +Most useful for web applications as it can pass in the session user +name which might be different to the connection user name. Can be up +to 64 bytes long but do not to include the password for security +reasons and the first character of the identifier should not be +':'. This value can be retrieved on the server side using `V$SESSION` +view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + +#### ora_action + +Allows you to specify any string up to 32 bytes which may be retrieved +on the server side using `V$SESSION` view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + +#### ora_dbh_share + +Requires at least Perl 5.8.0 compiled with ithreads. + +Allows you to share +database connections between threads. The first connect will make the +connection, all following calls to connect with the same ora_dbh_share +attribute will use the same database connection. The value must be a +reference to a already shared scalar which is initialized to an empty +string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + +#### ora_envhp + +The first time a connection is made a new OCI 'environment' is +created by DBD::Oracle and stored in the driver handle. +Subsequent connects reuse (share) that same OCI environment +by default. + +The ora_envhp attribute can be used to disable the reuse of the OCI +environment from a previous connect. If the value is `0` then +a new OCI environment is allocated and used for this connection. + +The OCI environment holds information about the client side context, +such as the local NLS environment. By altering `%ENV` and setting +ora_envhp to 0 you can create connections with different NLS +settings. This is most useful for testing. + +#### ora_charset, ora_ncharset + +For oracle versions >= 9.2 you can specify the client charset and +ncharset with the ora_charset and ora_ncharset attributes. You +still need to pass `ora_envhp = 0` for all but the first connect. + +These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + +#### ora_verbose + +Use this value to enable DBD::Oracle only tracing. Simply either set +the ora_verbose attribute on the connect() method to the trace level +you desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + +or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + +In both cases the DBD::Oracle trace level is set to 6, which is the highest +level tracing most of the calls to OCI. + +#### ora_oci_success_warn + +Use this value to print otherwise silent OCI warnings that may happen +when an execute or fetch returns "Success With Info" or when you want +to tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + +#### ora_objects + +Use this value to enable extended embedded oracle objects mode. In extended: + +- 1 + +Embedded objects are returned as instance (including type-name etc.) instead of simple ARRAY. + +- 2 + +Determine object type for each instance. All object attributes are returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + +#### ora_ph_type + +The default placeholder datatype for the database session. +The `TYPE` or [ora_type](#pod_ora_type) attributes to L and +L override the datatype for individual placeholders. +The most frequent reason for using this attribute is to permit trailing spaces +in values passed by placeholders. + +Constants for the values allowed for this attribute can be imported using + + use DBD::Oracle qw(:ora_types); + +Only the following values are permitted for this attribute. + +- ORA_VARCHAR2 + +Oracle clients using OCI 8 will strip trailing spaces and allow embedded \0 bytes. +Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \0 bytes. +This is the normal default placeholder type. + +- ORA_STRING + +Do not strip trailing spaces and end the string at the first \0. + +- ORA_CHAR + +Do not strip trailing spaces and allow embedded \0. +Force 'blank-padded comparison semantics'. + +For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + +Will pad bloggs out to 8 characters and return the username. + +#### ora_parse_error_offset + +If the previous error was from a failed `prepare` due to a syntax error, +this attribute gives the offset into the `Statement` attribute where the +error was found. + +#### ora_array_chunk_size + +Due to OCI limitations, DBD::Oracle needs to buffer up rows of +bind values in its `execute_for_fetch` implementation. This attribute +sets the number of rows to buffer at a time (default value is 1000). + +The `execute_for_fetch` function will collect (at most) this many +rows in an array, send them off to the DB for execution, then go back +to collect the next chunk of rows and so on. This attribute can be +used to limit or extend the number of rows processed at a time. + +Note that this attribute also applies to `execute_array`, since that +method is implemented using `execute_for_fetch`. + +#### ora_connect_with_default_signals + +Sometimes the Oracle client seems to change some of the signal +handlers of the process during the connect phase. For instance, some +users have observed Perl's default `$SIG{INT}` handler being ignored +after connecting to an Oracle database. If this causes problems in +your application, set this attribute to an array reference of signals +you would like to be localized during the connect process. Once the +connect is complete, the signal handlers should be returned to their +previous state. + +For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + +NOTE disabling the signal handlers the OCI library sets up may affect +functionality in the OCI library. + +NOTE If you are using connect_cached then the above example will lead +to DBI thinking each connection is different as an anonymous array reference +is being used. To avoid this when using connect_cached you are advised +to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + +In more recent Perl versions you could possibly make use of new state +variables. + +## __connect_cached__ + +Implemented by DBI, no driver-specific impact. +Please note that connect_cached as not been tested with DRCP. + +## __data_sources__ + + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + +Returns a list of available databases. You will have to set either the 'ORACLE_HOME' or +'TNS_ADMIN' environment value to retrieve this list. It will read these values from +TNSNAMES.ORA file entries. + +# METHODS COMMON TO ALL HANDLES + +For all of the methods below, __$h__ can be either a database handle (__$dbh__) +or a statement handle (__$sth__). Note that _$dbh_ and _$sth_ can be replaced with +any variable name you choose: these are just the names most often used. Another +common variable used in this documentation is $_rv_, which stands for "return value". + +## __err__ + + $rv = $h->err; + +Returns the error code from the last method called. + +## __errstr__ + + $str = $h->errstr; + +Returns the last error that was reported by Oracle. Starting with "ORA-00000" code followed by the error message. + +## __state__ + + $str = $h->state; + +Oracle hasn't supported SQLSTATE since the early versions OCI. It will return empty when the command succeeds and +'S1000' (General Error) for all other errors. + +While this method can be called as either `$sth->state` or `$dbh->state`, it +is usually clearer to always use `$dbh->state`. + +## __trace__ + +Implemented by DBI, no driver-specific impact. + +## __trace_msg__ + +Implemented by DBI, no driver-specific impact. + +## __parse_trace_flag__ and __parse_trace_flags__ + +Implemented by DBI, no driver-specific impact. + +## __func__ + +DBD::Oracle uses the `func` method to support a variety of functions. + +## __Private database handle functions__ + +Some of these functions are called through the method func() +which is described in the DBI documentation. Any function that begins with ora_ +can be called directly. + +## __plsql_errstr__ + +This function returns a string which describes the errors +from the most recent PL/SQL function, procedure, package, +or package body compile in a format similar to the output +of the SQL*Plus command 'show errors'. + +The function returns undef if the error string could not +be retrieved due to a database error. +Look in $dbh->errstr for the cause of the failure. + +If there are no compile errors, an empty string is returned. + +Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + +## __dbms_output_enable / dbms_output_put / dbms_output_get__ + +These functions use the PL/SQL DBMS_OUTPUT package to store and +retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer +by dbms_output_put or any PL/SQL block can be retrieved by +dbms_output_get or any PL/SQL block connected to the same database +session. + +Stored text is not available until after dbms_output_put or the PL/SQL +block that saved it completes its execution. This means you __CAN NOT__ +use these functions to monitor long running PL/SQL procedures. + +Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + +Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + +## __dbms_output_enable ( [ buffer_size ] )__ + +This function calls DBMS_OUTPUT.ENABLE to enable calls to package +DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to +these procedures are ignored unless DBMS_OUTPUT.ENABLE is called +first. + +The buffer_size is the maximum amount of text that can be saved in the +buffer and must be between 2000 and 1,000,000. If buffer_size is not +given, the default is 20,000 bytes. + +## __dbms_output_put ( [ @lines ] )__ + +This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + +If all lines were saved successfully the function returns 1. Depending +on the context, an empty list or undef is returned for failure. + +If any line causes buffer_size to be exceeded, a buffer overflow error +is raised and the function call fails. Some of the text might be in +the buffer. + +## __dbms_output_get__ + +This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from +the buffer. + +In an array context, all complete lines are removed from the buffer and +returned as a list. If there are no complete lines, an empty list is +returned. + +In a scalar context, the first complete line is removed from the buffer +and returned. If there are no complete lines, undef is returned. + +Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or +DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, +DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + +## __reauthenticate ( $username, $password )__ + +Starts a new session against the current database using the credentials +supplied. + +## __private_attribute_info__ + + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + +Returns a hash of all private attributes used by DBD::Oracle, for either +a database or a statement handle. Currently, all the hash values are undef. + +# ATTRIBUTES COMMON TO ALL HANDLES + +## __InactiveDestroy__ (boolean) + +Implemented by DBI, no driver-specific impact. + +## __RaiseError__ (boolean, inherited) + +Forces errors to always raise an exception. Although it defaults to off, it is recommended that this +be turned on, as the alternative is to check the return value of every method (prepare, execute, fetch, etc.) +manually, which is easy to forget to do. + +## __PrintError__ (boolean, inherited) + +Forces database errors to also generate warnings, which can then be filtered with methods such as +locally redefining _$SIG{__WARN__}_ or using modules such as `CGI::Carp`. This attribute is on +by default. + +## __ShowErrorStatement__ (boolean, inherited) + +Appends information about the current statement to error messages. If placeholder information +is available, adds that as well. Defaults to true. + +## __Warn__ (boolean, inherited) + +Enables warnings. This is on by default, and should only be turned off in a local block +for a short a time only when absolutely needed. + +## __Executed__ (boolean, read-only) + +Indicates if a handle has been executed. For database handles, this value is true after the [do](#pod_do) method has been called, or +when one of the child statement handles has issued an [execute](#pod_execute). Issuing a [commit](#pod_commit) or [rollback](#pod_rollback) always resets the +attribute to false for database handles. For statement handles, any call to [execute](#pod_execute) or its variants will flip the value to +true for the lifetime of the statement handle. + +## __TraceLevel__ (integer, inherited) + +Sets the trace level, similar to the [trace](#pod_trace) method. See the sections on +[trace](#pod_trace) and [parse_trace_flag](#pod_parse_trace_flag) for more details. + +## __Active__ (boolean, read-only) + +Indicates if a handle is active or not. For database handles, this indicates if the database has +been disconnected or not. For statement handles, it indicates if all the data has been fetched yet +or not. Use of this attribute is not encouraged. + +## __Kids__ (integer, read-only) + +Returns the number of child processes created for each handle type. For a driver handle, indicates the number +of database handles created. For a database handle, indicates the number of statement handles created. For +statement handles, it always returns zero, because statement handles do not create kids. + +## __ActiveKids__ (integer, read-only) + +Same as `Kids`, but only returns those that are active. + +## __CachedKids__ (hash ref) + +Returns a hashref of handles. If called on a database handle, returns all statement handles created by use of the +`prepare_cached` method. If called on a driver handle, returns all database handles created by the [connect_cached](#pod_connect_cached) +method. + +## __ChildHandles__ (array ref) + +Implemented by DBI, no driver-specific impact. + +## __PrintWarn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleError__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleSetErr__ (code ref, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ErrCount__ (unsigned integer) + +Implemented by DBI, no driver-specific impact. + +## __FetchHashKeyName__ (string, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ChopBlanks__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Taint__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintIn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintOut__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Profile__ (inherited) + +Implemented by DBI, no driver-specific impact. + +## __Type__ (scalar) + +Returns `dr` for a driver handle, `db` for a database handle, and `st` for a statement handle. +Should be rarely needed. + +## __LongReadLen__ + +Implemented by DBI, no driver-specific impact. + +## __LongTruncOk__ + +Implemented by DBI, no driver-specific impact. + +## __CompatMode__ + +Type: boolean, inherited + +The CompatMode attribute is used by emulation layers (such as Oraperl) to enable compatible behaviour in the underlying driver (e.g., DBD::Oracle) for this handle. Not normally set by application code. + +It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. + +# ORACLE-SPECIFIC DATABASE HANDLE METHODS + +## __ora_can_unicode ( [ $refresh ] )__ + +Returns a number indicating whether either of the database character sets +is a Unicode encoding. Calls ora_nls_parameters() and passes the optional +$refresh parameter to it. + +0 = Neither character set is a Unicode encoding. + +1 = National character set is a Unicode encoding. + +2 = Database character set is a Unicode encoding. + +3 = Both character sets are Unicode encodings. + +## __ora_can_taf__ + +Returns true if the current connection supports TAF events. False if otherise. + +## __ora_nls_parameters ( [ $refresh ] )__ + +Returns a hash reference containing the current NLS parameters, as given +by the v$nls_parameters view. The values fetched are cached between calls. +To cause the latest values to be fetched, pass a true value to the function. + +# DATABASE HANDLE METHODS + +## __selectall_arrayref__ + + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectall_hashref__ + + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + +Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectcol_arrayref__ + + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the first column +from each rows returned by preparing and executing the SQL string. It is possible to specify exactly +which columns to return. See the DBI documentation for full details. + +## __prepare__ + + $sth = $dbh->prepare($statement, \%attr); + +Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. + +### __Prepare Attributes__ + +These attributes may be used in the `\%attr` parameter of the +L database handle method. + +- ora_placeholders + +Set to false to disable processing of placeholders. Used mainly for loading a +PL/SQL package that has been _wrapped_ with Oracle's `wrap` utility. + +- ora_auto_lob + +If true (the default), fetching retrieves the contents of the CLOB or +BLOB column in most circumstances. If false, fetching retrieves the +Oracle "LOB Locator" of the CLOB or BLOB value. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for more details. + +See also the LOB tests in 05dbi.t of Oracle::OCI for examples +of how to use LOB Locators. + +- ora_pers_lob + +If true the [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) method for the [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) will be +used for LOBs rather than the default method [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators). + +- ora_clbk_lob + +If true the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) method for the L will be used for LOBs. + +- ora_piece_lob + +If true the [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) method for the L will be used for LOBs. + +- ora_piece_size + +This is the max piece size for the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) +and [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) methods, in chars for CLOBS, and +bytes for BLOBS. + +- ora_check_sql + +If 1 (default), force SELECT statements to be described in prepare(). +If 0, allow SELECT statements to defer describe until execute(). + +See [Prepare Postponed Till Execute](#pod_Prepare Postponed Till Execute) for more information. + +- ora_exe_mode + +This will set the execute mode of the current statement. Presently +only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + +See [Scrollable Cursors](#pod_Scrollable Cursors) for more details. + +- ora_prefetch_rows + +Sets the number of rows to be prefetched. If it is not set, then the +default value is 1. See [Row Prefetching](#pod_Row Prefetching) for more details. + +- ora_prefetch_memory + +Sets the memory level for rows to be prefetched. The application then +fetches as many rows as will fit into that much memory. See L for more details. + +- ora_row_cache_off + +By default DBD::Oracle will use a row cache when fetching to cut down +the number of round trips to the server. If you do not want to use an +array fetch set this value to any value other than 0; + +See [Row Prefetching](#pod_Row Prefetching) for more details. + +### __Placeholders__ + +There are two types of placeholders that can be used in DBD::Oracle. The first is +the "question mark" type, in which each placeholder is represented by a single +question mark character. This is the method recommended by the DBI specs and is the most +portable. Each question mark is internally replaced by a "dollar sign number" in the order +in which they appear in the query (important when using [bind_param](#pod_bind_param)). + +The other placeholder type is "named parameters" in the format ":foo" which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + +The different types of placeholders cannot be mixed within a statement, but you may +use different ones for each statement handle you have. This is confusing at best, so +stick to one style within your program. + +## __prepare_cached__ + + $sth = $dbh->prepare_cached($statement, \%attr); + +Implemented by DBI, no driver-specific impact. This method is most useful +if the same query is used over and over as it will cut down round trips to the server. + +## __do__ + + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + +Prepare and execute a single statement. Returns the number of rows affected if the +query was successful, returns undef if an error occurred, and returns -1 if the +number of rows is unknown or not available. Note that this method will return __0E0__ instead +of 0 for 'no rows were affected', in order to always return a true value if no error occurred. + +## __last_insert_id__ + +Oracle does not implement auto_increment of serial type columns it uses predefined +sequences where the id numbers are either selected before insert, at insert time with a trigger, + or as part of the query. + +Below is an example of you to use the latter with the SQL returning clause to get the ID number back +on insert with the bind_param_inout method. +. + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + +## __commit__ + + $rv = $dbh->commit; + +Issues a COMMIT to the server, indicating that the current transaction is finished and that +all changes made will be visible to other processes. If AutoCommit is enabled, then +a warning is given and no COMMIT is issued. Returns true on success, false on error. + +## __rollback__ + + $rv = $dbh->rollback; + +Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit +is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and +false on error. + +## __begin_work__ + +This method turns on transactions until the next call to [commit](#pod_commit) or [rollback](#pod_rollback), if [AutoCommit](#pod_AutoCommit) is +currently enabled. If it is not enabled, calling begin_work will issue an error. Note that the +transaction will not actually begin until the first statement after begin_work is called. + +## __disconnect__ + + $rv = $dbh->disconnect; + +Disconnects from the Oracle database. Any uncommitted changes will be rolled back upon disconnection. It's +good policy to always explicitly call commit or rollback at some point before disconnecting, rather than +relying on the default rollback behavior. + +If the script exits before disconnect is called (or, more precisely, if the database handle is no longer +referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() +methods automatically. It is best to explicitly disconnect rather than rely on this behavior. + +## __ping__ + + $rv = $dbh->ping; + +This `ping` method is used to check the validity of a database handle. The value returned is +either 0, indicating that the connection is no longer valid, or 1, indicating the connection is valid. +This function does 1 round trip to the Oracle Server. + +## __get_info()__ + + $value = $dbh->get_info($info_type); + +DBD::Oracle supports `get_info()`, but (currently) only a few info types. + +## __table_info()__ + +DBD::Oracle supports attributes for `table_info()`. + +In Oracle, the concept of _user_ and _schema_ is (currently) the +same. Because database objects are owned by an user, the owner names +in the data dictionary views correspond to schema names. +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. + +Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + +TABLE_TYPE may contain a comma-separated list of table types. +The following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + +The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + +The special enumerations of catalogues, schemas and table types are +supported. However, TABLE_CAT is always NULL. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +`table_info()` performs a case-sensitive search. So, a selection +criterion should respect upper and lower case. +Normally, an identifier is case-insensitive. Oracle stores and +returns it in upper case. Sometimes, database objects are created +with quoted identifiers (for reserved words, mixed case, special +characters, ...). Such an identifier is case-sensitive (if not all +upper case). Oracle stores and returns it as given. +`table_info()` has no special quote handling, neither adds nor +removes quotes. + +## __primary_key_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary key constraint was created without an identifier, +PK_NAME contains a system generated name with the form SYS_Cn. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __foreign_key_info()__ + +This method (currently) supports the extended behaviour of SQL/CLI, i.e. the +result set contains foreign keys that refer to primary __and__ alternate keys. +The field UNIQUE_OR_PRIMARY distinguishes these keys. + +Oracle does not support catalogues, so `$pk_catalog` and `$fk_catalog` are +ignored as selection criteria (in the new style interface). +The UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always +NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary or foreign key constraints were created without an identifier, +UK_NAME or FK_NAME contains a system generated name with the form SYS_Cn. + +The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle (currently) +does not support other actions. + +The DELETE_RULE field may contain wrong values. This is a known Bug (#1271663) +in Oracle's data dictionary views. Currently (as of 8.1.7), 'RESTRICT' and +'SET DEFAULT' are not supported, 'CASCADE' is mapped correctly and all other +actions (incl. 'SET NULL') appear as 'NO ACTION'. + +The DEFERABILITY field is always NULL, because this columns is +not present in the ALL_CONSTRAINTS view of older Oracle releases. + +The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, +FK_TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __column_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + +Don't rely on the values of the BUFFER_LENGTH field! +Especially the length of FLOATs may be wrong. + +Datatype codes for non-standard types are subject to change. + +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +It is possible with Oracle to make the names of the various DB objects (table,column,index etc) +case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + +So in the example the exact case "Bla_BLA" must be used to get it info on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + +any case can be used to get info on the column. + +## __selectrow_array__ + + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + +Returns an array of row information after preparing and executing the provided SQL string. The rows are returned +by calling [fetchrow_array](#pod_fetchrow_array). The string can also be a statement handle generated by a previous prepare. Note that +only the first row of data is returned. If called in a scalar context, only the first column of the first row is +returned. Because this is not portable, it is not recommended that you use this method in that way. + +## __selectrow_arrayref__ + + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an array, by internal use of +the [fetchrow_arrayref](#pod_fetchrow_arrayref) method. + +## __selectrow_hashref__ + + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an hash, by internal use of +the [fetchrow_hashref](#pod_fetchrow_hashref) method. + +## __clone__ + + $other_dbh = $dbh->clone(); + +Creates a copy of the database handle by connecting with the same parameters as the original +handle, then trying to merge the attributes. See the DBI documentation for complete usage. + +# DATABASE HANDLE ATTRIBUTES + +## __AutoCommit__ (boolean) + +Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change +in the future, so it is highly recommended that you explicitly set it when +calling [connect](#pod_connect). + +## __ReadOnly__ (boolean) + + $dbh->{ReadOnly} = 1; + +Specifies if the current database connection should be in read-only mode or not. + +Please not that this method is not foolproof: there are still ways to update the +database. Consider this a safety net to catch applications that should not be +issuing commands such as INSERT, UPDATE, or DELETE. + +This method method requires DBI version 1.55 or better. + +## __Name__ (string, read-only) + +Returns the name of the current database. This is the same as the DSN, without the +"dbi:Oracle:" part. + +## __Username__ (string, read-only) + +Returns the name of the user connected to the database. + +## __Driver__ (handle, read-only) + +Holds the handle of the parent driver. The only recommended use for this is to find the name +of the driver using: + + $dbh->{Driver}->{Name} + +## __RowCacheSize__ + +DBD::Oracle supports both Server pre-fetch and Client side row caching. By default both +are turned on to give optimum performance. Most of the time one can just let DBD::Oracle +figure out the best optimization. + +### __Row Caching__ + +Row caching occurs on the client side and the object of it is to cut down the number of round +trips made to the server when fetching rows. At each fetch a set number of rows will be retrieved +from the server and stored locally. Further calls the server are made only when the end of the +local buffer(cache) is reached. + +Rows up to the specified top level row +count `RowCacheSize` are fetched if it occupies no more than the specified memory usage limit. +The default value is 0, which means that memory size is not included in computing the number of rows to prefetch. If +the `RowCacheSize` value is set to a negative number then the positive value of RowCacheSize is used +to compute the number of rows to prefetch. + +By default `RowCacheSize` is automatically set. If you want to totally turn off prefetching set this to 1. + +For any SQL statement that contains a LOB, Long or Object Type Row Caching will be turned off. However server side +caching still works. If you are only selecting a LOB Locator then Row Caching will still work. + +### Row Prefetching + +Row prefetching occurs on the server side and uses the DBI database handle attribute `RowCacheSize` and or the +Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improved performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. + +The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first +fetch that sets the current_positon to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are +loaded into the buffer and DBD::Oracle will not have to go back to the server for more rows. When record 11 is fetched DBD::Oracle +fetches and returns this row and the next 9 rows are loaded into the buffer. In this case if you fetch backwards from 10 to 1 +no server round trips are made. + +With large record sets it is best not to attempt to go to the last record as this may take some time, A large buffer size might even slow down +the fetch. If you must get the number of rows in a large record set you might try using an few large OCI_FETCH_ABSOLUTEs and then an OCI_FETCH_LAST, +this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. +If one requires only the first few rows there is no need to set a large prefetch value. + +If the ora_prefetch_memory less than 1 or not present then memory size is not included in computing the +number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it +is not included in the computing of the prefetch rows. + +# ORACLE-SPECIFIC STATEMENT HANDLE METHODS + +## __ora_stmt_type__ + +Returns the OCI Statement Type number for the SQL of a statement handle. + +## __ora_stmt_type_name__ + +Returns the OCI Statement Type name for the SQL of a statement handle. + +# DBI STATEMENT HANDLE OBJECT METHODS + +## __bind_param__ + + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + +Allows the user to bind a value and/or a data type to a placeholder. + +The value of `$param_num` is a number if using the '?' or if using ":foo" style placeholders, the complete name +(e.g. ":foo") must be given. +The `$bind_value` argument is fairly self-explanatory. A value of `undef` will +bind a `NULL` to the placeholder. Using `undef` is useful when you want +to change just the type and will be overwriting the value later. +(Any value is actually usable, but `undef` is easy and efficient). + +The `\%attr` hash is used to indicate the data type of the placeholder. +The default value is "varchar". If you need something else, you must +use one of the values provided by DBI or by DBD::Pg. To use a SQL value, +modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + +This will import some constants into your script. You can plug those +directly into the [bind_param](#pod_bind_param) call. Some common ones that you will +encounter are: + + SQL_INTEGER + +To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + +You can then set the data types by setting the value of the `ora_type` +key in the hash passed to [bind_param](#pod_bind_param). +The current list of Oracle data types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +Data types are "sticky," in that once a data type is set to a certain placeholder, +it will remain for that placeholder, unless it is explicitly set to something +else afterwards. If the statement has already been prepared, and you switch the +data type to something else, DBD::Oracle will re-prepare the statement for you before +doing the next execute. + +Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + +These attributes may be used in the `\%attr` parameter of the +L or L statement handle methods. + +- ora_type + +Specify the placeholder's datatype using an Oracle datatype. +A fatal error is raised if `ora_type` and the DBI `TYPE` attribute +are used for the same placeholder. +Some of these types are not supported by the current version of +DBD::Oracle and will cause a fatal error if used. +Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + +Potentially useful values when DBD::Oracle was built using OCI 7 and later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + +Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + +Additional values when DBD::Oracle was built using OCI 9.2 and later: + + SQLT_CHR, SQLT_BIN + +See [Binding Cursors](#pod_Binding Cursors) for the correct way to use ORA_RSET. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for how to use ORA_CLOB and ORA_BLOB. + +See [SYS.DBMS_SQL datatypes](#pod_SYS.DBMS_SQL datatypes) for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. + +See [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) for the correct way to use SQLT_CHR and SQLT_BIN. + +See [Other Data Types](#pod_Other Data Types) for more information. + +See also L. + +- ora_csform + +Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values +are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can +be imported from the DBD::Oracle module. Rarely needed. + +- ora_csid + +Specify the _integer_ OCI_ATTR_CHARSET_ID for the bind value. +Character set names can't be used currently. + +- ora_maxdata_size + +Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. +May be needed if a character set conversion from client to server +causes the data to use more space and so fail with a truncation error. + +- ora_maxarray_numentries + +Specify the maximum number of array entries to allocate. Used with +ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of +array entries Oracle can pass back to you in OUT variable of type +TABLE OF ... . + +- ora_internal_type + +Specify internal data representation. Currently is supported only for +ORA_NUMBER_TABLE. + +### Optimizing Results + +#### Prepare Postponed Till Execute + +The DBD::Oracle module can avoid an explicit 'describe' operation +prior to the execution of the statement unless the application requests +information about the results (such as $sth->{NAME}). This reduces +communication with the server and increases performance (reducing the +number of PARSE_CALLS inside the server). + +However, it also means that SQL errors are not detected until +`execute()` (or $sth->{NAME} etc) is called instead of when +`prepare()` is called. Note that if the describe is triggered by the +use of $sth->{NAME} or a similar attribute and the describe fails then +_an exception is thrown_ even if `RaiseError` is false! + +Set [ora_check_sql](#pod_ora_check_sql) to 0 in prepare() to enable this behaviour. + +## __bind_param_inout__ + + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + +DBD::Oracle fully supports bind_param_inout below are some uses for this method. + +### __Returning A Value from an INSERT__ + +Oracle supports an extended SQL insert syntax which will return one +or more of the values inserted. This can be particularly useful for +single-pass insertion of values with re-used sequence values +(avoiding a separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + +If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + +If you have many rows to insert you can take advantage of Oracle's built in execute array feature +with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + +Which will return all the ids into @out_values. + +- __Note:__ + +- This will only work for numbered (?) placeholders, + +- The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle + +- The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + +### Returning A Recordset + +DBD::Oracle does not currently support binding a PL/SQL table (aka array) +as an IN OUT parameter to any Perl data structure. You cannot therefore call +a PL/SQL function or procedure from DBI that uses a non-atomic datatype as +either a parameter, or a return value. However, if you are using Oracle 9.0.1 +or later, you can make use of table (or pipelined) functions. + +For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + +Currently, there is no way to directly call the function +Array_Example.Array_Func from DBI. However, by making the following relatively +painless additions, its not only possible, but extremely efficient. + +First, you need to create database object types that correspond to the record +and table types in the package. From the above example, these would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + +Now, assuming the existing function needs to remain unchanged (it is probably +being called from other PL/SQL code), we need to add a new function to the +package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + +As you can see, the new function is very simple. Now, it is a simple matter +of calling the function as a straight-forward SELECT from your DBI code. From +the above example, the code would look something like this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + +### __SYS.DBMS_SQL datatypes__ + +DBD::Oracle has built-in support for __SYS.DBMS_SQL.VARCHAR2_TABLE__ +and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +- __Note:__ + +- Take careful note that we use '\\@arr' here because the 'bind_param_inout' + will only take a reference to a scalar. + +### __ORA_VARCHAR2_TABLE__ + +SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. +( in bind_param() and bind_param_inout() ). When you bind array, you need +to specify full buffer size for OUT data. So, there are two parameters: +_max_len_ (specified as 3rd argument of bind_param_inout() ), +and _ora_maxarray_numentries_. They define maximum array entry length and +maximum rows, that can be passed to Oracle and back to you. In this +example we send array with 1 element with length=3, but allocate space for 100 +Oracle array entries with maximum length 10 of each. So, you can get no more +than 100 array entries with length <= 10. + +If you set _max_len_ to zero, maximum array entry length is calculated +as maximum length of entry of array bound. If 0 < _max_len_ < length( $some_element ), +truncation occur. + +If you set _ora_maxarray_numentries_ to zero, current (at bind time) bound +array length is used as maximum. If 0 < _ora_maxarray_numentries_ < scalar(@array), +not all array entries are bound. + +### __ORA_NUMBER_TABLE__ + +SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. +The main difference is internal data representation. Currently 2 types of +bind is allowed : as C-integer, or as C-double type. To select one of them, +you may specify additional bind parameter _ora_internal_type_ as either +__SQLT_INT__ or __SQLT_FLT__ for C-integer and C-double types. +Integer size is architecture-specific and is usually 32 or 64 bit. +Double is standard IEEE 754 type. + +_ora_internal_type_ defaults to double (SQLT_FLT). + +_max_len_ is ignored for OCI_NUMBER_TABLE. + +Currently, you cannot bind full native Oracle NUMBER(38). If you really need, +send request to dbi-dev list. + +The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + +If you change bind type to __SQLT_INT__, like: + + ora_internal_type => SQLT_INT + +you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + +## __bind_param_inout_array__ + +DBD::Oracle supports this undocumented feature of DBI. See [Returning A Value from an INSERT](#pod_Returning A Value from an INSERT) for an example. + +## __bind_param_array__ + + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + +Binds an array of values to a placeholder, so that each is used in turn by a call +to the [execute_array](#pod_execute_array) method. + +## __execute__ + + $rv = $sth->execute(@bind_values); + +Perform whatever processing is necessary to execute the prepared statement. + +## __execute_array__ + + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + +Execute a prepared statement once for each item in a passed-in hashref, or items that +were previously bound via the [bind_param_array](#pod_bind_param_array) method. See the DBI documentation +for more details. + +DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very +quickly. + +## __execute_for_fetch__ + + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + +Used internally by the [execute_array](#pod_execute_array) method, and rarely used directly. See the +DBI documentation for more details. + +## __fetchrow_arrayref__ + + $ary_ref = $sth->fetchrow_arrayref; + +Fetches the next row of data from the statement handle, and returns a reference to an array +holding the column values. Any columns that are NULL are returned as undef within the array. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +Note that the same array reference is returned for each fetch, so don't store the reference and +then use it after a later fetch. Also, the elements of the array are also reused for each row, +so take care if you want to take a reference to an element. See also [bind_columns](#pod_bind_columns). + +## __fetchrow_array__ + + @ary = $sth->fetchrow_array; + +Similar to the [fetchrow_arrayref](#pod_fetchrow_arrayref) method, but returns a list of column information rather than +a reference to a list. Do not use this in a scalar context. + +## __fetchrow_hashref__ + + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + +Fetches the next row of data and returns a hashref containing the name of the columns as the keys +and the data itself as the values. Any NULL value is returned as as undef value. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +The optional `$name` argument should be either `NAME`, `NAME_lc` or `NAME_uc`, and indicates +what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. + +## __fetchall_arrayref__ + + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + +Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the +statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, +the data read in so far will be returned. Because of this, you should always check `$sth->err` after +calling this method, unless [RaiseError](#pod_RaiseError) has been enabled. + +If `$slice` is an array reference, fetchall_arrayref uses the [fetchrow_arrayref](#pod_fetchrow_arrayref) method to fetch each +row as an array ref. If the `$slice` array is not empty then it is used as a slice to select individual +columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). + +With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. + +If `$slice` is a hash reference, fetchall_arrayref uses [fetchrow_hashref](#pod_fetchrow_hashref) to fetch each row as a hash reference. + +See the DBI documentation for a complete discussion. + +## __fetchall_hashref__ + + $hash_ref = $sth->fetchall_hashref( $key_field ); + +Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for +a full discussion. + +## __finish__ + + $rv = $sth->finish; + +Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed +when you have not fetched all the possible rows. + +## __rows__ + + $rv = $sth->rows; + +Returns the number of rows affected for updates, deletes and inserts and -1 for selects. + +## __bind_col__ + + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + +Binds a Perl variable and/or some attributes to an output column of a SELECT statement. +Column numbers count up from 1. You do not need to bind output columns in order to fetch data. + +NOTE: DBD::Oracle does not use the `$bind_type` to determine how to +bind the column; it uses what Oracle says the data type is. You can +however set a numeric bind type with the bind attributes +StrictlyTyped/DiscardString as these attributes are applied after the +column is retrieved. + +See the DBI documentation for a discussion of the optional parameters `\%attr` and `$bind_type` + +## __bind_columns__ + + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + +Calls the [bind_col](#pod_bind_col) method for each column in the SELECT statement, using the supplied list. + +## __dump_results__ + + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + +Fetches all the rows from the statement handle, calls `DBI::neat_list` for each row, and +prints the results to `$fh` (which defaults to `STDOUT`). Rows are separated by `$lsep` (which defaults +to a newline). Columns are separated by `$fsep` (which defaults to a comma). The `$maxlen` controls +how wide the output can be, and defaults to 35. + +This method is designed as a handy utility for prototyping and testing queries. Since it uses +"neat_list" to format and edit the string for reading by humans, it is not recommended +for data transfer applications. + +# STATEMENT HANDLE ATTRIBUTES + +## __NUM_OF_FIELDS__ (integer, read-only) + +Returns the number of columns returned by the current statement. A number will only be returned for +SELECT statements for INSERT, +UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NUM_OF_PARAMS__ (integer, read-only) + +Returns the number of placeholders in the current statement. + +## __NAME__ (arrayref, read-only) + +Returns an arrayref of column names for the current statement. This +method will only work for SELECT statements, for SHOW statements, and for +INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NAME_lc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to lower case. + +## __NAME_uc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to upper case. + +## __NAME_hash__ (hashref, read-only) + +Similar to the `NAME` attribute, but returns a hashref of column names instead of an arrayref. The names of the columns +are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. +This method returns undef if called before `execute()`. + +## __NAME_lc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __NAME_uc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __TYPE__ (arrayref, read-only) + +Returns an arrayref indicating the data type for each column in the statement. +This method returns undef if called before `execute()`. + +## __PRECISION__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. +The number indicates the precision for `NUMERIC` columns, the size in number of +characters for `CHAR` and `VARCHAR` columns, and for all other types of columns +it returns the number of _bytes_. +This method returns undef if called before `execute()`. + +## __SCALE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates the scale of the that column. The only type that will return a value is `NUMERIC`. +This method returns undef if called before `execute()`. + +## __NULLABLE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates if the column is nullable or not. 0 = not nullable, 1 = nullable, 2 = unknown. +This method returns undef if called before `execute()`. + +## __Database__ (dbh, read-only) + +Returns the database handle this statement handle was created from. + +## __ParamValues__ (hash ref, read-only) + +Returns a reference to a hash containing the values currently bound to placeholders. If the "named parameters" +type of placeholders are being used (such as ":foo"), then the keys of the hash will be the names of the +placeholders (without the colon). If the "dollar sign numbers" type of placeholders are being used, the keys of the hash will +be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, +starting at one and increasing for every placeholder. + +If this method is called before [execute](#pod_execute), the literal values passed in are returned. If called after +[execute](#pod_execute), then the quoted versions of the values are returned. + +## __ParamTypes__ (hash ref, read-only) + +Returns a reference to a hash containing the type names currently bound to placeholders. The keys +are the same as returned by the ParamValues method. The values are hashrefs containing a single key value +pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can +only be expressed by a Postgres type. The value is the internal number corresponding to the type originally +passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of +ParamTypes to be passed back to the [bind_param](#pod_bind_param) method. + +## __Statement__ (string, read-only) + +Returns the statement string passed to the most recent "prepare" method called in this database handle, even if that method +failed. This is especially useful where "RaiseError" is enabled and the exception handler checks $@ and sees that a `prepare` +method call failed. + +## __RowsInCache__ + +Returns the number of un-fetched rows in the cache for selects. + +# SCROLLABLE CURSORS + +Oracle supports the concept of a 'Scrollable Cursor' which is defined as a 'Result Set' where +the rows can be fetched either sequentially or non-sequentially. One can fetch rows forward, +backwards, from any given position or the n-th row from the current position in the result set. + +Rows are numbered sequentially starting at one and client-side caching of the partial or entire result set +can improve performance by limiting round trips to the server. + +Oracle does not support DML type operations with scrollable cursors so you are limited +to simple 'Select' operations only. As well you can not use this functionality with remote +mapped queries or if the LONG datatype is part of the select list. + +However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch methods. + +Only use scrollable cursors if you really have a good reason to. They do use up considerable +more server and client resources and have poorer response times than non-scrolling cursors. + +## Enabling Scrollable Cursors + +To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + +Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the +statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + +When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row +or you can still use any of the other fetch methods but with a poorer response time than if you used a +non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. + +## Scrollable Cursor Methods + +The following driver-specific methods are used with scrollable cursors. + +- ora_scroll_position + + $position = $sth->ora_scroll_position(); + +This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time +this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. +The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. + +- ora_fetch_scroll + + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + +Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset +value which will then determine the row that will be fetched. It returns the row as a list containing the field values. +Null fields are returned as _undef_ values in the list. + +The valid orientation constant and fetch offset values combination are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + +The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + +The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + +## Scrollable Cursor Usage + +Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + +and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll +method; + +- Fetching the Last Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +if the record set is large this could take some time. + +- Fetching the Current Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will still be 20 after this snippet. + +- Fetching the First Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the Next Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 5 after this snippet. + +- Fetching the Prior Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the 10th Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 10th to 14th Row + + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 14 after this snippet. + +- Fetching the 14th to 10th Row + + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 5th Row From the Present Position. + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 15 after this snippet. + +- Fetching the 9th Row Prior From the Present Position + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 6 after this snippet. + +- Use Finish + + $sth->finish(); + +When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of +cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. + +# LOBS AND LONGS + +The key to working with LOBs (CLOB, BLOBs) is to remember the value of an Oracle LOB column is not the content of the LOB. It's a +'LOB Locator' which, after being selected or inserted needs extra processing to read or write the content of the LOB. There are also legacy LONG types (LONG, LONG RAW, VARCHAR2) +which are presently deprecated by Oracle but are still in use. These LONG types do not utilize a 'LOB Locator' and also are more limited in +functionality than CLOB or BLOB fields. + +DBD::Oracle now offers three interfaces to LOB and LONG data, + +- [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) + +With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of +BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. + +- [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) + +With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. + +- [LOB Locator Method Interface](#pod_LOB Locator Method Interface) + +This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. + +Generally speaking the interface that you will chose will be dependent on what end you are trying to achieve. All have their benefits and +drawbacks. + +One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB column can be in one of three states; + +- NULL + +The table cell is created, but the cell holds no locator or value. +If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + +error when working with a LOB. + +You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + +- Empty + +A LOB instance with a locator exists in the cell, but it has no value. The length of the LOB is zero. In this case DBD::Oracle will return 'undef' for the field. + +- Populated + +A LOB instance with a locator and a value exists in the cell. You actually get the LOB value. + +## Data Interface for Persistent LOBs + +This is the original interface for LONG and LONG RAW datatypes and from Oracle 9iR1 and later the OCI API was extended to work directly with the other LOB datatypes. +In other words you can treat all LOB type data (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using the same techniques +you would use on other datatypes that store character or binary data. In some cases there are fewer round trips to the server as no 'LOB Locators' are +used, normally one can get an entire LOB is a single round trip. + +### Simple Fetch for LONGs and LONG RAWs + +As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG datatypes as a single large piece. +There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. +If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into +an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. + +For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the long1 fields but they will be truncated at 2MBs. + +### Using ora_ncs_buff_mtpl + +When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the +Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. +Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. + +However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer +value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes +but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes +(maybe less characters though) but you are using allot more memory that you need. + +You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can +also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. + +The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the +ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. + +If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + +This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) + +If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. + +This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. + +You can tune this value by setting ora_oci_success_warn which will display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + +In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. + +### Simple Fetch for CLOBs and BLOBs + +To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well +set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds +the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. + +For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this +and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. + +It seems with BLOBs you are not limited by the 64k. + +For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the lobs but they will be truncated at 2MBs. + +### Piecewise Fetch with Callback + +With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. +To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Simple Fetch for LONGs and LONG RAWs](#pod_Simple Fetch for LONGs and LONG RAWs) and [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is +dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. + +Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +#### Piecewise Fetch with Polling + +With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' +attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback). + +Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. + +Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +### Binding for Updates and Inserts for CLOBs and BLOBs + +To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method +'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + +So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. + +### Support for Remote LOBs; + +Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + +to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Below are the limitations of Remote LOBs; + +- Queries involving more than one database are not supported; + +so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + +as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + +- DDL commands are not supported; + +so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + +- Only binds and defines for data going into remote persistent LOBs are supported. + +so that parameter passing in PL/SQL where CHAR data is bound or defined for remote LOBs is not allowed . + +These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + +- If the remote object is a view such as + + CREATE VIEW v AS SELECT foo() FROM ... + +the following would not work: + + SELECT * FROM v@dbs2; + +- Limited PL/SQL parameter passing + +PL/SQL parameter passing is not allowed where the actual argument is a LOB type +and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. + +- RETURNING INTO does not support implicit conversions between CHAR and CLOB. + +so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + +## Locator Data Interface + +### Simple Usage + +When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob with the LongReadLen and LongTruncOk attributes. +The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +When inserting or updating LOBs some _major_ magic has to be performed +behind the scenes to make it transparent. Basically the driver has to +insert a 'LOB Locator' and then refetch the newly inserted LOB +Locator before being able to write the data into it. However, it works +well most of the time, and I've made it as fast as possible, just one +extra server-round-trip per insert or update after the first. For the +time being, only single-row LOB updates are supported. + +To insert or update a large LOB using a placeholder, DBD::Oracle has to +know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + +The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + +or use the corresponding integer values (112 and 113). + +One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has +to be able to tell which parameters relate to which table fields. +In all cases where it can possibly work it out for itself, it does, +however, if there are multiple LOB fields of the same type in the table +then you need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + +There are some limitations inherent in the way DBD::Oracle makes typical +LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + +The alternative is to disable the automatic LOB Locator processing. +If [ora_auto_lob](#pod_ora_auto_lob) is 0 in prepare(), you can fetch the LOB Locators and +do all the work yourself using the ora_lob_*() methods. +See the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) section below. + +### LOB support in PL/SQL + +LOB Locators can be passed to PL/SQL calls by binding them to placeholders +with the proper `ora_type`. If [ora_auto_lob](#pod_ora_auto_lob) is true, output LOB +parameters will be automatically returned as strings. + +If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), +strings can be bound to input LOB placeholders and will be automatically +converted to LOBs. + +Example: + # Build a large XML document, bind it as a CLOB, + # extract elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + +If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + +error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. +One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. + +## Persistent & Locator Interface Caveats + +Now that one has the option of using the Persistent or the Locator interface for LOBs the questions arises +which one to use. For starters, if you want to access LOBs over a dblink you will have to use the Persistent +interface so that choice is simple. The question of which one to use after that is a little more tricky. +It basically boils down to a choice between LOB size and speed. + +The Callback and Polling piecewise fetches are very very slow +when compared to the Simple and the Locator fetches but they can handle very large blocks of data. Given a situation where a +large LOB is to be read the Locator fetch may time out while either of the piecewise fetches may not. + +With the Simple fetch you are limited by physical memory of your server but it runs a little faster than the Locator, as there are fewer round trips +to the server. So if you have small LOBs and need to save a little bandwidth this is the one to use. It you are going after large LOBs then the Locator interface is the one to use. + +If you need to update more than a single row of with LOB data then the Persistent interface can do it while the Locator can't. + +If you encounter a situation where you have to access the legacy LOBs (LONG, LONG RAW) and the values are to large for you system then you can use +the Callback or Polling piecewise fetches to get all of the data. + +Not all of the Persistent interface has been implemented yet, the following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + +Most of the time you should just use the [Locator Data Interface](#pod_Locator Data Interface) as this is in one that has the best combination of speed and size. + +All this being said if you are doing some critical programming I would use the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) as this gives you very +fine grain control of your LOBs, of course the code for this will be somewhat more involved. + +## Data Interface for LOB Locators + +The following driver-specific methods let you manipulate "LOB Locators" directly. +To select a LOB locator directly set the if the `ora_auto_lob` +attribute to false, or alternatively they can be returned via PL/SQL procedure calls. + +(If using a DBI version earlier than 1.36 they must be called via the +func() method. Note that methods called via func() don't honour +RaiseError etc, and so it's important to check $dbh->err after each call. +It's recommended that you upgrade to DBI 1.38 or later.) + +Note that LOB locators are only valid while the statement handle that +created them is valid. When all references to the original statement +handle are lost, the handle is destroyed and the locators are freed. + +- ora_lob_read + + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + +Read a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobRead function. + +- ora_lob_write + + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + +Write/overwrite a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobWrite function. + +- ora_lob_append + + $rc = $dbh->ora_lob_append($lob_locator, $data); + +Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + +- ora_lob_trim + + $rc = $dbh->ora_lob_trim($lob_locator, $length); + +Trims the length of the LOB to $length. +Uses the Oracle OCILobTrim function. + +- ora_lob_length + + $length = $dbh->ora_lob_length($lob_locator); + +Returns the length of the LOB. +Uses the Oracle OCILobGetLength function. + +- ora_lob_is_init + + $is_init = $dbh->ora_lob_is_init($lob_locator); + +Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' +if there is an error. +Uses the Oracle OCILobLocatorIsInit function. + +- ora_lob_chunk_size + + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + +Returns the chunk size of the LOB. +Uses the Oracle OCILobGetChunkSize function. + +For optimal performance, Oracle recommends reading from and +writing to a LOB in batches using a multiple of the LOB chunk size. +In Oracle 10g and before, when all defaults are in place, this +chunk size defaults to 8k (8192). + +### LOB Locator Method Examples + +_Note:_ Make sure you first read the note in the section above about +multi-byte character set issues with these methods. + +The following examples demonstrate the usage of LOB Locators +to read, write, and append data, and to query the size of +large data. + +The following examples assume a table containing two large +object columns, one binary and one character, with a primary +key column, defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + +It also assumes a sequence for use in generating unique +lob_id field values, defined as follows: + + CREATE SEQUENCE lob_example_seq + +### Example: Inserting a new row with large data + +Unless enough memory is available to store and bind the +entire LOB data for insert all at once, the LOB columns must +be written interactively, piece by piece. In the case of a new row, +this is performed by first inserting a row, with empty values in +the LOB columns, then modifying the row by writing the large data +interactively to the LOB columns using their LOB locators as handles. + +The insert statement must create token values in the LOB +columns. Here, we use the empty string for both the binary +and character large object columns 'bindata' and 'chardata'. + +After the INSERT statement, a SELECT statement is used to +acquire LOB locators to the 'bindata' and 'chardata' fields +of the newly inserted row. Because these LOB locators are +subsequently written, they must be acquired from a select +statement containing the clause 'FOR UPDATE' (LOB locators +are only valid within the transaction that fetched them, so +can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + +In this example we demonstrate the use of ora_lob_write() +interactively to append data to the columns 'bin_data' and +'char_data'. Had we used ora_lob_append(), we could have +saved ourselves the trouble of keeping track of the offset +into the lobs. The snippet of code beneath the comment +'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + +The scalar variables $offset and $length are no longer +needed, because ora_lob_append() keeps track of the offset +for us. + +### Example: Updating an existing row with large data + +In this example, we demonstrate a technique for overwriting +a portion of a blob field with new binary data. The blob +data before and after the section overwritten remains +unchanged. Hence, this technique could be used for updating +fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + +After running this code, the row where lob_id = 5 will +contain, starting at position 100234 in the bin_data column, +the string "This string will overwrite a portion of the blob". + +### Example: Streaming character data from the database + +In this example, we demonstrate a technique for streaming +data from the database to a file handle, in this case +STDOUT. This allows more data to be read in and written out +than could be stored in memory at a given time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + +Notice that the select statement does not contain the phrase +"FOR UPDATE". Because we are only reading from the LOB +Locator returned, and not modifying the LOB it refers to, +the select statement does not require the "FOR UPDATE" +clause. + +A word of caution when using the data returned from an ora_lob_read in a conditional statement. +for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + +was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return +the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte +as $data will contain 0 which PERL will see as false and not print it out. + +### Example: Truncating existing large data + +In this example, we truncate the data already present in a +large object column in the database. Specifically, for each +row in the table, we truncate the 'bindata' value to half +its previous length. + +After acquiring a LOB Locator for the column, we query its +length, then we trim the length by half. Because we modify +the large objects with the call to ora_lob_trim(), we must +select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +# SPACES AND PADDING + +## Trailing Spaces + +Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder +values and uses Nonpadded Comparison Semantics with the result. +This causes trouble if the spaces are needed for +comparison with a CHAR value or to prevent the value from +becoming '' which Oracle treats as NULL. +Look for Blank-padded Comparison Semantics and Nonpadded +Comparison Semantics in Oracle's SQL Reference or Server +SQL Reference for more details. + +To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, +either change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or the placeholder +type for a particular call to L or L +with [ora_type](#pod_ora_type) or `TYPE`. +Using [ORA_CHAR](http://search.cpan.org/perldoc?ORA_CHAR) with [ora_type](http://search.cpan.org/perldoc?ora_type) or `SQL_CHAR` with `TYPE` +allows the placeholder to be used with Padded Comparison Semantics +if the value it is being compared to is a CHAR, NCHAR, or literal. + +Please remember that using spaces as a value or at the end of +a value makes visually distinguishing values with different +numbers of spaces difficult and should be avoided. + +Oracle Clients that use OCI 9.2 do not strip trailing spaces. + +## Padded Char Fields + +Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. +As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will +have to change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or placeholder +type for a particular call with L or L +with [ORA_CHAR](#pod_ORA_CHAR). + +# UNICODE + +DBD::Oracle now supports Unicode UTF-8. There are, however, a number +of issues you should be aware of, so please read all this section +carefully. + +In this section we'll discuss "Perl and Unicode", then "Oracle and +Unicode", and finally "DBD::Oracle and Unicode". + +Information about Unicode in general can be found at: +[http://www.unicode.org/](http://www.unicode.org/). It is well worth reading because there are +many misconceptions about Unicode and you may be holding some of them. + +## Perl and Unicode + +Perl began implementing Unicode with version 5.6, but the implementation +did not mature until version 5.8 and later. If you plan to use Unicode +you are _strongly_ urged to use Perl 5.8.2 or later and to _carefully_ read +the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + +And then read it again. + +Perl's internal Unicode format is UTF-8 +which corresponds to the Oracle character set called AL32UTF8. + +## Oracle and Unicode + +Oracle supports many characters sets, including several different forms +of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + +When you create an Oracle database, you must specify the DATABASE +character set (used for DDL, DML and CHAR datatypes) and the NATIONAL +character set (used for NCHAR and NCLOB types). +The character sets used in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + +The Oracle 9.2 and later default for the national character set is AL16UTF16. +The default for the database character set is often US7ASCII. +Although many experienced DBAs will consider an 8bit character set like +WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle +other than US7ASCII, requires that the NLS_LANG environment variable be set. +See the L<"Oracle UTF8 is not UTF-8"> section below. + +You are strongly urged to read the Oracle Internationalization documentation +specifically with respect the choices and trade offs for creating +a databases for use with international character sets. + +Oracle uses the NLS_LANG environment variable to indicate what +character set is being used on the client. When fetching data Oracle +will convert from whatever the database character set is to the client +character set specified by NLS_LANG. Similarly, when sending data to +the database Oracle will convert from the character set specified by +NLS_LANG to the database character set. + +The NLS_NCHAR environment variable can be used to define a different +character set for 'national' (NCHAR) character types. + +Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. +For example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + +## Oracle UTF8 is not UTF-8 + +AL32UTF8 should be used in preference to UTF8 if it works for you, +which it should for Oracle 9.2 or later. If you're using an old +version of Oracle that doesn't support AL32UTF8 then you should +avoid using any Unicode characters that require surrogates, in other +words characters beyond the Unicode BMP (Basic Multilingual Plane). + +That's because the character set that Oracle calls "UTF8" doesn't +conform to the UTF-8 standard in its handling of surrogate characters. +Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". +Here are a couple of extracts from [http://www.unicode.org/reports/tr26/](http://www.unicode.org/reports/tr26/): + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + +Oracle uses this internally because it collates (sorts) in the same order +as UTF16, which is the basis of Oracle's internal collation definitions. + +Rather than change UTF8 for clients Oracle chose to define a new character +set called "AL32UTF8" which does conform to the UTF-8 standard. +(The AL32UTF8 character set can't be used on the server because it +would break collation.) + +Because of that, for the rest of this document we'll use "AL32UTF8". +If you're using an Oracle version below 9.2 you'll need to use "UTF8" +until you upgrade. + +## DBD::Oracle and Unicode + +DBD::Oracle Unicode support has been implemented for Oracle versions 9 +or greater, and Perl version 5.6 or greater (though we _strongly_ +suggest that you use Perl 5.8.2 or later). + +You can check which Oracle version your DBD::Oracle was built with by +importing the `ORA_OCI` constant from DBD::Oracle. + +__Fetching Data__ + +Any data returned from Oracle to DBD::Oracle in the AL32UTF8 +character set will be marked as UTF-8 to ensure correct handling by Perl. + +For Oracle to return data in the AL32UTF8 character set the +NLS_LANG or NLS_NCHAR environment variable _must_ be set as described +in the previous section. + +When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR +is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + +When fetching other character data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + +__Sending Data using Placeholders__ + +Data bound to a placeholder is assumed to be in the default client +character set (specified by NLS_LANG) except for a few special +cases. These are listed here with the highest precedence first: + +If the `ora_csid` attribute is given to bind_param() then that +is passed to Oracle and takes precedence. + +If the value is a Perl Unicode string (UTF-8) then DBD::Oracle +ensures that Oracle uses the Unicode character set, regardless of +the NLS_LANG and NLS_NCHAR settings. + +If the placeholder is for inserting an NCLOB then the client NLS_NCHAR +character set is used. (That's useful but inconsistent with the other behaviour +so may change. Best to be explicit by using the `ora_csform` +attribute.) + +If the `ora_csform` attribute is given to bind_param() then that +determines if the value should be assumed to be in the default +(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + +or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + +Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to +insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert +will still happen but a error code of 0 will be returned with the following warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + +The warning will report the parameter number and the NCHAR setting that the query is running. + +__Sending Data using SQL__ + +Oracle assumes the SQL statement is in the default client character +set (as specified by NLS_LANG). So Unicode strings containing +non-ASCII characters should not be used unless the default client +character set is AL32UTF8. + +## DBD::Oracle and Other Character Sets and Encodings + +The only multi-byte Oracle character set supported by DBD::Oracle is +"AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +# OBJECT & COLLECTION DATA TYPES + +Oracle databases allow for the creation of object oriented like user-defined types. +There are two types of objects, Embedded--an object stored in a column of a regular table +and REF--an object that uses the REF retrieval mechanism. + +DBD::Oracle supports only the 'selection' of embedded objects of the following types OBJECT, VARRAY +and TABLE in any combination. Support is seamless and recursive, meaning you +need only supply a simple SQL statement to get all the values in an embedded object. +You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. + +Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + +The code to access all the data in the table could be something like this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + +Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. + +As stated before DBD::Oracle will automatically drill into the embedded object and extract +all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an +SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + +The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + +Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + +The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + +So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables +nested to 10 levels. + +Any NULL values found in the embedded object will be returned as 'undef'. + +# OTHER DATA TYPES + +DBD::Oracle does not _explicitly_ support most Oracle datatypes. +It simply asks Oracle to return them as strings and Oracle does so. +Mostly. Similarly when binding placeholder values DBD::Oracle binds +them as strings and Oracle converts them to the appropriate type, +such as DATE, when used. + +Some of these automatic conversions to and from strings use NLS +settings to control the formatting for output and the parsing for +input. The most common example is the DATE type. The default NLS +format for DATE might be DD-MON-YYYY and so when a DATE type is +fetched that's how Oracle will format the date. NLS settings also +control the default parsing of strings into DATE values. An error +will be generated if the contents of the string don't match the +NLS format. If you're dealing in dates which don't match the default +NLS format then you can either change the default NLS format or, more +commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") +to explicitly specify formats for converting to and from strings. + +A slightly more subtle problem can occur with NUMBER types. The +default NLS settings might format numbers with a fullstop ("`.`") +to separate thousands and a comma ("`,`") as the decimal point. +Perl will generate warnings and use incorrect values when numbers, +returned and formatted as strings in this way by Oracle, are used +in a numeric context. You could explicitly convert each numeric +value using the TO_CHAR(...) function but that gets tedious very +quickly. The best fix is to change the NLS settings. That can be +done for an individual connection by doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + +There are some types, like BOOLEAN, that Oracle does not automatically +convert to or from strings (pity). These need to be converted +explicitly using SQL or PL/SQL functions. + +Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + +#### Support for Insert of XMLType (ORA_XMLTYPE) + +Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special +requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For +example with a table like this; + + create table books (book_id number, book_xml XMLType); + +one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + +In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. +This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. + +#### Binding Cursors + +Cursors can be returned from PL/SQL blocks, either from stored +functions (or procedures with OUT parameters) or +from direct `OPEN` statements, as shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +The only special requirement is the use of `bind_param_inout()` with an +attribute hash parameter that specifies `ora_type` as `ORA_RSET`. +If you don't do that you'll get an error from the `execute()` like: +"ORA-06550: line X, column Y: PLS-00306: wrong number or types of +arguments in call to ...". + +Here's an alternative form using a function that returns a cursor. +This example uses the pre-defined weak (or generic) REF CURSOR type +SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +A cursor obtained from PL/SQL as above may be passed back to PL/SQL +by binding for input, as shown in this example, which explicitly +closes a cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + +It is not normally necessary to close a cursor +explicitly in this way. Oracle will close the cursor automatically +at the first client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to +the cursor handle from the PL/SQL statement handle delays the destruction +of the cursor handle for too long. This reference remains until the +PL/SQL handle is re-bound, re-executed or destroyed. + +See the `curref.pl` script in the Oracle.ex directory in the DBD::Oracle +source distribution for a complete working example. + +#### Fetching Nested Cursors + +Oracle supports the use of select list expressions of type REF CURSOR. +These may be explicit cursor expressions - `CURSOR(SELECT ...)`, or +calls to PL/SQL functions which return REF CURSOR values. The values +of these expressions are known as nested cursors. + +The value returned to a Perl program when a nested cursor is fetched +is a statement handle. This statement handle is ready to be fetched from. +It should not (indeed, must not) be executed. + +Oracle imposes a restriction on the order of fetching when nested +cursors are used. Suppose `$sth1` is a handle for a select statement +involving nested cursors, and `$sth2` is a nested cursor handle fetched +from `$sth1`. `$sth2` can only be fetched from while `$sth1` is +still active, and the row containing `$sth2` is still current in `$sth1`. +Any attempt to fetch another row from `$sth1` renders all nested cursor +handles previously fetched from `$sth1` defunct. + +Fetching from such a defunct handle results in an error with the message +`ERROR nested cursor is defunct (parent row is no longer current)`. + +This means that the `fetchall...` or `selectall...` methods are not useful +for queries returning nested cursors. By the time such a method returns, +all the nested cursor handles it has fetched will be defunct. + +It is necessary to use an explicit fetch loop, and to do all the +fetching of nested cursors within the loop, as the following example +shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + +The cursor returned by the function `sp_ListEmp` defined in the +previous section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + +#### Pre-fetching Nested Cursors + +By default, DBD::Oracle pre-fetches rows in order to reduce the number of +round trips to the server. For queries which do not involve nested cursors, +the number of pre-fetched rows is controlled by the DBI database handle +attribute `RowCacheSize` (q.v.). + +In Oracle, server side open cursors are a controlled resource, limited in +number, on a per session basis, to the value of the initialization +parameter `OPEN_CURSORS`. Nested cursors count towards this limit. +Each nested cursor in the current row counts 1, as does +each nested cursor in a pre-fetched row. Defunct nested cursors do not count. + +An Oracle specific database handle attribute, `ora_max_nested_cursors`, +further controls pre-fetching for queries involving nested cursors. For +each statement handle, the total number of nested cursors in pre-fetched +rows is limited to the value of this parameter. The default value +is 0, which disables pre-fetching for queries involving nested cursors. + +# PL/SQL Examples + +Most of these PL/SQL examples come from: Eric Bartley . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + +You can find more examples in the t/plsql.t file in the DBD::Oracle +source directory. + +Oracle 9.2 appears to have a bug where a variable bound +with bind_param_inout() that isn't assigned to by the executed +PL/SQL block may contain garbage. +See [http://www.mail-archive.com/dbi-users@perl.org/msg18835.html](http://www.mail-archive.com/dbi-users@perl.org/msg18835.html) + +## Avoid Using "SQL Call" + +Avoid using the "SQL Call" statement with DBD:Oracle as you might find that +DBD::Oracle will not raise an exception in some case. Specifically if you use +"SQL Call" to run a procedure all "No data found" exceptions will be quietly +ignored and returned as null. According to Oracle support this is part of the same +mechanism where; + + select (select * from dual where 0=1) from dual + +returns a null value rather than an exception. + +# CONTRIBUTING + +If you'd like DBD::Oracle to do something new or different the best way +to make that happen is to do it yourself and email to dbi-dev@perl.org a +patch of the source code (using 'diff' - see below) that shows the changes. + +## How to create a patch using Subversion + +The DBD::Oracle source code is maintained using Subversion (a replacement +for CVS, see [http://subversion.tigris.org/](http://subversion.tigris.org/)). To access the source +you'll need to install a Subversion client. Then, to get the source +code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + +If it prompts for a username and password use your perl.org account +if you have one, else just 'guest' and 'guest'. The source code will +be in a new subdirectory called `trunk`. + +To keep informed about changes to the source you can send an empty email +to dbd-oracle-changes-subscribe@perl.org after which you'll get an email with the +change log message and diff of each change checked-in to the source. + +After making your changes you can generate a patch file, but before +you do, make sure your source is still upto date using: + + svn update + +If you get any conflicts reported you'll need to fix them first. +Then generate the patch file from within the `trunk` directory using: + + svn diff > foo.patch + +Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. + +## How to create a patch without Subversion + +Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + +Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + +Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you want. + +Test your changes and then remove all temporary files: + + make test && make distclean + +Go back to the directory you originally unpacked the distribution: + + cd .. + +Unpack _another_ copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + +Then create a patch file by performing a recursive `diff` on the two +top level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + +## Speak before you patch + +For anything non-trivial or possibly controversial it's a good idea +to discuss (on dbi-dev@perl.org) the changes you propose before +actually spending time working on them. Otherwise you run the risk +of them being rejected because they don't fit into some larger plans +you may not be aware of. + +## GitHub repository + +A git mirror of the subversion is also available at +`https://github.com/yanick/DBD-Oracle`. + +# Oracle Related Links + +# WHICH VERSION OF DBD::ORACLE IS FOR ME? + +From version 1.25 onwards DBD::Oracle only support Oracle clients +9.2 or greater. Support for ProC connections was dropped in 1.29. + +If you are still stuck with an older version of Oracle or its client you might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + +As there are dozens of different versions of Oracle's clients this +list does not include all of them, just the major released versions of +Oracle. + +Note that one can still connect to any Oracle version with the older +DBD::Oracle versions the only problem you will have is that some of +the newer OCI and Oracle features available in later DBD::Oracle +releases will not be available to you. + +So to make a short story a little longer: + +- 1 + +If you are using Oracle 7 or early 8 DB and you can manage to get a 9 client and you can use +any DBD::Oracle version. + +- 2 + +If you have to use an Oracle 7 client then DBD::Oracle 1.17 should work + +- 3 + +Same thing for 8 up to R2, use 1.17, if you are lucky and have the right patch-set you might +go with 1.18. + +- 4 + +For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. Again this depends on your +patch-set, If you run into trouble go with 1.19 + +- 5 + +After 9.2 you can use any version you want. + +- 6 + +It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go back to 7 +and even get to 10. I am not sure what the 11g client can connect to. + +# BUGS AND LIMITATIONS + +There is a known problem with the 11.2g Oracle client and the +`DBMS_LOB.GETLENGTH()` PL/SQL function. +See [https://rt.cpan.org/Public/Bug/Display.html?id=69350](https://rt.cpan.org/Public/Bug/Display.html?id=69350) for the details. + +# SEE ALSO + +- [DBI](http://search.cpan.org/perldoc?DBI) + +http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in +the DBD::Oracle source distribution including the examples in the +Oracle.ex directory + +- DBD::Oracle Tutorial + +http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-oracle.html + +- Oracle Instant Client + +http://www.oracle.com/technology/tech/oci/instantclient/index.html + +- Oracle on Linux + +http://www.ixora.com.au/ + +- Free Oracle Tools and Links + +ora_explain supplied and installed with DBD::Oracle. + +http://www.orafaq.com/ + +http://vonnieda.org/oracletool/ + +- Commercial Oracle Tools and Links + +Assorted tools and references for general information. +No recommendation implied. + +http://www.platinum.com + +http://www.SoftTreeTech.com + +Also PL/Vision from RevealNet and Steven Feuerstein, and +"Q" from Savant Corporation. + +# AUTHORS + +DBI by Tim Bunce [http://www.tim.bunce.name](http://www.tim.bunce.name). + +The original `DBD::Oracle` was by Tim Bunce. +Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the +auspice of the Pythian Group ([http://www.pythian.com](http://www.pythian.com)). + +# ACKNOWLEDGEMENTS + +A great many people have helped with DBD::Oracle over the 17 years +between 1994 and 2011. Far too many to name, but we thank them all. +Many are named in the Changes file. + +# COPYRIGHT + +The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. +The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The Pythian Group). Canada. +The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. + +The DBD::Oracle module is free open source software; you can +redistribute it and/or modify it under the same terms as Perl 5. + +# AUTHORS + +- * + +Tim Bunce + +- * + +John Scoles + +- * + +Yanick Champoux + +# COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/dist.ini b/dist.ini deleted file mode 100644 index 013f79fc..00000000 --- a/dist.ini +++ /dev/null @@ -1,22 +0,0 @@ -name = DBD-Oracle -author = Tim Bunce -author = John Scoles -author = Yanick Champoux -license = Perl_5 -copyright_holder = Tim Bunce -copyright_year = 1994 - -version = 1.38 - -[Authority] -authority=cpan:PYTHIAN - -[MakeMaker::Custom] - -[@Filter] --bundle=@YANICK --remove=Author::YANICK::NextSemanticVersion --remove=ModuleBuild --remove=Authority --remove=Signature - diff --git a/err_bind/err_bind_param_inout_overrun_bug.msg b/err_bind/err_bind_param_inout_overrun_bug.msg deleted file mode 100644 index 83d9001f..00000000 --- a/err_bind/err_bind_param_inout_overrun_bug.msg +++ /dev/null @@ -1,108 +0,0 @@ -From dbi-users-return-215-Tim.Bunce=ig.co.uk@perl.org Mon Feb 5 23:03:29 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id XAA01289; Mon, 5 Feb 2001 23:03:27 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <06769-16@oink>; Fri, 6 Feb 1970 00:01:15 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 981413584:20:24069:0; Mon, 05 Feb 2001 22:53:04 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-2.mail.demon.net - id aa2024004; 5 Feb 2001 22:53 GMT -Received: (qmail 6267 invoked by uid 508); 5 Feb 2001 22:52:23 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6247 invoked from network); 5 Feb 2001 22:52:22 -0000 -Received: from seeme.dare.feddata.com (38.186.101.66) by tmtowtdi.perl.org - with SMTP; 5 Feb 2001 22:52:22 -0000 -Received: by seeme.dare.feddata.com; id OAA05466; - Mon, 5 Feb 2001 14:55:56 -0800 (PST) -Received: from ifyou.dare.feddata.com(38.186.101.111) by seeme.dare.feddata.com - via smap (4.1) id xma005448; Mon, 5 Feb 01 14:55:39 -0800 -Sender: oscar@dare.feddata.com -Message-ID: <3A7F2FB0.A1507582@pasadena.feddata.com> -Date: Mon, 05 Feb 2001 14:56:48 -0800 -From: Oscar DeMartino -Organization: Federal Data Corporation -X-Mailer: Mozilla 4.61 [en] (X11; U; SunOS 5.6 sun4u) -X-Accept-Language: en -MIME-Version: 1.0 -To: dbi-users@perl.org -Subject: Undetected error - Binding and Stored Procedures -Content-Type: multipart/alternative; - boundary="------------E1028F7A8304BE268EB8F67B" -Status: RO -Content-Length: 2042 -Lines: 66 - ---------------E1028F7A8304BE268EB8F67B -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -I am running Oracle 8.1.5 and am using many stored procedures. We -use returned cursors, and individual values. The problem is, when -a stored procedure is executed and the specified bound variable has not -be declared large enough to hold the returned value subsequent -bound variables do not get set and I cannot find any way to -automatically detect this. - -Example: - -The stored procedure takes 1-input value and returns three string -values. - -the stored procedure is prepared , so I get the statement handle. - -I bind the input variable, and then bind the three output variables (1, -2, & 3) -as 100 character strings. - -I then execute the statment handle. - -There do not appear to be any errors, after checking the returned value -(for the execute call), -and ->err and ->errstr are clean. - -variable 1 has the correct returned value. -BUT, output variable 2 & 3, have no value. - ------- -Executing the stored procedure using sqlplus (sql command line -interface) indicated: - -What really occured is that the returned output variables 1 & 3 were -under 100 characters long -output variable 2 was 120 characters long - ---------- - -I know I could make all output variables the max size allowed in the -database field -but this would seem to waste space in the perl code. Since the field in - -the database -is simply defined as a varchar2 with no size limitation (upto 32767). - ------ -Am I missing something about detecting that variables 2 & 3 did not get -stored correctly -by DBI::Oracle?? - - - --- -Oscar "Fred" DeMartino FFFFF DDDD CCC -320 N. Halstead Ave. Ste #160 F D D C C -Pasadena, CA 91107 FFF D D C -e-mail: Oscar.DeMartino@pasadena.feddata.com F D D C -Phone: (626)306-6649 F D D C C -Federal Data Corporation F DDDD CCC - - - ---------------E1028F7A8304BE268EB8F67B-- - diff --git a/err_bind/err_bindarrays.msg b/err_bind/err_bindarrays.msg deleted file mode 100644 index 8ca7a5d3..00000000 --- a/err_bind/err_bindarrays.msg +++ /dev/null @@ -1,241 +0,0 @@ -From cturner@redhat.com Tue Mar 27 06:01:56 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id GAA19714; Tue, 27 Mar 2001 06:01:56 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <13771-3@oink>; - Fri, 27 Mar 1970 06:00:50 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985668014:20:27605:3; Tue, 27 Mar 2001 04:40:14 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ab2125244; 27 Mar 2001 4:39 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id XAA32289 - for ; Mon, 26 Mar 2001 23:39:38 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2R4bvT12929; Mon, 26 Mar 2001 23:37:57 -0500 -Sender: cturner@redhat.com -To: Tim.Bunce@ig.co.uk -Subject: DBD::Oracle and OCI bound arrays -From: Chip Turner -Date: 26 Mar 2001 23:37:57 -0500 -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 980 -Lines: 29 - - -Hey Tim, - -The need to have true OCI bound arrays for DBD::Oracle has come up, -and it looks like I get the fun job of implementing them. Basically, -this will allow DBD::Oracle to do something the DCOracle python -library does. The idea is: - -my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -my @c1 = 'aa' .. 'zz'; -my @c2 = 'aaa' .. 'azz'; -$sth->execute(\@c1, \@c2); - -In other words, it populates the table with a single execute call, -passing two (or more) equally sized arrays in as references for bound -parameters. This has the potential to save a good amount of time, -especially for large datasets. - -This would pretty much be a proprietary extension for Oracle, though -similar uses could be done in other DBD's. - -Just thought I'd let you know what I was intending to do, and to see -if you had any interest in receiving it as a patch after I'm done. - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Tue Mar 27 09:29:48 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id JAA20809; Tue, 27 Mar 2001 09:29:42 +0100 (BST) -Date: Tue, 27 Mar 2001 09:29:41 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim.Bunce@ig.co.uk, dbi-dev@perl.org -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010327092941.D20616@ig.co.uk> -References: -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Mon, Mar 26, 2001 at 11:37:57PM -0500 -Content-Length: 1570 -Lines: 39 - -On Mon, Mar 26, 2001 at 11:37:57PM -0500, Chip Turner wrote: -> -> Hey Tim, -> -> The need to have true OCI bound arrays for DBD::Oracle has come up, -> and it looks like I get the fun job of implementing them. Basically, -> this will allow DBD::Oracle to do something the DCOracle python -> library does. The idea is: -> -> my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -> my @c1 = 'aa' .. 'zz'; -> my @c2 = 'aaa' .. 'azz'; -> $sth->execute(\@c1, \@c2); -> -> In other words, it populates the table with a single execute call, -> passing two (or more) equally sized arrays in as references for bound -> parameters. This has the potential to save a good amount of time, -> especially for large datasets. -> -> This would pretty much be a proprietary extension for Oracle, though -> similar uses could be done in other DBD's. -> -> Just thought I'd let you know what I was intending to do, and to see -> if you had any interest in receiving it as a patch after I'm done. - -I would *urge* you to discuss the implementation with me *before* -you get very far cutting code. - -And anyway, I think someone's already done much or all of the work. -Dig around in the dbi-dev archives. If you can't find the discussion -let me know. If you do, then ask them (via the dbi-dev list) what -the status is. - -I'm planning to make a DBI release next week and, hopefully, a -DBD::Oracle release the week after to cleare a backlog of patches I -have queued up. After that I'll be looking to add in the work of the -other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -Tim. - -From cturner@redhat.com Wed Mar 28 02:01:21 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id CAA27336; Wed, 28 Mar 2001 02:01:21 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <17151-9@oink>; - Sat, 28 Mar 1970 01:59:47 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985739868:20:27318:0; Wed, 28 Mar 2001 00:37:48 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ac2119835; 28 Mar 2001 0:37 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id TAA10445 - for ; Tue, 27 Mar 2001 19:37:35 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2S0ZoJ20115; Tue, 27 Mar 2001 19:35:50 -0500 -Sender: cturner@redhat.com -To: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -References: <20010327092941.D20616@ig.co.uk> -From: Chip Turner -Date: 27 Mar 2001 19:35:50 -0500 -In-Reply-To: <20010327092941.D20616@ig.co.uk> -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 1495 -Lines: 35 - -Tim Bunce writes: - -> I would *urge* you to discuss the implementation with me *before* -> you get very far cutting code. - -Unfortunately, it's a little late for this; I've mostly finished the -change (at least, enough for our needs), except for some review and -cleanups. It seems to work quite well (400 times faster than repeated -looping over a dataset) and passes all of DBD::Oracle's test suite. - -> And anyway, I think someone's already done much or all of the work. -> Dig around in the dbi-dev archives. If you can't find the discussion -> let me know. If you do, then ask them (via the dbi-dev list) what -> the status is. - -I checked as you suggest, but couldn't find any code, just discussion -of it. I'll check again, but it didn't seem that the person had put -it anywhere I could get at it. - -> I'm planning to make a DBI release next week and, hopefully, a -> DBD::Oracle release the week after to cleare a backlog of patches I -> have queued up. After that I'll be looking to add in the work of the -> other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -If you would like, the patch will probably be suitable for inclusion -by then, if you want it in by the next release. Should there be any -problems with it or its implementation, I'd be glad to clean it up if -you have interest in it (if not, that's cool too; we need it soon, -though, either way). - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Wed Mar 28 11:51:58 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id LAA00444; Wed, 28 Mar 2001 11:51:51 +0100 (BST) -Date: Wed, 28 Mar 2001 11:51:51 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010328115151.D29769@ig.co.uk> -References: <20010327092941.D20616@ig.co.uk> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Tue, Mar 27, 2001 at 07:35:50PM -0500 -Content-Length: 1786 -Lines: 40 - -On Tue, Mar 27, 2001 at 07:35:50PM -0500, Chip Turner wrote: -> Tim Bunce writes: -> -> > I would *urge* you to discuss the implementation with me *before* -> > you get very far cutting code. -> -> Unfortunately, it's a little late for this; I've mostly finished the -> change (at least, enough for our needs), except for some review and -> cleanups. It seems to work quite well (400 times faster than repeated -> looping over a dataset) and passes all of DBD::Oracle's test suite. - -I trust you've added some more tests for your new functionality! - -> > And anyway, I think someone's already done much or all of the work. -> > Dig around in the dbi-dev archives. If you can't find the discussion -> > let me know. If you do, then ask them (via the dbi-dev list) what -> > the status is. -> -> I checked as you suggest, but couldn't find any code, just discussion -> of it. I'll check again, but it didn't seem that the person had put -> it anywhere I could get at it. - -You could always ask them (CC me). - -> > I'm planning to make a DBI release next week and, hopefully, a -> > DBD::Oracle release the week after to cleare a backlog of patches I -> > have queued up. After that I'll be looking to add in the work of the -> > other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). -> -> If you would like, the patch will probably be suitable for inclusion -> by then, if you want it in by the next release. Should there be any -> problems with it or its implementation, I'd be glad to clean it up if -> you have interest in it (if not, that's cool too; we need it soon, -> though, either way). - -Thanks for the clean-up offer. Send it to me after I make the next -DBD::Oracle release (as a fresh patch over that version please - but -there shouldn't be too many changes). - -Tim. - diff --git a/err_bind/err_bindclobleak.msg b/err_bind/err_bindclobleak.msg deleted file mode 100644 index 1a31c760..00000000 --- a/err_bind/err_bindclobleak.msg +++ /dev/null @@ -1,58 +0,0 @@ -From PGWeiss@arity.com Thu Mar 9 09:51:45 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id JAA14948; Thu, 9 Mar 2000 09:51:43 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <27566-0@oink>; Mon, 9 Mar 1970 10:51:10 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 952595299:20:10439:68; Thu, 09 Mar 2000 09:48:19 GMT -Received: from image.arity.com ([140.239.104.130]) by punt-2.mail.demon.net - id aa2010598; 9 Mar 2000 9:47 GMT -Received: by image.arity.com with Internet Mail Service (5.5.2650.21) - id ; Thu, 9 Mar 2000 04:51:44 -0500 -Message-ID: -From: "Paul G. Weiss" -To: Perl-Win32-Database Mailing List , - "'Tim Bunce'" -Subject: Another CLOB related DBD::Oracle bug -Date: Thu, 9 Mar 2000 04:51:41 -0500 -MIME-Version: 1.0 -X-Mailer: Internet Mail Service (5.5.2650.21) -Content-Type: text/plain; charset="iso-8859-1" -Status: RO -Content-Length: 689 -Lines: 32 - -Binding a parameter to type ORA_CLOB causes a leak. -Consider: - -for (1..10000) -{ - for (1..100) - { - my $sth = $db->prepare('update item set descr = ? where id = ?'); - if ($leak) - { - $sth->bind_param(1, $descr, {ora_type => ORA_CLOB, -ora_field=>'DESCR'}); - $sth->bind_param(2, 12); - $sth->execute; - } - else - { - $sth->execute($descr,12); - } - } - sleep 1; -} - - -With $leak set to 1, i.e. binding the parameters explicitly the -program leaks. With $leak set to 0 it does not (but then I can't -set descr to anything greater than 4K nor can I set it to the -empty string). - -Is there a patch? - --P - diff --git a/err_bind/err_bindnullhash.msg b/err_bind/err_bindnullhash.msg deleted file mode 100644 index d9a98b9a..00000000 --- a/err_bind/err_bindnullhash.msg +++ /dev/null @@ -1,77 +0,0 @@ -From dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org Thu Jul 11 17:49:35 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g6BGnYH11008 - for ; Thu, 11 Jul 2002 17:49:34 +0100 (BST) - (envelope-from dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 11 Jul 2002 17:49:34 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1026401921:10:09249:41; Thu, 11 Jul 2002 15:38:41 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1124337; 11 Jul 2002 15:38 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id B567C2BF65 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 347792BF62 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Received: (qmail 95914 invoked by uid 1005); 11 Jul 2002 15:38:04 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 95896 invoked by uid 76); 11 Jul 2002 15:38:04 -0000 -Received: from ironmail1.cc.lehigh.edu (HELO ironmail1.cc.lehigh.edu) (128.180.39.26) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Thu Jul 11 15:38:04 2002 -0000 -Received: from ([128.180.39.20]) - by ironmail1.cc.lehigh.edu with ESMTP with TLS; - Thu, 11 Jul 2002 11:35:06 -0400 (EDT) -Received: from lawrencework (pc-lfn0.dept.Lehigh.EDU [128.180.52.51]) - by rain.CC.Lehigh.EDU (8.12.4/8.12.4) with SMTP id g6BFZ6rr022463 - for ; Thu, 11 Jul 2002 11:35:06 -0400 -Message-ID: <0a0401c228f0$93feda10$3334b480@lawrencework> -From: "Phil R Lawrence" -To: -References: <083b01c22824$70357340$3334b480@lawrencework> <20020711140937.A568@dansat.data-plan.com> -Subject: Re: error msg suggestion -Date: Thu, 11 Jul 2002 11:35:20 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2600.0000 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -X-Status: A -Content-Length: 636 -Lines: 21 - -Tim Bunce wrote: -> Binding an undef should work and be treated as a NULL. -> -> Probably a bug in your code or the driver. But you didn't -> say which driver. - -Hmmm. quite right, undefs do bind as NULL. However, in this case I am -binding $hash{non-existent-key}, which autoinstantiates to an undef, and looks -like this in the trace: - undef (magic-sg:y) - -Of course it was my dumb fault for having the wrong key for lookup, but -nonetheless, perhaps this should work the same as a normal undef. - -# $DBI::VERSION = "1.14"; -# $DBD::ODBC::VERSION = '0.28'; -$DSN = 'driver=Microsoft Access Driver (*.mdb);dbq=StudyManager.mdb'; - -Thanks, -Phil - - diff --git a/err_bind/err_trailingblank.msg b/err_bind/err_trailingblank.msg deleted file mode 100644 index cdf34a32..00000000 --- a/err_bind/err_trailingblank.msg +++ /dev/null @@ -1,345 +0,0 @@ -From dbi-users-bounce@isc.org Mon May 1 21:12:02 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id VAA16051; Mon, 1 May 2000 21:12:00 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <14295-42@oink>; Fri, 1 May 1970 21:06:08 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 957208278:10:19133:4; Mon, 01 May 2000 19:11:18 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1123094; 1 May 2000 19:11 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id B3CCF3FAA; - Mon, 1 May 2000 12:10:53 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Mon, 01 May 2000 12:05:42 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A70763E34 - for ; Mon, 1 May 2000 12:05:30 -0700 (PDT) -Received: from scotth.emsphone.com (scotth.emsphone.com [199.67.51.179]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA25897 - for ; - Mon, 1 May 2000 12:05:30 -0700 (PDT) env-from (shildret@scotth.emsphone.com) -Received: (from shildret@localhost) by scotth.emsphone.com (8.9.3/8.9.3) - id OAA50011 for dbi-users@isc.org; - Mon, 1 May 2000 14:05:48 -0500 (CDT) (envelope-from shildret) -Message-ID: -X-Mailer: XFMail 1.4.0 on FreeBSD -X-Priority: 3 (Normal) -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 8bit -MIME-Version: 1.0 -Resent-Date: Thu, 29 Jul 1999 22:07:08 +0100 -Resent-Message-Id: <19990729220708.G17723@ig.co.uk> -Resent-From: Tim Bunce -Resent-To: Tim Bunce -Date: Mon, 01 May 2000 14:05:48 -0500 (CDT) -Sender: shildret@scotth.emsphone.com -From: "Scott T. Hildreth" -To: "dbi-users@isc.org" -Subject: FW: Oracle & Trailing Blanks - possible change in DBD::Oracle -Resent-Sender: shildret@scotth.emsphone.com -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 3885 -Lines: 94 - - -Here is the help, I got regarding the trailing spaces. - ------FW: <19990729220708.G17723@ig.co.uk>----- - -Date: Thu, 29 Jul 1999 22:07:08 +0100 -From: Tim Bunce -To: Tim Bunce -Subject: Oracle & Trailing Blanks - possible change in DBD::Oracle -Cc: "Scott T. HIldreth" , - dbi-users@isc.org - - *** From dbi-users -- To unsubscribe, see the end of this message. *** - -On Thu, Jul 29, 1999 at 09:49:38PM +0100, Tim Bunce wrote: -> *** From dbi-users -- To unsubscribe, see the end of this message. *** -> -> On Thu, Jul 29, 1999 at 09:33:55AM -0500, Scott T. HIldreth wrote: -> > -> > Hi all, I wonder if someone can let me know if I got this right. -> > I have a key to match which can contain trailing blanks. The -> > field in the database is CHAR(18). If I match the key with -> > sqlplus, Oracle finds a match, with or without the trailing -> > blank. When I do an sth->execute( $key ), the key is not -> > found. I abstract the key with substr, so the trailing blank -> > is in the key, but no match is found. Do I need to place qoutes -> > around the value in $key? -> -> Somewhat hiddedn in the Oraperl.pm docs it says this: -> -> --- -> B Substitution variables are now bound as type 1 (VARCHAR2) -> and not type 5 (STRING) by default. This can alter the behaviour of -> SQL code which compares a char field with a substitution variable. -> See the String Comparison section in the Datatypes chapter of the -> Oracle OCI manual for more details. -> -> You can work around this by using DBD::Oracle's ability to specify -> the Oracle type to be used on a per field basis: -> -> $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) -> $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); -> $csr->bind_param(1, $value_x, $char_attrib); -> $csr->bind_param(2, $value_y, $char_attrib); -> ora_bind($csr); # bind with no parameters since we've done bind_param()'s -> --- -> -> Ignoring the Oraperl specifics there the key point is to use -> -> $csr->bind_param($idx, $value, { ora_type => 5 }); -> -> I'll add something to the DBD::Oracle docs. - -[You'll still need to blank-pad the string.] - -Looking at this issue again I've discovered that the key issue is that -type 1 strips trailing blanks whilst type 5 doesn't. - -I'rather m concerned by this. Since I'm against the DBI changing the -data in any way on principle and since Oraperl used to use type 5 -I'm strongly considering changing DBD::Oracle 'back' to using type 5. - -This would only affect anyone who relies on placeholders having -trailing blanks stripped off. (I'll provide a way to alter the -default with a single statement and/or env var for anyone affected). - -If that's you - speak up now! - -Tim. - ------------------------------------------------------------------------------- -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of -'unsubscribe'. ------------------------------------------------------------------------------- - - ---------------End of forwarded message------------------------- - ----------------------------------- -E-Mail: Scott T. Hildreth -Date: 01-May-00 -Time: 14:04:41 ----------------------------------- - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - -From joshua.horton@mail.tju.edu Fri May 23 07:43:09 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.6/8.12.6) with ESMTP id h4N6UY7T061880 - for ; Fri, 23 May 2003 07:43:09 +0100 (BST) - (envelope-from joshua.horton@mail.tju.edu) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 23 May 2003 07:43:09 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1053631164:10:02298:54; Thu, 22 May 2003 19:19:24 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116141; 22 May 2003 19:19 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id BD31E21C13C - for ; Thu, 22 May 2003 15:18:30 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail.tju.edu (fw-tr16.tju.edu [147.140.233.16]) - by dolly1.pobox.com (Postfix) with ESMTP id 615A521C06D - for ; Thu, 22 May 2003 15:18:22 -0400 (EDT) -Received: from PCSE447.tjh.tju.edu by mail.tju.edu for Tim.Bunce@pobox.com; Thu, 22 May 2003 15:17:54 -0400 -Message-Id: <031301c32096$de68f6f0$2310ae0a@PCSE447> -From: "Joshua Horton" -To: -Subject: Re: :Oracle and Oracle 9.2? -Date: Thu, 22 May 2003 15:18:03 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 5.50.4807.1700 -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 3511 -Lines: 99 - -Re: :Oracle and Oracle 9.2? - ----------------------------------------------------------------------------- ----- - - a.. From: Tim Bunce - b.. Subject: Re: :Oracle and Oracle 9.2? - c.. Date: Tue, 15 Apr 2003 07:36:55 -0700 - ----------------------------------------------------------------------------- ----- - -I'd appreciate it if other people with Oracle 9.2.x could let me -know if it passed or failed for them and what their exact oracle -version (four digits) and platform (operating system) is. - -Thanks. - -Tim. - -On Fri, Apr 04, 2003 at 01:48:36PM +0200, Smejkal Petr wrote: -> I have the same experience on Linux however on Windows all tests passes -(I'm not -> sure if it is related to different Oracle version - test of windows Perl -against -> Linux Oracle is OK). -> -> Linux Oracle: 9.2.0.2 -> Windows Oracle: 9.2.0.1 -> DBI: 1.35 -> DBD::Oracle: 1.14 -> -> -- Petr Smejkal -> -- Business Systems Analyst / Country IT Cz/Sk -> -- +420 284 059 639 -> -> > -----Original Message----- -> > From: Tom Malaher [mailto:[EMAIL PROTECTED] -> > Sent: Friday, April 04, 2003 1:35 AM -> > To: [EMAIL PROTECTED] -> > Subject: DBD::Oracle and Oracle 9.2? -> > -> > -> > My sysadmin is trying to install DBD::Oracle on a Solaris box running -> > Oracle 9.2. -> > -> > The ph_type.t test is failing with -> > -> > PERL_DL_NONLAZY=1 ./perl "-MExtUtils::Command::MM" "-e" -> > "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -> > t/base.......ok -> > t/cursor.....ok -> > t/general....ok -> > t/long.......ok -> > t/meta.......ok -> > t/ph_type....NOK 12 expected 'trailing' but got 'trailing ' -> > for VARCHAR2 -> > t/ph_type....FAILED test 12 -> > Failed 1/19 tests, 94.74% okay -> > t/plsql......ok -> > t/reauth.....skipped -> > all skipped: no reason given -> > t/select.....ok -> > Failed Test Stat Wstat Total Fail Failed List of Failed -> > -------------------------------------------------------------- -> > ----------------- -> > t/ph_type.t 19 1 5.26% 12 -> > 1 test skipped. -> > Failed 1/9 test scripts, 88.89% okay. 1/314 subtests failed, -> > 99.68% okay. -> > *** Error code 29 -> > make: Fatal error: Command failed for target `test_static' -> > -> > Is there a known problem with DBD::Oracle and Oracle 9.x? -> > Has Oracle changed the behavior of trailing spaces in VARCHAR2 fields? -> > -> > I've run the same test script on an oracle 8 installation -> > using DBD::Oracle 1.06 and DBI 1.14, and it works fine (no trailing -> > space is returned). -> > -> > Tom -> > -My config:HP-UX 11.11 (64-bit) on rp5470 2x733 5GB RAMOracle 9.2.0.2.0 -Enterprise Edition (64-bit)Perl 5.8.0 custom compiled with -./Configure -Duse64bitall -Ubincompat5005 -Duselargefiles -Dprefix=/opt/perl -5 ; all other options defaultDBI-1.32 all passed some skippedDBD-Oracle-1.14 -: PERL_DL_NONLAZY=1 /opt/perl5/bin/perl "-MExtUtils::Command::MM" -"-e" "test_harness(0, 'blib/lib', 'blib/arch')" -t/*.tt/base.......okt/cursor.....okt/general....okt/long.......okt/meta..... -..okt/ph_type....ok 11/19 expected 'trailing' but got 'trailing ' for -VARCHAR2t/ph_type....FAILED test 12 Failed 1/19 tests, 94.74% -okayt/plsql......okt/reauth.....skipped all skipped: no reason -givent/select.....okFailed Test Stat Wstat Total Fail Failed List of -Failed---------------------------------------------------------------------- --------------------------------------------------------t/ph_type.t -19 1 5.26% 121 test skipped.Failed 1/9 test scripts, 88.89% okay. -1/314 subtests failed, 99.68% okay.*** Error exit code 2Stop.Thanks,Josh -Horton - - -From nobody@fsck.com Tue Dec 30 14:33:50 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hBUEWNnP026077 - for ; Tue, 30 Dec 2003 14:33:50 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Dec 2003 14:33:50 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AbJwa-0003ua-H6; - Tue, 30 Dec 2003 13:29:56 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AbJwa-0003ua-H6 - for pobox@dbi.demon.co.uk; Tue, 30 Dec 2003 13:29:56 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 56DAD4C6 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3B3564C8 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 30 Dec 2003 08:29:54 -0500 (EST) -Received: (qmail 10988 invoked by uid 225); 30 Dec 2003 13:29:53 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 10984 invoked by alias); 30 Dec 2003 13:29:52 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 30 Dec 2003 05:29:41 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 8760D11153; Tue, 30 Dec 2003 08:29:37 -0500 (EST) -Subject: [cpan #4786] Oracle 9.2.0.0 fails a test in ph_types.t -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4786 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -To: "AdminCc of cpan Ticket #4786": ; -Date: Tue, 30 Dec 2003 08:29:37 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,SUPERLONG_LINE,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -Content-Length: 888 -Lines: 11 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -Assuming that ORA_OCI() gets set correctly when compiling against 9.2, the attached patch will work. I also tried this in SQL*Plus and was able to insert a trailing space into a VARCHAR2. (I replicated the test in ph_types.t). - -I did not test my patch as I installed DBD::Oracle 1.14 by setting the chops_spaces value in %test_info to 0. When I did that, everything installed fine. However, I didn't think that my solution was the best for the module, so I figured ORA_OCI should do the trick. - -I'm running Perl5.8.0 for Solaris2.9 going against the full Oracle build for 9.2. (I did not run into this issue, surprisingly, on Redhat9 running Perl 5.8.2, but I built against Oracle 9.1 there ...) - diff --git a/err_build/err_aix64.msg b/err_build/err_aix64.msg deleted file mode 100644 index f952e29e..00000000 --- a/err_build/err_aix64.msg +++ /dev/null @@ -1,142 +0,0 @@ -From SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com Fri Jan 7 16:11:33 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j07GAqfa044155 - for ; Fri, 7 Jan 2005 16:11:32 GMT - (envelope-from SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Fri, 07 Jan 2005 16:11:32 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CmvQB-0003Po-Kf; - Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CmvQB-0003Po-Kf - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CmvQA-0002zW-VM - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 49778102ACC; - Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 384E5FF808 - for ; Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Received-SPF: pass (boggle.pobox.com: domain of dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by boggle.pobox.com (Postfix) with SMTP id A74B8F4090 - for ; Fri, 7 Jan 2005 09:48:57 -0500 (EST) -Received: (qmail 2690 invoked by uid 514); 7 Jan 2005 14:48:56 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 2622 invoked from network); 7 Jan 2005 14:48:55 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 7 Jan 2005 14:48:55 -0000 -Received: (qmail 13078 invoked by uid 225); 7 Jan 2005 14:48:54 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 13048 invoked by alias); 7 Jan 2005 14:48:51 -0000 -X-Spam-Status: No, hits=-4.6 required=8.0 - tests=BAYES_00,HTML_MESSAGE,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: neutral (x1.develooper.com: local policy) -Received: from outmx020.isp.belgacom.be (HELO outmx020.isp.belgacom.be) (195.238.2.201) - by la.mx.develooper.com (qpsmtpd/0.28) with ESMTP; Fri, 07 Jan 2005 06:48:38 -0800 -Received: from outmx020.isp.belgacom.be (localhost [127.0.0.1]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmOgS020070 - for ; Fri, 7 Jan 2005 15:48:24 +0100 - (envelope-from ) -Received: from relaytwo.roularta.be (smtprelaytwo.roularta.be [194.78.177.23]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmMDA020034 - for ; Fri, 7 Jan 2005 15:48:22 +0100 - (envelope-from ) -Received: from rmgexch01.RMG.be ([89.0.35.150]) by roesfront3.RMG.be with Microsoft SMTPSVC(5.0.2195.6713); - Fri, 7 Jan 2005 15:47:50 +0100 -X-MimeOLE: Produced By Microsoft Exchange V6.5.7226.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----_=_NextPart_001_01C4F4C7.EE810087" -Subject: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Date: Fri, 7 Jan 2005 15:48:21 +0100 -Message-ID: -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Thread-Index: AcT0x+Y4G1R3vbX6Rh+QdPyNy/10eQ== -From: -To: -X-OriginalArrivalTime: 07 Jan 2005 14:47:50.0598 (UTC) FILETIME=[DC5D2E60:01C4F4C7] -Status: RO -Content-Length: 1678 -Lines: 62 - -------_=_NextPart_001_01C4F4C7.EE810087 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - -Hi,=20 -=20 -I finally succeeded in installing a 64bit build of Perl and its modules -for Oracle 64-bit. We were running in 32bit but integrating Proc and -cobols in our perl scripts only worked when we changed environments to -64bit causing problems for the oracle connections in perl. It's nothing -special, no editing of makefiles ... I can't believe I lost so much time -on this one ;) ( Now that I look back to my problems, they were probably -caused by using a wrong perl build for compiling the modules, Aix has -its default perl now under /bin.. stupid me )=20 -=20 -perl 5.8.6 64bit ----------------- -./Configure -de -Dcc=3Dgcc -Duse64bitall=20 -make -make test -make install -=20 -DBI 1.46 --------- -!!Make sure you are using the newly installed perl!! - check with perl -v it should show :=20 - This is perl, v5.8.6 built for aix-64all -perl Makefile.PL -make -make test -make install=20 -=20 -DBD-Oracle 1.16 ---------------- -!!Use correct perl like above mentioned!!=20 -export ORACLE_HOME=3D=20 -export LIBPATH=3D$ORACLE_HOME/lib -export LD_LIBRARY_PATH=3D$ORACLE_HOME/lib -=20 -perl Makefile.PL=20 -make -make test ( some test may still fail, I had 85% success on tests )=20 -make install=20 -=20 -Test -----=20 -=20 -test with :=20 - use DBI; - $dbh=3DDBI->connect("dbi:Oracle:","system","manager")|| die -$DBI::errstr; - $stmt=3D$dbh->prepare("select * from tab"); - $rc=3D$stmt->execute() || die $DBI::errstr; - while (my($record)=3D$stmt->fetchrow()) - { - print $record; - } -=20 -Happy 64-bit perling ;)=20 - -------_=_NextPart_001_01C4F4C7.EE810087-- - diff --git a/err_build/err_hpux_ld.msg b/err_build/err_hpux_ld.msg deleted file mode 100644 index 27f9cd07..00000000 --- a/err_build/err_hpux_ld.msg +++ /dev/null @@ -1,89 +0,0 @@ -From SRS0=JbZc=U3=lincolnbaxter.com=lab@bounce2.pobox.com Tue Jun 21 05:02:19 2005 -Return-Path: -X-Original-To: timbo@localhost -Delivered-To: timbo@localhost.data-plan.com -Received: from localhost (localhost [127.0.0.1]) - by timac.data-plan.com (Postfix) with ESMTP id B016F2A3D98 - for ; Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DkYXK-0003m5-Mr; - Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DkYXK-0003m5-Mr - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1DkYXJ-00006n-QE - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AF60172691; - Mon, 20 Jun 2005 22:29:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from ms-smtp-04-eri0.southeast.rr.com (ms-smtp-04-lbl.southeast.rr.com [24.25.9.103]) - by gold.pobox.com (Postfix) with ESMTP id A3C1E7272E - for ; Mon, 20 Jun 2005 22:29:11 -0400 (EDT) -Received: from lincolnbaxter.com (cpe-069-132-010-126.carolina.res.rr.com [69.132.10.126]) - by ms-smtp-04-eri0.southeast.rr.com (8.12.10/8.12.7) with ESMTP id j5L2TIL4001864 - for ; Mon, 20 Jun 2005 22:29:18 -0400 (EDT) -Received: (qmail 5171 invoked from network); 20 Jun 2005 22:29:07 -0400 -Received: from lws (192.168.0.25) - by lws with SMTP; 20 Jun 2005 22:29:07 -0400 -Subject: Re: gcc options when building DBD:Oracle -From: "Lincoln A. Baxter" -Reply-To: lab@lincolnbaxter.com -To: jriekenberg@everestkc.net -Cc: Tim Bunce -In-Reply-To: -References: -Content-Type: text/plain -Date: Mon, 20 Jun 2005 22:29:07 -0400 -Message-Id: <1119320947.17452.484.camel@lws> -Mime-Version: 1.0 -X-Mailer: Evolution 2.2.1.1 -Content-Transfer-Encoding: 7bit -X-Virus-Scanned: Symantec AntiVirus Scan Engine -Status: RO -Content-Length: 2011 -Lines: 38 - -Hi Jan, - -This looks like something that might be relatively easy to fix in -Makefile.PL. But I no longer have access to HPUX systems, and never -built DBD-Oracle with gcc on that platform. I could add your message to -the README.hpux file, but it is becoming less and less necessary to read -this file with newer versions of DBD-Oracle, in which Makefile.PL has -been made much smarter. - -Would you consider sending Tim or me a patch to Makefile.PL that -generates the right $(LD) command (only on HP rp8400, and only for your -version of gcc or later? - -Lincoln - -On Mon, 2005-06-20 at 15:36 -0500, jriekenberg@everestkc.net wrote: -> Lincoln, -> -> I recently built DBD:Oracle on an HP rp8400. Everything worked as expected until I actually issued the "make" command. Make proceeded as expected until it reached "MakeMaker dynamic_lib" section. The gcc line in that section failed with the error in the attached text file. Apparently gcc was not correctly passing the "+b" option to ld. Instead, it was attempting to interpret the option itself. It assumed the "+b" was a filename, and that failed because gcc could not find the file. I ended up adding the "-Xlinker" option before the "+b" and before the "$(LD_RUN_PATH)" in the line in Makefile. The line now looks like this: -> -> $(LD) -Xlinker +b -Xlinker "$(LD_RUN_PATH)" $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) -> -> Running "make" now works correctly. -> -> Also, "make test" returned the following error when attempting to build the various tests: -> -> /usr/lib/dld.sl: Can't shl_load() a library containing Thread Local Storage: /usr/lib/libcl.2 -> -> Setting LD_PRELOAD with "export LD_PRELOAD=/usr/lib/libcl.2" corrected this problem, and "make test" worked correctly. -> -> -> I didn't see DBD::Oracle documentation on exactly this, so I'm sending this to you. You may be aware of these items already. If so, please disregard this. -> -> Jon Riekenberg -> -> -> - - diff --git a/err_build/err_hpuxsuccess.msg b/err_build/err_hpuxsuccess.msg deleted file mode 100644 index c6edd79f..00000000 --- a/err_build/err_hpuxsuccess.msg +++ /dev/null @@ -1,279 +0,0 @@ -From dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org Tue Mar 23 17:00:25 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i2NGvAxX021862 - for ; Tue, 23 Mar 2004 17:00:23 GMT - (envelope-from dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 23 Mar 2004 17:00:23 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1B5oND-0000Ba-LH; - Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1B5oND-0000Ba-LH - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [208.210.124.70] (helo=majesty.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1B5oNC-00001d-92 - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:26 +0000 -Received: from majesty.pobox.com (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 18033954B4 - for ; Tue, 23 Mar 2004 11:03:24 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 3577D954BE - for ; Tue, 23 Mar 2004 11:03:21 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by majesty.pobox.com (Postfix) with SMTP - for ; Tue, 23 Mar 2004 11:02:41 -0500 (EST) -Received: (qmail 6527 invoked by uid 1005); 23 Mar 2004 16:02:21 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6510 invoked by uid 76); 23 Mar 2004 16:02:20 -0000 -Received: from x1.develooper.com (HELO x1.develooper.com) (63.251.223.170) - by onion.perl.org (qpsmtpd/0.27.1) with SMTP; Tue, 23 Mar 2004 08:02:20 -0800 -Received: (qmail 1985 invoked by uid 225); 23 Mar 2004 16:02:15 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 1893 invoked by alias); 23 Mar 2004 16:02:00 -0000 -X-Spam-Status: No, hits=0.0 required=7.0 - tests= -X-Spam-Check-By: la.mx.develooper.com -Received: from Unknown (HELO dundee.fpcc.net) (204.144.241.120) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Tue, 23 Mar 2004 08:01:44 -0800 -Received: from aberdeen.fpcc.net (aberdeen.fpcc.net [204.144.241.125]) - by dundee.fpcc.net (8.11.6/8.11.6) with ESMTP id i2NG1f111241; - Tue, 23 Mar 2004 09:01:41 -0700 -Received: from aberdeen.fpcc.net (localhost.localdomain [127.0.0.1]) - by aberdeen.fpcc.net (8.12.8/8.12.8) with ESMTP id i2NFrNOv024637; - Tue, 23 Mar 2004 08:53:23 -0700 -Received: (from laubster@localhost) - by aberdeen.fpcc.net (8.12.8/8.12.8/Submit) id i2NFrMOx024635; - Tue, 23 Mar 2004 08:53:22 -0700 -X-Authentication-Warning: aberdeen.fpcc.net: laubster set sender to dbiusers@laubster.org using -f -Date: Tue, 23 Mar 2004 08:53:22 -0700 -From: "J.D. Laub" -To: dbi-users@perl.org -Cc: lbaxter@fleetcc.com -Subject: SUCCESS: DBD::Oracle 1.15 on HP-UX 11.11 -Message-ID: <20040323155322.GA24576@aberdeen.fpcc.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -Organization: The Psychiatric Ward of Terrors -X-Virus-Checked: Checked -Status: RO -Content-Length: 9105 -Lines: 206 - -I've just had success building DBD::Oracle 1.15 on HP-UX 11.11 -(against both oracle 8.1.7 & oracle 9.2.0) & thought I'd share my -experience. - -Disclaimer: these instructions relate to our environment. It may be -that our sysadmins/dbas chose to configure/install things a certain -way (i.e., our install of $ORACLE_HOME/bin/sqlplus was *chosen* -to be 1.1/32), and/or that we're running old versions of software -(i.e., perhaps later releases of gcc don't ignore -mpa-risc-1-1). -In fact, there are probably some mistruths in here; rest assured -they're not intentional. :-) - -I'm unsure how (if?) I should go about getting this information into -the DBD::Oracle README.hpux. Lincoln, please contact me with any -thoughts you have. - - -### The summary ################################ - -Use the ansic compiler (~US$800/cpu). - -Shell variables I used: - PATH=/bin:$PATH # use 32bit ar & nm since using a 32bit cc - PERLDEST=/opt/perl_ora8 # or "perl_ora9" for an ora9 build - PATH=$PERLDEST/bin:$PATH # for build of DBI, pick up new perl - export LDLOADLIBS='+b : +s' # handy for ORACLE_SID connections to ora7 - unset PERLLIB # important to avoid outdated cruft - export ORACLE_USERID=scott/tiger # insecure - consider using "/" - ORACLE_SID=orcl - ORAENV_ASK=NO - . oraenv # sets LD_LIBRARY_PATH and SHLIB_PATH - -For ora8: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DAportable ' \ - -A prepend:ldflags='+z +DAportable ' - -For ora9: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DA2.0W ' \ - -A prepend:ldflags='+z +DA2.0W ' \ - -Dlibpth='/usr/lib/pa20_64 /usr/local/pa20_64/lib' - -After you use the above to install perl, DBI & DBD::Oracle will -build in the normal fashion. - - -### General Notes ################################ - -* During "make test", I received 1 failure (on -lib/ExtUtils/t/Constant) for ora8, and 3 failures (on -lib/ExtUtils/t/Constant, lib/ExtUtils/t/recurs, and t/op/write) for -ora9. Nevertheless, things seem mostly OK. - -* These are the various combinations possible for a given compiled -file on HP-UX 11.11 (the quoted description is what gets kicked out -by the "file" command): - - PA-RISC1.1/32bit ("PA-RISC1.1 relocatable object") - (I'll call this 1.1/32) - PA-RISC2.0/32bit ("PA-RISC2.0 relocatable object") - (I'll call this 2.0/32) - PA-RISC2.0/64bit ("ELF 64-bit MSB relocatable, PA-RISC 2.0 (LP64)") - (I'll call this 2.0/64) - -* "perl -v" lies about the RISC level: -$ file ./perl -./perl: PA-RISC1.1 shared executable dynamically linked -not stripped -$ ./perl -v | grep RISC -This is perl, v5.8.3 built for PA-RISC2.0 - -* If you'll be linking against 2.0/64 libraries, you'll have to -build all your object modules that way. I've not yet found a way -to link 32bit executables to 64bit libraries (and vice versa). Run -the "file" command on your Oracle libraries to find out which path -you'll have to take. - -* Two environment variables control where libraries are -searched. LD_LIBRARY_PATH and SHLIB_PATH (in that order) are -used for 64bit executables, while SHLIB_PATH is used for 32bit -executables. - -* I tried attempts using aCC as well as the default (free) cc that -comes with hpux; both avenues were too problematic to continue -pursuing. - -* The format of compiled objects is specified by compiler options. -According to the ansic compiler docs, the options are "+DAportable" -(for 1.1/32), "+DA2.0" (for 2.0/32), and "+DA2.0W" (for 2.0/64). -For gcc, the corresponding switches are -mpa-risc-1-1 (for 1.1/32) -and -mpa-risc-2-0 (for 2.0/64), but I've found that -mpa-risc-1-1 -is ineffective. (According to the "file" command, you *always* get -2.0/64.) - -* Our gcc displays the behavior described at -http://sources.redhat.com/ml/binutils/2002-10/msg00586.html and -http://aspn.activestate.com/ASPN/Mail/Message/perl5-porters/1641238 -, so is therefore unusable anytime '-lcl' is to be specified. -Unfortunately, that library is required for DBD::Oracle builds. -(The workaround of adding the 3 declarations does seem to work, -but littering those throughout perl's Configure, main.c, etc. -seems a big task.) Attempts to get gcc to use the hp ld instead -of the gnu ld (by specifying -mno-gnu-ld and -fno-gnu-linker) were -unsuccessful. The first html link shown above indicates you have -to rebuild gcc to use the hp linker, and that was not an incredibly -desirable path to pursue. - -* Our default PATH was set to put /usr/local/pa20_64/bin ahead of -/bin. This caused problems because (I think) the 64bit versions -of either ar (the archiver) or nm (the symbol lister) do not play -well with /bin/cc (the 32bit compiler). The tweak to put /bin at -the head of PATH, so we get the 32bit versions, takes care of the -problem. - -* I ran into an intermittent quirk during the build of perl in which -typing "make" (just after the Configure) did nothing. It turns out -that only dependencies were being written to "makefile", and that -removing "makefile" (so it could be automatically rebuilt) solved -the problem. - -* Most of my research on finding the right compiler/linker switches -was done with a "hello world" C program, trying the various -compilers and options, and trying to link it with the oracle -libraries. This proved to be a good choice, as trying to test -compilers/switches against the perl source distribution would have -proved quite difficult. - - -### DBD::Oracle specific ################################ - -* ora8 delivers its libraries in 2 formats: 1.1/32 (under -$ORACLE_HOME/lib) and 2.0/64 (under $ORACLE_HOME/lib64). ora7 -delivers only 1.1/32, while ora9 delivers only 2.0/64. It may seem -a bit inconsistent considering the ora8 setup, but ora9 libraries -are found under $ORACLE_HOME/lib and not $ORACLE_HOME/lib64. - -* Under ora8, oraenv incorrectly sets LD_LIBRARY_PATH to include -$ORACLE_HOME/lib instead of $ORACLE_HOME/lib64, so you've got to -make an override in oraenv_local if you want to use 2.0/64. It -doesn't harm anything, but oraenv unnecessarily sets LD_LIBRARY_PATH -for ora7 (a 64bit environment variable for a 32bit application). - -* If you use shared libraries AND you'll be upgrading Oracle, you -should expect you'll need to rebuild DBD::Oracle unless you'll keep -the old Oracle libraries available. - -* If you're building against ora8, the setting of LDLOADLIBS -is recommended so that when oraenv set SHLIB_PATH to the -$ORACLE_HOME/lib for ora7, the code will still find the ora8 -libraries. - -* We expect to need local (ORACLE_SID) connections for ora8 & -ora9. We could have gone with a single 2.0/64 perl coupled with -2 DBD::Oracle installs and PERLLIB twiddling in oraenv_local to -get to the right one. Instead, we chose to do 2 perl installs -(/opt/perl_ora8 and /opt/perl_ora9) because we can also connect -locally to ora7 by using the 1.1/32 ora8 version, something that -isn't possible with a 2.0/64 version. Also, we've some older 1.1/32 -machines into which we'd like to plop a tarball of the perl stuff, -so a 1.1/32 executable was desirable. - -* Some tests I ran were hinting that with 2.0/64, specifying "+b :" -on the build of DBD::Oracle correctly configured Oracle.sl as far as -the chatr program is concerned, but it seemed that LD_LIBRARY_PATH -*always* needed to be set correctly. (I.e., the embedded path in -the library seemed to be ignored.) I didn't pursue researching this -since there's no way to get the ora9 compiled code to connect to -ora8, meaning LD_LIBRARY_PATH had to be set correctly anyway. - -Testing local (ORACLE_SID) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora9 cannot connect to ora8 or ora7: "UNKNOWN - OCI STATUS 1804) OCIInitialize. Check ORACLE_HOME and NLS - settings etc." - -Testing remote (sqlnet) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 can connect to ora9 -builds against 2.0/64 ora9 can connect to ora8 -builds against 2.0/64 ora9 cannot connect to ora7: "OCI-21500: internal - error code" - - -### Versions ################################ - -perl: 5.8.3 -dbi: 1.41 -dbd-oracle: 1.15 -$ strings /bin/cc | grep Compiler -HP92453-01 B.11.11.08 HP C Compiler -$ strings /bin/ld | grep linker -$Revision: 92453-07 linker linker crt0.o B.11.16 000601 $ -@(#)92453-07 linker command s800.sgs ld PA64 B.11.18 REL 000922 -$ gcc -v -Reading specs from /usr/local/pa20_64/lib/gcc-lib/hppa64-hp-hpux11.11/3.3.1/specs -Configured with: ../src/configure --enable-languages=c,c++ --prefix=/usr/local/pa20_64 --with-local-prefix=/usr/local/pa20_64 --with-gnu-as --with-as=/usr/local/pa20_64/bin/as --with-gnu-ld --with-ld=/usr/local/pa20_64/bin/ld --disable-shared --disable-nls --host=hppa64-hp-hpux11.11 -Thread model: single -gcc version 3.3.1 - --- -J.D. Laub (Laubster) |"Your leg's too long / Your skull's too strong / -dbiusers@laubster.org| Suppose your nose is wrong." - Renaldo & the Loaf - diff --git a/err_build/err_instantclient.msg b/err_build/err_instantclient.msg deleted file mode 100644 index f0e549eb..00000000 --- a/err_build/err_instantclient.msg +++ /dev/null @@ -1,207 +0,0 @@ -From SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Feb 2 10:11:05 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j12AAUZ6055956 - for ; Wed, 2 Feb 2005 10:11:05 GMT - (envelope-from SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 02 Feb 2005 10:11:05 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwGaQ-0002Bn-H6; - Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwGaQ-0002Bn-H6 - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwGaP-00042G-Vb - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 9C3FB1E3946; - Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 879981E3958 - for ; Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Received-SPF: pass (kelvin.pobox.com: domain of dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by kelvin.pobox.com (Postfix) with SMTP id D0B001E3946 - for ; Wed, 2 Feb 2005 04:14:08 -0500 (EST) -Received: (qmail 7188 invoked by uid 514); 2 Feb 2005 09:14:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -List-Id: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 2531 invoked from network); 2 Feb 2005 04:10:16 -0000 -Delivered-To: dbi-users@perl.org -X-Spam-Status: No, hits=-2.6 required=8.0 - tests=BAYES_00,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: pass (x1.develooper.com: local policy) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgw.shina.sankyo.co.jp: iscan owned process doing -bs -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: Making DBD::Oracle with Instant Client 10.1.0.3 -Date: Wed, 2 Feb 2005 13:09:58 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBE9@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUI3Q64h9ykph8RSl6pF0OpBbTqJA== -To: -X-OriginalArrivalTime: 02 Feb 2005 04:09:59.0005 (UTC) FILETIME=[0F7508D0:01C508DD] -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 44 - -Hi all, - -Thanks to the devel package, I've got succeeded in making DBD::Oracle -with the Oracle Instant Client 10.1.0.3, no *.mk files, in my linux box. -My recipe is: - -1) install both basic- and devel-10.1.0.3 rpm packages -2) export ORALCE_HOME="/usr/lib/oracle/10.1.0.3/client" -3) export LD_LIBRARY_PATH="$ORACLE_HOME/lib:$LD_LIBRARY_PATH" -4) modify the Makefile.PL file to bypass the find_headers() routine and - to pass a correct -I flag to cc (the attached dirty patch is FYI) -5) execute the Makefile.PL * with the -l option *, perl Makefile.PL -l -6) make && make test && make install -# I got many errors in t/30long.t (retrieving blobs ?) -# but it seems to work fairly. - -I hope this could help those who are annoyed with the "Unable to locate an -oracle.mk,..." error. - -Happy DBing, - -Satoshi - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+# my @h_dirs = find_headers(); - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client"; - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -From SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com Thu Feb 3 08:10:48 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j138AMOi093146 - for ; Thu, 3 Feb 2005 08:10:48 GMT - (envelope-from SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Thu, 03 Feb 2005 08:10:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwboD-0005ug-LV; - Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwboD-0005ug-LV - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwboD-0000Wn-82 - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 70999102D9F; - Thu, 3 Feb 2005 02:53:48 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 5F45E102DCC - for ; Thu, 3 Feb 2005 02:53:48 -0500 (EST) -X-Pobox-Antispam: Require PTR Record returned DENY: 210.81.52.253 has no PTR record -X-Pobox-Antispam: country/Japan returned DENY: sender address snisim@sankyo.co.jp matches TLD .jp (Japan) -Received-SPF: none (boggle.pobox.com: domain of snisim@sankyo.co.jp does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for snisim@sankyo.co.jp to mail through 210.81.52.253) -Received: from mailgws.shina.sankyo.co.jp (unknown [210.81.52.253]) - by boggle.pobox.com (Postfix) with ESMTP id A38A5102E20 - for ; Thu, 3 Feb 2005 02:53:46 -0500 (EST) -Received: from es007.sankyo.co.jp (localhost [127.0.0.1]) - by mailgws.shina.sankyo.co.jp (8.9.3p2/3.7W) with ESMTP id LAA15117 - for ; Thu, 3 Feb 2005 11:45:39 +0900 (JST) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgws.shina.sankyo.co.jp: iscan owned process doing -bs -Received: from EVS001.sankyo.co.jp ([10.14.121.200]) by es007.sankyo.co.jp with Microsoft SMTPSVC(6.0.3790.0); - Thu, 3 Feb 2005 11:45:39 +0900 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: RE: Making DBD::Oracle with Instant Client 10.1.0.3 -Content-class: urn:content-classes:message -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Date: Thu, 3 Feb 2005 11:46:07 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBEC@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUJEc1pQuIX++g2S8y4AE9WqWRYtQAhsK+Q -To: -X-OriginalArrivalTime: 03 Feb 2005 02:45:39.0123 (UTC) FILETIME=[71F21030:01C5099A] -Status: RO -Content-Length: 1192 -Lines: 36 - -Hi Tim, - -Thank you for your kind reply. - -I found my patch will cause a compilation error for the local variable -@h_dirs gets into undefined after commenting out the line 279. -It should be corrected as following: - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+ my @h_dirs; - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client" - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -I'm not a dbi-users member so I can't reply my post... I wonder if you can do it. - -Thanks, - -Satoshi - - diff --git a/err_build/err_makefileundef.msg b/err_build/err_makefileundef.msg deleted file mode 100644 index b98d782a..00000000 --- a/err_build/err_makefileundef.msg +++ /dev/null @@ -1,87 +0,0 @@ -From timbo Tue Apr 26 09:19:54 2005 -Return-path: -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 26 Apr 2005 09:19:54 -0700 (PDT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DQSgy-0006AU-4c; - Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DQSgy-0006AU-4c - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1DQSgy-0003uM-1T - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 759703B902A; - Tue, 26 Apr 2005 12:13:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 80C0A39F279 - for ; Tue, 26 Apr 2005 12:13:42 -0400 (EDT) -Received-SPF: none (kelvin.pobox.com: domain of lembark@wrkhors.com does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 66.246.154.128(mail-out.pilosoft.net) -Received: from mail.pilosoft.net (mail-out.pilosoft.net [66.246.154.128]) - by kelvin.pobox.com (Postfix) with ESMTP id 2ED743AB75B - for ; Tue, 26 Apr 2005 12:12:30 -0400 (EDT) -Received: from [192.168.1.2] (dsl-69-31-90-94.pilosoft.com [69.31.90.94]) - by mail.pilosoft.net (8.12.8/8.12.8) with ESMTP id j3QGA3u1014203 - for ; Tue, 26 Apr 2005 12:10:03 -0400 -Date: Tue, 26 Apr 2005 12:14:22 -0400 -From: Steven Lembark -Reply-To: lembark@wrkhors.com -To: Tim Bunce -Subject: Possible glitch in DBD::Oracle-1.48 Makefile.pl -Message-ID: <269F0144DC99100E7C80975F@[192.168.1.2]> -X-Mailer: Mulberry/3.1.3 (Linux/x86) -X-Workhorse: lembark 1.1 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii; format=flowed -Content-Transfer-Encoding: 7bit -Content-Disposition: inline -X-Virus-Scanned: ClamAV version 0.83, clamav-milter version 0.83 on mail.pilosoft.net -X-Virus-Status: Clean -X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=failed version=3.0.2 -X-Spam-Level: 0.0 -X-Spam-Checker-Version: SpamAssassin 3.0.2 (2004-11-16) on cheeta.pilosoft.net -X-Status: A -Content-Length: 1342 -Lines: 36 - -Linking with OTHERLDFLAGS = -L/opt/oracle/product/9.2/lib/ --L/opt/oracle/product/9.2/rdbms/lib/ -lclntsh `cat -/opt/oracle/product/9.2/lib/sysliblist` -ldl -lm [from 'build' rule] - -Checking if your kit is complete... -Looks good -Use of uninitialized value in substitution (s///) at Makefile.PL line 1446. -LD_RUN_PATH=/opt/oracle/product/9.2/lib:/opt/oracle/product/9.2/rdbms/lib -Using DBD::Oracle 1.16. - - - sub const_loadlibs { - my $self = shift; - local($_) = $self->SUPER::const_loadlibs(@_); - # edit LD_RUN_PATH ... - my ($ldrp) = m/^LD_RUN_PATH\s*=\s*(.*)/m; - # remove redundant /lib or /usr/lib as it can cause problems --> $ldrp =~ s!:(/usr)?/lib$!!; - # if it's empty then set it manually - #Lincoln: if pick the right library path - my $libdir = main::ora_libdir(); - $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; - #print "ldrp=$ldrp\n"; - - # stitch it back in - s/^LD_RUN_PATH\s*=\s*(.*)/LD_RUN_PATH=$ldrp/m; - my $env = $ENV{LD_RUN_PATH}; - print "Ignoring LD_RUN_PATH='$env' in environment\n" if $env; - print "LD_RUN_PATH=$ldrp\n"; - return $_; - } - --- -Steven Lembark 85-09 90th Street -Workhorse Computing Woodhaven, NY 11421 -lembark@wrkhors.com 1 888 359 3508 - diff --git a/err_build/err_memleak.msg b/err_build/err_memleak.msg deleted file mode 100644 index d40913d7..00000000 --- a/err_build/err_memleak.msg +++ /dev/null @@ -1,95 +0,0 @@ -From SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com Wed Sep 1 16:31:37 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i81FRlpg021884 - for ; Wed, 1 Sep 2004 16:31:37 +0100 (BST) - (envelope-from SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 Sep 2004 16:31:37 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C2WYO-00034m-M1; - Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C2WYO-00034m-M1 - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1C2WYO-0005CR-FY - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 1C1D6A758C; - Wed, 1 Sep 2004 10:57:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 184C8A7214 - for ; Wed, 1 Sep 2004 10:57:32 -0400 (EDT) -Received-SPF: fail (boggle.pobox.com: domain of www-data@pallas.eruditorum.org does not designate 63.251.223.170 as permitted sender) -X-SPF-Override: pass (client 63.251.223.170 was found in trusted-forwarder.org, overrides regular SPF fail) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.170(x1.develooper.com) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP id 7A6C9A7555 - for ; Wed, 1 Sep 2004 10:57:06 -0400 (EDT) -Received: (qmail 5427 invoked by uid 225); 1 Sep 2004 14:57:04 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 5403 invoked by alias); 1 Sep 2004 14:57:02 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 01 Sep 2004 07:56:59 -0700 -Received: by pallas.eruditorum.org (Postfix, from userid 33) - id 1FDD784C0F5; Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -Subject: [cpan #6245] Confirmed memory leak -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #6245 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -Date: Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -To: undisclosed-recipients: ; -Status: RO -Content-Length: 937 -Lines: 38 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -I Using : -1. SunOS 5.6 Generic_105181-33 sun4u sparc SUNW,Ultra-Enterprise - Perl 5.005_03 - DBI 1.37 - DBD-Oracle 1.14 - Oracle Release 8.1.5.0.0 - - -2. Linux 2.4.18-17.7.xsmp #1 SMP i686 - Perl 5.6.1 - DBI 1.41 - DBD-Oracle 1.16 - Oracle Release 8.1.6.0.0 - -II The following code: - -use strict; -use DBI; - -foreach ( 1 .. 100 ) { - my $dbh = DBI->connect( 'dbi:Oracle:host=****', '***', '***' ); - $dbh->disconnect(); - sleep(1) -} - -III Leak about 4K every 10 seconds - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8724 8720 2760 S 1.3 3.4 0:01 perl - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8736 8732 2760 S 0.7 3.4 0:01 perl - diff --git a/err_build/err_solarisnotes.msg b/err_build/err_solarisnotes.msg deleted file mode 100644 index eaddc475..00000000 --- a/err_build/err_solarisnotes.msg +++ /dev/null @@ -1,482 +0,0 @@ -From SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com Wed Dec 22 08:11:00 2004 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id iBM8Aog0091816 - for ; Wed, 22 Dec 2004 08:11:00 GMT - (envelope-from SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 22 Dec 2004 08:11:00 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Ch0it-0001A5-Rv; - Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Ch0it-0001A5-Rv - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Ch0is-0000To-R8 - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id F0F0DFE10C; - Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 8B2AAFE1C3 - for ; Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Received-SPF: none (lime.pobox.com: domain of alexzar@zorranlabs.com does not designate permitted sender hosts) -Received: from penguin.nocdirect.com (penguin.nocdirect.com [69.73.160.206]) - by lime.pobox.com (Postfix) with ESMTP id 2B41BFE159 - for ; Wed, 22 Dec 2004 02:13:17 -0500 (EST) -Received: from localhost ([127.0.0.1]) - by penguin.nocdirect.com with esmtps (TLSv1:DES-CBC3-SHA:168) - (Exim 4.43) - id 1Cgz53-0000fj-Bx; Tue, 21 Dec 2004 23:30:37 -0600 -Date: Tue, 21 Dec 2004 23:30:35 -0600 (CST) -From: Alex Zarutin -X-X-Sender: zorranla@penguin.nocdirect.com -To: Tim Bunce -Cc: dbi-users-help@perl.org -Subject: Step-by-Step installation manual of DBD-Oracle-1.16 on Sparc Solaris - 9 with Oracle 9.2.0.1.0 client. -Message-ID: -MIME-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-AntiAbuse: This header was added to track abuse, please include it with any abuse report -X-AntiAbuse: Primary Hostname - penguin.nocdirect.com -X-AntiAbuse: Original Domain - pobox.com -X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] -X-AntiAbuse: Sender Address Domain - zorranlabs.com -X-Source: -X-Source-Args: -X-Source-Dir: -Status: RO -X-Status: A -Content-Length: 15603 -Lines: 426 - - -Hi Tim, - -I have spent a couple days trying to install DBD-Oracle-1.16 (all -required stuff, such as GCC, DBI, etc has been installed before ) on -Sun-Fire v240 running Spark Solaris 9 with the Oracle 9.2.0.1.0 client -installed. The installation takes a couple minutes ONLY after you spend -days trying to make it workable. - -I wrote the log of what I do, in order to do not waste my time in -future. I am pretty sure that this log will be very useful for people -installing DBD-Oracle on Solaris. I published it on my log page, and left -link on it at http://cpanratings.perl.org/d/DBD-Oracle review page. I -would recommend you to add this log to the readme file of your next -releases. Log is written very detailed (step-by-step) with highlighted -typical mistakes. - -Environment: -Hardware/OS: bash-2.05# uname -a -SunOS qadmz41 5.9 Generic_117171-08 sun4u sparc SUNW,Sun-Fire-V240 -OS is actually "standard" Solaris 9 installation came on the box from -SUN - -Oracle Client: Oracle 9.2.0.1.0 -GCC: gcc version 3.3.2, installed to /usr/local/bin as a package from -http://www.sunfreeware.com/programlistsparc9.html -PERL: perl v5.8.5 built for sun4-solaris, installed to /usr/local/bin as -a package from http://www.sunfreeware.com/programlistsparc9.html -DBI: DBI-1.45, installed from http://search.cpan.org/~timb/DBI-1.45/ - -Step-by-Step Manual: - -Step 1: In order to install "DBD-Oracle-1.16" you need to download it, -set all appropriate environment variables (see readme for details) and -run <>. -I got an error that is mostly typical for Solaris installation: - -// ************************ Error 1 ***********************/ - -.... -Found header files in rdbms/demo. - -********************************************************* -I can't find the header files I need in your Oracle installation. -You probably need to install some more Oracle components. -I'll keep going, but the compile will probably fail. -See README.clients for more information. -********************************************************* -Checking for functioning wait.ph - -System: perl5.008005 sunos 5.9 generic sun4u sparc sunw,ultra-5_10 -solaris -Compiler: gcc -B/usr/ccs/bin/ -O -fno-strict-aliasing -pipe --I/usr/local/include -I/opt/gnu/include -D_LARGEFILE_SOURCE --D_FILE_OFFSET_BITS=64 - -.... -// *****************************************************/ - -Investigating this problem, I found that error message is thrown by the -"find_headers" sub of Makefile.PL, especially in this "if -(!$h_file{'oratypes.h'} || !$h_file{'ocidfn.h'})" evaluation. -So I checked these files to make sure that they are installed, but did -not find them under $ORACLE_HOME/rdbms -In the same time, I found an article saying about the similar problem -with DBD-Oracle on Linux, -http://baroti.homedns.org/steve/lost+found/cpan-install-DBD-Oracle-9-2-l -inux.html -They mentioned about two files, and since I was not sure about second -one, ociapr.h I copied both files. You should find its public.1.1.jar -file on the Disk3 of Oracle 9i installation set. - -bash-2.05# pwd -/ora_orig/Disk3/stage/Components/oracle.rdbms.oci/9.2.0.1.0/1/DataFiles - -bash-2.05# ls -al -total 970 -drwxr-xr-x 2 2840 42424 512 Aug 21 2002 . -drwxr-xr-x 3 2840 42424 512 Aug 21 2002 .. --rwxr-xr-x 1 2840 42424 2047 May 9 2002 bin.1.1.jar --rwxr-xr-x 1 2840 42424 206 May 9 2002 build.1.1.jar --rwxr-xr-x 1 2840 42424 135034 May 9 2002 demo.1.1.jar --rwxr-xr-x 1 2840 42424 329814 May 9 2002 public.1.1.jar - -You should just (as dba:oracle) to create the directory called public, -copy public.1.1.jar there and extract all files, since I would not guess -if the rest of them are used or not - -bash-2.05# mkdir $ORACLE_HOME/rdbms/public - -bash-2.05# ls -al $ORACLE_HOME/rdbms/public -total 3404 -drwxr-xr-x 2 oracle dba 512 Dec 21 12:12 . -drwxr-xr-x 10 oracle dba 512 Dec 21 12:05 .. -... --rw-r--r-- 1 oracle dba 6055 Mar 9 2002 ociapr.h --rw-r--r-- 1 oracle dba 10694 Jun 29 2000 ocidfn.h -... - -After that run <> again, and I hope process passes -fine. At least, it was fine in my case - -Step 2: You should <> the module, and as it appears on Solaris, -you will get typical problem. See my error log: - -// ************************ Error 2 ***********************/ -.... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -ld: fatal: file -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib//libclntsh.so: -wrong ELF class: ELFCLASS64 -ld: fatal: File processing errors. No output written to -blib/arch/auto/DBD/Oracle/Oracle.so -collect2: ld returned 1 exit status -*** Error code 1 -make: Fatal error: Command failed for target -`blib/arch/auto/DBD/Oracle/Oracle.so' - -// *****************************************************/ - -So, as another set on Google' posts showed that it is a possibility of -missing libraries compiled with 64 bits and same libraries compiled with -32 bits suppoert. As I understood, all components of installation, such -as Oracle client, Perl, GCC should support only one type of libraries, -either 32 or 64 bits. I found that having all as 32 bits is easier to me -than recompile perl, gcc as 64 (may be I am wrong in this assumption). -In order to have all of them as 32 bits, I changed lib to lib32 in -Manifest file (not Manifest.PL). - -You should replace the following lines in the "MakeMaker const_loadlibs -section": - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -By their lib32 clones: - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -And replace this line in "MakeMaker dynamic_lib section" (~~ line 491) - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread - -By its lib32 clone: - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread - -I hope, that after that process passes without any errors. Here is last -part, that I got during <>: - -..... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/local/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL -ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/local/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" -blib/script/ora_explain -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oracle.3 -Manifying blib/man3/DBD::Oraperl.3 - -III. Once we build the module, we should test it, to make sure that it -works fine. You should run <> to do it: - -Check that you have ORACLE_HOME, ORACLE_USERID, ORACLE_SID environment -variables set, like this: - -ORACLE_HOME=="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0 -ORACLE_USERID=STARSHIP/STARSHIP -ORACLE_SID=COLORADO - -When you run <>, you will probably get this errors: - -// ************************ Error 3 ***********************/ - -bash-2.05# make test -PERL_DL_NONLAZY=1 /usr/local/bin/perl "-MExtUtils::Command::MM" "-e" -"test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............DBI connect('','STARSHIP/STARSHIP',...) failed: -ORA-12545: Connect failed because target host or object does not exist -(DBD ERROR: OCIServerAttach) at t/10general.t line 12 -Undefined subroutine &main::BAILOUT called at t/10general.t line 15. -# Looks like your test died before it could output anything. -t/10general.............dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-31 - Failed 31/31 tests, 0.00% okay -..... - -// *****************************************************/ - -One more brainstorm, and I figured out another way to set ORACLE_USERID: - -ORACLE_USERID=STARSHIP/STARSHIP@COLORADO -ORACLE_SID=COLORADO - -Later, when tests finished, I was confirmed that it was probably -preferred way of setting ORACLE_USERID. -Tests did found correct settings, and "main" set of them returned the -following report: - -All tests successful, 1 test and 122 subtests skipped. -Files=18, Tests=1020, 24 wallclock secs (11.27 cusr + 1.34 csys = 12.61 -CPU) - -For the Extra test, less formal, but test anyway, I just commented these -two lines in test.pl file - -$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -and set the same values in the same form to the $dbuser as it was in -ORACLE_USERID , and -left $dbname empty, - -$dbname = ''; -$dbuser = 'STARSHIP/STARSHIP@COLORADO'; - -and got pretty good report: - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - -recommended) - as 'STARSHIP/STARSHIP@COLORADO' (via ORACLE_USERID env var or default - -recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -Fields: 6 -Names: 'NUM_T' 'DATE_T' 'CHAR_T' 'ROWID_T' -'RAW_T' 'NULL_T' -Lengths: 172 76 121 21 3 1 -OraTypes: 2 12 1 104 23 1 -SQLTypes: 8 93 12 -9104 -2 12 -Scale: 0 0 0 0 0 0 -Precision: 126 75 120 20 2 0 -Nullable: 1 1 1 1 1 1 -Est row width: 32 -Data rows: - fetch: '7.2', '21-DEC-04', 'STARSHIP', 'AAAADeAABAAAAZSAAA', '7D', -undef - -ora_logoff... -lda out of scope... - -Testing repetitive connect/open/close/disconnect: -If this test hangs then read the README.help file. -Expect sequence of digits, no other messages: -1 2 3 4 5 - -Test interaction of explicit close/logoff and implicit DESTROYs -Expect just 'done.', no other messages: -done. - -Testing row cache (5). -Test completed in 0 seconds. - -Test complete (0 seconds). -If the tests above have produced the 'expected' output then they have -passed. - -IV. The last part is actually target of all steps above, installing -build module. < did not surprise me, and it it passed -smoothly. - -bash-2.05# make install -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/dbdimp -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/ocitra -ce.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/mk.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.so -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.bs -Files found in blib/arch: installing files in blib/lib into architecture -dependent library tree -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/oraperl.ph -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/Oraperl.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle/GetInfo.pm -Installing /usr/local/share/man/man1/ora_explain.1 -Installing /usr/local/share/man/man3/DBD::Oracle.3 -Installing /usr/local/share/man/man3/DBD::Oraperl.3 -Installing /usr/local/bin/ora_explain -Writing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/.packl -ist -Appending installation info to -/usr/local/lib/perl5/5.8.5/sun4-solaris/perllocal.pod - -V. This is actually it, and you do not need to do anything else. But -investigating different errors during the various steps, I found the -very simple "independent sanity" testdbi perl script written by Jeff -Hunter. This script is not related to standard process of -making/buildin/testing/installation. It just verifies that you can -access DB and run a couple queries against it. The code itself, -testdbi.pl can be found at -http://www.idevelopment.info/data/Oracle/DBA_tips/Programming/PROGRAMMIN -G_2.shtml - -You just should set connection information, similar to how I did it, - - $ORACLE_SID = "COLORADO"; - $ORACLE_USERID = "STARSHIP"; - $ORACLE_PASSWORD = "STARSHIP"; - - $ENV{'ORACLE_SID'} = "$ORACLE_SID"; - $ENV{'ORACLE_HOME'} = /u01/app/oracle/product/9.2.0.1.0"; - -run it as any perl script, <>, and see result: - -bash-2.05# perl testdbi.pl - -Running testdbi.pl... - - (*) Attempting Oracle Login ... - OK - (*) Creating table TEST_DBI ... - OK - (*) Insert into TEST_DBI ... - 1 rows inserted. - 1 rows inserted. - 1 rows inserted. - OK - (*) Select from TEST_DBI ... - - --> TEST_DBI_INTR_NO : 1000 - --> TEST_DBI_NAME : Jeff Hunter - - --> TEST_DBI_INTR_NO : 1001 - --> TEST_DBI_NAME : Melody Hunter - - --> TEST_DBI_INTR_NO : 1002 - --> TEST_DBI_NAME : Alex Hunter - OK - - (*) Delete from TEST_DBI ... - 3 rows deleted. - OK - - (*) Drop table TEST_DBI ... - OK - - (*) Select USER and SYSTEM ... - - --> USER : STARSHIP - --> SYSDATE : 21-DEC-2004 16:49:59 - OK - - (*) Attempting Oracle Logoff ... - OK - -Ending testdbi.pl... - -With the best regards, - -Alex Zarutin - -Software Engineer -4thpass A Motorola Company -Seattle, WA -www.4thpass.com - - - - diff --git a/err_build/err_testfailnotable.msg b/err_build/err_testfailnotable.msg deleted file mode 100644 index 687d5ed7..00000000 --- a/err_build/err_testfailnotable.msg +++ /dev/null @@ -1,97 +0,0 @@ -From SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 18:10:51 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RHAOAK026067 - for ; Wed, 27 Oct 2004 18:10:51 +0100 (BST) - (envelope-from SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 18:10:51 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMp30-0000e2-Hh; - Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMp30-0000e2-Hh - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMp30-0001QS-2p - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 87C155A7D; - Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 7779A59A1 - for ; Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Received-SPF: pass (gold.pobox.com: domain of dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by gold.pobox.com (Postfix) with SMTP id DC5795A4A - for ; Wed, 27 Oct 2004 10:45:07 -0400 (EDT) -Received: (qmail 18140 invoked by uid 514); 27 Oct 2004 14:45:04 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 18131 invoked from network); 27 Oct 2004 14:45:04 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 14:45:04 -0000 -Received: (qmail 8663 invoked by uid 225); 27 Oct 2004 14:45:03 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 8659 invoked by alias); 27 Oct 2004 14:45:03 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from ns2.aramiska.net (HELO dmzms01.aramiska.net) (80.242.32.2) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 07:45:01 -0700 -Received: from ip-80-242-36-115.aramiska-arc.aramiska.net (ip-80-242-36-115.aramiska-arc.aramiska.net [80.242.36.115]) - by dmzms01.aramiska.net (Postfix) with ESMTP - id 9F21E1100D9; Wed, 27 Oct 2004 14:44:55 +0000 (UTC) -Received: from localhost (localhost [127.0.0.1]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id E558E7C; Wed, 27 Oct 2004 14:44:52 +0000 (UTC) -Received: from dansat.data-plan.com (ip-192-168-0-3.internal.data-plan.aramiska.net [192.168.0.3]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id D8A5E71; Wed, 27 Oct 2004 14:44:50 +0000 (UTC) -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9REioAA023212; - Wed, 27 Oct 2004 15:44:50 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i9REinmW023211; - Wed, 27 Oct 2004 15:44:49 +0100 (BST) -Date: Wed, 27 Oct 2004 15:44:49 +0100 -From: Tim Bunce -To: "H.Merijn Brand" -Cc: Tim Bunce , DBI developers -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Message-ID: <20041027144449.GB19991@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> <20041027093516.D001.H.M.BRAND@hccnet.nl> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20041027093516.D001.H.M.BRAND@hccnet.nl> -User-Agent: Mutt/1.4i -X-Virus-Scanned: by Aramiska Arc -Status: RO -Content-Length: 634 -Lines: 14 - -On Wed, Oct 27, 2004 at 09:39:33AM +0200, H.Merijn Brand wrote: -> On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> > file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> > size: 235224 bytes -> > md5: 9711550ed0ebfc743920a6a357ed717c -> -> I know you can't blame the test for not being able to create a table for the -> reason this failure shows, but there might be a more user-friendly way to fail ... - -Yeap. Some tests behave better in that situation. Looks like those -two need improving. Patches welcome! (I'd happily not touch DBD::Oracle -for a few months after the pain of the last few months :) - -Tim. - diff --git a/err_docs/err_trace.msg b/err_docs/err_trace.msg deleted file mode 100644 index 3d7500fb..00000000 --- a/err_docs/err_trace.msg +++ /dev/null @@ -1,14 +0,0 @@ -Add this to the DBD::Oracle docs as a handy note: - -$dbh->do(q{alter session set events '65285 trace name errorstack level 3'}); - -A trace file should then be generated. - -Trace files are generated in the 'user_dump_destination' specified in init.ora. - -Try $ORACLE_BASE/admin/$ORACLE_SID/udump. - -or the location returned by -select value -from v$parameter -where name like '%user_dump%' diff --git a/err_lob/err_csr_clob.msg b/err_lob/err_csr_clob.msg deleted file mode 100644 index 397d53b3..00000000 --- a/err_lob/err_csr_clob.msg +++ /dev/null @@ -1,65 +0,0 @@ -From dbi-users-bounce@isc.org Thu Sep 21 20:27:21 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id UAA18945; Thu, 21 Sep 2000 20:27:20 +0100 (BST) -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <02709-1@oink>; Mon, 21 Sep 1970 20:26:40 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 969564156:20:26825:1; Thu, 21 Sep 2000 19:22:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-2.mail.demon.net - id aa2026778; 21 Sep 2000 19:22 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 28A613E5D; - Thu, 21 Sep 2000 12:22:17 -0700 (PDT) -Received: with LISTAR (v1.0.0; list dbi-users); - Thu, 21 Sep 2000 12:17:37 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A59853E42 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) -Received: from wheel.cs.wisc.edu (wheel.cs.wisc.edu [128.105.121.12]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA00855 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) env-from (horn@wheel.cs.wisc.edu) -Received: (from horn@localhost) by wheel.cs.wisc.edu (8.9.2/8.9.2) id OAA16413 - for dbi-users@isc.org; Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -Date: Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -From: Jeffrey Horn -Message-Id: <200009211917.OAA16413@wheel.cs.wisc.edu> -To: dbi-users@isc.org -Subject: Setting ORA_TYPE after the fact... -Sender: horn@wheel.cs.wisc.edu -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: horn@cs.wisc.edu -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -X-Status: A -Content-Length: 969 -Lines: 20 - -I have a situation where I would like to return a cursor that contains a -CLOB as one of it's attributes from a PL/SQL procedure. What I get back is -a LOB locator and DBD doesn't actually read the CLOB but instead returns an -error. - -If I go through a bind/prepare/execute/fetch on a similar SQL statement all -is well. Is there any way that I can tell DBD that a given attribute of -a cursor is a CLOB once the cursor is already opened so that DBD will do the -right thing? - --- Jeff Horn - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_lob/err_loblenwide.msg b/err_lob/err_loblenwide.msg deleted file mode 100644 index 08023e97..00000000 --- a/err_lob/err_loblenwide.msg +++ /dev/null @@ -1,95 +0,0 @@ -From nobody@fsck.com Thu Dec 4 07:36:20 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hB47Y2nE066844 - for ; Thu, 4 Dec 2003 07:36:20 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 04 Dec 2003 07:36:20 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1ARgrA-0005O4-5M; - Wed, 03 Dec 2003 23:56:32 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1ARgrA-0005O4-5M - for pobox@dbi.demon.co.uk; Wed, 03 Dec 2003 23:56:32 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 314AB9A28F - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 188369A287 - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com[63.251.223.170]) - by icicle.pobox.com (Postfix) with SMTP - for ; Wed, 3 Dec 2003 18:56:31 -0500 (EST) -Received: (qmail 3178 invoked by uid 225); 3 Dec 2003 23:56:30 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 3174 invoked by alias); 3 Dec 2003 23:56:29 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Wed, 03 Dec 2003 15:56:18 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 91512114F1; Wed, 3 Dec 2003 18:56:07 -0500 (EST) -Subject: [cpan #4564] Perl DBI bug handling CLOBs -From: "Jay Turner via RT" -Reply-To: bug-DBI@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4564 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: J.Turner@mdl.com -To: "AdminCc of cpan Ticket #4564": ; -Date: Wed, 3 Dec 2003 18:56:07 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -X-Status: A -Content-Length: 1853 -Lines: 46 - - -This message about DBI was sent to you by J.Turner@mdl.com via rt.cpan.org - -Full context and any attached attachments can be found at: - - - -Date: Fri, 28 Feb 2003 16:55:28 -0800 - -It has come to my attention that PERL DBI counts on OCILobGetLength -returning BYTES. It returns CHARACTERS instead, which is the count of -variable-width characters. For multi-byte character sets this results -in errors such as: - -DBD::Oracle::st fetch failed: ORA-03130: the buffer for the next piece -to be fetched is required (DBD ERROR: OCILobGetLength) at id rmsc01.pl -line 294. - -The correct way to read CLOBs is - -1) Query the LOB locator for the CSID and CSFRM (character set ID and -form). A character set >= 800 is a mulitbyte character set and csfrm -<> 0 is CLOB. - -2) Pass the CSID and CSFRM to OCILobRead with AMT=0 and pass your -buffer address and size. - -3) Your callback routine must either be capable of completing the I/O -by allocating additional buffers, or it must notify the caller of -OCILobRead to free the lob locator, since an incomplete read jams the -locator-you can't use it for anything else without finishing the read -(attempts to reuse the locator will result in errors). - -Likewise, with OCILobWrite, you have to pass the CSID and CSFRM, with -AMT=0 and the buffer size in bytes. The callback can just say it has -zero bytes and set piece=OCI_LAST_PIECE. - -You cannot use the return value of OCILobGetLength as the size of the -data that is being read. The actual size of the data is unknown for -variable-width characters, and the buffer has to be big enough to -accomplish the translation, so you can't just double or triple the -return value from OCILobGetLength (I have seen that approach fail). - -You can simulate the effects of a foreign character set by - -$ export NLS_LANG=Japanese - diff --git a/err_lob/err_lobtesttblfail.msg b/err_lob/err_lobtesttblfail.msg deleted file mode 100644 index 1333ee88..00000000 --- a/err_lob/err_lobtesttblfail.msg +++ /dev/null @@ -1,208 +0,0 @@ -From SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 15:22:22 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RELAAO018624 - for ; Wed, 27 Oct 2004 15:22:22 +0100 (BST) - (envelope-from SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 15:22:22 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMiQ8-0000Eo-FG; - Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMiQ8-0000Eo-FG - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMiQ8-0006dS-9n - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B3BB911C325; - Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9947911C2CE - for ; Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Received-SPF: pass (icicle.pobox.com: domain of dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by icicle.pobox.com (Postfix) with SMTP id 5033611C34F - for ; Wed, 27 Oct 2004 03:39:46 -0400 (EDT) -Received: (qmail 12004 invoked by uid 514); 27 Oct 2004 07:39:43 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 11995 invoked from network); 27 Oct 2004 07:39:43 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 07:39:43 -0000 -Received: (qmail 13565 invoked by uid 225); 27 Oct 2004 07:39:43 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 13560 invoked by alias); 27 Oct 2004 07:39:42 -0000 -X-Spam-Status: No, hits=-3.7 required=8.0 - tests=BAYES_00,LARGE_HEX -X-Spam-Check-By: la.mx.develooper.com -Received: from smtp-vbr15.xs4all.nl (HELO smtp-vbr15.xs4all.nl) (194.109.24.35) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 00:39:40 -0700 -Received: from [127.0.0.1] (procura.xs4all.nl [213.84.163.145]) - by smtp-vbr15.xs4all.nl (8.12.11/8.12.11) with ESMTP id i9R7dWHI013040; - Wed, 27 Oct 2004 09:39:34 +0200 (CEST) - (envelope-from h.m.brand@hccnet.nl) -Date: Wed, 27 Oct 2004 09:39:33 +0200 -From: "H.Merijn Brand" -To: Tim Bunce -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Cc: DBI developers -In-Reply-To: <20041022213625.GA22377@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> -Message-Id: <20041027093516.D001.H.M.BRAND@hccnet.nl> -MIME-Version: 1.0 -Content-Type: text/plain; charset="US-ASCII" -X-Mailer: Becky! ver. 2.11.02 [en] -X-Virus-Scanned: by XS4ALL Virus Scanner -X-Virus-Checked: Checked -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i9RELAAO018624 -Status: RO -X-Status: A -Content-Length: 7175 -Lines: 134 - -On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> size: 235224 bytes -> md5: 9711550ed0ebfc743920a6a357ed717c - -I know you can't blame the test for not being able to create a table for the -reason this failure shows, but there might be a more user-friendly way to fail ... - -I'll report back when the DBA has fixed the tablespace - -HP-UX 11.11/64 (11i) + Oracle-9.2.0/64 + perl-5.8.5-dor/64 - -PERL_DL_NONLAZY=1 /pro/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, -'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............ok -t/15nls.................ok -t/20select..............ok -t/21nchar............... Database and client versions and character sets: -Database 9.2.0.1.0 CHAR set is US7ASCII (Non-Unicode), NCHAR set is AL16UTF16 ( -nicode) -Client 9.2.0.1 NLS_LANG is '', NLS_NCHAR is '' -t/21nchar...............ok -t/22nchar_al32utf8......ok -t/22nchar_utf8..........ok -t/23wide_db.............skipped - all skipped: Database character set is not Unicode -t/23wide_db_8bit........skipped - all skipped: Database character set is not Unicode -t/23wide_db_al32utf8....skipped - all skipped: Database character set is not Unicode -t/24implicit_utf8.......ok -t/25plsql...............ok -t/30long................ok 188/470DBD::Oracle::db do failed: ORA-03237: Initial -Extent of specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: -OCIStmtExecute) [for Statement "create table dbd_ora__drop_me ( idx integer, ln - NCLOB, dt date )"] at t/nchar_test_lib.pl line 356. -t/30long................ok 189/470DBD::Oracle::st execute failed: ORA-00942: ta -le or view does not exist (DBD ERROR: error possibly near <*> indicator at char -12 in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statem -nt "insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1= -0, :p2='0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X...'] at t/30long.t line 153. -# Failed test (t/30long.t at line 153) -t/30long................NOK 190DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=41, -:p2='12345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -...'] at t/30long.t line 154. -# Failed test (t/30long.t at line 154) -t/30long................NOK 191DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=42, -:p2='2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -...'] at t/30long.t line 155. -t/30long................NOK 192# Failed test (t/30long.t at line 155) -DBD::Oracle::st execute failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 12 in 'insert into <*>dbd_ora__dr -p_me values (:p1, :p2, SYSDATE)') [for Statement "insert into dbd_ora__drop_me -alues (?, ?, SYSDATE)" with ParamValues: :p1=43, :p2=undef] at t/30long.t line -56. -# Failed test (t/30long.t at line 156) -t/30long................NOK 193DBD::Oracle::db prepare failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 14 -in 'select * from <*>dbd_ora__drop_me order by idx') [for Statement "select * f -om dbd_ora__drop_me order by idx"] at t/30long.t line 170. -# Failed test (t/30long.t at line 170) -Can't call method "trace" on an undefined value at t/30long.t line 171. -t/30long................NOK 194# Looks like you planned 470 tests but only ran -94. -# Looks like your test died just after 194. -t/30long................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 190-470 - Failed 281/470 tests, 40.21% okay (less 122 skipped tests: 67 okay, 14. -6%) -t/31lob.................DBD::Oracle::db do failed: ORA-03237: Initial Extent of -specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: OCIStmtEx -cute) [for Statement " - CREATE TABLE dbd_ora__drop_me ( - id INTEGER NOT NULL, - data BLOB - ) - "] at t/31lob.t line 21. -DBD::Oracle::db do failed: ORA-00942: table or view does not exist (DBD ERROR: -rror possibly near <*> indicator at char 12 in 'INSERT INTO <*>dbd_ora__drop_me -(id,data) VALUES (1, EMPTY_BLOB())') [for Statement "INSERT INTO dbd_ora__drop_ -e (id,data) VALUES (1, EMPTY_BLOB())"] at t/31lob.t line 31. -DBD::Oracle::db prepare failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 17 in 'SELECT data FROM <*>dbd_or -__drop_me WHERE id = :p1') [for Statement "SELECT data FROM dbd_ora__drop_me WH -RE id = ?"] at t/31lob.t line 34. -Can't call method "bind_param" on an undefined value at t/31lob.t line 36. -# Looks like your test died before it could output anything. -t/31lob.................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-2 - Failed 2/2 tests, 0.00% okay -t/40ph_type.............ok -t/50cursor..............ok -t/60reauth..............ORACLE_USERID_2 not defined. Tests skipped. -skipped - all skipped: no reason given -t/70meta................ok -Failed Test Stat Wstat Total Fail Failed List of Failed -------------------------------------------------------------------------------- -t/30long.t 255 65280 470 557 118.51% 190-470 -t/31lob.t 255 65280 2 4 200.00% 1-2 -4 tests and 122 subtests skipped. -Failed 2/18 test scripts, 88.89% okay. 283/1883 subtests failed, 84.97% okay. -make: *** [test_dynamic] Error 255 - --- -H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/) -using perl-5.6.1, 5.8.0 & 633 on HP-UX 10.20 & 11.00, AIX 4.2, AIX 4.3, - WinNT 4, Win2K pro & WinCE 2.11 often with Tk800.024 &/| DBD-Unify -ftp://ftp.funet.fi/pub/languages/perl/CPAN/authors/id/H/HM/HMBRAND/ - - - - diff --git a/err_lob/err_nclob_form.msg b/err_lob/err_nclob_form.msg deleted file mode 100644 index 05587693..00000000 --- a/err_lob/err_nclob_form.msg +++ /dev/null @@ -1,189 +0,0 @@ -From dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org Tue Jul 22 07:40:59 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6M6UUD7096422 - for ; Tue, 22 Jul 2003 07:40:58 +0100 (BST) - (envelope-from dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 22 Jul 2003 07:40:58 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058814697:11:26523:33; Mon, 21 Jul 2003 19:11:37 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1126786; 21 Jul 2003 19:11 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E855B21C37F - for ; Mon, 21 Jul 2003 15:11:18 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 9010121C236 - for ; Mon, 21 Jul 2003 15:11:17 -0400 (EDT) -Received: (qmail 66848 invoked by uid 1005); 21 Jul 2003 19:11:15 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 66832 invoked by uid 76); 21 Jul 2003 19:11:15 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 21 Jul 2003 12:11:15 -0700 -Received: (qmail 559 invoked by uid 225); 21 Jul 2003 19:11:08 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 552 invoked by uid 507); 21 Jul 2003 19:11:07 -0000 -Received-SPF: unknown -Received: from sneakemail.com (HELO monkey.sneakemail.com) (207.106.87.13) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Mon, 21 Jul 2003 12:11:03 -0700 -Received: (qmail 22505 invoked by uid 501); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #3); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #2); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #1); 21 Jul 2003 19:10:57 -0000 -Date: Mon, 21 Jul 2003 21:10:53 +0200 -From: "Wolfgang Weisselberg" -To: dbi-users@perl.org -Subject: DBD::Oracle and unicode-NCLOBs leads to ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) -Message-ID: <13502-46198@sneakemail.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.6 required=7.0 tests=CARRIAGE_RETURNS,FROM_ENDS_IN_NUMS,FROM_HAS_MIXED_NUMS,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_MUTT version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 6055 -Lines: 132 - -Hello all! - -Even after extensive googling and looking through the docs I fail -to fetch NCLOBs from an Oracle 9.2i database where the national -character set is unicode. - -I believe it has been done before, but I could not find anything ... -I would be grateful for any pointers. - - -NCLOBs work like CLOBs when the national character set is not -unicode, even with the old DBI 1.21 and DBD::Oracle 1.12 on an -Oracle 8 client. NVarchar2 and NChar work OK even with unicode. - -Setting NSL_LANG to AMERICAN_AMERICA.UTF8 or .AL32UTF8 does not -help, as I suspected. - -I tried using Oracle 9.2i (the DB is using 9.2i) on a Debian -Linux box. I upgraded DBI to 1.37 and DBD::Oracle to 1.14 (the -newest versions according to CPAN). I got zero errors on make -test with both. Perl is Debian's normal "perl5 (revision 5.0 -version 6 subversion 1)". - -A simple - select memo from unicode_test -(memo being the NCLOB field) fails (again, only with the national -charset being unicode). - -The relevant code snippet (RaiseError being set, of course): - -| $| = 1; -| print "DBI: $DBI::VERSION\n", -| "DBD::Oracle $DBD::Oracle::VERSION\n"; -| my $sth = $dbh->prepare("select memo from unicode_test"); -| $sth->execute(); -| -| while ( my ($memo) = $sth->fetchrow_array() ) { -| print Dumper $memo; -| } -| exit; - - -The output: - -| DBI: 1.37 -| DBD::Oracle 1.14 -| $VAR1 = ''; -| $VAR1 = ''; -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. - - - -Running with tracelevel 3: - [...] -| dbd_st_prepare'd sql SELECT -| dbd_describe SELECT (EXPLICIT, lb 99999999)... -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_execute SELECT (out0, lob0)... -| dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -| <- execute= '0E0' at nclobtest.pl line 79 via nclobtest.pl line 60 -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -| 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x82f8e28)~INNER 'ParamValues') -| error: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| 1 <- FETCH= HASH(0x831661c)0keys at nclobtest.pl line 81 via nclobtest.pl line 60 -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. - - - -Tracelevel 9 (yes, it's a bit verbose :-/ ) - -[...] -| OCIDescriptorAlloc(0x831c058,0x8395228,OCI_DTYPE_LOB,0,0) -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| OCIAttrSet(0x8335b34,OCI_HTYPE_STMT,0xbffff30c,4,11,0x832d5a4)=SUCCESS -| OCIDefineByPos(0x8335b34,0x8395224,0x832d5a4,1,0x8395228,-1,112,0x83414e0,0x83414f0,0x8341500,0)=SUCCESS -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -[...] -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| 0 (rc=0): '' -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead(0x832d530,0x832d5a4,0x832c69c,0xbffff318,1,0x8394da0,24,(nil),(nil),0,1)=ERROR -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| OCIErrorGet(0x832d5a4,1,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=SUCCESS -| OCIErrorGet after OCILobRead (er1:ok): -1, 24806: ORA-24806: LOB form mismatch -| -| OCIErrorGet(0x832d5a4,2,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=NO_DATA -| 0 (rc=0): undef -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -[gets and prints error message] - - -Any ideas anyone? - --Wolfgang - diff --git a/err_lob/err_nulllobsegv.msg b/err_lob/err_nulllobsegv.msg deleted file mode 100644 index 6de3c99b..00000000 --- a/err_lob/err_nulllobsegv.msg +++ /dev/null @@ -1,93 +0,0 @@ -From dbi-users-return-1743-Tim.Bunce=ig.co.uk@perl.org Wed Apr 11 04:00:48 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id EAA17912; Wed, 11 Apr 2001 04:00:48 +0100 (BST) -Received: from 194.217.242.36 by oink with SMTP (PP) id <02579-1@oink>; - Sat, 11 Apr 1970 04:00:28 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 986956750:10:04398:0; Wed, 11 Apr 2001 02:39:10 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-1.mail.demon.net - id aa1106187; 11 Apr 2001 2:39 GMT -Received: (qmail 32618 invoked by uid 508); 11 Apr 2001 02:39:06 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 32603 invoked from network); 11 Apr 2001 02:39:05 -0000 -Received: from owns.warpcore.org (216.81.249.18) by tmtowtdi.perl.org with SMTP; - 11 Apr 2001 02:39:05 -0000 -Received: (from thebrain@localhost) by owns.warpcore.org (8.11.1/8.11.1) - id f3B2cxH06298 for dbi-users@perl.org; - Tue, 10 Apr 2001 21:38:59 -0500 -Date: Tue, 10 Apr 2001 21:38:59 -0500 -From: Stephen Clouse -To: dbi-users@perl.org -Subject: Bizarre DBD::Oracle Segfault -Message-ID: <20010410213859.B2766@owns.warpcore.org> -Mail-Followup-To: dbi-users@perl.org -Mime-Version: 1.0 -Content-Type: text/plain -Content-Disposition: inline; filename="msg.pgp" -User-Agent: Mutt/1.2.5i -Status: RO -Content-Length: 1918 -Lines: 54 - ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -I sent an email to the dbi-users list about a number of DBD::Oracle CLOB -handling problems waaaaaaaaaaaaaaay back (end of January or so) that today -someone dug up and inquired if I had ever found fixes for what I had pointed -out. - -The problems outlined that day turned out to be the test script itself, which -was doing so much bizarre stuff on one statement that DBD::Oracle just went to -sleep instead (and so was the actual program that instigated the writing of the -test script). - -Well, all but one problem was the script. This, the most serious one, continues -to linger: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',undef); - -On Linux, DBI 1.15, Oracle 8.1.6, and DBD::Oracle 1.06, this segfaults on the -execute. Unfortunately this manifests itself too deep in Oracle for me to -debug. - -The bizarre part is, either of the two snippets below will work: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',''); -$st->execute('B','B',undef); - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',$lobvalue); -$st->execute('B','B',undef); - -It's only when binding undef as the LOB value in the very first execute of a -statement that the segfault occurs. At any other time, it's kosher. That -qualifies as bizarre in my book. - -Your guess is better than mine. - -- -- -Stephen Clouse -Senior Programmer, IQ Coordinator Project Lead -The IQ Group, Inc. - ------BEGIN PGP SIGNATURE----- -Version: PGP 6.5.8 - -iQA+AwUBOtPDwgOGqGs0PadnEQLmtgCeJHTStLu8Q8oFb9UQ4995f8vhZH8Al1p6 -RD5m0FEJH2tQiY0+b6542mQ= -=L0M+ ------END PGP SIGNATURE----- - diff --git a/err_lob/err_tmplobfree.msg b/err_lob/err_tmplobfree.msg deleted file mode 100644 index 0ec8f940..00000000 --- a/err_lob/err_tmplobfree.msg +++ /dev/null @@ -1,537 +0,0 @@ -From SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com Wed Aug 25 17:53:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PGpkpQ033405 - for ; Wed, 25 Aug 2004 17:53:57 +0100 (BST) - (envelope-from SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 17:53:57 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Bzyve-0007kY-Gp; - Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Bzyve-0007kY-Gp - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Bzyvd-0000zb-Lg - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id AA6D8B0635; - Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 9B2A1B0BB0 - for ; Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -Received: from natnoddy.rzone.de (natnoddy.rzone.de [81.169.145.166]) - by lime.pobox.com (Postfix) with ESMTP id 2AAB1B0635 - for ; Wed, 25 Aug 2004 10:39:06 -0400 (EDT) -Received: from genericom.de (pD95195AC.dip.t-dialin.net [217.81.149.172]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7PEc05w018990 - for ; Wed, 25 Aug 2004 16:38:01 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412CA445.FC2F9EF2@genericom.de> -Date: Wed, 25 Aug 2004 16:37:57 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim.Bunce@pobox.com -Subject: DBD::Oracle: Freeing a temporary blob -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms4BC2D4519D41A502BB06559C" -Status: RO -X-Status: A -Content-Length: 4985 -Lines: 122 - -This is a cryptographically signed message in MIME format. - ---------------ms4BC2D4519D41A502BB06559C -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Dear Tim, - -first, I would really like to thank you for the great work you have done -with your DBI/DBD work. We are using it extensively in several projects -and we are highly pleased. - -Unfortunately I have now encountered a problem we need to fix urgently, -since our customer's production is seriously affected. - -We tried for many days to find a solution (google, newsgroups, -trial-and-error...), without luck. So my last chance is to contact you -directly, although I assume you have a lot work yourself. - ---- - -The problem: - -Our database contains a stored function "ReadUnitBlob()" that returns a -temporary blob: - -function ReadUnitBlob(UnitID_IN in integer) return blob -is -... -begin - ... - dbms_lob.createtemporary(retBlob, false, dbms_lob.call); - dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); - ... - return retBlob; -end; - -We call this function in Perl in a big loop to fetch a lot of blobs (~ -100000) using something like: - -my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -ora_auto_lob => 0 }); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); -my ($loc) = $sth->fetchrow_array(); -$sth->finish(); -... -while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) - ... - -Although this works, it has a big disadvantage: Oracle does not -automaticaly free the temporary blob, so it shortly runs out of temp. -space. (confirmed with "select * from v$temporary_lobs"). - -Acording to the Oracle docs this can be we solved by implicitly freeing -the temp. blob, e.g. by calling the PLSQL method -"dbms_lob.freetemporary()". I tried differnt ways to do this with -DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -locator from the my stored procedure and to pass it to a call of -"dbms_lob.freetemporary()": - -my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -ora_auto_lob => 0 }); -my $bloc; -$sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); - -obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) - -Can you help me??? Do you know a way how to free the temp. blob using -DBD::Oracle (using Oracle::OCI is not possible, since the customer is -strinctly refusing to install it). - -Otherwise, would it be possible include an additional DBD::Oracle LOB -Locator Method "ora_lob_freetemporary()" that warps -"OCILobFreeTemporary" ? - -Any help is really appreciated! - -Greeting from Germany, - - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------ms4BC2D4519D41A502BB06559C -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjUxNDM3NThaMCMGCSqG -SIb3DQEJBDEWBBS+u38esQAv19TdNkv4jgxlzsRqSzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAJQgoN5ASnyjnB7bgrv1+V7Cu4ULKe1CkHs0IEZaB -KuJcm98U7kskRyC5g6YNopuJxFbr19K3q5rrJGoUscKjiw== ---------------ms4BC2D4519D41A502BB06559C-- - - -From SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com Wed Aug 25 22:47:05 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PLjxpJ037568 - for ; Wed, 25 Aug 2004 22:47:04 +0100 (BST) - (envelope-from SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 22:47:04 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C04j1-00038v-Pz; - Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C04j1-00038v-Pz - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C04j0-00002I-FU - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:30 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AD1815463; - Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 85FFF55E7 - for ; Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Received-SPF: none (gold.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail04.svc.cra.dublin.eircom.net (mail04.svc.cra.dublin.eircom.net [159.134.118.20]) - by gold.pobox.com (Postfix) with SMTP id 14C005463 - for ; Wed, 25 Aug 2004 16:50:25 -0400 (EDT) -Received: (qmail 5678 messnum 5046341 invoked from network[213.94.228.233/unknown]); 25 Aug 2004 20:50:23 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail04.svc.cra.dublin.eircom.net (qp 5678) with SMTP; 25 Aug 2004 20:50:23 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PKsrof034865; - Wed, 25 Aug 2004 21:54:53 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7PKsqas034864; - Wed, 25 Aug 2004 21:54:52 +0100 (BST) -Date: Wed, 25 Aug 2004 21:54:52 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim.Bunce@pobox.com -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040825205452.GC34655@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412CA445.FC2F9EF2@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 4674 -Lines: 124 - -On Wed, Aug 25, 2004 at 04:37:57PM +0200, Philipp Lang wrote: -> Dear Tim, -> -> first, I would really like to thank you for the great work you have done -> with your DBI/DBD work. We are using it extensively in several projects -> and we are highly pleased. - -Thanks Philipp! - -> Unfortunately I have now encountered a problem we need to fix urgently, -> since our customer's production is seriously affected. -> -> We tried for many days to find a solution (google, newsgroups, -> trial-and-error...), without luck. So my last chance is to contact you -> directly, although I assume you have a lot work yourself. - -I am very busy and what little spare time I have for DBD::Oracle -is going into trying to get 1.16 released (which is proving to be -hard as we're tripping over Oracle bugs when an Oracle 8 client -talks to an Oracle 9+ server.) It's a major release that will help -many people so I need to give that priority. - -Separately I am exploring ways to fund DBI and DBD::Oracle development -so I can devote more time to it. There's is much that needs to be -done and much more that could be done beyond that. - -The Perl Foundation (TPF) have setup a way for people and companies -to make donations for DBI development [as yet unannounced so please -keep to yourself]. A note on the contribution could indicate that the -donor would like it used for a particular purpose, such as DBD::Oracle. - -Anyway, to cut a long story short, it would be much easier to devote -time to this if it could be funded in some way. - -I think the TPF setup is working so it could be done that way. -Alternatively you could contract me to do the work for you. -That would be quicker and simpler for you as TPF's non-profit -status doesn't make a difference to European donors. - -My standard daily rate for add-hoc consulting is 1600 Euro. -I'd expect to be able to sort this out inside a day, and prefer -fixed-price quotes anyway, so would 1600 Euro be okay? - -Of course, if you feel your company would like to either -make a general contribution to DBI/DBD::Oracle development beyond -that, or to fund the development of specific functionality that -would be of extra value to you then I'd be happy to talk about that. - -I hate asking for money, and would much rather dig into the code and -reply with a patch, but it's just not practical for me now. Sorry. - -Tim. - -> --- -> -> The problem: -> -> Our database contains a stored function "ReadUnitBlob()" that returns a -> temporary blob: -> -> function ReadUnitBlob(UnitID_IN in integer) return blob -> is -> ... -> begin -> ... -> dbms_lob.createtemporary(retBlob, false, dbms_lob.call); -> dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); -> ... -> return retBlob; -> end; -> -> We call this function in Perl in a big loop to fetch a lot of blobs (~ -> 100000) using something like: -> -> my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -> ora_auto_lob => 0 }); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> my ($loc) = $sth->fetchrow_array(); -> $sth->finish(); -> ... -> while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) -> ... -> -> Although this works, it has a big disadvantage: Oracle does not -> automaticaly free the temporary blob, so it shortly runs out of temp. -> space. (confirmed with "select * from v$temporary_lobs"). -> -> Acording to the Oracle docs this can be we solved by implicitly freeing -> the temp. blob, e.g. by calling the PLSQL method -> "dbms_lob.freetemporary()". I tried differnt ways to do this with -> DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -> locator from the my stored procedure and to pass it to a call of -> "dbms_lob.freetemporary()": -> -> my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -> ora_auto_lob => 0 }); -> my $bloc; -> $sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> -> obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) -> -> Can you help me??? Do you know a way how to free the temp. blob using -> DBD::Oracle (using Oracle::OCI is not possible, since the customer is -> strinctly refusing to install it). -> -> Otherwise, would it be possible include an additional DBD::Oracle LOB -> Locator Method "ora_lob_freetemporary()" that warps -> "OCILobFreeTemporary" ? -> -> Any help is really appreciated! -> -> Greeting from Germany, -> -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - -From SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com Thu Aug 26 14:06:45 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QD6Som051890 - for ; Thu, 26 Aug 2004 14:06:45 +0100 (BST) - (envelope-from SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 14:06:45 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0HX2-0003PB-Sd; - Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0HX2-0003PB-Sd - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0HX2-0003BR-F8 - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id DC4BFB0D27; - Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id CE95AB0D7D - for ; Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 81.169.145.165(natsmtp00.rzone.de) -Received: from natsmtp00.rzone.de (natsmtp00.rzone.de [81.169.145.165]) - by lime.pobox.com (Postfix) with ESMTP id 71107B0D27 - for ; Thu, 26 Aug 2004 06:30:56 -0400 (EDT) -Received: from genericom.de (pD9E61E09.dip.t-dialin.net [217.230.30.9]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7QAUoTY009695 - for ; Thu, 26 Aug 2004 12:30:51 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412DBBD7.2C124831@genericom.de> -Date: Thu, 26 Aug 2004 12:30:47 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------msB92907D67E7D4C0121D50420" -Status: O -X-Status: A -Content-Length: 3040 -Lines: 58 - -This is a cryptographically signed message in MIME format. - ---------------msB92907D67E7D4C0121D50420 -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Tim Bunce wrote: -> -> I hate asking for money, and would much rather dig into the code and -> reply with a patch, but it's just not practical for me now. Sorry. - -Thanks for your quick reply. I can fully understand your position in -this issue. We will need to submit this issue to our customer, and -eventually it will be their decision, since a) the problem technically -originates in external components -and b) our work is payed on a time and material basis. - -Thanks again, - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------msB92907D67E7D4C0121D50420 -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjYxMDMwNDhaMCMGCSqG -SIb3DQEJBDEWBBQbWUdl+peoD/lHpzCOnuQfzAsbJzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAXzFame8ymLqgf+7nZ4V7L9e9J+aG6z5ipa+iv76v -EFAg5QObdHdvTnq5QEAjEnLKgeUGvdgpS6PA0h+beEIeIA== ---------------msB92907D67E7D4C0121D50420-- - - -From SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com Thu Aug 26 16:42:55 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QFgKp1054926 - for ; Thu, 26 Aug 2004 16:42:55 +0100 (BST) - (envelope-from SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 16:42:55 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0L1E-0005sL-5Z; - Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0L1E-0005sL-5Z - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0L1E-0001t1-Cm - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 541E8AFAD6; - Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 1C39FB0747 - for ; Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail01.svc.cra.dublin.eircom.net (mail01.svc.cra.dublin.eircom.net [159.134.118.17]) - by lime.pobox.com (Postfix) with SMTP id BFBB5AFAD6 - for ; Thu, 26 Aug 2004 10:14:19 -0400 (EDT) -Received: (qmail 12246 messnum 7731352 invoked from network[213.94.228.233/unknown]); 26 Aug 2004 14:14:17 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail01.svc.cra.dublin.eircom.net (qp 12246) with SMTP; 26 Aug 2004 14:14:17 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QEItof052863; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7QEItr3052862; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) -Date: Thu, 26 Aug 2004 15:18:55 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040826141855.GC52359@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> <412DBBD7.2C124831@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412DBBD7.2C124831@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 926 -Lines: 25 - -Okay. Thanks. Let me know how it turns out. - -Tim. - -On Thu, Aug 26, 2004 at 12:30:47PM +0200, Philipp Lang wrote: -> Tim Bunce wrote: -> > -> > I hate asking for money, and would much rather dig into the code and -> > reply with a patch, but it's just not practical for me now. Sorry. -> -> Thanks for your quick reply. I can fully understand your position in -> this issue. We will need to submit this issue to our customer, and -> eventually it will be their decision, since a) the problem technically -> originates in external components -> and b) our work is payed on a time and material basis. -> -> Thanks again, -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - diff --git a/err_unicode/err_char.msg b/err_unicode/err_char.msg deleted file mode 100644 index d2a7a4a3..00000000 --- a/err_unicode/err_char.msg +++ /dev/null @@ -1,129 +0,0 @@ -From dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org Fri May 31 15:39:50 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g4VEdno73229 - for ; Fri, 31 May 2002 15:39:49 +0100 (BST) - (envelope-from dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 31 May 2002 15:39:49 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1022854157:20:06570:1; Fri, 31 May 2002 14:09:17 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2005972; 31 May 2002 14:08 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 210F42BF43 - for ; Fri, 31 May 2002 10:08:39 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (unknown [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 8D88B2BF11 - for ; Fri, 31 May 2002 10:08:38 -0400 (EDT) -Received: (qmail 47355 invoked by uid 1005); 31 May 2002 14:07:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 47340 invoked by uid 76); 31 May 2002 14:07:41 -0000 -Received: from wsrgeh.wsr.ac.at (HELO wsrgeh.wsr.ac.at) (143.130.16.2) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Fri May 31 14:07:41 2002 -0000 -Received: from dialog.wsr.ac.at (dialog.wsr.ac.at [143.130.50.66]) - by wsrgeh.wsr.ac.at (8.11.6/8.11.6) with ESMTP id g4VE8Or11772 - for ; Fri, 31 May 2002 16:08:24 +0200 -Received: (from hjp@localhost) - by dialog.wsr.ac.at (8.11.6/8.11.6) id g4VE8Nf12538 - for dbi-users@perl.org; Fri, 31 May 2002 16:08:23 +0200 -Date: Fri, 31 May 2002 16:08:23 +0200 -From: "Peter J. Holzer" -To: dbi-users@perl.org -Subject: Re: Insert a blank value into Oracle -Message-ID: <20020531160823.F28779@wsr.ac.at> -Mail-Followup-To: "Peter J. Holzer" , - dbi-users@perl.org -References: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw> -Mime-Version: 1.0 -Content-Type: multipart/signed; micalg=pgp-md5; - protocol="application/pgp-signature"; boundary="aZoGpuMECXJckB41" -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -In-Reply-To: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw>; from larry_wu@mail.gss.com.tw on Fri, May 31, 2002 at 06:38:45PM +0800 -Status: RO -Content-Length: 2819 -Lines: 74 - ---aZoGpuMECXJckB41 -Content-Type: text/plain; charset=iso-8859-1 -Content-Disposition: inline -Content-Transfer-Encoding: quoted-printable - -On 2002-05-31 18:38:45 +0800, Larry Wu (=A7d=A4l=B7=D3) wrote: -> I encountered a problem to insert a space value ( like ' ' ) into Oracle -> database. -[...] -> Unfortunately, I have a table A contained a not allow null column -> NotNullCol. Now I want to insert a row like below: ->=20 -> $sth =3D $dbh->prepare( qq{ insert into A ( KeyCol, NotNullCol ) -> values (?,?)} ); -> $sth->bind_param(1, '1'); -> $sth->bind_param(2, ' '); -> $sth->execute; ->=20 -> When I executed this file I got an error from Oracle: Can't insert NULL -> value into ( "A"."NotNullCol") (DBD ERROR: OCIStmtExecute). -> I think the space value was truncated in the process. Could any one tell = -me -> how to keep a blank space in my bind_param ? - -use DBD::Oracle qw(:ora_types); -[...] -$sth->bind_param(2, ' ', { ora_type =3D> ORA_CHAR }); - -This is a frequently asked question here. The default type for strings, -ORA_VARCHAR2, strips trailing blanks from strings. A few months ago, -during one of the diskussuions about this feature, Tim said that he -might add a way to change the default in a future version of -DBD::Oracle. If he doesn't, maybe a paragraph like the following should -be added to the doc (not sure where - it fits below "Using DBD::Oracle -with Oracle 8 - Features and Issues" but it isn't Oracle 8 specific): - - =3Dhead2 Inserting strings with trailing spaces - - OCI provides several string types which behave differently. - Unfortunately, none of them can store arbitrary perl strings. - By default, DBD::Oracle binds string variables as ORA_VARCHAR2, - which allows embedded NUL characters but strips trailing spaces. If - you need trailing spaces, but don't need embedded NUL characters, - you can explicetly bind the param to type ORA_CHAR with: - - $sth->bind_param(($field_num, $string_value, - { ora_type =3D> ORA_CHAR }); - - =20 - hp - ---=20 - _ | Peter J. Holzer | Aeltere Sources (also solche, die schon -|_|_) | Sysadmin WSR / LUGA | aelter als 12 Stunden sind) sollte man -| | | hjp@wsr.ac.at | bei Linux generell nicht einsetzen - -__/ | http://www.hjp.at/ | Real Time Linux?? -- Gerhard Schneider - ---aZoGpuMECXJckB41 -Content-Type: application/pgp-signature -Content-Disposition: inline - ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.0.6 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -iQDQAwUBPPeD11LjemazOuKpAQEtNAXUC6rFL0C0v6MNW/K5ggXcSDY7Xvrj6Ed/ -jqjHq2Dx+h2rIMWXCDIGZVphSG74u4FL41AQF/rzGR/e56qH7aAxVmaiLdQE/DRi -zzsoOHoPEg96FhHljDtCZyxHzsz9sRJ1dfW1PELn5r2OSYPPsVzMoeR4iEXnVjvV -ZYH/OfbKRKhysIHjcNYKcyQL87GXdjzCEas3Xz+jyxW2vqzGAwUfTim4ySY9rF37 -c5vopwrTFCsi58r1LccFhQqEfw== -=Xe8d ------END PGP SIGNATURE----- - ---aZoGpuMECXJckB41-- - diff --git a/err_unicode/err_twolongstr.msg b/err_unicode/err_twolongstr.msg deleted file mode 100644 index 5d6c357d..00000000 --- a/err_unicode/err_twolongstr.msg +++ /dev/null @@ -1,1256 +0,0 @@ -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Wed Nov 17 19:08:49 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAHJ8F8P027204 - for ; Wed, 17 Nov 2004 19:08:48 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 17 Nov 2004 19:08:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUUU6-0001mQ-FU; - Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUUU6-0001mQ-FU - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUUU6-0000DF-68 - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9D10A120BFA; - Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 8C898120BEF - for ; Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Received-SPF: none (icicle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by icicle.pobox.com (Postfix) with ESMTP id 362C6120BEC - for ; Wed, 17 Nov 2004 13:24:46 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 9C0CC244379 - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 17196-06 for ; - Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 3131324406F - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 10:22:44 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_006A_01C4CC8F.60A4F6F0" -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117173321.GA6272@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTMy6HoelzJHh9WSPaTpCdfuF1C4gABpsZg -Message-Id: <20041117182444.3131324406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 16865 -Lines: 527 - -This is a multi-part message in MIME format. - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -I did - it is attached to the posting. However, I will attach it again -here. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 9:33 AM -> To: Susan Cassidy -> Cc: dbi-users@perl.org -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> If you can post a small self-contained example that demonstrates -> the problem then I'll take a look. -> -> Tim. -> -> On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > I never got any response to my question about this problem. I -> thought I'd try again. -> > -> > -> > -> > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> 5.8.5. -> > -> > -> > -> > Thanks, -> > -> > Susan -> > -> > -> > -> > --------------------------------------------------------------------- -> ----------------------------------- -> > -> > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > Sent: Friday, November 05, 2004 10:23 AM -> > To: 'dbi-users@perl.org' -> > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for -> > insert into a LONG column' when data not LONG -> > -> > -> > -> > I had an application that was processing a bunch of xml and inserting -> into a table with a bunch of -> > VARCHAR2(4000) columns. -> > -> > -> > -> > A couple of the entries I was processing caused the 'ORA-01461: can -> bind a LONG value only for insert -> > into a LONG column' error. -> > -> > -> > -> > I put checks in for the length of the data, and nothing approached -> 4000 bytes in length. -> > -> > -> > -> > I tracked down some of the entries causing problems, and on certain -> specific data, if 2 columns -> > containing specific data are inserted together, I get this error. If -> only one of the 2 is inserted, I -> > do not get the error, regardless of which one of the two I insert. -> > -> > -> > -> > The lengths of the pieces of data are 1399 and 1397 characters. -> > -> > -> > -> > The data is somewhat odd-looking (we suspect some odd data is in this -> file), but there is no reason for -> > the error message to appear. -> > -> > -> > -> > Trace shows nothing helpful - it thinks the data is the right length. -> > -> > -> > -> > We've successfully inserted thousands of other, similar entries with -> no trouble. -> > -> > -> > -> > The basics are: -> > -> > #create table test_table (item1 varchar2(4000), item2 -> varchar2(4000)); -> > -> > -> > -> > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, ?)"; -> > -> > -> > -> > $sth=$dbh->prepare($statement) || -> > -> > errexit("bad prepare for stmt $statement, error: $DBI::errstr"); -> > -> > my $rc=$sth->execute(@vals) || -> > -> > errexit("can't execute statement: error: $DBI::errstr\n"); -> > -> > -> > -> > Trace shows: -> > -> > -> > -> > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > -> > -> prepare for DBD::Oracle::db (DBI::db=HASH(0x82d4178)~0x82d6580 -> 'INSERT INTO test_table -> > (item1,item2) VALUES (?, ?) -> > -> > ') thr#8148ff0 -> > -> > dbd_preparse scanned 2 distinct placeholders -> > -> > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl line -> 40 -> > -> > -> execute for DBD::Oracle::st (DBI::st=HASH(0x82d6640)~0x8149dcc -> 'version 11.2no service -> > password-encryptionservice -> > -> > udp-small-serversservice tcp-small-servers!hostname router1!!no ip -> domain-lookupip inspect name mysite -> > ftpip inspect name -> > -> > mysite smtpip inspect name mysite tcp!interface Ethernet0ip address -> 10.10.10.2 255.255.255.0ip -> > access-group 101 inip ins -> > -> > pect mysite inip inspect mysite outno keepalive!interface Serial0no -> ip addressencapsulation -> > frame-relay...' 'version 11.2 -> > -> > no service password-encryptionservice udp-small-serversservice tcp- -> small-servers!hostname router1!!no ip -> > domain-lookupip -> > -> > inspect name mysite ftpip inspect name mysite smtpip inspect name -> mysite tcp!interface Ethernet0ip -> > address 10.10.10.2 255 -> > -> > .255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite -> outno keepalive!interface Serial0no -> > ip addressencaps -> > -> > ulation frame-relayn...') thr#8148ff0 -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (type 0) -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (size -> 1399/1400/0, ptype 4, otype 1) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (type 0) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (size -> 1397/1398/0, ptype 4, otype 1) -> > -> > dbd_st_execute INSERT (out0, lob0)... -> > -> > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > <- execute= undef at test_insert_large.pl line 42 -> > -> > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> 'ParamValues') thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line 42 -> > -> > -> $DBI::errstr (&) FETCH from lasth=HASH -> > -> > >> DBD::Oracle::st::errstr -> > -> > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' -> > -> > -- DBI::END -> > -> > -> disconnect_all for DBD::Oracle::dr -> (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > -> > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > -> > Connect done -> > -> > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > -> > Size of vals is 2 -> > -> > val 1 size 1399, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!i -> > -> > nterface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11 -> > -> > .2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 IETF!router eigrp 69network -> > 10.0.0.0no auto-summar -> > -> > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0. -> > -> > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permit icmp 10.10.10.0 -> > 0.0.0.255 anyaccess- -> > -> > list 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-rep -> > -> > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 ad -> > -> > ministratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp a -> > -> > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 0.0.0.255 -> > time-exceededaccess-list 102 permit tcp -> > -> > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > val 2 size 1397, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11. -> > -> > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci 200 -> IETF!router eigrp 69network -> > 10.0.0.0no auto-summary -> > -> > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 0.0.0.0 -> 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0.0 -> > -> > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permiticmp 10.10.10.0 -> > 0.0.0.255 anyaccess-li -> > -> > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess-list -> 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-reply -> > -> > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 admi -> > -> > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp any -> > -> > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 time-exceededaccess-list -> > 102 permit tcp an -> > -> > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > can't execute statement: error: ORA-01461: can bind a LONG value only -> for insert into a LONG column (DBD -> > ERROR: OCIStmtEx -> > -> > ecute) -> > -> > -> > -> > ! -> DESTROY for DBD::Oracle::db (DBI::db=HASH(0x82d6580)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#0) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > -> > -> > I will attach the test program. Somehow it seems to think the -> datatype is LONG instead of VARCHAR. -> > -> > -> > -> > -> > -> > Anyone with ideas? -> > -> > -> > -> > -> > -> > Thanks, -> > -> > Susan -> - - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: application/octet-stream; - name="test_insert_large.pl" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="test_insert_large.pl" - -#!/usr/local/bin/perl -w=0A= -=0A= -use DBI;=0A= -=0A= -our $dbh;=0A= -our $sth;=0A= -=0A= -$dbuser=3D"proj1";=0A= -$dbpasswd=3D"proj1";=0A= -=0A= -$dbserver=3D'oracledev';=0A= -$db_sid=3D'AL32UTF8';=0A= -=0A= -##=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D connect to database = -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=0A= -=0A= -$dbh=3D DBI->connect("dbi:Oracle:host=3D$dbserver;sid=3D$db_sid", = -$dbuser, $dbpasswd,=0A= - {PrintError =3D> 0, AutoCommit =3D> 1}) or=0A= - errexit( "Unable to connect to $dbserver: $DBI::errstr");=0A= -print "Connect done\n";=0A= -=0A= -#create table test_table (item1 varchar2(4000), item2 varchar2(4000));=0A= -=0A= -=0A= -my $statement=3D"INSERT INTO test_table (item1,item2) VALUES (?, ?)";=0A= -print "stmt: $statement\n";=0A= -=0A= -@vals=3D(=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysite inip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permit icmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permiticmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= -);=0A= -=0A= -print "Size of vals is ",scalar @vals,"\n";=0A= -my $z=3D0;=0A= -foreach my $x (@vals) {=0A= - my $len=3Dlength($x);=0A= - print "val ",++$z, " size $len, is: '$x'\n";=0A= -}=0A= -=0A= -DBI->trace(2);=0A= - $sth=3D$dbh->prepare($statement) ||=0A= - errexit("bad prepare for stmt $statement, error: $DBI::errstr");=0A= - my $rc=3D$sth->execute(@vals) ||=0A= - errexit("can't execute statement: error: $DBI::errstr\n");=0A= -=0A= -print "Done\n";=0A= -exit;=0A= -=0A= -=0A= -sub errexit {=0A= - my (@msg)=3D@_;=0A= - print @msg,"\n";=0A= - exit 1;=0A= -}=0A= -=0A= -=0A= -=0A= - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0-- - - -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 00:15:21 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI0FC8G049539 - for ; Thu, 18 Nov 2004 00:15:21 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 00:15:21 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUVdd-0002Nv-CF; - Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUVdd-0002Nv-CF - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CUVdc-0005lu-Rs - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 4A256ADD6F; - Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3D82CADD64 - for ; Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Received-SPF: none (boggle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by boggle.pobox.com (Postfix) with ESMTP id B23D4ADCF6 - for ; Wed, 17 Nov 2004 14:38:15 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 0C9DF24435B - for ; Wed, 17 Nov 2004 11:38:14 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 18475-01 for ; - Wed, 17 Nov 2004 11:38:13 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id ACF0424406F - for ; Wed, 17 Nov 2004 11:38:13 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 11:36:14 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117192902.GA31595@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTM27+9yfJDVs3WQIWAKc6DR3EgdQAAKfgw -Message-Id: <20041117193813.ACF0424406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -X-Status: A -Content-Length: 14671 -Lines: 489 - -NLS_LANG=.UTF8 -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORACLE_HOME=/home/oracle/product/9.2.0 -ORACLE_SID=AL32UTF8 -ORACLE_BASE=/home/oracle - -NLS_NCHAR is not set, because we are not using any NVARCHAR data item, and -haven't needed it. - -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 11:29 AM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > I did - it is attached to the posting. However, I will attach it again -> > here. -> > -> > Thanks, -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 9:33 AM -> > > To: Susan Cassidy -> > > Cc: dbi-users@perl.org -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > If you can post a small self-contained example that demonstrates -> > > the problem then I'll take a look. -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > > > I never got any response to my question about this problem. I -> > > thought I'd try again. -> > > > -> > > > -> > > > -> > > > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> > > 5.8.5. -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > > -> > > > -> > > > -> > > > ----------------------------------------------------------------- -> ---- -> > > ----------------------------------- -> > > > -> > > > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > > > Sent: Friday, November 05, 2004 10:23 AM -> > > > To: 'dbi-users@perl.org' -> > > > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> > > 01461: can bind a LONG value only for -> > > > insert into a LONG column' when data not LONG -> > > > -> > > > -> > > > -> > > > I had an application that was processing a bunch of xml and -> inserting -> > > into a table with a bunch of -> > > > VARCHAR2(4000) columns. -> > > > -> > > > -> > > > -> > > > A couple of the entries I was processing caused the 'ORA-01461: -> can -> > > bind a LONG value only for insert -> > > > into a LONG column' error. -> > > > -> > > > -> > > > -> > > > I put checks in for the length of the data, and nothing -> approached -> > > 4000 bytes in length. -> > > > -> > > > -> > > > -> > > > I tracked down some of the entries causing problems, and on -> certain -> > > specific data, if 2 columns -> > > > containing specific data are inserted together, I get this error. -> If -> > > only one of the 2 is inserted, I -> > > > do not get the error, regardless of which one of the two I -> insert. -> > > > -> > > > -> > > > -> > > > The lengths of the pieces of data are 1399 and 1397 characters. -> > > > -> > > > -> > > > -> > > > The data is somewhat odd-looking (we suspect some odd data is in -> this -> > > file), but there is no reason for -> > > > the error message to appear. -> > > > -> > > > -> > > > -> > > > Trace shows nothing helpful - it thinks the data is the right -> length. -> > > > -> > > > -> > > > -> > > > We've successfully inserted thousands of other, similar entries -> with -> > > no trouble. -> > > > -> > > > -> > > > -> > > > The basics are: -> > > > -> > > > #create table test_table (item1 varchar2(4000), item2 -> > > varchar2(4000)); -> > > > -> > > > -> > > > -> > > > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, -> ?)"; -> > > > -> > > > -> > > > -> > > > $sth=$dbh->prepare($statement) || -> > > > -> > > > errexit("bad prepare for stmt $statement, error: -> $DBI::errstr"); -> > > > -> > > > my $rc=$sth->execute(@vals) || -> > > > -> > > > errexit("can't execute statement: error: $DBI::errstr\n"); -> > > > -> > > > -> > > > -> > > > Trace shows: -> > > > -> > > > -> > > > -> > > > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > > > -> > > > -> prepare for DBD::Oracle::db -> (DBI::db=HASH(0x82d4178)~0x82d6580 -> > > 'INSERT INTO test_table -> > > > (item1,item2) VALUES (?, ?) -> > > > -> > > > ') thr#8148ff0 -> > > > -> > > > dbd_preparse scanned 2 distinct placeholders -> > > > -> > > > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl -> line -> > > 40 -> > > > -> > > > -> execute for DBD::Oracle::st -> (DBI::st=HASH(0x82d6640)~0x8149dcc -> > > 'version 11.2no service -> > > > password-encryptionservice -> > > > -> > > > udp-small-serversservice tcp-small-servers!hostname router1!!no -> ip -> > > domain-lookupip inspect name mysite -> > > > ftpip inspect name -> > > > -> > > > mysite smtpip inspect name mysite tcp!interface Ethernet0ip -> address -> > > 10.10.10.2 255.255.255.0ip -> > > > access-group 101 inip ins -> > > > -> > > > pect mysite inip inspect mysite outno keepalive!interface -> Serial0no -> > > ip addressencapsulation -> > > > frame-relay...' 'version 11.2 -> > > > -> > > > no service password-encryptionservice udp-small-serversservice -> tcp- -> > > small-servers!hostname router1!!no ip -> > > > domain-lookupip -> > > > -> > > > inspect name mysite ftpip inspect name mysite smtpip inspect name -> > > mysite tcp!interface Ethernet0ip -> > > > address 10.10.10.2 255 -> > > > -> > > > .255.255.0ip access-group 101 inip inspect mysiteinip inspect -> mysite -> > > outno keepalive!interface Serial0no -> > > > ip addressencaps -> > > > -> > > > ulation frame-relayn...') thr#8148ff0 -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (type -> 0) -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (size -> > > 1399/1400/0, ptype 4, otype 1) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (type -> 0) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (size -> > > 1397/1398/0, ptype 4, otype 1) -> > > > -> > > > dbd_st_execute INSERT (out0, lob0)... -> > > > -> > > > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > <- execute= undef at test_insert_large.pl line 42 -> > > > -> > > > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> > > 'ParamValues') thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line -> 42 -> > > > -> > > > -> $DBI::errstr (&) FETCH from lasth=HASH -> > > > -> > > > >> DBD::Oracle::st::errstr -> > > > -> > > > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' -> > > > -> > > > -- DBI::END -> > > > -> > > > -> disconnect_all for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > > > -> > > > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > > > -> > > > Connect done -> > > > -> > > > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > > > -> > > > Size of vals is 2 -> > > > -> > > > val 1 size 1399, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!i -> > > > -> > > > nterface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11 -> > > > -> > > > .2 255.255.255.252ip access-group 102 inframe-relay interface- -> dlci -> > > 200 IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summar -> > > > -> > > > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> > > 0.0.0.0 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0. -> > > > -> > > > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permit icmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess- -> > > > -> > > > list 101 deny ip any anyaccess-list 102 permit eigrp any -> anyaccess- -> > > list 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-rep -> > > > -> > > > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 ad -> > > > -> > > > ministratively-prohibitedaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp a -> > > > -> > > > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> > > 10.10.10.0 0.0.0.255 -> > > > time-exceededaccess-list 102 permit tcp -> > > > -> > > > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line -> con -> > > 0line vty 0 4login!end' -> > > > -> > > > val 2 size 1397, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11. -> > > > -> > > > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 -> > > IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summary -> > > > -> > > > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 -> > > 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0.0 -> > > > -> > > > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permiticmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess-li -> > > > -> > > > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list -> > > 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-reply -> > > > -> > > > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 admi -> > > > -> > > > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp any -> > > > -> > > > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 time-exceededaccess-list -> > > > 102 permit tcp an -> > > > -> > > > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> > > 0line vty 0 4login!end' -> > > > -> > > > can't execute statement: error: ORA-01461: can bind a LONG value -> only -> > > for insert into a LONG column (DBD -> > > > ERROR: OCIStmtEx -> > > > -> > > > ecute) -> > > > -> > > > -> > > > -> > > > ! -> DESTROY for DBD::Oracle::db -> (DBI::db=HASH(0x82d6580)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#0) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY for DBD::Oracle::st -> (DBI::st=HASH(0x8149dcc)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > -> > > > -> > > > I will attach the test program. Somehow it seems to think the -> > > datatype is LONG instead of VARCHAR. -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Anyone with ideas? -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > -> > -> - - - -From SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 07:11:03 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI7Ar8G057950 - for ; Thu, 18 Nov 2004 07:11:03 GMT - (envelope-from SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 07:11:03 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUaCR-0002mS-7P; - Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUaCR-0002mS-7P - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUaCQ-0004JQ-R5 - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 17ACAA3F35; - Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from integer (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 04F8DA3EAC - for ; Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Received-SPF: none (integer.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by integer.pobox.com (Postfix) with ESMTP id A9FC6A3F4D - for ; Wed, 17 Nov 2004 19:30:43 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id DEA102441A9 - for ; Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 22204-10 for ; - Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 7AD52244370 - for ; Wed, 17 Nov 2004 16:30:40 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 16:28:41 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041118001712.GB49519@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTNA/o7HZXghXaJRbyz8M5kVQMQmwAAUBjg -Message-Id: <20041118003040.7AD52244370@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 1789 -Lines: 63 - -Hi, - -I set NLS_LANG to .US7ASCII, ran it again, and I get the same error. - -Of course, I could not use that in production. - -The really strange part, to me, was that if I just insert one of the 2 -problematic columns, it worked, but both together failed. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 4:17 PM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> And does the problem go away if NLS_LANG is set to a non-unicode charset? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 11:36:14AM -0800, Susan Cassidy wrote: -> > NLS_LANG=.UTF8 -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORACLE_HOME=/home/oracle/product/9.2.0 -> > ORACLE_SID=AL32UTF8 -> > ORACLE_BASE=/home/oracle -> > -> > NLS_NCHAR is not set, because we are not using any NVARCHAR data item, -> and -> > haven't needed it. -> > -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 11:29 AM -> > > To: Susan Cassidy -> > > Cc: 'Tim Bunce' -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > > > I did - it is attached to the posting. However, I will attach it -> again -> > > > here. -> > > > -> > > > Thanks, -> > > > Susan -> > > > - - diff --git a/err_unsorted/err_etherreal.msg b/err_unsorted/err_etherreal.msg deleted file mode 100644 index 1ad5c78e..00000000 --- a/err_unsorted/err_etherreal.msg +++ /dev/null @@ -1,90 +0,0 @@ -From dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org Tue Apr 30 14:47:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UDliR22576 - for ; Tue, 30 Apr 2002 14:47:44 +0100 (BST) - (envelope-from dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.23] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 14:47:44 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020172466:10:24548:59; Tue, 30 Apr 2002 13:14:26 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1023391; 30 Apr 2002 13:13 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id A94562C075 - for ; Tue, 30 Apr 2002 09:12:33 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id F24B22BFBE - for ; Tue, 30 Apr 2002 09:12:32 -0400 (EDT) -Received: (qmail 36589 invoked by uid 1005); 30 Apr 2002 13:12:28 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 36168 invoked by uid 76); 30 Apr 2002 13:10:41 -0000 -Content-Type: text/plain; - charset="iso-8859-1" -From: Calin Medianu -To: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Date: Tue, 30 Apr 2002 16:04:47 +0300 -X-Mailer: KMail [version 1.3.2] -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> <20020429233138.E16831@dansat.data-plan.com> -In-Reply-To: <20020429233138.E16831@dansat.data-plan.com> -Cc: dbi-users@perl.org -MIME-Version: 1.0 -Message-Id: <20020430131233.F24B22BFBE@dolly1.pobox.com> -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id g3UDliR22576 -Status: RO -X-Status: A -Content-Length: 1213 -Lines: 38 - -[Add note to DBD::Oracle docs about using ethereal to sniff Oracle packets] -[Not sure if this bug got fixed yet. Maybe not.] - -Me again with the slow cursors. - -I modified both queries to only return 10 rows. -I ran a sniffer (ethereal) on the NIC. It is pretty cool, it also decodes TNS. - -when I am using the SQL, it works like this, there are about 7 packets -received by my workstation to set up the session, then all 10 rows are in the -same packet, then there is another packet probably saying goodbye. - -When I am using the REF cursor, each row comes in it's own TNS packet, that -is why it is so slow! - -Any idea how to fix it? - -thanks a lot, - -Calin - -> On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> > Hello, -> > -> > I did the following. Wrote a perl script that retreves -> > data via a straight select from the database. Then I -> > wrote a stored procedure returning a ref cursor open -> > on the same select statement and retrieved the data as -> > well. Using the REF CURSOR/ sotred procedure was about -> > 3 time slower, that is 40 seconds instead of around -> > 10. -> > -> > Is this normal? Is this a problem with oracle or with -> > DBD::Oracle? -> -> DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. -> -> Get a level 3 trace and look for the "dbd_describe'd" line for the -> ref cursor. -> -> Tim. - diff --git a/err_unsorted/err_memleak2.msg b/err_unsorted/err_memleak2.msg deleted file mode 100644 index 97501852..00000000 --- a/err_unsorted/err_memleak2.msg +++ /dev/null @@ -1,476 +0,0 @@ -From mike@boom.net Fri Nov 28 22:23:33 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hASMLLnY018698 - for ; Fri, 28 Nov 2003 22:23:33 GMT - (envelope-from mike@boom.net) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 28 Nov 2003 22:23:33 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1APmgW-0006iM-9g; - Fri, 28 Nov 2003 17:45:40 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1APmgW-0006iM-9g - for pobox@dbi.demon.co.uk; Fri, 28 Nov 2003 17:45:40 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id E82CD95E03 - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B1EE595DFB - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: from abort.boom.net (abort.boom.net[69.36.241.24]) - by icicle.pobox.com (Postfix) with ESMTP - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: by abort.boom.net (Postfix, from userid 530) - id E3C8B8517A; Fri, 28 Nov 2003 09:45:36 -0800 (PST) -Date: Fri, 28 Nov 2003 09:45:36 -0800 -From: Mike Hedlund -To: dbi-users@perl.org -Cc: Tim.Bunce@pobox.com -Subject: Memory leak in DBD::Oracle 1.14 ... ? -Message-ID: <20031128174536.GJ10609@boom.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.5.4i -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id hASMLLnY018698 -Content-Length: 24309 -Lines: 434 - -I've attached a little script which replicates the problem on my machine as well as the build session log for DBD::Oracle 1.14. - -I've tested it using DBI 1.38 and DBI 1.28 with both DBD::Oracle 1.12 and 1.14. - -Regardless of the DBI version, DBD::Oracle 1.14 leaks on my system and DBD::Oracle 1.12 does not. I've noticed the leak when calling connect_cached(), do() (or prepare()/execute()/commit/finish). - --mike - - --------------------- script --------------- -#!/usr/bin/perl -use strict; -use DBI; - -my($dbp) = "dbi:Oracle:host=weirdo.com;port=1521;sid=SID"; -my($dbu) = "username"; -my($dbpass) = "password"; - -while (1) { - my($sth); - my(@row); - my($dbh) = DBI->connect_cached($dbp,$dbu,$dbpass) || die "Couldn't connect to oracle db: $DBI::errstr\n"; - -## -## uncomment these and it just leaks faster. -## -# $sth = $dbh->prepare("SELECT * from FROM_STATS"); -# $sth->execute; -# while(@row = $sth->fetchrow_array) { - ##print "row: @row\n"; -# } -# $sth->finish; -} -exit; ------------------------- end script -------------------- - - ------------- log --------------------------------------- -Script started on Fri 28 Nov 2003 09:11:15 AM PST -[mike@commando DBD-Oracle-1.14]$ setenv ORACLE_HOME /home/orahome -[mike@commando DBD-Oracle-1.14]$ make realclean -rm -f blib/script/ora_explain -rm -rf Oracle.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm ./blib Makefile.aperl blib/arch/auto/DBD/Oracle/extralibs.all perlmain.c tmon.out mon.out so_locations pm_to_blib *.o *.a perl.exe perl perl Oracle.bs Oracle.bso Oracle.def libOracle.def Oracle.exp Oracle.x core core.*perl.*.? *perl.core -mv Makefile Makefile.old > /dev/null 2>&1 -rm -rf blib/lib/auto/DBD/Oracle blib/arch/auto/DBD/Oracle -rm -rf DBD-Oracle-1.14 -rm -f blib/arch/auto/DBD/Oracle/Oracle.so blib/arch/auto/DBD/Oracle/Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.a -rm -f blib/lib/DBD/Oracle.pm blib/arch/auto/DBD/Oracle/dbdimp.h blib/lib/oraperl.ph -rm -f blib/arch/auto/DBD/Oracle/ocitrace.h blib/lib/Oraperl.pm -rm -f blib/arch/auto/DBD/Oracle/Oracle.h blib/arch/auto/DBD/Oracle/mk.pm -rm -f blib/lib/DBD/Oracle/GetInfo.pm -rm -rf Makefile Makefile.old -[mike@commando DBD-Oracle-1.14]$ perl Makefile.PL -v -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI - - Configuring DBD::Oracle ... - ->>> Remember to actually *READ* the README file! - Especially if you have any problems. - -Using Oracle in /home/orahome - -WARNING: could not decode oracle version from -/home/orahome/orainst/inspdver, or /home/orahome/install/unix.rgs -or from ORACLE_HOME path /home/orahome. -Oracle version based logic in Makefile.PL may produce erroneous results. - -Found header files in rdbms/public rdbms/demo. -Found /home/orahome/rdbms/demo/demo_rdbms.mk -Found /home/orahome/otrace/demo/atmoci.mk -Found /home/orahome/precomp/demo/proc/demo_proc.mk -Using /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/lib/env_rdbms.mk -Read a total of 2202 lines from /home/orahome/rdbms/lib/env_rdbms.mk (including inclusions) -Read a total of 2493 lines from /home/orahome/rdbms/demo/demo_rdbms.mk (including inclusions) -Deleted SHELL definition: SHELL=/bin/sh -Deleted LIB_EXT definition: LIB_EXT=a -Deleted OBJ_EXT definition: OBJ_EXT=o -Deleted AR definition: AR=ar -Deleted AS definition: AS=as -Deleted CC definition: CC=cc -Deleted CHMOD definition: CHMOD=chmod -Deleted CPP definition: CPP=cpp -Deleted ECHO definition: ECHO=echo -Deleted LD definition: LD=ld -Deleted PERL definition: PERL=perl -Deleted CFLAGS definition: CFLAGS=$(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ -Deleted OPTIMIZE definition: OPTIMIZE=$(OPTIMIZE3) -Deleted AR definition: AR=/usr/bin/ar -Deleted AS definition: AS=/usr/bin/as -Deleted LD definition: LD=/usr/bin/ld -Deleted CPP definition: CPP=/lib/cpp -Deleted CHMOD definition: CHMOD=/bin/chmod -Deleted ASFLAGS definition: ASFLAGS= -Deleting ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS definition: ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Deleting ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS33 definition: ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Appending '/home/orahome/rdbms/lib/libskgxpd.a /home/orahome/rdbms/lib/libskgxpu.a /home/orahome/rdbms/lib/libskgxpt.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxp9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxp9.a' to LIBS -Appending '/home/orahome/rdbms/lib/libskgxns.a /home/orahome/rdbms/lib/libskgxnd.a /home/orahome/rdbms/lib/libskgxnr.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxn9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxn9.a' to LIBS -Evaluating `cat $(LIBHOME)sysliblist` - expanded `cat /home/orahome/lib/sysliblist` - returned '-ldl -lm -lpthread -lnsl ' - -Attempting to discover Oracle OCI build rules -gcc -c -o DBD_ORA_OBJ.o DBD_ORA_OBJ.c -by executing: (make -f /home/orahome/rdbms/demo/demo_rdbms.mk build ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh' CC=echo OPTIMIZE= CCFLAGS= EXE=DBD_ORA_EXE OBJS=DBD_ORA_OBJ.o) -returned: -[echo -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh `cat /home/orahome/lib/sysliblist` -ldl -lm - -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -reduced to: -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -Oracle oci build command: - + -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - - - -System: perl5.008 linux stripples.devel.redhat.com 2.4.21-1.1931.2.382.entsmp #1 smp wed aug 6 17:18:52 edt 2003 i686 i686 i386 gnulinux -Compiler: gcc -O2 -g -pipe -march=i386 -mcpu=i686 -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -Linker: /usr/bin/ld -Sysliblist: -ldl -lm -lpthread -lnsl -Oracle makefiles would have used these definitions but we override them: - CC: cc - - CFLAGS: $(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) - [$(GFLAG) -O3 $(CDEBUG) $(CCFLAGS) -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -DLINUX -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS $(LPFLAGS) $(USRFLAGS)] - - LDFLAGS: -o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ - [-o $@ -L/home/orahome/rdbms/lib/ -L$(LIBHOME) -L$(LIBHOME)stubs/] - - -Linking with OTHERLDFLAGS = -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - [from 'build' rule] - - -MakeMaker (v6.03) -Checking if your kit is complete... -Looks good - ABSTRACT_FROM => q[Oracle.pm] - AUTHOR => q[Tim Bunce (dbi-users@perl.org)] - DEFINE => q[ -DUTF8_SUPPORT] - DIR => [] - EXE_FILES => [q[ora_explain]] - INC => q[-I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI] - NAME => q[DBD::Oracle] - OBJECT => q[$(O_FILES)] - PREREQ_PM => { DBI=>q[0] } - VERSION_FROM => q[Oracle.pm] - clean => { FILES=>q[Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm] } - dist => { DIST_DEFAULT=>q[clean distcheck disttest ci tardist], COMPRESS=>q[gzip -v9], PREOP=>q[$(MAKE) -f Makefile.old distdir], SUFFIX=>q[gz] } - dynamic_lib => { OTHERLDFLAGS=>q[ -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] } -Using PERL=/usr/bin/perl -LD_RUN_PATH=/home/orahome/lib:/home/orahome/rdbms/lib -Using DBD::Oracle 1.14. -Using DBD::Oracle 1.14. -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -Writing Makefile for DBD::Oracle - -*** If you have problems... - read all the log printed above, and the README and README.help files. - (Of course, you have read README by now anyway, haven't you?) - -[mike@commando DBD-Oracle-1.14]$ make -cp Oracle.pm blib/lib/DBD/Oracle.pm -cp Oracle.h blib/arch/auto/DBD/Oracle/Oracle.h -cp dbdimp.h blib/arch/auto/DBD/Oracle/dbdimp.h -cp oraperl.ph blib/lib/oraperl.ph -cp ocitrace.h blib/arch/auto/DBD/Oracle/ocitrace.h -cp Oraperl.pm blib/lib/Oraperl.pm -cp mk.pm blib/arch/auto/DBD/Oracle/mk.pm -cp lib/DBD/Oracle/GetInfo.pm blib/lib/DBD/Oracle/GetInfo.pm -/usr/bin/perl -p -e "s/~DRIVER~/Oracle/g" /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI/Driver.xst > Oracle.xsi -/usr/bin/perl /usr/lib/perl5/5.8.0/ExtUtils/xsubpp -typemap /usr/lib/perl5/5.8.0/ExtUtils/typemap Oracle.xs > Oracle.xsc && mv Oracle.xsc Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT dbdimp.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci7.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci8.c -Running Mkbootstrap for DBD::Oracle () -chmod 644 Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/home/orahome/lib:/home/orahome/rdbms/lib" gcc -shared -L/usr/local/lib Oracle.o dbdimp.o oci7.o oci8.o -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" blib/script/ora_explain -Manifying blib/man3/DBD::Oracle.3pm -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oraperl.3pm -[mike@commando DBD-Oracle-1.14]$ make test -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/base....... t/base.......ok 1/5 t/base.......ok 2/5 t/base.......ok 3/5 t/base.......ok 4/5 t/base.......ok 5/5 t/base.......ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/reauth.....skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.82 cusr + 0.33 csys = 4.15 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ make test TEST_VERBOSE=1 -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1, 'blib/lib', 'blib/arch')" t/*.t -t/base.......1..5 -ok 1 -ok 2 -ok 3 -ok 4 -ok 5 -ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/reauth.....ORACLE_USERID_2 not defined. -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.85 cusr + 0.32 csys = 4.17 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ perl _V-V -Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: - Platform: - osname=linux, osvers=2.4.21-1.1931.2.382.entsmp, archname=i386-linux-thread-multi - uname='linux str' - config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Dotherlibdirs=/usr/lib/perl5/5.8.0 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr' - hint=recommended, useposix=true, d_sigaction=define - usethreads=define use5005threads=undef' - useithreads=define usemultiplicity= - useperlio= d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=un uselongdouble= - usemymalloc=, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', - optimize='', - cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm' - ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)', gccosandvers='' -gccversion='3.2.2 200302' - intsize=r, longsize=r, ptrsize=5, doublesize=8, byteorder=1234 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - ivtype='long' -k', ivsize=4' -ivtype='l, nvtype='double' -o_nonbl', nvsize=, Off_t='', lseeksize=8 - alignbytes=4, prototype=define - Linker and Libraries: - ld='gcc' -l', ldflags =' -L/u' - libpth=/usr/local/lib /lib /usr/lib - libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil - perllibs= - libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libper - gnulibc_version='2.3.2' - Dynamic Linking: - dlsrc=dl_dlopen.xs, dlext=so', d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE' - cccdlflags='-fPIC' -ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5', lddlflags='s Unicode/Normalize XS/A' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING MULTIPLICITY USE_ITHREADS USE_LARGE_FILES PERL_IMPLICIT_CONTEXT - Locally applied patches: - MAINT18379 - Built under linux - Compiled at Aug 13 2003 11:47:58 - @INC: - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/site_perl/5.8.0 - /usr/lib/perl5/site_perl - /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/vendor_perl/5.8.0 - /usr/lib/perl5/vendor_perl - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - . -[mike@commando DBD-Oracle-1.14]$ ^D -Script done on Fri 28 Nov 2003 09:16:43 AM PST ------------- end log ----------------------------------- - - diff --git a/err_unsorted/err_multiora.msg b/err_unsorted/err_multiora.msg deleted file mode 100644 index 9f7bcf6c..00000000 --- a/err_unsorted/err_multiora.msg +++ /dev/null @@ -1,470 +0,0 @@ -From dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org Mon Jan 5 10:12:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05ACYn1063537 - for ; Mon, 5 Jan 2004 10:12:58 GMT - (envelope-from dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 10:12:58 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdQXY-0007a7-IO; - Mon, 05 Jan 2004 09:18:18 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdQXY-0007a7-IO - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 08:56:48 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id C92F0282F - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id B344B2B84 - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: (qmail 58691 invoked by uid 1005); 5 Jan 2004 08:56:38 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 58674 invoked by uid 76); 5 Jan 2004 08:56:38 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 05 Jan 2004 00:56:38 -0800 -Received: (qmail 17937 invoked by uid 225); 5 Jan 2004 08:56:36 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 17930 invoked by uid 507); 5 Jan 2004 08:56:36 -0000 -Received: from stone.sifira.dk (HELO mail.int.sifira.dk) (217.157.24.2) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Mon, 05 Jan 2004 00:56:05 -0800 -Received: from ash.int.sifira.dk (ash.int.sifira.dk [192.168.1.7]) by mail.int.sifira.dk (Postfix) with ESMTP id F127674F58; Mon, 5 Jan 2004 09:55:58 +0100 (MET) -Sender: kn@sifira.dk -To: "Anniballi, Fran" -Cc: -Subject: Re: Help - multiple Oracle versions -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -From: Kristian Nielsen -Date: 05 Jan 2004 09:55:59 +0100 -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Message-ID: <7sllomsrj4.fsf@ash.int.sifira.dk> -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-2.5 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_GNUS_UA version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1223 -Lines: 40 - -[Add notes to docs covering what's in this thread] - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - -From dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org Mon Jan 5 14:47:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05Ejvo1064760 - for ; Mon, 5 Jan 2004 14:47:30 GMT - (envelope-from dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 14:47:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdVCS-0004w0-Is; - Mon, 05 Jan 2004 13:55:22 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdVCS-0004w0-Is - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 13:55:21 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 548DE2C87 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 417692C81 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 08:55:19 -0500 (EST) -Received: (qmail 91728 invoked by uid 1005); 5 Jan 2004 13:55:17 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 48614 invoked by uid 76); 5 Jan 2004 12:24:01 -0000 -Delivered-To: dbi-users@perl.org -X-MimeOLE: Produced By Microsoft Exchange V6.0.6487.1 -content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; charset="iso-8859-1" -Subject: RE: Help - multiple Oracle versions -Date: Mon, 5 Jan 2004 07:23:23 -0500 -Message-ID: <6B003D25ADBDE347B5542AFE6A55B42E04537A09@tayexc13.americas.cpqcorp.net> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Help - multiple Oracle versions -Thread-Index: AcPTac0nADA1C8LsTdSTxpcvyeSNCgAHQWGQ -From: "Anniballi, Fran" -To: -Cc: -X-OriginalArrivalTime: 05 Jan 2004 12:23:24.0525 (UTC) FILETIME=[B6F761D0:01C3D386] -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.3 required=7.0 tests=CARRIAGE_RETURNS,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i05Ejvo1064760 -Status: RO -Content-Length: 1465 -Lines: 52 - -Thanks. Looks like this is what I'll need. - ------Original Message----- -From: kn@sifira.dk [mailto:kn@sifira.dk] -Sent: Monday, January 05, 2004 3:56 AM -To: Anniballi, Fran -Cc: dbi-users@perl.org -Subject: Re: Help - multiple Oracle versions - - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - - -From dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org Tue Jan 6 17:00:29 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i06GxrnC075337 - for ; Tue, 6 Jan 2004 17:00:29 GMT - (envelope-from dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 06 Jan 2004 17:00:29 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Adu0c-0004RW-9d; - Tue, 06 Jan 2004 16:24:47 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Adu0c-0004RW-9d - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 16:24:47 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 21A79495C - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 08B12494B - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 6 Jan 2004 11:24:45 -0500 (EST) -Received: (qmail 25114 invoked by uid 1005); 6 Jan 2004 16:24:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 25095 invoked by uid 76); 6 Jan 2004 16:24:42 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Tue, 06 Jan 2004 08:24:42 -0800 -Received: (qmail 16535 invoked by uid 225); 6 Jan 2004 16:24:39 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16527 invoked by uid 507); 6 Jan 2004 16:24:39 -0000 -Received: from mail.cybcon.com (HELO mail.cybcon.com) (216.190.188.5) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 06 Jan 2004 08:24:08 -0800 -Received: from poirot (dsl2-6.cybcon.com [208.186.116.6]) by mail.cybcon.com (8.11.6/8.11.6) with ESMTP id i06GNhn08916; Tue, 6 Jan 2004 08:23:43 -0800 -Subject: RE: Help - multiple Oracle versions -From: Jared Still -To: "Anniballi, Fran" -Cc: DBI List -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 (1.0.8-11) -Date: 06 Jan 2004 08:25:59 -0800 -Message-Id: <1073406359.324.244.camel@poirot.jks.com> -Mime-Version: 1.0 -X-CyberConnectics-MailScanner2-Information: Spam/Virus Scanned at CyberConnectics -X-CyberConnectics-MailScanner2: Found to be clean -X-CyberConnectics-MailScanner2-SpamCheck: -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.2 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_05_08,SUPERLONG_LINE version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 4050 -Lines: 102 - -I read quickly through this thread, so my apologies if someone -already pointed this out. - -It doesn't matter which version of Oracle you compiled DBD with, -you can connect to all your 8i/9i databases on any platform with it. - -Assume you compiled with 9i libs, and you can connect to 9i db's with -no problem, but are unable to connect to 8i, getting the error you -mentioned previously. - -It appears that you are changing your Oracle environment via the -oraenv shell script to change your ORACLE_HOME to the 8i version -of Oracle. - -If so, stop doing that. Just leave your environment at 9i, and -connect to your 8i database. It will be fine. This is the way -my linux server is setup, and DBD is used to connect to Oracle -versions 7.3, 8.1.6, 8.1.7 and 9.2.0 every day. - -At our site DBD is compiled with 8i libs so that we can still -connect to the version 7 databases. If you compile with 9i libs, -you will be unable to connect to version 7 databases. - -HTH - -Jared - - -On Sun, 2004-01-04 at 05:12, Anniballi, Fran wrote: -> This is all done on one UNIX box. -> -> If I try option one, it doesn't work. I can't access an oracle8 instance with oracle9 sqlplus (or the other way around). That is the real problem. Since I can't do this I have to reassign the pointers before I access it. I can do this fine with sqlplus but with dbi/dbd I have to compile with one or the other. -> -> For option two, if I have two versions of DBD:Oracle, how do I tell Perl which one to use? My scripts just say "/usr/bin/perl" in the first line. -> -> -----Original Message----- -> From: kn@sifira.dk [mailto:kn@sifira.dk] -> Sent: Saturday, January 03, 2004 1:04 PM -> To: dbi-users@perl.org -> Cc: Anniballi, Fran -> Subject: Re: Help - multiple Oracle versions -> -> -> "Anniballi, Fran" writes: -> -> > As soon as I recompile the same DBI/DBD with it pointing to Oracle 9 -> > environment (libraries), it doesn't work. It is looking for Oracle9 -> > library files and I obviously don't have it pointing to oracle9 -> > libraries when I access an Oracle 8 instance. Oracle 9 is not -> > compatible with Oracle 8 so I have to redirect the environment -> > variables at run time. -> -> It sounds like you are confusing the Oracle client version and the -> Oracle server version. -> -> Eg. if you set ORACLE_HOME to /usr/local/oracle8 (or whatever) and use -> /usr/local/oracle8/bin/sqlplus you are using the Oracle 8 client, while -> if you set it to /usr/local/oracle9 and call -> /usr/local/oracle9/bin/sqlplus, you are using the Oracle 9 client. -> -> Which Oracle instance you access is selected by the connection string; -> for example "sqlplus scott/tiger@DB8" might access the Oracle 8 -> instance, and "scott/tiger@DB9" might access the Oracle 9 instance. -> -> What people are telling you is that you can choose client version -> independently of the server version. For example, it is possible to set -> ORACLE_HOME to /usr/local/oracle9 and call -> -> /usr/local/oracle9/bin/sqlplus scott/tiger@DB8 -> -> to access the Oracle 8 instance with the Oracle 9 client. This of course -> requires that the definition for DB8 is present in the file -> /usr/local/oracle-9.2/network/admin/tnsnames.ora. -> -> So you should either -> -> 1. Use only the Oracle 9 client, not change ORACLE_HOME, and access both -> instances with Oracle 9 sqlplus and DBD::Oracle compiled against -> Oracle 9 libraries. -> -> or -> -> 2. Compile DBD::Oracle twice (once against Oracle 8 libraries, once -> against Oracle 9 libraries, just as you have two versions of sqlplus) -> and use each one with the proper ORACLE_HOME setting. -> -> My guess is that you will find possibility 1. the easiest. -> -> > The tnsnames.ora are all set. I did what you said already. -> > -> > Example: DBI/DBD will work fine if I compile the DBI/DBD pointing to -> > Oracle 8 environment(libraries) and access an Oracle 8 instance. I -> > didn't have to change tnsnames.ora -> -> Yes you do: You need to have BOTH Oracle instances defined in EACH -> tnsnames.ora. -> -> Hope this helps, -> -> - Kristian. - - - -From andy@andyh.co.uk Wed Jan 7 07:31:57 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i077VPn8081048 - for ; Wed, 7 Jan 2004 07:31:57 GMT - (envelope-from andy@andyh.co.uk) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 07 Jan 2004 07:31:57 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Ae0Yb-0002lT-IA; - Tue, 06 Jan 2004 23:24:17 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Ae0Yb-0002lT-IA - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 23:24:17 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 00D7C3C15 - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id CB5813BEA - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from mta03-svc.ntlworld.com (mta03-svc.ntlworld.com [62.253.162.43]) - by integer.pobox.com (Postfix) with ESMTP - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from excession ([80.2.244.47]) by mta03-svc.ntlworld.com - (InterMail vM.4.01.03.37 201-229-121-137-20020806) with SMTP - id <20040106232403.NEKJ9852.mta03-svc.ntlworld.com@excession>; - Tue, 6 Jan 2004 23:24:03 +0000 -Message-ID: <00bd01c3d4ac$e5713190$6564a8c0@excession> -From: "Andy Hassall" -To: "Eric Lenio" , "Tim Bunce" -Cc: -References: <20040102143310.GC27273@lenio.net> <20040104204914.GB60357@dansat.data-plan.com> <20040105123653.GA31473@lenio.net> <20040105223121.GG66760@dansat.data-plan.com> <20040106222634.GG11531@lenio.net> <20040106223845.GE78360@dansat.data-plan.com> <20040106225722.GI11531@lenio.net> -Subject: Re: DBI primary_key tests fail: oracle 8 -Date: Tue, 6 Jan 2004 23:29:14 -0000 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2800.1158 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 43 - -Eric Lenio wrote: -> OK Tim. One other note -- after reading through oracle docs, I think -> you might want to substitute 'session_user' for 'current_schema' in -> 'select sys_context(...)'. The definition of session_user is -> "returns the database -> user name by which the current user is authenticated" while -> current_schema is "returns the name of the default schema being used -> in the current session". -> Maybe it doesn't matter, I'm not an oracle guru by any stretch of the -> imagination. - -There's several usernames in the USERENV context: - -CURRENT_SCHEMA - -The schema/user used for unqualified object name resolution; by default the -user you logged in as, but alterable with 'alter session set -current_schema=x'. Useful for avoiding having to maintain loads of synonyms. - -CURRENT_USER - -The user you're currently authenticated as. Doesn't change in SQL and -anonymous PL/SQL, but changes within definer-rights PL/SQL stored procedures -to the owner of the stored procedure, since stored procs by default run with -the privileges of the owner, not the invoker. - -SESSION_USER - -Who you originally logged in as, and never changes (but see below). Looks -like the appropriate one to use. - -PROXY_USER - -I don't think DBD::Oracle supports proxy authentication so don't need to -worry about that one yet. Possibly a bit of a grey area if it does support -it in the future, since this would hold the username in the DSN, but it'd -reauthenticate and change the SESSION_USER on connect (which would probably -have to be specified as an attribute to the $dbh). - --- -Andy Hassall (andy@andyh.co.uk) icq(5747695) (http://www.andyh.co.uk) -Space: disk usage analysis tool (http://www.andyhsoftware.co.uk/space) - - diff --git a/err_unsorted/err_ora9ir2oci.msg b/err_unsorted/err_ora9ir2oci.msg deleted file mode 100644 index 7ed476e4..00000000 --- a/err_unsorted/err_ora9ir2oci.msg +++ /dev/null @@ -1,27 +0,0 @@ -http://otn.oracle.com/tech/oci/htdocs/oci9ir2_new_features - -OCI Session Pooling -Session Pooling is a new feature in Oracle 9i Database Release 2. -An application can now maintain a pool of sessions and use a session -from the pool when it needs it. This saves the time consuming process -of initiating a connection and authentication every time the process -needs a new session. Session Pooling is useful, especially when a -large number of stateless sessions are required for a very short -time. In a web scenario, where many users are connected for a short -time, and the primary operation is accessing data, it is a costly -operation to start up a new session every time. In such a scenario, -session pooling could boost up the performance. - -OCI Statement caching -Client-side statement caching is also introduced in Oracle9i Database -Release 2. This feature can be enabled at the time of session -creation. It allows users to have a cache of statements per session. -On the server, this means having cursors that ready to be used, -without the need to parse the statements again, and thus improving -performance significantly. With this feature enabled, applications -do not have to keep a track of the statements themselves, as the -OCI layer will do it for them. In addition, a tagging feature is -provided, which users can use as a key to save and search for -statements. - - diff --git a/err_unsorted/err_ref_type.msg b/err_unsorted/err_ref_type.msg deleted file mode 100644 index 26d86e14..00000000 --- a/err_unsorted/err_ref_type.msg +++ /dev/null @@ -1,115 +0,0 @@ -From dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org Wed Jul 23 18:40:02 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6NHUUA0010501 - for ; Wed, 23 Jul 2003 18:40:02 +0100 (BST) - (envelope-from dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 23 Jul 2003 18:40:02 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058948095:10:09585:8; Wed, 23 Jul 2003 08:14:55 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116163; 23 Jul 2003 8:14 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 88C1B21C024 - for ; Wed, 23 Jul 2003 04:13:51 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id AA89B21C082 - for ; Wed, 23 Jul 2003 04:13:50 -0400 (EDT) -Received: (qmail 26606 invoked by uid 1005); 23 Jul 2003 08:13:44 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 26590 invoked by uid 76); 23 Jul 2003 08:13:43 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Wed, 23 Jul 2003 01:13:43 -0700 -Received: (qmail 16360 invoked by uid 225); 23 Jul 2003 08:13:41 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16355 invoked by uid 507); 23 Jul 2003 08:13:41 -0000 -Received-SPF: unknown -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Wed, 23 Jul 2003 01:13:41 -0700 -Received: (qmail 5378 invoked from network); 23 Jul 2003 08:54:08 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 23 Jul 2003 08:54:08 -0000 -Received: (qmail 8984 invoked from network); 23 Jul 2003 08:13:49 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 23 Jul 2003 08:13:49 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Wed, 23 Jul 2003 10:13:49 +0200 (CEST) -Subject: Re: binding to parameters of type REF -From: Hendrik =?ISO-8859-1?Q?Fu=DF?= -To: dbi-users@perl.org -In-Reply-To: <1058865345.1241.56.camel@mars> -References: <1058865345.1241.56.camel@mars> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 -Date: 23 Jul 2003 10:11:49 +0200 -Message-Id: <1058947909.6353.5.camel@mars> -Mime-Version: 1.0 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.3 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,LARGE_HEX,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1354 -Lines: 56 - -I've also found out, that DBD::Oracle does not support type SQL_REF: -When not using DBD::Proxy I get: - - SQL type 20 for ':p1' is not fully supported, - bound as SQL_VARCHAR instead - -I even get segmentation faults when trying to fetch REF columns. :-( - -Any ideas? - -> Hi, -> -> I'm trying to bind a perl variable to an Oracle table reference with -> Oracle 9.2.0.3, DBD::Proxy and Perl::DBI 1.37 without success. I -> could'nt find help on this in the docs or list archives. I hope this is -> the right place to post. -> -> In SQL*Plus: -> -> SQL> desc getReference -> FUNCTION getReference RETURNS REF OF TABLETYPE -> -> SQL> select getReference() from dual; -> -> GETREFERENCE() -> ---------------------------------------------------------------------- -> 0000280209C229D2216EF6A5F4E030010A8D086AD3C204FC6EE0E46501E030010A8D08 -> 2CE703C0000E0000 -> -> -> My code: -> -> my $ref = undef; -> my $sth = $dbh->prepare('BEGIN ? := getReference(); END;'); -> $sth->bind_param_inout(1, \$ref, 128, SQL_REF ); -> $sth->execute(); -> -> yields: -> -> PLS-00382: expression is of wrong type -> -> -> Even fetching a reference does not work: -> -> my $sth = $dbh->prepare('SELECT getReference() FROM DUAL'); -> $sth->execute(); -> ($ref) = $sth->fetchrow_array(); -> -> yields undef in $ref. -> -> I'd very much appreciate your help. -> cheers, -> Hendrik - - - - diff --git a/err_unsorted/err_refcsr_rowcache.msg b/err_unsorted/err_refcsr_rowcache.msg deleted file mode 100644 index 5101d2ae..00000000 --- a/err_unsorted/err_refcsr_rowcache.msg +++ /dev/null @@ -1,85 +0,0 @@ -From dbi-users-bounce@isc.org Tue May 16 22:53:12 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id WAA29547; Tue, 16 May 2000 22:53:11 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <04730-2@oink>; Sat, 16 May 1970 22:51:48 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 958512876:10:15786:0; Tue, 16 May 2000 21:34:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1122388; 16 May 2000 21:33 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 661E53EC8; - Tue, 16 May 2000 14:33:38 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Tue, 16 May 2000 14:28:31 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id 7192F3E20 - for ; - Tue, 16 May 2000 14:28:27 -0700 (PDT) -Received: from anchor-post-34.mail.demon.net (anchor-post-34.mail.demon.net [194.217.242.92]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id OAA27204 - for ; - Tue, 16 May 2000 14:28:26 -0700 (PDT) env-from (Tim.Bunce@ig.co.uk) -Received: from ignite.demon.co.uk ([158.152.8.99] helo=oink) - by anchor-post-34.mail.demon.net with smtp (Exim 2.12 #1) - id 12rot7-000Mp4-0Y; Tue, 16 May 2000 22:28:25 +0100 -Received: from toad by oink with SMTP (PP) id <04650-0@oink>; - Sat, 16 May 1970 22:23:55 +0100 -Received: by toad.ig.co.uk (SMI-8.6/SMI-SVR4) id WAA29289; - Tue, 16 May 2000 22:23:50 +0100 -Date: Tue, 16 May 2000 22:23:50 +0100 -From: Tim Bunce -To: peter_dev@talk21.com -Cc: dbi-users@isc.org -Subject: Re: Oracle Stored Procs take longer than embedded SQL -Message-ID: <20000516222350.F28435@ig.co.uk> -References: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs>; from peter_dev@talk21.com on Tue, May 16, 2000 at 06:48:22PM +0100 -Organization: Paul Ingram Group, Software Systems, +44 1 483 862800 -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 1372 -Lines: 30 - -On Tue, May 16, 2000 at 06:48:22PM +0100, peter_dev@talk21.com wrote: -> I have a problem with the fetching of data from an Oracle Ref Cursor taking longer than the same query in Embeded SQL. -> -> $ get_sp.pl -> Fetched in 0.00774896144866943 seconds -> Completed in 0.106827020645142 seconds -> -> $ get_sql.pl -> Fetched in 0.00138604640960693 seconds -> Completed in 0.380790948867798 seconds -> -> In this example (Using the SCOTT/TIGER tables), while the Stored Procedure completed first, the actual fetch of the data took considerably longer. In a real situation (e.g. bigger tables ), this is easily the longest part of the task and causes the overall execution time to increase hugely. -> -> Any Help would be appreciated -> thanks - -Possibly related to the lack of a row cache on that statement handle. -You, or some kind volunteer, could probably hack that in without too -much work. - -Tim. - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_unsorted/err_refcsr_slow.msg b/err_unsorted/err_refcsr_slow.msg deleted file mode 100644 index 790d267d..00000000 --- a/err_unsorted/err_refcsr_slow.msg +++ /dev/null @@ -1,347 +0,0 @@ -From dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org Mon Apr 29 23:12:51 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TMCpR17212 - for ; Mon, 29 Apr 2002 23:12:51 +0100 (BST) - (envelope-from dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 29 Apr 2002 23:12:51 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020117986:10:17770:92; Mon, 29 Apr 2002 22:06:26 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1017591; 29 Apr 2002 22:06 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id 975037274A - for ; Mon, 29 Apr 2002 18:01:37 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by wormwood.pobox.com (Postfix) with SMTP id ED2897273F - for ; Mon, 29 Apr 2002 18:01:34 -0400 (EDT) -Received: (qmail 70462 invoked by uid 1005); 29 Apr 2002 21:59:33 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 20335 invoked by uid 76); 29 Apr 2002 20:18:55 -0000 -Message-ID: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Date: Mon, 29 Apr 2002 13:18:53 -0700 (PDT) -From: Calin Medianu -Reply-To: cmedianu@sfu.ca -Subject: DBD::Oracle Slow cursors -To: dbi-users@perl.org -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 568 -Lines: 21 - -Hello, - -I did the following. Wrote a perl script that retreves -data via a straight select from the database. Then I -wrote a stored procedure returning a ref cursor open -on the same select statement and retrieved the data as -well. Using the REF CURSOR/ sotred procedure was about -3 time slower, that is 40 seconds instead of around -10. - -Is this normal? Is this a problem with oracle or with -DBD::Oracle? - -Thanks, - -Calin Medianu - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org Tue Apr 30 00:06:36 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TN6aR17980 - for ; Tue, 30 Apr 2002 00:06:36 +0100 (BST) - (envelope-from dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 00:06:36 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020119533:20:05733:4; Mon, 29 Apr 2002 22:32:13 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2005393; 29 Apr 2002 22:32 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 4E6B73E6BF - for ; Mon, 29 Apr 2002 18:32:00 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-1.pobox.com (Postfix) with SMTP id BF79C3E6A0 - for ; Mon, 29 Apr 2002 18:31:59 -0400 (EDT) -Received: (qmail 87860 invoked by uid 1005); 29 Apr 2002 22:31:59 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 87844 invoked by uid 76); 29 Apr 2002 22:31:58 -0000 -Received: from mail01.svc.cra.dublin.eircom.net (HELO mail01.svc.cra.dublin.eircom.net) (159.134.118.17) - by onion.perl.org (qpsmtpd/0.07) with SMTP; Mon Apr 29 22:31:58 2002 -0000 -Received: (qmail 21911 messnum 119827 invoked from network[159.134.167.97/p865.as1.limerick1.eircom.net]); 29 Apr 2002 22:31:29 -0000 -Received: from p865.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.97) - by mail01.svc.cra.dublin.eircom.net (qp 21911) with SMTP; 29 Apr 2002 22:31:29 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g3TMVcR17579; - Mon, 29 Apr 2002 23:31:38 +0100 (BST) - (envelope-from timbo) -Date: Mon, 29 Apr 2002 23:31:38 +0100 -From: Tim Bunce -To: cmedianu@sfu.ca -Cc: dbi-users@perl.org -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020429233138.E16831@dansat.data-plan.com> -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020429201853.52283.qmail@web10007.mail.yahoo.com>; from calinm@yahoo.com on Mon, Apr 29, 2002 at 01:18:53PM -0700 -Content-Length: 651 -Lines: 20 - -On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> Hello, -> -> I did the following. Wrote a perl script that retreves -> data via a straight select from the database. Then I -> wrote a stored procedure returning a ref cursor open -> on the same select statement and retrieved the data as -> well. Using the REF CURSOR/ sotred procedure was about -> 3 time slower, that is 40 seconds instead of around -> 10. -> -> Is this normal? Is this a problem with oracle or with -> DBD::Oracle? - -DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. - -Get a level 3 trace and look for the "dbd_describe'd" line for the -ref cursor. - -Tim. - -From calinm@yahoo.com Tue Apr 30 22:02:56 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL2tR26878 - for ; Tue, 30 Apr 2002 22:02:55 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:02:55 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020198219:10:21718:114; Tue, 30 Apr 2002 20:23:39 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101732; 30 Apr 2002 20:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C6B4A2BFB4 - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10004.mail.yahoo.com (web10004.mail.yahoo.com [216.136.130.40]) - by dolly1.pobox.com (Postfix) with SMTP id 527BD2BF3D - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Message-ID: <20020430202321.54825.qmail@web10004.mail.yahoo.com> -Received: from [213.157.171.169] by web10004.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 13:23:20 PDT -Date: Tue, 30 Apr 2002 13:23:20 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -Cc: dbi-users@perl.org -In-Reply-To: <20020430140517.P16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 425 -Lines: 18 - -I "Solved" the problem. For Now.. I did -perl Makefile.PL -8 - -hoping that the buggy code would be recently added, -and it was. Now both the select and the cursor return -the data at the same speed, meaning fast.. - -Am I am missing much by not using the code for Oracle -8? - -Thanks, - -Calin - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From timbo@dansat.data-plan.com Wed May 1 16:49:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g41FnsR33994 - for ; Wed, 1 May 2002 16:49:54 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 May 2002 16:49:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020265865:20:10671:66; Wed, 01 May 2002 15:11:05 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-2.mail.demon.net - id aa2122069; 1 May 2002 15:10 GMT -Received: from cali-3.pobox.com (cali-3.pobox.com [64.71.166.116]) - by silk.pobox.com (Postfix) with ESMTP id F29CC3FDF2 - for ; Wed, 1 May 2002 11:09:52 -0400 (EDT) -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id E3A943E689 - for ; Wed, 1 May 2002 10:57:15 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id D1F523E688 - for ; Wed, 1 May 2002 10:57:14 -0400 (EDT) -Received: (qmail 96042 messnum 564683 invoked from network[159.134.166.63/p575.as1.limerick1.eircom.net]); 1 May 2002 14:57:13 -0000 -Received: from p575.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.63) - by mail03.svc.cra.dublin.eircom.net (qp 96042) with SMTP; 1 May 2002 14:57:13 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g41EvIh33626; - Wed, 1 May 2002 15:57:18 +0100 (BST) - (envelope-from timbo) -Date: Wed, 1 May 2002 15:57:18 +0100 -From: Tim Bunce -To: Calin Medianu -Cc: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020501155718.S16831@dansat.data-plan.com> -References: <20020430151126.Q16831@dansat.data-plan.com> <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020430183429.33340.qmail@web10005.mail.yahoo.com>; from calinm@yahoo.com on Tue, Apr 30, 2002 at 11:34:29AM -0700 -Status: RO -Content-Length: 3111 -Lines: 111 - -Thanks. I'll take a look when I get to DBD::Oracle again. - -I think the last row of that table applies and it doesn't refer to OCIBindObject(): - REF CURSOR variables - SQLT_RSET - Allocate a statement handle, OCIStmt, and then bind its address - (OCIStmt **) using the SQLT_RSET datatype. -Note that SQLT_REF isn't the same as SQLT_RSET. - -You could always try patching it yourself! - -Tim. - - -On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin Medianu wrote: -> It says here: -> http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> -> that 2 calls are neede to bind a ref , the second is -> to OCIBindObject() which I don't see in dbdimp.c. -> -> Could this be a reason? -> -> Cheers, -> -> Calin -> -> --- Tim Bunce wrote: -> > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > Medianu wrote: -> > > Me again with the slow cursors. -> > > -> > > I modified both queries to only return 10 rows. -> > > I ran a sniffer (ethereal) on the NIC. It is -> > pretty cool, it also decodes TNS. -> > > -> > > when I am using the SQL, it works like this, there -> > are about 7 packets -> > > received by my workstation to set up the session, -> > then all 10 rows are in the -> > > same packet, then there is another packet probably -> > saying goodbye. -> > > -> > > When I am using the REF cursor, each row comes in -> > it's own TNS packet, that -> > > is why it is so slow! -> > > -> > > Any idea how to fix it? -> > -> > Do a level 9 trace to get a log of the OCI calls and -> > confirm that -> > the fragment I posted is being called (may be -> > helpful to also -> > add an extra print statement into that code since -> > parsing the -> > OCI trace can be painful). -> > -> > Assuming the code is being called then as far as I -> > can see the code is -> > doing the right thing and it's probably an Oracle -> > OCI issue. -> > -> > You'd need to talk to Oracle support. No need to -> > mention perl etc. -> > Just talk about your OCI application and provide the -> > OCI call trace. -> > -> > Let me know what you find out! -> > -> > Tim. -> > -> > > thanks a lot, -> > > -> > > Calin -> > > -> > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> > Medianu wrote: -> > > > > Hello, -> > > > > -> > > > > I did the following. Wrote a perl script that -> > retreves -> > > > > data via a straight select from the database. -> > Then I -> > > > > wrote a stored procedure returning a ref -> > cursor open -> > > > > on the same select statement and retrieved the -> > data as -> > > > > well. Using the REF CURSOR/ sotred procedure -> > was about -> > > > > 3 time slower, that is 40 seconds instead of -> > around -> > > > > 10. -> > > > > -> > > > > Is this normal? Is this a problem with oracle -> > or with -> > > > > DBD::Oracle? -> > > > -> > > > DBD::Oracle. It probably isn't setting up a row -> > cache for the ref cursor. -> > > > -> > > > Get a level 3 trace and look for the -> > "dbd_describe'd" line for the -> > > > ref cursor. -> > > > -> > > > Tim. -> -> -> __________________________________________________ -> Do You Yahoo!? -> Yahoo! Health - your guide to health and wellness -> http://health.yahoo.com - diff --git a/err_unsorted/err_slowcsr.msg b/err_unsorted/err_slowcsr.msg deleted file mode 100644 index 80c43350..00000000 --- a/err_unsorted/err_slowcsr.msg +++ /dev/null @@ -1,316 +0,0 @@ -From calinm@yahoo.com Tue Apr 30 22:03:11 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL3AR27018 - for ; Tue, 30 Apr 2002 22:03:10 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:03:10 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020196981:10:23493:39; Tue, 30 Apr 2002 20:03:01 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-1.mail.demon.net - id aa1108477; 30 Apr 2002 20:02 GMT -Received: from dolly1.pobox.com (dolly1.pobox.com [207.106.49.22]) - by silk.pobox.com (Postfix) with ESMTP id 915563FCE8 - for ; Tue, 30 Apr 2002 14:35:38 -0400 (EDT) -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 343702BFDD - for ; Tue, 30 Apr 2002 14:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10005.mail.yahoo.com (web10005.mail.yahoo.com [216.136.130.41]) - by dolly1.pobox.com (Postfix) with SMTP id 6AA822BFA3 - for ; Tue, 30 Apr 2002 14:34:37 -0400 (EDT) -Message-ID: <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Received: from [213.157.171.169] by web10005.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 11:34:29 PDT -Date: Tue, 30 Apr 2002 11:34:29 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020430151126.Q16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 2457 -Lines: 96 - -It says here: -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 - -that 2 calls are neede to bind a ref , the second is -to OCIBindObject() which I don't see in dbdimp.c. - -Could this be a reason? - -Cheers, - -Calin - ---- Tim Bunce wrote: -> On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> Medianu wrote: -> > Me again with the slow cursors. -> > -> > I modified both queries to only return 10 rows. -> > I ran a sniffer (ethereal) on the NIC. It is -> pretty cool, it also decodes TNS. -> > -> > when I am using the SQL, it works like this, there -> are about 7 packets -> > received by my workstation to set up the session, -> then all 10 rows are in the -> > same packet, then there is another packet probably -> saying goodbye. -> > -> > When I am using the REF cursor, each row comes in -> it's own TNS packet, that -> > is why it is so slow! -> > -> > Any idea how to fix it? -> -> Do a level 9 trace to get a log of the OCI calls and -> confirm that -> the fragment I posted is being called (may be -> helpful to also -> add an extra print statement into that code since -> parsing the -> OCI trace can be painful). -> -> Assuming the code is being called then as far as I -> can see the code is -> doing the right thing and it's probably an Oracle -> OCI issue. -> -> You'd need to talk to Oracle support. No need to -> mention perl etc. -> Just talk about your OCI application and provide the -> OCI call trace. -> -> Let me know what you find out! -> -> Tim. -> -> > thanks a lot, -> > -> > Calin -> > -> > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> Medianu wrote: -> > > > Hello, -> > > > -> > > > I did the following. Wrote a perl script that -> retreves -> > > > data via a straight select from the database. -> Then I -> > > > wrote a stored procedure returning a ref -> cursor open -> > > > on the same select statement and retrieved the -> data as -> > > > well. Using the REF CURSOR/ sotred procedure -> was about -> > > > 3 time slower, that is 40 seconds instead of -> around -> > > > 10. -> > > > -> > > > Is this normal? Is this a problem with oracle -> or with -> > > > DBD::Oracle? -> > > -> > > DBD::Oracle. It probably isn't setting up a row -> cache for the ref cursor. -> > > -> > > Get a level 3 trace and look for the -> "dbd_describe'd" line for the -> > > ref cursor. -> > > -> > > Tim. - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From calinm@yahoo.com Fri May 3 13:48:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g43Cm5R50489 - for ; Fri, 3 May 2002 13:48:05 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 03 May 2002 13:48:05 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020429421:10:02019:143; Fri, 03 May 2002 12:37:01 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1123562; 3 May 2002 12:36 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id D7BD1725A1 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10008.mail.yahoo.com (web10008.mail.yahoo.com [216.136.130.44]) - by wormwood.pobox.com (Postfix) with SMTP id 3088772674 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Message-ID: <20020503123640.19648.qmail@web10008.mail.yahoo.com> -Received: from [213.157.171.169] by web10008.mail.yahoo.com via HTTP; Fri, 03 May 2002 05:36:40 PDT -Date: Fri, 3 May 2002 05:36:40 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020501155718.S16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -Content-Length: 3619 -Lines: 150 - -Sure, - -I'll give it a try next week. - -Cheers, - -Calin ---- Tim Bunce wrote: -> Thanks. I'll take a look when I get to DBD::Oracle -> again. -> -> I think the last row of that table applies and it -> doesn't refer to OCIBindObject(): -> REF CURSOR variables -> SQLT_RSET -> Allocate a statement handle, OCIStmt, and then -> bind its address -> (OCIStmt **) using the SQLT_RSET datatype. -> Note that SQLT_REF isn't the same as SQLT_RSET. -> -> You could always try patching it yourself! -> -> Tim. -> -> -> On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin -> Medianu wrote: -> > It says here: -> > -> -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> > -> > that 2 calls are neede to bind a ref , the second -> is -> > to OCIBindObject() which I don't see in dbdimp.c. -> > -> > Could this be a reason? -> > -> > Cheers, -> > -> > Calin -> > -> > --- Tim Bunce wrote: -> > > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > > Medianu wrote: -> > > > Me again with the slow cursors. -> > > > -> > > > I modified both queries to only return 10 -> rows. -> > > > I ran a sniffer (ethereal) on the NIC. It is -> > > pretty cool, it also decodes TNS. -> > > > -> > > > when I am using the SQL, it works like this, -> there -> > > are about 7 packets -> > > > received by my workstation to set up the -> session, -> > > then all 10 rows are in the -> > > > same packet, then there is another packet -> probably -> > > saying goodbye. -> > > > -> > > > When I am using the REF cursor, each row comes -> in -> > > it's own TNS packet, that -> > > > is why it is so slow! -> > > > -> > > > Any idea how to fix it? -> > > -> > > Do a level 9 trace to get a log of the OCI calls -> and -> > > confirm that -> > > the fragment I posted is being called (may be -> > > helpful to also -> > > add an extra print statement into that code -> since -> > > parsing the -> > > OCI trace can be painful). -> > > -> > > Assuming the code is being called then as far as -> I -> > > can see the code is -> > > doing the right thing and it's probably an -> Oracle -> > > OCI issue. -> > > -> > > You'd need to talk to Oracle support. No need to -> > > mention perl etc. -> > > Just talk about your OCI application and provide -> the -> > > OCI call trace. -> > > -> > > Let me know what you find out! -> > > -> > > Tim. -> > > -> > > > thanks a lot, -> > > > -> > > > Calin -> > > > -> > > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, -> Calin -> > > Medianu wrote: -> > > > > > Hello, -> > > > > > -> > > > > > I did the following. Wrote a perl script -> that -> > > retreves -> > > > > > data via a straight select from the -> database. -> > > Then I -> > > > > > wrote a stored procedure returning a ref -> > > cursor open -> > > > > > on the same select statement and retrieved -> the -> > > data as -> > > > > > well. Using the REF CURSOR/ sotred -> procedure -> > > was about -> > > > > > 3 time slower, that is 40 seconds instead -> of -> > > around -> > > > > > 10. -> > > > > > -> > > > > > Is this normal? Is this a problem with -> oracle -> > > or with -> > > > > > DBD::Oracle? -> > > > > -> > > > > DBD::Oracle. It probably isn't setting up a -> row -> > > cache for the ref cursor. -> > > > > -> > > > > Get a level 3 trace and look for the -> > > "dbd_describe'd" line for the -> > > > > ref cursor. -> > > > > -> > > > > Tim. -> > -> > -> > __________________________________________________ -> > Do You Yahoo!? -> > Yahoo! Health - your guide to health and wellness -> > http://health.yahoo.com - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - diff --git a/err_unsorted/err_svrparse.msg b/err_unsorted/err_svrparse.msg deleted file mode 100644 index 16886ca8..00000000 --- a/err_unsorted/err_svrparse.msg +++ /dev/null @@ -1,4717 +0,0 @@ -From cary.millsap@hotsos.com Thu Sep 12 23:38:20 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8CMbgC02618 - for ; Thu, 12 Sep 2002 23:38:03 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 12 Sep 2002 23:38:03 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031869308:20:16258:30; Thu, 12 Sep 2002 22:21:48 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2108888; 12 Sep 2002 22:21 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id A32132F05C9 - for ; Thu, 12 Sep 2002 18:21:34 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-3.pobox.com (Postfix) with ESMTP id D71F62F056D - for ; Thu, 12 Sep 2002 18:21:31 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8CMLQn17849; - Thu, 12 Sep 2002 17:21:26 -0500 -From: "Cary Millsap" -To: -Subject: -Date: Thu, 12 Sep 2002 17:21:17 -0500 -Message-ID: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_016A_01C25A80.D1527130" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 64884 -Lines: 2025 - -This is a multi-part message in MIME format. - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: multipart/alternative; - boundary="----=_NextPart_001_016B_01C25A80.D1557E70" - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -How are you doing? I hope you've had a good two years since I saw you on -the Oracle Geek Cruise event. - - - -I've been working on a project this year to construct a book about -optimizing Oracle response time. In my research, I've discovered -something about the DBI that I didn't expect: it executes two Oracle -parse calls for every one that I would expect an efficient DBI layer to -make. I've included my Perl source (below), the Oracle level-12 trace -data that shows the sequence of calls it's receiving from the Perl -application (below), a level-9 DBI trace from the application -(attached), and our version information (below). - - - -The reason I'm bringing this to your attention in this way is that I'm -relying pretty heavily upon Perl for performance measurement tools, -examples, and simulators in the text. I love the language and I want for -the book to be an encouragement for more people to use Perl. However, -this extra-parse behavior is one of the things that the book highlights -as an important scalability barrier (some other tools do it too, -unfortunately). Of course, this is a speed bump on the road to my goal -of helping to promote Perl. - - - -I was hoping that by showing you this specific data, you could make the -problem go away. - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - -Listing [listing.sqltrace.pl]: a simple application that executes a -database query - -#!/usr/bin/perl - - - - - -# $Header: /home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 21:10:25 -cvm Exp $ - -# Cary Millsap (cary.millsap@hotsos.com) - - - - - -use strict; - -use warnings; - -use DBI; - -use DBD::Oracle; - -use Getopt::Long; - -use Term::ReadKey; - - - - - -my $sth; # Oracle statement handle - -my $hostname = ""; - -my $username = "/"; - -my $password = ""; - -my $logfile = "ex1.log"; - -my %attr = ( - - RaiseError => 1, - - AutoCommit => 0, - -); - -my %opt = ( - - pause => 0, - -); - - - - - -# Get command line options and arguments. - -GetOptions( - - "pause" => \$opt{pause}, - -); - -my $key = 37; # default query value - -$key = $ARGV[0] if $ARGV[0]; - - - - - -# Connect to Oracle. - -my $dbh = DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr); - -$dbh->trace(9, $logfile); - - - - - -# Activate tracing. - -$sth = $dbh->prepare(q(alter session set events '10046 trace name -context forever, level 12')); - -$sth->execute; - - - - - -# Allow the user to find the Oracle session and activate OS diagnostic - -# tools like strace(1) or lsof(8). - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Execute the query to trace. - -$sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -$sth->execute($key); - - - - - -# Print output header. - -my @cdefs = qw(%8d %8d %32s); # column definitions - -my @hdefs = qw(Key Fkey Value); # column headings - -my $bformat = join(" ", @cdefs) . "\n"; - -my $hformat; ($hformat = $bformat) =~ s/%(\d*)\S+/%$1s/g; - -printf $hformat, @hdefs; - -printf $hformat, do { my @h; push @h, "-" x (/(\d+)/?$1:10) for @cdefs; -@h }; - - - - - -# Print query results. - -for my $row (@{$sth->fetchall_arrayref}) { - - printf $bformat, @$row; - -} - - - - - -# Allow the user to do final OS diagnostic stuff. - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Disconnect from Oracle. - -$dbh->disconnect; - - - - - -Listing [listing:sqltrace.trc]: raw SQL trace output for an execution of -our program - -/usr/local/oracle/admin/V816/udump/ora_17349.trc - -Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production - -With the Partitioning option - -JServer Release 8.1.6.0.0 - Production - -ORACLE_HOME = /usr/local/oracle/product/8.1.6 - -System name: Linux - -Node name: www.hotsos.com - -Release: 2.2.16-22enterprise - -Version: #1 SMP Tue Aug 22 16:29:32 EDT 2000 - -Machine: i686 - -Instance name: V816 - -Redo thread mounted by this instance: 1 - -Oracle process number: 8 - -Unix process pid: 17349, image: oracle@www.hotsos.com (TNS V1-V3) - - - -*** SESSION ID:(7.9) 2002-09-12 16:14:01.582 - -===================== - -PARSING IN CURSOR #1 len=69 dep=0 uid=12 oct=42 lid=12 tim=107309054 -hv=1509700594 ad='54af5e14' - -alter session set events '10046 trace name context forever, level 12' - -END OF STMT - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107309054 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -*** 2002-09-12 16:14:31.226 - -WAIT #1: nam='SQL*Net message from client' ela= 2964 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -WAIT #2: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #2: nam='SQL*Net message from client' ela= 0 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -BINDS #1: - - bind 0: dty=1 mxl=32(04) mal=00 scl=00 pre=00 oacflg=25 oacfl2=10 -size=32 offset=0 - - bfp=0940e7f0 bln=32 avl=04 flg=05 - - value="8542" - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #1: nam='file open' ela= 0 p1=0 p2=0 p3=0 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6671 p3=1 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6678 p3=1 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - -*** 2002-09-12 16:14:56.200 - -WAIT #1: nam='SQL*Net message from client' ela= 2496 p1=1650815232 p2=1 -p3=0 - -XCTEND rlbk=0, rd_only=1 - -STAT #1 id=1 cnt=1 pid=0 pos=0 obj=5156 op='TABLE ACCESS BY INDEX ROWID -T ' - -STAT #1 id=2 cnt=2 pid=1 pos=1 obj=5157 op='INDEX UNIQUE SCAN ' - - - - - -$ perl -V - -Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration: - - Platform: - - osname=linux, osvers=2.2.5-22smp, archname=i386-linux - - uname='linux porky.devel.redhat.com 2.2.5-22smp #1 smp wed jun 2 -09:11:51 edt 1999 i686 unknown ' - - config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -Dcc=gcc --Dcccdlflags=-fPIC -Dinstallprefix=/usr -Dprefix=/usr --Darchname=i386-linux -Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm --Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Uuselargefiles' - - hint=recommended, useposix=true, d_sigaction=define - - usethreads=undef use5005threads=undef useithreads=undef -usemultiplicity=undef - - useperlio=undef d_sfio=undef uselargefiles=undef - - use64bitint=undef use64bitall=undef uselongdouble=undef -usesocks=undef - - Compiler: - - cc='gcc', optimize='-O2 -march=i386 -mcpu=i686', gccversion=2.96 -20000731 (experimental) - - cppflags='-fno-strict-aliasing' - - ccflags ='-fno-strict-aliasing' - - stdchar='char', d_stdstdio=define, usevfork=false - - intsize=4, longsize=4, ptrsize=4, doublesize=8 - - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', -lseeksize=4 - - alignbytes=4, usemymalloc=n, prototype=define - - Linker and Libraries: - - ld='gcc', ldflags =' -L/usr/local/lib' - - libpth=/usr/local/lib /lib /usr/lib - - libs=-lnsl -ldl -lm -lc -lcrypt - - libc=/lib/libc-2.1.92.so, so=so, useshrplib=false, libperl=libperl.a - - Dynamic Linking: - - dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' - - cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' - - - - - -Characteristics of this binary (from libperl): - - Compile-time options: - - Built under linux - - Compiled at Aug 7 2000 10:59:51 - - @INC: - - /usr/lib/perl5/5.6.0/i386-linux - - /usr/lib/perl5/5.6.0 - - /usr/lib/perl5/site_perl/5.6.0/i386-linux - - /usr/lib/perl5/site_perl/5.6.0 - - /usr/lib/perl5/site_perl - - . - - - - - -Other site information - -- Redhat Linux 7.0 - -- Oracle 8.1.6.1.0 - -- DBD-Oracle 1.12 - -- DBI 1.30 - - - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

How are you doing? I hope you’ve had a good two = -years -since I saw you on the Oracle Geek Cruise event.

- -

 

- -

I’ve been working on a project this year to = -construct -a book about optimizing Oracle response time. In my research, I’ve -discovered something about the DBI that I didn’t expect: it = -executes two -Oracle parse calls for every one that I would expect an efficient DBI = -layer to -make. I’ve included my Perl source (below), the Oracle level-12 = -trace -data that shows the sequence of calls it’s receiving from the Perl = -application -(below), a level-9 DBI trace from the application (attached), and our = -version information -(below).

- -

 

- -

The reason I’m bringing this to your attention = -in this -way is that I’m relying pretty heavily upon Perl for performance -measurement tools, examples, and simulators in the text. I love the = -language -and I want for the book to be an encouragement for more people to use = -Perl. -However, this extra-parse behavior is one of the things that the book = -highlights -as an important scalability barrier (some other tools do it too, = -unfortunately). -Of course, this is a speed bump on the road to my goal of helping to = -promote Perl.

- -

 

- -

I was hoping that by showing you this specific data, = -you -could make the problem go away.

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -
- -

Listing [listing.sqltrace.pl]: a simple = -application that -executes a database query

- -
- -
- -

#!/usr/bin/perl

- -

- -

- -

 

- -

 

- -

# = -$Header: -/home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 = -21:10:25 cvm Exp $

- -

- -

# = -Cary Millsap (cary.millsap@hotsos.com)

- -

- -

 

- -

 

- -

use = -strict;

- -

- -

use = -warnings;

- -

- -

use = -DBI;

- -

- -

use = -DBD::Oracle;

- -

- -

use = -Getopt::Long;

- -

- -

use = -Term::ReadKey;

- -

- -

 

- -

 

- -

my -$sth;           &n= -bsp;        -# Oracle statement handle

- -

- -

my = -$hostname =3D -"";

- -

- -

my = -$username =3D -"/";

- -

- -

my = -$password =3D -"";

- -

- -

my = -$logfile  -=3D "ex1.log";

- -

- -

my = -%attr =3D (

- -

- -

    -RaiseError =3D> 1,

- -

- -

    -AutoCommit =3D> 0,

- -

- -

);

- -

- -

my = -%opt =3D (

- -

- -

    -pause   =3D> 0,

- -

- -

);

- -

- -

 

- -

 

- -

# Get = -command line -options and arguments.

- -

- -

GetOptions(

- -

- -

    -"pause" =3D> \$opt{pause},

- -

- -

);

- -

- -

my = -$key =3D -37;           &nbs= -p;  - # default query value

- -

- -

$key = -=3D $ARGV[0] if -$ARGV[0];

- -

- -

 

- -

 

- -

# = -Connect to -Oracle.

- -

- -

my = -$dbh =3D -DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr);

- -

- -

$dbh->trace(9, -$logfile);

- -

- -

 

- -

 

- -

# = -Activate -tracing.

- -

- -

$sth = -=3D -$dbh->prepare(q(alter session set events '10046 trace name context = -forever, -level 12'));

- -

- -

$sth->execute;

- -

- -

 

- -

 

- -

# = -Allow the user -to find the Oracle session and activate OS diagnostic

- -

- -

# = -tools like -strace(1) or lsof(8).

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Execute the -query to trace.

- -

- -

$sth = -=3D -$dbh->prepare(q(select key, fkey, value from t where = -key=3D?));

- -

- -

$sth->execute($key);

- -

- -

 

- -

 

- -

# = -Print output -header.

- -

- -

my = -@cdefs =3D qw(%8d -%8d %32s);   # column definitions

- -

- -

my = -@hdefs =3D qw(Key -Fkey Value); # column headings

- -

- -

my = -$bformat =3D -join("  ", @cdefs) . "\n";

- -

- -

my = -$hformat; -($hformat =3D $bformat) =3D~ s/%(\d*)\S+/%$1s/g;

- -

- -

printf $hformat, -@hdefs;

- -

- -

printf $hformat, -do { my @h; push @h, "-" x (/(\d+)/?$1:10) for = -@cdefs; @h };

- -

- -

 

- -

 

- -

# = -Print query -results.

- -

- -

for = -my $row -(@{$sth->fetchall_arrayref}) {

- -

- -

    -printf $bformat, @$row;

- -

- -

}

- -

- -

- -

 

- -

 

- -

# = -Allow the user -to do final OS diagnostic stuff.

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Disconnect from -Oracle.

- -

- -

$dbh->disconnect;

- -
- -

 

- -

 

- -
- -

Listing [listing:sqltrace.trc]: raw SQL trace = -output for -an execution of our program

- -
- -
- -

/usr/local/oracle/admin/V816/udump/ora_17349.tr= -c

- -

Oracle8i Enterprise -Edition Release 8.1.6.1.0 - Production

- -

With = -the -Partitioning option

- -

JServer Release -8.1.6.0.0 - Production

- -

ORACLE_HOME =3D -/usr/local/oracle/product/8.1.6

- -

System -name:        Linux

- -

Node name:  = -www.hotsos.com

- -

Release:    = -2.2.16-22enterprise

- -

Version:    #1 -SMP Tue Aug 22 16:29:32 EDT 2000

- -

Machine:    = -i686

- -

Instance name: -V816

- -

Redo = -thread -mounted by this instance: 1

- -

Oracle process -number: 8

- -

Unix = -process pid: -17349, image: oracle@www.hotsos.com (TNS V1-V3)

- -

 

- -

*** = -SESSION -ID:(7.9) 2002-09-12 16:14:01.582

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D69 dep=3D0 uid=3D12 oct=3D42 lid=3D12 = -tim=3D107309054 hv=3D1509700594 -ad=3D'54af5e14'

- -

alter = -session set -events '10046 trace name context forever, level 12'

- -

END = -OF STMT

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -309054

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

*** = -2002-09-12 -16:14:31.226

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2964 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#2 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312018 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

WAIT = -#2: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#2: -nam=3D'SQL*Net message from client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312019 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

BINDS = -#1:

- -

 bind 0: -dty=3D1 mxl=3D32(04) mal=3D00 scl=3D00 pre=3D00 oacflg=3D25 oacfl2=3D10 = -size=3D32 offset=3D0

- -

   bfp=3D0940e7f0 bln=3D32 avl=3D04 flg=3D05

- -

   -value=3D"8542"

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#1: nam=3D'file -open' ela=3D 0 p1=3D0 p2=3D0 p3=3D0

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6671 p3=3D1

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6678 p3=3D1

- -

FETCH -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

*** = -2002-09-12 -16:14:56.200

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2496 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

XCTEND rlbk=3D0, -rd_only=3D1

- -

STAT = -#1 id=3D1 cnt=3D1 -pid=3D0 pos=3D0 obj=3D5156 op=3D'TABLE ACCESS BY INDEX ROWID T = -'

- -

STAT = -#1 id=3D2 cnt=3D2 -pid=3D1 pos=3D1 obj=3D5157 op=3D'INDEX UNIQUE SCAN '

- -
- -

 

- -

 

- -

$ perl -V

- -

Summary of my perl5 (revision 5.0 version 6 subversion 0) = -configuration:

- -

  Platform:

- -

    osname=3Dlinux, osvers=3D2.2.5-22smp, = -archname=3Di386-linux

- -

    uname=3D'linux porky.devel.redhat.com = -2.2.5-22smp #1 smp -wed jun 2 09:11:51 edt 1999 i686 unknown '

- -

    config_args=3D'-des -Doptimize=3D-O2 = --march=3Di386 -mcpu=3Di686 --Dcc=3Dgcc -Dcccdlflags=3D-fPIC -Dinstallprefix=3D/usr -Dprefix=3D/usr = --Darchname=3Di386-linux --Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm -Di_gdbm -Di_shadow = --Di_syslog -Dman3ext=3D3pm -Uuselargefiles'

- -

    hint=3Drecommended, useposix=3Dtrue, = -d_sigaction=3Ddefine

- -

    usethreads=3Dundef use5005threads=3Dundef = -useithreads=3Dundef -usemultiplicity=3Dundef

- -

    useperlio=3Dundef d_sfio=3Dundef = -uselargefiles=3Dundef

- -

    use64bitint=3Dundef use64bitall=3Dundef = -uselongdouble=3Dundef -usesocks=3Dundef

- -

  Compiler:

- -

    cc=3D'gcc', optimize=3D'-O2 -march=3Di386 = --mcpu=3Di686', gccversion=3D2.96 -20000731 (experimental)

- -

    = -cppflags=3D'-fno-strict-aliasing'

- -

    ccflags = -=3D'-fno-strict-aliasing'

- -

    stdchar=3D'char', d_stdstdio=3Ddefine, = -usevfork=3Dfalse

- -

    intsize=3D4, longsize=3D4, ptrsize=3D4, = -doublesize=3D8

- -

    d_longlong=3Ddefine, longlongsize=3D8, = -d_longdbl=3Ddefine, -longdblsize=3D12

- -

    ivtype=3D'long', ivsize=3D4, = -nvtype=3D'double', nvsize=3D8, Off_t=3D'off_t', -lseeksize=3D4

- -

    alignbytes=3D4, usemymalloc=3Dn, = -prototype=3Ddefine

- -

  Linker and Libraries:

- -

    ld=3D'gcc', ldflags =3D' = --L/usr/local/lib'

- -

    libpth=3D/usr/local/lib /lib = -/usr/lib

- -

    libs=3D-lnsl -ldl -lm -lc = --lcrypt

- -

    libc=3D/lib/libc-2.1.92.so, so=3Dso, = -useshrplib=3Dfalse, libperl=3Dlibperl.a

- -

  Dynamic Linking:

- -

    dlsrc=3Ddl_dlopen.xs, dlext=3Dso, = -d_dlsymun=3Dundef, ccdlflags=3D'-rdynamic'

- -

    cccdlflags=3D'-fPIC', lddlflags=3D'-shared = --L/usr/local/lib'

- -

 

- -

 

- -

Characteristics of this binary (from libperl): = -

- -

  Compile-time options:

- -

  Built under linux

- -

  Compiled at Aug  7 2000 10:59:51

- -

  @INC:

- -

    = -/usr/lib/perl5/5.6.0/i386-linux

- -

    /usr/lib/perl5/5.6.0

- -

    = -/usr/lib/perl5/site_perl/5.6.0/i386-linux

- -

    = -/usr/lib/perl5/site_perl/5.6.0

- -

    /usr/lib/perl5/site_perl

- -

    .

- -

 

- -

 

- -

Other site information

- -

- Redhat Linux 7.0

- -

- Oracle 8.1.6.1.0

- -

- DBD-Oracle 1.12

- -

- DBI 1.30

- -

 

- -
- - - - - -------=_NextPart_001_016B_01C25A80.D1557E70-- - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: application/octet-stream; - name="ex1.log" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="ex1.log" - - DBI::db=3DHASH(0x8235a74) trace level set to 9 in DBI 1.30-nothread=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'alter session set events '10046 trace name context forever, level 12'')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240f68)=3D>DBI::st=3DHASH(0x8240f98),= - DBD::Oracle::st, 8240f74, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= -OCIHandleAlloc(0x82465d8,0x826c948,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826bf48,0x82559ec,'alter session set events '10046 = -trace name context forever, level 12'',69,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0x826c94c,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql ALTER=0A= - dbd_describe skipped for ALTER=0A= - <- prepare=3D DBI::st=3DHASH(0x8240f68) at ex1.pl line 38=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240f68)~0x8240f98)=0A= - dbd_st_execute ALTER (out0, lob0)...=0A= -OCIStmtExecute(0x82557c4,0x826bf48,0x82559ec,1,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff654,(nil),9,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute ALTER returned (SUCCESS, rpc0, fn52, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 39=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'select key, fkey, value from t where key=3D?')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240fe0)=3D>DBI::st=3DHASH(0x8240fb0),= - DBD::Oracle::st, 8240fec, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= - dbd_preparse scanned 1 distinct placeholders=0A= -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where = -key=3D:p1',44,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql SELECT=0A= - dbd_describe SELECT (EXPLICIT, lb 80)...=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3DSUCCES= -S=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3dc,(nil),18,0x82559ec)=3DSUCC= -ESS=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d1c0,1)=3DSUCCESS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d6,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d4,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d8,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1da,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1db,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1e8,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 1: 'KEY' NO null , otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d200,2)=3DSUCCESS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d216,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d214,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d218,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d228,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 2: 'FKEY' NULLable, otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d240,3)=3DSUCCESS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d256,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d254,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d258,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d268,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 3: 'VALUE' NULLable, otype 1-> 5, dbsize 32/33, p32.s0=0A= -OCIAttrSet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3d4,4,11,0x82559ec)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d1c4,0x82559ec,1,0x826e8d0,134,5,0x826d438,= -0x826d448,0x826d458,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d204,0x82559ec,2,0x826eaf8,134,5,0x826ca28,= -0x826ca38,0x826ca48,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d244,0x82559ec,3,0x826cbb8,33,5,0x826ca58,0= -x826cbe0,0x826cbf0,0)=3DSUCCESS=0A= - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231)=0A= - <- prepare=3D DBI::st=3DHASH(0x8240fe0) at ex1.pl line 50=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240f98)~INNER)=0A= -OCIHandleFree(0x826bf48,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef at ex1.pl line 51=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240fe0)~0x8240fb0 = -'8542')=0A= - bind :p1 <=3D=3D '8542' (type 0)=0A= - bind :p1 <=3D=3D '8542' (size 4/5/0, ptype 7, otype 1)=0A= - bind :p1 <=3D=3D '8542' (size 4/4, otype 1, indp 0, at_exec 1)=0A= -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb= -6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS=0A= -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da= -090)=3DSUCCESS=0A= - bind :p1 done with ftype 1=0A= - dbd_st_execute SELECT (out0, lob0)...=0A= - in ':p1' [0,0]: len 4, ind 0=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 51=0A= - -> fetchall_arrayref for DBD::Oracle::st = -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0)=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DSUCCESS=0A= - dbih_setup_fbav for 3 fields =3D> 0x8240fbc=0A= - dbd_st_fetch 3 fields SUCCESS=0A= - 0 (rc=3D0): '8542'=0A= - 1 (rc=3D0): '8542'=0A= - 2 (rc=3D0): 'value'=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DNO_DATA=0A= - dbd_st_fetch no-more-data=0A= - <- fetchall_arrayref=3D [ ARRAY(0x82411f0) ] row1 at ex1.pl line 62=0A= - -> disconnect for DBD::Oracle::db = -(DBI::db=3DHASH(0x8235b34)~0x8235a74)=0A= -OCISessionEnd(0x82557c4,0x82559ec,0x826c384,0)=3DSUCCESS=0A= -OCIServerDetach(0x8255834,0x82559ec,0)=3DSUCCESS=0A= - <- disconnect=3D 1 at ex1.pl line 74=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240fb0)~INNER)=0A= -OCIHandleFree(0x826e4a0,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -> DESTROY for DBD::Oracle::db (DBI::db=3DHASH(0x8235a74)~INNER)=0A= -OCIHandleFree(0x826c384,OCI_HTYPE_SESSION)=3DSUCCESS=0A= -OCIHandleFree(0x8255834,OCI_HTYPE_SERVER)=3DSUCCESS=0A= -OCIHandleFree(0x82557c4,OCI_HTYPE_SVCCTX)=3DSUCCESS=0A= -OCIHandleFree(0x82559ec,OCI_HTYPE_ERROR)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -------=_NextPart_000_016A_01C25A80.D1527130-- - - -From timbo@dansat.data-plan.com Fri Sep 13 07:30:31 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6UUC04053 - for ; Fri, 13 Sep 2002 07:30:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:30:30 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031871608:20:03733:55; Thu, 12 Sep 2002 23:00:08 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id ab2122693; 12 Sep 2002 23:00 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id AE0642F0B8A - for ; Thu, 12 Sep 2002 18:58:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id 931D42F0D0A - for ; Thu, 12 Sep 2002 18:58:19 -0400 (EDT) -Received: (qmail 57270 messnum 519666 invoked from network[159.134.164.69/p69.as1.limerick1.eircom.net]); 12 Sep 2002 22:58:17 -0000 -Received: from p69.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.69) - by mail03.svc.cra.dublin.eircom.net (qp 57270) with SMTP; 12 Sep 2002 22:58:17 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8CMwEQ02798; - Thu, 12 Sep 2002 23:58:14 +0100 (BST) - (envelope-from timbo) -Date: Thu, 12 Sep 2002 23:58:14 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls -Message-ID: <20020912225814.GG539@dansat.data-plan.com> -References: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 3530 -Lines: 77 - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCESS - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 '8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCESS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - -From cary.millsap@hotsos.com Fri Sep 13 07:31:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6VsC04590 - for ; Fri, 13 Sep 2002 07:31:54 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:31:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031889643:20:09494:0; Fri, 13 Sep 2002 04:00:43 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-2.mail.demon.net - id aa2008866; 13 Sep 2002 4:00 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id C94C67264F - for ; Fri, 13 Sep 2002 00:00:07 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by wormwood.pobox.com (Postfix) with ESMTP id A821072676 - for ; Fri, 13 Sep 2002 00:00:06 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D405n19404 - for ; Thu, 12 Sep 2002 23:00:05 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 22:59:56 -0500 -Message-ID: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020912225814.GG539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4825 -Lines: 129 - -Tim, - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Thursday, September 12, 2002 5:58 PM -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you -on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer -to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make -the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I -can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect -that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - - -From timbo@dansat.data-plan.com Fri Sep 13 10:48:59 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D9mwC06022 - for ; Fri, 13 Sep 2002 10:48:58 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 10:48:58 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031907122:20:19599:21; Fri, 13 Sep 2002 08:52:02 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2129553; 13 Sep 2002 8:52 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 99E263E660 - for ; Fri, 13 Sep 2002 04:51:54 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-2.pobox.com (Postfix) with SMTP id 721613E637 - for ; Fri, 13 Sep 2002 04:51:53 -0400 (EDT) -Received: (qmail 29161 messnum 524631 invoked from network[159.134.167.5/p773.as1.limerick1.eircom.net]); 13 Sep 2002 08:51:51 -0000 -Received: from p773.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.5) - by mail03.svc.cra.dublin.eircom.net (qp 29161) with SMTP; 13 Sep 2002 08:51:51 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8D8prO05752; - Fri, 13 Sep 2002 09:51:53 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 09:51:53 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913085153.GJ539@dansat.data-plan.com> -References: <20020912225814.GG539@dansat.data-plan.com> <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 6172 -Lines: 154 - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more "official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -> key=:p1',44,1,0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - -From cary.millsap@hotsos.com Fri Sep 13 17:52:40 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DGqdC10778 - for ; Fri, 13 Sep 2002 17:52:39 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 17:52:39 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031932999:10:25604:102; Fri, 13 Sep 2002 16:03:19 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101673; 13 Sep 2002 16:03 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E4A692C078 - for ; Fri, 13 Sep 2002 12:02:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 1609E2C03F - for ; Fri, 13 Sep 2002 12:02:29 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DG2Sn24856 - for ; Fri, 13 Sep 2002 11:02:28 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Fri, 13 Sep 2002 11:02:20 -0500 -Message-ID: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913085153.GJ539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 9234 -Lines: 248 - -Tim, - -I think it's important for a developer to have the ability to turn this -on and off. But I would argue that 0 is the correct default. I think of -it as a probability times cost function. The cost of leaving the setting -at 1 accidentally in a production application is pretty high: if the app -doesn't scale (because it's parsing too much), then it jeopardizes the -business' ability to succeed with it. - -The probability of leaving the option set to 1 accidentally during -production is very high. A point in evidence is that I didn't find the -parameter until I corresponded personally with you. I in fact *still* -don't know where to find it. I've checked Descartes & Bunce, perldoc -DBI, and perldoc DBD::Oracle without finding it yet... - -If the default were 0, the probability of leaving the option set to 0 -accidentally during development would be much lower. A developer faced -with a SQL syntax problem he doesn't understand will do the research -necessary to fix that problem. He can't release his code until he does. - -The problem with the default of 1 is, in my opinion, that most -developers will never learn of the feature, and they'll accidentally -leave it turned on in production. The proportion of developers who -competently performance-test their code is, unfortunately, -microscopically small. But they all do some level of functional testing. - -I would recommend making the ora_check_sql feature a more prominently -documented feature, presumably in "perldoc DBD::Oracle". - -I did learn in a test that specifying the option in the DBI->connect() -call doesn't do anything. Is it possible that you could allow us to -specify it at the connection level? The workaround is to do something -like this: - - use Getopt::Long; - my %prepare_attr = (ora_check_sql=>0); - GetOptions("dev"=>\$dev); - $prepare_attr{ora_check_sql} = 1 if $dev; - # developer must specify the command-line flag to get the -unscalable - # behavior that's necessary for functional testing - ... - $sth = $dbh->prepare($sql, %prepare_attr); # MUST specify -%p..attr - -...But I doubt that most Oracle application developers would come up -with this without some coaching. - -I'll definitely keep an eye open for projects you might like. It would -be a hell of an opportunity for someone to have you, I think. It seems -that if you could make a list like Oracle-L (1,900 people) aware that -there's an opportunity, it would improve your chances of finding -something quickly. It's of course bad taste to advertise oneself overtly -on those lists, but there is almost always a clever way to do it anyway -without offending anyone. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:52 AM -To: Cary Millsap -Cc: 'Tim Bunce' -Subject: Re: two Oracle parse calls - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge -to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our -lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a -preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more -"official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw -you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 -trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret -them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t -where -> key=:p1',44,1,0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: -231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), -{ -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call -parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:37 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLbC13725 - for ; Fri, 13 Sep 2002 23:21:37 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:37 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031951069:20:15816:152; Fri, 13 Sep 2002 21:04:29 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2120669; 13 Sep 2002 21:04 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 544863E642 - for ; Fri, 13 Sep 2002 17:04:17 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id 0AE7C3E667 - for ; Fri, 13 Sep 2002 17:04:16 -0400 (EDT) -Received: (qmail 16221 messnum 355694 invoked from network[159.134.166.226/p738.as1.limerick1.eircom.net]); 13 Sep 2002 21:04:14 -0000 -Received: from p738.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.226) - by mail05.svc.cra.dublin.eircom.net (qp 16221) with SMTP; 13 Sep 2002 21:04:14 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DL4Lx12642; - Fri, 13 Sep 2002 22:04:21 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:04:21 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913210421.GR539@dansat.data-plan.com> -References: <20020913085153.GJ539@dansat.data-plan.com> <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 3078 -Lines: 70 - -On Fri, Sep 13, 2002 at 11:02:20AM -0500, Cary Millsap wrote: -> Tim, -> -> I think it's important for a developer to have the ability to turn this -> on and off. But I would argue that 0 is the correct default. I think of -> it as a probability times cost function. The cost of leaving the setting -> at 1 accidentally in a production application is pretty high: if the app -> doesn't scale (because it's parsing too much), then it jeopardizes the -> business' ability to succeed with it. -> -> The probability of leaving the option set to 1 accidentally during -> production is very high. A point in evidence is that I didn't find the -> parameter until I corresponded personally with you. I in fact *still* -> don't know where to find it. I've checked Descartes & Bunce, perldoc -> DBI, and perldoc DBD::Oracle without finding it yet... - -It's not documented. - -As I recall it... originally DBD::Oracle defered the describe as -long as possible. But people reported very slow select performance: - - http://www.faqchest.com/prgm/dbi-l/dbi-99/dbi-9910/dbi-991005/dbi99101218_28018.html - -Turned out that the row cache logic needed the describe to try to -work out an optimal row cache size. Without the describe the row -cache wasn't getting set up. - -At some point I added code that would just set OCI_ATTR_PREFETCH_MEMORY -to a set size if ora_check_sql was 0. But I can't remember now why -I left ora_check_sql=1. - -It was possibly in relation to wanting to be able to use the -OCI_ATTR_PARSE_ERROR_OFFSET attribute to be able to highlight the -point in a query where the error was detected. But I think execute() -needs to be able to do that anyway (to catch syntax errors in -non-select statements). - -There is another problem. If the describe has been defered and the -application uses $sth->{NAME} or other similar attribute then the -describe has to be done at that point. The code is thee to do that -but the problem is how should the DBI behave if there's an error -in the SQL? It currently always croaks (rather than return undef, -in order to give a useful error message), but that's rather surprising -behaviour to many people and very unhelpful to some. - -There may well be other subtle issues that I can't recall right now. - -> I would recommend making the ora_check_sql feature a more prominently -> documented feature, presumably in "perldoc DBD::Oracle". -> -> I did learn in a test that specifying the option in the DBI->connect() -> call doesn't do anything. Is it possible that you could allow us to -> specify it at the connection level? - -By making it a database handle attribute, yes, that would be my plan. - -> I'll definitely keep an eye open for projects you might like. It would -> be a hell of an opportunity for someone to have you, I think. - -Thanks. - -> It seems that if you could make a list like Oracle-L (1,900 people) aware -> that there's an opportunity, it would improve your chances of finding -> something quickly. It's of course bad taste to advertise oneself overtly -> on those lists, but there is almost always a clever way to do it anyway -> without offending anyone. - -:-) - -Tim. - -From cary.millsap@hotsos.com Fri Sep 13 07:32:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6W1C04656 - for ; Fri, 13 Sep 2002 07:32:01 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:32:01 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031891038:20:04710:44; Fri, 13 Sep 2002 04:23:58 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id ab2004623; 13 Sep 2002 4:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 942A82BF2C - for ; Fri, 13 Sep 2002 00:23:44 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 73C982BF33 - for ; Fri, 13 Sep 2002 00:23:42 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D4Ndn19584 - for ; Thu, 12 Sep 2002 23:23:39 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 23:23:30 -0500 -Message-ID: <019301c25add$53f5dfd0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0194_01C25AB3.6B1FD7D0" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -Content-Length: 36859 -Lines: 1209 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Well, that was easy. Setting ora_check_sql=>0 does solve the problem. - - - -I now shift into "Please make 0 the default" mode. - - - -Here are the Oracle trace files, by the way, with a splash of color to -illustrate how the Oracle kernel sees what's going on (I hope you have -an HTML mail reader)... - - - -With {ora_check_sql=>1} (or no setting at all), here's what Oracle does -for the application: - - - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - - - -The PARSING IN CURSOR section tells us what SQL it is that we're -executing. Each line beginning with "PARSE" is emitted only when Oracle -executes a parse call. There are two. The first is wasted. - - - -Here's the same application with {ora_check_sql=>1} (the official new -default value, I am sure :-)): - - - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=109776065 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -FETCH #1:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=109776065 - - - -One parse call; problem solved. - - - -Thank you sincerely for your help. - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- -From: Cary Millsap [mailto:cary.millsap@hotsos.com] -Sent: Thursday, September 12, 2002 11:00 PM -To: 'Tim Bunce' -Subject: RE: two Oracle parse calls - - - -Tim, - - - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - - - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- - -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] - -Sent: Thursday, September 12, 2002 5:58 PM - -To: Cary Millsap - -Cc: tim.bunce@pobox.com - -Subject: two Oracle parse calls - - - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: - -> Tim, - -> - -> How are you doing? I hope you've had a good two years since I saw you -on - -> the Oracle Geek Cruise event. - - - -Yes thanks. And you? - - - -> I've been working on a project this year to construct a book about - -> optimizing Oracle response time. In my research, I've discovered - -> something about the DBI that I didn't expect: it executes two Oracle - -> parse calls for every one that I would expect an efficient DBI layer -to - -> make. I've included my Perl source (below), the Oracle level-12 trace - -> data that shows the sequence of calls it's receiving from the Perl - -> application (below), a level-9 DBI trace from the application - -> (attached), and our version information (below). - -> - -> I was hoping that by showing you this specific data, you could make -the - -> problem go away. - - - -I can only do what OCI lets me do... but within that I'll do what I -can... - - - -I'm not familar with Oracle trace logs so I can't readily intrepret them - -and I'll take what you say at face value. - - - -But I am familar with DBD::Oracle :) and the logs it writes :) - - - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -> $sth->execute($key); - - - - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - - dbd_preparse scanned 1 distinct placeholders - -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS - -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - - dbd_st_prepare'd sql SELECT - - dbd_describe SELECT (EXPLICIT, lb 80)... - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') - -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS - -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - - bind :p1 done with ftype 1 - - dbd_st_execute SELECT (out0, lob0)... - - in ':p1' [0,0]: len 4, ind 0 - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - - <- execute= '0E0' at ex1.pl line 51 - - - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - - - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -call that prepare() does. - - - -It doesn't do that for non-select statements so you could check if - -non-selects also have two parse calls. - - - -Also try doing - - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - - - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the - -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -is possibly redundant and could be removed (but Oracle ought to detect -that - -anyway and not make a round-trip for it, and certainly not call parse). - - - -If non-selects only have one parse call but ora_check_sql=>0 doesn't - -fix selects, then I might be able to do a simple patch to avoid the - -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - - - -Then the issue will be: should ora_check_sql=>0 be the default... - - - -Tim. - - - -p.s. I'd love a copy of your book when it's ready! - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Well, that was easy. Setting ora_check_sql=3D>0 = -does solve the -problem.

- -

 

- -

I now shift into "Please make 0 the = -default" mode.

- -

 

- -

Here are the Oracle trace files, by the way, with a = -splash -of color to illustrate how the Oracle kernel sees what’s going on = -(I hope -you have an HTML mail reader)...

- -

 

- -

With {ora_check_sql=3D>1} (or no setting at all), = -here’s -what Oracle does for the application:

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #2 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312018 = -hv=3D1997601641 ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF STMT

- -

PARSE = -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312019 = -hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF = -STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

FETCH = -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

 

- -

The PARSING IN CURSOR section tells us what SQL it is = -that -we’re executing. Each line beginning with “PARSE” is = -emitted -only when Oracle executes a parse call. There are two. The first is = -wasted.

- -

 

- -

Here’s the same application with = -{ora_check_sql=3D>1} (the official new = -default value, I -am sure J):

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 = -dep=3D0 uid=3D12 -oct=3D3 lid=3D12 tim=3D109776065 hv=3D1997601641 = -ad=3D'54af1384'

- -

select key, fkey, value from = -t where -key=3D:p1

- -

END OF STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

FETCH = -#1:c=3D0,e=3D0,p=3D0,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D109= -776065

- -

 

- -

One parse call; problem solved.

- -

 

- -

Thank you sincerely for your help.

- -

 

- -

 

- -

Cary = -Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System = -Performance, -Feb 9-12 Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 = -Middelfart Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----
-From: Cary Millsap [mailto:cary.millsap@hotsos.com]
-Sent: Thursday, September 12, 2002 11:00 PM
-To: 'Tim Bunce'
-Subject: RE: two Oracle parse calls

- -

 

- -

Tim,

- -

 

- -

Thanks so very much. The attribute ora_check_sql=3D>0 is new = -knowledge -to me; this is a nice reward for having written to you. I will test it = -either -tonight or the first thing tomorrow and then inform you of the results -immediately after that. If it solves the problem, then I will lobby you = -to make -0 the default value and probably consider the issue "problem = -solved."

- -

 

- -

Things are very well, thank you. I've been at home with my = -family now -for over three straight weeks, and we're having a nice time of our lives = -these -days with the business settling into stride a bit. Tonight is a big = -night for -me. I've just crossed the line of accepting a preliminary offer from = -O'Reilly. -This book project has actually been underway for quite some time now, = -but as of -tonight it's quite a bit more "official."

- -

 

- -

 

- -

Cary Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec = -9-11 -Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System Performance, Feb = -9-12 -Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 Middelfart = -Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----

- -

From: Tim Bunce [mailto:Tim.Bunce@pobox.com]

- -

Sent: Thursday, September 12, 2002 5:58 PM

- -

To: Cary Millsap

- -

Cc: tim.bunce@pobox.com

- -

Subject: two Oracle parse calls

- -

 

- -

On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap = -wrote:

- -

> Tim,

- -

>

- -

> How are you doing? I hope you've had a good two years since = -I saw -you on

- -

> the Oracle Geek Cruise event.

- -

 

- -

Yes thanks. And you?

- -

 

- -

> I've been working on a project this year to construct a = -book about

- -

> optimizing Oracle response time. In my research, I've = -discovered

- -

> something about the DBI that I didn't expect: it executes = -two -Oracle

- -

> parse calls for every one that I would expect an efficient = -DBI -layer to

- -

> make. I've included my Perl source (below), the Oracle = -level-12 -trace

- -

> data that shows the sequence of calls it's receiving from = -the Perl

- -

> application (below), a level-9 DBI trace from the = -application

- -

> (attached), and our version information = -(below).

- -

>

- -

> I was hoping that by showing you this specific data, you = -could -make the

- -

> problem go away.

- -

 

- -

I can only do what OCI lets me do... but within that I'll do = -what I -can...

- -

 

- -

I'm not familar with Oracle trace logs so I can't readily = -intrepret -them

- -

and I'll take what you say at face value.

- -

 

- -

But I am familar with DBD::Oracle :) and the logs it writes = -:)

- -

 

- -

> $sth =3D $dbh->prepare(q(select key, fkey, value from t = -where -key=3D?));

- -

> $sth->execute($key);

- -

 

- -

 

- -

    -> prepare for DBD::Oracle::db -(DBI::db=3DHASH(0x8235b34)~0x8235a74 'select key, fkey, value from t = -where -key=3D?')

- -

    dbd_preparse scanned 1 distinct = -placeholders

- -

OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCC= -ESS

- -

OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from = -t -where key=3D:p1',44,1,0)=3DSUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)= -=3DSUCCESS

- -

    dbd_st_prepare'd sql SELECT

- -

    dbd_describe SELECT (EXPLICIT, lb = -80)...

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3D= -SUCCESS

- -

    dbd_describe'd 3 columns (row bytes: 76 max, = -40 est -avg, cache: 231)

- -

    <- prepare=3D DBI::st=3DHASH(0x8240fe0) at = -ex1.pl -line 50

- -

    -> execute for DBD::Oracle::st -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0 '8542')

- -

OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x8= -26cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS - -

OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40= -,0x401da090)=3DSUCCESS

- -

       bind :p1 done with ftype = -1

- -

    dbd_st_execute SELECT (out0, = -lob0)...

- -

       in  ':p1' [0,0]: = -len  4, -ind 0

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3D= -SUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec= -)=3DSUCCESS

- -

    dbd_st_execute SELECT returned (SUCCESS, = -rpc0, fn4, -out0)

- -

    <- execute=3D '0E0' at ex1.pl line = -51

- -

 

- -

Given those OCI calls, what is DBD::Oracle doing that it = -shouldn't?

- -

 

- -

I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

call that prepare() does.

- -

 

- -

It doesn't do that for non-select statements so you could check = -if

- -

non-selects also have two parse calls.

- -

 

- -

Also try doing

- -

  $sth =3D $dbh->prepare(q(select key, fkey, value from = -t where -key=3D?), { ora_check_sql=3D> 0 });

- -

 

- -

which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till = -after the

- -

main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

is possibly redundant and could be removed (but Oracle ought to = -detect -that

- -

anyway and not make a round-trip for it, and certainly not call = -parse).

- -

 

- -

If non-selects only have one parse call but = -ora_check_sql=3D>0 doesn't

- -

fix selects, then I might be able to do a simple patch to avoid = -the

- -

OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if = -ora_check_sql=3D>0.

- -

 

- -

Then the issue will be: should ora_check_sql=3D>0 be the = -default...

- -

 

- -

Tim.

- -

 

- -

p.s. I'd love a copy of your book when it's = -ready!

- -
- - - - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0-- - - -From cary.millsap@hotsos.com Fri Sep 13 21:17:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DKHhC12417 - for ; Fri, 13 Sep 2002 21:17:43 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 21:17:43 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031946929:20:18513:70; Fri, 13 Sep 2002 19:55:29 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2018248; 13 Sep 2002 19:55 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 7FC402C01F - for ; Fri, 13 Sep 2002 15:55:06 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 76A5E2BFE1 - for ; Fri, 13 Sep 2002 15:55:05 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DJt4n26736 - for ; Fri, 13 Sep 2002 14:55:04 -0500 -From: "Cary Millsap" -To: "Tim Bunce" -Subject: A little more data -Date: Fri, 13 Sep 2002 14:54:56 -0500 -Message-ID: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0203_01C25B35.89729F60" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4948 -Lines: 166 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -I hope this is helpful. I have noticed that I cannot produce the -extra-parse problem on my 8.1.7 laptop database, no matter what the -setting of ora_check_sql. All of the data I've sent you is from our -8.1.6 Linux database. If you really needed it, I could produce level-9 -DBI trace data from identical tests on both platforms, but I won't spend -the time doing that unless you say it will help... - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - - - - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

I hope this is helpful… I have noticed that I = -cannot -produce the extra-parse problem on my 8.1.7 laptop database, no matter = -what the -setting of ora_check_sql. All of the data I’ve sent you is from = -our 8.1.6 -Linux database. If you really needed it, I could produce level-9 DBI = -trace data -from identical tests on both platforms, but I won’t spend the time = -doing -that unless you say it will help...

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -

 

- -
- - - - - -------=_NextPart_000_0203_01C25B35.89729F60-- - - -From timbo@dansat.data-plan.com Fri Sep 13 22:05:30 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL5UC12942 - for ; Fri, 13 Sep 2002 22:05:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:05:30 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031948458:10:20432:5; Fri, 13 Sep 2002 20:20:58 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-1.mail.demon.net - id aa1020174; 13 Sep 2002 20:20 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 8A60E3E659 - for ; Fri, 13 Sep 2002 16:20:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id CAC663E685 - for ; Fri, 13 Sep 2002 16:20:36 -0400 (EDT) -Received: (qmail 37861 messnum 258096 invoked from network[159.134.164.124/p124.as1.limerick1.eircom.net]); 13 Sep 2002 20:20:35 -0000 -Received: from p124.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.124) - by mail05.svc.cra.dublin.eircom.net (qp 37861) with SMTP; 13 Sep 2002 20:20:35 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DKKhu12535; - Fri, 13 Sep 2002 21:20:43 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 21:20:43 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data -Message-ID: <20020913202043.GO539@dansat.data-plan.com> -References: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1098 -Lines: 34 - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - -From cary.millsap@hotsos.com Fri Sep 13 22:04:47 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL4kC12684 - for ; Fri, 13 Sep 2002 22:04:46 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:04:46 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031949629:20:13745:23; Fri, 13 Sep 2002 20:40:29 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2013849; 13 Sep 2002 20:40 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 7D90A3E650 - for ; Fri, 13 Sep 2002 16:40:20 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-1.pobox.com (Postfix) with ESMTP id 785AB3E642 - for ; Fri, 13 Sep 2002 16:40:19 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DKeIn27106 - for ; Fri, 13 Sep 2002 15:40:18 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: A little more data -Date: Fri, 13 Sep 2002 15:40:10 -0500 -Message-ID: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913202043.GO539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 1999 -Lines: 63 - -Well, it's 1.06 on my Windows machine (the most up-to-date version -available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -but interesting that (admitting now that there's a new degree of freedom -running loose amid the test) "the older version performs better than the -newer one." :) That's certainly not a fair statement if the diff between -8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:21 PM -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't -spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:32 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLWC13692 - for ; Fri, 13 Sep 2002 23:21:32 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:32 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031952887:10:13297:20; Fri, 13 Sep 2002 21:34:47 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1118141; 13 Sep 2002 21:34 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C7D482BF23 - for ; Fri, 13 Sep 2002 17:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail00.svc.cra.dublin.eircom.net (mail00.svc.cra.dublin.eircom.net [159.134.118.16]) - by dolly1.pobox.com (Postfix) with SMTP id 8352A2BF6C - for ; Fri, 13 Sep 2002 17:34:36 -0400 (EDT) -Received: (qmail 5093 messnum 521124 invoked from network[159.134.164.134/p134.as1.limerick1.eircom.net]); 13 Sep 2002 21:34:34 -0000 -Received: from p134.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.134) - by mail00.svc.cra.dublin.eircom.net (qp 5093) with SMTP; 13 Sep 2002 21:34:34 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DLYeI13070; - Fri, 13 Sep 2002 22:34:40 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:34:40 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: A little more data -Message-ID: <20020913213440.GS539@dansat.data-plan.com> -References: <20020913202043.GO539@dansat.data-plan.com> <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 2282 -Lines: 69 - -According my RCS the default for ora_check_sql changed from 0 to 1 -around version 1.03. - -Tim. - -On Fri, Sep 13, 2002 at 03:40:10PM -0500, Cary Millsap wrote: -> Well, it's 1.06 on my Windows machine (the most up-to-date version -> available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -> but interesting that (admitting now that there's a new degree of freedom -> running loose amid the test) "the older version performs better than the -> newer one." :) That's certainly not a fair statement if the diff between -> 8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Friday, September 13, 2002 3:21 PM -> To: Cary Millsap -> Cc: Tim Bunce -> Subject: Re: A little more data -> -> If they're using the same version of DBD::Oracle then -> the change must me on the sever side. Maybe Oracle's -> woken up to the fact they don't need a second parse! -> -> Tim. -> -> On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > -> > -> > I hope this is helpful. I have noticed that I cannot produce the -> > extra-parse problem on my 8.1.7 laptop database, no matter what the -> > setting of ora_check_sql. All of the data I've sent you is from our -> > 8.1.6 Linux database. If you really needed it, I could produce level-9 -> > DBI trace data from identical tests on both platforms, but I won't -> spend -> > the time doing that unless you say it will help... -> > -> > -> > -> > Cary Millsap -> > Hotsos Enterprises, Ltd. -> > http://www.hotsos.com -> > -> > Upcoming events: -> > - Hotsos Clinic , Oct 1-3 San -> > Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> > - 2003 Hotsos Symposium on -> > OracleR System Performance, Feb 9-12 Dallas -> > - Next event: Miracle Database Forum , Sep -> > 20-22 Middlefart Denmark -> > -> > -> > -> - diff --git a/err_unsorted/err_xml.msg b/err_unsorted/err_xml.msg deleted file mode 100644 index 7a60a0cb..00000000 --- a/err_unsorted/err_xml.msg +++ /dev/null @@ -1,118 +0,0 @@ -From dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org Fri Aug 15 14:41:14 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h7FDe3MA043557 - for ; Fri, 15 Aug 2003 14:41:13 +0100 (BST) - (envelope-from dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 15 Aug 2003 14:41:13 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 19nc4X-0006LQ-BC; - Fri, 15 Aug 2003 10:44:41 +0000 -Received: from [207.106.49.22] (helo=dolly1.pobox.com) - by punt-3.mail.demon.net with esmtp id 19nc4X-0006LQ-BC - for pobox@dbi.demon.co.uk; Fri, 15 Aug 2003 10:44:41 +0000 -Received: from dolly1.pobox.com (localhost[127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 16F6B21C13B - for ; Fri, 15 Aug 2003 06:44:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.develooper.com[63.251.223.166]) - by dolly1.pobox.com (Postfix) with SMTP id 021F121C36F - for ; Fri, 15 Aug 2003 06:44:40 -0400 (EDT) -Received: (qmail 78180 invoked by uid 1005); 15 Aug 2003 10:44:34 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 71287 invoked by uid 76); 15 Aug 2003 10:32:13 -0000 -Delivered-To: dbi-users@perl.org -Received-SPF: unknown (domain of sender andyhassall@yahoo.com does not designate mailers: NXDOMAIN) -Message-ID: <20030815103200.24313.qmail@web9605.mail.yahoo.com> -Date: Fri, 15 Aug 2003 11:32:00 +0100 (BST) -From: =?iso-8859-1?q?Andy=20Hassall?= -Reply-To: andy@andyh.co.uk -Subject: Re: ERROR OCIDefineObject call needed but not implemented yet using XMLElement function -To: Susan Cassidy , dbi-users@perl.org -In-Reply-To: -MIME-Version: 1.0 -Content-Type: text/plain; charset=iso-8859-1 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.8 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,SPAM_PHRASE_01_02 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id h7FDe3MA043557 -Status: RO -Content-Length: 2299 -Lines: 65 - - --- Susan Cassidy wrote: > I am using DBD::Oracle. -I was on version 1.12, then I installed version -> 1.14, with the same result. -> -> This is Oracle 9.2.0. -> -> I have this select statement that works fine from SQL*Plus: -> -> select XMLElement("Sequences", -> XMLElement("Sequence", -> XMLATTRIBUTES ( b.local_name AS "ic-acckey", -> b.mol_type AS "molecule", -> n.seq_name AS "title"))) -> from gcg_bioseq b, gcg_annot_seq_name a, gcg_seq_name n -> where -> b.local_name = 'K00306' and -> b.seq_status = 'D' and -> b.seq_oid = a.seq_oid and -> a.seq_name_oid = n.seq_name_oid and -> n.name_type = 'LOCUS' -> -> -> When I run it via DBI/DBD I get this (trace level 2): -> -> DBI 1.32-nothread dispatch trace level set to 2 -> Note: perl is running without the recommended perl -w option -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x1b2314)~0x122bec ' -[snip -> Field 1 has an Oracle type (108) which is not explicitly supported -> fbh 1: -> -'XMLELEMENT("SEQUENCES",XMLELEMENT("SEQUENCE",XMLATTRIBUTES(B.LOCAL_NAMEAS"IC-ACCKEY",B.MOL_TYPEAS"MOLECULE",N.SEQ_NAMEAS"TITLE")))' -[snip] -> Error: prepare failed -> at line 56, error: ERROR OCIDefineObject call needed but not -> implemented yet -> -> Is there any other workaround for this than wrapping this up in a PL/SQL -> function? - - Don't rely on the implicit conversion to a string type that is done when -SQL*Plus displays an XMLElement; add .getClobVal() to the end of the -statement to retrieve it as a CLOB rather than the XMLElement object type -(which DBD::Oracle doesn't accept). - - i.e. - -select XMLElement("Sequences", - XMLElement("Sequence", - XMLATTRIBUTES ( b.local_name AS "ic-acckey", - b.mol_type AS "molecule", - n.seq_name AS "title"))).getClobVal() - from ... - - (or getStringVal() for a VARCHAR2) - -===== --- -Andy Hassall (andy@andyh.org) icq(5747695) http://www.andyh.co.uk -http://www.andyhsoftware.co.uk/space | disk usage analysis tool - -________________________________________________________________________ -Want to chat instantly with your online friends? Get the FREE Yahoo! -Messenger http://uk.messenger.yahoo.com/ - - diff --git a/err_unsorted/err_xml2.msg b/err_unsorted/err_xml2.msg deleted file mode 100644 index 3bb291c5..00000000 --- a/err_unsorted/err_xml2.msg +++ /dev/null @@ -1,700 +0,0 @@ -From dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org Fri Jan 30 12:50:15 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UClt3q069307 - for ; Fri, 30 Jan 2004 12:50:14 GMT - (envelope-from dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 12:50:14 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmWGJ-00057X-AG; - Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmWGJ-00057X-AG - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [207.8.214.3] (helo=puzzle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmWGI-0007XK-P3 - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:34 +0000 -Received: from puzzle.pobox.com (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 029E8701C6 - for ; Fri, 30 Jan 2004 05:52:34 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 12ABF701C1 - for ; Fri, 30 Jan 2004 05:52:30 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by puzzle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 05:51:10 -0500 (EST) -Received: (qmail 33345 invoked by uid 1005); 30 Jan 2004 10:50:36 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 33175 invoked by uid 76); 30 Jan 2004 10:50:26 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Fri, 30 Jan 2004 02:50:25 -0800 -Received: (qmail 21117 invoked by uid 225); 30 Jan 2004 10:48:52 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 21080 invoked by uid 507); 30 Jan 2004 10:48:49 -0000 -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Fri, 30 Jan 2004 02:48:46 -0800 -Received: (qmail 31958 invoked from network); 30 Jan 2004 11:50:38 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 30 Jan 2004 11:50:38 -0000 -Received: (qmail 6921 invoked from network); 30 Jan 2004 10:49:58 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 30 Jan 2004 10:49:58 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Fri, 30 Jan 2004 11:49:58 +0100 (CET) -Subject: DBD-Oracle and XMLType -From: Hendrik Fuss -To: "dbi-dev@perl.org" -Content-Type: multipart/mixed; boundary="=-fkyM33WAvQ5xV0uCPeSD" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 11:41:31 +0100 -Message-Id: <1075459292.7305.46.camel@mars> -Mime-Version: 1.0 -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.5 required=7.0 tests=MIME_LONG_LINE_QP,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01,TO_ADDRESS_EQ_REAL version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 8148 -Lines: 302 - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -Hi everyone, - -It's been a while since I last posted here. In September 2003 I was -trying to add support for binding XMLType objects to DBD-Oracle, so that -you could easily insert large (ie >4k) XML data into an XMLType table. - -Unfortunately my employer fired me in October 2003 and in the remaining -time I had to work on other projects, so I wasn't able to complete the -DBD project. Since I won't have access to an oracle database from now -on, I thought the least I can do is to provide my code as it is to the -list. Blame German economy. :-( - -The attached patch (based on DBD-Oracle 1.15) enables you to upload -XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -I added a function dbd_rebind_ph_nty for that purpose. You need to -create that XMLType object first using the C function -createxmlfromstring in xml.c. - -The XMLType object is either created from an OCIString or from a -temporary CLOB depending on the length of the source string. Have a look -at the bottom of ociap.h, all the (undocumented) XMLType functions are -there, and there are also some constants in oci.h. - -I'm not sure if the CLOB code currently works. - -Here is another code fragment: - - my $xml =3D createxml($dbh, 'Test document'); - my $sth =3D $dbh->prepare('INSERT INTO xml_type VALUES (?)'); - $sth->bind_param(1, $xml, { ora_type =3D> 108 }); # SQLT_NTY - $sth->execute(); - -Please note that this code is really just early development, which I -wouldn't publish under normal circumstances. :) I just hope it might me -useful to someone. - -Well then, time to say goodbye -thanks to Tim and everyone who contributed to dbi for a great piece of -software - -Cheers, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Description: -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - -151a152 -> case 108: /* SQLT_NTY */ -992a994,996 -> case SQL_UDT: -> return 108; /* Oracle NTY */ ->=20 -1004a1009,1072 -> static int -> dbd_rebind_ph_nty(sth, imp_sth, phs) -> SV* sth; -> imp_sth_t *imp_sth; -> phs_t *phs; -> { -> OCIType *tdo =3D NULL; -> sword status; -> SV* ptr; ->=20 -> if (phs->is_inout) -> croak("OUT binding for NTY is currently unsupported"); ->=20 -> /* ensure that the value is a support named object type */ -> /* (currently only OCIXMLType*) */ -> if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -> OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -> (CONST text*)"SYS", 3, -> (CONST text*)"XMLTYPE", 7, -> (CONST text*)0, 0, -> OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -> &tdo); ->=20 -> ptr =3D SvRV(phs->sv); -> phs->progv =3D (void*) SvIV(ptr); -> phs->maxlen =3D sizeof(OCIXMLType*); -> } -> else -> croak("Unsupported named object type for bind parameter"); ->=20 ->=20 -> /* bind by name */ ->=20 -> OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -> (text*)phs->name, (sb4)strlen(phs->name), -> (dvoid *) NULL, /* value supplied in BindObject later */ -> 0, -> (ub2)phs->ftype, 0, -> NULL, -> 0, 0, -> NULL, -> (ub4)OCI_DEFAULT, -> status -> ); ->=20 -> if (status !=3D OCI_SUCCESS) { -> oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -> return 0; -> } -> if (DBIS->debug >=3D 3) -> PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); ->=20 ->=20 -> /* bind the object */ ->=20 -> OCIBindObject(phs->bndhp, imp_sth->errhp, -> (CONST OCIType*)tdo, -> (dvoid **)&phs->progv, -> (ub4*)NULL, -> (dvoid **)NULL, -> (ub4*)NULL); ->=20 -> return 2; -> } -1309a1378,1380 -> case 108: -> done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -> break; -1331c1403 -< int at_exec =3D (phs->desc_h =3D=3D NULL); ---- -> int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); -1419c1491 -< if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) ---- -> if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQL= -T_NTY)) -1420a1493 -> /* ref allowed for OCIXMLType* */ -2219a2293 -> case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Disposition: attachment; filename=xml.c -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; name=xml.c; charset=ISO-8859-1 - -#include "oci.h" -#include - -/* This helper function creates an XMLType object from a string source. - * - * The resulting object can be bound to a placeholder, if ora_type =3D> - * SQLT_NTY is specified. - */ - -static void checkerr(errhp, status) -OCIError *errhp; -sword status; -{ - text errbuf[512]; - ub4 buflen; - sb4 errcode; - - switch (status) - { - case OCI_SUCCESS: - break; - case OCI_SUCCESS_WITH_INFO: - printf("Error - OCI_SUCCESS_WITH_INFO\n"); - break; - case OCI_NEED_DATA: - printf("Error - OCI_NEED_DATA\n"); - break; - case OCI_NO_DATA: - printf("Error - OCI_NO_DATA\n"); - break; - case OCI_ERROR: - OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, - errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR); - printf("Error - %s\n", errbuf); - exit(1); - break; - case OCI_INVALID_HANDLE: - printf("Error - OCI_INVALID_HANDLE\n"); - break; - case OCI_STILL_EXECUTING: - printf("Error - OCI_STILL_EXECUTE\n"); - break; - case OCI_CONTINUE: - printf("Error - OCI_CONTINUE\n"); - break; - default: - break; - } -} - - -#define MAX_OCISTRING_LEN 32766 - -SV* createxmlfromstring(SV* dbh, char* source) { - OCIXMLType *xml =3D NULL; - ub4 len; - ub1 src_type; - dvoid* src_ptr =3D NULL; - D_imp_dbh(dbh); - SV* sv_dest; - - len =3D strlen(source); - if(len > MAX_OCISTRING_LEN) { - src_type =3D OCI_XMLTYPE_CREATE_CLOB; - - printf("OCIDescriptorAlloc\n"); - checkerr( imp_dbh->errhp, - OCIDescriptorAlloc((dvoid*)imp_dbh->envhp, - (dvoid **)&src_ptr, - (ub4)OCI_DTYPE_LOB, - (size_t)0, - (dvoid**)0) ); - - printf("OCILobCreateTemporary\n"); - checkerr( imp_dbh->errhp, - OCILobCreateTemporary(imp_dbh->svchp, - imp_dbh->errhp,=20 - (OCILobLocator*) src_ptr, - (ub2)0,=20 - SQLCS_IMPLICIT,=20 - OCI_TEMP_CLOB,=20 - OCI_ATTR_NOCACHE,=20 - OCI_DURATION_SESSION) ); - - printf("OCILobWrite\n"); - checkerr (imp_dbh->errhp, - OCILobWriteAppend(imp_dbh->svchp, - imp_dbh->errhp, - (OCILobLocator*) src_ptr, - &len,=20 - (ub1*)source, - len, - OCI_ONE_PIECE, - (dvoid *)0,=20 - (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, - 0, - SQLCS_IMPLICIT)); - - } else { - src_type =3D OCI_XMLTYPE_CREATE_OCISTRING; - - printf("OCIStringAssignText\n"); - checkerr( imp_dbh->errhp, - OCIStringAssignText(imp_dbh->envhp, - imp_dbh->errhp,=20 - (CONST text*) source,=20 - (ub2) strlen(source), - (OCIString **) &src_ptr) - ); - } - - printf("OCIXMLTypeCreateFromSrc\n"); - checkerr( imp_dbh->errhp, - OCIXMLTypeCreateFromSrc(imp_dbh->svchp, - imp_dbh->errhp, - (OCIDuration)OCI_DURATION_CALLOUT, - (ub1)src_type, - (dvoid *)src_ptr, - (sb4)OCI_IND_NOTNULL, - &xml) - ); - - - /* free temporary resources */ - if( src_type =3D=3D OCI_XMLTYPE_CREATE_CLOB ) { - checkerr( imp_dbh->errhp, - OCILobFreeTemporary(imp_dbh->svchp, imp_dbh->errhp, - (OCILobLocator*) src_ptr) ); - - checkerr( imp_dbh->errhp, - OCIDescriptorFree((dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB) ); - } - - - sv_dest =3D newSViv(0); - sv_setref_pv(sv_dest, "OCIXMLTypePtr", xml); - return sv_dest; -} - ---=-fkyM33WAvQ5xV0uCPeSD-- - - - -From hendrik.fuss@morphochem.de Fri Jan 30 16:56:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UGsO3v071338 - for ; Fri, 30 Jan 2004 16:56:27 GMT - (envelope-from hendrik.fuss@morphochem.de) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 16:56:27 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmZJF-0001wN-DK; - Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmZJF-0001wN-DK - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmZJE-0003GM-Bm - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:48 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 334DE30C57 - for ; Fri, 30 Jan 2004 09:07:47 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id E65B230C2C - for ; Fri, 30 Jan 2004 09:07:45 -0500 (EST) -Received: from babel.morphochem.de (unknown [212.89.121.1]) - by boggle.pobox.com (Postfix) with ESMTP - for ; Fri, 30 Jan 2004 09:07:04 -0500 (EST) -Received: (qmail 29768 invoked from network); 30 Jan 2004 15:10:09 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) - by 212.89.121.1 with SMTP; 30 Jan 2004 15:10:09 -0000 -Received: (qmail 11736 invoked from network); 30 Jan 2004 14:09:30 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) - (envelope-sender ) - by localhost.morphochem.de (qmail-ldap-1.03) with SMTP - for ; 30 Jan 2004 14:09:30 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) - by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; - Fri, 30 Jan 2004 15:09:30 +0100 (CET) -Subject: Re: DBD-Oracle and XMLType -From: Hendrik Fuss -To: Tim Bunce -Cc: "dbi-dev@perl.org" -In-Reply-To: <20040130133443.GC70215@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> - <20040130133443.GC70215@dansat.data-plan.com> -Content-Type: multipart/mixed; boundary="=-Sq1IOPDEhKoqxUKefiS3" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 15:01:03 +0100 -Message-Id: <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Status: RO -X-Status: A -Content-Length: 5585 -Lines: 196 - - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -> > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.= -c -> > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > create that XMLType object first using the C function -> > createxmlfromstring in xml.c. ->=20 -> I there any chance you could post that as a context diff (diff -u ideally -> or else diff -c)? It's much safer and more useful. Thanks. - -Good idea. Here's a diff -u of dbdimp.c. - -By the way: I have thougt about general support of named types, not just -XMLType, but you need to get the type description (TDO) from somewhere. -My code just checks if the perl variable is a blessed reference of -"OCIXMLTypePtr". - -Also note that my code can't handle downloading of XMLType objects yet. - -best wishes, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Description: Context diff for dbdimp.c -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - ---- dbdimp.c.orig 2004-01-30 14:48:55.000000000 +0100 -+++ dbdimp.c 2003-10-07 12:17:17.000000000 +0200 -@@ -1,5 +1,5 @@ - /* -- $Id: dbdimp.c,v 1.1.1.1 2003/10/02 10:45:20 hfuss Exp $ -+ $Id: dbdimp.c,v 1.3 2003/10/07 10:17:17 hfuss Exp $ -=20 - Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce -=20 -@@ -149,6 +149,7 @@ - case 97: /* CHARZ */ - case 106: /* MLSLABEL */ - case 102: /* SQLT_CUR OCI 7 cursor variable */ -+ case 108: /* SQLT_NTY */ - case 112: /* SQLT_CLOB / long */ - case 113: /* SQLT_BLOB / long */ - case 116: /* SQLT_RSET OCI 8 cursor variable */ -@@ -990,6 +991,9 @@ - case SQL_LONGVARCHAR: - return 8; /* Oracle LONG */ -=20 -+ case SQL_UDT: -+ return 108; /* Oracle NTY */ -+ - case SQL_DATE: - case SQL_TIME: - case SQL_TIMESTAMP: -@@ -1002,6 +1006,70 @@ - } -=20 -=20 -+static int -+dbd_rebind_ph_nty(sth, imp_sth, phs) -+ SV* sth; -+ imp_sth_t *imp_sth; -+ phs_t *phs; -+{ -+ OCIType *tdo =3D NULL; -+ sword status; -+ SV* ptr; -+ -+ if (phs->is_inout) -+ croak("OUT binding for NTY is currently unsupported"); -+ -+ /* ensure that the value is a support named object type */ -+ /* (currently only OCIXMLType*) */ -+ if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -+ OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -+ (CONST text*)"SYS", 3, -+ (CONST text*)"XMLTYPE", 7, -+ (CONST text*)0, 0, -+ OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -+ &tdo); -+ -+ ptr =3D SvRV(phs->sv); -+ phs->progv =3D (void*) SvIV(ptr); -+ phs->maxlen =3D sizeof(OCIXMLType*); -+ } -+ else -+ croak("Unsupported named object type for bind parameter"); -+ -+ -+ /* bind by name */ -+ -+ OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -+ (text*)phs->name, (sb4)strlen(phs->name), -+ (dvoid *) NULL, /* value supplied in BindObject later */ -+ 0, -+ (ub2)phs->ftype, 0, -+ NULL, -+ 0, 0, -+ NULL, -+ (ub4)OCI_DEFAULT, -+ status -+ ); -+ -+ if (status !=3D OCI_SUCCESS) { -+ oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -+ return 0; -+ } -+ if (DBIS->debug >=3D 3) -+ PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); -+ -+ -+ /* bind the object */ -+ -+ OCIBindObject(phs->bndhp, imp_sth->errhp, -+ (CONST OCIType*)tdo, -+ (dvoid **)&phs->progv, -+ (ub4*)NULL, -+ (dvoid **)NULL, -+ (ub4*)NULL); -+ -+ return 2; -+} -=20 - static int=20 - dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr)=20 -@@ -1307,6 +1375,9 @@ - case SQLT_RSET: - done =3D dbd_rebind_ph_rset(sth, imp_sth, phs); - break; -+ case 108: -+ done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -+ break; - #else - case 102: /* SQLT_CUR */ - done =3D dbd_rebind_ph_cursor(sth, imp_sth, phs); -@@ -1315,6 +1386,7 @@ - default: - done =3D dbd_rebind_ph_char(sth, imp_sth, phs, &alen_ptr); - } -+ - if (done !=3D 1) { - if (done =3D=3D 2) { /* the rebind did the OCI bind call itself successfu= -lly */ - if (DBIS->debug >=3D 3) -@@ -1328,7 +1400,7 @@ - #ifdef OCI_V8_SYNTAX - if (phs->maxlen > phs->maxlen_bound) { - sword status; -- int at_exec =3D (phs->desc_h =3D=3D NULL); -+ int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, (sb4)strlen(phs->name), - phs->progv, -@@ -1416,8 +1488,9 @@ - } - assert(name !=3D Nullch); -=20 -- if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) -+ if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQLT= -_NTY)) - /* dbi handle allowed for cursor variables */ -+ /* ref allowed for OCIXMLType* */ - croak("Can't bind a reference (%s)", neatsvpv(newvalue,0)); - if (SvTYPE(newvalue) > SVt_PVLV) /* hook for later array logic? */ - croak("Can't bind a non-scalar value (%s)", neatsvpv(newvalue,0)); -@@ -2217,6 +2290,7 @@ - #ifdef OCI_V8_SYNTAX - case SQLT_CLOB: sql_fbh.dbtype =3D SQL_CLOB; break; - case SQLT_BLOB: sql_fbh.dbtype =3D SQL_BLOB; break; -+ case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - #endif - #ifdef SQLT_TIMESTAMP_TZ - case SQLT_TIMESTAMP_TZ: sql_fbh.dbtype =3D SQL_TIMESTAMP; break; - ---=-Sq1IOPDEhKoqxUKefiS3-- - - - -From timbo@dansat.data-plan.com Fri Jan 30 18:32:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UIVK3f073353 - for ; Fri, 30 Jan 2004 18:32:30 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 18:32:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmceP-000603-GP; - Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmceP-000603-GP - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [208.210.124.73] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1AmceO-0006dQ-DB - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:52 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 25AEA3F13D - for ; Fri, 30 Jan 2004 12:41:51 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9FB863F16E - for ; Fri, 30 Jan 2004 12:41:49 -0500 (EST) -Received: from mail09.svc.cra.dublin.eircom.net (mail09.svc.cra.dublin.eircom.net [159.134.118.25]) - by icicle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 12:41:11 -0500 (EST) -Received: (qmail 9504 messnum 226571 invoked from network[213.94.228.233/unknown]); 30 Jan 2004 17:40:43 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail09.svc.cra.dublin.eircom.net (qp 9504) with SMTP; 30 Jan 2004 17:40:43 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UHf33A072739; - Fri, 30 Jan 2004 17:41:03 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i0UHf2Wr072738; - Fri, 30 Jan 2004 17:41:02 GMT -Date: Fri, 30 Jan 2004 17:41:02 +0000 -From: Tim Bunce -To: Hendrik Fuss -Cc: Tim Bunce , "dbi-dev@perl.org" -Subject: Re: DBD-Oracle and XMLType -Message-ID: <20040130174102.GB72657@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> <20040130133443.GC70215@dansat.data-plan.com> <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <1075471263.7305.73.camel@mars> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1129 -Lines: 29 - -On Fri, Jan 30, 2004 at 03:01:03PM +0100, Hendrik Fuss wrote: -> > > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -> > > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > > create that XMLType object first using the C function -> > > createxmlfromstring in xml.c. -> > -> > I there any chance you could post that as a context diff (diff -u ideally -> > or else diff -c)? It's much safer and more useful. Thanks. -> -> Good idea. Here's a diff -u of dbdimp.c. - -Thanks. - -> By the way: I have thougt about general support of named types, not just -> XMLType, but you need to get the type description (TDO) from somewhere. -> My code just checks if the perl variable is a blessed reference of -> "OCIXMLTypePtr". - -Doing the equivalent of m/^OCI(\w+)Ptr$/ and then calling OCITypeByName -with $1 uppercased might take us (or someone) a step further. - -> Also note that my code can't handle downloading of XMLType objects yet. - -I'll trust that some kind soul with an itch will send a patch :-) - -Thanks again Hendrik. - -Tim. - diff --git a/err_unsorted/err_xmltypebindplsql.msg b/err_unsorted/err_xmltypebindplsql.msg deleted file mode 100644 index 08faa725..00000000 --- a/err_unsorted/err_xmltypebindplsql.msg +++ /dev/null @@ -1,174 +0,0 @@ -From dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org Thu Apr 25 11:02:42 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3PA2gK34525 - for ; Thu, 25 Apr 2002 11:02:42 +0100 (BST) - (envelope-from dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 25 Apr 2002 11:02:42 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1019721492:10:18778:60; Thu, 25 Apr 2002 07:58:12 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1109782; 25 Apr 2002 7:58 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 791692BF11 - for ; Thu, 25 Apr 2002 03:58:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id 976FB2BEE4 - for ; Thu, 25 Apr 2002 03:58:07 -0400 (EDT) -Received: (qmail 84467 invoked by uid 1005); 25 Apr 2002 07:58:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 77923 invoked by uid 76); 24 Apr 2002 23:08:56 -0000 -Date: Wed, 24 Apr 2002 19:08:54 -0400 -From: Mark Stillwell -To: dbi-users-help@perl.org, dbi-users@perl.org -Subject: Oracle 9 XMLTYPE insert -Message-ID: <20020424190852.C22854@byrd.biostat.ufl.edu> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -Status: RO -Content-Length: 1469 -Lines: 43 - -I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -Here is my problem, I have a table named 'test' with three fields: eid -(integer), x (SYS.XMLTYPE) and formname (text) - -I create a database handler and connect to the database just fine. - -I create a new statement handler with the following command: - -$sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -SYS.XMLTYPE.CREATEXML(?), ?"); - -I loop over some data, $eid gets and integer, $xmlvalue gets a string, -and $formname gets a string. So long as $xmlvalue is relatively short -$sth->execute($eid, $xmlvalue, $formname); works great, but as soon as -it becomes long enough to force the use of clob's I have a problem. - -So I tried the following: - -$sth->bind_param(1, $i); -$sth->bind_param(2, $xmlvalue, { ora_type => ORA_CLOB }); -$sth->bind_param(3, $intable); -$sth->execute; - -This works great if column 'x' is a normal CLOB and I omit the -sys.xmltype.createxml statement above, but when 'x' is of type -sys.xmltype I get the following error: - -nvalid LOB locator specified -ORA-06512: at "SYS.XMLTYPE", line 0 - -Right now I've hacked the setup so there is a supplemental table called -'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE test SET x -= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem like the -right way to do this. - -Is there any way to do what I want in the current version of -DBI/OracleDBD? - --- -Mark Stillwell -marklee@ufl.edu -http://plaza.ufl.edu/marklee/ - -From dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org Wed May 8 16:11:46 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g48FBjo24814 - for ; Wed, 8 May 2002 16:11:45 +0100 (BST) - (envelope-from dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 08 May 2002 16:11:45 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020870336:20:08175:2; Wed, 08 May 2002 15:05:36 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2109147; 8 May 2002 15:05 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id 68FE23E6D4 - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-3.pobox.com (Postfix) with SMTP id 33A783E64D - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Received: (qmail 65232 invoked by uid 1005); 8 May 2002 15:01:47 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 60079 invoked by uid 76); 8 May 2002 14:50:53 -0000 -From: "Ben Middleton" -To: -Cc: -Subject: Re: Oracle 9 XMLTYPE insert -Date: Wed, 8 May 2002 15:50:47 +0100 -Message-ID: -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0) -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -Content-Length: 1311 -Lines: 39 - -Hi. - -Not sure if you ever resolved this: - -> I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -> Here is my problem, I have a table named 'test' with three fields: -> eid (integer), x (SYS.XMLTYPE) and formname (text) - -> I create a new statement handler with the following command: - -> $sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -> SYS.XMLTYPE.CREATEXML(?), ?"); - -.... - -> Invalid LOB locator specified -> ORA-06512: at "SYS.XMLTYPE", line 0 - -> Right now I've hacked the setup so there is a supplemental table -> called 'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE -> test SET x= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem -> like the right way to do this. - -> Is there any way to do what I want in the current version of -> DBI/OracleDBD? - -I don't think that the current DBI/DBD can bind a CLOB to a PL/SQL function -(which is all the CREATEXML function is) - hence you will have to go with -the intermediate CLOB table solution. - -Incidentally, if you are using Oracle9i - have you tried using a TEMPORARY -TABLE with a CLOB column (see SQL Reference Guide)? If setup correctly, this -is automatically truncated at the end of a transaction, is managed by the -Server, and provides some efficiency benefits. We use this here quite -effectively. - -Ben. - - diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index ff71f86b..780e5901 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -11,6 +11,12 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; +{ + $DBD::Oracle::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Oracle database driver for the DBI module use DBI (); @@ -117,7 +123,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::dr; # ====== DRIVER ====== +{ package DBD::Oracle::dr; +{ + $DBD::Oracle::dr::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DRIVER ====== use strict; my %dbnames = (); # holds list of known databases (oratab + tnsnames) @@ -316,7 +328,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::db; # ====== DATABASE ====== +{ package DBD::Oracle::db; +{ + $DBD::Oracle::db::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DATABASE ====== use strict; use DBI qw(:sql_types); @@ -1008,7 +1026,13 @@ SQL } # end of package DBD::Oracle::db -{ package DBD::Oracle::st; # ====== STATEMENT ====== +{ package DBD::Oracle::st; +{ + $DBD::Oracle::st::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== STATEMENT ====== sub bind_param_inout_array { @@ -1099,9 +1123,18 @@ SQL 1; -__END__ +=pod + +=head1 NAME + +DBD::Oracle - Oracle database driver for the DBI module + +=head1 VERSION + +version 1.38 + =head1 SYNOPSIS use DBI; @@ -1115,7 +1148,6 @@ __END__ # for some advanced uses you may need Oracle type values: use DBD::Oracle qw(:ora_types); - =head1 DESCRIPTION DBD::Oracle is a Perl module which works with the DBI module to provide @@ -1223,7 +1255,6 @@ If port name is not specified, 1521 is the default. If service name is not speci The following examples show several ways a connection can be created: - $dbh = DBI->connect('dbi:Oracle:DB','username','password'); $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); @@ -1554,7 +1585,6 @@ DBDOxxxx where xxxx is the current version number. This value can be retrieved on the server side using V$SESSION_CONNECT_INFO or GV$SESSION_CONNECT_INFO - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); $dbh->{ora_driver_name} = $q; @@ -1725,7 +1755,6 @@ If the previous error was from a failed C due to a syntax error, this attribute gives the offset into the C attribute where the error was found. - =head4 ora_array_chunk_size Due to OCI limitations, DBD::Oracle needs to buffer up rows of @@ -1948,7 +1977,6 @@ DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. Starts a new session against the current database using the credentials supplied. - =head2 B $hashref = $dbh->private_attribute_info(); @@ -2076,7 +2104,6 @@ Implemented by DBI, no driver-specific impact. Implemented by DBI, no driver-specific impact. - =head2 B Type: boolean, inherited @@ -2085,7 +2112,6 @@ The CompatMode attribute is used by emulation layers (such as Oraperl) to enable It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. - =head1 ORACLE-SPECIFIC DATABASE HANDLE METHODS =head2 B @@ -2245,7 +2271,6 @@ The different types of placeholders cannot be mixed within a statement, but you use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. - =head2 B $sth = $dbh->prepare_cached($statement, \%attr); @@ -2264,7 +2289,6 @@ query was successful, returns undef if an error occurred, and returns -1 if the number of rows is unknown or not available. Note that this method will return B<0E0> instead of 0 for 'no rows were affected', in order to always return a true value if no error occurred. - =head2 B Oracle does not implement auto_increment of serial type columns it uses predefined @@ -2320,7 +2344,6 @@ If the script exits before disconnect is called (or, more precisely, if the data referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() methods automatically. It is best to explicitly disconnect rather than rely on this behavior. - =head2 B $rv = $dbh->ping; @@ -2669,7 +2692,6 @@ Examples: ## This executes the statement with 567 (integer) and "Zool" (varchar) $sth->execute(); - These attributes may be used in the C<\%attr> parameter of the L or L statement handle methods. @@ -2764,10 +2786,8 @@ Set L to 0 in prepare() to enable this behaviour. $rv = $sth->bind_param_inout($param_num, \$scalar, 0); - DBD::Oracle fully supports bind_param_inout below are some uses for this method. - =head3 B Oracle supports an extended SQL insert syntax which will return one @@ -2941,10 +2961,6 @@ the above example, the code would look something like this : ... } - - - - =head3 B DBD::Oracle has built-in support for B @@ -2979,13 +2995,11 @@ and B datatypes. The simple example is here: =item B -=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' +=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' will only take a reference to a scalar. =back - - =head3 B SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. @@ -3094,7 +3108,6 @@ you get: DBD::Oracle supports this undocumented feature of DBI. See L for an example. - =head2 B $rv = $sth->bind_param_array($param_num, $array_ref_or_value) @@ -3104,8 +3117,6 @@ DBD::Oracle supports this undocumented feature of DBI. See L method. - - =head2 B $rv = $sth->execute(@bind_values); @@ -3372,7 +3383,6 @@ However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch Only use scrollable cursors if you really have a good reason to. They do use up considerable more server and client resources and have poorer response times than non-scrolling cursors. - =head2 Enabling Scrollable Cursors To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; @@ -3388,7 +3398,6 @@ When the statement is executed you will then be able to use 'ora_fetch_scroll' m or you can still use any of the other fetch methods but with a poorer response time than if you used a non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. - =head2 Scrollable Cursor Methods The following driver-specific methods are used with scrollable cursors. @@ -3728,7 +3737,6 @@ You can tune this value by setting ora_oci_success_warn which will display the f In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. - =head3 Simple Fetch for CLOBs and BLOBs To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well @@ -4130,7 +4138,6 @@ Uses the Oracle OCILobTrim function. Returns the length of the LOB. Uses the Oracle OCILobGetLength function. - =item ora_lob_is_init $is_init = $dbh->ora_lob_is_init($lob_locator); @@ -4177,7 +4184,6 @@ lob_id field values, defined as follows: CREATE SEQUENCE lob_example_seq - =head3 Example: Inserting a new row with large data Unless enough memory is available to store and bind the @@ -4243,7 +4249,6 @@ can't be used effectively if AutoCommit is enabled). $offset += $length; } - In this example we demonstrate the use of ora_lob_write() interactively to append data to the columns 'bin_data' and 'char_data'. Had we used ora_lob_append(), we could have @@ -4260,7 +4265,6 @@ The scalar variables $offset and $length are no longer needed, because ora_lob_append() keeps track of the offset for us. - =head3 Example: Updating an existing row with large data In this example, we demonstrate a technique for overwriting @@ -4445,7 +4449,6 @@ WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other than US7ASCII, requires that the NLS_LANG environment variable be set. See the L<"Oracle UTF8 is not UTF-8"> section below. - You are strongly urged to read the Oracle Internationalization documentation specifically with respect the choices and trade offs for creating a databases for use with international character sets. @@ -4552,7 +4555,6 @@ If the C attribute is given to bind_param() then that determines if the value should be assumed to be in the default (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); ... $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); @@ -4593,7 +4595,6 @@ and TABLE in any combination. Support is seamless and recursive, meaning you need only supply a simple SQL statement to get all the values in an embedded object. You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. - Array example, given this type and table; CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); @@ -4746,7 +4747,6 @@ There are some types, like BOOLEAN, that Oracle does not automatically convert to or from strings (pity). These need to be converted explicitly using SQL or PL/SQL functions. - Examples: # DATE values @@ -4801,7 +4801,6 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" - =head4 Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special @@ -4949,7 +4948,6 @@ shows: } } - The cursor returned by the function C defined in the previous section can be fetched as a nested cursor as follows: @@ -5330,7 +5328,6 @@ There is a known problem with the 11.2g Oracle client and the C PL/SQL function. See L for the details. - =head1 SEE ALSO =over @@ -5398,4 +5395,34 @@ The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. The DBD::Oracle module is free open source software; you can redistribute it and/or modify it under the same terms as Perl 5. +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + + +__END__ + + diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index edacde25..d57d0592 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,4 +1,10 @@ package DBD::Oracle::GetInfo; +{ + $DBD::Oracle::GetInfo::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Wrapper to get Oracle information use strict; @@ -279,4 +285,44 @@ our %info = ( 1; + + +=pod + +=head1 NAME + +DBD::Oracle::GetInfo - Wrapper to get Oracle information + +=head1 VERSION + +version 1.38 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + + __END__ diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 39a99498..f7a4850f 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,25 +1,70 @@ -package DBD::Oracle::Object; -# ABSTRACT: Wrapper for Oracle objects - -use strict; -use warnings; - -sub type_name { shift->{type_name} } - -sub attributes { @{shift->{attributes}} } - -sub attr_hash { - my $self = shift; - return $self->{attr_hash} ||= { $self->attributes }; -} - -sub attr { - my $self = shift; - if (@_) { - my $key = shift; - return $self->attr_hash->{$key}; - } - return $self->attr_hash; -} - -1; +package DBD::Oracle::Object; +{ + $DBD::Oracle::Object::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; +} +# ABSTRACT: Wrapper for Oracle objects + +use strict; +use warnings; + +sub type_name { shift->{type_name} } + +sub attributes { @{shift->{attributes}} } + +sub attr_hash { + my $self = shift; + return $self->{attr_hash} ||= { $self->attributes }; +} + +sub attr { + my $self = shift; + if (@_) { + my $key = shift; + return $self->attr_hash->{$key}; + } + return $self->attr_hash; +} + +1; + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Object - Wrapper for Oracle objects + +=head1 VERSION + +version 1.38 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 6e422308..96f153ef 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,8 +1,24 @@ package DBD::Oracle::Troubleshooting; +{ + $DBD::Oracle::Troubleshooting::VERSION = '1.38'; +} +BEGIN { + $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; +} #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle + +__END__ =pod +=head1 NAME + +DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle + +=head1 VERSION + +version 1.38 + =head1 CONNECTING TO ORACLE If you are reading this it is assumed that you have successfully @@ -29,7 +45,6 @@ For Windows the solution is to add this value to you PATH PATH=c:\app\oracle\product\xx.x.x;%PATH% - If you get past this stage and get a ORA-12154: TNS:could not resolve the connect identifier specified @@ -61,7 +76,6 @@ Protocol Adapter". If it generates any errors which look relevant then please talk to your Oracle technical support (and not the dbi-users mailing list). - =head1 USING THE LONG TYPES Some examples related to the use of LONG types are available in @@ -96,7 +110,6 @@ It turns out that now it is necessary to edit the same file and append this and then run "genclntsh", the libclntsh is properly generated and the linkage with DBD::Oracle proceeds properly. - =head2 cc1: invalid option `tune=pentium4'" error If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. @@ -153,7 +166,7 @@ To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY as you would for an install against 10g Standard Edition, Standard Edition One, or Enterprise Edition -=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 +=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 DBD::Oracle seems to hit some sort of bug with the above two versions of DB. The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also @@ -172,7 +185,6 @@ So far there is no patch for this but here are some work arounds or this way utf8::downgrade($parameter, 1); - =head1 CYGWIN @@ -335,4 +347,30 @@ oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + diff --git a/t/000-report-versions.t b/t/000-report-versions.t new file mode 100644 index 00000000..2d4a9a19 --- /dev/null +++ b/t/000-report-versions.t @@ -0,0 +1,446 @@ +#!perl +use warnings; +use strict; +use Test::More 0.94; + +# Include a cut-down version of YAML::Tiny so we don't introduce unnecessary +# dependencies ourselves. + +package Local::YAML::Tiny; + +use strict; +use Carp 'croak'; + +# UTF Support? +sub HAVE_UTF8 () { $] >= 5.007003 } +BEGIN { + if ( HAVE_UTF8 ) { + # The string eval helps hide this from Test::MinimumVersion + eval "require utf8;"; + die "Failed to load UTF-8 support" if $@; + } + + # Class structure + require 5.004; + $YAML::Tiny::VERSION = '1.40'; + + # Error storage + $YAML::Tiny::errstr = ''; +} + +# Printable characters for escapes +my %UNESCAPES = ( + z => "\x00", a => "\x07", t => "\x09", + n => "\x0a", v => "\x0b", f => "\x0c", + r => "\x0d", e => "\x1b", '\\' => '\\', +); + + +##################################################################### +# Implementation + +# Create an empty YAML::Tiny object +sub new { + my $class = shift; + bless [ @_ ], $class; +} + +# Create an object from a file +sub read { + my $class = ref $_[0] ? ref shift : shift; + + # Check the file + my $file = shift or return $class->_error( 'You did not specify a file name' ); + return $class->_error( "File '$file' does not exist" ) unless -e $file; + return $class->_error( "'$file' is a directory, not a file" ) unless -f _; + return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; + + # Slurp in the file + local $/ = undef; + local *CFG; + unless ( open(CFG, $file) ) { + return $class->_error("Failed to open file '$file': $!"); + } + my $contents = ; + unless ( close(CFG) ) { + return $class->_error("Failed to close file '$file': $!"); + } + + $class->read_string( $contents ); +} + +# Create an object from a string +sub read_string { + my $class = ref $_[0] ? ref shift : shift; + my $self = bless [], $class; + my $string = $_[0]; + unless ( defined $string ) { + return $self->_error("Did not provide a string to load"); + } + + # Byte order marks + # NOTE: Keeping this here to educate maintainers + # my %BOM = ( + # "\357\273\277" => 'UTF-8', + # "\376\377" => 'UTF-16BE', + # "\377\376" => 'UTF-16LE', + # "\377\376\0\0" => 'UTF-32LE' + # "\0\0\376\377" => 'UTF-32BE', + # ); + if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) { + return $self->_error("Stream has a non UTF-8 BOM"); + } else { + # Strip UTF-8 bom if found, we'll just ignore it + $string =~ s/^\357\273\277//; + } + + # Try to decode as utf8 + utf8::decode($string) if HAVE_UTF8; + + # Check for some special cases + return $self unless length $string; + unless ( $string =~ /[\012\015]+\z/ ) { + return $self->_error("Stream does not end with newline character"); + } + + # Split the file into lines + my @lines = grep { ! /^\s*(?:\#.*)?\z/ } + split /(?:\015{1,2}\012|\015|\012)/, $string; + + # Strip the initial YAML header + @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; + + # A nibbling parser + while ( @lines ) { + # Do we have a document header? + if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { + # Handle scalar documents + shift @lines; + if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { + push @$self, $self->_read_scalar( "$1", [ undef ], \@lines ); + next; + } + } + + if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { + # A naked document + push @$self, undef; + while ( @lines and $lines[0] !~ /^---/ ) { + shift @lines; + } + + } elsif ( $lines[0] =~ /^\s*\-/ ) { + # An array at the root + my $document = [ ]; + push @$self, $document; + $self->_read_array( $document, [ 0 ], \@lines ); + + } elsif ( $lines[0] =~ /^(\s*)\S/ ) { + # A hash at the root + my $document = { }; + push @$self, $document; + $self->_read_hash( $document, [ length($1) ], \@lines ); + + } else { + croak("YAML::Tiny failed to classify the line '$lines[0]'"); + } + } + + $self; +} + +# Deparse a scalar string to the actual scalar +sub _read_scalar { + my ($self, $string, $indent, $lines) = @_; + + # Trim trailing whitespace + $string =~ s/\s*\z//; + + # Explitic null/undef + return undef if $string eq '~'; + + # Quotes + if ( $string =~ /^\'(.*?)\'\z/ ) { + return '' unless defined $1; + $string = $1; + $string =~ s/\'\'/\'/g; + return $string; + } + if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) { + # Reusing the variable is a little ugly, + # but avoids a new variable and a string copy. + $string = $1; + $string =~ s/\\"/"/g; + $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; + return $string; + } + + # Special cases + if ( $string =~ /^[\'\"!&]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + return {} if $string eq '{}'; + return [] if $string eq '[]'; + + # Regular unquoted string + return $string unless $string =~ /^[>|]/; + + # Error + croak("YAML::Tiny failed to find multi-line scalar content") unless @$lines; + + # Check the indent depth + $lines->[0] =~ /^(\s*)/; + $indent->[-1] = length("$1"); + if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Pull the lines + my @multiline = (); + while ( @$lines ) { + $lines->[0] =~ /^(\s*)/; + last unless length($1) >= $indent->[-1]; + push @multiline, substr(shift(@$lines), length($1)); + } + + my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; + my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; + return join( $j, @multiline ) . $t; +} + +# Parse an array +sub _read_array { + my ($self, $array, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { + # Inline nested hash + my $indent2 = length("$1"); + $lines->[0] =~ s/-/ /; + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { + # Array entry with a value + shift @$lines; + push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { + shift @$lines; + unless ( @$lines ) { + push @$array, undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)\-/ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] == $indent2 ) { + # Null array entry + push @$array, undef; + } else { + # Naked indenter + push @$array, [ ]; + $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines ); + } + + } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines ); + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + + } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { + # This is probably a structure like the following... + # --- + # foo: + # - list + # bar: value + # + # ... so lets return and let the hash parser handle it + return 1; + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + } + + return 1; +} + +# Parse an array +sub _read_hash { + my ($self, $hash, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Get the key + unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { + if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + my $key = $1; + + # Do we have a value? + if ( length $lines->[0] ) { + # Yes + $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines ); + } else { + # An indent + shift @$lines; + unless ( @$lines ) { + $hash->{$key} = undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)-/ ) { + $hash->{$key} = []; + $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } elsif ( $lines->[0] =~ /^(\s*)./ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] >= $indent2 ) { + # Null hash entry + $hash->{$key} = undef; + } else { + $hash->{$key} = {}; + $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } + } + } + } + + return 1; +} + +# Set error +sub _error { + $YAML::Tiny::errstr = $_[1]; + undef; +} + +# Retrieve error +sub errstr { + $YAML::Tiny::errstr; +} + + + +##################################################################### +# Use Scalar::Util if possible, otherwise emulate it + +BEGIN { + eval { + require Scalar::Util; + }; + if ( $@ ) { + # Failed to load Scalar::Util + eval <<'END_PERL'; +sub refaddr { + my $pkg = ref($_[0]) or return undef; + if (!!UNIVERSAL::can($_[0], 'can')) { + bless $_[0], 'Scalar::Util::Fake'; + } else { + $pkg = undef; + } + "$_[0]" =~ /0x(\w+)/; + my $i = do { local $^W; hex $1 }; + bless $_[0], $pkg if defined $pkg; + $i; +} +END_PERL + } else { + Scalar::Util->import('refaddr'); + } +} + + +##################################################################### +# main test +##################################################################### + +package main; + +BEGIN { + + # Skip modules that either don't want to be loaded directly, such as + # Module::Install, or that mess with the test count, such as the Test::* + # modules listed here. + # + # Moose::Role conflicts if Moose is loaded as well, but Moose::Role is in + # the Moose distribution and it's certain that someone who uses + # Moose::Role also uses Moose somewhere, so if we disallow Moose::Role, + # we'll still get the relevant version number. + + my %skip = map { $_ => 1 } qw( + App::FatPacker + Class::Accessor::Classy + Devel::Cover + Module::Install + Moose::Role + POE::Loop::Tk + Template::Test + Test::Kwalitee + Test::Pod::Coverage + Test::Portability::Files + Test::YAML::Meta + ); + + my $Test = Test::Builder->new; + + $Test->plan(skip_all => "META.yml could not be found") + unless -f 'META.yml' and -r _; + + my $meta = (Local::YAML::Tiny->read('META.yml'))->[0]; + my %requires; + for my $require_key (grep { /requires/ } keys %$meta) { + my %h = %{ $meta->{$require_key} }; + $requires{$_}++ for keys %h; + } + delete $requires{perl}; + + diag("Testing with Perl $], $^X"); + for my $module (sort keys %requires) { + if ($skip{$module}) { + note "$module doesn't want to be loaded directly, skipping"; + next; + } + local $SIG{__WARN__} = sub { note "$module: $_[0]" }; + use_ok $module or BAIL_OUT("can't load $module"); + my $version = $module->VERSION; + $version = 'undefined' unless defined $version; + diag(" $module version is $version"); + } + done_testing; +} diff --git a/xt/changes.t b/xt/changes.t deleted file mode 100644 index 27a4808a..00000000 --- a/xt/changes.t +++ /dev/null @@ -1,8 +0,0 @@ -use strict; -use warnings; - -use Test::More; - -eval 'use Test::CPAN::Changes'; -plan skip_all => 'Test::CPAN::Changes required for this test' if $@; -changes_ok(); diff --git a/xt/manifest.t b/xt/manifest.t deleted file mode 100644 index 00df9957..00000000 --- a/xt/manifest.t +++ /dev/null @@ -1,21 +0,0 @@ -use strict; -use warnings; - -use ExtUtils::Manifest qw/ fullcheck /; - -use Test::More tests => 1; - -my ( $missing, $extra ) = do { - local *STDERR; - - # hush little baby, don't you cry - open STDERR, '>', \my $stderr; - - fullcheck(); -}; - -ok @$missing + @$extra == 0, 'manifest in sync' or do { - diag "missing files:\n", map { " \t $_\n " } @$missing if @$missing; - diag "extra files: \n", map { "\t$_\n" } @$extra if @$extra; -}; - diff --git a/xt/pod.t b/xt/pod.t deleted file mode 100644 index 66481225..00000000 --- a/xt/pod.t +++ /dev/null @@ -1,11 +0,0 @@ -use Test::More; - -eval "use Test::Pod"; - -plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; - -pod_file_ok( 'Oracle.pm' ); -pod_file_ok( 'lib/DBD/Oracle/Object.pm' ); -pod_file_ok( 'lib/DBD/Oracle/GetInfo.pm' ); - -done_testing; From e2a3764035d473d00e2c282f1aca27503607e8dc Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 10 Feb 2012 13:38:38 -0500 Subject: [PATCH 129/637] rt74753, for truncated strings --- dbdimp.c | 7 +++++++ t/rt74753-utf8-encoded.t | 23 ++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 87e36826..f60989b8 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3222,6 +3222,13 @@ dbd_phs_sv_complete(phs_t *phs, SV *sv, I32 debug) SvCUR_set(sv, phs->alen); *SvEND(sv) = '\0'; SvPOK_only_UTF8(sv); + if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { +#ifdef sv_utf8_decode + sv_utf8_decode(sv); +#else + SvUTF8_on(sv); +#endif + } } else { /* shouldn't happen */ debug = 2; diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index ae318ad2..d50b1aee 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 2; +use Test::More tests => 3; use DBI; use Encode; @@ -57,18 +57,13 @@ $sth->execute; is Encode::is_utf8($val) => 1, "utf8 encoded"; -$dbh->disconnect; - - -__END__ - -undef $val; - $sth = $dbh->prepare(<<'END_SQL'); declare l_ret varchar2(10); begin - select ltrim(rtrim(to_char(0, 'L'))) + select ltrim(rtrim(to_char(0, 'L'))) + || ltrim(rtrim(to_char(0, 'L'))) + || ltrim(rtrim(to_char(0, 'L'))) into l_ret from dual; -- @@ -76,11 +71,13 @@ begin end; END_SQL -$sth->bind_param_inout( ':ret', \$val, 100 ); -$sth->execute; +$val = undef; -diag "val=[$val] len=@{[ length($val) ]}" while $sth->fetch; +# WARNING: does *not* truncate. DBD::Oracle doesn't heed the 3rd parameter +$sth->bind_param_inout(':ret', \$val, 1); +$sth->execute; -diag "utf8 is ", Encode::is_utf8($val) ? 'on' : 'off'; +is Encode::is_utf8($val) => 1, "truncated, yet utf8 encoded"; $dbh->disconnect; + From 2aafbf795fbd354ae269e4f17ce49c70855428ec Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 10 Feb 2012 13:38:38 -0500 Subject: [PATCH 130/637] rt74753, for truncated strings --- MANIFEST | 1 + dbdimp.c | 7 +++++++ t/rt74753-utf8-encoded.t | 23 ++++++++++------------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/MANIFEST b/MANIFEST index 436c409e..34c7a9d4 100644 --- a/MANIFEST +++ b/MANIFEST @@ -89,5 +89,6 @@ t/70meta.t t/80ora_charset.t t/nchar_test_lib.pl t/rt13865.t +t/rt74753-utf8-encoded.t test.pl typemap diff --git a/dbdimp.c b/dbdimp.c index 87e36826..f60989b8 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3222,6 +3222,13 @@ dbd_phs_sv_complete(phs_t *phs, SV *sv, I32 debug) SvCUR_set(sv, phs->alen); *SvEND(sv) = '\0'; SvPOK_only_UTF8(sv); + if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { +#ifdef sv_utf8_decode + sv_utf8_decode(sv); +#else + SvUTF8_on(sv); +#endif + } } else { /* shouldn't happen */ debug = 2; diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index ae318ad2..d50b1aee 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 2; +use Test::More tests => 3; use DBI; use Encode; @@ -57,18 +57,13 @@ $sth->execute; is Encode::is_utf8($val) => 1, "utf8 encoded"; -$dbh->disconnect; - - -__END__ - -undef $val; - $sth = $dbh->prepare(<<'END_SQL'); declare l_ret varchar2(10); begin - select ltrim(rtrim(to_char(0, 'L'))) + select ltrim(rtrim(to_char(0, 'L'))) + || ltrim(rtrim(to_char(0, 'L'))) + || ltrim(rtrim(to_char(0, 'L'))) into l_ret from dual; -- @@ -76,11 +71,13 @@ begin end; END_SQL -$sth->bind_param_inout( ':ret', \$val, 100 ); -$sth->execute; +$val = undef; -diag "val=[$val] len=@{[ length($val) ]}" while $sth->fetch; +# WARNING: does *not* truncate. DBD::Oracle doesn't heed the 3rd parameter +$sth->bind_param_inout(':ret', \$val, 1); +$sth->execute; -diag "utf8 is ", Encode::is_utf8($val) ? 'on' : 'off'; +is Encode::is_utf8($val) => 1, "truncated, yet utf8 encoded"; $dbh->disconnect; + From 941cdd06ad26611cadcadec32c858431d3add16a Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 10 Feb 2012 19:17:15 +0000 Subject: [PATCH 131/637] rt74753 for truncated strings with some code tidying git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15138 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- dbdimp.c | 7 + lib/DBD/Oracle.pm | 105 ++++++++------- lib/DBD/Oracle/GetInfo.pm | 274 +++++++++++++++++--------------------- t/rt74753-utf8-encoded.t | 23 ++-- 5 files changed, 192 insertions(+), 219 deletions(-) diff --git a/Changes b/Changes index b14e1680..8b7b9b70 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -NEXT 2012-02-08 +NEXT [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED diff --git a/dbdimp.c b/dbdimp.c index 87e36826..f60989b8 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3222,6 +3222,13 @@ dbd_phs_sv_complete(phs_t *phs, SV *sv, I32 debug) SvCUR_set(sv, phs->alen); *SvEND(sv) = '\0'; SvPOK_only_UTF8(sv); + if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { +#ifdef sv_utf8_decode + sv_utf8_decode(sv); +#else + SvUTF8_on(sv); +#endif + } } else { /* shouldn't happen */ debug = 2; diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9e610a68..780e5901 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -59,42 +59,50 @@ BEGIN { } sub driver{ - return $drh if $drh; - my($class, $attr) = @_; - my $oci = DBD::Oracle::ORA_OCI(); - - $class .= "::dr"; - - # not a 'my' since we use it above to prevent multiple drivers - - $drh = DBI::_new_drh($class, { - 'Name' => 'Oracle', - 'Version' => $VERSION, - 'Err' => \my $err, - 'Errstr' => \my $errstr, - 'Attribution' => "DBD::Oracle $VERSION using OCI$oci by Tim Bunce", - }); - DBD::Oracle::dr::init_oci($drh) ; - $drh->STORE('ShowErrorStatement', 1); - DBD::Oracle::db->install_method("ora_lob_read"); - DBD::Oracle::db->install_method("ora_lob_write"); - DBD::Oracle::db->install_method("ora_lob_append"); - DBD::Oracle::db->install_method("ora_lob_trim"); - DBD::Oracle::db->install_method("ora_lob_length"); - DBD::Oracle::db->install_method("ora_lob_chunk_size"); - DBD::Oracle::db->install_method("ora_lob_is_init"); - DBD::Oracle::db->install_method("ora_nls_parameters"); - DBD::Oracle::db->install_method("ora_can_unicode"); - DBD::Oracle::db->install_method("ora_can_taf"); - DBD::Oracle::db->install_method("ora_db_startup"); - DBD::Oracle::db->install_method("ora_db_shutdown"); - DBD::Oracle::st->install_method("ora_fetch_scroll"); - DBD::Oracle::st->install_method("ora_scroll_position"); - DBD::Oracle::st->install_method("ora_ping"); - DBD::Oracle::st->install_method("ora_stmt_type_name"); - DBD::Oracle::st->install_method("ora_stmt_type"); - $drh; - + return $drh if $drh; + + my($class, $attr) = @_; + my $oci = DBD::Oracle::ORA_OCI(); + + $class .= "::dr"; + + # not a 'my' since we use it above to prevent multiple drivers + + $drh = DBI::_new_drh($class, { + 'Name' => 'Oracle', + 'Version' => $VERSION, + 'Err' => \my $err, + 'Errstr' => \my $errstr, + 'Attribution' => "DBD::Oracle $VERSION using OCI$oci by Tim Bunce", + }); + + DBD::Oracle::dr::init_oci($drh) ; + $drh->STORE('ShowErrorStatement', 1); + + DBD::Oracle::db->install_method($_) for qw/ + ora_lob_read + ora_lob_write + ora_lob_append + ora_lob_trim + ora_lob_length + ora_lob_chunk_size + ora_lob_is_init + ora_nls_parameters + ora_can_unicode + ora_can_taf + ora_db_startup + ora_db_shutdown + /; + + DBD::Oracle::st->install_method($_) for qw/ + ora_fetch_scroll + ora_scroll_position + ora_ping + ora_stmt_type_name + ora_stmt_type + /; + + $drh; } @@ -1095,24 +1103,21 @@ BEGIN { return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_count errors") if $err_count; - if (!wantarray) { - return $tuple_count; - } - - return ($tuple_count, defined $row_count ? $row_count : undef); - - + return wantarray + ? ($tuple_count, defined $row_count ? $row_count : undef) + : $tuple_count; } sub private_attribute_info { - return {ora_lengths => undef, - ora_types => undef, - ora_rowid => undef, - ora_est_row_width => undef, - ora_type => undef, - ora_fail_over => undef, - }; + return { map { $_ => undef } qw/ + ora_lengths + ora_types + ora_rowid + ora_est_row_width + ora_type + ora_fail_over + / }; } } diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 29ba9b1c..d57d0592 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -96,27 +96,59 @@ sub sql_user_name { our %info = ( - 20 => 'Y', # SQL_ACCESSIBLE_PROCEDURES + 0 => 0, # SQL_MAX_DRIVER_CONNECTIONS + 1 => 0, # SQL_MAX_CONCURRENT_ACTIVITIES + 2 => \&sql_data_source_name, # SQL_DATA_SOURCE_NAME + 3 => 147209344, # SQL_DRIVER_HDBC + 4 => 147212776, # SQL_DRIVER_HENV +# 5 => undef, # SQL_DRIVER_HSTMT + 6 => $INC{'DBD/Oracle.pm'}, # SQL_DRIVER_NAME + 7 => $sql_driver_ver, # SQL_DRIVER_VER + 8 => 191, # SQL_FETCH_DIRECTION + 9 => 1, # SQL_ODBC_API_CONFORMANCE + 10 => '03.52', # SQL_ODBC_VER + 11 => 'Y', # SQL_ROW_UPDATES + 12 => 0, # SQL_ODBC_SAG_CLI_CONFORMANCE + 13 => sub {"$_[0]->{Name}"}, # SQL_SERVER_NAME + 14 => '\\', # SQL_SEARCH_PATTERN_ESCAPE + 15 => 1, # SQL_ODBC_SQL_CONFORMANCE + 16 => 'DEVEL', # SQL_DATABASE_NAME + 17 => 'Oracle', # SQL_DBMS_NAME + 18 => \&sql_dbms_version, # SQL_DBMS_VERSION 19 => 'Y', # SQL_ACCESSIBLE_TABLES - 0 => 0, # SQL_ACTIVE_CONNECTIONS - 116 => 0, # SQL_ACTIVE_ENVIRONMENTS - 1 => 0, # SQL_ACTIVE_STATEMENTS - 169 => 64, # SQL_AGGREGATE_FUNCTIONS - 117 => 0, # SQL_ALTER_DOMAIN - 86 => 1029739, # SQL_ALTER_TABLE - 10021 => 2, # SQL_ASYNC_MODE - 120 => 0, # SQL_BATCH_ROW_COUNT - 121 => 0, # SQL_BATCH_SUPPORT - 82 => 88, # SQL_BOOKMARK_PERSISTENCE - 114 => 2, # SQL_CATALOG_LOCATION - 10003 => 'N', # SQL_CATALOG_NAME - 41 => '@', # SQL_CATALOG_NAME_SEPARATOR - 42 => 'Database Link', # SQL_CATALOG_TERM - 92 => 3, # SQL_CATALOG_USAGE - 10004 => '', # SQL_COLLATING_SEQUENCE - 10004 => '', # SQL_COLLATION_SEQ - 87 => 'Y', # SQL_COLUMN_ALIAS + 20 => 'Y', # SQL_ACCESSIBLE_PROCEDURES + 21 => 'Y', # SQL_PROCEDURES 22 => 1, # SQL_CONCAT_NULL_BEHAVIOR + 23 => 2, # SQL_CURSOR_COMMIT_BEHAVIOR + 24 => 2, # SQL_CURSOR_ROLLBACK_BEHAVIOR + 25 => 'N', # SQL_DATA_SOURCE_READ_ONLY + 26 => 8, # SQL_DEFAULT_TRANSACTION_ISOLATION + 27 => 'Y', # SQL_EXPRESSIONS_IN_ORDERBY + 28 => 1, # SQL_IDENTIFIER_CASE + 29 => '"', # SQL_IDENTIFIER_QUOTE_CHAR + 30 => 30, # SQL_MAXIMUM_COLUMN_NAME_LENGTH + 31 => 30, # SQL_MAXIMUM_CURSOR_NAME_LENGTH + 32 => 30, # SQL_MAXIMUM_SCHEMA_NAME_LENGTH + 33 => 92, # SQL_MAX_PROCEDURE_NAME_LEN + 34 => 0, # SQL_MAXIMUM_CATALOG_NAME_LENGTH + 35 => 30, # SQL_MAXIMUM_TABLE_NAME_LENGTH + 36 => 'Y', # SQL_MULT_RESULT_SETS + 37 => 'Y', # SQL_MULTIPLE_ACTIVE_TXN + 38 => 'Y', # SQL_OUTER_JOINS + 39 => 'Owner', # SQL_SCHEMA_TERM + 40 => 'Procedure', # SQL_PROCEDURE_TERM + 41 => '@', # SQL_QUALIFIER_NAME_SEPARATOR + 42 => 'Database Link', # SQL_QUALIFIER_TERM + 43 => 7, # SQL_SCROLL_CONCURRENCY + 44 => 19, # SQL_SCROLL_OPTIONS + 45 => 'Table', # SQL_TABLE_TERM + 46 => 3, # SQL_TRANSACTION_CAPABLE + 47 => \&sql_user_name, # SQL_USER_NAME + 48 => 1, # SQL_CONVERT_FUNCTIONS + 49 => 16646015, # SQL_NUMERIC_FUNCTIONS + 50 => 8355839, # SQL_STRING_FUNCTIONS + 51 => 7, # SQL_SYSTEM_FUNCTIONS + 52 => 1023999, # SQL_TIMEDATE_FUNCTIONS 53 => 10518015, # SQL_CONVERT_BIGINT 54 => 10775839, # SQL_CONVERT_BINARY 55 => 10518015, # SQL_CONVERT_BIT @@ -125,12 +157,7 @@ our %info = ( 58 => 10518015, # SQL_CONVERT_DECIMAL 59 => 10514943, # SQL_CONVERT_DOUBLE 60 => 10514943, # SQL_CONVERT_FLOAT - 48 => 1, # SQL_CONVERT_FUNCTIONS - 173 => 0, # SQL_CONVERT_GUID 61 => 10518015, # SQL_CONVERT_INTEGER - 123 => 0, # SQL_CONVERT_INTERVAL_DAY_TIME - 124 => 0, # SQL_CONVERT_INTERVAL_YEAR_MONTH - 71 => 265216, # SQL_CONVERT_LONGVARBINARY 62 => 14680833, # SQL_CONVERT_LONGVARCHAR 63 => 10518015, # SQL_CONVERT_NUMERIC 64 => 10514943, # SQL_CONVERT_REAL @@ -140,10 +167,62 @@ our %info = ( 68 => 10518015, # SQL_CONVERT_TINYINT 69 => 10775839, # SQL_CONVERT_VARBINARY 70 => 15204351, # SQL_CONVERT_VARCHAR + 71 => 265216, # SQL_CONVERT_LONGVARBINARY + 72 => 10, # SQL_TRANSACTION_ISOLATION_OPTION + 73 => 'N', # SQL_ODBC_SQL_OPT_IEF + 74 => 2, # SQL_CORRELATION_NAME + 75 => 1, # SQL_NON_NULLABLE_COLUMNS +# 76 => undef, # SQL_DRIVER_HLIB + 77 => '03.52', # SQL_DRIVER_ODBC_VER + 78 => 1, # SQL_LOCK_TYPES + 79 => 1, # SQL_POS_OPERATIONS + 80 => 7, # SQL_POSITIONED_STATEMENTS + 81 => 15, # SQL_GETDATA_EXTENSIONS + 82 => 88, # SQL_BOOKMARK_PERSISTENCE + 83 => 0, # SQL_STATIC_SENSITIVITY + 84 => 0, # SQL_FILE_USAGE + 85 => 1, # SQL_NULL_COLLATION + 86 => 1029739, # SQL_ALTER_TABLE + 87 => 'Y', # SQL_COLUMN_ALIAS + 88 => 2, # SQL_GROUP_BY + 89 => \&sql_keywords, # SQL_KEYWORDS + 90 => 'N', # SQL_ORDER_BY_COLUMNS_IN_SELECT + 91 => 31, # SQL_SCHEMA_USAGE + 92 => 3, # SQL_QUALIFIER_USAGE + 93 => 3, # SQL_QUOTED_IDENTIFIER_CASE + 94 => '$#', # SQL_SPECIAL_CHARACTERS + 95 => 31, # SQL_SUBQUERIES + 96 => 3, # SQL_UNION_STATEMENT + 97 => 0, # SQL_MAXIMUM_COLUMNS_IN_GROUP_BY + 98 => 0, # SQL_MAXIMUM_COLUMNS_IN_INDEX + 99 => 0, # SQL_MAXIMUM_COLUMNS_IN_ORDER_BY + 100 => 1000, # SQL_MAXIMUM_COLUMNS_IN_SELECT + 101 => 1000, # SQL_MAXIMUM_COLUMNS_IN_TABLE + 102 => 0, # SQL_MAXIMUM_INDEX_SIZE + 103 => 'N', # SQL_MAX_ROW_SIZE_INCLUDES_LONG + 104 => 0, # SQL_MAXIMUM_ROW_SIZE + 105 => 0, # SQL_MAXIMUM_STATEMENT_LENGTH + 106 => 0, # SQL_MAXIMUM_TABLES_IN_SELECT + 107 => 30, # SQL_MAXIMUM_USER_NAME_LENGTH + 108 => 0, # SQL_MAX_CHAR_LITERAL_LEN + 109 => 0, # SQL_TIMEDATE_ADD_INTERVALS + 110 => 0, # SQL_TIMEDATE_DIFF_INTERVALS + 111 => 'N', # SQL_NEED_LONG_DATA_LEN + 112 => 0, # SQL_MAX_BINARY_LITERAL_LEN + 113 => 'Y', # SQL_LIKE_ESCAPE_CLAUSE + 114 => 2, # SQL_QUALIFIER_LOCATION + 115 => 127, # SQL_OUTER_JOIN_CAPABILITIES + 116 => 0, # SQL_ACTIVE_ENVIRONMENTS + 117 => 0, # SQL_ALTER_DOMAIN + 118 => 1, # SQL_SQL_CONFORMANCE + 119 => 0, # SQL_DATETIME_LITERALS + 120 => 0, # SQL_BATCH_ROW_COUNT + 121 => 0, # SQL_BATCH_SUPPORT 122 => 15106047, # SQL_CONVERT_WCHAR + 123 => 0, # SQL_CONVERT_INTERVAL_DAY_TIME + 124 => 0, # SQL_CONVERT_INTERVAL_YEAR_MONTH 125 => 14680833, # SQL_CONVERT_WLONGVARCHAR 126 => 15106047, # SQL_CONVERT_WVARCHAR - 74 => 2, # SQL_CORRELATION_NAME 127 => 0, # SQL_CREATE_ASSERTION 128 => 0, # SQL_CREATE_CHARACTER_SET 129 => 0, # SQL_CREATE_COLLATION @@ -152,29 +231,7 @@ our %info = ( 132 => 14305, # SQL_CREATE_TABLE 133 => 0, # SQL_CREATE_TRANSLATION 134 => 3, # SQL_CREATE_VIEW - 23 => 2, # SQL_CURSOR_COMMIT_BEHAVIOR - 24 => 2, # SQL_CURSOR_ROLLBACK_BEHAVIOR - 10001 => 1, # SQL_CURSOR_SENSITIVITY - 16 => 'DEVEL', # SQL_DATABASE_NAME - 2 => \&sql_data_source_name, # SQL_DATA_SOURCE_NAME - 25 => 'N', # SQL_DATA_SOURCE_READ_ONLY - 119 => 0, # SQL_DATETIME_LITERALS - 17 => 'Oracle', # SQL_DBMS_NAME - 18 => \&sql_dbms_version, # SQL_DBMS_VER - 18 => \&sql_dbms_version, # SQL_DBMS_VERSION - 170 => 3, # SQL_DDL_INDEX - 26 => 8, # SQL_DEFAULT_TRANSACTION_ISOLATION - 26 => 8, # SQL_DEFAULT_TXN_ISOLATION - 10002 => 'Y', # SQL_DESCRIBE_PARAMETER - 171 => '03.52.0002.0002', # SQL_DM_VER - 3 => 147209344, # SQL_DRIVER_HDBC # 135 => undef, # SQL_DRIVER_HDESC - 4 => 147212776, # SQL_DRIVER_HENV -# 76 => undef, # SQL_DRIVER_HLIB -# 5 => undef, # SQL_DRIVER_HSTMT - 6 => $INC{'DBD/Oracle.pm'}, # SQL_DRIVER_NAME - 77 => '03.52', # SQL_DRIVER_ODBC_VER - 7 => $sql_driver_ver, # SQL_DRIVER_VER 136 => 0, # SQL_DROP_ASSERTION 137 => 0, # SQL_DROP_CHARACTER_SET 138 => 0, # SQL_DROP_COLLATION @@ -185,107 +242,15 @@ our %info = ( 143 => 1, # SQL_DROP_VIEW 144 => 0, # SQL_DYNAMIC_CURSOR_ATTRIBUTES1 145 => 0, # SQL_DYNAMIC_CURSOR_ATTRIBUTES2 - 27 => 'Y', # SQL_EXPRESSIONS_IN_ORDERBY - 8 => 191, # SQL_FETCH_DIRECTION - 84 => 0, # SQL_FILE_USAGE 146 => 57345, # SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1 147 => 2183, # SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2 - 81 => 15, # SQL_GETDATA_EXTENSIONS - 88 => 2, # SQL_GROUP_BY - 28 => 1, # SQL_IDENTIFIER_CASE - 29 => '"', # SQL_IDENTIFIER_QUOTE_CHAR 148 => 3, # SQL_INDEX_KEYWORDS 149 => 65568, # SQL_INFO_SCHEMA_VIEWS - 172 => 7, # SQL_INSERT_STATEMENT - 73 => 'N', # SQL_INTEGRITY 150 => 0, # SQL_KEYSET_CURSOR_ATTRIBUTES1 151 => 0, # SQL_KEYSET_CURSOR_ATTRIBUTES2 - 89 => \&sql_keywords, # SQL_KEYWORDS - 113 => 'Y', # SQL_LIKE_ESCAPE_CLAUSE - 78 => 1, # SQL_LOCK_TYPES - 34 => 0, # SQL_MAXIMUM_CATALOG_NAME_LENGTH - 97 => 0, # SQL_MAXIMUM_COLUMNS_IN_GROUP_BY - 98 => 0, # SQL_MAXIMUM_COLUMNS_IN_INDEX - 99 => 0, # SQL_MAXIMUM_COLUMNS_IN_ORDER_BY - 100 => 1000, # SQL_MAXIMUM_COLUMNS_IN_SELECT - 101 => 1000, # SQL_MAXIMUM_COLUMNS_IN_TABLE - 30 => 30, # SQL_MAXIMUM_COLUMN_NAME_LENGTH - 1 => 0, # SQL_MAXIMUM_CONCURRENT_ACTIVITIES - 31 => 30, # SQL_MAXIMUM_CURSOR_NAME_LENGTH - 0 => 0, # SQL_MAXIMUM_DRIVER_CONNECTIONS - 10005 => 30, # SQL_MAXIMUM_IDENTIFIER_LENGTH - 102 => 0, # SQL_MAXIMUM_INDEX_SIZE - 104 => 0, # SQL_MAXIMUM_ROW_SIZE - 32 => 30, # SQL_MAXIMUM_SCHEMA_NAME_LENGTH - 105 => 0, # SQL_MAXIMUM_STATEMENT_LENGTH -# 20000 => undef, # SQL_MAXIMUM_STMT_OCTETS -# 20001 => undef, # SQL_MAXIMUM_STMT_OCTETS_DATA -# 20002 => undef, # SQL_MAXIMUM_STMT_OCTETS_SCHEMA - 106 => 0, # SQL_MAXIMUM_TABLES_IN_SELECT - 35 => 30, # SQL_MAXIMUM_TABLE_NAME_LENGTH - 107 => 30, # SQL_MAXIMUM_USER_NAME_LENGTH - 10022 => 0, # SQL_MAX_ASYNC_CONCURRENT_STATEMENTS - 112 => 0, # SQL_MAX_BINARY_LITERAL_LEN - 34 => 0, # SQL_MAX_CATALOG_NAME_LEN - 108 => 0, # SQL_MAX_CHAR_LITERAL_LEN - 97 => 0, # SQL_MAX_COLUMNS_IN_GROUP_BY - 98 => 0, # SQL_MAX_COLUMNS_IN_INDEX - 99 => 0, # SQL_MAX_COLUMNS_IN_ORDER_BY - 100 => 1000, # SQL_MAX_COLUMNS_IN_SELECT - 101 => 1000, # SQL_MAX_COLUMNS_IN_TABLE - 30 => 30, # SQL_MAX_COLUMN_NAME_LEN - 1 => 0, # SQL_MAX_CONCURRENT_ACTIVITIES - 31 => 30, # SQL_MAX_CURSOR_NAME_LEN - 0 => 0, # SQL_MAX_DRIVER_CONNECTIONS - 10005 => 30, # SQL_MAX_IDENTIFIER_LEN - 102 => 0, # SQL_MAX_INDEX_SIZE - 32 => 30, # SQL_MAX_OWNER_NAME_LEN - 33 => 92, # SQL_MAX_PROCEDURE_NAME_LEN - 34 => 0, # SQL_MAX_QUALIFIER_NAME_LEN - 104 => 0, # SQL_MAX_ROW_SIZE - 103 => 'N', # SQL_MAX_ROW_SIZE_INCLUDES_LONG - 32 => 30, # SQL_MAX_SCHEMA_NAME_LEN - 105 => 0, # SQL_MAX_STATEMENT_LEN - 106 => 0, # SQL_MAX_TABLES_IN_SELECT - 35 => 30, # SQL_MAX_TABLE_NAME_LEN - 107 => 30, # SQL_MAX_USER_NAME_LEN - 37 => 'Y', # SQL_MULTIPLE_ACTIVE_TXN - 36 => 'Y', # SQL_MULT_RESULT_SETS - 111 => 'N', # SQL_NEED_LONG_DATA_LEN - 75 => 1, # SQL_NON_NULLABLE_COLUMNS - 85 => 1, # SQL_NULL_COLLATION - 49 => 16646015, # SQL_NUMERIC_FUNCTIONS - 9 => 1, # SQL_ODBC_API_CONFORMANCE 152 => 3, # SQL_ODBC_INTERFACE_CONFORMANCE - 12 => 0, # SQL_ODBC_SAG_CLI_CONFORMANCE - 15 => 1, # SQL_ODBC_SQL_CONFORMANCE - 73 => 'N', # SQL_ODBC_SQL_OPT_IEF - 10 => '03.52', # SQL_ODBC_VER - 115 => 127, # SQL_OJ_CAPABILITIES - 90 => 'N', # SQL_ORDER_BY_COLUMNS_IN_SELECT - 38 => 'Y', # SQL_OUTER_JOINS - 115 => 127, # SQL_OUTER_JOIN_CAPABILITIES - 39 => 'Owner', # SQL_OWNER_TERM - 91 => 31, # SQL_OWNER_USAGE 153 => 2, # SQL_PARAM_ARRAY_ROW_COUNTS 154 => 3, # SQL_PARAM_ARRAY_SELECTS - 80 => 7, # SQL_POSITIONED_STATEMENTS - 79 => 1, # SQL_POS_OPERATIONS - 21 => 'Y', # SQL_PROCEDURES - 40 => 'Procedure', # SQL_PROCEDURE_TERM - 114 => 2, # SQL_QUALIFIER_LOCATION - 41 => '@', # SQL_QUALIFIER_NAME_SEPARATOR - 42 => 'Database Link', # SQL_QUALIFIER_TERM - 92 => 3, # SQL_QUALIFIER_USAGE - 93 => 3, # SQL_QUOTED_IDENTIFIER_CASE - 11 => 'Y', # SQL_ROW_UPDATES - 39 => 'Owner', # SQL_SCHEMA_TERM - 91 => 31, # SQL_SCHEMA_USAGE - 43 => 7, # SQL_SCROLL_CONCURRENCY - 44 => 19, # SQL_SCROLL_OPTIONS - 14 => '\\', # SQL_SEARCH_PATTERN_ESCAPE - 13 => sub {"$_[0]->{Name}"}, # SQL_SERVER_NAME - 94 => '$#', # SQL_SPECIAL_CHARACTERS 155 => 0, # SQL_SQL92_DATETIME_FUNCTIONS 156 => 0, # SQL_SQL92_FOREIGN_KEY_DELETE_RULE 157 => 0, # SQL_SQL92_FOREIGN_KEY_UPDATE_RULE @@ -297,26 +262,25 @@ our %info = ( 163 => 0, # SQL_SQL92_ROW_VALUE_CONSTRUCTOR 164 => 0, # SQL_SQL92_STRING_FUNCTIONS 165 => 1, # SQL_SQL92_VALUE_EXPRESSIONS - 118 => 1, # SQL_SQL_CONFORMANCE 166 => 3, # SQL_STANDARD_CLI_CONFORMANCE 167 => 57935, # SQL_STATIC_CURSOR_ATTRIBUTES1 168 => 4231, # SQL_STATIC_CURSOR_ATTRIBUTES2 - 83 => 0, # SQL_STATIC_SENSITIVITY - 50 => 8355839, # SQL_STRING_FUNCTIONS - 95 => 31, # SQL_SUBQUERIES - 51 => 7, # SQL_SYSTEM_FUNCTIONS - 45 => 'Table', # SQL_TABLE_TERM - 109 => 0, # SQL_TIMEDATE_ADD_INTERVALS - 110 => 0, # SQL_TIMEDATE_DIFF_INTERVALS - 52 => 1023999, # SQL_TIMEDATE_FUNCTIONS - 46 => 3, # SQL_TRANSACTION_CAPABLE - 72 => 10, # SQL_TRANSACTION_ISOLATION_OPTION - 46 => 3, # SQL_TXN_CAPABLE - 72 => 10, # SQL_TXN_ISOLATION_OPTION - 96 => 3, # SQL_UNION - 96 => 3, # SQL_UNION_STATEMENT - 47 => \&sql_user_name, # SQL_USER_NAME + 169 => 64, # SQL_AGGREGATE_FUNCTIONS + 170 => 3, # SQL_DDL_INDEX + 171 => '03.52.0002.0002', # SQL_DM_VER + 172 => 7, # SQL_INSERT_STATEMENT + 173 => 0, # SQL_CONVERT_GUID 10000 => 1995, # SQL_XOPEN_CLI_YEAR + 10001 => 1, # SQL_CURSOR_SENSITIVITY + 10002 => 'Y', # SQL_DESCRIBE_PARAMETER + 10003 => 'N', # SQL_CATALOG_NAME + 10004 => '', # SQL_COLLATING_SEQUENCE + 10005 => 30, # SQL_MAXIMUM_IDENTIFIER_LENGTH + 10021 => 2, # SQL_ASYNC_MODE + 10022 => 0, # SQL_MAX_ASYNC_CONCURRENT_STATEMENTS +# 20000 => undef, # SQL_MAXIMUM_STMT_OCTETS +# 20001 => undef, # SQL_MAXIMUM_STMT_OCTETS_DATA +# 20002 => undef, # SQL_MAXIMUM_STMT_OCTETS_SCHEMA ); 1; diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index ae318ad2..d50b1aee 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 2; +use Test::More tests => 3; use DBI; use Encode; @@ -57,18 +57,13 @@ $sth->execute; is Encode::is_utf8($val) => 1, "utf8 encoded"; -$dbh->disconnect; - - -__END__ - -undef $val; - $sth = $dbh->prepare(<<'END_SQL'); declare l_ret varchar2(10); begin - select ltrim(rtrim(to_char(0, 'L'))) + select ltrim(rtrim(to_char(0, 'L'))) + || ltrim(rtrim(to_char(0, 'L'))) + || ltrim(rtrim(to_char(0, 'L'))) into l_ret from dual; -- @@ -76,11 +71,13 @@ begin end; END_SQL -$sth->bind_param_inout( ':ret', \$val, 100 ); -$sth->execute; +$val = undef; -diag "val=[$val] len=@{[ length($val) ]}" while $sth->fetch; +# WARNING: does *not* truncate. DBD::Oracle doesn't heed the 3rd parameter +$sth->bind_param_inout(':ret', \$val, 1); +$sth->execute; -diag "utf8 is ", Encode::is_utf8($val) ? 'on' : 'off'; +is Encode::is_utf8($val) => 1, "truncated, yet utf8 encoded"; $dbh->disconnect; + From 9a2faeb5bc18c5e357efc25de5a45a3300ca18ce Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 24 Feb 2012 16:14:56 -0500 Subject: [PATCH 132/637] add diag for bequeather --- Changes | 1 + lib/DBD/Oracle/Troubleshooting.pm | 16 ++++++++++++++++ t/10general.t | 24 ++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index b2a2b58c..9728652e 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,7 @@ Revision history for DBD::Oracle on Lion. (Martin J. Evans) - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] - fix typos. (patch by Julián Moreno Patiño) [rt73999] + - add troubleshoot doc and diag for error with bequeather. [rt75263] [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 6e422308..37034663 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -61,6 +61,22 @@ Protocol Adapter". If it generates any errors which look relevant then please talk to your Oracle technical support (and not the dbi-users mailing list). +=head2 Connecting using a bequeather + +If you are using a bequeather to connect to a server +on the same host as the client, you might have +to add + + bequeath_detach = yes + +to your sqlnet.ora file or you won't be able to safely use fork/system +functions in Perl. + +See the discussion at +L +and L +for more gory details. + =head1 USING THE LONG TYPES diff --git a/t/10general.t b/t/10general.t index eefa5d88..1e492db0 100644 --- a/t/10general.t +++ b/t/10general.t @@ -38,8 +38,28 @@ SKIP: { # basic check that we can fork subprocesses and wait for the status # after having connected to Oracle - is system("exit 1;"), 1<<8, 'system exit 1 should return 256'; - is system("exit 0;"), 0, 'system exit 0 should return 0'; + # at some point, this should become a subtest + + my $success = is system("exit 1;"), 1<<8, 'system exit 1 should return 256'; + $success &&= is system("exit 0;"), 0, 'system exit 0 should return 0'; + + unless ( $success ) { + diag <prepare(q{ From 6c70f2595dacf747e397af14cd1c3a94744c77fa Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 24 Feb 2012 21:21:38 +0000 Subject: [PATCH 133/637] add doc about beqeather and signals git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15176 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 1 + lib/DBD/Oracle/Troubleshooting.pm | 16 ++++++++++++++++ t/10general.t | 24 ++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 8b7b9b70..cd0bb996 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,7 @@ NEXT on Lion. (Martin J. Evans) - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] - fix typos. (patch by Julián Moreno Patiño) [rt73999] + - add troubleshoot doc and diag for error with bequeather. [rt75263] [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 96f153ef..41896ae5 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -76,6 +76,22 @@ Protocol Adapter". If it generates any errors which look relevant then please talk to your Oracle technical support (and not the dbi-users mailing list). +=head2 Connecting using a bequeather + +If you are using a bequeather to connect to a server +on the same host as the client, you might have +to add + + bequeath_detach = yes + +to your sqlnet.ora file or you won't be able to safely use fork/system +functions in Perl. + +See the discussion at +L +and L +for more gory details. + =head1 USING THE LONG TYPES Some examples related to the use of LONG types are available in diff --git a/t/10general.t b/t/10general.t index eefa5d88..1e492db0 100644 --- a/t/10general.t +++ b/t/10general.t @@ -38,8 +38,28 @@ SKIP: { # basic check that we can fork subprocesses and wait for the status # after having connected to Oracle - is system("exit 1;"), 1<<8, 'system exit 1 should return 256'; - is system("exit 0;"), 0, 'system exit 0 should return 0'; + # at some point, this should become a subtest + + my $success = is system("exit 1;"), 1<<8, 'system exit 1 should return 256'; + $success &&= is system("exit 0;"), 0, 'system exit 0 should return 0'; + + unless ( $success ) { + diag <prepare(q{ From f17899de45ce0b5bcea2f9d5deb639c847ddac9c Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 24 Feb 2012 16:25:18 -0500 Subject: [PATCH 134/637] Build results of 255ebb9 (on master) --- .gitignore | 14 - Changes | 2 +- INSTALL | 44 + LICENSE | 377 ++ MANIFEST.SKIP | 32 - META.json | 97 + META.yml | 63 + README | 4338 ++++++++++++++- README.mkdn | 4228 +++++++++++++++ dist.ini | 22 - err_bind/err_bind_param_inout_overrun_bug.msg | 108 - err_bind/err_bindarrays.msg | 241 - err_bind/err_bindclobleak.msg | 58 - err_bind/err_bindnullhash.msg | 77 - err_bind/err_trailingblank.msg | 345 -- err_build/err_aix64.msg | 142 - err_build/err_hpux_ld.msg | 89 - err_build/err_hpuxsuccess.msg | 279 - err_build/err_instantclient.msg | 207 - err_build/err_makefileundef.msg | 87 - err_build/err_memleak.msg | 95 - err_build/err_solarisnotes.msg | 482 -- err_build/err_testfailnotable.msg | 97 - err_docs/err_trace.msg | 14 - err_lob/err_csr_clob.msg | 65 - err_lob/err_loblenwide.msg | 95 - err_lob/err_lobtesttblfail.msg | 208 - err_lob/err_nclob_form.msg | 189 - err_lob/err_nulllobsegv.msg | 93 - err_lob/err_tmplobfree.msg | 537 -- err_unicode/err_char.msg | 129 - err_unicode/err_twolongstr.msg | 1256 ----- err_unsorted/err_etherreal.msg | 90 - err_unsorted/err_memleak2.msg | 476 -- err_unsorted/err_multiora.msg | 470 -- err_unsorted/err_ora9ir2oci.msg | 27 - err_unsorted/err_ref_type.msg | 115 - err_unsorted/err_refcsr_rowcache.msg | 85 - err_unsorted/err_refcsr_slow.msg | 347 -- err_unsorted/err_slowcsr.msg | 316 -- err_unsorted/err_svrparse.msg | 4717 ----------------- err_unsorted/err_xml.msg | 118 - err_unsorted/err_xml2.msg | 700 --- err_unsorted/err_xmltypebindplsql.msg | 174 - lib/DBD/Oracle.pm | 109 +- lib/DBD/Oracle/GetInfo.pm | 46 + lib/DBD/Oracle/Object.pm | 95 +- lib/DBD/Oracle/Troubleshooting.pm | 48 +- t/000-report-versions.t | 446 ++ xt/changes.t | 8 - xt/manifest.t | 21 - xt/pod.t | 11 - 52 files changed, 9593 insertions(+), 12936 deletions(-) delete mode 100644 .gitignore create mode 100644 INSTALL create mode 100644 LICENSE delete mode 100644 MANIFEST.SKIP create mode 100644 META.json create mode 100644 META.yml create mode 100644 README.mkdn delete mode 100644 dist.ini delete mode 100644 err_bind/err_bind_param_inout_overrun_bug.msg delete mode 100644 err_bind/err_bindarrays.msg delete mode 100644 err_bind/err_bindclobleak.msg delete mode 100644 err_bind/err_bindnullhash.msg delete mode 100644 err_bind/err_trailingblank.msg delete mode 100644 err_build/err_aix64.msg delete mode 100644 err_build/err_hpux_ld.msg delete mode 100644 err_build/err_hpuxsuccess.msg delete mode 100644 err_build/err_instantclient.msg delete mode 100644 err_build/err_makefileundef.msg delete mode 100644 err_build/err_memleak.msg delete mode 100644 err_build/err_solarisnotes.msg delete mode 100644 err_build/err_testfailnotable.msg delete mode 100644 err_docs/err_trace.msg delete mode 100644 err_lob/err_csr_clob.msg delete mode 100644 err_lob/err_loblenwide.msg delete mode 100644 err_lob/err_lobtesttblfail.msg delete mode 100644 err_lob/err_nclob_form.msg delete mode 100644 err_lob/err_nulllobsegv.msg delete mode 100644 err_lob/err_tmplobfree.msg delete mode 100644 err_unicode/err_char.msg delete mode 100644 err_unicode/err_twolongstr.msg delete mode 100644 err_unsorted/err_etherreal.msg delete mode 100644 err_unsorted/err_memleak2.msg delete mode 100644 err_unsorted/err_multiora.msg delete mode 100644 err_unsorted/err_ora9ir2oci.msg delete mode 100644 err_unsorted/err_ref_type.msg delete mode 100644 err_unsorted/err_refcsr_rowcache.msg delete mode 100644 err_unsorted/err_refcsr_slow.msg delete mode 100644 err_unsorted/err_slowcsr.msg delete mode 100644 err_unsorted/err_svrparse.msg delete mode 100644 err_unsorted/err_xml.msg delete mode 100644 err_unsorted/err_xml2.msg delete mode 100644 err_unsorted/err_xmltypebindplsql.msg create mode 100644 t/000-report-versions.t delete mode 100644 xt/changes.t delete mode 100644 xt/manifest.t delete mode 100644 xt/pod.t diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 15e927c8..00000000 --- a/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -pm_to_blib -MYMETA.yml -Makefile -Makefile.old -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -blib -MYMETA.json -dbdimp.o -mk.pm -oci8.o -DBD-Oracle* diff --git a/Changes b/Changes index 9728652e..a6b20e80 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.39_00 2012-02-24 [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..b5ab17a0 --- /dev/null +++ b/INSTALL @@ -0,0 +1,44 @@ + +This is the Perl distribution DBD-Oracle. + +Installing DBD-Oracle is straightforward. + +## Installation with cpanm + +If you have cpanm, you only need one line: + + % cpanm DBD::Oracle + +If you are installing into a system-wide directory, you may need to pass the +"-S" flag to cpanm, which uses sudo to install the module: + + % cpanm -S DBD::Oracle + +## Installing with the CPAN shell + +Alternatively, if your CPAN shell is set up, you should just be able to do: + + % cpan DBD::Oracle + +## Manual installation + +As a last resort, you can manually install it. Download the tarball, untar it, +then build it: + + % perl Makefile.PL + % make && make test + +Then install it: + + % make install + +If you are installing into a system-wide directory, you may need to run: + + % sudo make install + +## Documentation + +DBD-Oracle documentation is available as POD. +You can run perldoc from a shell to read the documentation: + + % perldoc DBD::Oracle diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..a6a371c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,377 @@ +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +Terms of the Perl programming language system itself + +a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or +b) the "Artistic License" + +--- The GNU General Public License, Version 1, February 1989 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The GNU General Public License, Version 1, February 1989 + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! + + +--- The Artistic License 1.0 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The Artistic License 1.0 + +The Artistic License + +Preamble + +The intent of this document is to state the conditions under which a Package +may be copied, such that the Copyright Holder maintains some semblance of +artistic control over the development of the package, while giving the users of +the package the right to use and distribute the Package in a more-or-less +customary fashion, plus the right to make reasonable modifications. + +Definitions: + + - "Package" refers to the collection of files distributed by the Copyright + Holder, and derivatives of that collection of files created through + textual modification. + - "Standard Version" refers to such a Package if it has not been modified, + or has been modified in accordance with the wishes of the Copyright + Holder. + - "Copyright Holder" is whoever is named in the copyright or copyrights for + the package. + - "You" is you, if you're thinking about copying or distributing this Package. + - "Reasonable copying fee" is whatever you can justify on the basis of media + cost, duplication charges, time of people involved, and so on. (You will + not be required to justify it to the Copyright Holder, but only to the + computing community at large as a market that must bear the fee.) + - "Freely Available" means that no fee is charged for the item itself, though + there may be fees involved in handling the item. It also means that + recipients of the item may redistribute it under the same conditions they + received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications derived +from the Public Domain or from the Copyright Holder. A Package modified in such +a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided that +you insert a prominent notice in each changed file stating how and when you +changed that file, and provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major archive site + such as ftp.uu.net, or by allowing the Copyright Holder to include your + modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict with + standard executables, which must also be provided, and provide a separate + manual page for each non-standard executable that clearly documents how it + differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or executable +form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where to + get the Standard Version. + + b) accompany the distribution with the machine-readable source of the Package + with your modifications. + + c) accompany any non-standard executables with their corresponding Standard + Version executables, giving the non-standard executables non-standard + names, and clearly documenting the differences in manual pages (or + equivalent), together with instructions on where to get the Standard + Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. You +may not charge a fee for this Package itself. However, you may distribute this +Package in aggregate with other (possibly commercial) programs as part of a +larger (possibly commercial) software distribution provided that you do not +advertise this Package as a product of your own. + +6. The scripts and library files supplied as input to or produced as output +from the programs of this Package do not automatically fall under the copyright +of this Package, but belong to whomever generated them, and may be sold +commercially, and may be aggregated with this Package. + +7. C or perl subroutines supplied by you and linked into this Package shall not +be considered part of this Package. + +8. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +The End + diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP deleted file mode 100644 index c7db4c66..00000000 --- a/MANIFEST.SKIP +++ /dev/null @@ -1,32 +0,0 @@ -^DBD-Oracle-.* -\.svn\b -\.orig$ -\..*.swp$ -^.pure -^DIST/ -^MANIFEST\. -^Makefile$ -^blib/ -^csr/ -^err[/_] -^old/ -^info/ -^oci8/ -^oracle/ -^tags$ -~$ -^\.git -^xt -dbdimp.o -Makefile.old -mk.pm -MYMETA.json -MYMETA.yml -oci8.o -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -pm_to_blib - -dist.ini diff --git a/META.json b/META.json new file mode 100644 index 00000000..e16e6541 --- /dev/null +++ b/META.json @@ -0,0 +1,97 @@ +{ + "abstract" : "Oracle database driver for the DBI module", + "author" : [ + "Tim Bunce ", + "John Scoles", + "Yanick Champoux " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "DBD-Oracle", + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "6.30" + } + }, + "runtime" : { + "requires" : { + "DBI" : 0, + "DynaLoader" : 0, + "Exporter" : 0, + "perl" : "5.006", + "strict" : 0, + "warnings" : 0 + } + }, + "test" : { + "requires" : { + "Carp" : 0, + "Config" : 0, + "Data::Dumper" : 0, + "Devel::Peek" : 0, + "Encode" : 0, + "Math::BigInt" : 0, + "Oraperl" : 0, + "Scalar::Util" : 0, + "Test::More" : "0.94", + "Thread::Semaphore" : 0, + "utf8" : 0, + "vars" : 0 + } + } + }, + "provides" : { + "DBD::Oracle" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.39_00" + }, + "DBD::Oracle::GetInfo" : { + "file" : "lib/DBD/Oracle/GetInfo.pm", + "version" : "1.39_00" + }, + "DBD::Oracle::Object" : { + "file" : "lib/DBD/Oracle/Object.pm", + "version" : "1.39_00" + }, + "DBD::Oracle::Troubleshooting" : { + "file" : "lib/DBD/Oracle/Troubleshooting.pm", + "version" : "1.39_00" + }, + "DBD::Oracle::db" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.39_00" + }, + "DBD::Oracle::dr" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.39_00" + }, + "DBD::Oracle::st" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.39_00" + } + }, + "release_status" : "testing", + "resources" : { + "bugtracker" : { + "mailto" : "bug-dbd-oracle at rt.cpan.org", + "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle" + }, + "homepage" : "http://search.cpan.org/dist/DBD-Oracle/", + "repository" : { + "type" : "git", + "url" : "git://github.com/yanick/DBD-Oracle.git", + "web" : "http://github.com/yanick/DBD-Oracle/tree" + } + }, + "version" : "1.39_00", + "x_authority" : "cpan:PYTHIAN" +} + diff --git a/META.yml b/META.yml new file mode 100644 index 00000000..c4f5e2cb --- /dev/null +++ b/META.yml @@ -0,0 +1,63 @@ +--- +abstract: 'Oracle database driver for the DBI module' +author: + - 'Tim Bunce ' + - 'John Scoles' + - 'Yanick Champoux ' +build_requires: + Carp: 0 + Config: 0 + Data::Dumper: 0 + Devel::Peek: 0 + Encode: 0 + Math::BigInt: 0 + Oraperl: 0 + Scalar::Util: 0 + Test::More: 0.94 + Thread::Semaphore: 0 + utf8: 0 + vars: 0 +configure_requires: + ExtUtils::MakeMaker: 6.30 +dynamic_config: 0 +generated_by: 'Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: DBD-Oracle +provides: + DBD::Oracle: + file: lib/DBD/Oracle.pm + version: 1.39_00 + DBD::Oracle::GetInfo: + file: lib/DBD/Oracle/GetInfo.pm + version: 1.39_00 + DBD::Oracle::Object: + file: lib/DBD/Oracle/Object.pm + version: 1.39_00 + DBD::Oracle::Troubleshooting: + file: lib/DBD/Oracle/Troubleshooting.pm + version: 1.39_00 + DBD::Oracle::db: + file: lib/DBD/Oracle.pm + version: 1.39_00 + DBD::Oracle::dr: + file: lib/DBD/Oracle.pm + version: 1.39_00 + DBD::Oracle::st: + file: lib/DBD/Oracle.pm + version: 1.39_00 +requires: + DBI: 0 + DynaLoader: 0 + Exporter: 0 + perl: 5.006 + strict: 0 + warnings: 0 +resources: + bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle + homepage: http://search.cpan.org/dist/DBD-Oracle/ + repository: git://github.com/yanick/DBD-Oracle.git +version: 1.39_00 +x_authority: cpan:PYTHIAN diff --git a/README b/README index fd2b28aa..02004bd9 100644 --- a/README +++ b/README @@ -1,301 +1,4183 @@ +NAME + DBD::Oracle - Oracle database driver for the DBI module -DBD::Oracle -- an Oracle interface for Perl 5. +VERSION + version 1.39_00 - Copyright (c) 1994-2006 Tim Bunce, Ireland. +SYNOPSIS + use DBI; - See the COPYRIGHT section in the Oracle.pm file for terms. - See also the MAINTAINER section in the Oracle.pm + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); - PLEASE READ THE ENTIRE README FILE CAREFULLY ! + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); - AND THEN READ ANY README.* FILES RELEVANT TO YOUR PLATFORM: + # See the DBI module documentation for full details - README.aix.txt - AIX - README.hpux.txt - HP-UX - README.java.txt - Java/thread problem on Solaris - README.macosx.txt - Mac OS/X - README.win32.txt - MS Windows - README.wingcc.txt - MS Windows using GCC - README.* - see if there's a file for your platform + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); - You may find these useful +DESCRIPTION + DBD::Oracle is a Perl module which works with the DBI module to provide + access to Oracle databases. - README.help.txt - Help and hints on build problems - README.sec.txt - Oracle security issues to be aware of - README.login.txt - Help on how to connect to Oracle - README.longs.txt - Help on handling LONGs - README.clients.txt - What Oracle client files you need installed + This documentation describes driver specific behaviour and restrictions. + It is not supposed to be used as the only reference for the user. In any + case consult the DBI documentation first! +CONSTANTS + :ora_session_modes + ORA_SYSDBA ORA_SYSOPER ORA_SYSASM -*** QUICK START GUIDE: + :ora_types + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN - The DBI requires one or more 'driver' modules to talk to databases. - Fetch, build and install the DBI module as per its README file. - You may then delete its source directory tree since it's no longer needed. - Use the 'perldoc DBI' command to read the DBI documentation. + SQLCS_IMPLICIT + SQLCS_NCHAR + SQLCS_IMPLICIT and SQLCS_NCHAR are *character set form* values. See + notes about Unicode elsewhere in this document. - Fetch this DBD::Oracle driver module and unpack it. - Follow the guidelines in this README file carefully. + SQLT_INT + SQLT_FLT + These types are used only internally, and may be specified as + internal bind type for ORA_NUMBER_TABLE. See notes about + ORA_NUMBER_TABLE elsewhere in this document + ORA_OCI + Oracle doesn't provide a formal API for determining the exact + version number of the OCI client library used, so DBD::Oracle has to + go digging (and sometimes has to more or less guess). The ORA_OCI + constant holds the result of that process. -*** *BEFORE* BUILDING, TESTING AND INSTALLING DBD::Oracle: + In string context ORA_OCI returns the full "A.B.C.D" version string. - Build, test and install Perl 5 (at least 5.6.1) - It is very important to TEST it and INSTALL it! + In numeric context ORA_OCI returns the major.minor version number + (8.1, 9.2, 10.0 etc). But note that version numbers are not actually + floating point and so if Oracle ever makes a release that has a two + digit minor version, such as 9.10 it will have a lower numeric value + than the preceding 9.9 release. So use with care. - Build, test and install the DBI module (at least DBI 1.51). - It is very important to TEST it and INSTALL it! + The contents and format of ORA_OCI are subject to change (it may, + for example, become a *version object* in later releases). I + recommend that you avoid checking for exact values. - Remember to *read* the DBI README file and this one CAREFULLY! + :ora_fetch_orient + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE - Install enough Oracle software to enable DBD::Oracle to build. + These constants are used to set the orientation of a fetch on a + scrollable cursor. - For Oracle Instant Client: that means install the following packages: - * The "Basic" package for the essential Oracle libraries. - * The "SDK" package for the headers and makefile. - * The "SQL*Plus" component is optional, but will help you check - your configuration and DBD::Oracle determine your Oracle version. + :ora_exe_modes + OCI_STMT_SCROLLABLE_READONLY - For full Oracle installs: that usually includes Pro*C and SQL*Net. - (That's not very specific because it varies between Oracle releases.). - As of release 1.22 support of Oracle clients before 9 was dropped. - The main reason for this is that next few versions of DBD::Oracle will introduce a number of new features - whicht will required a great deal of extra coding to make the OCI 8 work. - As well it is getting harder to find an Oracle client 8 to test against as well - Oracle no longer supports clients before 9. + :ora_fail_over + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL - The ORACLE_HOME environment variable must point to the Oracle Home - used to create DBD::Oracle. (Not essential under MS Windows). +DBI CLASS METHODS + connect + This method creates a database handle by connecting to a database, and + is the DBI equivalent of the "new" method. To open a connection to an + Oracle database you need to specify a database connection string (URL), + username and password. -*** MOST IMPORTANTLY: + The connection string is always of the form: "dbi:Oracle:" There are several ways to identify a database: - Make sure Oracle is working and you can use the Oracle sqlplus - command to talk to the database from the machine you - want to build DBD::Oracle on. This often involves setting - environment variables like PATH, LD_LIBRARY_PATH, TWO_TASK etc. - Consult Oracle documentation for more details. + 1 If the database is local, specifying the SID or service name will be + enough. - Only once you can connect to Oracle using sqlplus - should you try building and testing DBD::Oracle. + 2 If the database is defined in a TNSNAMES.ORA file, you can use the + service name given in the file -*** BUILDING: + 3 To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, + of the form: //host[:port][/service_name] -Execute: + If port name is not specified, 1521 is the default. If service name is + not specified, the hostname will be used as a service name. - perl Makefile.PL # use a perl that's in your PATH + The following examples show several ways a connection can be created: -Use the perl that is first on your PATH. Then execute: + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - make + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); -If you get an error like "make: not found" you need to find the -directory that has the make command installed in it (e.g. /usr/ccs/bin -on Solaris) and add that to your PATH environment variable. + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); -Don't worry about most warnings when make runs, specifically ones like -"end-of-loop code not reached", "... due to prototype", -"cast increases required alignment of target type", etc. + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); -If you have problems see the 'IF YOU HAVE PROBLEMS' section below. -If it builds without error you should then run 'make test'. For the -main tests to work they must be able to connect to an Oracle database. + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); -The tests default to using a DSN of "dbi:Oracle:" which means you'll be -connected to the default database based on your TWO_TASK or ORACLE_SID -environment variables. This default can be altered either by defining the -ORACLE_DSN environment variable or the DBI_DSN environment variable. -See the oracle_test_dsn() sub in t/nchar_test_lib.pl + OS authentication + To connect to a local database with a user which has been set up to + authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): -The supplied tests will connect to the database using the value of the -ORACLE_USERID environment variable to supply the username/password. -So you should set that to a valid user (e.g. 'scott/tiger') and ensure that -this user has sufficient privileges to create, insert into, select from and -drop a table, is also able to create, call and drop a procedure and is able to select from -systemtables like 'v$sessions'. Using 'system/manager' might work but is not -recommended! See also + $dbh = DBI->connect('dbi:Oracle:','/',''); -README.login.txt. + Note the lack of a connection name (use the ORACLE_SID environment + variable). If an explicit SID is used you will probably get an ORA-01004 + error. - make test + That only works for local databases. (Authentication to remote Oracle + databases using your Unix login name without a password is possible but + it is not secure and not recommended so not documented here. -If the all the formal tests pass then, finally, run: + Oracle Environment Variables + To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME + environment variable should be set correctly. In general, the value used + should match the version of Oracle that was used to build DBD::Oracle. + If using dynamic linking then ORACLE_HOME should match the version of + Oracle that will be used to load in the Oracle client libraries (via + LD_LIBRARY_PATH, ldconfig, or similar on Unix). - make install + Oracle can use two environment variables to specify default connections: + ORACLE_SID and TWO_TASK. + To use them, specify either a local SID or service name, or a service + name that is specified in the TNSNAMES.ORA file. -*** IF YOU HAVE PROBLEMS: + Note that if you have *both* local and remote databases, and you have + ORACLE_SID *and* TWO_TASK set, and you don't specify a fully qualified + connect string on the command line, TWO_TASK takes precedence over + ORACLE_SID (i.e. you get connected to remote system). -Make sure you are using a recent perl (5.6.1 or later) and make -sure it's on your PATH so you can say 'perl Makefile.PL' and not -'/path/to/perl Makefile.PL'. + It is highly recommended not to rely on environment variables and to + always explicitly specify the SID in the connection string. This can + prevent serious mistakes such as dropping a schema in the wrong + database, and generally makes debugging and troubleshooting easier. -If you get compiler errors refering to Perl's own header files -(.../CORE/*.h) then there is something wrong with your installation. -It is important to use a Perl that was built on the system you are using. -It's also important to use the same compiler that was used to build the -Perl you are using. + Also remember that depending on the operating system you are using the + differing "ORACLE" environment variables may be case sensitive, so if + you are not connecting as you should double check the case of both the + variable and its value. -If you have build/link or core dump problems try: - perl Makefile.PL -p -or - perl Makefile.PL -nob -If it helps then please let me know (and please include a copy -of the log from the failed default build, the log from the build that -worked, plus the output of the "perl -V" command). + Timezones + If the query is run through SQL*Net (mostly queries that are executed on + remote servers), Oracle will return the time zone based on the setting + of the UNIX environment variable "TZ" for the user who started the + listener. -Do not hand edit the generated Makefile unless you are completely sure -you understand the implications! Always try to make changes via the -Makefile.PL command line and/or editing the Makefile.PL. -You should not need to make any changes. If you do please let us -know so that I can try to make it automatic in a later release. + If the query is run locally, Oracle will return the time zone based on + the "TZ" environment variable setting of the user running the query. -If you just can't login or login takes a long time then read -README.login.txt + With local queries, you can change the time zone for a particular user + by simply changing the setting of "TZ". To check the current setting, + issue the UNIX "date" command. -If you have linking problems (errors related to libraries or functions) -then you could try forcing a 'static' build using: + Oracle DRCP + DBD::Oracle supports DRCP (Database Resident Connection Pool) so if you + have an 11.2 database and DRCP is enabled you can direct all of your + connections to it by adding ':POOLED' to the SID or setting a connection + attribute of ora_drcp, or set the SERVER=POOLED when using a TNSENTRY + style connection or even by setting an environment variable ORA_DRCP. + All of which are demonstrated below; - make realclean - perl Makefile.PL LINKTYPE=static - make - make perl (you'll need to use and install _this_ new perl binary) - make test - make -f Makefile.aperl inst_perl MAP_TARGET=perl (install new perl) - make install (install DBD::Oracle) + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') -But that's not recommended these days. + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') ->>> Also carefully read the README.help.txt file which is full of useful ->>> tips and workarounds for various problems of various systems. + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) -*** HOW TO REPORT PROBLEMS + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') -This software is supported via the dbi-users@perl.org mailing list. -(You don't need to subscribe to the list in order to post.) + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") -Please do NOT post problems to comp.lang.perl.*, perl5-porters@perl.org, -http://www.cpanforum.com/dist/DBD-Oracle, or google groups etc. + if the ORA_DRCP environment variable is set then just this -If you're *sure* the problem is a bug then you can post a bug report -to http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle -Problem reports that don't include sufficient detail (including the -information listed below and how to reproduce the problem) -are unlikely to get resolved. + $dbh = DBI->connect('dbi:Oracle:DB','username','password') -For more information and to keep informed about progress you can join the -mailing list. Send a message to dbi-users-help@perl.org for more information. + You can find a white paper on setting up DRCP and its advantages at + . -Please post details of any problems (or changes you needed to make) to -dbi-users@perl.org. - - -** IT IS IMPORTANT TO INCLUDE *ALL* THE FOLLOWING INFORMATION: + Please note that DRCP support in DBD::Oracle is relatively new so the + mechanics or its implementation are subject to change. -1. A complete log of all steps of the build, e.g.: + TAF (Transparent Application Failover) + Transparent Application Failover (TAF) is the feature in OCI that allows + for clients to automatically reconnect to an instance in the event of a + failure of the instance. The reconnect happens automatically from within + the OCI (Oracle Call Interface) library. DBD::Oracle now supports a + callback function that will fire when a TAF event takes place. The main + use of the callback is to give your program the opportunity to inform + the user that a failover is taking place. - (do a make realclean first) - perl Makefile.PL - make - make test + You will have to set up TAF on your instance before you can use this + callback. You can test your instance to see if you can use TAF callback + with - Make sure to include the 'stderr' output. The best way to do this is - to use the "script" command (man script). If that's not available - then "command > command.log 2>&1" (assuming you're not using csh). - The "2>&1" is required (after the stdout redirect) to redirect stderr - to the same place. + $dbh->ora_can_taf(); - If a test fails then also include the output of: + If you try to set up a callback without it being enabled DBD::Oracle + will croak. - perl -Mblib t/.t + It is outside the scope of this documents to go through all of the + possible TAF situations you might want to set up but here is a simple + example: -2. Full details of which version of Oracle client and server you're using - (if it wasn't automatically found and printed by "perl Makefile.PL") + The TNS entry for the instance has had the following added to the + CONNECT_DATA section -3. The output of perl -V (that's a capital V, not lowercase) + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) -4. If you get errors like "undefined symbol", "symbol not found", - "undefined reference", "Text relocation remains" or any similar - error then include the output of "perl Makefile.PL -s XXX" - where XXX is the name of one of the symbols. - Please don't send the entire output of this command, - just any obviously 'interesting' parts (if there are any). - See also the LINKTYPE=static notes above. + You will also have to create your own perl function that will be called + from the client. You can name it anything you want and it will always be + passed two parameters, the failover event value and the failover type. + You can also set a sleep value in case of failover error and the OCI + client will sleep for the specified seconds before it attempts another + event. -5. If you get a core dump, rebuild DBD::Oracle with debugging - enabled by executing: perl Makefile.PL -g (note the -g option) - then rerun the code to get a new core dump file, finally use a - debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. - NOTE: I may not be able to help you much without a stack trace! - It is worth fetching and building the GNU GDB debugger (>=4.15) if - you don't have a good debugger on your system. If desperate try: - make perl; ./perl script; echo '$c' | adb ./perl core - Also see the Devel::CoreStack module on CPAN. - -6. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun - make test after setting the environment variable PERL_DL_DEBUG to 2. - -7. If your installation succeeds, but your script does not behave - as you expect, the problem may be on your end. Before - sending to dbi-users, try writing a *small*, easy to use test case - to reproduce your problem. Also, use the DBI->trace method to - trace your database calls. + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants -It is important to check that you are using the latest version before -posting. If you're not then you're *very* likely to be told "upgrade to -the latest". You would do yourself a favour by upgrading beforehand. + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); -Try to help yourself first, then try to help others help you by following -these guidelines carefully. And remember, please don't mail developers -directly - use the dbi-users mailing list. + #create the perl TAF event function -Regards, -Tim. + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ -=============================================================================== -Examples and other info: + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); -README.help.txt -- READ IT FIRST IF YOU HAVE ANY PROBLEMS -README.win32.txt -- building DBD::Oracle under MS Windows -README.wingcc.txt -- building DBD::Oracle under MS Windows with gcc -README.macosx.txt -- building DBD::Oracle under MacOS X -README.clients.txt -- building/using DBD::Oracle on minimally configured systems -README.login.txt -- help for login problems -README.longs.txt -- examples dealing with LONG types (blobs) + } + return 0; + } -DBI 'home page': http://dbi.perl.org + The TAF types are as follows -Old archive site for Perl DB information: - ftp://ftp.demon.co.uk/pub/perl/db/ -Mailing list archive: /DBI/perldb-interest/ -Perl 4 Oraperl (v2.4) /perl4/oraperl/ - -Jeff Stander's stuff stands out for Oraperl: -Directories of interest might be - /pub/Oracle/sources - /pub/Oracle/sources/jstander - /pub/Oracle/sources/jstander/distrib - /pub/Oracle/sources/jstander/tsmlib - /pub/Oracle/sources/jstander/wdbex - /pub/Oracle/sources/web/scripts - /pub/Oracle/sources/dba - /pub/Oracle/sources/dba/imp2sql7 - /pub/Oracle/sources/Lonnroth - /pub/Oracle/sources/harrison - -http://www.bf.rmit.edu.au/~orafaq/perlish.html -ftp://ftp.bf.rmit.edu.au/pub/perl/db -ftp://ftp.bf.rmit.edu.au/pub/Oracle -ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources -ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip - -DBI and DBD::Oracle are very portable. If Perl and Oracle run on a platform -then the chances are that DBD::Oracle will as well. - -=============================================================================== - -See the large README.help.txt file for lots of hints and advice -about building and runtime issues. - -End. + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + + The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + + Connect Attributes + ora_ncs_buff_mtpl + You can customize the size of the buffer when selecting LOBs with the + built-in AUTO Lob. The default value is 4 which is probably excessive + for most situations but is needed for backward compatibility. If you not + converting between a NCS on the DB and the Client then you might want to + set this to 1 to reduce memory usage. + + This value can also be specified with the "ORA_DBD_NCS_BUFFER" + environment variable in which case it sets the value at the connect + stage. + + ora_drcp + For Oracle 11.2 or greater. + + Set to *1* to enable DRCP. Can also be set via the "ORA_DRCP" + environment variable. + + ora_drcp_class + If you are using DRCP, you can set a CONNECTION_CLASS for your pools as + well. As sessions from a DRCP cannot be shared by users, you can use + this setting to identify the same user across different applications. + OCI will ensure that sessions belonging to a 'class' are not shared + outside the class'. + + The values for ora_drcp_class cannot contain a '*' and must be less than + 1024 characters. + + This value can be also be specified with the "ORA_DRCP_CLASS" + environment variable. + + ora_drcp_min + This optional value specifies the minimum number of sessions that are + initially opened. New sessions are only opened after this value has been + reached. + + The default value is 4 and any value above 0 is valid. + + Generally, it should be set to the number of concurrent statements the + application is planning or expecting to run. + + This value can also be specified with the "ORA_DRCP_MIN" environment + variable. + + ora_drcp_max + This optional value specifies the maximum number of sessions that can be + open at one time. Once reached no more sessions can be opened until one + becomes free. The default value is 40 and any value above 1 is valid. + You should not set this value lower than ora_drcp_min as that will just + waste resources. + + This value can also be specified with the "ORA_DRCP_MAX" environment + variable. + + ora_drcp_incr + This optional value specifies the next increment for sessions to be + started if the current number of sessions are less than ora_drcp_max. + The default value is 2 and any value above 0 is valid as long as the + value of ora_drcp_min + ora_drcp_incr is not greater than ora_drcp_max. + + This value can also be specified with the "ORA_DRCP_INCR" environment + variable. + + ora_taf + If your Oracle instance has been configured to use TAF events you can + enable the TAF callback by setting this option to any *true* value. + + ora_taf_function + The name of the Perl subroutine that will be called from OCI when a TAF + event occurs. You must supply a perl function to use the callback and it + will always receive two parameters, the failover event value and the + failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + + ora_taf_sleep + The amount of time in seconds the OCI client will sleep between + attempting successive failover events when the event is OCI_FO_ERROR. + + ora_session_mode + The ora_session_mode attribute can be used to connect with SYSDBA, + SYSOPER and ORA_SYSASM authorization. The ORA_SYSDBA, ORA_SYSOPER and + ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + + This is one case where setting ORACLE_SID may be useful since connecting + as SYSDBA or SYSOPER via SQL*Net is frequently disabled for security + reasons. + + Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + + It has been reported that this only works if $dsn does not contain a SID + so that Oracle then uses the value of ORACLE_SID (not TWO_TASK) + environment variable to connect to a local instance. Also the username + and password should be empty, and the user executing the script needs to + be part of the dba group or osdba group. + + ora_oratab_orahome + Passing a true value for the ora_oratab_orahome attribute will make + DBD::Oracle change $ENV{ORACLE_HOME} to make the Oracle home directory + that specified in the "/etc/oratab" file *if* the database to connect to + is specified as a SID that exists in the oratab file, and DBD::Oracle + was built to use the Oracle 7 OCI API (not Oracle 8+). + + ora_module_name + After connecting to the database the value of this attribute is passed + to the SET_MODULE() function in the "DBMS_APPLICATION_INFO" PL/SQL + package. This can be used to identify the application to the DBA for + monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + + The maximum size is 48 bytes. + + ora_driver_name + For 11g and later you can now set the name of the driver layer using + OCI. Perl, Perl5, ApachePerl so on. Names starting with "ORA" are + reserved. You can enter up to 8 characters. If none is enter then this + will default to DBDOxxxx where xxxx is the current version number. This + value can be retrieved on the server side using V$SESSION_CONNECT_INFO + or GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + + ora_client_info + Allows you to add any value (up to 64 bytes) to your session and it can + be retrieved on the server side from the "V$SESSION"a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + + ora_client_identifier + Allows you to specify the user identifier in the session handle. + + Most useful for web applications as it can pass in the session user name + which might be different to the connection user name. Can be up to 64 + bytes long but do not to include the password for security reasons and + the first character of the identifier should not be ':'. This value can + be retrieved on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + + ora_action + Allows you to specify any string up to 32 bytes which may be retrieved + on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + + ora_dbh_share + Requires at least Perl 5.8.0 compiled with ithreads. + + Allows you to share database connections between threads. The first + connect will make the connection, all following calls to connect with + the same ora_dbh_share attribute will use the same database connection. + The value must be a reference to a already shared scalar which is + initialized to an empty string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + + ora_envhp + The first time a connection is made a new OCI 'environment' is created + by DBD::Oracle and stored in the driver handle. Subsequent connects + reuse (share) that same OCI environment by default. + + The ora_envhp attribute can be used to disable the reuse of the OCI + environment from a previous connect. If the value is 0 then a new OCI + environment is allocated and used for this connection. + + The OCI environment holds information about the client side context, + such as the local NLS environment. By altering %ENV and setting + ora_envhp to 0 you can create connections with different NLS settings. + This is most useful for testing. + + ora_charset, ora_ncharset + For oracle versions >= 9.2 you can specify the client charset and + ncharset with the ora_charset and ora_ncharset attributes. You still + need to pass "ora_envhp = 0" for all but the first connect. + + These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + + ora_verbose + Use this value to enable DBD::Oracle only tracing. Simply either set the + ora_verbose attribute on the connect() method to the trace level you + desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + + or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + + In both cases the DBD::Oracle trace level is set to 6, which is the + highest level tracing most of the calls to OCI. + + ora_oci_success_warn + Use this value to print otherwise silent OCI warnings that may happen + when an execute or fetch returns "Success With Info" or when you want to + tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + + ora_objects + Use this value to enable extended embedded oracle objects mode. In + extended: + + 1 Embedded objects are returned as instance + (including type-name etc.) instead of simple ARRAY. + + 2 Determine object type for each instance. All object attributes are + returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + + ora_ph_type + The default placeholder datatype for the database session. The "TYPE" or + "ora_type" attributes to "bind_param" in DBI and "bind_param_inout" in + DBI override the datatype for individual placeholders. The most frequent + reason for using this attribute is to permit trailing spaces in values + passed by placeholders. + + Constants for the values allowed for this attribute can be imported + using + + use DBD::Oracle qw(:ora_types); + + Only the following values are permitted for this attribute. + + ORA_VARCHAR2 + Oracle clients using OCI 8 will strip trailing spaces and allow + embedded \0 bytes. Oracle clients using OCI 9.2 do not strip + trailing spaces and allow embedded \0 bytes. This is the normal + default placeholder type. + + ORA_STRING + Do not strip trailing spaces and end the string at the first \0. + + ORA_CHAR + Do not strip trailing spaces and allow embedded \0. Force + 'blank-padded comparison semantics'. + + For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + + Will pad bloggs out to 8 characters and return the username. + + ora_parse_error_offset + If the previous error was from a failed "prepare" due to a syntax error, + this attribute gives the offset into the "Statement" attribute where the + error was found. + + ora_array_chunk_size + Due to OCI limitations, DBD::Oracle needs to buffer up rows of bind + values in its "execute_for_fetch" implementation. This attribute sets + the number of rows to buffer at a time (default value is 1000). + + The "execute_for_fetch" function will collect (at most) this many rows + in an array, send them off to the DB for execution, then go back to + collect the next chunk of rows and so on. This attribute can be used to + limit or extend the number of rows processed at a time. + + Note that this attribute also applies to "execute_array", since that + method is implemented using "execute_for_fetch". + + ora_connect_with_default_signals + Sometimes the Oracle client seems to change some of the signal handlers + of the process during the connect phase. For instance, some users have + observed Perl's default $SIG{INT} handler being ignored after connecting + to an Oracle database. If this causes problems in your application, set + this attribute to an array reference of signals you would like to be + localized during the connect process. Once the connect is complete, the + signal handlers should be returned to their previous state. + + For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + + NOTE disabling the signal handlers the OCI library sets up may affect + functionality in the OCI library. + + NOTE If you are using connect_cached then the above example will lead to + DBI thinking each connection is different as an anonymous array + reference is being used. To avoid this when using connect_cached you are + advised to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + + In more recent Perl versions you could possibly make use of new state + variables. + + connect_cached + Implemented by DBI, no driver-specific impact. Please note that + connect_cached as not been tested with DRCP. + + data_sources + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + + Returns a list of available databases. You will have to set either the + 'ORACLE_HOME' or 'TNS_ADMIN' environment value to retrieve this list. It + will read these values from TNSNAMES.ORA file entries. + +METHODS COMMON TO ALL HANDLES + For all of the methods below, $h can be either a database handle ($dbh) + or a statement handle ($sth). Note that *$dbh* and *$sth* can be + replaced with any variable name you choose: these are just the names + most often used. Another common variable used in this documentation is + $*rv*, which stands for "return value". + + err + $rv = $h->err; + + Returns the error code from the last method called. + + errstr + $str = $h->errstr; + + Returns the last error that was reported by Oracle. Starting with + "ORA-00000" code followed by the error message. + + state + $str = $h->state; + + Oracle hasn't supported SQLSTATE since the early versions OCI. It will + return empty when the command succeeds and 'S1000' (General Error) for + all other errors. + + While this method can be called as either "$sth->state" or + "$dbh->state", it is usually clearer to always use "$dbh->state". + + trace + Implemented by DBI, no driver-specific impact. + + trace_msg + Implemented by DBI, no driver-specific impact. + + parse_trace_flag and parse_trace_flags + Implemented by DBI, no driver-specific impact. + + func + DBD::Oracle uses the "func" method to support a variety of functions. + + Private database handle functions + Some of these functions are called through the method func() which is + described in the DBI documentation. Any function that begins with ora_ + can be called directly. + + plsql_errstr + This function returns a string which describes the errors from the most + recent PL/SQL function, procedure, package, or package body compile in a + format similar to the output of the SQL*Plus command 'show errors'. + + The function returns undef if the error string could not be retrieved + due to a database error. Look in $dbh->errstr for the cause of the + failure. + + If there are no compile errors, an empty string is returned. + + Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + + dbms_output_enable / dbms_output_put / dbms_output_get + These functions use the PL/SQL DBMS_OUTPUT package to store and retrieve + text using the DBMS_OUTPUT buffer. Text stored in this buffer by + dbms_output_put or any PL/SQL block can be retrieved by dbms_output_get + or any PL/SQL block connected to the same database session. + + Stored text is not available until after dbms_output_put or the PL/SQL + block that saved it completes its execution. This means you CAN NOT use + these functions to monitor long running PL/SQL procedures. + + Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + + Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + + dbms_output_enable ( [ buffer_size ] ) + This function calls DBMS_OUTPUT.ENABLE to enable calls to package + DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to these + procedures are ignored unless DBMS_OUTPUT.ENABLE is called first. + + The buffer_size is the maximum amount of text that can be saved in the + buffer and must be between 2000 and 1,000,000. If buffer_size is not + given, the default is 20,000 bytes. + + dbms_output_put ( [ @lines ] ) + This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + + If all lines were saved successfully the function returns 1. Depending + on the context, an empty list or undef is returned for failure. + + If any line causes buffer_size to be exceeded, a buffer overflow error + is raised and the function call fails. Some of the text might be in the + buffer. + + dbms_output_get + This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from + the buffer. + + In an array context, all complete lines are removed from the buffer and + returned as a list. If there are no complete lines, an empty list is + returned. + + In a scalar context, the first complete line is removed from the buffer + and returned. If there are no complete lines, undef is returned. + + Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or + DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, + DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + + reauthenticate ( $username, $password ) + Starts a new session against the current database using the credentials + supplied. + + private_attribute_info + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + + Returns a hash of all private attributes used by DBD::Oracle, for either + a database or a statement handle. Currently, all the hash values are + undef. + +ATTRIBUTES COMMON TO ALL HANDLES + InactiveDestroy (boolean) + Implemented by DBI, no driver-specific impact. + + RaiseError (boolean, inherited) + Forces errors to always raise an exception. Although it defaults to off, + it is recommended that this be turned on, as the alternative is to check + the return value of every method (prepare, execute, fetch, etc.) + manually, which is easy to forget to do. + + PrintError (boolean, inherited) + Forces database errors to also generate warnings, which can then be + filtered with methods such as locally redefining *$SIG{__WARN__}* or + using modules such as "CGI::Carp". This attribute is on by default. + + ShowErrorStatement (boolean, inherited) + Appends information about the current statement to error messages. If + placeholder information is available, adds that as well. Defaults to + true. + + Warn (boolean, inherited) + Enables warnings. This is on by default, and should only be turned off + in a local block for a short a time only when absolutely needed. + + Executed (boolean, read-only) + Indicates if a handle has been executed. For database handles, this + value is true after the "do" method has been called, or when one of the + child statement handles has issued an "execute". Issuing a "commit" or + "rollback" always resets the attribute to false for database handles. + For statement handles, any call to "execute" or its variants will flip + the value to true for the lifetime of the statement handle. + + TraceLevel (integer, inherited) + Sets the trace level, similar to the "trace" method. See the sections on + "trace" and "parse_trace_flag" for more details. + + Active (boolean, read-only) + Indicates if a handle is active or not. For database handles, this + indicates if the database has been disconnected or not. For statement + handles, it indicates if all the data has been fetched yet or not. Use + of this attribute is not encouraged. + + Kids (integer, read-only) + Returns the number of child processes created for each handle type. For + a driver handle, indicates the number of database handles created. For a + database handle, indicates the number of statement handles created. For + statement handles, it always returns zero, because statement handles do + not create kids. + + ActiveKids (integer, read-only) + Same as "Kids", but only returns those that are active. + + CachedKids (hash ref) + Returns a hashref of handles. If called on a database handle, returns + all statement handles created by use of the "prepare_cached" method. If + called on a driver handle, returns all database handles created by the + "connect_cached" method. + + ChildHandles (array ref) + Implemented by DBI, no driver-specific impact. + + PrintWarn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleError (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleSetErr (code ref, inherited) + Implemented by DBI, no driver-specific impact. + + ErrCount (unsigned integer) + Implemented by DBI, no driver-specific impact. + + FetchHashKeyName (string, inherited) + Implemented by DBI, no driver-specific impact. + + ChopBlanks (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Taint (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintIn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintOut (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Profile (inherited) + Implemented by DBI, no driver-specific impact. + + Type (scalar) + Returns "dr" for a driver handle, "db" for a database handle, and "st" + for a statement handle. Should be rarely needed. + + LongReadLen + Implemented by DBI, no driver-specific impact. + + LongTruncOk + Implemented by DBI, no driver-specific impact. + + CompatMode + Type: boolean, inherited + + The CompatMode attribute is used by emulation layers (such as Oraperl) + to enable compatible behaviour in the underlying driver (e.g., + DBD::Oracle) for this handle. Not normally set by application code. + + It also has the effect of disabling the 'quick FETCH' of attribute + values from the handles attribute cache. So all attribute values are + handled by the drivers own FETCH method. This makes them slightly slower + but is useful for special-purpose drivers like DBD::Multiplex. + +ORACLE-SPECIFIC DATABASE HANDLE METHODS + ora_can_unicode ( [ $refresh ] ) + Returns a number indicating whether either of the database character + sets is a Unicode encoding. Calls ora_nls_parameters() and passes the + optional $refresh parameter to it. + + 0 = Neither character set is a Unicode encoding. + + 1 = National character set is a Unicode encoding. + + 2 = Database character set is a Unicode encoding. + + 3 = Both character sets are Unicode encodings. + + ora_can_taf + Returns true if the current connection supports TAF events. False if + otherise. + + ora_nls_parameters ( [ $refresh ] ) + Returns a hash reference containing the current NLS parameters, as given + by the v$nls_parameters view. The values fetched are cached between + calls. To cause the latest values to be fetched, pass a true value to + the function. + +DATABASE HANDLE METHODS + selectall_arrayref + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the rows returned by + preparing and executing the SQL string. See the DBI documentation for + full details. + + selectall_hashref + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + + Returns a reference to a hash containing the rows returned by preparing + and executing the SQL string. See the DBI documentation for full + details. + + selectcol_arrayref + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the first column from each + rows returned by preparing and executing the SQL string. It is possible + to specify exactly which columns to return. See the DBI documentation + for full details. + + prepare + $sth = $dbh->prepare($statement, \%attr); + + Prepares a statement for later execution by the database engine and + returns a reference to a statement handle object. + + Prepare Attributes + These attributes may be used in the "\%attr" parameter of the "prepare" + in DBI database handle method. + + ora_placeholders + Set to false to disable processing of placeholders. Used mainly for + loading a PL/SQL package that has been *wrapped* with Oracle's + "wrap" utility. + + ora_auto_lob + If true (the default), fetching retrieves the contents of the CLOB + or BLOB column in most circumstances. If false, fetching retrieves + the Oracle "LOB Locator" of the CLOB or BLOB value. + + See "LOBs and LONGs" for more details. + + See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how + to use LOB Locators. + + ora_pers_lob + If true the "Simple Fetch for CLOBs and BLOBs" method for the "Data + Interface for Persistent LOBs" will be used for LOBs rather than the + default method "Data Interface for LOB Locators". + + ora_clbk_lob + If true the "Piecewise Fetch with Callback" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_lob + If true the "Piecewise Fetch with Polling" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_size + This is the max piece size for the "Piecewise Fetch with Callback" + and "Piecewise Fetch with Polling" methods, in chars for CLOBS, and + bytes for BLOBS. + + ora_check_sql + If 1 (default), force SELECT statements to be described in + prepare(). If 0, allow SELECT statements to defer describe until + execute(). + + See "Prepare Postponed Till Execute" for more information. + + ora_exe_mode + This will set the execute mode of the current statement. Presently + only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + + See "Scrollable Cursors" for more details. + + ora_prefetch_rows + Sets the number of rows to be prefetched. If it is not set, then the + default value is 1. See "Row Prefetching" for more details. + + ora_prefetch_memory + Sets the memory level for rows to be prefetched. The application + then fetches as many rows as will fit into that much memory. See + "Row Prefetching" for more details. + + ora_row_cache_off + By default DBD::Oracle will use a row cache when fetching to cut + down the number of round trips to the server. If you do not want to + use an array fetch set this value to any value other than 0; + + See "Row Prefetching" for more details. + + Placeholders + There are two types of placeholders that can be used in DBD::Oracle. The + first is the "question mark" type, in which each placeholder is + represented by a single question mark character. This is the method + recommended by the DBI specs and is the most portable. Each question + mark is internally replaced by a "dollar sign number" in the order in + which they appear in the query (important when using "bind_param"). + + The other placeholder type is "named parameters" in the format ":foo" + which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + + The different types of placeholders cannot be mixed within a statement, + but you may use different ones for each statement handle you have. This + is confusing at best, so stick to one style within your program. + + prepare_cached + $sth = $dbh->prepare_cached($statement, \%attr); + + Implemented by DBI, no driver-specific impact. This method is most + useful if the same query is used over and over as it will cut down round + trips to the server. + + do + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + + Prepare and execute a single statement. Returns the number of rows + affected if the query was successful, returns undef if an error + occurred, and returns -1 if the number of rows is unknown or not + available. Note that this method will return 0E0 instead of 0 for 'no + rows were affected', in order to always return a true value if no error + occurred. + + last_insert_id + Oracle does not implement auto_increment of serial type columns it uses + predefined sequences where the id numbers are either selected before + insert, at insert time with a trigger, or as part of the query. + + Below is an example of you to use the latter with the SQL returning + clause to get the ID number back on insert with the bind_param_inout + method. . + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + + commit + $rv = $dbh->commit; + + Issues a COMMIT to the server, indicating that the current transaction + is finished and that all changes made will be visible to other + processes. If AutoCommit is enabled, then a warning is given and no + COMMIT is issued. Returns true on success, false on error. + + rollback + $rv = $dbh->rollback; + + Issues a ROLLBACK to the server, which discards any changes made in the + current transaction. If AutoCommit is enabled, then a warning is given + and no ROLLBACK is issued. Returns true on success, and false on error. + + begin_work + This method turns on transactions until the next call to "commit" or + "rollback", if "AutoCommit" is currently enabled. If it is not enabled, + calling begin_work will issue an error. Note that the transaction will + not actually begin until the first statement after begin_work is called. + + disconnect + $rv = $dbh->disconnect; + + Disconnects from the Oracle database. Any uncommitted changes will be + rolled back upon disconnection. It's good policy to always explicitly + call commit or rollback at some point before disconnecting, rather than + relying on the default rollback behavior. + + If the script exits before disconnect is called (or, more precisely, if + the database handle is no longer referenced by anything), then the + database handle's DESTROY method will call the rollback() and + disconnect() methods automatically. It is best to explicitly disconnect + rather than rely on this behavior. + + ping + $rv = $dbh->ping; + + This "ping" method is used to check the validity of a database handle. + The value returned is either 0, indicating that the connection is no + longer valid, or 1, indicating the connection is valid. This function + does 1 round trip to the Oracle Server. + + get_info() + $value = $dbh->get_info($info_type); + + DBD::Oracle supports "get_info()", but (currently) only a few info + types. + + table_info() + DBD::Oracle supports attributes for "table_info()". + + In Oracle, the concept of *user* and *schema* is (currently) the same. + Because database objects are owned by an user, the owner names in the + data dictionary views correspond to schema names. Oracle does not + support catalogues so TABLE_CAT is ignored as selection criterion. + + Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + + TABLE_TYPE may contain a comma-separated list of table types. The + following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + + The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + + The special enumerations of catalogues, schemas and table types are + supported. However, TABLE_CAT is always NULL. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. "table_info()" performs a case-sensitive search. So, a + selection criterion should respect upper and lower case. Normally, an + identifier is case-insensitive. Oracle stores and returns it in upper + case. Sometimes, database objects are created with quoted identifiers + (for reserved words, mixed case, special characters, ...). Such an + identifier is case-sensitive (if not all upper case). Oracle stores and + returns it as given. "table_info()" has no special quote handling, + neither adds nor removes quotes. + + primary_key_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + If the primary key constraint was created without an identifier, PK_NAME + contains a system generated name with the form SYS_Cn. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + foreign_key_info() + This method (currently) supports the extended behaviour of SQL/CLI, i.e. + the result set contains foreign keys that refer to primary and alternate + keys. The field UNIQUE_OR_PRIMARY distinguishes these keys. + + Oracle does not support catalogues, so $pk_catalog and $fk_catalog are + ignored as selection criteria (in the new style interface). The + UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always NULL + (undef). See "table_info()" for more detailed information. + + If the primary or foreign key constraints were created without an + identifier, UK_NAME or FK_NAME contains a system generated name with the + form SYS_Cn. + + The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle + (currently) does not support other actions. + + The DELETE_RULE field may contain wrong values. This is a known Bug + (#1271663) in Oracle's data dictionary views. Currently (as of 8.1.7), + 'RESTRICT' and 'SET DEFAULT' are not supported, 'CASCADE' is mapped + correctly and all other actions (incl. 'SET NULL') appear as 'NO + ACTION'. + + The DEFERABILITY field is always NULL, because this columns is not + present in the ALL_CONSTRAINTS view of older Oracle releases. + + The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, + FK_TABLE_SCHEM, FK_TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + column_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + + Don't rely on the values of the BUFFER_LENGTH field! Especially the + length of FLOATs may be wrong. + + Datatype codes for non-standard types are subject to change. + + Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + It is possible with Oracle to make the names of the various DB objects + (table,column,index etc) case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + + So in the example the exact case "Bla_BLA" must be used to get it info + on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + + any case can be used to get info on the column. + + selectrow_array + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + + Returns an array of row information after preparing and executing the + provided SQL string. The rows are returned by calling "fetchrow_array". + The string can also be a statement handle generated by a previous + prepare. Note that only the first row of data is returned. If called in + a scalar context, only the first column of the first row is returned. + Because this is not portable, it is not recommended that you use this + method in that way. + + selectrow_arrayref + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an array, by internal use of the "fetchrow_arrayref" + method. + + selectrow_hashref + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an hash, by internal use of the "fetchrow_hashref" method. + + clone + $other_dbh = $dbh->clone(); + + Creates a copy of the database handle by connecting with the same + parameters as the original handle, then trying to merge the attributes. + See the DBI documentation for complete usage. + +DATABASE HANDLE ATTRIBUTES + AutoCommit (boolean) + Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is + on, but this may change in the future, so it is highly recommended that + you explicitly set it when calling "connect". + + ReadOnly (boolean) + $dbh->{ReadOnly} = 1; + + Specifies if the current database connection should be in read-only mode + or not. + + Please not that this method is not foolproof: there are still ways to + update the database. Consider this a safety net to catch applications + that should not be issuing commands such as INSERT, UPDATE, or DELETE. + + This method method requires DBI version 1.55 or better. + + Name (string, read-only) + Returns the name of the current database. This is the same as the DSN, + without the "dbi:Oracle:" part. + + Username (string, read-only) + Returns the name of the user connected to the database. + + Driver (handle, read-only) + Holds the handle of the parent driver. The only recommended use for this + is to find the name of the driver using: + + $dbh->{Driver}->{Name} + + RowCacheSize + DBD::Oracle supports both Server pre-fetch and Client side row caching. + By default both are turned on to give optimum performance. Most of the + time one can just let DBD::Oracle figure out the best optimization. + + Row Caching + Row caching occurs on the client side and the object of it is to cut + down the number of round trips made to the server when fetching rows. At + each fetch a set number of rows will be retrieved from the server and + stored locally. Further calls the server are made only when the end of + the local buffer(cache) is reached. + + Rows up to the specified top level row count "RowCacheSize" are fetched + if it occupies no more than the specified memory usage limit. The + default value is 0, which means that memory size is not included in + computing the number of rows to prefetch. If the "RowCacheSize" value is + set to a negative number then the positive value of RowCacheSize is used + to compute the number of rows to prefetch. + + By default "RowCacheSize" is automatically set. If you want to totally + turn off prefetching set this to 1. + + For any SQL statement that contains a LOB, Long or Object Type Row + Caching will be turned off. However server side caching still works. If + you are only selecting a LOB Locator then Row Caching will still work. + + Row Prefetching + Row prefetching occurs on the server side and uses the DBI database + handle attribute "RowCacheSize" and or the Prepare Attribute + 'ora_prefetch_memory'. Tweaking these values may yield improved + performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + + In the above example 10 rows will be prefetched up to a maximum of 10000 + bytes of data. The Oracle® Call Interface Programmer's Guide, suggests + a good row cache value for a scrollable cursor is about 20% of expected + size of the record set. + + The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) + when it needs to get new rows. This happens on the first fetch that sets + the current_positon to any value other than 0. In the above example if + we do a OCI_FETCH_FIRST the first 10 rows are loaded into the buffer and + DBD::Oracle will not have to go back to the server for more rows. When + record 11 is fetched DBD::Oracle fetches and returns this row and the + next 9 rows are loaded into the buffer. In this case if you fetch + backwards from 10 to 1 no server round trips are made. + + With large record sets it is best not to attempt to go to the last + record as this may take some time, A large buffer size might even slow + down the fetch. If you must get the number of rows in a large record set + you might try using an few large OCI_FETCH_ABSOLUTEs and then an + OCI_FETCH_LAST, this might save some time. So if you had a record set of + 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one + would fetch the first 5000 rows into the buffer then the next 5000 rows. + If one requires only the first few rows there is no need to set a large + prefetch value. + + If the ora_prefetch_memory less than 1 or not present then memory size + is not included in computing the number of rows to prefetch otherwise + the number of rows will be limited to memory size. Likewise if the + RowCacheSize is less than 1 it is not included in the computing of the + prefetch rows. + +ORACLE-SPECIFIC STATEMENT HANDLE METHODS + ora_stmt_type + Returns the OCI Statement Type number for the SQL of a statement handle. + + ora_stmt_type_name + Returns the OCI Statement Type name for the SQL of a statement handle. + +DBI STATEMENT HANDLE OBJECT METHODS + bind_param + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + + Allows the user to bind a value and/or a data type to a placeholder. + + The value of $param_num is a number if using the '?' or if using ":foo" + style placeholders, the complete name (e.g. ":foo") must be given. The + $bind_value argument is fairly self-explanatory. A value of "undef" will + bind a "NULL" to the placeholder. Using "undef" is useful when you want + to change just the type and will be overwriting the value later. (Any + value is actually usable, but "undef" is easy and efficient). + + The "\%attr" hash is used to indicate the data type of the placeholder. + The default value is "varchar". If you need something else, you must use + one of the values provided by DBI or by DBD::Pg. To use a SQL value, + modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + + This will import some constants into your script. You can plug those + directly into the "bind_param" call. Some common ones that you will + encounter are: + + SQL_INTEGER + + To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + + You can then set the data types by setting the value of the "ora_type" + key in the hash passed to "bind_param". The current list of Oracle data + types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + + Data types are "sticky," in that once a data type is set to a certain + placeholder, it will remain for that placeholder, unless it is + explicitly set to something else afterwards. If the statement has + already been prepared, and you switch the data type to something else, + DBD::Oracle will re-prepare the statement for you before doing the next + execute. + + Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + + These attributes may be used in the "\%attr" parameter of the + "bind_param" in DBI or "bind_param_inout" in DBI statement handle + methods. + + ora_type + Specify the placeholder's datatype using an Oracle datatype. A fatal + error is raised if "ora_type" and the DBI "TYPE" attribute are used + for the same placeholder. Some of these types are not supported by + the current version of DBD::Oracle and will cause a fatal error if + used. Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + + Potentially useful values when DBD::Oracle was built using OCI 7 and + later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + + Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + + Additional values when DBD::Oracle was built using OCI 9.2 and + later: + + SQLT_CHR, SQLT_BIN + + See "Binding Cursors" for the correct way to use ORA_RSET. + + See "LOBs and LONGs" for how to use ORA_CLOB and ORA_BLOB. + + See "SYS.DBMS_SQL datatypes" for ORA_VARCHAR2_TABLE, + ORA_NUMBER_TABLE. + + See "Data Interface for Persistent LOBs" for the correct way to use + SQLT_CHR and SQLT_BIN. + + See "Other Data Types" for more information. + + See also "Placeholders and Bind Values" in DBI. + + ora_csform + Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values + are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can + be imported from the DBD::Oracle module. Rarely needed. + + ora_csid + Specify the *integer* OCI_ATTR_CHARSET_ID for the bind value. + Character set names can't be used currently. + + ora_maxdata_size + Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. May be + needed if a character set conversion from client to server causes + the data to use more space and so fail with a truncation error. + + ora_maxarray_numentries + Specify the maximum number of array entries to allocate. Used with + ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of + array entries Oracle can pass back to you in OUT variable of type + TABLE OF ... . + + ora_internal_type + Specify internal data representation. Currently is supported only + for ORA_NUMBER_TABLE. + + Optimizing Results + Prepare Postponed Till Execute + The DBD::Oracle module can avoid an explicit 'describe' operation prior + to the execution of the statement unless the application requests + information about the results (such as $sth->{NAME}). This reduces + communication with the server and increases performance (reducing the + number of PARSE_CALLS inside the server). + + However, it also means that SQL errors are not detected until + "execute()" (or $sth->{NAME} etc) is called instead of when "prepare()" + is called. Note that if the describe is triggered by the use of + $sth->{NAME} or a similar attribute and the describe fails then *an + exception is thrown* even if "RaiseError" is false! + + Set "ora_check_sql" to 0 in prepare() to enable this behaviour. + + bind_param_inout + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + + DBD::Oracle fully supports bind_param_inout below are some uses for this + method. + + Returning A Value from an INSERT + Oracle supports an extended SQL insert syntax which will return one or + more of the values inserted. This can be particularly useful for + single-pass insertion of values with re-used sequence values (avoiding a + separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + + If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + + If you have many rows to insert you can take advantage of Oracle's built + in execute array feature with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + + Which will return all the ids into @out_values. + + Note: + This will only work for numbered (?) placeholders, + The third parameter of bind_param_inout_array, (0 in the example), + "maxlen" is required by DBI but not used by DBD::Oracle + The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + + Returning A Recordset + DBD::Oracle does not currently support binding a PL/SQL table (aka + array) as an IN OUT parameter to any Perl data structure. You cannot + therefore call a PL/SQL function or procedure from DBI that uses a + non-atomic datatype as either a parameter, or a return value. However, + if you are using Oracle 9.0.1 or later, you can make use of table (or + pipelined) functions. + + For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + + Currently, there is no way to directly call the function + Array_Example.Array_Func from DBI. However, by making the following + relatively painless additions, its not only possible, but extremely + efficient. + + First, you need to create database object types that correspond to the + record and table types in the package. From the above example, these + would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + + Now, assuming the existing function needs to remain unchanged (it is + probably being called from other PL/SQL code), we need to add a new + function to the package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + + As you can see, the new function is very simple. Now, it is a simple + matter of calling the function as a straight-forward SELECT from your + DBI code. From the above example, the code would look something like + this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + + SYS.DBMS_SQL datatypes + DBD::Oracle has built-in support for SYS.DBMS_SQL.VARCHAR2_TABLE and + SYS.DBMS_SQL.NUMBER_TABLE datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + Note: + Take careful note that we use '\\@arr' here because the + 'bind_param_inout' will only take a reference to a scalar. + + ORA_VARCHAR2_TABLE + SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. ( + in bind_param() and bind_param_inout() ). When you bind array, you need + to specify full buffer size for OUT data. So, there are two parameters: + *max_len* (specified as 3rd argument of bind_param_inout() ), and + *ora_maxarray_numentries*. They define maximum array entry length and + maximum rows, that can be passed to Oracle and back to you. In this + example we send array with 1 element with length=3, but allocate space + for 100 Oracle array entries with maximum length 10 of each. So, you can + get no more than 100 array entries with length <= 10. + + If you set *max_len* to zero, maximum array entry length is calculated + as maximum length of entry of array bound. If 0 < *max_len* < length( + $some_element ), truncation occur. + + If you set *ora_maxarray_numentries* to zero, current (at bind time) + bound array length is used as maximum. If 0 < *ora_maxarray_numentries* + < scalar(@array), not all array entries are bound. + + ORA_NUMBER_TABLE + SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike + ORA_VARCHAR2_TABLE. The main difference is internal data representation. + Currently 2 types of bind is allowed : as C-integer, or as C-double + type. To select one of them, you may specify additional bind parameter + *ora_internal_type* as either SQLT_INT or SQLT_FLT for C-integer and + C-double types. Integer size is architecture-specific and is usually 32 + or 64 bit. Double is standard IEEE 754 type. + + *ora_internal_type* defaults to double (SQLT_FLT). + + *max_len* is ignored for OCI_NUMBER_TABLE. + + Currently, you cannot bind full native Oracle NUMBER(38). If you really + need, send request to dbi-dev list. + + The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + + If you change bind type to SQLT_INT, like: + + ora_internal_type => SQLT_INT + + you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + + bind_param_inout_array + DBD::Oracle supports this undocumented feature of DBI. See "Returning A + Value from an INSERT" for an example. + + bind_param_array + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + + Binds an array of values to a placeholder, so that each is used in turn + by a call to the "execute_array" method. + + execute + $rv = $sth->execute(@bind_values); + + Perform whatever processing is necessary to execute the prepared + statement. + + execute_array + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + Execute a prepared statement once for each item in a passed-in hashref, + or items that were previously bound via the "bind_param_array" method. + See the DBI documentation for more details. + + DBD::Oracle takes full advantage of OCI's array interface so inserts and + updates using this interface will run very quickly. + + execute_for_fetch + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + Used internally by the "execute_array" method, and rarely used directly. + See the DBI documentation for more details. + + fetchrow_arrayref + $ary_ref = $sth->fetchrow_arrayref; + + Fetches the next row of data from the statement handle, and returns a + reference to an array holding the column values. Any columns that are + NULL are returned as undef within the array. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + Note that the same array reference is returned for each fetch, so don't + store the reference and then use it after a later fetch. Also, the + elements of the array are also reused for each row, so take care if you + want to take a reference to an element. See also "bind_columns". + + fetchrow_array + @ary = $sth->fetchrow_array; + + Similar to the "fetchrow_arrayref" method, but returns a list of column + information rather than a reference to a list. Do not use this in a + scalar context. + + fetchrow_hashref + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + + Fetches the next row of data and returns a hashref containing the name + of the columns as the keys and the data itself as the values. Any NULL + value is returned as as undef value. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + The optional $name argument should be either "NAME", "NAME_lc" or + "NAME_uc", and indicates what sort of transformation to make to the keys + in the hash. By default Oracle uses upper case. + + fetchall_arrayref + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + + Returns a reference to an array of arrays that contains all the + remaining rows to be fetched from the statement handle. If there are no + more rows, an empty arrayref will be returned. If an error occurs, the + data read in so far will be returned. Because of this, you should always + check "$sth->err" after calling this method, unless "RaiseError" has + been enabled. + + If $slice is an array reference, fetchall_arrayref uses the + "fetchrow_arrayref" method to fetch each row as an array ref. If the + $slice array is not empty then it is used as a slice to select + individual columns by perl array index number (starting at 0, unlike + column and parameter numbers which start at 1). + + With no parameters, or if $slice is undefined, fetchall_arrayref acts as + if passed an empty array ref. + + If $slice is a hash reference, fetchall_arrayref uses "fetchrow_hashref" + to fetch each row as a hash reference. + + See the DBI documentation for a complete discussion. + + fetchall_hashref + $hash_ref = $sth->fetchall_hashref( $key_field ); + + Returns a hashref containing all rows to be fetched from the statement + handle. See the DBI documentation for a full discussion. + + finish + $rv = $sth->finish; + + Indicates to DBI that you are finished with the statement handle and are + not going to use it again. Only needed when you have not fetched all the + possible rows. + + rows + $rv = $sth->rows; + + Returns the number of rows affected for updates, deletes and inserts and + -1 for selects. + + bind_col + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + + Binds a Perl variable and/or some attributes to an output column of a + SELECT statement. Column numbers count up from 1. You do not need to + bind output columns in order to fetch data. + + NOTE: DBD::Oracle does not use the $bind_type to determine how to bind + the column; it uses what Oracle says the data type is. You can however + set a numeric bind type with the bind attributes + StrictlyTyped/DiscardString as these attributes are applied after the + column is retrieved. + + See the DBI documentation for a discussion of the optional parameters + "\%attr" and $bind_type + + bind_columns + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + + Calls the "bind_col" method for each column in the SELECT statement, + using the supplied list. + + dump_results + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + + Fetches all the rows from the statement handle, calls "DBI::neat_list" + for each row, and prints the results to $fh (which defaults to STDOUT). + Rows are separated by $lsep (which defaults to a newline). Columns are + separated by $fsep (which defaults to a comma). The $maxlen controls how + wide the output can be, and defaults to 35. + + This method is designed as a handy utility for prototyping and testing + queries. Since it uses "neat_list" to format and edit the string for + reading by humans, it is not recommended for data transfer applications. + +STATEMENT HANDLE ATTRIBUTES + NUM_OF_FIELDS (integer, read-only) + Returns the number of columns returned by the current statement. A + number will only be returned for SELECT statements for INSERT, UPDATE, + and DELETE statements which contain a RETURNING clause. This method + returns undef if called before "execute()". + + NUM_OF_PARAMS (integer, read-only) + Returns the number of placeholders in the current statement. + + NAME (arrayref, read-only) + Returns an arrayref of column names for the current statement. This + method will only work for SELECT statements, for SHOW statements, and + for INSERT, UPDATE, and DELETE statements which contain a RETURNING + clause. This method returns undef if called before "execute()". + + NAME_lc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to lower case. + + NAME_uc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to upper case. + + NAME_hash (hashref, read-only) + Similar to the "NAME" attribute, but returns a hashref of column names + instead of an arrayref. The names of the columns are the keys of the + hash, and the values represent the order in which the columns are + returned, starting at 0. This method returns undef if called before + "execute()". + + NAME_lc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + NAME_uc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + TYPE (arrayref, read-only) + Returns an arrayref indicating the data type for each column in the + statement. This method returns undef if called before "execute()". + + PRECISION (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the precision for "NUMERIC" columns, the + size in number of characters for "CHAR" and "VARCHAR" columns, and for + all other types of columns it returns the number of *bytes*. This method + returns undef if called before "execute()". + + SCALE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the scale of the that column. The only + type that will return a value is "NUMERIC". This method returns undef if + called before "execute()". + + NULLABLE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates if the column is nullable or not. 0 = + not nullable, 1 = nullable, 2 = unknown. This method returns undef if + called before "execute()". + + Database (dbh, read-only) + Returns the database handle this statement handle was created from. + + ParamValues (hash ref, read-only) + Returns a reference to a hash containing the values currently bound to + placeholders. If the "named parameters" type of placeholders are being + used (such as ":foo"), then the keys of the hash will be the names of + the placeholders (without the colon). If the "dollar sign numbers" type + of placeholders are being used, the keys of the hash will be the + numbers, without the dollar signs. If the "question mark" type is used, + integer numbers will be returned, starting at one and increasing for + every placeholder. + + If this method is called before "execute", the literal values passed in + are returned. If called after "execute", then the quoted versions of the + values are returned. + + ParamTypes (hash ref, read-only) + Returns a reference to a hash containing the type names currently bound + to placeholders. The keys are the same as returned by the ParamValues + method. The values are hashrefs containing a single key value pair, in + which the key is either 'TYPE' if the type has a generic SQL equivalent, + and 'pg_type' if the type can only be expressed by a Postgres type. The + value is the internal number corresponding to the type originally passed + in. (Placeholders that have not yet been bound will return undef as the + value). This allows the output of ParamTypes to be passed back to the + "bind_param" method. + + Statement (string, read-only) + Returns the statement string passed to the most recent "prepare" method + called in this database handle, even if that method failed. This is + especially useful where "RaiseError" is enabled and the exception + handler checks $@ and sees that a "prepare" method call failed. + + RowsInCache + Returns the number of un-fetched rows in the cache for selects. + +SCROLLABLE CURSORS + Oracle supports the concept of a 'Scrollable Cursor' which is defined as + a 'Result Set' where the rows can be fetched either sequentially or + non-sequentially. One can fetch rows forward, backwards, from any given + position or the n-th row from the current position in the result set. + + Rows are numbered sequentially starting at one and client-side caching + of the partial or entire result set can improve performance by limiting + round trips to the server. + + Oracle does not support DML type operations with scrollable cursors so + you are limited to simple 'Select' operations only. As well you can not + use this functionality with remote mapped queries or if the LONG + datatype is part of the select list. + + However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, + and fetch methods. + + Only use scrollable cursors if you really have a good reason to. They do + use up considerable more server and client resources and have poorer + response times than non-scrolling cursors. + + Enabling Scrollable Cursors + To enable this functionality you must first import the 'Fetch + Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + + Next you will have to tell DBD::Oracle that you will be using scrolling + by setting the ora_exe_mode attribute on the statement handle to + 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + + When the statement is executed you will then be able to use + 'ora_fetch_scroll' method to get a row or you can still use any of the + other fetch methods but with a poorer response time than if you used a + non-scrolling cursor. As well scrollable cursors are compatible with any + applicable bind methods. + + Scrollable Cursor Methods + The following driver-specific methods are used with scrollable cursors. + + ora_scroll_position + $position = $sth->ora_scroll_position(); + + This method returns the current position (row number) attribute of + the result set. Prior to the first fetch this value is 0. This is + the only time this value will be 0 after the first fetch the value + will be set, so you can use this value to test if any rows have been + fetched. The minimum value will always be 1 after the first fetch. + The maximum value will always be the total number of rows in the + record set. + + ora_fetch_scroll + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + + Works the same as "fetchrow_arrayref", excepts one passes in a + 'Fetch Orientation' constant and a fetch_offset value which will + then determine the row that will be fetched. It returns the row as a + list containing the field values. Null fields are returned as + *undef* values in the list. + + The valid orientation constant and fetch offset values combination + are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + + The effect that a ora_fetch_scroll method call has on the + current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + + The effects of the differing orientation constants on the first + fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + + Scrollable Cursor Usage + Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + + and one assumes that the number of rows returned from the query is 20, + the code snippets below will illustrate the use of ora_fetch_scroll + method; + + Fetching the Last Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute to will be 20 after this snippet. This + is also a way to get the number of rows in the record set, however, + if the record set is large this could take some time. + + Fetching the Current Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will still be 20 after this snippet. + + Fetching the First Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the Next Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 5 after this snippet. + + Fetching the Prior Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the 10th Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 10th to 14th Row + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 14 after this snippet. + + Fetching the 14th to 10th Row + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 5th Row From the Present Position. + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 15 after this snippet. + + Fetching the 9th Row Prior From the Present Position + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 6 after this snippet. + + Use Finish + $sth->finish(); + + When using scrollable cursors it is required that you use the + $sth->finish() method when you are done with the cursor as this type + of cursor has to be explicitly cancelled on the server. If you do + not do this you may cause resource problems on your database. + +LOBS AND LONGS + The key to working with LOBs (CLOB, BLOBs) is to remember the value of + an Oracle LOB column is not the content of the LOB. It's a 'LOB Locator' + which, after being selected or inserted needs extra processing to read + or write the content of the LOB. There are also legacy LONG types (LONG, + LONG RAW, VARCHAR2) which are presently deprecated by Oracle but are + still in use. These LONG types do not utilize a 'LOB Locator' and also + are more limited in functionality than CLOB or BLOB fields. + + DBD::Oracle now offers three interfaces to LOB and LONG data, + + "Data Interface for Persistent LOBs" + With this interface DBD::Oracle handles your data directly utilizing + regular OCI calls, Oracle itself takes care of the LOB Locator + operations in the case of BLOBs and CLOBs treating them exactly as + if they were the same as the legacy LONG or LONG RAW types. + + "Data Interface for LOB Locators" + With this interface DBD::Oracle handles your data utilizing LOB + Locator OCI calls so it only works with CLOB and BLOB datatypes. + With this interface DBD::Oracle takes care of the LOB Locator + operations for you. + + "LOB Locator Method Interface" + This allows the user direct access to the LOB Locator methods, so + you have to take case of the LOB Locator operations yourself. + + Generally speaking the interface that you will chose will be dependent + on what end you are trying to achieve. All have their benefits and + drawbacks. + + One point to remember when working with LOBs (CLOBs, BLOBs) is if your + LOB column can be in one of three states; + + NULL + The table cell is created, but the cell holds no locator or value. + If your LOB field is in this state then there is no LOB Locator that + DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + + error when working with a LOB. + + You can correct this by using an SQL UPDATE statement to reset the + LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB + or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + + Empty + A LOB instance with a locator exists in the cell, but it has no + value. The length of the LOB is zero. In this case DBD::Oracle will + return 'undef' for the field. + + Populated + A LOB instance with a locator and a value exists in the cell. You + actually get the LOB value. + + Data Interface for Persistent LOBs + This is the original interface for LONG and LONG RAW datatypes and from + Oracle 9iR1 and later the OCI API was extended to work directly with the + other LOB datatypes. In other words you can treat all LOB type data + (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can + perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using + the same techniques you would use on other datatypes that store + character or binary data. In some cases there are fewer round trips to + the server as no 'LOB Locators' are used, normally one can get an entire + LOB is a single round trip. + + Simple Fetch for LONGs and LONG RAWs + As the name implies this is the simplest way to use this interface. + DBD::Oracle just attempts to get your LONG datatypes as a single large + piece. There are no special settings, simply set the database handle's + 'LongReadLen' attribute to a value that will be the larger than the + expected size of the LONG or LONG RAW. If the size of the LONG or LONG + RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A + Truncation' error. To stop this set the database handle's 'LongTruncOk' + attribute to '1'. The maximum value of 'LongReadLen' seems to be + dependent on the physical memory limits of the box that Oracle is + running on. You have most likely reached this limit if you run into an + 'ORA-01062: unable to allocate memory for define buffer' error. One + solution is to set the size of 'LongReadLen' to a lower value. + + For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select out all of the long1 fields in the table as long as they are + all under 2MB in length. A value in long1 longer than this will throw an + error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the long1 fields but they will be + truncated at 2MBs. + + Using ora_ncs_buff_mtpl + When getting CLOBs and NCLOBs in or out of Oracle, the Server will + translate from the Server's NCharSet to the Client's. If they happen to + be the same or at least compatible then all of these actions are a 1 + char to 1 char bases. Thus if you set your LongReadLen buffer to + 10_000_000 you will get up to 10_000_000 char. + + However if the Server has to translate from one NCharSet to another it + will use bytes for conversion. The buffer value is set to 4 * + LONG_READ_LEN which was very wasteful as you might only be asking for + 10_000_000 bytes but you were actually using 40_000_000 bytes of buffer + under the hood. You would still get 10_000_000 bytes (maybe less + characters though) but you are using allot more memory that you need. + + You can now customize the size of the buffer by setting the + 'ora_ncs_buff_mtpl' either on the connection or statement handle. You + can also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you + will have to go back and change all your code if you are getting into + trouble. + + The default value is still set to 4 for backward compatibility. You can + lower this value and thus increase the amount of data you can retrieve. + If the ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error + telling you to increase this buffer by one. + + If the error is not captured then you may get at some random point later + on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + + This is one of the more obscure ORA errors (have some fun and report it + to Meta-Link they will scratch their heads for hours) + + If you get this, simply increment the ora_ncs_buff_mtpl by one until it + goes away. + + This should greatly increase your ability to select very large CLOBs or + NCLOBs, by freeing up a large block of memory. + + You can tune this value by setting ora_oci_success_warn which will + display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + + In the case above the query Got 28 characters (well really only 20 + characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) + thus saving 40bytes of memory. + + Simple Fetch for CLOBs and BLOBs + To use this interface for CLOBs and LOBs datatypes set the + 'ora_pers_lob' attribute of the statement handle to '1' with the prepare + method, as well set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. If the + size of the LOB exceeds the 'LongReadLen' DBD::Oracle will return a + 'ORA-24345: A Truncation' error. To stop this set the database handle's + 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems + to be dependent on the physical memory limits of the box that Oracle is + running on in the same way that LONGs and LONG RAWs are. + + For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, + this is an internal OCI limit complain to them if you want it changed. + However if you CLOB is longer than this and also larger than the + 'LongReadLen' than the 'LongReadLen' in chars is returned. + + It seems with BLOBs you are not limited by the 64k. + + For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the lobs but they will be truncated + at 2MBs. + + Piecewise Fetch with Callback + With a piecewise callback fetch DBD::Oracle sets up a function that will + 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, + CLOB, BLOB) piece by piece. To use this interface set the 'ora_clbk_lob' + attribute of the statement handle to '1' with the prepare method. Next + set the 'ora_piece_size' to the size of the piece that you want to + return on the callback. Finally set the database handle's 'LongReadLen' + attribute to a value that will be the larger than the expected size of + the LOB. Like the "Simple Fetch for LONGs and LONG RAWs" and "Simple + Fetch for CLOBs and BLOBs" the if the size of the LOB exceeds the is + 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the + LOB or set the 'LongReadLen' to a higher value. With this interface the + value of 'ora_piece_size' seems to be constrained by the same memory + limit as found on the Simple Fetch interface. If you encounter an + 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller + value. The value for 'LongReadLen' is dependent on the version and + settings of the Oracle DB you are using. In theory it ranges from 8GBs + in 9iR1 up to 128 terabytes with 11g but you will also be limited by the + physical memory of your PERL instance. + + Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will + throw an error. + + Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 filed is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Piecewise Fetch with Polling + With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB + during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by + piece. To use this interface set the 'ora_piece_lob' attribute of the + statement handle to '1' with the prepare method. Next set the + 'ora_piece_size' to the size of the piece that you want to return on the + callback. Finally set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. Like + the "Piecewise Fetch with Callback" and Simple Fetches if the size of + the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' + attribute to truncate the LOB or set the 'LongReadLen' to a higher + value. With this interface the value of 'ora_piece_size' seems to be + constrained by the same memory limit as found on the "Piecewise Fetch + with Callback". + + Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will + throw an error. + + Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 field is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Binding for Updates and Inserts for CLOBs and BLOBs + To bind for updates and inserts all that is required to use this + interface is to set the statement handle's prepare method 'ora_type' + attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in + the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + + So far the only limit reached with this form of insert is the LOBs must + be under 2GB in size. + + Support for Remote LOBs; + Starting with Oracle 10gR2 the interface for Persistent LOBs was + expanded to support remote LOBs (access over a dblink). Given a database + called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + + to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Below are the limitations of Remote LOBs; + + Queries involving more than one database are not supported; + so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + + as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + + DDL commands are not supported; + so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + + Only binds and defines for data going into remote persistent LOBs are + supported. + so that parameter passing in PL/SQL where CHAR data is bound or + defined for remote LOBs is not allowed . + + These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + + If the remote object is a view such as + CREATE VIEW v AS SELECT foo() FROM ... + + the following would not work: + + SELECT * FROM v@dbs2; + + Limited PL/SQL parameter passing + PL/SQL parameter passing is not allowed where the actual argument is + a LOB type and the remote argument is one of VARCHAR2, NVARCHAR2, + CHAR, NCHAR, or RAW. + + RETURNING INTO does not support implicit conversions between CHAR and + CLOB. + so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + + Locator Data Interface + Simple Usage + When fetching LOBs with this interface a 'LOB Locator' is created then + used to get the lob with the LongReadLen and LongTruncOk attributes. The + value for 'LongReadLen' is dependent on the version and settings of the + Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 + terabytes with 11g but you will also be limited by the physical memory + of your PERL instance. + + When inserting or updating LOBs some *major* magic has to be performed + behind the scenes to make it transparent. Basically the driver has to + insert a 'LOB Locator' and then refetch the newly inserted LOB Locator + before being able to write the data into it. However, it works well most + of the time, and I've made it as fast as possible, just one extra + server-round-trip per insert or update after the first. For the time + being, only single-row LOB updates are supported. + + To insert or update a large LOB using a placeholder, DBD::Oracle has to + know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + + The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + + or use the corresponding integer values (112 and 113). + + One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has to + be able to tell which parameters relate to which table fields. In all + cases where it can possibly work it out for itself, it does, however, if + there are multiple LOB fields of the same type in the table then you + need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + + There are some limitations inherent in the way DBD::Oracle makes typical + LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + + The alternative is to disable the automatic LOB Locator processing. If + "ora_auto_lob" is 0 in prepare(), you can fetch the LOB Locators and do + all the work yourself using the ora_lob_*() methods. See the "Data + Interface for LOB Locators" section below. + + LOB support in PL/SQL + LOB Locators can be passed to PL/SQL calls by binding them to + placeholders with the proper "ora_type". If "ora_auto_lob" is true, + output LOB parameters will be automatically returned as strings. + + If the Oracle driver has support for temporary LOBs (Oracle 9i and + higher), strings can be bound to input LOB placeholders and will be + automatically converted to LOBs. + + Example: # Build a large XML document, bind it as a CLOB, # extract + elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + + If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + + error, while attempting to insert a LOB, this means the Oracle user has + insufficient space for LOB you are trying to insert. One solution it to + use "alter database datafile 'sss.ggg' resize Mnnn" to increase the + available memory for LOBs. + + Persistent & Locator Interface Caveats + Now that one has the option of using the Persistent or the Locator + interface for LOBs the questions arises which one to use. For starters, + if you want to access LOBs over a dblink you will have to use the + Persistent interface so that choice is simple. The question of which one + to use after that is a little more tricky. It basically boils down to a + choice between LOB size and speed. + + The Callback and Polling piecewise fetches are very very slow when + compared to the Simple and the Locator fetches but they can handle very + large blocks of data. Given a situation where a large LOB is to be read + the Locator fetch may time out while either of the piecewise fetches may + not. + + With the Simple fetch you are limited by physical memory of your server + but it runs a little faster than the Locator, as there are fewer round + trips to the server. So if you have small LOBs and need to save a little + bandwidth this is the one to use. It you are going after large LOBs then + the Locator interface is the one to use. + + If you need to update more than a single row of with LOB data then the + Persistent interface can do it while the Locator can't. + + If you encounter a situation where you have to access the legacy LOBs + (LONG, LONG RAW) and the values are to large for you system then you can + use the Callback or Polling piecewise fetches to get all of the data. + + Not all of the Persistent interface has been implemented yet, the + following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + + Most of the time you should just use the "Locator Data Interface" as + this is in one that has the best combination of speed and size. + + All this being said if you are doing some critical programming I would + use the "Data Interface for LOB Locators" as this gives you very fine + grain control of your LOBs, of course the code for this will be somewhat + more involved. + + Data Interface for LOB Locators + The following driver-specific methods let you manipulate "LOB Locators" + directly. To select a LOB locator directly set the if the "ora_auto_lob" + attribute to false, or alternatively they can be returned via PL/SQL + procedure calls. + + (If using a DBI version earlier than 1.36 they must be called via the + func() method. Note that methods called via func() don't honour + RaiseError etc, and so it's important to check $dbh->err after each + call. It's recommended that you upgrade to DBI 1.38 or later.) + + Note that LOB locators are only valid while the statement handle that + created them is valid. When all references to the original statement + handle are lost, the handle is destroyed and the locators are freed. + + ora_lob_read + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + + Read a portion of the LOB. $offset starts at 1. Uses the Oracle + OCILobRead function. + + ora_lob_write + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + + Write/overwrite a portion of the LOB. $offset starts at 1. Uses the + Oracle OCILobWrite function. + + ora_lob_append + $rc = $dbh->ora_lob_append($lob_locator, $data); + + Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + + ora_lob_trim + $rc = $dbh->ora_lob_trim($lob_locator, $length); + + Trims the length of the LOB to $length. Uses the Oracle OCILobTrim + function. + + ora_lob_length + $length = $dbh->ora_lob_length($lob_locator); + + Returns the length of the LOB. Uses the Oracle OCILobGetLength + function. + + ora_lob_is_init + $is_init = $dbh->ora_lob_is_init($lob_locator); + + Returns true(1) if the Lob Locator is initialized false(0) if it is + not, or 'undef' if there is an error. Uses the Oracle + OCILobLocatorIsInit function. + + ora_lob_chunk_size + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + + Returns the chunk size of the LOB. Uses the Oracle + OCILobGetChunkSize function. + + For optimal performance, Oracle recommends reading from and writing + to a LOB in batches using a multiple of the LOB chunk size. In + Oracle 10g and before, when all defaults are in place, this chunk + size defaults to 8k (8192). + + LOB Locator Method Examples + *Note:* Make sure you first read the note in the section above about + multi-byte character set issues with these methods. + + The following examples demonstrate the usage of LOB Locators to read, + write, and append data, and to query the size of large data. + + The following examples assume a table containing two large object + columns, one binary and one character, with a primary key column, + defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + + It also assumes a sequence for use in generating unique lob_id field + values, defined as follows: + + CREATE SEQUENCE lob_example_seq + + Example: Inserting a new row with large data + Unless enough memory is available to store and bind the entire LOB data + for insert all at once, the LOB columns must be written interactively, + piece by piece. In the case of a new row, this is performed by first + inserting a row, with empty values in the LOB columns, then modifying + the row by writing the large data interactively to the LOB columns using + their LOB locators as handles. + + The insert statement must create token values in the LOB columns. Here, + we use the empty string for both the binary and character large object + columns 'bindata' and 'chardata'. + + After the INSERT statement, a SELECT statement is used to acquire LOB + locators to the 'bindata' and 'chardata' fields of the newly inserted + row. Because these LOB locators are subsequently written, they must be + acquired from a select statement containing the clause 'FOR UPDATE' (LOB + locators are only valid within the transaction that fetched them, so + can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + + In this example we demonstrate the use of ora_lob_write() interactively + to append data to the columns 'bin_data' and 'char_data'. Had we used + ora_lob_append(), we could have saved ourselves the trouble of keeping + track of the offset into the lobs. The snippet of code beneath the + comment 'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + + The scalar variables $offset and $length are no longer needed, because + ora_lob_append() keeps track of the offset for us. + + Example: Updating an existing row with large data + In this example, we demonstrate a technique for overwriting a portion of + a blob field with new binary data. The blob data before and after the + section overwritten remains unchanged. Hence, this technique could be + used for updating fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + + After running this code, the row where lob_id = 5 will contain, starting + at position 100234 in the bin_data column, the string "This string will + overwrite a portion of the blob". + + Example: Streaming character data from the database + In this example, we demonstrate a technique for streaming data from the + database to a file handle, in this case STDOUT. This allows more data to + be read in and written out than could be stored in memory at a given + time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + + Notice that the select statement does not contain the phrase "FOR + UPDATE". Because we are only reading from the LOB Locator returned, and + not modifying the LOB it refers to, the select statement does not + require the "FOR UPDATE" clause. + + A word of caution when using the data returned from an ora_lob_read in a + conditional statement. for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + + was used with a chunk size of 4096 against a blob that requires more + than 1 chunk to return the data and the last chunk is one byte long and + contains a zero (ASCII 48) you will miss this last byte as $data will + contain 0 which PERL will see as false and not print it out. + + Example: Truncating existing large data + In this example, we truncate the data already present in a large object + column in the database. Specifically, for each row in the table, we + truncate the 'bindata' value to half its previous length. + + After acquiring a LOB Locator for the column, we query its length, then + we trim the length by half. Because we modify the large objects with the + call to ora_lob_trim(), we must select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +SPACES AND PADDING + Trailing Spaces + Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder + values and uses Nonpadded Comparison Semantics with the result. This + causes trouble if the spaces are needed for comparison with a CHAR value + or to prevent the value from becoming '' which Oracle treats as NULL. + Look for Blank-padded Comparison Semantics and Nonpadded Comparison + Semantics in Oracle's SQL Reference or Server SQL Reference for more + details. + + To preserve trailing spaces in placeholder values for Oracle clients + that use OCI 8, either change the default placeholder type with + "ora_ph_type" or the placeholder type for a particular call to "bind" in + DBI or "bind_param_inout" in DBI with "ora_type" or "TYPE". Using + ORA_CHAR with ora_type or "SQL_CHAR" with "TYPE" allows the placeholder + to be used with Padded Comparison Semantics if the value it is being + compared to is a CHAR, NCHAR, or literal. + + Please remember that using spaces as a value or at the end of a value + makes visually distinguishing values with different numbers of spaces + difficult and should be avoided. + + Oracle Clients that use OCI 9.2 do not strip trailing spaces. + + Padded Char Fields + Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder + values to the size of the CHAR. As the default placeholder type value in + DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will have to + change the default placeholder type with "ora_ph_type" or placeholder + type for a particular call with "bind" in DBI or "bind_param_inout" in + DBI with "ORA_CHAR". + +UNICODE + DBD::Oracle now supports Unicode UTF-8. There are, however, a number of + issues you should be aware of, so please read all this section + carefully. + + In this section we'll discuss "Perl and Unicode", then "Oracle and + Unicode", and finally "DBD::Oracle and Unicode". + + Information about Unicode in general can be found at: + . It is well worth reading because there are + many misconceptions about Unicode and you may be holding some of them. + + Perl and Unicode + Perl began implementing Unicode with version 5.6, but the implementation + did not mature until version 5.8 and later. If you plan to use Unicode + you are *strongly* urged to use Perl 5.8.2 or later and to *carefully* + read the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + + And then read it again. + + Perl's internal Unicode format is UTF-8 which corresponds to the Oracle + character set called AL32UTF8. + + Oracle and Unicode + Oracle supports many characters sets, including several different forms + of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + + When you create an Oracle database, you must specify the DATABASE + character set (used for DDL, DML and CHAR datatypes) and the NATIONAL + character set (used for NCHAR and NCLOB types). The character sets used + in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + + The Oracle 9.2 and later default for the national character set is + AL16UTF16. The default for the database character set is often US7ASCII. + Although many experienced DBAs will consider an 8bit character set like + WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other + than US7ASCII, requires that the NLS_LANG environment variable be set. + See the "Oracle UTF8 is not UTF-8" section below. + + You are strongly urged to read the Oracle Internationalization + documentation specifically with respect the choices and trade offs for + creating a databases for use with international character sets. + + Oracle uses the NLS_LANG environment variable to indicate what character + set is being used on the client. When fetching data Oracle will convert + from whatever the database character set is to the client character set + specified by NLS_LANG. Similarly, when sending data to the database + Oracle will convert from the character set specified by NLS_LANG to the + database character set. + + The NLS_NCHAR environment variable can be used to define a different + character set for 'national' (NCHAR) character types. + + Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. For + example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + + Oracle UTF8 is not UTF-8 + AL32UTF8 should be used in preference to UTF8 if it works for you, which + it should for Oracle 9.2 or later. If you're using an old version of + Oracle that doesn't support AL32UTF8 then you should avoid using any + Unicode characters that require surrogates, in other words characters + beyond the Unicode BMP (Basic Multilingual Plane). + + That's because the character set that Oracle calls "UTF8" doesn't + conform to the UTF-8 standard in its handling of surrogate characters. + Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". + Here are a couple of extracts from + : + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + + Oracle uses this internally because it collates (sorts) in the same + order as UTF16, which is the basis of Oracle's internal collation + definitions. + + Rather than change UTF8 for clients Oracle chose to define a new + character set called "AL32UTF8" which does conform to the UTF-8 + standard. (The AL32UTF8 character set can't be used on the server + because it would break collation.) + + Because of that, for the rest of this document we'll use "AL32UTF8". If + you're using an Oracle version below 9.2 you'll need to use "UTF8" until + you upgrade. + + DBD::Oracle and Unicode + DBD::Oracle Unicode support has been implemented for Oracle versions 9 + or greater, and Perl version 5.6 or greater (though we *strongly* + suggest that you use Perl 5.8.2 or later). + + You can check which Oracle version your DBD::Oracle was built with by + importing the "ORA_OCI" constant from DBD::Oracle. + + Fetching Data + + Any data returned from Oracle to DBD::Oracle in the AL32UTF8 character + set will be marked as UTF-8 to ensure correct handling by Perl. + + For Oracle to return data in the AL32UTF8 character set the NLS_LANG or + NLS_NCHAR environment variable *must* be set as described in the + previous section. + + When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle + will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR is + AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + + When fetching other character data from Oracle, DBD::Oracle will set the + Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + + Sending Data using Placeholders + + Data bound to a placeholder is assumed to be in the default client + character set (specified by NLS_LANG) except for a few special cases. + These are listed here with the highest precedence first: + + If the "ora_csid" attribute is given to bind_param() then that is passed + to Oracle and takes precedence. + + If the value is a Perl Unicode string (UTF-8) then DBD::Oracle ensures + that Oracle uses the Unicode character set, regardless of the NLS_LANG + and NLS_NCHAR settings. + + If the placeholder is for inserting an NCLOB then the client NLS_NCHAR + character set is used. (That's useful but inconsistent with the other + behaviour so may change. Best to be explicit by using the "ora_csform" + attribute.) + + If the "ora_csform" attribute is given to bind_param() then that + determines if the value should be assumed to be in the default + (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + Binding with bind_param_array and execute_array is also UTF-8 compatible + in the same way. If you attempt to insert UTF-8 data into a non UTF-8 + Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert will + still happen but a error code of 0 will be returned with the following + warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + + The warning will report the parameter number and the NCHAR setting that + the query is running. + + Sending Data using SQL + + Oracle assumes the SQL statement is in the default client character set + (as specified by NLS_LANG). So Unicode strings containing non-ASCII + characters should not be used unless the default client character set is + AL32UTF8. + + DBD::Oracle and Other Character Sets and Encodings + The only multi-byte Oracle character set supported by DBD::Oracle is + "AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +OBJECT & COLLECTION DATA TYPES + Oracle databases allow for the creation of object oriented like + user-defined types. There are two types of objects, Embedded--an object + stored in a column of a regular table and REF--an object that uses the + REF retrieval mechanism. + + DBD::Oracle supports only the 'selection' of embedded objects of the + following types OBJECT, VARRAY and TABLE in any combination. Support is + seamless and recursive, meaning you need only supply a simple SQL + statement to get all the values in an embedded object. You can either + get the values as an array of scalars or they can be returned into a + DBD::Oracle::Object. + + Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + + The code to access all the data in the table could be something like + this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + + Note that values in PHONE_NUMBERS are returned as an array reference + '@$phone'. + + As stated before DBD::Oracle will automatically drill into the embedded + object and extract all of the data as reference arrays of scalars. The + example below has OBJECT type embedded in a TABLE type embedded in an + SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + + The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + + Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + + The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + + So far DBD::Oracle has been tested on a table with 20 embedded Objects, + Varrays and Tables nested to 10 levels. + + Any NULL values found in the embedded object will be returned as + 'undef'. + +OTHER DATA TYPES + DBD::Oracle does not *explicitly* support most Oracle datatypes. It + simply asks Oracle to return them as strings and Oracle does so. Mostly. + Similarly when binding placeholder values DBD::Oracle binds them as + strings and Oracle converts them to the appropriate type, such as DATE, + when used. + + Some of these automatic conversions to and from strings use NLS settings + to control the formatting for output and the parsing for input. The most + common example is the DATE type. The default NLS format for DATE might + be DD-MON-YYYY and so when a DATE type is fetched that's how Oracle will + format the date. NLS settings also control the default parsing of + strings into DATE values. An error will be generated if the contents of + the string don't match the NLS format. If you're dealing in dates which + don't match the default NLS format then you can either change the + default NLS format or, more commonly, use TO_CHAR(field, "format") and + TO_DATE(?, "format") to explicitly specify formats for converting to and + from strings. + + A slightly more subtle problem can occur with NUMBER types. The default + NLS settings might format numbers with a fullstop (""."") to separate + thousands and a comma ("","") as the decimal point. Perl will generate + warnings and use incorrect values when numbers, returned and formatted + as strings in this way by Oracle, are used in a numeric context. You + could explicitly convert each numeric value using the TO_CHAR(...) + function but that gets tedious very quickly. The best fix is to change + the NLS settings. That can be done for an individual connection by + doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + + There are some types, like BOOLEAN, that Oracle does not automatically + convert to or from strings (pity). These need to be converted explicitly + using SQL or PL/SQL functions. + + Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + + Support for Insert of XMLType (ORA_XMLTYPE) + Inserting large XML data sets into tables with XMLType fields is now + supported by DBD::Oracle. The only special requirement is the use of + bind_param() with an attribute hash parameter that specifies ora_type as + ORA_XMLTYPE. For example with a table like this; + + create table books (book_id number, book_xml XMLType); + + one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + + In the above case we will assume that $xml has 10000 Book nodes and is + over 32k in size and is well formed XML. This will also work for XML + that is smaller than 32k as well. Attempting to insert malformed XML + will cause an error. + + Binding Cursors + Cursors can be returned from PL/SQL blocks, either from stored functions + (or procedures with OUT parameters) or from direct "OPEN" statements, as + shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + The only special requirement is the use of "bind_param_inout()" with an + attribute hash parameter that specifies "ora_type" as "ORA_RSET". If you + don't do that you'll get an error from the "execute()" like: "ORA-06550: + line X, column Y: PLS-00306: wrong number or types of arguments in call + to ...". + + Here's an alternative form using a function that returns a cursor. This + example uses the pre-defined weak (or generic) REF CURSOR type + SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + A cursor obtained from PL/SQL as above may be passed back to PL/SQL by + binding for input, as shown in this example, which explicitly closes a + cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + + It is not normally necessary to close a cursor explicitly in this way. + Oracle will close the cursor automatically at the first client-server + interaction after the cursor statement handle is destroyed. An explicit + close may be desirable if the reference to the cursor handle from the + PL/SQL statement handle delays the destruction of the cursor handle for + too long. This reference remains until the PL/SQL handle is re-bound, + re-executed or destroyed. + + See the "curref.pl" script in the Oracle.ex directory in the DBD::Oracle + source distribution for a complete working example. + + Fetching Nested Cursors + Oracle supports the use of select list expressions of type REF CURSOR. + These may be explicit cursor expressions - "CURSOR(SELECT ...)", or + calls to PL/SQL functions which return REF CURSOR values. The values of + these expressions are known as nested cursors. + + The value returned to a Perl program when a nested cursor is fetched is + a statement handle. This statement handle is ready to be fetched from. + It should not (indeed, must not) be executed. + + Oracle imposes a restriction on the order of fetching when nested + cursors are used. Suppose $sth1 is a handle for a select statement + involving nested cursors, and $sth2 is a nested cursor handle fetched + from $sth1. $sth2 can only be fetched from while $sth1 is still active, + and the row containing $sth2 is still current in $sth1. Any attempt to + fetch another row from $sth1 renders all nested cursor handles + previously fetched from $sth1 defunct. + + Fetching from such a defunct handle results in an error with the message + "ERROR nested cursor is defunct (parent row is no longer current)". + + This means that the "fetchall..." or "selectall..." methods are not + useful for queries returning nested cursors. By the time such a method + returns, all the nested cursor handles it has fetched will be defunct. + + It is necessary to use an explicit fetch loop, and to do all the + fetching of nested cursors within the loop, as the following example + shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + + The cursor returned by the function "sp_ListEmp" defined in the previous + section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + + Pre-fetching Nested Cursors + By default, DBD::Oracle pre-fetches rows in order to reduce the number + of round trips to the server. For queries which do not involve nested + cursors, the number of pre-fetched rows is controlled by the DBI + database handle attribute "RowCacheSize" (q.v.). + + In Oracle, server side open cursors are a controlled resource, limited + in number, on a per session basis, to the value of the initialization + parameter "OPEN_CURSORS". Nested cursors count towards this limit. Each + nested cursor in the current row counts 1, as does each nested cursor in + a pre-fetched row. Defunct nested cursors do not count. + + An Oracle specific database handle attribute, "ora_max_nested_cursors", + further controls pre-fetching for queries involving nested cursors. For + each statement handle, the total number of nested cursors in pre-fetched + rows is limited to the value of this parameter. The default value is 0, + which disables pre-fetching for queries involving nested cursors. + +PL/SQL Examples + Most of these PL/SQL examples come from: Eric Bartley + . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + + You can find more examples in the t/plsql.t file in the DBD::Oracle + source directory. + + Oracle 9.2 appears to have a bug where a variable bound with + bind_param_inout() that isn't assigned to by the executed PL/SQL block + may contain garbage. See + + + Avoid Using "SQL Call" + Avoid using the "SQL Call" statement with DBD:Oracle as you might find + that DBD::Oracle will not raise an exception in some case. Specifically + if you use "SQL Call" to run a procedure all "No data found" exceptions + will be quietly ignored and returned as null. According to Oracle + support this is part of the same mechanism where; + + select (select * from dual where 0=1) from dual + + returns a null value rather than an exception. + +CONTRIBUTING + If you'd like DBD::Oracle to do something new or different the best way + to make that happen is to do it yourself and email to dbi-dev@perl.org a + patch of the source code (using 'diff' - see below) that shows the + changes. + + How to create a patch using Subversion + The DBD::Oracle source code is maintained using Subversion (a + replacement for CVS, see ). To access the + source you'll need to install a Subversion client. Then, to get the + source code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + + If it prompts for a username and password use your perl.org account if + you have one, else just 'guest' and 'guest'. The source code will be in + a new subdirectory called "trunk". + + To keep informed about changes to the source you can send an empty email + to dbd-oracle-changes-subscribe@perl.org after which you'll get an email + with the change log message and diff of each change checked-in to the + source. + + After making your changes you can generate a patch file, but before you + do, make sure your source is still upto date using: + + svn update + + If you get any conflicts reported you'll need to fix them first. Then + generate the patch file from within the "trunk" directory using: + + svn diff > foo.patch + + Read the patch file, as a sanity check, and then email it to + dbi-dev@perl.org. + + How to create a patch without Subversion + Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + + Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + + Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you + want. + + Test your changes and then remove all temporary files: + + make test && make distclean + + Go back to the directory you originally unpacked the distribution: + + cd .. + + Unpack *another* copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + + Then create a patch file by performing a recursive "diff" on the two top + level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + + Speak before you patch + For anything non-trivial or possibly controversial it's a good idea to + discuss (on dbi-dev@perl.org) the changes you propose before actually + spending time working on them. Otherwise you run the risk of them being + rejected because they don't fit into some larger plans you may not be + aware of. + + GitHub repository + A git mirror of the subversion is also available at + `https://github.com/yanick/DBD-Oracle`. + +Oracle Related Links +WHICH VERSION OF DBD::ORACLE IS FOR ME? + From version 1.25 onwards DBD::Oracle only support Oracle clients 9.2 or + greater. Support for ProC connections was dropped in 1.29. + + If you are still stuck with an older version of Oracle or its client you + might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + + As there are dozens of different versions of Oracle's clients this list + does not include all of them, just the major released versions of + Oracle. + + Note that one can still connect to any Oracle version with the older + DBD::Oracle versions the only problem you will have is that some of the + newer OCI and Oracle features available in later DBD::Oracle releases + will not be available to you. + + So to make a short story a little longer: + + 1 If you are using Oracle 7 or early 8 DB and you can manage to get a + 9 client and you can use any DBD::Oracle version. + + 2 If you have to use an Oracle 7 client then DBD::Oracle 1.17 should + work + + 3 Same thing for 8 up to R2, use 1.17, if you are lucky and have the + right patch-set you might go with 1.18. + + 4 For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. + Again this depends on your patch-set, If you run into trouble go + with 1.19 + + 5 After 9.2 you can use any version you want. + + 6 It seems that the 10g client can only connect to 9 and 11 DBs while + the 9 can go back to 7 and even get to 10. I am not sure what the + 11g client can connect to. + +BUGS AND LIMITATIONS + There is a known problem with the 11.2g Oracle client and the + "DBMS_LOB.GETLENGTH()" PL/SQL function. See + for the details. + +SEE ALSO + DBI http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in + the DBD::Oracle source distribution including the examples in the + Oracle.ex directory + + DBD::Oracle Tutorial + http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-ora + cle.html + + Oracle Instant Client + http://www.oracle.com/technology/tech/oci/instantclient/index.html + + Oracle on Linux + http://www.ixora.com.au/ + + Free Oracle Tools and Links + ora_explain supplied and installed with DBD::Oracle. + + http://www.orafaq.com/ + + http://vonnieda.org/oracletool/ + + Commercial Oracle Tools and Links + Assorted tools and references for general information. No + recommendation implied. + + http://www.platinum.com + + http://www.SoftTreeTech.com + + Also PL/Vision from RevealNet and Steven Feuerstein, and "Q" from + Savant Corporation. + +AUTHORS + DBI by Tim Bunce . + + The original "DBD::Oracle" was by Tim Bunce. Maintained as of release + 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the + auspice of the Pythian Group (). + +ACKNOWLEDGEMENTS + A great many people have helped with DBD::Oracle over the 17 years + between 1994 and 2011. Far too many to name, but we thank them all. Many + are named in the Changes file. + +COPYRIGHT + The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. + The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The + Pythian Group). Canada. The DBD::Oracle module is Copyright (c) 2011 + John Scoles. Canada. + + The DBD::Oracle module is free open source software; you can + redistribute it and/or modify it under the same terms as Perl 5. + +AUTHORS + * Tim Bunce + + * John Scoles + + * Yanick Champoux + +COPYRIGHT AND LICENSE + This software is copyright (c) 1994 by Tim Bunce. + + This is free software; you can redistribute it and/or modify it under + the same terms as the Perl 5 programming language system itself. diff --git a/README.mkdn b/README.mkdn new file mode 100644 index 00000000..6ab143c3 --- /dev/null +++ b/README.mkdn @@ -0,0 +1,4228 @@ +# NAME + +DBD::Oracle - Oracle database driver for the DBI module + +# VERSION + +version 1.39_00 + +# SYNOPSIS + + use DBI; + + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); + + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); + + # See the DBI module documentation for full details + + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); + +# DESCRIPTION + +DBD::Oracle is a Perl module which works with the DBI module to provide +access to Oracle databases. + +This documentation describes driver specific behaviour and restrictions. It is +not supposed to be used as the only reference for the user. In any case +consult the [DBI](http://search.cpan.org/perldoc?DBI) documentation first! + +# CONSTANTS + +- :ora_session_modes + +ORA_SYSDBA ORA_SYSOPER ORA_SYSASM + +- :ora_types + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +- SQLCS_IMPLICIT + +- SQLCS_NCHAR + +SQLCS_IMPLICIT and SQLCS_NCHAR are _character set form_ values. +See notes about Unicode elsewhere in this document. + +- SQLT_INT + +- SQLT_FLT + +These types are used only internally, and may be specified as internal +bind type for ORA_NUMBER_TABLE. See notes about ORA_NUMBER_TABLE elsewhere +in this document + +- ORA_OCI + +Oracle doesn't provide a formal API for determining the exact version +number of the OCI client library used, so DBD::Oracle has to go digging +(and sometimes has to more or less guess). The ORA_OCI constant +holds the result of that process. + +In string context ORA_OCI returns the full "A.B.C.D" version string. + +In numeric context ORA_OCI returns the major.minor version number +(8.1, 9.2, 10.0 etc). But note that version numbers are not actually +floating point and so if Oracle ever makes a release that has a two +digit minor version, such as `9.10` it will have a lower numeric +value than the preceding `9.9` release. So use with care. + +The contents and format of ORA_OCI are subject to change (it may, +for example, become a _version object_ in later releases). +I recommend that you avoid checking for exact values. + +- :ora_fetch_orient + + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE + +These constants are used to set the orientation of a fetch on a scrollable cursor. + +- :ora_exe_modes + + OCI_STMT_SCROLLABLE_READONLY + +- :ora_fail_over + + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + +# DBI CLASS METHODS + +## __connect__ + +This method creates a database handle by connecting to a database, and is the DBI equivalent of the "new" method. +To open a connection to an Oracle database you need to specify a database connection string (URL), username and password. + +The connection string is always of the form: "dbi:Oracle:" +There are several ways to identify a database: + +- 1 + +If the database is local, specifying the SID or service name will be enough. + +- 2 + +If the database is defined in a TNSNAMES.ORA file, you can use the service name given in the file + +- 3 + +To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: +//host[:port][/service_name] + +If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. + +The following examples show several ways a connection can be created: + + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); + + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); + + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); + + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); + +### OS authentication + +To connect to a local database with a user which has been set up to +authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): + + $dbh = DBI->connect('dbi:Oracle:','/',''); + +Note the lack of a connection name (use the ORACLE_SID environment +variable). If an explicit SID is used you will probably get an ORA-01004 error. + +That only works for local databases. (Authentication to remote Oracle +databases using your Unix login name without a password is possible +but it is not secure and not recommended so not documented here. + +### Oracle Environment Variables + +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). + +Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. + +To use them, specify either a local SID or service name, or a service name that is specified in the TNSNAMES.ORA file. + +Note that if you have *both* local and remote databases, and you have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO_TASK takes precedence over ORACLE_SID (i.e. you get connected to remote system). + +It is highly recommended not to rely on environment variables and to always explicitly specify the SID in the connection string. This can prevent serious mistakes such as dropping a schema in the wrong database, and generally makes debugging and troubleshooting easier. + +Also remember that depending on the operating system you are using the differing "ORACLE" environment variables may be case sensitive, so if you are not connecting as you should double check the case of both the variable and its value. + +### Timezones + +If the query is run through SQL*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. + +If the query is run locally, Oracle will return the time zone based on the "TZ" environment variable setting of the user running +the query. + +With local queries, you can change the time zone for a particular user by simply changing the setting of "TZ". To check the current setting, +issue the UNIX "date" command. + +### Oracle DRCP + +DBD::Oracle supports DRCP (Database Resident Connection Pool) so +if you have an 11.2 database and DRCP is enabled you can direct +all of your connections to it by adding ':POOLED' to the SID or +setting a connection attribute of ora_drcp, or set the SERVER=POOLED +when using a TNSENTRY style connection or even by setting an +environment variable ORA_DRCP. All of which are demonstrated below; + + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') + + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') + + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") + + if the ORA_DRCP environment variable is set then just this + + $dbh = DBI->connect('dbi:Oracle:DB','username','password') + +You can find a white paper on setting up DRCP and its advantages at [http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf](http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf). + +Please note that DRCP support in DBD::Oracle is relatively new so the +mechanics or its implementation are subject to change. + +### TAF (Transparent Application Failover) + +Transparent Application Failover (TAF) is the feature in OCI that +allows for clients to automatically reconnect to an instance in the +event of a failure of the instance. The reconnect happens +automatically from within the OCI (Oracle Call Interface) library. +DBD::Oracle now supports a callback function that will fire when a TAF +event takes place. The main use of the callback is to give your +program the opportunity to inform the user that a failover is taking +place. + +You will have to set up TAF on your instance before you can use this +callback. You can test your instance to see if you can use TAF +callback with + + $dbh->ora_can_taf(); + +If you try to set up a callback without it being enabled DBD::Oracle will croak. + +It is outside the scope of this documents to go through all of the +possible TAF situations you might want to set up but here is a simple +example: + +The TNS entry for the instance has had the following added to the +CONNECT_DATA section + + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) + +You will also have to create your own perl function that will be +called from the client. You can name it anything you want and it will +always be passed two parameters, the failover event value and the +failover type. You can also set a sleep value in case of failover +error and the OCI client will sleep for the specified seconds before it +attempts another event. + + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants + + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + + #create the perl TAF event function + + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ + + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); + + } + return 0; + } + +The TAF types are as follows + + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + +The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + +### Connect Attributes + +#### ora_ncs_buff_mtpl + +You can customize the size of the buffer when selecting LOBs with +the built-in AUTO Lob. The default value is 4 which is probably +excessive for most situations but is needed for backward +compatibility. If you not converting between a NCS on the DB and the +Client then you might want to set this to 1 to reduce memory usage. + +This value can also be specified with the `ORA_DBD_NCS_BUFFER` +environment variable in which case it sets the value at the connect +stage. + +#### ora_drcp + +For Oracle 11.2 or greater. + +Set to _1_ to enable DRCP. Can also be set via the `ORA_DRCP` environment variable. + +#### ora_drcp_class + +If you are using DRCP, you can set a CONNECTION_CLASS for your pools +as well. As sessions from a DRCP cannot be shared by users, you can +use this setting to identify the same user across different +applications. OCI will ensure that sessions belonging to a 'class' are +not shared outside the class'. + +The values for ora_drcp_class cannot contain a '*' and must be less +than 1024 characters. + +This value can be also be specified with the `ORA_DRCP_CLASS` +environment variable. + +#### ora_drcp_min + +This optional value specifies the minimum number of sessions that are +initially opened. New sessions are only opened after this value has +been reached. + +The default value is 4 and any value above 0 is valid. + +Generally, it should be set to the number of concurrent statements the +application is planning or expecting to run. + +This value can also be specified with the `ORA_DRCP_MIN` environment +variable. + +#### ora_drcp_max + +This optional value specifies the maximum number of sessions that can +be open at one time. Once reached no more sessions can be opened +until one becomes free. The default value is 40 and any value above 1 +is valid. You should not set this value lower than ora_drcp_min as +that will just waste resources. + +This value can also be specified with the `ORA_DRCP_MAX` environment +variable. + +#### ora_drcp_incr + +This optional value specifies the next increment for sessions to be +started if the current number of sessions are less than +ora_drcp_max. The default value is 2 and any value above 0 is +valid as long as the value of ora_drcp_min + ora_drcp_incr is not +greater than ora_drcp_max. + +This value can also be specified with the `ORA_DRCP_INCR` environment +variable. + +#### ora_taf + +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option to any _true_ value. + +#### ora_taf_function + +The name of the Perl subroutine that will be called from OCI when a +TAF event occurs. You must supply a perl function to use the callback +and it will always receive two parameters, the failover event value +and the failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + +#### ora_taf_sleep + +The amount of time in seconds the OCI client will sleep between attempting +successive failover events when the event is OCI_FO_ERROR. + +#### ora_session_mode + +The ora_session_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA_SYSASM authorization. +The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + +This is one case where setting ORACLE_SID may be useful since +connecting as SYSDBA or SYSOPER via SQL*Net is frequently disabled +for security reasons. + +Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + +It has been reported that this only works if `$dsn` does not contain +a SID so that Oracle then uses the value of ORACLE_SID (not +TWO_TASK) environment variable to connect to a local instance. Also +the username and password should be empty, and the user executing the +script needs to be part of the dba group or osdba group. + +#### ora_oratab_orahome + +Passing a true value for the ora_oratab_orahome attribute will make +DBD::Oracle change `$ENV{ORACLE_HOME}` to make the Oracle home directory +that specified in the `/etc/oratab` file _if_ the database to connect to +is specified as a SID that exists in the oratab file, and DBD::Oracle was +built to use the Oracle 7 OCI API (not Oracle 8+). + +#### ora_module_name + +After connecting to the database the value of this attribute is passed +to the SET_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL +package. This can be used to identify the application to the DBA for +monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + +The maximum size is 48 bytes. + +#### ora_driver_name + +For 11g and later you can now set the name of the driver layer using OCI. +Perl, Perl5, ApachePerl so on. Names starting with "ORA" are reserved. You +can enter up to 8 characters. If none is enter then this will default to +DBDOxxxx where xxxx is the current version number. This value can be +retrieved on the server side using V$SESSION_CONNECT_INFO or +GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + +#### ora_client_info + +Allows you to add any value (up to 64 bytes) to your session and it can be +retrieved on the server side from the `V$SESSION`a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + +#### ora_client_identifier + +Allows you to specify the user identifier in the session handle. + +Most useful for web applications as it can pass in the session user +name which might be different to the connection user name. Can be up +to 64 bytes long but do not to include the password for security +reasons and the first character of the identifier should not be +':'. This value can be retrieved on the server side using `V$SESSION` +view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + +#### ora_action + +Allows you to specify any string up to 32 bytes which may be retrieved +on the server side using `V$SESSION` view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + +#### ora_dbh_share + +Requires at least Perl 5.8.0 compiled with ithreads. + +Allows you to share +database connections between threads. The first connect will make the +connection, all following calls to connect with the same ora_dbh_share +attribute will use the same database connection. The value must be a +reference to a already shared scalar which is initialized to an empty +string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + +#### ora_envhp + +The first time a connection is made a new OCI 'environment' is +created by DBD::Oracle and stored in the driver handle. +Subsequent connects reuse (share) that same OCI environment +by default. + +The ora_envhp attribute can be used to disable the reuse of the OCI +environment from a previous connect. If the value is `0` then +a new OCI environment is allocated and used for this connection. + +The OCI environment holds information about the client side context, +such as the local NLS environment. By altering `%ENV` and setting +ora_envhp to 0 you can create connections with different NLS +settings. This is most useful for testing. + +#### ora_charset, ora_ncharset + +For oracle versions >= 9.2 you can specify the client charset and +ncharset with the ora_charset and ora_ncharset attributes. You +still need to pass `ora_envhp = 0` for all but the first connect. + +These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + +#### ora_verbose + +Use this value to enable DBD::Oracle only tracing. Simply either set +the ora_verbose attribute on the connect() method to the trace level +you desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + +or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + +In both cases the DBD::Oracle trace level is set to 6, which is the highest +level tracing most of the calls to OCI. + +#### ora_oci_success_warn + +Use this value to print otherwise silent OCI warnings that may happen +when an execute or fetch returns "Success With Info" or when you want +to tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + +#### ora_objects + +Use this value to enable extended embedded oracle objects mode. In extended: + +- 1 + +Embedded objects are returned as instance (including type-name etc.) instead of simple ARRAY. + +- 2 + +Determine object type for each instance. All object attributes are returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + +#### ora_ph_type + +The default placeholder datatype for the database session. +The `TYPE` or [ora_type](#pod_ora_type) attributes to L and +L override the datatype for individual placeholders. +The most frequent reason for using this attribute is to permit trailing spaces +in values passed by placeholders. + +Constants for the values allowed for this attribute can be imported using + + use DBD::Oracle qw(:ora_types); + +Only the following values are permitted for this attribute. + +- ORA_VARCHAR2 + +Oracle clients using OCI 8 will strip trailing spaces and allow embedded \0 bytes. +Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \0 bytes. +This is the normal default placeholder type. + +- ORA_STRING + +Do not strip trailing spaces and end the string at the first \0. + +- ORA_CHAR + +Do not strip trailing spaces and allow embedded \0. +Force 'blank-padded comparison semantics'. + +For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + +Will pad bloggs out to 8 characters and return the username. + +#### ora_parse_error_offset + +If the previous error was from a failed `prepare` due to a syntax error, +this attribute gives the offset into the `Statement` attribute where the +error was found. + +#### ora_array_chunk_size + +Due to OCI limitations, DBD::Oracle needs to buffer up rows of +bind values in its `execute_for_fetch` implementation. This attribute +sets the number of rows to buffer at a time (default value is 1000). + +The `execute_for_fetch` function will collect (at most) this many +rows in an array, send them off to the DB for execution, then go back +to collect the next chunk of rows and so on. This attribute can be +used to limit or extend the number of rows processed at a time. + +Note that this attribute also applies to `execute_array`, since that +method is implemented using `execute_for_fetch`. + +#### ora_connect_with_default_signals + +Sometimes the Oracle client seems to change some of the signal +handlers of the process during the connect phase. For instance, some +users have observed Perl's default `$SIG{INT}` handler being ignored +after connecting to an Oracle database. If this causes problems in +your application, set this attribute to an array reference of signals +you would like to be localized during the connect process. Once the +connect is complete, the signal handlers should be returned to their +previous state. + +For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + +NOTE disabling the signal handlers the OCI library sets up may affect +functionality in the OCI library. + +NOTE If you are using connect_cached then the above example will lead +to DBI thinking each connection is different as an anonymous array reference +is being used. To avoid this when using connect_cached you are advised +to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + +In more recent Perl versions you could possibly make use of new state +variables. + +## __connect_cached__ + +Implemented by DBI, no driver-specific impact. +Please note that connect_cached as not been tested with DRCP. + +## __data_sources__ + + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + +Returns a list of available databases. You will have to set either the 'ORACLE_HOME' or +'TNS_ADMIN' environment value to retrieve this list. It will read these values from +TNSNAMES.ORA file entries. + +# METHODS COMMON TO ALL HANDLES + +For all of the methods below, __$h__ can be either a database handle (__$dbh__) +or a statement handle (__$sth__). Note that _$dbh_ and _$sth_ can be replaced with +any variable name you choose: these are just the names most often used. Another +common variable used in this documentation is $_rv_, which stands for "return value". + +## __err__ + + $rv = $h->err; + +Returns the error code from the last method called. + +## __errstr__ + + $str = $h->errstr; + +Returns the last error that was reported by Oracle. Starting with "ORA-00000" code followed by the error message. + +## __state__ + + $str = $h->state; + +Oracle hasn't supported SQLSTATE since the early versions OCI. It will return empty when the command succeeds and +'S1000' (General Error) for all other errors. + +While this method can be called as either `$sth->state` or `$dbh->state`, it +is usually clearer to always use `$dbh->state`. + +## __trace__ + +Implemented by DBI, no driver-specific impact. + +## __trace_msg__ + +Implemented by DBI, no driver-specific impact. + +## __parse_trace_flag__ and __parse_trace_flags__ + +Implemented by DBI, no driver-specific impact. + +## __func__ + +DBD::Oracle uses the `func` method to support a variety of functions. + +## __Private database handle functions__ + +Some of these functions are called through the method func() +which is described in the DBI documentation. Any function that begins with ora_ +can be called directly. + +## __plsql_errstr__ + +This function returns a string which describes the errors +from the most recent PL/SQL function, procedure, package, +or package body compile in a format similar to the output +of the SQL*Plus command 'show errors'. + +The function returns undef if the error string could not +be retrieved due to a database error. +Look in $dbh->errstr for the cause of the failure. + +If there are no compile errors, an empty string is returned. + +Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + +## __dbms_output_enable / dbms_output_put / dbms_output_get__ + +These functions use the PL/SQL DBMS_OUTPUT package to store and +retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer +by dbms_output_put or any PL/SQL block can be retrieved by +dbms_output_get or any PL/SQL block connected to the same database +session. + +Stored text is not available until after dbms_output_put or the PL/SQL +block that saved it completes its execution. This means you __CAN NOT__ +use these functions to monitor long running PL/SQL procedures. + +Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + +Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + +## __dbms_output_enable ( [ buffer_size ] )__ + +This function calls DBMS_OUTPUT.ENABLE to enable calls to package +DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to +these procedures are ignored unless DBMS_OUTPUT.ENABLE is called +first. + +The buffer_size is the maximum amount of text that can be saved in the +buffer and must be between 2000 and 1,000,000. If buffer_size is not +given, the default is 20,000 bytes. + +## __dbms_output_put ( [ @lines ] )__ + +This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + +If all lines were saved successfully the function returns 1. Depending +on the context, an empty list or undef is returned for failure. + +If any line causes buffer_size to be exceeded, a buffer overflow error +is raised and the function call fails. Some of the text might be in +the buffer. + +## __dbms_output_get__ + +This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from +the buffer. + +In an array context, all complete lines are removed from the buffer and +returned as a list. If there are no complete lines, an empty list is +returned. + +In a scalar context, the first complete line is removed from the buffer +and returned. If there are no complete lines, undef is returned. + +Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or +DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, +DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + +## __reauthenticate ( $username, $password )__ + +Starts a new session against the current database using the credentials +supplied. + +## __private_attribute_info__ + + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + +Returns a hash of all private attributes used by DBD::Oracle, for either +a database or a statement handle. Currently, all the hash values are undef. + +# ATTRIBUTES COMMON TO ALL HANDLES + +## __InactiveDestroy__ (boolean) + +Implemented by DBI, no driver-specific impact. + +## __RaiseError__ (boolean, inherited) + +Forces errors to always raise an exception. Although it defaults to off, it is recommended that this +be turned on, as the alternative is to check the return value of every method (prepare, execute, fetch, etc.) +manually, which is easy to forget to do. + +## __PrintError__ (boolean, inherited) + +Forces database errors to also generate warnings, which can then be filtered with methods such as +locally redefining _$SIG{__WARN__}_ or using modules such as `CGI::Carp`. This attribute is on +by default. + +## __ShowErrorStatement__ (boolean, inherited) + +Appends information about the current statement to error messages. If placeholder information +is available, adds that as well. Defaults to true. + +## __Warn__ (boolean, inherited) + +Enables warnings. This is on by default, and should only be turned off in a local block +for a short a time only when absolutely needed. + +## __Executed__ (boolean, read-only) + +Indicates if a handle has been executed. For database handles, this value is true after the [do](#pod_do) method has been called, or +when one of the child statement handles has issued an [execute](#pod_execute). Issuing a [commit](#pod_commit) or [rollback](#pod_rollback) always resets the +attribute to false for database handles. For statement handles, any call to [execute](#pod_execute) or its variants will flip the value to +true for the lifetime of the statement handle. + +## __TraceLevel__ (integer, inherited) + +Sets the trace level, similar to the [trace](#pod_trace) method. See the sections on +[trace](#pod_trace) and [parse_trace_flag](#pod_parse_trace_flag) for more details. + +## __Active__ (boolean, read-only) + +Indicates if a handle is active or not. For database handles, this indicates if the database has +been disconnected or not. For statement handles, it indicates if all the data has been fetched yet +or not. Use of this attribute is not encouraged. + +## __Kids__ (integer, read-only) + +Returns the number of child processes created for each handle type. For a driver handle, indicates the number +of database handles created. For a database handle, indicates the number of statement handles created. For +statement handles, it always returns zero, because statement handles do not create kids. + +## __ActiveKids__ (integer, read-only) + +Same as `Kids`, but only returns those that are active. + +## __CachedKids__ (hash ref) + +Returns a hashref of handles. If called on a database handle, returns all statement handles created by use of the +`prepare_cached` method. If called on a driver handle, returns all database handles created by the [connect_cached](#pod_connect_cached) +method. + +## __ChildHandles__ (array ref) + +Implemented by DBI, no driver-specific impact. + +## __PrintWarn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleError__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleSetErr__ (code ref, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ErrCount__ (unsigned integer) + +Implemented by DBI, no driver-specific impact. + +## __FetchHashKeyName__ (string, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ChopBlanks__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Taint__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintIn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintOut__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Profile__ (inherited) + +Implemented by DBI, no driver-specific impact. + +## __Type__ (scalar) + +Returns `dr` for a driver handle, `db` for a database handle, and `st` for a statement handle. +Should be rarely needed. + +## __LongReadLen__ + +Implemented by DBI, no driver-specific impact. + +## __LongTruncOk__ + +Implemented by DBI, no driver-specific impact. + +## __CompatMode__ + +Type: boolean, inherited + +The CompatMode attribute is used by emulation layers (such as Oraperl) to enable compatible behaviour in the underlying driver (e.g., DBD::Oracle) for this handle. Not normally set by application code. + +It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. + +# ORACLE-SPECIFIC DATABASE HANDLE METHODS + +## __ora_can_unicode ( [ $refresh ] )__ + +Returns a number indicating whether either of the database character sets +is a Unicode encoding. Calls ora_nls_parameters() and passes the optional +$refresh parameter to it. + +0 = Neither character set is a Unicode encoding. + +1 = National character set is a Unicode encoding. + +2 = Database character set is a Unicode encoding. + +3 = Both character sets are Unicode encodings. + +## __ora_can_taf__ + +Returns true if the current connection supports TAF events. False if otherise. + +## __ora_nls_parameters ( [ $refresh ] )__ + +Returns a hash reference containing the current NLS parameters, as given +by the v$nls_parameters view. The values fetched are cached between calls. +To cause the latest values to be fetched, pass a true value to the function. + +# DATABASE HANDLE METHODS + +## __selectall_arrayref__ + + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectall_hashref__ + + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + +Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectcol_arrayref__ + + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the first column +from each rows returned by preparing and executing the SQL string. It is possible to specify exactly +which columns to return. See the DBI documentation for full details. + +## __prepare__ + + $sth = $dbh->prepare($statement, \%attr); + +Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. + +### __Prepare Attributes__ + +These attributes may be used in the `\%attr` parameter of the +L database handle method. + +- ora_placeholders + +Set to false to disable processing of placeholders. Used mainly for loading a +PL/SQL package that has been _wrapped_ with Oracle's `wrap` utility. + +- ora_auto_lob + +If true (the default), fetching retrieves the contents of the CLOB or +BLOB column in most circumstances. If false, fetching retrieves the +Oracle "LOB Locator" of the CLOB or BLOB value. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for more details. + +See also the LOB tests in 05dbi.t of Oracle::OCI for examples +of how to use LOB Locators. + +- ora_pers_lob + +If true the [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) method for the [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) will be +used for LOBs rather than the default method [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators). + +- ora_clbk_lob + +If true the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) method for the L will be used for LOBs. + +- ora_piece_lob + +If true the [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) method for the L will be used for LOBs. + +- ora_piece_size + +This is the max piece size for the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) +and [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) methods, in chars for CLOBS, and +bytes for BLOBS. + +- ora_check_sql + +If 1 (default), force SELECT statements to be described in prepare(). +If 0, allow SELECT statements to defer describe until execute(). + +See [Prepare Postponed Till Execute](#pod_Prepare Postponed Till Execute) for more information. + +- ora_exe_mode + +This will set the execute mode of the current statement. Presently +only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + +See [Scrollable Cursors](#pod_Scrollable Cursors) for more details. + +- ora_prefetch_rows + +Sets the number of rows to be prefetched. If it is not set, then the +default value is 1. See [Row Prefetching](#pod_Row Prefetching) for more details. + +- ora_prefetch_memory + +Sets the memory level for rows to be prefetched. The application then +fetches as many rows as will fit into that much memory. See L for more details. + +- ora_row_cache_off + +By default DBD::Oracle will use a row cache when fetching to cut down +the number of round trips to the server. If you do not want to use an +array fetch set this value to any value other than 0; + +See [Row Prefetching](#pod_Row Prefetching) for more details. + +### __Placeholders__ + +There are two types of placeholders that can be used in DBD::Oracle. The first is +the "question mark" type, in which each placeholder is represented by a single +question mark character. This is the method recommended by the DBI specs and is the most +portable. Each question mark is internally replaced by a "dollar sign number" in the order +in which they appear in the query (important when using [bind_param](#pod_bind_param)). + +The other placeholder type is "named parameters" in the format ":foo" which is the one Oralce prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + +The different types of placeholders cannot be mixed within a statement, but you may +use different ones for each statement handle you have. This is confusing at best, so +stick to one style within your program. + +## __prepare_cached__ + + $sth = $dbh->prepare_cached($statement, \%attr); + +Implemented by DBI, no driver-specific impact. This method is most useful +if the same query is used over and over as it will cut down round trips to the server. + +## __do__ + + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + +Prepare and execute a single statement. Returns the number of rows affected if the +query was successful, returns undef if an error occurred, and returns -1 if the +number of rows is unknown or not available. Note that this method will return __0E0__ instead +of 0 for 'no rows were affected', in order to always return a true value if no error occurred. + +## __last_insert_id__ + +Oracle does not implement auto_increment of serial type columns it uses predefined +sequences where the id numbers are either selected before insert, at insert time with a trigger, + or as part of the query. + +Below is an example of you to use the latter with the SQL returning clause to get the ID number back +on insert with the bind_param_inout method. +. + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + +## __commit__ + + $rv = $dbh->commit; + +Issues a COMMIT to the server, indicating that the current transaction is finished and that +all changes made will be visible to other processes. If AutoCommit is enabled, then +a warning is given and no COMMIT is issued. Returns true on success, false on error. + +## __rollback__ + + $rv = $dbh->rollback; + +Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit +is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and +false on error. + +## __begin_work__ + +This method turns on transactions until the next call to [commit](#pod_commit) or [rollback](#pod_rollback), if [AutoCommit](#pod_AutoCommit) is +currently enabled. If it is not enabled, calling begin_work will issue an error. Note that the +transaction will not actually begin until the first statement after begin_work is called. + +## __disconnect__ + + $rv = $dbh->disconnect; + +Disconnects from the Oracle database. Any uncommitted changes will be rolled back upon disconnection. It's +good policy to always explicitly call commit or rollback at some point before disconnecting, rather than +relying on the default rollback behavior. + +If the script exits before disconnect is called (or, more precisely, if the database handle is no longer +referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() +methods automatically. It is best to explicitly disconnect rather than rely on this behavior. + +## __ping__ + + $rv = $dbh->ping; + +This `ping` method is used to check the validity of a database handle. The value returned is +either 0, indicating that the connection is no longer valid, or 1, indicating the connection is valid. +This function does 1 round trip to the Oracle Server. + +## __get_info()__ + + $value = $dbh->get_info($info_type); + +DBD::Oracle supports `get_info()`, but (currently) only a few info types. + +## __table_info()__ + +DBD::Oracle supports attributes for `table_info()`. + +In Oracle, the concept of _user_ and _schema_ is (currently) the +same. Because database objects are owned by an user, the owner names +in the data dictionary views correspond to schema names. +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. + +Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + +TABLE_TYPE may contain a comma-separated list of table types. +The following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + +The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + +The special enumerations of catalogues, schemas and table types are +supported. However, TABLE_CAT is always NULL. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +`table_info()` performs a case-sensitive search. So, a selection +criterion should respect upper and lower case. +Normally, an identifier is case-insensitive. Oracle stores and +returns it in upper case. Sometimes, database objects are created +with quoted identifiers (for reserved words, mixed case, special +characters, ...). Such an identifier is case-sensitive (if not all +upper case). Oracle stores and returns it as given. +`table_info()` has no special quote handling, neither adds nor +removes quotes. + +## __primary_key_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary key constraint was created without an identifier, +PK_NAME contains a system generated name with the form SYS_Cn. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __foreign_key_info()__ + +This method (currently) supports the extended behaviour of SQL/CLI, i.e. the +result set contains foreign keys that refer to primary __and__ alternate keys. +The field UNIQUE_OR_PRIMARY distinguishes these keys. + +Oracle does not support catalogues, so `$pk_catalog` and `$fk_catalog` are +ignored as selection criteria (in the new style interface). +The UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always +NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary or foreign key constraints were created without an identifier, +UK_NAME or FK_NAME contains a system generated name with the form SYS_Cn. + +The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle (currently) +does not support other actions. + +The DELETE_RULE field may contain wrong values. This is a known Bug (#1271663) +in Oracle's data dictionary views. Currently (as of 8.1.7), 'RESTRICT' and +'SET DEFAULT' are not supported, 'CASCADE' is mapped correctly and all other +actions (incl. 'SET NULL') appear as 'NO ACTION'. + +The DEFERABILITY field is always NULL, because this columns is +not present in the ALL_CONSTRAINTS view of older Oracle releases. + +The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, +FK_TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __column_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + +Don't rely on the values of the BUFFER_LENGTH field! +Especially the length of FLOATs may be wrong. + +Datatype codes for non-standard types are subject to change. + +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +It is possible with Oracle to make the names of the various DB objects (table,column,index etc) +case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + +So in the example the exact case "Bla_BLA" must be used to get it info on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + +any case can be used to get info on the column. + +## __selectrow_array__ + + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + +Returns an array of row information after preparing and executing the provided SQL string. The rows are returned +by calling [fetchrow_array](#pod_fetchrow_array). The string can also be a statement handle generated by a previous prepare. Note that +only the first row of data is returned. If called in a scalar context, only the first column of the first row is +returned. Because this is not portable, it is not recommended that you use this method in that way. + +## __selectrow_arrayref__ + + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an array, by internal use of +the [fetchrow_arrayref](#pod_fetchrow_arrayref) method. + +## __selectrow_hashref__ + + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an hash, by internal use of +the [fetchrow_hashref](#pod_fetchrow_hashref) method. + +## __clone__ + + $other_dbh = $dbh->clone(); + +Creates a copy of the database handle by connecting with the same parameters as the original +handle, then trying to merge the attributes. See the DBI documentation for complete usage. + +# DATABASE HANDLE ATTRIBUTES + +## __AutoCommit__ (boolean) + +Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change +in the future, so it is highly recommended that you explicitly set it when +calling [connect](#pod_connect). + +## __ReadOnly__ (boolean) + + $dbh->{ReadOnly} = 1; + +Specifies if the current database connection should be in read-only mode or not. + +Please not that this method is not foolproof: there are still ways to update the +database. Consider this a safety net to catch applications that should not be +issuing commands such as INSERT, UPDATE, or DELETE. + +This method method requires DBI version 1.55 or better. + +## __Name__ (string, read-only) + +Returns the name of the current database. This is the same as the DSN, without the +"dbi:Oracle:" part. + +## __Username__ (string, read-only) + +Returns the name of the user connected to the database. + +## __Driver__ (handle, read-only) + +Holds the handle of the parent driver. The only recommended use for this is to find the name +of the driver using: + + $dbh->{Driver}->{Name} + +## __RowCacheSize__ + +DBD::Oracle supports both Server pre-fetch and Client side row caching. By default both +are turned on to give optimum performance. Most of the time one can just let DBD::Oracle +figure out the best optimization. + +### __Row Caching__ + +Row caching occurs on the client side and the object of it is to cut down the number of round +trips made to the server when fetching rows. At each fetch a set number of rows will be retrieved +from the server and stored locally. Further calls the server are made only when the end of the +local buffer(cache) is reached. + +Rows up to the specified top level row +count `RowCacheSize` are fetched if it occupies no more than the specified memory usage limit. +The default value is 0, which means that memory size is not included in computing the number of rows to prefetch. If +the `RowCacheSize` value is set to a negative number then the positive value of RowCacheSize is used +to compute the number of rows to prefetch. + +By default `RowCacheSize` is automatically set. If you want to totally turn off prefetching set this to 1. + +For any SQL statement that contains a LOB, Long or Object Type Row Caching will be turned off. However server side +caching still works. If you are only selecting a LOB Locator then Row Caching will still work. + +### Row Prefetching + +Row prefetching occurs on the server side and uses the DBI database handle attribute `RowCacheSize` and or the +Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improved performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. + +The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first +fetch that sets the current_positon to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are +loaded into the buffer and DBD::Oracle will not have to go back to the server for more rows. When record 11 is fetched DBD::Oracle +fetches and returns this row and the next 9 rows are loaded into the buffer. In this case if you fetch backwards from 10 to 1 +no server round trips are made. + +With large record sets it is best not to attempt to go to the last record as this may take some time, A large buffer size might even slow down +the fetch. If you must get the number of rows in a large record set you might try using an few large OCI_FETCH_ABSOLUTEs and then an OCI_FETCH_LAST, +this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. +If one requires only the first few rows there is no need to set a large prefetch value. + +If the ora_prefetch_memory less than 1 or not present then memory size is not included in computing the +number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it +is not included in the computing of the prefetch rows. + +# ORACLE-SPECIFIC STATEMENT HANDLE METHODS + +## __ora_stmt_type__ + +Returns the OCI Statement Type number for the SQL of a statement handle. + +## __ora_stmt_type_name__ + +Returns the OCI Statement Type name for the SQL of a statement handle. + +# DBI STATEMENT HANDLE OBJECT METHODS + +## __bind_param__ + + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + +Allows the user to bind a value and/or a data type to a placeholder. + +The value of `$param_num` is a number if using the '?' or if using ":foo" style placeholders, the complete name +(e.g. ":foo") must be given. +The `$bind_value` argument is fairly self-explanatory. A value of `undef` will +bind a `NULL` to the placeholder. Using `undef` is useful when you want +to change just the type and will be overwriting the value later. +(Any value is actually usable, but `undef` is easy and efficient). + +The `\%attr` hash is used to indicate the data type of the placeholder. +The default value is "varchar". If you need something else, you must +use one of the values provided by DBI or by DBD::Pg. To use a SQL value, +modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + +This will import some constants into your script. You can plug those +directly into the [bind_param](#pod_bind_param) call. Some common ones that you will +encounter are: + + SQL_INTEGER + +To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + +You can then set the data types by setting the value of the `ora_type` +key in the hash passed to [bind_param](#pod_bind_param). +The current list of Oracle data types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +Data types are "sticky," in that once a data type is set to a certain placeholder, +it will remain for that placeholder, unless it is explicitly set to something +else afterwards. If the statement has already been prepared, and you switch the +data type to something else, DBD::Oracle will re-prepare the statement for you before +doing the next execute. + +Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + +These attributes may be used in the `\%attr` parameter of the +L or L statement handle methods. + +- ora_type + +Specify the placeholder's datatype using an Oracle datatype. +A fatal error is raised if `ora_type` and the DBI `TYPE` attribute +are used for the same placeholder. +Some of these types are not supported by the current version of +DBD::Oracle and will cause a fatal error if used. +Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + +Potentially useful values when DBD::Oracle was built using OCI 7 and later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + +Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + +Additional values when DBD::Oracle was built using OCI 9.2 and later: + + SQLT_CHR, SQLT_BIN + +See [Binding Cursors](#pod_Binding Cursors) for the correct way to use ORA_RSET. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for how to use ORA_CLOB and ORA_BLOB. + +See [SYS.DBMS_SQL datatypes](#pod_SYS.DBMS_SQL datatypes) for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. + +See [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) for the correct way to use SQLT_CHR and SQLT_BIN. + +See [Other Data Types](#pod_Other Data Types) for more information. + +See also L. + +- ora_csform + +Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values +are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can +be imported from the DBD::Oracle module. Rarely needed. + +- ora_csid + +Specify the _integer_ OCI_ATTR_CHARSET_ID for the bind value. +Character set names can't be used currently. + +- ora_maxdata_size + +Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. +May be needed if a character set conversion from client to server +causes the data to use more space and so fail with a truncation error. + +- ora_maxarray_numentries + +Specify the maximum number of array entries to allocate. Used with +ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of +array entries Oracle can pass back to you in OUT variable of type +TABLE OF ... . + +- ora_internal_type + +Specify internal data representation. Currently is supported only for +ORA_NUMBER_TABLE. + +### Optimizing Results + +#### Prepare Postponed Till Execute + +The DBD::Oracle module can avoid an explicit 'describe' operation +prior to the execution of the statement unless the application requests +information about the results (such as $sth->{NAME}). This reduces +communication with the server and increases performance (reducing the +number of PARSE_CALLS inside the server). + +However, it also means that SQL errors are not detected until +`execute()` (or $sth->{NAME} etc) is called instead of when +`prepare()` is called. Note that if the describe is triggered by the +use of $sth->{NAME} or a similar attribute and the describe fails then +_an exception is thrown_ even if `RaiseError` is false! + +Set [ora_check_sql](#pod_ora_check_sql) to 0 in prepare() to enable this behaviour. + +## __bind_param_inout__ + + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + +DBD::Oracle fully supports bind_param_inout below are some uses for this method. + +### __Returning A Value from an INSERT__ + +Oracle supports an extended SQL insert syntax which will return one +or more of the values inserted. This can be particularly useful for +single-pass insertion of values with re-used sequence values +(avoiding a separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + +If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + +If you have many rows to insert you can take advantage of Oracle's built in execute array feature +with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + +Which will return all the ids into @out_values. + +- __Note:__ + +- This will only work for numbered (?) placeholders, + +- The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle + +- The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + +### Returning A Recordset + +DBD::Oracle does not currently support binding a PL/SQL table (aka array) +as an IN OUT parameter to any Perl data structure. You cannot therefore call +a PL/SQL function or procedure from DBI that uses a non-atomic datatype as +either a parameter, or a return value. However, if you are using Oracle 9.0.1 +or later, you can make use of table (or pipelined) functions. + +For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + +Currently, there is no way to directly call the function +Array_Example.Array_Func from DBI. However, by making the following relatively +painless additions, its not only possible, but extremely efficient. + +First, you need to create database object types that correspond to the record +and table types in the package. From the above example, these would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + +Now, assuming the existing function needs to remain unchanged (it is probably +being called from other PL/SQL code), we need to add a new function to the +package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + +As you can see, the new function is very simple. Now, it is a simple matter +of calling the function as a straight-forward SELECT from your DBI code. From +the above example, the code would look something like this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + +### __SYS.DBMS_SQL datatypes__ + +DBD::Oracle has built-in support for __SYS.DBMS_SQL.VARCHAR2_TABLE__ +and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +- __Note:__ + +- Take careful note that we use '\\@arr' here because the 'bind_param_inout' + will only take a reference to a scalar. + +### __ORA_VARCHAR2_TABLE__ + +SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. +( in bind_param() and bind_param_inout() ). When you bind array, you need +to specify full buffer size for OUT data. So, there are two parameters: +_max_len_ (specified as 3rd argument of bind_param_inout() ), +and _ora_maxarray_numentries_. They define maximum array entry length and +maximum rows, that can be passed to Oracle and back to you. In this +example we send array with 1 element with length=3, but allocate space for 100 +Oracle array entries with maximum length 10 of each. So, you can get no more +than 100 array entries with length <= 10. + +If you set _max_len_ to zero, maximum array entry length is calculated +as maximum length of entry of array bound. If 0 < _max_len_ < length( $some_element ), +truncation occur. + +If you set _ora_maxarray_numentries_ to zero, current (at bind time) bound +array length is used as maximum. If 0 < _ora_maxarray_numentries_ < scalar(@array), +not all array entries are bound. + +### __ORA_NUMBER_TABLE__ + +SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. +The main difference is internal data representation. Currently 2 types of +bind is allowed : as C-integer, or as C-double type. To select one of them, +you may specify additional bind parameter _ora_internal_type_ as either +__SQLT_INT__ or __SQLT_FLT__ for C-integer and C-double types. +Integer size is architecture-specific and is usually 32 or 64 bit. +Double is standard IEEE 754 type. + +_ora_internal_type_ defaults to double (SQLT_FLT). + +_max_len_ is ignored for OCI_NUMBER_TABLE. + +Currently, you cannot bind full native Oracle NUMBER(38). If you really need, +send request to dbi-dev list. + +The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + +If you change bind type to __SQLT_INT__, like: + + ora_internal_type => SQLT_INT + +you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + +## __bind_param_inout_array__ + +DBD::Oracle supports this undocumented feature of DBI. See [Returning A Value from an INSERT](#pod_Returning A Value from an INSERT) for an example. + +## __bind_param_array__ + + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + +Binds an array of values to a placeholder, so that each is used in turn by a call +to the [execute_array](#pod_execute_array) method. + +## __execute__ + + $rv = $sth->execute(@bind_values); + +Perform whatever processing is necessary to execute the prepared statement. + +## __execute_array__ + + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + +Execute a prepared statement once for each item in a passed-in hashref, or items that +were previously bound via the [bind_param_array](#pod_bind_param_array) method. See the DBI documentation +for more details. + +DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very +quickly. + +## __execute_for_fetch__ + + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + +Used internally by the [execute_array](#pod_execute_array) method, and rarely used directly. See the +DBI documentation for more details. + +## __fetchrow_arrayref__ + + $ary_ref = $sth->fetchrow_arrayref; + +Fetches the next row of data from the statement handle, and returns a reference to an array +holding the column values. Any columns that are NULL are returned as undef within the array. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +Note that the same array reference is returned for each fetch, so don't store the reference and +then use it after a later fetch. Also, the elements of the array are also reused for each row, +so take care if you want to take a reference to an element. See also [bind_columns](#pod_bind_columns). + +## __fetchrow_array__ + + @ary = $sth->fetchrow_array; + +Similar to the [fetchrow_arrayref](#pod_fetchrow_arrayref) method, but returns a list of column information rather than +a reference to a list. Do not use this in a scalar context. + +## __fetchrow_hashref__ + + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + +Fetches the next row of data and returns a hashref containing the name of the columns as the keys +and the data itself as the values. Any NULL value is returned as as undef value. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +The optional `$name` argument should be either `NAME`, `NAME_lc` or `NAME_uc`, and indicates +what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. + +## __fetchall_arrayref__ + + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + +Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the +statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, +the data read in so far will be returned. Because of this, you should always check `$sth->err` after +calling this method, unless [RaiseError](#pod_RaiseError) has been enabled. + +If `$slice` is an array reference, fetchall_arrayref uses the [fetchrow_arrayref](#pod_fetchrow_arrayref) method to fetch each +row as an array ref. If the `$slice` array is not empty then it is used as a slice to select individual +columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). + +With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. + +If `$slice` is a hash reference, fetchall_arrayref uses [fetchrow_hashref](#pod_fetchrow_hashref) to fetch each row as a hash reference. + +See the DBI documentation for a complete discussion. + +## __fetchall_hashref__ + + $hash_ref = $sth->fetchall_hashref( $key_field ); + +Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for +a full discussion. + +## __finish__ + + $rv = $sth->finish; + +Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed +when you have not fetched all the possible rows. + +## __rows__ + + $rv = $sth->rows; + +Returns the number of rows affected for updates, deletes and inserts and -1 for selects. + +## __bind_col__ + + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + +Binds a Perl variable and/or some attributes to an output column of a SELECT statement. +Column numbers count up from 1. You do not need to bind output columns in order to fetch data. + +NOTE: DBD::Oracle does not use the `$bind_type` to determine how to +bind the column; it uses what Oracle says the data type is. You can +however set a numeric bind type with the bind attributes +StrictlyTyped/DiscardString as these attributes are applied after the +column is retrieved. + +See the DBI documentation for a discussion of the optional parameters `\%attr` and `$bind_type` + +## __bind_columns__ + + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + +Calls the [bind_col](#pod_bind_col) method for each column in the SELECT statement, using the supplied list. + +## __dump_results__ + + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + +Fetches all the rows from the statement handle, calls `DBI::neat_list` for each row, and +prints the results to `$fh` (which defaults to `STDOUT`). Rows are separated by `$lsep` (which defaults +to a newline). Columns are separated by `$fsep` (which defaults to a comma). The `$maxlen` controls +how wide the output can be, and defaults to 35. + +This method is designed as a handy utility for prototyping and testing queries. Since it uses +"neat_list" to format and edit the string for reading by humans, it is not recommended +for data transfer applications. + +# STATEMENT HANDLE ATTRIBUTES + +## __NUM_OF_FIELDS__ (integer, read-only) + +Returns the number of columns returned by the current statement. A number will only be returned for +SELECT statements for INSERT, +UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NUM_OF_PARAMS__ (integer, read-only) + +Returns the number of placeholders in the current statement. + +## __NAME__ (arrayref, read-only) + +Returns an arrayref of column names for the current statement. This +method will only work for SELECT statements, for SHOW statements, and for +INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NAME_lc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to lower case. + +## __NAME_uc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to upper case. + +## __NAME_hash__ (hashref, read-only) + +Similar to the `NAME` attribute, but returns a hashref of column names instead of an arrayref. The names of the columns +are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. +This method returns undef if called before `execute()`. + +## __NAME_lc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __NAME_uc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __TYPE__ (arrayref, read-only) + +Returns an arrayref indicating the data type for each column in the statement. +This method returns undef if called before `execute()`. + +## __PRECISION__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. +The number indicates the precision for `NUMERIC` columns, the size in number of +characters for `CHAR` and `VARCHAR` columns, and for all other types of columns +it returns the number of _bytes_. +This method returns undef if called before `execute()`. + +## __SCALE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates the scale of the that column. The only type that will return a value is `NUMERIC`. +This method returns undef if called before `execute()`. + +## __NULLABLE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates if the column is nullable or not. 0 = not nullable, 1 = nullable, 2 = unknown. +This method returns undef if called before `execute()`. + +## __Database__ (dbh, read-only) + +Returns the database handle this statement handle was created from. + +## __ParamValues__ (hash ref, read-only) + +Returns a reference to a hash containing the values currently bound to placeholders. If the "named parameters" +type of placeholders are being used (such as ":foo"), then the keys of the hash will be the names of the +placeholders (without the colon). If the "dollar sign numbers" type of placeholders are being used, the keys of the hash will +be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, +starting at one and increasing for every placeholder. + +If this method is called before [execute](#pod_execute), the literal values passed in are returned. If called after +[execute](#pod_execute), then the quoted versions of the values are returned. + +## __ParamTypes__ (hash ref, read-only) + +Returns a reference to a hash containing the type names currently bound to placeholders. The keys +are the same as returned by the ParamValues method. The values are hashrefs containing a single key value +pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can +only be expressed by a Postgres type. The value is the internal number corresponding to the type originally +passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of +ParamTypes to be passed back to the [bind_param](#pod_bind_param) method. + +## __Statement__ (string, read-only) + +Returns the statement string passed to the most recent "prepare" method called in this database handle, even if that method +failed. This is especially useful where "RaiseError" is enabled and the exception handler checks $@ and sees that a `prepare` +method call failed. + +## __RowsInCache__ + +Returns the number of un-fetched rows in the cache for selects. + +# SCROLLABLE CURSORS + +Oracle supports the concept of a 'Scrollable Cursor' which is defined as a 'Result Set' where +the rows can be fetched either sequentially or non-sequentially. One can fetch rows forward, +backwards, from any given position or the n-th row from the current position in the result set. + +Rows are numbered sequentially starting at one and client-side caching of the partial or entire result set +can improve performance by limiting round trips to the server. + +Oracle does not support DML type operations with scrollable cursors so you are limited +to simple 'Select' operations only. As well you can not use this functionality with remote +mapped queries or if the LONG datatype is part of the select list. + +However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch methods. + +Only use scrollable cursors if you really have a good reason to. They do use up considerable +more server and client resources and have poorer response times than non-scrolling cursors. + +## Enabling Scrollable Cursors + +To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + +Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the +statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + +When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row +or you can still use any of the other fetch methods but with a poorer response time than if you used a +non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. + +## Scrollable Cursor Methods + +The following driver-specific methods are used with scrollable cursors. + +- ora_scroll_position + + $position = $sth->ora_scroll_position(); + +This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time +this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. +The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. + +- ora_fetch_scroll + + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + +Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset +value which will then determine the row that will be fetched. It returns the row as a list containing the field values. +Null fields are returned as _undef_ values in the list. + +The valid orientation constant and fetch offset values combination are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + +The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + +The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + +## Scrollable Cursor Usage + +Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + +and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll +method; + +- Fetching the Last Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +if the record set is large this could take some time. + +- Fetching the Current Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will still be 20 after this snippet. + +- Fetching the First Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the Next Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 5 after this snippet. + +- Fetching the Prior Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the 10th Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 10th to 14th Row + + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 14 after this snippet. + +- Fetching the 14th to 10th Row + + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 5th Row From the Present Position. + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 15 after this snippet. + +- Fetching the 9th Row Prior From the Present Position + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 6 after this snippet. + +- Use Finish + + $sth->finish(); + +When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of +cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. + +# LOBS AND LONGS + +The key to working with LOBs (CLOB, BLOBs) is to remember the value of an Oracle LOB column is not the content of the LOB. It's a +'LOB Locator' which, after being selected or inserted needs extra processing to read or write the content of the LOB. There are also legacy LONG types (LONG, LONG RAW, VARCHAR2) +which are presently deprecated by Oracle but are still in use. These LONG types do not utilize a 'LOB Locator' and also are more limited in +functionality than CLOB or BLOB fields. + +DBD::Oracle now offers three interfaces to LOB and LONG data, + +- [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) + +With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of +BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. + +- [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) + +With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. + +- [LOB Locator Method Interface](#pod_LOB Locator Method Interface) + +This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. + +Generally speaking the interface that you will chose will be dependent on what end you are trying to achieve. All have their benefits and +drawbacks. + +One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB column can be in one of three states; + +- NULL + +The table cell is created, but the cell holds no locator or value. +If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + +error when working with a LOB. + +You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + +- Empty + +A LOB instance with a locator exists in the cell, but it has no value. The length of the LOB is zero. In this case DBD::Oracle will return 'undef' for the field. + +- Populated + +A LOB instance with a locator and a value exists in the cell. You actually get the LOB value. + +## Data Interface for Persistent LOBs + +This is the original interface for LONG and LONG RAW datatypes and from Oracle 9iR1 and later the OCI API was extended to work directly with the other LOB datatypes. +In other words you can treat all LOB type data (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using the same techniques +you would use on other datatypes that store character or binary data. In some cases there are fewer round trips to the server as no 'LOB Locators' are +used, normally one can get an entire LOB is a single round trip. + +### Simple Fetch for LONGs and LONG RAWs + +As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG datatypes as a single large piece. +There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. +If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into +an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. + +For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the long1 fields but they will be truncated at 2MBs. + +### Using ora_ncs_buff_mtpl + +When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the +Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. +Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. + +However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer +value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes +but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes +(maybe less characters though) but you are using allot more memory that you need. + +You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can +also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. + +The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the +ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. + +If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + +This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) + +If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. + +This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. + +You can tune this value by setting ora_oci_success_warn which will display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + +In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. + +### Simple Fetch for CLOBs and BLOBs + +To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well +set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds +the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. + +For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this +and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. + +It seems with BLOBs you are not limited by the 64k. + +For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the lobs but they will be truncated at 2MBs. + +### Piecewise Fetch with Callback + +With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. +To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Simple Fetch for LONGs and LONG RAWs](#pod_Simple Fetch for LONGs and LONG RAWs) and [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is +dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. + +Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +#### Piecewise Fetch with Polling + +With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' +attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback). + +Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. + +Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +### Binding for Updates and Inserts for CLOBs and BLOBs + +To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method +'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + +So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. + +### Support for Remote LOBs; + +Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + +to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Below are the limitations of Remote LOBs; + +- Queries involving more than one database are not supported; + +so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + +as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + +- DDL commands are not supported; + +so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + +- Only binds and defines for data going into remote persistent LOBs are supported. + +so that parameter passing in PL/SQL where CHAR data is bound or defined for remote LOBs is not allowed . + +These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + +- If the remote object is a view such as + + CREATE VIEW v AS SELECT foo() FROM ... + +the following would not work: + + SELECT * FROM v@dbs2; + +- Limited PL/SQL parameter passing + +PL/SQL parameter passing is not allowed where the actual argument is a LOB type +and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. + +- RETURNING INTO does not support implicit conversions between CHAR and CLOB. + +so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + +## Locator Data Interface + +### Simple Usage + +When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob with the LongReadLen and LongTruncOk attributes. +The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +When inserting or updating LOBs some _major_ magic has to be performed +behind the scenes to make it transparent. Basically the driver has to +insert a 'LOB Locator' and then refetch the newly inserted LOB +Locator before being able to write the data into it. However, it works +well most of the time, and I've made it as fast as possible, just one +extra server-round-trip per insert or update after the first. For the +time being, only single-row LOB updates are supported. + +To insert or update a large LOB using a placeholder, DBD::Oracle has to +know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + +The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + +or use the corresponding integer values (112 and 113). + +One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has +to be able to tell which parameters relate to which table fields. +In all cases where it can possibly work it out for itself, it does, +however, if there are multiple LOB fields of the same type in the table +then you need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + +There are some limitations inherent in the way DBD::Oracle makes typical +LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + +The alternative is to disable the automatic LOB Locator processing. +If [ora_auto_lob](#pod_ora_auto_lob) is 0 in prepare(), you can fetch the LOB Locators and +do all the work yourself using the ora_lob_*() methods. +See the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) section below. + +### LOB support in PL/SQL + +LOB Locators can be passed to PL/SQL calls by binding them to placeholders +with the proper `ora_type`. If [ora_auto_lob](#pod_ora_auto_lob) is true, output LOB +parameters will be automatically returned as strings. + +If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), +strings can be bound to input LOB placeholders and will be automatically +converted to LOBs. + +Example: + # Build a large XML document, bind it as a CLOB, + # extract elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + +If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + +error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. +One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. + +## Persistent & Locator Interface Caveats + +Now that one has the option of using the Persistent or the Locator interface for LOBs the questions arises +which one to use. For starters, if you want to access LOBs over a dblink you will have to use the Persistent +interface so that choice is simple. The question of which one to use after that is a little more tricky. +It basically boils down to a choice between LOB size and speed. + +The Callback and Polling piecewise fetches are very very slow +when compared to the Simple and the Locator fetches but they can handle very large blocks of data. Given a situation where a +large LOB is to be read the Locator fetch may time out while either of the piecewise fetches may not. + +With the Simple fetch you are limited by physical memory of your server but it runs a little faster than the Locator, as there are fewer round trips +to the server. So if you have small LOBs and need to save a little bandwidth this is the one to use. It you are going after large LOBs then the Locator interface is the one to use. + +If you need to update more than a single row of with LOB data then the Persistent interface can do it while the Locator can't. + +If you encounter a situation where you have to access the legacy LOBs (LONG, LONG RAW) and the values are to large for you system then you can use +the Callback or Polling piecewise fetches to get all of the data. + +Not all of the Persistent interface has been implemented yet, the following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + +Most of the time you should just use the [Locator Data Interface](#pod_Locator Data Interface) as this is in one that has the best combination of speed and size. + +All this being said if you are doing some critical programming I would use the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) as this gives you very +fine grain control of your LOBs, of course the code for this will be somewhat more involved. + +## Data Interface for LOB Locators + +The following driver-specific methods let you manipulate "LOB Locators" directly. +To select a LOB locator directly set the if the `ora_auto_lob` +attribute to false, or alternatively they can be returned via PL/SQL procedure calls. + +(If using a DBI version earlier than 1.36 they must be called via the +func() method. Note that methods called via func() don't honour +RaiseError etc, and so it's important to check $dbh->err after each call. +It's recommended that you upgrade to DBI 1.38 or later.) + +Note that LOB locators are only valid while the statement handle that +created them is valid. When all references to the original statement +handle are lost, the handle is destroyed and the locators are freed. + +- ora_lob_read + + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + +Read a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobRead function. + +- ora_lob_write + + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + +Write/overwrite a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobWrite function. + +- ora_lob_append + + $rc = $dbh->ora_lob_append($lob_locator, $data); + +Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + +- ora_lob_trim + + $rc = $dbh->ora_lob_trim($lob_locator, $length); + +Trims the length of the LOB to $length. +Uses the Oracle OCILobTrim function. + +- ora_lob_length + + $length = $dbh->ora_lob_length($lob_locator); + +Returns the length of the LOB. +Uses the Oracle OCILobGetLength function. + +- ora_lob_is_init + + $is_init = $dbh->ora_lob_is_init($lob_locator); + +Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' +if there is an error. +Uses the Oracle OCILobLocatorIsInit function. + +- ora_lob_chunk_size + + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + +Returns the chunk size of the LOB. +Uses the Oracle OCILobGetChunkSize function. + +For optimal performance, Oracle recommends reading from and +writing to a LOB in batches using a multiple of the LOB chunk size. +In Oracle 10g and before, when all defaults are in place, this +chunk size defaults to 8k (8192). + +### LOB Locator Method Examples + +_Note:_ Make sure you first read the note in the section above about +multi-byte character set issues with these methods. + +The following examples demonstrate the usage of LOB Locators +to read, write, and append data, and to query the size of +large data. + +The following examples assume a table containing two large +object columns, one binary and one character, with a primary +key column, defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + +It also assumes a sequence for use in generating unique +lob_id field values, defined as follows: + + CREATE SEQUENCE lob_example_seq + +### Example: Inserting a new row with large data + +Unless enough memory is available to store and bind the +entire LOB data for insert all at once, the LOB columns must +be written interactively, piece by piece. In the case of a new row, +this is performed by first inserting a row, with empty values in +the LOB columns, then modifying the row by writing the large data +interactively to the LOB columns using their LOB locators as handles. + +The insert statement must create token values in the LOB +columns. Here, we use the empty string for both the binary +and character large object columns 'bindata' and 'chardata'. + +After the INSERT statement, a SELECT statement is used to +acquire LOB locators to the 'bindata' and 'chardata' fields +of the newly inserted row. Because these LOB locators are +subsequently written, they must be acquired from a select +statement containing the clause 'FOR UPDATE' (LOB locators +are only valid within the transaction that fetched them, so +can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + +In this example we demonstrate the use of ora_lob_write() +interactively to append data to the columns 'bin_data' and +'char_data'. Had we used ora_lob_append(), we could have +saved ourselves the trouble of keeping track of the offset +into the lobs. The snippet of code beneath the comment +'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + +The scalar variables $offset and $length are no longer +needed, because ora_lob_append() keeps track of the offset +for us. + +### Example: Updating an existing row with large data + +In this example, we demonstrate a technique for overwriting +a portion of a blob field with new binary data. The blob +data before and after the section overwritten remains +unchanged. Hence, this technique could be used for updating +fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + +After running this code, the row where lob_id = 5 will +contain, starting at position 100234 in the bin_data column, +the string "This string will overwrite a portion of the blob". + +### Example: Streaming character data from the database + +In this example, we demonstrate a technique for streaming +data from the database to a file handle, in this case +STDOUT. This allows more data to be read in and written out +than could be stored in memory at a given time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + +Notice that the select statement does not contain the phrase +"FOR UPDATE". Because we are only reading from the LOB +Locator returned, and not modifying the LOB it refers to, +the select statement does not require the "FOR UPDATE" +clause. + +A word of caution when using the data returned from an ora_lob_read in a conditional statement. +for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + +was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return +the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte +as $data will contain 0 which PERL will see as false and not print it out. + +### Example: Truncating existing large data + +In this example, we truncate the data already present in a +large object column in the database. Specifically, for each +row in the table, we truncate the 'bindata' value to half +its previous length. + +After acquiring a LOB Locator for the column, we query its +length, then we trim the length by half. Because we modify +the large objects with the call to ora_lob_trim(), we must +select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +# SPACES AND PADDING + +## Trailing Spaces + +Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder +values and uses Nonpadded Comparison Semantics with the result. +This causes trouble if the spaces are needed for +comparison with a CHAR value or to prevent the value from +becoming '' which Oracle treats as NULL. +Look for Blank-padded Comparison Semantics and Nonpadded +Comparison Semantics in Oracle's SQL Reference or Server +SQL Reference for more details. + +To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, +either change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or the placeholder +type for a particular call to L or L +with [ora_type](#pod_ora_type) or `TYPE`. +Using [ORA_CHAR](http://search.cpan.org/perldoc?ORA_CHAR) with [ora_type](http://search.cpan.org/perldoc?ora_type) or `SQL_CHAR` with `TYPE` +allows the placeholder to be used with Padded Comparison Semantics +if the value it is being compared to is a CHAR, NCHAR, or literal. + +Please remember that using spaces as a value or at the end of +a value makes visually distinguishing values with different +numbers of spaces difficult and should be avoided. + +Oracle Clients that use OCI 9.2 do not strip trailing spaces. + +## Padded Char Fields + +Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. +As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will +have to change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or placeholder +type for a particular call with L or L +with [ORA_CHAR](#pod_ORA_CHAR). + +# UNICODE + +DBD::Oracle now supports Unicode UTF-8. There are, however, a number +of issues you should be aware of, so please read all this section +carefully. + +In this section we'll discuss "Perl and Unicode", then "Oracle and +Unicode", and finally "DBD::Oracle and Unicode". + +Information about Unicode in general can be found at: +[http://www.unicode.org/](http://www.unicode.org/). It is well worth reading because there are +many misconceptions about Unicode and you may be holding some of them. + +## Perl and Unicode + +Perl began implementing Unicode with version 5.6, but the implementation +did not mature until version 5.8 and later. If you plan to use Unicode +you are _strongly_ urged to use Perl 5.8.2 or later and to _carefully_ read +the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + +And then read it again. + +Perl's internal Unicode format is UTF-8 +which corresponds to the Oracle character set called AL32UTF8. + +## Oracle and Unicode + +Oracle supports many characters sets, including several different forms +of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + +When you create an Oracle database, you must specify the DATABASE +character set (used for DDL, DML and CHAR datatypes) and the NATIONAL +character set (used for NCHAR and NCLOB types). +The character sets used in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + +The Oracle 9.2 and later default for the national character set is AL16UTF16. +The default for the database character set is often US7ASCII. +Although many experienced DBAs will consider an 8bit character set like +WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle +other than US7ASCII, requires that the NLS_LANG environment variable be set. +See the L<"Oracle UTF8 is not UTF-8"> section below. + +You are strongly urged to read the Oracle Internationalization documentation +specifically with respect the choices and trade offs for creating +a databases for use with international character sets. + +Oracle uses the NLS_LANG environment variable to indicate what +character set is being used on the client. When fetching data Oracle +will convert from whatever the database character set is to the client +character set specified by NLS_LANG. Similarly, when sending data to +the database Oracle will convert from the character set specified by +NLS_LANG to the database character set. + +The NLS_NCHAR environment variable can be used to define a different +character set for 'national' (NCHAR) character types. + +Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. +For example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + +## Oracle UTF8 is not UTF-8 + +AL32UTF8 should be used in preference to UTF8 if it works for you, +which it should for Oracle 9.2 or later. If you're using an old +version of Oracle that doesn't support AL32UTF8 then you should +avoid using any Unicode characters that require surrogates, in other +words characters beyond the Unicode BMP (Basic Multilingual Plane). + +That's because the character set that Oracle calls "UTF8" doesn't +conform to the UTF-8 standard in its handling of surrogate characters. +Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". +Here are a couple of extracts from [http://www.unicode.org/reports/tr26/](http://www.unicode.org/reports/tr26/): + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + +Oracle uses this internally because it collates (sorts) in the same order +as UTF16, which is the basis of Oracle's internal collation definitions. + +Rather than change UTF8 for clients Oracle chose to define a new character +set called "AL32UTF8" which does conform to the UTF-8 standard. +(The AL32UTF8 character set can't be used on the server because it +would break collation.) + +Because of that, for the rest of this document we'll use "AL32UTF8". +If you're using an Oracle version below 9.2 you'll need to use "UTF8" +until you upgrade. + +## DBD::Oracle and Unicode + +DBD::Oracle Unicode support has been implemented for Oracle versions 9 +or greater, and Perl version 5.6 or greater (though we _strongly_ +suggest that you use Perl 5.8.2 or later). + +You can check which Oracle version your DBD::Oracle was built with by +importing the `ORA_OCI` constant from DBD::Oracle. + +__Fetching Data__ + +Any data returned from Oracle to DBD::Oracle in the AL32UTF8 +character set will be marked as UTF-8 to ensure correct handling by Perl. + +For Oracle to return data in the AL32UTF8 character set the +NLS_LANG or NLS_NCHAR environment variable _must_ be set as described +in the previous section. + +When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR +is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + +When fetching other character data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + +__Sending Data using Placeholders__ + +Data bound to a placeholder is assumed to be in the default client +character set (specified by NLS_LANG) except for a few special +cases. These are listed here with the highest precedence first: + +If the `ora_csid` attribute is given to bind_param() then that +is passed to Oracle and takes precedence. + +If the value is a Perl Unicode string (UTF-8) then DBD::Oracle +ensures that Oracle uses the Unicode character set, regardless of +the NLS_LANG and NLS_NCHAR settings. + +If the placeholder is for inserting an NCLOB then the client NLS_NCHAR +character set is used. (That's useful but inconsistent with the other behaviour +so may change. Best to be explicit by using the `ora_csform` +attribute.) + +If the `ora_csform` attribute is given to bind_param() then that +determines if the value should be assumed to be in the default +(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + +or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + +Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to +insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert +will still happen but a error code of 0 will be returned with the following warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + +The warning will report the parameter number and the NCHAR setting that the query is running. + +__Sending Data using SQL__ + +Oracle assumes the SQL statement is in the default client character +set (as specified by NLS_LANG). So Unicode strings containing +non-ASCII characters should not be used unless the default client +character set is AL32UTF8. + +## DBD::Oracle and Other Character Sets and Encodings + +The only multi-byte Oracle character set supported by DBD::Oracle is +"AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +# OBJECT & COLLECTION DATA TYPES + +Oracle databases allow for the creation of object oriented like user-defined types. +There are two types of objects, Embedded--an object stored in a column of a regular table +and REF--an object that uses the REF retrieval mechanism. + +DBD::Oracle supports only the 'selection' of embedded objects of the following types OBJECT, VARRAY +and TABLE in any combination. Support is seamless and recursive, meaning you +need only supply a simple SQL statement to get all the values in an embedded object. +You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. + +Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + +The code to access all the data in the table could be something like this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + +Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. + +As stated before DBD::Oracle will automatically drill into the embedded object and extract +all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an +SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + +The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + +Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + +The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + +So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables +nested to 10 levels. + +Any NULL values found in the embedded object will be returned as 'undef'. + +# OTHER DATA TYPES + +DBD::Oracle does not _explicitly_ support most Oracle datatypes. +It simply asks Oracle to return them as strings and Oracle does so. +Mostly. Similarly when binding placeholder values DBD::Oracle binds +them as strings and Oracle converts them to the appropriate type, +such as DATE, when used. + +Some of these automatic conversions to and from strings use NLS +settings to control the formatting for output and the parsing for +input. The most common example is the DATE type. The default NLS +format for DATE might be DD-MON-YYYY and so when a DATE type is +fetched that's how Oracle will format the date. NLS settings also +control the default parsing of strings into DATE values. An error +will be generated if the contents of the string don't match the +NLS format. If you're dealing in dates which don't match the default +NLS format then you can either change the default NLS format or, more +commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") +to explicitly specify formats for converting to and from strings. + +A slightly more subtle problem can occur with NUMBER types. The +default NLS settings might format numbers with a fullstop ("`.`") +to separate thousands and a comma ("`,`") as the decimal point. +Perl will generate warnings and use incorrect values when numbers, +returned and formatted as strings in this way by Oracle, are used +in a numeric context. You could explicitly convert each numeric +value using the TO_CHAR(...) function but that gets tedious very +quickly. The best fix is to change the NLS settings. That can be +done for an individual connection by doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + +There are some types, like BOOLEAN, that Oracle does not automatically +convert to or from strings (pity). These need to be converted +explicitly using SQL or PL/SQL functions. + +Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + +#### Support for Insert of XMLType (ORA_XMLTYPE) + +Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special +requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For +example with a table like this; + + create table books (book_id number, book_xml XMLType); + +one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + +In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. +This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. + +#### Binding Cursors + +Cursors can be returned from PL/SQL blocks, either from stored +functions (or procedures with OUT parameters) or +from direct `OPEN` statements, as shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +The only special requirement is the use of `bind_param_inout()` with an +attribute hash parameter that specifies `ora_type` as `ORA_RSET`. +If you don't do that you'll get an error from the `execute()` like: +"ORA-06550: line X, column Y: PLS-00306: wrong number or types of +arguments in call to ...". + +Here's an alternative form using a function that returns a cursor. +This example uses the pre-defined weak (or generic) REF CURSOR type +SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +A cursor obtained from PL/SQL as above may be passed back to PL/SQL +by binding for input, as shown in this example, which explicitly +closes a cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + +It is not normally necessary to close a cursor +explicitly in this way. Oracle will close the cursor automatically +at the first client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to +the cursor handle from the PL/SQL statement handle delays the destruction +of the cursor handle for too long. This reference remains until the +PL/SQL handle is re-bound, re-executed or destroyed. + +See the `curref.pl` script in the Oracle.ex directory in the DBD::Oracle +source distribution for a complete working example. + +#### Fetching Nested Cursors + +Oracle supports the use of select list expressions of type REF CURSOR. +These may be explicit cursor expressions - `CURSOR(SELECT ...)`, or +calls to PL/SQL functions which return REF CURSOR values. The values +of these expressions are known as nested cursors. + +The value returned to a Perl program when a nested cursor is fetched +is a statement handle. This statement handle is ready to be fetched from. +It should not (indeed, must not) be executed. + +Oracle imposes a restriction on the order of fetching when nested +cursors are used. Suppose `$sth1` is a handle for a select statement +involving nested cursors, and `$sth2` is a nested cursor handle fetched +from `$sth1`. `$sth2` can only be fetched from while `$sth1` is +still active, and the row containing `$sth2` is still current in `$sth1`. +Any attempt to fetch another row from `$sth1` renders all nested cursor +handles previously fetched from `$sth1` defunct. + +Fetching from such a defunct handle results in an error with the message +`ERROR nested cursor is defunct (parent row is no longer current)`. + +This means that the `fetchall...` or `selectall...` methods are not useful +for queries returning nested cursors. By the time such a method returns, +all the nested cursor handles it has fetched will be defunct. + +It is necessary to use an explicit fetch loop, and to do all the +fetching of nested cursors within the loop, as the following example +shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + +The cursor returned by the function `sp_ListEmp` defined in the +previous section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + +#### Pre-fetching Nested Cursors + +By default, DBD::Oracle pre-fetches rows in order to reduce the number of +round trips to the server. For queries which do not involve nested cursors, +the number of pre-fetched rows is controlled by the DBI database handle +attribute `RowCacheSize` (q.v.). + +In Oracle, server side open cursors are a controlled resource, limited in +number, on a per session basis, to the value of the initialization +parameter `OPEN_CURSORS`. Nested cursors count towards this limit. +Each nested cursor in the current row counts 1, as does +each nested cursor in a pre-fetched row. Defunct nested cursors do not count. + +An Oracle specific database handle attribute, `ora_max_nested_cursors`, +further controls pre-fetching for queries involving nested cursors. For +each statement handle, the total number of nested cursors in pre-fetched +rows is limited to the value of this parameter. The default value +is 0, which disables pre-fetching for queries involving nested cursors. + +# PL/SQL Examples + +Most of these PL/SQL examples come from: Eric Bartley . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + +You can find more examples in the t/plsql.t file in the DBD::Oracle +source directory. + +Oracle 9.2 appears to have a bug where a variable bound +with bind_param_inout() that isn't assigned to by the executed +PL/SQL block may contain garbage. +See [http://www.mail-archive.com/dbi-users@perl.org/msg18835.html](http://www.mail-archive.com/dbi-users@perl.org/msg18835.html) + +## Avoid Using "SQL Call" + +Avoid using the "SQL Call" statement with DBD:Oracle as you might find that +DBD::Oracle will not raise an exception in some case. Specifically if you use +"SQL Call" to run a procedure all "No data found" exceptions will be quietly +ignored and returned as null. According to Oracle support this is part of the same +mechanism where; + + select (select * from dual where 0=1) from dual + +returns a null value rather than an exception. + +# CONTRIBUTING + +If you'd like DBD::Oracle to do something new or different the best way +to make that happen is to do it yourself and email to dbi-dev@perl.org a +patch of the source code (using 'diff' - see below) that shows the changes. + +## How to create a patch using Subversion + +The DBD::Oracle source code is maintained using Subversion (a replacement +for CVS, see [http://subversion.tigris.org/](http://subversion.tigris.org/)). To access the source +you'll need to install a Subversion client. Then, to get the source +code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + +If it prompts for a username and password use your perl.org account +if you have one, else just 'guest' and 'guest'. The source code will +be in a new subdirectory called `trunk`. + +To keep informed about changes to the source you can send an empty email +to dbd-oracle-changes-subscribe@perl.org after which you'll get an email with the +change log message and diff of each change checked-in to the source. + +After making your changes you can generate a patch file, but before +you do, make sure your source is still upto date using: + + svn update + +If you get any conflicts reported you'll need to fix them first. +Then generate the patch file from within the `trunk` directory using: + + svn diff > foo.patch + +Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. + +## How to create a patch without Subversion + +Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + +Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + +Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you want. + +Test your changes and then remove all temporary files: + + make test && make distclean + +Go back to the directory you originally unpacked the distribution: + + cd .. + +Unpack _another_ copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + +Then create a patch file by performing a recursive `diff` on the two +top level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + +## Speak before you patch + +For anything non-trivial or possibly controversial it's a good idea +to discuss (on dbi-dev@perl.org) the changes you propose before +actually spending time working on them. Otherwise you run the risk +of them being rejected because they don't fit into some larger plans +you may not be aware of. + +## GitHub repository + +A git mirror of the subversion is also available at +`https://github.com/yanick/DBD-Oracle`. + +# Oracle Related Links + +# WHICH VERSION OF DBD::ORACLE IS FOR ME? + +From version 1.25 onwards DBD::Oracle only support Oracle clients +9.2 or greater. Support for ProC connections was dropped in 1.29. + +If you are still stuck with an older version of Oracle or its client you might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + +As there are dozens of different versions of Oracle's clients this +list does not include all of them, just the major released versions of +Oracle. + +Note that one can still connect to any Oracle version with the older +DBD::Oracle versions the only problem you will have is that some of +the newer OCI and Oracle features available in later DBD::Oracle +releases will not be available to you. + +So to make a short story a little longer: + +- 1 + +If you are using Oracle 7 or early 8 DB and you can manage to get a 9 client and you can use +any DBD::Oracle version. + +- 2 + +If you have to use an Oracle 7 client then DBD::Oracle 1.17 should work + +- 3 + +Same thing for 8 up to R2, use 1.17, if you are lucky and have the right patch-set you might +go with 1.18. + +- 4 + +For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. Again this depends on your +patch-set, If you run into trouble go with 1.19 + +- 5 + +After 9.2 you can use any version you want. + +- 6 + +It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go back to 7 +and even get to 10. I am not sure what the 11g client can connect to. + +# BUGS AND LIMITATIONS + +There is a known problem with the 11.2g Oracle client and the +`DBMS_LOB.GETLENGTH()` PL/SQL function. +See [https://rt.cpan.org/Public/Bug/Display.html?id=69350](https://rt.cpan.org/Public/Bug/Display.html?id=69350) for the details. + +# SEE ALSO + +- [DBI](http://search.cpan.org/perldoc?DBI) + +http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in +the DBD::Oracle source distribution including the examples in the +Oracle.ex directory + +- DBD::Oracle Tutorial + +http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-oracle.html + +- Oracle Instant Client + +http://www.oracle.com/technology/tech/oci/instantclient/index.html + +- Oracle on Linux + +http://www.ixora.com.au/ + +- Free Oracle Tools and Links + +ora_explain supplied and installed with DBD::Oracle. + +http://www.orafaq.com/ + +http://vonnieda.org/oracletool/ + +- Commercial Oracle Tools and Links + +Assorted tools and references for general information. +No recommendation implied. + +http://www.platinum.com + +http://www.SoftTreeTech.com + +Also PL/Vision from RevealNet and Steven Feuerstein, and +"Q" from Savant Corporation. + +# AUTHORS + +DBI by Tim Bunce [http://www.tim.bunce.name](http://www.tim.bunce.name). + +The original `DBD::Oracle` was by Tim Bunce. +Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the +auspice of the Pythian Group ([http://www.pythian.com](http://www.pythian.com)). + +# ACKNOWLEDGEMENTS + +A great many people have helped with DBD::Oracle over the 17 years +between 1994 and 2011. Far too many to name, but we thank them all. +Many are named in the Changes file. + +# COPYRIGHT + +The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. +The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The Pythian Group). Canada. +The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. + +The DBD::Oracle module is free open source software; you can +redistribute it and/or modify it under the same terms as Perl 5. + +# AUTHORS + +- * + +Tim Bunce + +- * + +John Scoles + +- * + +Yanick Champoux + +# COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/dist.ini b/dist.ini deleted file mode 100644 index 013f79fc..00000000 --- a/dist.ini +++ /dev/null @@ -1,22 +0,0 @@ -name = DBD-Oracle -author = Tim Bunce -author = John Scoles -author = Yanick Champoux -license = Perl_5 -copyright_holder = Tim Bunce -copyright_year = 1994 - -version = 1.38 - -[Authority] -authority=cpan:PYTHIAN - -[MakeMaker::Custom] - -[@Filter] --bundle=@YANICK --remove=Author::YANICK::NextSemanticVersion --remove=ModuleBuild --remove=Authority --remove=Signature - diff --git a/err_bind/err_bind_param_inout_overrun_bug.msg b/err_bind/err_bind_param_inout_overrun_bug.msg deleted file mode 100644 index 83d9001f..00000000 --- a/err_bind/err_bind_param_inout_overrun_bug.msg +++ /dev/null @@ -1,108 +0,0 @@ -From dbi-users-return-215-Tim.Bunce=ig.co.uk@perl.org Mon Feb 5 23:03:29 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id XAA01289; Mon, 5 Feb 2001 23:03:27 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <06769-16@oink>; Fri, 6 Feb 1970 00:01:15 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 981413584:20:24069:0; Mon, 05 Feb 2001 22:53:04 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-2.mail.demon.net - id aa2024004; 5 Feb 2001 22:53 GMT -Received: (qmail 6267 invoked by uid 508); 5 Feb 2001 22:52:23 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6247 invoked from network); 5 Feb 2001 22:52:22 -0000 -Received: from seeme.dare.feddata.com (38.186.101.66) by tmtowtdi.perl.org - with SMTP; 5 Feb 2001 22:52:22 -0000 -Received: by seeme.dare.feddata.com; id OAA05466; - Mon, 5 Feb 2001 14:55:56 -0800 (PST) -Received: from ifyou.dare.feddata.com(38.186.101.111) by seeme.dare.feddata.com - via smap (4.1) id xma005448; Mon, 5 Feb 01 14:55:39 -0800 -Sender: oscar@dare.feddata.com -Message-ID: <3A7F2FB0.A1507582@pasadena.feddata.com> -Date: Mon, 05 Feb 2001 14:56:48 -0800 -From: Oscar DeMartino -Organization: Federal Data Corporation -X-Mailer: Mozilla 4.61 [en] (X11; U; SunOS 5.6 sun4u) -X-Accept-Language: en -MIME-Version: 1.0 -To: dbi-users@perl.org -Subject: Undetected error - Binding and Stored Procedures -Content-Type: multipart/alternative; - boundary="------------E1028F7A8304BE268EB8F67B" -Status: RO -Content-Length: 2042 -Lines: 66 - ---------------E1028F7A8304BE268EB8F67B -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -I am running Oracle 8.1.5 and am using many stored procedures. We -use returned cursors, and individual values. The problem is, when -a stored procedure is executed and the specified bound variable has not -be declared large enough to hold the returned value subsequent -bound variables do not get set and I cannot find any way to -automatically detect this. - -Example: - -The stored procedure takes 1-input value and returns three string -values. - -the stored procedure is prepared , so I get the statement handle. - -I bind the input variable, and then bind the three output variables (1, -2, & 3) -as 100 character strings. - -I then execute the statment handle. - -There do not appear to be any errors, after checking the returned value -(for the execute call), -and ->err and ->errstr are clean. - -variable 1 has the correct returned value. -BUT, output variable 2 & 3, have no value. - ------- -Executing the stored procedure using sqlplus (sql command line -interface) indicated: - -What really occured is that the returned output variables 1 & 3 were -under 100 characters long -output variable 2 was 120 characters long - ---------- - -I know I could make all output variables the max size allowed in the -database field -but this would seem to waste space in the perl code. Since the field in - -the database -is simply defined as a varchar2 with no size limitation (upto 32767). - ------ -Am I missing something about detecting that variables 2 & 3 did not get -stored correctly -by DBI::Oracle?? - - - --- -Oscar "Fred" DeMartino FFFFF DDDD CCC -320 N. Halstead Ave. Ste #160 F D D C C -Pasadena, CA 91107 FFF D D C -e-mail: Oscar.DeMartino@pasadena.feddata.com F D D C -Phone: (626)306-6649 F D D C C -Federal Data Corporation F DDDD CCC - - - ---------------E1028F7A8304BE268EB8F67B-- - diff --git a/err_bind/err_bindarrays.msg b/err_bind/err_bindarrays.msg deleted file mode 100644 index 8ca7a5d3..00000000 --- a/err_bind/err_bindarrays.msg +++ /dev/null @@ -1,241 +0,0 @@ -From cturner@redhat.com Tue Mar 27 06:01:56 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id GAA19714; Tue, 27 Mar 2001 06:01:56 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <13771-3@oink>; - Fri, 27 Mar 1970 06:00:50 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985668014:20:27605:3; Tue, 27 Mar 2001 04:40:14 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ab2125244; 27 Mar 2001 4:39 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id XAA32289 - for ; Mon, 26 Mar 2001 23:39:38 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2R4bvT12929; Mon, 26 Mar 2001 23:37:57 -0500 -Sender: cturner@redhat.com -To: Tim.Bunce@ig.co.uk -Subject: DBD::Oracle and OCI bound arrays -From: Chip Turner -Date: 26 Mar 2001 23:37:57 -0500 -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 980 -Lines: 29 - - -Hey Tim, - -The need to have true OCI bound arrays for DBD::Oracle has come up, -and it looks like I get the fun job of implementing them. Basically, -this will allow DBD::Oracle to do something the DCOracle python -library does. The idea is: - -my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -my @c1 = 'aa' .. 'zz'; -my @c2 = 'aaa' .. 'azz'; -$sth->execute(\@c1, \@c2); - -In other words, it populates the table with a single execute call, -passing two (or more) equally sized arrays in as references for bound -parameters. This has the potential to save a good amount of time, -especially for large datasets. - -This would pretty much be a proprietary extension for Oracle, though -similar uses could be done in other DBD's. - -Just thought I'd let you know what I was intending to do, and to see -if you had any interest in receiving it as a patch after I'm done. - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Tue Mar 27 09:29:48 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id JAA20809; Tue, 27 Mar 2001 09:29:42 +0100 (BST) -Date: Tue, 27 Mar 2001 09:29:41 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim.Bunce@ig.co.uk, dbi-dev@perl.org -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010327092941.D20616@ig.co.uk> -References: -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Mon, Mar 26, 2001 at 11:37:57PM -0500 -Content-Length: 1570 -Lines: 39 - -On Mon, Mar 26, 2001 at 11:37:57PM -0500, Chip Turner wrote: -> -> Hey Tim, -> -> The need to have true OCI bound arrays for DBD::Oracle has come up, -> and it looks like I get the fun job of implementing them. Basically, -> this will allow DBD::Oracle to do something the DCOracle python -> library does. The idea is: -> -> my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -> my @c1 = 'aa' .. 'zz'; -> my @c2 = 'aaa' .. 'azz'; -> $sth->execute(\@c1, \@c2); -> -> In other words, it populates the table with a single execute call, -> passing two (or more) equally sized arrays in as references for bound -> parameters. This has the potential to save a good amount of time, -> especially for large datasets. -> -> This would pretty much be a proprietary extension for Oracle, though -> similar uses could be done in other DBD's. -> -> Just thought I'd let you know what I was intending to do, and to see -> if you had any interest in receiving it as a patch after I'm done. - -I would *urge* you to discuss the implementation with me *before* -you get very far cutting code. - -And anyway, I think someone's already done much or all of the work. -Dig around in the dbi-dev archives. If you can't find the discussion -let me know. If you do, then ask them (via the dbi-dev list) what -the status is. - -I'm planning to make a DBI release next week and, hopefully, a -DBD::Oracle release the week after to cleare a backlog of patches I -have queued up. After that I'll be looking to add in the work of the -other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -Tim. - -From cturner@redhat.com Wed Mar 28 02:01:21 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id CAA27336; Wed, 28 Mar 2001 02:01:21 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <17151-9@oink>; - Sat, 28 Mar 1970 01:59:47 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985739868:20:27318:0; Wed, 28 Mar 2001 00:37:48 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ac2119835; 28 Mar 2001 0:37 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id TAA10445 - for ; Tue, 27 Mar 2001 19:37:35 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2S0ZoJ20115; Tue, 27 Mar 2001 19:35:50 -0500 -Sender: cturner@redhat.com -To: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -References: <20010327092941.D20616@ig.co.uk> -From: Chip Turner -Date: 27 Mar 2001 19:35:50 -0500 -In-Reply-To: <20010327092941.D20616@ig.co.uk> -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 1495 -Lines: 35 - -Tim Bunce writes: - -> I would *urge* you to discuss the implementation with me *before* -> you get very far cutting code. - -Unfortunately, it's a little late for this; I've mostly finished the -change (at least, enough for our needs), except for some review and -cleanups. It seems to work quite well (400 times faster than repeated -looping over a dataset) and passes all of DBD::Oracle's test suite. - -> And anyway, I think someone's already done much or all of the work. -> Dig around in the dbi-dev archives. If you can't find the discussion -> let me know. If you do, then ask them (via the dbi-dev list) what -> the status is. - -I checked as you suggest, but couldn't find any code, just discussion -of it. I'll check again, but it didn't seem that the person had put -it anywhere I could get at it. - -> I'm planning to make a DBI release next week and, hopefully, a -> DBD::Oracle release the week after to cleare a backlog of patches I -> have queued up. After that I'll be looking to add in the work of the -> other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -If you would like, the patch will probably be suitable for inclusion -by then, if you want it in by the next release. Should there be any -problems with it or its implementation, I'd be glad to clean it up if -you have interest in it (if not, that's cool too; we need it soon, -though, either way). - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Wed Mar 28 11:51:58 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id LAA00444; Wed, 28 Mar 2001 11:51:51 +0100 (BST) -Date: Wed, 28 Mar 2001 11:51:51 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010328115151.D29769@ig.co.uk> -References: <20010327092941.D20616@ig.co.uk> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Tue, Mar 27, 2001 at 07:35:50PM -0500 -Content-Length: 1786 -Lines: 40 - -On Tue, Mar 27, 2001 at 07:35:50PM -0500, Chip Turner wrote: -> Tim Bunce writes: -> -> > I would *urge* you to discuss the implementation with me *before* -> > you get very far cutting code. -> -> Unfortunately, it's a little late for this; I've mostly finished the -> change (at least, enough for our needs), except for some review and -> cleanups. It seems to work quite well (400 times faster than repeated -> looping over a dataset) and passes all of DBD::Oracle's test suite. - -I trust you've added some more tests for your new functionality! - -> > And anyway, I think someone's already done much or all of the work. -> > Dig around in the dbi-dev archives. If you can't find the discussion -> > let me know. If you do, then ask them (via the dbi-dev list) what -> > the status is. -> -> I checked as you suggest, but couldn't find any code, just discussion -> of it. I'll check again, but it didn't seem that the person had put -> it anywhere I could get at it. - -You could always ask them (CC me). - -> > I'm planning to make a DBI release next week and, hopefully, a -> > DBD::Oracle release the week after to cleare a backlog of patches I -> > have queued up. After that I'll be looking to add in the work of the -> > other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). -> -> If you would like, the patch will probably be suitable for inclusion -> by then, if you want it in by the next release. Should there be any -> problems with it or its implementation, I'd be glad to clean it up if -> you have interest in it (if not, that's cool too; we need it soon, -> though, either way). - -Thanks for the clean-up offer. Send it to me after I make the next -DBD::Oracle release (as a fresh patch over that version please - but -there shouldn't be too many changes). - -Tim. - diff --git a/err_bind/err_bindclobleak.msg b/err_bind/err_bindclobleak.msg deleted file mode 100644 index 1a31c760..00000000 --- a/err_bind/err_bindclobleak.msg +++ /dev/null @@ -1,58 +0,0 @@ -From PGWeiss@arity.com Thu Mar 9 09:51:45 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id JAA14948; Thu, 9 Mar 2000 09:51:43 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <27566-0@oink>; Mon, 9 Mar 1970 10:51:10 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 952595299:20:10439:68; Thu, 09 Mar 2000 09:48:19 GMT -Received: from image.arity.com ([140.239.104.130]) by punt-2.mail.demon.net - id aa2010598; 9 Mar 2000 9:47 GMT -Received: by image.arity.com with Internet Mail Service (5.5.2650.21) - id ; Thu, 9 Mar 2000 04:51:44 -0500 -Message-ID: -From: "Paul G. Weiss" -To: Perl-Win32-Database Mailing List , - "'Tim Bunce'" -Subject: Another CLOB related DBD::Oracle bug -Date: Thu, 9 Mar 2000 04:51:41 -0500 -MIME-Version: 1.0 -X-Mailer: Internet Mail Service (5.5.2650.21) -Content-Type: text/plain; charset="iso-8859-1" -Status: RO -Content-Length: 689 -Lines: 32 - -Binding a parameter to type ORA_CLOB causes a leak. -Consider: - -for (1..10000) -{ - for (1..100) - { - my $sth = $db->prepare('update item set descr = ? where id = ?'); - if ($leak) - { - $sth->bind_param(1, $descr, {ora_type => ORA_CLOB, -ora_field=>'DESCR'}); - $sth->bind_param(2, 12); - $sth->execute; - } - else - { - $sth->execute($descr,12); - } - } - sleep 1; -} - - -With $leak set to 1, i.e. binding the parameters explicitly the -program leaks. With $leak set to 0 it does not (but then I can't -set descr to anything greater than 4K nor can I set it to the -empty string). - -Is there a patch? - --P - diff --git a/err_bind/err_bindnullhash.msg b/err_bind/err_bindnullhash.msg deleted file mode 100644 index d9a98b9a..00000000 --- a/err_bind/err_bindnullhash.msg +++ /dev/null @@ -1,77 +0,0 @@ -From dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org Thu Jul 11 17:49:35 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g6BGnYH11008 - for ; Thu, 11 Jul 2002 17:49:34 +0100 (BST) - (envelope-from dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 11 Jul 2002 17:49:34 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1026401921:10:09249:41; Thu, 11 Jul 2002 15:38:41 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1124337; 11 Jul 2002 15:38 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id B567C2BF65 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 347792BF62 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Received: (qmail 95914 invoked by uid 1005); 11 Jul 2002 15:38:04 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 95896 invoked by uid 76); 11 Jul 2002 15:38:04 -0000 -Received: from ironmail1.cc.lehigh.edu (HELO ironmail1.cc.lehigh.edu) (128.180.39.26) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Thu Jul 11 15:38:04 2002 -0000 -Received: from ([128.180.39.20]) - by ironmail1.cc.lehigh.edu with ESMTP with TLS; - Thu, 11 Jul 2002 11:35:06 -0400 (EDT) -Received: from lawrencework (pc-lfn0.dept.Lehigh.EDU [128.180.52.51]) - by rain.CC.Lehigh.EDU (8.12.4/8.12.4) with SMTP id g6BFZ6rr022463 - for ; Thu, 11 Jul 2002 11:35:06 -0400 -Message-ID: <0a0401c228f0$93feda10$3334b480@lawrencework> -From: "Phil R Lawrence" -To: -References: <083b01c22824$70357340$3334b480@lawrencework> <20020711140937.A568@dansat.data-plan.com> -Subject: Re: error msg suggestion -Date: Thu, 11 Jul 2002 11:35:20 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2600.0000 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -X-Status: A -Content-Length: 636 -Lines: 21 - -Tim Bunce wrote: -> Binding an undef should work and be treated as a NULL. -> -> Probably a bug in your code or the driver. But you didn't -> say which driver. - -Hmmm. quite right, undefs do bind as NULL. However, in this case I am -binding $hash{non-existent-key}, which autoinstantiates to an undef, and looks -like this in the trace: - undef (magic-sg:y) - -Of course it was my dumb fault for having the wrong key for lookup, but -nonetheless, perhaps this should work the same as a normal undef. - -# $DBI::VERSION = "1.14"; -# $DBD::ODBC::VERSION = '0.28'; -$DSN = 'driver=Microsoft Access Driver (*.mdb);dbq=StudyManager.mdb'; - -Thanks, -Phil - - diff --git a/err_bind/err_trailingblank.msg b/err_bind/err_trailingblank.msg deleted file mode 100644 index cdf34a32..00000000 --- a/err_bind/err_trailingblank.msg +++ /dev/null @@ -1,345 +0,0 @@ -From dbi-users-bounce@isc.org Mon May 1 21:12:02 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id VAA16051; Mon, 1 May 2000 21:12:00 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <14295-42@oink>; Fri, 1 May 1970 21:06:08 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 957208278:10:19133:4; Mon, 01 May 2000 19:11:18 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1123094; 1 May 2000 19:11 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id B3CCF3FAA; - Mon, 1 May 2000 12:10:53 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Mon, 01 May 2000 12:05:42 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A70763E34 - for ; Mon, 1 May 2000 12:05:30 -0700 (PDT) -Received: from scotth.emsphone.com (scotth.emsphone.com [199.67.51.179]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA25897 - for ; - Mon, 1 May 2000 12:05:30 -0700 (PDT) env-from (shildret@scotth.emsphone.com) -Received: (from shildret@localhost) by scotth.emsphone.com (8.9.3/8.9.3) - id OAA50011 for dbi-users@isc.org; - Mon, 1 May 2000 14:05:48 -0500 (CDT) (envelope-from shildret) -Message-ID: -X-Mailer: XFMail 1.4.0 on FreeBSD -X-Priority: 3 (Normal) -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 8bit -MIME-Version: 1.0 -Resent-Date: Thu, 29 Jul 1999 22:07:08 +0100 -Resent-Message-Id: <19990729220708.G17723@ig.co.uk> -Resent-From: Tim Bunce -Resent-To: Tim Bunce -Date: Mon, 01 May 2000 14:05:48 -0500 (CDT) -Sender: shildret@scotth.emsphone.com -From: "Scott T. Hildreth" -To: "dbi-users@isc.org" -Subject: FW: Oracle & Trailing Blanks - possible change in DBD::Oracle -Resent-Sender: shildret@scotth.emsphone.com -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 3885 -Lines: 94 - - -Here is the help, I got regarding the trailing spaces. - ------FW: <19990729220708.G17723@ig.co.uk>----- - -Date: Thu, 29 Jul 1999 22:07:08 +0100 -From: Tim Bunce -To: Tim Bunce -Subject: Oracle & Trailing Blanks - possible change in DBD::Oracle -Cc: "Scott T. HIldreth" , - dbi-users@isc.org - - *** From dbi-users -- To unsubscribe, see the end of this message. *** - -On Thu, Jul 29, 1999 at 09:49:38PM +0100, Tim Bunce wrote: -> *** From dbi-users -- To unsubscribe, see the end of this message. *** -> -> On Thu, Jul 29, 1999 at 09:33:55AM -0500, Scott T. HIldreth wrote: -> > -> > Hi all, I wonder if someone can let me know if I got this right. -> > I have a key to match which can contain trailing blanks. The -> > field in the database is CHAR(18). If I match the key with -> > sqlplus, Oracle finds a match, with or without the trailing -> > blank. When I do an sth->execute( $key ), the key is not -> > found. I abstract the key with substr, so the trailing blank -> > is in the key, but no match is found. Do I need to place qoutes -> > around the value in $key? -> -> Somewhat hiddedn in the Oraperl.pm docs it says this: -> -> --- -> B Substitution variables are now bound as type 1 (VARCHAR2) -> and not type 5 (STRING) by default. This can alter the behaviour of -> SQL code which compares a char field with a substitution variable. -> See the String Comparison section in the Datatypes chapter of the -> Oracle OCI manual for more details. -> -> You can work around this by using DBD::Oracle's ability to specify -> the Oracle type to be used on a per field basis: -> -> $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) -> $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); -> $csr->bind_param(1, $value_x, $char_attrib); -> $csr->bind_param(2, $value_y, $char_attrib); -> ora_bind($csr); # bind with no parameters since we've done bind_param()'s -> --- -> -> Ignoring the Oraperl specifics there the key point is to use -> -> $csr->bind_param($idx, $value, { ora_type => 5 }); -> -> I'll add something to the DBD::Oracle docs. - -[You'll still need to blank-pad the string.] - -Looking at this issue again I've discovered that the key issue is that -type 1 strips trailing blanks whilst type 5 doesn't. - -I'rather m concerned by this. Since I'm against the DBI changing the -data in any way on principle and since Oraperl used to use type 5 -I'm strongly considering changing DBD::Oracle 'back' to using type 5. - -This would only affect anyone who relies on placeholders having -trailing blanks stripped off. (I'll provide a way to alter the -default with a single statement and/or env var for anyone affected). - -If that's you - speak up now! - -Tim. - ------------------------------------------------------------------------------- -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of -'unsubscribe'. ------------------------------------------------------------------------------- - - ---------------End of forwarded message------------------------- - ----------------------------------- -E-Mail: Scott T. Hildreth -Date: 01-May-00 -Time: 14:04:41 ----------------------------------- - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - -From joshua.horton@mail.tju.edu Fri May 23 07:43:09 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.6/8.12.6) with ESMTP id h4N6UY7T061880 - for ; Fri, 23 May 2003 07:43:09 +0100 (BST) - (envelope-from joshua.horton@mail.tju.edu) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 23 May 2003 07:43:09 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1053631164:10:02298:54; Thu, 22 May 2003 19:19:24 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116141; 22 May 2003 19:19 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id BD31E21C13C - for ; Thu, 22 May 2003 15:18:30 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail.tju.edu (fw-tr16.tju.edu [147.140.233.16]) - by dolly1.pobox.com (Postfix) with ESMTP id 615A521C06D - for ; Thu, 22 May 2003 15:18:22 -0400 (EDT) -Received: from PCSE447.tjh.tju.edu by mail.tju.edu for Tim.Bunce@pobox.com; Thu, 22 May 2003 15:17:54 -0400 -Message-Id: <031301c32096$de68f6f0$2310ae0a@PCSE447> -From: "Joshua Horton" -To: -Subject: Re: :Oracle and Oracle 9.2? -Date: Thu, 22 May 2003 15:18:03 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 5.50.4807.1700 -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 3511 -Lines: 99 - -Re: :Oracle and Oracle 9.2? - ----------------------------------------------------------------------------- ----- - - a.. From: Tim Bunce - b.. Subject: Re: :Oracle and Oracle 9.2? - c.. Date: Tue, 15 Apr 2003 07:36:55 -0700 - ----------------------------------------------------------------------------- ----- - -I'd appreciate it if other people with Oracle 9.2.x could let me -know if it passed or failed for them and what their exact oracle -version (four digits) and platform (operating system) is. - -Thanks. - -Tim. - -On Fri, Apr 04, 2003 at 01:48:36PM +0200, Smejkal Petr wrote: -> I have the same experience on Linux however on Windows all tests passes -(I'm not -> sure if it is related to different Oracle version - test of windows Perl -against -> Linux Oracle is OK). -> -> Linux Oracle: 9.2.0.2 -> Windows Oracle: 9.2.0.1 -> DBI: 1.35 -> DBD::Oracle: 1.14 -> -> -- Petr Smejkal -> -- Business Systems Analyst / Country IT Cz/Sk -> -- +420 284 059 639 -> -> > -----Original Message----- -> > From: Tom Malaher [mailto:[EMAIL PROTECTED] -> > Sent: Friday, April 04, 2003 1:35 AM -> > To: [EMAIL PROTECTED] -> > Subject: DBD::Oracle and Oracle 9.2? -> > -> > -> > My sysadmin is trying to install DBD::Oracle on a Solaris box running -> > Oracle 9.2. -> > -> > The ph_type.t test is failing with -> > -> > PERL_DL_NONLAZY=1 ./perl "-MExtUtils::Command::MM" "-e" -> > "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -> > t/base.......ok -> > t/cursor.....ok -> > t/general....ok -> > t/long.......ok -> > t/meta.......ok -> > t/ph_type....NOK 12 expected 'trailing' but got 'trailing ' -> > for VARCHAR2 -> > t/ph_type....FAILED test 12 -> > Failed 1/19 tests, 94.74% okay -> > t/plsql......ok -> > t/reauth.....skipped -> > all skipped: no reason given -> > t/select.....ok -> > Failed Test Stat Wstat Total Fail Failed List of Failed -> > -------------------------------------------------------------- -> > ----------------- -> > t/ph_type.t 19 1 5.26% 12 -> > 1 test skipped. -> > Failed 1/9 test scripts, 88.89% okay. 1/314 subtests failed, -> > 99.68% okay. -> > *** Error code 29 -> > make: Fatal error: Command failed for target `test_static' -> > -> > Is there a known problem with DBD::Oracle and Oracle 9.x? -> > Has Oracle changed the behavior of trailing spaces in VARCHAR2 fields? -> > -> > I've run the same test script on an oracle 8 installation -> > using DBD::Oracle 1.06 and DBI 1.14, and it works fine (no trailing -> > space is returned). -> > -> > Tom -> > -My config:HP-UX 11.11 (64-bit) on rp5470 2x733 5GB RAMOracle 9.2.0.2.0 -Enterprise Edition (64-bit)Perl 5.8.0 custom compiled with -./Configure -Duse64bitall -Ubincompat5005 -Duselargefiles -Dprefix=/opt/perl -5 ; all other options defaultDBI-1.32 all passed some skippedDBD-Oracle-1.14 -: PERL_DL_NONLAZY=1 /opt/perl5/bin/perl "-MExtUtils::Command::MM" -"-e" "test_harness(0, 'blib/lib', 'blib/arch')" -t/*.tt/base.......okt/cursor.....okt/general....okt/long.......okt/meta..... -..okt/ph_type....ok 11/19 expected 'trailing' but got 'trailing ' for -VARCHAR2t/ph_type....FAILED test 12 Failed 1/19 tests, 94.74% -okayt/plsql......okt/reauth.....skipped all skipped: no reason -givent/select.....okFailed Test Stat Wstat Total Fail Failed List of -Failed---------------------------------------------------------------------- --------------------------------------------------------t/ph_type.t -19 1 5.26% 121 test skipped.Failed 1/9 test scripts, 88.89% okay. -1/314 subtests failed, 99.68% okay.*** Error exit code 2Stop.Thanks,Josh -Horton - - -From nobody@fsck.com Tue Dec 30 14:33:50 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hBUEWNnP026077 - for ; Tue, 30 Dec 2003 14:33:50 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Dec 2003 14:33:50 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AbJwa-0003ua-H6; - Tue, 30 Dec 2003 13:29:56 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AbJwa-0003ua-H6 - for pobox@dbi.demon.co.uk; Tue, 30 Dec 2003 13:29:56 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 56DAD4C6 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3B3564C8 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 30 Dec 2003 08:29:54 -0500 (EST) -Received: (qmail 10988 invoked by uid 225); 30 Dec 2003 13:29:53 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 10984 invoked by alias); 30 Dec 2003 13:29:52 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 30 Dec 2003 05:29:41 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 8760D11153; Tue, 30 Dec 2003 08:29:37 -0500 (EST) -Subject: [cpan #4786] Oracle 9.2.0.0 fails a test in ph_types.t -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4786 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -To: "AdminCc of cpan Ticket #4786": ; -Date: Tue, 30 Dec 2003 08:29:37 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,SUPERLONG_LINE,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -Content-Length: 888 -Lines: 11 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -Assuming that ORA_OCI() gets set correctly when compiling against 9.2, the attached patch will work. I also tried this in SQL*Plus and was able to insert a trailing space into a VARCHAR2. (I replicated the test in ph_types.t). - -I did not test my patch as I installed DBD::Oracle 1.14 by setting the chops_spaces value in %test_info to 0. When I did that, everything installed fine. However, I didn't think that my solution was the best for the module, so I figured ORA_OCI should do the trick. - -I'm running Perl5.8.0 for Solaris2.9 going against the full Oracle build for 9.2. (I did not run into this issue, surprisingly, on Redhat9 running Perl 5.8.2, but I built against Oracle 9.1 there ...) - diff --git a/err_build/err_aix64.msg b/err_build/err_aix64.msg deleted file mode 100644 index f952e29e..00000000 --- a/err_build/err_aix64.msg +++ /dev/null @@ -1,142 +0,0 @@ -From SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com Fri Jan 7 16:11:33 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j07GAqfa044155 - for ; Fri, 7 Jan 2005 16:11:32 GMT - (envelope-from SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Fri, 07 Jan 2005 16:11:32 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CmvQB-0003Po-Kf; - Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CmvQB-0003Po-Kf - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CmvQA-0002zW-VM - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 49778102ACC; - Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 384E5FF808 - for ; Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Received-SPF: pass (boggle.pobox.com: domain of dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by boggle.pobox.com (Postfix) with SMTP id A74B8F4090 - for ; Fri, 7 Jan 2005 09:48:57 -0500 (EST) -Received: (qmail 2690 invoked by uid 514); 7 Jan 2005 14:48:56 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 2622 invoked from network); 7 Jan 2005 14:48:55 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 7 Jan 2005 14:48:55 -0000 -Received: (qmail 13078 invoked by uid 225); 7 Jan 2005 14:48:54 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 13048 invoked by alias); 7 Jan 2005 14:48:51 -0000 -X-Spam-Status: No, hits=-4.6 required=8.0 - tests=BAYES_00,HTML_MESSAGE,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: neutral (x1.develooper.com: local policy) -Received: from outmx020.isp.belgacom.be (HELO outmx020.isp.belgacom.be) (195.238.2.201) - by la.mx.develooper.com (qpsmtpd/0.28) with ESMTP; Fri, 07 Jan 2005 06:48:38 -0800 -Received: from outmx020.isp.belgacom.be (localhost [127.0.0.1]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmOgS020070 - for ; Fri, 7 Jan 2005 15:48:24 +0100 - (envelope-from ) -Received: from relaytwo.roularta.be (smtprelaytwo.roularta.be [194.78.177.23]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmMDA020034 - for ; Fri, 7 Jan 2005 15:48:22 +0100 - (envelope-from ) -Received: from rmgexch01.RMG.be ([89.0.35.150]) by roesfront3.RMG.be with Microsoft SMTPSVC(5.0.2195.6713); - Fri, 7 Jan 2005 15:47:50 +0100 -X-MimeOLE: Produced By Microsoft Exchange V6.5.7226.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----_=_NextPart_001_01C4F4C7.EE810087" -Subject: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Date: Fri, 7 Jan 2005 15:48:21 +0100 -Message-ID: -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Thread-Index: AcT0x+Y4G1R3vbX6Rh+QdPyNy/10eQ== -From: -To: -X-OriginalArrivalTime: 07 Jan 2005 14:47:50.0598 (UTC) FILETIME=[DC5D2E60:01C4F4C7] -Status: RO -Content-Length: 1678 -Lines: 62 - -------_=_NextPart_001_01C4F4C7.EE810087 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - -Hi,=20 -=20 -I finally succeeded in installing a 64bit build of Perl and its modules -for Oracle 64-bit. We were running in 32bit but integrating Proc and -cobols in our perl scripts only worked when we changed environments to -64bit causing problems for the oracle connections in perl. It's nothing -special, no editing of makefiles ... I can't believe I lost so much time -on this one ;) ( Now that I look back to my problems, they were probably -caused by using a wrong perl build for compiling the modules, Aix has -its default perl now under /bin.. stupid me )=20 -=20 -perl 5.8.6 64bit ----------------- -./Configure -de -Dcc=3Dgcc -Duse64bitall=20 -make -make test -make install -=20 -DBI 1.46 --------- -!!Make sure you are using the newly installed perl!! - check with perl -v it should show :=20 - This is perl, v5.8.6 built for aix-64all -perl Makefile.PL -make -make test -make install=20 -=20 -DBD-Oracle 1.16 ---------------- -!!Use correct perl like above mentioned!!=20 -export ORACLE_HOME=3D=20 -export LIBPATH=3D$ORACLE_HOME/lib -export LD_LIBRARY_PATH=3D$ORACLE_HOME/lib -=20 -perl Makefile.PL=20 -make -make test ( some test may still fail, I had 85% success on tests )=20 -make install=20 -=20 -Test -----=20 -=20 -test with :=20 - use DBI; - $dbh=3DDBI->connect("dbi:Oracle:","system","manager")|| die -$DBI::errstr; - $stmt=3D$dbh->prepare("select * from tab"); - $rc=3D$stmt->execute() || die $DBI::errstr; - while (my($record)=3D$stmt->fetchrow()) - { - print $record; - } -=20 -Happy 64-bit perling ;)=20 - -------_=_NextPart_001_01C4F4C7.EE810087-- - diff --git a/err_build/err_hpux_ld.msg b/err_build/err_hpux_ld.msg deleted file mode 100644 index 27f9cd07..00000000 --- a/err_build/err_hpux_ld.msg +++ /dev/null @@ -1,89 +0,0 @@ -From SRS0=JbZc=U3=lincolnbaxter.com=lab@bounce2.pobox.com Tue Jun 21 05:02:19 2005 -Return-Path: -X-Original-To: timbo@localhost -Delivered-To: timbo@localhost.data-plan.com -Received: from localhost (localhost [127.0.0.1]) - by timac.data-plan.com (Postfix) with ESMTP id B016F2A3D98 - for ; Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DkYXK-0003m5-Mr; - Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DkYXK-0003m5-Mr - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1DkYXJ-00006n-QE - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AF60172691; - Mon, 20 Jun 2005 22:29:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from ms-smtp-04-eri0.southeast.rr.com (ms-smtp-04-lbl.southeast.rr.com [24.25.9.103]) - by gold.pobox.com (Postfix) with ESMTP id A3C1E7272E - for ; Mon, 20 Jun 2005 22:29:11 -0400 (EDT) -Received: from lincolnbaxter.com (cpe-069-132-010-126.carolina.res.rr.com [69.132.10.126]) - by ms-smtp-04-eri0.southeast.rr.com (8.12.10/8.12.7) with ESMTP id j5L2TIL4001864 - for ; Mon, 20 Jun 2005 22:29:18 -0400 (EDT) -Received: (qmail 5171 invoked from network); 20 Jun 2005 22:29:07 -0400 -Received: from lws (192.168.0.25) - by lws with SMTP; 20 Jun 2005 22:29:07 -0400 -Subject: Re: gcc options when building DBD:Oracle -From: "Lincoln A. Baxter" -Reply-To: lab@lincolnbaxter.com -To: jriekenberg@everestkc.net -Cc: Tim Bunce -In-Reply-To: -References: -Content-Type: text/plain -Date: Mon, 20 Jun 2005 22:29:07 -0400 -Message-Id: <1119320947.17452.484.camel@lws> -Mime-Version: 1.0 -X-Mailer: Evolution 2.2.1.1 -Content-Transfer-Encoding: 7bit -X-Virus-Scanned: Symantec AntiVirus Scan Engine -Status: RO -Content-Length: 2011 -Lines: 38 - -Hi Jan, - -This looks like something that might be relatively easy to fix in -Makefile.PL. But I no longer have access to HPUX systems, and never -built DBD-Oracle with gcc on that platform. I could add your message to -the README.hpux file, but it is becoming less and less necessary to read -this file with newer versions of DBD-Oracle, in which Makefile.PL has -been made much smarter. - -Would you consider sending Tim or me a patch to Makefile.PL that -generates the right $(LD) command (only on HP rp8400, and only for your -version of gcc or later? - -Lincoln - -On Mon, 2005-06-20 at 15:36 -0500, jriekenberg@everestkc.net wrote: -> Lincoln, -> -> I recently built DBD:Oracle on an HP rp8400. Everything worked as expected until I actually issued the "make" command. Make proceeded as expected until it reached "MakeMaker dynamic_lib" section. The gcc line in that section failed with the error in the attached text file. Apparently gcc was not correctly passing the "+b" option to ld. Instead, it was attempting to interpret the option itself. It assumed the "+b" was a filename, and that failed because gcc could not find the file. I ended up adding the "-Xlinker" option before the "+b" and before the "$(LD_RUN_PATH)" in the line in Makefile. The line now looks like this: -> -> $(LD) -Xlinker +b -Xlinker "$(LD_RUN_PATH)" $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) -> -> Running "make" now works correctly. -> -> Also, "make test" returned the following error when attempting to build the various tests: -> -> /usr/lib/dld.sl: Can't shl_load() a library containing Thread Local Storage: /usr/lib/libcl.2 -> -> Setting LD_PRELOAD with "export LD_PRELOAD=/usr/lib/libcl.2" corrected this problem, and "make test" worked correctly. -> -> -> I didn't see DBD::Oracle documentation on exactly this, so I'm sending this to you. You may be aware of these items already. If so, please disregard this. -> -> Jon Riekenberg -> -> -> - - diff --git a/err_build/err_hpuxsuccess.msg b/err_build/err_hpuxsuccess.msg deleted file mode 100644 index c6edd79f..00000000 --- a/err_build/err_hpuxsuccess.msg +++ /dev/null @@ -1,279 +0,0 @@ -From dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org Tue Mar 23 17:00:25 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i2NGvAxX021862 - for ; Tue, 23 Mar 2004 17:00:23 GMT - (envelope-from dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 23 Mar 2004 17:00:23 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1B5oND-0000Ba-LH; - Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1B5oND-0000Ba-LH - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [208.210.124.70] (helo=majesty.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1B5oNC-00001d-92 - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:26 +0000 -Received: from majesty.pobox.com (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 18033954B4 - for ; Tue, 23 Mar 2004 11:03:24 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 3577D954BE - for ; Tue, 23 Mar 2004 11:03:21 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by majesty.pobox.com (Postfix) with SMTP - for ; Tue, 23 Mar 2004 11:02:41 -0500 (EST) -Received: (qmail 6527 invoked by uid 1005); 23 Mar 2004 16:02:21 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6510 invoked by uid 76); 23 Mar 2004 16:02:20 -0000 -Received: from x1.develooper.com (HELO x1.develooper.com) (63.251.223.170) - by onion.perl.org (qpsmtpd/0.27.1) with SMTP; Tue, 23 Mar 2004 08:02:20 -0800 -Received: (qmail 1985 invoked by uid 225); 23 Mar 2004 16:02:15 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 1893 invoked by alias); 23 Mar 2004 16:02:00 -0000 -X-Spam-Status: No, hits=0.0 required=7.0 - tests= -X-Spam-Check-By: la.mx.develooper.com -Received: from Unknown (HELO dundee.fpcc.net) (204.144.241.120) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Tue, 23 Mar 2004 08:01:44 -0800 -Received: from aberdeen.fpcc.net (aberdeen.fpcc.net [204.144.241.125]) - by dundee.fpcc.net (8.11.6/8.11.6) with ESMTP id i2NG1f111241; - Tue, 23 Mar 2004 09:01:41 -0700 -Received: from aberdeen.fpcc.net (localhost.localdomain [127.0.0.1]) - by aberdeen.fpcc.net (8.12.8/8.12.8) with ESMTP id i2NFrNOv024637; - Tue, 23 Mar 2004 08:53:23 -0700 -Received: (from laubster@localhost) - by aberdeen.fpcc.net (8.12.8/8.12.8/Submit) id i2NFrMOx024635; - Tue, 23 Mar 2004 08:53:22 -0700 -X-Authentication-Warning: aberdeen.fpcc.net: laubster set sender to dbiusers@laubster.org using -f -Date: Tue, 23 Mar 2004 08:53:22 -0700 -From: "J.D. Laub" -To: dbi-users@perl.org -Cc: lbaxter@fleetcc.com -Subject: SUCCESS: DBD::Oracle 1.15 on HP-UX 11.11 -Message-ID: <20040323155322.GA24576@aberdeen.fpcc.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -Organization: The Psychiatric Ward of Terrors -X-Virus-Checked: Checked -Status: RO -Content-Length: 9105 -Lines: 206 - -I've just had success building DBD::Oracle 1.15 on HP-UX 11.11 -(against both oracle 8.1.7 & oracle 9.2.0) & thought I'd share my -experience. - -Disclaimer: these instructions relate to our environment. It may be -that our sysadmins/dbas chose to configure/install things a certain -way (i.e., our install of $ORACLE_HOME/bin/sqlplus was *chosen* -to be 1.1/32), and/or that we're running old versions of software -(i.e., perhaps later releases of gcc don't ignore -mpa-risc-1-1). -In fact, there are probably some mistruths in here; rest assured -they're not intentional. :-) - -I'm unsure how (if?) I should go about getting this information into -the DBD::Oracle README.hpux. Lincoln, please contact me with any -thoughts you have. - - -### The summary ################################ - -Use the ansic compiler (~US$800/cpu). - -Shell variables I used: - PATH=/bin:$PATH # use 32bit ar & nm since using a 32bit cc - PERLDEST=/opt/perl_ora8 # or "perl_ora9" for an ora9 build - PATH=$PERLDEST/bin:$PATH # for build of DBI, pick up new perl - export LDLOADLIBS='+b : +s' # handy for ORACLE_SID connections to ora7 - unset PERLLIB # important to avoid outdated cruft - export ORACLE_USERID=scott/tiger # insecure - consider using "/" - ORACLE_SID=orcl - ORAENV_ASK=NO - . oraenv # sets LD_LIBRARY_PATH and SHLIB_PATH - -For ora8: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DAportable ' \ - -A prepend:ldflags='+z +DAportable ' - -For ora9: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DA2.0W ' \ - -A prepend:ldflags='+z +DA2.0W ' \ - -Dlibpth='/usr/lib/pa20_64 /usr/local/pa20_64/lib' - -After you use the above to install perl, DBI & DBD::Oracle will -build in the normal fashion. - - -### General Notes ################################ - -* During "make test", I received 1 failure (on -lib/ExtUtils/t/Constant) for ora8, and 3 failures (on -lib/ExtUtils/t/Constant, lib/ExtUtils/t/recurs, and t/op/write) for -ora9. Nevertheless, things seem mostly OK. - -* These are the various combinations possible for a given compiled -file on HP-UX 11.11 (the quoted description is what gets kicked out -by the "file" command): - - PA-RISC1.1/32bit ("PA-RISC1.1 relocatable object") - (I'll call this 1.1/32) - PA-RISC2.0/32bit ("PA-RISC2.0 relocatable object") - (I'll call this 2.0/32) - PA-RISC2.0/64bit ("ELF 64-bit MSB relocatable, PA-RISC 2.0 (LP64)") - (I'll call this 2.0/64) - -* "perl -v" lies about the RISC level: -$ file ./perl -./perl: PA-RISC1.1 shared executable dynamically linked -not stripped -$ ./perl -v | grep RISC -This is perl, v5.8.3 built for PA-RISC2.0 - -* If you'll be linking against 2.0/64 libraries, you'll have to -build all your object modules that way. I've not yet found a way -to link 32bit executables to 64bit libraries (and vice versa). Run -the "file" command on your Oracle libraries to find out which path -you'll have to take. - -* Two environment variables control where libraries are -searched. LD_LIBRARY_PATH and SHLIB_PATH (in that order) are -used for 64bit executables, while SHLIB_PATH is used for 32bit -executables. - -* I tried attempts using aCC as well as the default (free) cc that -comes with hpux; both avenues were too problematic to continue -pursuing. - -* The format of compiled objects is specified by compiler options. -According to the ansic compiler docs, the options are "+DAportable" -(for 1.1/32), "+DA2.0" (for 2.0/32), and "+DA2.0W" (for 2.0/64). -For gcc, the corresponding switches are -mpa-risc-1-1 (for 1.1/32) -and -mpa-risc-2-0 (for 2.0/64), but I've found that -mpa-risc-1-1 -is ineffective. (According to the "file" command, you *always* get -2.0/64.) - -* Our gcc displays the behavior described at -http://sources.redhat.com/ml/binutils/2002-10/msg00586.html and -http://aspn.activestate.com/ASPN/Mail/Message/perl5-porters/1641238 -, so is therefore unusable anytime '-lcl' is to be specified. -Unfortunately, that library is required for DBD::Oracle builds. -(The workaround of adding the 3 declarations does seem to work, -but littering those throughout perl's Configure, main.c, etc. -seems a big task.) Attempts to get gcc to use the hp ld instead -of the gnu ld (by specifying -mno-gnu-ld and -fno-gnu-linker) were -unsuccessful. The first html link shown above indicates you have -to rebuild gcc to use the hp linker, and that was not an incredibly -desirable path to pursue. - -* Our default PATH was set to put /usr/local/pa20_64/bin ahead of -/bin. This caused problems because (I think) the 64bit versions -of either ar (the archiver) or nm (the symbol lister) do not play -well with /bin/cc (the 32bit compiler). The tweak to put /bin at -the head of PATH, so we get the 32bit versions, takes care of the -problem. - -* I ran into an intermittent quirk during the build of perl in which -typing "make" (just after the Configure) did nothing. It turns out -that only dependencies were being written to "makefile", and that -removing "makefile" (so it could be automatically rebuilt) solved -the problem. - -* Most of my research on finding the right compiler/linker switches -was done with a "hello world" C program, trying the various -compilers and options, and trying to link it with the oracle -libraries. This proved to be a good choice, as trying to test -compilers/switches against the perl source distribution would have -proved quite difficult. - - -### DBD::Oracle specific ################################ - -* ora8 delivers its libraries in 2 formats: 1.1/32 (under -$ORACLE_HOME/lib) and 2.0/64 (under $ORACLE_HOME/lib64). ora7 -delivers only 1.1/32, while ora9 delivers only 2.0/64. It may seem -a bit inconsistent considering the ora8 setup, but ora9 libraries -are found under $ORACLE_HOME/lib and not $ORACLE_HOME/lib64. - -* Under ora8, oraenv incorrectly sets LD_LIBRARY_PATH to include -$ORACLE_HOME/lib instead of $ORACLE_HOME/lib64, so you've got to -make an override in oraenv_local if you want to use 2.0/64. It -doesn't harm anything, but oraenv unnecessarily sets LD_LIBRARY_PATH -for ora7 (a 64bit environment variable for a 32bit application). - -* If you use shared libraries AND you'll be upgrading Oracle, you -should expect you'll need to rebuild DBD::Oracle unless you'll keep -the old Oracle libraries available. - -* If you're building against ora8, the setting of LDLOADLIBS -is recommended so that when oraenv set SHLIB_PATH to the -$ORACLE_HOME/lib for ora7, the code will still find the ora8 -libraries. - -* We expect to need local (ORACLE_SID) connections for ora8 & -ora9. We could have gone with a single 2.0/64 perl coupled with -2 DBD::Oracle installs and PERLLIB twiddling in oraenv_local to -get to the right one. Instead, we chose to do 2 perl installs -(/opt/perl_ora8 and /opt/perl_ora9) because we can also connect -locally to ora7 by using the 1.1/32 ora8 version, something that -isn't possible with a 2.0/64 version. Also, we've some older 1.1/32 -machines into which we'd like to plop a tarball of the perl stuff, -so a 1.1/32 executable was desirable. - -* Some tests I ran were hinting that with 2.0/64, specifying "+b :" -on the build of DBD::Oracle correctly configured Oracle.sl as far as -the chatr program is concerned, but it seemed that LD_LIBRARY_PATH -*always* needed to be set correctly. (I.e., the embedded path in -the library seemed to be ignored.) I didn't pursue researching this -since there's no way to get the ora9 compiled code to connect to -ora8, meaning LD_LIBRARY_PATH had to be set correctly anyway. - -Testing local (ORACLE_SID) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora9 cannot connect to ora8 or ora7: "UNKNOWN - OCI STATUS 1804) OCIInitialize. Check ORACLE_HOME and NLS - settings etc." - -Testing remote (sqlnet) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 can connect to ora9 -builds against 2.0/64 ora9 can connect to ora8 -builds against 2.0/64 ora9 cannot connect to ora7: "OCI-21500: internal - error code" - - -### Versions ################################ - -perl: 5.8.3 -dbi: 1.41 -dbd-oracle: 1.15 -$ strings /bin/cc | grep Compiler -HP92453-01 B.11.11.08 HP C Compiler -$ strings /bin/ld | grep linker -$Revision: 92453-07 linker linker crt0.o B.11.16 000601 $ -@(#)92453-07 linker command s800.sgs ld PA64 B.11.18 REL 000922 -$ gcc -v -Reading specs from /usr/local/pa20_64/lib/gcc-lib/hppa64-hp-hpux11.11/3.3.1/specs -Configured with: ../src/configure --enable-languages=c,c++ --prefix=/usr/local/pa20_64 --with-local-prefix=/usr/local/pa20_64 --with-gnu-as --with-as=/usr/local/pa20_64/bin/as --with-gnu-ld --with-ld=/usr/local/pa20_64/bin/ld --disable-shared --disable-nls --host=hppa64-hp-hpux11.11 -Thread model: single -gcc version 3.3.1 - --- -J.D. Laub (Laubster) |"Your leg's too long / Your skull's too strong / -dbiusers@laubster.org| Suppose your nose is wrong." - Renaldo & the Loaf - diff --git a/err_build/err_instantclient.msg b/err_build/err_instantclient.msg deleted file mode 100644 index f0e549eb..00000000 --- a/err_build/err_instantclient.msg +++ /dev/null @@ -1,207 +0,0 @@ -From SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Feb 2 10:11:05 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j12AAUZ6055956 - for ; Wed, 2 Feb 2005 10:11:05 GMT - (envelope-from SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 02 Feb 2005 10:11:05 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwGaQ-0002Bn-H6; - Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwGaQ-0002Bn-H6 - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwGaP-00042G-Vb - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 9C3FB1E3946; - Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 879981E3958 - for ; Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Received-SPF: pass (kelvin.pobox.com: domain of dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by kelvin.pobox.com (Postfix) with SMTP id D0B001E3946 - for ; Wed, 2 Feb 2005 04:14:08 -0500 (EST) -Received: (qmail 7188 invoked by uid 514); 2 Feb 2005 09:14:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -List-Id: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 2531 invoked from network); 2 Feb 2005 04:10:16 -0000 -Delivered-To: dbi-users@perl.org -X-Spam-Status: No, hits=-2.6 required=8.0 - tests=BAYES_00,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: pass (x1.develooper.com: local policy) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgw.shina.sankyo.co.jp: iscan owned process doing -bs -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: Making DBD::Oracle with Instant Client 10.1.0.3 -Date: Wed, 2 Feb 2005 13:09:58 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBE9@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUI3Q64h9ykph8RSl6pF0OpBbTqJA== -To: -X-OriginalArrivalTime: 02 Feb 2005 04:09:59.0005 (UTC) FILETIME=[0F7508D0:01C508DD] -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 44 - -Hi all, - -Thanks to the devel package, I've got succeeded in making DBD::Oracle -with the Oracle Instant Client 10.1.0.3, no *.mk files, in my linux box. -My recipe is: - -1) install both basic- and devel-10.1.0.3 rpm packages -2) export ORALCE_HOME="/usr/lib/oracle/10.1.0.3/client" -3) export LD_LIBRARY_PATH="$ORACLE_HOME/lib:$LD_LIBRARY_PATH" -4) modify the Makefile.PL file to bypass the find_headers() routine and - to pass a correct -I flag to cc (the attached dirty patch is FYI) -5) execute the Makefile.PL * with the -l option *, perl Makefile.PL -l -6) make && make test && make install -# I got many errors in t/30long.t (retrieving blobs ?) -# but it seems to work fairly. - -I hope this could help those who are annoyed with the "Unable to locate an -oracle.mk,..." error. - -Happy DBing, - -Satoshi - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+# my @h_dirs = find_headers(); - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client"; - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -From SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com Thu Feb 3 08:10:48 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j138AMOi093146 - for ; Thu, 3 Feb 2005 08:10:48 GMT - (envelope-from SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Thu, 03 Feb 2005 08:10:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwboD-0005ug-LV; - Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwboD-0005ug-LV - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwboD-0000Wn-82 - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 70999102D9F; - Thu, 3 Feb 2005 02:53:48 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 5F45E102DCC - for ; Thu, 3 Feb 2005 02:53:48 -0500 (EST) -X-Pobox-Antispam: Require PTR Record returned DENY: 210.81.52.253 has no PTR record -X-Pobox-Antispam: country/Japan returned DENY: sender address snisim@sankyo.co.jp matches TLD .jp (Japan) -Received-SPF: none (boggle.pobox.com: domain of snisim@sankyo.co.jp does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for snisim@sankyo.co.jp to mail through 210.81.52.253) -Received: from mailgws.shina.sankyo.co.jp (unknown [210.81.52.253]) - by boggle.pobox.com (Postfix) with ESMTP id A38A5102E20 - for ; Thu, 3 Feb 2005 02:53:46 -0500 (EST) -Received: from es007.sankyo.co.jp (localhost [127.0.0.1]) - by mailgws.shina.sankyo.co.jp (8.9.3p2/3.7W) with ESMTP id LAA15117 - for ; Thu, 3 Feb 2005 11:45:39 +0900 (JST) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgws.shina.sankyo.co.jp: iscan owned process doing -bs -Received: from EVS001.sankyo.co.jp ([10.14.121.200]) by es007.sankyo.co.jp with Microsoft SMTPSVC(6.0.3790.0); - Thu, 3 Feb 2005 11:45:39 +0900 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: RE: Making DBD::Oracle with Instant Client 10.1.0.3 -Content-class: urn:content-classes:message -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Date: Thu, 3 Feb 2005 11:46:07 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBEC@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUJEc1pQuIX++g2S8y4AE9WqWRYtQAhsK+Q -To: -X-OriginalArrivalTime: 03 Feb 2005 02:45:39.0123 (UTC) FILETIME=[71F21030:01C5099A] -Status: RO -Content-Length: 1192 -Lines: 36 - -Hi Tim, - -Thank you for your kind reply. - -I found my patch will cause a compilation error for the local variable -@h_dirs gets into undefined after commenting out the line 279. -It should be corrected as following: - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+ my @h_dirs; - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client" - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -I'm not a dbi-users member so I can't reply my post... I wonder if you can do it. - -Thanks, - -Satoshi - - diff --git a/err_build/err_makefileundef.msg b/err_build/err_makefileundef.msg deleted file mode 100644 index b98d782a..00000000 --- a/err_build/err_makefileundef.msg +++ /dev/null @@ -1,87 +0,0 @@ -From timbo Tue Apr 26 09:19:54 2005 -Return-path: -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 26 Apr 2005 09:19:54 -0700 (PDT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DQSgy-0006AU-4c; - Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DQSgy-0006AU-4c - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1DQSgy-0003uM-1T - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 759703B902A; - Tue, 26 Apr 2005 12:13:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 80C0A39F279 - for ; Tue, 26 Apr 2005 12:13:42 -0400 (EDT) -Received-SPF: none (kelvin.pobox.com: domain of lembark@wrkhors.com does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 66.246.154.128(mail-out.pilosoft.net) -Received: from mail.pilosoft.net (mail-out.pilosoft.net [66.246.154.128]) - by kelvin.pobox.com (Postfix) with ESMTP id 2ED743AB75B - for ; Tue, 26 Apr 2005 12:12:30 -0400 (EDT) -Received: from [192.168.1.2] (dsl-69-31-90-94.pilosoft.com [69.31.90.94]) - by mail.pilosoft.net (8.12.8/8.12.8) with ESMTP id j3QGA3u1014203 - for ; Tue, 26 Apr 2005 12:10:03 -0400 -Date: Tue, 26 Apr 2005 12:14:22 -0400 -From: Steven Lembark -Reply-To: lembark@wrkhors.com -To: Tim Bunce -Subject: Possible glitch in DBD::Oracle-1.48 Makefile.pl -Message-ID: <269F0144DC99100E7C80975F@[192.168.1.2]> -X-Mailer: Mulberry/3.1.3 (Linux/x86) -X-Workhorse: lembark 1.1 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii; format=flowed -Content-Transfer-Encoding: 7bit -Content-Disposition: inline -X-Virus-Scanned: ClamAV version 0.83, clamav-milter version 0.83 on mail.pilosoft.net -X-Virus-Status: Clean -X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=failed version=3.0.2 -X-Spam-Level: 0.0 -X-Spam-Checker-Version: SpamAssassin 3.0.2 (2004-11-16) on cheeta.pilosoft.net -X-Status: A -Content-Length: 1342 -Lines: 36 - -Linking with OTHERLDFLAGS = -L/opt/oracle/product/9.2/lib/ --L/opt/oracle/product/9.2/rdbms/lib/ -lclntsh `cat -/opt/oracle/product/9.2/lib/sysliblist` -ldl -lm [from 'build' rule] - -Checking if your kit is complete... -Looks good -Use of uninitialized value in substitution (s///) at Makefile.PL line 1446. -LD_RUN_PATH=/opt/oracle/product/9.2/lib:/opt/oracle/product/9.2/rdbms/lib -Using DBD::Oracle 1.16. - - - sub const_loadlibs { - my $self = shift; - local($_) = $self->SUPER::const_loadlibs(@_); - # edit LD_RUN_PATH ... - my ($ldrp) = m/^LD_RUN_PATH\s*=\s*(.*)/m; - # remove redundant /lib or /usr/lib as it can cause problems --> $ldrp =~ s!:(/usr)?/lib$!!; - # if it's empty then set it manually - #Lincoln: if pick the right library path - my $libdir = main::ora_libdir(); - $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; - #print "ldrp=$ldrp\n"; - - # stitch it back in - s/^LD_RUN_PATH\s*=\s*(.*)/LD_RUN_PATH=$ldrp/m; - my $env = $ENV{LD_RUN_PATH}; - print "Ignoring LD_RUN_PATH='$env' in environment\n" if $env; - print "LD_RUN_PATH=$ldrp\n"; - return $_; - } - --- -Steven Lembark 85-09 90th Street -Workhorse Computing Woodhaven, NY 11421 -lembark@wrkhors.com 1 888 359 3508 - diff --git a/err_build/err_memleak.msg b/err_build/err_memleak.msg deleted file mode 100644 index d40913d7..00000000 --- a/err_build/err_memleak.msg +++ /dev/null @@ -1,95 +0,0 @@ -From SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com Wed Sep 1 16:31:37 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i81FRlpg021884 - for ; Wed, 1 Sep 2004 16:31:37 +0100 (BST) - (envelope-from SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 Sep 2004 16:31:37 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C2WYO-00034m-M1; - Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C2WYO-00034m-M1 - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1C2WYO-0005CR-FY - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 1C1D6A758C; - Wed, 1 Sep 2004 10:57:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 184C8A7214 - for ; Wed, 1 Sep 2004 10:57:32 -0400 (EDT) -Received-SPF: fail (boggle.pobox.com: domain of www-data@pallas.eruditorum.org does not designate 63.251.223.170 as permitted sender) -X-SPF-Override: pass (client 63.251.223.170 was found in trusted-forwarder.org, overrides regular SPF fail) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.170(x1.develooper.com) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP id 7A6C9A7555 - for ; Wed, 1 Sep 2004 10:57:06 -0400 (EDT) -Received: (qmail 5427 invoked by uid 225); 1 Sep 2004 14:57:04 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 5403 invoked by alias); 1 Sep 2004 14:57:02 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 01 Sep 2004 07:56:59 -0700 -Received: by pallas.eruditorum.org (Postfix, from userid 33) - id 1FDD784C0F5; Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -Subject: [cpan #6245] Confirmed memory leak -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #6245 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -Date: Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -To: undisclosed-recipients: ; -Status: RO -Content-Length: 937 -Lines: 38 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -I Using : -1. SunOS 5.6 Generic_105181-33 sun4u sparc SUNW,Ultra-Enterprise - Perl 5.005_03 - DBI 1.37 - DBD-Oracle 1.14 - Oracle Release 8.1.5.0.0 - - -2. Linux 2.4.18-17.7.xsmp #1 SMP i686 - Perl 5.6.1 - DBI 1.41 - DBD-Oracle 1.16 - Oracle Release 8.1.6.0.0 - -II The following code: - -use strict; -use DBI; - -foreach ( 1 .. 100 ) { - my $dbh = DBI->connect( 'dbi:Oracle:host=****', '***', '***' ); - $dbh->disconnect(); - sleep(1) -} - -III Leak about 4K every 10 seconds - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8724 8720 2760 S 1.3 3.4 0:01 perl - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8736 8732 2760 S 0.7 3.4 0:01 perl - diff --git a/err_build/err_solarisnotes.msg b/err_build/err_solarisnotes.msg deleted file mode 100644 index eaddc475..00000000 --- a/err_build/err_solarisnotes.msg +++ /dev/null @@ -1,482 +0,0 @@ -From SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com Wed Dec 22 08:11:00 2004 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id iBM8Aog0091816 - for ; Wed, 22 Dec 2004 08:11:00 GMT - (envelope-from SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 22 Dec 2004 08:11:00 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Ch0it-0001A5-Rv; - Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Ch0it-0001A5-Rv - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Ch0is-0000To-R8 - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id F0F0DFE10C; - Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 8B2AAFE1C3 - for ; Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Received-SPF: none (lime.pobox.com: domain of alexzar@zorranlabs.com does not designate permitted sender hosts) -Received: from penguin.nocdirect.com (penguin.nocdirect.com [69.73.160.206]) - by lime.pobox.com (Postfix) with ESMTP id 2B41BFE159 - for ; Wed, 22 Dec 2004 02:13:17 -0500 (EST) -Received: from localhost ([127.0.0.1]) - by penguin.nocdirect.com with esmtps (TLSv1:DES-CBC3-SHA:168) - (Exim 4.43) - id 1Cgz53-0000fj-Bx; Tue, 21 Dec 2004 23:30:37 -0600 -Date: Tue, 21 Dec 2004 23:30:35 -0600 (CST) -From: Alex Zarutin -X-X-Sender: zorranla@penguin.nocdirect.com -To: Tim Bunce -Cc: dbi-users-help@perl.org -Subject: Step-by-Step installation manual of DBD-Oracle-1.16 on Sparc Solaris - 9 with Oracle 9.2.0.1.0 client. -Message-ID: -MIME-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-AntiAbuse: This header was added to track abuse, please include it with any abuse report -X-AntiAbuse: Primary Hostname - penguin.nocdirect.com -X-AntiAbuse: Original Domain - pobox.com -X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] -X-AntiAbuse: Sender Address Domain - zorranlabs.com -X-Source: -X-Source-Args: -X-Source-Dir: -Status: RO -X-Status: A -Content-Length: 15603 -Lines: 426 - - -Hi Tim, - -I have spent a couple days trying to install DBD-Oracle-1.16 (all -required stuff, such as GCC, DBI, etc has been installed before ) on -Sun-Fire v240 running Spark Solaris 9 with the Oracle 9.2.0.1.0 client -installed. The installation takes a couple minutes ONLY after you spend -days trying to make it workable. - -I wrote the log of what I do, in order to do not waste my time in -future. I am pretty sure that this log will be very useful for people -installing DBD-Oracle on Solaris. I published it on my log page, and left -link on it at http://cpanratings.perl.org/d/DBD-Oracle review page. I -would recommend you to add this log to the readme file of your next -releases. Log is written very detailed (step-by-step) with highlighted -typical mistakes. - -Environment: -Hardware/OS: bash-2.05# uname -a -SunOS qadmz41 5.9 Generic_117171-08 sun4u sparc SUNW,Sun-Fire-V240 -OS is actually "standard" Solaris 9 installation came on the box from -SUN - -Oracle Client: Oracle 9.2.0.1.0 -GCC: gcc version 3.3.2, installed to /usr/local/bin as a package from -http://www.sunfreeware.com/programlistsparc9.html -PERL: perl v5.8.5 built for sun4-solaris, installed to /usr/local/bin as -a package from http://www.sunfreeware.com/programlistsparc9.html -DBI: DBI-1.45, installed from http://search.cpan.org/~timb/DBI-1.45/ - -Step-by-Step Manual: - -Step 1: In order to install "DBD-Oracle-1.16" you need to download it, -set all appropriate environment variables (see readme for details) and -run <>. -I got an error that is mostly typical for Solaris installation: - -// ************************ Error 1 ***********************/ - -.... -Found header files in rdbms/demo. - -********************************************************* -I can't find the header files I need in your Oracle installation. -You probably need to install some more Oracle components. -I'll keep going, but the compile will probably fail. -See README.clients for more information. -********************************************************* -Checking for functioning wait.ph - -System: perl5.008005 sunos 5.9 generic sun4u sparc sunw,ultra-5_10 -solaris -Compiler: gcc -B/usr/ccs/bin/ -O -fno-strict-aliasing -pipe --I/usr/local/include -I/opt/gnu/include -D_LARGEFILE_SOURCE --D_FILE_OFFSET_BITS=64 - -.... -// *****************************************************/ - -Investigating this problem, I found that error message is thrown by the -"find_headers" sub of Makefile.PL, especially in this "if -(!$h_file{'oratypes.h'} || !$h_file{'ocidfn.h'})" evaluation. -So I checked these files to make sure that they are installed, but did -not find them under $ORACLE_HOME/rdbms -In the same time, I found an article saying about the similar problem -with DBD-Oracle on Linux, -http://baroti.homedns.org/steve/lost+found/cpan-install-DBD-Oracle-9-2-l -inux.html -They mentioned about two files, and since I was not sure about second -one, ociapr.h I copied both files. You should find its public.1.1.jar -file on the Disk3 of Oracle 9i installation set. - -bash-2.05# pwd -/ora_orig/Disk3/stage/Components/oracle.rdbms.oci/9.2.0.1.0/1/DataFiles - -bash-2.05# ls -al -total 970 -drwxr-xr-x 2 2840 42424 512 Aug 21 2002 . -drwxr-xr-x 3 2840 42424 512 Aug 21 2002 .. --rwxr-xr-x 1 2840 42424 2047 May 9 2002 bin.1.1.jar --rwxr-xr-x 1 2840 42424 206 May 9 2002 build.1.1.jar --rwxr-xr-x 1 2840 42424 135034 May 9 2002 demo.1.1.jar --rwxr-xr-x 1 2840 42424 329814 May 9 2002 public.1.1.jar - -You should just (as dba:oracle) to create the directory called public, -copy public.1.1.jar there and extract all files, since I would not guess -if the rest of them are used or not - -bash-2.05# mkdir $ORACLE_HOME/rdbms/public - -bash-2.05# ls -al $ORACLE_HOME/rdbms/public -total 3404 -drwxr-xr-x 2 oracle dba 512 Dec 21 12:12 . -drwxr-xr-x 10 oracle dba 512 Dec 21 12:05 .. -... --rw-r--r-- 1 oracle dba 6055 Mar 9 2002 ociapr.h --rw-r--r-- 1 oracle dba 10694 Jun 29 2000 ocidfn.h -... - -After that run <> again, and I hope process passes -fine. At least, it was fine in my case - -Step 2: You should <> the module, and as it appears on Solaris, -you will get typical problem. See my error log: - -// ************************ Error 2 ***********************/ -.... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -ld: fatal: file -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib//libclntsh.so: -wrong ELF class: ELFCLASS64 -ld: fatal: File processing errors. No output written to -blib/arch/auto/DBD/Oracle/Oracle.so -collect2: ld returned 1 exit status -*** Error code 1 -make: Fatal error: Command failed for target -`blib/arch/auto/DBD/Oracle/Oracle.so' - -// *****************************************************/ - -So, as another set on Google' posts showed that it is a possibility of -missing libraries compiled with 64 bits and same libraries compiled with -32 bits suppoert. As I understood, all components of installation, such -as Oracle client, Perl, GCC should support only one type of libraries, -either 32 or 64 bits. I found that having all as 32 bits is easier to me -than recompile perl, gcc as 64 (may be I am wrong in this assumption). -In order to have all of them as 32 bits, I changed lib to lib32 in -Manifest file (not Manifest.PL). - -You should replace the following lines in the "MakeMaker const_loadlibs -section": - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -By their lib32 clones: - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -And replace this line in "MakeMaker dynamic_lib section" (~~ line 491) - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread - -By its lib32 clone: - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread - -I hope, that after that process passes without any errors. Here is last -part, that I got during <>: - -..... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/local/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL -ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/local/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" -blib/script/ora_explain -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oracle.3 -Manifying blib/man3/DBD::Oraperl.3 - -III. Once we build the module, we should test it, to make sure that it -works fine. You should run <> to do it: - -Check that you have ORACLE_HOME, ORACLE_USERID, ORACLE_SID environment -variables set, like this: - -ORACLE_HOME=="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0 -ORACLE_USERID=STARSHIP/STARSHIP -ORACLE_SID=COLORADO - -When you run <>, you will probably get this errors: - -// ************************ Error 3 ***********************/ - -bash-2.05# make test -PERL_DL_NONLAZY=1 /usr/local/bin/perl "-MExtUtils::Command::MM" "-e" -"test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............DBI connect('','STARSHIP/STARSHIP',...) failed: -ORA-12545: Connect failed because target host or object does not exist -(DBD ERROR: OCIServerAttach) at t/10general.t line 12 -Undefined subroutine &main::BAILOUT called at t/10general.t line 15. -# Looks like your test died before it could output anything. -t/10general.............dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-31 - Failed 31/31 tests, 0.00% okay -..... - -// *****************************************************/ - -One more brainstorm, and I figured out another way to set ORACLE_USERID: - -ORACLE_USERID=STARSHIP/STARSHIP@COLORADO -ORACLE_SID=COLORADO - -Later, when tests finished, I was confirmed that it was probably -preferred way of setting ORACLE_USERID. -Tests did found correct settings, and "main" set of them returned the -following report: - -All tests successful, 1 test and 122 subtests skipped. -Files=18, Tests=1020, 24 wallclock secs (11.27 cusr + 1.34 csys = 12.61 -CPU) - -For the Extra test, less formal, but test anyway, I just commented these -two lines in test.pl file - -$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -and set the same values in the same form to the $dbuser as it was in -ORACLE_USERID , and -left $dbname empty, - -$dbname = ''; -$dbuser = 'STARSHIP/STARSHIP@COLORADO'; - -and got pretty good report: - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - -recommended) - as 'STARSHIP/STARSHIP@COLORADO' (via ORACLE_USERID env var or default - -recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -Fields: 6 -Names: 'NUM_T' 'DATE_T' 'CHAR_T' 'ROWID_T' -'RAW_T' 'NULL_T' -Lengths: 172 76 121 21 3 1 -OraTypes: 2 12 1 104 23 1 -SQLTypes: 8 93 12 -9104 -2 12 -Scale: 0 0 0 0 0 0 -Precision: 126 75 120 20 2 0 -Nullable: 1 1 1 1 1 1 -Est row width: 32 -Data rows: - fetch: '7.2', '21-DEC-04', 'STARSHIP', 'AAAADeAABAAAAZSAAA', '7D', -undef - -ora_logoff... -lda out of scope... - -Testing repetitive connect/open/close/disconnect: -If this test hangs then read the README.help file. -Expect sequence of digits, no other messages: -1 2 3 4 5 - -Test interaction of explicit close/logoff and implicit DESTROYs -Expect just 'done.', no other messages: -done. - -Testing row cache (5). -Test completed in 0 seconds. - -Test complete (0 seconds). -If the tests above have produced the 'expected' output then they have -passed. - -IV. The last part is actually target of all steps above, installing -build module. < did not surprise me, and it it passed -smoothly. - -bash-2.05# make install -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/dbdimp -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/ocitra -ce.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/mk.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.so -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.bs -Files found in blib/arch: installing files in blib/lib into architecture -dependent library tree -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/oraperl.ph -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/Oraperl.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle/GetInfo.pm -Installing /usr/local/share/man/man1/ora_explain.1 -Installing /usr/local/share/man/man3/DBD::Oracle.3 -Installing /usr/local/share/man/man3/DBD::Oraperl.3 -Installing /usr/local/bin/ora_explain -Writing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/.packl -ist -Appending installation info to -/usr/local/lib/perl5/5.8.5/sun4-solaris/perllocal.pod - -V. This is actually it, and you do not need to do anything else. But -investigating different errors during the various steps, I found the -very simple "independent sanity" testdbi perl script written by Jeff -Hunter. This script is not related to standard process of -making/buildin/testing/installation. It just verifies that you can -access DB and run a couple queries against it. The code itself, -testdbi.pl can be found at -http://www.idevelopment.info/data/Oracle/DBA_tips/Programming/PROGRAMMIN -G_2.shtml - -You just should set connection information, similar to how I did it, - - $ORACLE_SID = "COLORADO"; - $ORACLE_USERID = "STARSHIP"; - $ORACLE_PASSWORD = "STARSHIP"; - - $ENV{'ORACLE_SID'} = "$ORACLE_SID"; - $ENV{'ORACLE_HOME'} = /u01/app/oracle/product/9.2.0.1.0"; - -run it as any perl script, <>, and see result: - -bash-2.05# perl testdbi.pl - -Running testdbi.pl... - - (*) Attempting Oracle Login ... - OK - (*) Creating table TEST_DBI ... - OK - (*) Insert into TEST_DBI ... - 1 rows inserted. - 1 rows inserted. - 1 rows inserted. - OK - (*) Select from TEST_DBI ... - - --> TEST_DBI_INTR_NO : 1000 - --> TEST_DBI_NAME : Jeff Hunter - - --> TEST_DBI_INTR_NO : 1001 - --> TEST_DBI_NAME : Melody Hunter - - --> TEST_DBI_INTR_NO : 1002 - --> TEST_DBI_NAME : Alex Hunter - OK - - (*) Delete from TEST_DBI ... - 3 rows deleted. - OK - - (*) Drop table TEST_DBI ... - OK - - (*) Select USER and SYSTEM ... - - --> USER : STARSHIP - --> SYSDATE : 21-DEC-2004 16:49:59 - OK - - (*) Attempting Oracle Logoff ... - OK - -Ending testdbi.pl... - -With the best regards, - -Alex Zarutin - -Software Engineer -4thpass A Motorola Company -Seattle, WA -www.4thpass.com - - - - diff --git a/err_build/err_testfailnotable.msg b/err_build/err_testfailnotable.msg deleted file mode 100644 index 687d5ed7..00000000 --- a/err_build/err_testfailnotable.msg +++ /dev/null @@ -1,97 +0,0 @@ -From SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 18:10:51 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RHAOAK026067 - for ; Wed, 27 Oct 2004 18:10:51 +0100 (BST) - (envelope-from SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 18:10:51 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMp30-0000e2-Hh; - Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMp30-0000e2-Hh - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMp30-0001QS-2p - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 87C155A7D; - Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 7779A59A1 - for ; Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Received-SPF: pass (gold.pobox.com: domain of dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by gold.pobox.com (Postfix) with SMTP id DC5795A4A - for ; Wed, 27 Oct 2004 10:45:07 -0400 (EDT) -Received: (qmail 18140 invoked by uid 514); 27 Oct 2004 14:45:04 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 18131 invoked from network); 27 Oct 2004 14:45:04 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 14:45:04 -0000 -Received: (qmail 8663 invoked by uid 225); 27 Oct 2004 14:45:03 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 8659 invoked by alias); 27 Oct 2004 14:45:03 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from ns2.aramiska.net (HELO dmzms01.aramiska.net) (80.242.32.2) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 07:45:01 -0700 -Received: from ip-80-242-36-115.aramiska-arc.aramiska.net (ip-80-242-36-115.aramiska-arc.aramiska.net [80.242.36.115]) - by dmzms01.aramiska.net (Postfix) with ESMTP - id 9F21E1100D9; Wed, 27 Oct 2004 14:44:55 +0000 (UTC) -Received: from localhost (localhost [127.0.0.1]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id E558E7C; Wed, 27 Oct 2004 14:44:52 +0000 (UTC) -Received: from dansat.data-plan.com (ip-192-168-0-3.internal.data-plan.aramiska.net [192.168.0.3]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id D8A5E71; Wed, 27 Oct 2004 14:44:50 +0000 (UTC) -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9REioAA023212; - Wed, 27 Oct 2004 15:44:50 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i9REinmW023211; - Wed, 27 Oct 2004 15:44:49 +0100 (BST) -Date: Wed, 27 Oct 2004 15:44:49 +0100 -From: Tim Bunce -To: "H.Merijn Brand" -Cc: Tim Bunce , DBI developers -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Message-ID: <20041027144449.GB19991@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> <20041027093516.D001.H.M.BRAND@hccnet.nl> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20041027093516.D001.H.M.BRAND@hccnet.nl> -User-Agent: Mutt/1.4i -X-Virus-Scanned: by Aramiska Arc -Status: RO -Content-Length: 634 -Lines: 14 - -On Wed, Oct 27, 2004 at 09:39:33AM +0200, H.Merijn Brand wrote: -> On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> > file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> > size: 235224 bytes -> > md5: 9711550ed0ebfc743920a6a357ed717c -> -> I know you can't blame the test for not being able to create a table for the -> reason this failure shows, but there might be a more user-friendly way to fail ... - -Yeap. Some tests behave better in that situation. Looks like those -two need improving. Patches welcome! (I'd happily not touch DBD::Oracle -for a few months after the pain of the last few months :) - -Tim. - diff --git a/err_docs/err_trace.msg b/err_docs/err_trace.msg deleted file mode 100644 index 3d7500fb..00000000 --- a/err_docs/err_trace.msg +++ /dev/null @@ -1,14 +0,0 @@ -Add this to the DBD::Oracle docs as a handy note: - -$dbh->do(q{alter session set events '65285 trace name errorstack level 3'}); - -A trace file should then be generated. - -Trace files are generated in the 'user_dump_destination' specified in init.ora. - -Try $ORACLE_BASE/admin/$ORACLE_SID/udump. - -or the location returned by -select value -from v$parameter -where name like '%user_dump%' diff --git a/err_lob/err_csr_clob.msg b/err_lob/err_csr_clob.msg deleted file mode 100644 index 397d53b3..00000000 --- a/err_lob/err_csr_clob.msg +++ /dev/null @@ -1,65 +0,0 @@ -From dbi-users-bounce@isc.org Thu Sep 21 20:27:21 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id UAA18945; Thu, 21 Sep 2000 20:27:20 +0100 (BST) -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <02709-1@oink>; Mon, 21 Sep 1970 20:26:40 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 969564156:20:26825:1; Thu, 21 Sep 2000 19:22:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-2.mail.demon.net - id aa2026778; 21 Sep 2000 19:22 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 28A613E5D; - Thu, 21 Sep 2000 12:22:17 -0700 (PDT) -Received: with LISTAR (v1.0.0; list dbi-users); - Thu, 21 Sep 2000 12:17:37 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A59853E42 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) -Received: from wheel.cs.wisc.edu (wheel.cs.wisc.edu [128.105.121.12]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA00855 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) env-from (horn@wheel.cs.wisc.edu) -Received: (from horn@localhost) by wheel.cs.wisc.edu (8.9.2/8.9.2) id OAA16413 - for dbi-users@isc.org; Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -Date: Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -From: Jeffrey Horn -Message-Id: <200009211917.OAA16413@wheel.cs.wisc.edu> -To: dbi-users@isc.org -Subject: Setting ORA_TYPE after the fact... -Sender: horn@wheel.cs.wisc.edu -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: horn@cs.wisc.edu -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -X-Status: A -Content-Length: 969 -Lines: 20 - -I have a situation where I would like to return a cursor that contains a -CLOB as one of it's attributes from a PL/SQL procedure. What I get back is -a LOB locator and DBD doesn't actually read the CLOB but instead returns an -error. - -If I go through a bind/prepare/execute/fetch on a similar SQL statement all -is well. Is there any way that I can tell DBD that a given attribute of -a cursor is a CLOB once the cursor is already opened so that DBD will do the -right thing? - --- Jeff Horn - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_lob/err_loblenwide.msg b/err_lob/err_loblenwide.msg deleted file mode 100644 index 08023e97..00000000 --- a/err_lob/err_loblenwide.msg +++ /dev/null @@ -1,95 +0,0 @@ -From nobody@fsck.com Thu Dec 4 07:36:20 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hB47Y2nE066844 - for ; Thu, 4 Dec 2003 07:36:20 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 04 Dec 2003 07:36:20 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1ARgrA-0005O4-5M; - Wed, 03 Dec 2003 23:56:32 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1ARgrA-0005O4-5M - for pobox@dbi.demon.co.uk; Wed, 03 Dec 2003 23:56:32 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 314AB9A28F - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 188369A287 - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com[63.251.223.170]) - by icicle.pobox.com (Postfix) with SMTP - for ; Wed, 3 Dec 2003 18:56:31 -0500 (EST) -Received: (qmail 3178 invoked by uid 225); 3 Dec 2003 23:56:30 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 3174 invoked by alias); 3 Dec 2003 23:56:29 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Wed, 03 Dec 2003 15:56:18 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 91512114F1; Wed, 3 Dec 2003 18:56:07 -0500 (EST) -Subject: [cpan #4564] Perl DBI bug handling CLOBs -From: "Jay Turner via RT" -Reply-To: bug-DBI@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4564 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: J.Turner@mdl.com -To: "AdminCc of cpan Ticket #4564": ; -Date: Wed, 3 Dec 2003 18:56:07 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -X-Status: A -Content-Length: 1853 -Lines: 46 - - -This message about DBI was sent to you by J.Turner@mdl.com via rt.cpan.org - -Full context and any attached attachments can be found at: - - - -Date: Fri, 28 Feb 2003 16:55:28 -0800 - -It has come to my attention that PERL DBI counts on OCILobGetLength -returning BYTES. It returns CHARACTERS instead, which is the count of -variable-width characters. For multi-byte character sets this results -in errors such as: - -DBD::Oracle::st fetch failed: ORA-03130: the buffer for the next piece -to be fetched is required (DBD ERROR: OCILobGetLength) at id rmsc01.pl -line 294. - -The correct way to read CLOBs is - -1) Query the LOB locator for the CSID and CSFRM (character set ID and -form). A character set >= 800 is a mulitbyte character set and csfrm -<> 0 is CLOB. - -2) Pass the CSID and CSFRM to OCILobRead with AMT=0 and pass your -buffer address and size. - -3) Your callback routine must either be capable of completing the I/O -by allocating additional buffers, or it must notify the caller of -OCILobRead to free the lob locator, since an incomplete read jams the -locator-you can't use it for anything else without finishing the read -(attempts to reuse the locator will result in errors). - -Likewise, with OCILobWrite, you have to pass the CSID and CSFRM, with -AMT=0 and the buffer size in bytes. The callback can just say it has -zero bytes and set piece=OCI_LAST_PIECE. - -You cannot use the return value of OCILobGetLength as the size of the -data that is being read. The actual size of the data is unknown for -variable-width characters, and the buffer has to be big enough to -accomplish the translation, so you can't just double or triple the -return value from OCILobGetLength (I have seen that approach fail). - -You can simulate the effects of a foreign character set by - -$ export NLS_LANG=Japanese - diff --git a/err_lob/err_lobtesttblfail.msg b/err_lob/err_lobtesttblfail.msg deleted file mode 100644 index 1333ee88..00000000 --- a/err_lob/err_lobtesttblfail.msg +++ /dev/null @@ -1,208 +0,0 @@ -From SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 15:22:22 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RELAAO018624 - for ; Wed, 27 Oct 2004 15:22:22 +0100 (BST) - (envelope-from SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 15:22:22 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMiQ8-0000Eo-FG; - Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMiQ8-0000Eo-FG - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMiQ8-0006dS-9n - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B3BB911C325; - Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9947911C2CE - for ; Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Received-SPF: pass (icicle.pobox.com: domain of dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by icicle.pobox.com (Postfix) with SMTP id 5033611C34F - for ; Wed, 27 Oct 2004 03:39:46 -0400 (EDT) -Received: (qmail 12004 invoked by uid 514); 27 Oct 2004 07:39:43 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 11995 invoked from network); 27 Oct 2004 07:39:43 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 07:39:43 -0000 -Received: (qmail 13565 invoked by uid 225); 27 Oct 2004 07:39:43 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 13560 invoked by alias); 27 Oct 2004 07:39:42 -0000 -X-Spam-Status: No, hits=-3.7 required=8.0 - tests=BAYES_00,LARGE_HEX -X-Spam-Check-By: la.mx.develooper.com -Received: from smtp-vbr15.xs4all.nl (HELO smtp-vbr15.xs4all.nl) (194.109.24.35) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 00:39:40 -0700 -Received: from [127.0.0.1] (procura.xs4all.nl [213.84.163.145]) - by smtp-vbr15.xs4all.nl (8.12.11/8.12.11) with ESMTP id i9R7dWHI013040; - Wed, 27 Oct 2004 09:39:34 +0200 (CEST) - (envelope-from h.m.brand@hccnet.nl) -Date: Wed, 27 Oct 2004 09:39:33 +0200 -From: "H.Merijn Brand" -To: Tim Bunce -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Cc: DBI developers -In-Reply-To: <20041022213625.GA22377@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> -Message-Id: <20041027093516.D001.H.M.BRAND@hccnet.nl> -MIME-Version: 1.0 -Content-Type: text/plain; charset="US-ASCII" -X-Mailer: Becky! ver. 2.11.02 [en] -X-Virus-Scanned: by XS4ALL Virus Scanner -X-Virus-Checked: Checked -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i9RELAAO018624 -Status: RO -X-Status: A -Content-Length: 7175 -Lines: 134 - -On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> size: 235224 bytes -> md5: 9711550ed0ebfc743920a6a357ed717c - -I know you can't blame the test for not being able to create a table for the -reason this failure shows, but there might be a more user-friendly way to fail ... - -I'll report back when the DBA has fixed the tablespace - -HP-UX 11.11/64 (11i) + Oracle-9.2.0/64 + perl-5.8.5-dor/64 - -PERL_DL_NONLAZY=1 /pro/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, -'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............ok -t/15nls.................ok -t/20select..............ok -t/21nchar............... Database and client versions and character sets: -Database 9.2.0.1.0 CHAR set is US7ASCII (Non-Unicode), NCHAR set is AL16UTF16 ( -nicode) -Client 9.2.0.1 NLS_LANG is '', NLS_NCHAR is '' -t/21nchar...............ok -t/22nchar_al32utf8......ok -t/22nchar_utf8..........ok -t/23wide_db.............skipped - all skipped: Database character set is not Unicode -t/23wide_db_8bit........skipped - all skipped: Database character set is not Unicode -t/23wide_db_al32utf8....skipped - all skipped: Database character set is not Unicode -t/24implicit_utf8.......ok -t/25plsql...............ok -t/30long................ok 188/470DBD::Oracle::db do failed: ORA-03237: Initial -Extent of specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: -OCIStmtExecute) [for Statement "create table dbd_ora__drop_me ( idx integer, ln - NCLOB, dt date )"] at t/nchar_test_lib.pl line 356. -t/30long................ok 189/470DBD::Oracle::st execute failed: ORA-00942: ta -le or view does not exist (DBD ERROR: error possibly near <*> indicator at char -12 in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statem -nt "insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1= -0, :p2='0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X...'] at t/30long.t line 153. -# Failed test (t/30long.t at line 153) -t/30long................NOK 190DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=41, -:p2='12345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -...'] at t/30long.t line 154. -# Failed test (t/30long.t at line 154) -t/30long................NOK 191DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=42, -:p2='2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -...'] at t/30long.t line 155. -t/30long................NOK 192# Failed test (t/30long.t at line 155) -DBD::Oracle::st execute failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 12 in 'insert into <*>dbd_ora__dr -p_me values (:p1, :p2, SYSDATE)') [for Statement "insert into dbd_ora__drop_me -alues (?, ?, SYSDATE)" with ParamValues: :p1=43, :p2=undef] at t/30long.t line -56. -# Failed test (t/30long.t at line 156) -t/30long................NOK 193DBD::Oracle::db prepare failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 14 -in 'select * from <*>dbd_ora__drop_me order by idx') [for Statement "select * f -om dbd_ora__drop_me order by idx"] at t/30long.t line 170. -# Failed test (t/30long.t at line 170) -Can't call method "trace" on an undefined value at t/30long.t line 171. -t/30long................NOK 194# Looks like you planned 470 tests but only ran -94. -# Looks like your test died just after 194. -t/30long................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 190-470 - Failed 281/470 tests, 40.21% okay (less 122 skipped tests: 67 okay, 14. -6%) -t/31lob.................DBD::Oracle::db do failed: ORA-03237: Initial Extent of -specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: OCIStmtEx -cute) [for Statement " - CREATE TABLE dbd_ora__drop_me ( - id INTEGER NOT NULL, - data BLOB - ) - "] at t/31lob.t line 21. -DBD::Oracle::db do failed: ORA-00942: table or view does not exist (DBD ERROR: -rror possibly near <*> indicator at char 12 in 'INSERT INTO <*>dbd_ora__drop_me -(id,data) VALUES (1, EMPTY_BLOB())') [for Statement "INSERT INTO dbd_ora__drop_ -e (id,data) VALUES (1, EMPTY_BLOB())"] at t/31lob.t line 31. -DBD::Oracle::db prepare failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 17 in 'SELECT data FROM <*>dbd_or -__drop_me WHERE id = :p1') [for Statement "SELECT data FROM dbd_ora__drop_me WH -RE id = ?"] at t/31lob.t line 34. -Can't call method "bind_param" on an undefined value at t/31lob.t line 36. -# Looks like your test died before it could output anything. -t/31lob.................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-2 - Failed 2/2 tests, 0.00% okay -t/40ph_type.............ok -t/50cursor..............ok -t/60reauth..............ORACLE_USERID_2 not defined. Tests skipped. -skipped - all skipped: no reason given -t/70meta................ok -Failed Test Stat Wstat Total Fail Failed List of Failed -------------------------------------------------------------------------------- -t/30long.t 255 65280 470 557 118.51% 190-470 -t/31lob.t 255 65280 2 4 200.00% 1-2 -4 tests and 122 subtests skipped. -Failed 2/18 test scripts, 88.89% okay. 283/1883 subtests failed, 84.97% okay. -make: *** [test_dynamic] Error 255 - --- -H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/) -using perl-5.6.1, 5.8.0 & 633 on HP-UX 10.20 & 11.00, AIX 4.2, AIX 4.3, - WinNT 4, Win2K pro & WinCE 2.11 often with Tk800.024 &/| DBD-Unify -ftp://ftp.funet.fi/pub/languages/perl/CPAN/authors/id/H/HM/HMBRAND/ - - - - diff --git a/err_lob/err_nclob_form.msg b/err_lob/err_nclob_form.msg deleted file mode 100644 index 05587693..00000000 --- a/err_lob/err_nclob_form.msg +++ /dev/null @@ -1,189 +0,0 @@ -From dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org Tue Jul 22 07:40:59 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6M6UUD7096422 - for ; Tue, 22 Jul 2003 07:40:58 +0100 (BST) - (envelope-from dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 22 Jul 2003 07:40:58 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058814697:11:26523:33; Mon, 21 Jul 2003 19:11:37 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1126786; 21 Jul 2003 19:11 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E855B21C37F - for ; Mon, 21 Jul 2003 15:11:18 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 9010121C236 - for ; Mon, 21 Jul 2003 15:11:17 -0400 (EDT) -Received: (qmail 66848 invoked by uid 1005); 21 Jul 2003 19:11:15 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 66832 invoked by uid 76); 21 Jul 2003 19:11:15 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 21 Jul 2003 12:11:15 -0700 -Received: (qmail 559 invoked by uid 225); 21 Jul 2003 19:11:08 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 552 invoked by uid 507); 21 Jul 2003 19:11:07 -0000 -Received-SPF: unknown -Received: from sneakemail.com (HELO monkey.sneakemail.com) (207.106.87.13) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Mon, 21 Jul 2003 12:11:03 -0700 -Received: (qmail 22505 invoked by uid 501); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #3); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #2); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #1); 21 Jul 2003 19:10:57 -0000 -Date: Mon, 21 Jul 2003 21:10:53 +0200 -From: "Wolfgang Weisselberg" -To: dbi-users@perl.org -Subject: DBD::Oracle and unicode-NCLOBs leads to ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) -Message-ID: <13502-46198@sneakemail.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.6 required=7.0 tests=CARRIAGE_RETURNS,FROM_ENDS_IN_NUMS,FROM_HAS_MIXED_NUMS,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_MUTT version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 6055 -Lines: 132 - -Hello all! - -Even after extensive googling and looking through the docs I fail -to fetch NCLOBs from an Oracle 9.2i database where the national -character set is unicode. - -I believe it has been done before, but I could not find anything ... -I would be grateful for any pointers. - - -NCLOBs work like CLOBs when the national character set is not -unicode, even with the old DBI 1.21 and DBD::Oracle 1.12 on an -Oracle 8 client. NVarchar2 and NChar work OK even with unicode. - -Setting NSL_LANG to AMERICAN_AMERICA.UTF8 or .AL32UTF8 does not -help, as I suspected. - -I tried using Oracle 9.2i (the DB is using 9.2i) on a Debian -Linux box. I upgraded DBI to 1.37 and DBD::Oracle to 1.14 (the -newest versions according to CPAN). I got zero errors on make -test with both. Perl is Debian's normal "perl5 (revision 5.0 -version 6 subversion 1)". - -A simple - select memo from unicode_test -(memo being the NCLOB field) fails (again, only with the national -charset being unicode). - -The relevant code snippet (RaiseError being set, of course): - -| $| = 1; -| print "DBI: $DBI::VERSION\n", -| "DBD::Oracle $DBD::Oracle::VERSION\n"; -| my $sth = $dbh->prepare("select memo from unicode_test"); -| $sth->execute(); -| -| while ( my ($memo) = $sth->fetchrow_array() ) { -| print Dumper $memo; -| } -| exit; - - -The output: - -| DBI: 1.37 -| DBD::Oracle 1.14 -| $VAR1 = ''; -| $VAR1 = ''; -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. - - - -Running with tracelevel 3: - [...] -| dbd_st_prepare'd sql SELECT -| dbd_describe SELECT (EXPLICIT, lb 99999999)... -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_execute SELECT (out0, lob0)... -| dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -| <- execute= '0E0' at nclobtest.pl line 79 via nclobtest.pl line 60 -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -| 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x82f8e28)~INNER 'ParamValues') -| error: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| 1 <- FETCH= HASH(0x831661c)0keys at nclobtest.pl line 81 via nclobtest.pl line 60 -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. - - - -Tracelevel 9 (yes, it's a bit verbose :-/ ) - -[...] -| OCIDescriptorAlloc(0x831c058,0x8395228,OCI_DTYPE_LOB,0,0) -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| OCIAttrSet(0x8335b34,OCI_HTYPE_STMT,0xbffff30c,4,11,0x832d5a4)=SUCCESS -| OCIDefineByPos(0x8335b34,0x8395224,0x832d5a4,1,0x8395228,-1,112,0x83414e0,0x83414f0,0x8341500,0)=SUCCESS -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -[...] -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| 0 (rc=0): '' -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead(0x832d530,0x832d5a4,0x832c69c,0xbffff318,1,0x8394da0,24,(nil),(nil),0,1)=ERROR -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| OCIErrorGet(0x832d5a4,1,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=SUCCESS -| OCIErrorGet after OCILobRead (er1:ok): -1, 24806: ORA-24806: LOB form mismatch -| -| OCIErrorGet(0x832d5a4,2,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=NO_DATA -| 0 (rc=0): undef -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -[gets and prints error message] - - -Any ideas anyone? - --Wolfgang - diff --git a/err_lob/err_nulllobsegv.msg b/err_lob/err_nulllobsegv.msg deleted file mode 100644 index 6de3c99b..00000000 --- a/err_lob/err_nulllobsegv.msg +++ /dev/null @@ -1,93 +0,0 @@ -From dbi-users-return-1743-Tim.Bunce=ig.co.uk@perl.org Wed Apr 11 04:00:48 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id EAA17912; Wed, 11 Apr 2001 04:00:48 +0100 (BST) -Received: from 194.217.242.36 by oink with SMTP (PP) id <02579-1@oink>; - Sat, 11 Apr 1970 04:00:28 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 986956750:10:04398:0; Wed, 11 Apr 2001 02:39:10 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-1.mail.demon.net - id aa1106187; 11 Apr 2001 2:39 GMT -Received: (qmail 32618 invoked by uid 508); 11 Apr 2001 02:39:06 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 32603 invoked from network); 11 Apr 2001 02:39:05 -0000 -Received: from owns.warpcore.org (216.81.249.18) by tmtowtdi.perl.org with SMTP; - 11 Apr 2001 02:39:05 -0000 -Received: (from thebrain@localhost) by owns.warpcore.org (8.11.1/8.11.1) - id f3B2cxH06298 for dbi-users@perl.org; - Tue, 10 Apr 2001 21:38:59 -0500 -Date: Tue, 10 Apr 2001 21:38:59 -0500 -From: Stephen Clouse -To: dbi-users@perl.org -Subject: Bizarre DBD::Oracle Segfault -Message-ID: <20010410213859.B2766@owns.warpcore.org> -Mail-Followup-To: dbi-users@perl.org -Mime-Version: 1.0 -Content-Type: text/plain -Content-Disposition: inline; filename="msg.pgp" -User-Agent: Mutt/1.2.5i -Status: RO -Content-Length: 1918 -Lines: 54 - ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -I sent an email to the dbi-users list about a number of DBD::Oracle CLOB -handling problems waaaaaaaaaaaaaaay back (end of January or so) that today -someone dug up and inquired if I had ever found fixes for what I had pointed -out. - -The problems outlined that day turned out to be the test script itself, which -was doing so much bizarre stuff on one statement that DBD::Oracle just went to -sleep instead (and so was the actual program that instigated the writing of the -test script). - -Well, all but one problem was the script. This, the most serious one, continues -to linger: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',undef); - -On Linux, DBI 1.15, Oracle 8.1.6, and DBD::Oracle 1.06, this segfaults on the -execute. Unfortunately this manifests itself too deep in Oracle for me to -debug. - -The bizarre part is, either of the two snippets below will work: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',''); -$st->execute('B','B',undef); - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',$lobvalue); -$st->execute('B','B',undef); - -It's only when binding undef as the LOB value in the very first execute of a -statement that the segfault occurs. At any other time, it's kosher. That -qualifies as bizarre in my book. - -Your guess is better than mine. - -- -- -Stephen Clouse -Senior Programmer, IQ Coordinator Project Lead -The IQ Group, Inc. - ------BEGIN PGP SIGNATURE----- -Version: PGP 6.5.8 - -iQA+AwUBOtPDwgOGqGs0PadnEQLmtgCeJHTStLu8Q8oFb9UQ4995f8vhZH8Al1p6 -RD5m0FEJH2tQiY0+b6542mQ= -=L0M+ ------END PGP SIGNATURE----- - diff --git a/err_lob/err_tmplobfree.msg b/err_lob/err_tmplobfree.msg deleted file mode 100644 index 0ec8f940..00000000 --- a/err_lob/err_tmplobfree.msg +++ /dev/null @@ -1,537 +0,0 @@ -From SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com Wed Aug 25 17:53:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PGpkpQ033405 - for ; Wed, 25 Aug 2004 17:53:57 +0100 (BST) - (envelope-from SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 17:53:57 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Bzyve-0007kY-Gp; - Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Bzyve-0007kY-Gp - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Bzyvd-0000zb-Lg - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id AA6D8B0635; - Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 9B2A1B0BB0 - for ; Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -Received: from natnoddy.rzone.de (natnoddy.rzone.de [81.169.145.166]) - by lime.pobox.com (Postfix) with ESMTP id 2AAB1B0635 - for ; Wed, 25 Aug 2004 10:39:06 -0400 (EDT) -Received: from genericom.de (pD95195AC.dip.t-dialin.net [217.81.149.172]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7PEc05w018990 - for ; Wed, 25 Aug 2004 16:38:01 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412CA445.FC2F9EF2@genericom.de> -Date: Wed, 25 Aug 2004 16:37:57 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim.Bunce@pobox.com -Subject: DBD::Oracle: Freeing a temporary blob -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms4BC2D4519D41A502BB06559C" -Status: RO -X-Status: A -Content-Length: 4985 -Lines: 122 - -This is a cryptographically signed message in MIME format. - ---------------ms4BC2D4519D41A502BB06559C -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Dear Tim, - -first, I would really like to thank you for the great work you have done -with your DBI/DBD work. We are using it extensively in several projects -and we are highly pleased. - -Unfortunately I have now encountered a problem we need to fix urgently, -since our customer's production is seriously affected. - -We tried for many days to find a solution (google, newsgroups, -trial-and-error...), without luck. So my last chance is to contact you -directly, although I assume you have a lot work yourself. - ---- - -The problem: - -Our database contains a stored function "ReadUnitBlob()" that returns a -temporary blob: - -function ReadUnitBlob(UnitID_IN in integer) return blob -is -... -begin - ... - dbms_lob.createtemporary(retBlob, false, dbms_lob.call); - dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); - ... - return retBlob; -end; - -We call this function in Perl in a big loop to fetch a lot of blobs (~ -100000) using something like: - -my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -ora_auto_lob => 0 }); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); -my ($loc) = $sth->fetchrow_array(); -$sth->finish(); -... -while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) - ... - -Although this works, it has a big disadvantage: Oracle does not -automaticaly free the temporary blob, so it shortly runs out of temp. -space. (confirmed with "select * from v$temporary_lobs"). - -Acording to the Oracle docs this can be we solved by implicitly freeing -the temp. blob, e.g. by calling the PLSQL method -"dbms_lob.freetemporary()". I tried differnt ways to do this with -DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -locator from the my stored procedure and to pass it to a call of -"dbms_lob.freetemporary()": - -my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -ora_auto_lob => 0 }); -my $bloc; -$sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); - -obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) - -Can you help me??? Do you know a way how to free the temp. blob using -DBD::Oracle (using Oracle::OCI is not possible, since the customer is -strinctly refusing to install it). - -Otherwise, would it be possible include an additional DBD::Oracle LOB -Locator Method "ora_lob_freetemporary()" that warps -"OCILobFreeTemporary" ? - -Any help is really appreciated! - -Greeting from Germany, - - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------ms4BC2D4519D41A502BB06559C -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjUxNDM3NThaMCMGCSqG -SIb3DQEJBDEWBBS+u38esQAv19TdNkv4jgxlzsRqSzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAJQgoN5ASnyjnB7bgrv1+V7Cu4ULKe1CkHs0IEZaB -KuJcm98U7kskRyC5g6YNopuJxFbr19K3q5rrJGoUscKjiw== ---------------ms4BC2D4519D41A502BB06559C-- - - -From SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com Wed Aug 25 22:47:05 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PLjxpJ037568 - for ; Wed, 25 Aug 2004 22:47:04 +0100 (BST) - (envelope-from SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 22:47:04 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C04j1-00038v-Pz; - Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C04j1-00038v-Pz - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C04j0-00002I-FU - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:30 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AD1815463; - Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 85FFF55E7 - for ; Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Received-SPF: none (gold.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail04.svc.cra.dublin.eircom.net (mail04.svc.cra.dublin.eircom.net [159.134.118.20]) - by gold.pobox.com (Postfix) with SMTP id 14C005463 - for ; Wed, 25 Aug 2004 16:50:25 -0400 (EDT) -Received: (qmail 5678 messnum 5046341 invoked from network[213.94.228.233/unknown]); 25 Aug 2004 20:50:23 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail04.svc.cra.dublin.eircom.net (qp 5678) with SMTP; 25 Aug 2004 20:50:23 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PKsrof034865; - Wed, 25 Aug 2004 21:54:53 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7PKsqas034864; - Wed, 25 Aug 2004 21:54:52 +0100 (BST) -Date: Wed, 25 Aug 2004 21:54:52 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim.Bunce@pobox.com -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040825205452.GC34655@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412CA445.FC2F9EF2@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 4674 -Lines: 124 - -On Wed, Aug 25, 2004 at 04:37:57PM +0200, Philipp Lang wrote: -> Dear Tim, -> -> first, I would really like to thank you for the great work you have done -> with your DBI/DBD work. We are using it extensively in several projects -> and we are highly pleased. - -Thanks Philipp! - -> Unfortunately I have now encountered a problem we need to fix urgently, -> since our customer's production is seriously affected. -> -> We tried for many days to find a solution (google, newsgroups, -> trial-and-error...), without luck. So my last chance is to contact you -> directly, although I assume you have a lot work yourself. - -I am very busy and what little spare time I have for DBD::Oracle -is going into trying to get 1.16 released (which is proving to be -hard as we're tripping over Oracle bugs when an Oracle 8 client -talks to an Oracle 9+ server.) It's a major release that will help -many people so I need to give that priority. - -Separately I am exploring ways to fund DBI and DBD::Oracle development -so I can devote more time to it. There's is much that needs to be -done and much more that could be done beyond that. - -The Perl Foundation (TPF) have setup a way for people and companies -to make donations for DBI development [as yet unannounced so please -keep to yourself]. A note on the contribution could indicate that the -donor would like it used for a particular purpose, such as DBD::Oracle. - -Anyway, to cut a long story short, it would be much easier to devote -time to this if it could be funded in some way. - -I think the TPF setup is working so it could be done that way. -Alternatively you could contract me to do the work for you. -That would be quicker and simpler for you as TPF's non-profit -status doesn't make a difference to European donors. - -My standard daily rate for add-hoc consulting is 1600 Euro. -I'd expect to be able to sort this out inside a day, and prefer -fixed-price quotes anyway, so would 1600 Euro be okay? - -Of course, if you feel your company would like to either -make a general contribution to DBI/DBD::Oracle development beyond -that, or to fund the development of specific functionality that -would be of extra value to you then I'd be happy to talk about that. - -I hate asking for money, and would much rather dig into the code and -reply with a patch, but it's just not practical for me now. Sorry. - -Tim. - -> --- -> -> The problem: -> -> Our database contains a stored function "ReadUnitBlob()" that returns a -> temporary blob: -> -> function ReadUnitBlob(UnitID_IN in integer) return blob -> is -> ... -> begin -> ... -> dbms_lob.createtemporary(retBlob, false, dbms_lob.call); -> dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); -> ... -> return retBlob; -> end; -> -> We call this function in Perl in a big loop to fetch a lot of blobs (~ -> 100000) using something like: -> -> my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -> ora_auto_lob => 0 }); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> my ($loc) = $sth->fetchrow_array(); -> $sth->finish(); -> ... -> while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) -> ... -> -> Although this works, it has a big disadvantage: Oracle does not -> automaticaly free the temporary blob, so it shortly runs out of temp. -> space. (confirmed with "select * from v$temporary_lobs"). -> -> Acording to the Oracle docs this can be we solved by implicitly freeing -> the temp. blob, e.g. by calling the PLSQL method -> "dbms_lob.freetemporary()". I tried differnt ways to do this with -> DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -> locator from the my stored procedure and to pass it to a call of -> "dbms_lob.freetemporary()": -> -> my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -> ora_auto_lob => 0 }); -> my $bloc; -> $sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> -> obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) -> -> Can you help me??? Do you know a way how to free the temp. blob using -> DBD::Oracle (using Oracle::OCI is not possible, since the customer is -> strinctly refusing to install it). -> -> Otherwise, would it be possible include an additional DBD::Oracle LOB -> Locator Method "ora_lob_freetemporary()" that warps -> "OCILobFreeTemporary" ? -> -> Any help is really appreciated! -> -> Greeting from Germany, -> -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - -From SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com Thu Aug 26 14:06:45 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QD6Som051890 - for ; Thu, 26 Aug 2004 14:06:45 +0100 (BST) - (envelope-from SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 14:06:45 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0HX2-0003PB-Sd; - Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0HX2-0003PB-Sd - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0HX2-0003BR-F8 - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id DC4BFB0D27; - Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id CE95AB0D7D - for ; Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 81.169.145.165(natsmtp00.rzone.de) -Received: from natsmtp00.rzone.de (natsmtp00.rzone.de [81.169.145.165]) - by lime.pobox.com (Postfix) with ESMTP id 71107B0D27 - for ; Thu, 26 Aug 2004 06:30:56 -0400 (EDT) -Received: from genericom.de (pD9E61E09.dip.t-dialin.net [217.230.30.9]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7QAUoTY009695 - for ; Thu, 26 Aug 2004 12:30:51 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412DBBD7.2C124831@genericom.de> -Date: Thu, 26 Aug 2004 12:30:47 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------msB92907D67E7D4C0121D50420" -Status: O -X-Status: A -Content-Length: 3040 -Lines: 58 - -This is a cryptographically signed message in MIME format. - ---------------msB92907D67E7D4C0121D50420 -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Tim Bunce wrote: -> -> I hate asking for money, and would much rather dig into the code and -> reply with a patch, but it's just not practical for me now. Sorry. - -Thanks for your quick reply. I can fully understand your position in -this issue. We will need to submit this issue to our customer, and -eventually it will be their decision, since a) the problem technically -originates in external components -and b) our work is payed on a time and material basis. - -Thanks again, - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------msB92907D67E7D4C0121D50420 -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjYxMDMwNDhaMCMGCSqG -SIb3DQEJBDEWBBQbWUdl+peoD/lHpzCOnuQfzAsbJzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAXzFame8ymLqgf+7nZ4V7L9e9J+aG6z5ipa+iv76v -EFAg5QObdHdvTnq5QEAjEnLKgeUGvdgpS6PA0h+beEIeIA== ---------------msB92907D67E7D4C0121D50420-- - - -From SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com Thu Aug 26 16:42:55 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QFgKp1054926 - for ; Thu, 26 Aug 2004 16:42:55 +0100 (BST) - (envelope-from SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 16:42:55 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0L1E-0005sL-5Z; - Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0L1E-0005sL-5Z - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0L1E-0001t1-Cm - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 541E8AFAD6; - Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 1C39FB0747 - for ; Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail01.svc.cra.dublin.eircom.net (mail01.svc.cra.dublin.eircom.net [159.134.118.17]) - by lime.pobox.com (Postfix) with SMTP id BFBB5AFAD6 - for ; Thu, 26 Aug 2004 10:14:19 -0400 (EDT) -Received: (qmail 12246 messnum 7731352 invoked from network[213.94.228.233/unknown]); 26 Aug 2004 14:14:17 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail01.svc.cra.dublin.eircom.net (qp 12246) with SMTP; 26 Aug 2004 14:14:17 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QEItof052863; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7QEItr3052862; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) -Date: Thu, 26 Aug 2004 15:18:55 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040826141855.GC52359@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> <412DBBD7.2C124831@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412DBBD7.2C124831@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 926 -Lines: 25 - -Okay. Thanks. Let me know how it turns out. - -Tim. - -On Thu, Aug 26, 2004 at 12:30:47PM +0200, Philipp Lang wrote: -> Tim Bunce wrote: -> > -> > I hate asking for money, and would much rather dig into the code and -> > reply with a patch, but it's just not practical for me now. Sorry. -> -> Thanks for your quick reply. I can fully understand your position in -> this issue. We will need to submit this issue to our customer, and -> eventually it will be their decision, since a) the problem technically -> originates in external components -> and b) our work is payed on a time and material basis. -> -> Thanks again, -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - diff --git a/err_unicode/err_char.msg b/err_unicode/err_char.msg deleted file mode 100644 index d2a7a4a3..00000000 --- a/err_unicode/err_char.msg +++ /dev/null @@ -1,129 +0,0 @@ -From dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org Fri May 31 15:39:50 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g4VEdno73229 - for ; Fri, 31 May 2002 15:39:49 +0100 (BST) - (envelope-from dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 31 May 2002 15:39:49 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1022854157:20:06570:1; Fri, 31 May 2002 14:09:17 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2005972; 31 May 2002 14:08 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 210F42BF43 - for ; Fri, 31 May 2002 10:08:39 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (unknown [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 8D88B2BF11 - for ; Fri, 31 May 2002 10:08:38 -0400 (EDT) -Received: (qmail 47355 invoked by uid 1005); 31 May 2002 14:07:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 47340 invoked by uid 76); 31 May 2002 14:07:41 -0000 -Received: from wsrgeh.wsr.ac.at (HELO wsrgeh.wsr.ac.at) (143.130.16.2) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Fri May 31 14:07:41 2002 -0000 -Received: from dialog.wsr.ac.at (dialog.wsr.ac.at [143.130.50.66]) - by wsrgeh.wsr.ac.at (8.11.6/8.11.6) with ESMTP id g4VE8Or11772 - for ; Fri, 31 May 2002 16:08:24 +0200 -Received: (from hjp@localhost) - by dialog.wsr.ac.at (8.11.6/8.11.6) id g4VE8Nf12538 - for dbi-users@perl.org; Fri, 31 May 2002 16:08:23 +0200 -Date: Fri, 31 May 2002 16:08:23 +0200 -From: "Peter J. Holzer" -To: dbi-users@perl.org -Subject: Re: Insert a blank value into Oracle -Message-ID: <20020531160823.F28779@wsr.ac.at> -Mail-Followup-To: "Peter J. Holzer" , - dbi-users@perl.org -References: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw> -Mime-Version: 1.0 -Content-Type: multipart/signed; micalg=pgp-md5; - protocol="application/pgp-signature"; boundary="aZoGpuMECXJckB41" -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -In-Reply-To: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw>; from larry_wu@mail.gss.com.tw on Fri, May 31, 2002 at 06:38:45PM +0800 -Status: RO -Content-Length: 2819 -Lines: 74 - ---aZoGpuMECXJckB41 -Content-Type: text/plain; charset=iso-8859-1 -Content-Disposition: inline -Content-Transfer-Encoding: quoted-printable - -On 2002-05-31 18:38:45 +0800, Larry Wu (=A7d=A4l=B7=D3) wrote: -> I encountered a problem to insert a space value ( like ' ' ) into Oracle -> database. -[...] -> Unfortunately, I have a table A contained a not allow null column -> NotNullCol. Now I want to insert a row like below: ->=20 -> $sth =3D $dbh->prepare( qq{ insert into A ( KeyCol, NotNullCol ) -> values (?,?)} ); -> $sth->bind_param(1, '1'); -> $sth->bind_param(2, ' '); -> $sth->execute; ->=20 -> When I executed this file I got an error from Oracle: Can't insert NULL -> value into ( "A"."NotNullCol") (DBD ERROR: OCIStmtExecute). -> I think the space value was truncated in the process. Could any one tell = -me -> how to keep a blank space in my bind_param ? - -use DBD::Oracle qw(:ora_types); -[...] -$sth->bind_param(2, ' ', { ora_type =3D> ORA_CHAR }); - -This is a frequently asked question here. The default type for strings, -ORA_VARCHAR2, strips trailing blanks from strings. A few months ago, -during one of the diskussuions about this feature, Tim said that he -might add a way to change the default in a future version of -DBD::Oracle. If he doesn't, maybe a paragraph like the following should -be added to the doc (not sure where - it fits below "Using DBD::Oracle -with Oracle 8 - Features and Issues" but it isn't Oracle 8 specific): - - =3Dhead2 Inserting strings with trailing spaces - - OCI provides several string types which behave differently. - Unfortunately, none of them can store arbitrary perl strings. - By default, DBD::Oracle binds string variables as ORA_VARCHAR2, - which allows embedded NUL characters but strips trailing spaces. If - you need trailing spaces, but don't need embedded NUL characters, - you can explicetly bind the param to type ORA_CHAR with: - - $sth->bind_param(($field_num, $string_value, - { ora_type =3D> ORA_CHAR }); - - =20 - hp - ---=20 - _ | Peter J. Holzer | Aeltere Sources (also solche, die schon -|_|_) | Sysadmin WSR / LUGA | aelter als 12 Stunden sind) sollte man -| | | hjp@wsr.ac.at | bei Linux generell nicht einsetzen - -__/ | http://www.hjp.at/ | Real Time Linux?? -- Gerhard Schneider - ---aZoGpuMECXJckB41 -Content-Type: application/pgp-signature -Content-Disposition: inline - ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.0.6 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -iQDQAwUBPPeD11LjemazOuKpAQEtNAXUC6rFL0C0v6MNW/K5ggXcSDY7Xvrj6Ed/ -jqjHq2Dx+h2rIMWXCDIGZVphSG74u4FL41AQF/rzGR/e56qH7aAxVmaiLdQE/DRi -zzsoOHoPEg96FhHljDtCZyxHzsz9sRJ1dfW1PELn5r2OSYPPsVzMoeR4iEXnVjvV -ZYH/OfbKRKhysIHjcNYKcyQL87GXdjzCEas3Xz+jyxW2vqzGAwUfTim4ySY9rF37 -c5vopwrTFCsi58r1LccFhQqEfw== -=Xe8d ------END PGP SIGNATURE----- - ---aZoGpuMECXJckB41-- - diff --git a/err_unicode/err_twolongstr.msg b/err_unicode/err_twolongstr.msg deleted file mode 100644 index 5d6c357d..00000000 --- a/err_unicode/err_twolongstr.msg +++ /dev/null @@ -1,1256 +0,0 @@ -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Wed Nov 17 19:08:49 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAHJ8F8P027204 - for ; Wed, 17 Nov 2004 19:08:48 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 17 Nov 2004 19:08:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUUU6-0001mQ-FU; - Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUUU6-0001mQ-FU - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUUU6-0000DF-68 - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9D10A120BFA; - Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 8C898120BEF - for ; Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Received-SPF: none (icicle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by icicle.pobox.com (Postfix) with ESMTP id 362C6120BEC - for ; Wed, 17 Nov 2004 13:24:46 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 9C0CC244379 - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 17196-06 for ; - Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 3131324406F - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 10:22:44 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_006A_01C4CC8F.60A4F6F0" -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117173321.GA6272@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTMy6HoelzJHh9WSPaTpCdfuF1C4gABpsZg -Message-Id: <20041117182444.3131324406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 16865 -Lines: 527 - -This is a multi-part message in MIME format. - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -I did - it is attached to the posting. However, I will attach it again -here. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 9:33 AM -> To: Susan Cassidy -> Cc: dbi-users@perl.org -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> If you can post a small self-contained example that demonstrates -> the problem then I'll take a look. -> -> Tim. -> -> On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > I never got any response to my question about this problem. I -> thought I'd try again. -> > -> > -> > -> > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> 5.8.5. -> > -> > -> > -> > Thanks, -> > -> > Susan -> > -> > -> > -> > --------------------------------------------------------------------- -> ----------------------------------- -> > -> > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > Sent: Friday, November 05, 2004 10:23 AM -> > To: 'dbi-users@perl.org' -> > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for -> > insert into a LONG column' when data not LONG -> > -> > -> > -> > I had an application that was processing a bunch of xml and inserting -> into a table with a bunch of -> > VARCHAR2(4000) columns. -> > -> > -> > -> > A couple of the entries I was processing caused the 'ORA-01461: can -> bind a LONG value only for insert -> > into a LONG column' error. -> > -> > -> > -> > I put checks in for the length of the data, and nothing approached -> 4000 bytes in length. -> > -> > -> > -> > I tracked down some of the entries causing problems, and on certain -> specific data, if 2 columns -> > containing specific data are inserted together, I get this error. If -> only one of the 2 is inserted, I -> > do not get the error, regardless of which one of the two I insert. -> > -> > -> > -> > The lengths of the pieces of data are 1399 and 1397 characters. -> > -> > -> > -> > The data is somewhat odd-looking (we suspect some odd data is in this -> file), but there is no reason for -> > the error message to appear. -> > -> > -> > -> > Trace shows nothing helpful - it thinks the data is the right length. -> > -> > -> > -> > We've successfully inserted thousands of other, similar entries with -> no trouble. -> > -> > -> > -> > The basics are: -> > -> > #create table test_table (item1 varchar2(4000), item2 -> varchar2(4000)); -> > -> > -> > -> > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, ?)"; -> > -> > -> > -> > $sth=$dbh->prepare($statement) || -> > -> > errexit("bad prepare for stmt $statement, error: $DBI::errstr"); -> > -> > my $rc=$sth->execute(@vals) || -> > -> > errexit("can't execute statement: error: $DBI::errstr\n"); -> > -> > -> > -> > Trace shows: -> > -> > -> > -> > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > -> > -> prepare for DBD::Oracle::db (DBI::db=HASH(0x82d4178)~0x82d6580 -> 'INSERT INTO test_table -> > (item1,item2) VALUES (?, ?) -> > -> > ') thr#8148ff0 -> > -> > dbd_preparse scanned 2 distinct placeholders -> > -> > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl line -> 40 -> > -> > -> execute for DBD::Oracle::st (DBI::st=HASH(0x82d6640)~0x8149dcc -> 'version 11.2no service -> > password-encryptionservice -> > -> > udp-small-serversservice tcp-small-servers!hostname router1!!no ip -> domain-lookupip inspect name mysite -> > ftpip inspect name -> > -> > mysite smtpip inspect name mysite tcp!interface Ethernet0ip address -> 10.10.10.2 255.255.255.0ip -> > access-group 101 inip ins -> > -> > pect mysite inip inspect mysite outno keepalive!interface Serial0no -> ip addressencapsulation -> > frame-relay...' 'version 11.2 -> > -> > no service password-encryptionservice udp-small-serversservice tcp- -> small-servers!hostname router1!!no ip -> > domain-lookupip -> > -> > inspect name mysite ftpip inspect name mysite smtpip inspect name -> mysite tcp!interface Ethernet0ip -> > address 10.10.10.2 255 -> > -> > .255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite -> outno keepalive!interface Serial0no -> > ip addressencaps -> > -> > ulation frame-relayn...') thr#8148ff0 -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (type 0) -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (size -> 1399/1400/0, ptype 4, otype 1) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (type 0) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (size -> 1397/1398/0, ptype 4, otype 1) -> > -> > dbd_st_execute INSERT (out0, lob0)... -> > -> > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > <- execute= undef at test_insert_large.pl line 42 -> > -> > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> 'ParamValues') thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line 42 -> > -> > -> $DBI::errstr (&) FETCH from lasth=HASH -> > -> > >> DBD::Oracle::st::errstr -> > -> > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' -> > -> > -- DBI::END -> > -> > -> disconnect_all for DBD::Oracle::dr -> (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > -> > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > -> > Connect done -> > -> > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > -> > Size of vals is 2 -> > -> > val 1 size 1399, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!i -> > -> > nterface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11 -> > -> > .2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 IETF!router eigrp 69network -> > 10.0.0.0no auto-summar -> > -> > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0. -> > -> > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permit icmp 10.10.10.0 -> > 0.0.0.255 anyaccess- -> > -> > list 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-rep -> > -> > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 ad -> > -> > ministratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp a -> > -> > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 0.0.0.255 -> > time-exceededaccess-list 102 permit tcp -> > -> > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > val 2 size 1397, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11. -> > -> > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci 200 -> IETF!router eigrp 69network -> > 10.0.0.0no auto-summary -> > -> > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 0.0.0.0 -> 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0.0 -> > -> > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permiticmp 10.10.10.0 -> > 0.0.0.255 anyaccess-li -> > -> > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess-list -> 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-reply -> > -> > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 admi -> > -> > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp any -> > -> > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 time-exceededaccess-list -> > 102 permit tcp an -> > -> > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > can't execute statement: error: ORA-01461: can bind a LONG value only -> for insert into a LONG column (DBD -> > ERROR: OCIStmtEx -> > -> > ecute) -> > -> > -> > -> > ! -> DESTROY for DBD::Oracle::db (DBI::db=HASH(0x82d6580)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#0) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > -> > -> > I will attach the test program. Somehow it seems to think the -> datatype is LONG instead of VARCHAR. -> > -> > -> > -> > -> > -> > Anyone with ideas? -> > -> > -> > -> > -> > -> > Thanks, -> > -> > Susan -> - - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: application/octet-stream; - name="test_insert_large.pl" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="test_insert_large.pl" - -#!/usr/local/bin/perl -w=0A= -=0A= -use DBI;=0A= -=0A= -our $dbh;=0A= -our $sth;=0A= -=0A= -$dbuser=3D"proj1";=0A= -$dbpasswd=3D"proj1";=0A= -=0A= -$dbserver=3D'oracledev';=0A= -$db_sid=3D'AL32UTF8';=0A= -=0A= -##=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D connect to database = -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=0A= -=0A= -$dbh=3D DBI->connect("dbi:Oracle:host=3D$dbserver;sid=3D$db_sid", = -$dbuser, $dbpasswd,=0A= - {PrintError =3D> 0, AutoCommit =3D> 1}) or=0A= - errexit( "Unable to connect to $dbserver: $DBI::errstr");=0A= -print "Connect done\n";=0A= -=0A= -#create table test_table (item1 varchar2(4000), item2 varchar2(4000));=0A= -=0A= -=0A= -my $statement=3D"INSERT INTO test_table (item1,item2) VALUES (?, ?)";=0A= -print "stmt: $statement\n";=0A= -=0A= -@vals=3D(=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysite inip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permit icmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permiticmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= -);=0A= -=0A= -print "Size of vals is ",scalar @vals,"\n";=0A= -my $z=3D0;=0A= -foreach my $x (@vals) {=0A= - my $len=3Dlength($x);=0A= - print "val ",++$z, " size $len, is: '$x'\n";=0A= -}=0A= -=0A= -DBI->trace(2);=0A= - $sth=3D$dbh->prepare($statement) ||=0A= - errexit("bad prepare for stmt $statement, error: $DBI::errstr");=0A= - my $rc=3D$sth->execute(@vals) ||=0A= - errexit("can't execute statement: error: $DBI::errstr\n");=0A= -=0A= -print "Done\n";=0A= -exit;=0A= -=0A= -=0A= -sub errexit {=0A= - my (@msg)=3D@_;=0A= - print @msg,"\n";=0A= - exit 1;=0A= -}=0A= -=0A= -=0A= -=0A= - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0-- - - -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 00:15:21 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI0FC8G049539 - for ; Thu, 18 Nov 2004 00:15:21 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 00:15:21 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUVdd-0002Nv-CF; - Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUVdd-0002Nv-CF - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CUVdc-0005lu-Rs - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 4A256ADD6F; - Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3D82CADD64 - for ; Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Received-SPF: none (boggle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by boggle.pobox.com (Postfix) with ESMTP id B23D4ADCF6 - for ; Wed, 17 Nov 2004 14:38:15 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 0C9DF24435B - for ; Wed, 17 Nov 2004 11:38:14 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 18475-01 for ; - Wed, 17 Nov 2004 11:38:13 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id ACF0424406F - for ; Wed, 17 Nov 2004 11:38:13 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 11:36:14 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117192902.GA31595@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTM27+9yfJDVs3WQIWAKc6DR3EgdQAAKfgw -Message-Id: <20041117193813.ACF0424406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -X-Status: A -Content-Length: 14671 -Lines: 489 - -NLS_LANG=.UTF8 -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORACLE_HOME=/home/oracle/product/9.2.0 -ORACLE_SID=AL32UTF8 -ORACLE_BASE=/home/oracle - -NLS_NCHAR is not set, because we are not using any NVARCHAR data item, and -haven't needed it. - -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 11:29 AM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > I did - it is attached to the posting. However, I will attach it again -> > here. -> > -> > Thanks, -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 9:33 AM -> > > To: Susan Cassidy -> > > Cc: dbi-users@perl.org -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > If you can post a small self-contained example that demonstrates -> > > the problem then I'll take a look. -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > > > I never got any response to my question about this problem. I -> > > thought I'd try again. -> > > > -> > > > -> > > > -> > > > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> > > 5.8.5. -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > > -> > > > -> > > > -> > > > ----------------------------------------------------------------- -> ---- -> > > ----------------------------------- -> > > > -> > > > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > > > Sent: Friday, November 05, 2004 10:23 AM -> > > > To: 'dbi-users@perl.org' -> > > > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> > > 01461: can bind a LONG value only for -> > > > insert into a LONG column' when data not LONG -> > > > -> > > > -> > > > -> > > > I had an application that was processing a bunch of xml and -> inserting -> > > into a table with a bunch of -> > > > VARCHAR2(4000) columns. -> > > > -> > > > -> > > > -> > > > A couple of the entries I was processing caused the 'ORA-01461: -> can -> > > bind a LONG value only for insert -> > > > into a LONG column' error. -> > > > -> > > > -> > > > -> > > > I put checks in for the length of the data, and nothing -> approached -> > > 4000 bytes in length. -> > > > -> > > > -> > > > -> > > > I tracked down some of the entries causing problems, and on -> certain -> > > specific data, if 2 columns -> > > > containing specific data are inserted together, I get this error. -> If -> > > only one of the 2 is inserted, I -> > > > do not get the error, regardless of which one of the two I -> insert. -> > > > -> > > > -> > > > -> > > > The lengths of the pieces of data are 1399 and 1397 characters. -> > > > -> > > > -> > > > -> > > > The data is somewhat odd-looking (we suspect some odd data is in -> this -> > > file), but there is no reason for -> > > > the error message to appear. -> > > > -> > > > -> > > > -> > > > Trace shows nothing helpful - it thinks the data is the right -> length. -> > > > -> > > > -> > > > -> > > > We've successfully inserted thousands of other, similar entries -> with -> > > no trouble. -> > > > -> > > > -> > > > -> > > > The basics are: -> > > > -> > > > #create table test_table (item1 varchar2(4000), item2 -> > > varchar2(4000)); -> > > > -> > > > -> > > > -> > > > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, -> ?)"; -> > > > -> > > > -> > > > -> > > > $sth=$dbh->prepare($statement) || -> > > > -> > > > errexit("bad prepare for stmt $statement, error: -> $DBI::errstr"); -> > > > -> > > > my $rc=$sth->execute(@vals) || -> > > > -> > > > errexit("can't execute statement: error: $DBI::errstr\n"); -> > > > -> > > > -> > > > -> > > > Trace shows: -> > > > -> > > > -> > > > -> > > > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > > > -> > > > -> prepare for DBD::Oracle::db -> (DBI::db=HASH(0x82d4178)~0x82d6580 -> > > 'INSERT INTO test_table -> > > > (item1,item2) VALUES (?, ?) -> > > > -> > > > ') thr#8148ff0 -> > > > -> > > > dbd_preparse scanned 2 distinct placeholders -> > > > -> > > > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl -> line -> > > 40 -> > > > -> > > > -> execute for DBD::Oracle::st -> (DBI::st=HASH(0x82d6640)~0x8149dcc -> > > 'version 11.2no service -> > > > password-encryptionservice -> > > > -> > > > udp-small-serversservice tcp-small-servers!hostname router1!!no -> ip -> > > domain-lookupip inspect name mysite -> > > > ftpip inspect name -> > > > -> > > > mysite smtpip inspect name mysite tcp!interface Ethernet0ip -> address -> > > 10.10.10.2 255.255.255.0ip -> > > > access-group 101 inip ins -> > > > -> > > > pect mysite inip inspect mysite outno keepalive!interface -> Serial0no -> > > ip addressencapsulation -> > > > frame-relay...' 'version 11.2 -> > > > -> > > > no service password-encryptionservice udp-small-serversservice -> tcp- -> > > small-servers!hostname router1!!no ip -> > > > domain-lookupip -> > > > -> > > > inspect name mysite ftpip inspect name mysite smtpip inspect name -> > > mysite tcp!interface Ethernet0ip -> > > > address 10.10.10.2 255 -> > > > -> > > > .255.255.0ip access-group 101 inip inspect mysiteinip inspect -> mysite -> > > outno keepalive!interface Serial0no -> > > > ip addressencaps -> > > > -> > > > ulation frame-relayn...') thr#8148ff0 -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (type -> 0) -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (size -> > > 1399/1400/0, ptype 4, otype 1) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (type -> 0) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (size -> > > 1397/1398/0, ptype 4, otype 1) -> > > > -> > > > dbd_st_execute INSERT (out0, lob0)... -> > > > -> > > > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > <- execute= undef at test_insert_large.pl line 42 -> > > > -> > > > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> > > 'ParamValues') thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line -> 42 -> > > > -> > > > -> $DBI::errstr (&) FETCH from lasth=HASH -> > > > -> > > > >> DBD::Oracle::st::errstr -> > > > -> > > > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' -> > > > -> > > > -- DBI::END -> > > > -> > > > -> disconnect_all for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > > > -> > > > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > > > -> > > > Connect done -> > > > -> > > > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > > > -> > > > Size of vals is 2 -> > > > -> > > > val 1 size 1399, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!i -> > > > -> > > > nterface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11 -> > > > -> > > > .2 255.255.255.252ip access-group 102 inframe-relay interface- -> dlci -> > > 200 IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summar -> > > > -> > > > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> > > 0.0.0.0 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0. -> > > > -> > > > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permit icmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess- -> > > > -> > > > list 101 deny ip any anyaccess-list 102 permit eigrp any -> anyaccess- -> > > list 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-rep -> > > > -> > > > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 ad -> > > > -> > > > ministratively-prohibitedaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp a -> > > > -> > > > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> > > 10.10.10.0 0.0.0.255 -> > > > time-exceededaccess-list 102 permit tcp -> > > > -> > > > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line -> con -> > > 0line vty 0 4login!end' -> > > > -> > > > val 2 size 1397, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11. -> > > > -> > > > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 -> > > IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summary -> > > > -> > > > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 -> > > 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0.0 -> > > > -> > > > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permiticmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess-li -> > > > -> > > > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list -> > > 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-reply -> > > > -> > > > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 admi -> > > > -> > > > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp any -> > > > -> > > > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 time-exceededaccess-list -> > > > 102 permit tcp an -> > > > -> > > > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> > > 0line vty 0 4login!end' -> > > > -> > > > can't execute statement: error: ORA-01461: can bind a LONG value -> only -> > > for insert into a LONG column (DBD -> > > > ERROR: OCIStmtEx -> > > > -> > > > ecute) -> > > > -> > > > -> > > > -> > > > ! -> DESTROY for DBD::Oracle::db -> (DBI::db=HASH(0x82d6580)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#0) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY for DBD::Oracle::st -> (DBI::st=HASH(0x8149dcc)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > -> > > > -> > > > I will attach the test program. Somehow it seems to think the -> > > datatype is LONG instead of VARCHAR. -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Anyone with ideas? -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > -> > -> - - - -From SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 07:11:03 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI7Ar8G057950 - for ; Thu, 18 Nov 2004 07:11:03 GMT - (envelope-from SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 07:11:03 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUaCR-0002mS-7P; - Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUaCR-0002mS-7P - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUaCQ-0004JQ-R5 - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 17ACAA3F35; - Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from integer (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 04F8DA3EAC - for ; Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Received-SPF: none (integer.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by integer.pobox.com (Postfix) with ESMTP id A9FC6A3F4D - for ; Wed, 17 Nov 2004 19:30:43 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id DEA102441A9 - for ; Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 22204-10 for ; - Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 7AD52244370 - for ; Wed, 17 Nov 2004 16:30:40 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 16:28:41 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041118001712.GB49519@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTNA/o7HZXghXaJRbyz8M5kVQMQmwAAUBjg -Message-Id: <20041118003040.7AD52244370@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 1789 -Lines: 63 - -Hi, - -I set NLS_LANG to .US7ASCII, ran it again, and I get the same error. - -Of course, I could not use that in production. - -The really strange part, to me, was that if I just insert one of the 2 -problematic columns, it worked, but both together failed. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 4:17 PM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> And does the problem go away if NLS_LANG is set to a non-unicode charset? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 11:36:14AM -0800, Susan Cassidy wrote: -> > NLS_LANG=.UTF8 -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORACLE_HOME=/home/oracle/product/9.2.0 -> > ORACLE_SID=AL32UTF8 -> > ORACLE_BASE=/home/oracle -> > -> > NLS_NCHAR is not set, because we are not using any NVARCHAR data item, -> and -> > haven't needed it. -> > -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 11:29 AM -> > > To: Susan Cassidy -> > > Cc: 'Tim Bunce' -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > > > I did - it is attached to the posting. However, I will attach it -> again -> > > > here. -> > > > -> > > > Thanks, -> > > > Susan -> > > > - - diff --git a/err_unsorted/err_etherreal.msg b/err_unsorted/err_etherreal.msg deleted file mode 100644 index 1ad5c78e..00000000 --- a/err_unsorted/err_etherreal.msg +++ /dev/null @@ -1,90 +0,0 @@ -From dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org Tue Apr 30 14:47:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UDliR22576 - for ; Tue, 30 Apr 2002 14:47:44 +0100 (BST) - (envelope-from dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.23] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 14:47:44 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020172466:10:24548:59; Tue, 30 Apr 2002 13:14:26 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1023391; 30 Apr 2002 13:13 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id A94562C075 - for ; Tue, 30 Apr 2002 09:12:33 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id F24B22BFBE - for ; Tue, 30 Apr 2002 09:12:32 -0400 (EDT) -Received: (qmail 36589 invoked by uid 1005); 30 Apr 2002 13:12:28 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 36168 invoked by uid 76); 30 Apr 2002 13:10:41 -0000 -Content-Type: text/plain; - charset="iso-8859-1" -From: Calin Medianu -To: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Date: Tue, 30 Apr 2002 16:04:47 +0300 -X-Mailer: KMail [version 1.3.2] -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> <20020429233138.E16831@dansat.data-plan.com> -In-Reply-To: <20020429233138.E16831@dansat.data-plan.com> -Cc: dbi-users@perl.org -MIME-Version: 1.0 -Message-Id: <20020430131233.F24B22BFBE@dolly1.pobox.com> -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id g3UDliR22576 -Status: RO -X-Status: A -Content-Length: 1213 -Lines: 38 - -[Add note to DBD::Oracle docs about using ethereal to sniff Oracle packets] -[Not sure if this bug got fixed yet. Maybe not.] - -Me again with the slow cursors. - -I modified both queries to only return 10 rows. -I ran a sniffer (ethereal) on the NIC. It is pretty cool, it also decodes TNS. - -when I am using the SQL, it works like this, there are about 7 packets -received by my workstation to set up the session, then all 10 rows are in the -same packet, then there is another packet probably saying goodbye. - -When I am using the REF cursor, each row comes in it's own TNS packet, that -is why it is so slow! - -Any idea how to fix it? - -thanks a lot, - -Calin - -> On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> > Hello, -> > -> > I did the following. Wrote a perl script that retreves -> > data via a straight select from the database. Then I -> > wrote a stored procedure returning a ref cursor open -> > on the same select statement and retrieved the data as -> > well. Using the REF CURSOR/ sotred procedure was about -> > 3 time slower, that is 40 seconds instead of around -> > 10. -> > -> > Is this normal? Is this a problem with oracle or with -> > DBD::Oracle? -> -> DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. -> -> Get a level 3 trace and look for the "dbd_describe'd" line for the -> ref cursor. -> -> Tim. - diff --git a/err_unsorted/err_memleak2.msg b/err_unsorted/err_memleak2.msg deleted file mode 100644 index 97501852..00000000 --- a/err_unsorted/err_memleak2.msg +++ /dev/null @@ -1,476 +0,0 @@ -From mike@boom.net Fri Nov 28 22:23:33 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hASMLLnY018698 - for ; Fri, 28 Nov 2003 22:23:33 GMT - (envelope-from mike@boom.net) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 28 Nov 2003 22:23:33 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1APmgW-0006iM-9g; - Fri, 28 Nov 2003 17:45:40 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1APmgW-0006iM-9g - for pobox@dbi.demon.co.uk; Fri, 28 Nov 2003 17:45:40 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id E82CD95E03 - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B1EE595DFB - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: from abort.boom.net (abort.boom.net[69.36.241.24]) - by icicle.pobox.com (Postfix) with ESMTP - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: by abort.boom.net (Postfix, from userid 530) - id E3C8B8517A; Fri, 28 Nov 2003 09:45:36 -0800 (PST) -Date: Fri, 28 Nov 2003 09:45:36 -0800 -From: Mike Hedlund -To: dbi-users@perl.org -Cc: Tim.Bunce@pobox.com -Subject: Memory leak in DBD::Oracle 1.14 ... ? -Message-ID: <20031128174536.GJ10609@boom.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.5.4i -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id hASMLLnY018698 -Content-Length: 24309 -Lines: 434 - -I've attached a little script which replicates the problem on my machine as well as the build session log for DBD::Oracle 1.14. - -I've tested it using DBI 1.38 and DBI 1.28 with both DBD::Oracle 1.12 and 1.14. - -Regardless of the DBI version, DBD::Oracle 1.14 leaks on my system and DBD::Oracle 1.12 does not. I've noticed the leak when calling connect_cached(), do() (or prepare()/execute()/commit/finish). - --mike - - --------------------- script --------------- -#!/usr/bin/perl -use strict; -use DBI; - -my($dbp) = "dbi:Oracle:host=weirdo.com;port=1521;sid=SID"; -my($dbu) = "username"; -my($dbpass) = "password"; - -while (1) { - my($sth); - my(@row); - my($dbh) = DBI->connect_cached($dbp,$dbu,$dbpass) || die "Couldn't connect to oracle db: $DBI::errstr\n"; - -## -## uncomment these and it just leaks faster. -## -# $sth = $dbh->prepare("SELECT * from FROM_STATS"); -# $sth->execute; -# while(@row = $sth->fetchrow_array) { - ##print "row: @row\n"; -# } -# $sth->finish; -} -exit; ------------------------- end script -------------------- - - ------------- log --------------------------------------- -Script started on Fri 28 Nov 2003 09:11:15 AM PST -[mike@commando DBD-Oracle-1.14]$ setenv ORACLE_HOME /home/orahome -[mike@commando DBD-Oracle-1.14]$ make realclean -rm -f blib/script/ora_explain -rm -rf Oracle.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm ./blib Makefile.aperl blib/arch/auto/DBD/Oracle/extralibs.all perlmain.c tmon.out mon.out so_locations pm_to_blib *.o *.a perl.exe perl perl Oracle.bs Oracle.bso Oracle.def libOracle.def Oracle.exp Oracle.x core core.*perl.*.? *perl.core -mv Makefile Makefile.old > /dev/null 2>&1 -rm -rf blib/lib/auto/DBD/Oracle blib/arch/auto/DBD/Oracle -rm -rf DBD-Oracle-1.14 -rm -f blib/arch/auto/DBD/Oracle/Oracle.so blib/arch/auto/DBD/Oracle/Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.a -rm -f blib/lib/DBD/Oracle.pm blib/arch/auto/DBD/Oracle/dbdimp.h blib/lib/oraperl.ph -rm -f blib/arch/auto/DBD/Oracle/ocitrace.h blib/lib/Oraperl.pm -rm -f blib/arch/auto/DBD/Oracle/Oracle.h blib/arch/auto/DBD/Oracle/mk.pm -rm -f blib/lib/DBD/Oracle/GetInfo.pm -rm -rf Makefile Makefile.old -[mike@commando DBD-Oracle-1.14]$ perl Makefile.PL -v -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI - - Configuring DBD::Oracle ... - ->>> Remember to actually *READ* the README file! - Especially if you have any problems. - -Using Oracle in /home/orahome - -WARNING: could not decode oracle version from -/home/orahome/orainst/inspdver, or /home/orahome/install/unix.rgs -or from ORACLE_HOME path /home/orahome. -Oracle version based logic in Makefile.PL may produce erroneous results. - -Found header files in rdbms/public rdbms/demo. -Found /home/orahome/rdbms/demo/demo_rdbms.mk -Found /home/orahome/otrace/demo/atmoci.mk -Found /home/orahome/precomp/demo/proc/demo_proc.mk -Using /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/lib/env_rdbms.mk -Read a total of 2202 lines from /home/orahome/rdbms/lib/env_rdbms.mk (including inclusions) -Read a total of 2493 lines from /home/orahome/rdbms/demo/demo_rdbms.mk (including inclusions) -Deleted SHELL definition: SHELL=/bin/sh -Deleted LIB_EXT definition: LIB_EXT=a -Deleted OBJ_EXT definition: OBJ_EXT=o -Deleted AR definition: AR=ar -Deleted AS definition: AS=as -Deleted CC definition: CC=cc -Deleted CHMOD definition: CHMOD=chmod -Deleted CPP definition: CPP=cpp -Deleted ECHO definition: ECHO=echo -Deleted LD definition: LD=ld -Deleted PERL definition: PERL=perl -Deleted CFLAGS definition: CFLAGS=$(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ -Deleted OPTIMIZE definition: OPTIMIZE=$(OPTIMIZE3) -Deleted AR definition: AR=/usr/bin/ar -Deleted AS definition: AS=/usr/bin/as -Deleted LD definition: LD=/usr/bin/ld -Deleted CPP definition: CPP=/lib/cpp -Deleted CHMOD definition: CHMOD=/bin/chmod -Deleted ASFLAGS definition: ASFLAGS= -Deleting ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS definition: ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Deleting ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS33 definition: ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Appending '/home/orahome/rdbms/lib/libskgxpd.a /home/orahome/rdbms/lib/libskgxpu.a /home/orahome/rdbms/lib/libskgxpt.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxp9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxp9.a' to LIBS -Appending '/home/orahome/rdbms/lib/libskgxns.a /home/orahome/rdbms/lib/libskgxnd.a /home/orahome/rdbms/lib/libskgxnr.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxn9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxn9.a' to LIBS -Evaluating `cat $(LIBHOME)sysliblist` - expanded `cat /home/orahome/lib/sysliblist` - returned '-ldl -lm -lpthread -lnsl ' - -Attempting to discover Oracle OCI build rules -gcc -c -o DBD_ORA_OBJ.o DBD_ORA_OBJ.c -by executing: (make -f /home/orahome/rdbms/demo/demo_rdbms.mk build ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh' CC=echo OPTIMIZE= CCFLAGS= EXE=DBD_ORA_EXE OBJS=DBD_ORA_OBJ.o) -returned: -[echo -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh `cat /home/orahome/lib/sysliblist` -ldl -lm - -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -reduced to: -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -Oracle oci build command: - + -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - - - -System: perl5.008 linux stripples.devel.redhat.com 2.4.21-1.1931.2.382.entsmp #1 smp wed aug 6 17:18:52 edt 2003 i686 i686 i386 gnulinux -Compiler: gcc -O2 -g -pipe -march=i386 -mcpu=i686 -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -Linker: /usr/bin/ld -Sysliblist: -ldl -lm -lpthread -lnsl -Oracle makefiles would have used these definitions but we override them: - CC: cc - - CFLAGS: $(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) - [$(GFLAG) -O3 $(CDEBUG) $(CCFLAGS) -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -DLINUX -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS $(LPFLAGS) $(USRFLAGS)] - - LDFLAGS: -o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ - [-o $@ -L/home/orahome/rdbms/lib/ -L$(LIBHOME) -L$(LIBHOME)stubs/] - - -Linking with OTHERLDFLAGS = -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - [from 'build' rule] - - -MakeMaker (v6.03) -Checking if your kit is complete... -Looks good - ABSTRACT_FROM => q[Oracle.pm] - AUTHOR => q[Tim Bunce (dbi-users@perl.org)] - DEFINE => q[ -DUTF8_SUPPORT] - DIR => [] - EXE_FILES => [q[ora_explain]] - INC => q[-I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI] - NAME => q[DBD::Oracle] - OBJECT => q[$(O_FILES)] - PREREQ_PM => { DBI=>q[0] } - VERSION_FROM => q[Oracle.pm] - clean => { FILES=>q[Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm] } - dist => { DIST_DEFAULT=>q[clean distcheck disttest ci tardist], COMPRESS=>q[gzip -v9], PREOP=>q[$(MAKE) -f Makefile.old distdir], SUFFIX=>q[gz] } - dynamic_lib => { OTHERLDFLAGS=>q[ -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] } -Using PERL=/usr/bin/perl -LD_RUN_PATH=/home/orahome/lib:/home/orahome/rdbms/lib -Using DBD::Oracle 1.14. -Using DBD::Oracle 1.14. -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -Writing Makefile for DBD::Oracle - -*** If you have problems... - read all the log printed above, and the README and README.help files. - (Of course, you have read README by now anyway, haven't you?) - -[mike@commando DBD-Oracle-1.14]$ make -cp Oracle.pm blib/lib/DBD/Oracle.pm -cp Oracle.h blib/arch/auto/DBD/Oracle/Oracle.h -cp dbdimp.h blib/arch/auto/DBD/Oracle/dbdimp.h -cp oraperl.ph blib/lib/oraperl.ph -cp ocitrace.h blib/arch/auto/DBD/Oracle/ocitrace.h -cp Oraperl.pm blib/lib/Oraperl.pm -cp mk.pm blib/arch/auto/DBD/Oracle/mk.pm -cp lib/DBD/Oracle/GetInfo.pm blib/lib/DBD/Oracle/GetInfo.pm -/usr/bin/perl -p -e "s/~DRIVER~/Oracle/g" /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI/Driver.xst > Oracle.xsi -/usr/bin/perl /usr/lib/perl5/5.8.0/ExtUtils/xsubpp -typemap /usr/lib/perl5/5.8.0/ExtUtils/typemap Oracle.xs > Oracle.xsc && mv Oracle.xsc Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT dbdimp.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci7.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci8.c -Running Mkbootstrap for DBD::Oracle () -chmod 644 Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/home/orahome/lib:/home/orahome/rdbms/lib" gcc -shared -L/usr/local/lib Oracle.o dbdimp.o oci7.o oci8.o -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" blib/script/ora_explain -Manifying blib/man3/DBD::Oracle.3pm -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oraperl.3pm -[mike@commando DBD-Oracle-1.14]$ make test -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/base....... t/base.......ok 1/5 t/base.......ok 2/5 t/base.......ok 3/5 t/base.......ok 4/5 t/base.......ok 5/5 t/base.......ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/reauth.....skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.82 cusr + 0.33 csys = 4.15 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ make test TEST_VERBOSE=1 -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1, 'blib/lib', 'blib/arch')" t/*.t -t/base.......1..5 -ok 1 -ok 2 -ok 3 -ok 4 -ok 5 -ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/reauth.....ORACLE_USERID_2 not defined. -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.85 cusr + 0.32 csys = 4.17 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ perl _V-V -Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: - Platform: - osname=linux, osvers=2.4.21-1.1931.2.382.entsmp, archname=i386-linux-thread-multi - uname='linux str' - config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Dotherlibdirs=/usr/lib/perl5/5.8.0 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr' - hint=recommended, useposix=true, d_sigaction=define - usethreads=define use5005threads=undef' - useithreads=define usemultiplicity= - useperlio= d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=un uselongdouble= - usemymalloc=, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', - optimize='', - cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm' - ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)', gccosandvers='' -gccversion='3.2.2 200302' - intsize=r, longsize=r, ptrsize=5, doublesize=8, byteorder=1234 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - ivtype='long' -k', ivsize=4' -ivtype='l, nvtype='double' -o_nonbl', nvsize=, Off_t='', lseeksize=8 - alignbytes=4, prototype=define - Linker and Libraries: - ld='gcc' -l', ldflags =' -L/u' - libpth=/usr/local/lib /lib /usr/lib - libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil - perllibs= - libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libper - gnulibc_version='2.3.2' - Dynamic Linking: - dlsrc=dl_dlopen.xs, dlext=so', d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE' - cccdlflags='-fPIC' -ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5', lddlflags='s Unicode/Normalize XS/A' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING MULTIPLICITY USE_ITHREADS USE_LARGE_FILES PERL_IMPLICIT_CONTEXT - Locally applied patches: - MAINT18379 - Built under linux - Compiled at Aug 13 2003 11:47:58 - @INC: - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/site_perl/5.8.0 - /usr/lib/perl5/site_perl - /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/vendor_perl/5.8.0 - /usr/lib/perl5/vendor_perl - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - . -[mike@commando DBD-Oracle-1.14]$ ^D -Script done on Fri 28 Nov 2003 09:16:43 AM PST ------------- end log ----------------------------------- - - diff --git a/err_unsorted/err_multiora.msg b/err_unsorted/err_multiora.msg deleted file mode 100644 index 9f7bcf6c..00000000 --- a/err_unsorted/err_multiora.msg +++ /dev/null @@ -1,470 +0,0 @@ -From dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org Mon Jan 5 10:12:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05ACYn1063537 - for ; Mon, 5 Jan 2004 10:12:58 GMT - (envelope-from dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 10:12:58 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdQXY-0007a7-IO; - Mon, 05 Jan 2004 09:18:18 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdQXY-0007a7-IO - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 08:56:48 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id C92F0282F - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id B344B2B84 - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: (qmail 58691 invoked by uid 1005); 5 Jan 2004 08:56:38 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 58674 invoked by uid 76); 5 Jan 2004 08:56:38 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 05 Jan 2004 00:56:38 -0800 -Received: (qmail 17937 invoked by uid 225); 5 Jan 2004 08:56:36 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 17930 invoked by uid 507); 5 Jan 2004 08:56:36 -0000 -Received: from stone.sifira.dk (HELO mail.int.sifira.dk) (217.157.24.2) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Mon, 05 Jan 2004 00:56:05 -0800 -Received: from ash.int.sifira.dk (ash.int.sifira.dk [192.168.1.7]) by mail.int.sifira.dk (Postfix) with ESMTP id F127674F58; Mon, 5 Jan 2004 09:55:58 +0100 (MET) -Sender: kn@sifira.dk -To: "Anniballi, Fran" -Cc: -Subject: Re: Help - multiple Oracle versions -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -From: Kristian Nielsen -Date: 05 Jan 2004 09:55:59 +0100 -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Message-ID: <7sllomsrj4.fsf@ash.int.sifira.dk> -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-2.5 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_GNUS_UA version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1223 -Lines: 40 - -[Add notes to docs covering what's in this thread] - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - -From dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org Mon Jan 5 14:47:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05Ejvo1064760 - for ; Mon, 5 Jan 2004 14:47:30 GMT - (envelope-from dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 14:47:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdVCS-0004w0-Is; - Mon, 05 Jan 2004 13:55:22 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdVCS-0004w0-Is - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 13:55:21 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 548DE2C87 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 417692C81 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 08:55:19 -0500 (EST) -Received: (qmail 91728 invoked by uid 1005); 5 Jan 2004 13:55:17 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 48614 invoked by uid 76); 5 Jan 2004 12:24:01 -0000 -Delivered-To: dbi-users@perl.org -X-MimeOLE: Produced By Microsoft Exchange V6.0.6487.1 -content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; charset="iso-8859-1" -Subject: RE: Help - multiple Oracle versions -Date: Mon, 5 Jan 2004 07:23:23 -0500 -Message-ID: <6B003D25ADBDE347B5542AFE6A55B42E04537A09@tayexc13.americas.cpqcorp.net> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Help - multiple Oracle versions -Thread-Index: AcPTac0nADA1C8LsTdSTxpcvyeSNCgAHQWGQ -From: "Anniballi, Fran" -To: -Cc: -X-OriginalArrivalTime: 05 Jan 2004 12:23:24.0525 (UTC) FILETIME=[B6F761D0:01C3D386] -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.3 required=7.0 tests=CARRIAGE_RETURNS,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i05Ejvo1064760 -Status: RO -Content-Length: 1465 -Lines: 52 - -Thanks. Looks like this is what I'll need. - ------Original Message----- -From: kn@sifira.dk [mailto:kn@sifira.dk] -Sent: Monday, January 05, 2004 3:56 AM -To: Anniballi, Fran -Cc: dbi-users@perl.org -Subject: Re: Help - multiple Oracle versions - - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - - -From dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org Tue Jan 6 17:00:29 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i06GxrnC075337 - for ; Tue, 6 Jan 2004 17:00:29 GMT - (envelope-from dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 06 Jan 2004 17:00:29 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Adu0c-0004RW-9d; - Tue, 06 Jan 2004 16:24:47 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Adu0c-0004RW-9d - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 16:24:47 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 21A79495C - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 08B12494B - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 6 Jan 2004 11:24:45 -0500 (EST) -Received: (qmail 25114 invoked by uid 1005); 6 Jan 2004 16:24:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 25095 invoked by uid 76); 6 Jan 2004 16:24:42 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Tue, 06 Jan 2004 08:24:42 -0800 -Received: (qmail 16535 invoked by uid 225); 6 Jan 2004 16:24:39 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16527 invoked by uid 507); 6 Jan 2004 16:24:39 -0000 -Received: from mail.cybcon.com (HELO mail.cybcon.com) (216.190.188.5) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 06 Jan 2004 08:24:08 -0800 -Received: from poirot (dsl2-6.cybcon.com [208.186.116.6]) by mail.cybcon.com (8.11.6/8.11.6) with ESMTP id i06GNhn08916; Tue, 6 Jan 2004 08:23:43 -0800 -Subject: RE: Help - multiple Oracle versions -From: Jared Still -To: "Anniballi, Fran" -Cc: DBI List -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 (1.0.8-11) -Date: 06 Jan 2004 08:25:59 -0800 -Message-Id: <1073406359.324.244.camel@poirot.jks.com> -Mime-Version: 1.0 -X-CyberConnectics-MailScanner2-Information: Spam/Virus Scanned at CyberConnectics -X-CyberConnectics-MailScanner2: Found to be clean -X-CyberConnectics-MailScanner2-SpamCheck: -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.2 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_05_08,SUPERLONG_LINE version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 4050 -Lines: 102 - -I read quickly through this thread, so my apologies if someone -already pointed this out. - -It doesn't matter which version of Oracle you compiled DBD with, -you can connect to all your 8i/9i databases on any platform with it. - -Assume you compiled with 9i libs, and you can connect to 9i db's with -no problem, but are unable to connect to 8i, getting the error you -mentioned previously. - -It appears that you are changing your Oracle environment via the -oraenv shell script to change your ORACLE_HOME to the 8i version -of Oracle. - -If so, stop doing that. Just leave your environment at 9i, and -connect to your 8i database. It will be fine. This is the way -my linux server is setup, and DBD is used to connect to Oracle -versions 7.3, 8.1.6, 8.1.7 and 9.2.0 every day. - -At our site DBD is compiled with 8i libs so that we can still -connect to the version 7 databases. If you compile with 9i libs, -you will be unable to connect to version 7 databases. - -HTH - -Jared - - -On Sun, 2004-01-04 at 05:12, Anniballi, Fran wrote: -> This is all done on one UNIX box. -> -> If I try option one, it doesn't work. I can't access an oracle8 instance with oracle9 sqlplus (or the other way around). That is the real problem. Since I can't do this I have to reassign the pointers before I access it. I can do this fine with sqlplus but with dbi/dbd I have to compile with one or the other. -> -> For option two, if I have two versions of DBD:Oracle, how do I tell Perl which one to use? My scripts just say "/usr/bin/perl" in the first line. -> -> -----Original Message----- -> From: kn@sifira.dk [mailto:kn@sifira.dk] -> Sent: Saturday, January 03, 2004 1:04 PM -> To: dbi-users@perl.org -> Cc: Anniballi, Fran -> Subject: Re: Help - multiple Oracle versions -> -> -> "Anniballi, Fran" writes: -> -> > As soon as I recompile the same DBI/DBD with it pointing to Oracle 9 -> > environment (libraries), it doesn't work. It is looking for Oracle9 -> > library files and I obviously don't have it pointing to oracle9 -> > libraries when I access an Oracle 8 instance. Oracle 9 is not -> > compatible with Oracle 8 so I have to redirect the environment -> > variables at run time. -> -> It sounds like you are confusing the Oracle client version and the -> Oracle server version. -> -> Eg. if you set ORACLE_HOME to /usr/local/oracle8 (or whatever) and use -> /usr/local/oracle8/bin/sqlplus you are using the Oracle 8 client, while -> if you set it to /usr/local/oracle9 and call -> /usr/local/oracle9/bin/sqlplus, you are using the Oracle 9 client. -> -> Which Oracle instance you access is selected by the connection string; -> for example "sqlplus scott/tiger@DB8" might access the Oracle 8 -> instance, and "scott/tiger@DB9" might access the Oracle 9 instance. -> -> What people are telling you is that you can choose client version -> independently of the server version. For example, it is possible to set -> ORACLE_HOME to /usr/local/oracle9 and call -> -> /usr/local/oracle9/bin/sqlplus scott/tiger@DB8 -> -> to access the Oracle 8 instance with the Oracle 9 client. This of course -> requires that the definition for DB8 is present in the file -> /usr/local/oracle-9.2/network/admin/tnsnames.ora. -> -> So you should either -> -> 1. Use only the Oracle 9 client, not change ORACLE_HOME, and access both -> instances with Oracle 9 sqlplus and DBD::Oracle compiled against -> Oracle 9 libraries. -> -> or -> -> 2. Compile DBD::Oracle twice (once against Oracle 8 libraries, once -> against Oracle 9 libraries, just as you have two versions of sqlplus) -> and use each one with the proper ORACLE_HOME setting. -> -> My guess is that you will find possibility 1. the easiest. -> -> > The tnsnames.ora are all set. I did what you said already. -> > -> > Example: DBI/DBD will work fine if I compile the DBI/DBD pointing to -> > Oracle 8 environment(libraries) and access an Oracle 8 instance. I -> > didn't have to change tnsnames.ora -> -> Yes you do: You need to have BOTH Oracle instances defined in EACH -> tnsnames.ora. -> -> Hope this helps, -> -> - Kristian. - - - -From andy@andyh.co.uk Wed Jan 7 07:31:57 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i077VPn8081048 - for ; Wed, 7 Jan 2004 07:31:57 GMT - (envelope-from andy@andyh.co.uk) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 07 Jan 2004 07:31:57 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Ae0Yb-0002lT-IA; - Tue, 06 Jan 2004 23:24:17 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Ae0Yb-0002lT-IA - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 23:24:17 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 00D7C3C15 - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id CB5813BEA - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from mta03-svc.ntlworld.com (mta03-svc.ntlworld.com [62.253.162.43]) - by integer.pobox.com (Postfix) with ESMTP - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from excession ([80.2.244.47]) by mta03-svc.ntlworld.com - (InterMail vM.4.01.03.37 201-229-121-137-20020806) with SMTP - id <20040106232403.NEKJ9852.mta03-svc.ntlworld.com@excession>; - Tue, 6 Jan 2004 23:24:03 +0000 -Message-ID: <00bd01c3d4ac$e5713190$6564a8c0@excession> -From: "Andy Hassall" -To: "Eric Lenio" , "Tim Bunce" -Cc: -References: <20040102143310.GC27273@lenio.net> <20040104204914.GB60357@dansat.data-plan.com> <20040105123653.GA31473@lenio.net> <20040105223121.GG66760@dansat.data-plan.com> <20040106222634.GG11531@lenio.net> <20040106223845.GE78360@dansat.data-plan.com> <20040106225722.GI11531@lenio.net> -Subject: Re: DBI primary_key tests fail: oracle 8 -Date: Tue, 6 Jan 2004 23:29:14 -0000 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2800.1158 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 43 - -Eric Lenio wrote: -> OK Tim. One other note -- after reading through oracle docs, I think -> you might want to substitute 'session_user' for 'current_schema' in -> 'select sys_context(...)'. The definition of session_user is -> "returns the database -> user name by which the current user is authenticated" while -> current_schema is "returns the name of the default schema being used -> in the current session". -> Maybe it doesn't matter, I'm not an oracle guru by any stretch of the -> imagination. - -There's several usernames in the USERENV context: - -CURRENT_SCHEMA - -The schema/user used for unqualified object name resolution; by default the -user you logged in as, but alterable with 'alter session set -current_schema=x'. Useful for avoiding having to maintain loads of synonyms. - -CURRENT_USER - -The user you're currently authenticated as. Doesn't change in SQL and -anonymous PL/SQL, but changes within definer-rights PL/SQL stored procedures -to the owner of the stored procedure, since stored procs by default run with -the privileges of the owner, not the invoker. - -SESSION_USER - -Who you originally logged in as, and never changes (but see below). Looks -like the appropriate one to use. - -PROXY_USER - -I don't think DBD::Oracle supports proxy authentication so don't need to -worry about that one yet. Possibly a bit of a grey area if it does support -it in the future, since this would hold the username in the DSN, but it'd -reauthenticate and change the SESSION_USER on connect (which would probably -have to be specified as an attribute to the $dbh). - --- -Andy Hassall (andy@andyh.co.uk) icq(5747695) (http://www.andyh.co.uk) -Space: disk usage analysis tool (http://www.andyhsoftware.co.uk/space) - - diff --git a/err_unsorted/err_ora9ir2oci.msg b/err_unsorted/err_ora9ir2oci.msg deleted file mode 100644 index 7ed476e4..00000000 --- a/err_unsorted/err_ora9ir2oci.msg +++ /dev/null @@ -1,27 +0,0 @@ -http://otn.oracle.com/tech/oci/htdocs/oci9ir2_new_features - -OCI Session Pooling -Session Pooling is a new feature in Oracle 9i Database Release 2. -An application can now maintain a pool of sessions and use a session -from the pool when it needs it. This saves the time consuming process -of initiating a connection and authentication every time the process -needs a new session. Session Pooling is useful, especially when a -large number of stateless sessions are required for a very short -time. In a web scenario, where many users are connected for a short -time, and the primary operation is accessing data, it is a costly -operation to start up a new session every time. In such a scenario, -session pooling could boost up the performance. - -OCI Statement caching -Client-side statement caching is also introduced in Oracle9i Database -Release 2. This feature can be enabled at the time of session -creation. It allows users to have a cache of statements per session. -On the server, this means having cursors that ready to be used, -without the need to parse the statements again, and thus improving -performance significantly. With this feature enabled, applications -do not have to keep a track of the statements themselves, as the -OCI layer will do it for them. In addition, a tagging feature is -provided, which users can use as a key to save and search for -statements. - - diff --git a/err_unsorted/err_ref_type.msg b/err_unsorted/err_ref_type.msg deleted file mode 100644 index 26d86e14..00000000 --- a/err_unsorted/err_ref_type.msg +++ /dev/null @@ -1,115 +0,0 @@ -From dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org Wed Jul 23 18:40:02 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6NHUUA0010501 - for ; Wed, 23 Jul 2003 18:40:02 +0100 (BST) - (envelope-from dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 23 Jul 2003 18:40:02 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058948095:10:09585:8; Wed, 23 Jul 2003 08:14:55 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116163; 23 Jul 2003 8:14 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 88C1B21C024 - for ; Wed, 23 Jul 2003 04:13:51 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id AA89B21C082 - for ; Wed, 23 Jul 2003 04:13:50 -0400 (EDT) -Received: (qmail 26606 invoked by uid 1005); 23 Jul 2003 08:13:44 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 26590 invoked by uid 76); 23 Jul 2003 08:13:43 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Wed, 23 Jul 2003 01:13:43 -0700 -Received: (qmail 16360 invoked by uid 225); 23 Jul 2003 08:13:41 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16355 invoked by uid 507); 23 Jul 2003 08:13:41 -0000 -Received-SPF: unknown -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Wed, 23 Jul 2003 01:13:41 -0700 -Received: (qmail 5378 invoked from network); 23 Jul 2003 08:54:08 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 23 Jul 2003 08:54:08 -0000 -Received: (qmail 8984 invoked from network); 23 Jul 2003 08:13:49 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 23 Jul 2003 08:13:49 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Wed, 23 Jul 2003 10:13:49 +0200 (CEST) -Subject: Re: binding to parameters of type REF -From: Hendrik =?ISO-8859-1?Q?Fu=DF?= -To: dbi-users@perl.org -In-Reply-To: <1058865345.1241.56.camel@mars> -References: <1058865345.1241.56.camel@mars> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 -Date: 23 Jul 2003 10:11:49 +0200 -Message-Id: <1058947909.6353.5.camel@mars> -Mime-Version: 1.0 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.3 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,LARGE_HEX,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1354 -Lines: 56 - -I've also found out, that DBD::Oracle does not support type SQL_REF: -When not using DBD::Proxy I get: - - SQL type 20 for ':p1' is not fully supported, - bound as SQL_VARCHAR instead - -I even get segmentation faults when trying to fetch REF columns. :-( - -Any ideas? - -> Hi, -> -> I'm trying to bind a perl variable to an Oracle table reference with -> Oracle 9.2.0.3, DBD::Proxy and Perl::DBI 1.37 without success. I -> could'nt find help on this in the docs or list archives. I hope this is -> the right place to post. -> -> In SQL*Plus: -> -> SQL> desc getReference -> FUNCTION getReference RETURNS REF OF TABLETYPE -> -> SQL> select getReference() from dual; -> -> GETREFERENCE() -> ---------------------------------------------------------------------- -> 0000280209C229D2216EF6A5F4E030010A8D086AD3C204FC6EE0E46501E030010A8D08 -> 2CE703C0000E0000 -> -> -> My code: -> -> my $ref = undef; -> my $sth = $dbh->prepare('BEGIN ? := getReference(); END;'); -> $sth->bind_param_inout(1, \$ref, 128, SQL_REF ); -> $sth->execute(); -> -> yields: -> -> PLS-00382: expression is of wrong type -> -> -> Even fetching a reference does not work: -> -> my $sth = $dbh->prepare('SELECT getReference() FROM DUAL'); -> $sth->execute(); -> ($ref) = $sth->fetchrow_array(); -> -> yields undef in $ref. -> -> I'd very much appreciate your help. -> cheers, -> Hendrik - - - - diff --git a/err_unsorted/err_refcsr_rowcache.msg b/err_unsorted/err_refcsr_rowcache.msg deleted file mode 100644 index 5101d2ae..00000000 --- a/err_unsorted/err_refcsr_rowcache.msg +++ /dev/null @@ -1,85 +0,0 @@ -From dbi-users-bounce@isc.org Tue May 16 22:53:12 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id WAA29547; Tue, 16 May 2000 22:53:11 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <04730-2@oink>; Sat, 16 May 1970 22:51:48 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 958512876:10:15786:0; Tue, 16 May 2000 21:34:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1122388; 16 May 2000 21:33 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 661E53EC8; - Tue, 16 May 2000 14:33:38 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Tue, 16 May 2000 14:28:31 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id 7192F3E20 - for ; - Tue, 16 May 2000 14:28:27 -0700 (PDT) -Received: from anchor-post-34.mail.demon.net (anchor-post-34.mail.demon.net [194.217.242.92]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id OAA27204 - for ; - Tue, 16 May 2000 14:28:26 -0700 (PDT) env-from (Tim.Bunce@ig.co.uk) -Received: from ignite.demon.co.uk ([158.152.8.99] helo=oink) - by anchor-post-34.mail.demon.net with smtp (Exim 2.12 #1) - id 12rot7-000Mp4-0Y; Tue, 16 May 2000 22:28:25 +0100 -Received: from toad by oink with SMTP (PP) id <04650-0@oink>; - Sat, 16 May 1970 22:23:55 +0100 -Received: by toad.ig.co.uk (SMI-8.6/SMI-SVR4) id WAA29289; - Tue, 16 May 2000 22:23:50 +0100 -Date: Tue, 16 May 2000 22:23:50 +0100 -From: Tim Bunce -To: peter_dev@talk21.com -Cc: dbi-users@isc.org -Subject: Re: Oracle Stored Procs take longer than embedded SQL -Message-ID: <20000516222350.F28435@ig.co.uk> -References: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs>; from peter_dev@talk21.com on Tue, May 16, 2000 at 06:48:22PM +0100 -Organization: Paul Ingram Group, Software Systems, +44 1 483 862800 -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 1372 -Lines: 30 - -On Tue, May 16, 2000 at 06:48:22PM +0100, peter_dev@talk21.com wrote: -> I have a problem with the fetching of data from an Oracle Ref Cursor taking longer than the same query in Embeded SQL. -> -> $ get_sp.pl -> Fetched in 0.00774896144866943 seconds -> Completed in 0.106827020645142 seconds -> -> $ get_sql.pl -> Fetched in 0.00138604640960693 seconds -> Completed in 0.380790948867798 seconds -> -> In this example (Using the SCOTT/TIGER tables), while the Stored Procedure completed first, the actual fetch of the data took considerably longer. In a real situation (e.g. bigger tables ), this is easily the longest part of the task and causes the overall execution time to increase hugely. -> -> Any Help would be appreciated -> thanks - -Possibly related to the lack of a row cache on that statement handle. -You, or some kind volunteer, could probably hack that in without too -much work. - -Tim. - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_unsorted/err_refcsr_slow.msg b/err_unsorted/err_refcsr_slow.msg deleted file mode 100644 index 790d267d..00000000 --- a/err_unsorted/err_refcsr_slow.msg +++ /dev/null @@ -1,347 +0,0 @@ -From dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org Mon Apr 29 23:12:51 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TMCpR17212 - for ; Mon, 29 Apr 2002 23:12:51 +0100 (BST) - (envelope-from dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 29 Apr 2002 23:12:51 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020117986:10:17770:92; Mon, 29 Apr 2002 22:06:26 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1017591; 29 Apr 2002 22:06 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id 975037274A - for ; Mon, 29 Apr 2002 18:01:37 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by wormwood.pobox.com (Postfix) with SMTP id ED2897273F - for ; Mon, 29 Apr 2002 18:01:34 -0400 (EDT) -Received: (qmail 70462 invoked by uid 1005); 29 Apr 2002 21:59:33 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 20335 invoked by uid 76); 29 Apr 2002 20:18:55 -0000 -Message-ID: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Date: Mon, 29 Apr 2002 13:18:53 -0700 (PDT) -From: Calin Medianu -Reply-To: cmedianu@sfu.ca -Subject: DBD::Oracle Slow cursors -To: dbi-users@perl.org -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 568 -Lines: 21 - -Hello, - -I did the following. Wrote a perl script that retreves -data via a straight select from the database. Then I -wrote a stored procedure returning a ref cursor open -on the same select statement and retrieved the data as -well. Using the REF CURSOR/ sotred procedure was about -3 time slower, that is 40 seconds instead of around -10. - -Is this normal? Is this a problem with oracle or with -DBD::Oracle? - -Thanks, - -Calin Medianu - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org Tue Apr 30 00:06:36 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TN6aR17980 - for ; Tue, 30 Apr 2002 00:06:36 +0100 (BST) - (envelope-from dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 00:06:36 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020119533:20:05733:4; Mon, 29 Apr 2002 22:32:13 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2005393; 29 Apr 2002 22:32 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 4E6B73E6BF - for ; Mon, 29 Apr 2002 18:32:00 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-1.pobox.com (Postfix) with SMTP id BF79C3E6A0 - for ; Mon, 29 Apr 2002 18:31:59 -0400 (EDT) -Received: (qmail 87860 invoked by uid 1005); 29 Apr 2002 22:31:59 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 87844 invoked by uid 76); 29 Apr 2002 22:31:58 -0000 -Received: from mail01.svc.cra.dublin.eircom.net (HELO mail01.svc.cra.dublin.eircom.net) (159.134.118.17) - by onion.perl.org (qpsmtpd/0.07) with SMTP; Mon Apr 29 22:31:58 2002 -0000 -Received: (qmail 21911 messnum 119827 invoked from network[159.134.167.97/p865.as1.limerick1.eircom.net]); 29 Apr 2002 22:31:29 -0000 -Received: from p865.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.97) - by mail01.svc.cra.dublin.eircom.net (qp 21911) with SMTP; 29 Apr 2002 22:31:29 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g3TMVcR17579; - Mon, 29 Apr 2002 23:31:38 +0100 (BST) - (envelope-from timbo) -Date: Mon, 29 Apr 2002 23:31:38 +0100 -From: Tim Bunce -To: cmedianu@sfu.ca -Cc: dbi-users@perl.org -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020429233138.E16831@dansat.data-plan.com> -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020429201853.52283.qmail@web10007.mail.yahoo.com>; from calinm@yahoo.com on Mon, Apr 29, 2002 at 01:18:53PM -0700 -Content-Length: 651 -Lines: 20 - -On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> Hello, -> -> I did the following. Wrote a perl script that retreves -> data via a straight select from the database. Then I -> wrote a stored procedure returning a ref cursor open -> on the same select statement and retrieved the data as -> well. Using the REF CURSOR/ sotred procedure was about -> 3 time slower, that is 40 seconds instead of around -> 10. -> -> Is this normal? Is this a problem with oracle or with -> DBD::Oracle? - -DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. - -Get a level 3 trace and look for the "dbd_describe'd" line for the -ref cursor. - -Tim. - -From calinm@yahoo.com Tue Apr 30 22:02:56 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL2tR26878 - for ; Tue, 30 Apr 2002 22:02:55 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:02:55 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020198219:10:21718:114; Tue, 30 Apr 2002 20:23:39 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101732; 30 Apr 2002 20:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C6B4A2BFB4 - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10004.mail.yahoo.com (web10004.mail.yahoo.com [216.136.130.40]) - by dolly1.pobox.com (Postfix) with SMTP id 527BD2BF3D - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Message-ID: <20020430202321.54825.qmail@web10004.mail.yahoo.com> -Received: from [213.157.171.169] by web10004.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 13:23:20 PDT -Date: Tue, 30 Apr 2002 13:23:20 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -Cc: dbi-users@perl.org -In-Reply-To: <20020430140517.P16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 425 -Lines: 18 - -I "Solved" the problem. For Now.. I did -perl Makefile.PL -8 - -hoping that the buggy code would be recently added, -and it was. Now both the select and the cursor return -the data at the same speed, meaning fast.. - -Am I am missing much by not using the code for Oracle -8? - -Thanks, - -Calin - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From timbo@dansat.data-plan.com Wed May 1 16:49:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g41FnsR33994 - for ; Wed, 1 May 2002 16:49:54 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 May 2002 16:49:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020265865:20:10671:66; Wed, 01 May 2002 15:11:05 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-2.mail.demon.net - id aa2122069; 1 May 2002 15:10 GMT -Received: from cali-3.pobox.com (cali-3.pobox.com [64.71.166.116]) - by silk.pobox.com (Postfix) with ESMTP id F29CC3FDF2 - for ; Wed, 1 May 2002 11:09:52 -0400 (EDT) -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id E3A943E689 - for ; Wed, 1 May 2002 10:57:15 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id D1F523E688 - for ; Wed, 1 May 2002 10:57:14 -0400 (EDT) -Received: (qmail 96042 messnum 564683 invoked from network[159.134.166.63/p575.as1.limerick1.eircom.net]); 1 May 2002 14:57:13 -0000 -Received: from p575.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.63) - by mail03.svc.cra.dublin.eircom.net (qp 96042) with SMTP; 1 May 2002 14:57:13 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g41EvIh33626; - Wed, 1 May 2002 15:57:18 +0100 (BST) - (envelope-from timbo) -Date: Wed, 1 May 2002 15:57:18 +0100 -From: Tim Bunce -To: Calin Medianu -Cc: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020501155718.S16831@dansat.data-plan.com> -References: <20020430151126.Q16831@dansat.data-plan.com> <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020430183429.33340.qmail@web10005.mail.yahoo.com>; from calinm@yahoo.com on Tue, Apr 30, 2002 at 11:34:29AM -0700 -Status: RO -Content-Length: 3111 -Lines: 111 - -Thanks. I'll take a look when I get to DBD::Oracle again. - -I think the last row of that table applies and it doesn't refer to OCIBindObject(): - REF CURSOR variables - SQLT_RSET - Allocate a statement handle, OCIStmt, and then bind its address - (OCIStmt **) using the SQLT_RSET datatype. -Note that SQLT_REF isn't the same as SQLT_RSET. - -You could always try patching it yourself! - -Tim. - - -On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin Medianu wrote: -> It says here: -> http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> -> that 2 calls are neede to bind a ref , the second is -> to OCIBindObject() which I don't see in dbdimp.c. -> -> Could this be a reason? -> -> Cheers, -> -> Calin -> -> --- Tim Bunce wrote: -> > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > Medianu wrote: -> > > Me again with the slow cursors. -> > > -> > > I modified both queries to only return 10 rows. -> > > I ran a sniffer (ethereal) on the NIC. It is -> > pretty cool, it also decodes TNS. -> > > -> > > when I am using the SQL, it works like this, there -> > are about 7 packets -> > > received by my workstation to set up the session, -> > then all 10 rows are in the -> > > same packet, then there is another packet probably -> > saying goodbye. -> > > -> > > When I am using the REF cursor, each row comes in -> > it's own TNS packet, that -> > > is why it is so slow! -> > > -> > > Any idea how to fix it? -> > -> > Do a level 9 trace to get a log of the OCI calls and -> > confirm that -> > the fragment I posted is being called (may be -> > helpful to also -> > add an extra print statement into that code since -> > parsing the -> > OCI trace can be painful). -> > -> > Assuming the code is being called then as far as I -> > can see the code is -> > doing the right thing and it's probably an Oracle -> > OCI issue. -> > -> > You'd need to talk to Oracle support. No need to -> > mention perl etc. -> > Just talk about your OCI application and provide the -> > OCI call trace. -> > -> > Let me know what you find out! -> > -> > Tim. -> > -> > > thanks a lot, -> > > -> > > Calin -> > > -> > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> > Medianu wrote: -> > > > > Hello, -> > > > > -> > > > > I did the following. Wrote a perl script that -> > retreves -> > > > > data via a straight select from the database. -> > Then I -> > > > > wrote a stored procedure returning a ref -> > cursor open -> > > > > on the same select statement and retrieved the -> > data as -> > > > > well. Using the REF CURSOR/ sotred procedure -> > was about -> > > > > 3 time slower, that is 40 seconds instead of -> > around -> > > > > 10. -> > > > > -> > > > > Is this normal? Is this a problem with oracle -> > or with -> > > > > DBD::Oracle? -> > > > -> > > > DBD::Oracle. It probably isn't setting up a row -> > cache for the ref cursor. -> > > > -> > > > Get a level 3 trace and look for the -> > "dbd_describe'd" line for the -> > > > ref cursor. -> > > > -> > > > Tim. -> -> -> __________________________________________________ -> Do You Yahoo!? -> Yahoo! Health - your guide to health and wellness -> http://health.yahoo.com - diff --git a/err_unsorted/err_slowcsr.msg b/err_unsorted/err_slowcsr.msg deleted file mode 100644 index 80c43350..00000000 --- a/err_unsorted/err_slowcsr.msg +++ /dev/null @@ -1,316 +0,0 @@ -From calinm@yahoo.com Tue Apr 30 22:03:11 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL3AR27018 - for ; Tue, 30 Apr 2002 22:03:10 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:03:10 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020196981:10:23493:39; Tue, 30 Apr 2002 20:03:01 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-1.mail.demon.net - id aa1108477; 30 Apr 2002 20:02 GMT -Received: from dolly1.pobox.com (dolly1.pobox.com [207.106.49.22]) - by silk.pobox.com (Postfix) with ESMTP id 915563FCE8 - for ; Tue, 30 Apr 2002 14:35:38 -0400 (EDT) -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 343702BFDD - for ; Tue, 30 Apr 2002 14:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10005.mail.yahoo.com (web10005.mail.yahoo.com [216.136.130.41]) - by dolly1.pobox.com (Postfix) with SMTP id 6AA822BFA3 - for ; Tue, 30 Apr 2002 14:34:37 -0400 (EDT) -Message-ID: <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Received: from [213.157.171.169] by web10005.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 11:34:29 PDT -Date: Tue, 30 Apr 2002 11:34:29 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020430151126.Q16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 2457 -Lines: 96 - -It says here: -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 - -that 2 calls are neede to bind a ref , the second is -to OCIBindObject() which I don't see in dbdimp.c. - -Could this be a reason? - -Cheers, - -Calin - ---- Tim Bunce wrote: -> On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> Medianu wrote: -> > Me again with the slow cursors. -> > -> > I modified both queries to only return 10 rows. -> > I ran a sniffer (ethereal) on the NIC. It is -> pretty cool, it also decodes TNS. -> > -> > when I am using the SQL, it works like this, there -> are about 7 packets -> > received by my workstation to set up the session, -> then all 10 rows are in the -> > same packet, then there is another packet probably -> saying goodbye. -> > -> > When I am using the REF cursor, each row comes in -> it's own TNS packet, that -> > is why it is so slow! -> > -> > Any idea how to fix it? -> -> Do a level 9 trace to get a log of the OCI calls and -> confirm that -> the fragment I posted is being called (may be -> helpful to also -> add an extra print statement into that code since -> parsing the -> OCI trace can be painful). -> -> Assuming the code is being called then as far as I -> can see the code is -> doing the right thing and it's probably an Oracle -> OCI issue. -> -> You'd need to talk to Oracle support. No need to -> mention perl etc. -> Just talk about your OCI application and provide the -> OCI call trace. -> -> Let me know what you find out! -> -> Tim. -> -> > thanks a lot, -> > -> > Calin -> > -> > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> Medianu wrote: -> > > > Hello, -> > > > -> > > > I did the following. Wrote a perl script that -> retreves -> > > > data via a straight select from the database. -> Then I -> > > > wrote a stored procedure returning a ref -> cursor open -> > > > on the same select statement and retrieved the -> data as -> > > > well. Using the REF CURSOR/ sotred procedure -> was about -> > > > 3 time slower, that is 40 seconds instead of -> around -> > > > 10. -> > > > -> > > > Is this normal? Is this a problem with oracle -> or with -> > > > DBD::Oracle? -> > > -> > > DBD::Oracle. It probably isn't setting up a row -> cache for the ref cursor. -> > > -> > > Get a level 3 trace and look for the -> "dbd_describe'd" line for the -> > > ref cursor. -> > > -> > > Tim. - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From calinm@yahoo.com Fri May 3 13:48:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g43Cm5R50489 - for ; Fri, 3 May 2002 13:48:05 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 03 May 2002 13:48:05 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020429421:10:02019:143; Fri, 03 May 2002 12:37:01 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1123562; 3 May 2002 12:36 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id D7BD1725A1 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10008.mail.yahoo.com (web10008.mail.yahoo.com [216.136.130.44]) - by wormwood.pobox.com (Postfix) with SMTP id 3088772674 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Message-ID: <20020503123640.19648.qmail@web10008.mail.yahoo.com> -Received: from [213.157.171.169] by web10008.mail.yahoo.com via HTTP; Fri, 03 May 2002 05:36:40 PDT -Date: Fri, 3 May 2002 05:36:40 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020501155718.S16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -Content-Length: 3619 -Lines: 150 - -Sure, - -I'll give it a try next week. - -Cheers, - -Calin ---- Tim Bunce wrote: -> Thanks. I'll take a look when I get to DBD::Oracle -> again. -> -> I think the last row of that table applies and it -> doesn't refer to OCIBindObject(): -> REF CURSOR variables -> SQLT_RSET -> Allocate a statement handle, OCIStmt, and then -> bind its address -> (OCIStmt **) using the SQLT_RSET datatype. -> Note that SQLT_REF isn't the same as SQLT_RSET. -> -> You could always try patching it yourself! -> -> Tim. -> -> -> On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin -> Medianu wrote: -> > It says here: -> > -> -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> > -> > that 2 calls are neede to bind a ref , the second -> is -> > to OCIBindObject() which I don't see in dbdimp.c. -> > -> > Could this be a reason? -> > -> > Cheers, -> > -> > Calin -> > -> > --- Tim Bunce wrote: -> > > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > > Medianu wrote: -> > > > Me again with the slow cursors. -> > > > -> > > > I modified both queries to only return 10 -> rows. -> > > > I ran a sniffer (ethereal) on the NIC. It is -> > > pretty cool, it also decodes TNS. -> > > > -> > > > when I am using the SQL, it works like this, -> there -> > > are about 7 packets -> > > > received by my workstation to set up the -> session, -> > > then all 10 rows are in the -> > > > same packet, then there is another packet -> probably -> > > saying goodbye. -> > > > -> > > > When I am using the REF cursor, each row comes -> in -> > > it's own TNS packet, that -> > > > is why it is so slow! -> > > > -> > > > Any idea how to fix it? -> > > -> > > Do a level 9 trace to get a log of the OCI calls -> and -> > > confirm that -> > > the fragment I posted is being called (may be -> > > helpful to also -> > > add an extra print statement into that code -> since -> > > parsing the -> > > OCI trace can be painful). -> > > -> > > Assuming the code is being called then as far as -> I -> > > can see the code is -> > > doing the right thing and it's probably an -> Oracle -> > > OCI issue. -> > > -> > > You'd need to talk to Oracle support. No need to -> > > mention perl etc. -> > > Just talk about your OCI application and provide -> the -> > > OCI call trace. -> > > -> > > Let me know what you find out! -> > > -> > > Tim. -> > > -> > > > thanks a lot, -> > > > -> > > > Calin -> > > > -> > > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, -> Calin -> > > Medianu wrote: -> > > > > > Hello, -> > > > > > -> > > > > > I did the following. Wrote a perl script -> that -> > > retreves -> > > > > > data via a straight select from the -> database. -> > > Then I -> > > > > > wrote a stored procedure returning a ref -> > > cursor open -> > > > > > on the same select statement and retrieved -> the -> > > data as -> > > > > > well. Using the REF CURSOR/ sotred -> procedure -> > > was about -> > > > > > 3 time slower, that is 40 seconds instead -> of -> > > around -> > > > > > 10. -> > > > > > -> > > > > > Is this normal? Is this a problem with -> oracle -> > > or with -> > > > > > DBD::Oracle? -> > > > > -> > > > > DBD::Oracle. It probably isn't setting up a -> row -> > > cache for the ref cursor. -> > > > > -> > > > > Get a level 3 trace and look for the -> > > "dbd_describe'd" line for the -> > > > > ref cursor. -> > > > > -> > > > > Tim. -> > -> > -> > __________________________________________________ -> > Do You Yahoo!? -> > Yahoo! Health - your guide to health and wellness -> > http://health.yahoo.com - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - diff --git a/err_unsorted/err_svrparse.msg b/err_unsorted/err_svrparse.msg deleted file mode 100644 index 16886ca8..00000000 --- a/err_unsorted/err_svrparse.msg +++ /dev/null @@ -1,4717 +0,0 @@ -From cary.millsap@hotsos.com Thu Sep 12 23:38:20 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8CMbgC02618 - for ; Thu, 12 Sep 2002 23:38:03 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 12 Sep 2002 23:38:03 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031869308:20:16258:30; Thu, 12 Sep 2002 22:21:48 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2108888; 12 Sep 2002 22:21 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id A32132F05C9 - for ; Thu, 12 Sep 2002 18:21:34 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-3.pobox.com (Postfix) with ESMTP id D71F62F056D - for ; Thu, 12 Sep 2002 18:21:31 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8CMLQn17849; - Thu, 12 Sep 2002 17:21:26 -0500 -From: "Cary Millsap" -To: -Subject: -Date: Thu, 12 Sep 2002 17:21:17 -0500 -Message-ID: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_016A_01C25A80.D1527130" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 64884 -Lines: 2025 - -This is a multi-part message in MIME format. - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: multipart/alternative; - boundary="----=_NextPart_001_016B_01C25A80.D1557E70" - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -How are you doing? I hope you've had a good two years since I saw you on -the Oracle Geek Cruise event. - - - -I've been working on a project this year to construct a book about -optimizing Oracle response time. In my research, I've discovered -something about the DBI that I didn't expect: it executes two Oracle -parse calls for every one that I would expect an efficient DBI layer to -make. I've included my Perl source (below), the Oracle level-12 trace -data that shows the sequence of calls it's receiving from the Perl -application (below), a level-9 DBI trace from the application -(attached), and our version information (below). - - - -The reason I'm bringing this to your attention in this way is that I'm -relying pretty heavily upon Perl for performance measurement tools, -examples, and simulators in the text. I love the language and I want for -the book to be an encouragement for more people to use Perl. However, -this extra-parse behavior is one of the things that the book highlights -as an important scalability barrier (some other tools do it too, -unfortunately). Of course, this is a speed bump on the road to my goal -of helping to promote Perl. - - - -I was hoping that by showing you this specific data, you could make the -problem go away. - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - -Listing [listing.sqltrace.pl]: a simple application that executes a -database query - -#!/usr/bin/perl - - - - - -# $Header: /home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 21:10:25 -cvm Exp $ - -# Cary Millsap (cary.millsap@hotsos.com) - - - - - -use strict; - -use warnings; - -use DBI; - -use DBD::Oracle; - -use Getopt::Long; - -use Term::ReadKey; - - - - - -my $sth; # Oracle statement handle - -my $hostname = ""; - -my $username = "/"; - -my $password = ""; - -my $logfile = "ex1.log"; - -my %attr = ( - - RaiseError => 1, - - AutoCommit => 0, - -); - -my %opt = ( - - pause => 0, - -); - - - - - -# Get command line options and arguments. - -GetOptions( - - "pause" => \$opt{pause}, - -); - -my $key = 37; # default query value - -$key = $ARGV[0] if $ARGV[0]; - - - - - -# Connect to Oracle. - -my $dbh = DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr); - -$dbh->trace(9, $logfile); - - - - - -# Activate tracing. - -$sth = $dbh->prepare(q(alter session set events '10046 trace name -context forever, level 12')); - -$sth->execute; - - - - - -# Allow the user to find the Oracle session and activate OS diagnostic - -# tools like strace(1) or lsof(8). - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Execute the query to trace. - -$sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -$sth->execute($key); - - - - - -# Print output header. - -my @cdefs = qw(%8d %8d %32s); # column definitions - -my @hdefs = qw(Key Fkey Value); # column headings - -my $bformat = join(" ", @cdefs) . "\n"; - -my $hformat; ($hformat = $bformat) =~ s/%(\d*)\S+/%$1s/g; - -printf $hformat, @hdefs; - -printf $hformat, do { my @h; push @h, "-" x (/(\d+)/?$1:10) for @cdefs; -@h }; - - - - - -# Print query results. - -for my $row (@{$sth->fetchall_arrayref}) { - - printf $bformat, @$row; - -} - - - - - -# Allow the user to do final OS diagnostic stuff. - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Disconnect from Oracle. - -$dbh->disconnect; - - - - - -Listing [listing:sqltrace.trc]: raw SQL trace output for an execution of -our program - -/usr/local/oracle/admin/V816/udump/ora_17349.trc - -Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production - -With the Partitioning option - -JServer Release 8.1.6.0.0 - Production - -ORACLE_HOME = /usr/local/oracle/product/8.1.6 - -System name: Linux - -Node name: www.hotsos.com - -Release: 2.2.16-22enterprise - -Version: #1 SMP Tue Aug 22 16:29:32 EDT 2000 - -Machine: i686 - -Instance name: V816 - -Redo thread mounted by this instance: 1 - -Oracle process number: 8 - -Unix process pid: 17349, image: oracle@www.hotsos.com (TNS V1-V3) - - - -*** SESSION ID:(7.9) 2002-09-12 16:14:01.582 - -===================== - -PARSING IN CURSOR #1 len=69 dep=0 uid=12 oct=42 lid=12 tim=107309054 -hv=1509700594 ad='54af5e14' - -alter session set events '10046 trace name context forever, level 12' - -END OF STMT - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107309054 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -*** 2002-09-12 16:14:31.226 - -WAIT #1: nam='SQL*Net message from client' ela= 2964 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -WAIT #2: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #2: nam='SQL*Net message from client' ela= 0 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -BINDS #1: - - bind 0: dty=1 mxl=32(04) mal=00 scl=00 pre=00 oacflg=25 oacfl2=10 -size=32 offset=0 - - bfp=0940e7f0 bln=32 avl=04 flg=05 - - value="8542" - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #1: nam='file open' ela= 0 p1=0 p2=0 p3=0 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6671 p3=1 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6678 p3=1 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - -*** 2002-09-12 16:14:56.200 - -WAIT #1: nam='SQL*Net message from client' ela= 2496 p1=1650815232 p2=1 -p3=0 - -XCTEND rlbk=0, rd_only=1 - -STAT #1 id=1 cnt=1 pid=0 pos=0 obj=5156 op='TABLE ACCESS BY INDEX ROWID -T ' - -STAT #1 id=2 cnt=2 pid=1 pos=1 obj=5157 op='INDEX UNIQUE SCAN ' - - - - - -$ perl -V - -Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration: - - Platform: - - osname=linux, osvers=2.2.5-22smp, archname=i386-linux - - uname='linux porky.devel.redhat.com 2.2.5-22smp #1 smp wed jun 2 -09:11:51 edt 1999 i686 unknown ' - - config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -Dcc=gcc --Dcccdlflags=-fPIC -Dinstallprefix=/usr -Dprefix=/usr --Darchname=i386-linux -Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm --Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Uuselargefiles' - - hint=recommended, useposix=true, d_sigaction=define - - usethreads=undef use5005threads=undef useithreads=undef -usemultiplicity=undef - - useperlio=undef d_sfio=undef uselargefiles=undef - - use64bitint=undef use64bitall=undef uselongdouble=undef -usesocks=undef - - Compiler: - - cc='gcc', optimize='-O2 -march=i386 -mcpu=i686', gccversion=2.96 -20000731 (experimental) - - cppflags='-fno-strict-aliasing' - - ccflags ='-fno-strict-aliasing' - - stdchar='char', d_stdstdio=define, usevfork=false - - intsize=4, longsize=4, ptrsize=4, doublesize=8 - - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', -lseeksize=4 - - alignbytes=4, usemymalloc=n, prototype=define - - Linker and Libraries: - - ld='gcc', ldflags =' -L/usr/local/lib' - - libpth=/usr/local/lib /lib /usr/lib - - libs=-lnsl -ldl -lm -lc -lcrypt - - libc=/lib/libc-2.1.92.so, so=so, useshrplib=false, libperl=libperl.a - - Dynamic Linking: - - dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' - - cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' - - - - - -Characteristics of this binary (from libperl): - - Compile-time options: - - Built under linux - - Compiled at Aug 7 2000 10:59:51 - - @INC: - - /usr/lib/perl5/5.6.0/i386-linux - - /usr/lib/perl5/5.6.0 - - /usr/lib/perl5/site_perl/5.6.0/i386-linux - - /usr/lib/perl5/site_perl/5.6.0 - - /usr/lib/perl5/site_perl - - . - - - - - -Other site information - -- Redhat Linux 7.0 - -- Oracle 8.1.6.1.0 - -- DBD-Oracle 1.12 - -- DBI 1.30 - - - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

How are you doing? I hope you’ve had a good two = -years -since I saw you on the Oracle Geek Cruise event.

- -

 

- -

I’ve been working on a project this year to = -construct -a book about optimizing Oracle response time. In my research, I’ve -discovered something about the DBI that I didn’t expect: it = -executes two -Oracle parse calls for every one that I would expect an efficient DBI = -layer to -make. I’ve included my Perl source (below), the Oracle level-12 = -trace -data that shows the sequence of calls it’s receiving from the Perl = -application -(below), a level-9 DBI trace from the application (attached), and our = -version information -(below).

- -

 

- -

The reason I’m bringing this to your attention = -in this -way is that I’m relying pretty heavily upon Perl for performance -measurement tools, examples, and simulators in the text. I love the = -language -and I want for the book to be an encouragement for more people to use = -Perl. -However, this extra-parse behavior is one of the things that the book = -highlights -as an important scalability barrier (some other tools do it too, = -unfortunately). -Of course, this is a speed bump on the road to my goal of helping to = -promote Perl.

- -

 

- -

I was hoping that by showing you this specific data, = -you -could make the problem go away.

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -
- -

Listing [listing.sqltrace.pl]: a simple = -application that -executes a database query

- -
- -
- -

#!/usr/bin/perl

- -

- -

- -

 

- -

 

- -

# = -$Header: -/home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 = -21:10:25 cvm Exp $

- -

- -

# = -Cary Millsap (cary.millsap@hotsos.com)

- -

- -

 

- -

 

- -

use = -strict;

- -

- -

use = -warnings;

- -

- -

use = -DBI;

- -

- -

use = -DBD::Oracle;

- -

- -

use = -Getopt::Long;

- -

- -

use = -Term::ReadKey;

- -

- -

 

- -

 

- -

my -$sth;           &n= -bsp;        -# Oracle statement handle

- -

- -

my = -$hostname =3D -"";

- -

- -

my = -$username =3D -"/";

- -

- -

my = -$password =3D -"";

- -

- -

my = -$logfile  -=3D "ex1.log";

- -

- -

my = -%attr =3D (

- -

- -

    -RaiseError =3D> 1,

- -

- -

    -AutoCommit =3D> 0,

- -

- -

);

- -

- -

my = -%opt =3D (

- -

- -

    -pause   =3D> 0,

- -

- -

);

- -

- -

 

- -

 

- -

# Get = -command line -options and arguments.

- -

- -

GetOptions(

- -

- -

    -"pause" =3D> \$opt{pause},

- -

- -

);

- -

- -

my = -$key =3D -37;           &nbs= -p;  - # default query value

- -

- -

$key = -=3D $ARGV[0] if -$ARGV[0];

- -

- -

 

- -

 

- -

# = -Connect to -Oracle.

- -

- -

my = -$dbh =3D -DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr);

- -

- -

$dbh->trace(9, -$logfile);

- -

- -

 

- -

 

- -

# = -Activate -tracing.

- -

- -

$sth = -=3D -$dbh->prepare(q(alter session set events '10046 trace name context = -forever, -level 12'));

- -

- -

$sth->execute;

- -

- -

 

- -

 

- -

# = -Allow the user -to find the Oracle session and activate OS diagnostic

- -

- -

# = -tools like -strace(1) or lsof(8).

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Execute the -query to trace.

- -

- -

$sth = -=3D -$dbh->prepare(q(select key, fkey, value from t where = -key=3D?));

- -

- -

$sth->execute($key);

- -

- -

 

- -

 

- -

# = -Print output -header.

- -

- -

my = -@cdefs =3D qw(%8d -%8d %32s);   # column definitions

- -

- -

my = -@hdefs =3D qw(Key -Fkey Value); # column headings

- -

- -

my = -$bformat =3D -join("  ", @cdefs) . "\n";

- -

- -

my = -$hformat; -($hformat =3D $bformat) =3D~ s/%(\d*)\S+/%$1s/g;

- -

- -

printf $hformat, -@hdefs;

- -

- -

printf $hformat, -do { my @h; push @h, "-" x (/(\d+)/?$1:10) for = -@cdefs; @h };

- -

- -

 

- -

 

- -

# = -Print query -results.

- -

- -

for = -my $row -(@{$sth->fetchall_arrayref}) {

- -

- -

    -printf $bformat, @$row;

- -

- -

}

- -

- -

- -

 

- -

 

- -

# = -Allow the user -to do final OS diagnostic stuff.

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Disconnect from -Oracle.

- -

- -

$dbh->disconnect;

- -
- -

 

- -

 

- -
- -

Listing [listing:sqltrace.trc]: raw SQL trace = -output for -an execution of our program

- -
- -
- -

/usr/local/oracle/admin/V816/udump/ora_17349.tr= -c

- -

Oracle8i Enterprise -Edition Release 8.1.6.1.0 - Production

- -

With = -the -Partitioning option

- -

JServer Release -8.1.6.0.0 - Production

- -

ORACLE_HOME =3D -/usr/local/oracle/product/8.1.6

- -

System -name:        Linux

- -

Node name:  = -www.hotsos.com

- -

Release:    = -2.2.16-22enterprise

- -

Version:    #1 -SMP Tue Aug 22 16:29:32 EDT 2000

- -

Machine:    = -i686

- -

Instance name: -V816

- -

Redo = -thread -mounted by this instance: 1

- -

Oracle process -number: 8

- -

Unix = -process pid: -17349, image: oracle@www.hotsos.com (TNS V1-V3)

- -

 

- -

*** = -SESSION -ID:(7.9) 2002-09-12 16:14:01.582

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D69 dep=3D0 uid=3D12 oct=3D42 lid=3D12 = -tim=3D107309054 hv=3D1509700594 -ad=3D'54af5e14'

- -

alter = -session set -events '10046 trace name context forever, level 12'

- -

END = -OF STMT

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -309054

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

*** = -2002-09-12 -16:14:31.226

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2964 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#2 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312018 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

WAIT = -#2: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#2: -nam=3D'SQL*Net message from client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312019 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

BINDS = -#1:

- -

 bind 0: -dty=3D1 mxl=3D32(04) mal=3D00 scl=3D00 pre=3D00 oacflg=3D25 oacfl2=3D10 = -size=3D32 offset=3D0

- -

   bfp=3D0940e7f0 bln=3D32 avl=3D04 flg=3D05

- -

   -value=3D"8542"

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#1: nam=3D'file -open' ela=3D 0 p1=3D0 p2=3D0 p3=3D0

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6671 p3=3D1

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6678 p3=3D1

- -

FETCH -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

*** = -2002-09-12 -16:14:56.200

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2496 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

XCTEND rlbk=3D0, -rd_only=3D1

- -

STAT = -#1 id=3D1 cnt=3D1 -pid=3D0 pos=3D0 obj=3D5156 op=3D'TABLE ACCESS BY INDEX ROWID T = -'

- -

STAT = -#1 id=3D2 cnt=3D2 -pid=3D1 pos=3D1 obj=3D5157 op=3D'INDEX UNIQUE SCAN '

- -
- -

 

- -

 

- -

$ perl -V

- -

Summary of my perl5 (revision 5.0 version 6 subversion 0) = -configuration:

- -

  Platform:

- -

    osname=3Dlinux, osvers=3D2.2.5-22smp, = -archname=3Di386-linux

- -

    uname=3D'linux porky.devel.redhat.com = -2.2.5-22smp #1 smp -wed jun 2 09:11:51 edt 1999 i686 unknown '

- -

    config_args=3D'-des -Doptimize=3D-O2 = --march=3Di386 -mcpu=3Di686 --Dcc=3Dgcc -Dcccdlflags=3D-fPIC -Dinstallprefix=3D/usr -Dprefix=3D/usr = --Darchname=3Di386-linux --Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm -Di_gdbm -Di_shadow = --Di_syslog -Dman3ext=3D3pm -Uuselargefiles'

- -

    hint=3Drecommended, useposix=3Dtrue, = -d_sigaction=3Ddefine

- -

    usethreads=3Dundef use5005threads=3Dundef = -useithreads=3Dundef -usemultiplicity=3Dundef

- -

    useperlio=3Dundef d_sfio=3Dundef = -uselargefiles=3Dundef

- -

    use64bitint=3Dundef use64bitall=3Dundef = -uselongdouble=3Dundef -usesocks=3Dundef

- -

  Compiler:

- -

    cc=3D'gcc', optimize=3D'-O2 -march=3Di386 = --mcpu=3Di686', gccversion=3D2.96 -20000731 (experimental)

- -

    = -cppflags=3D'-fno-strict-aliasing'

- -

    ccflags = -=3D'-fno-strict-aliasing'

- -

    stdchar=3D'char', d_stdstdio=3Ddefine, = -usevfork=3Dfalse

- -

    intsize=3D4, longsize=3D4, ptrsize=3D4, = -doublesize=3D8

- -

    d_longlong=3Ddefine, longlongsize=3D8, = -d_longdbl=3Ddefine, -longdblsize=3D12

- -

    ivtype=3D'long', ivsize=3D4, = -nvtype=3D'double', nvsize=3D8, Off_t=3D'off_t', -lseeksize=3D4

- -

    alignbytes=3D4, usemymalloc=3Dn, = -prototype=3Ddefine

- -

  Linker and Libraries:

- -

    ld=3D'gcc', ldflags =3D' = --L/usr/local/lib'

- -

    libpth=3D/usr/local/lib /lib = -/usr/lib

- -

    libs=3D-lnsl -ldl -lm -lc = --lcrypt

- -

    libc=3D/lib/libc-2.1.92.so, so=3Dso, = -useshrplib=3Dfalse, libperl=3Dlibperl.a

- -

  Dynamic Linking:

- -

    dlsrc=3Ddl_dlopen.xs, dlext=3Dso, = -d_dlsymun=3Dundef, ccdlflags=3D'-rdynamic'

- -

    cccdlflags=3D'-fPIC', lddlflags=3D'-shared = --L/usr/local/lib'

- -

 

- -

 

- -

Characteristics of this binary (from libperl): = -

- -

  Compile-time options:

- -

  Built under linux

- -

  Compiled at Aug  7 2000 10:59:51

- -

  @INC:

- -

    = -/usr/lib/perl5/5.6.0/i386-linux

- -

    /usr/lib/perl5/5.6.0

- -

    = -/usr/lib/perl5/site_perl/5.6.0/i386-linux

- -

    = -/usr/lib/perl5/site_perl/5.6.0

- -

    /usr/lib/perl5/site_perl

- -

    .

- -

 

- -

 

- -

Other site information

- -

- Redhat Linux 7.0

- -

- Oracle 8.1.6.1.0

- -

- DBD-Oracle 1.12

- -

- DBI 1.30

- -

 

- -
- - - - - -------=_NextPart_001_016B_01C25A80.D1557E70-- - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: application/octet-stream; - name="ex1.log" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="ex1.log" - - DBI::db=3DHASH(0x8235a74) trace level set to 9 in DBI 1.30-nothread=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'alter session set events '10046 trace name context forever, level 12'')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240f68)=3D>DBI::st=3DHASH(0x8240f98),= - DBD::Oracle::st, 8240f74, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= -OCIHandleAlloc(0x82465d8,0x826c948,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826bf48,0x82559ec,'alter session set events '10046 = -trace name context forever, level 12'',69,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0x826c94c,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql ALTER=0A= - dbd_describe skipped for ALTER=0A= - <- prepare=3D DBI::st=3DHASH(0x8240f68) at ex1.pl line 38=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240f68)~0x8240f98)=0A= - dbd_st_execute ALTER (out0, lob0)...=0A= -OCIStmtExecute(0x82557c4,0x826bf48,0x82559ec,1,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff654,(nil),9,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute ALTER returned (SUCCESS, rpc0, fn52, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 39=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'select key, fkey, value from t where key=3D?')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240fe0)=3D>DBI::st=3DHASH(0x8240fb0),= - DBD::Oracle::st, 8240fec, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= - dbd_preparse scanned 1 distinct placeholders=0A= -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where = -key=3D:p1',44,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql SELECT=0A= - dbd_describe SELECT (EXPLICIT, lb 80)...=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3DSUCCES= -S=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3dc,(nil),18,0x82559ec)=3DSUCC= -ESS=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d1c0,1)=3DSUCCESS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d6,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d4,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d8,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1da,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1db,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1e8,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 1: 'KEY' NO null , otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d200,2)=3DSUCCESS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d216,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d214,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d218,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d228,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 2: 'FKEY' NULLable, otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d240,3)=3DSUCCESS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d256,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d254,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d258,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d268,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 3: 'VALUE' NULLable, otype 1-> 5, dbsize 32/33, p32.s0=0A= -OCIAttrSet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3d4,4,11,0x82559ec)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d1c4,0x82559ec,1,0x826e8d0,134,5,0x826d438,= -0x826d448,0x826d458,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d204,0x82559ec,2,0x826eaf8,134,5,0x826ca28,= -0x826ca38,0x826ca48,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d244,0x82559ec,3,0x826cbb8,33,5,0x826ca58,0= -x826cbe0,0x826cbf0,0)=3DSUCCESS=0A= - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231)=0A= - <- prepare=3D DBI::st=3DHASH(0x8240fe0) at ex1.pl line 50=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240f98)~INNER)=0A= -OCIHandleFree(0x826bf48,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef at ex1.pl line 51=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240fe0)~0x8240fb0 = -'8542')=0A= - bind :p1 <=3D=3D '8542' (type 0)=0A= - bind :p1 <=3D=3D '8542' (size 4/5/0, ptype 7, otype 1)=0A= - bind :p1 <=3D=3D '8542' (size 4/4, otype 1, indp 0, at_exec 1)=0A= -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb= -6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS=0A= -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da= -090)=3DSUCCESS=0A= - bind :p1 done with ftype 1=0A= - dbd_st_execute SELECT (out0, lob0)...=0A= - in ':p1' [0,0]: len 4, ind 0=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 51=0A= - -> fetchall_arrayref for DBD::Oracle::st = -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0)=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DSUCCESS=0A= - dbih_setup_fbav for 3 fields =3D> 0x8240fbc=0A= - dbd_st_fetch 3 fields SUCCESS=0A= - 0 (rc=3D0): '8542'=0A= - 1 (rc=3D0): '8542'=0A= - 2 (rc=3D0): 'value'=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DNO_DATA=0A= - dbd_st_fetch no-more-data=0A= - <- fetchall_arrayref=3D [ ARRAY(0x82411f0) ] row1 at ex1.pl line 62=0A= - -> disconnect for DBD::Oracle::db = -(DBI::db=3DHASH(0x8235b34)~0x8235a74)=0A= -OCISessionEnd(0x82557c4,0x82559ec,0x826c384,0)=3DSUCCESS=0A= -OCIServerDetach(0x8255834,0x82559ec,0)=3DSUCCESS=0A= - <- disconnect=3D 1 at ex1.pl line 74=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240fb0)~INNER)=0A= -OCIHandleFree(0x826e4a0,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -> DESTROY for DBD::Oracle::db (DBI::db=3DHASH(0x8235a74)~INNER)=0A= -OCIHandleFree(0x826c384,OCI_HTYPE_SESSION)=3DSUCCESS=0A= -OCIHandleFree(0x8255834,OCI_HTYPE_SERVER)=3DSUCCESS=0A= -OCIHandleFree(0x82557c4,OCI_HTYPE_SVCCTX)=3DSUCCESS=0A= -OCIHandleFree(0x82559ec,OCI_HTYPE_ERROR)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -------=_NextPart_000_016A_01C25A80.D1527130-- - - -From timbo@dansat.data-plan.com Fri Sep 13 07:30:31 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6UUC04053 - for ; Fri, 13 Sep 2002 07:30:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:30:30 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031871608:20:03733:55; Thu, 12 Sep 2002 23:00:08 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id ab2122693; 12 Sep 2002 23:00 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id AE0642F0B8A - for ; Thu, 12 Sep 2002 18:58:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id 931D42F0D0A - for ; Thu, 12 Sep 2002 18:58:19 -0400 (EDT) -Received: (qmail 57270 messnum 519666 invoked from network[159.134.164.69/p69.as1.limerick1.eircom.net]); 12 Sep 2002 22:58:17 -0000 -Received: from p69.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.69) - by mail03.svc.cra.dublin.eircom.net (qp 57270) with SMTP; 12 Sep 2002 22:58:17 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8CMwEQ02798; - Thu, 12 Sep 2002 23:58:14 +0100 (BST) - (envelope-from timbo) -Date: Thu, 12 Sep 2002 23:58:14 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls -Message-ID: <20020912225814.GG539@dansat.data-plan.com> -References: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 3530 -Lines: 77 - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCESS - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 '8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCESS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - -From cary.millsap@hotsos.com Fri Sep 13 07:31:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6VsC04590 - for ; Fri, 13 Sep 2002 07:31:54 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:31:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031889643:20:09494:0; Fri, 13 Sep 2002 04:00:43 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-2.mail.demon.net - id aa2008866; 13 Sep 2002 4:00 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id C94C67264F - for ; Fri, 13 Sep 2002 00:00:07 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by wormwood.pobox.com (Postfix) with ESMTP id A821072676 - for ; Fri, 13 Sep 2002 00:00:06 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D405n19404 - for ; Thu, 12 Sep 2002 23:00:05 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 22:59:56 -0500 -Message-ID: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020912225814.GG539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4825 -Lines: 129 - -Tim, - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Thursday, September 12, 2002 5:58 PM -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you -on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer -to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make -the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I -can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect -that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - - -From timbo@dansat.data-plan.com Fri Sep 13 10:48:59 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D9mwC06022 - for ; Fri, 13 Sep 2002 10:48:58 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 10:48:58 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031907122:20:19599:21; Fri, 13 Sep 2002 08:52:02 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2129553; 13 Sep 2002 8:52 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 99E263E660 - for ; Fri, 13 Sep 2002 04:51:54 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-2.pobox.com (Postfix) with SMTP id 721613E637 - for ; Fri, 13 Sep 2002 04:51:53 -0400 (EDT) -Received: (qmail 29161 messnum 524631 invoked from network[159.134.167.5/p773.as1.limerick1.eircom.net]); 13 Sep 2002 08:51:51 -0000 -Received: from p773.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.5) - by mail03.svc.cra.dublin.eircom.net (qp 29161) with SMTP; 13 Sep 2002 08:51:51 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8D8prO05752; - Fri, 13 Sep 2002 09:51:53 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 09:51:53 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913085153.GJ539@dansat.data-plan.com> -References: <20020912225814.GG539@dansat.data-plan.com> <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 6172 -Lines: 154 - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more "official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -> key=:p1',44,1,0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - -From cary.millsap@hotsos.com Fri Sep 13 17:52:40 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DGqdC10778 - for ; Fri, 13 Sep 2002 17:52:39 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 17:52:39 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031932999:10:25604:102; Fri, 13 Sep 2002 16:03:19 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101673; 13 Sep 2002 16:03 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E4A692C078 - for ; Fri, 13 Sep 2002 12:02:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 1609E2C03F - for ; Fri, 13 Sep 2002 12:02:29 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DG2Sn24856 - for ; Fri, 13 Sep 2002 11:02:28 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Fri, 13 Sep 2002 11:02:20 -0500 -Message-ID: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913085153.GJ539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 9234 -Lines: 248 - -Tim, - -I think it's important for a developer to have the ability to turn this -on and off. But I would argue that 0 is the correct default. I think of -it as a probability times cost function. The cost of leaving the setting -at 1 accidentally in a production application is pretty high: if the app -doesn't scale (because it's parsing too much), then it jeopardizes the -business' ability to succeed with it. - -The probability of leaving the option set to 1 accidentally during -production is very high. A point in evidence is that I didn't find the -parameter until I corresponded personally with you. I in fact *still* -don't know where to find it. I've checked Descartes & Bunce, perldoc -DBI, and perldoc DBD::Oracle without finding it yet... - -If the default were 0, the probability of leaving the option set to 0 -accidentally during development would be much lower. A developer faced -with a SQL syntax problem he doesn't understand will do the research -necessary to fix that problem. He can't release his code until he does. - -The problem with the default of 1 is, in my opinion, that most -developers will never learn of the feature, and they'll accidentally -leave it turned on in production. The proportion of developers who -competently performance-test their code is, unfortunately, -microscopically small. But they all do some level of functional testing. - -I would recommend making the ora_check_sql feature a more prominently -documented feature, presumably in "perldoc DBD::Oracle". - -I did learn in a test that specifying the option in the DBI->connect() -call doesn't do anything. Is it possible that you could allow us to -specify it at the connection level? The workaround is to do something -like this: - - use Getopt::Long; - my %prepare_attr = (ora_check_sql=>0); - GetOptions("dev"=>\$dev); - $prepare_attr{ora_check_sql} = 1 if $dev; - # developer must specify the command-line flag to get the -unscalable - # behavior that's necessary for functional testing - ... - $sth = $dbh->prepare($sql, %prepare_attr); # MUST specify -%p..attr - -...But I doubt that most Oracle application developers would come up -with this without some coaching. - -I'll definitely keep an eye open for projects you might like. It would -be a hell of an opportunity for someone to have you, I think. It seems -that if you could make a list like Oracle-L (1,900 people) aware that -there's an opportunity, it would improve your chances of finding -something quickly. It's of course bad taste to advertise oneself overtly -on those lists, but there is almost always a clever way to do it anyway -without offending anyone. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:52 AM -To: Cary Millsap -Cc: 'Tim Bunce' -Subject: Re: two Oracle parse calls - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge -to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our -lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a -preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more -"official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw -you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 -trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret -them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t -where -> key=:p1',44,1,0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: -231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), -{ -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call -parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:37 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLbC13725 - for ; Fri, 13 Sep 2002 23:21:37 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:37 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031951069:20:15816:152; Fri, 13 Sep 2002 21:04:29 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2120669; 13 Sep 2002 21:04 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 544863E642 - for ; Fri, 13 Sep 2002 17:04:17 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id 0AE7C3E667 - for ; Fri, 13 Sep 2002 17:04:16 -0400 (EDT) -Received: (qmail 16221 messnum 355694 invoked from network[159.134.166.226/p738.as1.limerick1.eircom.net]); 13 Sep 2002 21:04:14 -0000 -Received: from p738.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.226) - by mail05.svc.cra.dublin.eircom.net (qp 16221) with SMTP; 13 Sep 2002 21:04:14 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DL4Lx12642; - Fri, 13 Sep 2002 22:04:21 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:04:21 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913210421.GR539@dansat.data-plan.com> -References: <20020913085153.GJ539@dansat.data-plan.com> <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 3078 -Lines: 70 - -On Fri, Sep 13, 2002 at 11:02:20AM -0500, Cary Millsap wrote: -> Tim, -> -> I think it's important for a developer to have the ability to turn this -> on and off. But I would argue that 0 is the correct default. I think of -> it as a probability times cost function. The cost of leaving the setting -> at 1 accidentally in a production application is pretty high: if the app -> doesn't scale (because it's parsing too much), then it jeopardizes the -> business' ability to succeed with it. -> -> The probability of leaving the option set to 1 accidentally during -> production is very high. A point in evidence is that I didn't find the -> parameter until I corresponded personally with you. I in fact *still* -> don't know where to find it. I've checked Descartes & Bunce, perldoc -> DBI, and perldoc DBD::Oracle without finding it yet... - -It's not documented. - -As I recall it... originally DBD::Oracle defered the describe as -long as possible. But people reported very slow select performance: - - http://www.faqchest.com/prgm/dbi-l/dbi-99/dbi-9910/dbi-991005/dbi99101218_28018.html - -Turned out that the row cache logic needed the describe to try to -work out an optimal row cache size. Without the describe the row -cache wasn't getting set up. - -At some point I added code that would just set OCI_ATTR_PREFETCH_MEMORY -to a set size if ora_check_sql was 0. But I can't remember now why -I left ora_check_sql=1. - -It was possibly in relation to wanting to be able to use the -OCI_ATTR_PARSE_ERROR_OFFSET attribute to be able to highlight the -point in a query where the error was detected. But I think execute() -needs to be able to do that anyway (to catch syntax errors in -non-select statements). - -There is another problem. If the describe has been defered and the -application uses $sth->{NAME} or other similar attribute then the -describe has to be done at that point. The code is thee to do that -but the problem is how should the DBI behave if there's an error -in the SQL? It currently always croaks (rather than return undef, -in order to give a useful error message), but that's rather surprising -behaviour to many people and very unhelpful to some. - -There may well be other subtle issues that I can't recall right now. - -> I would recommend making the ora_check_sql feature a more prominently -> documented feature, presumably in "perldoc DBD::Oracle". -> -> I did learn in a test that specifying the option in the DBI->connect() -> call doesn't do anything. Is it possible that you could allow us to -> specify it at the connection level? - -By making it a database handle attribute, yes, that would be my plan. - -> I'll definitely keep an eye open for projects you might like. It would -> be a hell of an opportunity for someone to have you, I think. - -Thanks. - -> It seems that if you could make a list like Oracle-L (1,900 people) aware -> that there's an opportunity, it would improve your chances of finding -> something quickly. It's of course bad taste to advertise oneself overtly -> on those lists, but there is almost always a clever way to do it anyway -> without offending anyone. - -:-) - -Tim. - -From cary.millsap@hotsos.com Fri Sep 13 07:32:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6W1C04656 - for ; Fri, 13 Sep 2002 07:32:01 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:32:01 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031891038:20:04710:44; Fri, 13 Sep 2002 04:23:58 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id ab2004623; 13 Sep 2002 4:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 942A82BF2C - for ; Fri, 13 Sep 2002 00:23:44 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 73C982BF33 - for ; Fri, 13 Sep 2002 00:23:42 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D4Ndn19584 - for ; Thu, 12 Sep 2002 23:23:39 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 23:23:30 -0500 -Message-ID: <019301c25add$53f5dfd0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0194_01C25AB3.6B1FD7D0" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -Content-Length: 36859 -Lines: 1209 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Well, that was easy. Setting ora_check_sql=>0 does solve the problem. - - - -I now shift into "Please make 0 the default" mode. - - - -Here are the Oracle trace files, by the way, with a splash of color to -illustrate how the Oracle kernel sees what's going on (I hope you have -an HTML mail reader)... - - - -With {ora_check_sql=>1} (or no setting at all), here's what Oracle does -for the application: - - - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - - - -The PARSING IN CURSOR section tells us what SQL it is that we're -executing. Each line beginning with "PARSE" is emitted only when Oracle -executes a parse call. There are two. The first is wasted. - - - -Here's the same application with {ora_check_sql=>1} (the official new -default value, I am sure :-)): - - - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=109776065 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -FETCH #1:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=109776065 - - - -One parse call; problem solved. - - - -Thank you sincerely for your help. - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- -From: Cary Millsap [mailto:cary.millsap@hotsos.com] -Sent: Thursday, September 12, 2002 11:00 PM -To: 'Tim Bunce' -Subject: RE: two Oracle parse calls - - - -Tim, - - - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - - - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- - -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] - -Sent: Thursday, September 12, 2002 5:58 PM - -To: Cary Millsap - -Cc: tim.bunce@pobox.com - -Subject: two Oracle parse calls - - - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: - -> Tim, - -> - -> How are you doing? I hope you've had a good two years since I saw you -on - -> the Oracle Geek Cruise event. - - - -Yes thanks. And you? - - - -> I've been working on a project this year to construct a book about - -> optimizing Oracle response time. In my research, I've discovered - -> something about the DBI that I didn't expect: it executes two Oracle - -> parse calls for every one that I would expect an efficient DBI layer -to - -> make. I've included my Perl source (below), the Oracle level-12 trace - -> data that shows the sequence of calls it's receiving from the Perl - -> application (below), a level-9 DBI trace from the application - -> (attached), and our version information (below). - -> - -> I was hoping that by showing you this specific data, you could make -the - -> problem go away. - - - -I can only do what OCI lets me do... but within that I'll do what I -can... - - - -I'm not familar with Oracle trace logs so I can't readily intrepret them - -and I'll take what you say at face value. - - - -But I am familar with DBD::Oracle :) and the logs it writes :) - - - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -> $sth->execute($key); - - - - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - - dbd_preparse scanned 1 distinct placeholders - -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS - -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - - dbd_st_prepare'd sql SELECT - - dbd_describe SELECT (EXPLICIT, lb 80)... - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') - -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS - -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - - bind :p1 done with ftype 1 - - dbd_st_execute SELECT (out0, lob0)... - - in ':p1' [0,0]: len 4, ind 0 - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - - <- execute= '0E0' at ex1.pl line 51 - - - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - - - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -call that prepare() does. - - - -It doesn't do that for non-select statements so you could check if - -non-selects also have two parse calls. - - - -Also try doing - - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - - - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the - -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -is possibly redundant and could be removed (but Oracle ought to detect -that - -anyway and not make a round-trip for it, and certainly not call parse). - - - -If non-selects only have one parse call but ora_check_sql=>0 doesn't - -fix selects, then I might be able to do a simple patch to avoid the - -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - - - -Then the issue will be: should ora_check_sql=>0 be the default... - - - -Tim. - - - -p.s. I'd love a copy of your book when it's ready! - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Well, that was easy. Setting ora_check_sql=3D>0 = -does solve the -problem.

- -

 

- -

I now shift into "Please make 0 the = -default" mode.

- -

 

- -

Here are the Oracle trace files, by the way, with a = -splash -of color to illustrate how the Oracle kernel sees what’s going on = -(I hope -you have an HTML mail reader)...

- -

 

- -

With {ora_check_sql=3D>1} (or no setting at all), = -here’s -what Oracle does for the application:

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #2 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312018 = -hv=3D1997601641 ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF STMT

- -

PARSE = -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312019 = -hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF = -STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

FETCH = -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

 

- -

The PARSING IN CURSOR section tells us what SQL it is = -that -we’re executing. Each line beginning with “PARSE” is = -emitted -only when Oracle executes a parse call. There are two. The first is = -wasted.

- -

 

- -

Here’s the same application with = -{ora_check_sql=3D>1} (the official new = -default value, I -am sure J):

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 = -dep=3D0 uid=3D12 -oct=3D3 lid=3D12 tim=3D109776065 hv=3D1997601641 = -ad=3D'54af1384'

- -

select key, fkey, value from = -t where -key=3D:p1

- -

END OF STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

FETCH = -#1:c=3D0,e=3D0,p=3D0,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D109= -776065

- -

 

- -

One parse call; problem solved.

- -

 

- -

Thank you sincerely for your help.

- -

 

- -

 

- -

Cary = -Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System = -Performance, -Feb 9-12 Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 = -Middelfart Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----
-From: Cary Millsap [mailto:cary.millsap@hotsos.com]
-Sent: Thursday, September 12, 2002 11:00 PM
-To: 'Tim Bunce'
-Subject: RE: two Oracle parse calls

- -

 

- -

Tim,

- -

 

- -

Thanks so very much. The attribute ora_check_sql=3D>0 is new = -knowledge -to me; this is a nice reward for having written to you. I will test it = -either -tonight or the first thing tomorrow and then inform you of the results -immediately after that. If it solves the problem, then I will lobby you = -to make -0 the default value and probably consider the issue "problem = -solved."

- -

 

- -

Things are very well, thank you. I've been at home with my = -family now -for over three straight weeks, and we're having a nice time of our lives = -these -days with the business settling into stride a bit. Tonight is a big = -night for -me. I've just crossed the line of accepting a preliminary offer from = -O'Reilly. -This book project has actually been underway for quite some time now, = -but as of -tonight it's quite a bit more "official."

- -

 

- -

 

- -

Cary Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec = -9-11 -Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System Performance, Feb = -9-12 -Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 Middelfart = -Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----

- -

From: Tim Bunce [mailto:Tim.Bunce@pobox.com]

- -

Sent: Thursday, September 12, 2002 5:58 PM

- -

To: Cary Millsap

- -

Cc: tim.bunce@pobox.com

- -

Subject: two Oracle parse calls

- -

 

- -

On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap = -wrote:

- -

> Tim,

- -

>

- -

> How are you doing? I hope you've had a good two years since = -I saw -you on

- -

> the Oracle Geek Cruise event.

- -

 

- -

Yes thanks. And you?

- -

 

- -

> I've been working on a project this year to construct a = -book about

- -

> optimizing Oracle response time. In my research, I've = -discovered

- -

> something about the DBI that I didn't expect: it executes = -two -Oracle

- -

> parse calls for every one that I would expect an efficient = -DBI -layer to

- -

> make. I've included my Perl source (below), the Oracle = -level-12 -trace

- -

> data that shows the sequence of calls it's receiving from = -the Perl

- -

> application (below), a level-9 DBI trace from the = -application

- -

> (attached), and our version information = -(below).

- -

>

- -

> I was hoping that by showing you this specific data, you = -could -make the

- -

> problem go away.

- -

 

- -

I can only do what OCI lets me do... but within that I'll do = -what I -can...

- -

 

- -

I'm not familar with Oracle trace logs so I can't readily = -intrepret -them

- -

and I'll take what you say at face value.

- -

 

- -

But I am familar with DBD::Oracle :) and the logs it writes = -:)

- -

 

- -

> $sth =3D $dbh->prepare(q(select key, fkey, value from t = -where -key=3D?));

- -

> $sth->execute($key);

- -

 

- -

 

- -

    -> prepare for DBD::Oracle::db -(DBI::db=3DHASH(0x8235b34)~0x8235a74 'select key, fkey, value from t = -where -key=3D?')

- -

    dbd_preparse scanned 1 distinct = -placeholders

- -

OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCC= -ESS

- -

OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from = -t -where key=3D:p1',44,1,0)=3DSUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)= -=3DSUCCESS

- -

    dbd_st_prepare'd sql SELECT

- -

    dbd_describe SELECT (EXPLICIT, lb = -80)...

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3D= -SUCCESS

- -

    dbd_describe'd 3 columns (row bytes: 76 max, = -40 est -avg, cache: 231)

- -

    <- prepare=3D DBI::st=3DHASH(0x8240fe0) at = -ex1.pl -line 50

- -

    -> execute for DBD::Oracle::st -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0 '8542')

- -

OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x8= -26cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS - -

OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40= -,0x401da090)=3DSUCCESS

- -

       bind :p1 done with ftype = -1

- -

    dbd_st_execute SELECT (out0, = -lob0)...

- -

       in  ':p1' [0,0]: = -len  4, -ind 0

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3D= -SUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec= -)=3DSUCCESS

- -

    dbd_st_execute SELECT returned (SUCCESS, = -rpc0, fn4, -out0)

- -

    <- execute=3D '0E0' at ex1.pl line = -51

- -

 

- -

Given those OCI calls, what is DBD::Oracle doing that it = -shouldn't?

- -

 

- -

I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

call that prepare() does.

- -

 

- -

It doesn't do that for non-select statements so you could check = -if

- -

non-selects also have two parse calls.

- -

 

- -

Also try doing

- -

  $sth =3D $dbh->prepare(q(select key, fkey, value from = -t where -key=3D?), { ora_check_sql=3D> 0 });

- -

 

- -

which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till = -after the

- -

main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

is possibly redundant and could be removed (but Oracle ought to = -detect -that

- -

anyway and not make a round-trip for it, and certainly not call = -parse).

- -

 

- -

If non-selects only have one parse call but = -ora_check_sql=3D>0 doesn't

- -

fix selects, then I might be able to do a simple patch to avoid = -the

- -

OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if = -ora_check_sql=3D>0.

- -

 

- -

Then the issue will be: should ora_check_sql=3D>0 be the = -default...

- -

 

- -

Tim.

- -

 

- -

p.s. I'd love a copy of your book when it's = -ready!

- -
- - - - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0-- - - -From cary.millsap@hotsos.com Fri Sep 13 21:17:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DKHhC12417 - for ; Fri, 13 Sep 2002 21:17:43 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 21:17:43 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031946929:20:18513:70; Fri, 13 Sep 2002 19:55:29 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2018248; 13 Sep 2002 19:55 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 7FC402C01F - for ; Fri, 13 Sep 2002 15:55:06 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 76A5E2BFE1 - for ; Fri, 13 Sep 2002 15:55:05 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DJt4n26736 - for ; Fri, 13 Sep 2002 14:55:04 -0500 -From: "Cary Millsap" -To: "Tim Bunce" -Subject: A little more data -Date: Fri, 13 Sep 2002 14:54:56 -0500 -Message-ID: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0203_01C25B35.89729F60" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4948 -Lines: 166 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -I hope this is helpful. I have noticed that I cannot produce the -extra-parse problem on my 8.1.7 laptop database, no matter what the -setting of ora_check_sql. All of the data I've sent you is from our -8.1.6 Linux database. If you really needed it, I could produce level-9 -DBI trace data from identical tests on both platforms, but I won't spend -the time doing that unless you say it will help... - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - - - - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

I hope this is helpful… I have noticed that I = -cannot -produce the extra-parse problem on my 8.1.7 laptop database, no matter = -what the -setting of ora_check_sql. All of the data I’ve sent you is from = -our 8.1.6 -Linux database. If you really needed it, I could produce level-9 DBI = -trace data -from identical tests on both platforms, but I won’t spend the time = -doing -that unless you say it will help...

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -

 

- -
- - - - - -------=_NextPart_000_0203_01C25B35.89729F60-- - - -From timbo@dansat.data-plan.com Fri Sep 13 22:05:30 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL5UC12942 - for ; Fri, 13 Sep 2002 22:05:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:05:30 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031948458:10:20432:5; Fri, 13 Sep 2002 20:20:58 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-1.mail.demon.net - id aa1020174; 13 Sep 2002 20:20 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 8A60E3E659 - for ; Fri, 13 Sep 2002 16:20:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id CAC663E685 - for ; Fri, 13 Sep 2002 16:20:36 -0400 (EDT) -Received: (qmail 37861 messnum 258096 invoked from network[159.134.164.124/p124.as1.limerick1.eircom.net]); 13 Sep 2002 20:20:35 -0000 -Received: from p124.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.124) - by mail05.svc.cra.dublin.eircom.net (qp 37861) with SMTP; 13 Sep 2002 20:20:35 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DKKhu12535; - Fri, 13 Sep 2002 21:20:43 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 21:20:43 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data -Message-ID: <20020913202043.GO539@dansat.data-plan.com> -References: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1098 -Lines: 34 - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - -From cary.millsap@hotsos.com Fri Sep 13 22:04:47 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL4kC12684 - for ; Fri, 13 Sep 2002 22:04:46 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:04:46 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031949629:20:13745:23; Fri, 13 Sep 2002 20:40:29 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2013849; 13 Sep 2002 20:40 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 7D90A3E650 - for ; Fri, 13 Sep 2002 16:40:20 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-1.pobox.com (Postfix) with ESMTP id 785AB3E642 - for ; Fri, 13 Sep 2002 16:40:19 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DKeIn27106 - for ; Fri, 13 Sep 2002 15:40:18 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: A little more data -Date: Fri, 13 Sep 2002 15:40:10 -0500 -Message-ID: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913202043.GO539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 1999 -Lines: 63 - -Well, it's 1.06 on my Windows machine (the most up-to-date version -available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -but interesting that (admitting now that there's a new degree of freedom -running loose amid the test) "the older version performs better than the -newer one." :) That's certainly not a fair statement if the diff between -8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:21 PM -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't -spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:32 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLWC13692 - for ; Fri, 13 Sep 2002 23:21:32 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:32 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031952887:10:13297:20; Fri, 13 Sep 2002 21:34:47 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1118141; 13 Sep 2002 21:34 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C7D482BF23 - for ; Fri, 13 Sep 2002 17:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail00.svc.cra.dublin.eircom.net (mail00.svc.cra.dublin.eircom.net [159.134.118.16]) - by dolly1.pobox.com (Postfix) with SMTP id 8352A2BF6C - for ; Fri, 13 Sep 2002 17:34:36 -0400 (EDT) -Received: (qmail 5093 messnum 521124 invoked from network[159.134.164.134/p134.as1.limerick1.eircom.net]); 13 Sep 2002 21:34:34 -0000 -Received: from p134.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.134) - by mail00.svc.cra.dublin.eircom.net (qp 5093) with SMTP; 13 Sep 2002 21:34:34 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DLYeI13070; - Fri, 13 Sep 2002 22:34:40 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:34:40 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: A little more data -Message-ID: <20020913213440.GS539@dansat.data-plan.com> -References: <20020913202043.GO539@dansat.data-plan.com> <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 2282 -Lines: 69 - -According my RCS the default for ora_check_sql changed from 0 to 1 -around version 1.03. - -Tim. - -On Fri, Sep 13, 2002 at 03:40:10PM -0500, Cary Millsap wrote: -> Well, it's 1.06 on my Windows machine (the most up-to-date version -> available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -> but interesting that (admitting now that there's a new degree of freedom -> running loose amid the test) "the older version performs better than the -> newer one." :) That's certainly not a fair statement if the diff between -> 8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Friday, September 13, 2002 3:21 PM -> To: Cary Millsap -> Cc: Tim Bunce -> Subject: Re: A little more data -> -> If they're using the same version of DBD::Oracle then -> the change must me on the sever side. Maybe Oracle's -> woken up to the fact they don't need a second parse! -> -> Tim. -> -> On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > -> > -> > I hope this is helpful. I have noticed that I cannot produce the -> > extra-parse problem on my 8.1.7 laptop database, no matter what the -> > setting of ora_check_sql. All of the data I've sent you is from our -> > 8.1.6 Linux database. If you really needed it, I could produce level-9 -> > DBI trace data from identical tests on both platforms, but I won't -> spend -> > the time doing that unless you say it will help... -> > -> > -> > -> > Cary Millsap -> > Hotsos Enterprises, Ltd. -> > http://www.hotsos.com -> > -> > Upcoming events: -> > - Hotsos Clinic , Oct 1-3 San -> > Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> > - 2003 Hotsos Symposium on -> > OracleR System Performance, Feb 9-12 Dallas -> > - Next event: Miracle Database Forum , Sep -> > 20-22 Middlefart Denmark -> > -> > -> > -> - diff --git a/err_unsorted/err_xml.msg b/err_unsorted/err_xml.msg deleted file mode 100644 index 7a60a0cb..00000000 --- a/err_unsorted/err_xml.msg +++ /dev/null @@ -1,118 +0,0 @@ -From dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org Fri Aug 15 14:41:14 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h7FDe3MA043557 - for ; Fri, 15 Aug 2003 14:41:13 +0100 (BST) - (envelope-from dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 15 Aug 2003 14:41:13 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 19nc4X-0006LQ-BC; - Fri, 15 Aug 2003 10:44:41 +0000 -Received: from [207.106.49.22] (helo=dolly1.pobox.com) - by punt-3.mail.demon.net with esmtp id 19nc4X-0006LQ-BC - for pobox@dbi.demon.co.uk; Fri, 15 Aug 2003 10:44:41 +0000 -Received: from dolly1.pobox.com (localhost[127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 16F6B21C13B - for ; Fri, 15 Aug 2003 06:44:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.develooper.com[63.251.223.166]) - by dolly1.pobox.com (Postfix) with SMTP id 021F121C36F - for ; Fri, 15 Aug 2003 06:44:40 -0400 (EDT) -Received: (qmail 78180 invoked by uid 1005); 15 Aug 2003 10:44:34 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 71287 invoked by uid 76); 15 Aug 2003 10:32:13 -0000 -Delivered-To: dbi-users@perl.org -Received-SPF: unknown (domain of sender andyhassall@yahoo.com does not designate mailers: NXDOMAIN) -Message-ID: <20030815103200.24313.qmail@web9605.mail.yahoo.com> -Date: Fri, 15 Aug 2003 11:32:00 +0100 (BST) -From: =?iso-8859-1?q?Andy=20Hassall?= -Reply-To: andy@andyh.co.uk -Subject: Re: ERROR OCIDefineObject call needed but not implemented yet using XMLElement function -To: Susan Cassidy , dbi-users@perl.org -In-Reply-To: -MIME-Version: 1.0 -Content-Type: text/plain; charset=iso-8859-1 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.8 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,SPAM_PHRASE_01_02 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id h7FDe3MA043557 -Status: RO -Content-Length: 2299 -Lines: 65 - - --- Susan Cassidy wrote: > I am using DBD::Oracle. -I was on version 1.12, then I installed version -> 1.14, with the same result. -> -> This is Oracle 9.2.0. -> -> I have this select statement that works fine from SQL*Plus: -> -> select XMLElement("Sequences", -> XMLElement("Sequence", -> XMLATTRIBUTES ( b.local_name AS "ic-acckey", -> b.mol_type AS "molecule", -> n.seq_name AS "title"))) -> from gcg_bioseq b, gcg_annot_seq_name a, gcg_seq_name n -> where -> b.local_name = 'K00306' and -> b.seq_status = 'D' and -> b.seq_oid = a.seq_oid and -> a.seq_name_oid = n.seq_name_oid and -> n.name_type = 'LOCUS' -> -> -> When I run it via DBI/DBD I get this (trace level 2): -> -> DBI 1.32-nothread dispatch trace level set to 2 -> Note: perl is running without the recommended perl -w option -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x1b2314)~0x122bec ' -[snip -> Field 1 has an Oracle type (108) which is not explicitly supported -> fbh 1: -> -'XMLELEMENT("SEQUENCES",XMLELEMENT("SEQUENCE",XMLATTRIBUTES(B.LOCAL_NAMEAS"IC-ACCKEY",B.MOL_TYPEAS"MOLECULE",N.SEQ_NAMEAS"TITLE")))' -[snip] -> Error: prepare failed -> at line 56, error: ERROR OCIDefineObject call needed but not -> implemented yet -> -> Is there any other workaround for this than wrapping this up in a PL/SQL -> function? - - Don't rely on the implicit conversion to a string type that is done when -SQL*Plus displays an XMLElement; add .getClobVal() to the end of the -statement to retrieve it as a CLOB rather than the XMLElement object type -(which DBD::Oracle doesn't accept). - - i.e. - -select XMLElement("Sequences", - XMLElement("Sequence", - XMLATTRIBUTES ( b.local_name AS "ic-acckey", - b.mol_type AS "molecule", - n.seq_name AS "title"))).getClobVal() - from ... - - (or getStringVal() for a VARCHAR2) - -===== --- -Andy Hassall (andy@andyh.org) icq(5747695) http://www.andyh.co.uk -http://www.andyhsoftware.co.uk/space | disk usage analysis tool - -________________________________________________________________________ -Want to chat instantly with your online friends? Get the FREE Yahoo! -Messenger http://uk.messenger.yahoo.com/ - - diff --git a/err_unsorted/err_xml2.msg b/err_unsorted/err_xml2.msg deleted file mode 100644 index 3bb291c5..00000000 --- a/err_unsorted/err_xml2.msg +++ /dev/null @@ -1,700 +0,0 @@ -From dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org Fri Jan 30 12:50:15 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UClt3q069307 - for ; Fri, 30 Jan 2004 12:50:14 GMT - (envelope-from dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 12:50:14 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmWGJ-00057X-AG; - Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmWGJ-00057X-AG - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [207.8.214.3] (helo=puzzle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmWGI-0007XK-P3 - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:34 +0000 -Received: from puzzle.pobox.com (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 029E8701C6 - for ; Fri, 30 Jan 2004 05:52:34 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 12ABF701C1 - for ; Fri, 30 Jan 2004 05:52:30 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by puzzle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 05:51:10 -0500 (EST) -Received: (qmail 33345 invoked by uid 1005); 30 Jan 2004 10:50:36 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 33175 invoked by uid 76); 30 Jan 2004 10:50:26 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Fri, 30 Jan 2004 02:50:25 -0800 -Received: (qmail 21117 invoked by uid 225); 30 Jan 2004 10:48:52 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 21080 invoked by uid 507); 30 Jan 2004 10:48:49 -0000 -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Fri, 30 Jan 2004 02:48:46 -0800 -Received: (qmail 31958 invoked from network); 30 Jan 2004 11:50:38 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 30 Jan 2004 11:50:38 -0000 -Received: (qmail 6921 invoked from network); 30 Jan 2004 10:49:58 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 30 Jan 2004 10:49:58 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Fri, 30 Jan 2004 11:49:58 +0100 (CET) -Subject: DBD-Oracle and XMLType -From: Hendrik Fuss -To: "dbi-dev@perl.org" -Content-Type: multipart/mixed; boundary="=-fkyM33WAvQ5xV0uCPeSD" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 11:41:31 +0100 -Message-Id: <1075459292.7305.46.camel@mars> -Mime-Version: 1.0 -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.5 required=7.0 tests=MIME_LONG_LINE_QP,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01,TO_ADDRESS_EQ_REAL version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 8148 -Lines: 302 - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -Hi everyone, - -It's been a while since I last posted here. In September 2003 I was -trying to add support for binding XMLType objects to DBD-Oracle, so that -you could easily insert large (ie >4k) XML data into an XMLType table. - -Unfortunately my employer fired me in October 2003 and in the remaining -time I had to work on other projects, so I wasn't able to complete the -DBD project. Since I won't have access to an oracle database from now -on, I thought the least I can do is to provide my code as it is to the -list. Blame German economy. :-( - -The attached patch (based on DBD-Oracle 1.15) enables you to upload -XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -I added a function dbd_rebind_ph_nty for that purpose. You need to -create that XMLType object first using the C function -createxmlfromstring in xml.c. - -The XMLType object is either created from an OCIString or from a -temporary CLOB depending on the length of the source string. Have a look -at the bottom of ociap.h, all the (undocumented) XMLType functions are -there, and there are also some constants in oci.h. - -I'm not sure if the CLOB code currently works. - -Here is another code fragment: - - my $xml =3D createxml($dbh, 'Test document'); - my $sth =3D $dbh->prepare('INSERT INTO xml_type VALUES (?)'); - $sth->bind_param(1, $xml, { ora_type =3D> 108 }); # SQLT_NTY - $sth->execute(); - -Please note that this code is really just early development, which I -wouldn't publish under normal circumstances. :) I just hope it might me -useful to someone. - -Well then, time to say goodbye -thanks to Tim and everyone who contributed to dbi for a great piece of -software - -Cheers, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Description: -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - -151a152 -> case 108: /* SQLT_NTY */ -992a994,996 -> case SQL_UDT: -> return 108; /* Oracle NTY */ ->=20 -1004a1009,1072 -> static int -> dbd_rebind_ph_nty(sth, imp_sth, phs) -> SV* sth; -> imp_sth_t *imp_sth; -> phs_t *phs; -> { -> OCIType *tdo =3D NULL; -> sword status; -> SV* ptr; ->=20 -> if (phs->is_inout) -> croak("OUT binding for NTY is currently unsupported"); ->=20 -> /* ensure that the value is a support named object type */ -> /* (currently only OCIXMLType*) */ -> if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -> OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -> (CONST text*)"SYS", 3, -> (CONST text*)"XMLTYPE", 7, -> (CONST text*)0, 0, -> OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -> &tdo); ->=20 -> ptr =3D SvRV(phs->sv); -> phs->progv =3D (void*) SvIV(ptr); -> phs->maxlen =3D sizeof(OCIXMLType*); -> } -> else -> croak("Unsupported named object type for bind parameter"); ->=20 ->=20 -> /* bind by name */ ->=20 -> OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -> (text*)phs->name, (sb4)strlen(phs->name), -> (dvoid *) NULL, /* value supplied in BindObject later */ -> 0, -> (ub2)phs->ftype, 0, -> NULL, -> 0, 0, -> NULL, -> (ub4)OCI_DEFAULT, -> status -> ); ->=20 -> if (status !=3D OCI_SUCCESS) { -> oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -> return 0; -> } -> if (DBIS->debug >=3D 3) -> PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); ->=20 ->=20 -> /* bind the object */ ->=20 -> OCIBindObject(phs->bndhp, imp_sth->errhp, -> (CONST OCIType*)tdo, -> (dvoid **)&phs->progv, -> (ub4*)NULL, -> (dvoid **)NULL, -> (ub4*)NULL); ->=20 -> return 2; -> } -1309a1378,1380 -> case 108: -> done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -> break; -1331c1403 -< int at_exec =3D (phs->desc_h =3D=3D NULL); ---- -> int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); -1419c1491 -< if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) ---- -> if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQL= -T_NTY)) -1420a1493 -> /* ref allowed for OCIXMLType* */ -2219a2293 -> case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Disposition: attachment; filename=xml.c -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; name=xml.c; charset=ISO-8859-1 - -#include "oci.h" -#include - -/* This helper function creates an XMLType object from a string source. - * - * The resulting object can be bound to a placeholder, if ora_type =3D> - * SQLT_NTY is specified. - */ - -static void checkerr(errhp, status) -OCIError *errhp; -sword status; -{ - text errbuf[512]; - ub4 buflen; - sb4 errcode; - - switch (status) - { - case OCI_SUCCESS: - break; - case OCI_SUCCESS_WITH_INFO: - printf("Error - OCI_SUCCESS_WITH_INFO\n"); - break; - case OCI_NEED_DATA: - printf("Error - OCI_NEED_DATA\n"); - break; - case OCI_NO_DATA: - printf("Error - OCI_NO_DATA\n"); - break; - case OCI_ERROR: - OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, - errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR); - printf("Error - %s\n", errbuf); - exit(1); - break; - case OCI_INVALID_HANDLE: - printf("Error - OCI_INVALID_HANDLE\n"); - break; - case OCI_STILL_EXECUTING: - printf("Error - OCI_STILL_EXECUTE\n"); - break; - case OCI_CONTINUE: - printf("Error - OCI_CONTINUE\n"); - break; - default: - break; - } -} - - -#define MAX_OCISTRING_LEN 32766 - -SV* createxmlfromstring(SV* dbh, char* source) { - OCIXMLType *xml =3D NULL; - ub4 len; - ub1 src_type; - dvoid* src_ptr =3D NULL; - D_imp_dbh(dbh); - SV* sv_dest; - - len =3D strlen(source); - if(len > MAX_OCISTRING_LEN) { - src_type =3D OCI_XMLTYPE_CREATE_CLOB; - - printf("OCIDescriptorAlloc\n"); - checkerr( imp_dbh->errhp, - OCIDescriptorAlloc((dvoid*)imp_dbh->envhp, - (dvoid **)&src_ptr, - (ub4)OCI_DTYPE_LOB, - (size_t)0, - (dvoid**)0) ); - - printf("OCILobCreateTemporary\n"); - checkerr( imp_dbh->errhp, - OCILobCreateTemporary(imp_dbh->svchp, - imp_dbh->errhp,=20 - (OCILobLocator*) src_ptr, - (ub2)0,=20 - SQLCS_IMPLICIT,=20 - OCI_TEMP_CLOB,=20 - OCI_ATTR_NOCACHE,=20 - OCI_DURATION_SESSION) ); - - printf("OCILobWrite\n"); - checkerr (imp_dbh->errhp, - OCILobWriteAppend(imp_dbh->svchp, - imp_dbh->errhp, - (OCILobLocator*) src_ptr, - &len,=20 - (ub1*)source, - len, - OCI_ONE_PIECE, - (dvoid *)0,=20 - (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, - 0, - SQLCS_IMPLICIT)); - - } else { - src_type =3D OCI_XMLTYPE_CREATE_OCISTRING; - - printf("OCIStringAssignText\n"); - checkerr( imp_dbh->errhp, - OCIStringAssignText(imp_dbh->envhp, - imp_dbh->errhp,=20 - (CONST text*) source,=20 - (ub2) strlen(source), - (OCIString **) &src_ptr) - ); - } - - printf("OCIXMLTypeCreateFromSrc\n"); - checkerr( imp_dbh->errhp, - OCIXMLTypeCreateFromSrc(imp_dbh->svchp, - imp_dbh->errhp, - (OCIDuration)OCI_DURATION_CALLOUT, - (ub1)src_type, - (dvoid *)src_ptr, - (sb4)OCI_IND_NOTNULL, - &xml) - ); - - - /* free temporary resources */ - if( src_type =3D=3D OCI_XMLTYPE_CREATE_CLOB ) { - checkerr( imp_dbh->errhp, - OCILobFreeTemporary(imp_dbh->svchp, imp_dbh->errhp, - (OCILobLocator*) src_ptr) ); - - checkerr( imp_dbh->errhp, - OCIDescriptorFree((dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB) ); - } - - - sv_dest =3D newSViv(0); - sv_setref_pv(sv_dest, "OCIXMLTypePtr", xml); - return sv_dest; -} - ---=-fkyM33WAvQ5xV0uCPeSD-- - - - -From hendrik.fuss@morphochem.de Fri Jan 30 16:56:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UGsO3v071338 - for ; Fri, 30 Jan 2004 16:56:27 GMT - (envelope-from hendrik.fuss@morphochem.de) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 16:56:27 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmZJF-0001wN-DK; - Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmZJF-0001wN-DK - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmZJE-0003GM-Bm - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:48 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 334DE30C57 - for ; Fri, 30 Jan 2004 09:07:47 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id E65B230C2C - for ; Fri, 30 Jan 2004 09:07:45 -0500 (EST) -Received: from babel.morphochem.de (unknown [212.89.121.1]) - by boggle.pobox.com (Postfix) with ESMTP - for ; Fri, 30 Jan 2004 09:07:04 -0500 (EST) -Received: (qmail 29768 invoked from network); 30 Jan 2004 15:10:09 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) - by 212.89.121.1 with SMTP; 30 Jan 2004 15:10:09 -0000 -Received: (qmail 11736 invoked from network); 30 Jan 2004 14:09:30 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) - (envelope-sender ) - by localhost.morphochem.de (qmail-ldap-1.03) with SMTP - for ; 30 Jan 2004 14:09:30 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) - by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; - Fri, 30 Jan 2004 15:09:30 +0100 (CET) -Subject: Re: DBD-Oracle and XMLType -From: Hendrik Fuss -To: Tim Bunce -Cc: "dbi-dev@perl.org" -In-Reply-To: <20040130133443.GC70215@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> - <20040130133443.GC70215@dansat.data-plan.com> -Content-Type: multipart/mixed; boundary="=-Sq1IOPDEhKoqxUKefiS3" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 15:01:03 +0100 -Message-Id: <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Status: RO -X-Status: A -Content-Length: 5585 -Lines: 196 - - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -> > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.= -c -> > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > create that XMLType object first using the C function -> > createxmlfromstring in xml.c. ->=20 -> I there any chance you could post that as a context diff (diff -u ideally -> or else diff -c)? It's much safer and more useful. Thanks. - -Good idea. Here's a diff -u of dbdimp.c. - -By the way: I have thougt about general support of named types, not just -XMLType, but you need to get the type description (TDO) from somewhere. -My code just checks if the perl variable is a blessed reference of -"OCIXMLTypePtr". - -Also note that my code can't handle downloading of XMLType objects yet. - -best wishes, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Description: Context diff for dbdimp.c -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - ---- dbdimp.c.orig 2004-01-30 14:48:55.000000000 +0100 -+++ dbdimp.c 2003-10-07 12:17:17.000000000 +0200 -@@ -1,5 +1,5 @@ - /* -- $Id: dbdimp.c,v 1.1.1.1 2003/10/02 10:45:20 hfuss Exp $ -+ $Id: dbdimp.c,v 1.3 2003/10/07 10:17:17 hfuss Exp $ -=20 - Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce -=20 -@@ -149,6 +149,7 @@ - case 97: /* CHARZ */ - case 106: /* MLSLABEL */ - case 102: /* SQLT_CUR OCI 7 cursor variable */ -+ case 108: /* SQLT_NTY */ - case 112: /* SQLT_CLOB / long */ - case 113: /* SQLT_BLOB / long */ - case 116: /* SQLT_RSET OCI 8 cursor variable */ -@@ -990,6 +991,9 @@ - case SQL_LONGVARCHAR: - return 8; /* Oracle LONG */ -=20 -+ case SQL_UDT: -+ return 108; /* Oracle NTY */ -+ - case SQL_DATE: - case SQL_TIME: - case SQL_TIMESTAMP: -@@ -1002,6 +1006,70 @@ - } -=20 -=20 -+static int -+dbd_rebind_ph_nty(sth, imp_sth, phs) -+ SV* sth; -+ imp_sth_t *imp_sth; -+ phs_t *phs; -+{ -+ OCIType *tdo =3D NULL; -+ sword status; -+ SV* ptr; -+ -+ if (phs->is_inout) -+ croak("OUT binding for NTY is currently unsupported"); -+ -+ /* ensure that the value is a support named object type */ -+ /* (currently only OCIXMLType*) */ -+ if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -+ OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -+ (CONST text*)"SYS", 3, -+ (CONST text*)"XMLTYPE", 7, -+ (CONST text*)0, 0, -+ OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -+ &tdo); -+ -+ ptr =3D SvRV(phs->sv); -+ phs->progv =3D (void*) SvIV(ptr); -+ phs->maxlen =3D sizeof(OCIXMLType*); -+ } -+ else -+ croak("Unsupported named object type for bind parameter"); -+ -+ -+ /* bind by name */ -+ -+ OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -+ (text*)phs->name, (sb4)strlen(phs->name), -+ (dvoid *) NULL, /* value supplied in BindObject later */ -+ 0, -+ (ub2)phs->ftype, 0, -+ NULL, -+ 0, 0, -+ NULL, -+ (ub4)OCI_DEFAULT, -+ status -+ ); -+ -+ if (status !=3D OCI_SUCCESS) { -+ oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -+ return 0; -+ } -+ if (DBIS->debug >=3D 3) -+ PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); -+ -+ -+ /* bind the object */ -+ -+ OCIBindObject(phs->bndhp, imp_sth->errhp, -+ (CONST OCIType*)tdo, -+ (dvoid **)&phs->progv, -+ (ub4*)NULL, -+ (dvoid **)NULL, -+ (ub4*)NULL); -+ -+ return 2; -+} -=20 - static int=20 - dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr)=20 -@@ -1307,6 +1375,9 @@ - case SQLT_RSET: - done =3D dbd_rebind_ph_rset(sth, imp_sth, phs); - break; -+ case 108: -+ done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -+ break; - #else - case 102: /* SQLT_CUR */ - done =3D dbd_rebind_ph_cursor(sth, imp_sth, phs); -@@ -1315,6 +1386,7 @@ - default: - done =3D dbd_rebind_ph_char(sth, imp_sth, phs, &alen_ptr); - } -+ - if (done !=3D 1) { - if (done =3D=3D 2) { /* the rebind did the OCI bind call itself successfu= -lly */ - if (DBIS->debug >=3D 3) -@@ -1328,7 +1400,7 @@ - #ifdef OCI_V8_SYNTAX - if (phs->maxlen > phs->maxlen_bound) { - sword status; -- int at_exec =3D (phs->desc_h =3D=3D NULL); -+ int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, (sb4)strlen(phs->name), - phs->progv, -@@ -1416,8 +1488,9 @@ - } - assert(name !=3D Nullch); -=20 -- if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) -+ if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQLT= -_NTY)) - /* dbi handle allowed for cursor variables */ -+ /* ref allowed for OCIXMLType* */ - croak("Can't bind a reference (%s)", neatsvpv(newvalue,0)); - if (SvTYPE(newvalue) > SVt_PVLV) /* hook for later array logic? */ - croak("Can't bind a non-scalar value (%s)", neatsvpv(newvalue,0)); -@@ -2217,6 +2290,7 @@ - #ifdef OCI_V8_SYNTAX - case SQLT_CLOB: sql_fbh.dbtype =3D SQL_CLOB; break; - case SQLT_BLOB: sql_fbh.dbtype =3D SQL_BLOB; break; -+ case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - #endif - #ifdef SQLT_TIMESTAMP_TZ - case SQLT_TIMESTAMP_TZ: sql_fbh.dbtype =3D SQL_TIMESTAMP; break; - ---=-Sq1IOPDEhKoqxUKefiS3-- - - - -From timbo@dansat.data-plan.com Fri Jan 30 18:32:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UIVK3f073353 - for ; Fri, 30 Jan 2004 18:32:30 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 18:32:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmceP-000603-GP; - Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmceP-000603-GP - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [208.210.124.73] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1AmceO-0006dQ-DB - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:52 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 25AEA3F13D - for ; Fri, 30 Jan 2004 12:41:51 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9FB863F16E - for ; Fri, 30 Jan 2004 12:41:49 -0500 (EST) -Received: from mail09.svc.cra.dublin.eircom.net (mail09.svc.cra.dublin.eircom.net [159.134.118.25]) - by icicle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 12:41:11 -0500 (EST) -Received: (qmail 9504 messnum 226571 invoked from network[213.94.228.233/unknown]); 30 Jan 2004 17:40:43 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail09.svc.cra.dublin.eircom.net (qp 9504) with SMTP; 30 Jan 2004 17:40:43 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UHf33A072739; - Fri, 30 Jan 2004 17:41:03 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i0UHf2Wr072738; - Fri, 30 Jan 2004 17:41:02 GMT -Date: Fri, 30 Jan 2004 17:41:02 +0000 -From: Tim Bunce -To: Hendrik Fuss -Cc: Tim Bunce , "dbi-dev@perl.org" -Subject: Re: DBD-Oracle and XMLType -Message-ID: <20040130174102.GB72657@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> <20040130133443.GC70215@dansat.data-plan.com> <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <1075471263.7305.73.camel@mars> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1129 -Lines: 29 - -On Fri, Jan 30, 2004 at 03:01:03PM +0100, Hendrik Fuss wrote: -> > > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -> > > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > > create that XMLType object first using the C function -> > > createxmlfromstring in xml.c. -> > -> > I there any chance you could post that as a context diff (diff -u ideally -> > or else diff -c)? It's much safer and more useful. Thanks. -> -> Good idea. Here's a diff -u of dbdimp.c. - -Thanks. - -> By the way: I have thougt about general support of named types, not just -> XMLType, but you need to get the type description (TDO) from somewhere. -> My code just checks if the perl variable is a blessed reference of -> "OCIXMLTypePtr". - -Doing the equivalent of m/^OCI(\w+)Ptr$/ and then calling OCITypeByName -with $1 uppercased might take us (or someone) a step further. - -> Also note that my code can't handle downloading of XMLType objects yet. - -I'll trust that some kind soul with an itch will send a patch :-) - -Thanks again Hendrik. - -Tim. - diff --git a/err_unsorted/err_xmltypebindplsql.msg b/err_unsorted/err_xmltypebindplsql.msg deleted file mode 100644 index 08faa725..00000000 --- a/err_unsorted/err_xmltypebindplsql.msg +++ /dev/null @@ -1,174 +0,0 @@ -From dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org Thu Apr 25 11:02:42 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3PA2gK34525 - for ; Thu, 25 Apr 2002 11:02:42 +0100 (BST) - (envelope-from dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 25 Apr 2002 11:02:42 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1019721492:10:18778:60; Thu, 25 Apr 2002 07:58:12 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1109782; 25 Apr 2002 7:58 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 791692BF11 - for ; Thu, 25 Apr 2002 03:58:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id 976FB2BEE4 - for ; Thu, 25 Apr 2002 03:58:07 -0400 (EDT) -Received: (qmail 84467 invoked by uid 1005); 25 Apr 2002 07:58:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 77923 invoked by uid 76); 24 Apr 2002 23:08:56 -0000 -Date: Wed, 24 Apr 2002 19:08:54 -0400 -From: Mark Stillwell -To: dbi-users-help@perl.org, dbi-users@perl.org -Subject: Oracle 9 XMLTYPE insert -Message-ID: <20020424190852.C22854@byrd.biostat.ufl.edu> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -Status: RO -Content-Length: 1469 -Lines: 43 - -I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -Here is my problem, I have a table named 'test' with three fields: eid -(integer), x (SYS.XMLTYPE) and formname (text) - -I create a database handler and connect to the database just fine. - -I create a new statement handler with the following command: - -$sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -SYS.XMLTYPE.CREATEXML(?), ?"); - -I loop over some data, $eid gets and integer, $xmlvalue gets a string, -and $formname gets a string. So long as $xmlvalue is relatively short -$sth->execute($eid, $xmlvalue, $formname); works great, but as soon as -it becomes long enough to force the use of clob's I have a problem. - -So I tried the following: - -$sth->bind_param(1, $i); -$sth->bind_param(2, $xmlvalue, { ora_type => ORA_CLOB }); -$sth->bind_param(3, $intable); -$sth->execute; - -This works great if column 'x' is a normal CLOB and I omit the -sys.xmltype.createxml statement above, but when 'x' is of type -sys.xmltype I get the following error: - -nvalid LOB locator specified -ORA-06512: at "SYS.XMLTYPE", line 0 - -Right now I've hacked the setup so there is a supplemental table called -'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE test SET x -= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem like the -right way to do this. - -Is there any way to do what I want in the current version of -DBI/OracleDBD? - --- -Mark Stillwell -marklee@ufl.edu -http://plaza.ufl.edu/marklee/ - -From dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org Wed May 8 16:11:46 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g48FBjo24814 - for ; Wed, 8 May 2002 16:11:45 +0100 (BST) - (envelope-from dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 08 May 2002 16:11:45 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020870336:20:08175:2; Wed, 08 May 2002 15:05:36 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2109147; 8 May 2002 15:05 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id 68FE23E6D4 - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-3.pobox.com (Postfix) with SMTP id 33A783E64D - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Received: (qmail 65232 invoked by uid 1005); 8 May 2002 15:01:47 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 60079 invoked by uid 76); 8 May 2002 14:50:53 -0000 -From: "Ben Middleton" -To: -Cc: -Subject: Re: Oracle 9 XMLTYPE insert -Date: Wed, 8 May 2002 15:50:47 +0100 -Message-ID: -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0) -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -Content-Length: 1311 -Lines: 39 - -Hi. - -Not sure if you ever resolved this: - -> I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -> Here is my problem, I have a table named 'test' with three fields: -> eid (integer), x (SYS.XMLTYPE) and formname (text) - -> I create a new statement handler with the following command: - -> $sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -> SYS.XMLTYPE.CREATEXML(?), ?"); - -.... - -> Invalid LOB locator specified -> ORA-06512: at "SYS.XMLTYPE", line 0 - -> Right now I've hacked the setup so there is a supplemental table -> called 'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE -> test SET x= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem -> like the right way to do this. - -> Is there any way to do what I want in the current version of -> DBI/OracleDBD? - -I don't think that the current DBI/DBD can bind a CLOB to a PL/SQL function -(which is all the CREATEXML function is) - hence you will have to go with -the intermediate CLOB table solution. - -Incidentally, if you are using Oracle9i - have you tried using a TEMPORARY -TABLE with a CLOB column (see SQL Reference Guide)? If setup correctly, this -is automatically truncated at the end of a transaction, is managed by the -Server, and provides some efficiency benefits. We use this here quite -effectively. - -Ben. - - diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index ff71f86b..99b8e935 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -11,6 +11,12 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; +{ + $DBD::Oracle::VERSION = '1.39_00'; +} +BEGIN { + $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Oracle database driver for the DBI module use DBI (); @@ -117,7 +123,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::dr; # ====== DRIVER ====== +{ package DBD::Oracle::dr; +{ + $DBD::Oracle::dr::VERSION = '1.39_00'; +} +BEGIN { + $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DRIVER ====== use strict; my %dbnames = (); # holds list of known databases (oratab + tnsnames) @@ -316,7 +328,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::db; # ====== DATABASE ====== +{ package DBD::Oracle::db; +{ + $DBD::Oracle::db::VERSION = '1.39_00'; +} +BEGIN { + $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DATABASE ====== use strict; use DBI qw(:sql_types); @@ -1008,7 +1026,13 @@ SQL } # end of package DBD::Oracle::db -{ package DBD::Oracle::st; # ====== STATEMENT ====== +{ package DBD::Oracle::st; +{ + $DBD::Oracle::st::VERSION = '1.39_00'; +} +BEGIN { + $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== STATEMENT ====== sub bind_param_inout_array { @@ -1099,9 +1123,18 @@ SQL 1; -__END__ +=pod + +=head1 NAME + +DBD::Oracle - Oracle database driver for the DBI module + +=head1 VERSION + +version 1.39_00 + =head1 SYNOPSIS use DBI; @@ -1115,7 +1148,6 @@ __END__ # for some advanced uses you may need Oracle type values: use DBD::Oracle qw(:ora_types); - =head1 DESCRIPTION DBD::Oracle is a Perl module which works with the DBI module to provide @@ -1223,7 +1255,6 @@ If port name is not specified, 1521 is the default. If service name is not speci The following examples show several ways a connection can be created: - $dbh = DBI->connect('dbi:Oracle:DB','username','password'); $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); @@ -1554,7 +1585,6 @@ DBDOxxxx where xxxx is the current version number. This value can be retrieved on the server side using V$SESSION_CONNECT_INFO or GV$SESSION_CONNECT_INFO - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); $dbh->{ora_driver_name} = $q; @@ -1725,7 +1755,6 @@ If the previous error was from a failed C due to a syntax error, this attribute gives the offset into the C attribute where the error was found. - =head4 ora_array_chunk_size Due to OCI limitations, DBD::Oracle needs to buffer up rows of @@ -1948,7 +1977,6 @@ DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. Starts a new session against the current database using the credentials supplied. - =head2 B $hashref = $dbh->private_attribute_info(); @@ -2076,7 +2104,6 @@ Implemented by DBI, no driver-specific impact. Implemented by DBI, no driver-specific impact. - =head2 B Type: boolean, inherited @@ -2085,7 +2112,6 @@ The CompatMode attribute is used by emulation layers (such as Oraperl) to enable It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. - =head1 ORACLE-SPECIFIC DATABASE HANDLE METHODS =head2 B @@ -2245,7 +2271,6 @@ The different types of placeholders cannot be mixed within a statement, but you use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. - =head2 B $sth = $dbh->prepare_cached($statement, \%attr); @@ -2264,7 +2289,6 @@ query was successful, returns undef if an error occurred, and returns -1 if the number of rows is unknown or not available. Note that this method will return B<0E0> instead of 0 for 'no rows were affected', in order to always return a true value if no error occurred. - =head2 B Oracle does not implement auto_increment of serial type columns it uses predefined @@ -2320,7 +2344,6 @@ If the script exits before disconnect is called (or, more precisely, if the data referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() methods automatically. It is best to explicitly disconnect rather than rely on this behavior. - =head2 B $rv = $dbh->ping; @@ -2669,7 +2692,6 @@ Examples: ## This executes the statement with 567 (integer) and "Zool" (varchar) $sth->execute(); - These attributes may be used in the C<\%attr> parameter of the L or L statement handle methods. @@ -2764,10 +2786,8 @@ Set L to 0 in prepare() to enable this behaviour. $rv = $sth->bind_param_inout($param_num, \$scalar, 0); - DBD::Oracle fully supports bind_param_inout below are some uses for this method. - =head3 B Oracle supports an extended SQL insert syntax which will return one @@ -2941,10 +2961,6 @@ the above example, the code would look something like this : ... } - - - - =head3 B DBD::Oracle has built-in support for B @@ -2979,13 +2995,11 @@ and B datatypes. The simple example is here: =item B -=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' +=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' will only take a reference to a scalar. =back - - =head3 B SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. @@ -3094,7 +3108,6 @@ you get: DBD::Oracle supports this undocumented feature of DBI. See L for an example. - =head2 B $rv = $sth->bind_param_array($param_num, $array_ref_or_value) @@ -3104,8 +3117,6 @@ DBD::Oracle supports this undocumented feature of DBI. See L method. - - =head2 B $rv = $sth->execute(@bind_values); @@ -3372,7 +3383,6 @@ However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch Only use scrollable cursors if you really have a good reason to. They do use up considerable more server and client resources and have poorer response times than non-scrolling cursors. - =head2 Enabling Scrollable Cursors To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; @@ -3388,7 +3398,6 @@ When the statement is executed you will then be able to use 'ora_fetch_scroll' m or you can still use any of the other fetch methods but with a poorer response time than if you used a non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. - =head2 Scrollable Cursor Methods The following driver-specific methods are used with scrollable cursors. @@ -3728,7 +3737,6 @@ You can tune this value by setting ora_oci_success_warn which will display the f In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. - =head3 Simple Fetch for CLOBs and BLOBs To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well @@ -4130,7 +4138,6 @@ Uses the Oracle OCILobTrim function. Returns the length of the LOB. Uses the Oracle OCILobGetLength function. - =item ora_lob_is_init $is_init = $dbh->ora_lob_is_init($lob_locator); @@ -4177,7 +4184,6 @@ lob_id field values, defined as follows: CREATE SEQUENCE lob_example_seq - =head3 Example: Inserting a new row with large data Unless enough memory is available to store and bind the @@ -4243,7 +4249,6 @@ can't be used effectively if AutoCommit is enabled). $offset += $length; } - In this example we demonstrate the use of ora_lob_write() interactively to append data to the columns 'bin_data' and 'char_data'. Had we used ora_lob_append(), we could have @@ -4260,7 +4265,6 @@ The scalar variables $offset and $length are no longer needed, because ora_lob_append() keeps track of the offset for us. - =head3 Example: Updating an existing row with large data In this example, we demonstrate a technique for overwriting @@ -4445,7 +4449,6 @@ WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other than US7ASCII, requires that the NLS_LANG environment variable be set. See the L<"Oracle UTF8 is not UTF-8"> section below. - You are strongly urged to read the Oracle Internationalization documentation specifically with respect the choices and trade offs for creating a databases for use with international character sets. @@ -4552,7 +4555,6 @@ If the C attribute is given to bind_param() then that determines if the value should be assumed to be in the default (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); ... $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); @@ -4593,7 +4595,6 @@ and TABLE in any combination. Support is seamless and recursive, meaning you need only supply a simple SQL statement to get all the values in an embedded object. You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. - Array example, given this type and table; CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); @@ -4746,7 +4747,6 @@ There are some types, like BOOLEAN, that Oracle does not automatically convert to or from strings (pity). These need to be converted explicitly using SQL or PL/SQL functions. - Examples: # DATE values @@ -4801,7 +4801,6 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" - =head4 Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special @@ -4949,7 +4948,6 @@ shows: } } - The cursor returned by the function C defined in the previous section can be fetched as a nested cursor as follows: @@ -5330,7 +5328,6 @@ There is a known problem with the 11.2g Oracle client and the C PL/SQL function. See L for the details. - =head1 SEE ALSO =over @@ -5398,4 +5395,34 @@ The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. The DBD::Oracle module is free open source software; you can redistribute it and/or modify it under the same terms as Perl 5. +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + + +__END__ + + diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index edacde25..a8162ed1 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,4 +1,10 @@ package DBD::Oracle::GetInfo; +{ + $DBD::Oracle::GetInfo::VERSION = '1.39_00'; +} +BEGIN { + $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Wrapper to get Oracle information use strict; @@ -279,4 +285,44 @@ our %info = ( 1; + + +=pod + +=head1 NAME + +DBD::Oracle::GetInfo - Wrapper to get Oracle information + +=head1 VERSION + +version 1.39_00 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + + __END__ diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 39a99498..a6641f12 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,25 +1,70 @@ -package DBD::Oracle::Object; -# ABSTRACT: Wrapper for Oracle objects - -use strict; -use warnings; - -sub type_name { shift->{type_name} } - -sub attributes { @{shift->{attributes}} } - -sub attr_hash { - my $self = shift; - return $self->{attr_hash} ||= { $self->attributes }; -} - -sub attr { - my $self = shift; - if (@_) { - my $key = shift; - return $self->attr_hash->{$key}; - } - return $self->attr_hash; -} - -1; +package DBD::Oracle::Object; +{ + $DBD::Oracle::Object::VERSION = '1.39_00'; +} +BEGIN { + $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; +} +# ABSTRACT: Wrapper for Oracle objects + +use strict; +use warnings; + +sub type_name { shift->{type_name} } + +sub attributes { @{shift->{attributes}} } + +sub attr_hash { + my $self = shift; + return $self->{attr_hash} ||= { $self->attributes }; +} + +sub attr { + my $self = shift; + if (@_) { + my $key = shift; + return $self->attr_hash->{$key}; + } + return $self->attr_hash; +} + +1; + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Object - Wrapper for Oracle objects + +=head1 VERSION + +version 1.39_00 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 37034663..9b790b4b 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,8 +1,24 @@ package DBD::Oracle::Troubleshooting; +{ + $DBD::Oracle::Troubleshooting::VERSION = '1.39_00'; +} +BEGIN { + $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; +} #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle + +__END__ =pod +=head1 NAME + +DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle + +=head1 VERSION + +version 1.39_00 + =head1 CONNECTING TO ORACLE If you are reading this it is assumed that you have successfully @@ -29,7 +45,6 @@ For Windows the solution is to add this value to you PATH PATH=c:\app\oracle\product\xx.x.x;%PATH% - If you get past this stage and get a ORA-12154: TNS:could not resolve the connect identifier specified @@ -77,7 +92,6 @@ L and L for more gory details. - =head1 USING THE LONG TYPES Some examples related to the use of LONG types are available in @@ -112,7 +126,6 @@ It turns out that now it is necessary to edit the same file and append this and then run "genclntsh", the libclntsh is properly generated and the linkage with DBD::Oracle proceeds properly. - =head2 cc1: invalid option `tune=pentium4'" error If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. @@ -169,7 +182,7 @@ To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY as you would for an install against 10g Standard Edition, Standard Edition One, or Enterprise Edition -=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 +=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 DBD::Oracle seems to hit some sort of bug with the above two versions of DB. The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also @@ -188,7 +201,6 @@ So far there is no patch for this but here are some work arounds or this way utf8::downgrade($parameter, 1); - =head1 CYGWIN @@ -351,4 +363,30 @@ oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + diff --git a/t/000-report-versions.t b/t/000-report-versions.t new file mode 100644 index 00000000..2d4a9a19 --- /dev/null +++ b/t/000-report-versions.t @@ -0,0 +1,446 @@ +#!perl +use warnings; +use strict; +use Test::More 0.94; + +# Include a cut-down version of YAML::Tiny so we don't introduce unnecessary +# dependencies ourselves. + +package Local::YAML::Tiny; + +use strict; +use Carp 'croak'; + +# UTF Support? +sub HAVE_UTF8 () { $] >= 5.007003 } +BEGIN { + if ( HAVE_UTF8 ) { + # The string eval helps hide this from Test::MinimumVersion + eval "require utf8;"; + die "Failed to load UTF-8 support" if $@; + } + + # Class structure + require 5.004; + $YAML::Tiny::VERSION = '1.40'; + + # Error storage + $YAML::Tiny::errstr = ''; +} + +# Printable characters for escapes +my %UNESCAPES = ( + z => "\x00", a => "\x07", t => "\x09", + n => "\x0a", v => "\x0b", f => "\x0c", + r => "\x0d", e => "\x1b", '\\' => '\\', +); + + +##################################################################### +# Implementation + +# Create an empty YAML::Tiny object +sub new { + my $class = shift; + bless [ @_ ], $class; +} + +# Create an object from a file +sub read { + my $class = ref $_[0] ? ref shift : shift; + + # Check the file + my $file = shift or return $class->_error( 'You did not specify a file name' ); + return $class->_error( "File '$file' does not exist" ) unless -e $file; + return $class->_error( "'$file' is a directory, not a file" ) unless -f _; + return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; + + # Slurp in the file + local $/ = undef; + local *CFG; + unless ( open(CFG, $file) ) { + return $class->_error("Failed to open file '$file': $!"); + } + my $contents = ; + unless ( close(CFG) ) { + return $class->_error("Failed to close file '$file': $!"); + } + + $class->read_string( $contents ); +} + +# Create an object from a string +sub read_string { + my $class = ref $_[0] ? ref shift : shift; + my $self = bless [], $class; + my $string = $_[0]; + unless ( defined $string ) { + return $self->_error("Did not provide a string to load"); + } + + # Byte order marks + # NOTE: Keeping this here to educate maintainers + # my %BOM = ( + # "\357\273\277" => 'UTF-8', + # "\376\377" => 'UTF-16BE', + # "\377\376" => 'UTF-16LE', + # "\377\376\0\0" => 'UTF-32LE' + # "\0\0\376\377" => 'UTF-32BE', + # ); + if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) { + return $self->_error("Stream has a non UTF-8 BOM"); + } else { + # Strip UTF-8 bom if found, we'll just ignore it + $string =~ s/^\357\273\277//; + } + + # Try to decode as utf8 + utf8::decode($string) if HAVE_UTF8; + + # Check for some special cases + return $self unless length $string; + unless ( $string =~ /[\012\015]+\z/ ) { + return $self->_error("Stream does not end with newline character"); + } + + # Split the file into lines + my @lines = grep { ! /^\s*(?:\#.*)?\z/ } + split /(?:\015{1,2}\012|\015|\012)/, $string; + + # Strip the initial YAML header + @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; + + # A nibbling parser + while ( @lines ) { + # Do we have a document header? + if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { + # Handle scalar documents + shift @lines; + if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { + push @$self, $self->_read_scalar( "$1", [ undef ], \@lines ); + next; + } + } + + if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { + # A naked document + push @$self, undef; + while ( @lines and $lines[0] !~ /^---/ ) { + shift @lines; + } + + } elsif ( $lines[0] =~ /^\s*\-/ ) { + # An array at the root + my $document = [ ]; + push @$self, $document; + $self->_read_array( $document, [ 0 ], \@lines ); + + } elsif ( $lines[0] =~ /^(\s*)\S/ ) { + # A hash at the root + my $document = { }; + push @$self, $document; + $self->_read_hash( $document, [ length($1) ], \@lines ); + + } else { + croak("YAML::Tiny failed to classify the line '$lines[0]'"); + } + } + + $self; +} + +# Deparse a scalar string to the actual scalar +sub _read_scalar { + my ($self, $string, $indent, $lines) = @_; + + # Trim trailing whitespace + $string =~ s/\s*\z//; + + # Explitic null/undef + return undef if $string eq '~'; + + # Quotes + if ( $string =~ /^\'(.*?)\'\z/ ) { + return '' unless defined $1; + $string = $1; + $string =~ s/\'\'/\'/g; + return $string; + } + if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) { + # Reusing the variable is a little ugly, + # but avoids a new variable and a string copy. + $string = $1; + $string =~ s/\\"/"/g; + $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; + return $string; + } + + # Special cases + if ( $string =~ /^[\'\"!&]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + return {} if $string eq '{}'; + return [] if $string eq '[]'; + + # Regular unquoted string + return $string unless $string =~ /^[>|]/; + + # Error + croak("YAML::Tiny failed to find multi-line scalar content") unless @$lines; + + # Check the indent depth + $lines->[0] =~ /^(\s*)/; + $indent->[-1] = length("$1"); + if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Pull the lines + my @multiline = (); + while ( @$lines ) { + $lines->[0] =~ /^(\s*)/; + last unless length($1) >= $indent->[-1]; + push @multiline, substr(shift(@$lines), length($1)); + } + + my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; + my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; + return join( $j, @multiline ) . $t; +} + +# Parse an array +sub _read_array { + my ($self, $array, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { + # Inline nested hash + my $indent2 = length("$1"); + $lines->[0] =~ s/-/ /; + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { + # Array entry with a value + shift @$lines; + push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { + shift @$lines; + unless ( @$lines ) { + push @$array, undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)\-/ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] == $indent2 ) { + # Null array entry + push @$array, undef; + } else { + # Naked indenter + push @$array, [ ]; + $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines ); + } + + } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines ); + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + + } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { + # This is probably a structure like the following... + # --- + # foo: + # - list + # bar: value + # + # ... so lets return and let the hash parser handle it + return 1; + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + } + + return 1; +} + +# Parse an array +sub _read_hash { + my ($self, $hash, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Get the key + unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { + if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + my $key = $1; + + # Do we have a value? + if ( length $lines->[0] ) { + # Yes + $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines ); + } else { + # An indent + shift @$lines; + unless ( @$lines ) { + $hash->{$key} = undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)-/ ) { + $hash->{$key} = []; + $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } elsif ( $lines->[0] =~ /^(\s*)./ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] >= $indent2 ) { + # Null hash entry + $hash->{$key} = undef; + } else { + $hash->{$key} = {}; + $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } + } + } + } + + return 1; +} + +# Set error +sub _error { + $YAML::Tiny::errstr = $_[1]; + undef; +} + +# Retrieve error +sub errstr { + $YAML::Tiny::errstr; +} + + + +##################################################################### +# Use Scalar::Util if possible, otherwise emulate it + +BEGIN { + eval { + require Scalar::Util; + }; + if ( $@ ) { + # Failed to load Scalar::Util + eval <<'END_PERL'; +sub refaddr { + my $pkg = ref($_[0]) or return undef; + if (!!UNIVERSAL::can($_[0], 'can')) { + bless $_[0], 'Scalar::Util::Fake'; + } else { + $pkg = undef; + } + "$_[0]" =~ /0x(\w+)/; + my $i = do { local $^W; hex $1 }; + bless $_[0], $pkg if defined $pkg; + $i; +} +END_PERL + } else { + Scalar::Util->import('refaddr'); + } +} + + +##################################################################### +# main test +##################################################################### + +package main; + +BEGIN { + + # Skip modules that either don't want to be loaded directly, such as + # Module::Install, or that mess with the test count, such as the Test::* + # modules listed here. + # + # Moose::Role conflicts if Moose is loaded as well, but Moose::Role is in + # the Moose distribution and it's certain that someone who uses + # Moose::Role also uses Moose somewhere, so if we disallow Moose::Role, + # we'll still get the relevant version number. + + my %skip = map { $_ => 1 } qw( + App::FatPacker + Class::Accessor::Classy + Devel::Cover + Module::Install + Moose::Role + POE::Loop::Tk + Template::Test + Test::Kwalitee + Test::Pod::Coverage + Test::Portability::Files + Test::YAML::Meta + ); + + my $Test = Test::Builder->new; + + $Test->plan(skip_all => "META.yml could not be found") + unless -f 'META.yml' and -r _; + + my $meta = (Local::YAML::Tiny->read('META.yml'))->[0]; + my %requires; + for my $require_key (grep { /requires/ } keys %$meta) { + my %h = %{ $meta->{$require_key} }; + $requires{$_}++ for keys %h; + } + delete $requires{perl}; + + diag("Testing with Perl $], $^X"); + for my $module (sort keys %requires) { + if ($skip{$module}) { + note "$module doesn't want to be loaded directly, skipping"; + next; + } + local $SIG{__WARN__} = sub { note "$module: $_[0]" }; + use_ok $module or BAIL_OUT("can't load $module"); + my $version = $module->VERSION; + $version = 'undefined' unless defined $version; + diag(" $module version is $version"); + } + done_testing; +} diff --git a/xt/changes.t b/xt/changes.t deleted file mode 100644 index 27a4808a..00000000 --- a/xt/changes.t +++ /dev/null @@ -1,8 +0,0 @@ -use strict; -use warnings; - -use Test::More; - -eval 'use Test::CPAN::Changes'; -plan skip_all => 'Test::CPAN::Changes required for this test' if $@; -changes_ok(); diff --git a/xt/manifest.t b/xt/manifest.t deleted file mode 100644 index 00df9957..00000000 --- a/xt/manifest.t +++ /dev/null @@ -1,21 +0,0 @@ -use strict; -use warnings; - -use ExtUtils::Manifest qw/ fullcheck /; - -use Test::More tests => 1; - -my ( $missing, $extra ) = do { - local *STDERR; - - # hush little baby, don't you cry - open STDERR, '>', \my $stderr; - - fullcheck(); -}; - -ok @$missing + @$extra == 0, 'manifest in sync' or do { - diag "missing files:\n", map { " \t $_\n " } @$missing if @$missing; - diag "extra files: \n", map { "\t$_\n" } @$extra if @$extra; -}; - diff --git a/xt/pod.t b/xt/pod.t deleted file mode 100644 index 66481225..00000000 --- a/xt/pod.t +++ /dev/null @@ -1,11 +0,0 @@ -use Test::More; - -eval "use Test::Pod"; - -plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; - -pod_file_ok( 'Oracle.pm' ); -pod_file_ok( 'lib/DBD/Oracle/Object.pm' ); -pod_file_ok( 'lib/DBD/Oracle/GetInfo.pm' ); - -done_testing; From b8b4efc94c483c5e9c7924fce267eaaed1fb28ec Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 24 Feb 2012 16:28:29 -0500 Subject: [PATCH 135/637] bumping version to v1.39_00 --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 013f79fc..f06dfeb4 100644 --- a/dist.ini +++ b/dist.ini @@ -6,7 +6,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.38 +version = 1.39_00 [Authority] authority=cpan:PYTHIAN From 8b1d3c20ddc5d681b75aaaf6b56ee3258b2f403b Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 24 Feb 2012 16:35:23 -0500 Subject: [PATCH 136/637] v1.39_00 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED [RT73798] - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) [RT74544] - PL/SQL out values were not utf8 encoded [RT74753] (Steve Baldwin + Martin J. Evans) [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work on Lion. (Martin J. Evans) - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] - fix typos. (patch by Julián Moreno Patiño) [rt73999] - add troubleshoot doc and diag for error with bequeather. [rt75263] [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' [RT74001] --- Changes | 2 ++ dist.ini | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Changes b/Changes index 9728652e..847de60f 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} +1.39_00 2012-02-24 + [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED [RT73798] diff --git a/dist.ini b/dist.ini index f06dfeb4..221f505c 100644 --- a/dist.ini +++ b/dist.ini @@ -19,4 +19,6 @@ authority=cpan:PYTHIAN -remove=ModuleBuild -remove=Authority -remove=Signature +-remove=UploadToCPAN +[FakeRelease] From 5bc5a8b955d484d506a3e6b55bf26f3458193d13 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 24 Feb 2012 16:40:34 -0500 Subject: [PATCH 137/637] remove twitter plugin --- dist.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/dist.ini b/dist.ini index 221f505c..182573b8 100644 --- a/dist.ini +++ b/dist.ini @@ -20,5 +20,6 @@ authority=cpan:PYTHIAN -remove=Authority -remove=Signature -remove=UploadToCPAN +-remove=Twitter [FakeRelease] From af6bbc64f16a1786b536d0c2058a082e7093c148 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 1 Mar 2012 15:23:43 +0000 Subject: [PATCH 138/637] Some pod changes for StrictlyTyped/DiscardString Clarify LongReadLen on long types default LongReadLen to 1Mb when calling column_info if the default has not been changed git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15192 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 18 +++++++++++----- lib/DBD/Oracle.pm | 52 +++++++++++++++++++++++++++++++++++++++++------ t/70meta.t | 32 +++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 13 deletions(-) diff --git a/Changes b/Changes index cd0bb996..82edeaa8 100644 --- a/Changes +++ b/Changes @@ -1,14 +1,20 @@ Revision history for DBD::Oracle -NEXT +NEXT [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED [RT73798] - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) [RT74544] - - PL/SQL out values were not utf8 encoded [RT74753] + - PL/SQL out values were not utf8 encoded [RT74753] (Steve Baldwin + Martin J. Evans) + - Applied patch from Rafael Kitover (Caelum) to column_info to handle + DEFAULT columns greater in length than the DBI default of 80. The + DEFAULT column is a long and it is a PITA to have to set + LongReadLen which you can only do on a connection handle in + DBD::Oracle. The default maximum size is now 1Mb; above that you + will still have to set LongReadLen (Martin J. Evans) [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work @@ -16,6 +22,8 @@ NEXT - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] - fix typos. (patch by Julián Moreno Patiño) [rt73999] - add troubleshoot doc and diag for error with bequeather. [rt75263] + - clarification of when StrictlyTyped/DiscardString can be used and + LongReadLen (Martin J. Evans) [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' @@ -32,7 +40,7 @@ NEXT 1.37_00 2011-12-30 [ENHANCEMENTS] - - added SYSASM session mode. [RT651211] (patch from + - added SYSASM session mode. [RT651211] (patch from Anthony DeRobertis, reported by Julián Moreno Patiño) [BUG FIXES] @@ -50,7 +58,7 @@ NEXT - Fix documentation for 'ora_fetch_scroll()' Changes in DBD-Oracle 1.36 (6-12-2011) - + - promote 1.35_00 to official release Changes in DBD-Oracle 1.35_00 (18-11-2011) @@ -110,7 +118,7 @@ Changes in DBD-Oracle 1.31_00 - don't gag diag() on the tests by default - SKIP condition in 10general.t was reversed (reported by Alois) [RT#46761] - Check for LD_LIBRARY_PATH_(32|64) as well for solaris [RT#46761] - - convert a symbolically linked ORACLE_HOME to an absolute path + - convert a symbolically linked ORACLE_HOME to an absolute path (patch by H.Merijn Brand, applied by Martin J. Evans) [rt70785] [DOCUMENTATION] diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 780e5901..9cf21d81 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -753,7 +753,38 @@ SQL } } $SQL .= " ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION\n"; - my $sth = $dbh->prepare( $SQL ) or return undef; + + + # Since DATA_DEFAULT is a LONG, DEFAULT values longer than 80 chars will + # throw an ORA-24345 by default; so we check if LongReadLen is set at + # the default value, and if so, set it to something less likely to fail + # in common usage. + # + # We do not set LongTruncOk however as that would make COLUMN_DEF + # incorrect, in those (extreme!) cases it would be better if the user + # sets LongReadLen herself. + + my $long_read_len = $dbh->FETCH('LongReadLen'); + + my ($sth, $exc); + + { + local $@; + eval { + $dbh->STORE(LongReadLen => 1024*1024) if $long_read_len == 80; + $sth = $dbh->prepare( $SQL ); + }; + $exc = $@; + } + if ($exc) { + $dbh->STORE(LongReadLen => 80) if $long_read_len == 80; + die $exc; + } + + $dbh->STORE(LongReadLen => 80) if $long_read_len == 80; + + return undef if not $sth; + $sth->execute( @BindVals ) or return undef; $sth; } @@ -2098,7 +2129,12 @@ Should be rarely needed. =head2 B -Implemented by DBI, no driver-specific impact. +The maximum size of long or longraw columns to retrieve. If one of +these columns is longer than LongReadLen then either a data truncation +error will be raised (LongTrunkOk is false) or the column will be +silently truncated (LongTruncOk is true). + +DBI currently defaults this to 80. =head2 B @@ -2458,7 +2494,11 @@ Especially the length of FLOATs may be wrong. Datatype codes for non-standard types are subject to change. -Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG so you +may have to set LongReadLen on the connection handle before calling +column_info if you have a large default column. After DBD::Oracle 1.40 +LongReadLen is set automatically to 1Mb when calling column_info and +reset aftwerwards. The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. @@ -3239,9 +3279,9 @@ Column numbers count up from 1. You do not need to bind output columns in order NOTE: DBD::Oracle does not use the C<$bind_type> to determine how to bind the column; it uses what Oracle says the data type is. You can -however set a numeric bind type with the bind attributes -StrictlyTyped/DiscardString as these attributes are applied after the -column is retrieved. +however set the StrictlyTyped/DiscardString attributes and these will +take effect as these attributes are applied after the column is +retrieved. See the DBI documentation for a discussion of the optional parameters C<\%attr> and C<$bind_type> diff --git a/t/70meta.t b/t/70meta.t index d8e29938..301c8c62 100644 --- a/t/70meta.t +++ b/t/70meta.t @@ -12,10 +12,10 @@ $| = 1; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', { PrintError => 0 }); +my $dbh = DBI->connect($dsn, $dbuser, '', { RaiseError => 1, PrintError => 0 }); if ($dbh) { - plan tests=>13; + plan tests=>21; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -53,6 +53,34 @@ ok($sql_dbms_version, 'dbms_version'); note "sql_dbms_version=$sql_dbms_version"; like($sql_dbms_version, qr/^\d+\.\d+\.\d+$/, 'matched'); +# test long DEFAULT from column_info +SKIP: { + my $table = "dbd_ora__drop_me" . ($ENV{DBD_ORACLE_SEQ}||''); + + eval { $dbh->do("DROP TABLE $table") }; + + my $created = eval { $dbh->do("CREATE TABLE $table (testcol NUMBER(15) DEFAULT to_number(decode(substrb(userenv('CLIENT_INFO'),1,1),' ', null,substrb(userenv('CLIENT_INFO'),1,10))))") }; + + skip 'could not create test table', 8 unless $created; + + is $dbh->{LongReadLen}, 80, 'LongReadLen is at default'; + + ok((my $sth = $dbh->column_info(undef, '%', uc($table), '%')), 'column_info sth'); + + is $dbh->{LongReadLen}, 80, 'LongReadLen still at default'; + + ok((my $info = eval { $sth->fetchrow_hashref }), 'sth->fetchrow_hashref lived') + or diag $@; + + is $info->{COLUMN_DEF}, "to_number(decode(substrb(userenv('CLIENT_INFO'),1,1),' ', null,substrb(userenv('CLIENT_INFO'),1,10)))", 'long DEFAULT matched'; + + ok($sth->finish, 'sth->finish'); + + is $dbh->{LongReadLen}, 80, 'LongReadLen still at default'; + + ok($dbh->do("DROP TABLE $table"), 'drop table'); +} + $dbh->disconnect; exit 0; From d09c31278ec5c4943e0cfc934bd019be2445828d Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 1 Mar 2012 15:23:43 +0000 Subject: [PATCH 139/637] Some pod changes for StrictlyTyped/DiscardString Clarify LongReadLen on long types default LongReadLen to 1Mb when calling column_info if the default has not been changed git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15192 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 18 +++++++++++----- lib/DBD/Oracle.pm | 52 +++++++++++++++++++++++++++++++++++++++++------ t/70meta.t | 32 +++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 13 deletions(-) diff --git a/Changes b/Changes index cd0bb996..82edeaa8 100644 --- a/Changes +++ b/Changes @@ -1,14 +1,20 @@ Revision history for DBD::Oracle -NEXT +NEXT [BUG FIXES] - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED [RT73798] - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) [RT74544] - - PL/SQL out values were not utf8 encoded [RT74753] + - PL/SQL out values were not utf8 encoded [RT74753] (Steve Baldwin + Martin J. Evans) + - Applied patch from Rafael Kitover (Caelum) to column_info to handle + DEFAULT columns greater in length than the DBI default of 80. The + DEFAULT column is a long and it is a PITA to have to set + LongReadLen which you can only do on a connection handle in + DBD::Oracle. The default maximum size is now 1Mb; above that you + will still have to set LongReadLen (Martin J. Evans) [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work @@ -16,6 +22,8 @@ NEXT - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] - fix typos. (patch by Julián Moreno Patiño) [rt73999] - add troubleshoot doc and diag for error with bequeather. [rt75263] + - clarification of when StrictlyTyped/DiscardString can be used and + LongReadLen (Martin J. Evans) [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' @@ -32,7 +40,7 @@ NEXT 1.37_00 2011-12-30 [ENHANCEMENTS] - - added SYSASM session mode. [RT651211] (patch from + - added SYSASM session mode. [RT651211] (patch from Anthony DeRobertis, reported by Julián Moreno Patiño) [BUG FIXES] @@ -50,7 +58,7 @@ NEXT - Fix documentation for 'ora_fetch_scroll()' Changes in DBD-Oracle 1.36 (6-12-2011) - + - promote 1.35_00 to official release Changes in DBD-Oracle 1.35_00 (18-11-2011) @@ -110,7 +118,7 @@ Changes in DBD-Oracle 1.31_00 - don't gag diag() on the tests by default - SKIP condition in 10general.t was reversed (reported by Alois) [RT#46761] - Check for LD_LIBRARY_PATH_(32|64) as well for solaris [RT#46761] - - convert a symbolically linked ORACLE_HOME to an absolute path + - convert a symbolically linked ORACLE_HOME to an absolute path (patch by H.Merijn Brand, applied by Martin J. Evans) [rt70785] [DOCUMENTATION] diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 780e5901..9cf21d81 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -753,7 +753,38 @@ SQL } } $SQL .= " ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION\n"; - my $sth = $dbh->prepare( $SQL ) or return undef; + + + # Since DATA_DEFAULT is a LONG, DEFAULT values longer than 80 chars will + # throw an ORA-24345 by default; so we check if LongReadLen is set at + # the default value, and if so, set it to something less likely to fail + # in common usage. + # + # We do not set LongTruncOk however as that would make COLUMN_DEF + # incorrect, in those (extreme!) cases it would be better if the user + # sets LongReadLen herself. + + my $long_read_len = $dbh->FETCH('LongReadLen'); + + my ($sth, $exc); + + { + local $@; + eval { + $dbh->STORE(LongReadLen => 1024*1024) if $long_read_len == 80; + $sth = $dbh->prepare( $SQL ); + }; + $exc = $@; + } + if ($exc) { + $dbh->STORE(LongReadLen => 80) if $long_read_len == 80; + die $exc; + } + + $dbh->STORE(LongReadLen => 80) if $long_read_len == 80; + + return undef if not $sth; + $sth->execute( @BindVals ) or return undef; $sth; } @@ -2098,7 +2129,12 @@ Should be rarely needed. =head2 B -Implemented by DBI, no driver-specific impact. +The maximum size of long or longraw columns to retrieve. If one of +these columns is longer than LongReadLen then either a data truncation +error will be raised (LongTrunkOk is false) or the column will be +silently truncated (LongTruncOk is true). + +DBI currently defaults this to 80. =head2 B @@ -2458,7 +2494,11 @@ Especially the length of FLOATs may be wrong. Datatype codes for non-standard types are subject to change. -Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG so you +may have to set LongReadLen on the connection handle before calling +column_info if you have a large default column. After DBD::Oracle 1.40 +LongReadLen is set automatically to 1Mb when calling column_info and +reset aftwerwards. The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. @@ -3239,9 +3279,9 @@ Column numbers count up from 1. You do not need to bind output columns in order NOTE: DBD::Oracle does not use the C<$bind_type> to determine how to bind the column; it uses what Oracle says the data type is. You can -however set a numeric bind type with the bind attributes -StrictlyTyped/DiscardString as these attributes are applied after the -column is retrieved. +however set the StrictlyTyped/DiscardString attributes and these will +take effect as these attributes are applied after the column is +retrieved. See the DBI documentation for a discussion of the optional parameters C<\%attr> and C<$bind_type> diff --git a/t/70meta.t b/t/70meta.t index d8e29938..301c8c62 100644 --- a/t/70meta.t +++ b/t/70meta.t @@ -12,10 +12,10 @@ $| = 1; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', { PrintError => 0 }); +my $dbh = DBI->connect($dsn, $dbuser, '', { RaiseError => 1, PrintError => 0 }); if ($dbh) { - plan tests=>13; + plan tests=>21; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -53,6 +53,34 @@ ok($sql_dbms_version, 'dbms_version'); note "sql_dbms_version=$sql_dbms_version"; like($sql_dbms_version, qr/^\d+\.\d+\.\d+$/, 'matched'); +# test long DEFAULT from column_info +SKIP: { + my $table = "dbd_ora__drop_me" . ($ENV{DBD_ORACLE_SEQ}||''); + + eval { $dbh->do("DROP TABLE $table") }; + + my $created = eval { $dbh->do("CREATE TABLE $table (testcol NUMBER(15) DEFAULT to_number(decode(substrb(userenv('CLIENT_INFO'),1,1),' ', null,substrb(userenv('CLIENT_INFO'),1,10))))") }; + + skip 'could not create test table', 8 unless $created; + + is $dbh->{LongReadLen}, 80, 'LongReadLen is at default'; + + ok((my $sth = $dbh->column_info(undef, '%', uc($table), '%')), 'column_info sth'); + + is $dbh->{LongReadLen}, 80, 'LongReadLen still at default'; + + ok((my $info = eval { $sth->fetchrow_hashref }), 'sth->fetchrow_hashref lived') + or diag $@; + + is $info->{COLUMN_DEF}, "to_number(decode(substrb(userenv('CLIENT_INFO'),1,1),' ', null,substrb(userenv('CLIENT_INFO'),1,10)))", 'long DEFAULT matched'; + + ok($sth->finish, 'sth->finish'); + + is $dbh->{LongReadLen}, 80, 'LongReadLen still at default'; + + ok($dbh->do("DROP TABLE $table"), 'drop table'); +} + $dbh->disconnect; exit 0; From 295090f411f5d8772d3e7dc4668d30d5d171178d Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 8 Mar 2012 15:08:01 -0500 Subject: [PATCH 140/637] preps for the release --- Changes | 1 + dist.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 847de60f..32e4503d 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,7 @@ Revision history for DBD::Oracle {{$NEXT}} + - promote 1.39_00 to official release 1.39_00 2012-02-24 diff --git a/dist.ini b/dist.ini index 221f505c..c67c8f92 100644 --- a/dist.ini +++ b/dist.ini @@ -6,7 +6,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.39_00 +version = 1.40 [Authority] authority=cpan:PYTHIAN From d0880e5efecf6faa24f049f0a1545f4de323e50f Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 1 Mar 2012 15:23:43 +0000 Subject: [PATCH 141/637] Some pod changes for StrictlyTyped/DiscardString Clarify LongReadLen on long types default LongReadLen to 1Mb when calling column_info if the default has not been changed git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15192 50811bd7-b8ce-0310-adc1-d9db26280581 Conflicts: Changes --- Changes | 16 +++++++++++---- lib/DBD/Oracle.pm | 52 +++++++++++++++++++++++++++++++++++++++++------ t/70meta.t | 32 +++++++++++++++++++++++++++-- 3 files changed, 88 insertions(+), 12 deletions(-) diff --git a/Changes b/Changes index 32e4503d..69e92911 100644 --- a/Changes +++ b/Changes @@ -10,8 +10,14 @@ Revision history for DBD::Oracle [RT73798] - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) [RT74544] - - PL/SQL out values were not utf8 encoded [RT74753] + - PL/SQL out values were not utf8 encoded [RT74753] (Steve Baldwin + Martin J. Evans) + - Applied patch from Rafael Kitover (Caelum) to column_info to handle + DEFAULT columns greater in length than the DBI default of 80. The + DEFAULT column is a long and it is a PITA to have to set + LongReadLen which you can only do on a connection handle in + DBD::Oracle. The default maximum size is now 1Mb; above that you + will still have to set LongReadLen (Martin J. Evans) [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work @@ -19,6 +25,8 @@ Revision history for DBD::Oracle - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] - fix typos. (patch by Julián Moreno Patiño) [rt73999] - add troubleshoot doc and diag for error with bequeather. [rt75263] + - clarification of when StrictlyTyped/DiscardString can be used and + LongReadLen (Martin J. Evans) [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' @@ -31,7 +39,7 @@ Revision history for DBD::Oracle 1.37_00 2011-12-30 [ENHANCEMENTS] - - added SYSASM session mode. [RT651211] (patch from + - added SYSASM session mode. [RT651211] (patch from Anthony DeRobertis, reported by Julián Moreno Patiño) [BUG FIXES] @@ -49,7 +57,7 @@ Revision history for DBD::Oracle - Fix documentation for 'ora_fetch_scroll()' Changes in DBD-Oracle 1.36 (6-12-2011) - + - promote 1.35_00 to official release Changes in DBD-Oracle 1.35_00 (18-11-2011) @@ -109,7 +117,7 @@ Changes in DBD-Oracle 1.31_00 - don't gag diag() on the tests by default - SKIP condition in 10general.t was reversed (reported by Alois) [RT#46761] - Check for LD_LIBRARY_PATH_(32|64) as well for solaris [RT#46761] - - convert a symbolically linked ORACLE_HOME to an absolute path + - convert a symbolically linked ORACLE_HOME to an absolute path (patch by H.Merijn Brand, applied by Martin J. Evans) [rt70785] [DOCUMENTATION] diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index ff71f86b..7cbdf5ad 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -735,7 +735,38 @@ SQL } } $SQL .= " ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION\n"; - my $sth = $dbh->prepare( $SQL ) or return undef; + + + # Since DATA_DEFAULT is a LONG, DEFAULT values longer than 80 chars will + # throw an ORA-24345 by default; so we check if LongReadLen is set at + # the default value, and if so, set it to something less likely to fail + # in common usage. + # + # We do not set LongTruncOk however as that would make COLUMN_DEF + # incorrect, in those (extreme!) cases it would be better if the user + # sets LongReadLen herself. + + my $long_read_len = $dbh->FETCH('LongReadLen'); + + my ($sth, $exc); + + { + local $@; + eval { + $dbh->STORE(LongReadLen => 1024*1024) if $long_read_len == 80; + $sth = $dbh->prepare( $SQL ); + }; + $exc = $@; + } + if ($exc) { + $dbh->STORE(LongReadLen => 80) if $long_read_len == 80; + die $exc; + } + + $dbh->STORE(LongReadLen => 80) if $long_read_len == 80; + + return undef if not $sth; + $sth->execute( @BindVals ) or return undef; $sth; } @@ -2070,7 +2101,12 @@ Should be rarely needed. =head2 B -Implemented by DBI, no driver-specific impact. +The maximum size of long or longraw columns to retrieve. If one of +these columns is longer than LongReadLen then either a data truncation +error will be raised (LongTrunkOk is false) or the column will be +silently truncated (LongTruncOk is true). + +DBI currently defaults this to 80. =head2 B @@ -2435,7 +2471,11 @@ Especially the length of FLOATs may be wrong. Datatype codes for non-standard types are subject to change. -Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG so you +may have to set LongReadLen on the connection handle before calling +column_info if you have a large default column. After DBD::Oracle 1.40 +LongReadLen is set automatically to 1Mb when calling column_info and +reset aftwerwards. The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. @@ -3228,9 +3268,9 @@ Column numbers count up from 1. You do not need to bind output columns in order NOTE: DBD::Oracle does not use the C<$bind_type> to determine how to bind the column; it uses what Oracle says the data type is. You can -however set a numeric bind type with the bind attributes -StrictlyTyped/DiscardString as these attributes are applied after the -column is retrieved. +however set the StrictlyTyped/DiscardString attributes and these will +take effect as these attributes are applied after the column is +retrieved. See the DBI documentation for a discussion of the optional parameters C<\%attr> and C<$bind_type> diff --git a/t/70meta.t b/t/70meta.t index d8e29938..301c8c62 100644 --- a/t/70meta.t +++ b/t/70meta.t @@ -12,10 +12,10 @@ $| = 1; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', { PrintError => 0 }); +my $dbh = DBI->connect($dsn, $dbuser, '', { RaiseError => 1, PrintError => 0 }); if ($dbh) { - plan tests=>13; + plan tests=>21; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -53,6 +53,34 @@ ok($sql_dbms_version, 'dbms_version'); note "sql_dbms_version=$sql_dbms_version"; like($sql_dbms_version, qr/^\d+\.\d+\.\d+$/, 'matched'); +# test long DEFAULT from column_info +SKIP: { + my $table = "dbd_ora__drop_me" . ($ENV{DBD_ORACLE_SEQ}||''); + + eval { $dbh->do("DROP TABLE $table") }; + + my $created = eval { $dbh->do("CREATE TABLE $table (testcol NUMBER(15) DEFAULT to_number(decode(substrb(userenv('CLIENT_INFO'),1,1),' ', null,substrb(userenv('CLIENT_INFO'),1,10))))") }; + + skip 'could not create test table', 8 unless $created; + + is $dbh->{LongReadLen}, 80, 'LongReadLen is at default'; + + ok((my $sth = $dbh->column_info(undef, '%', uc($table), '%')), 'column_info sth'); + + is $dbh->{LongReadLen}, 80, 'LongReadLen still at default'; + + ok((my $info = eval { $sth->fetchrow_hashref }), 'sth->fetchrow_hashref lived') + or diag $@; + + is $info->{COLUMN_DEF}, "to_number(decode(substrb(userenv('CLIENT_INFO'),1,1),' ', null,substrb(userenv('CLIENT_INFO'),1,10)))", 'long DEFAULT matched'; + + ok($sth->finish, 'sth->finish'); + + is $dbh->{LongReadLen}, 80, 'LongReadLen still at default'; + + ok($dbh->do("DROP TABLE $table"), 'drop table'); +} + $dbh->disconnect; exit 0; From d80c813bf165944c44dc19d30c949730b3060a70 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 8 Mar 2012 15:39:14 -0500 Subject: [PATCH 142/637] rejuggling the Changelog --- Changes | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/Changes b/Changes index 69e92911..630fa98d 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,21 @@ Revision history for DBD::Oracle {{$NEXT}} + + [BUG FIXES] + - Applied patch from Rafael Kitover (Caelum) to column_info to handle + DEFAULT columns greater in length than the DBI default of 80. The + DEFAULT column is a long and it is a PITA to have to set + LongReadLen which you can only do on a connection handle in + DBD::Oracle. The default maximum size is now 1Mb; above that you + will still have to set LongReadLen (Martin J. Evans) + + + [DOCUMENTATION] + - clarification of when StrictlyTyped/DiscardString can be used and + LongReadLen (Martin J. Evans) + +1.40 2012-03-08 - promote 1.39_00 to official release 1.39_00 2012-02-24 @@ -12,12 +27,6 @@ Revision history for DBD::Oracle [RT74544] - PL/SQL out values were not utf8 encoded [RT74753] (Steve Baldwin + Martin J. Evans) - - Applied patch from Rafael Kitover (Caelum) to column_info to handle - DEFAULT columns greater in length than the DBI default of 80. The - DEFAULT column is a long and it is a PITA to have to set - LongReadLen which you can only do on a connection handle in - DBD::Oracle. The default maximum size is now 1Mb; above that you - will still have to set LongReadLen (Martin J. Evans) [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work @@ -25,8 +34,6 @@ Revision history for DBD::Oracle - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] - fix typos. (patch by Julián Moreno Patiño) [rt73999] - add troubleshoot doc and diag for error with bequeather. [rt75263] - - clarification of when StrictlyTyped/DiscardString can be used and - LongReadLen (Martin J. Evans) [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' From 8cda25ddba790b72b494b1459d09a099c24ad588 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 8 Mar 2012 20:50:22 +0000 Subject: [PATCH 143/637] merge back v1.40 release changes Mostly versioning and rejuggling of Changelog git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15206 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 30 ++++++++++++++++++------------ META.json | 18 +++++++++++------- META.yml | 16 ++++++++-------- README | 20 ++++++++++++++------ README.mkdn | 23 ++++++++++++++++------- lib/DBD/Oracle.pm | 10 +++++----- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pm | 4 ++-- 9 files changed, 78 insertions(+), 51 deletions(-) diff --git a/Changes b/Changes index 82edeaa8..74702a5d 100644 --- a/Changes +++ b/Changes @@ -3,12 +3,6 @@ Revision history for DBD::Oracle NEXT [BUG FIXES] - - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED - [RT73798] - - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) - [RT74544] - - PL/SQL out values were not utf8 encoded [RT74753] - (Steve Baldwin + Martin J. Evans) - Applied patch from Rafael Kitover (Caelum) to column_info to handle DEFAULT columns greater in length than the DBI default of 80. The DEFAULT column is a long and it is a PITA to have to set @@ -16,18 +10,30 @@ NEXT DBD::Oracle. The default maximum size is now 1Mb; above that you will still have to set LongReadLen (Martin J. Evans) + + [DOCUMENTATION] + - clarification of when StrictlyTyped/DiscardString can be used and + LongReadLen (Martin J. Evans) + +1.40 2012-03-08 + - promote 1.39_00 to official release + +1.39_00 2012-02-24 + + [BUG FIXES] + - TAF supports now conditional to presence of OCI_ATTR_TAF_ENABLED + [RT73798] + - detect broken Win32::TieRegistry (patch by Rafael Kitover (Caelum)) + [RT74544] + - PL/SQL out values were not utf8 encoded [RT74753] + (Steve Baldwin + Martin J. Evans) + [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work on Lion. (Martin J. Evans) - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] - fix typos. (patch by Julián Moreno Patiño) [rt73999] - add troubleshoot doc and diag for error with bequeather. [rt75263] - - clarification of when StrictlyTyped/DiscardString can be used and - LongReadLen (Martin J. Evans) - - [OTHERS] - - change the shebang line of examples to the more modern '/usr/bin/env perl' - [RT74001] [OTHERS] - change the shebang line of examples to the more modern '/usr/bin/env perl' diff --git a/META.json b/META.json index 3af05f40..d80794cf 100644 --- a/META.json +++ b/META.json @@ -51,31 +51,31 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.38" + "version" : "1.40" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.38" + "version" : "1.40" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.38" + "version" : "1.40" }, "DBD::Oracle::Troubleshooting" : { "file" : "lib/DBD/Oracle/Troubleshooting.pm", - "version" : "1.38" + "version" : "1.40" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.38" + "version" : "1.40" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.38" + "version" : "1.40" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.38" + "version" : "1.40" } }, "release_status" : "stable", @@ -91,7 +91,11 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, +<<<<<<< HEAD "version" : "1.38", +======= + "version" : "1.40", +>>>>>>> build/master "x_authority" : "cpan:PYTHIAN" } diff --git a/META.yml b/META.yml index c1c09bd4..d7e0423a 100644 --- a/META.yml +++ b/META.yml @@ -29,25 +29,25 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.38 + version: 1.40 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.38 + version: 1.40 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.38 + version: 1.40 DBD::Oracle::Troubleshooting: file: lib/DBD/Oracle/Troubleshooting.pm - version: 1.38 + version: 1.40 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.38 + version: 1.40 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.38 + version: 1.40 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.38 + version: 1.40 requires: DBI: 0 DynaLoader: 0 @@ -59,5 +59,5 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.38 +version: 1.40 x_authority: cpan:PYTHIAN diff --git a/README b/README index bf8f7b60..6bbe76e0 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.38 + version 1.40 SYNOPSIS use DBI; @@ -884,7 +884,12 @@ ATTRIBUTES COMMON TO ALL HANDLES for a statement handle. Should be rarely needed. LongReadLen - Implemented by DBI, no driver-specific impact. + The maximum size of long or longraw columns to retrieve. If one of these + columns is longer than LongReadLen then either a data truncation error + will be raised (LongTrunkOk is false) or the column will be silently + truncated (LongTruncOk is true). + + DBI currently defaults this to 80. LongTruncOk Implemented by DBI, no driver-specific impact. @@ -1223,7 +1228,11 @@ DATABASE HANDLE METHODS Datatype codes for non-standard types are subject to change. - Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. + Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG so you + may have to set LongReadLen on the connection handle before calling + column_info if you have a large default column. After DBD::Oracle 1.40 + LongReadLen is set automatically to 1Mb when calling column_info and + reset aftwerwards. The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. @@ -1994,9 +2003,8 @@ DBI STATEMENT HANDLE OBJECT METHODS NOTE: DBD::Oracle does not use the $bind_type to determine how to bind the column; it uses what Oracle says the data type is. You can however - set a numeric bind type with the bind attributes - StrictlyTyped/DiscardString as these attributes are applied after the - column is retrieved. + set the StrictlyTyped/DiscardString attributes and these will take + effect as these attributes are applied after the column is retrieved. See the DBI documentation for a discussion of the optional parameters "\%attr" and $bind_type diff --git a/README.mkdn b/README.mkdn index efd36615..1e07efa9 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.38 +version 1.40 # SYNOPSIS @@ -953,7 +953,12 @@ Should be rarely needed. ## __LongReadLen__ -Implemented by DBI, no driver-specific impact. +The maximum size of long or longraw columns to retrieve. If one of +these columns is longer than LongReadLen then either a data truncation +error will be raised (LongTrunkOk is false) or the column will be +silently truncated (LongTruncOk is true). + +DBI currently defaults this to 80. ## __LongTruncOk__ @@ -1309,7 +1314,11 @@ Especially the length of FLOATs may be wrong. Datatype codes for non-standard types are subject to change. -Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG. +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG so you +may have to set LongReadLen on the connection handle before calling +column_info if you have a large default column. After DBD::Oracle 1.40 +LongReadLen is set automatically to 1Mb when calling column_info and +reset aftwerwards. The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. @@ -2078,9 +2087,9 @@ Column numbers count up from 1. You do not need to bind output columns in order NOTE: DBD::Oracle does not use the `$bind_type` to determine how to bind the column; it uses what Oracle says the data type is. You can -however set a numeric bind type with the bind attributes -StrictlyTyped/DiscardString as these attributes are applied after the -column is retrieved. +however set the StrictlyTyped/DiscardString attributes and these will +take effect as these attributes are applied after the column is +retrieved. See the DBI documentation for a discussion of the optional parameters `\%attr` and `$bind_type` @@ -4225,4 +4234,4 @@ Yanick Champoux This software is copyright (c) 1994 by Tim Bunce. This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. \ No newline at end of file +the same terms as the Perl 5 programming language system itself. diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9cf21d81..75d21877 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.38'; + $DBD::Oracle::VERSION = '1.40'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -125,7 +125,7 @@ BEGIN { { package DBD::Oracle::dr; { - $DBD::Oracle::dr::VERSION = '1.38'; + $DBD::Oracle::dr::VERSION = '1.40'; } BEGIN { $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; @@ -330,7 +330,7 @@ BEGIN { { package DBD::Oracle::db; { - $DBD::Oracle::db::VERSION = '1.38'; + $DBD::Oracle::db::VERSION = '1.40'; } BEGIN { $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; @@ -1059,7 +1059,7 @@ SQL { package DBD::Oracle::st; { - $DBD::Oracle::st::VERSION = '1.38'; + $DBD::Oracle::st::VERSION = '1.40'; } BEGIN { $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; @@ -1164,7 +1164,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.38 +version 1.40 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index d57d0592..c61c6dd4 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.38'; + $DBD::Oracle::GetInfo::VERSION = '1.40'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.38 +version 1.40 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index f7a4850f..642198ce 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.38'; + $DBD::Oracle::Object::VERSION = '1.40'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.38 +version 1.40 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 41896ae5..6d5c973d 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Troubleshooting; { - $DBD::Oracle::Troubleshooting::VERSION = '1.38'; + $DBD::Oracle::Troubleshooting::VERSION = '1.40'; } BEGIN { $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; @@ -17,7 +17,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.38 +version 1.40 =head1 CONNECTING TO ORACLE From e10f32629ae72c62c15d839e8c8b71e27e833ba7 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 8 Mar 2012 16:49:48 -0500 Subject: [PATCH 144/637] RT69350: make 31lob.t resistant to 11.2 --- t/31lob.t | 91 +++++++++++++++++++++++++------------------------------ 1 file changed, 41 insertions(+), 50 deletions(-) diff --git a/t/31lob.t b/t/31lob.t index fcbe30f9..2701e274 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -8,34 +8,23 @@ use DBI; unshift @INC ,'t'; require 'nchar_test_lib.pl'; -plan skip_all => "see RT#69350" - if ORA_OCI() =~ /^11\.2\./; - -my $dbh; -$| = 1; -SKIP: { - - my $dsn = oracle_test_dsn(); - my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - $dbh = DBI->connect($dsn, $dbuser, '',{ - PrintError => 0, - }); - if ($dbh) { - plan tests => 12; - } else { - plan skip_all => "Unable to connect to Oracle"; - } +my $dbh = DBI->connect($dsn, $dbuser, '',{ PrintError => 0, }); - my $table = table(); - drop_table($dbh); +plan $dbh ? ( tests => 12 ) + : ( skip_all => "Unable to connect to Oracle" ); + +my $table = table(); +drop_table($dbh); - $dbh->do(qq{ +$dbh->do( <<"END_SQL" ); CREATE TABLE $table ( id INTEGER NOT NULL, data BLOB ) - }); +END_SQL my ($stmt, $sth, $id, $loc); ## test with insert empty blob and select locator. @@ -76,23 +65,18 @@ is (ref $loc, "OCILobLocatorPtr", "returned valid locator"); sub temp_lob_count { my $dbh = shift; - my $stmt = " - SELECT cache_lobs + nocache_lobs AS temp_lob_count - FROM v\$temporary_lobs templob, - v\$session sess - WHERE sess.sid = templob.sid - AND sess.audsid = userenv('sessionid') "; - my ($count) = $dbh->selectrow_array($stmt); - return $count; + return $dbh->selectrow_array(<<'END_SQL'); + SELECT cache_lobs + nocache_lobs AS temp_lob_count + FROM v$temporary_lobs templob, + v$session sess + WHERE sess.sid = templob.sid + AND sess.audsid = userenv('sessionid') +END_SQL } sub have_v_session { - - $dbh->do('select * from v$session where 0=1'); - if ($dbh->err){ - return if ($dbh->err == 942); - } - return 1; + $dbh->do('select * from v$session where 0=1'); + return $dbh->err != 942; } @@ -117,7 +101,6 @@ sub have_v_session { is( $dbh->ora_lob_is_init($loc), 1, "returned initialized locator" ); - # write string > 32k $large_value = 'ABCD' x 10_000; @@ -152,11 +135,20 @@ sub have_v_session { if $dbh->err == 6553 || $dbh->err == 600; } - is( $len, length($large_value), "returned length via PL/SQL" ); + TODO: { + local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" + if ORA_OCI() =~ /^11\.2\./; + is( $len, length($large_value), "returned length via PL/SQL" ); + } - - $stmt = " + $dbh->{LongReadLen} = length($large_value) * 2; + + my $out; + my $inout = lc $large_value; + + eval { + $sth = $dbh->prepare( <<'END_SQL', { ora_auto_lob => 1 } ); DECLARE -- testing IN, OUT, and IN OUT: -- p_out will be set to LOWER(p_in) @@ -182,18 +174,19 @@ sub have_v_session { END; BEGIN lower_lob(:in, :out, :inout); - END; "; + END; +END_SQL - my $out; - my $inout = lc $large_value; + $sth->bind_param( ':in', $large_value, { ora_type => ORA_BLOB }); - local $dbh->{LongReadLen} = length($large_value) * 2; + $sth->bind_param_inout( ':out', \$out, 100, { ora_type => ORA_BLOB } ); + $sth->bind_param_inout( ':inout', \$inout, 100, { ora_type => ORA_BLOB } ); + $sth->execute; - $sth = $dbh->prepare( $stmt, { ora_auto_lob => 1 } ); - $sth->bind_param( ':in', $large_value, { ora_type => ORA_BLOB }); - $sth->bind_param_inout( ':out', \$out, 100, { ora_type => ORA_BLOB } ); - $sth->bind_param_inout( ':inout', \$inout, 100, { ora_type => ORA_BLOB } ); - $sth->execute; + }; + + local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" + if ORA_OCI() =~ /^11\.2\./; skip "Your Oracle PL/SQL installation does not implement temporary LOBS", 3 if $dbh->err && $dbh->err == 6550; @@ -211,6 +204,4 @@ sub have_v_session { $dbh->do("DROP TABLE $table"); $dbh->disconnect; -} - 1; From e3727de048731af11d6acb719f5ffcba06de502a Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 9 Mar 2012 14:24:03 -0500 Subject: [PATCH 145/637] tidying code --- t/01base.t | 45 +++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/t/01base.t b/t/01base.t index b06c84b1..a243ea66 100755 --- a/t/01base.t +++ b/t/01base.t @@ -1,5 +1,8 @@ #!perl -w +use strict; +use warnings; + # Base DBD Driver Test use Test::More tests => 6; @@ -8,45 +11,23 @@ require_ok('DBI'); eval { import DBI; }; -ok(!$@, 'import DBI'); -$switch = DBI->internal; -is(ref $switch, 'DBI::dr', 'internal'); +is $@ => '', 'successfully import DBI'; -eval { +is ref DBI->internal => 'DBI::dr', 'internal'; + +my $drh = eval { # This is a special case. install_driver should not normally be used. - $drh = DBI->install_driver('Oracle'); + DBI->install_driver('Oracle'); }; -my $ev = $@; -ok(!$ev, 'install_driver'); -if ($ev) { - $ev =~ s/\n\n+/\n/g; - warn "Failed to load Oracle extension and/or shared libraries:\n$@"; - warn "The remaining tests will probably also fail with the same error.\a\n\n"; - # try to provide some useful pointers for some cases - if ($@ =~ /Solaris patch.*Java/i) { - warn "*** Please read the README.java.txt file for help. ***\n"; - } - else { - warn "*** Please read the README and README.help.txt files for help. ***\n"; - } - warn "\n"; - sleep 5; -} +is $@ => '', 'install_driver' + or diag "Failed to load Oracle extension and/or shared libraries"; SKIP: { - skip 'install_driver failed - skipping remaining', 2 if $ev; + skip 'install_driver failed - skipping remaining', 2 if $@; - is(ref $drh, 'DBI::dr', 'install_driver'); + is ref $drh => 'DBI::dr', 'install_driver'; - ok($drh->{Version}, 'version'); + ok $drh->{Version}, 'version'; } - -# end. - -__END__ - -You must install a Solaris patch to run this version of -the Java runtime. -Please see the README and release notes for more information. From fc0dd0420f9cd9344ba9f2df1f2e9aeb78a45559 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 9 Mar 2012 14:32:37 -0500 Subject: [PATCH 146/637] code tidying up --- t/38taf.t | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/t/38taf.t b/t/38taf.t index 3cf8f3c1..eb09234b 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -15,22 +15,15 @@ $| = 1; # create a database handle my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '',)}; -if ($dbh) { - if ($dbh->ora_can_taf()){ - plan tests => 1; - } - else { - plan tests =>1; - } -} else { - plan skip_all => "Unable to connect to Oracle"; -} + +my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } + or plan skip_all => "Unable to connect to Oracle"; + +plan tests => 1; $dbh->disconnect; -if (!$dbh->ora_can_taf()){ +if ( !$dbh->ora_can_taf ){ eval {$dbh = DBI->connect($dsn, $dbuser, '',{ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf'})}; ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); @@ -38,11 +31,10 @@ if (!$dbh->ora_can_taf()){ } else { - ok($dbh = DBI->connect($dsn, $dbuser, '',{ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf'}),"Well this is all I can test!"); + ok $dbh = DBI->connect($dsn, $dbuser, '',{ + ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf' + }); } $dbh->disconnect; -#not much I can do with taf as I cannot really shut down somones server pephaps later - -1; From 04de9a30ea158fc760bf459703ac1deb2a4e73ec Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 12 Mar 2012 09:44:34 +0000 Subject: [PATCH 147/637] Changes to ensure test succeeds if you cannot connect to Oracle - as mostly people installing via CPAN shell cannot. Typo in skip msg git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15210 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ t/70meta.t | 3 ++- t/80ora_charset.t | 2 +- t/rt74753-utf8-encoded.t | 11 ++++++++--- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index 74702a5d..5829a396 100644 --- a/Changes +++ b/Changes @@ -10,6 +10,9 @@ NEXT DBD::Oracle. The default maximum size is now 1Mb; above that you will still have to set LongReadLen (Martin J. Evans) + - Fixed 70meta and rt74753-utf8-encoded to not die if you cannot + connect to Oracle or you cannot install from cpan if you have not + set up a valid Oracle connection. [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and diff --git a/t/70meta.t b/t/70meta.t index 301c8c62..7c193357 100644 --- a/t/70meta.t +++ b/t/70meta.t @@ -12,10 +12,11 @@ $| = 1; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', { RaiseError => 1, PrintError => 0 }); +my $dbh = DBI->connect($dsn, $dbuser, '', {PrintError => 0 }); if ($dbh) { plan tests=>21; + $dbh->{RaiseError} = 1; } else { plan skip_all => "Unable to connect to Oracle"; } diff --git a/t/80ora_charset.t b/t/80ora_charset.t index 22daf754..6a7b8c63 100644 --- a/t/80ora_charset.t +++ b/t/80ora_charset.t @@ -51,7 +51,7 @@ SKIP: { plan tests => $testcount; } else { - plan skip_all => "Unable to connect to Oraclee"; + plan skip_all => "Unable to connect to Oracle"; } show_test_data( $tdata ,0 ); diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index d50b1aee..4ef0c3bb 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 3; +use Test::More; use DBI; use Encode; @@ -18,8 +18,13 @@ $ENV{NLS_LANG} = 'AMERICAN_AMERICA.UTF8'; $ENV{NLS_NCHAR} = 'UTF8'; my $dbh = DBI->connect( $dsn, $dbuser, '', { - PrintError => 0, AutoCommit => 0, RaiseError => 1, -},); + PrintError => 0, AutoCommit => 0}); +if (!$dbh) { + plan skip_all => 'Unable to connect to Oracle'; +} else { + plan tests => 3; + $dbh->{RaiseError} = 1; +} $dbh->do(q(alter session set nls_territory = 'GERMANY')); From fadcd8305802f41f05cc9cc88a129fab6af659dc Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 12 Mar 2012 09:44:34 +0000 Subject: [PATCH 148/637] Changes to ensure test succeeds if you cannot connect to Oracle - as mostly people installing via CPAN shell cannot. Typo in skip msg git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15210 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ t/70meta.t | 3 ++- t/80ora_charset.t | 2 +- t/rt74753-utf8-encoded.t | 11 ++++++++--- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index 74702a5d..5829a396 100644 --- a/Changes +++ b/Changes @@ -10,6 +10,9 @@ NEXT DBD::Oracle. The default maximum size is now 1Mb; above that you will still have to set LongReadLen (Martin J. Evans) + - Fixed 70meta and rt74753-utf8-encoded to not die if you cannot + connect to Oracle or you cannot install from cpan if you have not + set up a valid Oracle connection. [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and diff --git a/t/70meta.t b/t/70meta.t index 301c8c62..7c193357 100644 --- a/t/70meta.t +++ b/t/70meta.t @@ -12,10 +12,11 @@ $| = 1; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', { RaiseError => 1, PrintError => 0 }); +my $dbh = DBI->connect($dsn, $dbuser, '', {PrintError => 0 }); if ($dbh) { plan tests=>21; + $dbh->{RaiseError} = 1; } else { plan skip_all => "Unable to connect to Oracle"; } diff --git a/t/80ora_charset.t b/t/80ora_charset.t index 22daf754..6a7b8c63 100644 --- a/t/80ora_charset.t +++ b/t/80ora_charset.t @@ -51,7 +51,7 @@ SKIP: { plan tests => $testcount; } else { - plan skip_all => "Unable to connect to Oraclee"; + plan skip_all => "Unable to connect to Oracle"; } show_test_data( $tdata ,0 ); diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index d50b1aee..4ef0c3bb 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 3; +use Test::More; use DBI; use Encode; @@ -18,8 +18,13 @@ $ENV{NLS_LANG} = 'AMERICAN_AMERICA.UTF8'; $ENV{NLS_NCHAR} = 'UTF8'; my $dbh = DBI->connect( $dsn, $dbuser, '', { - PrintError => 0, AutoCommit => 0, RaiseError => 1, -},); + PrintError => 0, AutoCommit => 0}); +if (!$dbh) { + plan skip_all => 'Unable to connect to Oracle'; +} else { + plan tests => 3; + $dbh->{RaiseError} = 1; +} $dbh->do(q(alter session set nls_territory = 'GERMANY')); From 50e9d421ba0c6c53ba53236a48d12a424a7e22ed Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 12 Mar 2012 15:46:00 -0400 Subject: [PATCH 149/637] taking in v1.42 changes --- Changes | 3 +++ dist.ini | 3 ++- t/rt74753-utf8-encoded.t | 7 ++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 630fa98d..3cfa4bd2 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,9 @@ Revision history for DBD::Oracle - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) +1.42 2012-03-13 + - skip rt74753-utf8-encoded.t if db is not unicode + 1.40 2012-03-08 - promote 1.39_00 to official release diff --git a/dist.ini b/dist.ini index c89ef550..c7cee301 100644 --- a/dist.ini +++ b/dist.ini @@ -6,7 +6,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.40 +version = 1.42 [Authority] authority=cpan:PYTHIAN @@ -21,5 +21,6 @@ authority=cpan:PYTHIAN -remove=Signature -remove=UploadToCPAN -remove=Twitter +-remove=Test::Compile [FakeRelease] diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index d50b1aee..de8f7037 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 3; +use Test::More; use DBI; use Encode; @@ -21,6 +21,11 @@ my $dbh = DBI->connect( $dsn, $dbuser, '', { PrintError => 0, AutoCommit => 0, RaiseError => 1, },); +plan skip_all => "unable to connect to Oracle database" if not $dbh; +plan skip_all => "database character set is not Unicode" unless db_ochar_is_utf($dbh); + +plan tests => 3; + $dbh->do(q(alter session set nls_territory = 'GERMANY')); my $sth = $dbh->prepare(<<"END_SQL"); From ea81eda132a5f0716ca78a32b649817ca83a6e7a Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 12 Mar 2012 09:44:34 +0000 Subject: [PATCH 150/637] Changes to ensure test succeeds if you cannot connect to Oracle - as mostly people installing via CPAN shell cannot. Typo in skip msg git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15210 50811bd7-b8ce-0310-adc1-d9db26280581 Conflicts: t/rt74753-utf8-encoded.t --- Changes | 3 +++ t/70meta.t | 3 ++- t/80ora_charset.t | 2 +- t/rt74753-utf8-encoded.t | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index 3cfa4bd2..6261b7b9 100644 --- a/Changes +++ b/Changes @@ -10,6 +10,9 @@ Revision history for DBD::Oracle DBD::Oracle. The default maximum size is now 1Mb; above that you will still have to set LongReadLen (Martin J. Evans) + - Fixed 70meta and rt74753-utf8-encoded to not die if you cannot + connect to Oracle or you cannot install from cpan if you have not + set up a valid Oracle connection. [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and diff --git a/t/70meta.t b/t/70meta.t index 301c8c62..7c193357 100644 --- a/t/70meta.t +++ b/t/70meta.t @@ -12,10 +12,11 @@ $| = 1; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', { RaiseError => 1, PrintError => 0 }); +my $dbh = DBI->connect($dsn, $dbuser, '', {PrintError => 0 }); if ($dbh) { plan tests=>21; + $dbh->{RaiseError} = 1; } else { plan skip_all => "Unable to connect to Oracle"; } diff --git a/t/80ora_charset.t b/t/80ora_charset.t index 22daf754..6a7b8c63 100644 --- a/t/80ora_charset.t +++ b/t/80ora_charset.t @@ -51,7 +51,7 @@ SKIP: { plan tests => $testcount; } else { - plan skip_all => "Unable to connect to Oraclee"; + plan skip_all => "Unable to connect to Oracle"; } show_test_data( $tdata ,0 ); diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index de8f7037..e184c98f 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -18,8 +18,8 @@ $ENV{NLS_LANG} = 'AMERICAN_AMERICA.UTF8'; $ENV{NLS_NCHAR} = 'UTF8'; my $dbh = DBI->connect( $dsn, $dbuser, '', { - PrintError => 0, AutoCommit => 0, RaiseError => 1, -},); + PrintError => 0, AutoCommit => 0 +}); plan skip_all => "unable to connect to Oracle database" if not $dbh; plan skip_all => "database character set is not Unicode" unless db_ochar_is_utf($dbh); From bc25f7eed94531ac9fce152e6cf782fe73aef972 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 13 Mar 2012 15:01:03 +0000 Subject: [PATCH 151/637] taking in v1.42 changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15215 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ t/rt74753-utf8-encoded.t | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index 5829a396..81bdd0c6 100644 --- a/Changes +++ b/Changes @@ -18,6 +18,9 @@ NEXT - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) +1.42 2012-03-13 + - skip rt74753-utf8-encoded.t if db is not unicode + 1.40 2012-03-08 - promote 1.39_00 to official release diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index 4ef0c3bb..e184c98f 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -18,13 +18,13 @@ $ENV{NLS_LANG} = 'AMERICAN_AMERICA.UTF8'; $ENV{NLS_NCHAR} = 'UTF8'; my $dbh = DBI->connect( $dsn, $dbuser, '', { - PrintError => 0, AutoCommit => 0}); -if (!$dbh) { - plan skip_all => 'Unable to connect to Oracle'; -} else { - plan tests => 3; - $dbh->{RaiseError} = 1; -} + PrintError => 0, AutoCommit => 0 +}); + +plan skip_all => "unable to connect to Oracle database" if not $dbh; +plan skip_all => "database character set is not Unicode" unless db_ochar_is_utf($dbh); + +plan tests => 3; $dbh->do(q(alter session set nls_territory = 'GERMANY')); From 554cc3f80a773c56f8700198d8af6c40decb5910 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 13 Mar 2012 15:01:03 +0000 Subject: [PATCH 152/637] taking in v1.42 changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15215 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ t/rt74753-utf8-encoded.t | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index 5829a396..81bdd0c6 100644 --- a/Changes +++ b/Changes @@ -18,6 +18,9 @@ NEXT - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) +1.42 2012-03-13 + - skip rt74753-utf8-encoded.t if db is not unicode + 1.40 2012-03-08 - promote 1.39_00 to official release diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index 4ef0c3bb..e184c98f 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -18,13 +18,13 @@ $ENV{NLS_LANG} = 'AMERICAN_AMERICA.UTF8'; $ENV{NLS_NCHAR} = 'UTF8'; my $dbh = DBI->connect( $dsn, $dbuser, '', { - PrintError => 0, AutoCommit => 0}); -if (!$dbh) { - plan skip_all => 'Unable to connect to Oracle'; -} else { - plan tests => 3; - $dbh->{RaiseError} = 1; -} + PrintError => 0, AutoCommit => 0 +}); + +plan skip_all => "unable to connect to Oracle database" if not $dbh; +plan skip_all => "database character set is not Unicode" unless db_ochar_is_utf($dbh); + +plan tests => 3; $dbh->do(q(alter session set nls_territory = 'GERMANY')); From d95d2278e46fb5ca4c700115b2659d6181aba4f2 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 13 Mar 2012 15:01:12 +0000 Subject: [PATCH 153/637] RT69350: make 31lob.t resistant to 11.2 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15216 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/31lob.t | 91 +++++++++++++++++++++++++------------------------------ 1 file changed, 41 insertions(+), 50 deletions(-) diff --git a/t/31lob.t b/t/31lob.t index fcbe30f9..2701e274 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -8,34 +8,23 @@ use DBI; unshift @INC ,'t'; require 'nchar_test_lib.pl'; -plan skip_all => "see RT#69350" - if ORA_OCI() =~ /^11\.2\./; - -my $dbh; -$| = 1; -SKIP: { - - my $dsn = oracle_test_dsn(); - my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - $dbh = DBI->connect($dsn, $dbuser, '',{ - PrintError => 0, - }); - if ($dbh) { - plan tests => 12; - } else { - plan skip_all => "Unable to connect to Oracle"; - } +my $dbh = DBI->connect($dsn, $dbuser, '',{ PrintError => 0, }); - my $table = table(); - drop_table($dbh); +plan $dbh ? ( tests => 12 ) + : ( skip_all => "Unable to connect to Oracle" ); + +my $table = table(); +drop_table($dbh); - $dbh->do(qq{ +$dbh->do( <<"END_SQL" ); CREATE TABLE $table ( id INTEGER NOT NULL, data BLOB ) - }); +END_SQL my ($stmt, $sth, $id, $loc); ## test with insert empty blob and select locator. @@ -76,23 +65,18 @@ is (ref $loc, "OCILobLocatorPtr", "returned valid locator"); sub temp_lob_count { my $dbh = shift; - my $stmt = " - SELECT cache_lobs + nocache_lobs AS temp_lob_count - FROM v\$temporary_lobs templob, - v\$session sess - WHERE sess.sid = templob.sid - AND sess.audsid = userenv('sessionid') "; - my ($count) = $dbh->selectrow_array($stmt); - return $count; + return $dbh->selectrow_array(<<'END_SQL'); + SELECT cache_lobs + nocache_lobs AS temp_lob_count + FROM v$temporary_lobs templob, + v$session sess + WHERE sess.sid = templob.sid + AND sess.audsid = userenv('sessionid') +END_SQL } sub have_v_session { - - $dbh->do('select * from v$session where 0=1'); - if ($dbh->err){ - return if ($dbh->err == 942); - } - return 1; + $dbh->do('select * from v$session where 0=1'); + return $dbh->err != 942; } @@ -117,7 +101,6 @@ sub have_v_session { is( $dbh->ora_lob_is_init($loc), 1, "returned initialized locator" ); - # write string > 32k $large_value = 'ABCD' x 10_000; @@ -152,11 +135,20 @@ sub have_v_session { if $dbh->err == 6553 || $dbh->err == 600; } - is( $len, length($large_value), "returned length via PL/SQL" ); + TODO: { + local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" + if ORA_OCI() =~ /^11\.2\./; + is( $len, length($large_value), "returned length via PL/SQL" ); + } - - $stmt = " + $dbh->{LongReadLen} = length($large_value) * 2; + + my $out; + my $inout = lc $large_value; + + eval { + $sth = $dbh->prepare( <<'END_SQL', { ora_auto_lob => 1 } ); DECLARE -- testing IN, OUT, and IN OUT: -- p_out will be set to LOWER(p_in) @@ -182,18 +174,19 @@ sub have_v_session { END; BEGIN lower_lob(:in, :out, :inout); - END; "; + END; +END_SQL - my $out; - my $inout = lc $large_value; + $sth->bind_param( ':in', $large_value, { ora_type => ORA_BLOB }); - local $dbh->{LongReadLen} = length($large_value) * 2; + $sth->bind_param_inout( ':out', \$out, 100, { ora_type => ORA_BLOB } ); + $sth->bind_param_inout( ':inout', \$inout, 100, { ora_type => ORA_BLOB } ); + $sth->execute; - $sth = $dbh->prepare( $stmt, { ora_auto_lob => 1 } ); - $sth->bind_param( ':in', $large_value, { ora_type => ORA_BLOB }); - $sth->bind_param_inout( ':out', \$out, 100, { ora_type => ORA_BLOB } ); - $sth->bind_param_inout( ':inout', \$inout, 100, { ora_type => ORA_BLOB } ); - $sth->execute; + }; + + local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" + if ORA_OCI() =~ /^11\.2\./; skip "Your Oracle PL/SQL installation does not implement temporary LOBS", 3 if $dbh->err && $dbh->err == 6550; @@ -211,6 +204,4 @@ sub have_v_session { $dbh->do("DROP TABLE $table"); $dbh->disconnect; -} - 1; From eb6a04b462a6894b76435b738aae5a2c8a3efd87 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 13 Mar 2012 15:01:12 +0000 Subject: [PATCH 154/637] RT69350: make 31lob.t resistant to 11.2 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15216 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/31lob.t | 91 +++++++++++++++++++++++++------------------------------ 1 file changed, 41 insertions(+), 50 deletions(-) diff --git a/t/31lob.t b/t/31lob.t index fcbe30f9..2701e274 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -8,34 +8,23 @@ use DBI; unshift @INC ,'t'; require 'nchar_test_lib.pl'; -plan skip_all => "see RT#69350" - if ORA_OCI() =~ /^11\.2\./; - -my $dbh; -$| = 1; -SKIP: { - - my $dsn = oracle_test_dsn(); - my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - $dbh = DBI->connect($dsn, $dbuser, '',{ - PrintError => 0, - }); - if ($dbh) { - plan tests => 12; - } else { - plan skip_all => "Unable to connect to Oracle"; - } +my $dbh = DBI->connect($dsn, $dbuser, '',{ PrintError => 0, }); - my $table = table(); - drop_table($dbh); +plan $dbh ? ( tests => 12 ) + : ( skip_all => "Unable to connect to Oracle" ); + +my $table = table(); +drop_table($dbh); - $dbh->do(qq{ +$dbh->do( <<"END_SQL" ); CREATE TABLE $table ( id INTEGER NOT NULL, data BLOB ) - }); +END_SQL my ($stmt, $sth, $id, $loc); ## test with insert empty blob and select locator. @@ -76,23 +65,18 @@ is (ref $loc, "OCILobLocatorPtr", "returned valid locator"); sub temp_lob_count { my $dbh = shift; - my $stmt = " - SELECT cache_lobs + nocache_lobs AS temp_lob_count - FROM v\$temporary_lobs templob, - v\$session sess - WHERE sess.sid = templob.sid - AND sess.audsid = userenv('sessionid') "; - my ($count) = $dbh->selectrow_array($stmt); - return $count; + return $dbh->selectrow_array(<<'END_SQL'); + SELECT cache_lobs + nocache_lobs AS temp_lob_count + FROM v$temporary_lobs templob, + v$session sess + WHERE sess.sid = templob.sid + AND sess.audsid = userenv('sessionid') +END_SQL } sub have_v_session { - - $dbh->do('select * from v$session where 0=1'); - if ($dbh->err){ - return if ($dbh->err == 942); - } - return 1; + $dbh->do('select * from v$session where 0=1'); + return $dbh->err != 942; } @@ -117,7 +101,6 @@ sub have_v_session { is( $dbh->ora_lob_is_init($loc), 1, "returned initialized locator" ); - # write string > 32k $large_value = 'ABCD' x 10_000; @@ -152,11 +135,20 @@ sub have_v_session { if $dbh->err == 6553 || $dbh->err == 600; } - is( $len, length($large_value), "returned length via PL/SQL" ); + TODO: { + local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" + if ORA_OCI() =~ /^11\.2\./; + is( $len, length($large_value), "returned length via PL/SQL" ); + } - - $stmt = " + $dbh->{LongReadLen} = length($large_value) * 2; + + my $out; + my $inout = lc $large_value; + + eval { + $sth = $dbh->prepare( <<'END_SQL', { ora_auto_lob => 1 } ); DECLARE -- testing IN, OUT, and IN OUT: -- p_out will be set to LOWER(p_in) @@ -182,18 +174,19 @@ sub have_v_session { END; BEGIN lower_lob(:in, :out, :inout); - END; "; + END; +END_SQL - my $out; - my $inout = lc $large_value; + $sth->bind_param( ':in', $large_value, { ora_type => ORA_BLOB }); - local $dbh->{LongReadLen} = length($large_value) * 2; + $sth->bind_param_inout( ':out', \$out, 100, { ora_type => ORA_BLOB } ); + $sth->bind_param_inout( ':inout', \$inout, 100, { ora_type => ORA_BLOB } ); + $sth->execute; - $sth = $dbh->prepare( $stmt, { ora_auto_lob => 1 } ); - $sth->bind_param( ':in', $large_value, { ora_type => ORA_BLOB }); - $sth->bind_param_inout( ':out', \$out, 100, { ora_type => ORA_BLOB } ); - $sth->bind_param_inout( ':inout', \$inout, 100, { ora_type => ORA_BLOB } ); - $sth->execute; + }; + + local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" + if ORA_OCI() =~ /^11\.2\./; skip "Your Oracle PL/SQL installation does not implement temporary LOBS", 3 if $dbh->err && $dbh->err == 6550; @@ -211,6 +204,4 @@ sub have_v_session { $dbh->do("DROP TABLE $table"); $dbh->disconnect; -} - 1; From 903d0593c689679af2fa21a513f4c0f3cae16fc2 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 13 Mar 2012 15:01:17 +0000 Subject: [PATCH 155/637] tidying code git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15217 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/01base.t | 45 +++++++++++++-------------------------------- t/38taf.t | 26 +++++++++----------------- 2 files changed, 22 insertions(+), 49 deletions(-) diff --git a/t/01base.t b/t/01base.t index b06c84b1..a243ea66 100755 --- a/t/01base.t +++ b/t/01base.t @@ -1,5 +1,8 @@ #!perl -w +use strict; +use warnings; + # Base DBD Driver Test use Test::More tests => 6; @@ -8,45 +11,23 @@ require_ok('DBI'); eval { import DBI; }; -ok(!$@, 'import DBI'); -$switch = DBI->internal; -is(ref $switch, 'DBI::dr', 'internal'); +is $@ => '', 'successfully import DBI'; -eval { +is ref DBI->internal => 'DBI::dr', 'internal'; + +my $drh = eval { # This is a special case. install_driver should not normally be used. - $drh = DBI->install_driver('Oracle'); + DBI->install_driver('Oracle'); }; -my $ev = $@; -ok(!$ev, 'install_driver'); -if ($ev) { - $ev =~ s/\n\n+/\n/g; - warn "Failed to load Oracle extension and/or shared libraries:\n$@"; - warn "The remaining tests will probably also fail with the same error.\a\n\n"; - # try to provide some useful pointers for some cases - if ($@ =~ /Solaris patch.*Java/i) { - warn "*** Please read the README.java.txt file for help. ***\n"; - } - else { - warn "*** Please read the README and README.help.txt files for help. ***\n"; - } - warn "\n"; - sleep 5; -} +is $@ => '', 'install_driver' + or diag "Failed to load Oracle extension and/or shared libraries"; SKIP: { - skip 'install_driver failed - skipping remaining', 2 if $ev; + skip 'install_driver failed - skipping remaining', 2 if $@; - is(ref $drh, 'DBI::dr', 'install_driver'); + is ref $drh => 'DBI::dr', 'install_driver'; - ok($drh->{Version}, 'version'); + ok $drh->{Version}, 'version'; } - -# end. - -__END__ - -You must install a Solaris patch to run this version of -the Java runtime. -Please see the README and release notes for more information. diff --git a/t/38taf.t b/t/38taf.t index 3cf8f3c1..eb09234b 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -15,22 +15,15 @@ $| = 1; # create a database handle my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '',)}; -if ($dbh) { - if ($dbh->ora_can_taf()){ - plan tests => 1; - } - else { - plan tests =>1; - } -} else { - plan skip_all => "Unable to connect to Oracle"; -} + +my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } + or plan skip_all => "Unable to connect to Oracle"; + +plan tests => 1; $dbh->disconnect; -if (!$dbh->ora_can_taf()){ +if ( !$dbh->ora_can_taf ){ eval {$dbh = DBI->connect($dsn, $dbuser, '',{ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf'})}; ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); @@ -38,11 +31,10 @@ if (!$dbh->ora_can_taf()){ } else { - ok($dbh = DBI->connect($dsn, $dbuser, '',{ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf'}),"Well this is all I can test!"); + ok $dbh = DBI->connect($dsn, $dbuser, '',{ + ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf' + }); } $dbh->disconnect; -#not much I can do with taf as I cannot really shut down somones server pephaps later - -1; From 1f3b2cc6c9698b55ca74b138ea8694bddcf510b5 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 13 Mar 2012 15:01:17 +0000 Subject: [PATCH 156/637] tidying code git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15217 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/01base.t | 45 +++++++++++++-------------------------------- t/38taf.t | 26 +++++++++----------------- 2 files changed, 22 insertions(+), 49 deletions(-) diff --git a/t/01base.t b/t/01base.t index b06c84b1..a243ea66 100755 --- a/t/01base.t +++ b/t/01base.t @@ -1,5 +1,8 @@ #!perl -w +use strict; +use warnings; + # Base DBD Driver Test use Test::More tests => 6; @@ -8,45 +11,23 @@ require_ok('DBI'); eval { import DBI; }; -ok(!$@, 'import DBI'); -$switch = DBI->internal; -is(ref $switch, 'DBI::dr', 'internal'); +is $@ => '', 'successfully import DBI'; -eval { +is ref DBI->internal => 'DBI::dr', 'internal'; + +my $drh = eval { # This is a special case. install_driver should not normally be used. - $drh = DBI->install_driver('Oracle'); + DBI->install_driver('Oracle'); }; -my $ev = $@; -ok(!$ev, 'install_driver'); -if ($ev) { - $ev =~ s/\n\n+/\n/g; - warn "Failed to load Oracle extension and/or shared libraries:\n$@"; - warn "The remaining tests will probably also fail with the same error.\a\n\n"; - # try to provide some useful pointers for some cases - if ($@ =~ /Solaris patch.*Java/i) { - warn "*** Please read the README.java.txt file for help. ***\n"; - } - else { - warn "*** Please read the README and README.help.txt files for help. ***\n"; - } - warn "\n"; - sleep 5; -} +is $@ => '', 'install_driver' + or diag "Failed to load Oracle extension and/or shared libraries"; SKIP: { - skip 'install_driver failed - skipping remaining', 2 if $ev; + skip 'install_driver failed - skipping remaining', 2 if $@; - is(ref $drh, 'DBI::dr', 'install_driver'); + is ref $drh => 'DBI::dr', 'install_driver'; - ok($drh->{Version}, 'version'); + ok $drh->{Version}, 'version'; } - -# end. - -__END__ - -You must install a Solaris patch to run this version of -the Java runtime. -Please see the README and release notes for more information. diff --git a/t/38taf.t b/t/38taf.t index 3cf8f3c1..eb09234b 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -15,22 +15,15 @@ $| = 1; # create a database handle my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '',)}; -if ($dbh) { - if ($dbh->ora_can_taf()){ - plan tests => 1; - } - else { - plan tests =>1; - } -} else { - plan skip_all => "Unable to connect to Oracle"; -} + +my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } + or plan skip_all => "Unable to connect to Oracle"; + +plan tests => 1; $dbh->disconnect; -if (!$dbh->ora_can_taf()){ +if ( !$dbh->ora_can_taf ){ eval {$dbh = DBI->connect($dsn, $dbuser, '',{ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf'})}; ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); @@ -38,11 +31,10 @@ if (!$dbh->ora_can_taf()){ } else { - ok($dbh = DBI->connect($dsn, $dbuser, '',{ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf'}),"Well this is all I can test!"); + ok $dbh = DBI->connect($dsn, $dbuser, '',{ + ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf' + }); } $dbh->disconnect; -#not much I can do with taf as I cannot really shut down somones server pephaps later - -1; From e0bee3799c1ea478d6a88d1c7e2d77a67c760e6f Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 15:00:36 +0000 Subject: [PATCH 157/637] Fix rt 75163 - cannot fetch bfile lobs when ora_auto_lobs is off git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15218 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 +++++++ Oracle.xs | 15 +++++++++++++++ dbdimp.c | 30 +++++++++++++++++++++++++----- dbdimp.h | 2 +- oci8.c | 2 +- ocitrace.h | 7 +++++++ 6 files changed, 56 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index 81bdd0c6..1f5ffc93 100644 --- a/Changes +++ b/Changes @@ -14,6 +14,13 @@ NEXT connect to Oracle or you cannot install from cpan if you have not set up a valid Oracle connection. + - Fixed 75163. Bfile lobs were not being opened before fetching if + ora_auto_lobs was disabled (Martin J. Evans). + + Note: this has a minor impact on non bfile lobs when ora_auto_lobs + is not in force as an additional call to OCILobFileIsOpen will be + made. + [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) diff --git a/Oracle.xs b/Oracle.xs index 1a1f3db2..d4a90c2f 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -560,6 +560,21 @@ ora_lob_read(dbh, locator, offset, length) dest_sv = &PL_sv_undef; return; } + { + /* see rt 75163 */ + boolean is_open; + + OCILobFileIsOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, &is_open, status); + if (status == OCI_SUCCESS && !is_open) { + OCILobFileOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, + (ub1)OCI_FILE_READONLY, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCILobFileOpen"); + dest_sv = &PL_sv_undef; + } + } + } + OCILobRead_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, &amtp, (ub4)offset, /* offset starts at 1 */ bufp, (ub4)bufp_len, diff --git a/dbdimp.c b/dbdimp.c index f60989b8..8ed61023 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3977,16 +3977,36 @@ dbd_st_finish(SV *sth, imp_sth_t *imp_sth) void -ora_free_fbh_contents(imp_fbh_t *fbh) +ora_free_fbh_contents(SV *sth, imp_fbh_t *fbh) { dTHX; + D_imp_sth(sth); + D_imp_dbh_from_sth; + if (fbh->fb_ary) fb_ary_free(fbh->fb_ary); sv_free(fbh->name_sv); - if (fbh->desc_h) - OCIDescriptorFree_log(fbh->desc_h, fbh->desc_t); - if (fbh->obj) + + /* see rt 75163 */ + if (fbh->desc_h) { + boolean is_open; + sword status; + + OCILobFileIsOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, fbh->desc_h, &is_open, status); + if (status == OCI_SUCCESS && is_open) { + OCILobFileClose_log_stat(imp_sth->svchp, imp_sth->errhp, + fbh->desc_h, status); + } + + + OCIDescriptorFree_log(fbh->desc_h, fbh->desc_t); + } + + if (fbh->obj) { + if (fbh->obj->obj_value) + OCIObjectFree(fbh->imp_sth->envhp, fbh->imp_sth->errhp, fbh->obj->obj_value, (ub2)0); Safefree(fbh->obj); + } } @@ -4092,7 +4112,7 @@ dbd_st_destroy(SV *sth, imp_sth_t *imp_sth) imp_sth->eod_errno = 1403; for(i=0; i < fields; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i]; - ora_free_fbh_contents(fbh); + ora_free_fbh_contents(sth, fbh); } Safefree(imp_sth->fbh); if (imp_sth->fbh_cbuf) diff --git a/dbdimp.h b/dbdimp.h index 632e2814..68664a3a 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -321,7 +321,7 @@ extern ub2 al16utf16_csid; void dbd_init_oci _((dbistate_t *dbistate)); void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); void dbd_fbh_dump(imp_fbh_t *fbh, int i, int aidx); -void ora_free_fbh_contents _((imp_fbh_t *fbh)); +void ora_free_fbh_contents _((SV *sth, imp_fbh_t *fbh)); void ora_free_templob _((SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc)); int ora_dbtype_is_long _((int dbtype)); fb_ary_t *fb_ary_alloc _((ub4 bufl, int size)); diff --git a/oci8.c b/oci8.c index 351410ba..0de4e4bc 100644 --- a/oci8.c +++ b/oci8.c @@ -4651,7 +4651,7 @@ ora_free_lob_refetch(SV *sth, imp_sth_t *imp_sth) for(i=0; i < lr->num_fields; ++i) { imp_fbh_t *fbh = &lr->fbh_ary[i]; - ora_free_fbh_contents(fbh); + ora_free_fbh_contents(sth, fbh); } sv_free(lr->fbh_ary_sv); Safefree(imp_sth->lob_refetch); diff --git a/ocitrace.h b/ocitrace.h index 39c0fdb7..d5f1c101 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -127,6 +127,13 @@ OciTp, (void*)svchp,(void*)envhp, src_type, src_ptr,oci_status_name(stat)),stat \ : stat +#define OCILobFileIsOpen_log_stat(envhp,errhp,loc,is_open,stat) \ + stat = OCILobFileIsOpen(envhp,errhp,loc,is_open);\ + (DBD_OCI_TRACEON) \ + ? PerlIO_printf(DBD_OCI_TRACEFP, \ + "%sOCILobFileIsOpen_log_stat(%p,%p,%p,%p,%d)=%s\n",\ + OciTp, (void*)envhp, (void*)errhp, loc, is_open, *is_open,oci_status_name(stat)),stat : stat + #define OCILobLocatorIsInit_log_stat(envhp,errhp,loc,is_initp,stat)\ stat =OCILobLocatorIsInit (envhp,errhp,loc,is_initp );\ (DBD_OCI_TRACEON) \ From 48401d2378e84dd94fa304f6d25378e442968046 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 15:00:36 +0000 Subject: [PATCH 158/637] Fix rt 75163 - cannot fetch bfile lobs when ora_auto_lobs is off git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15218 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 +++++++ Oracle.xs | 15 +++++++++++++++ dbdimp.c | 30 +++++++++++++++++++++++++----- dbdimp.h | 2 +- oci8.c | 2 +- ocitrace.h | 7 +++++++ 6 files changed, 56 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index 81bdd0c6..1f5ffc93 100644 --- a/Changes +++ b/Changes @@ -14,6 +14,13 @@ NEXT connect to Oracle or you cannot install from cpan if you have not set up a valid Oracle connection. + - Fixed 75163. Bfile lobs were not being opened before fetching if + ora_auto_lobs was disabled (Martin J. Evans). + + Note: this has a minor impact on non bfile lobs when ora_auto_lobs + is not in force as an additional call to OCILobFileIsOpen will be + made. + [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) diff --git a/Oracle.xs b/Oracle.xs index 1a1f3db2..d4a90c2f 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -560,6 +560,21 @@ ora_lob_read(dbh, locator, offset, length) dest_sv = &PL_sv_undef; return; } + { + /* see rt 75163 */ + boolean is_open; + + OCILobFileIsOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, &is_open, status); + if (status == OCI_SUCCESS && !is_open) { + OCILobFileOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, + (ub1)OCI_FILE_READONLY, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCILobFileOpen"); + dest_sv = &PL_sv_undef; + } + } + } + OCILobRead_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, &amtp, (ub4)offset, /* offset starts at 1 */ bufp, (ub4)bufp_len, diff --git a/dbdimp.c b/dbdimp.c index f60989b8..8ed61023 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3977,16 +3977,36 @@ dbd_st_finish(SV *sth, imp_sth_t *imp_sth) void -ora_free_fbh_contents(imp_fbh_t *fbh) +ora_free_fbh_contents(SV *sth, imp_fbh_t *fbh) { dTHX; + D_imp_sth(sth); + D_imp_dbh_from_sth; + if (fbh->fb_ary) fb_ary_free(fbh->fb_ary); sv_free(fbh->name_sv); - if (fbh->desc_h) - OCIDescriptorFree_log(fbh->desc_h, fbh->desc_t); - if (fbh->obj) + + /* see rt 75163 */ + if (fbh->desc_h) { + boolean is_open; + sword status; + + OCILobFileIsOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, fbh->desc_h, &is_open, status); + if (status == OCI_SUCCESS && is_open) { + OCILobFileClose_log_stat(imp_sth->svchp, imp_sth->errhp, + fbh->desc_h, status); + } + + + OCIDescriptorFree_log(fbh->desc_h, fbh->desc_t); + } + + if (fbh->obj) { + if (fbh->obj->obj_value) + OCIObjectFree(fbh->imp_sth->envhp, fbh->imp_sth->errhp, fbh->obj->obj_value, (ub2)0); Safefree(fbh->obj); + } } @@ -4092,7 +4112,7 @@ dbd_st_destroy(SV *sth, imp_sth_t *imp_sth) imp_sth->eod_errno = 1403; for(i=0; i < fields; ++i) { imp_fbh_t *fbh = &imp_sth->fbh[i]; - ora_free_fbh_contents(fbh); + ora_free_fbh_contents(sth, fbh); } Safefree(imp_sth->fbh); if (imp_sth->fbh_cbuf) diff --git a/dbdimp.h b/dbdimp.h index 632e2814..68664a3a 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -321,7 +321,7 @@ extern ub2 al16utf16_csid; void dbd_init_oci _((dbistate_t *dbistate)); void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); void dbd_fbh_dump(imp_fbh_t *fbh, int i, int aidx); -void ora_free_fbh_contents _((imp_fbh_t *fbh)); +void ora_free_fbh_contents _((SV *sth, imp_fbh_t *fbh)); void ora_free_templob _((SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc)); int ora_dbtype_is_long _((int dbtype)); fb_ary_t *fb_ary_alloc _((ub4 bufl, int size)); diff --git a/oci8.c b/oci8.c index 351410ba..0de4e4bc 100644 --- a/oci8.c +++ b/oci8.c @@ -4651,7 +4651,7 @@ ora_free_lob_refetch(SV *sth, imp_sth_t *imp_sth) for(i=0; i < lr->num_fields; ++i) { imp_fbh_t *fbh = &lr->fbh_ary[i]; - ora_free_fbh_contents(fbh); + ora_free_fbh_contents(sth, fbh); } sv_free(lr->fbh_ary_sv); Safefree(imp_sth->lob_refetch); diff --git a/ocitrace.h b/ocitrace.h index 39c0fdb7..d5f1c101 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -127,6 +127,13 @@ OciTp, (void*)svchp,(void*)envhp, src_type, src_ptr,oci_status_name(stat)),stat \ : stat +#define OCILobFileIsOpen_log_stat(envhp,errhp,loc,is_open,stat) \ + stat = OCILobFileIsOpen(envhp,errhp,loc,is_open);\ + (DBD_OCI_TRACEON) \ + ? PerlIO_printf(DBD_OCI_TRACEFP, \ + "%sOCILobFileIsOpen_log_stat(%p,%p,%p,%p,%d)=%s\n",\ + OciTp, (void*)envhp, (void*)errhp, loc, is_open, *is_open,oci_status_name(stat)),stat : stat + #define OCILobLocatorIsInit_log_stat(envhp,errhp,loc,is_initp,stat)\ stat =OCILobLocatorIsInit (envhp,errhp,loc,is_initp );\ (DBD_OCI_TRACEON) \ From 18512dbf58b588e5d91d294ffb18e91635e32562 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 16:08:58 +0000 Subject: [PATCH 159/637] Examples of changes to get rid of DBIS usage. I'll try and do more when I have time. Ideally, I'd like the calls to DBIS->debug to move to DBIc_TRACE which is more flexible and could introduce DBD tracing (which would allow us to throw away ora_verbose) git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15219 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 8ed61023..04bd3dfe 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -512,23 +512,23 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (DBD_ATTRIB_TRUE(attr,"ora_objects",11,svp)) DBD_ATTRIB_GET_IV( attr, "ora_objects",11, svp, ora_objects); - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) + if (DBIc_DBISTATE(imp_dbh)->debug >= 6 || dbd_verbose >= 6 ) dump_env_to_trace(); /* dbi_imp_data code adapted from DBD::mysql */ if (DBIc_has(imp_dbh, DBIcf_IMPSET)) { /* dbi_imp_data from take_imp_data */ if (DBIc_has(imp_dbh, DBIcf_ACTIVE)) { - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "dbd_db_login6 skip connect\n"); + if (DBIc_DBISTATE(imp_dbh)->debug >= 2 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_dbh), "dbd_db_login6 skip connect\n"); /* tell our parent we've adopted an active child */ ++DBIc_ACTIVE_KIDS(DBIc_PARENT_COM(imp_dbh)); return 1; } /* not ACTIVE so connect not skipped */ - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + if (DBIc_DBISTATE(imp_dbh)->debug >= 2 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_dbh), "dbd_db_login6 IMPSET but not ACTIVE so connect not skipped\n"); } @@ -566,8 +566,8 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S shared_dbh -> refcnt++ ; imp_dbh -> shared_dbh_priv_sv = shared_dbh_priv_sv ; imp_dbh -> shared_dbh = shared_dbh ; - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_db_login: use shared Oracle database handles.\n"); + if (DBIc_DBISTATE(imp_dbh)->debug >= 2 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_dbh), " dbd_db_login: use shared Oracle database handles.\n"); } else { shared_dbh = NULL ; } @@ -717,17 +717,19 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S * BTW: NLS_NCHAR is set as follows: NSL_LANG=AL32UTF8 */ - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_dbh)->debug >= 3 || dbd_verbose >= 3 ) { oratext charsetname[OCI_NLS_MAXBUFSZ]; oratext ncharsetname[OCI_NLS_MAXBUFSZ]; OCINlsCharSetIdToName(imp_dbh->envhp,charsetname, sizeof(charsetname),charsetid ); OCINlsCharSetIdToName(imp_dbh->envhp,ncharsetname, sizeof(ncharsetname),ncharsetid ); - PerlIO_printf(DBILOGFP," charset id=%d, name=%s, ncharset id=%d, name=%s" - " (csid: utf8=%d al32utf8=%d)\n", - charsetid,charsetname, ncharsetid,ncharsetname, utf8_csid, al32utf8_csid); + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + " charset id=%d, name=%s, ncharset id=%d, name=%s" + " (csid: utf8=%d al32utf8=%d)\n", + charsetid,charsetname, ncharsetid,ncharsetname, utf8_csid, al32utf8_csid); #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) - PerlIO_printf(DBILOGFP," Useing DRCP Connection\n "); + PerlIO_printf(DBIc_LOGPIO(imp_dbh)," Using DRCP Connection\n "); #endif } @@ -814,12 +816,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S return 0; } - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf(DBILOGFP,"Using DRCP with session settings min=%d, max=%d, and increment=%d\n",imp_dbh->pool_min, + if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + "Using DRCP with session settings min=%d, max=%d, and increment=%d\n", + imp_dbh->pool_min, imp_dbh->pool_max, imp_dbh->pool_incr); if (imp_dbh->pool_class) - PerlIO_printf(DBILOGFP,"with connection class=%s\n",imp_dbh->pool_class); + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + "with connection class=%s\n",imp_dbh->pool_class); } } @@ -913,8 +920,11 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); } - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf(DBILOGFP,"Setting up TAF with wait time of %d seconds\n",imp_dbh->taf_sleep); + if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + "Setting up TAF with wait time of %d seconds\n", + imp_dbh->taf_sleep); } status = reg_taf_callback(imp_dbh); if (status != OCI_SUCCESS) { From 4b95ca4dc7d016bed4c3b8e3c074e0cdc61fc058 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 16:08:58 +0000 Subject: [PATCH 160/637] Examples of changes to get rid of DBIS usage. I'll try and do more when I have time. Ideally, I'd like the calls to DBIS->debug to move to DBIc_TRACE which is more flexible and could introduce DBD tracing (which would allow us to throw away ora_verbose) git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15219 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 8ed61023..04bd3dfe 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -512,23 +512,23 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (DBD_ATTRIB_TRUE(attr,"ora_objects",11,svp)) DBD_ATTRIB_GET_IV( attr, "ora_objects",11, svp, ora_objects); - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) + if (DBIc_DBISTATE(imp_dbh)->debug >= 6 || dbd_verbose >= 6 ) dump_env_to_trace(); /* dbi_imp_data code adapted from DBD::mysql */ if (DBIc_has(imp_dbh, DBIcf_IMPSET)) { /* dbi_imp_data from take_imp_data */ if (DBIc_has(imp_dbh, DBIcf_ACTIVE)) { - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "dbd_db_login6 skip connect\n"); + if (DBIc_DBISTATE(imp_dbh)->debug >= 2 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_dbh), "dbd_db_login6 skip connect\n"); /* tell our parent we've adopted an active child */ ++DBIc_ACTIVE_KIDS(DBIc_PARENT_COM(imp_dbh)); return 1; } /* not ACTIVE so connect not skipped */ - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + if (DBIc_DBISTATE(imp_dbh)->debug >= 2 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_dbh), "dbd_db_login6 IMPSET but not ACTIVE so connect not skipped\n"); } @@ -566,8 +566,8 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S shared_dbh -> refcnt++ ; imp_dbh -> shared_dbh_priv_sv = shared_dbh_priv_sv ; imp_dbh -> shared_dbh = shared_dbh ; - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_db_login: use shared Oracle database handles.\n"); + if (DBIc_DBISTATE(imp_dbh)->debug >= 2 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_dbh), " dbd_db_login: use shared Oracle database handles.\n"); } else { shared_dbh = NULL ; } @@ -717,17 +717,19 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S * BTW: NLS_NCHAR is set as follows: NSL_LANG=AL32UTF8 */ - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_dbh)->debug >= 3 || dbd_verbose >= 3 ) { oratext charsetname[OCI_NLS_MAXBUFSZ]; oratext ncharsetname[OCI_NLS_MAXBUFSZ]; OCINlsCharSetIdToName(imp_dbh->envhp,charsetname, sizeof(charsetname),charsetid ); OCINlsCharSetIdToName(imp_dbh->envhp,ncharsetname, sizeof(ncharsetname),ncharsetid ); - PerlIO_printf(DBILOGFP," charset id=%d, name=%s, ncharset id=%d, name=%s" - " (csid: utf8=%d al32utf8=%d)\n", - charsetid,charsetname, ncharsetid,ncharsetname, utf8_csid, al32utf8_csid); + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + " charset id=%d, name=%s, ncharset id=%d, name=%s" + " (csid: utf8=%d al32utf8=%d)\n", + charsetid,charsetname, ncharsetid,ncharsetname, utf8_csid, al32utf8_csid); #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) - PerlIO_printf(DBILOGFP," Useing DRCP Connection\n "); + PerlIO_printf(DBIc_LOGPIO(imp_dbh)," Using DRCP Connection\n "); #endif } @@ -814,12 +816,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S return 0; } - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf(DBILOGFP,"Using DRCP with session settings min=%d, max=%d, and increment=%d\n",imp_dbh->pool_min, + if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + "Using DRCP with session settings min=%d, max=%d, and increment=%d\n", + imp_dbh->pool_min, imp_dbh->pool_max, imp_dbh->pool_incr); if (imp_dbh->pool_class) - PerlIO_printf(DBILOGFP,"with connection class=%s\n",imp_dbh->pool_class); + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + "with connection class=%s\n",imp_dbh->pool_class); } } @@ -913,8 +920,11 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); } - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf(DBILOGFP,"Setting up TAF with wait time of %d seconds\n",imp_dbh->taf_sleep); + if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + "Setting up TAF with wait time of %d seconds\n", + imp_dbh->taf_sleep); } status = reg_taf_callback(imp_dbh); if (status != OCI_SUCCESS) { From d58ac11cf333527dbe2592ca9886ca81c5d7fe4b Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 16:15:36 +0000 Subject: [PATCH 161/637] start removing DBIS usage git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15220 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index 1f5ffc93..d7bce20d 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,8 @@ NEXT is not in force as an additional call to OCILobFileIsOpen will be made. + - Start removing DBIS usage (Martin J. Evans). + [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) From 2ee2fc36241ad33f7643245bcd8c6bb885a44be5 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 16:15:36 +0000 Subject: [PATCH 162/637] start removing DBIS usage git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15220 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index 1f5ffc93..d7bce20d 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,8 @@ NEXT is not in force as an additional call to OCILobFileIsOpen will be made. + - Start removing DBIS usage (Martin J. Evans). + [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) From db7e6a5fd48aae7b95b7f950f709f611d9bac738 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 16:45:02 +0000 Subject: [PATCH 163/637] more removing DBIS usage some cannot be done without restructuring as some functions don't have a handle git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15221 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 455 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 286 insertions(+), 169 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 04bd3dfe..9785fddb 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1383,12 +1383,13 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ bufp = SvPV(source, len); if (DBIS->debug >=3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " creating xml from string that is %lu long\n",(unsigned long)len); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " creating xml from string that is %lu long\n",(unsigned long)len); if(len > MAX_OCISTRING_LEN) { src_type = OCI_XMLTYPE_CREATE_CLOB; if (DBIS->debug >=5 || dbd_verbose >= 5 ) - PerlIO_printf(DBILOGFP, " use a temp lob locator for large xml \n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " use a temp lob locator for large xml \n"); OCIDescriptorAlloc_ok(imp_dbh->envhp, &src_ptr, OCI_DTYPE_LOB); @@ -1413,7 +1414,8 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ } else { src_type = OCI_XMLTYPE_CREATE_OCISTRING; if (DBIS->debug >=5 || dbd_verbose >= 5 ) - PerlIO_printf(DBILOGFP, " use a OCIStringAssignText for small xml \n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " use a OCIStringAssignText for small xml \n"); OCIStringAssignText(imp_dbh->envhp, imp_dbh->errhp, bufp, @@ -1578,8 +1580,9 @@ phs_t *phs; if (imp_sth->all_params_hv) { DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv); if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_preparse scanned %d distinct placeholders\n", - (int)DBIc_NUM_PARAMS(imp_sth)); + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " dbd_preparse scanned %d distinct placeholders\n", + (int)DBIc_NUM_PARAMS(imp_sth)); } } @@ -1716,7 +1719,8 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) arr=(AV*)(SvRV(phs->sv)); if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): array_numstruct=%d\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): array_numstruct=%d\n", phs->array_numstruct); } /* If no number of entries to bind specified, @@ -1728,15 +1732,18 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if( numarrayentries >= 0 ){ phs->array_numstruct = numarrayentries+1; if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): array_numstruct=%d (calculated) \n", - phs->array_numstruct); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): array_numstruct=%d (calculated) \n", + phs->array_numstruct); } } /* Fix charset */ csform = phs->csform; if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): original csform=%d\n", - (int)csform); + PerlIO_printf(DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): original csform=%d\n", + (int)csform); } /* Calculate each bound structure maxlen. * If maxlen<=0, let maxlen=MAX ( length($$_) each @array ); @@ -1769,14 +1776,18 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) maxlen=length+1; } if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): length(array[%d])=%d\n", - i,(int)length); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): length(array[%d])=%d\n", + i,(int)length); } } if(SvUTF8(item) ){ flag_data_is_utf8=1; if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): is_utf8(array[%d])=true\n", i); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): is_utf8(array[%d])=true\n", i); } if (csform != SQLCS_NCHAR) { /* try to default csform to avoid translation through non-unicode */ @@ -1786,14 +1797,19 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) csform = SQLCS_IMPLICIT; /* else leave csform == 0 */ if (trace_level || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): rebinding %s with UTF8 value %s", phs->name, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): rebinding %s with UTF8 value %s", + phs->name, (csform == SQLCS_NCHAR) ? "so setting csform=SQLCS_IMPLICIT" : (csform == SQLCS_IMPLICIT) ? "so setting csform=SQLCS_NCHAR" : "but neither CHAR nor NCHAR are unicode\n"); } }else{ if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): is_utf8(array[%d])=false\n", i); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): is_utf8(array[%d])=false\n", i); } } } @@ -1801,13 +1817,17 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if( phs->maxlen <=0 ){ phs->maxlen=maxlen; if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): phs->maxlen calculated =%ld\n", - (long)maxlen); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): phs->maxlen calculated =%ld\n", + (long)maxlen); } } else{ if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): phs->maxlen forsed =%ld\n", - (long)maxlen); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): phs->maxlen forsed =%ld\n", + (long)maxlen); } } } @@ -1833,13 +1853,16 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) buflen=need_allocate_rows* phs->maxlen; /* We need buffer for at least ora_maxarray_numentries entries */ /* Upgrade array buffer to new length */ if( ora_realloc_phs_array(phs,need_allocate_rows,buflen) ){ - croak("Unable to bind %s - %d structures by %d bytes requires too much memory.", - phs->name, need_allocate_rows, buflen ); + croak("Unable to bind %s - %d structures by %d bytes requires too much memory.", + phs->name, need_allocate_rows, buflen ); }else{ - if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): ora_realloc_phs_array(,need_allocate_rows=%d,buflen=%d) succeeded.\n", - need_allocate_rows,buflen); - } + if (trace_level >= 2 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): ora_realloc_phs_array(," + "need_allocate_rows=%d,buflen=%d) succeeded.\n", + need_allocate_rows,buflen); + } } /* If maximum allowed bind numentries is less than allowed, * do not bind full array @@ -1850,48 +1873,54 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) /* Fill array buffer with string data */ { - int i; /* Not to require C99 mode */ - for(i=0;i0) ){ + int i; /* Not to require C99 mode */ + for(i=0;i0) ){ /* Limit string length to maxlen. FIXME: This may corrupt UTF-8 data. */ - if( itemlen > (unsigned int) phs->maxlen-1 ){ - itemlen=phs->maxlen-1; - } - memcpy( phs->array_buf+phs->maxlen*i, - str, - itemlen); - /* Set last byte to zero */ - phs->array_buf[ phs->maxlen*i + itemlen ]=0; - phs->array_indicators[i]=0; - phs->array_lengths[i]=itemlen+1; /* Zero byte */ - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): " - "Copying length=%lu array[%d]='%s'.\n", - (unsigned long)itemlen,i,str); - } - }else{ - /* Mark NULL */ - phs->array_indicators[i]=1; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): " - "Copying length=%lu array[%d]=NULL (length==0 or ! str) .\n", - (unsigned long)itemlen,i); - } - } - }else{ - /* Mark NULL */ - phs->array_indicators[i]=1; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): " - "Copying length=? array[%d]=NULL av_fetch failed.\n", i); - } - } - } + if( itemlen > (unsigned int) phs->maxlen-1 ){ + itemlen=phs->maxlen-1; + } + memcpy( phs->array_buf+phs->maxlen*i, + str, + itemlen); + /* Set last byte to zero */ + phs->array_buf[ phs->maxlen*i + itemlen ]=0; + phs->array_indicators[i]=0; + phs->array_lengths[i]=itemlen+1; /* Zero byte */ + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): " + "Copying length=%lu array[%d]='%s'.\n", + (unsigned long)itemlen,i,str); + } + }else{ + /* Mark NULL */ + phs->array_indicators[i]=1; + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): " + "Copying length=%lu array[%d]=NULL (length==0 or ! str) .\n", + (unsigned long)itemlen,i); + } + } + }else{ + /* Mark NULL */ + phs->array_indicators[i]=1; + if (trace_level >= 3 || dbd_verbose >= 3 ) { + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): " + "Copying length=? array[%d]=NULL av_fetch failed.\n", i); + } + } + } } /* Do actual bind */ OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, @@ -1944,7 +1973,9 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) csid = utf8_csid; /* not al32utf8_csid here on purpose */ if (trace_level >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): bind %s <== %s " + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): bind %s <== %s " "(%s, %s, csid %d->%d->%d, ftype %d, csform %d (%s)->%d (%s), maxlen %lu, maxdata_size %lu)\n", phs->name, neatsvpv(phs->sv,0), (phs->is_inout) ? "inout" : "in", @@ -2115,8 +2146,10 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { arr=(AV*)(SvRV(phs->sv)); if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): array_numstruct=%d\n", - phs->array_numstruct); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): array_numstruct=%d\n", + phs->array_numstruct); } /* If no number of entries to bind specified,*/ /* set phs->array_numstruct to the scalar(@array) bound.*/ @@ -2126,7 +2159,9 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { if( numarrayentries >= 0 ){ phs->array_numstruct = numarrayentries+1; if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): array_numstruct=%d (calculated) \n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): array_numstruct=%d (calculated) \n", phs->array_numstruct); } } @@ -2144,8 +2179,10 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { phs->maxlen=sizeof(double); } if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): phs->maxlen calculated =%ld\n", - (long)phs->maxlen); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): phs->maxlen calculated =%ld\n", + (long)phs->maxlen); } if( phs->array_numstruct == 0 ){ @@ -2157,13 +2194,18 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { phs->ora_maxarray_numentries=phs->array_numstruct; if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): ora_maxarray_numentries assumed=phs->array_numstruct=%d\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): ora_maxarray_numentries " + "assumed=phs->array_numstruct=%d\n", phs->array_numstruct); } }else{ if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): ora_maxarray_numentries=%d\n", - phs->ora_maxarray_numentries); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): ora_maxarray_numentries=%d\n", + phs->ora_maxarray_numentries); } } @@ -2176,19 +2218,22 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /* Upgrade array buffer to new length */ if( ora_realloc_phs_array(phs,need_allocate_rows,buflen) ){ - croak("Unable to bind %s - %d structures by %d bytes requires too much memory.", - phs->name, need_allocate_rows, buflen ); + croak("Unable to bind %s - %d structures by %d bytes requires too much memory.", + phs->name, need_allocate_rows, buflen ); }else{ - if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): ora_realloc_phs_array(,need_allocate_rows=%d,buflen=%d) succeeded.\n", - need_allocate_rows,buflen); - } + if (trace_level >= 2 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): ora_realloc_phs_array(," + "need_allocate_rows=%d,buflen=%d) succeeded.\n", + need_allocate_rows,buflen); + } } /* If maximum allowed bind numentries is less than allowed, * do not bind full array */ if( phs->array_numstruct > phs->ora_maxarray_numentries ){ - phs->array_numstruct = phs->ora_maxarray_numentries; + phs->array_numstruct = phs->ora_maxarray_numentries; } /* Fill array buffer with data */ @@ -2234,7 +2279,8 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { } phs->array_lengths[i]=sizeof(int); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " + PerlIO_printf( + DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " "(integer) array[%d]=%d%s\n", i, *(int*)(phs->array_buf+phs->maxlen*i), phs->array_indicators[i] ? " (NULL)" : "" ); @@ -2255,7 +2301,9 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { *(double*)(phs->array_buf+phs->maxlen*i)=val; phs->array_indicators[i]=0; if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " "let (double) array[%d]=%lf - NOT NULL\n", i, val); } @@ -2265,29 +2313,35 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { *(double*)(phs->array_buf+phs->maxlen*i)=0; phs->array_indicators[i]=0; if (trace_level >= 2 || dbd_verbose >= 3 ){ - STRLEN l; - char *p=SvPV(item,l); - - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=\"%s\" =NaN. Set =0 - NOT NULL\n", - i, p ? p : "" ); + STRLEN l; + char *p=SvPV(item,l); + + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d]=\"%s\" =NaN. Set =0 - NOT NULL\n", + i, p ? p : "" ); } }else{ /* NULL */ phs->array_indicators[i]=1; if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " - "let (double) array[%d] NULL\n", - i); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d] NULL\n", + i); } } } phs->array_lengths[i]=sizeof(double); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " - "(double) array[%d]=%lf%s\n", - i, *(double*)(phs->array_buf+phs->maxlen*i), - phs->array_indicators[i] ? " (NULL)" : "" ); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "(double) array[%d]=%lf%s\n", + i, *(double*)(phs->array_buf+phs->maxlen*i), + phs->array_indicators[i] ? " (NULL)" : "" ); } } break; @@ -2296,7 +2350,9 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /* item not defined, mark NULL */ phs->array_indicators[i]=1; if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " "Copying length=? array[%d]=NULL av_fetch failed.\n", i); } } @@ -2522,13 +2578,20 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) if (DBIS->debug >= 2 || dbd_verbose >= 3 ) { char *val = neatsvpv(phs->sv,10); - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_char() (1): bind %s <== %.1000s (", phs->name, val); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_char() (1): bind %s <== %.1000s (", phs->name, val); if (!SvOK(phs->sv)) - PerlIO_printf(DBILOGFP, "NULL, "); - PerlIO_printf(DBILOGFP, "size %ld/%ld/%ld, ",(long)SvCUR(phs->sv),(long)SvLEN(phs->sv),(long)phs->maxlen); - PerlIO_printf(DBILOGFP, "ptype %d(%s), otype %d %s)\n",(int)SvTYPE(phs->sv), sql_typecode_name(phs->ftype),phs->ftype,(phs->is_inout) ? ", inout" : ""); - - + PerlIO_printf(DBIc_LOGPIO(imp_sth), "NULL, "); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "size %ld/%ld/%ld, ", + (long)SvCUR(phs->sv),(long)SvLEN(phs->sv),(long)phs->maxlen); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "ptype %d(%s), otype %d %s)\n", + (int)SvTYPE(phs->sv), sql_typecode_name(phs->ftype), + phs->ftype,(phs->is_inout) ? ", inout" : ""); } /* At the moment we always do sv_setsv() and rebind. */ @@ -2596,11 +2659,15 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { UV neatsvpvlen = (UV)DBIc_DBISTATE(imp_sth)->neatsvpvlen; char *val = neatsvpv(phs->sv,10); - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_char() (2): bind %s <== '%.*s' (size %ld/%ld, otype %d(%s), indp %d, at_exec %d)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_char() (2): bind %s <== '%.*s' (size %ld/%ld, " + "otype %d(%s), indp %d, at_exec %d)\n", phs->name, (int)(phs->alen > neatsvpvlen ? neatsvpvlen : phs->alen), (phs->progv) ? val: "", - (long)phs->alen, (long)phs->maxlen, phs->ftype,sql_typecode_name(phs->ftype), phs->indp, at_exec); + (long)phs->alen, (long)phs->maxlen, + phs->ftype,sql_typecode_name(phs->ftype), phs->indp, at_exec); } return 1; @@ -2622,7 +2689,12 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) sword status; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " pp_rebind_ph_rset_in: BEGIN\n calling OCIBindByName(stmhp=%p, bndhp=%p, errhp=%p, name=%s, csrstmhp=%p, ftype=%d)\n", imp_sth->stmhp, phs->bndhp, imp_sth->errhp, phs->name, imp_sth_csr->stmhp, phs->ftype); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " pp_rebind_ph_rset_in: BEGIN\n calling OCIBindByName(stmhp=%p, " + "bndhp=%p, errhp=%p, name=%s, csrstmhp=%p, ftype=%d)\n", + imp_sth->stmhp, phs->bndhp, imp_sth->errhp, phs->name, + imp_sth_csr->stmhp, phs->ftype); OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), @@ -2642,7 +2714,7 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " pp_rebind_ph_rset_in: END\n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " pp_rebind_ph_rset_in: END\n"); return 2; } @@ -2651,7 +2723,7 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) int pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) { -dTHX; + dTHX; if (pre_exec) { /* pre-execute - allocate a statement handle */ dSP; @@ -2661,9 +2733,12 @@ dTHX; sword status; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " pp_exec_rset bind %s - allocating new sth...\n", phs->name); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " pp_exec_rset bind %s - allocating new sth...\n", + phs->name); - /* extproc deallocates everything for us */ + /* extproc deallocates everything for us */ if (is_extproc) return 1; @@ -2718,8 +2793,10 @@ dTHX; FREETMPS; LEAVE; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " pp_exec_rset bind %s - allocated %s...\n", - phs->name, neatsvpv(phs->sv, 0)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " pp_exec_rset bind %s - allocated %s...\n", + phs->name, neatsvpv(phs->sv, 0)); } else { /* post-execute - setup the statement handle */ @@ -2728,8 +2805,10 @@ dTHX; D_impdata(imp_sth_csr, imp_sth_t, sth_csr); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " bind %s - initialising new %s for cursor 0x%lx...\n", - phs->name, neatsvpv(sth_csr,0), (unsigned long)phs->progv); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " bind %s - initialising new %s for cursor 0x%lx...\n", + phs->name, neatsvpv(sth_csr,0), (unsigned long)phs->progv); /* copy appropriate handles and atributes from parent statement */ imp_sth_csr->envhp = imp_sth->envhp; @@ -2773,7 +2852,7 @@ sword status; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " in dbd_rebind_ph_xml\n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " in dbd_rebind_ph_xml\n"); /*go and create the XML dom from the passed in value*/ @@ -2818,7 +2897,7 @@ sword status; return 0; } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " pp_rebind_ph_nty: END\n"); /* bind the object */ @@ -2846,9 +2925,14 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) ub2 csid; if (trace_level >= 5 || dbd_verbose >= 5 ) - PerlIO_printf(DBILOGFP, "dbd_rebind_ph() (1): rebinding %s as %s (%s, ftype %d (%s), csid %d, csform %d(%s), inout %d)\n", - phs->name, (SvPOK(phs->sv) ? neatsvpv(phs->sv,10) : "NULL"),(SvUTF8(phs->sv) ? "is-utf8" : "not-utf8"), - phs->ftype,sql_typecode_name(phs->ftype),phs->csid, phs->csform,oci_csform_name(phs->csform), phs->is_inout); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph() (1): rebinding %s as %s (%s, ftype %d (%s), " + "csid %d, csform %d(%s), inout %d)\n", + phs->name, (SvPOK(phs->sv) ? neatsvpv(phs->sv,10) : "NULL"), + (SvUTF8(phs->sv) ? "is-utf8" : "not-utf8"), + phs->ftype,sql_typecode_name(phs->ftype), phs->csid, phs->csform, + oci_csform_name(phs->csform), phs->is_inout); switch (phs->ftype) { case ORA_VARCHAR2_TABLE: @@ -2873,13 +2957,14 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (done == 2) { /* the dbd_rebind_* did the OCI bind call itself successfully */ if (trace_level >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " rebind %s done with ftype %d (%s)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " rebind %s done with ftype %d (%s)\n", phs->name, phs->ftype,sql_typecode_name(phs->ftype)); return 1; } if (trace_level >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " bind %s as ftype %d (%s)\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), " bind %s as ftype %d (%s)\n", phs->name, phs->ftype,sql_typecode_name(phs->ftype)); if (done != 1) { @@ -2927,7 +3012,9 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) else if (CSFORM_IMPLIES_UTF8(SQLCS_NCHAR)) csform = SQLCS_NCHAR; /* else leave csform == 0 */ if (trace_level || dbd_verbose >= 3) - PerlIO_printf(DBILOGFP, "dbd_rebind_ph() (2): rebinding %s with UTF8 value %s", phs->name, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph() (2): rebinding %s with UTF8 value %s", phs->name, (csform == SQLCS_IMPLICIT) ? "so setting csform=SQLCS_IMPLICIT" : (csform == SQLCS_NCHAR) ? "so setting csform=SQLCS_NCHAR" : "but neither CHAR nor NCHAR are unicode\n"); @@ -2956,15 +3043,18 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) csid = utf8_csid; /* not al32utf8_csid here on purpose */ if (trace_level >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "dbd_rebind_ph(): bind %s <== %s " - "(%s, %s, csid %d->%d->%d, ftype %d (%s), csform %d(%s)->%d(%s), maxlen %lu, maxdata_size %lu)\n", - phs->name, neatsvpv(phs->sv,10), - (phs->is_inout) ? "inout" : "in", - (SvUTF8(phs->sv) ? "is-utf8" : "not-utf8"), - phs->csid_orig, phs->csid, csid, - phs->ftype,sql_typecode_name(phs->ftype), phs->csform, oci_csform_name(phs->csform), csform, oci_csform_name(csform), - (unsigned long)phs->maxlen, (unsigned long)phs->maxdata_size); - + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph(): bind %s <== %s " + "(%s, %s, csid %d->%d->%d, ftype %d (%s), csform %d(%s)->%d(%s), " + "maxlen %lu, maxdata_size %lu)\n", + phs->name, neatsvpv(phs->sv,10), + (phs->is_inout) ? "inout" : "in", + (SvUTF8(phs->sv) ? "is-utf8" : "not-utf8"), + phs->csid_orig, phs->csid, csid, + phs->ftype, sql_typecode_name(phs->ftype), phs->csform, + oci_csform_name(phs->csform), csform, oci_csform_name(csform), + (unsigned long)phs->maxlen, (unsigned long)phs->maxdata_size); if (csid) { OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, @@ -3035,14 +3125,15 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ croak("Can't bind ``lvalue'' mode scalar as inout parameter (currently)"); if (DBIS->debug >= 2 || dbd_verbose >= 3 ) { - PerlIO_printf(DBILOGFP, "dbd_bind_ph(1): bind %s <== %s (type %ld (%s)", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), "dbd_bind_ph(1): bind %s <== %s (type %ld (%s)", name, neatsvpv(newvalue,0), (long)sql_type,sql_typecode_name(sql_type)); if (is_inout) - PerlIO_printf(DBILOGFP, ", inout 0x%lx, maxlen %ld", + PerlIO_printf(DBIc_LOGPIO(imp_sth), ", inout 0x%lx, maxlen %ld", (long)newvalue, (long)maxlen); if (attribs) - PerlIO_printf(DBILOGFP, ", attribs: %s", neatsvpv(attribs,0)); - PerlIO_printf(DBILOGFP, ")\n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), ", attribs: %s", neatsvpv(attribs,0)); + PerlIO_printf(DBIc_LOGPIO(imp_sth), ")\n"); } phs_svp = hv_fetch(imp_sth->all_params_hv, name, name_len, 0); @@ -3294,9 +3385,10 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_st_execute %s (out%d, lob%d)...\n", - oci_stmt_type_name(imp_sth->stmt_type), outparams, imp_sth->has_lobs); - + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_st_execute %s (out%d, lob%d)...\n", + oci_stmt_type_name(imp_sth->stmt_type), outparams, imp_sth->has_lobs); /* Don't attempt execute for nested cursor. It would be meaningless, and Oracle code has been seen to core dump */ @@ -3326,11 +3418,12 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- else if (SvTYPE(sv) == SVt_RV && SvTYPE(SvRV(sv)) == SVt_PVAV) { if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " with %s = [] (len %ld/%ld, indp %d, otype %d, ptype %d)\n", - phs->name, - (long)phs->alen, (long)phs->maxlen, phs->indp, - phs->ftype, (int)SvTYPE(sv)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " with %s = [] (len %ld/%ld, indp %d, otype %d, ptype %d)\n", + phs->name, + (long)phs->alen, (long)phs->maxlen, phs->indp, + phs->ftype, (int)SvTYPE(sv)); av_clear((AV*)SvRV(sv)); } else @@ -3351,12 +3444,15 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- ub2 prev_alen = phs->alen; phs->alen = (SvOK(sv)) ? SvCUR(sv) + phs->alen_incnull : 0+phs->alen_incnull; if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " with %s = '%.*s' (len %ld(%ld)/%ld, indp %d, otype %d, ptype %d)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " with %s = '%.*s' (len %ld(%ld)/%ld, indp %d, " + "otype %d, ptype %d)\n", phs->name, (int)phs->alen, - (phs->indp == -1) ? "" : SvPVX(sv), - (long)phs->alen, (long)prev_alen, (long)phs->maxlen, phs->indp, - phs->ftype, (int)SvTYPE(sv)); + (phs->indp == -1) ? "" : SvPVX(sv), + (long)phs->alen, (long)prev_alen, + (long)phs->maxlen, phs->indp, + phs->ftype, (int)SvTYPE(sv)); } } } @@ -3372,7 +3468,10 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP,"Statement Execute Mode is %d (%s)\n",imp_sth->exe_mode,oci_exe_mode(imp_sth->exe_mode)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Statement Execute Mode is %d (%s)\n", + imp_sth->exe_mode,oci_exe_mode(imp_sth->exe_mode)); OCIStmtExecute_log_stat(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, (ub4)(is_select ? 0: 1), @@ -3402,7 +3501,8 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- if (debug >= 2 || dbd_verbose >= 3 ) { ub2 sqlfncode; OCIAttrGet_stmhp_stat(imp_sth, &sqlfncode, 0, OCI_ATTR_SQLFNCODE, status); - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " dbd_st_execute %s returned (%s, rpc%ld, fn%d, out%d)\n", oci_stmt_type_name(imp_sth->stmt_type), oci_status_name(status), @@ -3427,8 +3527,10 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); SV *sv = phs->sv; if (debug >= 2 || dbd_verbose >= 3 ) { - PerlIO_printf(DBILOGFP, - "dbd_st_execute(): Analyzing inout a parameter '%s of type=%d name=%s'\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_st_execute(): Analyzing inout a parameter '%s" + "of type=%d name=%s'\n", phs->name,phs->ftype,sql_typecode_name(phs->ftype)); } if( phs->ftype == ORA_VARCHAR2_TABLE ){ @@ -3511,7 +3613,9 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat else if (CSFORM_IMPLIES_UTF8(SQLCS_NCHAR)) csform = SQLCS_NCHAR; /* else leave csform == 0 */ if (trace_level || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "do_bind_array_exec() (2): rebinding %s with UTF8 value %s", phs->name, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "do_bind_array_exec() (2): rebinding %s with UTF8 value %s", phs->name, (csform == SQLCS_IMPLICIT) ? "so setting csform=SQLCS_IMPLICIT" : (csform == SQLCS_NCHAR) ? "so setting csform=SQLCS_NCHAR" : "but neither CHAR nor NCHAR are unicode\n"); @@ -3560,16 +3664,19 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat } if (trace_level >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "do_bind_array_exec(): bind %s <== [array of values] " - "(%s, %s, csid %d->%d->%d, ftype %d (%s), csform %d (%s)->%d (%s), maxlen %lu, maxdata_size %lu)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "do_bind_array_exec(): bind %s <== [array of values] " + "(%s, %s, csid %d->%d->%d, ftype %d (%s), csform %d (%s)->%d (%s)" + ", maxlen %lu, maxdata_size %lu)\n", phs->name, (phs->is_inout) ? "inout" : "in", (utf8 ? "is-utf8" : "not-utf8"), phs->csid_orig, phs->csid, csid, - phs->ftype,sql_typecode_name(phs->ftype), phs->csform,oci_csform_name(phs->csform), csform,oci_csform_name(csform), + phs->ftype, sql_typecode_name(phs->ftype), + phs->csform,oci_csform_name(phs->csform), csform,oci_csform_name(csform), (unsigned long)phs->maxlen, (unsigned long)phs->maxdata_size); - if (csid) { OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, &csid, (ub4) 0, (ub4) OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); @@ -3633,10 +3740,12 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er tuples_utf8_av=newAV(); if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " ora_st_execute_array %s count=%d (%s %s %s)...\n", - oci_stmt_type_name(imp_sth->stmt_type), exe_count, - neatsvpv(tuples,0), neatsvpv(tuples_status,0), - neatsvpv(columns, 0)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " ora_st_execute_array %s count=%d (%s %s %s)...\n", + oci_stmt_type_name(imp_sth->stmt_type), exe_count, + neatsvpv(tuples,0), neatsvpv(tuples_status,0), + neatsvpv(columns, 0)); if (is_select) { croak("ora_st_execute_array(): SELECT statement not supported " @@ -3822,8 +3931,10 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er OCIAttrGet_stmhp_stat(imp_sth, &num_errs, 0, OCI_ATTR_NUM_DML_ERRORS, status); if (debug >= 6 || dbd_verbose >= 6 ) - PerlIO_printf(DBILOGFP, " ora_st_execute_array %d errors in batch.\n", - num_errs); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " ora_st_execute_array %d errors in batch.\n", + num_errs); if(num_errs && tuples_status_av) { OCIError *row_errhp, *tmp_errhp; @@ -3844,8 +3955,10 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er OCIAttrGet_log_stat(row_errhp, OCI_HTYPE_ERROR, &row_off, 0, OCI_ATTR_DML_ROW_OFFSET, imp_sth->errhp, status); if (debug >= 6 || dbd_verbose >= 6 ) - PerlIO_printf(DBILOGFP, " ora_st_execute_array error in row %d.\n", - row_off); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " ora_st_execute_array error in row %d.\n", + row_off); sv_setpv(err_svs[1], ""); err_code = oci_error_get(row_errhp, exe_status, NULL, err_svs[1], debug); sv_setiv(err_svs[0], (IV)err_code); @@ -3908,8 +4021,10 @@ dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, ftype = ftype; /* no unused */ if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " blob_read field %d+1, ftype %d, offset %ld, len %ld, destoffset %ld, retlen %ld\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " blob_read field %d+1, ftype %d, offset %ld, len %ld, " + "destoffset %ld, retlen %ld\n", field, imp_sth->fbh[field].ftype, offset, len, destoffset, (long)retl); SvCUR_set(bufsv, destoffset+retl); @@ -4060,7 +4175,9 @@ ora_free_templob(SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc) if (is_temporary) { if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { - PerlIO_printf(DBILOGFP, " OCILobFreeTemporary %s\n", oci_status_name(status)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobFreeTemporary %s\n", oci_status_name(status)); } OCILobFreeTemporary_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, status); if (status != OCI_SUCCESS) { From 9f16ac3a7e5264f064fb769070f8d004365ae53a Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 16:45:02 +0000 Subject: [PATCH 164/637] more removing DBIS usage some cannot be done without restructuring as some functions don't have a handle git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15221 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 455 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 286 insertions(+), 169 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 04bd3dfe..9785fddb 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1383,12 +1383,13 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ bufp = SvPV(source, len); if (DBIS->debug >=3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " creating xml from string that is %lu long\n",(unsigned long)len); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " creating xml from string that is %lu long\n",(unsigned long)len); if(len > MAX_OCISTRING_LEN) { src_type = OCI_XMLTYPE_CREATE_CLOB; if (DBIS->debug >=5 || dbd_verbose >= 5 ) - PerlIO_printf(DBILOGFP, " use a temp lob locator for large xml \n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " use a temp lob locator for large xml \n"); OCIDescriptorAlloc_ok(imp_dbh->envhp, &src_ptr, OCI_DTYPE_LOB); @@ -1413,7 +1414,8 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ } else { src_type = OCI_XMLTYPE_CREATE_OCISTRING; if (DBIS->debug >=5 || dbd_verbose >= 5 ) - PerlIO_printf(DBILOGFP, " use a OCIStringAssignText for small xml \n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " use a OCIStringAssignText for small xml \n"); OCIStringAssignText(imp_dbh->envhp, imp_dbh->errhp, bufp, @@ -1578,8 +1580,9 @@ phs_t *phs; if (imp_sth->all_params_hv) { DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv); if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_preparse scanned %d distinct placeholders\n", - (int)DBIc_NUM_PARAMS(imp_sth)); + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " dbd_preparse scanned %d distinct placeholders\n", + (int)DBIc_NUM_PARAMS(imp_sth)); } } @@ -1716,7 +1719,8 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) arr=(AV*)(SvRV(phs->sv)); if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): array_numstruct=%d\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): array_numstruct=%d\n", phs->array_numstruct); } /* If no number of entries to bind specified, @@ -1728,15 +1732,18 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if( numarrayentries >= 0 ){ phs->array_numstruct = numarrayentries+1; if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): array_numstruct=%d (calculated) \n", - phs->array_numstruct); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): array_numstruct=%d (calculated) \n", + phs->array_numstruct); } } /* Fix charset */ csform = phs->csform; if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): original csform=%d\n", - (int)csform); + PerlIO_printf(DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): original csform=%d\n", + (int)csform); } /* Calculate each bound structure maxlen. * If maxlen<=0, let maxlen=MAX ( length($$_) each @array ); @@ -1769,14 +1776,18 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) maxlen=length+1; } if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): length(array[%d])=%d\n", - i,(int)length); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): length(array[%d])=%d\n", + i,(int)length); } } if(SvUTF8(item) ){ flag_data_is_utf8=1; if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): is_utf8(array[%d])=true\n", i); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): is_utf8(array[%d])=true\n", i); } if (csform != SQLCS_NCHAR) { /* try to default csform to avoid translation through non-unicode */ @@ -1786,14 +1797,19 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) csform = SQLCS_IMPLICIT; /* else leave csform == 0 */ if (trace_level || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): rebinding %s with UTF8 value %s", phs->name, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): rebinding %s with UTF8 value %s", + phs->name, (csform == SQLCS_NCHAR) ? "so setting csform=SQLCS_IMPLICIT" : (csform == SQLCS_IMPLICIT) ? "so setting csform=SQLCS_NCHAR" : "but neither CHAR nor NCHAR are unicode\n"); } }else{ if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): is_utf8(array[%d])=false\n", i); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): is_utf8(array[%d])=false\n", i); } } } @@ -1801,13 +1817,17 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if( phs->maxlen <=0 ){ phs->maxlen=maxlen; if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): phs->maxlen calculated =%ld\n", - (long)maxlen); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): phs->maxlen calculated =%ld\n", + (long)maxlen); } } else{ if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): phs->maxlen forsed =%ld\n", - (long)maxlen); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): phs->maxlen forsed =%ld\n", + (long)maxlen); } } } @@ -1833,13 +1853,16 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) buflen=need_allocate_rows* phs->maxlen; /* We need buffer for at least ora_maxarray_numentries entries */ /* Upgrade array buffer to new length */ if( ora_realloc_phs_array(phs,need_allocate_rows,buflen) ){ - croak("Unable to bind %s - %d structures by %d bytes requires too much memory.", - phs->name, need_allocate_rows, buflen ); + croak("Unable to bind %s - %d structures by %d bytes requires too much memory.", + phs->name, need_allocate_rows, buflen ); }else{ - if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): ora_realloc_phs_array(,need_allocate_rows=%d,buflen=%d) succeeded.\n", - need_allocate_rows,buflen); - } + if (trace_level >= 2 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): ora_realloc_phs_array(," + "need_allocate_rows=%d,buflen=%d) succeeded.\n", + need_allocate_rows,buflen); + } } /* If maximum allowed bind numentries is less than allowed, * do not bind full array @@ -1850,48 +1873,54 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) /* Fill array buffer with string data */ { - int i; /* Not to require C99 mode */ - for(i=0;i0) ){ + int i; /* Not to require C99 mode */ + for(i=0;i0) ){ /* Limit string length to maxlen. FIXME: This may corrupt UTF-8 data. */ - if( itemlen > (unsigned int) phs->maxlen-1 ){ - itemlen=phs->maxlen-1; - } - memcpy( phs->array_buf+phs->maxlen*i, - str, - itemlen); - /* Set last byte to zero */ - phs->array_buf[ phs->maxlen*i + itemlen ]=0; - phs->array_indicators[i]=0; - phs->array_lengths[i]=itemlen+1; /* Zero byte */ - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): " - "Copying length=%lu array[%d]='%s'.\n", - (unsigned long)itemlen,i,str); - } - }else{ - /* Mark NULL */ - phs->array_indicators[i]=1; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): " - "Copying length=%lu array[%d]=NULL (length==0 or ! str) .\n", - (unsigned long)itemlen,i); - } - } - }else{ - /* Mark NULL */ - phs->array_indicators[i]=1; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): " - "Copying length=? array[%d]=NULL av_fetch failed.\n", i); - } - } - } + if( itemlen > (unsigned int) phs->maxlen-1 ){ + itemlen=phs->maxlen-1; + } + memcpy( phs->array_buf+phs->maxlen*i, + str, + itemlen); + /* Set last byte to zero */ + phs->array_buf[ phs->maxlen*i + itemlen ]=0; + phs->array_indicators[i]=0; + phs->array_lengths[i]=itemlen+1; /* Zero byte */ + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): " + "Copying length=%lu array[%d]='%s'.\n", + (unsigned long)itemlen,i,str); + } + }else{ + /* Mark NULL */ + phs->array_indicators[i]=1; + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): " + "Copying length=%lu array[%d]=NULL (length==0 or ! str) .\n", + (unsigned long)itemlen,i); + } + } + }else{ + /* Mark NULL */ + phs->array_indicators[i]=1; + if (trace_level >= 3 || dbd_verbose >= 3 ) { + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): " + "Copying length=? array[%d]=NULL av_fetch failed.\n", i); + } + } + } } /* Do actual bind */ OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, @@ -1944,7 +1973,9 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) csid = utf8_csid; /* not al32utf8_csid here on purpose */ if (trace_level >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_varchar2_table(): bind %s <== %s " + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_varchar2_table(): bind %s <== %s " "(%s, %s, csid %d->%d->%d, ftype %d, csform %d (%s)->%d (%s), maxlen %lu, maxdata_size %lu)\n", phs->name, neatsvpv(phs->sv,0), (phs->is_inout) ? "inout" : "in", @@ -2115,8 +2146,10 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { arr=(AV*)(SvRV(phs->sv)); if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): array_numstruct=%d\n", - phs->array_numstruct); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): array_numstruct=%d\n", + phs->array_numstruct); } /* If no number of entries to bind specified,*/ /* set phs->array_numstruct to the scalar(@array) bound.*/ @@ -2126,7 +2159,9 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { if( numarrayentries >= 0 ){ phs->array_numstruct = numarrayentries+1; if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): array_numstruct=%d (calculated) \n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): array_numstruct=%d (calculated) \n", phs->array_numstruct); } } @@ -2144,8 +2179,10 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { phs->maxlen=sizeof(double); } if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): phs->maxlen calculated =%ld\n", - (long)phs->maxlen); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): phs->maxlen calculated =%ld\n", + (long)phs->maxlen); } if( phs->array_numstruct == 0 ){ @@ -2157,13 +2194,18 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { phs->ora_maxarray_numentries=phs->array_numstruct; if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): ora_maxarray_numentries assumed=phs->array_numstruct=%d\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): ora_maxarray_numentries " + "assumed=phs->array_numstruct=%d\n", phs->array_numstruct); } }else{ if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): ora_maxarray_numentries=%d\n", - phs->ora_maxarray_numentries); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): ora_maxarray_numentries=%d\n", + phs->ora_maxarray_numentries); } } @@ -2176,19 +2218,22 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /* Upgrade array buffer to new length */ if( ora_realloc_phs_array(phs,need_allocate_rows,buflen) ){ - croak("Unable to bind %s - %d structures by %d bytes requires too much memory.", - phs->name, need_allocate_rows, buflen ); + croak("Unable to bind %s - %d structures by %d bytes requires too much memory.", + phs->name, need_allocate_rows, buflen ); }else{ - if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): ora_realloc_phs_array(,need_allocate_rows=%d,buflen=%d) succeeded.\n", - need_allocate_rows,buflen); - } + if (trace_level >= 2 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): ora_realloc_phs_array(," + "need_allocate_rows=%d,buflen=%d) succeeded.\n", + need_allocate_rows,buflen); + } } /* If maximum allowed bind numentries is less than allowed, * do not bind full array */ if( phs->array_numstruct > phs->ora_maxarray_numentries ){ - phs->array_numstruct = phs->ora_maxarray_numentries; + phs->array_numstruct = phs->ora_maxarray_numentries; } /* Fill array buffer with data */ @@ -2234,7 +2279,8 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { } phs->array_lengths[i]=sizeof(int); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " + PerlIO_printf( + DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " "(integer) array[%d]=%d%s\n", i, *(int*)(phs->array_buf+phs->maxlen*i), phs->array_indicators[i] ? " (NULL)" : "" ); @@ -2255,7 +2301,9 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { *(double*)(phs->array_buf+phs->maxlen*i)=val; phs->array_indicators[i]=0; if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " "let (double) array[%d]=%lf - NOT NULL\n", i, val); } @@ -2265,29 +2313,35 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { *(double*)(phs->array_buf+phs->maxlen*i)=0; phs->array_indicators[i]=0; if (trace_level >= 2 || dbd_verbose >= 3 ){ - STRLEN l; - char *p=SvPV(item,l); - - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=\"%s\" =NaN. Set =0 - NOT NULL\n", - i, p ? p : "" ); + STRLEN l; + char *p=SvPV(item,l); + + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d]=\"%s\" =NaN. Set =0 - NOT NULL\n", + i, p ? p : "" ); } }else{ /* NULL */ phs->array_indicators[i]=1; if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " - "let (double) array[%d] NULL\n", - i); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d] NULL\n", + i); } } } phs->array_lengths[i]=sizeof(double); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " - "(double) array[%d]=%lf%s\n", - i, *(double*)(phs->array_buf+phs->maxlen*i), - phs->array_indicators[i] ? " (NULL)" : "" ); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "(double) array[%d]=%lf%s\n", + i, *(double*)(phs->array_buf+phs->maxlen*i), + phs->array_indicators[i] ? " (NULL)" : "" ); } } break; @@ -2296,7 +2350,9 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /* item not defined, mark NULL */ phs->array_indicators[i]=1; if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_number_table(): " + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " "Copying length=? array[%d]=NULL av_fetch failed.\n", i); } } @@ -2522,13 +2578,20 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) if (DBIS->debug >= 2 || dbd_verbose >= 3 ) { char *val = neatsvpv(phs->sv,10); - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_char() (1): bind %s <== %.1000s (", phs->name, val); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_char() (1): bind %s <== %.1000s (", phs->name, val); if (!SvOK(phs->sv)) - PerlIO_printf(DBILOGFP, "NULL, "); - PerlIO_printf(DBILOGFP, "size %ld/%ld/%ld, ",(long)SvCUR(phs->sv),(long)SvLEN(phs->sv),(long)phs->maxlen); - PerlIO_printf(DBILOGFP, "ptype %d(%s), otype %d %s)\n",(int)SvTYPE(phs->sv), sql_typecode_name(phs->ftype),phs->ftype,(phs->is_inout) ? ", inout" : ""); - - + PerlIO_printf(DBIc_LOGPIO(imp_sth), "NULL, "); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "size %ld/%ld/%ld, ", + (long)SvCUR(phs->sv),(long)SvLEN(phs->sv),(long)phs->maxlen); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "ptype %d(%s), otype %d %s)\n", + (int)SvTYPE(phs->sv), sql_typecode_name(phs->ftype), + phs->ftype,(phs->is_inout) ? ", inout" : ""); } /* At the moment we always do sv_setsv() and rebind. */ @@ -2596,11 +2659,15 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { UV neatsvpvlen = (UV)DBIc_DBISTATE(imp_sth)->neatsvpvlen; char *val = neatsvpv(phs->sv,10); - PerlIO_printf(DBILOGFP, "dbd_rebind_ph_char() (2): bind %s <== '%.*s' (size %ld/%ld, otype %d(%s), indp %d, at_exec %d)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_char() (2): bind %s <== '%.*s' (size %ld/%ld, " + "otype %d(%s), indp %d, at_exec %d)\n", phs->name, (int)(phs->alen > neatsvpvlen ? neatsvpvlen : phs->alen), (phs->progv) ? val: "", - (long)phs->alen, (long)phs->maxlen, phs->ftype,sql_typecode_name(phs->ftype), phs->indp, at_exec); + (long)phs->alen, (long)phs->maxlen, + phs->ftype,sql_typecode_name(phs->ftype), phs->indp, at_exec); } return 1; @@ -2622,7 +2689,12 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) sword status; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " pp_rebind_ph_rset_in: BEGIN\n calling OCIBindByName(stmhp=%p, bndhp=%p, errhp=%p, name=%s, csrstmhp=%p, ftype=%d)\n", imp_sth->stmhp, phs->bndhp, imp_sth->errhp, phs->name, imp_sth_csr->stmhp, phs->ftype); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " pp_rebind_ph_rset_in: BEGIN\n calling OCIBindByName(stmhp=%p, " + "bndhp=%p, errhp=%p, name=%s, csrstmhp=%p, ftype=%d)\n", + imp_sth->stmhp, phs->bndhp, imp_sth->errhp, phs->name, + imp_sth_csr->stmhp, phs->ftype); OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), @@ -2642,7 +2714,7 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " pp_rebind_ph_rset_in: END\n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " pp_rebind_ph_rset_in: END\n"); return 2; } @@ -2651,7 +2723,7 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) int pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) { -dTHX; + dTHX; if (pre_exec) { /* pre-execute - allocate a statement handle */ dSP; @@ -2661,9 +2733,12 @@ dTHX; sword status; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " pp_exec_rset bind %s - allocating new sth...\n", phs->name); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " pp_exec_rset bind %s - allocating new sth...\n", + phs->name); - /* extproc deallocates everything for us */ + /* extproc deallocates everything for us */ if (is_extproc) return 1; @@ -2718,8 +2793,10 @@ dTHX; FREETMPS; LEAVE; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " pp_exec_rset bind %s - allocated %s...\n", - phs->name, neatsvpv(phs->sv, 0)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " pp_exec_rset bind %s - allocated %s...\n", + phs->name, neatsvpv(phs->sv, 0)); } else { /* post-execute - setup the statement handle */ @@ -2728,8 +2805,10 @@ dTHX; D_impdata(imp_sth_csr, imp_sth_t, sth_csr); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " bind %s - initialising new %s for cursor 0x%lx...\n", - phs->name, neatsvpv(sth_csr,0), (unsigned long)phs->progv); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " bind %s - initialising new %s for cursor 0x%lx...\n", + phs->name, neatsvpv(sth_csr,0), (unsigned long)phs->progv); /* copy appropriate handles and atributes from parent statement */ imp_sth_csr->envhp = imp_sth->envhp; @@ -2773,7 +2852,7 @@ sword status; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " in dbd_rebind_ph_xml\n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " in dbd_rebind_ph_xml\n"); /*go and create the XML dom from the passed in value*/ @@ -2818,7 +2897,7 @@ sword status; return 0; } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " pp_rebind_ph_nty: END\n"); /* bind the object */ @@ -2846,9 +2925,14 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) ub2 csid; if (trace_level >= 5 || dbd_verbose >= 5 ) - PerlIO_printf(DBILOGFP, "dbd_rebind_ph() (1): rebinding %s as %s (%s, ftype %d (%s), csid %d, csform %d(%s), inout %d)\n", - phs->name, (SvPOK(phs->sv) ? neatsvpv(phs->sv,10) : "NULL"),(SvUTF8(phs->sv) ? "is-utf8" : "not-utf8"), - phs->ftype,sql_typecode_name(phs->ftype),phs->csid, phs->csform,oci_csform_name(phs->csform), phs->is_inout); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph() (1): rebinding %s as %s (%s, ftype %d (%s), " + "csid %d, csform %d(%s), inout %d)\n", + phs->name, (SvPOK(phs->sv) ? neatsvpv(phs->sv,10) : "NULL"), + (SvUTF8(phs->sv) ? "is-utf8" : "not-utf8"), + phs->ftype,sql_typecode_name(phs->ftype), phs->csid, phs->csform, + oci_csform_name(phs->csform), phs->is_inout); switch (phs->ftype) { case ORA_VARCHAR2_TABLE: @@ -2873,13 +2957,14 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (done == 2) { /* the dbd_rebind_* did the OCI bind call itself successfully */ if (trace_level >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " rebind %s done with ftype %d (%s)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " rebind %s done with ftype %d (%s)\n", phs->name, phs->ftype,sql_typecode_name(phs->ftype)); return 1; } if (trace_level >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " bind %s as ftype %d (%s)\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), " bind %s as ftype %d (%s)\n", phs->name, phs->ftype,sql_typecode_name(phs->ftype)); if (done != 1) { @@ -2927,7 +3012,9 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) else if (CSFORM_IMPLIES_UTF8(SQLCS_NCHAR)) csform = SQLCS_NCHAR; /* else leave csform == 0 */ if (trace_level || dbd_verbose >= 3) - PerlIO_printf(DBILOGFP, "dbd_rebind_ph() (2): rebinding %s with UTF8 value %s", phs->name, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph() (2): rebinding %s with UTF8 value %s", phs->name, (csform == SQLCS_IMPLICIT) ? "so setting csform=SQLCS_IMPLICIT" : (csform == SQLCS_NCHAR) ? "so setting csform=SQLCS_NCHAR" : "but neither CHAR nor NCHAR are unicode\n"); @@ -2956,15 +3043,18 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) csid = utf8_csid; /* not al32utf8_csid here on purpose */ if (trace_level >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "dbd_rebind_ph(): bind %s <== %s " - "(%s, %s, csid %d->%d->%d, ftype %d (%s), csform %d(%s)->%d(%s), maxlen %lu, maxdata_size %lu)\n", - phs->name, neatsvpv(phs->sv,10), - (phs->is_inout) ? "inout" : "in", - (SvUTF8(phs->sv) ? "is-utf8" : "not-utf8"), - phs->csid_orig, phs->csid, csid, - phs->ftype,sql_typecode_name(phs->ftype), phs->csform, oci_csform_name(phs->csform), csform, oci_csform_name(csform), - (unsigned long)phs->maxlen, (unsigned long)phs->maxdata_size); - + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph(): bind %s <== %s " + "(%s, %s, csid %d->%d->%d, ftype %d (%s), csform %d(%s)->%d(%s), " + "maxlen %lu, maxdata_size %lu)\n", + phs->name, neatsvpv(phs->sv,10), + (phs->is_inout) ? "inout" : "in", + (SvUTF8(phs->sv) ? "is-utf8" : "not-utf8"), + phs->csid_orig, phs->csid, csid, + phs->ftype, sql_typecode_name(phs->ftype), phs->csform, + oci_csform_name(phs->csform), csform, oci_csform_name(csform), + (unsigned long)phs->maxlen, (unsigned long)phs->maxdata_size); if (csid) { OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, @@ -3035,14 +3125,15 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ croak("Can't bind ``lvalue'' mode scalar as inout parameter (currently)"); if (DBIS->debug >= 2 || dbd_verbose >= 3 ) { - PerlIO_printf(DBILOGFP, "dbd_bind_ph(1): bind %s <== %s (type %ld (%s)", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), "dbd_bind_ph(1): bind %s <== %s (type %ld (%s)", name, neatsvpv(newvalue,0), (long)sql_type,sql_typecode_name(sql_type)); if (is_inout) - PerlIO_printf(DBILOGFP, ", inout 0x%lx, maxlen %ld", + PerlIO_printf(DBIc_LOGPIO(imp_sth), ", inout 0x%lx, maxlen %ld", (long)newvalue, (long)maxlen); if (attribs) - PerlIO_printf(DBILOGFP, ", attribs: %s", neatsvpv(attribs,0)); - PerlIO_printf(DBILOGFP, ")\n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), ", attribs: %s", neatsvpv(attribs,0)); + PerlIO_printf(DBIc_LOGPIO(imp_sth), ")\n"); } phs_svp = hv_fetch(imp_sth->all_params_hv, name, name_len, 0); @@ -3294,9 +3385,10 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_st_execute %s (out%d, lob%d)...\n", - oci_stmt_type_name(imp_sth->stmt_type), outparams, imp_sth->has_lobs); - + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_st_execute %s (out%d, lob%d)...\n", + oci_stmt_type_name(imp_sth->stmt_type), outparams, imp_sth->has_lobs); /* Don't attempt execute for nested cursor. It would be meaningless, and Oracle code has been seen to core dump */ @@ -3326,11 +3418,12 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- else if (SvTYPE(sv) == SVt_RV && SvTYPE(SvRV(sv)) == SVt_PVAV) { if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " with %s = [] (len %ld/%ld, indp %d, otype %d, ptype %d)\n", - phs->name, - (long)phs->alen, (long)phs->maxlen, phs->indp, - phs->ftype, (int)SvTYPE(sv)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " with %s = [] (len %ld/%ld, indp %d, otype %d, ptype %d)\n", + phs->name, + (long)phs->alen, (long)phs->maxlen, phs->indp, + phs->ftype, (int)SvTYPE(sv)); av_clear((AV*)SvRV(sv)); } else @@ -3351,12 +3444,15 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- ub2 prev_alen = phs->alen; phs->alen = (SvOK(sv)) ? SvCUR(sv) + phs->alen_incnull : 0+phs->alen_incnull; if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " with %s = '%.*s' (len %ld(%ld)/%ld, indp %d, otype %d, ptype %d)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " with %s = '%.*s' (len %ld(%ld)/%ld, indp %d, " + "otype %d, ptype %d)\n", phs->name, (int)phs->alen, - (phs->indp == -1) ? "" : SvPVX(sv), - (long)phs->alen, (long)prev_alen, (long)phs->maxlen, phs->indp, - phs->ftype, (int)SvTYPE(sv)); + (phs->indp == -1) ? "" : SvPVX(sv), + (long)phs->alen, (long)prev_alen, + (long)phs->maxlen, phs->indp, + phs->ftype, (int)SvTYPE(sv)); } } } @@ -3372,7 +3468,10 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP,"Statement Execute Mode is %d (%s)\n",imp_sth->exe_mode,oci_exe_mode(imp_sth->exe_mode)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Statement Execute Mode is %d (%s)\n", + imp_sth->exe_mode,oci_exe_mode(imp_sth->exe_mode)); OCIStmtExecute_log_stat(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, (ub4)(is_select ? 0: 1), @@ -3402,7 +3501,8 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- if (debug >= 2 || dbd_verbose >= 3 ) { ub2 sqlfncode; OCIAttrGet_stmhp_stat(imp_sth, &sqlfncode, 0, OCI_ATTR_SQLFNCODE, status); - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " dbd_st_execute %s returned (%s, rpc%ld, fn%d, out%d)\n", oci_stmt_type_name(imp_sth->stmt_type), oci_status_name(status), @@ -3427,8 +3527,10 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- phs_t *phs = (phs_t*)(void*)SvPVX(AvARRAY(imp_sth->out_params_av)[i]); SV *sv = phs->sv; if (debug >= 2 || dbd_verbose >= 3 ) { - PerlIO_printf(DBILOGFP, - "dbd_st_execute(): Analyzing inout a parameter '%s of type=%d name=%s'\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_st_execute(): Analyzing inout a parameter '%s" + "of type=%d name=%s'\n", phs->name,phs->ftype,sql_typecode_name(phs->ftype)); } if( phs->ftype == ORA_VARCHAR2_TABLE ){ @@ -3511,7 +3613,9 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat else if (CSFORM_IMPLIES_UTF8(SQLCS_NCHAR)) csform = SQLCS_NCHAR; /* else leave csform == 0 */ if (trace_level || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "do_bind_array_exec() (2): rebinding %s with UTF8 value %s", phs->name, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "do_bind_array_exec() (2): rebinding %s with UTF8 value %s", phs->name, (csform == SQLCS_IMPLICIT) ? "so setting csform=SQLCS_IMPLICIT" : (csform == SQLCS_NCHAR) ? "so setting csform=SQLCS_NCHAR" : "but neither CHAR nor NCHAR are unicode\n"); @@ -3560,16 +3664,19 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat } if (trace_level >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, "do_bind_array_exec(): bind %s <== [array of values] " - "(%s, %s, csid %d->%d->%d, ftype %d (%s), csform %d (%s)->%d (%s), maxlen %lu, maxdata_size %lu)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "do_bind_array_exec(): bind %s <== [array of values] " + "(%s, %s, csid %d->%d->%d, ftype %d (%s), csform %d (%s)->%d (%s)" + ", maxlen %lu, maxdata_size %lu)\n", phs->name, (phs->is_inout) ? "inout" : "in", (utf8 ? "is-utf8" : "not-utf8"), phs->csid_orig, phs->csid, csid, - phs->ftype,sql_typecode_name(phs->ftype), phs->csform,oci_csform_name(phs->csform), csform,oci_csform_name(csform), + phs->ftype, sql_typecode_name(phs->ftype), + phs->csform,oci_csform_name(phs->csform), csform,oci_csform_name(csform), (unsigned long)phs->maxlen, (unsigned long)phs->maxdata_size); - if (csid) { OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, &csid, (ub4) 0, (ub4) OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); @@ -3633,10 +3740,12 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er tuples_utf8_av=newAV(); if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " ora_st_execute_array %s count=%d (%s %s %s)...\n", - oci_stmt_type_name(imp_sth->stmt_type), exe_count, - neatsvpv(tuples,0), neatsvpv(tuples_status,0), - neatsvpv(columns, 0)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " ora_st_execute_array %s count=%d (%s %s %s)...\n", + oci_stmt_type_name(imp_sth->stmt_type), exe_count, + neatsvpv(tuples,0), neatsvpv(tuples_status,0), + neatsvpv(columns, 0)); if (is_select) { croak("ora_st_execute_array(): SELECT statement not supported " @@ -3822,8 +3931,10 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er OCIAttrGet_stmhp_stat(imp_sth, &num_errs, 0, OCI_ATTR_NUM_DML_ERRORS, status); if (debug >= 6 || dbd_verbose >= 6 ) - PerlIO_printf(DBILOGFP, " ora_st_execute_array %d errors in batch.\n", - num_errs); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " ora_st_execute_array %d errors in batch.\n", + num_errs); if(num_errs && tuples_status_av) { OCIError *row_errhp, *tmp_errhp; @@ -3844,8 +3955,10 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er OCIAttrGet_log_stat(row_errhp, OCI_HTYPE_ERROR, &row_off, 0, OCI_ATTR_DML_ROW_OFFSET, imp_sth->errhp, status); if (debug >= 6 || dbd_verbose >= 6 ) - PerlIO_printf(DBILOGFP, " ora_st_execute_array error in row %d.\n", - row_off); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " ora_st_execute_array error in row %d.\n", + row_off); sv_setpv(err_svs[1], ""); err_code = oci_error_get(row_errhp, exe_status, NULL, err_svs[1], debug); sv_setiv(err_svs[0], (IV)err_code); @@ -3908,8 +4021,10 @@ dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, ftype = ftype; /* no unused */ if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " blob_read field %d+1, ftype %d, offset %ld, len %ld, destoffset %ld, retlen %ld\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " blob_read field %d+1, ftype %d, offset %ld, len %ld, " + "destoffset %ld, retlen %ld\n", field, imp_sth->fbh[field].ftype, offset, len, destoffset, (long)retl); SvCUR_set(bufsv, destoffset+retl); @@ -4060,7 +4175,9 @@ ora_free_templob(SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc) if (is_temporary) { if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { - PerlIO_printf(DBILOGFP, " OCILobFreeTemporary %s\n", oci_status_name(status)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobFreeTemporary %s\n", oci_status_name(status)); } OCILobFreeTemporary_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, status); if (status != OCI_SUCCESS) { From 305a954ccf35d9fb8670f94be755909559d87a57 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 17:09:06 +0000 Subject: [PATCH 165/637] more removing DBIS usage some cannot be done without restructuring as some functions don't have a handle git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15222 50811bd7-b8ce-0310-adc1-d9db26280581 --- oci8.c | 335 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 231 insertions(+), 104 deletions(-) diff --git a/oci8.c b/oci8.c index 0de4e4bc..1f380415 100644 --- a/oci8.c +++ b/oci8.c @@ -1067,7 +1067,9 @@ dbd_st_prepare(SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs) OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->stmt_type, 0, OCI_ATTR_STMT_TYPE, status); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_st_prepare'd sql %s ( auto_lob%d, check_sql%d)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_st_prepare'd sql %s ( auto_lob%d, check_sql%d)\n", oci_stmt_type_name(imp_sth->stmt_type), imp_sth->auto_lob, ora_check_sql); @@ -1228,8 +1230,6 @@ dbd_phs_out(dvoid *octxp, OCIBind *bindp, return OCI_CONTINUE; } - - /* -------------------------------------------------------------- Fetch callback fill buffers. Finaly figured out how this fucntion works @@ -1281,7 +1281,7 @@ presist_lob_fetch_cbk(dvoid *octxp, OCIDefine *dfnhp, ub4 iter, dvoid **bufpp, } -/* TAF or Trasarent Application Failoever callback +/* TAF or Transparent Application Failoever callback Works like this. The fuction below is registered on the server, when the server is set up to use it, when an exe is called (not sure about other server round trips) and the server fails tt should get into this cbk error below. @@ -1340,7 +1340,7 @@ reg_taf_callback( imp_dbh_t *imp_dbh) strcpy((char *)cb->function,imp_dbh->taf_function); if (dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, " In reg_taf_callback\n"); + PerlIO_printf(DBIc_LOGPIO(imp_dbh), " In reg_taf_callback\n"); } /* set the context up as a pointer to the taf callback struct*/ @@ -1428,7 +1428,10 @@ fetch_func_varfield(SV *sth, imp_fbh_t *fbh, SV *dest_sv) } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " fetching field %d of %d. LONG value truncated from %lu to %lu.\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " fetching field %d of %d. LONG value truncated from " + "%lu to %lu.\n", fbh->field_num+1, DBIc_NUM_FIELDS(imp_sth), ul_t(datalen), ul_t(bytelen)); datalen = bytelen; @@ -1488,9 +1491,10 @@ fetch_func_rset(SV *sth, imp_fbh_t *fbh, SV *dest_sv) int count; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " fetch_func_rset - allocating handle for cursor nested within %s ...\n", - neatsvpv(sth, 0)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " fetch_func_rset - allocating handle for cursor nested within %s ...\n", + neatsvpv(sth, 0)); ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newRV((SV*)DBIc_MY_H(imp_dbh)))); @@ -1508,9 +1512,10 @@ fetch_func_rset(SV *sth, imp_fbh_t *fbh, SV *dest_sv) PUTBACK; FREETMPS; LEAVE; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " fetch_func_rset - ... allocated %s for nested cursor\n", - neatsvpv(dest_sv, 0)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " fetch_func_rset - ... allocated %s for nested cursor\n", + neatsvpv(dest_sv, 0)); fbh->special = (void *)newSVsv(dest_sv); @@ -1543,7 +1548,10 @@ dbd_rebind_ph_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs) dTHX; if (DBIS->debug >= 6 || dbd_verbose >= 6 ) - PerlIO_printf(DBILOGFP, " dbd_rebind_ph_rset phs->is_inout=%d\n",phs->is_inout); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_rebind_ph_rset phs->is_inout=%d\n", + phs->is_inout); /* Only do this part for inout cursor refs because pp_exec_rset only gets called for all the output params */ if (phs->is_inout) { @@ -1674,7 +1682,9 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " calling OCILobWrite phs->csid=%d phs->csform=%d amtp=%d\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " calling OCILobWrite phs->csid=%d phs->csform=%d amtp=%d\n", phs->csid, phs->csform, amtp ); /* write lob data */ @@ -1754,7 +1764,10 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, /* lab 0, 0, (ub2)0, (ub1)SQLCS_IMPLICIT, status); */ if (dbis->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, BufLen %lu, Got %lu\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, " + "BufLen %lu, Got %lu\n", fbh->field_num+1, oci_status_name(status), ul_t(loblen), ul_t(imp_sth->long_readlen), ul_t(buflen), ul_t(amtp)); if (status != OCI_SUCCESS) { @@ -1774,15 +1787,20 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, assert(amtp == 0); SvGROW(dest_sv, byte_destoffset + 1); if (dbis->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, BufLen %lu, Got %lu\n", - fbh->field_num+1, "SKIPPED", (unsigned long)loblen, - (unsigned long)imp_sth->long_readlen, (unsigned long)buflen, - (unsigned long)amtp); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, " + "BufLen %lu, Got %lu\n", + fbh->field_num+1, "SKIPPED", (unsigned long)loblen, + (unsigned long)imp_sth->long_readlen, (unsigned long)buflen, + (unsigned long)amtp); } if (dbis->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " blob_read field %d, ftype %d, offset %ld, len %lu, destoffset %ld, retlen %lu\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " blob_read field %d, ftype %d, offset %ld, len %lu, " + "destoffset %ld, retlen %lu\n", fbh->field_num+1, ftype, offset, len, destoffset, ul_t(amtp)); SvCUR_set(dest_sv, byte_destoffset+amtp); @@ -1875,9 +1893,10 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " blob_read field %d: ftype %d %s, offset %ld, len %lu." - "LOB csform %d, len %lu, amtp %lu, (destoffset=%ld)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " blob_read field %d: ftype %d %s, offset %ld, len %lu." + "LOB csform %d, len %lu, amtp %lu, (destoffset=%ld)\n", fbh->field_num+1, ftype, type_name, offset, ul_t(len), csform,(unsigned long) (loblen), ul_t(amtp), destoffset); @@ -1890,8 +1909,10 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, 0, 0, (ub2)0 , csform, status); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, BufLen %lu, amtp %lu\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu," + "BufLen %lu, amtp %lu\n", fbh->field_num+1, oci_status_name(status), ul_t(loblen), ul_t(imp_sth->long_readlen), ul_t(buflen), ul_t(amtp)); if (status != OCI_SUCCESS) { @@ -1905,8 +1926,10 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, else { assert(amtp == 0); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, BufLen %lu, Got %lu\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, " + "BufLen %lu, Got %lu\n", fbh->field_num+1, "SKIPPED", ul_t(loblen), ul_t(imp_sth->long_readlen), ul_t(buflen), ul_t(amtp)); } @@ -2052,10 +2075,13 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des if (ftype == ORA_CLOB) strcpy(buf,"characters"); - PerlIO_printf(DBILOGFP, - " OCILobRead %s %s: csform %d (%s), LOBlen %lu(%s), LongReadLen %lu(%s), BufLen %lu(%s), Got %lu(%s)\n", - name, oci_status_name(status), csform,oci_csform_name(csform), ul_t(loblen),buf , - ul_t(imp_sth->long_readlen),buf, ul_t(buflen),buf, ul_t(amtp),buf); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead %s %s: csform %d (%s), LOBlen %lu(%s), " + "LongReadLen %lu(%s), BufLen %lu(%s), Got %lu(%s)\n", + name, oci_status_name(status), csform, oci_csform_name(csform), + ul_t(loblen),buf , + ul_t(imp_sth->long_readlen),buf, ul_t(buflen),buf, ul_t(amtp),buf); } if (ftype == ORA_BFILE) { @@ -2082,8 +2108,10 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des SvCUR(dest_sv) = amtp; *SvEND(dest_sv) = '\0'; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " OCILobRead %s %s: LOBlen %lu, LongReadLen %lu, BufLen %lu, Got %lu\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead %s %s: LOBlen %lu, LongReadLen %lu, " + "BufLen %lu, Got %lu\n", name, "SKIPPED", ul_t(loblen), ul_t(imp_sth->long_readlen), ul_t(buflen), ul_t(amtp)); } @@ -2644,7 +2672,7 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) sword status = OCI_NEED_DATA; if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf(DBILOGFP, "in fetch_get_piece \n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), "in fetch_get_piece \n"); } while (status == OCI_NEED_DATA){ @@ -2701,10 +2729,18 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) if (DBIS->debug >= 6 || dbd_verbose >= 6 ){ if (fb_ary->piece_count==1){ - PerlIO_printf(DBILOGFP," Fetch persistent lob of %d (Char/Bytes) with Polling in 1 piece\n",actual_bufl); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Fetch persistent lob of %d (Char/Bytes) with Polling " + "in 1 piece\n", + actual_bufl); } else { - PerlIO_printf(DBILOGFP," Fetch persistent lob of %d (Char/Bytes) with Polling in %d piece(s) of %d (Char/Bytes) and one piece of %d (Char/Bytes)\n",actual_bufl,fb_ary->piece_count,fbh->piece_size,buflen); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Fetch persistent lob of %d (Char/Bytes) with Polling " + "in %d piece(s) of %d (Char/Bytes) and one piece of %d (Char/Bytes)\n", + actual_bufl,fb_ary->piece_count,fbh->piece_size,buflen); } } sv_setpvn(dest_sv, (char*)fb_ary->cb_abuf,(STRLEN)actual_bufl); @@ -2821,10 +2857,14 @@ void rs_array_init(imp_sth_t *imp_sth) imp_sth->rs_array_status =OCI_SUCCESS; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " rs_array_init:imp_sth->rs_array_size=%d, rs_array_idx=%d, prefetch_rows=%d, rs_array_status=%s\n",imp_sth->rs_array_size,imp_sth->rs_array_idx,imp_sth->prefetch_rows,oci_status_name(imp_sth->rs_array_status)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " rs_array_init:imp_sth->rs_array_size=%d, rs_array_idx=%d, " + "prefetch_rows=%d, rs_array_status=%s\n", + imp_sth->rs_array_size, imp_sth->rs_array_idx, imp_sth->prefetch_rows, + oci_status_name(imp_sth->rs_array_status)); } - static int /* --- Setup the row cache for this sth --- */ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, int has_longs) { @@ -2949,11 +2989,14 @@ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, if (DBIS->debug >= 3 || dbd_verbose >= 3 || oci_warn) /*will also display if oci_warn is on*/ - PerlIO_printf(DBILOGFP, - " cache settings DB Handle RowCacheSize=%d,Statement Handle RowCacheSize=%d, OCI_ATTR_PREFETCH_ROWS=%lu, OCI_ATTR_PREFETCH_MEMORY=%lu, Rows per Fetch=%d, Multiple Row Fetch=%s\n", - imp_dbh->RowCacheSize,imp_sth->RowCacheSize,(unsigned long) (prefetch_rows), (unsigned long) (prefetch_mem),cache_rows,(imp_sth->row_cache_off)?"Off":"On"); - - + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " cache settings DB Handle RowCacheSize=%d,Statement Handle " + "RowCacheSize=%d, OCI_ATTR_PREFETCH_ROWS=%lu, " + "OCI_ATTR_PREFETCH_MEMORY=%lu, Rows per Fetch=%d, Multiple Row Fetch=%s\n", + imp_dbh->RowCacheSize, imp_sth->RowCacheSize, + (unsigned long) (prefetch_rows), (unsigned long) (prefetch_mem), + cache_rows,(imp_sth->row_cache_off)?"Off":"On"); return num_errors; } @@ -2969,7 +3012,9 @@ describe_obj(SV *sth,imp_sth_t *imp_sth,OCIParam *parm,fbh_obj_t *obj,int level OCIRef *type_ref; if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, "At level=%d in description an embedded object \n",level); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "At level=%d in description an embedded object \n",level); } /*Describe the field (OCIParm) we know it is a object or a collection */ @@ -3046,14 +3091,20 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { } if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { - PerlIO_printf(DBILOGFP, "Getting the properties of object named =%s at level %d typecode=%d\n",obj->type_name,level,obj->typecode); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Getting the properties of object named =%s at level %d typecode=%d\n", + obj->type_name,level,obj->typecode); } if (obj->typecode == OCI_TYPECODE_OBJECT || obj->typecode == OCI_TYPECODE_OPAQUE){ OCIParam *list_attr= (OCIParam *) 0; ub2 pos; if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { - PerlIO_printf(DBILOGFP, "Object named =%s at level %d is an Object\n",obj->type_name,level); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Object named =%s at level %d is an Object\n", + obj->type_name,level); } OCIAttrGet_parmdp(imp_sth, obj->parmdp, (dvoid *)&obj->obj_ref, 0, OCI_ATTR_REF_TDO, status); @@ -3125,7 +3176,10 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { } if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { - PerlIO_printf(DBILOGFP, "Getting property #%d, named=%s and its typecode is %d \n",pos,fld->type_name,fld->typecode); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Getting property #%d, named=%s and its typecode is %d \n", + pos, fld->type_name, fld->typecode); } if (fld->typecode == OCI_TYPECODE_OBJECT || fld->typecode == OCI_TYPECODE_VARRAY || fld->typecode == OCI_TYPECODE_TABLE || fld->typecode == OCI_TYPECODE_NAMEDCOLLECTION){ @@ -3139,7 +3193,10 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { /*well this is an embedded table or varray of some form so find out what is in it*/ if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { - PerlIO_printf(DBILOGFP, "Object named =%s at level %d is an Varray or Table\n",obj->type_name,level); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Object named =%s at level %d is an Varray or Table\n", + obj->type_name,level); } OCIAttrGet_parmdp(imp_sth, obj->parmdp, (dvoid *)&obj->col_typecode, 0, OCI_ATTR_COLLECTION_TYPECODE, status); @@ -3184,28 +3241,40 @@ dump_struct(imp_sth_t *imp_sth,fbh_obj_t *obj,int level){ int i; /*dumps the contents of the current fbh->obj*/ - PerlIO_printf(DBILOGFP, " level=%d type_name = %s\n",level,obj->type_name); - PerlIO_printf(DBILOGFP, " type_namel = %u\n",obj->type_namel); - PerlIO_printf(DBILOGFP, " parmdp = %p\n",obj->parmdp); - PerlIO_printf(DBILOGFP, " parmap = %p\n",obj->parmap); - PerlIO_printf(DBILOGFP, " tdo = %p\n",obj->tdo); - PerlIO_printf(DBILOGFP, " typecode = %s\n",oci_typecode_name(obj->typecode)); - PerlIO_printf(DBILOGFP, " col_typecode = %d\n",obj->col_typecode); - PerlIO_printf(DBILOGFP, " element_typecode = %s\n",oci_typecode_name(obj->element_typecode)); - PerlIO_printf(DBILOGFP, " obj_ref = %p\n",obj->obj_ref); - PerlIO_printf(DBILOGFP, " obj_value = %p\n",obj->obj_value); - PerlIO_printf(DBILOGFP, " obj_type = %p\n",obj->obj_type); - PerlIO_printf(DBILOGFP, " is_final_type = %u\n",obj->is_final_type); - PerlIO_printf(DBILOGFP, " field_count = %d\n",obj->field_count); - PerlIO_printf(DBILOGFP, " fields = %p\n",obj->fields); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " level=%d type_name = %s\n",level,obj->type_name); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " type_namel = %u\n",obj->type_namel); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " parmdp = %p\n",obj->parmdp); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " parmap = %p\n",obj->parmap); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " tdo = %p\n",obj->tdo); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " typecode = %s\n",oci_typecode_name(obj->typecode)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " col_typecode = %d\n",obj->col_typecode); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " element_typecode = %s\n",oci_typecode_name(obj->element_typecode)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " obj_ref = %p\n",obj->obj_ref); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " obj_value = %p\n",obj->obj_value); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " obj_type = %p\n",obj->obj_type); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " is_final_type = %u\n",obj->is_final_type); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " field_count = %d\n",obj->field_count); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " fields = %p\n",obj->fields); for (i = 0; i < obj->field_count;i++){ fbh_obj_t *fld = &obj->fields[i]; - PerlIO_printf(DBILOGFP, " \n--->sub objects\n "); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " \n--->sub objects\n "); dump_struct(imp_sth,fld,level+1); } - PerlIO_printf(DBILOGFP, " \n--->done %s\n ",obj->type_name); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " \n--->done %s\n ",obj->type_name); return 1; } @@ -3247,14 +3316,18 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (imp_sth->stmt_type != OCI_STMT_SELECT) { /* XXX DISABLED, see num_fields test below */ if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_describe skipped for %s\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_describe skipped for %s\n", oci_stmt_type_name(imp_sth->stmt_type)); /* imp_sth memory was cleared when created so no setup required here */ return 1; } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_describe %s (%s, lb %lu)...\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_describe %s (%s, lb %lu)...\n", oci_stmt_type_name(imp_sth->stmt_type), DBIc_ACTIVE(imp_sth) ? "implicit" : "EXPLICIT", (unsigned long)long_readlen); @@ -3278,8 +3351,10 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) } if (num_fields == 0) { if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_describe skipped for %s (no fields returned)\n", - oci_stmt_type_name(imp_sth->stmt_type)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_describe skipped for %s (no fields returned)\n", + oci_stmt_type_name(imp_sth->stmt_type)); /* imp_sth memory was cleared when created so no setup required here */ return 1; } @@ -3339,7 +3414,10 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->ftype = 5; /* default: return as null terminated string */ if (DBIS->debug >= 4 || dbd_verbose >= 4 ) - PerlIO_printf(DBILOGFP, "Describe col #%d type=%d(%s)\n",i,fbh->dbtype,sql_typecode_name(fbh->dbtype)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Describe col #%d type=%d(%s)\n", + i,fbh->dbtype,sql_typecode_name(fbh->dbtype)); switch (fbh->dbtype) { /* the simple types */ @@ -3598,18 +3676,22 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->disize = fbh->dbsize; p = "Field %d has an Oracle type (%d) which is not explicitly supported%s"; if (DBIS->debug >= 1 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, p, i, fbh->dbtype, "\n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), p, i, fbh->dbtype, "\n"); if (PL_dowarn) warn(p, i, fbh->dbtype, ""); break; } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, name %s\n" - " : dbsize %d, char_used %d, char_size %d, csid %d, csform %d(%s), disize %d\n", - i, fbh->dbtype, sql_typecode_name(fbh->dbtype),fbh->scale, fbh->prec, fbh->nullok, fbh->name, - fbh->dbsize, fbh->len_char_used, fbh->len_char_size, fbh->csid,fbh->csform,oci_csform_name(fbh->csform), fbh->disize); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, " + "name %s\n : dbsize %d, char_used %d, char_size %d, " + "csid %d, csform %d(%s), disize %d\n", + i, fbh->dbtype, sql_typecode_name(fbh->dbtype), fbh->scale, + fbh->prec, fbh->nullok, fbh->name, fbh->dbsize, + fbh->len_char_used, fbh->len_char_size, + fbh->csid,fbh->csform,oci_csform_name(fbh->csform), fbh->disize); if (fbh->ftype == 5) /* XXX need to handle wide chars somehow */ fbh->disize += 1; /* allow for null terminator */ @@ -3689,7 +3771,10 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (fbh->ftype == 108) { /* Embedded object bind it differently*/ if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ - PerlIO_printf(DBILOGFP,"Field #%d is a object or colection of some sort. Using OCIDefineObject and or OCIObjectPin \n",i); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Field #%d is a object or colection of some sort. " + "Using OCIDefineObject and or OCIObjectPin \n",i); } Newz(1, fbh->obj, 1, fbh_obj_t); fbh->obj->typecode=fbh->dbtype; @@ -3719,7 +3804,10 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if ( (fbh->dbtype == 1) && fbh->csform ) { /* csform may be 0 when talking to Oracle 8.0 database*/ if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " calling OCIAttrSet OCI_ATTR_CHARSET_FORM with csform=%d (%s)\n", fbh->csform,oci_csform_name(fbh->csform) ); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " calling OCIAttrSet OCI_ATTR_CHARSET_FORM with csform=%d (%s)\n", + fbh->csform,oci_csform_name(fbh->csform) ); OCIAttrSet_log_stat( fbh->defnp, (ub4) OCI_HTYPE_DEFINE, (dvoid *) &fbh->csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status ); if (status != OCI_SUCCESS) { @@ -3732,9 +3820,11 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " dbd_describe'd %d columns (row bytes: %d max, %d est avg, cache: %d)\n", - (int)num_fields, imp_sth->t_dbsize, imp_sth->est_width, imp_sth->prefetch_rows); + (int)num_fields, imp_sth->t_dbsize, imp_sth->est_width, + imp_sth->prefetch_rows); return (num_errors>0) ? 0 : 1; } @@ -3775,7 +3865,9 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ } else { if (DBIS->debug >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, " dbd_st_fetch %d fields...\n", DBIc_NUM_FIELDS(imp_sth)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_st_fetch %d fields...\n", DBIc_NUM_FIELDS(imp_sth)); } if (imp_sth->fetch_orient != OCI_DEFAULT) { @@ -3783,8 +3875,12 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ croak ("attempt to use a scrollable cursor without first setting ora_exe_mode to OCI_STMT_SCROLLABLE_READONLY\n") ; if (DBIS->debug >= 4 || dbd_verbose >= 4 ) - PerlIO_printf(DBILOGFP," Scrolling Fetch, postion before fetch=%d, Orientation = %s , Fetchoffset =%d\n", - imp_sth->fetch_position,oci_fetch_options(imp_sth->fetch_orient),imp_sth->fetch_offset); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Scrolling Fetch, postion before fetch=%d, " + "Orientation = %s , Fetchoffset =%d\n", + imp_sth->fetch_position, oci_fetch_options(imp_sth->fetch_orient), + imp_sth->fetch_offset); OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp,1, imp_sth->fetch_orient,imp_sth->fetch_offset, status); /*this will work without a round trip so might as well open it up for all statments handles*/ @@ -3792,8 +3888,10 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->fetch_position, 0, OCI_ATTR_CURRENT_POSITION, status); if (DBIS->debug >= 4 || dbd_verbose >= 4 ) - PerlIO_printf(DBILOGFP," Scrolling Fetch, postion after fetch=%d\n",imp_sth->fetch_position); - + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Scrolling Fetch, postion after fetch=%d\n", + imp_sth->fetch_position); } else { @@ -3808,7 +3906,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_sth->rs_array_idx++; if (imp_sth->rs_array_num_rows<=imp_sth->rs_array_idx && (imp_sth->rs_array_status==OCI_SUCCESS || imp_sth->rs_array_status==OCI_SUCCESS_WITH_INFO)) { -/* PerlIO_printf(DBILOGFP, " dbd_st_fetch fields...b\n");*/ +/* PerlIO_printf(DBIc_LOGPIO(imp_sth), " dbd_st_fetch fields...b\n");*/ OCIStmtFetch_log_stat(imp_sth->stmhp,imp_sth->errhp,imp_sth->rs_array_size,(ub2)OCI_FETCH_NEXT,OCI_DEFAULT,status); @@ -3823,7 +3921,9 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_sth->RowsInCache =imp_sth->rs_array_size; if (DBIS->debug >= 4 || dbd_verbose >= 4 || oci_warn) - PerlIO_printf(DBILOGFP,"...Fetched %d rows\n",imp_sth->rs_array_num_rows); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "...Fetched %d rows\n",imp_sth->rs_array_num_rows); } imp_dbh->RowsInCache--; @@ -3847,7 +3947,10 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ dTHR; /* for DBIc_ACTIVE_off */ DBIc_ACTIVE_off(imp_sth); /* eg finish */ if (DBIS->debug >= 3 || dbd_verbose >= 3 || oci_warn) - PerlIO_printf(DBILOGFP, " dbd_st_fetch no-more-data, fetch count=%d\n",imp_sth->rs_fetch_count-1); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_st_fetch no-more-data, fetch count=%d\n", + imp_sth->rs_fetch_count-1); return Nullav; } if (status != OCI_SUCCESS_WITH_INFO) { @@ -3868,7 +3971,10 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ av = DBIS->get_fbav(imp_sth); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { - PerlIO_printf(DBILOGFP, " dbd_st_fetched %d fields with status of %d(%s)\n", num_fields,status, oci_status_name(status)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_st_fetched %d fields with status of %d(%s)\n", + num_fields,status, oci_status_name(status)); } ChopBlanks = DBIc_has(imp_sth, DBIcf_ChopBlanks); @@ -3883,7 +3989,9 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf(DBILOGFP, " field #%d with rc=%d(%s)\n",i+1,rc,oci_col_return_codes(rc)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " field #%d with rc=%d(%s)\n",i+1,rc,oci_col_return_codes(rc)); } if (rc == 1406 /* field was truncated */ @@ -4003,7 +4111,9 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ } if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ - PerlIO_printf(DBILOGFP, "\n %p (field=%d): %s\n", av, i,neatsvpv(sv,10)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "\n %p (field=%d): %s\n", av, i,neatsvpv(sv,10)); } } return (err) ? Nullav : av; @@ -4243,7 +4353,10 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) tablename=new_tablename; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " lob refetch using a synonym named=%s for %s \n", syn_name,tablename); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " lob refetch using a synonym named=%s for %s \n", + syn_name,tablename); } @@ -4279,7 +4392,10 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " lob refetch from table %s, %d columns:\n", tablename, numcols); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " lob refetch from table %s, %d columns:\n", + tablename, numcols); for (i = 1; i <= (long)numcols; i++) { ub2 col_dbtype; @@ -4300,7 +4416,9 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) break; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " lob refetch table col %d: '%.*s' otype %d\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " lob refetch table col %d: '%.*s' otype %d\n", (int)i, (int)col_name_len,col_name, col_dbtype); if (col_dbtype != SQLT_CLOB && col_dbtype != SQLT_BLOB) @@ -4381,9 +4499,11 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) if (phs->ftype != SvIV(sv_other)) continue; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " both %s and %s have type %d - ambiguous\n", - neatsvpv(sv,0), neatsvpv(sv_other,0), (int)SvIV(sv_other)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " both %s and %s have type %d - ambiguous\n", + neatsvpv(sv,0), neatsvpv(sv_other,0), + (int)SvIV(sv_other)); Safefree(lr); sv_free((SV*)lob_cols_hv); return oci_error(sth, errhp, OCI_ERROR, @@ -4398,8 +4518,9 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) sv_catpv(sql_select, sql_field); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " lob refetch %s param: otype %d, matched field '%s' %s(%s)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " lob refetch %s param: otype %d, matched field '%s' %s(%s)\n", phs->name, phs->ftype, p, (phs->ora_field) ? "by name " : "by type ", sql_field); (void)hv_delete(lob_cols_hv, p, i, G_DISCARD); @@ -4417,7 +4538,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) if (!matched) { ++unmatched_params; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " lob refetch %s param: otype %d, UNMATCHED\n", phs->name, phs->ftype); } @@ -4434,7 +4556,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) sv_catpv(sql_select, tablename); sv_catpv(sql_select, " where rowid = :rid for update"); /* get row with lock */ if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " lob refetch sql: %s\n", SvPVX(sql_select)); lr->stmthp = NULL; lr->bindhp = NULL; @@ -4474,7 +4597,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) phs = (phs_t*)(void*)SvPVX(*phs_svp); fbh->special = phs; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " lob refetch %d for '%s' param: ftype %d setup\n", (int)i+1,fbh->name, fbh->dbtype); fbh->fb_ary = fb_ary_alloc(fbh->disize, 1); @@ -4598,7 +4722,9 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " calling OCILobWrite fbh->csid=%d fbh->csform=%d amtp=%d\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " calling OCILobWrite fbh->csid=%d fbh->csform=%d amtp=%d\n", fbh->csid, fbh->csform, amtp ); OCILobWrite_log_stat(imp_sth->svchp, errhp, @@ -4619,7 +4745,8 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " lob refetch %d for '%s' param: ftype %d, len %ld: %s %s\n", i+1,fbh->name, fbh->dbtype, ul_t(amtp), (rc==1405 ? "NULL" : (amtp > 0) ? "LobWrite" : "LobTrim"), oci_status_name(status)); From 9877cff2de5f21915aab7e9ee0e210958e254783 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 17:09:06 +0000 Subject: [PATCH 166/637] more removing DBIS usage some cannot be done without restructuring as some functions don't have a handle git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15222 50811bd7-b8ce-0310-adc1-d9db26280581 --- oci8.c | 335 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 231 insertions(+), 104 deletions(-) diff --git a/oci8.c b/oci8.c index 0de4e4bc..1f380415 100644 --- a/oci8.c +++ b/oci8.c @@ -1067,7 +1067,9 @@ dbd_st_prepare(SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs) OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->stmt_type, 0, OCI_ATTR_STMT_TYPE, status); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_st_prepare'd sql %s ( auto_lob%d, check_sql%d)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_st_prepare'd sql %s ( auto_lob%d, check_sql%d)\n", oci_stmt_type_name(imp_sth->stmt_type), imp_sth->auto_lob, ora_check_sql); @@ -1228,8 +1230,6 @@ dbd_phs_out(dvoid *octxp, OCIBind *bindp, return OCI_CONTINUE; } - - /* -------------------------------------------------------------- Fetch callback fill buffers. Finaly figured out how this fucntion works @@ -1281,7 +1281,7 @@ presist_lob_fetch_cbk(dvoid *octxp, OCIDefine *dfnhp, ub4 iter, dvoid **bufpp, } -/* TAF or Trasarent Application Failoever callback +/* TAF or Transparent Application Failoever callback Works like this. The fuction below is registered on the server, when the server is set up to use it, when an exe is called (not sure about other server round trips) and the server fails tt should get into this cbk error below. @@ -1340,7 +1340,7 @@ reg_taf_callback( imp_dbh_t *imp_dbh) strcpy((char *)cb->function,imp_dbh->taf_function); if (dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, " In reg_taf_callback\n"); + PerlIO_printf(DBIc_LOGPIO(imp_dbh), " In reg_taf_callback\n"); } /* set the context up as a pointer to the taf callback struct*/ @@ -1428,7 +1428,10 @@ fetch_func_varfield(SV *sth, imp_fbh_t *fbh, SV *dest_sv) } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " fetching field %d of %d. LONG value truncated from %lu to %lu.\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " fetching field %d of %d. LONG value truncated from " + "%lu to %lu.\n", fbh->field_num+1, DBIc_NUM_FIELDS(imp_sth), ul_t(datalen), ul_t(bytelen)); datalen = bytelen; @@ -1488,9 +1491,10 @@ fetch_func_rset(SV *sth, imp_fbh_t *fbh, SV *dest_sv) int count; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " fetch_func_rset - allocating handle for cursor nested within %s ...\n", - neatsvpv(sth, 0)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " fetch_func_rset - allocating handle for cursor nested within %s ...\n", + neatsvpv(sth, 0)); ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newRV((SV*)DBIc_MY_H(imp_dbh)))); @@ -1508,9 +1512,10 @@ fetch_func_rset(SV *sth, imp_fbh_t *fbh, SV *dest_sv) PUTBACK; FREETMPS; LEAVE; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " fetch_func_rset - ... allocated %s for nested cursor\n", - neatsvpv(dest_sv, 0)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " fetch_func_rset - ... allocated %s for nested cursor\n", + neatsvpv(dest_sv, 0)); fbh->special = (void *)newSVsv(dest_sv); @@ -1543,7 +1548,10 @@ dbd_rebind_ph_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs) dTHX; if (DBIS->debug >= 6 || dbd_verbose >= 6 ) - PerlIO_printf(DBILOGFP, " dbd_rebind_ph_rset phs->is_inout=%d\n",phs->is_inout); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_rebind_ph_rset phs->is_inout=%d\n", + phs->is_inout); /* Only do this part for inout cursor refs because pp_exec_rset only gets called for all the output params */ if (phs->is_inout) { @@ -1674,7 +1682,9 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " calling OCILobWrite phs->csid=%d phs->csform=%d amtp=%d\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " calling OCILobWrite phs->csid=%d phs->csform=%d amtp=%d\n", phs->csid, phs->csform, amtp ); /* write lob data */ @@ -1754,7 +1764,10 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, /* lab 0, 0, (ub2)0, (ub1)SQLCS_IMPLICIT, status); */ if (dbis->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, BufLen %lu, Got %lu\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, " + "BufLen %lu, Got %lu\n", fbh->field_num+1, oci_status_name(status), ul_t(loblen), ul_t(imp_sth->long_readlen), ul_t(buflen), ul_t(amtp)); if (status != OCI_SUCCESS) { @@ -1774,15 +1787,20 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, assert(amtp == 0); SvGROW(dest_sv, byte_destoffset + 1); if (dbis->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, BufLen %lu, Got %lu\n", - fbh->field_num+1, "SKIPPED", (unsigned long)loblen, - (unsigned long)imp_sth->long_readlen, (unsigned long)buflen, - (unsigned long)amtp); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, " + "BufLen %lu, Got %lu\n", + fbh->field_num+1, "SKIPPED", (unsigned long)loblen, + (unsigned long)imp_sth->long_readlen, (unsigned long)buflen, + (unsigned long)amtp); } if (dbis->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " blob_read field %d, ftype %d, offset %ld, len %lu, destoffset %ld, retlen %lu\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " blob_read field %d, ftype %d, offset %ld, len %lu, " + "destoffset %ld, retlen %lu\n", fbh->field_num+1, ftype, offset, len, destoffset, ul_t(amtp)); SvCUR_set(dest_sv, byte_destoffset+amtp); @@ -1875,9 +1893,10 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " blob_read field %d: ftype %d %s, offset %ld, len %lu." - "LOB csform %d, len %lu, amtp %lu, (destoffset=%ld)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " blob_read field %d: ftype %d %s, offset %ld, len %lu." + "LOB csform %d, len %lu, amtp %lu, (destoffset=%ld)\n", fbh->field_num+1, ftype, type_name, offset, ul_t(len), csform,(unsigned long) (loblen), ul_t(amtp), destoffset); @@ -1890,8 +1909,10 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, 0, 0, (ub2)0 , csform, status); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, BufLen %lu, amtp %lu\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu," + "BufLen %lu, amtp %lu\n", fbh->field_num+1, oci_status_name(status), ul_t(loblen), ul_t(imp_sth->long_readlen), ul_t(buflen), ul_t(amtp)); if (status != OCI_SUCCESS) { @@ -1905,8 +1926,10 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, else { assert(amtp == 0); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, BufLen %lu, Got %lu\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, " + "BufLen %lu, Got %lu\n", fbh->field_num+1, "SKIPPED", ul_t(loblen), ul_t(imp_sth->long_readlen), ul_t(buflen), ul_t(amtp)); } @@ -2052,10 +2075,13 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des if (ftype == ORA_CLOB) strcpy(buf,"characters"); - PerlIO_printf(DBILOGFP, - " OCILobRead %s %s: csform %d (%s), LOBlen %lu(%s), LongReadLen %lu(%s), BufLen %lu(%s), Got %lu(%s)\n", - name, oci_status_name(status), csform,oci_csform_name(csform), ul_t(loblen),buf , - ul_t(imp_sth->long_readlen),buf, ul_t(buflen),buf, ul_t(amtp),buf); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead %s %s: csform %d (%s), LOBlen %lu(%s), " + "LongReadLen %lu(%s), BufLen %lu(%s), Got %lu(%s)\n", + name, oci_status_name(status), csform, oci_csform_name(csform), + ul_t(loblen),buf , + ul_t(imp_sth->long_readlen),buf, ul_t(buflen),buf, ul_t(amtp),buf); } if (ftype == ORA_BFILE) { @@ -2082,8 +2108,10 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des SvCUR(dest_sv) = amtp; *SvEND(dest_sv) = '\0'; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " OCILobRead %s %s: LOBlen %lu, LongReadLen %lu, BufLen %lu, Got %lu\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " OCILobRead %s %s: LOBlen %lu, LongReadLen %lu, " + "BufLen %lu, Got %lu\n", name, "SKIPPED", ul_t(loblen), ul_t(imp_sth->long_readlen), ul_t(buflen), ul_t(amtp)); } @@ -2644,7 +2672,7 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) sword status = OCI_NEED_DATA; if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf(DBILOGFP, "in fetch_get_piece \n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), "in fetch_get_piece \n"); } while (status == OCI_NEED_DATA){ @@ -2701,10 +2729,18 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) if (DBIS->debug >= 6 || dbd_verbose >= 6 ){ if (fb_ary->piece_count==1){ - PerlIO_printf(DBILOGFP," Fetch persistent lob of %d (Char/Bytes) with Polling in 1 piece\n",actual_bufl); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Fetch persistent lob of %d (Char/Bytes) with Polling " + "in 1 piece\n", + actual_bufl); } else { - PerlIO_printf(DBILOGFP," Fetch persistent lob of %d (Char/Bytes) with Polling in %d piece(s) of %d (Char/Bytes) and one piece of %d (Char/Bytes)\n",actual_bufl,fb_ary->piece_count,fbh->piece_size,buflen); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Fetch persistent lob of %d (Char/Bytes) with Polling " + "in %d piece(s) of %d (Char/Bytes) and one piece of %d (Char/Bytes)\n", + actual_bufl,fb_ary->piece_count,fbh->piece_size,buflen); } } sv_setpvn(dest_sv, (char*)fb_ary->cb_abuf,(STRLEN)actual_bufl); @@ -2821,10 +2857,14 @@ void rs_array_init(imp_sth_t *imp_sth) imp_sth->rs_array_status =OCI_SUCCESS; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " rs_array_init:imp_sth->rs_array_size=%d, rs_array_idx=%d, prefetch_rows=%d, rs_array_status=%s\n",imp_sth->rs_array_size,imp_sth->rs_array_idx,imp_sth->prefetch_rows,oci_status_name(imp_sth->rs_array_status)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " rs_array_init:imp_sth->rs_array_size=%d, rs_array_idx=%d, " + "prefetch_rows=%d, rs_array_status=%s\n", + imp_sth->rs_array_size, imp_sth->rs_array_idx, imp_sth->prefetch_rows, + oci_status_name(imp_sth->rs_array_status)); } - static int /* --- Setup the row cache for this sth --- */ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, int has_longs) { @@ -2949,11 +2989,14 @@ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, if (DBIS->debug >= 3 || dbd_verbose >= 3 || oci_warn) /*will also display if oci_warn is on*/ - PerlIO_printf(DBILOGFP, - " cache settings DB Handle RowCacheSize=%d,Statement Handle RowCacheSize=%d, OCI_ATTR_PREFETCH_ROWS=%lu, OCI_ATTR_PREFETCH_MEMORY=%lu, Rows per Fetch=%d, Multiple Row Fetch=%s\n", - imp_dbh->RowCacheSize,imp_sth->RowCacheSize,(unsigned long) (prefetch_rows), (unsigned long) (prefetch_mem),cache_rows,(imp_sth->row_cache_off)?"Off":"On"); - - + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " cache settings DB Handle RowCacheSize=%d,Statement Handle " + "RowCacheSize=%d, OCI_ATTR_PREFETCH_ROWS=%lu, " + "OCI_ATTR_PREFETCH_MEMORY=%lu, Rows per Fetch=%d, Multiple Row Fetch=%s\n", + imp_dbh->RowCacheSize, imp_sth->RowCacheSize, + (unsigned long) (prefetch_rows), (unsigned long) (prefetch_mem), + cache_rows,(imp_sth->row_cache_off)?"Off":"On"); return num_errors; } @@ -2969,7 +3012,9 @@ describe_obj(SV *sth,imp_sth_t *imp_sth,OCIParam *parm,fbh_obj_t *obj,int level OCIRef *type_ref; if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, "At level=%d in description an embedded object \n",level); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "At level=%d in description an embedded object \n",level); } /*Describe the field (OCIParm) we know it is a object or a collection */ @@ -3046,14 +3091,20 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { } if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { - PerlIO_printf(DBILOGFP, "Getting the properties of object named =%s at level %d typecode=%d\n",obj->type_name,level,obj->typecode); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Getting the properties of object named =%s at level %d typecode=%d\n", + obj->type_name,level,obj->typecode); } if (obj->typecode == OCI_TYPECODE_OBJECT || obj->typecode == OCI_TYPECODE_OPAQUE){ OCIParam *list_attr= (OCIParam *) 0; ub2 pos; if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { - PerlIO_printf(DBILOGFP, "Object named =%s at level %d is an Object\n",obj->type_name,level); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Object named =%s at level %d is an Object\n", + obj->type_name,level); } OCIAttrGet_parmdp(imp_sth, obj->parmdp, (dvoid *)&obj->obj_ref, 0, OCI_ATTR_REF_TDO, status); @@ -3125,7 +3176,10 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { } if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { - PerlIO_printf(DBILOGFP, "Getting property #%d, named=%s and its typecode is %d \n",pos,fld->type_name,fld->typecode); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Getting property #%d, named=%s and its typecode is %d \n", + pos, fld->type_name, fld->typecode); } if (fld->typecode == OCI_TYPECODE_OBJECT || fld->typecode == OCI_TYPECODE_VARRAY || fld->typecode == OCI_TYPECODE_TABLE || fld->typecode == OCI_TYPECODE_NAMEDCOLLECTION){ @@ -3139,7 +3193,10 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { /*well this is an embedded table or varray of some form so find out what is in it*/ if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { - PerlIO_printf(DBILOGFP, "Object named =%s at level %d is an Varray or Table\n",obj->type_name,level); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Object named =%s at level %d is an Varray or Table\n", + obj->type_name,level); } OCIAttrGet_parmdp(imp_sth, obj->parmdp, (dvoid *)&obj->col_typecode, 0, OCI_ATTR_COLLECTION_TYPECODE, status); @@ -3184,28 +3241,40 @@ dump_struct(imp_sth_t *imp_sth,fbh_obj_t *obj,int level){ int i; /*dumps the contents of the current fbh->obj*/ - PerlIO_printf(DBILOGFP, " level=%d type_name = %s\n",level,obj->type_name); - PerlIO_printf(DBILOGFP, " type_namel = %u\n",obj->type_namel); - PerlIO_printf(DBILOGFP, " parmdp = %p\n",obj->parmdp); - PerlIO_printf(DBILOGFP, " parmap = %p\n",obj->parmap); - PerlIO_printf(DBILOGFP, " tdo = %p\n",obj->tdo); - PerlIO_printf(DBILOGFP, " typecode = %s\n",oci_typecode_name(obj->typecode)); - PerlIO_printf(DBILOGFP, " col_typecode = %d\n",obj->col_typecode); - PerlIO_printf(DBILOGFP, " element_typecode = %s\n",oci_typecode_name(obj->element_typecode)); - PerlIO_printf(DBILOGFP, " obj_ref = %p\n",obj->obj_ref); - PerlIO_printf(DBILOGFP, " obj_value = %p\n",obj->obj_value); - PerlIO_printf(DBILOGFP, " obj_type = %p\n",obj->obj_type); - PerlIO_printf(DBILOGFP, " is_final_type = %u\n",obj->is_final_type); - PerlIO_printf(DBILOGFP, " field_count = %d\n",obj->field_count); - PerlIO_printf(DBILOGFP, " fields = %p\n",obj->fields); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " level=%d type_name = %s\n",level,obj->type_name); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " type_namel = %u\n",obj->type_namel); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " parmdp = %p\n",obj->parmdp); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " parmap = %p\n",obj->parmap); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " tdo = %p\n",obj->tdo); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " typecode = %s\n",oci_typecode_name(obj->typecode)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " col_typecode = %d\n",obj->col_typecode); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " element_typecode = %s\n",oci_typecode_name(obj->element_typecode)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " obj_ref = %p\n",obj->obj_ref); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " obj_value = %p\n",obj->obj_value); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " obj_type = %p\n",obj->obj_type); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " is_final_type = %u\n",obj->is_final_type); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " field_count = %d\n",obj->field_count); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " fields = %p\n",obj->fields); for (i = 0; i < obj->field_count;i++){ fbh_obj_t *fld = &obj->fields[i]; - PerlIO_printf(DBILOGFP, " \n--->sub objects\n "); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " \n--->sub objects\n "); dump_struct(imp_sth,fld,level+1); } - PerlIO_printf(DBILOGFP, " \n--->done %s\n ",obj->type_name); + PerlIO_printf(DBIc_LOGPIO(imp_sth), " \n--->done %s\n ",obj->type_name); return 1; } @@ -3247,14 +3316,18 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (imp_sth->stmt_type != OCI_STMT_SELECT) { /* XXX DISABLED, see num_fields test below */ if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_describe skipped for %s\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_describe skipped for %s\n", oci_stmt_type_name(imp_sth->stmt_type)); /* imp_sth memory was cleared when created so no setup required here */ return 1; } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_describe %s (%s, lb %lu)...\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_describe %s (%s, lb %lu)...\n", oci_stmt_type_name(imp_sth->stmt_type), DBIc_ACTIVE(imp_sth) ? "implicit" : "EXPLICIT", (unsigned long)long_readlen); @@ -3278,8 +3351,10 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) } if (num_fields == 0) { if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_describe skipped for %s (no fields returned)\n", - oci_stmt_type_name(imp_sth->stmt_type)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_describe skipped for %s (no fields returned)\n", + oci_stmt_type_name(imp_sth->stmt_type)); /* imp_sth memory was cleared when created so no setup required here */ return 1; } @@ -3339,7 +3414,10 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->ftype = 5; /* default: return as null terminated string */ if (DBIS->debug >= 4 || dbd_verbose >= 4 ) - PerlIO_printf(DBILOGFP, "Describe col #%d type=%d(%s)\n",i,fbh->dbtype,sql_typecode_name(fbh->dbtype)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Describe col #%d type=%d(%s)\n", + i,fbh->dbtype,sql_typecode_name(fbh->dbtype)); switch (fbh->dbtype) { /* the simple types */ @@ -3598,18 +3676,22 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->disize = fbh->dbsize; p = "Field %d has an Oracle type (%d) which is not explicitly supported%s"; if (DBIS->debug >= 1 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, p, i, fbh->dbtype, "\n"); + PerlIO_printf(DBIc_LOGPIO(imp_sth), p, i, fbh->dbtype, "\n"); if (PL_dowarn) warn(p, i, fbh->dbtype, ""); break; } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, name %s\n" - " : dbsize %d, char_used %d, char_size %d, csid %d, csform %d(%s), disize %d\n", - i, fbh->dbtype, sql_typecode_name(fbh->dbtype),fbh->scale, fbh->prec, fbh->nullok, fbh->name, - fbh->dbsize, fbh->len_char_used, fbh->len_char_size, fbh->csid,fbh->csform,oci_csform_name(fbh->csform), fbh->disize); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, " + "name %s\n : dbsize %d, char_used %d, char_size %d, " + "csid %d, csform %d(%s), disize %d\n", + i, fbh->dbtype, sql_typecode_name(fbh->dbtype), fbh->scale, + fbh->prec, fbh->nullok, fbh->name, fbh->dbsize, + fbh->len_char_used, fbh->len_char_size, + fbh->csid,fbh->csform,oci_csform_name(fbh->csform), fbh->disize); if (fbh->ftype == 5) /* XXX need to handle wide chars somehow */ fbh->disize += 1; /* allow for null terminator */ @@ -3689,7 +3771,10 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (fbh->ftype == 108) { /* Embedded object bind it differently*/ if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ - PerlIO_printf(DBILOGFP,"Field #%d is a object or colection of some sort. Using OCIDefineObject and or OCIObjectPin \n",i); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Field #%d is a object or colection of some sort. " + "Using OCIDefineObject and or OCIObjectPin \n",i); } Newz(1, fbh->obj, 1, fbh_obj_t); fbh->obj->typecode=fbh->dbtype; @@ -3719,7 +3804,10 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if ( (fbh->dbtype == 1) && fbh->csform ) { /* csform may be 0 when talking to Oracle 8.0 database*/ if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " calling OCIAttrSet OCI_ATTR_CHARSET_FORM with csform=%d (%s)\n", fbh->csform,oci_csform_name(fbh->csform) ); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " calling OCIAttrSet OCI_ATTR_CHARSET_FORM with csform=%d (%s)\n", + fbh->csform,oci_csform_name(fbh->csform) ); OCIAttrSet_log_stat( fbh->defnp, (ub4) OCI_HTYPE_DEFINE, (dvoid *) &fbh->csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status ); if (status != OCI_SUCCESS) { @@ -3732,9 +3820,11 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " dbd_describe'd %d columns (row bytes: %d max, %d est avg, cache: %d)\n", - (int)num_fields, imp_sth->t_dbsize, imp_sth->est_width, imp_sth->prefetch_rows); + (int)num_fields, imp_sth->t_dbsize, imp_sth->est_width, + imp_sth->prefetch_rows); return (num_errors>0) ? 0 : 1; } @@ -3775,7 +3865,9 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ } else { if (DBIS->debug >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, " dbd_st_fetch %d fields...\n", DBIc_NUM_FIELDS(imp_sth)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_st_fetch %d fields...\n", DBIc_NUM_FIELDS(imp_sth)); } if (imp_sth->fetch_orient != OCI_DEFAULT) { @@ -3783,8 +3875,12 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ croak ("attempt to use a scrollable cursor without first setting ora_exe_mode to OCI_STMT_SCROLLABLE_READONLY\n") ; if (DBIS->debug >= 4 || dbd_verbose >= 4 ) - PerlIO_printf(DBILOGFP," Scrolling Fetch, postion before fetch=%d, Orientation = %s , Fetchoffset =%d\n", - imp_sth->fetch_position,oci_fetch_options(imp_sth->fetch_orient),imp_sth->fetch_offset); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Scrolling Fetch, postion before fetch=%d, " + "Orientation = %s , Fetchoffset =%d\n", + imp_sth->fetch_position, oci_fetch_options(imp_sth->fetch_orient), + imp_sth->fetch_offset); OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp,1, imp_sth->fetch_orient,imp_sth->fetch_offset, status); /*this will work without a round trip so might as well open it up for all statments handles*/ @@ -3792,8 +3888,10 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->fetch_position, 0, OCI_ATTR_CURRENT_POSITION, status); if (DBIS->debug >= 4 || dbd_verbose >= 4 ) - PerlIO_printf(DBILOGFP," Scrolling Fetch, postion after fetch=%d\n",imp_sth->fetch_position); - + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Scrolling Fetch, postion after fetch=%d\n", + imp_sth->fetch_position); } else { @@ -3808,7 +3906,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_sth->rs_array_idx++; if (imp_sth->rs_array_num_rows<=imp_sth->rs_array_idx && (imp_sth->rs_array_status==OCI_SUCCESS || imp_sth->rs_array_status==OCI_SUCCESS_WITH_INFO)) { -/* PerlIO_printf(DBILOGFP, " dbd_st_fetch fields...b\n");*/ +/* PerlIO_printf(DBIc_LOGPIO(imp_sth), " dbd_st_fetch fields...b\n");*/ OCIStmtFetch_log_stat(imp_sth->stmhp,imp_sth->errhp,imp_sth->rs_array_size,(ub2)OCI_FETCH_NEXT,OCI_DEFAULT,status); @@ -3823,7 +3921,9 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_sth->RowsInCache =imp_sth->rs_array_size; if (DBIS->debug >= 4 || dbd_verbose >= 4 || oci_warn) - PerlIO_printf(DBILOGFP,"...Fetched %d rows\n",imp_sth->rs_array_num_rows); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "...Fetched %d rows\n",imp_sth->rs_array_num_rows); } imp_dbh->RowsInCache--; @@ -3847,7 +3947,10 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ dTHR; /* for DBIc_ACTIVE_off */ DBIc_ACTIVE_off(imp_sth); /* eg finish */ if (DBIS->debug >= 3 || dbd_verbose >= 3 || oci_warn) - PerlIO_printf(DBILOGFP, " dbd_st_fetch no-more-data, fetch count=%d\n",imp_sth->rs_fetch_count-1); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_st_fetch no-more-data, fetch count=%d\n", + imp_sth->rs_fetch_count-1); return Nullav; } if (status != OCI_SUCCESS_WITH_INFO) { @@ -3868,7 +3971,10 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ av = DBIS->get_fbav(imp_sth); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { - PerlIO_printf(DBILOGFP, " dbd_st_fetched %d fields with status of %d(%s)\n", num_fields,status, oci_status_name(status)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " dbd_st_fetched %d fields with status of %d(%s)\n", + num_fields,status, oci_status_name(status)); } ChopBlanks = DBIc_has(imp_sth, DBIcf_ChopBlanks); @@ -3883,7 +3989,9 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf(DBILOGFP, " field #%d with rc=%d(%s)\n",i+1,rc,oci_col_return_codes(rc)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " field #%d with rc=%d(%s)\n",i+1,rc,oci_col_return_codes(rc)); } if (rc == 1406 /* field was truncated */ @@ -4003,7 +4111,9 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ } if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ - PerlIO_printf(DBILOGFP, "\n %p (field=%d): %s\n", av, i,neatsvpv(sv,10)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "\n %p (field=%d): %s\n", av, i,neatsvpv(sv,10)); } } return (err) ? Nullav : av; @@ -4243,7 +4353,10 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) tablename=new_tablename; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " lob refetch using a synonym named=%s for %s \n", syn_name,tablename); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " lob refetch using a synonym named=%s for %s \n", + syn_name,tablename); } @@ -4279,7 +4392,10 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " lob refetch from table %s, %d columns:\n", tablename, numcols); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " lob refetch from table %s, %d columns:\n", + tablename, numcols); for (i = 1; i <= (long)numcols; i++) { ub2 col_dbtype; @@ -4300,7 +4416,9 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) break; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " lob refetch table col %d: '%.*s' otype %d\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " lob refetch table col %d: '%.*s' otype %d\n", (int)i, (int)col_name_len,col_name, col_dbtype); if (col_dbtype != SQLT_CLOB && col_dbtype != SQLT_BLOB) @@ -4381,9 +4499,11 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) if (phs->ftype != SvIV(sv_other)) continue; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " both %s and %s have type %d - ambiguous\n", - neatsvpv(sv,0), neatsvpv(sv_other,0), (int)SvIV(sv_other)); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " both %s and %s have type %d - ambiguous\n", + neatsvpv(sv,0), neatsvpv(sv_other,0), + (int)SvIV(sv_other)); Safefree(lr); sv_free((SV*)lob_cols_hv); return oci_error(sth, errhp, OCI_ERROR, @@ -4398,8 +4518,9 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) sv_catpv(sql_select, sql_field); if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, - " lob refetch %s param: otype %d, matched field '%s' %s(%s)\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " lob refetch %s param: otype %d, matched field '%s' %s(%s)\n", phs->name, phs->ftype, p, (phs->ora_field) ? "by name " : "by type ", sql_field); (void)hv_delete(lob_cols_hv, p, i, G_DISCARD); @@ -4417,7 +4538,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) if (!matched) { ++unmatched_params; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " lob refetch %s param: otype %d, UNMATCHED\n", phs->name, phs->ftype); } @@ -4434,7 +4556,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) sv_catpv(sql_select, tablename); sv_catpv(sql_select, " where rowid = :rid for update"); /* get row with lock */ if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " lob refetch sql: %s\n", SvPVX(sql_select)); lr->stmthp = NULL; lr->bindhp = NULL; @@ -4474,7 +4597,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) phs = (phs_t*)(void*)SvPVX(*phs_svp); fbh->special = phs; if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " lob refetch %d for '%s' param: ftype %d setup\n", (int)i+1,fbh->name, fbh->dbtype); fbh->fb_ary = fb_ary_alloc(fbh->disize, 1); @@ -4598,7 +4722,9 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " calling OCILobWrite fbh->csid=%d fbh->csform=%d amtp=%d\n", + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " calling OCILobWrite fbh->csid=%d fbh->csform=%d amtp=%d\n", fbh->csid, fbh->csform, amtp ); OCILobWrite_log_stat(imp_sth->svchp, errhp, @@ -4619,7 +4745,8 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl } if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf( + DBIc_LOGPIO(imp_sth), " lob refetch %d for '%s' param: ftype %d, len %ld: %s %s\n", i+1,fbh->name, fbh->dbtype, ul_t(amtp), (rc==1405 ? "NULL" : (amtp > 0) ? "LobWrite" : "LobTrim"), oci_status_name(status)); From 6f93dd092d5bee3ccdc2366890ccd07ce861b688 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 17:15:01 +0000 Subject: [PATCH 167/637] more removing DBIS usage some cannot be done without restructuring as some functions don't have a handle most of these would be better as DBIc_TRACE git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15223 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 9785fddb..5518343e 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1382,12 +1382,12 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ len = SvLEN(source); bufp = SvPV(source, len); - if (DBIS->debug >=3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >=3 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " creating xml from string that is %lu long\n",(unsigned long)len); if(len > MAX_OCISTRING_LEN) { src_type = OCI_XMLTYPE_CREATE_CLOB; - if (DBIS->debug >=5 || dbd_verbose >= 5 ) + if (DBIc_DBISTATE(imp_sth)->debug >=5 || dbd_verbose >= 5 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " use a temp lob locator for large xml \n"); @@ -1413,7 +1413,7 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ } else { src_type = OCI_XMLTYPE_CREATE_OCISTRING; - if (DBIS->debug >=5 || dbd_verbose >= 5 ) + if (DBIc_DBISTATE(imp_sth)->debug >=5 || dbd_verbose >= 5 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " use a OCIStringAssignText for small xml \n"); OCIStringAssignText(imp_dbh->envhp, @@ -1579,7 +1579,7 @@ phs_t *phs; *dest = '\0'; if (imp_sth->all_params_hv) { DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv); - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 2 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " dbd_preparse scanned %d distinct placeholders\n", (int)DBIc_NUM_PARAMS(imp_sth)); @@ -1704,7 +1704,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) dTHX; /*D_imp_dbh_from_sth ;*/ sword status; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; ub1 csform; ub2 csid; @@ -2121,7 +2121,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { dTHX; /*D_imp_dbh_from_sth ;*/ sword status; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; int need_allocate_rows; int buflen; @@ -2576,7 +2576,7 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) } - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 2 || dbd_verbose >= 3 ) { char *val = neatsvpv(phs->sv,10); PerlIO_printf( DBIc_LOGPIO(imp_sth), @@ -2656,7 +2656,7 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) phs->alen = value_len + phs->alen_incnull; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { UV neatsvpvlen = (UV)DBIc_DBISTATE(imp_sth)->neatsvpvlen; char *val = neatsvpv(phs->sv,10); PerlIO_printf( @@ -2688,7 +2688,7 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) D_impdata(imp_sth_csr, imp_sth_t, sth_csr); sword status; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " pp_rebind_ph_rset_in: BEGIN\n calling OCIBindByName(stmhp=%p, " @@ -2713,7 +2713,7 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) return 0; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " pp_rebind_ph_rset_in: END\n"); return 2; @@ -2732,7 +2732,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) int count; sword status; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " pp_exec_rset bind %s - allocating new sth...\n", @@ -2792,7 +2792,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) PUTBACK; FREETMPS; LEAVE; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " pp_exec_rset bind %s - allocated %s...\n", @@ -2804,7 +2804,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) SV * sth_csr = phs->sv; D_impdata(imp_sth_csr, imp_sth_t, sth_csr); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " bind %s - initialising new %s for cursor 0x%lx...\n", @@ -2851,7 +2851,7 @@ sword status; SV* ptr; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " in dbd_rebind_ph_xml\n"); /*go and create the XML dom from the passed in value*/ @@ -2896,7 +2896,7 @@ sword status; oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); return 0; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " pp_rebind_ph_nty: END\n"); @@ -2920,7 +2920,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) sword status; int done = 0; int at_exec; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; ub1 csform; ub2 csid; @@ -3124,7 +3124,7 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ if (SvTYPE(newvalue) == SVt_PVLV && is_inout) /* may allow later */ croak("Can't bind ``lvalue'' mode scalar as inout parameter (currently)"); - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 2 || dbd_verbose >= 3 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_bind_ph(1): bind %s <== %s (type %ld (%s)", name, neatsvpv(newvalue,0), (long)sql_type,sql_typecode_name(sql_type)); @@ -3377,7 +3377,7 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- dTHR; dTHX; ub4 row_count = 0; - int debug = DBIS->debug; + int debug = DBIc_DBISTATE(imp_sth)->debug; int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0; D_imp_dbh_from_sth; sword status; @@ -3576,7 +3576,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat sword status; ub1 csform; ub2 csid; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; int i; OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), @@ -3719,7 +3719,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er dTHX; dTHR; ub4 row_count = 0; - int debug = DBIS->debug; + int debug = DBIc_DBISTATE(imp_sth)->debug; D_imp_dbh_from_sth; sword status, exe_status; int is_select = (imp_sth->stmt_type == OCI_STMT_SELECT); @@ -4020,7 +4020,7 @@ dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, } ftype = ftype; /* no unused */ - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " blob_read field %d+1, ftype %d, offset %ld, len %ld, " @@ -4174,7 +4174,7 @@ ora_free_templob(SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc) } if (is_temporary) { - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), " OCILobFreeTemporary %s\n", oci_status_name(status)); From e107a54f7a39fc23e47ffd7800de28328eb42118 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 14 Mar 2012 17:15:01 +0000 Subject: [PATCH 168/637] more removing DBIS usage some cannot be done without restructuring as some functions don't have a handle most of these would be better as DBIc_TRACE git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15223 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 9785fddb..5518343e 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1382,12 +1382,12 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ len = SvLEN(source); bufp = SvPV(source, len); - if (DBIS->debug >=3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >=3 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " creating xml from string that is %lu long\n",(unsigned long)len); if(len > MAX_OCISTRING_LEN) { src_type = OCI_XMLTYPE_CREATE_CLOB; - if (DBIS->debug >=5 || dbd_verbose >= 5 ) + if (DBIc_DBISTATE(imp_sth)->debug >=5 || dbd_verbose >= 5 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " use a temp lob locator for large xml \n"); @@ -1413,7 +1413,7 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ } else { src_type = OCI_XMLTYPE_CREATE_OCISTRING; - if (DBIS->debug >=5 || dbd_verbose >= 5 ) + if (DBIc_DBISTATE(imp_sth)->debug >=5 || dbd_verbose >= 5 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " use a OCIStringAssignText for small xml \n"); OCIStringAssignText(imp_dbh->envhp, @@ -1579,7 +1579,7 @@ phs_t *phs; *dest = '\0'; if (imp_sth->all_params_hv) { DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv); - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 2 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " dbd_preparse scanned %d distinct placeholders\n", (int)DBIc_NUM_PARAMS(imp_sth)); @@ -1704,7 +1704,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) dTHX; /*D_imp_dbh_from_sth ;*/ sword status; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; ub1 csform; ub2 csid; @@ -2121,7 +2121,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { dTHX; /*D_imp_dbh_from_sth ;*/ sword status; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; int need_allocate_rows; int buflen; @@ -2576,7 +2576,7 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) } - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 2 || dbd_verbose >= 3 ) { char *val = neatsvpv(phs->sv,10); PerlIO_printf( DBIc_LOGPIO(imp_sth), @@ -2656,7 +2656,7 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) phs->alen = value_len + phs->alen_incnull; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { UV neatsvpvlen = (UV)DBIc_DBISTATE(imp_sth)->neatsvpvlen; char *val = neatsvpv(phs->sv,10); PerlIO_printf( @@ -2688,7 +2688,7 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) D_impdata(imp_sth_csr, imp_sth_t, sth_csr); sword status; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " pp_rebind_ph_rset_in: BEGIN\n calling OCIBindByName(stmhp=%p, " @@ -2713,7 +2713,7 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) return 0; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " pp_rebind_ph_rset_in: END\n"); return 2; @@ -2732,7 +2732,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) int count; sword status; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " pp_exec_rset bind %s - allocating new sth...\n", @@ -2792,7 +2792,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) PUTBACK; FREETMPS; LEAVE; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " pp_exec_rset bind %s - allocated %s...\n", @@ -2804,7 +2804,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) SV * sth_csr = phs->sv; D_impdata(imp_sth_csr, imp_sth_t, sth_csr); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " bind %s - initialising new %s for cursor 0x%lx...\n", @@ -2851,7 +2851,7 @@ sword status; SV* ptr; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " in dbd_rebind_ph_xml\n"); /*go and create the XML dom from the passed in value*/ @@ -2896,7 +2896,7 @@ sword status; oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); return 0; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " pp_rebind_ph_nty: END\n"); @@ -2920,7 +2920,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) sword status; int done = 0; int at_exec; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; ub1 csform; ub2 csid; @@ -3124,7 +3124,7 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ if (SvTYPE(newvalue) == SVt_PVLV && is_inout) /* may allow later */ croak("Can't bind ``lvalue'' mode scalar as inout parameter (currently)"); - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 2 || dbd_verbose >= 3 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_bind_ph(1): bind %s <== %s (type %ld (%s)", name, neatsvpv(newvalue,0), (long)sql_type,sql_typecode_name(sql_type)); @@ -3377,7 +3377,7 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- dTHR; dTHX; ub4 row_count = 0; - int debug = DBIS->debug; + int debug = DBIc_DBISTATE(imp_sth)->debug; int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0; D_imp_dbh_from_sth; sword status; @@ -3576,7 +3576,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat sword status; ub1 csform; ub2 csid; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; int i; OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), @@ -3719,7 +3719,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er dTHX; dTHR; ub4 row_count = 0; - int debug = DBIS->debug; + int debug = DBIc_DBISTATE(imp_sth)->debug; D_imp_dbh_from_sth; sword status, exe_status; int is_select = (imp_sth->stmt_type == OCI_STMT_SELECT); @@ -4020,7 +4020,7 @@ dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, } ftype = ftype; /* no unused */ - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " blob_read field %d+1, ftype %d, offset %ld, len %ld, " @@ -4174,7 +4174,7 @@ ora_free_templob(SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc) } if (is_temporary) { - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), " OCILobFreeTemporary %s\n", oci_status_name(status)); From 41aad3c658807a62bacaaf58b336ac3fcb009a98 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 15 Mar 2012 17:08:24 +0000 Subject: [PATCH 169/637] More changes to remove DBIS usage git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15225 50811bd7-b8ce-0310-adc1-d9db26280581 --- Oracle.xs | 54 +++--- dbdimp.c | 422 +++++++++++++++++++++++---------------------- dbdimp.h | 10 +- oci8.c | 493 ++++++++++++++++++++++++++++++++--------------------- ocitrace.h | 360 +++++++++++++++++++------------------- 5 files changed, 731 insertions(+), 608 deletions(-) diff --git a/Oracle.xs b/Oracle.xs index d4a90c2f..2c7ffc00 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -305,9 +305,9 @@ ora_db_startup(dbh, attribs) croak("ora_pfile is not a string"); str = (text*)SvPV(*svp, svp_len); OCIHandleAlloc(imp_dbh->envhp, (dvoid**)&admhp, (ub4)OCI_HTYPE_ADMIN, (size_t)0, (dvoid**)0); - OCIAttrSet_log_stat((dvoid*)admhp, (ub4)OCI_HTYPE_ADMIN, (dvoid*)str, (ub4)svp_len, (ub4)OCI_ATTR_ADMIN_PFILE, (OCIError*)imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, (dvoid*)admhp, (ub4)OCI_HTYPE_ADMIN, (dvoid*)str, (ub4)svp_len, (ub4)OCI_ATTR_ADMIN_PFILE, (OCIError*)imp_dbh->errhp, status); } - OCIDBStartup_log_stat(imp_dbh->svchp, imp_dbh->errhp, admhp, mode, flags, status); + OCIDBStartup_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, admhp, mode, flags, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCIDBStartup"); ST(0) = &PL_sv_undef; @@ -315,7 +315,7 @@ ora_db_startup(dbh, attribs) else { ST(0) = &PL_sv_yes; } - if (admhp) OCIHandleFree_log_stat((dvoid*)admhp, (ub4)OCI_HTYPE_ADMIN, status); + if (admhp) OCIHandleFree_log_stat(imp_dbh, (dvoid*)admhp, (ub4)OCI_HTYPE_ADMIN, status); #else croak("OCIDBStartup not available"); #endif @@ -338,7 +338,7 @@ ora_db_shutdown(dbh, attribs) mode = OCI_DEFAULT; DBD_ATTRIB_GET_IV(attribs, "ora_mode", 8, svp, mode); admhp = (OCIAdmin*)0; - OCIDBShutdown_log_stat(imp_dbh->svchp, imp_dbh->errhp, admhp, mode, status); + OCIDBShutdown_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, admhp, mode, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCIDBShutdown"); ST(0) = &PL_sv_undef; @@ -359,7 +359,7 @@ ora_can_taf(dbh) ub4 can_taf = 0; CODE: #ifdef OCI_ATTR_TAF_ENABLED - OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, + OCIAttrGet_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { # else @@ -391,14 +391,14 @@ ora_ping(dbh) /*so we should stay connected but we cannot get nay new connections*/ { #if !defined(ORA_OCI_102) - OCIServerVersion_log_stat(imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); + OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); #else vernum = ora_db_version(dbh,imp_dbh); /* OCIPing causes server failures if called against server ver < 10.2 */ if (((int)((vernum>>24) & 0xFF) < 10 ) || (((int)((vernum>>24) & 0xFF) == 10 ) && ((int)((vernum>>20) & 0x0F) < 2 ))){ - OCIServerVersion_log_stat(imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); + OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); } else { - OCIPing_log_stat(imp_dbh->svchp,imp_dbh->errhp,status); + OCIPing_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,status); } #endif if (status != OCI_SUCCESS){ @@ -441,7 +441,7 @@ ora_lob_write(dbh, locator, offset, data) /* if (0 && SvUTF8(data) && !IN_BYTES) { amtp = sv_len_utf8(data); } */ /* added by lab: */ /* LAB do something about length here? see above comment */ - OCILobCharSetForm_log_stat( imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); + OCILobCharSetForm_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetForm"); ST(0) = &PL_sv_undef; @@ -449,7 +449,12 @@ ora_lob_write(dbh, locator, offset, data) } #ifdef OCI_ATTR_CHARSET_ID /* Effectively only used so AL32UTF8 works properly */ - OCILobCharSetId_log_stat( imp_dbh->envhp, imp_dbh->errhp, locator, &csid, status ); + OCILobCharSetId_log_stat(imp_dbh, + imp_dbh->envhp, + imp_dbh->errhp, + locator, + &csid, + status ); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetId"); ST(0) = &PL_sv_undef; @@ -459,7 +464,7 @@ ora_lob_write(dbh, locator, offset, data) /* if data is utf8 but charset isn't then switch to utf8 csid */ csid = (SvUTF8(data) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); - OCILobWrite_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, + OCILobWrite_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &amtp, (ub4)offset, bufp, (ub4)data_len, OCI_ONE_PIECE, NULL, NULL, @@ -497,7 +502,7 @@ ora_lob_append(dbh, locator, data) /* if (1 && SvUTF8(data) && !IN_BYTES) */ /* added by lab: */ /* LAB do something about length here? see above comment */ - OCILobCharSetForm_log_stat( imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); + OCILobCharSetForm_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetForm"); ST(0) = &PL_sv_undef; @@ -505,7 +510,12 @@ ora_lob_append(dbh, locator, data) } #ifdef OCI_ATTR_CHARSET_ID /* Effectively only used so AL32UTF8 works properly */ - OCILobCharSetId_log_stat( imp_dbh->envhp, imp_dbh->errhp, locator, &csid, status ); + OCILobCharSetId_log_stat(imp_dbh, + imp_dbh->envhp, + imp_dbh->errhp, + locator, + &csid, + status ); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetId"); ST(0) = &PL_sv_undef; @@ -514,7 +524,7 @@ ora_lob_append(dbh, locator, data) #endif /* OCI_ATTR_CHARSET_ID */ /* if data is utf8 but charset isn't then switch to utf8 csid */ csid = (SvUTF8(data) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); - OCILobWriteAppend_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, + OCILobWriteAppend_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &amtp, bufp, (ub4)data_len, OCI_ONE_PIECE, NULL, NULL, csid, csform, status); @@ -554,7 +564,7 @@ ora_lob_read(dbh, locator, offset, length) /* if locator is CLOB and data is UTF8 and not in bytes pragma */ /* if (0 && SvUTF8(dest_sv) && !IN_BYTES) { amtp = sv_len_utf8(dest_sv); } */ /* added by lab: */ - OCILobCharSetForm_log_stat( imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); + OCILobCharSetForm_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetForm"); dest_sv = &PL_sv_undef; @@ -564,9 +574,9 @@ ora_lob_read(dbh, locator, offset, length) /* see rt 75163 */ boolean is_open; - OCILobFileIsOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, &is_open, status); + OCILobFileIsOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &is_open, status); if (status == OCI_SUCCESS && !is_open) { - OCILobFileOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, + OCILobFileOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, (ub1)OCI_FILE_READONLY, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobFileOpen"); @@ -575,7 +585,7 @@ ora_lob_read(dbh, locator, offset, length) } } - OCILobRead_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, + OCILobRead_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &amtp, (ub4)offset, /* offset starts at 1 */ bufp, (ub4)bufp_len, 0, 0, (ub2)0, csform, status); @@ -603,7 +613,7 @@ ora_lob_trim(dbh, locator, length) D_imp_dbh(dbh); sword status; CODE: - OCILobTrim_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, length, status); + OCILobTrim_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, length, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobTrim"); ST(0) = &PL_sv_undef; @@ -621,7 +631,7 @@ ora_lob_is_init(dbh, locator) sword status; boolean is_init = 0; CODE: - OCILobLocatorIsInit_log_stat(imp_dbh->envhp,imp_dbh->errhp,locator,&is_init,status); + OCILobLocatorIsInit_log_stat(imp_dbh, imp_dbh->envhp,imp_dbh->errhp,locator,&is_init,status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobLocatorIsInit ora_lob_is_init"); ST(0) = &PL_sv_undef; @@ -639,7 +649,7 @@ ora_lob_length(dbh, locator) sword status; ub4 len = 0; CODE: - OCILobGetLength_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, &len, status); + OCILobGetLength_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &len, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobGetLength ora_lob_length"); ST(0) = &PL_sv_undef; @@ -658,7 +668,7 @@ ora_lob_chunk_size(dbh, locator) sword status; ub4 chunk_size = 0; CODE: - OCILobGetChunkSize_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, &chunk_size, status); + OCILobGetChunkSize_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &chunk_size, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobGetChunkSize"); ST(0) = &PL_sv_undef; diff --git a/dbdimp.c b/dbdimp.c index 5518343e..3c417f2b 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -62,11 +62,12 @@ struct sql_fbh_st { }; static sql_fbh_t ora2sql_type _((imp_fbh_t* fbh)); -void ora_free_phs_contents _((phs_t *phs)); -static void dump_env_to_trace(); +void ora_free_phs_contents _((imp_sth_t *imp_sth, phs_t *phs)); +static void dump_env_to_trace(imp_dbh_t *imp_dbh); static sb4 -oci_error_get(OCIError *errhp, sword status, char *what, SV *errstr, int debug) +oci_error_get(imp_xxh_t *imp_xxh, + OCIError *errhp, sword status, char *what, SV *errstr, int debug) { dTHX; text errbuf[1024]; @@ -86,16 +87,17 @@ oci_error_get(OCIError *errhp, sword status, char *what, SV *errstr, int debug) } while( ++recno - && OCIErrorGet_log_stat(errhp, recno, (text*)NULL, &eg_errcode, errbuf, + && OCIErrorGet_log_stat(imp_xxh, errhp, recno, (text*)NULL, &eg_errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR, eg_status) != OCI_NO_DATA - && eg_status != OCI_INVALID_HANDLE - && recno < 100 + && eg_status != OCI_INVALID_HANDLE + && recno < 100 ) { if (debug >= 4 || recno>1/*XXX temp*/ || dbd_verbose >= 4 ) - PerlIO_printf(DBILOGFP, " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", - what ? what : "", (long)recno, - (eg_status==OCI_SUCCESS) ? "ok" : oci_status_name(eg_status), - status, (long)eg_errcode, errbuf); + PerlIO_printf(DBIc_LOGPIO(imp_xxh), + " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", + what ? what : "", (long)recno, + (eg_status==OCI_SUCCESS) ? "ok" : oci_status_name(eg_status), + status, (long)eg_errcode, errbuf); errcode = eg_errcode; sv_catpv(errstr, (char*)errbuf); if (*(SvEND(errstr)-1) == '\n') @@ -205,34 +207,32 @@ dbd_discon_all(SV *drh, imp_drh_t *imp_drh) { dTHR; dTHX; - /* The disconnect_all concept is flawed and needs more work */ + + /* The disconnect_all concept is flawed and needs more work */ if (!PL_dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { - DBIh_SET_ERR_CHAR(drh, (imp_xxh_t*)imp_drh, Nullch, 1, "disconnect_all not implemented", Nullch, Nullch); - return FALSE; + DBIh_SET_ERR_CHAR(drh, (imp_xxh_t*)imp_drh, Nullch, 1, "disconnect_all not implemented", Nullch, Nullch); + return FALSE; } return FALSE; } - void -dbd_fbh_dump(imp_fbh_t *fbh, int i, int aidx) +dbd_fbh_dump(imp_sth_t *imp_sth, imp_fbh_t *fbh, int i, int aidx) { dTHX; - PerlIO *fp = DBILOGFP; - PerlIO_printf(fp, " fbh %d: '%s'\t%s, ", + PerlIO_printf(DBIc_LOGPIO(imp_sth), " fbh %d: '%s'\t%s, ", i, fbh->name, (fbh->nullok) ? "NULLable" : "NO null "); - PerlIO_printf(fp, "otype %3d->%3d, dbsize %ld/%ld, p%d.s%d\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), "otype %3d->%3d, dbsize %ld/%ld, p%d.s%d\n", fbh->dbtype, fbh->ftype, (long)fbh->dbsize,(long)fbh->disize, fbh->prec, fbh->scale); if (fbh->fb_ary) { - PerlIO_printf(fp, " out: ftype %d, bufl %d. indp %d, rlen %d, rcode %d\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), " out: ftype %d, bufl %d. indp %d, rlen %d, rcode %d\n", fbh->ftype, fbh->fb_ary->bufl, fbh->fb_ary->aindp[aidx], fbh->fb_ary->arlen[aidx], fbh->fb_ary->arcode[aidx]); } } - int ora_dbtype_is_long(int dbtype) { @@ -430,10 +430,10 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("ora_driver_name is not a string"); imp_dbh->driver_name = (char *) SvPV (*svp, svp_len ); imp_dbh->driver_namel= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); } else { - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION,(text*)"DBDO1.28",7,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION,(text*)"DBDO1.28",7,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); } #endif /*ORA_OCI_112*/ @@ -443,7 +443,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("ora_action is not a string"); imp_dbh->action = (char *) SvPV (*svp, svp_len ); imp_dbh->actionl= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_module_name", 15)) && SvOK(*svp)) { @@ -452,7 +452,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("ora_module_name is not a string"); imp_dbh->module_name = (char *) SvPV (*svp, svp_len ); imp_dbh->module_namel= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); } if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_identifier", 21)) && SvOK(*svp)) { @@ -461,7 +461,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("ora_client_identifier is not a string"); imp_dbh->client_identifier = (char *) SvPV (*svp, svp_len ); imp_dbh->client_identifierl= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); } if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_info", 15)) && SvOK(*svp)) { @@ -470,7 +470,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("ora_client_info is not a string"); imp_dbh->client_info = (char *) SvPV (*svp, svp_len ); imp_dbh->client_infol= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); } @@ -513,7 +513,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S DBD_ATTRIB_GET_IV( attr, "ora_objects",11, svp, ora_objects); if (DBIc_DBISTATE(imp_dbh)->debug >= 6 || dbd_verbose >= 6 ) - dump_env_to_trace(); + dump_env_to_trace(imp_dbh); /* dbi_imp_data code adapted from DBD::mysql */ if (DBIc_has(imp_dbh, DBIcf_IMPSET)) { @@ -590,14 +590,14 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S { size_t rsize = 0; /* Get CLIENT char and nchar charset id values */ - OCINlsEnvironmentVariableGet_log_stat( &charsetid,(size_t) 0, OCI_NLS_CHARSET_ID, 0, &rsize ,status ); + OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &charsetid,(size_t) 0, OCI_NLS_CHARSET_ID, 0, &rsize ,status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "OCINlsEnvironmentVariableGet(OCI_NLS_CHARSET_ID) Check NLS settings etc."); return 0; } - OCINlsEnvironmentVariableGet_log_stat( &ncharsetid,(size_t) 0, OCI_NLS_NCHARSET_ID, 0, &rsize ,status ); + OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &ncharsetid,(size_t) 0, OCI_NLS_NCHARSET_ID, 0, &rsize ,status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "OCINlsEnvironmentVariableGet(OCI_NLS_NCHARSET_ID) Check NLS settings etc."); @@ -624,7 +624,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S form attribute. }*/ - OCIEnvNlsCreate_log_stat( &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, + OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, charsetid, ncharsetid, status ); if (status != OCI_SUCCESS) { @@ -665,7 +665,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (new_charsetid) charsetid = new_charsetid; if (new_ncharsetid) ncharsetid = new_ncharsetid; imp_dbh->envhp = NULL; - OCIEnvNlsCreate_log_stat( &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, + OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, charsetid, ncharsetid, status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, @@ -686,7 +686,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (shared_dbh_ssv) { /*is this a cached or shared handle from DBI*/ if (!imp_dbh->envhp) { /*no hande so create a new one*/ - OCIEnvInit_log_stat( &imp_dbh->envhp, OCI_DEFAULT, 0, 0, status); + OCIEnvInit_log_stat(imp_dbh, &imp_dbh->envhp, OCI_DEFAULT, 0, 0, status); if (status != OCI_SUCCESS) { oci_error(dbh, (OCIError*)imp_dbh->envhp, status, "OCIEnvInit"); return 0; @@ -694,8 +694,8 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } } - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIAttrGet_log_stat(imp_dbh->envhp, OCI_HTYPE_ENV, &charsetid, (ub4)0 , + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &charsetid, (ub4)0 , OCI_ATTR_ENV_CHARSET_ID, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { @@ -703,7 +703,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S return 0; } - OCIAttrGet_log_stat(imp_dbh->envhp, OCI_HTYPE_ENV, &ncharsetid, (ub4)0 , + OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &ncharsetid, (ub4)0 , OCI_ATTR_ENV_NCHARSET_ID, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { @@ -735,12 +735,12 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!shared_dbh) { - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCIServerAttach"); - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); return 0; } @@ -762,57 +762,60 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!imp_dbh->pool_incr) imp_dbh->pool_incr = 2; - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->poolhp, OCI_HTYPE_SPOOL, status); - - OCISessionPoolCreate_log_stat(imp_dbh->envhp, - imp_dbh->errhp, - imp_dbh->poolhp, - (OraText **) &imp_dbh->pool_name, - (ub4 *) &imp_dbh->pool_namel, - (OraText *) dbname, - strlen(dbname), - imp_dbh->pool_min, - imp_dbh->pool_max, - imp_dbh->pool_incr, - (OraText *) uid, - strlen(uid), - (OraText *) pwd, - strlen(pwd), - status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->poolhp, OCI_HTYPE_SPOOL, status); + + OCISessionPoolCreate_log_stat( + imp_dbh, + imp_dbh->envhp, + imp_dbh->errhp, + imp_dbh->poolhp, + (OraText **) &imp_dbh->pool_name, + (ub4 *) &imp_dbh->pool_namel, + (OraText *) dbname, + strlen(dbname), + imp_dbh->pool_min, + imp_dbh->pool_max, + imp_dbh->pool_incr, + (OraText *) uid, + strlen(uid), + (OraText *) pwd, + strlen(pwd), + status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionPoolCreate"); - OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); - OCIHandleFree_log_stat(imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); return 0; } - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_AUTHINFO, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_AUTHINFO, status); - OCIAttrSet_log_stat(imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, &purity, (ub4) 0,(ub4) OCI_ATTR_PURITY, imp_dbh->errhp, status); if (imp_dbh->pool_class) /*pool_class may or may not be used */ - OCIAttrSet_log_stat(imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, (OraText *) imp_dbh->pool_class, (ub4) imp_dbh->pool_classl, (ub4) OCI_ATTR_CONNECTION_CLASS, imp_dbh->errhp, status); cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); - OCISessionGet_log_stat(imp_dbh->envhp, imp_dbh->errhp, &imp_dbh->svchp, imp_dbh->authp, + OCISessionGet_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, &imp_dbh->svchp, imp_dbh->authp, imp_dbh->pool_name, (ub4)strlen((char *)imp_dbh->pool_name), status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionGet"); - OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); - OCISessionPoolDestroy(imp_dbh->poolhp, imp_dbh->errhp,status); - OCIHandleFree_log_stat(imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); + OCISessionPoolDestroy_log_stat( + imp_dbh, imp_dbh->poolhp, imp_dbh->errhp,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); return 0; } @@ -833,28 +836,28 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S else { #endif /* ORA_OCI_112 */ - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); OCIServerAttach_log_stat(imp_dbh, dbname,OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCIServerAttach"); - OCIHandleFree_log_stat(imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); if (forced_new_environment) - OCIHandleFree_log_stat(imp_dbh->envhp, OCI_HTYPE_ENV, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); return 0; } - OCIAttrSet_log_stat( imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp, status); - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->seshp, OCI_HTYPE_SESSION, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->seshp, OCI_HTYPE_SESSION, status); cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); - OCISessionBegin_log_stat( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp,cred_type, sess_mode_type, status); + OCISessionBegin_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp,cred_type, sess_mode_type, status); if (status == OCI_SUCCESS_WITH_INFO) { /* eg ORA-28011: the account will expire soon; change your password now */ @@ -863,17 +866,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); - OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); - OCIHandleFree_log_stat(imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); if (forced_new_environment) - OCIHandleFree_log_stat(imp_dbh->envhp, OCI_HTYPE_ENV, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); return 0; } - OCIAttrSet_log_stat(imp_dbh->svchp, (ub4) OCI_HTYPE_SVCCTX, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->svchp, (ub4) OCI_HTYPE_SVCCTX, imp_dbh->seshp, (ub4) 0,(ub4) OCI_ATTR_SESSION, imp_dbh->errhp, status); #ifdef ORA_OCI_112 } @@ -912,7 +915,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S can_taf = 0; #ifdef OCI_ATTR_TAF_ENABLED - OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, + OCIAttrGet_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); #endif @@ -943,7 +946,7 @@ dbd_db_commit(SV *dbh, imp_dbh_t *imp_dbh) { dTHX; sword status; - OCITransCommit_log_stat(imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT, status); + OCITransCommit_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCITransCommit"); return 0; @@ -966,7 +969,7 @@ dbd_st_cancel(SV *sth, imp_sth_t *imp_sth) /* if we are using a scrolling cursor we should get rid of the cursor by fetching row 0 */ if (imp_sth->exe_mode==OCI_STMT_SCROLLABLE_READONLY){ - OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp, 0,OCI_FETCH_NEXT,0, status); + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp, 0,OCI_FETCH_NEXT,0, status); } return 1; } @@ -978,7 +981,7 @@ dbd_db_rollback(SV *dbh, imp_dbh_t *imp_dbh) { dTHX; sword status; - OCITransRollback_log_stat(imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT, status); + OCITransRollback_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCITransRollback"); return 0; @@ -1056,17 +1059,17 @@ dbd_db_disconnect(SV *dbh, imp_dbh_t *imp_dbh) sword s_se, s_sd; #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { - OCISessionRelease_log_stat(imp_dbh->svchp, imp_dbh->errhp,s_se); + OCISessionRelease_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp,s_se); } else { #endif - OCISessionEnd_log_stat(imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, + OCISessionEnd_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, OCI_DEFAULT, s_se); #ifdef ORA_OCI_112 } #endif if (s_se) oci_error(dbh, imp_dbh->errhp, s_se, "OCISessionEnd"); - OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, s_sd); + OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, s_sd); if (s_sd) oci_error(dbh, imp_dbh->errhp, s_sd, "OCIServerDetach"); if (s_se || s_sd) return 0; @@ -1104,29 +1107,29 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) OCIFocbkStruct tafailover; tafailover.fo_ctx = NULL; tafailover.callback_function = NULL; - OCIAttrSet_log_stat(imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, (dvoid *) &tafailover, (ub4) 0, (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); } #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { - OCIHandleFree_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION,status); - OCISessionPoolDestroy_log_stat(imp_dbh->poolhp, imp_dbh->errhp,status); - OCIHandleFree_log_stat(imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION,status); + OCISessionPoolDestroy_log_stat(imp_dbh, imp_dbh->poolhp, imp_dbh->errhp,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); } else { #endif - OCIHandleFree_log_stat(imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); #ifdef ORA_OCI_112 } #endif - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); } - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); dbd_db_destroy_out: DBIc_IMPSET_off(imp_dbh); } @@ -1150,7 +1153,7 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) else if (kl==15 && strEQ(key, "ora_driver_name") ) { imp_dbh->driver_name = (char *) SvPV (valuesv, vl ); imp_dbh->driver_namel= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); } else if (kl==8 && strEQ(key, "ora_drcp") ) { imp_dbh->using_drcp = 1; @@ -1182,30 +1185,30 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) else if (kl==10 && strEQ(key, "ora_action") ) { imp_dbh->action = (char *) SvPV (valuesv, vl ); imp_dbh->actionl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } else if (kl==10 && strEQ(key, "ora_action") ) { imp_dbh->action = (char *) SvPV (valuesv, vl ); imp_dbh->actionl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } else if (kl==21 && strEQ(key, "ora_client_identifier") ) { imp_dbh->client_identifier = (char *) SvPV (valuesv, vl ); imp_dbh->client_identifierl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); } else if (kl==15 && strEQ(key, "ora_client_info") ) { imp_dbh->client_info = (char *) SvPV (valuesv, vl ); imp_dbh->client_infol= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); } else if (kl==15 && strEQ(key, "ora_module_name") ) { imp_dbh->module_name = (char *) SvPV (valuesv, vl ); imp_dbh->module_namel= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); } else if (kl==20 && strEQ(key, "ora_oci_success_warn") ) { @@ -1391,9 +1394,9 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ PerlIO_printf(DBIc_LOGPIO(imp_sth), " use a temp lob locator for large xml \n"); - OCIDescriptorAlloc_ok(imp_dbh->envhp, &src_ptr, OCI_DTYPE_LOB); + OCIDescriptorAlloc_ok(imp_dbh, imp_dbh->envhp, &src_ptr, OCI_DTYPE_LOB); - OCILobCreateTemporary_log_stat(imp_dbh->svchp, imp_sth->errhp, + OCILobCreateTemporary_log_stat(imp_dbh, imp_dbh->svchp, imp_sth->errhp, (OCILobLocator *) src_ptr, (ub2) OCI_DEFAULT, (ub1) OCI_DEFAULT, OCI_TEMP_CLOB, FALSE, OCI_DURATION_SESSION, status); @@ -1402,7 +1405,7 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ } csid = (SvUTF8(source) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); buflen = len; - OCILobWriteAppend_log_stat(imp_dbh->svchp, imp_dbh->errhp, src_ptr, + OCILobWriteAppend_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, src_ptr, &buflen, bufp, (ub4)len, OCI_ONE_PIECE, NULL, NULL, csid, csform, status); @@ -1425,13 +1428,15 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ - status = OCIXMLTypeCreateFromSrc(imp_dbh->svchp, - imp_dbh->errhp, - (OCIDuration)OCI_DURATION_CALLOUT, - (ub1)src_type, - (dvoid *)src_ptr, - (sb4)OCI_IND_NOTNULL, - &xml); + OCIXMLTypeCreateFromSrc_log_stat(imp_dbh, + imp_dbh->svchp, + imp_dbh->errhp, + (OCIDuration)OCI_DURATION_CALLOUT, + (ub1)src_type, + (dvoid *)src_ptr, + (sb4)OCI_IND_NOTNULL, + &xml, + status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIXMLTypeCreateFromSrc"); @@ -1442,7 +1447,7 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ OCILobFreeTemporary(imp_dbh->svchp, imp_dbh->errhp, (OCILobLocator*) src_ptr); - OCIDescriptorFree((dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB); + OCIDescriptorFree_log(imp_dbh, (dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB); } @@ -1923,7 +1928,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } } /* Do actual bind */ - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), phs->array_buf, phs->maxlen, @@ -1939,7 +1944,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); return 0; } - OCIBindArrayOfStruct_log_stat(phs->bndhp, imp_sth->errhp, + OCIBindArrayOfStruct_log_stat(imp_sth, phs->bndhp, imp_sth->errhp, (unsigned)phs->maxlen, /* Skip parameter for the next data value */ (unsigned)sizeof (OCIInd), /* Skip parameter for the next indicator value */ (unsigned)sizeof(unsigned short), /* Skip parameter for the next actual length value */ @@ -1952,7 +1957,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) /* Fixup charset */ if (csform) { /* set OCI_ATTR_CHARSET_FORM before we get the default OCI_ATTR_CHARSET_ID */ - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_FORM)")); @@ -1961,7 +1966,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (!phs->csid_orig) { /* get the default csid Oracle would use */ - OCIAttrGet_log_stat(phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , + OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); } @@ -1986,7 +1991,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (csid) { - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csid, (ub4) 0, (ub4) OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_ID)")); @@ -1995,7 +2000,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (phs->maxdata_size) { - OCIAttrSet_log_stat(phs->bndhp, (ub4)OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4)OCI_HTYPE_BIND, phs->array_buf, (ub4)phs->array_buflen, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); @@ -2009,10 +2014,10 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) /* Copy array data from array buffer into perl array */ /* Returns false on error, true on success */ -int dbd_phs_varchar_table_posy_exe(phs_t *phs){ +int dbd_phs_varchar_table_posy_exe(imp_sth_t *imp_sth, phs_t *phs){ dTHX; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; if( ( ! SvROK(phs->sv) ) || (SvTYPE(SvRV(phs->sv))!=SVt_PVAV) ) { /* Allow only array binds */ @@ -2020,7 +2025,7 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ neatsvpv(phs->sv,0), phs->name); } if (trace_level >= 1 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): Called for '%s' : array_numstruct=%d, maxlen=%ld \n", phs->name, phs->array_numstruct, @@ -2060,14 +2065,14 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ if( item ){ SvSetMagicSV(item,&PL_sv_undef); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): arr[%d] = undef; SvSetMagicSV(item,&PL_sv_undef);\n",i); } } else{ av_store(arr,i,&PL_sv_undef); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): arr[%d] = undef; av_store(arr,i,&PL_sv_undef);\n",i); } } @@ -2076,7 +2081,7 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ if( (phs->array_indicators[i] == -2) || (phs->array_indicators[i] > 0) ){ /* Truncation occurred */ if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): Placeholder '%s': data truncated at %d row.\n", phs->name,i); } @@ -2088,7 +2093,7 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ sv_setpvn_mg(item,phs->array_buf+phs->maxlen*i,phs->array_lengths[i]); SvPOK_only_UTF8(item); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): arr[%d] = '%s'; " "sv_setpvn_mg(item,phs->array_buf+phs->maxlen*i,phs->array_lengths[i]); \n", i, phs->array_buf+phs->maxlen*i @@ -2098,7 +2103,7 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ else{ av_store(arr,i,newSVpvn(phs->array_buf+phs->maxlen*i,phs->array_lengths[i])); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): arr[%d] = '%s'; " "av_store(arr,i,newSVpvn(phs->array_buf+phs->maxlen*i,phs->array_lengths[i])); \n", i, phs->array_buf+phs->maxlen*i @@ -2109,7 +2114,7 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ } } if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): scalar(@arr)=%ld.\n", (long)av_len(arr)+1); } @@ -2359,7 +2364,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { } } /* Do actual bind */ - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), phs->array_buf, phs->maxlen, @@ -2375,7 +2380,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); return 0; } - OCIBindArrayOfStruct_log_stat(phs->bndhp, imp_sth->errhp, + OCIBindArrayOfStruct_log_stat(imp_sth, phs->bndhp, imp_sth->errhp, (unsigned)phs->maxlen, /* Skip parameter for the next data value */ (unsigned)sizeof(OCIInd), /* Skip parameter for the next indicator value */ (unsigned)sizeof(unsigned short), /* Skip parameter for the next actual length value */ @@ -2386,7 +2391,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { return 0; } if (phs->maxdata_size) { - OCIAttrSet_log_stat(phs->bndhp, (ub4)OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4)OCI_HTYPE_BIND, phs->array_buf, (ub4)phs->array_buflen, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); @@ -2400,10 +2405,10 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /* Copy array data from array buffer into perl array */ /* Returns false on error, true on success */ -int dbd_phs_number_table_post_exe(phs_t *phs){ +int dbd_phs_number_table_post_exe(imp_sth_t *imp_sth, phs_t *phs){ dTHX; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; if( ( ! SvROK(phs->sv) ) || (SvTYPE(SvRV(phs->sv))!=SVt_PVAV) ) { /* Allow only array binds */ @@ -2411,7 +2416,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ neatsvpv(phs->sv,0), phs->name); } if (trace_level >= 1 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): Called for '%s' : array_numstruct=%d, maxlen=%ld \n", phs->name, phs->array_numstruct, @@ -2457,7 +2462,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ if( item ){ SvSetMagicSV(item,&PL_sv_undef); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): arr[%d] = undef; SvSetMagicSV(item,&PL_sv_undef);\n", i ); @@ -2465,7 +2470,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ }else{ av_store(arr,i,&PL_sv_undef); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): arr[%d] = undef; av_store(arr,i,&PL_sv_undef);\n", i ); @@ -2475,7 +2480,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ if( (phs->array_indicators[i] == -2) || (phs->array_indicators[i] > 0) ){ /* Truncation occurred */ if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): Placeholder '%s': data truncated at %d row.\n", phs->name,i); } @@ -2486,7 +2491,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ switch(phs->ora_internal_type){ case SQLT_INT: if (trace_level >= 4 || dbd_verbose >= 4 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): (int) set arr[%d] = %d \n", i, *(int*)(phs->array_buf+phs->maxlen*i) ); @@ -2495,7 +2500,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ break; case SQLT_FLT: if (trace_level >= 4 || dbd_verbose >= 4 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): (double) set arr[%d] = %lf \n", i, *(double*)(phs->array_buf+phs->maxlen*i) ); @@ -2505,7 +2510,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ if (trace_level >= 3 || dbd_verbose >= 3 ){ STRLEN l; char *str= SvPOK(item) ? SvPV(item,l) : "" ; - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): arr[%d] = '%s'\n", i, str ? str : "" ); @@ -2514,7 +2519,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ switch(phs->ora_internal_type){ case SQLT_INT: if (trace_level >= 4 || dbd_verbose >= 4 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): (int) store new arr[%d] = %d \n", i, *(int*)(phs->array_buf+phs->maxlen*i) ); @@ -2523,7 +2528,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ break; case SQLT_FLT: if (trace_level >= 4 || dbd_verbose >= 4 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): (double) store new arr[%d] = %lf \n", i, *(double*)(phs->array_buf+phs->maxlen*i) ); @@ -2538,7 +2543,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ item=*pitem; } str= item ? ( SvPOK(item) ? SvPV(item,l) : "" ) : ""; - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): arr[%d] = '%s'\n", i, str ? str : "" ); @@ -2548,7 +2553,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ } } if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): scalar(@arr)=%ld.\n", (long)av_len(arr)+1); } @@ -2696,7 +2701,7 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) imp_sth->stmhp, phs->bndhp, imp_sth->errhp, phs->name, imp_sth_csr->stmhp, phs->ftype); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), &imp_sth_csr->stmhp, 0, @@ -2744,18 +2749,18 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) if (!phs->desc_h || 1) { /* XXX phs->desc_t != OCI_HTYPE_STMT) */ if (phs->desc_h) { - OCIHandleFree_log_stat(phs->desc_h, phs->desc_t, status); + OCIHandleFree_log_stat(imp_sth, phs->desc_h, phs->desc_t, status); phs->desc_h = NULL; } phs->desc_t = OCI_HTYPE_STMT; - OCIHandleAlloc_ok(imp_sth->envhp, &phs->desc_h, phs->desc_t, status); + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &phs->desc_h, phs->desc_t, status); } phs->progv = (char*)&phs->desc_h; phs->maxlen = 0; - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), phs->progv, @@ -2864,12 +2869,19 @@ sword status; /* ensure that the value is a support named object type */ /* (currently only OCIXMLType*) */ if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { - OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, - (CONST text*)"SYS", 3, - (CONST text*)"XMLTYPE", 7, - (CONST text*)0, 0, - OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, - &tdo); + /* TO_DO not logging: */ + OCITypeByName_log( + imp_sth, + imp_sth->envhp, + imp_sth->errhp, + imp_sth->svchp, + (CONST text*)"SYS", 3, /* schema_name, schema_length */ + (CONST text*)"XMLTYPE", 7, /* type_name, type_length */ + (CONST text*)0, 0, /* version_name, version_length */ + OCI_DURATION_CALLOUT, /* pin_duration */ + OCI_TYPEGET_HEADER, /* get_option */ + &tdo, /* tdo */ + status); ptr = SvRV(phs->sv); phs->progv = (void*) SvIV(ptr); phs->maxlen = sizeof(OCIXMLType*); @@ -2880,7 +2892,7 @@ sword status; /* bind by name */ - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), (dvoid *) NULL, /* value supplied in BindObject later */ 0, @@ -2974,7 +2986,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) at_exec = (phs->desc_h == NULL); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), phs->progv, phs->maxlen ? (sb4)phs->maxlen : 1, /* else bind "" fails */ @@ -2991,7 +3003,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) return 0; } if (at_exec) { - OCIBindDynamic_log(phs->bndhp, imp_sth->errhp, + OCIBindDynamic_log(imp_sth, phs->bndhp, imp_sth->errhp, (dvoid *)phs, dbd_phs_in, (dvoid *)phs, dbd_phs_out, status); @@ -3022,7 +3034,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (csform) { /* set OCI_ATTR_CHARSET_FORM before we get the default OCI_ATTR_CHARSET_ID */ - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_FORM)")); @@ -3031,7 +3043,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (!phs->csid_orig) { /* get the default csid Oracle would use */ - OCIAttrGet_log_stat(phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , + OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); } @@ -3057,7 +3069,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) (unsigned long)phs->maxlen, (unsigned long)phs->maxdata_size); if (csid) { - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csid, (ub4) 0, (ub4) OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_ID)")); @@ -3066,7 +3078,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (phs->maxdata_size) { - OCIAttrSet_log_stat(phs->bndhp, (ub4)OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4)OCI_HTYPE_BIND, neatsvpv(phs->sv,0), (ub4)phs->maxdata_size, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); @@ -3278,7 +3290,7 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ /* --- functions to 'complete' the fetch of a value --- */ void -dbd_phs_sv_complete(phs_t *phs, SV *sv, I32 debug) +dbd_phs_sv_complete(imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug) { dTHX; char *note = ""; @@ -3356,14 +3368,15 @@ dbd_phs_sv_complete(phs_t *phs, SV *sv, I32 debug) } } void -dbd_phs_avsv_complete(phs_t *phs, I32 index, I32 debug) +dbd_phs_avsv_complete(imp_sth_t *imp_sth, phs_t *phs, I32 index, I32 debug) { dTHX; AV *av = (AV*)SvRV(phs->sv); SV *sv = *av_fetch(av, index, 1); - dbd_phs_sv_complete(phs, sv, 0); + dbd_phs_sv_complete(imp_sth, phs, sv, 0); if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_phs_avsv_complete out '%s'[%ld] = %s (arcode %d, ind %d, len %d)\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " dbd_phs_avsv_complete out '%s'[%ld] = %s (arcode %d, ind %d, len %d)\n", phs->name, (long)index, neatsvpv(sv,0), phs->arcode, phs->indp, phs->alen); } @@ -3473,7 +3486,7 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- "Statement Execute Mode is %d (%s)\n", imp_sth->exe_mode,oci_exe_mode(imp_sth->exe_mode)); - OCIStmtExecute_log_stat(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, + OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, (ub4)(is_select ? 0: 1), 0, 0, 0,(ub4)imp_sth->exe_mode,status); @@ -3534,11 +3547,11 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- phs->name,phs->ftype,sql_typecode_name(phs->ftype)); } if( phs->ftype == ORA_VARCHAR2_TABLE ){ - dbd_phs_varchar_table_posy_exe(phs); + dbd_phs_varchar_table_posy_exe(imp_sth, phs); continue; } if( phs->ftype == ORA_NUMBER_TABLE ){ - dbd_phs_number_table_post_exe(phs); + dbd_phs_number_table_post_exe(imp_sth, phs); continue; } @@ -3551,10 +3564,10 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- AV *av = (AV*)SvRV(sv); I32 avlen = AvFILL(av); if (avlen >= 0) - dbd_phs_avsv_complete(phs, avlen, debug); + dbd_phs_avsv_complete(imp_sth, phs, avlen, debug); } else { - dbd_phs_sv_complete(phs, sv, debug); + dbd_phs_sv_complete(imp_sth, phs, sv, debug); } } } @@ -3578,7 +3591,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat ub2 csid; int trace_level = DBIc_DBISTATE(imp_sth)->debug; int i; - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), 0, phs->maxlen ? (sb4)phs->maxlen : 1, /* else bind "" fails */ @@ -3595,7 +3608,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat } - OCIBindDynamic_log(phs->bndhp, imp_sth->errhp, + OCIBindDynamic_log(imp_sth, phs->bndhp, imp_sth->errhp, (dvoid *)phs, dbd_phs_in, (dvoid *)phs, dbd_phs_out, status); if (status != OCI_SUCCESS) { @@ -3623,7 +3636,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat if (csform) { /* set OCI_ATTR_CHARSET_FORM before we get the default OCI_ATTR_CHARSET_ID */ - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_FORM)")); @@ -3632,7 +3645,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat } if (!phs->csid_orig) { /* get the default csid Oracle would use */ - OCIAttrGet_log_stat(phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , + OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); } @@ -3678,7 +3691,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat (unsigned long)phs->maxlen, (unsigned long)phs->maxdata_size); if (csid) { - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csid, (ub4) 0, (ub4) OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_ID)")); @@ -3900,7 +3913,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er if(autocommit) oci_mode |= OCI_COMMIT_ON_SUCCESS; - OCIStmtExecute_log_stat(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, + OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, exe_count, 0, 0, 0, oci_mode, exe_status); OCIAttrGet_stmhp_stat(imp_sth, &row_count, 0, OCI_ATTR_ROW_COUNT, status); @@ -3922,7 +3935,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er AV *av = (AV*)SvRV(sv); I32 avlen = AvFILL(av); for (j=0;j<=avlen;j++){ - dbd_phs_avsv_complete(phs, j, debug); + dbd_phs_avsv_complete(imp_sth, phs, j, debug); } } } @@ -3946,13 +3959,13 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er err_svs[0] = newSViv((IV)0); err_svs[1] = newSVpvn("", 0); err_svs[2] = newSVpvn("S1000",5); - OCIHandleAlloc_ok(imp_sth->envhp, &row_errhp, OCI_HTYPE_ERROR, status); - OCIHandleAlloc_ok(imp_sth->envhp, &tmp_errhp, OCI_HTYPE_ERROR, status); + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &row_errhp, OCI_HTYPE_ERROR, status); + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &tmp_errhp, OCI_HTYPE_ERROR, status); for(i = 0; (unsigned int) i < num_errs; i++) { - OCIParamGet_log_stat(imp_sth->errhp, OCI_HTYPE_ERROR, + OCIParamGet_log_stat(imp_sth, imp_sth->errhp, OCI_HTYPE_ERROR, tmp_errhp, (dvoid *)&row_errhp, (ub4)i, status); - OCIAttrGet_log_stat(row_errhp, OCI_HTYPE_ERROR, &row_off, 0, + OCIAttrGet_log_stat(imp_sth, row_errhp, OCI_HTYPE_ERROR, &row_off, 0, OCI_ATTR_DML_ROW_OFFSET, imp_sth->errhp, status); if (debug >= 6 || dbd_verbose >= 6 ) PerlIO_printf( @@ -3960,18 +3973,18 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er " ora_st_execute_array error in row %d.\n", row_off); sv_setpv(err_svs[1], ""); - err_code = oci_error_get(row_errhp, exe_status, NULL, err_svs[1], debug); + err_code = oci_error_get((imp_xxh_t *)imp_sth, row_errhp, exe_status, NULL, err_svs[1], debug); sv_setiv(err_svs[0], (IV)err_code); av_store(tuples_status_av, row_off, newRV_noinc((SV *)(av_make(3, err_svs)))); } - OCIHandleFree_log_stat(tmp_errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(row_errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_sth, tmp_errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_sth, row_errhp, OCI_HTYPE_ERROR, status); /* Do a commit here if autocommit is set, since Oracle doesn't do that for us when some rows are in error. */ if(autocommit) { - OCITransCommit_log_stat(imp_sth->svchp, imp_sth->errhp, + OCITransCommit_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCITransCommit"); @@ -4090,7 +4103,7 @@ dbd_st_finish(SV *sth, imp_sth_t *imp_sth) not sure if we need this for non scrolling cursors they should die on a OER(1403) no records)*/ - OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp, 0, + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp, 0, OCI_FETCH_NEXT,0, status); if (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO) { @@ -4117,14 +4130,14 @@ ora_free_fbh_contents(SV *sth, imp_fbh_t *fbh) boolean is_open; sword status; - OCILobFileIsOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, fbh->desc_h, &is_open, status); + OCILobFileIsOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, fbh->desc_h, &is_open, status); if (status == OCI_SUCCESS && is_open) { - OCILobFileClose_log_stat(imp_sth->svchp, imp_sth->errhp, + OCILobFileClose_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, fbh->desc_h, status); } - OCIDescriptorFree_log(fbh->desc_h, fbh->desc_t); + OCIDescriptorFree_log(imp_sth, fbh->desc_h, fbh->desc_t); } if (fbh->obj) { @@ -4136,11 +4149,11 @@ ora_free_fbh_contents(SV *sth, imp_fbh_t *fbh) } void -ora_free_phs_contents(phs_t *phs) +ora_free_phs_contents(imp_sth_t *imp_sth, phs_t *phs) { dTHX; if (phs->desc_h) - OCIDescriptorFree_log(phs->desc_h, phs->desc_t); + OCIDescriptorFree_log(imp_sth, phs->desc_h, phs->desc_t); if( phs->array_buf ){ free(phs->array_buf); phs->array_buf=NULL; @@ -4167,7 +4180,7 @@ ora_free_templob(SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc) #if defined(OCI_HTYPE_DIRPATH_FN_CTX) /* >= 9.0 */ boolean is_temporary = 0; sword status; - OCILobIsTemporary_log_stat(imp_sth->envhp, imp_sth->errhp, lobloc, &is_temporary, status); + OCILobIsTemporary_log_stat(imp_sth, imp_sth->envhp, imp_sth->errhp, lobloc, &is_temporary, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobIsTemporary"); return; @@ -4179,7 +4192,7 @@ ora_free_templob(SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc) DBIc_LOGPIO(imp_sth), " OCILobFreeTemporary %s\n", oci_status_name(status)); } - OCILobFreeTemporary_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, status); + OCILobFreeTemporary_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobloc, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobFreeTemporary"); return; @@ -4208,11 +4221,11 @@ dbd_st_destroy(SV *sth, imp_sth_t *imp_sth) cursor by fetching row 0 */ if (imp_sth->exe_mode==OCI_STMT_SCROLLABLE_READONLY){ - OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp, 0,OCI_FETCH_NEXT,0, status); + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp, 0,OCI_FETCH_NEXT,0, status); } if (imp_sth->dschp){ - OCIHandleFree_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); } @@ -4223,7 +4236,7 @@ dbd_st_destroy(SV *sth, imp_sth_t *imp_sth) if (!PL_dirty) { /* XXX not ideal, leak may be a problem in some cases */ if (!imp_sth->nested_cursor) { - OCIHandleFree_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, status); if (status != OCI_SUCCESS) oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); } @@ -4260,7 +4273,7 @@ dbd_st_destroy(SV *sth, imp_sth_t *imp_sth) phs_t *phs = (phs_t*)(void*)SvPVX(sv); if (phs->desc_h && phs->desc_t == OCI_DTYPE_LOB) ora_free_templob(sth, imp_sth, (OCILobLocator*)phs->desc_h); - ora_free_phs_contents(phs); + ora_free_phs_contents(imp_sth, phs); } } sv_free((SV*)imp_sth->all_params_hv); @@ -4482,9 +4495,8 @@ ora2sql_type(imp_fbh_t* fbh) { } static void -dump_env_to_trace() { +dump_env_to_trace(imp_dbh_t *imp_dbh) { dTHX; - PerlIO *fp = DBILOGFP; int i = 0; char *p; @@ -4496,10 +4508,10 @@ dump_env_to_trace() { #endif - PerlIO_printf(fp, "Environment variables:\n"); + PerlIO_printf(DBIc_LOGPIO(imp_dbh), "Environment variables:\n"); do { - p = (char*)environ[i++]; - PerlIO_printf(fp,"\t%s\n",p); + p = (char*)environ[i++]; + PerlIO_printf(DBIc_LOGPIO(imp_dbh),"\t%s\n",p); } while ((char*)environ[i] != '\0'); } diff --git a/dbdimp.h b/dbdimp.h index 68664a3a..19e6e176 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -320,7 +320,7 @@ extern ub2 al16utf16_csid; void dbd_init_oci _((dbistate_t *dbistate)); void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); -void dbd_fbh_dump(imp_fbh_t *fbh, int i, int aidx); +void dbd_fbh_dump(imp_sth_t *imp_sth, imp_fbh_t *fbh, int i, int aidx); void ora_free_fbh_contents _((SV *sth, imp_fbh_t *fbh)); void ora_free_templob _((SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc)); int ora_dbtype_is_long _((int dbtype)); @@ -329,8 +329,8 @@ fb_ary_t *fb_ary_cb_alloc _((ub4 piece_size,ub4 max_len, int size)); int ora_db_reauthenticate _((SV *dbh, imp_dbh_t *imp_dbh, char *uid, char *pwd)); -void dbd_phs_sv_complete _((phs_t *phs, SV *sv, I32 debug)); -void dbd_phs_avsv_complete _((phs_t *phs, I32 index, I32 debug)); +void dbd_phs_sv_complete _((imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug)); +void dbd_phs_avsv_complete _((imp_sth_t *imp_sth, phs_t *phs, I32 index, I32 debug)); int pp_exec_rset _((SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec)); int pp_rebind_ph_rset_in _((SV *sth, imp_sth_t *imp_sth, phs_t *phs)); @@ -366,8 +366,8 @@ int ora_st_execute_array _((SV *sth, imp_sth_t *imp_sth, SV *tuples, SV * ora_create_xml _((SV *dbh, char *source)); void ora_free_lob_refetch _((SV *sth, imp_sth_t *imp_sth)); -void dbd_phs_avsv_complete _((phs_t *phs, I32 index, I32 debug)); -void dbd_phs_sv_complete _((phs_t *phs, SV *sv, I32 debug)); +void dbd_phs_avsv_complete _((imp_sth_t *imp_sth, phs_t *phs, I32 index, I32 debug)); +void dbd_phs_sv_complete _((imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug)); int post_execute_lobs _((SV *sth, imp_sth_t *imp_sth, ub4 row_count)); ub4 ora_parse_uid _((imp_dbh_t *imp_dbh, char **uidp, char **pwdp)); char *ora_sql_error _((imp_sth_t *imp_sth, char *msg)); diff --git a/oci8.c b/oci8.c index 1f380415..48d00d67 100644 --- a/oci8.c +++ b/oci8.c @@ -109,7 +109,7 @@ oci_ptype_name(int ptype) return SvPVX(sv); } */ - + char * oci_exe_mode(ub4 mode) { @@ -812,7 +812,8 @@ oci_fetch_options(ub4 fetchtype) static sb4 -oci_error_get(OCIError *errhp, sword status, char *what, SV *errstr, int debug) +oci_error_get(imp_xxh_t *imp_xxh, + OCIError *errhp, sword status, char *what, SV *errstr, int debug) { dTHX; text errbuf[1024]; @@ -834,12 +835,13 @@ oci_error_get(OCIError *errhp, sword status, char *what, SV *errstr, int debug) } while( ++recno - && OCIErrorGet_log_stat(errhp, recno, (text*)NULL, &eg_errcode, errbuf, + && OCIErrorGet_log_stat(imp_xxh, errhp, recno, (text*)NULL, &eg_errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR, eg_status) != OCI_NO_DATA && eg_status != OCI_INVALID_HANDLE && recno < 100) { if (debug >= 4 || recno>1/*XXX temp*/) - PerlIO_printf(DBILOGFP, " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", + PerlIO_printf(DBIc_LOGPIO(imp_xxh), + " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", what ? what : "", (long)recno, (eg_status==OCI_SUCCESS) ? "ok" : oci_status_name(eg_status), status, (long)eg_errcode, errbuf); @@ -873,7 +875,8 @@ oci_error_err(SV *h, OCIError *errhp, sword status, char *what, sb4 force_err) sb4 errcode; SV *errstr_sv = sv_newmortal(); SV *errcode_sv = sv_newmortal(); - errcode = oci_error_get(errhp, status, what, errstr_sv, DBIS->debug); + errcode = oci_error_get(imp_xxh, errhp, status, what, errstr_sv, + DBIc_DBISTATE(imp_xxh)->debug); if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { #ifdef sv_utf8_decode sv_utf8_decode(errstr_sv); @@ -1051,14 +1054,14 @@ dbd_st_prepare(SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs) - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_sth->stmhp, OCI_HTYPE_STMT, status); - OCIStmtPrepare_log_stat(imp_sth->stmhp, imp_sth->errhp, + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_sth->stmhp, OCI_HTYPE_STMT, status); + OCIStmtPrepare_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp, (text*)imp_sth->statement, (ub4)strlen(imp_sth->statement), OCI_NTV_SYNTAX, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIStmtPrepare"); - OCIHandleFree_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, status); return 0; } @@ -1066,7 +1069,7 @@ dbd_st_prepare(SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs) OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->stmt_type, 0, OCI_ATTR_STMT_TYPE, status); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_st_prepare'd sql %s ( auto_lob%d, check_sql%d)\n", @@ -1348,9 +1351,9 @@ reg_taf_callback( imp_dbh_t *imp_dbh) tafailover.callback_function = &taf_cbk; /* register the callback */ - OCIAttrSet_log_stat(imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, - (dvoid *) &tafailover, (ub4) 0, - (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, + (dvoid *) &tafailover, (ub4) 0, + (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); return status; } @@ -1427,7 +1430,7 @@ fetch_func_varfield(SV *sth, imp_fbh_t *fbh, SV *dest_sv) return 0; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " fetching field %d of %d. LONG value truncated from " @@ -1454,6 +1457,7 @@ static void fetch_cleanup_rset(SV *sth, imp_fbh_t *fbh) { dTHX; + D_imp_sth(sth); SV *sth_nested = (SV *)fbh->special; fbh->special = NULL; @@ -1468,8 +1472,8 @@ fetch_cleanup_rset(SV *sth, imp_fbh_t *fbh) if (fbh_nested->fetch_cleanup) fbh_nested->fetch_cleanup(sth_nested, fbh_nested); } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_sth), " fetch_cleanup_rset - deactivating handle %s (defunct nested cursor)\n", neatsvpv(sth_nested, 0)); @@ -1490,7 +1494,7 @@ fetch_func_rset(SV *sth, imp_fbh_t *fbh, SV *dest_sv) HV *init_attr = newHV(); int count; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " fetch_func_rset - allocating handle for cursor nested within %s ...\n", @@ -1511,7 +1515,7 @@ fetch_func_rset(SV *sth, imp_fbh_t *fbh, SV *dest_sv) SvREFCNT_dec(init_attr); PUTBACK; FREETMPS; LEAVE; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " fetch_func_rset - ... allocated %s for nested cursor\n", @@ -1547,7 +1551,7 @@ dbd_rebind_ph_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { dTHX; - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_rebind_ph_rset phs->is_inout=%d\n", @@ -1600,11 +1604,11 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (!phs->desc_h) { ++imp_sth->has_lobs; phs->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_sth->envhp, + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &phs->desc_h, phs->desc_t); } - OCIAttrSet_log_stat(phs->desc_h, phs->desc_t, + OCIAttrSet_log_stat(imp_sth, phs->desc_h, phs->desc_t, &lobEmpty, 0, OCI_ATTR_LOBEMPTY, imp_sth->errhp, status); if (status != OCI_SUCCESS) @@ -1635,7 +1639,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) src = INT2PTR(OCILobLocator *, SvIV(SvRV(phs->sv))); dest = (OCILobLocator **) phs->progv; - OCILobLocatorAssign_log_stat(imp_dbh->svchp, imp_sth->errhp, src, dest, status); + OCILobLocatorAssign_log_stat(imp_dbh, imp_dbh->svchp, imp_sth->errhp, src, dest, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobLocatorAssign"); return 0; @@ -1655,7 +1659,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (amtp > 0) { ub1 lobtype = (phs->ftype == 112 ? OCI_TEMP_CLOB : OCI_TEMP_BLOB); - OCILobCreateTemporary_log_stat(imp_dbh->svchp, imp_sth->errhp, + OCILobCreateTemporary_log_stat(imp_dbh, imp_dbh->svchp, imp_sth->errhp, (OCILobLocator *) phs->desc_h, (ub2) OCI_DEFAULT, (ub1) OCI_DEFAULT, lobtype, TRUE, OCI_DURATION_SESSION, status); if (status != OCI_SUCCESS) { @@ -1666,12 +1670,22 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if( ! phs->csid ) { ub1 csform = SQLCS_IMPLICIT; ub2 csid = 0; - OCILobCharSetForm_log_stat( imp_sth->envhp, imp_sth->errhp, (OCILobLocator*)phs->desc_h, &csform, status ); + OCILobCharSetForm_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + (OCILobLocator*)phs->desc_h, + &csform, + status ); if (status != OCI_SUCCESS) return oci_error(sth, imp_sth->errhp, status, "OCILobCharSetForm"); #ifdef OCI_ATTR_CHARSET_ID /* Effectively only used so AL32UTF8 works properly */ - OCILobCharSetId_log_stat( imp_sth->envhp, imp_sth->errhp, (OCILobLocator*)phs->desc_h, &csid, status ); + OCILobCharSetId_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + (OCILobLocator*)phs->desc_h, + &csid, + status ); if (status != OCI_SUCCESS) return oci_error(sth, imp_sth->errhp, status, "OCILobCharSetId"); #endif /* OCI_ATTR_CHARSET_ID */ @@ -1681,7 +1695,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) phs->csform = csform; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " calling OCILobWrite phs->csid=%d phs->csform=%d amtp=%d\n", @@ -1689,7 +1703,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) /* write lob data */ - OCILobWrite_log_stat(imp_sth->svchp, imp_sth->errhp, + OCILobWrite_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, (OCILobLocator*)phs->desc_h, &amtp, 1, SvPVX(phs->sv), amtp, OCI_ONE_PIECE, 0,0, phs->csid, phs->csform, status); if (status != OCI_SUCCESS) { @@ -1722,7 +1736,12 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, */ ub1 csform = SQLCS_IMPLICIT; - OCILobCharSetForm_log_stat( imp_sth->envhp, imp_sth->errhp, lobl, &csform, status ); + OCILobCharSetForm_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + lobl, + &csform, + status ); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobCharSetForm"); sv_set_undef(dest_sv); /* signal error */ @@ -1737,7 +1756,7 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, return 0; } - OCILobGetLength_log_stat(imp_sth->svchp, imp_sth->errhp, + OCILobGetLength_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobl, &loblen, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobGetLength ora_blob_read_mb_piece"); @@ -1758,7 +1777,7 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, New(42, buffer, buflen, ub1); - OCILobRead_log_stat(imp_sth->svchp, imp_sth->errhp, lobl, + OCILobRead_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobl, &amtp, (ub4)1 + offset, buffer, buflen, 0, 0, (ub2)0 ,csform ,status ); /* lab 0, 0, (ub2)0, (ub1)SQLCS_IMPLICIT, status); */ @@ -1842,14 +1861,19 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, return 0; } - OCILobGetLength_log_stat(imp_sth->svchp, imp_sth->errhp, lobl, &loblen, status); + OCILobGetLength_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobl, &loblen, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobGetLength ora_blob_read_piece"); sv_set_undef(dest_sv); /* signal error */ return 0; } - OCILobCharSetForm_log_stat( imp_sth->envhp, imp_sth->errhp, lobl, &csform, status ); + OCILobCharSetForm_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + lobl, + &csform, + status ); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobCharSetForm"); sv_set_undef(dest_sv); /* signal error */ @@ -1892,7 +1916,7 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, buflen = amtp; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " blob_read field %d: ftype %d %s, offset %ld, len %lu." @@ -1904,11 +1928,11 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, ub1 * bufp = (ub1 *)(SvPVX(dest_sv)); bufp += destoffset; - OCILobRead_log_stat(imp_sth->svchp, imp_sth->errhp, lobl, + OCILobRead_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobl, &amtp, (ub4)1 + offset, bufp, buflen, 0, 0, (ub2)0 , csform, status); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu," @@ -1925,7 +1949,7 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, } else { assert(amtp == 0); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, " @@ -1964,7 +1988,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des /* The length is expressed in terms of bytes for BLOBs and BFILEs, */ /* and in terms of characters for CLOBs and NCLOBS */ - OCILobGetLength_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, &loblen, status); + OCILobGetLength_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobloc, &loblen, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobGetLength fetch_lob"); return 0; @@ -2024,7 +2048,12 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des if (loblen > 0) { ub1 csform = 0; - OCILobCharSetForm_log_stat(imp_sth->envhp, imp_sth->errhp, lobloc, &csform, status ); + OCILobCharSetForm_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + lobloc, + &csform, + status ); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobCharSetForm"); sv_set_undef(dest_sv); @@ -2032,7 +2061,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des } if (ftype == ORA_BFILE) { - OCILobFileOpen_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, + OCILobFileOpen_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobloc, (ub1)OCI_FILE_READONLY, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobFileOpen"); @@ -2041,7 +2070,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des } } - OCILobRead_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, + OCILobRead_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobloc, &amtp, (ub4)1, SvPVX(dest_sv), buflen, 0, 0, (ub2)0, csform, status); @@ -2069,7 +2098,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des - if (DBIS->debug >= 3 || dbd_verbose >= 3 || oci_warn){ + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 || oci_warn){ char buf[11]; strcpy(buf,"bytes"); if (ftype == ORA_CLOB) @@ -2085,7 +2114,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des } if (ftype == ORA_BFILE) { - OCILobFileClose_log_stat(imp_sth->svchp, imp_sth->errhp, + OCILobFileClose_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobloc, status); } @@ -2107,7 +2136,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des /* tell perl what we've put in its dest_sv */ SvCUR(dest_sv) = amtp; *SvEND(dest_sv) = '\0'; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " OCILobRead %s %s: LOBlen %lu, LongReadLen %lu, " @@ -2143,18 +2172,18 @@ fetch_func_getrefpv(SV *sth, imp_fbh_t *fbh, SV *dest_sv) #ifdef OCI_DTYPE_REF static void -fbh_setup_getrefpv(imp_fbh_t *fbh, int desc_t, char *bless) +fbh_setup_getrefpv(imp_sth_t *imp_sth, imp_fbh_t *fbh, int desc_t, char *bless) { dTHX; if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), " col %d: otype %d, desctype %d, %s", fbh->field_num, fbh->dbtype, desc_t, bless); fbh->ftype = fbh->dbtype; fbh->disize = fbh->dbsize; fbh->fetch_func = fetch_func_getrefpv; fbh->bless = bless; fbh->desc_t = desc_t; - OCIDescriptorAlloc_ok(fbh->imp_sth->envhp, &fbh->desc_h, fbh->desc_t); + OCIDescriptorAlloc_ok(imp_sth, fbh->imp_sth->envhp, &fbh->desc_h, fbh->desc_t); } #endif @@ -2211,6 +2240,7 @@ calc_cache_rows(int cache_rows, int num_fields, int est_width, int has_longs,ub4 static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeCode typecode, dvoid *attr_value ) { dTHX; + D_imp_sth(sth); text str_buf[200]; double dnum; size_t str_len; @@ -2224,8 +2254,10 @@ static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeC SV *raw_sv; /* get the data based on the type code*/ - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, " getting value of object attribute named %s with typecode=%s\n",name,oci_typecode_name(typecode)); + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " getting value of object attribute named %s with typecode=%s\n", + name,oci_typecode_name(typecode)); } switch (typecode) @@ -2234,13 +2266,14 @@ static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeC case OCI_TYPECODE_INTERVAL_YM : case OCI_TYPECODE_INTERVAL_DS : - OCIIntervalToText_log_stat(fbh->imp_sth->envhp, - fbh->imp_sth->errhp, - attr_value, - str_buf, - (size_t) 200, - &str_len, - status); + OCIIntervalToText_log_stat(fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + attr_value, + str_buf, + (size_t) 200, + &str_len, + status); str_buf[str_len+1] = '\0'; av_push(list, newSVpv( (char *) str_buf,0)); break; @@ -2251,8 +2284,13 @@ static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeC ub4_str_len = 200; - OCIDateTimeToText_log_stat(fbh->imp_sth->envhp, - fbh->imp_sth->errhp,attr_value,&ub4_str_len,str_buf,status); + OCIDateTimeToText_log_stat(fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + attr_value, + &ub4_str_len, + str_buf, + status); if (typecode == OCI_TYPECODE_TIMESTAMP_TZ || typecode == OCI_TYPECODE_TIMESTAMP_LTZ){ char s_tz_hour[3]="000"; @@ -2285,7 +2323,12 @@ static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeC case OCI_TYPECODE_DATE : /* fixed length string*/ ub4_str_len = 200; - OCIDateToText_log_stat(fbh->imp_sth->errhp, (CONST OCIDate *) attr_value,&ub4_str_len,str_buf,status); + OCIDateToText_log_stat(fbh->imp_sth, + fbh->imp_sth->errhp, + (CONST OCIDate *) attr_value, + &ub4_str_len, + str_buf, + status); str_buf[ub4_str_len+1] = '\0'; av_push(list, newSVpv( (char *) str_buf,0)); break; @@ -2373,6 +2416,7 @@ int get_object (SV *sth, AV *list, imp_fbh_t *fbh,fbh_obj_t *base_obj,OCIComplexObject *value, OCIType *instance_tdo, dvoid *obj_ind){ dTHX; + D_imp_sth(sth); sword status; dvoid *element ; dvoid *attr_value; @@ -2388,8 +2432,10 @@ get_object (SV *sth, AV *list, imp_fbh_t *fbh,fbh_obj_t *base_obj,OCIComplexObje OCIType *tdo = instance_tdo ? instance_tdo : obj->tdo; - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, " getting attributes of object named %s with typecode=%s\n",obj->type_name,oci_typecode_name(obj->typecode)); + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " getting attributes of object named %s with typecode=%s\n", + obj->type_name,oci_typecode_name(obj->typecode)); } switch (obj->typecode) { @@ -2417,7 +2463,11 @@ get_object (SV *sth, AV *list, imp_fbh_t *fbh,fbh_obj_t *base_obj,OCIComplexObje return 0; } - OCITypeByRef_log_stat(fbh->imp_sth->envhp,fbh->imp_sth->errhp,type_ref,&tdo,status); + OCITypeByRef_log_stat(fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + type_ref, + &tdo,status); if (status != OCI_SUCCESS) { oci_error(sth, fbh->imp_sth->errhp, status, "OCITypeByRef"); @@ -2441,15 +2491,15 @@ get_object (SV *sth, AV *list, imp_fbh_t *fbh,fbh_obj_t *base_obj,OCIComplexObje } if (tdo != obj->tdo) { /* new subtyped -> get obj description */ - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, " describe subtype (tdo=%p) of object type %s (tdo=%p)\n",(void*)tdo,base_obj->type_name,(void*)base_obj->tdo); + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), " describe subtype (tdo=%p) of object type %s (tdo=%p)\n",(void*)tdo,base_obj->type_name,(void*)base_obj->tdo); } Newz(1, obj->next_subtype, 1, fbh_obj_t); obj->next_subtype->tdo = tdo; if ( describe_obj_by_tdo(sth, fbh->imp_sth, obj->next_subtype, 0 /*unknown level there*/) ) { obj = obj->next_subtype; - if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ){ dump_struct(fbh->imp_sth,obj,0); } } @@ -2458,8 +2508,8 @@ get_object (SV *sth, AV *list, imp_fbh_t *fbh,fbh_obj_t *base_obj,OCIComplexObje } } - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, " getting attributes of object subtype %s\n",obj->type_name); + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), " getting attributes of object subtype %s\n",obj->type_name); } } @@ -2495,11 +2545,23 @@ if the object or any of its properties are NULL, This is one little line in a 20 id only shows you examples with the C struct built in and only a single record. Nowhere does it say you can do it this way. */ - status = OCIObjectGetAttr(fbh->imp_sth->envhp, fbh->imp_sth->errhp, value, - obj_ind, tdo, - (CONST oratext**)&fld->type_name, &fld->type_namel, 1, - (ub4 *)0, 0, &attr_null_status, &attr_null_struct, - &attr_value, &attr_tdo); + OCIObjectGetAttr_log_stat( + fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + value, /* instance */ + obj_ind, /* null_struct */ + tdo, /* tdo */ + (CONST oratext**)&fld->type_name, /* names */ + &fld->type_namel, /* lengths */ + 1, /* name_count */ + (ub4 *)0, /* indexes */ + 0, /* index_count */ + &attr_null_status, /* attr_null_status */ + &attr_null_struct, /* attr_null_struct */ + &attr_value, /* attr_value */ + &attr_tdo, /* attr_tdo */ + status); if (status != OCI_SUCCESS) { oci_error(sth, fbh->imp_sth->errhp, status, "OCIObjectGetAttr"); @@ -2538,8 +2600,12 @@ id only shows you examples with the C struct built in and only a single record. case OCI_TYPECODE_TABLE : /* nested table */ case OCI_TYPECODE_VARRAY : /* variable array */ fld = &obj->fields[0]; /*get the field */ - OCIIterCreate_log_stat(fbh->imp_sth->envhp, fbh->imp_sth->errhp, - (OCIColl*) value, &itr,status); + OCIIterCreate_log_stat(fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + (OCIColl*) value, + &itr, + status); if (status != OCI_SUCCESS) { /*not really an error just no data oci_error(sth, fbh->imp_sth->errhp, status, "OCIIterCreate");*/ @@ -2567,8 +2633,11 @@ id only shows you examples with the C struct built in and only a single record. } /*nasty surprise here. one has to get rid of the iterator or you will leak memory not documented in oci or in demos */ - OCIIterDelete_log_stat( fbh->imp_sth->envhp, - fbh->imp_sth->errhp, &itr,status ); + OCIIterDelete_log_stat(fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + &itr, + status ); if (status != OCI_SUCCESS) { oci_error(sth, fbh->imp_sth->errhp, status, "OCIIterDelete"); return 0; @@ -2597,8 +2666,12 @@ static int fetch_func_oci_object(SV *sth, imp_fbh_t *fbh,SV *dest_sv) { dTHX; - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf(DBILOGFP, " getting an embedded object named %s with typecode=%s\n",fbh->obj->type_name,oci_typecode_name(fbh->obj->typecode)); + D_imp_sth(sth); + + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " getting an embedded object named %s with typecode=%s\n", + fbh->obj->type_name,oci_typecode_name(fbh->obj->typecode)); } if (fbh->obj->obj_ind && fbh->obj->obj_ind[0] == OCI_IND_NULL) { @@ -2630,14 +2703,22 @@ fetch_clbk_lob(SV *sth, imp_fbh_t *fbh,SV *dest_sv){ ub4 actual_bufl=imp_sth->piece_size*(fb_ary->piece_count)+fb_ary->bufl; if (fb_ary->piece_count==0){ - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) - PerlIO_printf(DBILOGFP," Fetch persistent lob of %d (char/bytes) with callback in 1 piece of %d (Char/Bytes)\n",actual_bufl,fb_ary->bufl); + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Fetch persistent lob of %d (char/bytes) with callback in 1 " + "piece of %d (Char/Bytes)\n", + actual_bufl,fb_ary->bufl); memcpy(fb_ary->cb_abuf,fb_ary->abuf,fb_ary->bufl ); } else { - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) - PerlIO_printf(DBILOGFP," Fetch persistent lob of %d (Char/Bytes) with callback in %d piece(s) of %d (Char/Bytes) and one piece of %d (Char/Bytes)\n",actual_bufl,fb_ary->piece_count,fbh->piece_size,fb_ary->bufl); + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Fetch persistent lob of %d (Char/Bytes) with callback in %d " + "piece(s) of %d (Char/Bytes) and one piece of %d (Char/Bytes)\n", + actual_bufl,fb_ary->piece_count,fbh->piece_size,fb_ary->bufl); memcpy(fb_ary->cb_abuf+imp_sth->piece_size*(fb_ary->piece_count),fb_ary->abuf,fb_ary->bufl ); } @@ -2671,21 +2752,22 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) ub2 rcode = 0; sword status = OCI_NEED_DATA; - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) { PerlIO_printf(DBIc_LOGPIO(imp_sth), "in fetch_get_piece \n"); } while (status == OCI_NEED_DATA){ - OCIStmtGetPieceInfo_log_stat(fbh->imp_sth->stmhp, - fbh->imp_sth->errhp, - &hdlptr, - &hdltype, - &in_out, - &iter, - &idx, - &piece, - status); + OCIStmtGetPieceInfo_log_stat(fbh->imp_sth, + fbh->imp_sth->stmhp, + fbh->imp_sth->errhp, + &hdlptr, + &hdltype, + &in_out, + &iter, + &idx, + &piece, + status); /* This is how this works First we get the piece Info above @@ -2700,7 +2782,8 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) */ if ( hdlptr==fbh->defnp){ - OCIStmtSetPieceInfo_log_stat(fbh->defnp, + OCIStmtSetPieceInfo_log_stat(fbh->imp_sth, + fbh->defnp, fbh->imp_sth->errhp, fb_ary->abuf, &buflen, @@ -2709,7 +2792,7 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) &rcode,status); - OCIStmtFetch_log_stat(fbh->imp_sth->stmhp,fbh->imp_sth->errhp,1,(ub2)OCI_FETCH_NEXT,OCI_DEFAULT,status); + OCIStmtFetch_log_stat(fbh->imp_sth, fbh->imp_sth->stmhp,fbh->imp_sth->errhp,1,(ub2)OCI_FETCH_NEXT,OCI_DEFAULT,status); if (status==OCI_SUCCESS_WITH_INFO && !DBIc_has(fbh->imp_sth,DBIcf_LongTruncOk)){ @@ -2727,7 +2810,7 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) } - if (DBIS->debug >= 6 || dbd_verbose >= 6 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ){ if (fb_ary->piece_count==1){ PerlIO_printf( DBIc_LOGPIO(imp_sth), @@ -2815,6 +2898,8 @@ empty_oci_object(fbh_obj_t *obj){ static void fetch_cleanup_pres_lobs(SV *sth,imp_fbh_t *fbh){ dTHX; + D_imp_sth(sth); + fb_ary_t *fb_ary = fbh->fb_ary; if( sth ) { /* For GCC not to warn on unused parameter*/ } @@ -2824,8 +2909,8 @@ fetch_cleanup_pres_lobs(SV *sth,imp_fbh_t *fbh){ fb_ary->cb_bufl=fbh->disize; /*reset this back to the max size for the fetch*/ memset( fb_ary->cb_abuf, '\0', fbh->disize ); /*clean out the call back buffer*/ - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) - PerlIO_printf(DBILOGFP," fetch_cleanup_pres_lobs \n"); + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) + PerlIO_printf(DBIc_LOGPIO(imp_sth)," fetch_cleanup_pres_lobs \n"); return; } @@ -2833,6 +2918,7 @@ fetch_cleanup_pres_lobs(SV *sth,imp_fbh_t *fbh){ static void fetch_cleanup_oci_object(SV *sth, imp_fbh_t *fbh){ dTHX; + D_imp_sth(sth); if( sth ) { /* For GCC not to warn on unused parameter*/ } @@ -2842,8 +2928,8 @@ fetch_cleanup_oci_object(SV *sth, imp_fbh_t *fbh){ } } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP," fetch_cleanup_oci_object \n"); + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_sth)," fetch_cleanup_oci_object \n"); return; } @@ -2856,7 +2942,7 @@ void rs_array_init(imp_sth_t *imp_sth) imp_sth->rs_fetch_count =0; imp_sth->rs_array_status =OCI_SUCCESS; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " rs_array_init:imp_sth->rs_array_size=%d, rs_array_idx=%d, " @@ -2950,7 +3036,7 @@ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, /* is prefetch_rows are greater than the RowCahceSize then use prefetch_rows*/ } - OCIAttrSet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, + OCIAttrSet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, &prefetch_mem, sizeof(prefetch_mem), OCI_ATTR_PREFETCH_MEMORY, imp_sth->errhp, status); @@ -2960,7 +3046,7 @@ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, ++num_errors; } - OCIAttrSet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, + OCIAttrSet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, &prefetch_rows, sizeof(prefetch_rows), OCI_ATTR_PREFETCH_ROWS, imp_sth->errhp, status); @@ -2988,7 +3074,7 @@ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, - if (DBIS->debug >= 3 || dbd_verbose >= 3 || oci_warn) /*will also display if oci_warn is on*/ + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 || oci_warn) /*will also display if oci_warn is on*/ PerlIO_printf( DBIc_LOGPIO(imp_sth), " cache settings DB Handle RowCacheSize=%d,Statement Handle " @@ -3011,7 +3097,7 @@ describe_obj(SV *sth,imp_sth_t *imp_sth,OCIParam *parm,fbh_obj_t *obj,int level sword status; OCIRef *type_ref; - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "At level=%d in description an embedded object \n",level); @@ -3026,7 +3112,12 @@ describe_obj(SV *sth,imp_sth_t *imp_sth,OCIParam *parm,fbh_obj_t *obj,int level return 0; } - OCITypeByRef_log_stat(imp_sth->envhp,imp_sth->errhp,type_ref,&obj->tdo,status); + OCITypeByRef_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + type_ref, + &obj->tdo, + status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCITypeByRef"); @@ -3044,7 +3135,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { ub4 type_namel, schema_namel; - OCIDescribeAny_log_stat(imp_sth->svchp,imp_sth->errhp,obj->tdo,(ub4)0,OCI_OTYPE_PTR,(ub1)1,OCI_PTYPE_TYPE,imp_sth->dschp,status); + OCIDescribeAny_log_stat(imp_sth, imp_sth->svchp,imp_sth->errhp,obj->tdo,(ub4)0,OCI_OTYPE_PTR,(ub1)1,OCI_PTYPE_TYPE,imp_sth->dschp,status); /*we have the Actual TDO so lets see what it is made up of by a describe*/ if (status != OCI_SUCCESS) { @@ -3090,7 +3181,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { return 0; } - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "Getting the properties of object named =%s at level %d typecode=%d\n", @@ -3100,7 +3191,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { if (obj->typecode == OCI_TYPECODE_OBJECT || obj->typecode == OCI_TYPECODE_OPAQUE){ OCIParam *list_attr= (OCIParam *) 0; ub2 pos; - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "Object named =%s at level %d is an Object\n", @@ -3115,7 +3206,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { } /*we will need a reff to the TDO for the pin operation*/ - OCIObjectPin_log_stat(imp_sth->envhp,imp_sth->errhp, obj->obj_ref,(dvoid **)&obj->obj_type,status); + OCIObjectPin_log_stat(imp_sth, imp_sth->envhp,imp_sth->errhp, obj->obj_ref,(dvoid **)&obj->obj_type,status); if (status != OCI_SUCCESS) { oci_error(sth,imp_sth->errhp, status, "OCIObjectPin"); @@ -3152,7 +3243,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { OCIParam *parmdf= (OCIParam *) 0; fbh_obj_t *fld = &obj->fields[pos-1]; /*get the field holder*/ - OCIParamGet_log_stat((dvoid *) list_attr,(ub4) OCI_DTYPE_PARAM, imp_sth->errhp,(dvoid *)&parmdf, (ub4) pos ,status); + OCIParamGet_log_stat(imp_sth, (dvoid *) list_attr,(ub4) OCI_DTYPE_PARAM, imp_sth->errhp,(dvoid *)&parmdf, (ub4) pos ,status); if (status != OCI_SUCCESS) { oci_error(sth,imp_sth->errhp, status, "OCIParamGet"); @@ -3175,7 +3266,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { return 0; } - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "Getting property #%d, named=%s and its typecode is %d \n", @@ -3192,7 +3283,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { } else { /*well this is an embedded table or varray of some form so find out what is in it*/ - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "Object named =%s at level %d is an Varray or Table\n", @@ -3315,7 +3406,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (imp_sth->stmt_type != OCI_STMT_SELECT) { /* XXX DISABLED, see num_fields test below */ - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_describe skipped for %s\n", @@ -3324,7 +3415,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) return 1; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_describe %s (%s, lb %lu)...\n", @@ -3335,7 +3426,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) /* sth is not 'active' (executing) then we need an explicit describe. */ if ( !DBIc_ACTIVE(imp_sth) ) { - OCIStmtExecute_log_stat(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, + OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, 0, 0, 0, 0, OCI_DESCRIBE_ONLY, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, @@ -3350,7 +3441,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) return 0; } if (num_fields == 0) { - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_describe skipped for %s (no fields returned)\n", @@ -3374,7 +3465,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->field_num = i; fbh->define_mode = OCI_DEFAULT; - OCIParamGet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, + OCIParamGet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, (dvoid**)&fbh->parmdp, (ub4)i, status); if (status != OCI_SUCCESS) { @@ -3413,7 +3504,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->name = SvPVX(fbh->name_sv); fbh->ftype = 5; /* default: return as null terminated string */ - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), "Describe col #%d type=%d(%s)\n", @@ -3555,7 +3646,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->fetch_cleanup = fetch_cleanup_oci_object; /* clean up any AV from the fetch*/ fbh->desc_t = SQLT_NTY; if (!imp_sth->dschp){ - OCIHandleAlloc_ok(imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); if (status != OCI_SUCCESS) { oci_error(h,imp_sth->errhp, status, "OCIHandleAlloc"); ++num_errors; @@ -3636,7 +3727,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->bless = "OCILobLocatorPtr"; fbh->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_sth->envhp, &fbh->desc_h, fbh->desc_t); + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &fbh->desc_h, fbh->desc_t); } @@ -3645,7 +3736,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) #ifdef OCI_DTYPE_REF case 111: /* REF */ - fbh_setup_getrefpv(fbh, OCI_DTYPE_REF, "OCIRefPtr"); + fbh_setup_getrefpv(imp_sth, fbh, OCI_DTYPE_REF, "OCIRefPtr"); break; #endif @@ -3675,14 +3766,14 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->ftype = fbh->dbtype; fbh->disize = fbh->dbsize; p = "Field %d has an Oracle type (%d) which is not explicitly supported%s"; - if (DBIS->debug >= 1 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 1 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), p, i, fbh->dbtype, "\n"); if (PL_dowarn) warn(p, i, fbh->dbtype, ""); break; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, " @@ -3705,8 +3796,8 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) est_width += avg_width; - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - dbd_fbh_dump(fbh, (int)i, 0); + if (DBIc_DBISTATE(imp_sth)->debug >= 2 || dbd_verbose >= 3 ) + dbd_fbh_dump(imp_sth, fbh, (int)i, 0); }/* end define of filed struct[i] fbh*/ @@ -3745,12 +3836,12 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) } if (fbh->ftype == ORA_RSET) { /* RSET */ - OCIHandleAlloc_ok(imp_sth->envhp, + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, (dvoid*)&((OCIStmt **)fb_ary->abuf)[0], OCI_HTYPE_STMT, status); } - OCIDefineByPos_log_stat(imp_sth->stmhp, + OCIDefineByPos_log_stat(imp_sth, imp_sth->stmhp, &fbh->defnp, imp_sth->errhp, (ub4) i, @@ -3766,11 +3857,11 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (fbh->clbk_lob){ /* use a dynamic callback for persistent binary and char lobs*/ - OCIDefineDynamic_log_stat(fbh->defnp,imp_sth->errhp,(dvoid *) fbh,status); + OCIDefineDynamic_log_stat(imp_sth, fbh->defnp,imp_sth->errhp,(dvoid *) fbh,status); } if (fbh->ftype == 108) { /* Embedded object bind it differently*/ - if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ){ PerlIO_printf( DBIc_LOGPIO(imp_sth), "Field #%d is a object or colection of some sort. " @@ -3782,10 +3873,10 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) ++num_errors; } - if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ){ dump_struct(imp_sth,fbh->obj,0); } - OCIDefineObject_log_stat(fbh->defnp,imp_sth->errhp,fbh->obj->tdo,(dvoid**)&fbh->obj->obj_value,(dvoid**)&fbh->obj->obj_ind,status); + OCIDefineObject_log_stat(imp_sth,fbh->defnp,imp_sth->errhp,fbh->obj->tdo,(dvoid**)&fbh->obj->obj_value,(dvoid**)&fbh->obj->obj_ind,status); if (status != OCI_SUCCESS) { oci_error(h,imp_sth->errhp, status, "OCIDefineObject"); @@ -3803,12 +3894,12 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) #ifdef OCI_ATTR_CHARSET_FORM if ( (fbh->dbtype == 1) && fbh->csform ) { /* csform may be 0 when talking to Oracle 8.0 database*/ - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " calling OCIAttrSet OCI_ATTR_CHARSET_FORM with csform=%d (%s)\n", fbh->csform,oci_csform_name(fbh->csform) ); - OCIAttrSet_log_stat( fbh->defnp, (ub4) OCI_HTYPE_DEFINE, (dvoid *) &fbh->csform, + OCIAttrSet_log_stat(imp_sth, fbh->defnp, (ub4) OCI_HTYPE_DEFINE, (dvoid *) &fbh->csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status ); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_CHARSET_FORM"); @@ -3819,7 +3910,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_describe'd %d columns (row bytes: %d max, %d est avg, cache: %d)\n", @@ -3864,7 +3955,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ status = OCI_SUCCESS; } else { - if (DBIS->debug >= 3 || dbd_verbose >= 3 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ){ PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_st_fetch %d fields...\n", DBIc_NUM_FIELDS(imp_sth)); @@ -3874,7 +3965,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (imp_sth->exe_mode!=OCI_STMT_SCROLLABLE_READONLY) croak ("attempt to use a scrollable cursor without first setting ora_exe_mode to OCI_STMT_SCROLLABLE_READONLY\n") ; - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " Scrolling Fetch, postion before fetch=%d, " @@ -3882,12 +3973,12 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_sth->fetch_position, oci_fetch_options(imp_sth->fetch_orient), imp_sth->fetch_offset); - OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp,1, imp_sth->fetch_orient,imp_sth->fetch_offset, status); + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp,1, imp_sth->fetch_orient,imp_sth->fetch_offset, status); /*this will work without a round trip so might as well open it up for all statments handles*/ /* defualt and OCI_FETCH_NEXT are the same so this avoids miscaluation on the next value*/ OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->fetch_position, 0, OCI_ATTR_CURRENT_POSITION, status); - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " Scrolling Fetch, postion after fetch=%d\n", @@ -3896,7 +3987,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ else { if (imp_sth->row_cache_off){ /*Do not use array fetch or local cache */ - OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp,1,(ub2)OCI_FETCH_NEXT, OCI_DEFAULT, status); + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp,1,(ub2)OCI_FETCH_NEXT, OCI_DEFAULT, status); imp_sth->rs_fetch_count++; imp_sth->rs_array_idx=0; @@ -3908,7 +3999,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (imp_sth->rs_array_num_rows<=imp_sth->rs_array_idx && (imp_sth->rs_array_status==OCI_SUCCESS || imp_sth->rs_array_status==OCI_SUCCESS_WITH_INFO)) { /* PerlIO_printf(DBIc_LOGPIO(imp_sth), " dbd_st_fetch fields...b\n");*/ - OCIStmtFetch_log_stat(imp_sth->stmhp,imp_sth->errhp,imp_sth->rs_array_size,(ub2)OCI_FETCH_NEXT,OCI_DEFAULT,status); + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp,imp_sth->errhp,imp_sth->rs_array_size,(ub2)OCI_FETCH_NEXT,OCI_DEFAULT,status); imp_sth->rs_array_status=status; imp_sth->rs_fetch_count++; @@ -3920,7 +4011,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_dbh->RowsInCache =imp_sth->rs_array_size; imp_sth->RowsInCache =imp_sth->rs_array_size; - if (DBIS->debug >= 4 || dbd_verbose >= 4 || oci_warn) + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 || oci_warn) PerlIO_printf( DBIc_LOGPIO(imp_sth), "...Fetched %d rows\n",imp_sth->rs_array_num_rows); @@ -3946,7 +4037,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (status == OCI_NO_DATA) { dTHR; /* for DBIc_ACTIVE_off */ DBIc_ACTIVE_off(imp_sth); /* eg finish */ - if (DBIS->debug >= 3 || dbd_verbose >= 3 || oci_warn) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 || oci_warn) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_st_fetch no-more-data, fetch count=%d\n", @@ -3968,9 +4059,9 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ /* per-field rcode value be dealt with as we fetch the data */ } - av = DBIS->get_fbav(imp_sth); + av = DBIc_DBISTATE(imp_sth)->get_fbav(imp_sth); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_st_fetched %d fields with status of %d(%s)\n", @@ -3988,7 +4079,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */; - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), " field #%d with rc=%d(%s)\n",i+1,rc,oci_col_return_codes(rc)); @@ -4110,7 +4201,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ oci_error(sth, imp_sth->errhp, OCI_ERROR, buf); } - if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ){ PerlIO_printf( DBIc_LOGPIO(imp_sth), "\n %p (field=%d): %s\n", av, i,neatsvpv(sv,10)); @@ -4140,21 +4231,21 @@ ora_parse_uid(imp_dbh_t *imp_dbh, char **uidp, char **pwdp) } #ifdef ORA_OCI_112 if (imp_dbh->using_drcp){ - OCIAttrSet_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION, *uidp, strlen(*uidp), (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp, status); - OCIAttrSet_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION, (strlen(*pwdp)) ? *pwdp : NULL, strlen(*pwdp), (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp, status); } else { #endif - OCIAttrSet_log_stat(imp_dbh->seshp, OCI_HTYPE_SESSION, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, *uidp, strlen(*uidp), (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp, status); - OCIAttrSet_log_stat(imp_dbh->seshp, OCI_HTYPE_SESSION, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, (strlen(*pwdp)) ? *pwdp : NULL, strlen(*pwdp), (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp, status); #ifdef ORA_OCI_112 @@ -4171,9 +4262,9 @@ ora_db_reauthenticate(SV *dbh, imp_dbh_t *imp_dbh, char *uid, char *pwd) sword status; /* XXX should possibly create new session before ending the old so */ /* that if the new one can't be created, the old will still work. */ - OCISessionEnd_log_stat(imp_dbh->svchp, imp_dbh->errhp, + OCISessionEnd_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, OCI_DEFAULT, status); /* XXX check status here?*/ - OCISessionBegin_log_stat( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, + OCISessionBegin_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, ora_parse_uid(imp_dbh, &uid, &pwd), (ub4) OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); @@ -4317,14 +4408,14 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) "Unable to parse table name for LOB refetch"); if (!imp_sth->dschp){ - OCIHandleAlloc_ok(imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); if (status != OCI_SUCCESS) { oci_error(sth,imp_sth->errhp, status, "OCIHandleAlloc"); } } - OCIDescribeAny_log_stat(imp_sth->svchp, errhp, tablename, strlen(tablename), + OCIDescribeAny_log_stat(imp_sth, imp_sth->svchp, errhp, tablename, strlen(tablename), (ub1)OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_SYN, imp_sth->dschp, status); if (status == OCI_SUCCESS) { /* There is a synonym, get the schema */ @@ -4335,14 +4426,14 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) strncpy(syn_name,tablename,strlen(tablename)); /* Put the synonym name here for later user */ - OCIAttrGet_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, + OCIAttrGet_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, &parmhp, 0, OCI_ATTR_PARAM, errhp, status); - OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM, + OCIAttrGet_log_stat(imp_sth, parmhp, OCI_DTYPE_PARAM, &syn_schema, &syn_schema_len, OCI_ATTR_SCHEMA_NAME, errhp, status); - OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM, + OCIAttrGet_log_stat(imp_sth, parmhp, OCI_DTYPE_PARAM, &tablename, &tn_len, OCI_ATTR_NAME, errhp, status); strncpy(new_tablename,syn_schema,syn_schema_len); @@ -4352,7 +4443,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) tablename=new_tablename; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch using a synonym named=%s for %s \n", @@ -4360,38 +4451,38 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } - OCIDescribeAny_log_stat(imp_sth->svchp, errhp, tablename, strlen(tablename), + OCIDescribeAny_log_stat(imp_sth, imp_sth->svchp, errhp, tablename, strlen(tablename), (ub1)OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_TABLE, imp_sth->dschp, status); if (status != OCI_SUCCESS) { /* XXX this OCI_PTYPE_TABLE->OCI_PTYPE_VIEW fallback should actually be */ /* a loop that includes synonyms etc */ - OCIDescribeAny_log_stat(imp_sth->svchp, errhp, tablename, strlen(tablename), + OCIDescribeAny_log_stat(imp_sth, imp_sth->svchp, errhp, tablename, strlen(tablename), (ub1)OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_VIEW, imp_sth->dschp, status); if (status != OCI_SUCCESS) { - OCIHandleFree_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); return oci_error(sth, errhp, status, "OCIDescribeAny(view)/LOB refetch"); } } - OCIAttrGet_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, + OCIAttrGet_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, &parmhp, 0, OCI_ATTR_PARAM, errhp, status); if (!status ) { - OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM, + OCIAttrGet_log_stat(imp_sth, parmhp, OCI_DTYPE_PARAM, &numcols, 0, OCI_ATTR_NUM_COLS, errhp, status); } if (!status ) { - OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM, + OCIAttrGet_log_stat(imp_sth, parmhp, OCI_DTYPE_PARAM, &collisthd, 0, OCI_ATTR_LIST_COLUMNS, errhp, status); } if (status != OCI_SUCCESS) { - OCIHandleFree_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); return oci_error(sth, errhp, status, "OCIDescribeAny/OCIAttrGet/LOB refetch"); } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch from table %s, %d columns:\n", @@ -4401,21 +4492,21 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) ub2 col_dbtype; char *col_name; ub4 col_name_len; - OCIParamGet_log_stat(collisthd, OCI_DTYPE_PARAM, errhp, (dvoid**)&colhd, i, status); + OCIParamGet_log_stat(imp_sth, collisthd, OCI_DTYPE_PARAM, errhp, (dvoid**)&colhd, i, status); if (status) break; - OCIAttrGet_log_stat(colhd, OCI_DTYPE_PARAM, &col_dbtype, 0, + OCIAttrGet_log_stat(imp_sth, colhd, OCI_DTYPE_PARAM, &col_dbtype, 0, OCI_ATTR_DATA_TYPE, errhp, status); if (status) break; - OCIAttrGet_log_stat(colhd, OCI_DTYPE_PARAM, &col_name, &col_name_len, + OCIAttrGet_log_stat(imp_sth, colhd, OCI_DTYPE_PARAM, &col_name, &col_name_len, OCI_ATTR_NAME, errhp, status); if (status) break; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch table col %d: '%.*s' otype %d\n", @@ -4435,17 +4526,17 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) (void)SvIOK_on(sv); /* "what a wonderful hack!" */ (void)hv_store(lob_cols_hv, col_name,col_name_len, sv,0); - OCIDescriptorFree(colhd, OCI_DTYPE_PARAM); + OCIDescriptorFree_log(imp_sth, colhd, OCI_DTYPE_PARAM); colhd = NULL; } if (colhd) - OCIDescriptorFree(colhd, OCI_DTYPE_PARAM); + OCIDescriptorFree_log(imp_sth, colhd, OCI_DTYPE_PARAM); if (status != OCI_SUCCESS) { oci_error(sth, errhp, status, "OCIDescribeAny/OCIParamGet/OCIAttrGet/LOB refetch"); - OCIHandleFree_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); return 0; } @@ -4498,7 +4589,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) while( (sv_other = hv_iternextsv(lob_cols_hv, &p_other, &i)) != NULL ) { if (phs->ftype != SvIV(sv_other)) continue; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " both %s and %s have type %d - ambiguous\n", @@ -4517,7 +4608,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) (SvCUR(sql_select)>7)?", ":"", p, &phs->name[1]); sv_catpv(sql_select, sql_field); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch %s param: otype %d, matched field '%s' %s(%s)\n", @@ -4530,14 +4621,14 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) fbh->dbtype = phs->ftype; fbh->disize = 99; fbh->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_sth->envhp, &fbh->desc_h, fbh->desc_t); + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &fbh->desc_h, fbh->desc_t); break; /* we're done with this placeholder now */ } if (!matched) { ++unmatched_params; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch %s param: otype %d, UNMATCHED\n", @@ -4555,7 +4646,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) sv_catpv(sql_select, " from "); sv_catpv(sql_select, tablename); sv_catpv(sql_select, " where rowid = :rid for update"); /* get row with lock */ - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch sql: %s\n", SvPVX(sql_select)); @@ -4564,8 +4655,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) lr->rowid = NULL; lr->parmdp_tmp = NULL; lr->parmdp_lob = NULL; - OCIHandleAlloc_ok(imp_sth->envhp, &lr->stmthp, OCI_HTYPE_STMT, status); - OCIStmtPrepare_log_stat(lr->stmthp, errhp, + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &lr->stmthp, OCI_HTYPE_STMT, status); + OCIStmtPrepare_log_stat(imp_sth, lr->stmthp, errhp, (text*)SvPVX(sql_select), SvCUR(sql_select), OCI_NTV_SYNTAX, OCI_DEFAULT, status); @@ -4576,11 +4667,11 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } /* bind the rowid input */ - OCIDescriptorAlloc_ok(imp_sth->envhp, &lr->rowid, OCI_DTYPE_ROWID); - OCIBindByName_log_stat(lr->stmthp, &lr->bindhp, errhp, (text*)":rid", 4, + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &lr->rowid, OCI_DTYPE_ROWID); + OCIBindByName_log_stat(imp_sth, lr->stmthp, &lr->bindhp, errhp, (text*)":rid", 4, &lr->rowid, sizeof(OCIRowid*), SQLT_RDD, 0,0,0,0,0, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { - OCIDescriptorFree(lr->rowid, OCI_DTYPE_ROWID); + OCIDescriptorFree_log(imp_sth, lr->rowid, OCI_DTYPE_ROWID); OCIHandleFree(lr->stmthp, OCI_HTYPE_STMT); Safefree(lr); return oci_error(sth, errhp, status, "OCIBindByPos/LOB refetch"); @@ -4596,17 +4687,17 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) croak("panic: LOB refetch for '%s' param (%ld) - name not found",fbh->name,(unsigned long)i+1); phs = (phs_t*)(void*)SvPVX(*phs_svp); fbh->special = phs; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch %d for '%s' param: ftype %d setup\n", (int)i+1,fbh->name, fbh->dbtype); fbh->fb_ary = fb_ary_alloc(fbh->disize, 1); - OCIDefineByPos_log_stat(lr->stmthp, &defnp, errhp, (ub4)i+1, + OCIDefineByPos_log_stat(imp_sth, lr->stmthp, &defnp, errhp, (ub4)i+1, &fbh->desc_h, -1, (ub2)fbh->ftype, fbh->fb_ary->aindp, 0, fbh->fb_ary->arcode, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { - OCIDescriptorFree(lr->rowid, OCI_DTYPE_ROWID); + OCIDescriptorFree_log(imp_sth, lr->rowid, OCI_DTYPE_ROWID); OCIHandleFree(lr->stmthp, OCI_HTYPE_STMT); Safefree(lr); fb_ary_free(fbh->fb_ary); @@ -4615,7 +4706,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } } - OCIHandleFree_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); imp_sth->lob_refetch = lr; /* structure copy */ return 1; @@ -4652,7 +4743,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl if (phs->desc_h && !phs->is_inout){ - OCILobFreeTemporary_log_stat(imp_sth->svchp, imp_sth->errhp, phs->desc_h, status); + OCILobFreeTemporary_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, phs->desc_h, status); /* boolean lobEmpty=1;*/ @@ -4682,7 +4773,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCIAttrGet OCI_ATTR_ROWID /LOB refetch"); - OCIStmtExecute_log_stat(imp_sth->svchp, lr->stmthp, errhp,1, 0, NULL, NULL, OCI_DEFAULT, status); /* execute and fetch */ + OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, lr->stmthp, errhp,1, 0, NULL, NULL, OCI_DEFAULT, status); /* execute and fetch */ if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, @@ -4706,12 +4797,22 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl if( ! fbh->csid ) { ub1 csform = SQLCS_IMPLICIT; ub2 csid = 0; - OCILobCharSetForm_log_stat( imp_sth->envhp, errhp, (OCILobLocator*)fbh->desc_h, &csform, status ); + OCILobCharSetForm_log_stat(imp_sth, + imp_sth->envhp, + errhp, + (OCILobLocator*)fbh->desc_h, + &csform, + status ); if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCILobCharSetForm"); #ifdef OCI_ATTR_CHARSET_ID /* Effectively only used so AL32UTF8 works properly */ - OCILobCharSetId_log_stat( imp_sth->envhp, errhp, (OCILobLocator*)fbh->desc_h, &csid, status ); + OCILobCharSetId_log_stat(imp_sth, + imp_sth->envhp, + errhp, + (OCILobLocator*)fbh->desc_h, + &csid, + status ); if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCILobCharSetId"); #endif /* OCI_ATTR_CHARSET_ID */ @@ -4721,13 +4822,13 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl fbh->csform = csform; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " calling OCILobWrite fbh->csid=%d fbh->csform=%d amtp=%d\n", fbh->csid, fbh->csform, amtp ); - OCILobWrite_log_stat(imp_sth->svchp, errhp, + OCILobWrite_log_stat(imp_sth, imp_sth->svchp, errhp, (OCILobLocator*)fbh->desc_h, &amtp, 1, SvPVX(phs->sv), amtp, OCI_ONE_PIECE, 0,0, fbh->csid ,fbh->csform, status); @@ -4736,7 +4837,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl } } else { /* amtp==0 so truncate LOB to zero length */ - OCILobTrim_log_stat(imp_sth->svchp, errhp, (OCILobLocator*)fbh->desc_h, 0, status); + OCILobTrim_log_stat(imp_sth, imp_sth->svchp, errhp, (OCILobLocator*)fbh->desc_h, 0, status); if (status != OCI_SUCCESS) { return oci_error(sth, errhp, status, "OCILobTrim in post_execute_lobs"); @@ -4744,7 +4845,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch %d for '%s' param: ftype %d, len %ld: %s %s\n", @@ -4770,8 +4871,8 @@ ora_free_lob_refetch(SV *sth, imp_sth_t *imp_sth) int i; sword status; if (lr->rowid) - OCIDescriptorFree(lr->rowid, OCI_DTYPE_ROWID); - OCIHandleFree_log_stat(lr->stmthp, OCI_HTYPE_STMT, status); + OCIDescriptorFree_log(imp_sth, lr->rowid, OCI_DTYPE_ROWID); + OCIHandleFree_log_stat(imp_sth, lr->stmthp, OCI_HTYPE_STMT, status); if (status != OCI_SUCCESS) oci_error(sth, imp_sth->errhp, status, "ora_free_lob_refetch/OCIHandleFree"); @@ -4800,7 +4901,7 @@ ora_db_version(SV *dbh, imp_dbh_t *imp_dbh) /* XXX should possibly create new session before ending the old so */ /* that if the new one can't be created, the old will still work. */ - OCIServerRelease_log_stat(imp_dbh->svchp, imp_dbh->errhp, buf, 2,OCI_HTYPE_SVCCTX, &vernum , status); + OCIServerRelease_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, buf, 2,OCI_HTYPE_SVCCTX, &vernum , status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionServerRelease"); return 0; diff --git a/ocitrace.h b/ocitrace.h index d5f1c101..bebe4cb9 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -6,8 +6,8 @@ Macros named "_log_stat" return status in last parameter. */ -#define DBD_OCI_TRACEON (DBIS->debug >= 6 || dbd_verbose>=6) -#define DBD_OCI_TRACEFP (DBILOGFP) +#define DBD_OCI_TRACEON(h) (DBIc_DBISTATE(h)->debug >= 6 || dbd_verbose >= 6) +#define DBD_OCI_TRACEFP(h) (DBIc_LOGPIO(h)) #define OciTp ("\tOCI") /* OCI Trace Prefix */ #define OciTstr(s) ((s) ? (text*)(s) : (text*)"") #define ul_t(v) ((unsigned long)(v)) @@ -36,121 +36,121 @@ If done well the log will read like a compilable program. */ -#define OCIServerRelease_log_stat(sc,errhp,b,bl,ht,ver,stat)\ +#define OCIServerRelease_log_stat(impdbh,sc,errhp,b,bl,ht,ver,stat) \ stat =OCIServerRelease(sc,errhp,b,bl,ht,ver);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCIServerRelease(%p)=%s\n",\ OciTp, sc,oci_status_name(stat)),stat \ : stat -#define OCISessionRelease_log_stat(svchp, errhp,stat)\ +#define OCISessionRelease_log_stat(impdbh,svchp, errhp,stat) \ stat =OCISessionRelease(svchp, errhp, NULL, (ub4)0, OCI_DEFAULT);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCISessionRelease(svchp=%p)=%s\n",\ OciTp, svchp,oci_status_name(stat)),stat \ : stat -#define OCISessionPoolDestroy_log_stat(ph, errhp,stat )\ +#define OCISessionPoolDestroy_log_stat(impdbh, ph, errhp,stat ) \ stat =OCISessionPoolDestroy(ph, errhp,OCI_DEFAULT);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCISessionPoolDestroy(ph=%p)=%s\n",\ OciTp, ph,oci_status_name(stat)),stat \ : stat -#define OCISessionGet_log_stat(envhp, errhp, sh, ah,pn,pnl,stat)\ +#define OCISessionGet_log_stat(impdbh,envhp, errhp, sh, ah,pn,pnl,stat) \ stat =OCISessionGet(envhp, errhp, sh, ah,pn,pnl,NULL,0, NULL, NULL, NULL, OCI_SESSGET_SPOOL);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCISessionGet(envhp=%p,sh=%p,ah=%p,pn=%p,pnl=%d)=%s\n",\ OciTp, envhp,sh,ah,pn,pnl,oci_status_name(stat)),stat \ : stat -#define OCISessionPoolCreate_log_stat(envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,stat)\ +#define OCISessionPoolCreate_log_stat(impdbh,envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,stat) \ stat =OCISessionPoolCreate(envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,OCI_DEFAULT);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCISessionPoolCreate(envhp=%p,ph=%p,pn=%p,pnl=%p,min=%d,max=%d,incr=%d, un=%s,unl=%d,pw=%s,pwl=%d)=%s\n",\ OciTp, envhp,ph,pn,pnl,sn,sm,si,un,unl,pw,pwl,oci_status_name(stat)),stat \ : stat #if defined(ORA_OCI_102) -#define OCIPing_log_stat(sc,errhp,stat)\ +#define OCIPing_log_stat(impdbh,sc,errhp,stat) \ stat =OCIPing(sc,errhp,OCI_DEFAULT);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCIPing(%p)=%s\n",\ OciTp, sc,oci_status_name(stat)),stat \ : stat #endif -#define OCIServerVersion_log_stat(sc,errhp,b,bl,ht,stat)\ +#define OCIServerVersion_log_stat(impdbh,sc,errhp,b,bl,ht,stat) \ stat =OCIServerVersion(sc,errhp,b,bl,ht);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCIServerVersion_log_stat(%p,%s)=%s\n",\ OciTp, sc,b,oci_status_name(stat)),stat \ : stat -#define OCIStmtGetPieceInfo_log_stat(stmhp,errhp,hdlptr,hdltyp,in_out,iter,idx,piece,stat)\ +#define OCIStmtGetPieceInfo_log_stat(impsth,stmhp,errhp,hdlptr,hdltyp,in_out,iter,idx,piece,stat) \ stat =OCIStmtGetPieceInfo(stmhp,errhp,hdlptr,hdltyp,in_out,iter,idx,piece);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIStmtGetPieceInfo_log_stat(%p,%p,%u)=%s\n",\ OciTp, (void*)errhp,fbh,*piece,oci_status_name(stat)),stat \ : stat -#define OCIStmtSetPieceInfo_log_stat(ptr,errhp,buf,blen,p,indp,rc,stat)\ +#define OCIStmtSetPieceInfo_log_stat(impsth,ptr,errhp,buf,blen,p,indp,rc,stat) \ stat =OCIStmtSetPieceInfo(ptr,OCI_HTYPE_DEFINE,errhp, buf, blen, p,indp,rc);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIStmtSetPieceInfo_log_stat(%p,%p,%d,%p)=%s\n",\ OciTp, (void*)errhp,fbh,piece,blen,oci_status_name(stat)),stat \ : stat -#define OCIDefineDynamic_log_stat(defnp,errhp,fbh,stat)\ +#define OCIDefineDynamic_log_stat(impsth,defnp,errhp,fbh,stat) \ stat =OCIDefineDynamic(defnp,errhp,fbh,(OCICallbackDefine) presist_lob_fetch_cbk );\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIDefineDynamic_log_stat(%p,%p,%p)=%s\n",\ OciTp, (void*)defnp, (void*)errhp,fbh,oci_status_name(stat)),stat \ : stat -#define OCIXMLTypeCreateFromSrc_log_stat(svchp,envhp,src_type,src_ptr,xml,stat)\ - stat =OCIXMLTypeCreateFromSrc (svchp,envhp,(OCIDuration)OCI_DURATION_CALLOUT,(ub1)src_type,(dvoid *)src_ptr,(sb4)OCI_IND_NOTNULL, xml);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ - "%sOCIXMLTypeCreateFromSrc_log_stat(%p,%p,%p,%p,%p)=%s\n",\ - OciTp, (void*)svchp,(void*)envhp, src_type, src_ptr,oci_status_name(stat)),stat \ +#define OCIXMLTypeCreateFromSrc_log_stat(impdbh,svchp,errhp,duration,src_type,src_ptr,ind,xml,stat) \ + stat =OCIXMLTypeCreateFromSrc (svchp,errhp,duration,(ub1)src_type,(dvoid *)src_ptr,(sb4)ind, xml);\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ + "%sOCIXMLTypeCreateFromSrc_log_stat(%p,%p,%d,%d,%p,%d,%p)=%s\n",\ + OciTp, (void*)svchp,(void*)errhp, duration, src_type, src_ptr, ind, xml, oci_status_name(stat)),stat \ : stat -#define OCILobFileIsOpen_log_stat(envhp,errhp,loc,is_open,stat) \ +#define OCILobFileIsOpen_log_stat(impdbh,envhp,errhp,loc,is_open,stat) \ stat = OCILobFileIsOpen(envhp,errhp,loc,is_open);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCILobFileIsOpen_log_stat(%p,%p,%p,%p,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp, loc, is_open, *is_open,oci_status_name(stat)),stat : stat -#define OCILobLocatorIsInit_log_stat(envhp,errhp,loc,is_initp,stat)\ +#define OCILobLocatorIsInit_log_stat(impdbh,envhp,errhp,loc,is_initp,stat) \ stat =OCILobLocatorIsInit (envhp,errhp,loc,is_initp );\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCILobLocatorIsInit_log_stat(%p,%p,%p,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,loc,*is_initp,oci_status_name(stat)),stat \ : stat -#define OCIObjectPin_log_stat(envhp,errhp,or,ot,stat)\ +#define OCIObjectPin_log_stat(impsth,envhp,errhp,or,ot,stat) \ stat = OCIObjectPin(envhp,errhp,or,(OCIComplexObject *)0,OCI_PIN_LATEST,OCI_DURATION_TRANS,OCI_LOCK_NONE,ot);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sObjectPin_log_stat(%p,%p,%p,%p)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,or,ot,oci_status_name(stat)),stat \ : stat - +/* #define OCICollGetElem_log_stat(envhp,errhp,v,i,ex,e,ne,stat)\ stat = OCICollGetElem(envhp,errhp, v,i,ex,e,ne);\ (DBD_OCI_TRACEON) \ @@ -158,8 +158,8 @@ "%sOCICollGetElem_log_stat(%p,%p,%d,%d,%d,%d,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,v,i,ex,e,ne,oci_status_name(stat)),stat \ : stat - - +*/ +/* #define OCITableFirst_log_stat(envhp,errhp,v,i,stat)\ stat = OCITableFirst(envhp,errhp,v,i);\ (DBD_OCI_TRACEON) \ @@ -167,60 +167,60 @@ "%sOCITableFirst_log_stat(%p,%p,%d,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,v,i,oci_status_name(stat)),stat \ : stat - -#define OCIObjectGetAttr_log_stat(envhp,errhp,v,no,ot,tn,tnl,ani,ans,av,atdo, stat)\ - stat = OCIObjectGetAttr(errhp,errhp,v,no,ot,tn,tnl,1,(ub4 *)0, 0,ani,ans,av,atdo,stat);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ - "%sOCIObjectGetAttr_log_stat(%p,%p,%d,%d,%d,%d,%d,%d,%d,%d,%d)=%s\n",\ - OciTp, (void*)envhp,(void*)errhp,v,no,ot,tn,tnl,ani,ans,av,atdo,(void*)errhp,oci_status_name(stat)),stat \ +*/ +#define OCIObjectGetAttr_log_stat(impsth,envhp,errhp,instance,nullstruct,tdo,names,lengths,namecount,indexes,indexcount,attrnullstatus,attrnullstruct,attrvalue, attrtdo, stat) \ + stat = OCIObjectGetAttr(envhp,errhp,instance,nullstruct,tdo,names,lengths,namecount,indexes,indexcount,attrnullstatus,attrnullstruct,attrvalue,attrtdo); \ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ + "%sOCIObjectGetAttr_log_stat(%p,%p,%p,%p,%p,%p,%p,%d,%p,%d,%p,%p,%p,%p)=%s\n",\ + OciTp, (void*)envhp,(void*)errhp,instance,nullstruct,tdo,names,lengths,namecount,indexes,indexcount,attrnullstatus,attrnullstruct,attrvalue,attrtdo,oci_status_name(stat)),stat \ : stat -#define OCIIntervalToText_log_stat(envhp,errhp,di,sb,ln,sl,stat)\ +#define OCIIntervalToText_log_stat(impsth,envhp,errhp,di,sb,ln,sl,stat) \ stat = OCIIntervalToText(envhp,errhp, *(OCIInterval**)di,3,3,sb,ln,sl);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIIntervalToText(%p,%p,%p,%s)=%s\n",\ OciTp, (void*)errhp, di,sl,sb,oci_status_name(stat)),stat \ : stat -#define OCIDateTimeToText_log_stat(envhp,errhp,d,sl,sb,stat)\ +#define OCIDateTimeToText_log_stat(impsth,envhp,errhp,d,sl,sb,stat) \ stat = OCIDateTimeToText(envhp,errhp, *(OCIDateTime**)d,(CONST text*) 0,(ub1) 0,6, (CONST text*) 0, (ub4) 0,(ub4 *)sl,sb );\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIDateTimeToText(%p,%p,%p,%s)=%s\n",\ OciTp, (void*)errhp, d,sl,sb,oci_status_name(stat)),stat \ : stat -#define OCIDateToText_log_stat(errhp,d,sl,sb,stat)\ +#define OCIDateToText_log_stat(impsth,errhp,d,sl,sb,stat) \ stat = OCIDateToText(errhp, (CONST OCIDate *) d,(CONST text*) 0,(ub1) 0, (CONST text*) 0, (ub4) 0,(ub4 *)sl,sb );\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sDateToText_log_stat(%p,%p,%p,%s)=%s\n",\ OciTp, (void*)errhp, d,sl,sb,oci_status_name(stat)),stat \ : stat -#define OCIIterDelete_log_stat(envhp,errhp,itr,stat)\ +#define OCIIterDelete_log_stat(impsth,envhp,errhp,itr,stat) \ stat = OCIIterDelete(envhp,errhp,itr );\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIIterDelete_log_stat(%p,%p,%p)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,itr,oci_status_name(stat)),stat \ : stat -#define OCIIterCreate_log_stat(envhp,errhp,coll,itr,stat)\ +#define OCIIterCreate_log_stat(impsth,envhp,errhp,coll,itr,stat) \ stat = OCIIterCreate(envhp,errhp,coll,itr);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sIterCreate_log_stat(%p,%p,%p)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,(void*)coll,oci_status_name(stat)),stat \ : stat - +/* #define OCICollSize_log_stat(envhp,errhp,coll,coll_siz,stat)\ stat = OCICollSize(envhp,errhp,(CONST OCIColl *)coll,coll_siz);\ (DBD_OCI_TRACEON) \ @@ -228,105 +228,105 @@ "%sOCICollSize_log_stat(%p,%p,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,oci_status_name(stat)),stat \ : stat - -#define OCIDefineObject_log_stat(defnp,errhp,tdo,eo_buff,eo_ind,stat)\ +*/ +#define OCIDefineObject_log_stat(impsth,defnp,errhp,tdo,eo_buff,eo_ind,stat) \ stat = OCIDefineObject(defnp,errhp,tdo,eo_buff,0,eo_ind, 0);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIDefineObject(%p,%p,%p)=%s\n",\ OciTp, (void*)defnp, (void*)errhp, (void*)tdo,oci_status_name(stat)),stat \ : stat -#define OCITypeByName_log_stat(envhp,errhp,svchp,p1,l,tdo,stat)\ - stat = OCITypeByName(envhp,errhp,svchp,(const oratext*)"",0,p1,l,0,0,OCI_DURATION_TRANS,OCI_TYPEGET_ALL,tdo);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ - "%sTypeByName(%p,%p,%p,%s,%d)=%s\n",\ - OciTp, (void*)envhp, (void*)errhp, (void*)svchp, (char*)(p1),(l),oci_status_name(stat)),stat \ - : stat +#define OCITypeByName_log(impsth,envhp,errhp,svchp,sn,snl,tn,tnl,vn,vnl,duration,option,tdo,stat) \ + stat = OCITypeByName(envhp,errhp,svchp,sn,snl,tn,tnl,vn,vnl,duration,option,tdo); \ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ + "%sTypeByName(%p,%p,%p,%s,%d,%s,%d,\"\",0,%d,%d,%p)=%s\n", \ + OciTp, (void*)envhp, (void*)errhp, (void*)svchp, sn,snl,tn,tnl,duration,option,tdo,oci_status_name(stat)), stat \ + :stat -#define OCITypeByRef_log_stat(envhp,errhp,ref,tdo,stat)\ +#define OCITypeByRef_log_stat(impsth,envhp,errhp,ref,tdo,stat) \ stat = OCITypeByRef(envhp,errhp,ref,OCI_DURATION_TRANS,OCI_TYPEGET_ALL,tdo);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sTypeByRef(%p,%p,%p)=%s\n",\ OciTp, (void*)envhp, (void*)errhp, (void*)ref,oci_status_name(stat)),stat \ : stat /* added by lab */ -#define OCILobCharSetId_log_stat( envhp, errhp, locp, csidp, stat ) \ +#define OCILobCharSetId_log_stat(impxxh, envhp, errhp, locp, csidp, stat ) \ stat = OCILobCharSetId( envhp, errhp, locp, csidp ); \ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impxxh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobCharSetId(%p,%p,%p,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp, (void*)locp, *csidp, oci_status_name(stat)),stat \ : stat /* added by lab */ -#define OCILobCharSetForm_log_stat( envhp, errhp, locp, formp, stat ) \ +#define OCILobCharSetForm_log_stat(impxxh, envhp, errhp, locp, formp, stat ) \ stat = OCILobCharSetForm( envhp, errhp, locp, formp ); \ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impxxh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobCharSetForm(%p,%p,%p,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp, (void*)locp, *formp, oci_status_name(stat)),stat \ : stat /* added by lab */ -#define OCINlsEnvironmentVariableGet_log_stat( valp, size, item, charset, rsizep ,stat ) \ +#define OCINlsEnvironmentVariableGet_log_stat(impdbh, valp, size, item, charset, rsizep ,stat ) \ stat = OCINlsEnvironmentVariableGet( valp, size, item, charset, rsizep ); \ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sNlsEnvironmentVariableGet(%d,%lu,%d,%d,%lu)=%s\n",\ OciTp, *valp, (unsigned long)size, item, charset, (unsigned long)*rsizep, oci_status_name(stat)),stat \ : stat /* added by lab */ -#define OCIEnvNlsCreate_log_stat( envp, mode, ctxp, f1, f2, f3, sz, usremepp ,chset, nchset ,stat ) \ +#define OCIEnvNlsCreate_log_stat(impdbh, envp, mode, ctxp, f1, f2, f3, sz, usremepp ,chset, nchset ,stat ) \ stat = OCIEnvNlsCreate(envp, mode, ctxp, f1, f2, f3, sz, usremepp ,chset, nchset ); \ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sEnvNlsEnvCreate(%p,%s,%d,%d,%p,%p,%p,%d,%p,%d,%d)=%s\n", \ OciTp, (void*)envp, oci_mode(mode),mode, ctxp, (void*)f1, (void*)f2, (void*)f3, sz, (void*)usremepp ,chset, nchset, oci_status_name(stat)),stat \ : stat -#define OCIAttrGet_log_stat(th,ht,ah,sp,at,eh,stat) \ +#define OCIAttrGet_log_stat(impxxh, th,ht,ah,sp,at,eh,stat) \ stat = OCIAttrGet(th,ht,ah,sp,at,eh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sAttrGet(%p,%s,%p,%p,%s,%p)=%s\n", \ OciTp, (void*)th,oci_hdtype_name(ht),(void*)ah,pul_t(sp),oci_attr_name(at),(void*)eh,\ oci_status_name(stat)),stat : stat -#define OCIAttrGet_d_log_stat(th,ht,ah,sp,at,eh,stat) \ +#define OCIAttrGet_d_log_stat(impsth, th,ht,ah,sp,at,eh,stat) \ stat = OCIAttrGet(th,ht,ah,sp,at,eh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sAttrGet(%p,%s,%p,%p,%s,%p)=%s\n", \ OciTp, (void*)th,oci_hdtype_name(ht),(void*)ah,pul_t(sp),oci_dtype_attr_name(at),(void*)eh,\ oci_status_name(stat)),stat : stat #define OCIAttrGet_parmap(imp_sth,dh, ht, p1, l, stat) \ - OCIAttrGet_log_stat(dh, ht, \ + OCIAttrGet_log_stat(imp_sth, dh, ht, \ (void*)(p1), (l), OCI_ATTR_PARAM, imp_sth->errhp, stat) #define OCIAttrGet_parmdp(imp_sth, parmdp, p1, l, a, stat) \ - OCIAttrGet_d_log_stat(parmdp, OCI_DTYPE_PARAM, \ + OCIAttrGet_d_log_stat(imp_sth, parmdp, OCI_DTYPE_PARAM, \ (void*)(p1), (l), (a), imp_sth->errhp, stat) #define OCIAttrGet_stmhp_stat(imp_sth, p1, l, a, stat) \ - OCIAttrGet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, \ + OCIAttrGet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, \ (void*)(p1), (l), (a), imp_sth->errhp, stat) -#define OCIAttrSet_log_stat(th,ht,ah,s1,a,eh,stat) \ +#define OCIAttrSet_log_stat(impxxh,th,ht,ah,s1,a,eh,stat) \ stat=OCIAttrSet(th,ht,ah,s1,a,eh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sAttrSet(%p,%s, %p,%lu,Attr=%s,%p)=%s\n", \ OciTp, (void*)th,oci_hdtype_name(ht),(void *)ah,ul_t(s1),oci_attr_name(a),(void*)eh, \ oci_status_name(stat)),stat : stat -#define OCIBindByName_log_stat(sh,bp,eh,p1,pl,v,vs,dt,in,al,rc,mx,cu,md,stat) \ +#define OCIBindByName_log_stat(impsth,sh,bp,eh,p1,pl,v,vs,dt,in,al,rc,mx,cu,md,stat) \ stat=OCIBindByName(sh,bp,eh,p1,pl,v,vs,dt,in,al,rc,mx,cu,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sBindByName(%p,%p,%p,\"%s\",placeh_len=%ld,value_p=%p,value_sz=%ld," \ "dty=%u,indp=%p,alenp=%p,rcodep=%p,maxarr_len=%lu,curelep=%p (*=%d),mode=%s,%lu)=%s\n",\ OciTp, (void*)sh,(void*)bp,(void*)eh,p1,sl_t(pl),(void*)(v), \ @@ -334,182 +334,182 @@ ul_t((mx)),pul_t((cu)),(cu ? *(int*)cu : 0 ) ,oci_bind_options(md),ul_t((md)), \ oci_status_name(stat)),stat : stat -#define OCIBindArrayOfStruct_log_stat(bp,ep,sd,si,sl,sr,stat) \ +#define OCIBindArrayOfStruct_log_stat(impsth,bp,ep,sd,si,sl,sr,stat) \ stat=OCIBindArrayOfStruct(bp,ep,sd,si,sl,sr); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIBindArrayOfStruct(%p,%p,%u,%u,%u,%u)=%s\n", \ OciTp,(void*)bp,(void*)ep,sd,si,sl,sr, \ oci_status_name(stat)),stat : stat -#define OCIBindDynamic_log(bh,eh,icx,cbi,ocx,cbo,stat) \ +#define OCIBindDynamic_log(impsth,bh,eh,icx,cbi,ocx,cbo,stat) \ stat=OCIBindDynamic(bh,eh,icx,cbi,ocx,cbo); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sBindDynamic(%p,%p,%p,%p,%p,%p)=%s\n", \ OciTp, (void*)bh,(void*)eh,(void*)icx,(void*)cbi, \ (void*)ocx,(void*)cbo, \ oci_status_name(stat)),stat : stat -#define OCIDefineByPos_log_stat(sh,dp,eh,p1,vp,vs,dt,ip,rp,cp,m,stat) \ +#define OCIDefineByPos_log_stat(impsth,sh,dp,eh,p1,vp,vs,dt,ip,rp,cp,m,stat) \ stat=OCIDefineByPos(sh,dp,eh,p1,vp,vs,dt,ip,rp,cp,m); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sDefineByPos(%p,%p,%p,%lu,%p,%ld,%u,%p,%p,%p,mode=%s,%lu)=%s\n", \ OciTp, (void*)sh,(void*)dp,(void*)eh,ul_t((p1)),(void*)(vp), \ sl_t(vs),(ub2)dt,(void*)(ip),(ub2*)(rp),(ub2*)(cp),oci_define_options(m),ul_t(m), \ oci_status_name(stat)),stat : stat -#define OCIDescribeAny_log_stat(sh,eh,op,ol,opt,il,ot,dh,stat) \ +#define OCIDescribeAny_log_stat(impsth,sh,eh,op,ol,opt,il,ot,dh,stat) \ stat=OCIDescribeAny(sh,eh,op,ol,opt,il,ot,dh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sDescribeAny(%p,%p,%p,%lu,%u,%u,%u,%p)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)op,ul_t(ol), \ (ub1)opt,(ub1)il,(ub1)ot,(void*)dh, \ oci_status_name(stat)),stat : stat -#define OCIDescriptorAlloc_ok(envhp, p1, t) \ - if (DBD_OCI_TRACEON) PerlIO_printf(DBD_OCI_TRACEFP, \ +#define OCIDescriptorAlloc_ok(impxxh,envhp, p1, t) \ + if (DBD_OCI_TRACEON(impxxh)) PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sDescriptorAlloc(%p,%p,%s,0,0)\n", \ OciTp,(void*)envhp,(void*)(p1),oci_hdtype_name(t)); \ if (OCIDescriptorAlloc((envhp), (void**)(p1), (t), 0, 0)==OCI_SUCCESS); \ else croak("OCIDescriptorAlloc (type %d) failed",t) -#define OCIDescriptorFree_log(d,t) \ - if (DBD_OCI_TRACEON) PerlIO_printf(DBD_OCI_TRACEFP, \ +#define OCIDescriptorFree_log(impxxh,d,t) \ + if (DBD_OCI_TRACEON(impxxh)) PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sDescriptorFree(%p,%s)\n", OciTp, (void*)d,oci_hdtype_name(t)); \ OCIDescriptorFree(d,t) -#define OCIEnvInit_log_stat(ev,md,xm,um,stat) \ +#define OCIEnvInit_log_stat(impdbh,ev,md,xm,um,stat) \ stat=OCIEnvInit(ev,md,xm,um); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sEnvInit(%p,%lu,%lu,%p)=%s\n", \ OciTp, (void*)ev,ul_t(md),ul_t(xm),(void*)um, \ oci_status_name(stat)),stat : stat -#define OCIErrorGet_log_stat(hp,rn,ss,ep,bp,bs,t, stat) \ +#define OCIErrorGet_log_stat(impxxh, hp,rn,ss,ep,bp,bs,t, stat) \ ((stat = OCIErrorGet(hp,rn,ss,ep,bp,bs,t)), \ - ((DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + ((DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sErrorGet(%p,%lu,\"%s\",%p,\"%s\",%lu,%lu)=%s\n", \ OciTp, (void*)hp,ul_t(rn),OciTstr(ss),psl_t(ep), \ bp,ul_t(bs),ul_t(t), oci_status_name(stat)),stat : stat)) -#define OCIHandleAlloc_log_stat(ph,hp,t,xs,ump,stat) \ +#define OCIHandleAlloc_log_stat(impxxh,ph,hp,t,xs,ump,stat) \ stat=OCIHandleAlloc(ph,hp,t,xs,ump); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sHandleAlloc(%p,%p,%s,%lu,%p)=%s\n", \ OciTp, (void*)ph,(void*)hp,oci_hdtype_name(t),ul_t(xs),(void*)ump, \ oci_status_name(stat)),stat : stat -#define OCIHandleAlloc_ok(envhp, p1, t, stat) \ - OCIHandleAlloc_log_stat((envhp),(void**)(p1),(t),0,0, stat); \ +#define OCIHandleAlloc_ok(impxxh,envhp, p1, t, stat) \ + OCIHandleAlloc_log_stat(impxxh,(envhp),(void**)(p1),(t),0,0, stat); \ if (stat==OCI_SUCCESS) ; \ else croak("OCIHandleAlloc(%s) failed",oci_hdtype_name(t)) -#define OCIHandleFree_log_stat(hp,t,stat) \ +#define OCIHandleFree_log_stat(impxxh,hp,t,stat) \ stat=OCIHandleFree( (hp), (t)); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sHandleFree(%p,%s)=%s\n",OciTp,(void*)hp,oci_hdtype_name(t), \ oci_status_name(stat)),stat : stat -#define OCILobGetLength_log_stat(sh,eh,lh,l,stat) \ +#define OCILobGetLength_log_stat(impxxh,sh,eh,lh,l,stat) \ stat=OCILobGetLength(sh,eh,lh,l); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobGetLength(%p,%p,%p,%p)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)lh,pul_t(l), \ oci_status_name(stat)),stat : stat -#define OCILobGetChunkSize_log_stat(sh,eh,lh,cs,stat) \ +#define OCILobGetChunkSize_log_stat(impdbh,sh,eh,lh,cs,stat) \ stat=OCILobGetChunkSize(sh,eh,lh,cs); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sLobGetChunkSize(%p,%p,%p,%p)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)lh,pul_t(cs), \ oci_status_name(stat)),stat : stat -#define OCILobFileOpen_log_stat(sv,eh,lh,mode,stat) \ +#define OCILobFileOpen_log_stat(impxxh,sv,eh,lh,mode,stat) \ stat=OCILobFileOpen(sv,eh,lh,mode); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobFileOpen(%p,%p,%p,%u)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,(ub1)mode, \ oci_status_name(stat)),stat : stat -#define OCILobFileClose_log_stat(sv,eh,lh,stat) \ +#define OCILobFileClose_log_stat(impsth,sv,eh,lh,stat) \ stat=OCILobFileClose(sv,eh,lh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sLobFileClose(%p,%p,%p)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh, \ oci_status_name(stat)),stat : stat /*Added by JPS for Jeffrey.Klein*/ -#define OCILobCreateTemporary_log_stat(sv,eh,lh,csi,csf,lt,ca,dur,stat) \ +#define OCILobCreateTemporary_log_stat(impdbh,sv,eh,lh,csi,csf,lt,ca,dur,stat) \ stat=OCILobCreateTemporary(sv,eh,lh,csi,csf,lt,ca,dur); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sLobCreateTemporary(%p,%p,%p,%lu,%lu,%lu,%lu,%lu)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh, \ ul_t(csi),ul_t(csf),ul_t(lt),ul_t(ca),ul_t(dur), \ oci_status_name(stat)),stat : stat /*end add*/ -#define OCILobFreeTemporary_log_stat(sv,eh,lh,stat) \ +#define OCILobFreeTemporary_log_stat(impxxh,sv,eh,lh,stat) \ stat=OCILobFreeTemporary(sv,eh,lh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobFreeTemporary(%p,%p,%p)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh, \ oci_status_name(stat)),stat : stat -#define OCILobIsTemporary_log_stat(ev,eh,lh,istemp,stat) \ +#define OCILobIsTemporary_log_stat(impsth,ev,eh,lh,istemp,stat) \ stat=OCILobIsTemporary(ev,eh,lh,istemp); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sLobIsTemporary(%p,%p,%p,%p)=%s\n", \ OciTp, (void*)ev,(void*)eh,(void*)lh,(void*)istemp, \ oci_status_name(stat)),stat : stat /*Added by JPS for Jeffrey.Klein */ -#define OCILobLocatorAssign_log_stat(sv,eh,src,dest,stat) \ +#define OCILobLocatorAssign_log_stat(impdbh,sv,eh,src,dest,stat) \ stat=OCILobLocatorAssign(sv,eh,src,dest); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sLobLocatorAssign(%p,%p,%p,%p)=%s\n", \ OciTp,(void*)sv,(void*)eh,(void*)src,(void*)dest, \ oci_status_name(stat)),stat : stat /*end add*/ -#define OCILobRead_log_stat(sv,eh,lh,am,of,bp,bl,cx,cb,csi,csf,stat) \ +#define OCILobRead_log_stat(impxxh,sv,eh,lh,am,of,bp,bl,cx,cb,csi,csf,stat) \ stat=OCILobRead(sv,eh,lh,am,of,bp,bl,cx,cb,csi,csf); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobRead(%p,%p,%p,%p,%lu,%p,%lu,%p,%p,%u,%u)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,pul_t(am),ul_t(of), \ (void*)bp,ul_t(bl),(void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ oci_status_name(stat)),stat : stat -#define OCILobTrim_log_stat(sv,eh,lh,l,stat) \ +#define OCILobTrim_log_stat(impxxh,sv,eh,lh,l,stat) \ stat=OCILobTrim(sv,eh,lh,l); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobTrim(%p,%p,%p,%lu)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,ul_t(l), \ oci_status_name(stat)),stat : stat -#define OCILobWrite_log_stat(sv,eh,lh,am,of,bp,bl,p1,cx,cb,csi,csf,stat) \ +#define OCILobWrite_log_stat(impxxh,sv,eh,lh,am,of,bp,bl,p1,cx,cb,csi,csf,stat) \ stat=OCILobWrite(sv,eh,lh,am,of,bp,bl,p1,cx,cb,csi,csf); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobWrite(%p,%p,%p,%p,%lu,%p,%lu,%u,%p,%p,%u,%u)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,pul_t(am),ul_t(of), \ (void*)bp,ul_t(bl),(ub1)p1, \ (void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ oci_status_name(stat)),stat : stat -#define OCILobWriteAppend_log_stat(sv,eh,lh,am,bp,bl,p1,cx,cb,csi,csf,stat) \ +#define OCILobWriteAppend_log_stat(impxxh,sv,eh,lh,am,bp,bl,p1,cx,cb,csi,csf,stat) \ stat=OCILobWriteAppend(sv,eh,lh,am,bp,bl,p1,cx,cb,csi,csf); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobWriteAppend(%p,%p,%p,%p,%p,%lu,%u,%p,%p,%u,%u)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,pul_t(am), \ (void*)bp,ul_t(bl),(ub1)p1, \ (void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ oci_status_name(stat)),stat : stat -#define OCIParamGet_log_stat(hp,ht,eh,pp,ps,stat) \ +#define OCIParamGet_log_stat(impsth,hp,ht,eh,pp,ps,stat) \ stat=OCIParamGet(hp,ht,eh,pp,ps); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sParamGet(%p,%lu,%p,%p,%lu,%s)=%s\n", \ OciTp, (void*)hp,ul_t((ht)),(void*)eh,(void*)pp,ul_t(ps), \ oci_hdtype_name(ht),oci_status_name(stat)),stat : stat @@ -517,78 +517,78 @@ #define OCIServerAttach_log_stat(imp_dbh, dbname,md,stat) \ stat=OCIServerAttach( imp_dbh->srvhp, imp_dbh->errhp, \ (text*)dbname, (sb4)strlen(dbname), md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(imp_dbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(imp_dbh), \ "%sServerAttach(%p, %p, \"%s\", %lu, mode=%s,%lu)=%s\n", \ OciTp, (void*)imp_dbh->srvhp,(void*)imp_dbh->errhp, dbname, \ ul_t(strlen(dbname)), oci_mode(md),ul_t(md),oci_status_name(stat)),stat : stat -#define OCIStmtExecute_log_stat(sv,st,eh,i,ro,si,so,md,stat) \ +#define OCIStmtExecute_log_stat(impsth,sv,st,eh,i,ro,si,so,md,stat) \ stat=OCIStmtExecute(sv,st,eh,i,ro,si,so,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sStmtExecute(%p,%p,%p,%lu,%lu,%p,%p,mode=%s,%lu)=%s\n", \ OciTp, (void*)sv,(void*)st,(void*)eh,ul_t((i)), \ ul_t((ro)),(void*)(si),(void*)(so),oci_exe_mode(md),ul_t((md)), \ oci_status_name(stat)),stat : stat -#define OCIStmtFetch_log_stat(sh,eh,nr,or,os,stat) \ - stat=OCIStmtFetch2(sh,eh,nr,or,os,OCI_DEFAULT); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ +#define OCIStmtFetch_log_stat(impsth,sh,eh,nr,or,os,stat) \ + stat=OCIStmtFetch2(sh,eh,nr,or,os,OCI_DEFAULT); \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sStmtFetch(%p,%p,%lu,%u,%d)=%s\n", \ OciTp, (void*)sh,(void*)eh,ul_t(nr),(ub2)or,(ub2)os, \ oci_status_name(stat)),stat : stat -#define OCIStmtPrepare_log_stat(sh,eh,s1,sl,l,m,stat) \ +#define OCIStmtPrepare_log_stat(impsth,sh,eh,s1,sl,l,m,stat) \ stat=OCIStmtPrepare(sh,eh,s1,sl,l,m); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sStmtPrepare(%p,%p,'%s',%lu,%lu,%lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,s1,ul_t(sl),ul_t(l),ul_t(m), \ oci_status_name(stat)),stat : stat -#define OCIServerDetach_log_stat(sh,eh,md,stat) \ +#define OCIServerDetach_log_stat(impdbh,sh,eh,md,stat) \ stat=OCIServerDetach(sh,eh,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sServerDetach(%p,%p,mode=%s,%lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,oci_mode(md),ul_t(md), \ oci_status_name(stat)),stat : stat -#define OCISessionBegin_log_stat(sh,eh,uh,cr,md,stat) \ +#define OCISessionBegin_log_stat(impdbh,sh,eh,uh,cr,md,stat) \ stat=OCISessionBegin(sh,eh,uh,cr,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sSessionBegin(%p,%p,%p,%lu,mode=%s %lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)uh,ul_t(cr),oci_mode(md),ul_t(md), \ oci_status_name(stat)),stat : stat -#define OCISessionEnd_log_stat(sh,eh,ah,md,stat) \ +#define OCISessionEnd_log_stat(impdbh,sh,eh,ah,md,stat) \ stat=OCISessionEnd(sh,eh,ah,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sSessionEnd(%p,%p,%p,mode=%s %lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)ah,oci_mode(md),ul_t(md), \ oci_status_name(stat)),stat : stat -#define OCITransCommit_log_stat(sh,eh,md,stat) \ +#define OCITransCommit_log_stat(impxxh,sh,eh,md,stat) \ stat=OCITransCommit(sh,eh,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sTransCommit(%p,%p,%lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,ul_t(md), \ oci_status_name(stat)),stat : stat -#define OCITransRollback_log_stat(sh,eh,md,stat) \ +#define OCITransRollback_log_stat(impdbh,sh,eh,md,stat) \ stat=OCITransRollback(sh,eh,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sTransRollback(%p,%p,mode=%s %lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,oci_mode(md),ul_t(md), \ oci_status_name(stat)),stat : stat -#define OCIDBStartup_log_stat(svchp,errhp,admhp,mode,flags,stat) \ +#define OCIDBStartup_log_stat(impdbh,svchp,errhp,admhp,mode,flags,stat) \ stat=OCIDBStartup(svchp,errhp,admhp,mode,flags); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCIDBStartup(%p,%p,%p,%u,%u)=%s\n", \ OciTp, (void*)svchp,(void*)errhp,(void*)admhp,mode,flags, \ oci_status_name(stat)),stat : stat -#define OCIDBShutdown_log_stat(svchp,errhp,admhp,mode,stat) \ +#define OCIDBShutdown_log_stat(impdbh,svchp,errhp,admhp,mode,stat) \ stat=OCIDBShutdown(svchp,errhp,admhp,mode); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCIDBShutdown(%p,%p,%p,%u)=%s\n", \ OciTp, (void*)svchp,(void*)errhp,(void*)admhp,mode, \ oci_status_name(stat)),stat : stat From 34757662502071e7d9c7320d470f69620f424d65 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 15 Mar 2012 17:08:24 +0000 Subject: [PATCH 170/637] More changes to remove DBIS usage git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15225 50811bd7-b8ce-0310-adc1-d9db26280581 --- Oracle.xs | 54 +++--- dbdimp.c | 422 +++++++++++++++++++++++---------------------- dbdimp.h | 10 +- oci8.c | 493 ++++++++++++++++++++++++++++++++--------------------- ocitrace.h | 360 +++++++++++++++++++------------------- 5 files changed, 731 insertions(+), 608 deletions(-) diff --git a/Oracle.xs b/Oracle.xs index d4a90c2f..2c7ffc00 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -305,9 +305,9 @@ ora_db_startup(dbh, attribs) croak("ora_pfile is not a string"); str = (text*)SvPV(*svp, svp_len); OCIHandleAlloc(imp_dbh->envhp, (dvoid**)&admhp, (ub4)OCI_HTYPE_ADMIN, (size_t)0, (dvoid**)0); - OCIAttrSet_log_stat((dvoid*)admhp, (ub4)OCI_HTYPE_ADMIN, (dvoid*)str, (ub4)svp_len, (ub4)OCI_ATTR_ADMIN_PFILE, (OCIError*)imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, (dvoid*)admhp, (ub4)OCI_HTYPE_ADMIN, (dvoid*)str, (ub4)svp_len, (ub4)OCI_ATTR_ADMIN_PFILE, (OCIError*)imp_dbh->errhp, status); } - OCIDBStartup_log_stat(imp_dbh->svchp, imp_dbh->errhp, admhp, mode, flags, status); + OCIDBStartup_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, admhp, mode, flags, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCIDBStartup"); ST(0) = &PL_sv_undef; @@ -315,7 +315,7 @@ ora_db_startup(dbh, attribs) else { ST(0) = &PL_sv_yes; } - if (admhp) OCIHandleFree_log_stat((dvoid*)admhp, (ub4)OCI_HTYPE_ADMIN, status); + if (admhp) OCIHandleFree_log_stat(imp_dbh, (dvoid*)admhp, (ub4)OCI_HTYPE_ADMIN, status); #else croak("OCIDBStartup not available"); #endif @@ -338,7 +338,7 @@ ora_db_shutdown(dbh, attribs) mode = OCI_DEFAULT; DBD_ATTRIB_GET_IV(attribs, "ora_mode", 8, svp, mode); admhp = (OCIAdmin*)0; - OCIDBShutdown_log_stat(imp_dbh->svchp, imp_dbh->errhp, admhp, mode, status); + OCIDBShutdown_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, admhp, mode, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCIDBShutdown"); ST(0) = &PL_sv_undef; @@ -359,7 +359,7 @@ ora_can_taf(dbh) ub4 can_taf = 0; CODE: #ifdef OCI_ATTR_TAF_ENABLED - OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, + OCIAttrGet_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { # else @@ -391,14 +391,14 @@ ora_ping(dbh) /*so we should stay connected but we cannot get nay new connections*/ { #if !defined(ORA_OCI_102) - OCIServerVersion_log_stat(imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); + OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); #else vernum = ora_db_version(dbh,imp_dbh); /* OCIPing causes server failures if called against server ver < 10.2 */ if (((int)((vernum>>24) & 0xFF) < 10 ) || (((int)((vernum>>24) & 0xFF) == 10 ) && ((int)((vernum>>20) & 0x0F) < 2 ))){ - OCIServerVersion_log_stat(imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); + OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); } else { - OCIPing_log_stat(imp_dbh->svchp,imp_dbh->errhp,status); + OCIPing_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,status); } #endif if (status != OCI_SUCCESS){ @@ -441,7 +441,7 @@ ora_lob_write(dbh, locator, offset, data) /* if (0 && SvUTF8(data) && !IN_BYTES) { amtp = sv_len_utf8(data); } */ /* added by lab: */ /* LAB do something about length here? see above comment */ - OCILobCharSetForm_log_stat( imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); + OCILobCharSetForm_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetForm"); ST(0) = &PL_sv_undef; @@ -449,7 +449,12 @@ ora_lob_write(dbh, locator, offset, data) } #ifdef OCI_ATTR_CHARSET_ID /* Effectively only used so AL32UTF8 works properly */ - OCILobCharSetId_log_stat( imp_dbh->envhp, imp_dbh->errhp, locator, &csid, status ); + OCILobCharSetId_log_stat(imp_dbh, + imp_dbh->envhp, + imp_dbh->errhp, + locator, + &csid, + status ); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetId"); ST(0) = &PL_sv_undef; @@ -459,7 +464,7 @@ ora_lob_write(dbh, locator, offset, data) /* if data is utf8 but charset isn't then switch to utf8 csid */ csid = (SvUTF8(data) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); - OCILobWrite_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, + OCILobWrite_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &amtp, (ub4)offset, bufp, (ub4)data_len, OCI_ONE_PIECE, NULL, NULL, @@ -497,7 +502,7 @@ ora_lob_append(dbh, locator, data) /* if (1 && SvUTF8(data) && !IN_BYTES) */ /* added by lab: */ /* LAB do something about length here? see above comment */ - OCILobCharSetForm_log_stat( imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); + OCILobCharSetForm_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetForm"); ST(0) = &PL_sv_undef; @@ -505,7 +510,12 @@ ora_lob_append(dbh, locator, data) } #ifdef OCI_ATTR_CHARSET_ID /* Effectively only used so AL32UTF8 works properly */ - OCILobCharSetId_log_stat( imp_dbh->envhp, imp_dbh->errhp, locator, &csid, status ); + OCILobCharSetId_log_stat(imp_dbh, + imp_dbh->envhp, + imp_dbh->errhp, + locator, + &csid, + status ); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetId"); ST(0) = &PL_sv_undef; @@ -514,7 +524,7 @@ ora_lob_append(dbh, locator, data) #endif /* OCI_ATTR_CHARSET_ID */ /* if data is utf8 but charset isn't then switch to utf8 csid */ csid = (SvUTF8(data) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); - OCILobWriteAppend_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, + OCILobWriteAppend_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &amtp, bufp, (ub4)data_len, OCI_ONE_PIECE, NULL, NULL, csid, csform, status); @@ -554,7 +564,7 @@ ora_lob_read(dbh, locator, offset, length) /* if locator is CLOB and data is UTF8 and not in bytes pragma */ /* if (0 && SvUTF8(dest_sv) && !IN_BYTES) { amtp = sv_len_utf8(dest_sv); } */ /* added by lab: */ - OCILobCharSetForm_log_stat( imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); + OCILobCharSetForm_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetForm"); dest_sv = &PL_sv_undef; @@ -564,9 +574,9 @@ ora_lob_read(dbh, locator, offset, length) /* see rt 75163 */ boolean is_open; - OCILobFileIsOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, &is_open, status); + OCILobFileIsOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &is_open, status); if (status == OCI_SUCCESS && !is_open) { - OCILobFileOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, + OCILobFileOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, (ub1)OCI_FILE_READONLY, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobFileOpen"); @@ -575,7 +585,7 @@ ora_lob_read(dbh, locator, offset, length) } } - OCILobRead_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, + OCILobRead_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &amtp, (ub4)offset, /* offset starts at 1 */ bufp, (ub4)bufp_len, 0, 0, (ub2)0, csform, status); @@ -603,7 +613,7 @@ ora_lob_trim(dbh, locator, length) D_imp_dbh(dbh); sword status; CODE: - OCILobTrim_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, length, status); + OCILobTrim_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, length, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobTrim"); ST(0) = &PL_sv_undef; @@ -621,7 +631,7 @@ ora_lob_is_init(dbh, locator) sword status; boolean is_init = 0; CODE: - OCILobLocatorIsInit_log_stat(imp_dbh->envhp,imp_dbh->errhp,locator,&is_init,status); + OCILobLocatorIsInit_log_stat(imp_dbh, imp_dbh->envhp,imp_dbh->errhp,locator,&is_init,status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobLocatorIsInit ora_lob_is_init"); ST(0) = &PL_sv_undef; @@ -639,7 +649,7 @@ ora_lob_length(dbh, locator) sword status; ub4 len = 0; CODE: - OCILobGetLength_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, &len, status); + OCILobGetLength_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &len, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobGetLength ora_lob_length"); ST(0) = &PL_sv_undef; @@ -658,7 +668,7 @@ ora_lob_chunk_size(dbh, locator) sword status; ub4 chunk_size = 0; CODE: - OCILobGetChunkSize_log_stat(imp_dbh->svchp, imp_dbh->errhp, locator, &chunk_size, status); + OCILobGetChunkSize_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &chunk_size, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCILobGetChunkSize"); ST(0) = &PL_sv_undef; diff --git a/dbdimp.c b/dbdimp.c index 5518343e..3c417f2b 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -62,11 +62,12 @@ struct sql_fbh_st { }; static sql_fbh_t ora2sql_type _((imp_fbh_t* fbh)); -void ora_free_phs_contents _((phs_t *phs)); -static void dump_env_to_trace(); +void ora_free_phs_contents _((imp_sth_t *imp_sth, phs_t *phs)); +static void dump_env_to_trace(imp_dbh_t *imp_dbh); static sb4 -oci_error_get(OCIError *errhp, sword status, char *what, SV *errstr, int debug) +oci_error_get(imp_xxh_t *imp_xxh, + OCIError *errhp, sword status, char *what, SV *errstr, int debug) { dTHX; text errbuf[1024]; @@ -86,16 +87,17 @@ oci_error_get(OCIError *errhp, sword status, char *what, SV *errstr, int debug) } while( ++recno - && OCIErrorGet_log_stat(errhp, recno, (text*)NULL, &eg_errcode, errbuf, + && OCIErrorGet_log_stat(imp_xxh, errhp, recno, (text*)NULL, &eg_errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR, eg_status) != OCI_NO_DATA - && eg_status != OCI_INVALID_HANDLE - && recno < 100 + && eg_status != OCI_INVALID_HANDLE + && recno < 100 ) { if (debug >= 4 || recno>1/*XXX temp*/ || dbd_verbose >= 4 ) - PerlIO_printf(DBILOGFP, " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", - what ? what : "", (long)recno, - (eg_status==OCI_SUCCESS) ? "ok" : oci_status_name(eg_status), - status, (long)eg_errcode, errbuf); + PerlIO_printf(DBIc_LOGPIO(imp_xxh), + " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", + what ? what : "", (long)recno, + (eg_status==OCI_SUCCESS) ? "ok" : oci_status_name(eg_status), + status, (long)eg_errcode, errbuf); errcode = eg_errcode; sv_catpv(errstr, (char*)errbuf); if (*(SvEND(errstr)-1) == '\n') @@ -205,34 +207,32 @@ dbd_discon_all(SV *drh, imp_drh_t *imp_drh) { dTHR; dTHX; - /* The disconnect_all concept is flawed and needs more work */ + + /* The disconnect_all concept is flawed and needs more work */ if (!PL_dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) { - DBIh_SET_ERR_CHAR(drh, (imp_xxh_t*)imp_drh, Nullch, 1, "disconnect_all not implemented", Nullch, Nullch); - return FALSE; + DBIh_SET_ERR_CHAR(drh, (imp_xxh_t*)imp_drh, Nullch, 1, "disconnect_all not implemented", Nullch, Nullch); + return FALSE; } return FALSE; } - void -dbd_fbh_dump(imp_fbh_t *fbh, int i, int aidx) +dbd_fbh_dump(imp_sth_t *imp_sth, imp_fbh_t *fbh, int i, int aidx) { dTHX; - PerlIO *fp = DBILOGFP; - PerlIO_printf(fp, " fbh %d: '%s'\t%s, ", + PerlIO_printf(DBIc_LOGPIO(imp_sth), " fbh %d: '%s'\t%s, ", i, fbh->name, (fbh->nullok) ? "NULLable" : "NO null "); - PerlIO_printf(fp, "otype %3d->%3d, dbsize %ld/%ld, p%d.s%d\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), "otype %3d->%3d, dbsize %ld/%ld, p%d.s%d\n", fbh->dbtype, fbh->ftype, (long)fbh->dbsize,(long)fbh->disize, fbh->prec, fbh->scale); if (fbh->fb_ary) { - PerlIO_printf(fp, " out: ftype %d, bufl %d. indp %d, rlen %d, rcode %d\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), " out: ftype %d, bufl %d. indp %d, rlen %d, rcode %d\n", fbh->ftype, fbh->fb_ary->bufl, fbh->fb_ary->aindp[aidx], fbh->fb_ary->arlen[aidx], fbh->fb_ary->arcode[aidx]); } } - int ora_dbtype_is_long(int dbtype) { @@ -430,10 +430,10 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("ora_driver_name is not a string"); imp_dbh->driver_name = (char *) SvPV (*svp, svp_len ); imp_dbh->driver_namel= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); } else { - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION,(text*)"DBDO1.28",7,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION,(text*)"DBDO1.28",7,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); } #endif /*ORA_OCI_112*/ @@ -443,7 +443,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("ora_action is not a string"); imp_dbh->action = (char *) SvPV (*svp, svp_len ); imp_dbh->actionl= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_module_name", 15)) && SvOK(*svp)) { @@ -452,7 +452,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("ora_module_name is not a string"); imp_dbh->module_name = (char *) SvPV (*svp, svp_len ); imp_dbh->module_namel= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); } if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_identifier", 21)) && SvOK(*svp)) { @@ -461,7 +461,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("ora_client_identifier is not a string"); imp_dbh->client_identifier = (char *) SvPV (*svp, svp_len ); imp_dbh->client_identifierl= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); } if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_info", 15)) && SvOK(*svp)) { @@ -470,7 +470,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S croak("ora_client_info is not a string"); imp_dbh->client_info = (char *) SvPV (*svp, svp_len ); imp_dbh->client_infol= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); } @@ -513,7 +513,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S DBD_ATTRIB_GET_IV( attr, "ora_objects",11, svp, ora_objects); if (DBIc_DBISTATE(imp_dbh)->debug >= 6 || dbd_verbose >= 6 ) - dump_env_to_trace(); + dump_env_to_trace(imp_dbh); /* dbi_imp_data code adapted from DBD::mysql */ if (DBIc_has(imp_dbh, DBIcf_IMPSET)) { @@ -590,14 +590,14 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S { size_t rsize = 0; /* Get CLIENT char and nchar charset id values */ - OCINlsEnvironmentVariableGet_log_stat( &charsetid,(size_t) 0, OCI_NLS_CHARSET_ID, 0, &rsize ,status ); + OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &charsetid,(size_t) 0, OCI_NLS_CHARSET_ID, 0, &rsize ,status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "OCINlsEnvironmentVariableGet(OCI_NLS_CHARSET_ID) Check NLS settings etc."); return 0; } - OCINlsEnvironmentVariableGet_log_stat( &ncharsetid,(size_t) 0, OCI_NLS_NCHARSET_ID, 0, &rsize ,status ); + OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &ncharsetid,(size_t) 0, OCI_NLS_NCHARSET_ID, 0, &rsize ,status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "OCINlsEnvironmentVariableGet(OCI_NLS_NCHARSET_ID) Check NLS settings etc."); @@ -624,7 +624,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S form attribute. }*/ - OCIEnvNlsCreate_log_stat( &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, + OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, charsetid, ncharsetid, status ); if (status != OCI_SUCCESS) { @@ -665,7 +665,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (new_charsetid) charsetid = new_charsetid; if (new_ncharsetid) ncharsetid = new_ncharsetid; imp_dbh->envhp = NULL; - OCIEnvNlsCreate_log_stat( &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, + OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, charsetid, ncharsetid, status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, @@ -686,7 +686,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (shared_dbh_ssv) { /*is this a cached or shared handle from DBI*/ if (!imp_dbh->envhp) { /*no hande so create a new one*/ - OCIEnvInit_log_stat( &imp_dbh->envhp, OCI_DEFAULT, 0, 0, status); + OCIEnvInit_log_stat(imp_dbh, &imp_dbh->envhp, OCI_DEFAULT, 0, 0, status); if (status != OCI_SUCCESS) { oci_error(dbh, (OCIError*)imp_dbh->envhp, status, "OCIEnvInit"); return 0; @@ -694,8 +694,8 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } } - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIAttrGet_log_stat(imp_dbh->envhp, OCI_HTYPE_ENV, &charsetid, (ub4)0 , + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &charsetid, (ub4)0 , OCI_ATTR_ENV_CHARSET_ID, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { @@ -703,7 +703,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S return 0; } - OCIAttrGet_log_stat(imp_dbh->envhp, OCI_HTYPE_ENV, &ncharsetid, (ub4)0 , + OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &ncharsetid, (ub4)0 , OCI_ATTR_ENV_NCHARSET_ID, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { @@ -735,12 +735,12 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!shared_dbh) { - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCIServerAttach"); - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); return 0; } @@ -762,57 +762,60 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!imp_dbh->pool_incr) imp_dbh->pool_incr = 2; - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->poolhp, OCI_HTYPE_SPOOL, status); - - OCISessionPoolCreate_log_stat(imp_dbh->envhp, - imp_dbh->errhp, - imp_dbh->poolhp, - (OraText **) &imp_dbh->pool_name, - (ub4 *) &imp_dbh->pool_namel, - (OraText *) dbname, - strlen(dbname), - imp_dbh->pool_min, - imp_dbh->pool_max, - imp_dbh->pool_incr, - (OraText *) uid, - strlen(uid), - (OraText *) pwd, - strlen(pwd), - status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->poolhp, OCI_HTYPE_SPOOL, status); + + OCISessionPoolCreate_log_stat( + imp_dbh, + imp_dbh->envhp, + imp_dbh->errhp, + imp_dbh->poolhp, + (OraText **) &imp_dbh->pool_name, + (ub4 *) &imp_dbh->pool_namel, + (OraText *) dbname, + strlen(dbname), + imp_dbh->pool_min, + imp_dbh->pool_max, + imp_dbh->pool_incr, + (OraText *) uid, + strlen(uid), + (OraText *) pwd, + strlen(pwd), + status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionPoolCreate"); - OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); - OCIHandleFree_log_stat(imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); return 0; } - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_AUTHINFO, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_AUTHINFO, status); - OCIAttrSet_log_stat(imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, &purity, (ub4) 0,(ub4) OCI_ATTR_PURITY, imp_dbh->errhp, status); if (imp_dbh->pool_class) /*pool_class may or may not be used */ - OCIAttrSet_log_stat(imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, (OraText *) imp_dbh->pool_class, (ub4) imp_dbh->pool_classl, (ub4) OCI_ATTR_CONNECTION_CLASS, imp_dbh->errhp, status); cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); - OCISessionGet_log_stat(imp_dbh->envhp, imp_dbh->errhp, &imp_dbh->svchp, imp_dbh->authp, + OCISessionGet_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, &imp_dbh->svchp, imp_dbh->authp, imp_dbh->pool_name, (ub4)strlen((char *)imp_dbh->pool_name), status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionGet"); - OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); - OCISessionPoolDestroy(imp_dbh->poolhp, imp_dbh->errhp,status); - OCIHandleFree_log_stat(imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); + OCISessionPoolDestroy_log_stat( + imp_dbh, imp_dbh->poolhp, imp_dbh->errhp,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); return 0; } @@ -833,28 +836,28 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S else { #endif /* ORA_OCI_112 */ - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); OCIServerAttach_log_stat(imp_dbh, dbname,OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCIServerAttach"); - OCIHandleFree_log_stat(imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); if (forced_new_environment) - OCIHandleFree_log_stat(imp_dbh->envhp, OCI_HTYPE_ENV, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); return 0; } - OCIAttrSet_log_stat( imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp, status); - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_dbh->seshp, OCI_HTYPE_SESSION, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->seshp, OCI_HTYPE_SESSION, status); cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); - OCISessionBegin_log_stat( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp,cred_type, sess_mode_type, status); + OCISessionBegin_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp,cred_type, sess_mode_type, status); if (status == OCI_SUCCESS_WITH_INFO) { /* eg ORA-28011: the account will expire soon; change your password now */ @@ -863,17 +866,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); - OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); - OCIHandleFree_log_stat(imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); if (forced_new_environment) - OCIHandleFree_log_stat(imp_dbh->envhp, OCI_HTYPE_ENV, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); return 0; } - OCIAttrSet_log_stat(imp_dbh->svchp, (ub4) OCI_HTYPE_SVCCTX, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->svchp, (ub4) OCI_HTYPE_SVCCTX, imp_dbh->seshp, (ub4) 0,(ub4) OCI_ATTR_SESSION, imp_dbh->errhp, status); #ifdef ORA_OCI_112 } @@ -912,7 +915,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S can_taf = 0; #ifdef OCI_ATTR_TAF_ENABLED - OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, + OCIAttrGet_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); #endif @@ -943,7 +946,7 @@ dbd_db_commit(SV *dbh, imp_dbh_t *imp_dbh) { dTHX; sword status; - OCITransCommit_log_stat(imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT, status); + OCITransCommit_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCITransCommit"); return 0; @@ -966,7 +969,7 @@ dbd_st_cancel(SV *sth, imp_sth_t *imp_sth) /* if we are using a scrolling cursor we should get rid of the cursor by fetching row 0 */ if (imp_sth->exe_mode==OCI_STMT_SCROLLABLE_READONLY){ - OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp, 0,OCI_FETCH_NEXT,0, status); + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp, 0,OCI_FETCH_NEXT,0, status); } return 1; } @@ -978,7 +981,7 @@ dbd_db_rollback(SV *dbh, imp_dbh_t *imp_dbh) { dTHX; sword status; - OCITransRollback_log_stat(imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT, status); + OCITransRollback_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCITransRollback"); return 0; @@ -1056,17 +1059,17 @@ dbd_db_disconnect(SV *dbh, imp_dbh_t *imp_dbh) sword s_se, s_sd; #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { - OCISessionRelease_log_stat(imp_dbh->svchp, imp_dbh->errhp,s_se); + OCISessionRelease_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp,s_se); } else { #endif - OCISessionEnd_log_stat(imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, + OCISessionEnd_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, OCI_DEFAULT, s_se); #ifdef ORA_OCI_112 } #endif if (s_se) oci_error(dbh, imp_dbh->errhp, s_se, "OCISessionEnd"); - OCIServerDetach_log_stat(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, s_sd); + OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, s_sd); if (s_sd) oci_error(dbh, imp_dbh->errhp, s_sd, "OCIServerDetach"); if (s_se || s_sd) return 0; @@ -1104,29 +1107,29 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) OCIFocbkStruct tafailover; tafailover.fo_ctx = NULL; tafailover.callback_function = NULL; - OCIAttrSet_log_stat(imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, (dvoid *) &tafailover, (ub4) 0, (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); } #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { - OCIHandleFree_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION,status); - OCISessionPoolDestroy_log_stat(imp_dbh->poolhp, imp_dbh->errhp,status); - OCIHandleFree_log_stat(imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION,status); + OCISessionPoolDestroy_log_stat(imp_dbh, imp_dbh->poolhp, imp_dbh->errhp,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); } else { #endif - OCIHandleFree_log_stat(imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); #ifdef ORA_OCI_112 } #endif - OCIHandleFree_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); } - OCIHandleFree_log_stat(imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); dbd_db_destroy_out: DBIc_IMPSET_off(imp_dbh); } @@ -1150,7 +1153,7 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) else if (kl==15 && strEQ(key, "ora_driver_name") ) { imp_dbh->driver_name = (char *) SvPV (valuesv, vl ); imp_dbh->driver_namel= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); } else if (kl==8 && strEQ(key, "ora_drcp") ) { imp_dbh->using_drcp = 1; @@ -1182,30 +1185,30 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) else if (kl==10 && strEQ(key, "ora_action") ) { imp_dbh->action = (char *) SvPV (valuesv, vl ); imp_dbh->actionl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } else if (kl==10 && strEQ(key, "ora_action") ) { imp_dbh->action = (char *) SvPV (valuesv, vl ); imp_dbh->actionl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } else if (kl==21 && strEQ(key, "ora_client_identifier") ) { imp_dbh->client_identifier = (char *) SvPV (valuesv, vl ); imp_dbh->client_identifierl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); } else if (kl==15 && strEQ(key, "ora_client_info") ) { imp_dbh->client_info = (char *) SvPV (valuesv, vl ); imp_dbh->client_infol= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); } else if (kl==15 && strEQ(key, "ora_module_name") ) { imp_dbh->module_name = (char *) SvPV (valuesv, vl ); imp_dbh->module_namel= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); } else if (kl==20 && strEQ(key, "ora_oci_success_warn") ) { @@ -1391,9 +1394,9 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ PerlIO_printf(DBIc_LOGPIO(imp_sth), " use a temp lob locator for large xml \n"); - OCIDescriptorAlloc_ok(imp_dbh->envhp, &src_ptr, OCI_DTYPE_LOB); + OCIDescriptorAlloc_ok(imp_dbh, imp_dbh->envhp, &src_ptr, OCI_DTYPE_LOB); - OCILobCreateTemporary_log_stat(imp_dbh->svchp, imp_sth->errhp, + OCILobCreateTemporary_log_stat(imp_dbh, imp_dbh->svchp, imp_sth->errhp, (OCILobLocator *) src_ptr, (ub2) OCI_DEFAULT, (ub1) OCI_DEFAULT, OCI_TEMP_CLOB, FALSE, OCI_DURATION_SESSION, status); @@ -1402,7 +1405,7 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ } csid = (SvUTF8(source) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); buflen = len; - OCILobWriteAppend_log_stat(imp_dbh->svchp, imp_dbh->errhp, src_ptr, + OCILobWriteAppend_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, src_ptr, &buflen, bufp, (ub4)len, OCI_ONE_PIECE, NULL, NULL, csid, csform, status); @@ -1425,13 +1428,15 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ - status = OCIXMLTypeCreateFromSrc(imp_dbh->svchp, - imp_dbh->errhp, - (OCIDuration)OCI_DURATION_CALLOUT, - (ub1)src_type, - (dvoid *)src_ptr, - (sb4)OCI_IND_NOTNULL, - &xml); + OCIXMLTypeCreateFromSrc_log_stat(imp_dbh, + imp_dbh->svchp, + imp_dbh->errhp, + (OCIDuration)OCI_DURATION_CALLOUT, + (ub1)src_type, + (dvoid *)src_ptr, + (sb4)OCI_IND_NOTNULL, + &xml, + status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIXMLTypeCreateFromSrc"); @@ -1442,7 +1447,7 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ OCILobFreeTemporary(imp_dbh->svchp, imp_dbh->errhp, (OCILobLocator*) src_ptr); - OCIDescriptorFree((dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB); + OCIDescriptorFree_log(imp_dbh, (dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB); } @@ -1923,7 +1928,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } } /* Do actual bind */ - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), phs->array_buf, phs->maxlen, @@ -1939,7 +1944,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); return 0; } - OCIBindArrayOfStruct_log_stat(phs->bndhp, imp_sth->errhp, + OCIBindArrayOfStruct_log_stat(imp_sth, phs->bndhp, imp_sth->errhp, (unsigned)phs->maxlen, /* Skip parameter for the next data value */ (unsigned)sizeof (OCIInd), /* Skip parameter for the next indicator value */ (unsigned)sizeof(unsigned short), /* Skip parameter for the next actual length value */ @@ -1952,7 +1957,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) /* Fixup charset */ if (csform) { /* set OCI_ATTR_CHARSET_FORM before we get the default OCI_ATTR_CHARSET_ID */ - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_FORM)")); @@ -1961,7 +1966,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (!phs->csid_orig) { /* get the default csid Oracle would use */ - OCIAttrGet_log_stat(phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , + OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); } @@ -1986,7 +1991,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (csid) { - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csid, (ub4) 0, (ub4) OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_ID)")); @@ -1995,7 +2000,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (phs->maxdata_size) { - OCIAttrSet_log_stat(phs->bndhp, (ub4)OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4)OCI_HTYPE_BIND, phs->array_buf, (ub4)phs->array_buflen, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); @@ -2009,10 +2014,10 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) /* Copy array data from array buffer into perl array */ /* Returns false on error, true on success */ -int dbd_phs_varchar_table_posy_exe(phs_t *phs){ +int dbd_phs_varchar_table_posy_exe(imp_sth_t *imp_sth, phs_t *phs){ dTHX; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; if( ( ! SvROK(phs->sv) ) || (SvTYPE(SvRV(phs->sv))!=SVt_PVAV) ) { /* Allow only array binds */ @@ -2020,7 +2025,7 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ neatsvpv(phs->sv,0), phs->name); } if (trace_level >= 1 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): Called for '%s' : array_numstruct=%d, maxlen=%ld \n", phs->name, phs->array_numstruct, @@ -2060,14 +2065,14 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ if( item ){ SvSetMagicSV(item,&PL_sv_undef); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): arr[%d] = undef; SvSetMagicSV(item,&PL_sv_undef);\n",i); } } else{ av_store(arr,i,&PL_sv_undef); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): arr[%d] = undef; av_store(arr,i,&PL_sv_undef);\n",i); } } @@ -2076,7 +2081,7 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ if( (phs->array_indicators[i] == -2) || (phs->array_indicators[i] > 0) ){ /* Truncation occurred */ if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): Placeholder '%s': data truncated at %d row.\n", phs->name,i); } @@ -2088,7 +2093,7 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ sv_setpvn_mg(item,phs->array_buf+phs->maxlen*i,phs->array_lengths[i]); SvPOK_only_UTF8(item); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): arr[%d] = '%s'; " "sv_setpvn_mg(item,phs->array_buf+phs->maxlen*i,phs->array_lengths[i]); \n", i, phs->array_buf+phs->maxlen*i @@ -2098,7 +2103,7 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ else{ av_store(arr,i,newSVpvn(phs->array_buf+phs->maxlen*i,phs->array_lengths[i])); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): arr[%d] = '%s'; " "av_store(arr,i,newSVpvn(phs->array_buf+phs->maxlen*i,phs->array_lengths[i])); \n", i, phs->array_buf+phs->maxlen*i @@ -2109,7 +2114,7 @@ int dbd_phs_varchar_table_posy_exe(phs_t *phs){ } } if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_varchar_table_posy_exe(): scalar(@arr)=%ld.\n", (long)av_len(arr)+1); } @@ -2359,7 +2364,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { } } /* Do actual bind */ - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), phs->array_buf, phs->maxlen, @@ -2375,7 +2380,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); return 0; } - OCIBindArrayOfStruct_log_stat(phs->bndhp, imp_sth->errhp, + OCIBindArrayOfStruct_log_stat(imp_sth, phs->bndhp, imp_sth->errhp, (unsigned)phs->maxlen, /* Skip parameter for the next data value */ (unsigned)sizeof(OCIInd), /* Skip parameter for the next indicator value */ (unsigned)sizeof(unsigned short), /* Skip parameter for the next actual length value */ @@ -2386,7 +2391,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { return 0; } if (phs->maxdata_size) { - OCIAttrSet_log_stat(phs->bndhp, (ub4)OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4)OCI_HTYPE_BIND, phs->array_buf, (ub4)phs->array_buflen, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); @@ -2400,10 +2405,10 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /* Copy array data from array buffer into perl array */ /* Returns false on error, true on success */ -int dbd_phs_number_table_post_exe(phs_t *phs){ +int dbd_phs_number_table_post_exe(imp_sth_t *imp_sth, phs_t *phs){ dTHX; - int trace_level = DBIS->debug; + int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; if( ( ! SvROK(phs->sv) ) || (SvTYPE(SvRV(phs->sv))!=SVt_PVAV) ) { /* Allow only array binds */ @@ -2411,7 +2416,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ neatsvpv(phs->sv,0), phs->name); } if (trace_level >= 1 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): Called for '%s' : array_numstruct=%d, maxlen=%ld \n", phs->name, phs->array_numstruct, @@ -2457,7 +2462,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ if( item ){ SvSetMagicSV(item,&PL_sv_undef); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): arr[%d] = undef; SvSetMagicSV(item,&PL_sv_undef);\n", i ); @@ -2465,7 +2470,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ }else{ av_store(arr,i,&PL_sv_undef); if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): arr[%d] = undef; av_store(arr,i,&PL_sv_undef);\n", i ); @@ -2475,7 +2480,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ if( (phs->array_indicators[i] == -2) || (phs->array_indicators[i] > 0) ){ /* Truncation occurred */ if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): Placeholder '%s': data truncated at %d row.\n", phs->name,i); } @@ -2486,7 +2491,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ switch(phs->ora_internal_type){ case SQLT_INT: if (trace_level >= 4 || dbd_verbose >= 4 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): (int) set arr[%d] = %d \n", i, *(int*)(phs->array_buf+phs->maxlen*i) ); @@ -2495,7 +2500,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ break; case SQLT_FLT: if (trace_level >= 4 || dbd_verbose >= 4 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): (double) set arr[%d] = %lf \n", i, *(double*)(phs->array_buf+phs->maxlen*i) ); @@ -2505,7 +2510,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ if (trace_level >= 3 || dbd_verbose >= 3 ){ STRLEN l; char *str= SvPOK(item) ? SvPV(item,l) : "" ; - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): arr[%d] = '%s'\n", i, str ? str : "" ); @@ -2514,7 +2519,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ switch(phs->ora_internal_type){ case SQLT_INT: if (trace_level >= 4 || dbd_verbose >= 4 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): (int) store new arr[%d] = %d \n", i, *(int*)(phs->array_buf+phs->maxlen*i) ); @@ -2523,7 +2528,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ break; case SQLT_FLT: if (trace_level >= 4 || dbd_verbose >= 4 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): (double) store new arr[%d] = %lf \n", i, *(double*)(phs->array_buf+phs->maxlen*i) ); @@ -2538,7 +2543,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ item=*pitem; } str= item ? ( SvPOK(item) ? SvPV(item,l) : "" ) : ""; - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): arr[%d] = '%s'\n", i, str ? str : "" ); @@ -2548,7 +2553,7 @@ int dbd_phs_number_table_post_exe(phs_t *phs){ } } if (trace_level >= 2 || dbd_verbose >= 3 ){ - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), "dbd_phs_number_table_post_exe(): scalar(@arr)=%ld.\n", (long)av_len(arr)+1); } @@ -2696,7 +2701,7 @@ pp_rebind_ph_rset_in(SV *sth, imp_sth_t *imp_sth, phs_t *phs) imp_sth->stmhp, phs->bndhp, imp_sth->errhp, phs->name, imp_sth_csr->stmhp, phs->ftype); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), &imp_sth_csr->stmhp, 0, @@ -2744,18 +2749,18 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) if (!phs->desc_h || 1) { /* XXX phs->desc_t != OCI_HTYPE_STMT) */ if (phs->desc_h) { - OCIHandleFree_log_stat(phs->desc_h, phs->desc_t, status); + OCIHandleFree_log_stat(imp_sth, phs->desc_h, phs->desc_t, status); phs->desc_h = NULL; } phs->desc_t = OCI_HTYPE_STMT; - OCIHandleAlloc_ok(imp_sth->envhp, &phs->desc_h, phs->desc_t, status); + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &phs->desc_h, phs->desc_t, status); } phs->progv = (char*)&phs->desc_h; phs->maxlen = 0; - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), phs->progv, @@ -2864,12 +2869,19 @@ sword status; /* ensure that the value is a support named object type */ /* (currently only OCIXMLType*) */ if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { - OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, - (CONST text*)"SYS", 3, - (CONST text*)"XMLTYPE", 7, - (CONST text*)0, 0, - OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, - &tdo); + /* TO_DO not logging: */ + OCITypeByName_log( + imp_sth, + imp_sth->envhp, + imp_sth->errhp, + imp_sth->svchp, + (CONST text*)"SYS", 3, /* schema_name, schema_length */ + (CONST text*)"XMLTYPE", 7, /* type_name, type_length */ + (CONST text*)0, 0, /* version_name, version_length */ + OCI_DURATION_CALLOUT, /* pin_duration */ + OCI_TYPEGET_HEADER, /* get_option */ + &tdo, /* tdo */ + status); ptr = SvRV(phs->sv); phs->progv = (void*) SvIV(ptr); phs->maxlen = sizeof(OCIXMLType*); @@ -2880,7 +2892,7 @@ sword status; /* bind by name */ - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), (dvoid *) NULL, /* value supplied in BindObject later */ 0, @@ -2974,7 +2986,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) at_exec = (phs->desc_h == NULL); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), phs->progv, phs->maxlen ? (sb4)phs->maxlen : 1, /* else bind "" fails */ @@ -2991,7 +3003,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) return 0; } if (at_exec) { - OCIBindDynamic_log(phs->bndhp, imp_sth->errhp, + OCIBindDynamic_log(imp_sth, phs->bndhp, imp_sth->errhp, (dvoid *)phs, dbd_phs_in, (dvoid *)phs, dbd_phs_out, status); @@ -3022,7 +3034,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (csform) { /* set OCI_ATTR_CHARSET_FORM before we get the default OCI_ATTR_CHARSET_ID */ - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_FORM)")); @@ -3031,7 +3043,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (!phs->csid_orig) { /* get the default csid Oracle would use */ - OCIAttrGet_log_stat(phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , + OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); } @@ -3057,7 +3069,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) (unsigned long)phs->maxlen, (unsigned long)phs->maxdata_size); if (csid) { - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csid, (ub4) 0, (ub4) OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_ID)")); @@ -3066,7 +3078,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (phs->maxdata_size) { - OCIAttrSet_log_stat(phs->bndhp, (ub4)OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4)OCI_HTYPE_BIND, neatsvpv(phs->sv,0), (ub4)phs->maxdata_size, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); @@ -3278,7 +3290,7 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ /* --- functions to 'complete' the fetch of a value --- */ void -dbd_phs_sv_complete(phs_t *phs, SV *sv, I32 debug) +dbd_phs_sv_complete(imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug) { dTHX; char *note = ""; @@ -3356,14 +3368,15 @@ dbd_phs_sv_complete(phs_t *phs, SV *sv, I32 debug) } } void -dbd_phs_avsv_complete(phs_t *phs, I32 index, I32 debug) +dbd_phs_avsv_complete(imp_sth_t *imp_sth, phs_t *phs, I32 index, I32 debug) { dTHX; AV *av = (AV*)SvRV(phs->sv); SV *sv = *av_fetch(av, index, 1); - dbd_phs_sv_complete(phs, sv, 0); + dbd_phs_sv_complete(imp_sth, phs, sv, 0); if (debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " dbd_phs_avsv_complete out '%s'[%ld] = %s (arcode %d, ind %d, len %d)\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " dbd_phs_avsv_complete out '%s'[%ld] = %s (arcode %d, ind %d, len %d)\n", phs->name, (long)index, neatsvpv(sv,0), phs->arcode, phs->indp, phs->alen); } @@ -3473,7 +3486,7 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- "Statement Execute Mode is %d (%s)\n", imp_sth->exe_mode,oci_exe_mode(imp_sth->exe_mode)); - OCIStmtExecute_log_stat(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, + OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, (ub4)(is_select ? 0: 1), 0, 0, 0,(ub4)imp_sth->exe_mode,status); @@ -3534,11 +3547,11 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- phs->name,phs->ftype,sql_typecode_name(phs->ftype)); } if( phs->ftype == ORA_VARCHAR2_TABLE ){ - dbd_phs_varchar_table_posy_exe(phs); + dbd_phs_varchar_table_posy_exe(imp_sth, phs); continue; } if( phs->ftype == ORA_NUMBER_TABLE ){ - dbd_phs_number_table_post_exe(phs); + dbd_phs_number_table_post_exe(imp_sth, phs); continue; } @@ -3551,10 +3564,10 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- AV *av = (AV*)SvRV(sv); I32 avlen = AvFILL(av); if (avlen >= 0) - dbd_phs_avsv_complete(phs, avlen, debug); + dbd_phs_avsv_complete(imp_sth, phs, avlen, debug); } else { - dbd_phs_sv_complete(phs, sv, debug); + dbd_phs_sv_complete(imp_sth, phs, sv, debug); } } } @@ -3578,7 +3591,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat ub2 csid; int trace_level = DBIc_DBISTATE(imp_sth)->debug; int i; - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, + OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), 0, phs->maxlen ? (sb4)phs->maxlen : 1, /* else bind "" fails */ @@ -3595,7 +3608,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat } - OCIBindDynamic_log(phs->bndhp, imp_sth->errhp, + OCIBindDynamic_log(imp_sth, phs->bndhp, imp_sth->errhp, (dvoid *)phs, dbd_phs_in, (dvoid *)phs, dbd_phs_out, status); if (status != OCI_SUCCESS) { @@ -3623,7 +3636,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat if (csform) { /* set OCI_ATTR_CHARSET_FORM before we get the default OCI_ATTR_CHARSET_ID */ - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_FORM)")); @@ -3632,7 +3645,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat } if (!phs->csid_orig) { /* get the default csid Oracle would use */ - OCIAttrGet_log_stat(phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , + OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); } @@ -3678,7 +3691,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat (unsigned long)phs->maxlen, (unsigned long)phs->maxdata_size); if (csid) { - OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND, + OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4) OCI_HTYPE_BIND, &csid, (ub4) 0, (ub4) OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); if ( status != OCI_SUCCESS ) { oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_ID)")); @@ -3900,7 +3913,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er if(autocommit) oci_mode |= OCI_COMMIT_ON_SUCCESS; - OCIStmtExecute_log_stat(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, + OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, exe_count, 0, 0, 0, oci_mode, exe_status); OCIAttrGet_stmhp_stat(imp_sth, &row_count, 0, OCI_ATTR_ROW_COUNT, status); @@ -3922,7 +3935,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er AV *av = (AV*)SvRV(sv); I32 avlen = AvFILL(av); for (j=0;j<=avlen;j++){ - dbd_phs_avsv_complete(phs, j, debug); + dbd_phs_avsv_complete(imp_sth, phs, j, debug); } } } @@ -3946,13 +3959,13 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er err_svs[0] = newSViv((IV)0); err_svs[1] = newSVpvn("", 0); err_svs[2] = newSVpvn("S1000",5); - OCIHandleAlloc_ok(imp_sth->envhp, &row_errhp, OCI_HTYPE_ERROR, status); - OCIHandleAlloc_ok(imp_sth->envhp, &tmp_errhp, OCI_HTYPE_ERROR, status); + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &row_errhp, OCI_HTYPE_ERROR, status); + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &tmp_errhp, OCI_HTYPE_ERROR, status); for(i = 0; (unsigned int) i < num_errs; i++) { - OCIParamGet_log_stat(imp_sth->errhp, OCI_HTYPE_ERROR, + OCIParamGet_log_stat(imp_sth, imp_sth->errhp, OCI_HTYPE_ERROR, tmp_errhp, (dvoid *)&row_errhp, (ub4)i, status); - OCIAttrGet_log_stat(row_errhp, OCI_HTYPE_ERROR, &row_off, 0, + OCIAttrGet_log_stat(imp_sth, row_errhp, OCI_HTYPE_ERROR, &row_off, 0, OCI_ATTR_DML_ROW_OFFSET, imp_sth->errhp, status); if (debug >= 6 || dbd_verbose >= 6 ) PerlIO_printf( @@ -3960,18 +3973,18 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er " ora_st_execute_array error in row %d.\n", row_off); sv_setpv(err_svs[1], ""); - err_code = oci_error_get(row_errhp, exe_status, NULL, err_svs[1], debug); + err_code = oci_error_get((imp_xxh_t *)imp_sth, row_errhp, exe_status, NULL, err_svs[1], debug); sv_setiv(err_svs[0], (IV)err_code); av_store(tuples_status_av, row_off, newRV_noinc((SV *)(av_make(3, err_svs)))); } - OCIHandleFree_log_stat(tmp_errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(row_errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_sth, tmp_errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_sth, row_errhp, OCI_HTYPE_ERROR, status); /* Do a commit here if autocommit is set, since Oracle doesn't do that for us when some rows are in error. */ if(autocommit) { - OCITransCommit_log_stat(imp_sth->svchp, imp_sth->errhp, + OCITransCommit_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCITransCommit"); @@ -4090,7 +4103,7 @@ dbd_st_finish(SV *sth, imp_sth_t *imp_sth) not sure if we need this for non scrolling cursors they should die on a OER(1403) no records)*/ - OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp, 0, + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp, 0, OCI_FETCH_NEXT,0, status); if (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO) { @@ -4117,14 +4130,14 @@ ora_free_fbh_contents(SV *sth, imp_fbh_t *fbh) boolean is_open; sword status; - OCILobFileIsOpen_log_stat(imp_dbh->svchp, imp_dbh->errhp, fbh->desc_h, &is_open, status); + OCILobFileIsOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, fbh->desc_h, &is_open, status); if (status == OCI_SUCCESS && is_open) { - OCILobFileClose_log_stat(imp_sth->svchp, imp_sth->errhp, + OCILobFileClose_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, fbh->desc_h, status); } - OCIDescriptorFree_log(fbh->desc_h, fbh->desc_t); + OCIDescriptorFree_log(imp_sth, fbh->desc_h, fbh->desc_t); } if (fbh->obj) { @@ -4136,11 +4149,11 @@ ora_free_fbh_contents(SV *sth, imp_fbh_t *fbh) } void -ora_free_phs_contents(phs_t *phs) +ora_free_phs_contents(imp_sth_t *imp_sth, phs_t *phs) { dTHX; if (phs->desc_h) - OCIDescriptorFree_log(phs->desc_h, phs->desc_t); + OCIDescriptorFree_log(imp_sth, phs->desc_h, phs->desc_t); if( phs->array_buf ){ free(phs->array_buf); phs->array_buf=NULL; @@ -4167,7 +4180,7 @@ ora_free_templob(SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc) #if defined(OCI_HTYPE_DIRPATH_FN_CTX) /* >= 9.0 */ boolean is_temporary = 0; sword status; - OCILobIsTemporary_log_stat(imp_sth->envhp, imp_sth->errhp, lobloc, &is_temporary, status); + OCILobIsTemporary_log_stat(imp_sth, imp_sth->envhp, imp_sth->errhp, lobloc, &is_temporary, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobIsTemporary"); return; @@ -4179,7 +4192,7 @@ ora_free_templob(SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc) DBIc_LOGPIO(imp_sth), " OCILobFreeTemporary %s\n", oci_status_name(status)); } - OCILobFreeTemporary_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, status); + OCILobFreeTemporary_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobloc, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobFreeTemporary"); return; @@ -4208,11 +4221,11 @@ dbd_st_destroy(SV *sth, imp_sth_t *imp_sth) cursor by fetching row 0 */ if (imp_sth->exe_mode==OCI_STMT_SCROLLABLE_READONLY){ - OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp, 0,OCI_FETCH_NEXT,0, status); + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp, 0,OCI_FETCH_NEXT,0, status); } if (imp_sth->dschp){ - OCIHandleFree_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); } @@ -4223,7 +4236,7 @@ dbd_st_destroy(SV *sth, imp_sth_t *imp_sth) if (!PL_dirty) { /* XXX not ideal, leak may be a problem in some cases */ if (!imp_sth->nested_cursor) { - OCIHandleFree_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, status); if (status != OCI_SUCCESS) oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); } @@ -4260,7 +4273,7 @@ dbd_st_destroy(SV *sth, imp_sth_t *imp_sth) phs_t *phs = (phs_t*)(void*)SvPVX(sv); if (phs->desc_h && phs->desc_t == OCI_DTYPE_LOB) ora_free_templob(sth, imp_sth, (OCILobLocator*)phs->desc_h); - ora_free_phs_contents(phs); + ora_free_phs_contents(imp_sth, phs); } } sv_free((SV*)imp_sth->all_params_hv); @@ -4482,9 +4495,8 @@ ora2sql_type(imp_fbh_t* fbh) { } static void -dump_env_to_trace() { +dump_env_to_trace(imp_dbh_t *imp_dbh) { dTHX; - PerlIO *fp = DBILOGFP; int i = 0; char *p; @@ -4496,10 +4508,10 @@ dump_env_to_trace() { #endif - PerlIO_printf(fp, "Environment variables:\n"); + PerlIO_printf(DBIc_LOGPIO(imp_dbh), "Environment variables:\n"); do { - p = (char*)environ[i++]; - PerlIO_printf(fp,"\t%s\n",p); + p = (char*)environ[i++]; + PerlIO_printf(DBIc_LOGPIO(imp_dbh),"\t%s\n",p); } while ((char*)environ[i] != '\0'); } diff --git a/dbdimp.h b/dbdimp.h index 68664a3a..19e6e176 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -320,7 +320,7 @@ extern ub2 al16utf16_csid; void dbd_init_oci _((dbistate_t *dbistate)); void dbd_preparse _((imp_sth_t *imp_sth, char *statement)); -void dbd_fbh_dump(imp_fbh_t *fbh, int i, int aidx); +void dbd_fbh_dump(imp_sth_t *imp_sth, imp_fbh_t *fbh, int i, int aidx); void ora_free_fbh_contents _((SV *sth, imp_fbh_t *fbh)); void ora_free_templob _((SV *sth, imp_sth_t *imp_sth, OCILobLocator *lobloc)); int ora_dbtype_is_long _((int dbtype)); @@ -329,8 +329,8 @@ fb_ary_t *fb_ary_cb_alloc _((ub4 piece_size,ub4 max_len, int size)); int ora_db_reauthenticate _((SV *dbh, imp_dbh_t *imp_dbh, char *uid, char *pwd)); -void dbd_phs_sv_complete _((phs_t *phs, SV *sv, I32 debug)); -void dbd_phs_avsv_complete _((phs_t *phs, I32 index, I32 debug)); +void dbd_phs_sv_complete _((imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug)); +void dbd_phs_avsv_complete _((imp_sth_t *imp_sth, phs_t *phs, I32 index, I32 debug)); int pp_exec_rset _((SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec)); int pp_rebind_ph_rset_in _((SV *sth, imp_sth_t *imp_sth, phs_t *phs)); @@ -366,8 +366,8 @@ int ora_st_execute_array _((SV *sth, imp_sth_t *imp_sth, SV *tuples, SV * ora_create_xml _((SV *dbh, char *source)); void ora_free_lob_refetch _((SV *sth, imp_sth_t *imp_sth)); -void dbd_phs_avsv_complete _((phs_t *phs, I32 index, I32 debug)); -void dbd_phs_sv_complete _((phs_t *phs, SV *sv, I32 debug)); +void dbd_phs_avsv_complete _((imp_sth_t *imp_sth, phs_t *phs, I32 index, I32 debug)); +void dbd_phs_sv_complete _((imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug)); int post_execute_lobs _((SV *sth, imp_sth_t *imp_sth, ub4 row_count)); ub4 ora_parse_uid _((imp_dbh_t *imp_dbh, char **uidp, char **pwdp)); char *ora_sql_error _((imp_sth_t *imp_sth, char *msg)); diff --git a/oci8.c b/oci8.c index 1f380415..48d00d67 100644 --- a/oci8.c +++ b/oci8.c @@ -109,7 +109,7 @@ oci_ptype_name(int ptype) return SvPVX(sv); } */ - + char * oci_exe_mode(ub4 mode) { @@ -812,7 +812,8 @@ oci_fetch_options(ub4 fetchtype) static sb4 -oci_error_get(OCIError *errhp, sword status, char *what, SV *errstr, int debug) +oci_error_get(imp_xxh_t *imp_xxh, + OCIError *errhp, sword status, char *what, SV *errstr, int debug) { dTHX; text errbuf[1024]; @@ -834,12 +835,13 @@ oci_error_get(OCIError *errhp, sword status, char *what, SV *errstr, int debug) } while( ++recno - && OCIErrorGet_log_stat(errhp, recno, (text*)NULL, &eg_errcode, errbuf, + && OCIErrorGet_log_stat(imp_xxh, errhp, recno, (text*)NULL, &eg_errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR, eg_status) != OCI_NO_DATA && eg_status != OCI_INVALID_HANDLE && recno < 100) { if (debug >= 4 || recno>1/*XXX temp*/) - PerlIO_printf(DBILOGFP, " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", + PerlIO_printf(DBIc_LOGPIO(imp_xxh), + " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", what ? what : "", (long)recno, (eg_status==OCI_SUCCESS) ? "ok" : oci_status_name(eg_status), status, (long)eg_errcode, errbuf); @@ -873,7 +875,8 @@ oci_error_err(SV *h, OCIError *errhp, sword status, char *what, sb4 force_err) sb4 errcode; SV *errstr_sv = sv_newmortal(); SV *errcode_sv = sv_newmortal(); - errcode = oci_error_get(errhp, status, what, errstr_sv, DBIS->debug); + errcode = oci_error_get(imp_xxh, errhp, status, what, errstr_sv, + DBIc_DBISTATE(imp_xxh)->debug); if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { #ifdef sv_utf8_decode sv_utf8_decode(errstr_sv); @@ -1051,14 +1054,14 @@ dbd_st_prepare(SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs) - OCIHandleAlloc_ok(imp_dbh->envhp, &imp_sth->stmhp, OCI_HTYPE_STMT, status); - OCIStmtPrepare_log_stat(imp_sth->stmhp, imp_sth->errhp, + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_sth->stmhp, OCI_HTYPE_STMT, status); + OCIStmtPrepare_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp, (text*)imp_sth->statement, (ub4)strlen(imp_sth->statement), OCI_NTV_SYNTAX, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCIStmtPrepare"); - OCIHandleFree_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, status); return 0; } @@ -1066,7 +1069,7 @@ dbd_st_prepare(SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs) OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->stmt_type, 0, OCI_ATTR_STMT_TYPE, status); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_st_prepare'd sql %s ( auto_lob%d, check_sql%d)\n", @@ -1348,9 +1351,9 @@ reg_taf_callback( imp_dbh_t *imp_dbh) tafailover.callback_function = &taf_cbk; /* register the callback */ - OCIAttrSet_log_stat(imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, - (dvoid *) &tafailover, (ub4) 0, - (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, + (dvoid *) &tafailover, (ub4) 0, + (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); return status; } @@ -1427,7 +1430,7 @@ fetch_func_varfield(SV *sth, imp_fbh_t *fbh, SV *dest_sv) return 0; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " fetching field %d of %d. LONG value truncated from " @@ -1454,6 +1457,7 @@ static void fetch_cleanup_rset(SV *sth, imp_fbh_t *fbh) { dTHX; + D_imp_sth(sth); SV *sth_nested = (SV *)fbh->special; fbh->special = NULL; @@ -1468,8 +1472,8 @@ fetch_cleanup_rset(SV *sth, imp_fbh_t *fbh) if (fbh_nested->fetch_cleanup) fbh_nested->fetch_cleanup(sth_nested, fbh_nested); } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_sth), " fetch_cleanup_rset - deactivating handle %s (defunct nested cursor)\n", neatsvpv(sth_nested, 0)); @@ -1490,7 +1494,7 @@ fetch_func_rset(SV *sth, imp_fbh_t *fbh, SV *dest_sv) HV *init_attr = newHV(); int count; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " fetch_func_rset - allocating handle for cursor nested within %s ...\n", @@ -1511,7 +1515,7 @@ fetch_func_rset(SV *sth, imp_fbh_t *fbh, SV *dest_sv) SvREFCNT_dec(init_attr); PUTBACK; FREETMPS; LEAVE; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " fetch_func_rset - ... allocated %s for nested cursor\n", @@ -1547,7 +1551,7 @@ dbd_rebind_ph_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { dTHX; - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_rebind_ph_rset phs->is_inout=%d\n", @@ -1600,11 +1604,11 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (!phs->desc_h) { ++imp_sth->has_lobs; phs->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_sth->envhp, + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &phs->desc_h, phs->desc_t); } - OCIAttrSet_log_stat(phs->desc_h, phs->desc_t, + OCIAttrSet_log_stat(imp_sth, phs->desc_h, phs->desc_t, &lobEmpty, 0, OCI_ATTR_LOBEMPTY, imp_sth->errhp, status); if (status != OCI_SUCCESS) @@ -1635,7 +1639,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) src = INT2PTR(OCILobLocator *, SvIV(SvRV(phs->sv))); dest = (OCILobLocator **) phs->progv; - OCILobLocatorAssign_log_stat(imp_dbh->svchp, imp_sth->errhp, src, dest, status); + OCILobLocatorAssign_log_stat(imp_dbh, imp_dbh->svchp, imp_sth->errhp, src, dest, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobLocatorAssign"); return 0; @@ -1655,7 +1659,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (amtp > 0) { ub1 lobtype = (phs->ftype == 112 ? OCI_TEMP_CLOB : OCI_TEMP_BLOB); - OCILobCreateTemporary_log_stat(imp_dbh->svchp, imp_sth->errhp, + OCILobCreateTemporary_log_stat(imp_dbh, imp_dbh->svchp, imp_sth->errhp, (OCILobLocator *) phs->desc_h, (ub2) OCI_DEFAULT, (ub1) OCI_DEFAULT, lobtype, TRUE, OCI_DURATION_SESSION, status); if (status != OCI_SUCCESS) { @@ -1666,12 +1670,22 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if( ! phs->csid ) { ub1 csform = SQLCS_IMPLICIT; ub2 csid = 0; - OCILobCharSetForm_log_stat( imp_sth->envhp, imp_sth->errhp, (OCILobLocator*)phs->desc_h, &csform, status ); + OCILobCharSetForm_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + (OCILobLocator*)phs->desc_h, + &csform, + status ); if (status != OCI_SUCCESS) return oci_error(sth, imp_sth->errhp, status, "OCILobCharSetForm"); #ifdef OCI_ATTR_CHARSET_ID /* Effectively only used so AL32UTF8 works properly */ - OCILobCharSetId_log_stat( imp_sth->envhp, imp_sth->errhp, (OCILobLocator*)phs->desc_h, &csid, status ); + OCILobCharSetId_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + (OCILobLocator*)phs->desc_h, + &csid, + status ); if (status != OCI_SUCCESS) return oci_error(sth, imp_sth->errhp, status, "OCILobCharSetId"); #endif /* OCI_ATTR_CHARSET_ID */ @@ -1681,7 +1695,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) phs->csform = csform; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " calling OCILobWrite phs->csid=%d phs->csform=%d amtp=%d\n", @@ -1689,7 +1703,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) /* write lob data */ - OCILobWrite_log_stat(imp_sth->svchp, imp_sth->errhp, + OCILobWrite_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, (OCILobLocator*)phs->desc_h, &amtp, 1, SvPVX(phs->sv), amtp, OCI_ONE_PIECE, 0,0, phs->csid, phs->csform, status); if (status != OCI_SUCCESS) { @@ -1722,7 +1736,12 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, */ ub1 csform = SQLCS_IMPLICIT; - OCILobCharSetForm_log_stat( imp_sth->envhp, imp_sth->errhp, lobl, &csform, status ); + OCILobCharSetForm_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + lobl, + &csform, + status ); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobCharSetForm"); sv_set_undef(dest_sv); /* signal error */ @@ -1737,7 +1756,7 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, return 0; } - OCILobGetLength_log_stat(imp_sth->svchp, imp_sth->errhp, + OCILobGetLength_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobl, &loblen, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobGetLength ora_blob_read_mb_piece"); @@ -1758,7 +1777,7 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, New(42, buffer, buflen, ub1); - OCILobRead_log_stat(imp_sth->svchp, imp_sth->errhp, lobl, + OCILobRead_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobl, &amtp, (ub4)1 + offset, buffer, buflen, 0, 0, (ub2)0 ,csform ,status ); /* lab 0, 0, (ub2)0, (ub1)SQLCS_IMPLICIT, status); */ @@ -1842,14 +1861,19 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, return 0; } - OCILobGetLength_log_stat(imp_sth->svchp, imp_sth->errhp, lobl, &loblen, status); + OCILobGetLength_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobl, &loblen, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobGetLength ora_blob_read_piece"); sv_set_undef(dest_sv); /* signal error */ return 0; } - OCILobCharSetForm_log_stat( imp_sth->envhp, imp_sth->errhp, lobl, &csform, status ); + OCILobCharSetForm_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + lobl, + &csform, + status ); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobCharSetForm"); sv_set_undef(dest_sv); /* signal error */ @@ -1892,7 +1916,7 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, buflen = amtp; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " blob_read field %d: ftype %d %s, offset %ld, len %lu." @@ -1904,11 +1928,11 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, ub1 * bufp = (ub1 *)(SvPVX(dest_sv)); bufp += destoffset; - OCILobRead_log_stat(imp_sth->svchp, imp_sth->errhp, lobl, + OCILobRead_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobl, &amtp, (ub4)1 + offset, bufp, buflen, 0, 0, (ub2)0 , csform, status); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu," @@ -1925,7 +1949,7 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, } else { assert(amtp == 0); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " OCILobRead field %d %s: LOBlen %lu, LongReadLen %lu, " @@ -1964,7 +1988,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des /* The length is expressed in terms of bytes for BLOBs and BFILEs, */ /* and in terms of characters for CLOBs and NCLOBS */ - OCILobGetLength_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, &loblen, status); + OCILobGetLength_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobloc, &loblen, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobGetLength fetch_lob"); return 0; @@ -2024,7 +2048,12 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des if (loblen > 0) { ub1 csform = 0; - OCILobCharSetForm_log_stat(imp_sth->envhp, imp_sth->errhp, lobloc, &csform, status ); + OCILobCharSetForm_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + lobloc, + &csform, + status ); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobCharSetForm"); sv_set_undef(dest_sv); @@ -2032,7 +2061,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des } if (ftype == ORA_BFILE) { - OCILobFileOpen_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, + OCILobFileOpen_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobloc, (ub1)OCI_FILE_READONLY, status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobFileOpen"); @@ -2041,7 +2070,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des } } - OCILobRead_log_stat(imp_sth->svchp, imp_sth->errhp, lobloc, + OCILobRead_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobloc, &amtp, (ub4)1, SvPVX(dest_sv), buflen, 0, 0, (ub2)0, csform, status); @@ -2069,7 +2098,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des - if (DBIS->debug >= 3 || dbd_verbose >= 3 || oci_warn){ + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 || oci_warn){ char buf[11]; strcpy(buf,"bytes"); if (ftype == ORA_CLOB) @@ -2085,7 +2114,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des } if (ftype == ORA_BFILE) { - OCILobFileClose_log_stat(imp_sth->svchp, imp_sth->errhp, + OCILobFileClose_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, lobloc, status); } @@ -2107,7 +2136,7 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des /* tell perl what we've put in its dest_sv */ SvCUR(dest_sv) = amtp; *SvEND(dest_sv) = '\0'; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " OCILobRead %s %s: LOBlen %lu, LongReadLen %lu, " @@ -2143,18 +2172,18 @@ fetch_func_getrefpv(SV *sth, imp_fbh_t *fbh, SV *dest_sv) #ifdef OCI_DTYPE_REF static void -fbh_setup_getrefpv(imp_fbh_t *fbh, int desc_t, char *bless) +fbh_setup_getrefpv(imp_sth_t *imp_sth, imp_fbh_t *fbh, int desc_t, char *bless) { dTHX; if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, + PerlIO_printf(DBIc_LOGPIO(imp_sth), " col %d: otype %d, desctype %d, %s", fbh->field_num, fbh->dbtype, desc_t, bless); fbh->ftype = fbh->dbtype; fbh->disize = fbh->dbsize; fbh->fetch_func = fetch_func_getrefpv; fbh->bless = bless; fbh->desc_t = desc_t; - OCIDescriptorAlloc_ok(fbh->imp_sth->envhp, &fbh->desc_h, fbh->desc_t); + OCIDescriptorAlloc_ok(imp_sth, fbh->imp_sth->envhp, &fbh->desc_h, fbh->desc_t); } #endif @@ -2211,6 +2240,7 @@ calc_cache_rows(int cache_rows, int num_fields, int est_width, int has_longs,ub4 static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeCode typecode, dvoid *attr_value ) { dTHX; + D_imp_sth(sth); text str_buf[200]; double dnum; size_t str_len; @@ -2224,8 +2254,10 @@ static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeC SV *raw_sv; /* get the data based on the type code*/ - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, " getting value of object attribute named %s with typecode=%s\n",name,oci_typecode_name(typecode)); + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " getting value of object attribute named %s with typecode=%s\n", + name,oci_typecode_name(typecode)); } switch (typecode) @@ -2234,13 +2266,14 @@ static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeC case OCI_TYPECODE_INTERVAL_YM : case OCI_TYPECODE_INTERVAL_DS : - OCIIntervalToText_log_stat(fbh->imp_sth->envhp, - fbh->imp_sth->errhp, - attr_value, - str_buf, - (size_t) 200, - &str_len, - status); + OCIIntervalToText_log_stat(fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + attr_value, + str_buf, + (size_t) 200, + &str_len, + status); str_buf[str_len+1] = '\0'; av_push(list, newSVpv( (char *) str_buf,0)); break; @@ -2251,8 +2284,13 @@ static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeC ub4_str_len = 200; - OCIDateTimeToText_log_stat(fbh->imp_sth->envhp, - fbh->imp_sth->errhp,attr_value,&ub4_str_len,str_buf,status); + OCIDateTimeToText_log_stat(fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + attr_value, + &ub4_str_len, + str_buf, + status); if (typecode == OCI_TYPECODE_TIMESTAMP_TZ || typecode == OCI_TYPECODE_TIMESTAMP_LTZ){ char s_tz_hour[3]="000"; @@ -2285,7 +2323,12 @@ static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeC case OCI_TYPECODE_DATE : /* fixed length string*/ ub4_str_len = 200; - OCIDateToText_log_stat(fbh->imp_sth->errhp, (CONST OCIDate *) attr_value,&ub4_str_len,str_buf,status); + OCIDateToText_log_stat(fbh->imp_sth, + fbh->imp_sth->errhp, + (CONST OCIDate *) attr_value, + &ub4_str_len, + str_buf, + status); str_buf[ub4_str_len+1] = '\0'; av_push(list, newSVpv( (char *) str_buf,0)); break; @@ -2373,6 +2416,7 @@ int get_object (SV *sth, AV *list, imp_fbh_t *fbh,fbh_obj_t *base_obj,OCIComplexObject *value, OCIType *instance_tdo, dvoid *obj_ind){ dTHX; + D_imp_sth(sth); sword status; dvoid *element ; dvoid *attr_value; @@ -2388,8 +2432,10 @@ get_object (SV *sth, AV *list, imp_fbh_t *fbh,fbh_obj_t *base_obj,OCIComplexObje OCIType *tdo = instance_tdo ? instance_tdo : obj->tdo; - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, " getting attributes of object named %s with typecode=%s\n",obj->type_name,oci_typecode_name(obj->typecode)); + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " getting attributes of object named %s with typecode=%s\n", + obj->type_name,oci_typecode_name(obj->typecode)); } switch (obj->typecode) { @@ -2417,7 +2463,11 @@ get_object (SV *sth, AV *list, imp_fbh_t *fbh,fbh_obj_t *base_obj,OCIComplexObje return 0; } - OCITypeByRef_log_stat(fbh->imp_sth->envhp,fbh->imp_sth->errhp,type_ref,&tdo,status); + OCITypeByRef_log_stat(fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + type_ref, + &tdo,status); if (status != OCI_SUCCESS) { oci_error(sth, fbh->imp_sth->errhp, status, "OCITypeByRef"); @@ -2441,15 +2491,15 @@ get_object (SV *sth, AV *list, imp_fbh_t *fbh,fbh_obj_t *base_obj,OCIComplexObje } if (tdo != obj->tdo) { /* new subtyped -> get obj description */ - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, " describe subtype (tdo=%p) of object type %s (tdo=%p)\n",(void*)tdo,base_obj->type_name,(void*)base_obj->tdo); + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), " describe subtype (tdo=%p) of object type %s (tdo=%p)\n",(void*)tdo,base_obj->type_name,(void*)base_obj->tdo); } Newz(1, obj->next_subtype, 1, fbh_obj_t); obj->next_subtype->tdo = tdo; if ( describe_obj_by_tdo(sth, fbh->imp_sth, obj->next_subtype, 0 /*unknown level there*/) ) { obj = obj->next_subtype; - if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ){ dump_struct(fbh->imp_sth,obj,0); } } @@ -2458,8 +2508,8 @@ get_object (SV *sth, AV *list, imp_fbh_t *fbh,fbh_obj_t *base_obj,OCIComplexObje } } - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { - PerlIO_printf(DBILOGFP, " getting attributes of object subtype %s\n",obj->type_name); + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), " getting attributes of object subtype %s\n",obj->type_name); } } @@ -2495,11 +2545,23 @@ if the object or any of its properties are NULL, This is one little line in a 20 id only shows you examples with the C struct built in and only a single record. Nowhere does it say you can do it this way. */ - status = OCIObjectGetAttr(fbh->imp_sth->envhp, fbh->imp_sth->errhp, value, - obj_ind, tdo, - (CONST oratext**)&fld->type_name, &fld->type_namel, 1, - (ub4 *)0, 0, &attr_null_status, &attr_null_struct, - &attr_value, &attr_tdo); + OCIObjectGetAttr_log_stat( + fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + value, /* instance */ + obj_ind, /* null_struct */ + tdo, /* tdo */ + (CONST oratext**)&fld->type_name, /* names */ + &fld->type_namel, /* lengths */ + 1, /* name_count */ + (ub4 *)0, /* indexes */ + 0, /* index_count */ + &attr_null_status, /* attr_null_status */ + &attr_null_struct, /* attr_null_struct */ + &attr_value, /* attr_value */ + &attr_tdo, /* attr_tdo */ + status); if (status != OCI_SUCCESS) { oci_error(sth, fbh->imp_sth->errhp, status, "OCIObjectGetAttr"); @@ -2538,8 +2600,12 @@ id only shows you examples with the C struct built in and only a single record. case OCI_TYPECODE_TABLE : /* nested table */ case OCI_TYPECODE_VARRAY : /* variable array */ fld = &obj->fields[0]; /*get the field */ - OCIIterCreate_log_stat(fbh->imp_sth->envhp, fbh->imp_sth->errhp, - (OCIColl*) value, &itr,status); + OCIIterCreate_log_stat(fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + (OCIColl*) value, + &itr, + status); if (status != OCI_SUCCESS) { /*not really an error just no data oci_error(sth, fbh->imp_sth->errhp, status, "OCIIterCreate");*/ @@ -2567,8 +2633,11 @@ id only shows you examples with the C struct built in and only a single record. } /*nasty surprise here. one has to get rid of the iterator or you will leak memory not documented in oci or in demos */ - OCIIterDelete_log_stat( fbh->imp_sth->envhp, - fbh->imp_sth->errhp, &itr,status ); + OCIIterDelete_log_stat(fbh->imp_sth, + fbh->imp_sth->envhp, + fbh->imp_sth->errhp, + &itr, + status ); if (status != OCI_SUCCESS) { oci_error(sth, fbh->imp_sth->errhp, status, "OCIIterDelete"); return 0; @@ -2597,8 +2666,12 @@ static int fetch_func_oci_object(SV *sth, imp_fbh_t *fbh,SV *dest_sv) { dTHX; - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf(DBILOGFP, " getting an embedded object named %s with typecode=%s\n",fbh->obj->type_name,oci_typecode_name(fbh->obj->typecode)); + D_imp_sth(sth); + + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), + " getting an embedded object named %s with typecode=%s\n", + fbh->obj->type_name,oci_typecode_name(fbh->obj->typecode)); } if (fbh->obj->obj_ind && fbh->obj->obj_ind[0] == OCI_IND_NULL) { @@ -2630,14 +2703,22 @@ fetch_clbk_lob(SV *sth, imp_fbh_t *fbh,SV *dest_sv){ ub4 actual_bufl=imp_sth->piece_size*(fb_ary->piece_count)+fb_ary->bufl; if (fb_ary->piece_count==0){ - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) - PerlIO_printf(DBILOGFP," Fetch persistent lob of %d (char/bytes) with callback in 1 piece of %d (Char/Bytes)\n",actual_bufl,fb_ary->bufl); + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Fetch persistent lob of %d (char/bytes) with callback in 1 " + "piece of %d (Char/Bytes)\n", + actual_bufl,fb_ary->bufl); memcpy(fb_ary->cb_abuf,fb_ary->abuf,fb_ary->bufl ); } else { - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) - PerlIO_printf(DBILOGFP," Fetch persistent lob of %d (Char/Bytes) with callback in %d piece(s) of %d (Char/Bytes) and one piece of %d (Char/Bytes)\n",actual_bufl,fb_ary->piece_count,fbh->piece_size,fb_ary->bufl); + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " Fetch persistent lob of %d (Char/Bytes) with callback in %d " + "piece(s) of %d (Char/Bytes) and one piece of %d (Char/Bytes)\n", + actual_bufl,fb_ary->piece_count,fbh->piece_size,fb_ary->bufl); memcpy(fb_ary->cb_abuf+imp_sth->piece_size*(fb_ary->piece_count),fb_ary->abuf,fb_ary->bufl ); } @@ -2671,21 +2752,22 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) ub2 rcode = 0; sword status = OCI_NEED_DATA; - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) { PerlIO_printf(DBIc_LOGPIO(imp_sth), "in fetch_get_piece \n"); } while (status == OCI_NEED_DATA){ - OCIStmtGetPieceInfo_log_stat(fbh->imp_sth->stmhp, - fbh->imp_sth->errhp, - &hdlptr, - &hdltype, - &in_out, - &iter, - &idx, - &piece, - status); + OCIStmtGetPieceInfo_log_stat(fbh->imp_sth, + fbh->imp_sth->stmhp, + fbh->imp_sth->errhp, + &hdlptr, + &hdltype, + &in_out, + &iter, + &idx, + &piece, + status); /* This is how this works First we get the piece Info above @@ -2700,7 +2782,8 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) */ if ( hdlptr==fbh->defnp){ - OCIStmtSetPieceInfo_log_stat(fbh->defnp, + OCIStmtSetPieceInfo_log_stat(fbh->imp_sth, + fbh->defnp, fbh->imp_sth->errhp, fb_ary->abuf, &buflen, @@ -2709,7 +2792,7 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) &rcode,status); - OCIStmtFetch_log_stat(fbh->imp_sth->stmhp,fbh->imp_sth->errhp,1,(ub2)OCI_FETCH_NEXT,OCI_DEFAULT,status); + OCIStmtFetch_log_stat(fbh->imp_sth, fbh->imp_sth->stmhp,fbh->imp_sth->errhp,1,(ub2)OCI_FETCH_NEXT,OCI_DEFAULT,status); if (status==OCI_SUCCESS_WITH_INFO && !DBIc_has(fbh->imp_sth,DBIcf_LongTruncOk)){ @@ -2727,7 +2810,7 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) } - if (DBIS->debug >= 6 || dbd_verbose >= 6 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ){ if (fb_ary->piece_count==1){ PerlIO_printf( DBIc_LOGPIO(imp_sth), @@ -2815,6 +2898,8 @@ empty_oci_object(fbh_obj_t *obj){ static void fetch_cleanup_pres_lobs(SV *sth,imp_fbh_t *fbh){ dTHX; + D_imp_sth(sth); + fb_ary_t *fb_ary = fbh->fb_ary; if( sth ) { /* For GCC not to warn on unused parameter*/ } @@ -2824,8 +2909,8 @@ fetch_cleanup_pres_lobs(SV *sth,imp_fbh_t *fbh){ fb_ary->cb_bufl=fbh->disize; /*reset this back to the max size for the fetch*/ memset( fb_ary->cb_abuf, '\0', fbh->disize ); /*clean out the call back buffer*/ - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) - PerlIO_printf(DBILOGFP," fetch_cleanup_pres_lobs \n"); + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) + PerlIO_printf(DBIc_LOGPIO(imp_sth)," fetch_cleanup_pres_lobs \n"); return; } @@ -2833,6 +2918,7 @@ fetch_cleanup_pres_lobs(SV *sth,imp_fbh_t *fbh){ static void fetch_cleanup_oci_object(SV *sth, imp_fbh_t *fbh){ dTHX; + D_imp_sth(sth); if( sth ) { /* For GCC not to warn on unused parameter*/ } @@ -2842,8 +2928,8 @@ fetch_cleanup_oci_object(SV *sth, imp_fbh_t *fbh){ } } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP," fetch_cleanup_oci_object \n"); + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_sth)," fetch_cleanup_oci_object \n"); return; } @@ -2856,7 +2942,7 @@ void rs_array_init(imp_sth_t *imp_sth) imp_sth->rs_fetch_count =0; imp_sth->rs_array_status =OCI_SUCCESS; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " rs_array_init:imp_sth->rs_array_size=%d, rs_array_idx=%d, " @@ -2950,7 +3036,7 @@ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, /* is prefetch_rows are greater than the RowCahceSize then use prefetch_rows*/ } - OCIAttrSet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, + OCIAttrSet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, &prefetch_mem, sizeof(prefetch_mem), OCI_ATTR_PREFETCH_MEMORY, imp_sth->errhp, status); @@ -2960,7 +3046,7 @@ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, ++num_errors; } - OCIAttrSet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, + OCIAttrSet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, &prefetch_rows, sizeof(prefetch_rows), OCI_ATTR_PREFETCH_ROWS, imp_sth->errhp, status); @@ -2988,7 +3074,7 @@ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, - if (DBIS->debug >= 3 || dbd_verbose >= 3 || oci_warn) /*will also display if oci_warn is on*/ + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 || oci_warn) /*will also display if oci_warn is on*/ PerlIO_printf( DBIc_LOGPIO(imp_sth), " cache settings DB Handle RowCacheSize=%d,Statement Handle " @@ -3011,7 +3097,7 @@ describe_obj(SV *sth,imp_sth_t *imp_sth,OCIParam *parm,fbh_obj_t *obj,int level sword status; OCIRef *type_ref; - if (DBIS->debug >= 5 || dbd_verbose >= 5 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "At level=%d in description an embedded object \n",level); @@ -3026,7 +3112,12 @@ describe_obj(SV *sth,imp_sth_t *imp_sth,OCIParam *parm,fbh_obj_t *obj,int level return 0; } - OCITypeByRef_log_stat(imp_sth->envhp,imp_sth->errhp,type_ref,&obj->tdo,status); + OCITypeByRef_log_stat(imp_sth, + imp_sth->envhp, + imp_sth->errhp, + type_ref, + &obj->tdo, + status); if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCITypeByRef"); @@ -3044,7 +3135,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { ub4 type_namel, schema_namel; - OCIDescribeAny_log_stat(imp_sth->svchp,imp_sth->errhp,obj->tdo,(ub4)0,OCI_OTYPE_PTR,(ub1)1,OCI_PTYPE_TYPE,imp_sth->dschp,status); + OCIDescribeAny_log_stat(imp_sth, imp_sth->svchp,imp_sth->errhp,obj->tdo,(ub4)0,OCI_OTYPE_PTR,(ub1)1,OCI_PTYPE_TYPE,imp_sth->dschp,status); /*we have the Actual TDO so lets see what it is made up of by a describe*/ if (status != OCI_SUCCESS) { @@ -3090,7 +3181,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { return 0; } - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "Getting the properties of object named =%s at level %d typecode=%d\n", @@ -3100,7 +3191,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { if (obj->typecode == OCI_TYPECODE_OBJECT || obj->typecode == OCI_TYPECODE_OPAQUE){ OCIParam *list_attr= (OCIParam *) 0; ub2 pos; - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "Object named =%s at level %d is an Object\n", @@ -3115,7 +3206,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { } /*we will need a reff to the TDO for the pin operation*/ - OCIObjectPin_log_stat(imp_sth->envhp,imp_sth->errhp, obj->obj_ref,(dvoid **)&obj->obj_type,status); + OCIObjectPin_log_stat(imp_sth, imp_sth->envhp,imp_sth->errhp, obj->obj_ref,(dvoid **)&obj->obj_type,status); if (status != OCI_SUCCESS) { oci_error(sth,imp_sth->errhp, status, "OCIObjectPin"); @@ -3152,7 +3243,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { OCIParam *parmdf= (OCIParam *) 0; fbh_obj_t *fld = &obj->fields[pos-1]; /*get the field holder*/ - OCIParamGet_log_stat((dvoid *) list_attr,(ub4) OCI_DTYPE_PARAM, imp_sth->errhp,(dvoid *)&parmdf, (ub4) pos ,status); + OCIParamGet_log_stat(imp_sth, (dvoid *) list_attr,(ub4) OCI_DTYPE_PARAM, imp_sth->errhp,(dvoid *)&parmdf, (ub4) pos ,status); if (status != OCI_SUCCESS) { oci_error(sth,imp_sth->errhp, status, "OCIParamGet"); @@ -3175,7 +3266,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { return 0; } - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "Getting property #%d, named=%s and its typecode is %d \n", @@ -3192,7 +3283,7 @@ describe_obj_by_tdo(SV *sth,imp_sth_t *imp_sth,fbh_obj_t *obj,ub2 level ) { } else { /*well this is an embedded table or varray of some form so find out what is in it*/ - if (DBIS->debug >= 6 || dbd_verbose >= 6 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "Object named =%s at level %d is an Varray or Table\n", @@ -3315,7 +3406,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (imp_sth->stmt_type != OCI_STMT_SELECT) { /* XXX DISABLED, see num_fields test below */ - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_describe skipped for %s\n", @@ -3324,7 +3415,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) return 1; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_describe %s (%s, lb %lu)...\n", @@ -3335,7 +3426,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) /* sth is not 'active' (executing) then we need an explicit describe. */ if ( !DBIc_ACTIVE(imp_sth) ) { - OCIStmtExecute_log_stat(imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, + OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, 0, 0, 0, 0, OCI_DESCRIBE_ONLY, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, @@ -3350,7 +3441,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) return 0; } if (num_fields == 0) { - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_describe skipped for %s (no fields returned)\n", @@ -3374,7 +3465,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->field_num = i; fbh->define_mode = OCI_DEFAULT; - OCIParamGet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, + OCIParamGet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, (dvoid**)&fbh->parmdp, (ub4)i, status); if (status != OCI_SUCCESS) { @@ -3413,7 +3504,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->name = SvPVX(fbh->name_sv); fbh->ftype = 5; /* default: return as null terminated string */ - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), "Describe col #%d type=%d(%s)\n", @@ -3555,7 +3646,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->fetch_cleanup = fetch_cleanup_oci_object; /* clean up any AV from the fetch*/ fbh->desc_t = SQLT_NTY; if (!imp_sth->dschp){ - OCIHandleAlloc_ok(imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); if (status != OCI_SUCCESS) { oci_error(h,imp_sth->errhp, status, "OCIHandleAlloc"); ++num_errors; @@ -3636,7 +3727,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->bless = "OCILobLocatorPtr"; fbh->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_sth->envhp, &fbh->desc_h, fbh->desc_t); + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &fbh->desc_h, fbh->desc_t); } @@ -3645,7 +3736,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) #ifdef OCI_DTYPE_REF case 111: /* REF */ - fbh_setup_getrefpv(fbh, OCI_DTYPE_REF, "OCIRefPtr"); + fbh_setup_getrefpv(imp_sth, fbh, OCI_DTYPE_REF, "OCIRefPtr"); break; #endif @@ -3675,14 +3766,14 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->ftype = fbh->dbtype; fbh->disize = fbh->dbsize; p = "Field %d has an Oracle type (%d) which is not explicitly supported%s"; - if (DBIS->debug >= 1 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 1 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), p, i, fbh->dbtype, "\n"); if (PL_dowarn) warn(p, i, fbh->dbtype, ""); break; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, " @@ -3705,8 +3796,8 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) est_width += avg_width; - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) - dbd_fbh_dump(fbh, (int)i, 0); + if (DBIc_DBISTATE(imp_sth)->debug >= 2 || dbd_verbose >= 3 ) + dbd_fbh_dump(imp_sth, fbh, (int)i, 0); }/* end define of filed struct[i] fbh*/ @@ -3745,12 +3836,12 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) } if (fbh->ftype == ORA_RSET) { /* RSET */ - OCIHandleAlloc_ok(imp_sth->envhp, + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, (dvoid*)&((OCIStmt **)fb_ary->abuf)[0], OCI_HTYPE_STMT, status); } - OCIDefineByPos_log_stat(imp_sth->stmhp, + OCIDefineByPos_log_stat(imp_sth, imp_sth->stmhp, &fbh->defnp, imp_sth->errhp, (ub4) i, @@ -3766,11 +3857,11 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (fbh->clbk_lob){ /* use a dynamic callback for persistent binary and char lobs*/ - OCIDefineDynamic_log_stat(fbh->defnp,imp_sth->errhp,(dvoid *) fbh,status); + OCIDefineDynamic_log_stat(imp_sth, fbh->defnp,imp_sth->errhp,(dvoid *) fbh,status); } if (fbh->ftype == 108) { /* Embedded object bind it differently*/ - if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ){ PerlIO_printf( DBIc_LOGPIO(imp_sth), "Field #%d is a object or colection of some sort. " @@ -3782,10 +3873,10 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) ++num_errors; } - if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ){ dump_struct(imp_sth,fbh->obj,0); } - OCIDefineObject_log_stat(fbh->defnp,imp_sth->errhp,fbh->obj->tdo,(dvoid**)&fbh->obj->obj_value,(dvoid**)&fbh->obj->obj_ind,status); + OCIDefineObject_log_stat(imp_sth,fbh->defnp,imp_sth->errhp,fbh->obj->tdo,(dvoid**)&fbh->obj->obj_value,(dvoid**)&fbh->obj->obj_ind,status); if (status != OCI_SUCCESS) { oci_error(h,imp_sth->errhp, status, "OCIDefineObject"); @@ -3803,12 +3894,12 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) #ifdef OCI_ATTR_CHARSET_FORM if ( (fbh->dbtype == 1) && fbh->csform ) { /* csform may be 0 when talking to Oracle 8.0 database*/ - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " calling OCIAttrSet OCI_ATTR_CHARSET_FORM with csform=%d (%s)\n", fbh->csform,oci_csform_name(fbh->csform) ); - OCIAttrSet_log_stat( fbh->defnp, (ub4) OCI_HTYPE_DEFINE, (dvoid *) &fbh->csform, + OCIAttrSet_log_stat(imp_sth, fbh->defnp, (ub4) OCI_HTYPE_DEFINE, (dvoid *) &fbh->csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status ); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_CHARSET_FORM"); @@ -3819,7 +3910,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_describe'd %d columns (row bytes: %d max, %d est avg, cache: %d)\n", @@ -3864,7 +3955,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ status = OCI_SUCCESS; } else { - if (DBIS->debug >= 3 || dbd_verbose >= 3 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ){ PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_st_fetch %d fields...\n", DBIc_NUM_FIELDS(imp_sth)); @@ -3874,7 +3965,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (imp_sth->exe_mode!=OCI_STMT_SCROLLABLE_READONLY) croak ("attempt to use a scrollable cursor without first setting ora_exe_mode to OCI_STMT_SCROLLABLE_READONLY\n") ; - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " Scrolling Fetch, postion before fetch=%d, " @@ -3882,12 +3973,12 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_sth->fetch_position, oci_fetch_options(imp_sth->fetch_orient), imp_sth->fetch_offset); - OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp,1, imp_sth->fetch_orient,imp_sth->fetch_offset, status); + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp,1, imp_sth->fetch_orient,imp_sth->fetch_offset, status); /*this will work without a round trip so might as well open it up for all statments handles*/ /* defualt and OCI_FETCH_NEXT are the same so this avoids miscaluation on the next value*/ OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->fetch_position, 0, OCI_ATTR_CURRENT_POSITION, status); - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " Scrolling Fetch, postion after fetch=%d\n", @@ -3896,7 +3987,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ else { if (imp_sth->row_cache_off){ /*Do not use array fetch or local cache */ - OCIStmtFetch_log_stat(imp_sth->stmhp, imp_sth->errhp,1,(ub2)OCI_FETCH_NEXT, OCI_DEFAULT, status); + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp,1,(ub2)OCI_FETCH_NEXT, OCI_DEFAULT, status); imp_sth->rs_fetch_count++; imp_sth->rs_array_idx=0; @@ -3908,7 +3999,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (imp_sth->rs_array_num_rows<=imp_sth->rs_array_idx && (imp_sth->rs_array_status==OCI_SUCCESS || imp_sth->rs_array_status==OCI_SUCCESS_WITH_INFO)) { /* PerlIO_printf(DBIc_LOGPIO(imp_sth), " dbd_st_fetch fields...b\n");*/ - OCIStmtFetch_log_stat(imp_sth->stmhp,imp_sth->errhp,imp_sth->rs_array_size,(ub2)OCI_FETCH_NEXT,OCI_DEFAULT,status); + OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp,imp_sth->errhp,imp_sth->rs_array_size,(ub2)OCI_FETCH_NEXT,OCI_DEFAULT,status); imp_sth->rs_array_status=status; imp_sth->rs_fetch_count++; @@ -3920,7 +4011,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_dbh->RowsInCache =imp_sth->rs_array_size; imp_sth->RowsInCache =imp_sth->rs_array_size; - if (DBIS->debug >= 4 || dbd_verbose >= 4 || oci_warn) + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 || oci_warn) PerlIO_printf( DBIc_LOGPIO(imp_sth), "...Fetched %d rows\n",imp_sth->rs_array_num_rows); @@ -3946,7 +4037,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (status == OCI_NO_DATA) { dTHR; /* for DBIc_ACTIVE_off */ DBIc_ACTIVE_off(imp_sth); /* eg finish */ - if (DBIS->debug >= 3 || dbd_verbose >= 3 || oci_warn) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 || oci_warn) PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_st_fetch no-more-data, fetch count=%d\n", @@ -3968,9 +4059,9 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ /* per-field rcode value be dealt with as we fetch the data */ } - av = DBIS->get_fbav(imp_sth); + av = DBIc_DBISTATE(imp_sth)->get_fbav(imp_sth); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), " dbd_st_fetched %d fields with status of %d(%s)\n", @@ -3988,7 +4079,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ SV *sv = AvARRAY(av)[i]; /* Note: we (re)use the SV in the AV */; - if (DBIS->debug >= 4 || dbd_verbose >= 4 ) { + if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) { PerlIO_printf( DBIc_LOGPIO(imp_sth), " field #%d with rc=%d(%s)\n",i+1,rc,oci_col_return_codes(rc)); @@ -4110,7 +4201,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ oci_error(sth, imp_sth->errhp, OCI_ERROR, buf); } - if (DBIS->debug >= 5 || dbd_verbose >= 5 ){ + if (DBIc_DBISTATE(imp_sth)->debug >= 5 || dbd_verbose >= 5 ){ PerlIO_printf( DBIc_LOGPIO(imp_sth), "\n %p (field=%d): %s\n", av, i,neatsvpv(sv,10)); @@ -4140,21 +4231,21 @@ ora_parse_uid(imp_dbh_t *imp_dbh, char **uidp, char **pwdp) } #ifdef ORA_OCI_112 if (imp_dbh->using_drcp){ - OCIAttrSet_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION, *uidp, strlen(*uidp), (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp, status); - OCIAttrSet_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION, (strlen(*pwdp)) ? *pwdp : NULL, strlen(*pwdp), (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp, status); } else { #endif - OCIAttrSet_log_stat(imp_dbh->seshp, OCI_HTYPE_SESSION, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, *uidp, strlen(*uidp), (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp, status); - OCIAttrSet_log_stat(imp_dbh->seshp, OCI_HTYPE_SESSION, + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, (strlen(*pwdp)) ? *pwdp : NULL, strlen(*pwdp), (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp, status); #ifdef ORA_OCI_112 @@ -4171,9 +4262,9 @@ ora_db_reauthenticate(SV *dbh, imp_dbh_t *imp_dbh, char *uid, char *pwd) sword status; /* XXX should possibly create new session before ending the old so */ /* that if the new one can't be created, the old will still work. */ - OCISessionEnd_log_stat(imp_dbh->svchp, imp_dbh->errhp, + OCISessionEnd_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, OCI_DEFAULT, status); /* XXX check status here?*/ - OCISessionBegin_log_stat( imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, + OCISessionBegin_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, ora_parse_uid(imp_dbh, &uid, &pwd), (ub4) OCI_DEFAULT, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); @@ -4317,14 +4408,14 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) "Unable to parse table name for LOB refetch"); if (!imp_sth->dschp){ - OCIHandleAlloc_ok(imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); if (status != OCI_SUCCESS) { oci_error(sth,imp_sth->errhp, status, "OCIHandleAlloc"); } } - OCIDescribeAny_log_stat(imp_sth->svchp, errhp, tablename, strlen(tablename), + OCIDescribeAny_log_stat(imp_sth, imp_sth->svchp, errhp, tablename, strlen(tablename), (ub1)OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_SYN, imp_sth->dschp, status); if (status == OCI_SUCCESS) { /* There is a synonym, get the schema */ @@ -4335,14 +4426,14 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) strncpy(syn_name,tablename,strlen(tablename)); /* Put the synonym name here for later user */ - OCIAttrGet_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, + OCIAttrGet_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, &parmhp, 0, OCI_ATTR_PARAM, errhp, status); - OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM, + OCIAttrGet_log_stat(imp_sth, parmhp, OCI_DTYPE_PARAM, &syn_schema, &syn_schema_len, OCI_ATTR_SCHEMA_NAME, errhp, status); - OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM, + OCIAttrGet_log_stat(imp_sth, parmhp, OCI_DTYPE_PARAM, &tablename, &tn_len, OCI_ATTR_NAME, errhp, status); strncpy(new_tablename,syn_schema,syn_schema_len); @@ -4352,7 +4443,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) tablename=new_tablename; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch using a synonym named=%s for %s \n", @@ -4360,38 +4451,38 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } - OCIDescribeAny_log_stat(imp_sth->svchp, errhp, tablename, strlen(tablename), + OCIDescribeAny_log_stat(imp_sth, imp_sth->svchp, errhp, tablename, strlen(tablename), (ub1)OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_TABLE, imp_sth->dschp, status); if (status != OCI_SUCCESS) { /* XXX this OCI_PTYPE_TABLE->OCI_PTYPE_VIEW fallback should actually be */ /* a loop that includes synonyms etc */ - OCIDescribeAny_log_stat(imp_sth->svchp, errhp, tablename, strlen(tablename), + OCIDescribeAny_log_stat(imp_sth, imp_sth->svchp, errhp, tablename, strlen(tablename), (ub1)OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_VIEW, imp_sth->dschp, status); if (status != OCI_SUCCESS) { - OCIHandleFree_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); return oci_error(sth, errhp, status, "OCIDescribeAny(view)/LOB refetch"); } } - OCIAttrGet_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, + OCIAttrGet_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, &parmhp, 0, OCI_ATTR_PARAM, errhp, status); if (!status ) { - OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM, + OCIAttrGet_log_stat(imp_sth, parmhp, OCI_DTYPE_PARAM, &numcols, 0, OCI_ATTR_NUM_COLS, errhp, status); } if (!status ) { - OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM, + OCIAttrGet_log_stat(imp_sth, parmhp, OCI_DTYPE_PARAM, &collisthd, 0, OCI_ATTR_LIST_COLUMNS, errhp, status); } if (status != OCI_SUCCESS) { - OCIHandleFree_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); return oci_error(sth, errhp, status, "OCIDescribeAny/OCIAttrGet/LOB refetch"); } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch from table %s, %d columns:\n", @@ -4401,21 +4492,21 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) ub2 col_dbtype; char *col_name; ub4 col_name_len; - OCIParamGet_log_stat(collisthd, OCI_DTYPE_PARAM, errhp, (dvoid**)&colhd, i, status); + OCIParamGet_log_stat(imp_sth, collisthd, OCI_DTYPE_PARAM, errhp, (dvoid**)&colhd, i, status); if (status) break; - OCIAttrGet_log_stat(colhd, OCI_DTYPE_PARAM, &col_dbtype, 0, + OCIAttrGet_log_stat(imp_sth, colhd, OCI_DTYPE_PARAM, &col_dbtype, 0, OCI_ATTR_DATA_TYPE, errhp, status); if (status) break; - OCIAttrGet_log_stat(colhd, OCI_DTYPE_PARAM, &col_name, &col_name_len, + OCIAttrGet_log_stat(imp_sth, colhd, OCI_DTYPE_PARAM, &col_name, &col_name_len, OCI_ATTR_NAME, errhp, status); if (status) break; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch table col %d: '%.*s' otype %d\n", @@ -4435,17 +4526,17 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) (void)SvIOK_on(sv); /* "what a wonderful hack!" */ (void)hv_store(lob_cols_hv, col_name,col_name_len, sv,0); - OCIDescriptorFree(colhd, OCI_DTYPE_PARAM); + OCIDescriptorFree_log(imp_sth, colhd, OCI_DTYPE_PARAM); colhd = NULL; } if (colhd) - OCIDescriptorFree(colhd, OCI_DTYPE_PARAM); + OCIDescriptorFree_log(imp_sth, colhd, OCI_DTYPE_PARAM); if (status != OCI_SUCCESS) { oci_error(sth, errhp, status, "OCIDescribeAny/OCIParamGet/OCIAttrGet/LOB refetch"); - OCIHandleFree_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); return 0; } @@ -4498,7 +4589,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) while( (sv_other = hv_iternextsv(lob_cols_hv, &p_other, &i)) != NULL ) { if (phs->ftype != SvIV(sv_other)) continue; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " both %s and %s have type %d - ambiguous\n", @@ -4517,7 +4608,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) (SvCUR(sql_select)>7)?", ":"", p, &phs->name[1]); sv_catpv(sql_select, sql_field); - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch %s param: otype %d, matched field '%s' %s(%s)\n", @@ -4530,14 +4621,14 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) fbh->dbtype = phs->ftype; fbh->disize = 99; fbh->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_sth->envhp, &fbh->desc_h, fbh->desc_t); + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &fbh->desc_h, fbh->desc_t); break; /* we're done with this placeholder now */ } if (!matched) { ++unmatched_params; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch %s param: otype %d, UNMATCHED\n", @@ -4555,7 +4646,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) sv_catpv(sql_select, " from "); sv_catpv(sql_select, tablename); sv_catpv(sql_select, " where rowid = :rid for update"); /* get row with lock */ - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch sql: %s\n", SvPVX(sql_select)); @@ -4564,8 +4655,8 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) lr->rowid = NULL; lr->parmdp_tmp = NULL; lr->parmdp_lob = NULL; - OCIHandleAlloc_ok(imp_sth->envhp, &lr->stmthp, OCI_HTYPE_STMT, status); - OCIStmtPrepare_log_stat(lr->stmthp, errhp, + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &lr->stmthp, OCI_HTYPE_STMT, status); + OCIStmtPrepare_log_stat(imp_sth, lr->stmthp, errhp, (text*)SvPVX(sql_select), SvCUR(sql_select), OCI_NTV_SYNTAX, OCI_DEFAULT, status); @@ -4576,11 +4667,11 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } /* bind the rowid input */ - OCIDescriptorAlloc_ok(imp_sth->envhp, &lr->rowid, OCI_DTYPE_ROWID); - OCIBindByName_log_stat(lr->stmthp, &lr->bindhp, errhp, (text*)":rid", 4, + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &lr->rowid, OCI_DTYPE_ROWID); + OCIBindByName_log_stat(imp_sth, lr->stmthp, &lr->bindhp, errhp, (text*)":rid", 4, &lr->rowid, sizeof(OCIRowid*), SQLT_RDD, 0,0,0,0,0, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { - OCIDescriptorFree(lr->rowid, OCI_DTYPE_ROWID); + OCIDescriptorFree_log(imp_sth, lr->rowid, OCI_DTYPE_ROWID); OCIHandleFree(lr->stmthp, OCI_HTYPE_STMT); Safefree(lr); return oci_error(sth, errhp, status, "OCIBindByPos/LOB refetch"); @@ -4596,17 +4687,17 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) croak("panic: LOB refetch for '%s' param (%ld) - name not found",fbh->name,(unsigned long)i+1); phs = (phs_t*)(void*)SvPVX(*phs_svp); fbh->special = phs; - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch %d for '%s' param: ftype %d setup\n", (int)i+1,fbh->name, fbh->dbtype); fbh->fb_ary = fb_ary_alloc(fbh->disize, 1); - OCIDefineByPos_log_stat(lr->stmthp, &defnp, errhp, (ub4)i+1, + OCIDefineByPos_log_stat(imp_sth, lr->stmthp, &defnp, errhp, (ub4)i+1, &fbh->desc_h, -1, (ub2)fbh->ftype, fbh->fb_ary->aindp, 0, fbh->fb_ary->arcode, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { - OCIDescriptorFree(lr->rowid, OCI_DTYPE_ROWID); + OCIDescriptorFree_log(imp_sth, lr->rowid, OCI_DTYPE_ROWID); OCIHandleFree(lr->stmthp, OCI_HTYPE_STMT); Safefree(lr); fb_ary_free(fbh->fb_ary); @@ -4615,7 +4706,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) } } - OCIHandleFree_log_stat(imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + OCIHandleFree_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); imp_sth->lob_refetch = lr; /* structure copy */ return 1; @@ -4652,7 +4743,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl if (phs->desc_h && !phs->is_inout){ - OCILobFreeTemporary_log_stat(imp_sth->svchp, imp_sth->errhp, phs->desc_h, status); + OCILobFreeTemporary_log_stat(imp_sth, imp_sth->svchp, imp_sth->errhp, phs->desc_h, status); /* boolean lobEmpty=1;*/ @@ -4682,7 +4773,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCIAttrGet OCI_ATTR_ROWID /LOB refetch"); - OCIStmtExecute_log_stat(imp_sth->svchp, lr->stmthp, errhp,1, 0, NULL, NULL, OCI_DEFAULT, status); /* execute and fetch */ + OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, lr->stmthp, errhp,1, 0, NULL, NULL, OCI_DEFAULT, status); /* execute and fetch */ if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, @@ -4706,12 +4797,22 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl if( ! fbh->csid ) { ub1 csform = SQLCS_IMPLICIT; ub2 csid = 0; - OCILobCharSetForm_log_stat( imp_sth->envhp, errhp, (OCILobLocator*)fbh->desc_h, &csform, status ); + OCILobCharSetForm_log_stat(imp_sth, + imp_sth->envhp, + errhp, + (OCILobLocator*)fbh->desc_h, + &csform, + status ); if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCILobCharSetForm"); #ifdef OCI_ATTR_CHARSET_ID /* Effectively only used so AL32UTF8 works properly */ - OCILobCharSetId_log_stat( imp_sth->envhp, errhp, (OCILobLocator*)fbh->desc_h, &csid, status ); + OCILobCharSetId_log_stat(imp_sth, + imp_sth->envhp, + errhp, + (OCILobLocator*)fbh->desc_h, + &csid, + status ); if (status != OCI_SUCCESS) return oci_error(sth, errhp, status, "OCILobCharSetId"); #endif /* OCI_ATTR_CHARSET_ID */ @@ -4721,13 +4822,13 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl fbh->csform = csform; } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " calling OCILobWrite fbh->csid=%d fbh->csform=%d amtp=%d\n", fbh->csid, fbh->csform, amtp ); - OCILobWrite_log_stat(imp_sth->svchp, errhp, + OCILobWrite_log_stat(imp_sth, imp_sth->svchp, errhp, (OCILobLocator*)fbh->desc_h, &amtp, 1, SvPVX(phs->sv), amtp, OCI_ONE_PIECE, 0,0, fbh->csid ,fbh->csform, status); @@ -4736,7 +4837,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl } } else { /* amtp==0 so truncate LOB to zero length */ - OCILobTrim_log_stat(imp_sth->svchp, errhp, (OCILobLocator*)fbh->desc_h, 0, status); + OCILobTrim_log_stat(imp_sth, imp_sth->svchp, errhp, (OCILobLocator*)fbh->desc_h, 0, status); if (status != OCI_SUCCESS) { return oci_error(sth, errhp, status, "OCILobTrim in post_execute_lobs"); @@ -4744,7 +4845,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl } - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " lob refetch %d for '%s' param: ftype %d, len %ld: %s %s\n", @@ -4770,8 +4871,8 @@ ora_free_lob_refetch(SV *sth, imp_sth_t *imp_sth) int i; sword status; if (lr->rowid) - OCIDescriptorFree(lr->rowid, OCI_DTYPE_ROWID); - OCIHandleFree_log_stat(lr->stmthp, OCI_HTYPE_STMT, status); + OCIDescriptorFree_log(imp_sth, lr->rowid, OCI_DTYPE_ROWID); + OCIHandleFree_log_stat(imp_sth, lr->stmthp, OCI_HTYPE_STMT, status); if (status != OCI_SUCCESS) oci_error(sth, imp_sth->errhp, status, "ora_free_lob_refetch/OCIHandleFree"); @@ -4800,7 +4901,7 @@ ora_db_version(SV *dbh, imp_dbh_t *imp_dbh) /* XXX should possibly create new session before ending the old so */ /* that if the new one can't be created, the old will still work. */ - OCIServerRelease_log_stat(imp_dbh->svchp, imp_dbh->errhp, buf, 2,OCI_HTYPE_SVCCTX, &vernum , status); + OCIServerRelease_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, buf, 2,OCI_HTYPE_SVCCTX, &vernum , status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionServerRelease"); return 0; diff --git a/ocitrace.h b/ocitrace.h index d5f1c101..bebe4cb9 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -6,8 +6,8 @@ Macros named "_log_stat" return status in last parameter. */ -#define DBD_OCI_TRACEON (DBIS->debug >= 6 || dbd_verbose>=6) -#define DBD_OCI_TRACEFP (DBILOGFP) +#define DBD_OCI_TRACEON(h) (DBIc_DBISTATE(h)->debug >= 6 || dbd_verbose >= 6) +#define DBD_OCI_TRACEFP(h) (DBIc_LOGPIO(h)) #define OciTp ("\tOCI") /* OCI Trace Prefix */ #define OciTstr(s) ((s) ? (text*)(s) : (text*)"") #define ul_t(v) ((unsigned long)(v)) @@ -36,121 +36,121 @@ If done well the log will read like a compilable program. */ -#define OCIServerRelease_log_stat(sc,errhp,b,bl,ht,ver,stat)\ +#define OCIServerRelease_log_stat(impdbh,sc,errhp,b,bl,ht,ver,stat) \ stat =OCIServerRelease(sc,errhp,b,bl,ht,ver);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCIServerRelease(%p)=%s\n",\ OciTp, sc,oci_status_name(stat)),stat \ : stat -#define OCISessionRelease_log_stat(svchp, errhp,stat)\ +#define OCISessionRelease_log_stat(impdbh,svchp, errhp,stat) \ stat =OCISessionRelease(svchp, errhp, NULL, (ub4)0, OCI_DEFAULT);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCISessionRelease(svchp=%p)=%s\n",\ OciTp, svchp,oci_status_name(stat)),stat \ : stat -#define OCISessionPoolDestroy_log_stat(ph, errhp,stat )\ +#define OCISessionPoolDestroy_log_stat(impdbh, ph, errhp,stat ) \ stat =OCISessionPoolDestroy(ph, errhp,OCI_DEFAULT);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCISessionPoolDestroy(ph=%p)=%s\n",\ OciTp, ph,oci_status_name(stat)),stat \ : stat -#define OCISessionGet_log_stat(envhp, errhp, sh, ah,pn,pnl,stat)\ +#define OCISessionGet_log_stat(impdbh,envhp, errhp, sh, ah,pn,pnl,stat) \ stat =OCISessionGet(envhp, errhp, sh, ah,pn,pnl,NULL,0, NULL, NULL, NULL, OCI_SESSGET_SPOOL);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCISessionGet(envhp=%p,sh=%p,ah=%p,pn=%p,pnl=%d)=%s\n",\ OciTp, envhp,sh,ah,pn,pnl,oci_status_name(stat)),stat \ : stat -#define OCISessionPoolCreate_log_stat(envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,stat)\ +#define OCISessionPoolCreate_log_stat(impdbh,envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,stat) \ stat =OCISessionPoolCreate(envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,OCI_DEFAULT);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCISessionPoolCreate(envhp=%p,ph=%p,pn=%p,pnl=%p,min=%d,max=%d,incr=%d, un=%s,unl=%d,pw=%s,pwl=%d)=%s\n",\ OciTp, envhp,ph,pn,pnl,sn,sm,si,un,unl,pw,pwl,oci_status_name(stat)),stat \ : stat #if defined(ORA_OCI_102) -#define OCIPing_log_stat(sc,errhp,stat)\ +#define OCIPing_log_stat(impdbh,sc,errhp,stat) \ stat =OCIPing(sc,errhp,OCI_DEFAULT);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCIPing(%p)=%s\n",\ OciTp, sc,oci_status_name(stat)),stat \ : stat #endif -#define OCIServerVersion_log_stat(sc,errhp,b,bl,ht,stat)\ +#define OCIServerVersion_log_stat(impdbh,sc,errhp,b,bl,ht,stat) \ stat =OCIServerVersion(sc,errhp,b,bl,ht);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCIServerVersion_log_stat(%p,%s)=%s\n",\ OciTp, sc,b,oci_status_name(stat)),stat \ : stat -#define OCIStmtGetPieceInfo_log_stat(stmhp,errhp,hdlptr,hdltyp,in_out,iter,idx,piece,stat)\ +#define OCIStmtGetPieceInfo_log_stat(impsth,stmhp,errhp,hdlptr,hdltyp,in_out,iter,idx,piece,stat) \ stat =OCIStmtGetPieceInfo(stmhp,errhp,hdlptr,hdltyp,in_out,iter,idx,piece);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIStmtGetPieceInfo_log_stat(%p,%p,%u)=%s\n",\ OciTp, (void*)errhp,fbh,*piece,oci_status_name(stat)),stat \ : stat -#define OCIStmtSetPieceInfo_log_stat(ptr,errhp,buf,blen,p,indp,rc,stat)\ +#define OCIStmtSetPieceInfo_log_stat(impsth,ptr,errhp,buf,blen,p,indp,rc,stat) \ stat =OCIStmtSetPieceInfo(ptr,OCI_HTYPE_DEFINE,errhp, buf, blen, p,indp,rc);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIStmtSetPieceInfo_log_stat(%p,%p,%d,%p)=%s\n",\ OciTp, (void*)errhp,fbh,piece,blen,oci_status_name(stat)),stat \ : stat -#define OCIDefineDynamic_log_stat(defnp,errhp,fbh,stat)\ +#define OCIDefineDynamic_log_stat(impsth,defnp,errhp,fbh,stat) \ stat =OCIDefineDynamic(defnp,errhp,fbh,(OCICallbackDefine) presist_lob_fetch_cbk );\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIDefineDynamic_log_stat(%p,%p,%p)=%s\n",\ OciTp, (void*)defnp, (void*)errhp,fbh,oci_status_name(stat)),stat \ : stat -#define OCIXMLTypeCreateFromSrc_log_stat(svchp,envhp,src_type,src_ptr,xml,stat)\ - stat =OCIXMLTypeCreateFromSrc (svchp,envhp,(OCIDuration)OCI_DURATION_CALLOUT,(ub1)src_type,(dvoid *)src_ptr,(sb4)OCI_IND_NOTNULL, xml);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ - "%sOCIXMLTypeCreateFromSrc_log_stat(%p,%p,%p,%p,%p)=%s\n",\ - OciTp, (void*)svchp,(void*)envhp, src_type, src_ptr,oci_status_name(stat)),stat \ +#define OCIXMLTypeCreateFromSrc_log_stat(impdbh,svchp,errhp,duration,src_type,src_ptr,ind,xml,stat) \ + stat =OCIXMLTypeCreateFromSrc (svchp,errhp,duration,(ub1)src_type,(dvoid *)src_ptr,(sb4)ind, xml);\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ + "%sOCIXMLTypeCreateFromSrc_log_stat(%p,%p,%d,%d,%p,%d,%p)=%s\n",\ + OciTp, (void*)svchp,(void*)errhp, duration, src_type, src_ptr, ind, xml, oci_status_name(stat)),stat \ : stat -#define OCILobFileIsOpen_log_stat(envhp,errhp,loc,is_open,stat) \ +#define OCILobFileIsOpen_log_stat(impdbh,envhp,errhp,loc,is_open,stat) \ stat = OCILobFileIsOpen(envhp,errhp,loc,is_open);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCILobFileIsOpen_log_stat(%p,%p,%p,%p,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp, loc, is_open, *is_open,oci_status_name(stat)),stat : stat -#define OCILobLocatorIsInit_log_stat(envhp,errhp,loc,is_initp,stat)\ +#define OCILobLocatorIsInit_log_stat(impdbh,envhp,errhp,loc,is_initp,stat) \ stat =OCILobLocatorIsInit (envhp,errhp,loc,is_initp );\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCILobLocatorIsInit_log_stat(%p,%p,%p,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,loc,*is_initp,oci_status_name(stat)),stat \ : stat -#define OCIObjectPin_log_stat(envhp,errhp,or,ot,stat)\ +#define OCIObjectPin_log_stat(impsth,envhp,errhp,or,ot,stat) \ stat = OCIObjectPin(envhp,errhp,or,(OCIComplexObject *)0,OCI_PIN_LATEST,OCI_DURATION_TRANS,OCI_LOCK_NONE,ot);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sObjectPin_log_stat(%p,%p,%p,%p)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,or,ot,oci_status_name(stat)),stat \ : stat - +/* #define OCICollGetElem_log_stat(envhp,errhp,v,i,ex,e,ne,stat)\ stat = OCICollGetElem(envhp,errhp, v,i,ex,e,ne);\ (DBD_OCI_TRACEON) \ @@ -158,8 +158,8 @@ "%sOCICollGetElem_log_stat(%p,%p,%d,%d,%d,%d,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,v,i,ex,e,ne,oci_status_name(stat)),stat \ : stat - - +*/ +/* #define OCITableFirst_log_stat(envhp,errhp,v,i,stat)\ stat = OCITableFirst(envhp,errhp,v,i);\ (DBD_OCI_TRACEON) \ @@ -167,60 +167,60 @@ "%sOCITableFirst_log_stat(%p,%p,%d,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,v,i,oci_status_name(stat)),stat \ : stat - -#define OCIObjectGetAttr_log_stat(envhp,errhp,v,no,ot,tn,tnl,ani,ans,av,atdo, stat)\ - stat = OCIObjectGetAttr(errhp,errhp,v,no,ot,tn,tnl,1,(ub4 *)0, 0,ani,ans,av,atdo,stat);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ - "%sOCIObjectGetAttr_log_stat(%p,%p,%d,%d,%d,%d,%d,%d,%d,%d,%d)=%s\n",\ - OciTp, (void*)envhp,(void*)errhp,v,no,ot,tn,tnl,ani,ans,av,atdo,(void*)errhp,oci_status_name(stat)),stat \ +*/ +#define OCIObjectGetAttr_log_stat(impsth,envhp,errhp,instance,nullstruct,tdo,names,lengths,namecount,indexes,indexcount,attrnullstatus,attrnullstruct,attrvalue, attrtdo, stat) \ + stat = OCIObjectGetAttr(envhp,errhp,instance,nullstruct,tdo,names,lengths,namecount,indexes,indexcount,attrnullstatus,attrnullstruct,attrvalue,attrtdo); \ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ + "%sOCIObjectGetAttr_log_stat(%p,%p,%p,%p,%p,%p,%p,%d,%p,%d,%p,%p,%p,%p)=%s\n",\ + OciTp, (void*)envhp,(void*)errhp,instance,nullstruct,tdo,names,lengths,namecount,indexes,indexcount,attrnullstatus,attrnullstruct,attrvalue,attrtdo,oci_status_name(stat)),stat \ : stat -#define OCIIntervalToText_log_stat(envhp,errhp,di,sb,ln,sl,stat)\ +#define OCIIntervalToText_log_stat(impsth,envhp,errhp,di,sb,ln,sl,stat) \ stat = OCIIntervalToText(envhp,errhp, *(OCIInterval**)di,3,3,sb,ln,sl);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIIntervalToText(%p,%p,%p,%s)=%s\n",\ OciTp, (void*)errhp, di,sl,sb,oci_status_name(stat)),stat \ : stat -#define OCIDateTimeToText_log_stat(envhp,errhp,d,sl,sb,stat)\ +#define OCIDateTimeToText_log_stat(impsth,envhp,errhp,d,sl,sb,stat) \ stat = OCIDateTimeToText(envhp,errhp, *(OCIDateTime**)d,(CONST text*) 0,(ub1) 0,6, (CONST text*) 0, (ub4) 0,(ub4 *)sl,sb );\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIDateTimeToText(%p,%p,%p,%s)=%s\n",\ OciTp, (void*)errhp, d,sl,sb,oci_status_name(stat)),stat \ : stat -#define OCIDateToText_log_stat(errhp,d,sl,sb,stat)\ +#define OCIDateToText_log_stat(impsth,errhp,d,sl,sb,stat) \ stat = OCIDateToText(errhp, (CONST OCIDate *) d,(CONST text*) 0,(ub1) 0, (CONST text*) 0, (ub4) 0,(ub4 *)sl,sb );\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sDateToText_log_stat(%p,%p,%p,%s)=%s\n",\ OciTp, (void*)errhp, d,sl,sb,oci_status_name(stat)),stat \ : stat -#define OCIIterDelete_log_stat(envhp,errhp,itr,stat)\ +#define OCIIterDelete_log_stat(impsth,envhp,errhp,itr,stat) \ stat = OCIIterDelete(envhp,errhp,itr );\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIIterDelete_log_stat(%p,%p,%p)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,itr,oci_status_name(stat)),stat \ : stat -#define OCIIterCreate_log_stat(envhp,errhp,coll,itr,stat)\ +#define OCIIterCreate_log_stat(impsth,envhp,errhp,coll,itr,stat) \ stat = OCIIterCreate(envhp,errhp,coll,itr);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sIterCreate_log_stat(%p,%p,%p)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,(void*)coll,oci_status_name(stat)),stat \ : stat - +/* #define OCICollSize_log_stat(envhp,errhp,coll,coll_siz,stat)\ stat = OCICollSize(envhp,errhp,(CONST OCIColl *)coll,coll_siz);\ (DBD_OCI_TRACEON) \ @@ -228,105 +228,105 @@ "%sOCICollSize_log_stat(%p,%p,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp,oci_status_name(stat)),stat \ : stat - -#define OCIDefineObject_log_stat(defnp,errhp,tdo,eo_buff,eo_ind,stat)\ +*/ +#define OCIDefineObject_log_stat(impsth,defnp,errhp,tdo,eo_buff,eo_ind,stat) \ stat = OCIDefineObject(defnp,errhp,tdo,eo_buff,0,eo_ind, 0);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIDefineObject(%p,%p,%p)=%s\n",\ OciTp, (void*)defnp, (void*)errhp, (void*)tdo,oci_status_name(stat)),stat \ : stat -#define OCITypeByName_log_stat(envhp,errhp,svchp,p1,l,tdo,stat)\ - stat = OCITypeByName(envhp,errhp,svchp,(const oratext*)"",0,p1,l,0,0,OCI_DURATION_TRANS,OCI_TYPEGET_ALL,tdo);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ - "%sTypeByName(%p,%p,%p,%s,%d)=%s\n",\ - OciTp, (void*)envhp, (void*)errhp, (void*)svchp, (char*)(p1),(l),oci_status_name(stat)),stat \ - : stat +#define OCITypeByName_log(impsth,envhp,errhp,svchp,sn,snl,tn,tnl,vn,vnl,duration,option,tdo,stat) \ + stat = OCITypeByName(envhp,errhp,svchp,sn,snl,tn,tnl,vn,vnl,duration,option,tdo); \ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ + "%sTypeByName(%p,%p,%p,%s,%d,%s,%d,\"\",0,%d,%d,%p)=%s\n", \ + OciTp, (void*)envhp, (void*)errhp, (void*)svchp, sn,snl,tn,tnl,duration,option,tdo,oci_status_name(stat)), stat \ + :stat -#define OCITypeByRef_log_stat(envhp,errhp,ref,tdo,stat)\ +#define OCITypeByRef_log_stat(impsth,envhp,errhp,ref,tdo,stat) \ stat = OCITypeByRef(envhp,errhp,ref,OCI_DURATION_TRANS,OCI_TYPEGET_ALL,tdo);\ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impsth)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sTypeByRef(%p,%p,%p)=%s\n",\ OciTp, (void*)envhp, (void*)errhp, (void*)ref,oci_status_name(stat)),stat \ : stat /* added by lab */ -#define OCILobCharSetId_log_stat( envhp, errhp, locp, csidp, stat ) \ +#define OCILobCharSetId_log_stat(impxxh, envhp, errhp, locp, csidp, stat ) \ stat = OCILobCharSetId( envhp, errhp, locp, csidp ); \ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impxxh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobCharSetId(%p,%p,%p,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp, (void*)locp, *csidp, oci_status_name(stat)),stat \ : stat /* added by lab */ -#define OCILobCharSetForm_log_stat( envhp, errhp, locp, formp, stat ) \ +#define OCILobCharSetForm_log_stat(impxxh, envhp, errhp, locp, formp, stat ) \ stat = OCILobCharSetForm( envhp, errhp, locp, formp ); \ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impxxh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobCharSetForm(%p,%p,%p,%d)=%s\n",\ OciTp, (void*)envhp, (void*)errhp, (void*)locp, *formp, oci_status_name(stat)),stat \ : stat /* added by lab */ -#define OCINlsEnvironmentVariableGet_log_stat( valp, size, item, charset, rsizep ,stat ) \ +#define OCINlsEnvironmentVariableGet_log_stat(impdbh, valp, size, item, charset, rsizep ,stat ) \ stat = OCINlsEnvironmentVariableGet( valp, size, item, charset, rsizep ); \ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sNlsEnvironmentVariableGet(%d,%lu,%d,%d,%lu)=%s\n",\ OciTp, *valp, (unsigned long)size, item, charset, (unsigned long)*rsizep, oci_status_name(stat)),stat \ : stat /* added by lab */ -#define OCIEnvNlsCreate_log_stat( envp, mode, ctxp, f1, f2, f3, sz, usremepp ,chset, nchset ,stat ) \ +#define OCIEnvNlsCreate_log_stat(impdbh, envp, mode, ctxp, f1, f2, f3, sz, usremepp ,chset, nchset ,stat ) \ stat = OCIEnvNlsCreate(envp, mode, ctxp, f1, f2, f3, sz, usremepp ,chset, nchset ); \ - (DBD_OCI_TRACEON) \ - ? PerlIO_printf(DBD_OCI_TRACEFP,\ + (DBD_OCI_TRACEON(impdbh)) \ + ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sEnvNlsEnvCreate(%p,%s,%d,%d,%p,%p,%p,%d,%p,%d,%d)=%s\n", \ OciTp, (void*)envp, oci_mode(mode),mode, ctxp, (void*)f1, (void*)f2, (void*)f3, sz, (void*)usremepp ,chset, nchset, oci_status_name(stat)),stat \ : stat -#define OCIAttrGet_log_stat(th,ht,ah,sp,at,eh,stat) \ +#define OCIAttrGet_log_stat(impxxh, th,ht,ah,sp,at,eh,stat) \ stat = OCIAttrGet(th,ht,ah,sp,at,eh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sAttrGet(%p,%s,%p,%p,%s,%p)=%s\n", \ OciTp, (void*)th,oci_hdtype_name(ht),(void*)ah,pul_t(sp),oci_attr_name(at),(void*)eh,\ oci_status_name(stat)),stat : stat -#define OCIAttrGet_d_log_stat(th,ht,ah,sp,at,eh,stat) \ +#define OCIAttrGet_d_log_stat(impsth, th,ht,ah,sp,at,eh,stat) \ stat = OCIAttrGet(th,ht,ah,sp,at,eh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sAttrGet(%p,%s,%p,%p,%s,%p)=%s\n", \ OciTp, (void*)th,oci_hdtype_name(ht),(void*)ah,pul_t(sp),oci_dtype_attr_name(at),(void*)eh,\ oci_status_name(stat)),stat : stat #define OCIAttrGet_parmap(imp_sth,dh, ht, p1, l, stat) \ - OCIAttrGet_log_stat(dh, ht, \ + OCIAttrGet_log_stat(imp_sth, dh, ht, \ (void*)(p1), (l), OCI_ATTR_PARAM, imp_sth->errhp, stat) #define OCIAttrGet_parmdp(imp_sth, parmdp, p1, l, a, stat) \ - OCIAttrGet_d_log_stat(parmdp, OCI_DTYPE_PARAM, \ + OCIAttrGet_d_log_stat(imp_sth, parmdp, OCI_DTYPE_PARAM, \ (void*)(p1), (l), (a), imp_sth->errhp, stat) #define OCIAttrGet_stmhp_stat(imp_sth, p1, l, a, stat) \ - OCIAttrGet_log_stat(imp_sth->stmhp, OCI_HTYPE_STMT, \ + OCIAttrGet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, \ (void*)(p1), (l), (a), imp_sth->errhp, stat) -#define OCIAttrSet_log_stat(th,ht,ah,s1,a,eh,stat) \ +#define OCIAttrSet_log_stat(impxxh,th,ht,ah,s1,a,eh,stat) \ stat=OCIAttrSet(th,ht,ah,s1,a,eh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sAttrSet(%p,%s, %p,%lu,Attr=%s,%p)=%s\n", \ OciTp, (void*)th,oci_hdtype_name(ht),(void *)ah,ul_t(s1),oci_attr_name(a),(void*)eh, \ oci_status_name(stat)),stat : stat -#define OCIBindByName_log_stat(sh,bp,eh,p1,pl,v,vs,dt,in,al,rc,mx,cu,md,stat) \ +#define OCIBindByName_log_stat(impsth,sh,bp,eh,p1,pl,v,vs,dt,in,al,rc,mx,cu,md,stat) \ stat=OCIBindByName(sh,bp,eh,p1,pl,v,vs,dt,in,al,rc,mx,cu,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sBindByName(%p,%p,%p,\"%s\",placeh_len=%ld,value_p=%p,value_sz=%ld," \ "dty=%u,indp=%p,alenp=%p,rcodep=%p,maxarr_len=%lu,curelep=%p (*=%d),mode=%s,%lu)=%s\n",\ OciTp, (void*)sh,(void*)bp,(void*)eh,p1,sl_t(pl),(void*)(v), \ @@ -334,182 +334,182 @@ ul_t((mx)),pul_t((cu)),(cu ? *(int*)cu : 0 ) ,oci_bind_options(md),ul_t((md)), \ oci_status_name(stat)),stat : stat -#define OCIBindArrayOfStruct_log_stat(bp,ep,sd,si,sl,sr,stat) \ +#define OCIBindArrayOfStruct_log_stat(impsth,bp,ep,sd,si,sl,sr,stat) \ stat=OCIBindArrayOfStruct(bp,ep,sd,si,sl,sr); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sOCIBindArrayOfStruct(%p,%p,%u,%u,%u,%u)=%s\n", \ OciTp,(void*)bp,(void*)ep,sd,si,sl,sr, \ oci_status_name(stat)),stat : stat -#define OCIBindDynamic_log(bh,eh,icx,cbi,ocx,cbo,stat) \ +#define OCIBindDynamic_log(impsth,bh,eh,icx,cbi,ocx,cbo,stat) \ stat=OCIBindDynamic(bh,eh,icx,cbi,ocx,cbo); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sBindDynamic(%p,%p,%p,%p,%p,%p)=%s\n", \ OciTp, (void*)bh,(void*)eh,(void*)icx,(void*)cbi, \ (void*)ocx,(void*)cbo, \ oci_status_name(stat)),stat : stat -#define OCIDefineByPos_log_stat(sh,dp,eh,p1,vp,vs,dt,ip,rp,cp,m,stat) \ +#define OCIDefineByPos_log_stat(impsth,sh,dp,eh,p1,vp,vs,dt,ip,rp,cp,m,stat) \ stat=OCIDefineByPos(sh,dp,eh,p1,vp,vs,dt,ip,rp,cp,m); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sDefineByPos(%p,%p,%p,%lu,%p,%ld,%u,%p,%p,%p,mode=%s,%lu)=%s\n", \ OciTp, (void*)sh,(void*)dp,(void*)eh,ul_t((p1)),(void*)(vp), \ sl_t(vs),(ub2)dt,(void*)(ip),(ub2*)(rp),(ub2*)(cp),oci_define_options(m),ul_t(m), \ oci_status_name(stat)),stat : stat -#define OCIDescribeAny_log_stat(sh,eh,op,ol,opt,il,ot,dh,stat) \ +#define OCIDescribeAny_log_stat(impsth,sh,eh,op,ol,opt,il,ot,dh,stat) \ stat=OCIDescribeAny(sh,eh,op,ol,opt,il,ot,dh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sDescribeAny(%p,%p,%p,%lu,%u,%u,%u,%p)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)op,ul_t(ol), \ (ub1)opt,(ub1)il,(ub1)ot,(void*)dh, \ oci_status_name(stat)),stat : stat -#define OCIDescriptorAlloc_ok(envhp, p1, t) \ - if (DBD_OCI_TRACEON) PerlIO_printf(DBD_OCI_TRACEFP, \ +#define OCIDescriptorAlloc_ok(impxxh,envhp, p1, t) \ + if (DBD_OCI_TRACEON(impxxh)) PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sDescriptorAlloc(%p,%p,%s,0,0)\n", \ OciTp,(void*)envhp,(void*)(p1),oci_hdtype_name(t)); \ if (OCIDescriptorAlloc((envhp), (void**)(p1), (t), 0, 0)==OCI_SUCCESS); \ else croak("OCIDescriptorAlloc (type %d) failed",t) -#define OCIDescriptorFree_log(d,t) \ - if (DBD_OCI_TRACEON) PerlIO_printf(DBD_OCI_TRACEFP, \ +#define OCIDescriptorFree_log(impxxh,d,t) \ + if (DBD_OCI_TRACEON(impxxh)) PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sDescriptorFree(%p,%s)\n", OciTp, (void*)d,oci_hdtype_name(t)); \ OCIDescriptorFree(d,t) -#define OCIEnvInit_log_stat(ev,md,xm,um,stat) \ +#define OCIEnvInit_log_stat(impdbh,ev,md,xm,um,stat) \ stat=OCIEnvInit(ev,md,xm,um); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sEnvInit(%p,%lu,%lu,%p)=%s\n", \ OciTp, (void*)ev,ul_t(md),ul_t(xm),(void*)um, \ oci_status_name(stat)),stat : stat -#define OCIErrorGet_log_stat(hp,rn,ss,ep,bp,bs,t, stat) \ +#define OCIErrorGet_log_stat(impxxh, hp,rn,ss,ep,bp,bs,t, stat) \ ((stat = OCIErrorGet(hp,rn,ss,ep,bp,bs,t)), \ - ((DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + ((DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sErrorGet(%p,%lu,\"%s\",%p,\"%s\",%lu,%lu)=%s\n", \ OciTp, (void*)hp,ul_t(rn),OciTstr(ss),psl_t(ep), \ bp,ul_t(bs),ul_t(t), oci_status_name(stat)),stat : stat)) -#define OCIHandleAlloc_log_stat(ph,hp,t,xs,ump,stat) \ +#define OCIHandleAlloc_log_stat(impxxh,ph,hp,t,xs,ump,stat) \ stat=OCIHandleAlloc(ph,hp,t,xs,ump); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sHandleAlloc(%p,%p,%s,%lu,%p)=%s\n", \ OciTp, (void*)ph,(void*)hp,oci_hdtype_name(t),ul_t(xs),(void*)ump, \ oci_status_name(stat)),stat : stat -#define OCIHandleAlloc_ok(envhp, p1, t, stat) \ - OCIHandleAlloc_log_stat((envhp),(void**)(p1),(t),0,0, stat); \ +#define OCIHandleAlloc_ok(impxxh,envhp, p1, t, stat) \ + OCIHandleAlloc_log_stat(impxxh,(envhp),(void**)(p1),(t),0,0, stat); \ if (stat==OCI_SUCCESS) ; \ else croak("OCIHandleAlloc(%s) failed",oci_hdtype_name(t)) -#define OCIHandleFree_log_stat(hp,t,stat) \ +#define OCIHandleFree_log_stat(impxxh,hp,t,stat) \ stat=OCIHandleFree( (hp), (t)); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sHandleFree(%p,%s)=%s\n",OciTp,(void*)hp,oci_hdtype_name(t), \ oci_status_name(stat)),stat : stat -#define OCILobGetLength_log_stat(sh,eh,lh,l,stat) \ +#define OCILobGetLength_log_stat(impxxh,sh,eh,lh,l,stat) \ stat=OCILobGetLength(sh,eh,lh,l); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobGetLength(%p,%p,%p,%p)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)lh,pul_t(l), \ oci_status_name(stat)),stat : stat -#define OCILobGetChunkSize_log_stat(sh,eh,lh,cs,stat) \ +#define OCILobGetChunkSize_log_stat(impdbh,sh,eh,lh,cs,stat) \ stat=OCILobGetChunkSize(sh,eh,lh,cs); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sLobGetChunkSize(%p,%p,%p,%p)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)lh,pul_t(cs), \ oci_status_name(stat)),stat : stat -#define OCILobFileOpen_log_stat(sv,eh,lh,mode,stat) \ +#define OCILobFileOpen_log_stat(impxxh,sv,eh,lh,mode,stat) \ stat=OCILobFileOpen(sv,eh,lh,mode); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobFileOpen(%p,%p,%p,%u)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,(ub1)mode, \ oci_status_name(stat)),stat : stat -#define OCILobFileClose_log_stat(sv,eh,lh,stat) \ +#define OCILobFileClose_log_stat(impsth,sv,eh,lh,stat) \ stat=OCILobFileClose(sv,eh,lh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sLobFileClose(%p,%p,%p)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh, \ oci_status_name(stat)),stat : stat /*Added by JPS for Jeffrey.Klein*/ -#define OCILobCreateTemporary_log_stat(sv,eh,lh,csi,csf,lt,ca,dur,stat) \ +#define OCILobCreateTemporary_log_stat(impdbh,sv,eh,lh,csi,csf,lt,ca,dur,stat) \ stat=OCILobCreateTemporary(sv,eh,lh,csi,csf,lt,ca,dur); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sLobCreateTemporary(%p,%p,%p,%lu,%lu,%lu,%lu,%lu)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh, \ ul_t(csi),ul_t(csf),ul_t(lt),ul_t(ca),ul_t(dur), \ oci_status_name(stat)),stat : stat /*end add*/ -#define OCILobFreeTemporary_log_stat(sv,eh,lh,stat) \ +#define OCILobFreeTemporary_log_stat(impxxh,sv,eh,lh,stat) \ stat=OCILobFreeTemporary(sv,eh,lh); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobFreeTemporary(%p,%p,%p)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh, \ oci_status_name(stat)),stat : stat -#define OCILobIsTemporary_log_stat(ev,eh,lh,istemp,stat) \ +#define OCILobIsTemporary_log_stat(impsth,ev,eh,lh,istemp,stat) \ stat=OCILobIsTemporary(ev,eh,lh,istemp); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sLobIsTemporary(%p,%p,%p,%p)=%s\n", \ OciTp, (void*)ev,(void*)eh,(void*)lh,(void*)istemp, \ oci_status_name(stat)),stat : stat /*Added by JPS for Jeffrey.Klein */ -#define OCILobLocatorAssign_log_stat(sv,eh,src,dest,stat) \ +#define OCILobLocatorAssign_log_stat(impdbh,sv,eh,src,dest,stat) \ stat=OCILobLocatorAssign(sv,eh,src,dest); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sLobLocatorAssign(%p,%p,%p,%p)=%s\n", \ OciTp,(void*)sv,(void*)eh,(void*)src,(void*)dest, \ oci_status_name(stat)),stat : stat /*end add*/ -#define OCILobRead_log_stat(sv,eh,lh,am,of,bp,bl,cx,cb,csi,csf,stat) \ +#define OCILobRead_log_stat(impxxh,sv,eh,lh,am,of,bp,bl,cx,cb,csi,csf,stat) \ stat=OCILobRead(sv,eh,lh,am,of,bp,bl,cx,cb,csi,csf); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobRead(%p,%p,%p,%p,%lu,%p,%lu,%p,%p,%u,%u)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,pul_t(am),ul_t(of), \ (void*)bp,ul_t(bl),(void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ oci_status_name(stat)),stat : stat -#define OCILobTrim_log_stat(sv,eh,lh,l,stat) \ +#define OCILobTrim_log_stat(impxxh,sv,eh,lh,l,stat) \ stat=OCILobTrim(sv,eh,lh,l); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobTrim(%p,%p,%p,%lu)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,ul_t(l), \ oci_status_name(stat)),stat : stat -#define OCILobWrite_log_stat(sv,eh,lh,am,of,bp,bl,p1,cx,cb,csi,csf,stat) \ +#define OCILobWrite_log_stat(impxxh,sv,eh,lh,am,of,bp,bl,p1,cx,cb,csi,csf,stat) \ stat=OCILobWrite(sv,eh,lh,am,of,bp,bl,p1,cx,cb,csi,csf); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobWrite(%p,%p,%p,%p,%lu,%p,%lu,%u,%p,%p,%u,%u)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,pul_t(am),ul_t(of), \ (void*)bp,ul_t(bl),(ub1)p1, \ (void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ oci_status_name(stat)),stat : stat -#define OCILobWriteAppend_log_stat(sv,eh,lh,am,bp,bl,p1,cx,cb,csi,csf,stat) \ +#define OCILobWriteAppend_log_stat(impxxh,sv,eh,lh,am,bp,bl,p1,cx,cb,csi,csf,stat) \ stat=OCILobWriteAppend(sv,eh,lh,am,bp,bl,p1,cx,cb,csi,csf); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobWriteAppend(%p,%p,%p,%p,%p,%lu,%u,%p,%p,%u,%u)=%s\n", \ OciTp, (void*)sv,(void*)eh,(void*)lh,pul_t(am), \ (void*)bp,ul_t(bl),(ub1)p1, \ (void*)cx,(void*)cb,(ub2)csi,(ub1)csf, \ oci_status_name(stat)),stat : stat -#define OCIParamGet_log_stat(hp,ht,eh,pp,ps,stat) \ +#define OCIParamGet_log_stat(impsth,hp,ht,eh,pp,ps,stat) \ stat=OCIParamGet(hp,ht,eh,pp,ps); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sParamGet(%p,%lu,%p,%p,%lu,%s)=%s\n", \ OciTp, (void*)hp,ul_t((ht)),(void*)eh,(void*)pp,ul_t(ps), \ oci_hdtype_name(ht),oci_status_name(stat)),stat : stat @@ -517,78 +517,78 @@ #define OCIServerAttach_log_stat(imp_dbh, dbname,md,stat) \ stat=OCIServerAttach( imp_dbh->srvhp, imp_dbh->errhp, \ (text*)dbname, (sb4)strlen(dbname), md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(imp_dbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(imp_dbh), \ "%sServerAttach(%p, %p, \"%s\", %lu, mode=%s,%lu)=%s\n", \ OciTp, (void*)imp_dbh->srvhp,(void*)imp_dbh->errhp, dbname, \ ul_t(strlen(dbname)), oci_mode(md),ul_t(md),oci_status_name(stat)),stat : stat -#define OCIStmtExecute_log_stat(sv,st,eh,i,ro,si,so,md,stat) \ +#define OCIStmtExecute_log_stat(impsth,sv,st,eh,i,ro,si,so,md,stat) \ stat=OCIStmtExecute(sv,st,eh,i,ro,si,so,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sStmtExecute(%p,%p,%p,%lu,%lu,%p,%p,mode=%s,%lu)=%s\n", \ OciTp, (void*)sv,(void*)st,(void*)eh,ul_t((i)), \ ul_t((ro)),(void*)(si),(void*)(so),oci_exe_mode(md),ul_t((md)), \ oci_status_name(stat)),stat : stat -#define OCIStmtFetch_log_stat(sh,eh,nr,or,os,stat) \ - stat=OCIStmtFetch2(sh,eh,nr,or,os,OCI_DEFAULT); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ +#define OCIStmtFetch_log_stat(impsth,sh,eh,nr,or,os,stat) \ + stat=OCIStmtFetch2(sh,eh,nr,or,os,OCI_DEFAULT); \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sStmtFetch(%p,%p,%lu,%u,%d)=%s\n", \ OciTp, (void*)sh,(void*)eh,ul_t(nr),(ub2)or,(ub2)os, \ oci_status_name(stat)),stat : stat -#define OCIStmtPrepare_log_stat(sh,eh,s1,sl,l,m,stat) \ +#define OCIStmtPrepare_log_stat(impsth,sh,eh,s1,sl,l,m,stat) \ stat=OCIStmtPrepare(sh,eh,s1,sl,l,m); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impsth)) ? PerlIO_printf(DBD_OCI_TRACEFP(impsth), \ "%sStmtPrepare(%p,%p,'%s',%lu,%lu,%lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,s1,ul_t(sl),ul_t(l),ul_t(m), \ oci_status_name(stat)),stat : stat -#define OCIServerDetach_log_stat(sh,eh,md,stat) \ +#define OCIServerDetach_log_stat(impdbh,sh,eh,md,stat) \ stat=OCIServerDetach(sh,eh,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sServerDetach(%p,%p,mode=%s,%lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,oci_mode(md),ul_t(md), \ oci_status_name(stat)),stat : stat -#define OCISessionBegin_log_stat(sh,eh,uh,cr,md,stat) \ +#define OCISessionBegin_log_stat(impdbh,sh,eh,uh,cr,md,stat) \ stat=OCISessionBegin(sh,eh,uh,cr,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sSessionBegin(%p,%p,%p,%lu,mode=%s %lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)uh,ul_t(cr),oci_mode(md),ul_t(md), \ oci_status_name(stat)),stat : stat -#define OCISessionEnd_log_stat(sh,eh,ah,md,stat) \ +#define OCISessionEnd_log_stat(impdbh,sh,eh,ah,md,stat) \ stat=OCISessionEnd(sh,eh,ah,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sSessionEnd(%p,%p,%p,mode=%s %lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)ah,oci_mode(md),ul_t(md), \ oci_status_name(stat)),stat : stat -#define OCITransCommit_log_stat(sh,eh,md,stat) \ +#define OCITransCommit_log_stat(impxxh,sh,eh,md,stat) \ stat=OCITransCommit(sh,eh,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sTransCommit(%p,%p,%lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,ul_t(md), \ oci_status_name(stat)),stat : stat -#define OCITransRollback_log_stat(sh,eh,md,stat) \ +#define OCITransRollback_log_stat(impdbh,sh,eh,md,stat) \ stat=OCITransRollback(sh,eh,md); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sTransRollback(%p,%p,mode=%s %lu)=%s\n", \ OciTp, (void*)sh,(void*)eh,oci_mode(md),ul_t(md), \ oci_status_name(stat)),stat : stat -#define OCIDBStartup_log_stat(svchp,errhp,admhp,mode,flags,stat) \ +#define OCIDBStartup_log_stat(impdbh,svchp,errhp,admhp,mode,flags,stat) \ stat=OCIDBStartup(svchp,errhp,admhp,mode,flags); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCIDBStartup(%p,%p,%p,%u,%u)=%s\n", \ OciTp, (void*)svchp,(void*)errhp,(void*)admhp,mode,flags, \ oci_status_name(stat)),stat : stat -#define OCIDBShutdown_log_stat(svchp,errhp,admhp,mode,stat) \ +#define OCIDBShutdown_log_stat(impdbh,svchp,errhp,admhp,mode,stat) \ stat=OCIDBShutdown(svchp,errhp,admhp,mode); \ - (DBD_OCI_TRACEON) ? PerlIO_printf(DBD_OCI_TRACEFP, \ + (DBD_OCI_TRACEON(impdbh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCIDBShutdown(%p,%p,%p,%u)=%s\n", \ OciTp, (void*)svchp,(void*)errhp,(void*)admhp,mode, \ oci_status_name(stat)),stat : stat From 884bbd3fddfdb3684e965733a10bca1430866ed5 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 26 Mar 2012 20:31:41 +0000 Subject: [PATCH 171/637] DBIS usage - change entry - it is done except 2 entries I'm not sure how to fix right now git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15247 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index d7bce20d..7977f101 100644 --- a/Changes +++ b/Changes @@ -21,7 +21,8 @@ NEXT is not in force as an additional call to OCILobFileIsOpen will be made. - - Start removing DBIS usage (Martin J. Evans). + - Removed almost all DBIS usage fixing and speeding up threaded + Perls (Martin J. Evans). [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and From d9f59558ea85980f480b2396bd489a877af0782d Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 26 Mar 2012 20:31:41 +0000 Subject: [PATCH 172/637] DBIS usage - change entry - it is done except 2 entries I'm not sure how to fix right now git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15247 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index d7bce20d..7977f101 100644 --- a/Changes +++ b/Changes @@ -21,7 +21,8 @@ NEXT is not in force as an additional call to OCILobFileIsOpen will be made. - - Start removing DBIS usage (Martin J. Evans). + - Removed almost all DBIS usage fixing and speeding up threaded + Perls (Martin J. Evans). [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and From 7ac5ad89764963721c955647ebe3875066fc19d8 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 30 Mar 2012 08:21:22 +0000 Subject: [PATCH 173/637] rewrite placeholder pod and document the 3rd placeholder variation git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15249 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 +++++-- lib/DBD/Oracle.pm | 27 +++++++++++++++++++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Changes b/Changes index 7977f101..71efc5c7 100644 --- a/Changes +++ b/Changes @@ -11,7 +11,7 @@ NEXT will still have to set LongReadLen (Martin J. Evans) - Fixed 70meta and rt74753-utf8-encoded to not die if you cannot - connect to Oracle or you cannot install from cpan if you have not + connect to Oracle or you cannot install from CPAN if you have not set up a valid Oracle connection. - Fixed 75163. Bfile lobs were not being opened before fetching if @@ -20,7 +20,7 @@ NEXT Note: this has a minor impact on non bfile lobs when ora_auto_lobs is not in force as an additional call to OCILobFileIsOpen will be made. - + - Removed almost all DBIS usage fixing and speeding up threaded Perls (Martin J. Evans). @@ -28,6 +28,9 @@ NEXT - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) + - Documented the 3rd type of placeholder and rewrote the existing + pod for placeholders (Martin J. Evans). + 1.42 2012-03-13 - skip rt74753-utf8-encoded.t if db is not unicode diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 75d21877..4bb7b713 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -2289,13 +2289,17 @@ See L for more details. =head3 B -There are two types of placeholders that can be used in DBD::Oracle. The first is -the "question mark" type, in which each placeholder is represented by a single -question mark character. This is the method recommended by the DBI specs and is the most -portable. Each question mark is internally replaced by a "dollar sign number" in the order -in which they appear in the query (important when using L). +There are three types of placeholders that can be used in +DBD::Oracle. -The other placeholder type is "named parameters" in the format ":foo" which is the one Oralce prefers. +The first is the "question mark" type, in which each placeholder is +represented by a single question mark character. This is the method +recommended by the DBI and is the most portable. Each question +mark is internally replaced by a "dollar sign number" in the order in +which they appear in the query (important when using L). + +The second type of placeholder is "named parameters" in the format +":foo" which is the one Oracle prefers. $dbh->{RaiseError} = 1; # save having to check each method call $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); @@ -2303,6 +2307,17 @@ The other placeholder type is "named parameters" in the format ":foo" which is t $sth->execute; DBI::dump_results($sth); +Note when calling bind_param with named parameters you must include +the leading colon. The advantage of this placeholder type is that you +can use the same placeholder more than once in the same SQL statement +but you only need to bind it once. + +The last placeholder type is a variation of the two above where you +name each placeholder :N (where N is a number). Like the named +placeholders above you can use the same placeholder multiple times in +the SQL but when you call bind_param you only need to pass the N +(e.g., for :1 you use bind_param(1,...) and not bind_param(':1',...). + The different types of placeholders cannot be mixed within a statement, but you may use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. From 2a7dab36cf93372c6945d862b68e9e2caa74974c Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 30 Mar 2012 08:21:22 +0000 Subject: [PATCH 174/637] rewrite placeholder pod and document the 3rd placeholder variation git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15249 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 +++++-- lib/DBD/Oracle.pm | 27 +++++++++++++++++++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Changes b/Changes index 7977f101..71efc5c7 100644 --- a/Changes +++ b/Changes @@ -11,7 +11,7 @@ NEXT will still have to set LongReadLen (Martin J. Evans) - Fixed 70meta and rt74753-utf8-encoded to not die if you cannot - connect to Oracle or you cannot install from cpan if you have not + connect to Oracle or you cannot install from CPAN if you have not set up a valid Oracle connection. - Fixed 75163. Bfile lobs were not being opened before fetching if @@ -20,7 +20,7 @@ NEXT Note: this has a minor impact on non bfile lobs when ora_auto_lobs is not in force as an additional call to OCILobFileIsOpen will be made. - + - Removed almost all DBIS usage fixing and speeding up threaded Perls (Martin J. Evans). @@ -28,6 +28,9 @@ NEXT - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) + - Documented the 3rd type of placeholder and rewrote the existing + pod for placeholders (Martin J. Evans). + 1.42 2012-03-13 - skip rt74753-utf8-encoded.t if db is not unicode diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 75d21877..4bb7b713 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -2289,13 +2289,17 @@ See L for more details. =head3 B -There are two types of placeholders that can be used in DBD::Oracle. The first is -the "question mark" type, in which each placeholder is represented by a single -question mark character. This is the method recommended by the DBI specs and is the most -portable. Each question mark is internally replaced by a "dollar sign number" in the order -in which they appear in the query (important when using L). +There are three types of placeholders that can be used in +DBD::Oracle. -The other placeholder type is "named parameters" in the format ":foo" which is the one Oralce prefers. +The first is the "question mark" type, in which each placeholder is +represented by a single question mark character. This is the method +recommended by the DBI and is the most portable. Each question +mark is internally replaced by a "dollar sign number" in the order in +which they appear in the query (important when using L). + +The second type of placeholder is "named parameters" in the format +":foo" which is the one Oracle prefers. $dbh->{RaiseError} = 1; # save having to check each method call $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); @@ -2303,6 +2307,17 @@ The other placeholder type is "named parameters" in the format ":foo" which is t $sth->execute; DBI::dump_results($sth); +Note when calling bind_param with named parameters you must include +the leading colon. The advantage of this placeholder type is that you +can use the same placeholder more than once in the same SQL statement +but you only need to bind it once. + +The last placeholder type is a variation of the two above where you +name each placeholder :N (where N is a number). Like the named +placeholders above you can use the same placeholder multiple times in +the SQL but when you call bind_param you only need to pass the N +(e.g., for :1 you use bind_param(1,...) and not bind_param(':1',...). + The different types of placeholders cannot be mixed within a statement, but you may use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. From 73e0b52336b7ba28926606d7062fef4be5f88528 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 30 Mar 2012 08:40:07 +0000 Subject: [PATCH 175/637] $dbh->err was being tested when it may not have been set git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15250 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ t/31lob.t | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 71efc5c7..2398d0dd 100644 --- a/Changes +++ b/Changes @@ -24,6 +24,8 @@ NEXT - Removed almost all DBIS usage fixing and speeding up threaded Perls (Martin J. Evans). + - Minor fix to avoid use of uninitialised variable in 31lob.t (Martin J. Evans) + [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) diff --git a/t/31lob.t b/t/31lob.t index 2701e274..9f8c99a2 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -76,7 +76,7 @@ END_SQL sub have_v_session { $dbh->do('select * from v$session where 0=1'); - return $dbh->err != 942; + return defined($dbh->err) ? $dbh->err != 942 : 1; } From fab957a5f853687ec291d626d3c9a0bea1840d00 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 30 Mar 2012 08:40:07 +0000 Subject: [PATCH 176/637] $dbh->err was being tested when it may not have been set git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15250 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ t/31lob.t | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 71efc5c7..2398d0dd 100644 --- a/Changes +++ b/Changes @@ -24,6 +24,8 @@ NEXT - Removed almost all DBIS usage fixing and speeding up threaded Perls (Martin J. Evans). + - Minor fix to avoid use of uninitialised variable in 31lob.t (Martin J. Evans) + [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) diff --git a/t/31lob.t b/t/31lob.t index 2701e274..9f8c99a2 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -76,7 +76,7 @@ END_SQL sub have_v_session { $dbh->do('select * from v$session where 0=1'); - return $dbh->err != 942; + return defined($dbh->err) ? $dbh->err != 942 : 1; } From ee567d9747d59b954a9c3392606a0bfe23c4d067 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 30 Mar 2012 08:41:25 +0000 Subject: [PATCH 177/637] remove last remaining DBIS usage: comment out 2 uses in dbd_phs_in/dbd_phs_out as they are oracle callbacks and we cannot pass anything in to identify the state struct. remove the last DBIS I can find git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15251 50811bd7-b8ce-0310-adc1-d9db26280581 --- oci8.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/oci8.c b/oci8.c index 48d00d67..c28befaf 100644 --- a/oci8.c +++ b/oci8.c @@ -1138,10 +1138,15 @@ dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, *alenp = phs->alen; *indpp = &phs->indp; *piecep = OCI_ONE_PIECE; + /* MJE commented out as we are avoiding DBIS now but as this is + an Oracle callback there is no way to pass something non + OCI into this func. + if (DBIS->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBILOGFP, " in '%s' [%lu,%lu]: len %2lu, ind %d%s, value=%s\n", phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), phs->indp, (phs->desc_h) ? " via descriptor" : "",neatsvpv(phs->sv,10)); + */ if (!tuples_av && (index > 0 || iter > 0)) croak(" Arrays and multiple iterations not currently supported by DBD::Oracle (in %d/%d)", index,iter); @@ -1225,10 +1230,15 @@ dbd_phs_out(dvoid *octxp, OCIBind *bindp, *alenpp = &phs->alen; *indpp = &phs->indp; *rcodepp= &phs->arcode; + /* MJE commented out as we are avoiding DBIS now but as this is + an Oracle callback there is no way to pass something non + OCI into this func. + if (DBIS->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBILOGFP, " out '%s' [%ld,%ld]: alen %2ld, piece %d%s\n", phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), *piecep, (phs->desc_h) ? " via descriptor" : ""); + */ *piecep = OCI_ONE_PIECE; return OCI_CONTINUE; } @@ -2175,7 +2185,7 @@ static void fbh_setup_getrefpv(imp_sth_t *imp_sth, imp_fbh_t *fbh, int desc_t, char *bless) { dTHX; - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 2 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " col %d: otype %d, desctype %d, %s", fbh->field_num, fbh->dbtype, desc_t, bless); fbh->ftype = fbh->dbtype; From 64589ba6aa2ecfce4e86026b29639fca27b4ba4f Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 30 Mar 2012 08:41:25 +0000 Subject: [PATCH 178/637] remove last remaining DBIS usage: comment out 2 uses in dbd_phs_in/dbd_phs_out as they are oracle callbacks and we cannot pass anything in to identify the state struct. remove the last DBIS I can find git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15251 50811bd7-b8ce-0310-adc1-d9db26280581 --- oci8.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/oci8.c b/oci8.c index 48d00d67..c28befaf 100644 --- a/oci8.c +++ b/oci8.c @@ -1138,10 +1138,15 @@ dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, *alenp = phs->alen; *indpp = &phs->indp; *piecep = OCI_ONE_PIECE; + /* MJE commented out as we are avoiding DBIS now but as this is + an Oracle callback there is no way to pass something non + OCI into this func. + if (DBIS->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBILOGFP, " in '%s' [%lu,%lu]: len %2lu, ind %d%s, value=%s\n", phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), phs->indp, (phs->desc_h) ? " via descriptor" : "",neatsvpv(phs->sv,10)); + */ if (!tuples_av && (index > 0 || iter > 0)) croak(" Arrays and multiple iterations not currently supported by DBD::Oracle (in %d/%d)", index,iter); @@ -1225,10 +1230,15 @@ dbd_phs_out(dvoid *octxp, OCIBind *bindp, *alenpp = &phs->alen; *indpp = &phs->indp; *rcodepp= &phs->arcode; + /* MJE commented out as we are avoiding DBIS now but as this is + an Oracle callback there is no way to pass something non + OCI into this func. + if (DBIS->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBILOGFP, " out '%s' [%ld,%ld]: alen %2ld, piece %d%s\n", phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), *piecep, (phs->desc_h) ? " via descriptor" : ""); + */ *piecep = OCI_ONE_PIECE; return OCI_CONTINUE; } @@ -2175,7 +2185,7 @@ static void fbh_setup_getrefpv(imp_sth_t *imp_sth, imp_fbh_t *fbh, int desc_t, char *bless) { dTHX; - if (DBIS->debug >= 2 || dbd_verbose >= 3 ) + if (DBIc_DBISTATE(imp_sth)->debug >= 2 || dbd_verbose >= 3 ) PerlIO_printf(DBIc_LOGPIO(imp_sth), " col %d: otype %d, desctype %d, %s", fbh->field_num, fbh->dbtype, desc_t, bless); fbh->ftype = fbh->dbtype; From 00f0cb7cacf60adf86a1b0f1d7049a49abf819ba Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 30 Mar 2012 13:44:52 +0000 Subject: [PATCH 179/637] DBIS is now completely removed git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15252 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index 2398d0dd..774b9ba7 100644 --- a/Changes +++ b/Changes @@ -21,7 +21,7 @@ NEXT is not in force as an additional call to OCILobFileIsOpen will be made. - - Removed almost all DBIS usage fixing and speeding up threaded + - Removed all DBIS usage fixing and speeding up threaded Perls (Martin J. Evans). - Minor fix to avoid use of uninitialised variable in 31lob.t (Martin J. Evans) From ca2142371406a1694f3e2778ee2fbbd546ce52cd Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 30 Mar 2012 13:44:52 +0000 Subject: [PATCH 180/637] DBIS is now completely removed git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15252 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index 2398d0dd..774b9ba7 100644 --- a/Changes +++ b/Changes @@ -21,7 +21,7 @@ NEXT is not in force as an additional call to OCILobFileIsOpen will be made. - - Removed almost all DBIS usage fixing and speeding up threaded + - Removed all DBIS usage fixing and speeding up threaded Perls (Martin J. Evans). - Minor fix to avoid use of uninitialised variable in 31lob.t (Martin J. Evans) From 7b92e63912f3bc0be24b1b83732e0bab9733ca80 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 30 Mar 2012 13:45:22 +0000 Subject: [PATCH 181/637] small spelling mistake in error git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15253 50811bd7-b8ce-0310-adc1-d9db26280581 --- oci8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oci8.c b/oci8.c index c28befaf..1dfc0d10 100644 --- a/oci8.c +++ b/oci8.c @@ -3978,7 +3978,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), - " Scrolling Fetch, postion before fetch=%d, " + " Scrolling Fetch, position before fetch=%d, " "Orientation = %s , Fetchoffset =%d\n", imp_sth->fetch_position, oci_fetch_options(imp_sth->fetch_orient), imp_sth->fetch_offset); From 46b64dc6d63eded8d9dcc425672a9cb3a50e2f9f Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 30 Mar 2012 13:45:22 +0000 Subject: [PATCH 182/637] small spelling mistake in error git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15253 50811bd7-b8ce-0310-adc1-d9db26280581 --- oci8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oci8.c b/oci8.c index c28befaf..1dfc0d10 100644 --- a/oci8.c +++ b/oci8.c @@ -3978,7 +3978,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), - " Scrolling Fetch, postion before fetch=%d, " + " Scrolling Fetch, position before fetch=%d, " "Orientation = %s , Fetchoffset =%d\n", imp_sth->fetch_position, oci_fetch_options(imp_sth->fetch_orient), imp_sth->fetch_offset); From 761e712fa3b3f13ad87f1654a0cbd3b13ecbc233 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 30 Mar 2012 14:31:49 -0400 Subject: [PATCH 183/637] bump version to 1.43_00 --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index c7cee301..78533959 100644 --- a/dist.ini +++ b/dist.ini @@ -6,7 +6,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.42 +version = 1.43_00 [Authority] authority=cpan:PYTHIAN From 033eaebed076280b6b205e31dc2ddd9ed12ddfdb Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 30 Mar 2012 14:36:18 -0400 Subject: [PATCH 184/637] Build results of 761e712 (on master) --- .gitignore | 14 - Changes | 2 +- INSTALL | 44 + LICENSE | 377 ++ MANIFEST.SKIP | 32 - META.json | 97 + META.yml | 63 + README | 4358 ++++++++++++++- README.mkdn | 4252 +++++++++++++++ dist.ini | 26 - err_bind/err_bind_param_inout_overrun_bug.msg | 108 - err_bind/err_bindarrays.msg | 241 - err_bind/err_bindclobleak.msg | 58 - err_bind/err_bindnullhash.msg | 77 - err_bind/err_trailingblank.msg | 345 -- err_build/err_aix64.msg | 142 - err_build/err_hpux_ld.msg | 89 - err_build/err_hpuxsuccess.msg | 279 - err_build/err_instantclient.msg | 207 - err_build/err_makefileundef.msg | 87 - err_build/err_memleak.msg | 95 - err_build/err_solarisnotes.msg | 482 -- err_build/err_testfailnotable.msg | 97 - err_docs/err_trace.msg | 14 - err_lob/err_csr_clob.msg | 65 - err_lob/err_loblenwide.msg | 95 - err_lob/err_lobtesttblfail.msg | 208 - err_lob/err_nclob_form.msg | 189 - err_lob/err_nulllobsegv.msg | 93 - err_lob/err_tmplobfree.msg | 537 -- err_unicode/err_char.msg | 129 - err_unicode/err_twolongstr.msg | 1256 ----- err_unsorted/err_etherreal.msg | 90 - err_unsorted/err_memleak2.msg | 476 -- err_unsorted/err_multiora.msg | 470 -- err_unsorted/err_ora9ir2oci.msg | 27 - err_unsorted/err_ref_type.msg | 115 - err_unsorted/err_refcsr_rowcache.msg | 85 - err_unsorted/err_refcsr_slow.msg | 347 -- err_unsorted/err_slowcsr.msg | 316 -- err_unsorted/err_svrparse.msg | 4717 ----------------- err_unsorted/err_xml.msg | 118 - err_unsorted/err_xml2.msg | 700 --- err_unsorted/err_xmltypebindplsql.msg | 174 - lib/DBD/Oracle.pm | 109 +- lib/DBD/Oracle/GetInfo.pm | 46 + lib/DBD/Oracle/Object.pm | 95 +- lib/DBD/Oracle/Troubleshooting.pm | 48 +- t/000-report-versions.t | 446 ++ xt/changes.t | 8 - xt/manifest.t | 21 - xt/pod.t | 11 - 52 files changed, 9637 insertions(+), 12940 deletions(-) delete mode 100644 .gitignore create mode 100644 INSTALL create mode 100644 LICENSE delete mode 100644 MANIFEST.SKIP create mode 100644 META.json create mode 100644 META.yml create mode 100644 README.mkdn delete mode 100644 dist.ini delete mode 100644 err_bind/err_bind_param_inout_overrun_bug.msg delete mode 100644 err_bind/err_bindarrays.msg delete mode 100644 err_bind/err_bindclobleak.msg delete mode 100644 err_bind/err_bindnullhash.msg delete mode 100644 err_bind/err_trailingblank.msg delete mode 100644 err_build/err_aix64.msg delete mode 100644 err_build/err_hpux_ld.msg delete mode 100644 err_build/err_hpuxsuccess.msg delete mode 100644 err_build/err_instantclient.msg delete mode 100644 err_build/err_makefileundef.msg delete mode 100644 err_build/err_memleak.msg delete mode 100644 err_build/err_solarisnotes.msg delete mode 100644 err_build/err_testfailnotable.msg delete mode 100644 err_docs/err_trace.msg delete mode 100644 err_lob/err_csr_clob.msg delete mode 100644 err_lob/err_loblenwide.msg delete mode 100644 err_lob/err_lobtesttblfail.msg delete mode 100644 err_lob/err_nclob_form.msg delete mode 100644 err_lob/err_nulllobsegv.msg delete mode 100644 err_lob/err_tmplobfree.msg delete mode 100644 err_unicode/err_char.msg delete mode 100644 err_unicode/err_twolongstr.msg delete mode 100644 err_unsorted/err_etherreal.msg delete mode 100644 err_unsorted/err_memleak2.msg delete mode 100644 err_unsorted/err_multiora.msg delete mode 100644 err_unsorted/err_ora9ir2oci.msg delete mode 100644 err_unsorted/err_ref_type.msg delete mode 100644 err_unsorted/err_refcsr_rowcache.msg delete mode 100644 err_unsorted/err_refcsr_slow.msg delete mode 100644 err_unsorted/err_slowcsr.msg delete mode 100644 err_unsorted/err_svrparse.msg delete mode 100644 err_unsorted/err_xml.msg delete mode 100644 err_unsorted/err_xml2.msg delete mode 100644 err_unsorted/err_xmltypebindplsql.msg create mode 100644 t/000-report-versions.t delete mode 100644 xt/changes.t delete mode 100644 xt/manifest.t delete mode 100644 xt/pod.t diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 15e927c8..00000000 --- a/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -pm_to_blib -MYMETA.yml -Makefile -Makefile.old -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -blib -MYMETA.json -dbdimp.o -mk.pm -oci8.o -DBD-Oracle* diff --git a/Changes b/Changes index 23e47861..38ea2311 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.43_00 2012-03-30 [BUG FIXES] - Applied patch from Rafael Kitover (Caelum) to column_info to handle diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..b5ab17a0 --- /dev/null +++ b/INSTALL @@ -0,0 +1,44 @@ + +This is the Perl distribution DBD-Oracle. + +Installing DBD-Oracle is straightforward. + +## Installation with cpanm + +If you have cpanm, you only need one line: + + % cpanm DBD::Oracle + +If you are installing into a system-wide directory, you may need to pass the +"-S" flag to cpanm, which uses sudo to install the module: + + % cpanm -S DBD::Oracle + +## Installing with the CPAN shell + +Alternatively, if your CPAN shell is set up, you should just be able to do: + + % cpan DBD::Oracle + +## Manual installation + +As a last resort, you can manually install it. Download the tarball, untar it, +then build it: + + % perl Makefile.PL + % make && make test + +Then install it: + + % make install + +If you are installing into a system-wide directory, you may need to run: + + % sudo make install + +## Documentation + +DBD-Oracle documentation is available as POD. +You can run perldoc from a shell to read the documentation: + + % perldoc DBD::Oracle diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..a6a371c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,377 @@ +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +Terms of the Perl programming language system itself + +a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or +b) the "Artistic License" + +--- The GNU General Public License, Version 1, February 1989 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The GNU General Public License, Version 1, February 1989 + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! + + +--- The Artistic License 1.0 --- + +This software is Copyright (c) 1994 by Tim Bunce. + +This is free software, licensed under: + + The Artistic License 1.0 + +The Artistic License + +Preamble + +The intent of this document is to state the conditions under which a Package +may be copied, such that the Copyright Holder maintains some semblance of +artistic control over the development of the package, while giving the users of +the package the right to use and distribute the Package in a more-or-less +customary fashion, plus the right to make reasonable modifications. + +Definitions: + + - "Package" refers to the collection of files distributed by the Copyright + Holder, and derivatives of that collection of files created through + textual modification. + - "Standard Version" refers to such a Package if it has not been modified, + or has been modified in accordance with the wishes of the Copyright + Holder. + - "Copyright Holder" is whoever is named in the copyright or copyrights for + the package. + - "You" is you, if you're thinking about copying or distributing this Package. + - "Reasonable copying fee" is whatever you can justify on the basis of media + cost, duplication charges, time of people involved, and so on. (You will + not be required to justify it to the Copyright Holder, but only to the + computing community at large as a market that must bear the fee.) + - "Freely Available" means that no fee is charged for the item itself, though + there may be fees involved in handling the item. It also means that + recipients of the item may redistribute it under the same conditions they + received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications derived +from the Public Domain or from the Copyright Holder. A Package modified in such +a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided that +you insert a prominent notice in each changed file stating how and when you +changed that file, and provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major archive site + such as ftp.uu.net, or by allowing the Copyright Holder to include your + modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict with + standard executables, which must also be provided, and provide a separate + manual page for each non-standard executable that clearly documents how it + differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or executable +form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where to + get the Standard Version. + + b) accompany the distribution with the machine-readable source of the Package + with your modifications. + + c) accompany any non-standard executables with their corresponding Standard + Version executables, giving the non-standard executables non-standard + names, and clearly documenting the differences in manual pages (or + equivalent), together with instructions on where to get the Standard + Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. You +may not charge a fee for this Package itself. However, you may distribute this +Package in aggregate with other (possibly commercial) programs as part of a +larger (possibly commercial) software distribution provided that you do not +advertise this Package as a product of your own. + +6. The scripts and library files supplied as input to or produced as output +from the programs of this Package do not automatically fall under the copyright +of this Package, but belong to whomever generated them, and may be sold +commercially, and may be aggregated with this Package. + +7. C or perl subroutines supplied by you and linked into this Package shall not +be considered part of this Package. + +8. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +The End + diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP deleted file mode 100644 index c7db4c66..00000000 --- a/MANIFEST.SKIP +++ /dev/null @@ -1,32 +0,0 @@ -^DBD-Oracle-.* -\.svn\b -\.orig$ -\..*.swp$ -^.pure -^DIST/ -^MANIFEST\. -^Makefile$ -^blib/ -^csr/ -^err[/_] -^old/ -^info/ -^oci8/ -^oracle/ -^tags$ -~$ -^\.git -^xt -dbdimp.o -Makefile.old -mk.pm -MYMETA.json -MYMETA.yml -oci8.o -Oracle.bs -Oracle.c -Oracle.o -Oracle.xsi -pm_to_blib - -dist.ini diff --git a/META.json b/META.json new file mode 100644 index 00000000..93db2c23 --- /dev/null +++ b/META.json @@ -0,0 +1,97 @@ +{ + "abstract" : "Oracle database driver for the DBI module", + "author" : [ + "Tim Bunce ", + "John Scoles", + "Yanick Champoux " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 4.300009, CPAN::Meta::Converter version 2.120630", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "DBD-Oracle", + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "6.30" + } + }, + "runtime" : { + "requires" : { + "DBI" : "0", + "DynaLoader" : "0", + "Exporter" : "0", + "perl" : "5.006", + "strict" : "0", + "warnings" : "0" + } + }, + "test" : { + "requires" : { + "Carp" : "0", + "Config" : "0", + "Data::Dumper" : "0", + "Devel::Peek" : "0", + "Encode" : "0", + "Math::BigInt" : "0", + "Oraperl" : "0", + "Scalar::Util" : "0", + "Test::More" : "0.94", + "Thread::Semaphore" : "0", + "utf8" : "0", + "vars" : "0" + } + } + }, + "provides" : { + "DBD::Oracle" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.43_00" + }, + "DBD::Oracle::GetInfo" : { + "file" : "lib/DBD/Oracle/GetInfo.pm", + "version" : "1.43_00" + }, + "DBD::Oracle::Object" : { + "file" : "lib/DBD/Oracle/Object.pm", + "version" : "1.43_00" + }, + "DBD::Oracle::Troubleshooting" : { + "file" : "lib/DBD/Oracle/Troubleshooting.pm", + "version" : "1.43_00" + }, + "DBD::Oracle::db" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.43_00" + }, + "DBD::Oracle::dr" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.43_00" + }, + "DBD::Oracle::st" : { + "file" : "lib/DBD/Oracle.pm", + "version" : "1.43_00" + } + }, + "release_status" : "testing", + "resources" : { + "bugtracker" : { + "mailto" : "bug-dbd-oracle at rt.cpan.org", + "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle" + }, + "homepage" : "http://search.cpan.org/dist/DBD-Oracle/", + "repository" : { + "type" : "git", + "url" : "git://github.com/yanick/DBD-Oracle.git", + "web" : "http://github.com/yanick/DBD-Oracle/tree" + } + }, + "version" : "1.43_00", + "x_authority" : "cpan:PYTHIAN" +} + diff --git a/META.yml b/META.yml new file mode 100644 index 00000000..93a77584 --- /dev/null +++ b/META.yml @@ -0,0 +1,63 @@ +--- +abstract: 'Oracle database driver for the DBI module' +author: + - 'Tim Bunce ' + - 'John Scoles' + - 'Yanick Champoux ' +build_requires: + Carp: 0 + Config: 0 + Data::Dumper: 0 + Devel::Peek: 0 + Encode: 0 + Math::BigInt: 0 + Oraperl: 0 + Scalar::Util: 0 + Test::More: 0.94 + Thread::Semaphore: 0 + utf8: 0 + vars: 0 +configure_requires: + ExtUtils::MakeMaker: 6.30 +dynamic_config: 0 +generated_by: 'Dist::Zilla version 4.300009, CPAN::Meta::Converter version 2.120630' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: DBD-Oracle +provides: + DBD::Oracle: + file: lib/DBD/Oracle.pm + version: 1.43_00 + DBD::Oracle::GetInfo: + file: lib/DBD/Oracle/GetInfo.pm + version: 1.43_00 + DBD::Oracle::Object: + file: lib/DBD/Oracle/Object.pm + version: 1.43_00 + DBD::Oracle::Troubleshooting: + file: lib/DBD/Oracle/Troubleshooting.pm + version: 1.43_00 + DBD::Oracle::db: + file: lib/DBD/Oracle.pm + version: 1.43_00 + DBD::Oracle::dr: + file: lib/DBD/Oracle.pm + version: 1.43_00 + DBD::Oracle::st: + file: lib/DBD/Oracle.pm + version: 1.43_00 +requires: + DBI: 0 + DynaLoader: 0 + Exporter: 0 + perl: 5.006 + strict: 0 + warnings: 0 +resources: + bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle + homepage: http://search.cpan.org/dist/DBD-Oracle/ + repository: git://github.com/yanick/DBD-Oracle.git +version: 1.43_00 +x_authority: cpan:PYTHIAN diff --git a/README b/README index fd2b28aa..5f6718ac 100644 --- a/README +++ b/README @@ -1,301 +1,4203 @@ +NAME + DBD::Oracle - Oracle database driver for the DBI module -DBD::Oracle -- an Oracle interface for Perl 5. +VERSION + version 1.43_00 - Copyright (c) 1994-2006 Tim Bunce, Ireland. +SYNOPSIS + use DBI; - See the COPYRIGHT section in the Oracle.pm file for terms. - See also the MAINTAINER section in the Oracle.pm + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); - PLEASE READ THE ENTIRE README FILE CAREFULLY ! + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); - AND THEN READ ANY README.* FILES RELEVANT TO YOUR PLATFORM: + # See the DBI module documentation for full details - README.aix.txt - AIX - README.hpux.txt - HP-UX - README.java.txt - Java/thread problem on Solaris - README.macosx.txt - Mac OS/X - README.win32.txt - MS Windows - README.wingcc.txt - MS Windows using GCC - README.* - see if there's a file for your platform + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); - You may find these useful +DESCRIPTION + DBD::Oracle is a Perl module which works with the DBI module to provide + access to Oracle databases. - README.help.txt - Help and hints on build problems - README.sec.txt - Oracle security issues to be aware of - README.login.txt - Help on how to connect to Oracle - README.longs.txt - Help on handling LONGs - README.clients.txt - What Oracle client files you need installed + This documentation describes driver specific behaviour and restrictions. + It is not supposed to be used as the only reference for the user. In any + case consult the DBI documentation first! +CONSTANTS + :ora_session_modes + ORA_SYSDBA ORA_SYSOPER ORA_SYSASM -*** QUICK START GUIDE: + :ora_types + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN - The DBI requires one or more 'driver' modules to talk to databases. - Fetch, build and install the DBI module as per its README file. - You may then delete its source directory tree since it's no longer needed. - Use the 'perldoc DBI' command to read the DBI documentation. + SQLCS_IMPLICIT + SQLCS_NCHAR + SQLCS_IMPLICIT and SQLCS_NCHAR are *character set form* values. See + notes about Unicode elsewhere in this document. - Fetch this DBD::Oracle driver module and unpack it. - Follow the guidelines in this README file carefully. + SQLT_INT + SQLT_FLT + These types are used only internally, and may be specified as + internal bind type for ORA_NUMBER_TABLE. See notes about + ORA_NUMBER_TABLE elsewhere in this document + ORA_OCI + Oracle doesn't provide a formal API for determining the exact + version number of the OCI client library used, so DBD::Oracle has to + go digging (and sometimes has to more or less guess). The ORA_OCI + constant holds the result of that process. -*** *BEFORE* BUILDING, TESTING AND INSTALLING DBD::Oracle: + In string context ORA_OCI returns the full "A.B.C.D" version string. - Build, test and install Perl 5 (at least 5.6.1) - It is very important to TEST it and INSTALL it! + In numeric context ORA_OCI returns the major.minor version number + (8.1, 9.2, 10.0 etc). But note that version numbers are not actually + floating point and so if Oracle ever makes a release that has a two + digit minor version, such as 9.10 it will have a lower numeric value + than the preceding 9.9 release. So use with care. - Build, test and install the DBI module (at least DBI 1.51). - It is very important to TEST it and INSTALL it! + The contents and format of ORA_OCI are subject to change (it may, + for example, become a *version object* in later releases). I + recommend that you avoid checking for exact values. - Remember to *read* the DBI README file and this one CAREFULLY! + :ora_fetch_orient + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE - Install enough Oracle software to enable DBD::Oracle to build. + These constants are used to set the orientation of a fetch on a + scrollable cursor. - For Oracle Instant Client: that means install the following packages: - * The "Basic" package for the essential Oracle libraries. - * The "SDK" package for the headers and makefile. - * The "SQL*Plus" component is optional, but will help you check - your configuration and DBD::Oracle determine your Oracle version. + :ora_exe_modes + OCI_STMT_SCROLLABLE_READONLY - For full Oracle installs: that usually includes Pro*C and SQL*Net. - (That's not very specific because it varies between Oracle releases.). - As of release 1.22 support of Oracle clients before 9 was dropped. - The main reason for this is that next few versions of DBD::Oracle will introduce a number of new features - whicht will required a great deal of extra coding to make the OCI 8 work. - As well it is getting harder to find an Oracle client 8 to test against as well - Oracle no longer supports clients before 9. + :ora_fail_over + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL - The ORACLE_HOME environment variable must point to the Oracle Home - used to create DBD::Oracle. (Not essential under MS Windows). +DBI CLASS METHODS + connect + This method creates a database handle by connecting to a database, and + is the DBI equivalent of the "new" method. To open a connection to an + Oracle database you need to specify a database connection string (URL), + username and password. -*** MOST IMPORTANTLY: + The connection string is always of the form: "dbi:Oracle:" There are several ways to identify a database: - Make sure Oracle is working and you can use the Oracle sqlplus - command to talk to the database from the machine you - want to build DBD::Oracle on. This often involves setting - environment variables like PATH, LD_LIBRARY_PATH, TWO_TASK etc. - Consult Oracle documentation for more details. + 1 If the database is local, specifying the SID or service name will be + enough. - Only once you can connect to Oracle using sqlplus - should you try building and testing DBD::Oracle. + 2 If the database is defined in a TNSNAMES.ORA file, you can use the + service name given in the file -*** BUILDING: + 3 To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, + of the form: //host[:port][/service_name] -Execute: + If port name is not specified, 1521 is the default. If service name is + not specified, the hostname will be used as a service name. - perl Makefile.PL # use a perl that's in your PATH + The following examples show several ways a connection can be created: -Use the perl that is first on your PATH. Then execute: + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - make + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); -If you get an error like "make: not found" you need to find the -directory that has the make command installed in it (e.g. /usr/ccs/bin -on Solaris) and add that to your PATH environment variable. + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); -Don't worry about most warnings when make runs, specifically ones like -"end-of-loop code not reached", "... due to prototype", -"cast increases required alignment of target type", etc. + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); -If you have problems see the 'IF YOU HAVE PROBLEMS' section below. -If it builds without error you should then run 'make test'. For the -main tests to work they must be able to connect to an Oracle database. + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); -The tests default to using a DSN of "dbi:Oracle:" which means you'll be -connected to the default database based on your TWO_TASK or ORACLE_SID -environment variables. This default can be altered either by defining the -ORACLE_DSN environment variable or the DBI_DSN environment variable. -See the oracle_test_dsn() sub in t/nchar_test_lib.pl + OS authentication + To connect to a local database with a user which has been set up to + authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): -The supplied tests will connect to the database using the value of the -ORACLE_USERID environment variable to supply the username/password. -So you should set that to a valid user (e.g. 'scott/tiger') and ensure that -this user has sufficient privileges to create, insert into, select from and -drop a table, is also able to create, call and drop a procedure and is able to select from -systemtables like 'v$sessions'. Using 'system/manager' might work but is not -recommended! See also + $dbh = DBI->connect('dbi:Oracle:','/',''); -README.login.txt. + Note the lack of a connection name (use the ORACLE_SID environment + variable). If an explicit SID is used you will probably get an ORA-01004 + error. - make test + That only works for local databases. (Authentication to remote Oracle + databases using your Unix login name without a password is possible but + it is not secure and not recommended so not documented here. -If the all the formal tests pass then, finally, run: + Oracle Environment Variables + To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME + environment variable should be set correctly. In general, the value used + should match the version of Oracle that was used to build DBD::Oracle. + If using dynamic linking then ORACLE_HOME should match the version of + Oracle that will be used to load in the Oracle client libraries (via + LD_LIBRARY_PATH, ldconfig, or similar on Unix). - make install + Oracle can use two environment variables to specify default connections: + ORACLE_SID and TWO_TASK. + To use them, specify either a local SID or service name, or a service + name that is specified in the TNSNAMES.ORA file. -*** IF YOU HAVE PROBLEMS: + Note that if you have *both* local and remote databases, and you have + ORACLE_SID *and* TWO_TASK set, and you don't specify a fully qualified + connect string on the command line, TWO_TASK takes precedence over + ORACLE_SID (i.e. you get connected to remote system). -Make sure you are using a recent perl (5.6.1 or later) and make -sure it's on your PATH so you can say 'perl Makefile.PL' and not -'/path/to/perl Makefile.PL'. + It is highly recommended not to rely on environment variables and to + always explicitly specify the SID in the connection string. This can + prevent serious mistakes such as dropping a schema in the wrong + database, and generally makes debugging and troubleshooting easier. -If you get compiler errors refering to Perl's own header files -(.../CORE/*.h) then there is something wrong with your installation. -It is important to use a Perl that was built on the system you are using. -It's also important to use the same compiler that was used to build the -Perl you are using. + Also remember that depending on the operating system you are using the + differing "ORACLE" environment variables may be case sensitive, so if + you are not connecting as you should double check the case of both the + variable and its value. -If you have build/link or core dump problems try: - perl Makefile.PL -p -or - perl Makefile.PL -nob -If it helps then please let me know (and please include a copy -of the log from the failed default build, the log from the build that -worked, plus the output of the "perl -V" command). + Timezones + If the query is run through SQL*Net (mostly queries that are executed on + remote servers), Oracle will return the time zone based on the setting + of the UNIX environment variable "TZ" for the user who started the + listener. -Do not hand edit the generated Makefile unless you are completely sure -you understand the implications! Always try to make changes via the -Makefile.PL command line and/or editing the Makefile.PL. -You should not need to make any changes. If you do please let us -know so that I can try to make it automatic in a later release. + If the query is run locally, Oracle will return the time zone based on + the "TZ" environment variable setting of the user running the query. -If you just can't login or login takes a long time then read -README.login.txt + With local queries, you can change the time zone for a particular user + by simply changing the setting of "TZ". To check the current setting, + issue the UNIX "date" command. -If you have linking problems (errors related to libraries or functions) -then you could try forcing a 'static' build using: + Oracle DRCP + DBD::Oracle supports DRCP (Database Resident Connection Pool) so if you + have an 11.2 database and DRCP is enabled you can direct all of your + connections to it by adding ':POOLED' to the SID or setting a connection + attribute of ora_drcp, or set the SERVER=POOLED when using a TNSENTRY + style connection or even by setting an environment variable ORA_DRCP. + All of which are demonstrated below; - make realclean - perl Makefile.PL LINKTYPE=static - make - make perl (you'll need to use and install _this_ new perl binary) - make test - make -f Makefile.aperl inst_perl MAP_TARGET=perl (install new perl) - make install (install DBD::Oracle) + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') -But that's not recommended these days. + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') ->>> Also carefully read the README.help.txt file which is full of useful ->>> tips and workarounds for various problems of various systems. + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) -*** HOW TO REPORT PROBLEMS + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') -This software is supported via the dbi-users@perl.org mailing list. -(You don't need to subscribe to the list in order to post.) + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") -Please do NOT post problems to comp.lang.perl.*, perl5-porters@perl.org, -http://www.cpanforum.com/dist/DBD-Oracle, or google groups etc. + if the ORA_DRCP environment variable is set then just this -If you're *sure* the problem is a bug then you can post a bug report -to http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle -Problem reports that don't include sufficient detail (including the -information listed below and how to reproduce the problem) -are unlikely to get resolved. + $dbh = DBI->connect('dbi:Oracle:DB','username','password') -For more information and to keep informed about progress you can join the -mailing list. Send a message to dbi-users-help@perl.org for more information. + You can find a white paper on setting up DRCP and its advantages at + . -Please post details of any problems (or changes you needed to make) to -dbi-users@perl.org. - - -** IT IS IMPORTANT TO INCLUDE *ALL* THE FOLLOWING INFORMATION: + Please note that DRCP support in DBD::Oracle is relatively new so the + mechanics or its implementation are subject to change. -1. A complete log of all steps of the build, e.g.: + TAF (Transparent Application Failover) + Transparent Application Failover (TAF) is the feature in OCI that allows + for clients to automatically reconnect to an instance in the event of a + failure of the instance. The reconnect happens automatically from within + the OCI (Oracle Call Interface) library. DBD::Oracle now supports a + callback function that will fire when a TAF event takes place. The main + use of the callback is to give your program the opportunity to inform + the user that a failover is taking place. - (do a make realclean first) - perl Makefile.PL - make - make test + You will have to set up TAF on your instance before you can use this + callback. You can test your instance to see if you can use TAF callback + with - Make sure to include the 'stderr' output. The best way to do this is - to use the "script" command (man script). If that's not available - then "command > command.log 2>&1" (assuming you're not using csh). - The "2>&1" is required (after the stdout redirect) to redirect stderr - to the same place. + $dbh->ora_can_taf(); - If a test fails then also include the output of: + If you try to set up a callback without it being enabled DBD::Oracle + will croak. - perl -Mblib t/.t + It is outside the scope of this documents to go through all of the + possible TAF situations you might want to set up but here is a simple + example: -2. Full details of which version of Oracle client and server you're using - (if it wasn't automatically found and printed by "perl Makefile.PL") + The TNS entry for the instance has had the following added to the + CONNECT_DATA section -3. The output of perl -V (that's a capital V, not lowercase) + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) -4. If you get errors like "undefined symbol", "symbol not found", - "undefined reference", "Text relocation remains" or any similar - error then include the output of "perl Makefile.PL -s XXX" - where XXX is the name of one of the symbols. - Please don't send the entire output of this command, - just any obviously 'interesting' parts (if there are any). - See also the LINKTYPE=static notes above. + You will also have to create your own perl function that will be called + from the client. You can name it anything you want and it will always be + passed two parameters, the failover event value and the failover type. + You can also set a sleep value in case of failover error and the OCI + client will sleep for the specified seconds before it attempts another + event. -5. If you get a core dump, rebuild DBD::Oracle with debugging - enabled by executing: perl Makefile.PL -g (note the -g option) - then rerun the code to get a new core dump file, finally use a - debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. - NOTE: I may not be able to help you much without a stack trace! - It is worth fetching and building the GNU GDB debugger (>=4.15) if - you don't have a good debugger on your system. If desperate try: - make perl; ./perl script; echo '$c' | adb ./perl core - Also see the Devel::CoreStack module on CPAN. - -6. If the stack trace mentions XS_DynaLoader_dl_load_file then rerun - make test after setting the environment variable PERL_DL_DEBUG to 2. - -7. If your installation succeeds, but your script does not behave - as you expect, the problem may be on your end. Before - sending to dbi-users, try writing a *small*, easy to use test case - to reproduce your problem. Also, use the DBI->trace method to - trace your database calls. + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants -It is important to check that you are using the latest version before -posting. If you're not then you're *very* likely to be told "upgrade to -the latest". You would do yourself a favour by upgrading beforehand. + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); -Try to help yourself first, then try to help others help you by following -these guidelines carefully. And remember, please don't mail developers -directly - use the dbi-users mailing list. + #create the perl TAF event function -Regards, -Tim. + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ -=============================================================================== -Examples and other info: + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); -README.help.txt -- READ IT FIRST IF YOU HAVE ANY PROBLEMS -README.win32.txt -- building DBD::Oracle under MS Windows -README.wingcc.txt -- building DBD::Oracle under MS Windows with gcc -README.macosx.txt -- building DBD::Oracle under MacOS X -README.clients.txt -- building/using DBD::Oracle on minimally configured systems -README.login.txt -- help for login problems -README.longs.txt -- examples dealing with LONG types (blobs) + } + return 0; + } -DBI 'home page': http://dbi.perl.org + The TAF types are as follows -Old archive site for Perl DB information: - ftp://ftp.demon.co.uk/pub/perl/db/ -Mailing list archive: /DBI/perldb-interest/ -Perl 4 Oraperl (v2.4) /perl4/oraperl/ - -Jeff Stander's stuff stands out for Oraperl: -Directories of interest might be - /pub/Oracle/sources - /pub/Oracle/sources/jstander - /pub/Oracle/sources/jstander/distrib - /pub/Oracle/sources/jstander/tsmlib - /pub/Oracle/sources/jstander/wdbex - /pub/Oracle/sources/web/scripts - /pub/Oracle/sources/dba - /pub/Oracle/sources/dba/imp2sql7 - /pub/Oracle/sources/Lonnroth - /pub/Oracle/sources/harrison - -http://www.bf.rmit.edu.au/~orafaq/perlish.html -ftp://ftp.bf.rmit.edu.au/pub/perl/db -ftp://ftp.bf.rmit.edu.au/pub/Oracle -ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources -ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip - -DBI and DBD::Oracle are very portable. If Perl and Oracle run on a platform -then the chances are that DBD::Oracle will as well. - -=============================================================================== - -See the large README.help.txt file for lots of hints and advice -about building and runtime issues. - -End. + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + + The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + + Connect Attributes + ora_ncs_buff_mtpl + You can customize the size of the buffer when selecting LOBs with the + built-in AUTO Lob. The default value is 4 which is probably excessive + for most situations but is needed for backward compatibility. If you not + converting between a NCS on the DB and the Client then you might want to + set this to 1 to reduce memory usage. + + This value can also be specified with the "ORA_DBD_NCS_BUFFER" + environment variable in which case it sets the value at the connect + stage. + + ora_drcp + For Oracle 11.2 or greater. + + Set to *1* to enable DRCP. Can also be set via the "ORA_DRCP" + environment variable. + + ora_drcp_class + If you are using DRCP, you can set a CONNECTION_CLASS for your pools as + well. As sessions from a DRCP cannot be shared by users, you can use + this setting to identify the same user across different applications. + OCI will ensure that sessions belonging to a 'class' are not shared + outside the class'. + + The values for ora_drcp_class cannot contain a '*' and must be less than + 1024 characters. + + This value can be also be specified with the "ORA_DRCP_CLASS" + environment variable. + + ora_drcp_min + This optional value specifies the minimum number of sessions that are + initially opened. New sessions are only opened after this value has been + reached. + + The default value is 4 and any value above 0 is valid. + + Generally, it should be set to the number of concurrent statements the + application is planning or expecting to run. + + This value can also be specified with the "ORA_DRCP_MIN" environment + variable. + + ora_drcp_max + This optional value specifies the maximum number of sessions that can be + open at one time. Once reached no more sessions can be opened until one + becomes free. The default value is 40 and any value above 1 is valid. + You should not set this value lower than ora_drcp_min as that will just + waste resources. + + This value can also be specified with the "ORA_DRCP_MAX" environment + variable. + + ora_drcp_incr + This optional value specifies the next increment for sessions to be + started if the current number of sessions are less than ora_drcp_max. + The default value is 2 and any value above 0 is valid as long as the + value of ora_drcp_min + ora_drcp_incr is not greater than ora_drcp_max. + + This value can also be specified with the "ORA_DRCP_INCR" environment + variable. + + ora_taf + If your Oracle instance has been configured to use TAF events you can + enable the TAF callback by setting this option to any *true* value. + + ora_taf_function + The name of the Perl subroutine that will be called from OCI when a TAF + event occurs. You must supply a perl function to use the callback and it + will always receive two parameters, the failover event value and the + failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + + ora_taf_sleep + The amount of time in seconds the OCI client will sleep between + attempting successive failover events when the event is OCI_FO_ERROR. + + ora_session_mode + The ora_session_mode attribute can be used to connect with SYSDBA, + SYSOPER and ORA_SYSASM authorization. The ORA_SYSDBA, ORA_SYSOPER and + ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + + This is one case where setting ORACLE_SID may be useful since connecting + as SYSDBA or SYSOPER via SQL*Net is frequently disabled for security + reasons. + + Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + + It has been reported that this only works if $dsn does not contain a SID + so that Oracle then uses the value of ORACLE_SID (not TWO_TASK) + environment variable to connect to a local instance. Also the username + and password should be empty, and the user executing the script needs to + be part of the dba group or osdba group. + + ora_oratab_orahome + Passing a true value for the ora_oratab_orahome attribute will make + DBD::Oracle change $ENV{ORACLE_HOME} to make the Oracle home directory + that specified in the "/etc/oratab" file *if* the database to connect to + is specified as a SID that exists in the oratab file, and DBD::Oracle + was built to use the Oracle 7 OCI API (not Oracle 8+). + + ora_module_name + After connecting to the database the value of this attribute is passed + to the SET_MODULE() function in the "DBMS_APPLICATION_INFO" PL/SQL + package. This can be used to identify the application to the DBA for + monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + + The maximum size is 48 bytes. + + ora_driver_name + For 11g and later you can now set the name of the driver layer using + OCI. Perl, Perl5, ApachePerl so on. Names starting with "ORA" are + reserved. You can enter up to 8 characters. If none is enter then this + will default to DBDOxxxx where xxxx is the current version number. This + value can be retrieved on the server side using V$SESSION_CONNECT_INFO + or GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + + ora_client_info + Allows you to add any value (up to 64 bytes) to your session and it can + be retrieved on the server side from the "V$SESSION"a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + + ora_client_identifier + Allows you to specify the user identifier in the session handle. + + Most useful for web applications as it can pass in the session user name + which might be different to the connection user name. Can be up to 64 + bytes long but do not to include the password for security reasons and + the first character of the identifier should not be ':'. This value can + be retrieved on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + + ora_action + Allows you to specify any string up to 32 bytes which may be retrieved + on the server side using "V$SESSION" view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + + ora_dbh_share + Requires at least Perl 5.8.0 compiled with ithreads. + + Allows you to share database connections between threads. The first + connect will make the connection, all following calls to connect with + the same ora_dbh_share attribute will use the same database connection. + The value must be a reference to a already shared scalar which is + initialized to an empty string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + + ora_envhp + The first time a connection is made a new OCI 'environment' is created + by DBD::Oracle and stored in the driver handle. Subsequent connects + reuse (share) that same OCI environment by default. + + The ora_envhp attribute can be used to disable the reuse of the OCI + environment from a previous connect. If the value is 0 then a new OCI + environment is allocated and used for this connection. + + The OCI environment holds information about the client side context, + such as the local NLS environment. By altering %ENV and setting + ora_envhp to 0 you can create connections with different NLS settings. + This is most useful for testing. + + ora_charset, ora_ncharset + For oracle versions >= 9.2 you can specify the client charset and + ncharset with the ora_charset and ora_ncharset attributes. You still + need to pass "ora_envhp = 0" for all but the first connect. + + These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + + ora_verbose + Use this value to enable DBD::Oracle only tracing. Simply either set the + ora_verbose attribute on the connect() method to the trace level you + desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + + or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + + In both cases the DBD::Oracle trace level is set to 6, which is the + highest level tracing most of the calls to OCI. + + ora_oci_success_warn + Use this value to print otherwise silent OCI warnings that may happen + when an execute or fetch returns "Success With Info" or when you want to + tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + + ora_objects + Use this value to enable extended embedded oracle objects mode. In + extended: + + 1 Embedded objects are returned as instance + (including type-name etc.) instead of simple ARRAY. + + 2 Determine object type for each instance. All object attributes are + returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + + ora_ph_type + The default placeholder datatype for the database session. The "TYPE" or + "ora_type" attributes to "bind_param" in DBI and "bind_param_inout" in + DBI override the datatype for individual placeholders. The most frequent + reason for using this attribute is to permit trailing spaces in values + passed by placeholders. + + Constants for the values allowed for this attribute can be imported + using + + use DBD::Oracle qw(:ora_types); + + Only the following values are permitted for this attribute. + + ORA_VARCHAR2 + Oracle clients using OCI 8 will strip trailing spaces and allow + embedded \0 bytes. Oracle clients using OCI 9.2 do not strip + trailing spaces and allow embedded \0 bytes. This is the normal + default placeholder type. + + ORA_STRING + Do not strip trailing spaces and end the string at the first \0. + + ORA_CHAR + Do not strip trailing spaces and allow embedded \0. Force + 'blank-padded comparison semantics'. + + For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + + Will pad bloggs out to 8 characters and return the username. + + ora_parse_error_offset + If the previous error was from a failed "prepare" due to a syntax error, + this attribute gives the offset into the "Statement" attribute where the + error was found. + + ora_array_chunk_size + Due to OCI limitations, DBD::Oracle needs to buffer up rows of bind + values in its "execute_for_fetch" implementation. This attribute sets + the number of rows to buffer at a time (default value is 1000). + + The "execute_for_fetch" function will collect (at most) this many rows + in an array, send them off to the DB for execution, then go back to + collect the next chunk of rows and so on. This attribute can be used to + limit or extend the number of rows processed at a time. + + Note that this attribute also applies to "execute_array", since that + method is implemented using "execute_for_fetch". + + ora_connect_with_default_signals + Sometimes the Oracle client seems to change some of the signal handlers + of the process during the connect phase. For instance, some users have + observed Perl's default $SIG{INT} handler being ignored after connecting + to an Oracle database. If this causes problems in your application, set + this attribute to an array reference of signals you would like to be + localized during the connect process. Once the connect is complete, the + signal handlers should be returned to their previous state. + + For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + + NOTE disabling the signal handlers the OCI library sets up may affect + functionality in the OCI library. + + NOTE If you are using connect_cached then the above example will lead to + DBI thinking each connection is different as an anonymous array + reference is being used. To avoid this when using connect_cached you are + advised to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + + In more recent Perl versions you could possibly make use of new state + variables. + + connect_cached + Implemented by DBI, no driver-specific impact. Please note that + connect_cached as not been tested with DRCP. + + data_sources + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + + Returns a list of available databases. You will have to set either the + 'ORACLE_HOME' or 'TNS_ADMIN' environment value to retrieve this list. It + will read these values from TNSNAMES.ORA file entries. + +METHODS COMMON TO ALL HANDLES + For all of the methods below, $h can be either a database handle ($dbh) + or a statement handle ($sth). Note that *$dbh* and *$sth* can be + replaced with any variable name you choose: these are just the names + most often used. Another common variable used in this documentation is + $*rv*, which stands for "return value". + + err + $rv = $h->err; + + Returns the error code from the last method called. + + errstr + $str = $h->errstr; + + Returns the last error that was reported by Oracle. Starting with + "ORA-00000" code followed by the error message. + + state + $str = $h->state; + + Oracle hasn't supported SQLSTATE since the early versions OCI. It will + return empty when the command succeeds and 'S1000' (General Error) for + all other errors. + + While this method can be called as either "$sth->state" or + "$dbh->state", it is usually clearer to always use "$dbh->state". + + trace + Implemented by DBI, no driver-specific impact. + + trace_msg + Implemented by DBI, no driver-specific impact. + + parse_trace_flag and parse_trace_flags + Implemented by DBI, no driver-specific impact. + + func + DBD::Oracle uses the "func" method to support a variety of functions. + + Private database handle functions + Some of these functions are called through the method func() which is + described in the DBI documentation. Any function that begins with ora_ + can be called directly. + + plsql_errstr + This function returns a string which describes the errors from the most + recent PL/SQL function, procedure, package, or package body compile in a + format similar to the output of the SQL*Plus command 'show errors'. + + The function returns undef if the error string could not be retrieved + due to a database error. Look in $dbh->errstr for the cause of the + failure. + + If there are no compile errors, an empty string is returned. + + Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + + dbms_output_enable / dbms_output_put / dbms_output_get + These functions use the PL/SQL DBMS_OUTPUT package to store and retrieve + text using the DBMS_OUTPUT buffer. Text stored in this buffer by + dbms_output_put or any PL/SQL block can be retrieved by dbms_output_get + or any PL/SQL block connected to the same database session. + + Stored text is not available until after dbms_output_put or the PL/SQL + block that saved it completes its execution. This means you CAN NOT use + these functions to monitor long running PL/SQL procedures. + + Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + + Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + + dbms_output_enable ( [ buffer_size ] ) + This function calls DBMS_OUTPUT.ENABLE to enable calls to package + DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to these + procedures are ignored unless DBMS_OUTPUT.ENABLE is called first. + + The buffer_size is the maximum amount of text that can be saved in the + buffer and must be between 2000 and 1,000,000. If buffer_size is not + given, the default is 20,000 bytes. + + dbms_output_put ( [ @lines ] ) + This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + + If all lines were saved successfully the function returns 1. Depending + on the context, an empty list or undef is returned for failure. + + If any line causes buffer_size to be exceeded, a buffer overflow error + is raised and the function call fails. Some of the text might be in the + buffer. + + dbms_output_get + This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from + the buffer. + + In an array context, all complete lines are removed from the buffer and + returned as a list. If there are no complete lines, an empty list is + returned. + + In a scalar context, the first complete line is removed from the buffer + and returned. If there are no complete lines, undef is returned. + + Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or + DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, + DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + + reauthenticate ( $username, $password ) + Starts a new session against the current database using the credentials + supplied. + + private_attribute_info + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + + Returns a hash of all private attributes used by DBD::Oracle, for either + a database or a statement handle. Currently, all the hash values are + undef. + +ATTRIBUTES COMMON TO ALL HANDLES + InactiveDestroy (boolean) + Implemented by DBI, no driver-specific impact. + + RaiseError (boolean, inherited) + Forces errors to always raise an exception. Although it defaults to off, + it is recommended that this be turned on, as the alternative is to check + the return value of every method (prepare, execute, fetch, etc.) + manually, which is easy to forget to do. + + PrintError (boolean, inherited) + Forces database errors to also generate warnings, which can then be + filtered with methods such as locally redefining *$SIG{__WARN__}* or + using modules such as "CGI::Carp". This attribute is on by default. + + ShowErrorStatement (boolean, inherited) + Appends information about the current statement to error messages. If + placeholder information is available, adds that as well. Defaults to + true. + + Warn (boolean, inherited) + Enables warnings. This is on by default, and should only be turned off + in a local block for a short a time only when absolutely needed. + + Executed (boolean, read-only) + Indicates if a handle has been executed. For database handles, this + value is true after the "do" method has been called, or when one of the + child statement handles has issued an "execute". Issuing a "commit" or + "rollback" always resets the attribute to false for database handles. + For statement handles, any call to "execute" or its variants will flip + the value to true for the lifetime of the statement handle. + + TraceLevel (integer, inherited) + Sets the trace level, similar to the "trace" method. See the sections on + "trace" and "parse_trace_flag" for more details. + + Active (boolean, read-only) + Indicates if a handle is active or not. For database handles, this + indicates if the database has been disconnected or not. For statement + handles, it indicates if all the data has been fetched yet or not. Use + of this attribute is not encouraged. + + Kids (integer, read-only) + Returns the number of child processes created for each handle type. For + a driver handle, indicates the number of database handles created. For a + database handle, indicates the number of statement handles created. For + statement handles, it always returns zero, because statement handles do + not create kids. + + ActiveKids (integer, read-only) + Same as "Kids", but only returns those that are active. + + CachedKids (hash ref) + Returns a hashref of handles. If called on a database handle, returns + all statement handles created by use of the "prepare_cached" method. If + called on a driver handle, returns all database handles created by the + "connect_cached" method. + + ChildHandles (array ref) + Implemented by DBI, no driver-specific impact. + + PrintWarn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleError (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + HandleSetErr (code ref, inherited) + Implemented by DBI, no driver-specific impact. + + ErrCount (unsigned integer) + Implemented by DBI, no driver-specific impact. + + FetchHashKeyName (string, inherited) + Implemented by DBI, no driver-specific impact. + + ChopBlanks (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Taint (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintIn (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + TaintOut (boolean, inherited) + Implemented by DBI, no driver-specific impact. + + Profile (inherited) + Implemented by DBI, no driver-specific impact. + + Type (scalar) + Returns "dr" for a driver handle, "db" for a database handle, and "st" + for a statement handle. Should be rarely needed. + + LongReadLen + The maximum size of long or longraw columns to retrieve. If one of these + columns is longer than LongReadLen then either a data truncation error + will be raised (LongTrunkOk is false) or the column will be silently + truncated (LongTruncOk is true). + + DBI currently defaults this to 80. + + LongTruncOk + Implemented by DBI, no driver-specific impact. + + CompatMode + Type: boolean, inherited + + The CompatMode attribute is used by emulation layers (such as Oraperl) + to enable compatible behaviour in the underlying driver (e.g., + DBD::Oracle) for this handle. Not normally set by application code. + + It also has the effect of disabling the 'quick FETCH' of attribute + values from the handles attribute cache. So all attribute values are + handled by the drivers own FETCH method. This makes them slightly slower + but is useful for special-purpose drivers like DBD::Multiplex. + +ORACLE-SPECIFIC DATABASE HANDLE METHODS + ora_can_unicode ( [ $refresh ] ) + Returns a number indicating whether either of the database character + sets is a Unicode encoding. Calls ora_nls_parameters() and passes the + optional $refresh parameter to it. + + 0 = Neither character set is a Unicode encoding. + + 1 = National character set is a Unicode encoding. + + 2 = Database character set is a Unicode encoding. + + 3 = Both character sets are Unicode encodings. + + ora_can_taf + Returns true if the current connection supports TAF events. False if + otherise. + + ora_nls_parameters ( [ $refresh ] ) + Returns a hash reference containing the current NLS parameters, as given + by the v$nls_parameters view. The values fetched are cached between + calls. To cause the latest values to be fetched, pass a true value to + the function. + +DATABASE HANDLE METHODS + selectall_arrayref + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the rows returned by + preparing and executing the SQL string. See the DBI documentation for + full details. + + selectall_hashref + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + + Returns a reference to a hash containing the rows returned by preparing + and executing the SQL string. See the DBI documentation for full + details. + + selectcol_arrayref + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + + Returns a reference to an array containing the first column from each + rows returned by preparing and executing the SQL string. It is possible + to specify exactly which columns to return. See the DBI documentation + for full details. + + prepare + $sth = $dbh->prepare($statement, \%attr); + + Prepares a statement for later execution by the database engine and + returns a reference to a statement handle object. + + Prepare Attributes + These attributes may be used in the "\%attr" parameter of the "prepare" + in DBI database handle method. + + ora_placeholders + Set to false to disable processing of placeholders. Used mainly for + loading a PL/SQL package that has been *wrapped* with Oracle's + "wrap" utility. + + ora_auto_lob + If true (the default), fetching retrieves the contents of the CLOB + or BLOB column in most circumstances. If false, fetching retrieves + the Oracle "LOB Locator" of the CLOB or BLOB value. + + See "LOBs and LONGs" for more details. + + See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how + to use LOB Locators. + + ora_pers_lob + If true the "Simple Fetch for CLOBs and BLOBs" method for the "Data + Interface for Persistent LOBs" will be used for LOBs rather than the + default method "Data Interface for LOB Locators". + + ora_clbk_lob + If true the "Piecewise Fetch with Callback" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_lob + If true the "Piecewise Fetch with Polling" method for the "Data + Interface for Persistent LOBs" will be used for LOBs. + + ora_piece_size + This is the max piece size for the "Piecewise Fetch with Callback" + and "Piecewise Fetch with Polling" methods, in chars for CLOBS, and + bytes for BLOBS. + + ora_check_sql + If 1 (default), force SELECT statements to be described in + prepare(). If 0, allow SELECT statements to defer describe until + execute(). + + See "Prepare Postponed Till Execute" for more information. + + ora_exe_mode + This will set the execute mode of the current statement. Presently + only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + + See "Scrollable Cursors" for more details. + + ora_prefetch_rows + Sets the number of rows to be prefetched. If it is not set, then the + default value is 1. See "Row Prefetching" for more details. + + ora_prefetch_memory + Sets the memory level for rows to be prefetched. The application + then fetches as many rows as will fit into that much memory. See + "Row Prefetching" for more details. + + ora_row_cache_off + By default DBD::Oracle will use a row cache when fetching to cut + down the number of round trips to the server. If you do not want to + use an array fetch set this value to any value other than 0; + + See "Row Prefetching" for more details. + + Placeholders + There are three types of placeholders that can be used in DBD::Oracle. + + The first is the "question mark" type, in which each placeholder is + represented by a single question mark character. This is the method + recommended by the DBI and is the most portable. Each question mark is + internally replaced by a "dollar sign number" in the order in which they + appear in the query (important when using "bind_param"). + + The second type of placeholder is "named parameters" in the format + ":foo" which is the one Oracle prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + + Note when calling bind_param with named parameters you must include the + leading colon. The advantage of this placeholder type is that you can + use the same placeholder more than once in the same SQL statement but + you only need to bind it once. + + The last placeholder type is a variation of the two above where you name + each placeholder :N (where N is a number). Like the named placeholders + above you can use the same placeholder multiple times in the SQL but + when you call bind_param you only need to pass the N (e.g., for :1 you + use bind_param(1,...) and not bind_param(':1',...). + + The different types of placeholders cannot be mixed within a statement, + but you may use different ones for each statement handle you have. This + is confusing at best, so stick to one style within your program. + + prepare_cached + $sth = $dbh->prepare_cached($statement, \%attr); + + Implemented by DBI, no driver-specific impact. This method is most + useful if the same query is used over and over as it will cut down round + trips to the server. + + do + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + + Prepare and execute a single statement. Returns the number of rows + affected if the query was successful, returns undef if an error + occurred, and returns -1 if the number of rows is unknown or not + available. Note that this method will return 0E0 instead of 0 for 'no + rows were affected', in order to always return a true value if no error + occurred. + + last_insert_id + Oracle does not implement auto_increment of serial type columns it uses + predefined sequences where the id numbers are either selected before + insert, at insert time with a trigger, or as part of the query. + + Below is an example of you to use the latter with the SQL returning + clause to get the ID number back on insert with the bind_param_inout + method. . + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + + commit + $rv = $dbh->commit; + + Issues a COMMIT to the server, indicating that the current transaction + is finished and that all changes made will be visible to other + processes. If AutoCommit is enabled, then a warning is given and no + COMMIT is issued. Returns true on success, false on error. + + rollback + $rv = $dbh->rollback; + + Issues a ROLLBACK to the server, which discards any changes made in the + current transaction. If AutoCommit is enabled, then a warning is given + and no ROLLBACK is issued. Returns true on success, and false on error. + + begin_work + This method turns on transactions until the next call to "commit" or + "rollback", if "AutoCommit" is currently enabled. If it is not enabled, + calling begin_work will issue an error. Note that the transaction will + not actually begin until the first statement after begin_work is called. + + disconnect + $rv = $dbh->disconnect; + + Disconnects from the Oracle database. Any uncommitted changes will be + rolled back upon disconnection. It's good policy to always explicitly + call commit or rollback at some point before disconnecting, rather than + relying on the default rollback behavior. + + If the script exits before disconnect is called (or, more precisely, if + the database handle is no longer referenced by anything), then the + database handle's DESTROY method will call the rollback() and + disconnect() methods automatically. It is best to explicitly disconnect + rather than rely on this behavior. + + ping + $rv = $dbh->ping; + + This "ping" method is used to check the validity of a database handle. + The value returned is either 0, indicating that the connection is no + longer valid, or 1, indicating the connection is valid. This function + does 1 round trip to the Oracle Server. + + get_info() + $value = $dbh->get_info($info_type); + + DBD::Oracle supports "get_info()", but (currently) only a few info + types. + + table_info() + DBD::Oracle supports attributes for "table_info()". + + In Oracle, the concept of *user* and *schema* is (currently) the same. + Because database objects are owned by an user, the owner names in the + data dictionary views correspond to schema names. Oracle does not + support catalogues so TABLE_CAT is ignored as selection criterion. + + Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + + TABLE_TYPE may contain a comma-separated list of table types. The + following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + + The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + + The special enumerations of catalogues, schemas and table types are + supported. However, TABLE_CAT is always NULL. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. "table_info()" performs a case-sensitive search. So, a + selection criterion should respect upper and lower case. Normally, an + identifier is case-insensitive. Oracle stores and returns it in upper + case. Sometimes, database objects are created with quoted identifiers + (for reserved words, mixed case, special characters, ...). Such an + identifier is case-sensitive (if not all upper case). Oracle stores and + returns it as given. "table_info()" has no special quote handling, + neither adds nor removes quotes. + + primary_key_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + If the primary key constraint was created without an identifier, PK_NAME + contains a system generated name with the form SYS_Cn. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + foreign_key_info() + This method (currently) supports the extended behaviour of SQL/CLI, i.e. + the result set contains foreign keys that refer to primary and alternate + keys. The field UNIQUE_OR_PRIMARY distinguishes these keys. + + Oracle does not support catalogues, so $pk_catalog and $fk_catalog are + ignored as selection criteria (in the new style interface). The + UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always NULL + (undef). See "table_info()" for more detailed information. + + If the primary or foreign key constraints were created without an + identifier, UK_NAME or FK_NAME contains a system generated name with the + form SYS_Cn. + + The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle + (currently) does not support other actions. + + The DELETE_RULE field may contain wrong values. This is a known Bug + (#1271663) in Oracle's data dictionary views. Currently (as of 8.1.7), + 'RESTRICT' and 'SET DEFAULT' are not supported, 'CASCADE' is mapped + correctly and all other actions (incl. 'SET NULL') appear as 'NO + ACTION'. + + The DEFERABILITY field is always NULL, because this columns is not + present in the ALL_CONSTRAINTS view of older Oracle releases. + + The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, + FK_TABLE_SCHEM, FK_TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + column_info() + Oracle does not support catalogues so TABLE_CAT is ignored as selection + criterion. The TABLE_CAT field of a fetched row is always NULL (undef). + See "table_info()" for more detailed information. + + The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + + Don't rely on the values of the BUFFER_LENGTH field! Especially the + length of FLOATs may be wrong. + + Datatype codes for non-standard types are subject to change. + + Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG so you + may have to set LongReadLen on the connection handle before calling + column_info if you have a large default column. After DBD::Oracle 1.40 + LongReadLen is set automatically to 1Mb when calling column_info and + reset aftwerwards. + + The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + + An identifier is passed *as is*, i.e. as the user provides or Oracle + returns it. See "table_info()" for more detailed information. + + It is possible with Oracle to make the names of the various DB objects + (table,column,index etc) case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + + So in the example the exact case "Bla_BLA" must be used to get it info + on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + + any case can be used to get info on the column. + + selectrow_array + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + + Returns an array of row information after preparing and executing the + provided SQL string. The rows are returned by calling "fetchrow_array". + The string can also be a statement handle generated by a previous + prepare. Note that only the first row of data is returned. If called in + a scalar context, only the first column of the first row is returned. + Because this is not portable, it is not recommended that you use this + method in that way. + + selectrow_arrayref + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an array, by internal use of the "fetchrow_arrayref" + method. + + selectrow_hashref + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + + Exactly the same as "selectrow_array", except that it returns a + reference to an hash, by internal use of the "fetchrow_hashref" method. + + clone + $other_dbh = $dbh->clone(); + + Creates a copy of the database handle by connecting with the same + parameters as the original handle, then trying to merge the attributes. + See the DBI documentation for complete usage. + +DATABASE HANDLE ATTRIBUTES + AutoCommit (boolean) + Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is + on, but this may change in the future, so it is highly recommended that + you explicitly set it when calling "connect". + + ReadOnly (boolean) + $dbh->{ReadOnly} = 1; + + Specifies if the current database connection should be in read-only mode + or not. + + Please not that this method is not foolproof: there are still ways to + update the database. Consider this a safety net to catch applications + that should not be issuing commands such as INSERT, UPDATE, or DELETE. + + This method method requires DBI version 1.55 or better. + + Name (string, read-only) + Returns the name of the current database. This is the same as the DSN, + without the "dbi:Oracle:" part. + + Username (string, read-only) + Returns the name of the user connected to the database. + + Driver (handle, read-only) + Holds the handle of the parent driver. The only recommended use for this + is to find the name of the driver using: + + $dbh->{Driver}->{Name} + + RowCacheSize + DBD::Oracle supports both Server pre-fetch and Client side row caching. + By default both are turned on to give optimum performance. Most of the + time one can just let DBD::Oracle figure out the best optimization. + + Row Caching + Row caching occurs on the client side and the object of it is to cut + down the number of round trips made to the server when fetching rows. At + each fetch a set number of rows will be retrieved from the server and + stored locally. Further calls the server are made only when the end of + the local buffer(cache) is reached. + + Rows up to the specified top level row count "RowCacheSize" are fetched + if it occupies no more than the specified memory usage limit. The + default value is 0, which means that memory size is not included in + computing the number of rows to prefetch. If the "RowCacheSize" value is + set to a negative number then the positive value of RowCacheSize is used + to compute the number of rows to prefetch. + + By default "RowCacheSize" is automatically set. If you want to totally + turn off prefetching set this to 1. + + For any SQL statement that contains a LOB, Long or Object Type Row + Caching will be turned off. However server side caching still works. If + you are only selecting a LOB Locator then Row Caching will still work. + + Row Prefetching + Row prefetching occurs on the server side and uses the DBI database + handle attribute "RowCacheSize" and or the Prepare Attribute + 'ora_prefetch_memory'. Tweaking these values may yield improved + performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + + In the above example 10 rows will be prefetched up to a maximum of 10000 + bytes of data. The Oracle® Call Interface Programmer's Guide, suggests + a good row cache value for a scrollable cursor is about 20% of expected + size of the record set. + + The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) + when it needs to get new rows. This happens on the first fetch that sets + the current_positon to any value other than 0. In the above example if + we do a OCI_FETCH_FIRST the first 10 rows are loaded into the buffer and + DBD::Oracle will not have to go back to the server for more rows. When + record 11 is fetched DBD::Oracle fetches and returns this row and the + next 9 rows are loaded into the buffer. In this case if you fetch + backwards from 10 to 1 no server round trips are made. + + With large record sets it is best not to attempt to go to the last + record as this may take some time, A large buffer size might even slow + down the fetch. If you must get the number of rows in a large record set + you might try using an few large OCI_FETCH_ABSOLUTEs and then an + OCI_FETCH_LAST, this might save some time. So if you had a record set of + 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one + would fetch the first 5000 rows into the buffer then the next 5000 rows. + If one requires only the first few rows there is no need to set a large + prefetch value. + + If the ora_prefetch_memory less than 1 or not present then memory size + is not included in computing the number of rows to prefetch otherwise + the number of rows will be limited to memory size. Likewise if the + RowCacheSize is less than 1 it is not included in the computing of the + prefetch rows. + +ORACLE-SPECIFIC STATEMENT HANDLE METHODS + ora_stmt_type + Returns the OCI Statement Type number for the SQL of a statement handle. + + ora_stmt_type_name + Returns the OCI Statement Type name for the SQL of a statement handle. + +DBI STATEMENT HANDLE OBJECT METHODS + bind_param + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + + Allows the user to bind a value and/or a data type to a placeholder. + + The value of $param_num is a number if using the '?' or if using ":foo" + style placeholders, the complete name (e.g. ":foo") must be given. The + $bind_value argument is fairly self-explanatory. A value of "undef" will + bind a "NULL" to the placeholder. Using "undef" is useful when you want + to change just the type and will be overwriting the value later. (Any + value is actually usable, but "undef" is easy and efficient). + + The "\%attr" hash is used to indicate the data type of the placeholder. + The default value is "varchar". If you need something else, you must use + one of the values provided by DBI or by DBD::Pg. To use a SQL value, + modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + + This will import some constants into your script. You can plug those + directly into the "bind_param" call. Some common ones that you will + encounter are: + + SQL_INTEGER + + To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + + You can then set the data types by setting the value of the "ora_type" + key in the hash passed to "bind_param". The current list of Oracle data + types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + + Data types are "sticky," in that once a data type is set to a certain + placeholder, it will remain for that placeholder, unless it is + explicitly set to something else afterwards. If the statement has + already been prepared, and you switch the data type to something else, + DBD::Oracle will re-prepare the statement for you before doing the next + execute. + + Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + + These attributes may be used in the "\%attr" parameter of the + "bind_param" in DBI or "bind_param_inout" in DBI statement handle + methods. + + ora_type + Specify the placeholder's datatype using an Oracle datatype. A fatal + error is raised if "ora_type" and the DBI "TYPE" attribute are used + for the same placeholder. Some of these types are not supported by + the current version of DBD::Oracle and will cause a fatal error if + used. Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + + Potentially useful values when DBD::Oracle was built using OCI 7 and + later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + + Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + + Additional values when DBD::Oracle was built using OCI 9.2 and + later: + + SQLT_CHR, SQLT_BIN + + See "Binding Cursors" for the correct way to use ORA_RSET. + + See "LOBs and LONGs" for how to use ORA_CLOB and ORA_BLOB. + + See "SYS.DBMS_SQL datatypes" for ORA_VARCHAR2_TABLE, + ORA_NUMBER_TABLE. + + See "Data Interface for Persistent LOBs" for the correct way to use + SQLT_CHR and SQLT_BIN. + + See "Other Data Types" for more information. + + See also "Placeholders and Bind Values" in DBI. + + ora_csform + Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values + are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can + be imported from the DBD::Oracle module. Rarely needed. + + ora_csid + Specify the *integer* OCI_ATTR_CHARSET_ID for the bind value. + Character set names can't be used currently. + + ora_maxdata_size + Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. May be + needed if a character set conversion from client to server causes + the data to use more space and so fail with a truncation error. + + ora_maxarray_numentries + Specify the maximum number of array entries to allocate. Used with + ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of + array entries Oracle can pass back to you in OUT variable of type + TABLE OF ... . + + ora_internal_type + Specify internal data representation. Currently is supported only + for ORA_NUMBER_TABLE. + + Optimizing Results + Prepare Postponed Till Execute + The DBD::Oracle module can avoid an explicit 'describe' operation prior + to the execution of the statement unless the application requests + information about the results (such as $sth->{NAME}). This reduces + communication with the server and increases performance (reducing the + number of PARSE_CALLS inside the server). + + However, it also means that SQL errors are not detected until + "execute()" (or $sth->{NAME} etc) is called instead of when "prepare()" + is called. Note that if the describe is triggered by the use of + $sth->{NAME} or a similar attribute and the describe fails then *an + exception is thrown* even if "RaiseError" is false! + + Set "ora_check_sql" to 0 in prepare() to enable this behaviour. + + bind_param_inout + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + + DBD::Oracle fully supports bind_param_inout below are some uses for this + method. + + Returning A Value from an INSERT + Oracle supports an extended SQL insert syntax which will return one or + more of the values inserted. This can be particularly useful for + single-pass insertion of values with re-used sequence values (avoiding a + separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + + If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + + If you have many rows to insert you can take advantage of Oracle's built + in execute array feature with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + + Which will return all the ids into @out_values. + + Note: + This will only work for numbered (?) placeholders, + The third parameter of bind_param_inout_array, (0 in the example), + "maxlen" is required by DBI but not used by DBD::Oracle + The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + + Returning A Recordset + DBD::Oracle does not currently support binding a PL/SQL table (aka + array) as an IN OUT parameter to any Perl data structure. You cannot + therefore call a PL/SQL function or procedure from DBI that uses a + non-atomic datatype as either a parameter, or a return value. However, + if you are using Oracle 9.0.1 or later, you can make use of table (or + pipelined) functions. + + For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + + Currently, there is no way to directly call the function + Array_Example.Array_Func from DBI. However, by making the following + relatively painless additions, its not only possible, but extremely + efficient. + + First, you need to create database object types that correspond to the + record and table types in the package. From the above example, these + would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + + Now, assuming the existing function needs to remain unchanged (it is + probably being called from other PL/SQL code), we need to add a new + function to the package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + + As you can see, the new function is very simple. Now, it is a simple + matter of calling the function as a straight-forward SELECT from your + DBI code. From the above example, the code would look something like + this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + + SYS.DBMS_SQL datatypes + DBD::Oracle has built-in support for SYS.DBMS_SQL.VARCHAR2_TABLE and + SYS.DBMS_SQL.NUMBER_TABLE datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + Note: + Take careful note that we use '\\@arr' here because the + 'bind_param_inout' will only take a reference to a scalar. + + ORA_VARCHAR2_TABLE + SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. ( + in bind_param() and bind_param_inout() ). When you bind array, you need + to specify full buffer size for OUT data. So, there are two parameters: + *max_len* (specified as 3rd argument of bind_param_inout() ), and + *ora_maxarray_numentries*. They define maximum array entry length and + maximum rows, that can be passed to Oracle and back to you. In this + example we send array with 1 element with length=3, but allocate space + for 100 Oracle array entries with maximum length 10 of each. So, you can + get no more than 100 array entries with length <= 10. + + If you set *max_len* to zero, maximum array entry length is calculated + as maximum length of entry of array bound. If 0 < *max_len* < length( + $some_element ), truncation occur. + + If you set *ora_maxarray_numentries* to zero, current (at bind time) + bound array length is used as maximum. If 0 < *ora_maxarray_numentries* + < scalar(@array), not all array entries are bound. + + ORA_NUMBER_TABLE + SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike + ORA_VARCHAR2_TABLE. The main difference is internal data representation. + Currently 2 types of bind is allowed : as C-integer, or as C-double + type. To select one of them, you may specify additional bind parameter + *ora_internal_type* as either SQLT_INT or SQLT_FLT for C-integer and + C-double types. Integer size is architecture-specific and is usually 32 + or 64 bit. Double is standard IEEE 754 type. + + *ora_internal_type* defaults to double (SQLT_FLT). + + *max_len* is ignored for OCI_NUMBER_TABLE. + + Currently, you cannot bind full native Oracle NUMBER(38). If you really + need, send request to dbi-dev list. + + The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + + If you change bind type to SQLT_INT, like: + + ora_internal_type => SQLT_INT + + you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + + bind_param_inout_array + DBD::Oracle supports this undocumented feature of DBI. See "Returning A + Value from an INSERT" for an example. + + bind_param_array + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + + Binds an array of values to a placeholder, so that each is used in turn + by a call to the "execute_array" method. + + execute + $rv = $sth->execute(@bind_values); + + Perform whatever processing is necessary to execute the prepared + statement. + + execute_array + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + Execute a prepared statement once for each item in a passed-in hashref, + or items that were previously bound via the "bind_param_array" method. + See the DBI documentation for more details. + + DBD::Oracle takes full advantage of OCI's array interface so inserts and + updates using this interface will run very quickly. + + execute_for_fetch + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + Used internally by the "execute_array" method, and rarely used directly. + See the DBI documentation for more details. + + fetchrow_arrayref + $ary_ref = $sth->fetchrow_arrayref; + + Fetches the next row of data from the statement handle, and returns a + reference to an array holding the column values. Any columns that are + NULL are returned as undef within the array. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + Note that the same array reference is returned for each fetch, so don't + store the reference and then use it after a later fetch. Also, the + elements of the array are also reused for each row, so take care if you + want to take a reference to an element. See also "bind_columns". + + fetchrow_array + @ary = $sth->fetchrow_array; + + Similar to the "fetchrow_arrayref" method, but returns a list of column + information rather than a reference to a list. Do not use this in a + scalar context. + + fetchrow_hashref + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + + Fetches the next row of data and returns a hashref containing the name + of the columns as the keys and the data itself as the values. Any NULL + value is returned as as undef value. + + If there are no more rows or if an error occurs, the this method return + undef. You should check "$sth->err" afterwards (or use the "RaiseError" + attribute) to discover if the undef returned was due to an error. + + The optional $name argument should be either "NAME", "NAME_lc" or + "NAME_uc", and indicates what sort of transformation to make to the keys + in the hash. By default Oracle uses upper case. + + fetchall_arrayref + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + + Returns a reference to an array of arrays that contains all the + remaining rows to be fetched from the statement handle. If there are no + more rows, an empty arrayref will be returned. If an error occurs, the + data read in so far will be returned. Because of this, you should always + check "$sth->err" after calling this method, unless "RaiseError" has + been enabled. + + If $slice is an array reference, fetchall_arrayref uses the + "fetchrow_arrayref" method to fetch each row as an array ref. If the + $slice array is not empty then it is used as a slice to select + individual columns by perl array index number (starting at 0, unlike + column and parameter numbers which start at 1). + + With no parameters, or if $slice is undefined, fetchall_arrayref acts as + if passed an empty array ref. + + If $slice is a hash reference, fetchall_arrayref uses "fetchrow_hashref" + to fetch each row as a hash reference. + + See the DBI documentation for a complete discussion. + + fetchall_hashref + $hash_ref = $sth->fetchall_hashref( $key_field ); + + Returns a hashref containing all rows to be fetched from the statement + handle. See the DBI documentation for a full discussion. + + finish + $rv = $sth->finish; + + Indicates to DBI that you are finished with the statement handle and are + not going to use it again. Only needed when you have not fetched all the + possible rows. + + rows + $rv = $sth->rows; + + Returns the number of rows affected for updates, deletes and inserts and + -1 for selects. + + bind_col + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + + Binds a Perl variable and/or some attributes to an output column of a + SELECT statement. Column numbers count up from 1. You do not need to + bind output columns in order to fetch data. + + NOTE: DBD::Oracle does not use the $bind_type to determine how to bind + the column; it uses what Oracle says the data type is. You can however + set the StrictlyTyped/DiscardString attributes and these will take + effect as these attributes are applied after the column is retrieved. + + See the DBI documentation for a discussion of the optional parameters + "\%attr" and $bind_type + + bind_columns + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + + Calls the "bind_col" method for each column in the SELECT statement, + using the supplied list. + + dump_results + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + + Fetches all the rows from the statement handle, calls "DBI::neat_list" + for each row, and prints the results to $fh (which defaults to STDOUT). + Rows are separated by $lsep (which defaults to a newline). Columns are + separated by $fsep (which defaults to a comma). The $maxlen controls how + wide the output can be, and defaults to 35. + + This method is designed as a handy utility for prototyping and testing + queries. Since it uses "neat_list" to format and edit the string for + reading by humans, it is not recommended for data transfer applications. + +STATEMENT HANDLE ATTRIBUTES + NUM_OF_FIELDS (integer, read-only) + Returns the number of columns returned by the current statement. A + number will only be returned for SELECT statements for INSERT, UPDATE, + and DELETE statements which contain a RETURNING clause. This method + returns undef if called before "execute()". + + NUM_OF_PARAMS (integer, read-only) + Returns the number of placeholders in the current statement. + + NAME (arrayref, read-only) + Returns an arrayref of column names for the current statement. This + method will only work for SELECT statements, for SHOW statements, and + for INSERT, UPDATE, and DELETE statements which contain a RETURNING + clause. This method returns undef if called before "execute()". + + NAME_lc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to lower case. + + NAME_uc (arrayref, read-only) + The same as the "NAME" attribute, except that all column names are + forced to upper case. + + NAME_hash (hashref, read-only) + Similar to the "NAME" attribute, but returns a hashref of column names + instead of an arrayref. The names of the columns are the keys of the + hash, and the values represent the order in which the columns are + returned, starting at 0. This method returns undef if called before + "execute()". + + NAME_lc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + NAME_uc_hash (hashref, read-only) + The same as the "NAME_hash" attribute, except that all column names are + forced to lower case. + + TYPE (arrayref, read-only) + Returns an arrayref indicating the data type for each column in the + statement. This method returns undef if called before "execute()". + + PRECISION (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the precision for "NUMERIC" columns, the + size in number of characters for "CHAR" and "VARCHAR" columns, and for + all other types of columns it returns the number of *bytes*. This method + returns undef if called before "execute()". + + SCALE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates the scale of the that column. The only + type that will return a value is "NUMERIC". This method returns undef if + called before "execute()". + + NULLABLE (arrayref, read-only) + Returns an arrayref of integer values for each column returned by the + statement. The number indicates if the column is nullable or not. 0 = + not nullable, 1 = nullable, 2 = unknown. This method returns undef if + called before "execute()". + + Database (dbh, read-only) + Returns the database handle this statement handle was created from. + + ParamValues (hash ref, read-only) + Returns a reference to a hash containing the values currently bound to + placeholders. If the "named parameters" type of placeholders are being + used (such as ":foo"), then the keys of the hash will be the names of + the placeholders (without the colon). If the "dollar sign numbers" type + of placeholders are being used, the keys of the hash will be the + numbers, without the dollar signs. If the "question mark" type is used, + integer numbers will be returned, starting at one and increasing for + every placeholder. + + If this method is called before "execute", the literal values passed in + are returned. If called after "execute", then the quoted versions of the + values are returned. + + ParamTypes (hash ref, read-only) + Returns a reference to a hash containing the type names currently bound + to placeholders. The keys are the same as returned by the ParamValues + method. The values are hashrefs containing a single key value pair, in + which the key is either 'TYPE' if the type has a generic SQL equivalent, + and 'pg_type' if the type can only be expressed by a Postgres type. The + value is the internal number corresponding to the type originally passed + in. (Placeholders that have not yet been bound will return undef as the + value). This allows the output of ParamTypes to be passed back to the + "bind_param" method. + + Statement (string, read-only) + Returns the statement string passed to the most recent "prepare" method + called in this database handle, even if that method failed. This is + especially useful where "RaiseError" is enabled and the exception + handler checks $@ and sees that a "prepare" method call failed. + + RowsInCache + Returns the number of un-fetched rows in the cache for selects. + +SCROLLABLE CURSORS + Oracle supports the concept of a 'Scrollable Cursor' which is defined as + a 'Result Set' where the rows can be fetched either sequentially or + non-sequentially. One can fetch rows forward, backwards, from any given + position or the n-th row from the current position in the result set. + + Rows are numbered sequentially starting at one and client-side caching + of the partial or entire result set can improve performance by limiting + round trips to the server. + + Oracle does not support DML type operations with scrollable cursors so + you are limited to simple 'Select' operations only. As well you can not + use this functionality with remote mapped queries or if the LONG + datatype is part of the select list. + + However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, + and fetch methods. + + Only use scrollable cursors if you really have a good reason to. They do + use up considerable more server and client resources and have poorer + response times than non-scrolling cursors. + + Enabling Scrollable Cursors + To enable this functionality you must first import the 'Fetch + Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + + Next you will have to tell DBD::Oracle that you will be using scrolling + by setting the ora_exe_mode attribute on the statement handle to + 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + + When the statement is executed you will then be able to use + 'ora_fetch_scroll' method to get a row or you can still use any of the + other fetch methods but with a poorer response time than if you used a + non-scrolling cursor. As well scrollable cursors are compatible with any + applicable bind methods. + + Scrollable Cursor Methods + The following driver-specific methods are used with scrollable cursors. + + ora_scroll_position + $position = $sth->ora_scroll_position(); + + This method returns the current position (row number) attribute of + the result set. Prior to the first fetch this value is 0. This is + the only time this value will be 0 after the first fetch the value + will be set, so you can use this value to test if any rows have been + fetched. The minimum value will always be 1 after the first fetch. + The maximum value will always be the total number of rows in the + record set. + + ora_fetch_scroll + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + + Works the same as "fetchrow_arrayref", excepts one passes in a + 'Fetch Orientation' constant and a fetch_offset value which will + then determine the row that will be fetched. It returns the row as a + list containing the field values. Null fields are returned as + *undef* values in the list. + + The valid orientation constant and fetch offset values combination + are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + + The effect that a ora_fetch_scroll method call has on the + current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + + The effects of the differing orientation constants on the first + fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + + Scrollable Cursor Usage + Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + + and one assumes that the number of rows returned from the query is 20, + the code snippets below will illustrate the use of ora_fetch_scroll + method; + + Fetching the Last Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute to will be 20 after this snippet. This + is also a way to get the number of rows in the record set, however, + if the record set is large this could take some time. + + Fetching the Current Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will still be 20 after this snippet. + + Fetching the First Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the Next Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 5 after this snippet. + + Fetching the Prior Row + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 1 after this snippet. + + Fetching the 10th Row + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 10th to 14th Row + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 14 after this snippet. + + Fetching the 14th to 10th Row + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 10 after this snippet. + + Fetching the 5th Row From the Present Position. + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 15 after this snippet. + + Fetching the 9th Row Prior From the Present Position + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + + The current_positon attribute will be 6 after this snippet. + + Use Finish + $sth->finish(); + + When using scrollable cursors it is required that you use the + $sth->finish() method when you are done with the cursor as this type + of cursor has to be explicitly cancelled on the server. If you do + not do this you may cause resource problems on your database. + +LOBS AND LONGS + The key to working with LOBs (CLOB, BLOBs) is to remember the value of + an Oracle LOB column is not the content of the LOB. It's a 'LOB Locator' + which, after being selected or inserted needs extra processing to read + or write the content of the LOB. There are also legacy LONG types (LONG, + LONG RAW, VARCHAR2) which are presently deprecated by Oracle but are + still in use. These LONG types do not utilize a 'LOB Locator' and also + are more limited in functionality than CLOB or BLOB fields. + + DBD::Oracle now offers three interfaces to LOB and LONG data, + + "Data Interface for Persistent LOBs" + With this interface DBD::Oracle handles your data directly utilizing + regular OCI calls, Oracle itself takes care of the LOB Locator + operations in the case of BLOBs and CLOBs treating them exactly as + if they were the same as the legacy LONG or LONG RAW types. + + "Data Interface for LOB Locators" + With this interface DBD::Oracle handles your data utilizing LOB + Locator OCI calls so it only works with CLOB and BLOB datatypes. + With this interface DBD::Oracle takes care of the LOB Locator + operations for you. + + "LOB Locator Method Interface" + This allows the user direct access to the LOB Locator methods, so + you have to take case of the LOB Locator operations yourself. + + Generally speaking the interface that you will chose will be dependent + on what end you are trying to achieve. All have their benefits and + drawbacks. + + One point to remember when working with LOBs (CLOBs, BLOBs) is if your + LOB column can be in one of three states; + + NULL + The table cell is created, but the cell holds no locator or value. + If your LOB field is in this state then there is no LOB Locator that + DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + + error when working with a LOB. + + You can correct this by using an SQL UPDATE statement to reset the + LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB + or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + + Empty + A LOB instance with a locator exists in the cell, but it has no + value. The length of the LOB is zero. In this case DBD::Oracle will + return 'undef' for the field. + + Populated + A LOB instance with a locator and a value exists in the cell. You + actually get the LOB value. + + Data Interface for Persistent LOBs + This is the original interface for LONG and LONG RAW datatypes and from + Oracle 9iR1 and later the OCI API was extended to work directly with the + other LOB datatypes. In other words you can treat all LOB type data + (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can + perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using + the same techniques you would use on other datatypes that store + character or binary data. In some cases there are fewer round trips to + the server as no 'LOB Locators' are used, normally one can get an entire + LOB is a single round trip. + + Simple Fetch for LONGs and LONG RAWs + As the name implies this is the simplest way to use this interface. + DBD::Oracle just attempts to get your LONG datatypes as a single large + piece. There are no special settings, simply set the database handle's + 'LongReadLen' attribute to a value that will be the larger than the + expected size of the LONG or LONG RAW. If the size of the LONG or LONG + RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A + Truncation' error. To stop this set the database handle's 'LongTruncOk' + attribute to '1'. The maximum value of 'LongReadLen' seems to be + dependent on the physical memory limits of the box that Oracle is + running on. You have most likely reached this limit if you run into an + 'ORA-01062: unable to allocate memory for define buffer' error. One + solution is to set the size of 'LongReadLen' to a lower value. + + For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select out all of the long1 fields in the table as long as they are + all under 2MB in length. A value in long1 longer than this will throw an + error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the long1 fields but they will be + truncated at 2MBs. + + Using ora_ncs_buff_mtpl + When getting CLOBs and NCLOBs in or out of Oracle, the Server will + translate from the Server's NCharSet to the Client's. If they happen to + be the same or at least compatible then all of these actions are a 1 + char to 1 char bases. Thus if you set your LongReadLen buffer to + 10_000_000 you will get up to 10_000_000 char. + + However if the Server has to translate from one NCharSet to another it + will use bytes for conversion. The buffer value is set to 4 * + LONG_READ_LEN which was very wasteful as you might only be asking for + 10_000_000 bytes but you were actually using 40_000_000 bytes of buffer + under the hood. You would still get 10_000_000 bytes (maybe less + characters though) but you are using allot more memory that you need. + + You can now customize the size of the buffer by setting the + 'ora_ncs_buff_mtpl' either on the connection or statement handle. You + can also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you + will have to go back and change all your code if you are getting into + trouble. + + The default value is still set to 4 for backward compatibility. You can + lower this value and thus increase the amount of data you can retrieve. + If the ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error + telling you to increase this buffer by one. + + If the error is not captured then you may get at some random point later + on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + + This is one of the more obscure ORA errors (have some fun and report it + to Meta-Link they will scratch their heads for hours) + + If you get this, simply increment the ora_ncs_buff_mtpl by one until it + goes away. + + This should greatly increase your ability to select very large CLOBs or + NCLOBs, by freeing up a large block of memory. + + You can tune this value by setting ora_oci_success_warn which will + display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + + In the case above the query Got 28 characters (well really only 20 + characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) + thus saving 40bytes of memory. + + Simple Fetch for CLOBs and BLOBs + To use this interface for CLOBs and LOBs datatypes set the + 'ora_pers_lob' attribute of the statement handle to '1' with the prepare + method, as well set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. If the + size of the LOB exceeds the 'LongReadLen' DBD::Oracle will return a + 'ORA-24345: A Truncation' error. To stop this set the database handle's + 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems + to be dependent on the physical memory limits of the box that Oracle is + running on in the same way that LONGs and LONG RAWs are. + + For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, + this is an internal OCI limit complain to them if you want it changed. + However if you CLOB is longer than this and also larger than the + 'LongReadLen' than the 'LongReadLen' in chars is returned. + + It seems with BLOBs you are not limited by the 64k. + + For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + + this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + + before the execute will return all the lobs but they will be truncated + at 2MBs. + + Piecewise Fetch with Callback + With a piecewise callback fetch DBD::Oracle sets up a function that will + 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, + CLOB, BLOB) piece by piece. To use this interface set the 'ora_clbk_lob' + attribute of the statement handle to '1' with the prepare method. Next + set the 'ora_piece_size' to the size of the piece that you want to + return on the callback. Finally set the database handle's 'LongReadLen' + attribute to a value that will be the larger than the expected size of + the LOB. Like the "Simple Fetch for LONGs and LONG RAWs" and "Simple + Fetch for CLOBs and BLOBs" the if the size of the LOB exceeds the is + 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the + LOB or set the 'LongReadLen' to a higher value. With this interface the + value of 'ora_piece_size' seems to be constrained by the same memory + limit as found on the Simple Fetch interface. If you encounter an + 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller + value. The value for 'LongReadLen' is dependent on the version and + settings of the Oracle DB you are using. In theory it ranges from 8GBs + in 9iR1 up to 128 terabytes with 11g but you will also be limited by the + physical memory of your PERL instance. + + Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will + throw an error. + + Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 filed is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Piecewise Fetch with Polling + With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB + during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by + piece. To use this interface set the 'ora_piece_lob' attribute of the + statement handle to '1' with the prepare method. Next set the + 'ora_piece_size' to the size of the piece that you want to return on the + callback. Finally set the database handle's 'LongReadLen' attribute to a + value that will be the larger than the expected size of the LOB. Like + the "Piecewise Fetch with Callback" and Simple Fetches if the size of + the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' + attribute to truncate the LOB or set the 'LongReadLen' to a higher + value. With this interface the value of 'ora_piece_size' seems to be + constrained by the same memory limit as found on the "Piecewise Fetch + with Callback". + + Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Will select out all of the LOBs in the table as long as they are all + under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) + DBD::Oracle will fetch it in at least 2 pieces to a maximum of 4 pieces + (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will + throw an error. + + Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + + Will select all of the long1 fields from table as long as they are is + under 20MB in length. If the long1 field is longer than 5MB + (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a + maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields + longer than 20MB will throw an error. + + Binding for Updates and Inserts for CLOBs and BLOBs + To bind for updates and inserts all that is required to use this + interface is to set the statement handle's prepare method 'ora_type' + attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in + the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + + So far the only limit reached with this form of insert is the LOBs must + be under 2GB in size. + + Support for Remote LOBs; + Starting with Oracle 10gR2 the interface for Persistent LOBs was + expanded to support remote LOBs (access over a dblink). Given a database + called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + + to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + + Below are the limitations of Remote LOBs; + + Queries involving more than one database are not supported; + so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + + as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + + DDL commands are not supported; + so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + + Only binds and defines for data going into remote persistent LOBs are + supported. + so that parameter passing in PL/SQL where CHAR data is bound or + defined for remote LOBs is not allowed . + + These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + + If the remote object is a view such as + CREATE VIEW v AS SELECT foo() FROM ... + + the following would not work: + + SELECT * FROM v@dbs2; + + Limited PL/SQL parameter passing + PL/SQL parameter passing is not allowed where the actual argument is + a LOB type and the remote argument is one of VARCHAR2, NVARCHAR2, + CHAR, NCHAR, or RAW. + + RETURNING INTO does not support implicit conversions between CHAR and + CLOB. + so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + + Locator Data Interface + Simple Usage + When fetching LOBs with this interface a 'LOB Locator' is created then + used to get the lob with the LongReadLen and LongTruncOk attributes. The + value for 'LongReadLen' is dependent on the version and settings of the + Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 + terabytes with 11g but you will also be limited by the physical memory + of your PERL instance. + + When inserting or updating LOBs some *major* magic has to be performed + behind the scenes to make it transparent. Basically the driver has to + insert a 'LOB Locator' and then refetch the newly inserted LOB Locator + before being able to write the data into it. However, it works well most + of the time, and I've made it as fast as possible, just one extra + server-round-trip per insert or update after the first. For the time + being, only single-row LOB updates are supported. + + To insert or update a large LOB using a placeholder, DBD::Oracle has to + know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + + The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + + or use the corresponding integer values (112 and 113). + + One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has to + be able to tell which parameters relate to which table fields. In all + cases where it can possibly work it out for itself, it does, however, if + there are multiple LOB fields of the same type in the table then you + need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + + There are some limitations inherent in the way DBD::Oracle makes typical + LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + + The alternative is to disable the automatic LOB Locator processing. If + "ora_auto_lob" is 0 in prepare(), you can fetch the LOB Locators and do + all the work yourself using the ora_lob_*() methods. See the "Data + Interface for LOB Locators" section below. + + LOB support in PL/SQL + LOB Locators can be passed to PL/SQL calls by binding them to + placeholders with the proper "ora_type". If "ora_auto_lob" is true, + output LOB parameters will be automatically returned as strings. + + If the Oracle driver has support for temporary LOBs (Oracle 9i and + higher), strings can be bound to input LOB placeholders and will be + automatically converted to LOBs. + + Example: # Build a large XML document, bind it as a CLOB, # extract + elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + + If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + + error, while attempting to insert a LOB, this means the Oracle user has + insufficient space for LOB you are trying to insert. One solution it to + use "alter database datafile 'sss.ggg' resize Mnnn" to increase the + available memory for LOBs. + + Persistent & Locator Interface Caveats + Now that one has the option of using the Persistent or the Locator + interface for LOBs the questions arises which one to use. For starters, + if you want to access LOBs over a dblink you will have to use the + Persistent interface so that choice is simple. The question of which one + to use after that is a little more tricky. It basically boils down to a + choice between LOB size and speed. + + The Callback and Polling piecewise fetches are very very slow when + compared to the Simple and the Locator fetches but they can handle very + large blocks of data. Given a situation where a large LOB is to be read + the Locator fetch may time out while either of the piecewise fetches may + not. + + With the Simple fetch you are limited by physical memory of your server + but it runs a little faster than the Locator, as there are fewer round + trips to the server. So if you have small LOBs and need to save a little + bandwidth this is the one to use. It you are going after large LOBs then + the Locator interface is the one to use. + + If you need to update more than a single row of with LOB data then the + Persistent interface can do it while the Locator can't. + + If you encounter a situation where you have to access the legacy LOBs + (LONG, LONG RAW) and the values are to large for you system then you can + use the Callback or Polling piecewise fetches to get all of the data. + + Not all of the Persistent interface has been implemented yet, the + following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + + Most of the time you should just use the "Locator Data Interface" as + this is in one that has the best combination of speed and size. + + All this being said if you are doing some critical programming I would + use the "Data Interface for LOB Locators" as this gives you very fine + grain control of your LOBs, of course the code for this will be somewhat + more involved. + + Data Interface for LOB Locators + The following driver-specific methods let you manipulate "LOB Locators" + directly. To select a LOB locator directly set the if the "ora_auto_lob" + attribute to false, or alternatively they can be returned via PL/SQL + procedure calls. + + (If using a DBI version earlier than 1.36 they must be called via the + func() method. Note that methods called via func() don't honour + RaiseError etc, and so it's important to check $dbh->err after each + call. It's recommended that you upgrade to DBI 1.38 or later.) + + Note that LOB locators are only valid while the statement handle that + created them is valid. When all references to the original statement + handle are lost, the handle is destroyed and the locators are freed. + + ora_lob_read + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + + Read a portion of the LOB. $offset starts at 1. Uses the Oracle + OCILobRead function. + + ora_lob_write + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + + Write/overwrite a portion of the LOB. $offset starts at 1. Uses the + Oracle OCILobWrite function. + + ora_lob_append + $rc = $dbh->ora_lob_append($lob_locator, $data); + + Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + + ora_lob_trim + $rc = $dbh->ora_lob_trim($lob_locator, $length); + + Trims the length of the LOB to $length. Uses the Oracle OCILobTrim + function. + + ora_lob_length + $length = $dbh->ora_lob_length($lob_locator); + + Returns the length of the LOB. Uses the Oracle OCILobGetLength + function. + + ora_lob_is_init + $is_init = $dbh->ora_lob_is_init($lob_locator); + + Returns true(1) if the Lob Locator is initialized false(0) if it is + not, or 'undef' if there is an error. Uses the Oracle + OCILobLocatorIsInit function. + + ora_lob_chunk_size + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + + Returns the chunk size of the LOB. Uses the Oracle + OCILobGetChunkSize function. + + For optimal performance, Oracle recommends reading from and writing + to a LOB in batches using a multiple of the LOB chunk size. In + Oracle 10g and before, when all defaults are in place, this chunk + size defaults to 8k (8192). + + LOB Locator Method Examples + *Note:* Make sure you first read the note in the section above about + multi-byte character set issues with these methods. + + The following examples demonstrate the usage of LOB Locators to read, + write, and append data, and to query the size of large data. + + The following examples assume a table containing two large object + columns, one binary and one character, with a primary key column, + defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + + It also assumes a sequence for use in generating unique lob_id field + values, defined as follows: + + CREATE SEQUENCE lob_example_seq + + Example: Inserting a new row with large data + Unless enough memory is available to store and bind the entire LOB data + for insert all at once, the LOB columns must be written interactively, + piece by piece. In the case of a new row, this is performed by first + inserting a row, with empty values in the LOB columns, then modifying + the row by writing the large data interactively to the LOB columns using + their LOB locators as handles. + + The insert statement must create token values in the LOB columns. Here, + we use the empty string for both the binary and character large object + columns 'bindata' and 'chardata'. + + After the INSERT statement, a SELECT statement is used to acquire LOB + locators to the 'bindata' and 'chardata' fields of the newly inserted + row. Because these LOB locators are subsequently written, they must be + acquired from a select statement containing the clause 'FOR UPDATE' (LOB + locators are only valid within the transaction that fetched them, so + can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + + In this example we demonstrate the use of ora_lob_write() interactively + to append data to the columns 'bin_data' and 'char_data'. Had we used + ora_lob_append(), we could have saved ourselves the trouble of keeping + track of the offset into the lobs. The snippet of code beneath the + comment 'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + + The scalar variables $offset and $length are no longer needed, because + ora_lob_append() keeps track of the offset for us. + + Example: Updating an existing row with large data + In this example, we demonstrate a technique for overwriting a portion of + a blob field with new binary data. The blob data before and after the + section overwritten remains unchanged. Hence, this technique could be + used for updating fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + + After running this code, the row where lob_id = 5 will contain, starting + at position 100234 in the bin_data column, the string "This string will + overwrite a portion of the blob". + + Example: Streaming character data from the database + In this example, we demonstrate a technique for streaming data from the + database to a file handle, in this case STDOUT. This allows more data to + be read in and written out than could be stored in memory at a given + time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + + Notice that the select statement does not contain the phrase "FOR + UPDATE". Because we are only reading from the LOB Locator returned, and + not modifying the LOB it refers to, the select statement does not + require the "FOR UPDATE" clause. + + A word of caution when using the data returned from an ora_lob_read in a + conditional statement. for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + + was used with a chunk size of 4096 against a blob that requires more + than 1 chunk to return the data and the last chunk is one byte long and + contains a zero (ASCII 48) you will miss this last byte as $data will + contain 0 which PERL will see as false and not print it out. + + Example: Truncating existing large data + In this example, we truncate the data already present in a large object + column in the database. Specifically, for each row in the table, we + truncate the 'bindata' value to half its previous length. + + After acquiring a LOB Locator for the column, we query its length, then + we trim the length by half. Because we modify the large objects with the + call to ora_lob_trim(), we must select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +SPACES AND PADDING + Trailing Spaces + Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder + values and uses Nonpadded Comparison Semantics with the result. This + causes trouble if the spaces are needed for comparison with a CHAR value + or to prevent the value from becoming '' which Oracle treats as NULL. + Look for Blank-padded Comparison Semantics and Nonpadded Comparison + Semantics in Oracle's SQL Reference or Server SQL Reference for more + details. + + To preserve trailing spaces in placeholder values for Oracle clients + that use OCI 8, either change the default placeholder type with + "ora_ph_type" or the placeholder type for a particular call to "bind" in + DBI or "bind_param_inout" in DBI with "ora_type" or "TYPE". Using + ORA_CHAR with ora_type or "SQL_CHAR" with "TYPE" allows the placeholder + to be used with Padded Comparison Semantics if the value it is being + compared to is a CHAR, NCHAR, or literal. + + Please remember that using spaces as a value or at the end of a value + makes visually distinguishing values with different numbers of spaces + difficult and should be avoided. + + Oracle Clients that use OCI 9.2 do not strip trailing spaces. + + Padded Char Fields + Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder + values to the size of the CHAR. As the default placeholder type value in + DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will have to + change the default placeholder type with "ora_ph_type" or placeholder + type for a particular call with "bind" in DBI or "bind_param_inout" in + DBI with "ORA_CHAR". + +UNICODE + DBD::Oracle now supports Unicode UTF-8. There are, however, a number of + issues you should be aware of, so please read all this section + carefully. + + In this section we'll discuss "Perl and Unicode", then "Oracle and + Unicode", and finally "DBD::Oracle and Unicode". + + Information about Unicode in general can be found at: + . It is well worth reading because there are + many misconceptions about Unicode and you may be holding some of them. + + Perl and Unicode + Perl began implementing Unicode with version 5.6, but the implementation + did not mature until version 5.8 and later. If you plan to use Unicode + you are *strongly* urged to use Perl 5.8.2 or later and to *carefully* + read the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + + And then read it again. + + Perl's internal Unicode format is UTF-8 which corresponds to the Oracle + character set called AL32UTF8. + + Oracle and Unicode + Oracle supports many characters sets, including several different forms + of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + + When you create an Oracle database, you must specify the DATABASE + character set (used for DDL, DML and CHAR datatypes) and the NATIONAL + character set (used for NCHAR and NCLOB types). The character sets used + in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + + The Oracle 9.2 and later default for the national character set is + AL16UTF16. The default for the database character set is often US7ASCII. + Although many experienced DBAs will consider an 8bit character set like + WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other + than US7ASCII, requires that the NLS_LANG environment variable be set. + See the "Oracle UTF8 is not UTF-8" section below. + + You are strongly urged to read the Oracle Internationalization + documentation specifically with respect the choices and trade offs for + creating a databases for use with international character sets. + + Oracle uses the NLS_LANG environment variable to indicate what character + set is being used on the client. When fetching data Oracle will convert + from whatever the database character set is to the client character set + specified by NLS_LANG. Similarly, when sending data to the database + Oracle will convert from the character set specified by NLS_LANG to the + database character set. + + The NLS_NCHAR environment variable can be used to define a different + character set for 'national' (NCHAR) character types. + + Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. For + example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + + Oracle UTF8 is not UTF-8 + AL32UTF8 should be used in preference to UTF8 if it works for you, which + it should for Oracle 9.2 or later. If you're using an old version of + Oracle that doesn't support AL32UTF8 then you should avoid using any + Unicode characters that require surrogates, in other words characters + beyond the Unicode BMP (Basic Multilingual Plane). + + That's because the character set that Oracle calls "UTF8" doesn't + conform to the UTF-8 standard in its handling of surrogate characters. + Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". + Here are a couple of extracts from + : + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + + Oracle uses this internally because it collates (sorts) in the same + order as UTF16, which is the basis of Oracle's internal collation + definitions. + + Rather than change UTF8 for clients Oracle chose to define a new + character set called "AL32UTF8" which does conform to the UTF-8 + standard. (The AL32UTF8 character set can't be used on the server + because it would break collation.) + + Because of that, for the rest of this document we'll use "AL32UTF8". If + you're using an Oracle version below 9.2 you'll need to use "UTF8" until + you upgrade. + + DBD::Oracle and Unicode + DBD::Oracle Unicode support has been implemented for Oracle versions 9 + or greater, and Perl version 5.6 or greater (though we *strongly* + suggest that you use Perl 5.8.2 or later). + + You can check which Oracle version your DBD::Oracle was built with by + importing the "ORA_OCI" constant from DBD::Oracle. + + Fetching Data + + Any data returned from Oracle to DBD::Oracle in the AL32UTF8 character + set will be marked as UTF-8 to ensure correct handling by Perl. + + For Oracle to return data in the AL32UTF8 character set the NLS_LANG or + NLS_NCHAR environment variable *must* be set as described in the + previous section. + + When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle + will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR is + AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + + When fetching other character data from Oracle, DBD::Oracle will set the + Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + + Sending Data using Placeholders + + Data bound to a placeholder is assumed to be in the default client + character set (specified by NLS_LANG) except for a few special cases. + These are listed here with the highest precedence first: + + If the "ora_csid" attribute is given to bind_param() then that is passed + to Oracle and takes precedence. + + If the value is a Perl Unicode string (UTF-8) then DBD::Oracle ensures + that Oracle uses the Unicode character set, regardless of the NLS_LANG + and NLS_NCHAR settings. + + If the placeholder is for inserting an NCLOB then the client NLS_NCHAR + character set is used. (That's useful but inconsistent with the other + behaviour so may change. Best to be explicit by using the "ora_csform" + attribute.) + + If the "ora_csform" attribute is given to bind_param() then that + determines if the value should be assumed to be in the default + (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + Binding with bind_param_array and execute_array is also UTF-8 compatible + in the same way. If you attempt to insert UTF-8 data into a non UTF-8 + Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert will + still happen but a error code of 0 will be returned with the following + warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + + The warning will report the parameter number and the NCHAR setting that + the query is running. + + Sending Data using SQL + + Oracle assumes the SQL statement is in the default client character set + (as specified by NLS_LANG). So Unicode strings containing non-ASCII + characters should not be used unless the default client character set is + AL32UTF8. + + DBD::Oracle and Other Character Sets and Encodings + The only multi-byte Oracle character set supported by DBD::Oracle is + "AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +OBJECT & COLLECTION DATA TYPES + Oracle databases allow for the creation of object oriented like + user-defined types. There are two types of objects, Embedded--an object + stored in a column of a regular table and REF--an object that uses the + REF retrieval mechanism. + + DBD::Oracle supports only the 'selection' of embedded objects of the + following types OBJECT, VARRAY and TABLE in any combination. Support is + seamless and recursive, meaning you need only supply a simple SQL + statement to get all the values in an embedded object. You can either + get the values as an array of scalars or they can be returned into a + DBD::Oracle::Object. + + Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + + The code to access all the data in the table could be something like + this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + + Note that values in PHONE_NUMBERS are returned as an array reference + '@$phone'. + + As stated before DBD::Oracle will automatically drill into the embedded + object and extract all of the data as reference arrays of scalars. The + example below has OBJECT type embedded in a TABLE type embedded in an + SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + + The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + + Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + + The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + + So far DBD::Oracle has been tested on a table with 20 embedded Objects, + Varrays and Tables nested to 10 levels. + + Any NULL values found in the embedded object will be returned as + 'undef'. + +OTHER DATA TYPES + DBD::Oracle does not *explicitly* support most Oracle datatypes. It + simply asks Oracle to return them as strings and Oracle does so. Mostly. + Similarly when binding placeholder values DBD::Oracle binds them as + strings and Oracle converts them to the appropriate type, such as DATE, + when used. + + Some of these automatic conversions to and from strings use NLS settings + to control the formatting for output and the parsing for input. The most + common example is the DATE type. The default NLS format for DATE might + be DD-MON-YYYY and so when a DATE type is fetched that's how Oracle will + format the date. NLS settings also control the default parsing of + strings into DATE values. An error will be generated if the contents of + the string don't match the NLS format. If you're dealing in dates which + don't match the default NLS format then you can either change the + default NLS format or, more commonly, use TO_CHAR(field, "format") and + TO_DATE(?, "format") to explicitly specify formats for converting to and + from strings. + + A slightly more subtle problem can occur with NUMBER types. The default + NLS settings might format numbers with a fullstop (""."") to separate + thousands and a comma ("","") as the decimal point. Perl will generate + warnings and use incorrect values when numbers, returned and formatted + as strings in this way by Oracle, are used in a numeric context. You + could explicitly convert each numeric value using the TO_CHAR(...) + function but that gets tedious very quickly. The best fix is to change + the NLS settings. That can be done for an individual connection by + doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + + There are some types, like BOOLEAN, that Oracle does not automatically + convert to or from strings (pity). These need to be converted explicitly + using SQL or PL/SQL functions. + + Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + + Support for Insert of XMLType (ORA_XMLTYPE) + Inserting large XML data sets into tables with XMLType fields is now + supported by DBD::Oracle. The only special requirement is the use of + bind_param() with an attribute hash parameter that specifies ora_type as + ORA_XMLTYPE. For example with a table like this; + + create table books (book_id number, book_xml XMLType); + + one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + + In the above case we will assume that $xml has 10000 Book nodes and is + over 32k in size and is well formed XML. This will also work for XML + that is smaller than 32k as well. Attempting to insert malformed XML + will cause an error. + + Binding Cursors + Cursors can be returned from PL/SQL blocks, either from stored functions + (or procedures with OUT parameters) or from direct "OPEN" statements, as + shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + The only special requirement is the use of "bind_param_inout()" with an + attribute hash parameter that specifies "ora_type" as "ORA_RSET". If you + don't do that you'll get an error from the "execute()" like: "ORA-06550: + line X, column Y: PLS-00306: wrong number or types of arguments in call + to ...". + + Here's an alternative form using a function that returns a cursor. This + example uses the pre-defined weak (or generic) REF CURSOR type + SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + + A cursor obtained from PL/SQL as above may be passed back to PL/SQL by + binding for input, as shown in this example, which explicitly closes a + cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + + It is not normally necessary to close a cursor explicitly in this way. + Oracle will close the cursor automatically at the first client-server + interaction after the cursor statement handle is destroyed. An explicit + close may be desirable if the reference to the cursor handle from the + PL/SQL statement handle delays the destruction of the cursor handle for + too long. This reference remains until the PL/SQL handle is re-bound, + re-executed or destroyed. + + See the "curref.pl" script in the Oracle.ex directory in the DBD::Oracle + source distribution for a complete working example. + + Fetching Nested Cursors + Oracle supports the use of select list expressions of type REF CURSOR. + These may be explicit cursor expressions - "CURSOR(SELECT ...)", or + calls to PL/SQL functions which return REF CURSOR values. The values of + these expressions are known as nested cursors. + + The value returned to a Perl program when a nested cursor is fetched is + a statement handle. This statement handle is ready to be fetched from. + It should not (indeed, must not) be executed. + + Oracle imposes a restriction on the order of fetching when nested + cursors are used. Suppose $sth1 is a handle for a select statement + involving nested cursors, and $sth2 is a nested cursor handle fetched + from $sth1. $sth2 can only be fetched from while $sth1 is still active, + and the row containing $sth2 is still current in $sth1. Any attempt to + fetch another row from $sth1 renders all nested cursor handles + previously fetched from $sth1 defunct. + + Fetching from such a defunct handle results in an error with the message + "ERROR nested cursor is defunct (parent row is no longer current)". + + This means that the "fetchall..." or "selectall..." methods are not + useful for queries returning nested cursors. By the time such a method + returns, all the nested cursor handles it has fetched will be defunct. + + It is necessary to use an explicit fetch loop, and to do all the + fetching of nested cursors within the loop, as the following example + shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + + The cursor returned by the function "sp_ListEmp" defined in the previous + section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + + Pre-fetching Nested Cursors + By default, DBD::Oracle pre-fetches rows in order to reduce the number + of round trips to the server. For queries which do not involve nested + cursors, the number of pre-fetched rows is controlled by the DBI + database handle attribute "RowCacheSize" (q.v.). + + In Oracle, server side open cursors are a controlled resource, limited + in number, on a per session basis, to the value of the initialization + parameter "OPEN_CURSORS". Nested cursors count towards this limit. Each + nested cursor in the current row counts 1, as does each nested cursor in + a pre-fetched row. Defunct nested cursors do not count. + + An Oracle specific database handle attribute, "ora_max_nested_cursors", + further controls pre-fetching for queries involving nested cursors. For + each statement handle, the total number of nested cursors in pre-fetched + rows is limited to the value of this parameter. The default value is 0, + which disables pre-fetching for queries involving nested cursors. + +PL/SQL Examples + Most of these PL/SQL examples come from: Eric Bartley + . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + + You can find more examples in the t/plsql.t file in the DBD::Oracle + source directory. + + Oracle 9.2 appears to have a bug where a variable bound with + bind_param_inout() that isn't assigned to by the executed PL/SQL block + may contain garbage. See + + + Avoid Using "SQL Call" + Avoid using the "SQL Call" statement with DBD:Oracle as you might find + that DBD::Oracle will not raise an exception in some case. Specifically + if you use "SQL Call" to run a procedure all "No data found" exceptions + will be quietly ignored and returned as null. According to Oracle + support this is part of the same mechanism where; + + select (select * from dual where 0=1) from dual + + returns a null value rather than an exception. + +CONTRIBUTING + If you'd like DBD::Oracle to do something new or different the best way + to make that happen is to do it yourself and email to dbi-dev@perl.org a + patch of the source code (using 'diff' - see below) that shows the + changes. + + How to create a patch using Subversion + The DBD::Oracle source code is maintained using Subversion (a + replacement for CVS, see ). To access the + source you'll need to install a Subversion client. Then, to get the + source code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + + If it prompts for a username and password use your perl.org account if + you have one, else just 'guest' and 'guest'. The source code will be in + a new subdirectory called "trunk". + + To keep informed about changes to the source you can send an empty email + to dbd-oracle-changes-subscribe@perl.org after which you'll get an email + with the change log message and diff of each change checked-in to the + source. + + After making your changes you can generate a patch file, but before you + do, make sure your source is still upto date using: + + svn update + + If you get any conflicts reported you'll need to fix them first. Then + generate the patch file from within the "trunk" directory using: + + svn diff > foo.patch + + Read the patch file, as a sanity check, and then email it to + dbi-dev@perl.org. + + How to create a patch without Subversion + Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + + Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + + Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you + want. + + Test your changes and then remove all temporary files: + + make test && make distclean + + Go back to the directory you originally unpacked the distribution: + + cd .. + + Unpack *another* copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + + Then create a patch file by performing a recursive "diff" on the two top + level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + + Speak before you patch + For anything non-trivial or possibly controversial it's a good idea to + discuss (on dbi-dev@perl.org) the changes you propose before actually + spending time working on them. Otherwise you run the risk of them being + rejected because they don't fit into some larger plans you may not be + aware of. + + GitHub repository + A git mirror of the subversion is also available at + `https://github.com/yanick/DBD-Oracle`. + +Oracle Related Links +WHICH VERSION OF DBD::ORACLE IS FOR ME? + From version 1.25 onwards DBD::Oracle only support Oracle clients 9.2 or + greater. Support for ProC connections was dropped in 1.29. + + If you are still stuck with an older version of Oracle or its client you + might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + + As there are dozens of different versions of Oracle's clients this list + does not include all of them, just the major released versions of + Oracle. + + Note that one can still connect to any Oracle version with the older + DBD::Oracle versions the only problem you will have is that some of the + newer OCI and Oracle features available in later DBD::Oracle releases + will not be available to you. + + So to make a short story a little longer: + + 1 If you are using Oracle 7 or early 8 DB and you can manage to get a + 9 client and you can use any DBD::Oracle version. + + 2 If you have to use an Oracle 7 client then DBD::Oracle 1.17 should + work + + 3 Same thing for 8 up to R2, use 1.17, if you are lucky and have the + right patch-set you might go with 1.18. + + 4 For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. + Again this depends on your patch-set, If you run into trouble go + with 1.19 + + 5 After 9.2 you can use any version you want. + + 6 It seems that the 10g client can only connect to 9 and 11 DBs while + the 9 can go back to 7 and even get to 10. I am not sure what the + 11g client can connect to. + +BUGS AND LIMITATIONS + There is a known problem with the 11.2g Oracle client and the + "DBMS_LOB.GETLENGTH()" PL/SQL function. See + for the details. + +SEE ALSO + DBI http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in + the DBD::Oracle source distribution including the examples in the + Oracle.ex directory + + DBD::Oracle Tutorial + http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-ora + cle.html + + Oracle Instant Client + http://www.oracle.com/technology/tech/oci/instantclient/index.html + + Oracle on Linux + http://www.ixora.com.au/ + + Free Oracle Tools and Links + ora_explain supplied and installed with DBD::Oracle. + + http://www.orafaq.com/ + + http://vonnieda.org/oracletool/ + + Commercial Oracle Tools and Links + Assorted tools and references for general information. No + recommendation implied. + + http://www.platinum.com + + http://www.SoftTreeTech.com + + Also PL/Vision from RevealNet and Steven Feuerstein, and "Q" from + Savant Corporation. + +AUTHORS + DBI by Tim Bunce . + + The original "DBD::Oracle" was by Tim Bunce. Maintained as of release + 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the + auspice of the Pythian Group (). + +ACKNOWLEDGEMENTS + A great many people have helped with DBD::Oracle over the 17 years + between 1994 and 2011. Far too many to name, but we thank them all. Many + are named in the Changes file. + +COPYRIGHT + The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. + The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The + Pythian Group). Canada. The DBD::Oracle module is Copyright (c) 2011 + John Scoles. Canada. + + The DBD::Oracle module is free open source software; you can + redistribute it and/or modify it under the same terms as Perl 5. + +AUTHORS + * Tim Bunce + + * John Scoles + + * Yanick Champoux + +COPYRIGHT AND LICENSE + This software is copyright (c) 1994 by Tim Bunce. + + This is free software; you can redistribute it and/or modify it under + the same terms as the Perl 5 programming language system itself. diff --git a/README.mkdn b/README.mkdn new file mode 100644 index 00000000..6faa9aac --- /dev/null +++ b/README.mkdn @@ -0,0 +1,4252 @@ +# NAME + +DBD::Oracle - Oracle database driver for the DBI module + +# VERSION + +version 1.43_00 + +# SYNOPSIS + + use DBI; + + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); + + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); + + # See the DBI module documentation for full details + + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); + +# DESCRIPTION + +DBD::Oracle is a Perl module which works with the DBI module to provide +access to Oracle databases. + +This documentation describes driver specific behaviour and restrictions. It is +not supposed to be used as the only reference for the user. In any case +consult the [DBI](http://search.cpan.org/perldoc?DBI) documentation first! + +# CONSTANTS + +- :ora_session_modes + +ORA_SYSDBA ORA_SYSOPER ORA_SYSASM + +- :ora_types + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +- SQLCS_IMPLICIT + +- SQLCS_NCHAR + +SQLCS_IMPLICIT and SQLCS_NCHAR are _character set form_ values. +See notes about Unicode elsewhere in this document. + +- SQLT_INT + +- SQLT_FLT + +These types are used only internally, and may be specified as internal +bind type for ORA_NUMBER_TABLE. See notes about ORA_NUMBER_TABLE elsewhere +in this document + +- ORA_OCI + +Oracle doesn't provide a formal API for determining the exact version +number of the OCI client library used, so DBD::Oracle has to go digging +(and sometimes has to more or less guess). The ORA_OCI constant +holds the result of that process. + +In string context ORA_OCI returns the full "A.B.C.D" version string. + +In numeric context ORA_OCI returns the major.minor version number +(8.1, 9.2, 10.0 etc). But note that version numbers are not actually +floating point and so if Oracle ever makes a release that has a two +digit minor version, such as `9.10` it will have a lower numeric +value than the preceding `9.9` release. So use with care. + +The contents and format of ORA_OCI are subject to change (it may, +for example, become a _version object_ in later releases). +I recommend that you avoid checking for exact values. + +- :ora_fetch_orient + + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE + +These constants are used to set the orientation of a fetch on a scrollable cursor. + +- :ora_exe_modes + + OCI_STMT_SCROLLABLE_READONLY + +- :ora_fail_over + + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + +# DBI CLASS METHODS + +## __connect__ + +This method creates a database handle by connecting to a database, and is the DBI equivalent of the "new" method. +To open a connection to an Oracle database you need to specify a database connection string (URL), username and password. + +The connection string is always of the form: "dbi:Oracle:" +There are several ways to identify a database: + +- 1 + +If the database is local, specifying the SID or service name will be enough. + +- 2 + +If the database is defined in a TNSNAMES.ORA file, you can use the service name given in the file + +- 3 + +To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: +//host[:port][/service_name] + +If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. + +The following examples show several ways a connection can be created: + + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); + + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); + + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); + + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); + +### OS authentication + +To connect to a local database with a user which has been set up to +authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): + + $dbh = DBI->connect('dbi:Oracle:','/',''); + +Note the lack of a connection name (use the ORACLE_SID environment +variable). If an explicit SID is used you will probably get an ORA-01004 error. + +That only works for local databases. (Authentication to remote Oracle +databases using your Unix login name without a password is possible +but it is not secure and not recommended so not documented here. + +### Oracle Environment Variables + +To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. +In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). + +Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. + +To use them, specify either a local SID or service name, or a service name that is specified in the TNSNAMES.ORA file. + +Note that if you have *both* local and remote databases, and you have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO_TASK takes precedence over ORACLE_SID (i.e. you get connected to remote system). + +It is highly recommended not to rely on environment variables and to always explicitly specify the SID in the connection string. This can prevent serious mistakes such as dropping a schema in the wrong database, and generally makes debugging and troubleshooting easier. + +Also remember that depending on the operating system you are using the differing "ORACLE" environment variables may be case sensitive, so if you are not connecting as you should double check the case of both the variable and its value. + +### Timezones + +If the query is run through SQL*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. + +If the query is run locally, Oracle will return the time zone based on the "TZ" environment variable setting of the user running +the query. + +With local queries, you can change the time zone for a particular user by simply changing the setting of "TZ". To check the current setting, +issue the UNIX "date" command. + +### Oracle DRCP + +DBD::Oracle supports DRCP (Database Resident Connection Pool) so +if you have an 11.2 database and DRCP is enabled you can direct +all of your connections to it by adding ':POOLED' to the SID or +setting a connection attribute of ora_drcp, or set the SERVER=POOLED +when using a TNSENTRY style connection or even by setting an +environment variable ORA_DRCP. All of which are demonstrated below; + + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') + + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) + + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') + + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") + + if the ORA_DRCP environment variable is set then just this + + $dbh = DBI->connect('dbi:Oracle:DB','username','password') + +You can find a white paper on setting up DRCP and its advantages at [http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf](http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf). + +Please note that DRCP support in DBD::Oracle is relatively new so the +mechanics or its implementation are subject to change. + +### TAF (Transparent Application Failover) + +Transparent Application Failover (TAF) is the feature in OCI that +allows for clients to automatically reconnect to an instance in the +event of a failure of the instance. The reconnect happens +automatically from within the OCI (Oracle Call Interface) library. +DBD::Oracle now supports a callback function that will fire when a TAF +event takes place. The main use of the callback is to give your +program the opportunity to inform the user that a failover is taking +place. + +You will have to set up TAF on your instance before you can use this +callback. You can test your instance to see if you can use TAF +callback with + + $dbh->ora_can_taf(); + +If you try to set up a callback without it being enabled DBD::Oracle will croak. + +It is outside the scope of this documents to go through all of the +possible TAF situations you might want to set up but here is a simple +example: + +The TNS entry for the instance has had the following added to the +CONNECT_DATA section + + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) + +You will also have to create your own perl function that will be +called from the client. You can name it anything you want and it will +always be passed two parameters, the failover event value and the +failover type. You can also set a sleep value in case of failover +error and the OCI client will sleep for the specified seconds before it +attempts another event. + + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants + + #set up TAF on the connection + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + + #create the perl TAF event function + + sub handle_taf { + my ($fo_event,$fo_type) = @_; + if ($fo_event == OCI_FO_BEGIN){ + + print " Instance Unavailable Please stand by!! \n"; + printf(" Your TAF type is %s \n", + (($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_ABORT){ + print " Failover aborted. Failover will not take place.\n"; + } + elsif ($fo_event == OCI_FO_END){ + printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE" + :($fo_type==OCI_FO_SESSION) ? "SESSION" + :($fo_type==OCI_FO_SELECT) ? "SELECT" + : "UNKNOWN!")); + } + elsif ($fo_event == OCI_FO_REAUTH){ + print " Failed over user. Resuming services\n"; + } + elsif ($fo_event == OCI_FO_ERROR){ + print " Failover error Sleeping...\n"; + } + else { + printf(" Bad Failover Event: %d.\n", $fo_event); + + } + return 0; + } + +The TAF types are as follows + + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. + +The TAF events are as follows + + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + +### Connect Attributes + +#### ora_ncs_buff_mtpl + +You can customize the size of the buffer when selecting LOBs with +the built-in AUTO Lob. The default value is 4 which is probably +excessive for most situations but is needed for backward +compatibility. If you not converting between a NCS on the DB and the +Client then you might want to set this to 1 to reduce memory usage. + +This value can also be specified with the `ORA_DBD_NCS_BUFFER` +environment variable in which case it sets the value at the connect +stage. + +#### ora_drcp + +For Oracle 11.2 or greater. + +Set to _1_ to enable DRCP. Can also be set via the `ORA_DRCP` environment variable. + +#### ora_drcp_class + +If you are using DRCP, you can set a CONNECTION_CLASS for your pools +as well. As sessions from a DRCP cannot be shared by users, you can +use this setting to identify the same user across different +applications. OCI will ensure that sessions belonging to a 'class' are +not shared outside the class'. + +The values for ora_drcp_class cannot contain a '*' and must be less +than 1024 characters. + +This value can be also be specified with the `ORA_DRCP_CLASS` +environment variable. + +#### ora_drcp_min + +This optional value specifies the minimum number of sessions that are +initially opened. New sessions are only opened after this value has +been reached. + +The default value is 4 and any value above 0 is valid. + +Generally, it should be set to the number of concurrent statements the +application is planning or expecting to run. + +This value can also be specified with the `ORA_DRCP_MIN` environment +variable. + +#### ora_drcp_max + +This optional value specifies the maximum number of sessions that can +be open at one time. Once reached no more sessions can be opened +until one becomes free. The default value is 40 and any value above 1 +is valid. You should not set this value lower than ora_drcp_min as +that will just waste resources. + +This value can also be specified with the `ORA_DRCP_MAX` environment +variable. + +#### ora_drcp_incr + +This optional value specifies the next increment for sessions to be +started if the current number of sessions are less than +ora_drcp_max. The default value is 2 and any value above 0 is +valid as long as the value of ora_drcp_min + ora_drcp_incr is not +greater than ora_drcp_max. + +This value can also be specified with the `ORA_DRCP_INCR` environment +variable. + +#### ora_taf + +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option to any _true_ value. + +#### ora_taf_function + +The name of the Perl subroutine that will be called from OCI when a +TAF event occurs. You must supply a perl function to use the callback +and it will always receive two parameters, the failover event value +and the failover type. Below is an example of a TAF function + + sub taf_event{ + my ($event, $type) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } + +#### ora_taf_sleep + +The amount of time in seconds the OCI client will sleep between attempting +successive failover events when the event is OCI_FO_ERROR. + +#### ora_session_mode + +The ora_session_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA_SYSASM authorization. +The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using + + use DBD::Oracle qw(:ora_session_modes); + +This is one case where setting ORACLE_SID may be useful since +connecting as SYSDBA or SYSOPER via SQL*Net is frequently disabled +for security reasons. + +Example: + + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + +It has been reported that this only works if `$dsn` does not contain +a SID so that Oracle then uses the value of ORACLE_SID (not +TWO_TASK) environment variable to connect to a local instance. Also +the username and password should be empty, and the user executing the +script needs to be part of the dba group or osdba group. + +#### ora_oratab_orahome + +Passing a true value for the ora_oratab_orahome attribute will make +DBD::Oracle change `$ENV{ORACLE_HOME}` to make the Oracle home directory +that specified in the `/etc/oratab` file _if_ the database to connect to +is specified as a SID that exists in the oratab file, and DBD::Oracle was +built to use the Oracle 7 OCI API (not Oracle 8+). + +#### ora_module_name + +After connecting to the database the value of this attribute is passed +to the SET_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL +package. This can be used to identify the application to the DBA for +monitoring and performance tuning purposes. For example: + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + + $dbh->{ora_module_name} = $y; + +The maximum size is 48 bytes. + +#### ora_driver_name + +For 11g and later you can now set the name of the driver layer using OCI. +Perl, Perl5, ApachePerl so on. Names starting with "ORA" are reserved. You +can enter up to 8 characters. If none is enter then this will default to +DBDOxxxx where xxxx is the current version number. This value can be +retrieved on the server side using V$SESSION_CONNECT_INFO or +GV$SESSION_CONNECT_INFO + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + + $dbh->{ora_driver_name} = $q; + +#### ora_client_info + +Allows you to add any value (up to 64 bytes) to your session and it can be +retrieved on the server side from the `V$SESSION`a view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + + $dbh->{ora_client_info} = "Remote2"; + +#### ora_client_identifier + +Allows you to specify the user identifier in the session handle. + +Most useful for web applications as it can pass in the session user +name which might be different to the connection user name. Can be up +to 64 bytes long but do not to include the password for security +reasons and the first character of the identifier should not be +':'. This value can be retrieved on the server side using `V$SESSION` +view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + + $dbh->{ora_client_identifier} = $local_user; + +#### ora_action + +Allows you to specify any string up to 32 bytes which may be retrieved +on the server side using `V$SESSION` view. + + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + + $dbh->{ora_action} = "New Long Query 22"; + +#### ora_dbh_share + +Requires at least Perl 5.8.0 compiled with ithreads. + +Allows you to share +database connections between threads. The first connect will make the +connection, all following calls to connect with the same ora_dbh_share +attribute will use the same database connection. The value must be a +reference to a already shared scalar which is initialized to an empty +string. + + our $orashr : shared = '' ; + + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + +#### ora_envhp + +The first time a connection is made a new OCI 'environment' is +created by DBD::Oracle and stored in the driver handle. +Subsequent connects reuse (share) that same OCI environment +by default. + +The ora_envhp attribute can be used to disable the reuse of the OCI +environment from a previous connect. If the value is `0` then +a new OCI environment is allocated and used for this connection. + +The OCI environment holds information about the client side context, +such as the local NLS environment. By altering `%ENV` and setting +ora_envhp to 0 you can create connections with different NLS +settings. This is most useful for testing. + +#### ora_charset, ora_ncharset + +For oracle versions >= 9.2 you can specify the client charset and +ncharset with the ora_charset and ora_ncharset attributes. You +still need to pass `ora_envhp = 0` for all but the first connect. + +These attributes override the settings from environment variables. + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); + +#### ora_verbose + +Use this value to enable DBD::Oracle only tracing. Simply either set +the ora_verbose attribute on the connect() method to the trace level +you desire like this + + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + +or set it directly on the DB handle like this; + + $dbh->{ora_verbose} =6; + +In both cases the DBD::Oracle trace level is set to 6, which is the highest +level tracing most of the calls to OCI. + +#### ora_oci_success_warn + +Use this value to print otherwise silent OCI warnings that may happen +when an execute or fetch returns "Success With Info" or when you want +to tune RowCaching and LOB Reads + + $dbh->{ora_oci_success_warn} = 1; + +#### ora_objects + +Use this value to enable extended embedded oracle objects mode. In extended: + +- 1 + +Embedded objects are returned as instance (including type-name etc.) instead of simple ARRAY. + +- 2 + +Determine object type for each instance. All object attributes are returned (not only super-type's attributes). + + $dbh->{ora_objects} = 1; + +#### ora_ph_type + +The default placeholder datatype for the database session. +The `TYPE` or [ora_type](#pod_ora_type) attributes to L and +L override the datatype for individual placeholders. +The most frequent reason for using this attribute is to permit trailing spaces +in values passed by placeholders. + +Constants for the values allowed for this attribute can be imported using + + use DBD::Oracle qw(:ora_types); + +Only the following values are permitted for this attribute. + +- ORA_VARCHAR2 + +Oracle clients using OCI 8 will strip trailing spaces and allow embedded \0 bytes. +Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \0 bytes. +This is the normal default placeholder type. + +- ORA_STRING + +Do not strip trailing spaces and end the string at the first \0. + +- ORA_CHAR + +Do not strip trailing spaces and allow embedded \0. +Force 'blank-padded comparison semantics'. + +For example: + + use DBD::Oracle qw(:ora_types); + + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + +Will pad bloggs out to 8 characters and return the username. + +#### ora_parse_error_offset + +If the previous error was from a failed `prepare` due to a syntax error, +this attribute gives the offset into the `Statement` attribute where the +error was found. + +#### ora_array_chunk_size + +Due to OCI limitations, DBD::Oracle needs to buffer up rows of +bind values in its `execute_for_fetch` implementation. This attribute +sets the number of rows to buffer at a time (default value is 1000). + +The `execute_for_fetch` function will collect (at most) this many +rows in an array, send them off to the DB for execution, then go back +to collect the next chunk of rows and so on. This attribute can be +used to limit or extend the number of rows processed at a time. + +Note that this attribute also applies to `execute_array`, since that +method is implemented using `execute_for_fetch`. + +#### ora_connect_with_default_signals + +Sometimes the Oracle client seems to change some of the signal +handlers of the process during the connect phase. For instance, some +users have observed Perl's default `$SIG{INT}` handler being ignored +after connecting to an Oracle database. If this causes problems in +your application, set this attribute to an array reference of signals +you would like to be localized during the connect process. Once the +connect is complete, the signal handlers should be returned to their +previous state. + +For example: + + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); + +NOTE disabling the signal handlers the OCI library sets up may affect +functionality in the OCI library. + +NOTE If you are using connect_cached then the above example will lead +to DBI thinking each connection is different as an anonymous array reference +is being used. To avoid this when using connect_cached you are advised +to use: + + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); + +In more recent Perl versions you could possibly make use of new state +variables. + +## __connect_cached__ + +Implemented by DBI, no driver-specific impact. +Please note that connect_cached as not been tested with DRCP. + +## __data_sources__ + + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); + +Returns a list of available databases. You will have to set either the 'ORACLE_HOME' or +'TNS_ADMIN' environment value to retrieve this list. It will read these values from +TNSNAMES.ORA file entries. + +# METHODS COMMON TO ALL HANDLES + +For all of the methods below, __$h__ can be either a database handle (__$dbh__) +or a statement handle (__$sth__). Note that _$dbh_ and _$sth_ can be replaced with +any variable name you choose: these are just the names most often used. Another +common variable used in this documentation is $_rv_, which stands for "return value". + +## __err__ + + $rv = $h->err; + +Returns the error code from the last method called. + +## __errstr__ + + $str = $h->errstr; + +Returns the last error that was reported by Oracle. Starting with "ORA-00000" code followed by the error message. + +## __state__ + + $str = $h->state; + +Oracle hasn't supported SQLSTATE since the early versions OCI. It will return empty when the command succeeds and +'S1000' (General Error) for all other errors. + +While this method can be called as either `$sth->state` or `$dbh->state`, it +is usually clearer to always use `$dbh->state`. + +## __trace__ + +Implemented by DBI, no driver-specific impact. + +## __trace_msg__ + +Implemented by DBI, no driver-specific impact. + +## __parse_trace_flag__ and __parse_trace_flags__ + +Implemented by DBI, no driver-specific impact. + +## __func__ + +DBD::Oracle uses the `func` method to support a variety of functions. + +## __Private database handle functions__ + +Some of these functions are called through the method func() +which is described in the DBI documentation. Any function that begins with ora_ +can be called directly. + +## __plsql_errstr__ + +This function returns a string which describes the errors +from the most recent PL/SQL function, procedure, package, +or package body compile in a format similar to the output +of the SQL*Plus command 'show errors'. + +The function returns undef if the error string could not +be retrieved due to a database error. +Look in $dbh->errstr for the cause of the failure. + +If there are no compile errors, an empty string is returned. + +Example: + + # Show the errors if CREATE PROCEDURE fails + $dbh->{RaiseError} = 0; + if ( $dbh->do( q{ + CREATE OR REPLACE PROCEDURE perl_dbd_oracle_test as + BEGIN + PROCEDURE filltab( stuff OUT TAB ); asdf + END; } ) ) {} # Statement succeeded + } + elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } # Utter failure + else { + my $msg = $dbh->func( 'plsql_errstr' ); + die $dbh->errstr if ! defined $msg; + die $msg if $msg; + } + +## __dbms_output_enable / dbms_output_put / dbms_output_get__ + +These functions use the PL/SQL DBMS_OUTPUT package to store and +retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer +by dbms_output_put or any PL/SQL block can be retrieved by +dbms_output_get or any PL/SQL block connected to the same database +session. + +Stored text is not available until after dbms_output_put or the PL/SQL +block that saved it completes its execution. This means you __CAN NOT__ +use these functions to monitor long running PL/SQL procedures. + +Example 1: + + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); + + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); + + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); + +Example 2: + + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; + + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); + +## __dbms_output_enable ( [ buffer_size ] )__ + +This function calls DBMS_OUTPUT.ENABLE to enable calls to package +DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to +these procedures are ignored unless DBMS_OUTPUT.ENABLE is called +first. + +The buffer_size is the maximum amount of text that can be saved in the +buffer and must be between 2000 and 1,000,000. If buffer_size is not +given, the default is 20,000 bytes. + +## __dbms_output_put ( [ @lines ] )__ + +This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. + +If all lines were saved successfully the function returns 1. Depending +on the context, an empty list or undef is returned for failure. + +If any line causes buffer_size to be exceeded, a buffer overflow error +is raised and the function call fails. Some of the text might be in +the buffer. + +## __dbms_output_get__ + +This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from +the buffer. + +In an array context, all complete lines are removed from the buffer and +returned as a list. If there are no complete lines, an empty list is +returned. + +In a scalar context, the first complete line is removed from the buffer +and returned. If there are no complete lines, undef is returned. + +Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or +DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, +DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. + +## __reauthenticate ( $username, $password )__ + +Starts a new session against the current database using the credentials +supplied. + +## __private_attribute_info__ + + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); + +Returns a hash of all private attributes used by DBD::Oracle, for either +a database or a statement handle. Currently, all the hash values are undef. + +# ATTRIBUTES COMMON TO ALL HANDLES + +## __InactiveDestroy__ (boolean) + +Implemented by DBI, no driver-specific impact. + +## __RaiseError__ (boolean, inherited) + +Forces errors to always raise an exception. Although it defaults to off, it is recommended that this +be turned on, as the alternative is to check the return value of every method (prepare, execute, fetch, etc.) +manually, which is easy to forget to do. + +## __PrintError__ (boolean, inherited) + +Forces database errors to also generate warnings, which can then be filtered with methods such as +locally redefining _$SIG{__WARN__}_ or using modules such as `CGI::Carp`. This attribute is on +by default. + +## __ShowErrorStatement__ (boolean, inherited) + +Appends information about the current statement to error messages. If placeholder information +is available, adds that as well. Defaults to true. + +## __Warn__ (boolean, inherited) + +Enables warnings. This is on by default, and should only be turned off in a local block +for a short a time only when absolutely needed. + +## __Executed__ (boolean, read-only) + +Indicates if a handle has been executed. For database handles, this value is true after the [do](#pod_do) method has been called, or +when one of the child statement handles has issued an [execute](#pod_execute). Issuing a [commit](#pod_commit) or [rollback](#pod_rollback) always resets the +attribute to false for database handles. For statement handles, any call to [execute](#pod_execute) or its variants will flip the value to +true for the lifetime of the statement handle. + +## __TraceLevel__ (integer, inherited) + +Sets the trace level, similar to the [trace](#pod_trace) method. See the sections on +[trace](#pod_trace) and [parse_trace_flag](#pod_parse_trace_flag) for more details. + +## __Active__ (boolean, read-only) + +Indicates if a handle is active or not. For database handles, this indicates if the database has +been disconnected or not. For statement handles, it indicates if all the data has been fetched yet +or not. Use of this attribute is not encouraged. + +## __Kids__ (integer, read-only) + +Returns the number of child processes created for each handle type. For a driver handle, indicates the number +of database handles created. For a database handle, indicates the number of statement handles created. For +statement handles, it always returns zero, because statement handles do not create kids. + +## __ActiveKids__ (integer, read-only) + +Same as `Kids`, but only returns those that are active. + +## __CachedKids__ (hash ref) + +Returns a hashref of handles. If called on a database handle, returns all statement handles created by use of the +`prepare_cached` method. If called on a driver handle, returns all database handles created by the [connect_cached](#pod_connect_cached) +method. + +## __ChildHandles__ (array ref) + +Implemented by DBI, no driver-specific impact. + +## __PrintWarn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleError__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __HandleSetErr__ (code ref, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ErrCount__ (unsigned integer) + +Implemented by DBI, no driver-specific impact. + +## __FetchHashKeyName__ (string, inherited) + +Implemented by DBI, no driver-specific impact. + +## __ChopBlanks__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Taint__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintIn__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __TaintOut__ (boolean, inherited) + +Implemented by DBI, no driver-specific impact. + +## __Profile__ (inherited) + +Implemented by DBI, no driver-specific impact. + +## __Type__ (scalar) + +Returns `dr` for a driver handle, `db` for a database handle, and `st` for a statement handle. +Should be rarely needed. + +## __LongReadLen__ + +The maximum size of long or longraw columns to retrieve. If one of +these columns is longer than LongReadLen then either a data truncation +error will be raised (LongTrunkOk is false) or the column will be +silently truncated (LongTruncOk is true). + +DBI currently defaults this to 80. + +## __LongTruncOk__ + +Implemented by DBI, no driver-specific impact. + +## __CompatMode__ + +Type: boolean, inherited + +The CompatMode attribute is used by emulation layers (such as Oraperl) to enable compatible behaviour in the underlying driver (e.g., DBD::Oracle) for this handle. Not normally set by application code. + +It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. + +# ORACLE-SPECIFIC DATABASE HANDLE METHODS + +## __ora_can_unicode ( [ $refresh ] )__ + +Returns a number indicating whether either of the database character sets +is a Unicode encoding. Calls ora_nls_parameters() and passes the optional +$refresh parameter to it. + +0 = Neither character set is a Unicode encoding. + +1 = National character set is a Unicode encoding. + +2 = Database character set is a Unicode encoding. + +3 = Both character sets are Unicode encodings. + +## __ora_can_taf__ + +Returns true if the current connection supports TAF events. False if otherise. + +## __ora_nls_parameters ( [ $refresh ] )__ + +Returns a hash reference containing the current NLS parameters, as given +by the v$nls_parameters view. The values fetched are cached between calls. +To cause the latest values to be fetched, pass a true value to the function. + +# DATABASE HANDLE METHODS + +## __selectall_arrayref__ + + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectall_hashref__ + + $hash_ref = $dbh->selectall_hashref($sql, $key_field); + +Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. +See the DBI documentation for full details. + +## __selectcol_arrayref__ + + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + +Returns a reference to an array containing the first column +from each rows returned by preparing and executing the SQL string. It is possible to specify exactly +which columns to return. See the DBI documentation for full details. + +## __prepare__ + + $sth = $dbh->prepare($statement, \%attr); + +Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. + +### __Prepare Attributes__ + +These attributes may be used in the `\%attr` parameter of the +L database handle method. + +- ora_placeholders + +Set to false to disable processing of placeholders. Used mainly for loading a +PL/SQL package that has been _wrapped_ with Oracle's `wrap` utility. + +- ora_auto_lob + +If true (the default), fetching retrieves the contents of the CLOB or +BLOB column in most circumstances. If false, fetching retrieves the +Oracle "LOB Locator" of the CLOB or BLOB value. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for more details. + +See also the LOB tests in 05dbi.t of Oracle::OCI for examples +of how to use LOB Locators. + +- ora_pers_lob + +If true the [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) method for the [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) will be +used for LOBs rather than the default method [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators). + +- ora_clbk_lob + +If true the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) method for the L will be used for LOBs. + +- ora_piece_lob + +If true the [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) method for the L will be used for LOBs. + +- ora_piece_size + +This is the max piece size for the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) +and [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) methods, in chars for CLOBS, and +bytes for BLOBS. + +- ora_check_sql + +If 1 (default), force SELECT statements to be described in prepare(). +If 0, allow SELECT statements to defer describe until execute(). + +See [Prepare Postponed Till Execute](#pod_Prepare Postponed Till Execute) for more information. + +- ora_exe_mode + +This will set the execute mode of the current statement. Presently +only one mode is supported; + + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + +See [Scrollable Cursors](#pod_Scrollable Cursors) for more details. + +- ora_prefetch_rows + +Sets the number of rows to be prefetched. If it is not set, then the +default value is 1. See [Row Prefetching](#pod_Row Prefetching) for more details. + +- ora_prefetch_memory + +Sets the memory level for rows to be prefetched. The application then +fetches as many rows as will fit into that much memory. See L for more details. + +- ora_row_cache_off + +By default DBD::Oracle will use a row cache when fetching to cut down +the number of round trips to the server. If you do not want to use an +array fetch set this value to any value other than 0; + +See [Row Prefetching](#pod_Row Prefetching) for more details. + +### __Placeholders__ + +There are three types of placeholders that can be used in +DBD::Oracle. + +The first is the "question mark" type, in which each placeholder is +represented by a single question mark character. This is the method +recommended by the DBI and is the most portable. Each question +mark is internally replaced by a "dollar sign number" in the order in +which they appear in the query (important when using [bind_param](#pod_bind_param)). + +The second type of placeholder is "named parameters" in the format +":foo" which is the one Oracle prefers. + + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); + +Note when calling bind_param with named parameters you must include +the leading colon. The advantage of this placeholder type is that you +can use the same placeholder more than once in the same SQL statement +but you only need to bind it once. + +The last placeholder type is a variation of the two above where you +name each placeholder :N (where N is a number). Like the named +placeholders above you can use the same placeholder multiple times in +the SQL but when you call bind_param you only need to pass the N +(e.g., for :1 you use bind_param(1,...) and not bind_param(':1',...). + +The different types of placeholders cannot be mixed within a statement, but you may +use different ones for each statement handle you have. This is confusing at best, so +stick to one style within your program. + +## __prepare_cached__ + + $sth = $dbh->prepare_cached($statement, \%attr); + +Implemented by DBI, no driver-specific impact. This method is most useful +if the same query is used over and over as it will cut down round trips to the server. + +## __do__ + + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); + +Prepare and execute a single statement. Returns the number of rows affected if the +query was successful, returns undef if an error occurred, and returns -1 if the +number of rows is unknown or not available. Note that this method will return __0E0__ instead +of 0 for 'no rows were affected', in order to always return a true value if no error occurred. + +## __last_insert_id__ + +Oracle does not implement auto_increment of serial type columns it uses predefined +sequences where the id numbers are either selected before insert, at insert time with a trigger, + or as part of the query. + +Below is an example of you to use the latter with the SQL returning clause to get the ID number back +on insert with the bind_param_inout method. +. + + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); + +## __commit__ + + $rv = $dbh->commit; + +Issues a COMMIT to the server, indicating that the current transaction is finished and that +all changes made will be visible to other processes. If AutoCommit is enabled, then +a warning is given and no COMMIT is issued. Returns true on success, false on error. + +## __rollback__ + + $rv = $dbh->rollback; + +Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit +is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and +false on error. + +## __begin_work__ + +This method turns on transactions until the next call to [commit](#pod_commit) or [rollback](#pod_rollback), if [AutoCommit](#pod_AutoCommit) is +currently enabled. If it is not enabled, calling begin_work will issue an error. Note that the +transaction will not actually begin until the first statement after begin_work is called. + +## __disconnect__ + + $rv = $dbh->disconnect; + +Disconnects from the Oracle database. Any uncommitted changes will be rolled back upon disconnection. It's +good policy to always explicitly call commit or rollback at some point before disconnecting, rather than +relying on the default rollback behavior. + +If the script exits before disconnect is called (or, more precisely, if the database handle is no longer +referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() +methods automatically. It is best to explicitly disconnect rather than rely on this behavior. + +## __ping__ + + $rv = $dbh->ping; + +This `ping` method is used to check the validity of a database handle. The value returned is +either 0, indicating that the connection is no longer valid, or 1, indicating the connection is valid. +This function does 1 round trip to the Oracle Server. + +## __get_info()__ + + $value = $dbh->get_info($info_type); + +DBD::Oracle supports `get_info()`, but (currently) only a few info types. + +## __table_info()__ + +DBD::Oracle supports attributes for `table_info()`. + +In Oracle, the concept of _user_ and _schema_ is (currently) the +same. Because database objects are owned by an user, the owner names +in the data dictionary views correspond to schema names. +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. + +Search patterns are supported for TABLE_SCHEM and TABLE_NAME. + +TABLE_TYPE may contain a comma-separated list of table types. +The following table types are supported: + + TABLE + VIEW + SYNONYM + SEQUENCE + +The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. + +The special enumerations of catalogues, schemas and table types are +supported. However, TABLE_CAT is always NULL. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +`table_info()` performs a case-sensitive search. So, a selection +criterion should respect upper and lower case. +Normally, an identifier is case-insensitive. Oracle stores and +returns it in upper case. Sometimes, database objects are created +with quoted identifiers (for reserved words, mixed case, special +characters, ...). Such an identifier is case-sensitive (if not all +upper case). Oracle stores and returns it as given. +`table_info()` has no special quote handling, neither adds nor +removes quotes. + +## __primary_key_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary key constraint was created without an identifier, +PK_NAME contains a system generated name with the form SYS_Cn. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __foreign_key_info()__ + +This method (currently) supports the extended behaviour of SQL/CLI, i.e. the +result set contains foreign keys that refer to primary __and__ alternate keys. +The field UNIQUE_OR_PRIMARY distinguishes these keys. + +Oracle does not support catalogues, so `$pk_catalog` and `$fk_catalog` are +ignored as selection criteria (in the new style interface). +The UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always +NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +If the primary or foreign key constraints were created without an identifier, +UK_NAME or FK_NAME contains a system generated name with the form SYS_Cn. + +The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle (currently) +does not support other actions. + +The DELETE_RULE field may contain wrong values. This is a known Bug (#1271663) +in Oracle's data dictionary views. Currently (as of 8.1.7), 'RESTRICT' and +'SET DEFAULT' are not supported, 'CASCADE' is mapped correctly and all other +actions (incl. 'SET NULL') appear as 'NO ACTION'. + +The DEFERABILITY field is always NULL, because this columns is +not present in the ALL_CONSTRAINTS view of older Oracle releases. + +The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, +FK_TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +## __column_info()__ + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See [table_info()](#pod_table_info()) for more detailed information. + +The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). + +Don't rely on the values of the BUFFER_LENGTH field! +Especially the length of FLOATs may be wrong. + +Datatype codes for non-standard types are subject to change. + +Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG so you +may have to set LongReadLen on the connection handle before calling +column_info if you have a large default column. After DBD::Oracle 1.40 +LongReadLen is set automatically to 1Mb when calling column_info and +reset aftwerwards. + +The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. + +An identifier is passed _as is_, i.e. as the user provides or +Oracle returns it. +See [table_info()](#pod_table_info()) for more detailed information. + +It is possible with Oracle to make the names of the various DB objects (table,column,index etc) +case sensitive. + + alter table bloggind add ("Bla_BLA" NUMBER) + +So in the example the exact case "Bla_BLA" must be used to get it info on the column. While this + + alter table bloggind add (Bla_BLA NUMBER) + +any case can be used to get info on the column. + +## __selectrow_array__ + + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + +Returns an array of row information after preparing and executing the provided SQL string. The rows are returned +by calling [fetchrow_array](#pod_fetchrow_array). The string can also be a statement handle generated by a previous prepare. Note that +only the first row of data is returned. If called in a scalar context, only the first column of the first row is +returned. Because this is not portable, it is not recommended that you use this method in that way. + +## __selectrow_arrayref__ + + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an array, by internal use of +the [fetchrow_arrayref](#pod_fetchrow_arrayref) method. + +## __selectrow_hashref__ + + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + +Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an hash, by internal use of +the [fetchrow_hashref](#pod_fetchrow_hashref) method. + +## __clone__ + + $other_dbh = $dbh->clone(); + +Creates a copy of the database handle by connecting with the same parameters as the original +handle, then trying to merge the attributes. See the DBI documentation for complete usage. + +# DATABASE HANDLE ATTRIBUTES + +## __AutoCommit__ (boolean) + +Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change +in the future, so it is highly recommended that you explicitly set it when +calling [connect](#pod_connect). + +## __ReadOnly__ (boolean) + + $dbh->{ReadOnly} = 1; + +Specifies if the current database connection should be in read-only mode or not. + +Please not that this method is not foolproof: there are still ways to update the +database. Consider this a safety net to catch applications that should not be +issuing commands such as INSERT, UPDATE, or DELETE. + +This method method requires DBI version 1.55 or better. + +## __Name__ (string, read-only) + +Returns the name of the current database. This is the same as the DSN, without the +"dbi:Oracle:" part. + +## __Username__ (string, read-only) + +Returns the name of the user connected to the database. + +## __Driver__ (handle, read-only) + +Holds the handle of the parent driver. The only recommended use for this is to find the name +of the driver using: + + $dbh->{Driver}->{Name} + +## __RowCacheSize__ + +DBD::Oracle supports both Server pre-fetch and Client side row caching. By default both +are turned on to give optimum performance. Most of the time one can just let DBD::Oracle +figure out the best optimization. + +### __Row Caching__ + +Row caching occurs on the client side and the object of it is to cut down the number of round +trips made to the server when fetching rows. At each fetch a set number of rows will be retrieved +from the server and stored locally. Further calls the server are made only when the end of the +local buffer(cache) is reached. + +Rows up to the specified top level row +count `RowCacheSize` are fetched if it occupies no more than the specified memory usage limit. +The default value is 0, which means that memory size is not included in computing the number of rows to prefetch. If +the `RowCacheSize` value is set to a negative number then the positive value of RowCacheSize is used +to compute the number of rows to prefetch. + +By default `RowCacheSize` is automatically set. If you want to totally turn off prefetching set this to 1. + +For any SQL statement that contains a LOB, Long or Object Type Row Caching will be turned off. However server side +caching still works. If you are only selecting a LOB Locator then Row Caching will still work. + +### Row Prefetching + +Row prefetching occurs on the server side and uses the DBI database handle attribute `RowCacheSize` and or the +Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improved performance. + + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. + +The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first +fetch that sets the current_positon to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are +loaded into the buffer and DBD::Oracle will not have to go back to the server for more rows. When record 11 is fetched DBD::Oracle +fetches and returns this row and the next 9 rows are loaded into the buffer. In this case if you fetch backwards from 10 to 1 +no server round trips are made. + +With large record sets it is best not to attempt to go to the last record as this may take some time, A large buffer size might even slow down +the fetch. If you must get the number of rows in a large record set you might try using an few large OCI_FETCH_ABSOLUTEs and then an OCI_FETCH_LAST, +this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. +If one requires only the first few rows there is no need to set a large prefetch value. + +If the ora_prefetch_memory less than 1 or not present then memory size is not included in computing the +number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it +is not included in the computing of the prefetch rows. + +# ORACLE-SPECIFIC STATEMENT HANDLE METHODS + +## __ora_stmt_type__ + +Returns the OCI Statement Type number for the SQL of a statement handle. + +## __ora_stmt_type_name__ + +Returns the OCI Statement Type name for the SQL of a statement handle. + +# DBI STATEMENT HANDLE OBJECT METHODS + +## __bind_param__ + + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); + +Allows the user to bind a value and/or a data type to a placeholder. + +The value of `$param_num` is a number if using the '?' or if using ":foo" style placeholders, the complete name +(e.g. ":foo") must be given. +The `$bind_value` argument is fairly self-explanatory. A value of `undef` will +bind a `NULL` to the placeholder. Using `undef` is useful when you want +to change just the type and will be overwriting the value later. +(Any value is actually usable, but `undef` is easy and efficient). + +The `\%attr` hash is used to indicate the data type of the placeholder. +The default value is "varchar". If you need something else, you must +use one of the values provided by DBI or by DBD::Pg. To use a SQL value, +modify your "use DBI" statement at the top of your script as follows: + + use DBI qw(:sql_types); + +This will import some constants into your script. You can plug those +directly into the [bind_param](#pod_bind_param) call. Some common ones that you will +encounter are: + + SQL_INTEGER + +To use Oracle SQL data types, import the list of values like this: + + use DBD::Pg qw(:ora_types); + +You can then set the data types by setting the value of the `ora_type` +key in the hash passed to [bind_param](#pod_bind_param). +The current list of Oracle data types exported is: + + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN + +Data types are "sticky," in that once a data type is set to a certain placeholder, +it will remain for that placeholder, unless it is explicitly set to something +else afterwards. If the statement has already been prepared, and you switch the +data type to something else, DBD::Oracle will re-prepare the statement for you before +doing the next execute. + +Examples: + + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); + + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); + + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); + + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); + + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); + + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); + + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); + + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); + +These attributes may be used in the `\%attr` parameter of the +L or L statement handle methods. + +- ora_type + +Specify the placeholder's datatype using an Oracle datatype. +A fatal error is raised if `ora_type` and the DBI `TYPE` attribute +are used for the same placeholder. +Some of these types are not supported by the current version of +DBD::Oracle and will cause a fatal error if used. +Constants for the Oracle datatypes may be imported using + + use DBD::Oracle qw(:ora_types); + +Potentially useful values when DBD::Oracle was built using OCI 7 and later: + + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET + +Additional values when DBD::Oracle was built using OCI 8 and later: + + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + +Additional values when DBD::Oracle was built using OCI 9.2 and later: + + SQLT_CHR, SQLT_BIN + +See [Binding Cursors](#pod_Binding Cursors) for the correct way to use ORA_RSET. + +See [LOBs and LONGs](#pod_LOBs and LONGs) for how to use ORA_CLOB and ORA_BLOB. + +See [SYS.DBMS_SQL datatypes](#pod_SYS.DBMS_SQL datatypes) for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. + +See [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) for the correct way to use SQLT_CHR and SQLT_BIN. + +See [Other Data Types](#pod_Other Data Types) for more information. + +See also L. + +- ora_csform + +Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values +are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can +be imported from the DBD::Oracle module. Rarely needed. + +- ora_csid + +Specify the _integer_ OCI_ATTR_CHARSET_ID for the bind value. +Character set names can't be used currently. + +- ora_maxdata_size + +Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. +May be needed if a character set conversion from client to server +causes the data to use more space and so fail with a truncation error. + +- ora_maxarray_numentries + +Specify the maximum number of array entries to allocate. Used with +ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of +array entries Oracle can pass back to you in OUT variable of type +TABLE OF ... . + +- ora_internal_type + +Specify internal data representation. Currently is supported only for +ORA_NUMBER_TABLE. + +### Optimizing Results + +#### Prepare Postponed Till Execute + +The DBD::Oracle module can avoid an explicit 'describe' operation +prior to the execution of the statement unless the application requests +information about the results (such as $sth->{NAME}). This reduces +communication with the server and increases performance (reducing the +number of PARSE_CALLS inside the server). + +However, it also means that SQL errors are not detected until +`execute()` (or $sth->{NAME} etc) is called instead of when +`prepare()` is called. Note that if the describe is triggered by the +use of $sth->{NAME} or a similar attribute and the describe fails then +_an exception is thrown_ even if `RaiseError` is false! + +Set [ora_check_sql](#pod_ora_check_sql) to 0 in prepare() to enable this behaviour. + +## __bind_param_inout__ + + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + +DBD::Oracle fully supports bind_param_inout below are some uses for this method. + +### __Returning A Value from an INSERT__ + +Oracle supports an extended SQL insert syntax which will return one +or more of the values inserted. This can be particularly useful for +single-pass insertion of values with re-used sequence values +(avoiding a separate "select seq.nextval from dual" step). + + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; + +If you have many columns to bind you can use code like this: + + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; + +If you have many rows to insert you can take advantage of Oracle's built in execute array feature +with code like this: + + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ + print 'returned id='.$id.'\n'; + } + +Which will return all the ids into @out_values. + +- __Note:__ + +- This will only work for numbered (?) placeholders, + +- The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle + +- The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. + +### Returning A Recordset + +DBD::Oracle does not currently support binding a PL/SQL table (aka array) +as an IN OUT parameter to any Perl data structure. You cannot therefore call +a PL/SQL function or procedure from DBI that uses a non-atomic datatype as +either a parameter, or a return value. However, if you are using Oracle 9.0.1 +or later, you can make use of table (or pipelined) functions. + +For example, assume you have the existing PL/SQL Package : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + -- + l_Ret taRec ; + -- + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + -- + END Array_Example ; + / + +Currently, there is no way to directly call the function +Array_Example.Array_Func from DBI. However, by making the following relatively +painless additions, its not only possible, but extremely efficient. + +First, you need to create database object types that correspond to the record +and table types in the package. From the above example, these would be : + + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; + + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; + +Now, assuming the existing function needs to remain unchanged (it is probably +being called from other PL/SQL code), we need to add a new function to the +package. Here's the new package specification and body : + + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; + + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; + +As you can see, the new function is very simple. Now, it is a simple matter +of calling the function as a straight-forward SELECT from your DBI code. From +the above example, the code would look something like this : + + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } + +### __SYS.DBMS_SQL datatypes__ + +DBD::Oracle has built-in support for __SYS.DBMS_SQL.VARCHAR2_TABLE__ +and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: + + my $statement=' + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; + END; + '; + + my $sth=$dbh->prepare( $statement ); + + my @arr=( "abc","efg","hij" ); + + $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 100 + } ) ; + $sth->bind_param_inout(":cc", \$cc, 100 ); + $sth->execute(); + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +- __Note:__ + +- Take careful note that we use '\\@arr' here because the 'bind_param_inout' + will only take a reference to a scalar. + +### __ORA_VARCHAR2_TABLE__ + +SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. +( in bind_param() and bind_param_inout() ). When you bind array, you need +to specify full buffer size for OUT data. So, there are two parameters: +_max_len_ (specified as 3rd argument of bind_param_inout() ), +and _ora_maxarray_numentries_. They define maximum array entry length and +maximum rows, that can be passed to Oracle and back to you. In this +example we send array with 1 element with length=3, but allocate space for 100 +Oracle array entries with maximum length 10 of each. So, you can get no more +than 100 array entries with length <= 10. + +If you set _max_len_ to zero, maximum array entry length is calculated +as maximum length of entry of array bound. If 0 < _max_len_ < length( $some_element ), +truncation occur. + +If you set _ora_maxarray_numentries_ to zero, current (at bind time) bound +array length is used as maximum. If 0 < _ora_maxarray_numentries_ < scalar(@array), +not all array entries are bound. + +### __ORA_NUMBER_TABLE__ + +SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. +The main difference is internal data representation. Currently 2 types of +bind is allowed : as C-integer, or as C-double type. To select one of them, +you may specify additional bind parameter _ora_internal_type_ as either +__SQLT_INT__ or __SQLT_FLT__ for C-integer and C-double types. +Integer size is architecture-specific and is usually 32 or 64 bit. +Double is standard IEEE 754 type. + +_ora_internal_type_ defaults to double (SQLT_FLT). + +_max_len_ is ignored for OCI_NUMBER_TABLE. + +Currently, you cannot bind full native Oracle NUMBER(38). If you really need, +send request to dbi-dev list. + +The usage example is here: + + $statement=' + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl(2); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + '; + + $sth=$dbh->prepare( $statement ); + + if( ! defined($sth) ){ + die "Prepare error: ",$dbh->errstr,"\n"; + } + + @arr=( 1,"2E0","3.5" ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => (scalar(@arr)+2), + ora_internal_type => SQLT_FLT + } ) ){ + die "bind :mytable error: ",$dbh->errstr,"\n"; + } + $cc=undef; + if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ + die "bind :cc error: ",$dbh->errstr,"\n"; + } + + if( not $sth->execute() ){ + die "Execute failed: ",$dbh->errstr,"\n"; + } + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + +The result is like: + + Result: cc=2 + arr=$VAR1 = [ + '1', + '2', + '3.5', + '-1', + '-2' + ]; + +If you change bind type to __SQLT_INT__, like: + + ora_internal_type => SQLT_INT + +you get: + + Result: cc=2 + arr=$VAR1 = [ + 1, + 2, + 3, + -1, + -2 + ]; + +## __bind_param_inout_array__ + +DBD::Oracle supports this undocumented feature of DBI. See [Returning A Value from an INSERT](#pod_Returning A Value from an INSERT) for an example. + +## __bind_param_array__ + + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + +Binds an array of values to a placeholder, so that each is used in turn by a call +to the [execute_array](#pod_execute_array) method. + +## __execute__ + + $rv = $sth->execute(@bind_values); + +Perform whatever processing is necessary to execute the prepared statement. + +## __execute_array__ + + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + +Execute a prepared statement once for each item in a passed-in hashref, or items that +were previously bound via the [bind_param_array](#pod_bind_param_array) method. See the DBI documentation +for more details. + +DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very +quickly. + +## __execute_for_fetch__ + + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + +Used internally by the [execute_array](#pod_execute_array) method, and rarely used directly. See the +DBI documentation for more details. + +## __fetchrow_arrayref__ + + $ary_ref = $sth->fetchrow_arrayref; + +Fetches the next row of data from the statement handle, and returns a reference to an array +holding the column values. Any columns that are NULL are returned as undef within the array. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +Note that the same array reference is returned for each fetch, so don't store the reference and +then use it after a later fetch. Also, the elements of the array are also reused for each row, +so take care if you want to take a reference to an element. See also [bind_columns](#pod_bind_columns). + +## __fetchrow_array__ + + @ary = $sth->fetchrow_array; + +Similar to the [fetchrow_arrayref](#pod_fetchrow_arrayref) method, but returns a list of column information rather than +a reference to a list. Do not use this in a scalar context. + +## __fetchrow_hashref__ + + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); + +Fetches the next row of data and returns a hashref containing the name of the columns as the keys +and the data itself as the values. Any NULL value is returned as as undef value. + +If there are no more rows or if an error occurs, the this method return undef. You should +check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +was due to an error. + +The optional `$name` argument should be either `NAME`, `NAME_lc` or `NAME_uc`, and indicates +what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. + +## __fetchall_arrayref__ + + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + +Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the +statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, +the data read in so far will be returned. Because of this, you should always check `$sth->err` after +calling this method, unless [RaiseError](#pod_RaiseError) has been enabled. + +If `$slice` is an array reference, fetchall_arrayref uses the [fetchrow_arrayref](#pod_fetchrow_arrayref) method to fetch each +row as an array ref. If the `$slice` array is not empty then it is used as a slice to select individual +columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). + +With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. + +If `$slice` is a hash reference, fetchall_arrayref uses [fetchrow_hashref](#pod_fetchrow_hashref) to fetch each row as a hash reference. + +See the DBI documentation for a complete discussion. + +## __fetchall_hashref__ + + $hash_ref = $sth->fetchall_hashref( $key_field ); + +Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for +a full discussion. + +## __finish__ + + $rv = $sth->finish; + +Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed +when you have not fetched all the possible rows. + +## __rows__ + + $rv = $sth->rows; + +Returns the number of rows affected for updates, deletes and inserts and -1 for selects. + +## __bind_col__ + + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + +Binds a Perl variable and/or some attributes to an output column of a SELECT statement. +Column numbers count up from 1. You do not need to bind output columns in order to fetch data. + +NOTE: DBD::Oracle does not use the `$bind_type` to determine how to +bind the column; it uses what Oracle says the data type is. You can +however set the StrictlyTyped/DiscardString attributes and these will +take effect as these attributes are applied after the column is +retrieved. + +See the DBI documentation for a discussion of the optional parameters `\%attr` and `$bind_type` + +## __bind_columns__ + + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + +Calls the [bind_col](#pod_bind_col) method for each column in the SELECT statement, using the supplied list. + +## __dump_results__ + + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + +Fetches all the rows from the statement handle, calls `DBI::neat_list` for each row, and +prints the results to `$fh` (which defaults to `STDOUT`). Rows are separated by `$lsep` (which defaults +to a newline). Columns are separated by `$fsep` (which defaults to a comma). The `$maxlen` controls +how wide the output can be, and defaults to 35. + +This method is designed as a handy utility for prototyping and testing queries. Since it uses +"neat_list" to format and edit the string for reading by humans, it is not recommended +for data transfer applications. + +# STATEMENT HANDLE ATTRIBUTES + +## __NUM_OF_FIELDS__ (integer, read-only) + +Returns the number of columns returned by the current statement. A number will only be returned for +SELECT statements for INSERT, +UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NUM_OF_PARAMS__ (integer, read-only) + +Returns the number of placeholders in the current statement. + +## __NAME__ (arrayref, read-only) + +Returns an arrayref of column names for the current statement. This +method will only work for SELECT statements, for SHOW statements, and for +INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. +This method returns undef if called before `execute()`. + +## __NAME_lc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to lower case. + +## __NAME_uc__ (arrayref, read-only) + +The same as the `NAME` attribute, except that all column names are forced to upper case. + +## __NAME_hash__ (hashref, read-only) + +Similar to the `NAME` attribute, but returns a hashref of column names instead of an arrayref. The names of the columns +are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. +This method returns undef if called before `execute()`. + +## __NAME_lc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __NAME_uc_hash__ (hashref, read-only) + +The same as the `NAME_hash` attribute, except that all column names are forced to lower case. + +## __TYPE__ (arrayref, read-only) + +Returns an arrayref indicating the data type for each column in the statement. +This method returns undef if called before `execute()`. + +## __PRECISION__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. +The number indicates the precision for `NUMERIC` columns, the size in number of +characters for `CHAR` and `VARCHAR` columns, and for all other types of columns +it returns the number of _bytes_. +This method returns undef if called before `execute()`. + +## __SCALE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates the scale of the that column. The only type that will return a value is `NUMERIC`. +This method returns undef if called before `execute()`. + +## __NULLABLE__ (arrayref, read-only) + +Returns an arrayref of integer values for each column returned by the statement. The number +indicates if the column is nullable or not. 0 = not nullable, 1 = nullable, 2 = unknown. +This method returns undef if called before `execute()`. + +## __Database__ (dbh, read-only) + +Returns the database handle this statement handle was created from. + +## __ParamValues__ (hash ref, read-only) + +Returns a reference to a hash containing the values currently bound to placeholders. If the "named parameters" +type of placeholders are being used (such as ":foo"), then the keys of the hash will be the names of the +placeholders (without the colon). If the "dollar sign numbers" type of placeholders are being used, the keys of the hash will +be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, +starting at one and increasing for every placeholder. + +If this method is called before [execute](#pod_execute), the literal values passed in are returned. If called after +[execute](#pod_execute), then the quoted versions of the values are returned. + +## __ParamTypes__ (hash ref, read-only) + +Returns a reference to a hash containing the type names currently bound to placeholders. The keys +are the same as returned by the ParamValues method. The values are hashrefs containing a single key value +pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can +only be expressed by a Postgres type. The value is the internal number corresponding to the type originally +passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of +ParamTypes to be passed back to the [bind_param](#pod_bind_param) method. + +## __Statement__ (string, read-only) + +Returns the statement string passed to the most recent "prepare" method called in this database handle, even if that method +failed. This is especially useful where "RaiseError" is enabled and the exception handler checks $@ and sees that a `prepare` +method call failed. + +## __RowsInCache__ + +Returns the number of un-fetched rows in the cache for selects. + +# SCROLLABLE CURSORS + +Oracle supports the concept of a 'Scrollable Cursor' which is defined as a 'Result Set' where +the rows can be fetched either sequentially or non-sequentially. One can fetch rows forward, +backwards, from any given position or the n-th row from the current position in the result set. + +Rows are numbered sequentially starting at one and client-side caching of the partial or entire result set +can improve performance by limiting round trips to the server. + +Oracle does not support DML type operations with scrollable cursors so you are limited +to simple 'Select' operations only. As well you can not use this functionality with remote +mapped queries or if the LONG datatype is part of the select list. + +However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch methods. + +Only use scrollable cursors if you really have a good reason to. They do use up considerable +more server and client resources and have poorer response times than non-scrolling cursors. + +## Enabling Scrollable Cursors + +To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; + + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + +Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the +statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; + + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + +When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row +or you can still use any of the other fetch methods but with a poorer response time than if you used a +non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. + +## Scrollable Cursor Methods + +The following driver-specific methods are used with scrollable cursors. + +- ora_scroll_position + + $position = $sth->ora_scroll_position(); + +This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time +this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. +The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. + +- ora_fetch_scroll + + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + +Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset +value which will then determine the row that will be fetched. It returns the row as a list containing the field values. +Null fields are returned as _undef_ values in the list. + +The valid orientation constant and fetch offset values combination are detailed below + + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + +The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + +The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + +## Scrollable Cursor Usage + +Given a simple code like this: + + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + +and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll +method; + +- Fetching the Last Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +if the record set is large this could take some time. + +- Fetching the Current Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will still be 20 after this snippet. + +- Fetching the First Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the Next Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 5 after this snippet. + +- Fetching the Prior Row + + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 1 after this snippet. + +- Fetching the 10th Row + + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 10th to 14th Row + + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 14 after this snippet. + +- Fetching the 14th to 10th Row + + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 10 after this snippet. + +- Fetching the 5th Row From the Present Position. + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 15 after this snippet. + +- Fetching the 9th Row Prior From the Present Position + + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; + +The current_positon attribute will be 6 after this snippet. + +- Use Finish + + $sth->finish(); + +When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of +cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. + +# LOBS AND LONGS + +The key to working with LOBs (CLOB, BLOBs) is to remember the value of an Oracle LOB column is not the content of the LOB. It's a +'LOB Locator' which, after being selected or inserted needs extra processing to read or write the content of the LOB. There are also legacy LONG types (LONG, LONG RAW, VARCHAR2) +which are presently deprecated by Oracle but are still in use. These LONG types do not utilize a 'LOB Locator' and also are more limited in +functionality than CLOB or BLOB fields. + +DBD::Oracle now offers three interfaces to LOB and LONG data, + +- [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) + +With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of +BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. + +- [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) + +With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. + +- [LOB Locator Method Interface](#pod_LOB Locator Method Interface) + +This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. + +Generally speaking the interface that you will chose will be dependent on what end you are trying to achieve. All have their benefits and +drawbacks. + +One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB column can be in one of three states; + +- NULL + +The table cell is created, but the cell holds no locator or value. +If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a + + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + +error when working with a LOB. + +You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; + + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. + +- Empty + +A LOB instance with a locator exists in the cell, but it has no value. The length of the LOB is zero. In this case DBD::Oracle will return 'undef' for the field. + +- Populated + +A LOB instance with a locator and a value exists in the cell. You actually get the LOB value. + +## Data Interface for Persistent LOBs + +This is the original interface for LONG and LONG RAW datatypes and from Oracle 9iR1 and later the OCI API was extended to work directly with the other LOB datatypes. +In other words you can treat all LOB type data (BLOB, CLOB) as if it was a LONG, LONG RAW, or VARCHAR2. So you can perform INSERT, UPDATE, fetch, bind, and define operations on LOBs using the same techniques +you would use on other datatypes that store character or binary data. In some cases there are fewer round trips to the server as no 'LOB Locators' are +used, normally one can get an entire LOB is a single round trip. + +### Simple Fetch for LONGs and LONG RAWs + +As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG datatypes as a single large piece. +There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. +If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into +an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. + +For example give this table; + + CREATE TABLE test_long ( + id NUMBER, + long1 long) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the long1 fields but they will be truncated at 2MBs. + +### Using ora_ncs_buff_mtpl + +When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the +Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. +Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. + +However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer +value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes +but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes +(maybe less characters though) but you are using allot more memory that you need. + +You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can +also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. + +The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the +ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. + +If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; + + ORA-03127: no new operations allowed until the active operation ends + +This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) + +If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. + +This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. + +You can tune this value by setting ora_oci_success_warn which will display the following + + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) + +In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. + +### Simple Fetch for CLOBs and BLOBs + +To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well +set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds +the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. + +For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this +and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. + +It seems with BLOBs you are not limited by the 64k. + +For example give this table; + + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + +this code; + + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; + + $dbh->{LongTruncOk}=1; + +before the execute will return all the lobs but they will be truncated at 2MBs. + +### Piecewise Fetch with Callback + +With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. +To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Simple Fetch for LONGs and LONG RAWs](#pod_Simple Fetch for LONGs and LONG RAWs) and [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is +dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +Using the table from the last example this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. + +Using the table from the first example (LONG) this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +#### Piecewise Fetch with Polling + +With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' +attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected +size of the LOB. Like the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback). + +Using the table from the example above this code; + + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. + +Finally with this code; + + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } + +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. + +### Binding for Updates and Inserts for CLOBs and BLOBs + +To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method +'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); + +So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. + +### Support for Remote LOBs; + +Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; + + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + +to a remote database called 'test_lobs', the following code will work; + + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Below are the limitations of Remote LOBs; + +- Queries involving more than one database are not supported; + +so the following returns an error: + + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + +as does: + + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; + +- DDL commands are not supported; + +so the following returns an error: + + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + +- Only binds and defines for data going into remote persistent LOBs are supported. + +so that parameter passing in PL/SQL where CHAR data is bound or defined for remote LOBs is not allowed . + +These statements all produce errors: + + SELECT foo() FROM table1@dbs2; + + SELECT foo()@dbs INTO char_val FROM DUAL; + + SELECT XMLType().getclobval FROM table1@dbs2; + +- If the remote object is a view such as + + CREATE VIEW v AS SELECT foo() FROM ... + +the following would not work: + + SELECT * FROM v@dbs2; + +- Limited PL/SQL parameter passing + +PL/SQL parameter passing is not allowed where the actual argument is a LOB type +and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. + +- RETURNING INTO does not support implicit conversions between CHAR and CLOB. + +so the following returns an error: + + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + +## Locator Data Interface + +### Simple Usage + +When fetching LOBs with this interface a 'LOB Locator' is created then used to get the lob with the LongReadLen and LongTruncOk attributes. +The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs +in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. + +When inserting or updating LOBs some _major_ magic has to be performed +behind the scenes to make it transparent. Basically the driver has to +insert a 'LOB Locator' and then refetch the newly inserted LOB +Locator before being able to write the data into it. However, it works +well most of the time, and I've made it as fast as possible, just one +extra server-round-trip per insert or update after the first. For the +time being, only single-row LOB updates are supported. + +To insert or update a large LOB using a placeholder, DBD::Oracle has to +know in advance that it is a LOB type. So you need to say: + + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + +The ORA_CLOB and ORA_BLOB constants can be imported using + + use DBD::Oracle qw(:ora_types); + +or use the corresponding integer values (112 and 113). + +One further wrinkle: for inserts and updates of LOBs, DBD::Oracle has +to be able to tell which parameters relate to which table fields. +In all cases where it can possibly work it out for itself, it does, +however, if there are multiple LOB fields of the same type in the table +then you need to tell it which field each LOB param relates to: + + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + +There are some limitations inherent in the way DBD::Oracle makes typical +LOB operations simple by hiding the LOB Locator processing: + + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. + +The alternative is to disable the automatic LOB Locator processing. +If [ora_auto_lob](#pod_ora_auto_lob) is 0 in prepare(), you can fetch the LOB Locators and +do all the work yourself using the ora_lob_*() methods. +See the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) section below. + +### LOB support in PL/SQL + +LOB Locators can be passed to PL/SQL calls by binding them to placeholders +with the proper `ora_type`. If [ora_auto_lob](#pod_ora_auto_lob) is true, output LOB +parameters will be automatically returned as strings. + +If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), +strings can be bound to input LOB placeholders and will be automatically +converted to LOBs. + +Example: + # Build a large XML document, bind it as a CLOB, + # extract elements through PL/SQL and return as a CLOB + + # $dbh is a connected database handle + # output will be large + + local $dbh->{LongReadLen} = 1_000_000; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + + my $out_clob; + + + + my $sth = $dbh->prepare(<bind_param( ':in', $in_clob, { ora_type => ORA_CLOB } ); + $sth->bind_param_inout( ':out', \$out_clob, 0, { ora_type => ORA_CLOB } ); + $sth->execute; + +If you ever get an + + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + +error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. +One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. + +## Persistent & Locator Interface Caveats + +Now that one has the option of using the Persistent or the Locator interface for LOBs the questions arises +which one to use. For starters, if you want to access LOBs over a dblink you will have to use the Persistent +interface so that choice is simple. The question of which one to use after that is a little more tricky. +It basically boils down to a choice between LOB size and speed. + +The Callback and Polling piecewise fetches are very very slow +when compared to the Simple and the Locator fetches but they can handle very large blocks of data. Given a situation where a +large LOB is to be read the Locator fetch may time out while either of the piecewise fetches may not. + +With the Simple fetch you are limited by physical memory of your server but it runs a little faster than the Locator, as there are fewer round trips +to the server. So if you have small LOBs and need to save a little bandwidth this is the one to use. It you are going after large LOBs then the Locator interface is the one to use. + +If you need to update more than a single row of with LOB data then the Persistent interface can do it while the Locator can't. + +If you encounter a situation where you have to access the legacy LOBs (LONG, LONG RAW) and the values are to large for you system then you can use +the Callback or Polling piecewise fetches to get all of the data. + +Not all of the Persistent interface has been implemented yet, the following are not supported; + + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + +Most of the time you should just use the [Locator Data Interface](#pod_Locator Data Interface) as this is in one that has the best combination of speed and size. + +All this being said if you are doing some critical programming I would use the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) as this gives you very +fine grain control of your LOBs, of course the code for this will be somewhat more involved. + +## Data Interface for LOB Locators + +The following driver-specific methods let you manipulate "LOB Locators" directly. +To select a LOB locator directly set the if the `ora_auto_lob` +attribute to false, or alternatively they can be returned via PL/SQL procedure calls. + +(If using a DBI version earlier than 1.36 they must be called via the +func() method. Note that methods called via func() don't honour +RaiseError etc, and so it's important to check $dbh->err after each call. +It's recommended that you upgrade to DBI 1.38 or later.) + +Note that LOB locators are only valid while the statement handle that +created them is valid. When all references to the original statement +handle are lost, the handle is destroyed and the locators are freed. + +- ora_lob_read + + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + +Read a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobRead function. + +- ora_lob_write + + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + +Write/overwrite a portion of the LOB. $offset starts at 1. +Uses the Oracle OCILobWrite function. + +- ora_lob_append + + $rc = $dbh->ora_lob_append($lob_locator, $data); + +Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. + +- ora_lob_trim + + $rc = $dbh->ora_lob_trim($lob_locator, $length); + +Trims the length of the LOB to $length. +Uses the Oracle OCILobTrim function. + +- ora_lob_length + + $length = $dbh->ora_lob_length($lob_locator); + +Returns the length of the LOB. +Uses the Oracle OCILobGetLength function. + +- ora_lob_is_init + + $is_init = $dbh->ora_lob_is_init($lob_locator); + +Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' +if there is an error. +Uses the Oracle OCILobLocatorIsInit function. + +- ora_lob_chunk_size + + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + +Returns the chunk size of the LOB. +Uses the Oracle OCILobGetChunkSize function. + +For optimal performance, Oracle recommends reading from and +writing to a LOB in batches using a multiple of the LOB chunk size. +In Oracle 10g and before, when all defaults are in place, this +chunk size defaults to 8k (8192). + +### LOB Locator Method Examples + +_Note:_ Make sure you first read the note in the section above about +multi-byte character set issues with these methods. + +The following examples demonstrate the usage of LOB Locators +to read, write, and append data, and to query the size of +large data. + +The following examples assume a table containing two large +object columns, one binary and one character, with a primary +key column, defined as follows: + + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) + +It also assumes a sequence for use in generating unique +lob_id field values, defined as follows: + + CREATE SEQUENCE lob_example_seq + +### Example: Inserting a new row with large data + +Unless enough memory is available to store and bind the +entire LOB data for insert all at once, the LOB columns must +be written interactively, piece by piece. In the case of a new row, +this is performed by first inserting a row, with empty values in +the LOB columns, then modifying the row by writing the large data +interactively to the LOB columns using their LOB locators as handles. + +The insert statement must create token values in the LOB +columns. Here, we use the empty string for both the binary +and character large object columns 'bindata' and 'chardata'. + +After the INSERT statement, a SELECT statement is used to +acquire LOB locators to the 'bindata' and 'chardata' fields +of the newly inserted row. Because these LOB locators are +subsequently written, they must be acquired from a select +statement containing the clause 'FOR UPDATE' (LOB locators +are only valid within the transaction that fetched them, so +can't be used effectively if AutoCommit is enabled). + + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + +In this example we demonstrate the use of ora_lob_write() +interactively to append data to the columns 'bin_data' and +'char_data'. Had we used ora_lob_append(), we could have +saved ourselves the trouble of keeping track of the offset +into the lobs. The snippet of code beneath the comment +'BEGIN WRITING BIN_DATA COLUMN' could look as follows: + + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } + +The scalar variables $offset and $length are no longer +needed, because ora_lob_append() keeps track of the offset +for us. + +### Example: Updating an existing row with large data + +In this example, we demonstrate a technique for overwriting +a portion of a blob field with new binary data. The blob +data before and after the section overwritten remains +unchanged. Hence, this technique could be used for updating +fixed length subfields embedded in a binary field. + + my $lob_id = 5; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); + + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); + +After running this code, the row where lob_id = 5 will +contain, starting at position 100234 in the bin_data column, +the string "This string will overwrite a portion of the blob". + +### Example: Streaming character data from the database + +In this example, we demonstrate a technique for streaming +data from the database to a file handle, in this case +STDOUT. This allows more data to be read in and written out +than could be stored in memory at a given time. + + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } + +Notice that the select statement does not contain the phrase +"FOR UPDATE". Because we are only reading from the LOB +Locator returned, and not modifying the LOB it refers to, +the select statement does not require the "FOR UPDATE" +clause. + +A word of caution when using the data returned from an ora_lob_read in a conditional statement. +for example if the code below; + + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } + +was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return +the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte +as $data will contain 0 which PERL will see as false and not print it out. + +### Example: Truncating existing large data + +In this example, we truncate the data already present in a +large object column in the database. Specifically, for each +row in the table, we truncate the 'bindata' value to half +its previous length. + +After acquiring a LOB Locator for the column, we query its +length, then we trim the length by half. Because we modify +the large objects with the call to ora_lob_trim(), we must +select the LOB locators 'FOR UPDATE'. + + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } + +# SPACES AND PADDING + +## Trailing Spaces + +Only the Oracle OCI 8 strips trailing spaces from VARCHAR placeholder +values and uses Nonpadded Comparison Semantics with the result. +This causes trouble if the spaces are needed for +comparison with a CHAR value or to prevent the value from +becoming '' which Oracle treats as NULL. +Look for Blank-padded Comparison Semantics and Nonpadded +Comparison Semantics in Oracle's SQL Reference or Server +SQL Reference for more details. + +To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, +either change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or the placeholder +type for a particular call to L or L +with [ora_type](#pod_ora_type) or `TYPE`. +Using [ORA_CHAR](http://search.cpan.org/perldoc?ORA_CHAR) with [ora_type](http://search.cpan.org/perldoc?ora_type) or `SQL_CHAR` with `TYPE` +allows the placeholder to be used with Padded Comparison Semantics +if the value it is being compared to is a CHAR, NCHAR, or literal. + +Please remember that using spaces as a value or at the end of +a value makes visually distinguishing values with different +numbers of spaces difficult and should be avoided. + +Oracle Clients that use OCI 9.2 do not strip trailing spaces. + +## Padded Char Fields + +Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. +As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will +have to change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or placeholder +type for a particular call with L or L +with [ORA_CHAR](#pod_ORA_CHAR). + +# UNICODE + +DBD::Oracle now supports Unicode UTF-8. There are, however, a number +of issues you should be aware of, so please read all this section +carefully. + +In this section we'll discuss "Perl and Unicode", then "Oracle and +Unicode", and finally "DBD::Oracle and Unicode". + +Information about Unicode in general can be found at: +[http://www.unicode.org/](http://www.unicode.org/). It is well worth reading because there are +many misconceptions about Unicode and you may be holding some of them. + +## Perl and Unicode + +Perl began implementing Unicode with version 5.6, but the implementation +did not mature until version 5.8 and later. If you plan to use Unicode +you are _strongly_ urged to use Perl 5.8.2 or later and to _carefully_ read +the Perl documentation on Unicode: + + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode + +And then read it again. + +Perl's internal Unicode format is UTF-8 +which corresponds to the Oracle character set called AL32UTF8. + +## Oracle and Unicode + +Oracle supports many characters sets, including several different forms +of Unicode. These include: + + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + +When you create an Oracle database, you must specify the DATABASE +character set (used for DDL, DML and CHAR datatypes) and the NATIONAL +character set (used for NCHAR and NCLOB types). +The character sets used in your database can be found using: + + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + +The Oracle 9.2 and later default for the national character set is AL16UTF16. +The default for the database character set is often US7ASCII. +Although many experienced DBAs will consider an 8bit character set like +WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle +other than US7ASCII, requires that the NLS_LANG environment variable be set. +See the L<"Oracle UTF8 is not UTF-8"> section below. + +You are strongly urged to read the Oracle Internationalization documentation +specifically with respect the choices and trade offs for creating +a databases for use with international character sets. + +Oracle uses the NLS_LANG environment variable to indicate what +character set is being used on the client. When fetching data Oracle +will convert from whatever the database character set is to the client +character set specified by NLS_LANG. Similarly, when sending data to +the database Oracle will convert from the character set specified by +NLS_LANG to the database character set. + +The NLS_NCHAR environment variable can be used to define a different +character set for 'national' (NCHAR) character types. + +Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. +For example: + + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 + +## Oracle UTF8 is not UTF-8 + +AL32UTF8 should be used in preference to UTF8 if it works for you, +which it should for Oracle 9.2 or later. If you're using an old +version of Oracle that doesn't support AL32UTF8 then you should +avoid using any Unicode characters that require surrogates, in other +words characters beyond the Unicode BMP (Basic Multilingual Plane). + +That's because the character set that Oracle calls "UTF8" doesn't +conform to the UTF-8 standard in its handling of surrogate characters. +Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". +Here are a couple of extracts from [http://www.unicode.org/reports/tr26/](http://www.unicode.org/reports/tr26/): + + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. + + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. + +Oracle uses this internally because it collates (sorts) in the same order +as UTF16, which is the basis of Oracle's internal collation definitions. + +Rather than change UTF8 for clients Oracle chose to define a new character +set called "AL32UTF8" which does conform to the UTF-8 standard. +(The AL32UTF8 character set can't be used on the server because it +would break collation.) + +Because of that, for the rest of this document we'll use "AL32UTF8". +If you're using an Oracle version below 9.2 you'll need to use "UTF8" +until you upgrade. + +## DBD::Oracle and Unicode + +DBD::Oracle Unicode support has been implemented for Oracle versions 9 +or greater, and Perl version 5.6 or greater (though we _strongly_ +suggest that you use Perl 5.8.2 or later). + +You can check which Oracle version your DBD::Oracle was built with by +importing the `ORA_OCI` constant from DBD::Oracle. + +__Fetching Data__ + +Any data returned from Oracle to DBD::Oracle in the AL32UTF8 +character set will be marked as UTF-8 to ensure correct handling by Perl. + +For Oracle to return data in the AL32UTF8 character set the +NLS_LANG or NLS_NCHAR environment variable _must_ be set as described +in the previous section. + +When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR +is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. + +When fetching other character data from Oracle, DBD::Oracle +will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. + +__Sending Data using Placeholders__ + +Data bound to a placeholder is assumed to be in the default client +character set (specified by NLS_LANG) except for a few special +cases. These are listed here with the highest precedence first: + +If the `ora_csid` attribute is given to bind_param() then that +is passed to Oracle and takes precedence. + +If the value is a Perl Unicode string (UTF-8) then DBD::Oracle +ensures that Oracle uses the Unicode character set, regardless of +the NLS_LANG and NLS_NCHAR settings. + +If the placeholder is for inserting an NCLOB then the client NLS_NCHAR +character set is used. (That's useful but inconsistent with the other behaviour +so may change. Best to be explicit by using the `ora_csform` +attribute.) + +If the `ora_csform` attribute is given to bind_param() then that +determines if the value should be assumed to be in the default +(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + +or + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + +Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to +insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert +will still happen but a error code of 0 will be returned with the following warning; + + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII + +The warning will report the parameter number and the NCHAR setting that the query is running. + +__Sending Data using SQL__ + +Oracle assumes the SQL statement is in the default client character +set (as specified by NLS_LANG). So Unicode strings containing +non-ASCII characters should not be used unless the default client +character set is AL32UTF8. + +## DBD::Oracle and Other Character Sets and Encodings + +The only multi-byte Oracle character set supported by DBD::Oracle is +"AL32UTF8" (and "UTF8"). Single-byte character sets should work well. + +# OBJECT & COLLECTION DATA TYPES + +Oracle databases allow for the creation of object oriented like user-defined types. +There are two types of objects, Embedded--an object stored in a column of a regular table +and REF--an object that uses the REF retrieval mechanism. + +DBD::Oracle supports only the 'selection' of embedded objects of the following types OBJECT, VARRAY +and TABLE in any combination. Support is seamless and recursive, meaning you +need only supply a simple SQL statement to get all the values in an embedded object. +You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. + +Array example, given this type and table; + + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) + +The code to access all the data in the table could be something like this; + + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; + + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } + +Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. + +As stated before DBD::Oracle will automatically drill into the embedded object and extract +all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an +SQL TABLE; + + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); + + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + +The following code will access all of the embedded data; + + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } + +Object example, given this object and table; + + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; + + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); + + CREATE TABLE people (id INTEGER, obj Person); + + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + +The following code will access the data; + + $dbh{'ora_objects'} =>1; + + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); + + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); + + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } + + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) + +So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables +nested to 10 levels. + +Any NULL values found in the embedded object will be returned as 'undef'. + +# OTHER DATA TYPES + +DBD::Oracle does not _explicitly_ support most Oracle datatypes. +It simply asks Oracle to return them as strings and Oracle does so. +Mostly. Similarly when binding placeholder values DBD::Oracle binds +them as strings and Oracle converts them to the appropriate type, +such as DATE, when used. + +Some of these automatic conversions to and from strings use NLS +settings to control the formatting for output and the parsing for +input. The most common example is the DATE type. The default NLS +format for DATE might be DD-MON-YYYY and so when a DATE type is +fetched that's how Oracle will format the date. NLS settings also +control the default parsing of strings into DATE values. An error +will be generated if the contents of the string don't match the +NLS format. If you're dealing in dates which don't match the default +NLS format then you can either change the default NLS format or, more +commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") +to explicitly specify formats for converting to and from strings. + +A slightly more subtle problem can occur with NUMBER types. The +default NLS settings might format numbers with a fullstop ("`.`") +to separate thousands and a comma ("`,`") as the decimal point. +Perl will generate warnings and use incorrect values when numbers, +returned and formatted as strings in this way by Oracle, are used +in a numeric context. You could explicitly convert each numeric +value using the TO_CHAR(...) function but that gets tedious very +quickly. The best fix is to change the NLS settings. That can be +done for an individual connection by doing: + + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + +There are some types, like BOOLEAN, that Oracle does not automatically +convert to or from strings (pity). These need to be converted +explicitly using SQL or PL/SQL functions. + +Examples: + + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + +#### Support for Insert of XMLType (ORA_XMLTYPE) + +Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special +requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For +example with a table like this; + + create table books (book_id number, book_xml XMLType); + +one can insert data using this code + + $SQL='insert into books values (1,:p_xml)'; + $xml= ' + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); + +In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. +This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. + +#### Binding Cursors + +Cursors can be returned from PL/SQL blocks, either from stored +functions (or procedures with OUT parameters) or +from direct `OPEN` statements, as shown below: + + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +The only special requirement is the use of `bind_param_inout()` with an +attribute hash parameter that specifies `ora_type` as `ORA_RSET`. +If you don't do that you'll get an error from the `execute()` like: +"ORA-06550: line X, column Y: PLS-00306: wrong number or types of +arguments in call to ...". + +Here's an alternative form using a function that returns a cursor. +This example uses the pre-defined weak (or generic) REF CURSOR type +SYS_REFCURSOR. This is an Oracle 9 feature. + + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); + + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } + +A cursor obtained from PL/SQL as above may be passed back to PL/SQL +by binding for input, as shown in this example, which explicitly +closes a cursor: + + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; + +It is not normally necessary to close a cursor +explicitly in this way. Oracle will close the cursor automatically +at the first client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to +the cursor handle from the PL/SQL statement handle delays the destruction +of the cursor handle for too long. This reference remains until the +PL/SQL handle is re-bound, re-executed or destroyed. + +See the `curref.pl` script in the Oracle.ex directory in the DBD::Oracle +source distribution for a complete working example. + +#### Fetching Nested Cursors + +Oracle supports the use of select list expressions of type REF CURSOR. +These may be explicit cursor expressions - `CURSOR(SELECT ...)`, or +calls to PL/SQL functions which return REF CURSOR values. The values +of these expressions are known as nested cursors. + +The value returned to a Perl program when a nested cursor is fetched +is a statement handle. This statement handle is ready to be fetched from. +It should not (indeed, must not) be executed. + +Oracle imposes a restriction on the order of fetching when nested +cursors are used. Suppose `$sth1` is a handle for a select statement +involving nested cursors, and `$sth2` is a nested cursor handle fetched +from `$sth1`. `$sth2` can only be fetched from while `$sth1` is +still active, and the row containing `$sth2` is still current in `$sth1`. +Any attempt to fetch another row from `$sth1` renders all nested cursor +handles previously fetched from `$sth1` defunct. + +Fetching from such a defunct handle results in an error with the message +`ERROR nested cursor is defunct (parent row is no longer current)`. + +This means that the `fetchall...` or `selectall...` methods are not useful +for queries returning nested cursors. By the time such a method returns, +all the nested cursor handles it has fetched will be defunct. + +It is necessary to use an explicit fetch loop, and to do all the +fetching of nested cursors within the loop, as the following example +shows: + + use DBI; + my $dbh = DBI->connect(...); + my $sth = $dbh->prepare(q{ + SELECT dname, CURSOR( + SELECT ename FROM emp + WHERE emp.deptno = dept.deptno + ORDER BY ename + ) FROM dept ORDER BY dname + }); + $sth->execute; + while ( my ($dname, $nested) = $sth->fetchrow_array ) { + print "$dname\n"; + while ( my ($ename) = $nested->fetchrow_array ) { + print " $ename\n"; + } + } + +The cursor returned by the function `sp_ListEmp` defined in the +previous section can be fetched as a nested cursor as follows: + + my $sth = $dbh->prepare(q{SELECT sp_ListEmp FROM dual}); + $sth->execute; + my ($nested) = $sth->fetchrow_array; + while ( my @row = $nested->fetchrow_array ) { ... } + +#### Pre-fetching Nested Cursors + +By default, DBD::Oracle pre-fetches rows in order to reduce the number of +round trips to the server. For queries which do not involve nested cursors, +the number of pre-fetched rows is controlled by the DBI database handle +attribute `RowCacheSize` (q.v.). + +In Oracle, server side open cursors are a controlled resource, limited in +number, on a per session basis, to the value of the initialization +parameter `OPEN_CURSORS`. Nested cursors count towards this limit. +Each nested cursor in the current row counts 1, as does +each nested cursor in a pre-fetched row. Defunct nested cursors do not count. + +An Oracle specific database handle attribute, `ora_max_nested_cursors`, +further controls pre-fetching for queries involving nested cursors. For +each statement handle, the total number of nested cursors in pre-fetched +rows is limited to the value of this parameter. The default value +is 0, which disables pre-fetching for queries involving nested cursors. + +# PL/SQL Examples + +Most of these PL/SQL examples come from: Eric Bartley . + + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ + + CREATE OR REPLACE PACKAGE plsql_example + IS + PROCEDURE proc_np; + + PROCEDURE proc_in ( + err_code IN NUMBER + ); + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ); + + FUNCTION func_np + RETURN VARCHAR2; + + END plsql_example; + / + + CREATE OR REPLACE PACKAGE BODY plsql_example + IS + PROCEDURE proc_np + IS + whoami VARCHAR2(20) := NULL; + BEGIN + SELECT USER INTO whoami FROM DUAL; + END; + + PROCEDURE proc_in ( + err_code IN NUMBER + ) + IS + BEGIN + RAISE_APPLICATION_ERROR(err_code, 'This is a test.'); + END; + + PROCEDURE proc_in_inout ( + test_num IN NUMBER, + is_odd IN OUT NUMBER + ) + IS + BEGIN + is_odd := MOD(test_num, 2); + END; + + FUNCTION func_np + RETURN VARCHAR2 + IS + ret_val VARCHAR2(20); + BEGIN + SELECT USER INTO ret_val FROM DUAL; + RETURN ret_val; + END; + + END plsql_example; + / + /* End PL/SQL for example package creation. */ + + use DBI; + + my($db, $csr, $ret_val); + + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; + + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; + + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; + + + + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). + + my $err_code = -20001; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); + + $csr->bind_param(":err_code", $err_code); + + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + + + + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. + + my $test_num = 5; + my $is_odd; + + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); + + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); + + $csr->bind_param_inout(":is_odd", \$is_odd, 1); + + # The execute will automagically update the value of $is_odd + $csr->execute; + + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + + + + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. + + my $whoami = ""; + + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); + + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; + + $db->disconnect; + +You can find more examples in the t/plsql.t file in the DBD::Oracle +source directory. + +Oracle 9.2 appears to have a bug where a variable bound +with bind_param_inout() that isn't assigned to by the executed +PL/SQL block may contain garbage. +See [http://www.mail-archive.com/dbi-users@perl.org/msg18835.html](http://www.mail-archive.com/dbi-users@perl.org/msg18835.html) + +## Avoid Using "SQL Call" + +Avoid using the "SQL Call" statement with DBD:Oracle as you might find that +DBD::Oracle will not raise an exception in some case. Specifically if you use +"SQL Call" to run a procedure all "No data found" exceptions will be quietly +ignored and returned as null. According to Oracle support this is part of the same +mechanism where; + + select (select * from dual where 0=1) from dual + +returns a null value rather than an exception. + +# CONTRIBUTING + +If you'd like DBD::Oracle to do something new or different the best way +to make that happen is to do it yourself and email to dbi-dev@perl.org a +patch of the source code (using 'diff' - see below) that shows the changes. + +## How to create a patch using Subversion + +The DBD::Oracle source code is maintained using Subversion (a replacement +for CVS, see [http://subversion.tigris.org/](http://subversion.tigris.org/)). To access the source +you'll need to install a Subversion client. Then, to get the source +code, do: + + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + +If it prompts for a username and password use your perl.org account +if you have one, else just 'guest' and 'guest'. The source code will +be in a new subdirectory called `trunk`. + +To keep informed about changes to the source you can send an empty email +to dbd-oracle-changes-subscribe@perl.org after which you'll get an email with the +change log message and diff of each change checked-in to the source. + +After making your changes you can generate a patch file, but before +you do, make sure your source is still upto date using: + + svn update + +If you get any conflicts reported you'll need to fix them first. +Then generate the patch file from within the `trunk` directory using: + + svn diff > foo.patch + +Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. + +## How to create a patch without Subversion + +Unpack a fresh copy of the distribution: + + tar xfz DBD-Oracle-1.40.tar.gz + +Rename the newly created top level directory: + + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + +Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you want. + +Test your changes and then remove all temporary files: + + make test && make distclean + +Go back to the directory you originally unpacked the distribution: + + cd .. + +Unpack _another_ copy of the original distribution you started with: + + tar xfz DBD-Oracle-1.40.tar.gz + +Then create a patch file by performing a recursive `diff` on the two +top level directories: + + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + +## Speak before you patch + +For anything non-trivial or possibly controversial it's a good idea +to discuss (on dbi-dev@perl.org) the changes you propose before +actually spending time working on them. Otherwise you run the risk +of them being rejected because they don't fit into some larger plans +you may not be aware of. + +## GitHub repository + +A git mirror of the subversion is also available at +`https://github.com/yanick/DBD-Oracle`. + +# Oracle Related Links + +# WHICH VERSION OF DBD::ORACLE IS FOR ME? + +From version 1.25 onwards DBD::Oracle only support Oracle clients +9.2 or greater. Support for ProC connections was dropped in 1.29. + +If you are still stuck with an older version of Oracle or its client you might want to look at the table below. + + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + +As there are dozens of different versions of Oracle's clients this +list does not include all of them, just the major released versions of +Oracle. + +Note that one can still connect to any Oracle version with the older +DBD::Oracle versions the only problem you will have is that some of +the newer OCI and Oracle features available in later DBD::Oracle +releases will not be available to you. + +So to make a short story a little longer: + +- 1 + +If you are using Oracle 7 or early 8 DB and you can manage to get a 9 client and you can use +any DBD::Oracle version. + +- 2 + +If you have to use an Oracle 7 client then DBD::Oracle 1.17 should work + +- 3 + +Same thing for 8 up to R2, use 1.17, if you are lucky and have the right patch-set you might +go with 1.18. + +- 4 + +For 8iR3 you can use any of the DBD::Oracle versions up to 1.21. Again this depends on your +patch-set, If you run into trouble go with 1.19 + +- 5 + +After 9.2 you can use any version you want. + +- 6 + +It seems that the 10g client can only connect to 9 and 11 DBs while the 9 can go back to 7 +and even get to 10. I am not sure what the 11g client can connect to. + +# BUGS AND LIMITATIONS + +There is a known problem with the 11.2g Oracle client and the +`DBMS_LOB.GETLENGTH()` PL/SQL function. +See [https://rt.cpan.org/Public/Bug/Display.html?id=69350](https://rt.cpan.org/Public/Bug/Display.html?id=69350) for the details. + +# SEE ALSO + +- [DBI](http://search.cpan.org/perldoc?DBI) + +http://search.cpan.org/~timb/DBD-Oracle/MANIFEST for all files in +the DBD::Oracle source distribution including the examples in the +Oracle.ex directory + +- DBD::Oracle Tutorial + +http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-oracle.html + +- Oracle Instant Client + +http://www.oracle.com/technology/tech/oci/instantclient/index.html + +- Oracle on Linux + +http://www.ixora.com.au/ + +- Free Oracle Tools and Links + +ora_explain supplied and installed with DBD::Oracle. + +http://www.orafaq.com/ + +http://vonnieda.org/oracletool/ + +- Commercial Oracle Tools and Links + +Assorted tools and references for general information. +No recommendation implied. + +http://www.platinum.com + +http://www.SoftTreeTech.com + +Also PL/Vision from RevealNet and Steven Feuerstein, and +"Q" from Savant Corporation. + +# AUTHORS + +DBI by Tim Bunce [http://www.tim.bunce.name](http://www.tim.bunce.name). + +The original `DBD::Oracle` was by Tim Bunce. +Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the +auspice of the Pythian Group ([http://www.pythian.com](http://www.pythian.com)). + +# ACKNOWLEDGEMENTS + +A great many people have helped with DBD::Oracle over the 17 years +between 1994 and 2011. Far too many to name, but we thank them all. +Many are named in the Changes file. + +# COPYRIGHT + +The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. +The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The Pythian Group). Canada. +The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. + +The DBD::Oracle module is free open source software; you can +redistribute it and/or modify it under the same terms as Perl 5. + +# AUTHORS + +- * + +Tim Bunce + +- * + +John Scoles + +- * + +Yanick Champoux + +# COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/dist.ini b/dist.ini deleted file mode 100644 index 78533959..00000000 --- a/dist.ini +++ /dev/null @@ -1,26 +0,0 @@ -name = DBD-Oracle -author = Tim Bunce -author = John Scoles -author = Yanick Champoux -license = Perl_5 -copyright_holder = Tim Bunce -copyright_year = 1994 - -version = 1.43_00 - -[Authority] -authority=cpan:PYTHIAN - -[MakeMaker::Custom] - -[@Filter] --bundle=@YANICK --remove=Author::YANICK::NextSemanticVersion --remove=ModuleBuild --remove=Authority --remove=Signature --remove=UploadToCPAN --remove=Twitter --remove=Test::Compile - -[FakeRelease] diff --git a/err_bind/err_bind_param_inout_overrun_bug.msg b/err_bind/err_bind_param_inout_overrun_bug.msg deleted file mode 100644 index 83d9001f..00000000 --- a/err_bind/err_bind_param_inout_overrun_bug.msg +++ /dev/null @@ -1,108 +0,0 @@ -From dbi-users-return-215-Tim.Bunce=ig.co.uk@perl.org Mon Feb 5 23:03:29 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id XAA01289; Mon, 5 Feb 2001 23:03:27 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <06769-16@oink>; Fri, 6 Feb 1970 00:01:15 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 981413584:20:24069:0; Mon, 05 Feb 2001 22:53:04 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-2.mail.demon.net - id aa2024004; 5 Feb 2001 22:53 GMT -Received: (qmail 6267 invoked by uid 508); 5 Feb 2001 22:52:23 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6247 invoked from network); 5 Feb 2001 22:52:22 -0000 -Received: from seeme.dare.feddata.com (38.186.101.66) by tmtowtdi.perl.org - with SMTP; 5 Feb 2001 22:52:22 -0000 -Received: by seeme.dare.feddata.com; id OAA05466; - Mon, 5 Feb 2001 14:55:56 -0800 (PST) -Received: from ifyou.dare.feddata.com(38.186.101.111) by seeme.dare.feddata.com - via smap (4.1) id xma005448; Mon, 5 Feb 01 14:55:39 -0800 -Sender: oscar@dare.feddata.com -Message-ID: <3A7F2FB0.A1507582@pasadena.feddata.com> -Date: Mon, 05 Feb 2001 14:56:48 -0800 -From: Oscar DeMartino -Organization: Federal Data Corporation -X-Mailer: Mozilla 4.61 [en] (X11; U; SunOS 5.6 sun4u) -X-Accept-Language: en -MIME-Version: 1.0 -To: dbi-users@perl.org -Subject: Undetected error - Binding and Stored Procedures -Content-Type: multipart/alternative; - boundary="------------E1028F7A8304BE268EB8F67B" -Status: RO -Content-Length: 2042 -Lines: 66 - ---------------E1028F7A8304BE268EB8F67B -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -I am running Oracle 8.1.5 and am using many stored procedures. We -use returned cursors, and individual values. The problem is, when -a stored procedure is executed and the specified bound variable has not -be declared large enough to hold the returned value subsequent -bound variables do not get set and I cannot find any way to -automatically detect this. - -Example: - -The stored procedure takes 1-input value and returns three string -values. - -the stored procedure is prepared , so I get the statement handle. - -I bind the input variable, and then bind the three output variables (1, -2, & 3) -as 100 character strings. - -I then execute the statment handle. - -There do not appear to be any errors, after checking the returned value -(for the execute call), -and ->err and ->errstr are clean. - -variable 1 has the correct returned value. -BUT, output variable 2 & 3, have no value. - ------- -Executing the stored procedure using sqlplus (sql command line -interface) indicated: - -What really occured is that the returned output variables 1 & 3 were -under 100 characters long -output variable 2 was 120 characters long - ---------- - -I know I could make all output variables the max size allowed in the -database field -but this would seem to waste space in the perl code. Since the field in - -the database -is simply defined as a varchar2 with no size limitation (upto 32767). - ------ -Am I missing something about detecting that variables 2 & 3 did not get -stored correctly -by DBI::Oracle?? - - - --- -Oscar "Fred" DeMartino FFFFF DDDD CCC -320 N. Halstead Ave. Ste #160 F D D C C -Pasadena, CA 91107 FFF D D C -e-mail: Oscar.DeMartino@pasadena.feddata.com F D D C -Phone: (626)306-6649 F D D C C -Federal Data Corporation F DDDD CCC - - - ---------------E1028F7A8304BE268EB8F67B-- - diff --git a/err_bind/err_bindarrays.msg b/err_bind/err_bindarrays.msg deleted file mode 100644 index 8ca7a5d3..00000000 --- a/err_bind/err_bindarrays.msg +++ /dev/null @@ -1,241 +0,0 @@ -From cturner@redhat.com Tue Mar 27 06:01:56 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id GAA19714; Tue, 27 Mar 2001 06:01:56 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <13771-3@oink>; - Fri, 27 Mar 1970 06:00:50 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985668014:20:27605:3; Tue, 27 Mar 2001 04:40:14 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ab2125244; 27 Mar 2001 4:39 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id XAA32289 - for ; Mon, 26 Mar 2001 23:39:38 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2R4bvT12929; Mon, 26 Mar 2001 23:37:57 -0500 -Sender: cturner@redhat.com -To: Tim.Bunce@ig.co.uk -Subject: DBD::Oracle and OCI bound arrays -From: Chip Turner -Date: 26 Mar 2001 23:37:57 -0500 -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 980 -Lines: 29 - - -Hey Tim, - -The need to have true OCI bound arrays for DBD::Oracle has come up, -and it looks like I get the fun job of implementing them. Basically, -this will allow DBD::Oracle to do something the DCOracle python -library does. The idea is: - -my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -my @c1 = 'aa' .. 'zz'; -my @c2 = 'aaa' .. 'azz'; -$sth->execute(\@c1, \@c2); - -In other words, it populates the table with a single execute call, -passing two (or more) equally sized arrays in as references for bound -parameters. This has the potential to save a good amount of time, -especially for large datasets. - -This would pretty much be a proprietary extension for Oracle, though -similar uses could be done in other DBD's. - -Just thought I'd let you know what I was intending to do, and to see -if you had any interest in receiving it as a patch after I'm done. - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Tue Mar 27 09:29:48 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id JAA20809; Tue, 27 Mar 2001 09:29:42 +0100 (BST) -Date: Tue, 27 Mar 2001 09:29:41 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim.Bunce@ig.co.uk, dbi-dev@perl.org -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010327092941.D20616@ig.co.uk> -References: -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Mon, Mar 26, 2001 at 11:37:57PM -0500 -Content-Length: 1570 -Lines: 39 - -On Mon, Mar 26, 2001 at 11:37:57PM -0500, Chip Turner wrote: -> -> Hey Tim, -> -> The need to have true OCI bound arrays for DBD::Oracle has come up, -> and it looks like I get the fun job of implementing them. Basically, -> this will allow DBD::Oracle to do something the DCOracle python -> library does. The idea is: -> -> my $sth = $dbh->prepare("INSERT INTO FooBar (c1, c2) VALUES (?, ?)"); -> my @c1 = 'aa' .. 'zz'; -> my @c2 = 'aaa' .. 'azz'; -> $sth->execute(\@c1, \@c2); -> -> In other words, it populates the table with a single execute call, -> passing two (or more) equally sized arrays in as references for bound -> parameters. This has the potential to save a good amount of time, -> especially for large datasets. -> -> This would pretty much be a proprietary extension for Oracle, though -> similar uses could be done in other DBD's. -> -> Just thought I'd let you know what I was intending to do, and to see -> if you had any interest in receiving it as a patch after I'm done. - -I would *urge* you to discuss the implementation with me *before* -you get very far cutting code. - -And anyway, I think someone's already done much or all of the work. -Dig around in the dbi-dev archives. If you can't find the discussion -let me know. If you do, then ask them (via the dbi-dev list) what -the status is. - -I'm planning to make a DBI release next week and, hopefully, a -DBD::Oracle release the week after to cleare a backlog of patches I -have queued up. After that I'll be looking to add in the work of the -other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -Tim. - -From cturner@redhat.com Wed Mar 28 02:01:21 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id CAA27336; Wed, 28 Mar 2001 02:01:21 +0100 (BST) -Received: from 194.217.242.7 by oink with SMTP (PP) id <17151-9@oink>; - Sat, 28 Mar 1970 01:59:47 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 985739868:20:27318:0; Wed, 28 Mar 2001 00:37:48 GMT -Received: from host154.207-175-42.redhat.com ([207.175.42.154]) - by punt-2.mail.demon.net id ac2119835; 28 Mar 2001 0:37 GMT -Received: from japh.meridian.redhat.com (IDENT:root@japh.meridian.redhat.com [207.175.42.27]) - by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id TAA10445 - for ; Tue, 27 Mar 2001 19:37:35 -0500 -Received: (from cturner@localhost) by japh.meridian.redhat.com (8.11.0/8.11.0) - id f2S0ZoJ20115; Tue, 27 Mar 2001 19:35:50 -0500 -Sender: cturner@redhat.com -To: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -References: <20010327092941.D20616@ig.co.uk> -From: Chip Turner -Date: 27 Mar 2001 19:35:50 -0500 -In-Reply-To: <20010327092941.D20616@ig.co.uk> -Message-ID: -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Status: A -Content-Length: 1495 -Lines: 35 - -Tim Bunce writes: - -> I would *urge* you to discuss the implementation with me *before* -> you get very far cutting code. - -Unfortunately, it's a little late for this; I've mostly finished the -change (at least, enough for our needs), except for some review and -cleanups. It seems to work quite well (400 times faster than repeated -looping over a dataset) and passes all of DBD::Oracle's test suite. - -> And anyway, I think someone's already done much or all of the work. -> Dig around in the dbi-dev archives. If you can't find the discussion -> let me know. If you do, then ask them (via the dbi-dev list) what -> the status is. - -I checked as you suggest, but couldn't find any code, just discussion -of it. I'll check again, but it didn't seem that the person had put -it anywhere I could get at it. - -> I'm planning to make a DBI release next week and, hopefully, a -> DBD::Oracle release the week after to cleare a backlog of patches I -> have queued up. After that I'll be looking to add in the work of the -> other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). - -If you would like, the patch will probably be suitable for inclusion -by then, if you want it in by the next release. Should there be any -problems with it or its implementation, I'd be glad to clean it up if -you have interest in it (if not, that's cool too; we need it soon, -though, either way). - -Chip - --- -Chip Turner cturner@redhat.com - RHN Web Engineer - -From timbo Wed Mar 28 11:51:58 2001 -Return-Path: -Received: by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id LAA00444; Wed, 28 Mar 2001 11:51:51 +0100 (BST) -Date: Wed, 28 Mar 2001 11:51:51 +0100 -From: Tim Bunce -To: Chip Turner -Cc: Tim Bunce -Subject: Re: DBD::Oracle and OCI bound arrays -Message-ID: <20010328115151.D29769@ig.co.uk> -References: <20010327092941.D20616@ig.co.uk> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: ; from Chip Turner on Tue, Mar 27, 2001 at 07:35:50PM -0500 -Content-Length: 1786 -Lines: 40 - -On Tue, Mar 27, 2001 at 07:35:50PM -0500, Chip Turner wrote: -> Tim Bunce writes: -> -> > I would *urge* you to discuss the implementation with me *before* -> > you get very far cutting code. -> -> Unfortunately, it's a little late for this; I've mostly finished the -> change (at least, enough for our needs), except for some review and -> cleanups. It seems to work quite well (400 times faster than repeated -> looping over a dataset) and passes all of DBD::Oracle's test suite. - -I trust you've added some more tests for your new functionality! - -> > And anyway, I think someone's already done much or all of the work. -> > Dig around in the dbi-dev archives. If you can't find the discussion -> > let me know. If you do, then ask them (via the dbi-dev list) what -> > the status is. -> -> I checked as you suggest, but couldn't find any code, just discussion -> of it. I'll check again, but it didn't seem that the person had put -> it anywhere I could get at it. - -You could always ask them (CC me). - -> > I'm planning to make a DBI release next week and, hopefully, a -> > DBD::Oracle release the week after to cleare a backlog of patches I -> > have queued up. After that I'll be looking to add in the work of the -> > other guy (whose also implemented it for DBD::DB2 and DBD::ODBC). -> -> If you would like, the patch will probably be suitable for inclusion -> by then, if you want it in by the next release. Should there be any -> problems with it or its implementation, I'd be glad to clean it up if -> you have interest in it (if not, that's cool too; we need it soon, -> though, either way). - -Thanks for the clean-up offer. Send it to me after I make the next -DBD::Oracle release (as a fresh patch over that version please - but -there shouldn't be too many changes). - -Tim. - diff --git a/err_bind/err_bindclobleak.msg b/err_bind/err_bindclobleak.msg deleted file mode 100644 index 1a31c760..00000000 --- a/err_bind/err_bindclobleak.msg +++ /dev/null @@ -1,58 +0,0 @@ -From PGWeiss@arity.com Thu Mar 9 09:51:45 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id JAA14948; Thu, 9 Mar 2000 09:51:43 GMT -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <27566-0@oink>; Mon, 9 Mar 1970 10:51:10 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 952595299:20:10439:68; Thu, 09 Mar 2000 09:48:19 GMT -Received: from image.arity.com ([140.239.104.130]) by punt-2.mail.demon.net - id aa2010598; 9 Mar 2000 9:47 GMT -Received: by image.arity.com with Internet Mail Service (5.5.2650.21) - id ; Thu, 9 Mar 2000 04:51:44 -0500 -Message-ID: -From: "Paul G. Weiss" -To: Perl-Win32-Database Mailing List , - "'Tim Bunce'" -Subject: Another CLOB related DBD::Oracle bug -Date: Thu, 9 Mar 2000 04:51:41 -0500 -MIME-Version: 1.0 -X-Mailer: Internet Mail Service (5.5.2650.21) -Content-Type: text/plain; charset="iso-8859-1" -Status: RO -Content-Length: 689 -Lines: 32 - -Binding a parameter to type ORA_CLOB causes a leak. -Consider: - -for (1..10000) -{ - for (1..100) - { - my $sth = $db->prepare('update item set descr = ? where id = ?'); - if ($leak) - { - $sth->bind_param(1, $descr, {ora_type => ORA_CLOB, -ora_field=>'DESCR'}); - $sth->bind_param(2, 12); - $sth->execute; - } - else - { - $sth->execute($descr,12); - } - } - sleep 1; -} - - -With $leak set to 1, i.e. binding the parameters explicitly the -program leaks. With $leak set to 0 it does not (but then I can't -set descr to anything greater than 4K nor can I set it to the -empty string). - -Is there a patch? - --P - diff --git a/err_bind/err_bindnullhash.msg b/err_bind/err_bindnullhash.msg deleted file mode 100644 index d9a98b9a..00000000 --- a/err_bind/err_bindnullhash.msg +++ /dev/null @@ -1,77 +0,0 @@ -From dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org Thu Jul 11 17:49:35 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g6BGnYH11008 - for ; Thu, 11 Jul 2002 17:49:34 +0100 (BST) - (envelope-from dbi-users-return-12580-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 11 Jul 2002 17:49:34 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1026401921:10:09249:41; Thu, 11 Jul 2002 15:38:41 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1124337; 11 Jul 2002 15:38 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id B567C2BF65 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 347792BF62 - for ; Thu, 11 Jul 2002 11:38:05 -0400 (EDT) -Received: (qmail 95914 invoked by uid 1005); 11 Jul 2002 15:38:04 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 95896 invoked by uid 76); 11 Jul 2002 15:38:04 -0000 -Received: from ironmail1.cc.lehigh.edu (HELO ironmail1.cc.lehigh.edu) (128.180.39.26) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Thu Jul 11 15:38:04 2002 -0000 -Received: from ([128.180.39.20]) - by ironmail1.cc.lehigh.edu with ESMTP with TLS; - Thu, 11 Jul 2002 11:35:06 -0400 (EDT) -Received: from lawrencework (pc-lfn0.dept.Lehigh.EDU [128.180.52.51]) - by rain.CC.Lehigh.EDU (8.12.4/8.12.4) with SMTP id g6BFZ6rr022463 - for ; Thu, 11 Jul 2002 11:35:06 -0400 -Message-ID: <0a0401c228f0$93feda10$3334b480@lawrencework> -From: "Phil R Lawrence" -To: -References: <083b01c22824$70357340$3334b480@lawrencework> <20020711140937.A568@dansat.data-plan.com> -Subject: Re: error msg suggestion -Date: Thu, 11 Jul 2002 11:35:20 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2600.0000 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -X-Status: A -Content-Length: 636 -Lines: 21 - -Tim Bunce wrote: -> Binding an undef should work and be treated as a NULL. -> -> Probably a bug in your code or the driver. But you didn't -> say which driver. - -Hmmm. quite right, undefs do bind as NULL. However, in this case I am -binding $hash{non-existent-key}, which autoinstantiates to an undef, and looks -like this in the trace: - undef (magic-sg:y) - -Of course it was my dumb fault for having the wrong key for lookup, but -nonetheless, perhaps this should work the same as a normal undef. - -# $DBI::VERSION = "1.14"; -# $DBD::ODBC::VERSION = '0.28'; -$DSN = 'driver=Microsoft Access Driver (*.mdb);dbq=StudyManager.mdb'; - -Thanks, -Phil - - diff --git a/err_bind/err_trailingblank.msg b/err_bind/err_trailingblank.msg deleted file mode 100644 index cdf34a32..00000000 --- a/err_bind/err_trailingblank.msg +++ /dev/null @@ -1,345 +0,0 @@ -From dbi-users-bounce@isc.org Mon May 1 21:12:02 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id VAA16051; Mon, 1 May 2000 21:12:00 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <14295-42@oink>; Fri, 1 May 1970 21:06:08 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 957208278:10:19133:4; Mon, 01 May 2000 19:11:18 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1123094; 1 May 2000 19:11 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id B3CCF3FAA; - Mon, 1 May 2000 12:10:53 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Mon, 01 May 2000 12:05:42 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A70763E34 - for ; Mon, 1 May 2000 12:05:30 -0700 (PDT) -Received: from scotth.emsphone.com (scotth.emsphone.com [199.67.51.179]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA25897 - for ; - Mon, 1 May 2000 12:05:30 -0700 (PDT) env-from (shildret@scotth.emsphone.com) -Received: (from shildret@localhost) by scotth.emsphone.com (8.9.3/8.9.3) - id OAA50011 for dbi-users@isc.org; - Mon, 1 May 2000 14:05:48 -0500 (CDT) (envelope-from shildret) -Message-ID: -X-Mailer: XFMail 1.4.0 on FreeBSD -X-Priority: 3 (Normal) -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 8bit -MIME-Version: 1.0 -Resent-Date: Thu, 29 Jul 1999 22:07:08 +0100 -Resent-Message-Id: <19990729220708.G17723@ig.co.uk> -Resent-From: Tim Bunce -Resent-To: Tim Bunce -Date: Mon, 01 May 2000 14:05:48 -0500 (CDT) -Sender: shildret@scotth.emsphone.com -From: "Scott T. Hildreth" -To: "dbi-users@isc.org" -Subject: FW: Oracle & Trailing Blanks - possible change in DBD::Oracle -Resent-Sender: shildret@scotth.emsphone.com -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 3885 -Lines: 94 - - -Here is the help, I got regarding the trailing spaces. - ------FW: <19990729220708.G17723@ig.co.uk>----- - -Date: Thu, 29 Jul 1999 22:07:08 +0100 -From: Tim Bunce -To: Tim Bunce -Subject: Oracle & Trailing Blanks - possible change in DBD::Oracle -Cc: "Scott T. HIldreth" , - dbi-users@isc.org - - *** From dbi-users -- To unsubscribe, see the end of this message. *** - -On Thu, Jul 29, 1999 at 09:49:38PM +0100, Tim Bunce wrote: -> *** From dbi-users -- To unsubscribe, see the end of this message. *** -> -> On Thu, Jul 29, 1999 at 09:33:55AM -0500, Scott T. HIldreth wrote: -> > -> > Hi all, I wonder if someone can let me know if I got this right. -> > I have a key to match which can contain trailing blanks. The -> > field in the database is CHAR(18). If I match the key with -> > sqlplus, Oracle finds a match, with or without the trailing -> > blank. When I do an sth->execute( $key ), the key is not -> > found. I abstract the key with substr, so the trailing blank -> > is in the key, but no match is found. Do I need to place qoutes -> > around the value in $key? -> -> Somewhat hiddedn in the Oraperl.pm docs it says this: -> -> --- -> B Substitution variables are now bound as type 1 (VARCHAR2) -> and not type 5 (STRING) by default. This can alter the behaviour of -> SQL code which compares a char field with a substitution variable. -> See the String Comparison section in the Datatypes chapter of the -> Oracle OCI manual for more details. -> -> You can work around this by using DBD::Oracle's ability to specify -> the Oracle type to be used on a per field basis: -> -> $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) -> $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); -> $csr->bind_param(1, $value_x, $char_attrib); -> $csr->bind_param(2, $value_y, $char_attrib); -> ora_bind($csr); # bind with no parameters since we've done bind_param()'s -> --- -> -> Ignoring the Oraperl specifics there the key point is to use -> -> $csr->bind_param($idx, $value, { ora_type => 5 }); -> -> I'll add something to the DBD::Oracle docs. - -[You'll still need to blank-pad the string.] - -Looking at this issue again I've discovered that the key issue is that -type 1 strips trailing blanks whilst type 5 doesn't. - -I'rather m concerned by this. Since I'm against the DBI changing the -data in any way on principle and since Oraperl used to use type 5 -I'm strongly considering changing DBD::Oracle 'back' to using type 5. - -This would only affect anyone who relies on placeholders having -trailing blanks stripped off. (I'll provide a way to alter the -default with a single statement and/or env var for anyone affected). - -If that's you - speak up now! - -Tim. - ------------------------------------------------------------------------------- -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of -'unsubscribe'. ------------------------------------------------------------------------------- - - ---------------End of forwarded message------------------------- - ----------------------------------- -E-Mail: Scott T. Hildreth -Date: 01-May-00 -Time: 14:04:41 ----------------------------------- - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - -From joshua.horton@mail.tju.edu Fri May 23 07:43:09 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.6/8.12.6) with ESMTP id h4N6UY7T061880 - for ; Fri, 23 May 2003 07:43:09 +0100 (BST) - (envelope-from joshua.horton@mail.tju.edu) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 23 May 2003 07:43:09 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1053631164:10:02298:54; Thu, 22 May 2003 19:19:24 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116141; 22 May 2003 19:19 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id BD31E21C13C - for ; Thu, 22 May 2003 15:18:30 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail.tju.edu (fw-tr16.tju.edu [147.140.233.16]) - by dolly1.pobox.com (Postfix) with ESMTP id 615A521C06D - for ; Thu, 22 May 2003 15:18:22 -0400 (EDT) -Received: from PCSE447.tjh.tju.edu by mail.tju.edu for Tim.Bunce@pobox.com; Thu, 22 May 2003 15:17:54 -0400 -Message-Id: <031301c32096$de68f6f0$2310ae0a@PCSE447> -From: "Joshua Horton" -To: -Subject: Re: :Oracle and Oracle 9.2? -Date: Thu, 22 May 2003 15:18:03 -0400 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 5.50.4807.1700 -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 3511 -Lines: 99 - -Re: :Oracle and Oracle 9.2? - ----------------------------------------------------------------------------- ----- - - a.. From: Tim Bunce - b.. Subject: Re: :Oracle and Oracle 9.2? - c.. Date: Tue, 15 Apr 2003 07:36:55 -0700 - ----------------------------------------------------------------------------- ----- - -I'd appreciate it if other people with Oracle 9.2.x could let me -know if it passed or failed for them and what their exact oracle -version (four digits) and platform (operating system) is. - -Thanks. - -Tim. - -On Fri, Apr 04, 2003 at 01:48:36PM +0200, Smejkal Petr wrote: -> I have the same experience on Linux however on Windows all tests passes -(I'm not -> sure if it is related to different Oracle version - test of windows Perl -against -> Linux Oracle is OK). -> -> Linux Oracle: 9.2.0.2 -> Windows Oracle: 9.2.0.1 -> DBI: 1.35 -> DBD::Oracle: 1.14 -> -> -- Petr Smejkal -> -- Business Systems Analyst / Country IT Cz/Sk -> -- +420 284 059 639 -> -> > -----Original Message----- -> > From: Tom Malaher [mailto:[EMAIL PROTECTED] -> > Sent: Friday, April 04, 2003 1:35 AM -> > To: [EMAIL PROTECTED] -> > Subject: DBD::Oracle and Oracle 9.2? -> > -> > -> > My sysadmin is trying to install DBD::Oracle on a Solaris box running -> > Oracle 9.2. -> > -> > The ph_type.t test is failing with -> > -> > PERL_DL_NONLAZY=1 ./perl "-MExtUtils::Command::MM" "-e" -> > "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -> > t/base.......ok -> > t/cursor.....ok -> > t/general....ok -> > t/long.......ok -> > t/meta.......ok -> > t/ph_type....NOK 12 expected 'trailing' but got 'trailing ' -> > for VARCHAR2 -> > t/ph_type....FAILED test 12 -> > Failed 1/19 tests, 94.74% okay -> > t/plsql......ok -> > t/reauth.....skipped -> > all skipped: no reason given -> > t/select.....ok -> > Failed Test Stat Wstat Total Fail Failed List of Failed -> > -------------------------------------------------------------- -> > ----------------- -> > t/ph_type.t 19 1 5.26% 12 -> > 1 test skipped. -> > Failed 1/9 test scripts, 88.89% okay. 1/314 subtests failed, -> > 99.68% okay. -> > *** Error code 29 -> > make: Fatal error: Command failed for target `test_static' -> > -> > Is there a known problem with DBD::Oracle and Oracle 9.x? -> > Has Oracle changed the behavior of trailing spaces in VARCHAR2 fields? -> > -> > I've run the same test script on an oracle 8 installation -> > using DBD::Oracle 1.06 and DBI 1.14, and it works fine (no trailing -> > space is returned). -> > -> > Tom -> > -My config:HP-UX 11.11 (64-bit) on rp5470 2x733 5GB RAMOracle 9.2.0.2.0 -Enterprise Edition (64-bit)Perl 5.8.0 custom compiled with -./Configure -Duse64bitall -Ubincompat5005 -Duselargefiles -Dprefix=/opt/perl -5 ; all other options defaultDBI-1.32 all passed some skippedDBD-Oracle-1.14 -: PERL_DL_NONLAZY=1 /opt/perl5/bin/perl "-MExtUtils::Command::MM" -"-e" "test_harness(0, 'blib/lib', 'blib/arch')" -t/*.tt/base.......okt/cursor.....okt/general....okt/long.......okt/meta..... -..okt/ph_type....ok 11/19 expected 'trailing' but got 'trailing ' for -VARCHAR2t/ph_type....FAILED test 12 Failed 1/19 tests, 94.74% -okayt/plsql......okt/reauth.....skipped all skipped: no reason -givent/select.....okFailed Test Stat Wstat Total Fail Failed List of -Failed---------------------------------------------------------------------- --------------------------------------------------------t/ph_type.t -19 1 5.26% 121 test skipped.Failed 1/9 test scripts, 88.89% okay. -1/314 subtests failed, 99.68% okay.*** Error exit code 2Stop.Thanks,Josh -Horton - - -From nobody@fsck.com Tue Dec 30 14:33:50 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hBUEWNnP026077 - for ; Tue, 30 Dec 2003 14:33:50 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Dec 2003 14:33:50 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AbJwa-0003ua-H6; - Tue, 30 Dec 2003 13:29:56 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AbJwa-0003ua-H6 - for pobox@dbi.demon.co.uk; Tue, 30 Dec 2003 13:29:56 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 56DAD4C6 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3B3564C8 - for ; Tue, 30 Dec 2003 08:29:55 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 30 Dec 2003 08:29:54 -0500 (EST) -Received: (qmail 10988 invoked by uid 225); 30 Dec 2003 13:29:53 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 10984 invoked by alias); 30 Dec 2003 13:29:52 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 30 Dec 2003 05:29:41 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 8760D11153; Tue, 30 Dec 2003 08:29:37 -0500 (EST) -Subject: [cpan #4786] Oracle 9.2.0.0 fails a test in ph_types.t -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4786 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -To: "AdminCc of cpan Ticket #4786": ; -Date: Tue, 30 Dec 2003 08:29:37 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,SUPERLONG_LINE,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -Content-Length: 888 -Lines: 11 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -Assuming that ORA_OCI() gets set correctly when compiling against 9.2, the attached patch will work. I also tried this in SQL*Plus and was able to insert a trailing space into a VARCHAR2. (I replicated the test in ph_types.t). - -I did not test my patch as I installed DBD::Oracle 1.14 by setting the chops_spaces value in %test_info to 0. When I did that, everything installed fine. However, I didn't think that my solution was the best for the module, so I figured ORA_OCI should do the trick. - -I'm running Perl5.8.0 for Solaris2.9 going against the full Oracle build for 9.2. (I did not run into this issue, surprisingly, on Redhat9 running Perl 5.8.2, but I built against Oracle 9.1 there ...) - diff --git a/err_build/err_aix64.msg b/err_build/err_aix64.msg deleted file mode 100644 index f952e29e..00000000 --- a/err_build/err_aix64.msg +++ /dev/null @@ -1,142 +0,0 @@ -From SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com Fri Jan 7 16:11:33 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j07GAqfa044155 - for ; Fri, 7 Jan 2005 16:11:32 GMT - (envelope-from SRS0=KVnF=PW=perl.org=dbi-users-return-25388-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Fri, 07 Jan 2005 16:11:32 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CmvQB-0003Po-Kf; - Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CmvQB-0003Po-Kf - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CmvQA-0002zW-VM - for pobox@data-plan.com; Fri, 07 Jan 2005 14:48:59 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 49778102ACC; - Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 384E5FF808 - for ; Fri, 7 Jan 2005 09:48:58 -0500 (EST) -Received-SPF: pass (boggle.pobox.com: domain of dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25388-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by boggle.pobox.com (Postfix) with SMTP id A74B8F4090 - for ; Fri, 7 Jan 2005 09:48:57 -0500 (EST) -Received: (qmail 2690 invoked by uid 514); 7 Jan 2005 14:48:56 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 2622 invoked from network); 7 Jan 2005 14:48:55 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 7 Jan 2005 14:48:55 -0000 -Received: (qmail 13078 invoked by uid 225); 7 Jan 2005 14:48:54 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 13048 invoked by alias); 7 Jan 2005 14:48:51 -0000 -X-Spam-Status: No, hits=-4.6 required=8.0 - tests=BAYES_00,HTML_MESSAGE,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: neutral (x1.develooper.com: local policy) -Received: from outmx020.isp.belgacom.be (HELO outmx020.isp.belgacom.be) (195.238.2.201) - by la.mx.develooper.com (qpsmtpd/0.28) with ESMTP; Fri, 07 Jan 2005 06:48:38 -0800 -Received: from outmx020.isp.belgacom.be (localhost [127.0.0.1]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmOgS020070 - for ; Fri, 7 Jan 2005 15:48:24 +0100 - (envelope-from ) -Received: from relaytwo.roularta.be (smtprelaytwo.roularta.be [194.78.177.23]) - by outmx020.isp.belgacom.be (8.12.11/8.12.11/Skynet-OUT-2.22) with ESMTP id j07EmMDA020034 - for ; Fri, 7 Jan 2005 15:48:22 +0100 - (envelope-from ) -Received: from rmgexch01.RMG.be ([89.0.35.150]) by roesfront3.RMG.be with Microsoft SMTPSVC(5.0.2195.6713); - Fri, 7 Jan 2005 15:47:50 +0100 -X-MimeOLE: Produced By Microsoft Exchange V6.5.7226.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----_=_NextPart_001_01C4F4C7.EE810087" -Subject: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Date: Fri, 7 Jan 2005 15:48:21 +0100 -Message-ID: -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: A succesfull 64-bit build of Perl-DBI-DBD:Oracle on IBM AIX 5.2 -Thread-Index: AcT0x+Y4G1R3vbX6Rh+QdPyNy/10eQ== -From: -To: -X-OriginalArrivalTime: 07 Jan 2005 14:47:50.0598 (UTC) FILETIME=[DC5D2E60:01C4F4C7] -Status: RO -Content-Length: 1678 -Lines: 62 - -------_=_NextPart_001_01C4F4C7.EE810087 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - -Hi,=20 -=20 -I finally succeeded in installing a 64bit build of Perl and its modules -for Oracle 64-bit. We were running in 32bit but integrating Proc and -cobols in our perl scripts only worked when we changed environments to -64bit causing problems for the oracle connections in perl. It's nothing -special, no editing of makefiles ... I can't believe I lost so much time -on this one ;) ( Now that I look back to my problems, they were probably -caused by using a wrong perl build for compiling the modules, Aix has -its default perl now under /bin.. stupid me )=20 -=20 -perl 5.8.6 64bit ----------------- -./Configure -de -Dcc=3Dgcc -Duse64bitall=20 -make -make test -make install -=20 -DBI 1.46 --------- -!!Make sure you are using the newly installed perl!! - check with perl -v it should show :=20 - This is perl, v5.8.6 built for aix-64all -perl Makefile.PL -make -make test -make install=20 -=20 -DBD-Oracle 1.16 ---------------- -!!Use correct perl like above mentioned!!=20 -export ORACLE_HOME=3D=20 -export LIBPATH=3D$ORACLE_HOME/lib -export LD_LIBRARY_PATH=3D$ORACLE_HOME/lib -=20 -perl Makefile.PL=20 -make -make test ( some test may still fail, I had 85% success on tests )=20 -make install=20 -=20 -Test -----=20 -=20 -test with :=20 - use DBI; - $dbh=3DDBI->connect("dbi:Oracle:","system","manager")|| die -$DBI::errstr; - $stmt=3D$dbh->prepare("select * from tab"); - $rc=3D$stmt->execute() || die $DBI::errstr; - while (my($record)=3D$stmt->fetchrow()) - { - print $record; - } -=20 -Happy 64-bit perling ;)=20 - -------_=_NextPart_001_01C4F4C7.EE810087-- - diff --git a/err_build/err_hpux_ld.msg b/err_build/err_hpux_ld.msg deleted file mode 100644 index 27f9cd07..00000000 --- a/err_build/err_hpux_ld.msg +++ /dev/null @@ -1,89 +0,0 @@ -From SRS0=JbZc=U3=lincolnbaxter.com=lab@bounce2.pobox.com Tue Jun 21 05:02:19 2005 -Return-Path: -X-Original-To: timbo@localhost -Delivered-To: timbo@localhost.data-plan.com -Received: from localhost (localhost [127.0.0.1]) - by timac.data-plan.com (Postfix) with ESMTP id B016F2A3D98 - for ; Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 21 Jun 2005 05:02:19 +0100 (IST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DkYXK-0003m5-Mr; - Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DkYXK-0003m5-Mr - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1DkYXJ-00006n-QE - for pobox@data-plan.com; Tue, 21 Jun 2005 02:30:50 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AF60172691; - Mon, 20 Jun 2005 22:29:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from ms-smtp-04-eri0.southeast.rr.com (ms-smtp-04-lbl.southeast.rr.com [24.25.9.103]) - by gold.pobox.com (Postfix) with ESMTP id A3C1E7272E - for ; Mon, 20 Jun 2005 22:29:11 -0400 (EDT) -Received: from lincolnbaxter.com (cpe-069-132-010-126.carolina.res.rr.com [69.132.10.126]) - by ms-smtp-04-eri0.southeast.rr.com (8.12.10/8.12.7) with ESMTP id j5L2TIL4001864 - for ; Mon, 20 Jun 2005 22:29:18 -0400 (EDT) -Received: (qmail 5171 invoked from network); 20 Jun 2005 22:29:07 -0400 -Received: from lws (192.168.0.25) - by lws with SMTP; 20 Jun 2005 22:29:07 -0400 -Subject: Re: gcc options when building DBD:Oracle -From: "Lincoln A. Baxter" -Reply-To: lab@lincolnbaxter.com -To: jriekenberg@everestkc.net -Cc: Tim Bunce -In-Reply-To: -References: -Content-Type: text/plain -Date: Mon, 20 Jun 2005 22:29:07 -0400 -Message-Id: <1119320947.17452.484.camel@lws> -Mime-Version: 1.0 -X-Mailer: Evolution 2.2.1.1 -Content-Transfer-Encoding: 7bit -X-Virus-Scanned: Symantec AntiVirus Scan Engine -Status: RO -Content-Length: 2011 -Lines: 38 - -Hi Jan, - -This looks like something that might be relatively easy to fix in -Makefile.PL. But I no longer have access to HPUX systems, and never -built DBD-Oracle with gcc on that platform. I could add your message to -the README.hpux file, but it is becoming less and less necessary to read -this file with newer versions of DBD-Oracle, in which Makefile.PL has -been made much smarter. - -Would you consider sending Tim or me a patch to Makefile.PL that -generates the right $(LD) command (only on HP rp8400, and only for your -version of gcc or later? - -Lincoln - -On Mon, 2005-06-20 at 15:36 -0500, jriekenberg@everestkc.net wrote: -> Lincoln, -> -> I recently built DBD:Oracle on an HP rp8400. Everything worked as expected until I actually issued the "make" command. Make proceeded as expected until it reached "MakeMaker dynamic_lib" section. The gcc line in that section failed with the error in the attached text file. Apparently gcc was not correctly passing the "+b" option to ld. Instead, it was attempting to interpret the option itself. It assumed the "+b" was a filename, and that failed because gcc could not find the file. I ended up adding the "-Xlinker" option before the "+b" and before the "$(LD_RUN_PATH)" in the line in Makefile. The line now looks like this: -> -> $(LD) -Xlinker +b -Xlinker "$(LD_RUN_PATH)" $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) -> -> Running "make" now works correctly. -> -> Also, "make test" returned the following error when attempting to build the various tests: -> -> /usr/lib/dld.sl: Can't shl_load() a library containing Thread Local Storage: /usr/lib/libcl.2 -> -> Setting LD_PRELOAD with "export LD_PRELOAD=/usr/lib/libcl.2" corrected this problem, and "make test" worked correctly. -> -> -> I didn't see DBD::Oracle documentation on exactly this, so I'm sending this to you. You may be aware of these items already. If so, please disregard this. -> -> Jon Riekenberg -> -> -> - - diff --git a/err_build/err_hpuxsuccess.msg b/err_build/err_hpuxsuccess.msg deleted file mode 100644 index c6edd79f..00000000 --- a/err_build/err_hpuxsuccess.msg +++ /dev/null @@ -1,279 +0,0 @@ -From dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org Tue Mar 23 17:00:25 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i2NGvAxX021862 - for ; Tue, 23 Mar 2004 17:00:23 GMT - (envelope-from dbi-users-return-22430-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 23 Mar 2004 17:00:23 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1B5oND-0000Ba-LH; - Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1B5oND-0000Ba-LH - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:27 +0000 -Received: from [208.210.124.70] (helo=majesty.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1B5oNC-00001d-92 - for pobox@dbi.demon.co.uk; Tue, 23 Mar 2004 16:03:26 +0000 -Received: from majesty.pobox.com (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 18033954B4 - for ; Tue, 23 Mar 2004 11:03:24 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by majesty.pobox.com (Postfix) with ESMTP id 3577D954BE - for ; Tue, 23 Mar 2004 11:03:21 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by majesty.pobox.com (Postfix) with SMTP - for ; Tue, 23 Mar 2004 11:02:41 -0500 (EST) -Received: (qmail 6527 invoked by uid 1005); 23 Mar 2004 16:02:21 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 6510 invoked by uid 76); 23 Mar 2004 16:02:20 -0000 -Received: from x1.develooper.com (HELO x1.develooper.com) (63.251.223.170) - by onion.perl.org (qpsmtpd/0.27.1) with SMTP; Tue, 23 Mar 2004 08:02:20 -0800 -Received: (qmail 1985 invoked by uid 225); 23 Mar 2004 16:02:15 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 1893 invoked by alias); 23 Mar 2004 16:02:00 -0000 -X-Spam-Status: No, hits=0.0 required=7.0 - tests= -X-Spam-Check-By: la.mx.develooper.com -Received: from Unknown (HELO dundee.fpcc.net) (204.144.241.120) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Tue, 23 Mar 2004 08:01:44 -0800 -Received: from aberdeen.fpcc.net (aberdeen.fpcc.net [204.144.241.125]) - by dundee.fpcc.net (8.11.6/8.11.6) with ESMTP id i2NG1f111241; - Tue, 23 Mar 2004 09:01:41 -0700 -Received: from aberdeen.fpcc.net (localhost.localdomain [127.0.0.1]) - by aberdeen.fpcc.net (8.12.8/8.12.8) with ESMTP id i2NFrNOv024637; - Tue, 23 Mar 2004 08:53:23 -0700 -Received: (from laubster@localhost) - by aberdeen.fpcc.net (8.12.8/8.12.8/Submit) id i2NFrMOx024635; - Tue, 23 Mar 2004 08:53:22 -0700 -X-Authentication-Warning: aberdeen.fpcc.net: laubster set sender to dbiusers@laubster.org using -f -Date: Tue, 23 Mar 2004 08:53:22 -0700 -From: "J.D. Laub" -To: dbi-users@perl.org -Cc: lbaxter@fleetcc.com -Subject: SUCCESS: DBD::Oracle 1.15 on HP-UX 11.11 -Message-ID: <20040323155322.GA24576@aberdeen.fpcc.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -Organization: The Psychiatric Ward of Terrors -X-Virus-Checked: Checked -Status: RO -Content-Length: 9105 -Lines: 206 - -I've just had success building DBD::Oracle 1.15 on HP-UX 11.11 -(against both oracle 8.1.7 & oracle 9.2.0) & thought I'd share my -experience. - -Disclaimer: these instructions relate to our environment. It may be -that our sysadmins/dbas chose to configure/install things a certain -way (i.e., our install of $ORACLE_HOME/bin/sqlplus was *chosen* -to be 1.1/32), and/or that we're running old versions of software -(i.e., perhaps later releases of gcc don't ignore -mpa-risc-1-1). -In fact, there are probably some mistruths in here; rest assured -they're not intentional. :-) - -I'm unsure how (if?) I should go about getting this information into -the DBD::Oracle README.hpux. Lincoln, please contact me with any -thoughts you have. - - -### The summary ################################ - -Use the ansic compiler (~US$800/cpu). - -Shell variables I used: - PATH=/bin:$PATH # use 32bit ar & nm since using a 32bit cc - PERLDEST=/opt/perl_ora8 # or "perl_ora9" for an ora9 build - PATH=$PERLDEST/bin:$PATH # for build of DBI, pick up new perl - export LDLOADLIBS='+b : +s' # handy for ORACLE_SID connections to ora7 - unset PERLLIB # important to avoid outdated cruft - export ORACLE_USERID=scott/tiger # insecure - consider using "/" - ORACLE_SID=orcl - ORAENV_ASK=NO - . oraenv # sets LD_LIBRARY_PATH and SHLIB_PATH - -For ora8: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DAportable ' \ - -A prepend:ldflags='+z +DAportable ' - -For ora9: - sh ./Configure -d -e -Dprefix=$PERLDEST \ - -A prepend:libswanted='cl pthread ' \ - -A prepend:ccflags='+z +DA2.0W ' \ - -A prepend:ldflags='+z +DA2.0W ' \ - -Dlibpth='/usr/lib/pa20_64 /usr/local/pa20_64/lib' - -After you use the above to install perl, DBI & DBD::Oracle will -build in the normal fashion. - - -### General Notes ################################ - -* During "make test", I received 1 failure (on -lib/ExtUtils/t/Constant) for ora8, and 3 failures (on -lib/ExtUtils/t/Constant, lib/ExtUtils/t/recurs, and t/op/write) for -ora9. Nevertheless, things seem mostly OK. - -* These are the various combinations possible for a given compiled -file on HP-UX 11.11 (the quoted description is what gets kicked out -by the "file" command): - - PA-RISC1.1/32bit ("PA-RISC1.1 relocatable object") - (I'll call this 1.1/32) - PA-RISC2.0/32bit ("PA-RISC2.0 relocatable object") - (I'll call this 2.0/32) - PA-RISC2.0/64bit ("ELF 64-bit MSB relocatable, PA-RISC 2.0 (LP64)") - (I'll call this 2.0/64) - -* "perl -v" lies about the RISC level: -$ file ./perl -./perl: PA-RISC1.1 shared executable dynamically linked -not stripped -$ ./perl -v | grep RISC -This is perl, v5.8.3 built for PA-RISC2.0 - -* If you'll be linking against 2.0/64 libraries, you'll have to -build all your object modules that way. I've not yet found a way -to link 32bit executables to 64bit libraries (and vice versa). Run -the "file" command on your Oracle libraries to find out which path -you'll have to take. - -* Two environment variables control where libraries are -searched. LD_LIBRARY_PATH and SHLIB_PATH (in that order) are -used for 64bit executables, while SHLIB_PATH is used for 32bit -executables. - -* I tried attempts using aCC as well as the default (free) cc that -comes with hpux; both avenues were too problematic to continue -pursuing. - -* The format of compiled objects is specified by compiler options. -According to the ansic compiler docs, the options are "+DAportable" -(for 1.1/32), "+DA2.0" (for 2.0/32), and "+DA2.0W" (for 2.0/64). -For gcc, the corresponding switches are -mpa-risc-1-1 (for 1.1/32) -and -mpa-risc-2-0 (for 2.0/64), but I've found that -mpa-risc-1-1 -is ineffective. (According to the "file" command, you *always* get -2.0/64.) - -* Our gcc displays the behavior described at -http://sources.redhat.com/ml/binutils/2002-10/msg00586.html and -http://aspn.activestate.com/ASPN/Mail/Message/perl5-porters/1641238 -, so is therefore unusable anytime '-lcl' is to be specified. -Unfortunately, that library is required for DBD::Oracle builds. -(The workaround of adding the 3 declarations does seem to work, -but littering those throughout perl's Configure, main.c, etc. -seems a big task.) Attempts to get gcc to use the hp ld instead -of the gnu ld (by specifying -mno-gnu-ld and -fno-gnu-linker) were -unsuccessful. The first html link shown above indicates you have -to rebuild gcc to use the hp linker, and that was not an incredibly -desirable path to pursue. - -* Our default PATH was set to put /usr/local/pa20_64/bin ahead of -/bin. This caused problems because (I think) the 64bit versions -of either ar (the archiver) or nm (the symbol lister) do not play -well with /bin/cc (the 32bit compiler). The tweak to put /bin at -the head of PATH, so we get the 32bit versions, takes care of the -problem. - -* I ran into an intermittent quirk during the build of perl in which -typing "make" (just after the Configure) did nothing. It turns out -that only dependencies were being written to "makefile", and that -removing "makefile" (so it could be automatically rebuilt) solved -the problem. - -* Most of my research on finding the right compiler/linker switches -was done with a "hello world" C program, trying the various -compilers and options, and trying to link it with the oracle -libraries. This proved to be a good choice, as trying to test -compilers/switches against the perl source distribution would have -proved quite difficult. - - -### DBD::Oracle specific ################################ - -* ora8 delivers its libraries in 2 formats: 1.1/32 (under -$ORACLE_HOME/lib) and 2.0/64 (under $ORACLE_HOME/lib64). ora7 -delivers only 1.1/32, while ora9 delivers only 2.0/64. It may seem -a bit inconsistent considering the ora8 setup, but ora9 libraries -are found under $ORACLE_HOME/lib and not $ORACLE_HOME/lib64. - -* Under ora8, oraenv incorrectly sets LD_LIBRARY_PATH to include -$ORACLE_HOME/lib instead of $ORACLE_HOME/lib64, so you've got to -make an override in oraenv_local if you want to use 2.0/64. It -doesn't harm anything, but oraenv unnecessarily sets LD_LIBRARY_PATH -for ora7 (a 64bit environment variable for a 32bit application). - -* If you use shared libraries AND you'll be upgrading Oracle, you -should expect you'll need to rebuild DBD::Oracle unless you'll keep -the old Oracle libraries available. - -* If you're building against ora8, the setting of LDLOADLIBS -is recommended so that when oraenv set SHLIB_PATH to the -$ORACLE_HOME/lib for ora7, the code will still find the ora8 -libraries. - -* We expect to need local (ORACLE_SID) connections for ora8 & -ora9. We could have gone with a single 2.0/64 perl coupled with -2 DBD::Oracle installs and PERLLIB twiddling in oraenv_local to -get to the right one. Instead, we chose to do 2 perl installs -(/opt/perl_ora8 and /opt/perl_ora9) because we can also connect -locally to ora7 by using the 1.1/32 ora8 version, something that -isn't possible with a 2.0/64 version. Also, we've some older 1.1/32 -machines into which we'd like to plop a tarball of the perl stuff, -so a 1.1/32 executable was desirable. - -* Some tests I ran were hinting that with 2.0/64, specifying "+b :" -on the build of DBD::Oracle correctly configured Oracle.sl as far as -the chatr program is concerned, but it seemed that LD_LIBRARY_PATH -*always* needed to be set correctly. (I.e., the embedded path in -the library seemed to be ignored.) I didn't pursue researching this -since there's no way to get the ora9 compiled code to connect to -ora8, meaning LD_LIBRARY_PATH had to be set correctly anyway. - -Testing local (ORACLE_SID) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora8 cannot connect to ora9: "ERROR OCIEnvInit" -builds against 2.0/64 ora9 cannot connect to ora8 or ora7: "UNKNOWN - OCI STATUS 1804) OCIInitialize. Check ORACLE_HOME and NLS - settings etc." - -Testing remote (sqlnet) connections: -builds against 1.1/32 ora8 can connect to ora7 -builds against 1.1/32 ora8 can connect to ora9 -builds against 2.0/64 ora9 can connect to ora8 -builds against 2.0/64 ora9 cannot connect to ora7: "OCI-21500: internal - error code" - - -### Versions ################################ - -perl: 5.8.3 -dbi: 1.41 -dbd-oracle: 1.15 -$ strings /bin/cc | grep Compiler -HP92453-01 B.11.11.08 HP C Compiler -$ strings /bin/ld | grep linker -$Revision: 92453-07 linker linker crt0.o B.11.16 000601 $ -@(#)92453-07 linker command s800.sgs ld PA64 B.11.18 REL 000922 -$ gcc -v -Reading specs from /usr/local/pa20_64/lib/gcc-lib/hppa64-hp-hpux11.11/3.3.1/specs -Configured with: ../src/configure --enable-languages=c,c++ --prefix=/usr/local/pa20_64 --with-local-prefix=/usr/local/pa20_64 --with-gnu-as --with-as=/usr/local/pa20_64/bin/as --with-gnu-ld --with-ld=/usr/local/pa20_64/bin/ld --disable-shared --disable-nls --host=hppa64-hp-hpux11.11 -Thread model: single -gcc version 3.3.1 - --- -J.D. Laub (Laubster) |"Your leg's too long / Your skull's too strong / -dbiusers@laubster.org| Suppose your nose is wrong." - Renaldo & the Loaf - diff --git a/err_build/err_instantclient.msg b/err_build/err_instantclient.msg deleted file mode 100644 index f0e549eb..00000000 --- a/err_build/err_instantclient.msg +++ /dev/null @@ -1,207 +0,0 @@ -From SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Feb 2 10:11:05 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j12AAUZ6055956 - for ; Wed, 2 Feb 2005 10:11:05 GMT - (envelope-from SRS0=8E1j=QQ=perl.org=dbi-users-return-25638-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 02 Feb 2005 10:11:05 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwGaQ-0002Bn-H6; - Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwGaQ-0002Bn-H6 - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwGaP-00042G-Vb - for pobox@data-plan.com; Wed, 02 Feb 2005 09:14:10 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 9C3FB1E3946; - Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 879981E3958 - for ; Wed, 2 Feb 2005 04:14:09 -0500 (EST) -Received-SPF: pass (kelvin.pobox.com: domain of dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-users-return-25638-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by kelvin.pobox.com (Postfix) with SMTP id D0B001E3946 - for ; Wed, 2 Feb 2005 04:14:08 -0500 (EST) -Received: (qmail 7188 invoked by uid 514); 2 Feb 2005 09:14:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -List-Id: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 2531 invoked from network); 2 Feb 2005 04:10:16 -0000 -Delivered-To: dbi-users@perl.org -X-Spam-Status: No, hits=-2.6 required=8.0 - tests=BAYES_00,NO_REAL_NAME -X-Spam-Check-By: la.mx.develooper.com -Received-SPF: pass (x1.develooper.com: local policy) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgw.shina.sankyo.co.jp: iscan owned process doing -bs -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: Making DBD::Oracle with Instant Client 10.1.0.3 -Date: Wed, 2 Feb 2005 13:09:58 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBE9@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUI3Q64h9ykph8RSl6pF0OpBbTqJA== -To: -X-OriginalArrivalTime: 02 Feb 2005 04:09:59.0005 (UTC) FILETIME=[0F7508D0:01C508DD] -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 44 - -Hi all, - -Thanks to the devel package, I've got succeeded in making DBD::Oracle -with the Oracle Instant Client 10.1.0.3, no *.mk files, in my linux box. -My recipe is: - -1) install both basic- and devel-10.1.0.3 rpm packages -2) export ORALCE_HOME="/usr/lib/oracle/10.1.0.3/client" -3) export LD_LIBRARY_PATH="$ORACLE_HOME/lib:$LD_LIBRARY_PATH" -4) modify the Makefile.PL file to bypass the find_headers() routine and - to pass a correct -I flag to cc (the attached dirty patch is FYI) -5) execute the Makefile.PL * with the -l option *, perl Makefile.PL -l -6) make && make test && make install -# I got many errors in t/30long.t (retrieving blobs ?) -# but it seems to work fairly. - -I hope this could help those who are annoyed with the "Unable to locate an -oracle.mk,..." error. - -Happy DBing, - -Satoshi - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+# my @h_dirs = find_headers(); - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client"; - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -From SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com Thu Feb 3 08:10:48 2005 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id j138AMOi093146 - for ; Thu, 3 Feb 2005 08:10:48 GMT - (envelope-from SRS0=Kn57=QR=sankyo.co.jp=snisim@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Thu, 03 Feb 2005 08:10:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CwboD-0005ug-LV; - Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CwboD-0005ug-LV - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CwboD-0000Wn-82 - for pobox@data-plan.com; Thu, 03 Feb 2005 07:53:49 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 70999102D9F; - Thu, 3 Feb 2005 02:53:48 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 5F45E102DCC - for ; Thu, 3 Feb 2005 02:53:48 -0500 (EST) -X-Pobox-Antispam: Require PTR Record returned DENY: 210.81.52.253 has no PTR record -X-Pobox-Antispam: country/Japan returned DENY: sender address snisim@sankyo.co.jp matches TLD .jp (Japan) -Received-SPF: none (boggle.pobox.com: domain of snisim@sankyo.co.jp does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for snisim@sankyo.co.jp to mail through 210.81.52.253) -Received: from mailgws.shina.sankyo.co.jp (unknown [210.81.52.253]) - by boggle.pobox.com (Postfix) with ESMTP id A38A5102E20 - for ; Thu, 3 Feb 2005 02:53:46 -0500 (EST) -Received: from es007.sankyo.co.jp (localhost [127.0.0.1]) - by mailgws.shina.sankyo.co.jp (8.9.3p2/3.7W) with ESMTP id LAA15117 - for ; Thu, 3 Feb 2005 11:45:39 +0900 (JST) -From: snisim@sankyo.co.jp -X-Authentication-Warning: mailgws.shina.sankyo.co.jp: iscan owned process doing -bs -Received: from EVS001.sankyo.co.jp ([10.14.121.200]) by es007.sankyo.co.jp with Microsoft SMTPSVC(6.0.3790.0); - Thu, 3 Feb 2005 11:45:39 +0900 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-2022-jp" -Content-Transfer-Encoding: 7bit -Subject: RE: Making DBD::Oracle with Instant Client 10.1.0.3 -Content-class: urn:content-classes:message -X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 -Date: Thu, 3 Feb 2005 11:46:07 +0900 -Message-ID: <7C6FBEDC782B5642BEAF9C9FDF3F431D83CBEC@EVS001.sankyo.co.jp> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Making DBD::Oracle with Instant Client 10.1.0.3 -Thread-Index: AcUJEc1pQuIX++g2S8y4AE9WqWRYtQAhsK+Q -To: -X-OriginalArrivalTime: 03 Feb 2005 02:45:39.0123 (UTC) FILETIME=[71F21030:01C5099A] -Status: RO -Content-Length: 1192 -Lines: 36 - -Hi Tim, - -Thank you for your kind reply. - -I found my patch will cause a compilation error for the local variable -@h_dirs gets into undefined after commenting out the line 279. -It should be corrected as following: - ---- Makefile.PL.orig 2004-10-22 18:07:04.000000000 +0900 -+++ Makefile.PL 2005-02-02 12:39:56.703125000 +0900 -@@ -276,7 +276,7 @@ - print "Oracle sysliblist: $syslibs\n"; - my $libdir = ora_libdir(); - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g" }; -- my @h_dirs = find_headers(); -+ my @h_dirs; - if ($client_version_full =~ /^8.0.6/ && $os eq 'hpux') { - $linkwith_msg = "-lextp -l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -lextp -l$lib $syslibs" ]; -@@ -286,7 +286,8 @@ - $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH/$libdir -l$lib $syslibs" ]; - } -- my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+# my $inc = join " ", map { "-I$OH/$_" } @h_dirs; -+ my $inc = "-I/usr/include/oracle/10.1.0.3/client" - $opts{INC} = "$inc -I$dbi_arch_dir"; - } - else { # --- trawl the guts of Oracle's make files looking the how it wants to link - -I'm not a dbi-users member so I can't reply my post... I wonder if you can do it. - -Thanks, - -Satoshi - - diff --git a/err_build/err_makefileundef.msg b/err_build/err_makefileundef.msg deleted file mode 100644 index b98d782a..00000000 --- a/err_build/err_makefileundef.msg +++ /dev/null @@ -1,87 +0,0 @@ -From timbo Tue Apr 26 09:19:54 2005 -Return-path: -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Tue, 26 Apr 2005 09:19:54 -0700 (PDT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1DQSgy-0006AU-4c; - Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1DQSgy-0006AU-4c - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from [207.8.226.2] (helo=kelvin.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1DQSgy-0003uM-1T - for pobox@data-plan.com; Tue, 26 Apr 2005 16:13:44 +0000 -Received: from kelvin.pobox.com (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 759703B902A; - Tue, 26 Apr 2005 12:13:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from kelvin (localhost [127.0.0.1]) - by kelvin.pobox.com (Postfix) with ESMTP id 80C0A39F279 - for ; Tue, 26 Apr 2005 12:13:42 -0400 (EDT) -Received-SPF: none (kelvin.pobox.com: domain of lembark@wrkhors.com does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 66.246.154.128(mail-out.pilosoft.net) -Received: from mail.pilosoft.net (mail-out.pilosoft.net [66.246.154.128]) - by kelvin.pobox.com (Postfix) with ESMTP id 2ED743AB75B - for ; Tue, 26 Apr 2005 12:12:30 -0400 (EDT) -Received: from [192.168.1.2] (dsl-69-31-90-94.pilosoft.com [69.31.90.94]) - by mail.pilosoft.net (8.12.8/8.12.8) with ESMTP id j3QGA3u1014203 - for ; Tue, 26 Apr 2005 12:10:03 -0400 -Date: Tue, 26 Apr 2005 12:14:22 -0400 -From: Steven Lembark -Reply-To: lembark@wrkhors.com -To: Tim Bunce -Subject: Possible glitch in DBD::Oracle-1.48 Makefile.pl -Message-ID: <269F0144DC99100E7C80975F@[192.168.1.2]> -X-Mailer: Mulberry/3.1.3 (Linux/x86) -X-Workhorse: lembark 1.1 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii; format=flowed -Content-Transfer-Encoding: 7bit -Content-Disposition: inline -X-Virus-Scanned: ClamAV version 0.83, clamav-milter version 0.83 on mail.pilosoft.net -X-Virus-Status: Clean -X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=failed version=3.0.2 -X-Spam-Level: 0.0 -X-Spam-Checker-Version: SpamAssassin 3.0.2 (2004-11-16) on cheeta.pilosoft.net -X-Status: A -Content-Length: 1342 -Lines: 36 - -Linking with OTHERLDFLAGS = -L/opt/oracle/product/9.2/lib/ --L/opt/oracle/product/9.2/rdbms/lib/ -lclntsh `cat -/opt/oracle/product/9.2/lib/sysliblist` -ldl -lm [from 'build' rule] - -Checking if your kit is complete... -Looks good -Use of uninitialized value in substitution (s///) at Makefile.PL line 1446. -LD_RUN_PATH=/opt/oracle/product/9.2/lib:/opt/oracle/product/9.2/rdbms/lib -Using DBD::Oracle 1.16. - - - sub const_loadlibs { - my $self = shift; - local($_) = $self->SUPER::const_loadlibs(@_); - # edit LD_RUN_PATH ... - my ($ldrp) = m/^LD_RUN_PATH\s*=\s*(.*)/m; - # remove redundant /lib or /usr/lib as it can cause problems --> $ldrp =~ s!:(/usr)?/lib$!!; - # if it's empty then set it manually - #Lincoln: if pick the right library path - my $libdir = main::ora_libdir(); - $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; - #print "ldrp=$ldrp\n"; - - # stitch it back in - s/^LD_RUN_PATH\s*=\s*(.*)/LD_RUN_PATH=$ldrp/m; - my $env = $ENV{LD_RUN_PATH}; - print "Ignoring LD_RUN_PATH='$env' in environment\n" if $env; - print "LD_RUN_PATH=$ldrp\n"; - return $_; - } - --- -Steven Lembark 85-09 90th Street -Workhorse Computing Woodhaven, NY 11421 -lembark@wrkhors.com 1 888 359 3508 - diff --git a/err_build/err_memleak.msg b/err_build/err_memleak.msg deleted file mode 100644 index d40913d7..00000000 --- a/err_build/err_memleak.msg +++ /dev/null @@ -1,95 +0,0 @@ -From SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com Wed Sep 1 16:31:37 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i81FRlpg021884 - for ; Wed, 1 Sep 2004 16:31:37 +0100 (BST) - (envelope-from SRS0=Dwok=LW=pallas.eruditorum.org=www-data@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 Sep 2004 16:31:37 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C2WYO-00034m-M1; - Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C2WYO-00034m-M1 - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1C2WYO-0005CR-FY - for pobox@data-plan.com; Wed, 01 Sep 2004 14:57:40 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 1C1D6A758C; - Wed, 1 Sep 2004 10:57:36 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 184C8A7214 - for ; Wed, 1 Sep 2004 10:57:32 -0400 (EDT) -Received-SPF: fail (boggle.pobox.com: domain of www-data@pallas.eruditorum.org does not designate 63.251.223.170 as permitted sender) -X-SPF-Override: pass (client 63.251.223.170 was found in trusted-forwarder.org, overrides regular SPF fail) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.170(x1.develooper.com) -Received: from x1.develooper.com (x1.develooper.com [63.251.223.170]) - by boggle.pobox.com (Postfix) with SMTP id 7A6C9A7555 - for ; Wed, 1 Sep 2004 10:57:06 -0400 (EDT) -Received: (qmail 5427 invoked by uid 225); 1 Sep 2004 14:57:04 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 5403 invoked by alias); 1 Sep 2004 14:57:02 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 01 Sep 2004 07:56:59 -0700 -Received: by pallas.eruditorum.org (Postfix, from userid 33) - id 1FDD784C0F5; Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -Subject: [cpan #6245] Confirmed memory leak -From: "Guest via RT" -Reply-To: bug-DBD-Oracle@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #6245 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: -Date: Wed, 1 Sep 2004 10:56:41 -0400 (EDT) -To: undisclosed-recipients: ; -Status: RO -Content-Length: 937 -Lines: 38 - - -This message about DBD-Oracle was sent to you by guest <> via rt.cpan.org - -Full context and any attached attachments can be found at: - - -I Using : -1. SunOS 5.6 Generic_105181-33 sun4u sparc SUNW,Ultra-Enterprise - Perl 5.005_03 - DBI 1.37 - DBD-Oracle 1.14 - Oracle Release 8.1.5.0.0 - - -2. Linux 2.4.18-17.7.xsmp #1 SMP i686 - Perl 5.6.1 - DBI 1.41 - DBD-Oracle 1.16 - Oracle Release 8.1.6.0.0 - -II The following code: - -use strict; -use DBI; - -foreach ( 1 .. 100 ) { - my $dbh = DBI->connect( 'dbi:Oracle:host=****', '***', '***' ); - $dbh->disconnect(); - sleep(1) -} - -III Leak about 4K every 10 seconds - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8724 8720 2760 S 1.3 3.4 0:01 perl - - PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND -24927 aldo 15 0 8736 8732 2760 S 0.7 3.4 0:01 perl - diff --git a/err_build/err_solarisnotes.msg b/err_build/err_solarisnotes.msg deleted file mode 100644 index eaddc475..00000000 --- a/err_build/err_solarisnotes.msg +++ /dev/null @@ -1,482 +0,0 @@ -From SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com Wed Dec 22 08:11:00 2004 -Received: from localhost (localhost [IPv6:::1]) - by dansat.data-plan.com (8.13.1/8.13.1) with ESMTP id iBM8Aog0091816 - for ; Wed, 22 Dec 2004 08:11:00 GMT - (envelope-from SRS0=uAXy=PG=zorranlabs.com=alexzar@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-6.2.5) - for timbo@localhost (single-drop); Wed, 22 Dec 2004 08:11:00 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Ch0it-0001A5-Rv; - Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Ch0it-0001A5-Rv - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Ch0is-0000To-R8 - for pobox@data-plan.com; Wed, 22 Dec 2004 07:15:51 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id F0F0DFE10C; - Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 8B2AAFE1C3 - for ; Wed, 22 Dec 2004 02:15:49 -0500 (EST) -Received-SPF: none (lime.pobox.com: domain of alexzar@zorranlabs.com does not designate permitted sender hosts) -Received: from penguin.nocdirect.com (penguin.nocdirect.com [69.73.160.206]) - by lime.pobox.com (Postfix) with ESMTP id 2B41BFE159 - for ; Wed, 22 Dec 2004 02:13:17 -0500 (EST) -Received: from localhost ([127.0.0.1]) - by penguin.nocdirect.com with esmtps (TLSv1:DES-CBC3-SHA:168) - (Exim 4.43) - id 1Cgz53-0000fj-Bx; Tue, 21 Dec 2004 23:30:37 -0600 -Date: Tue, 21 Dec 2004 23:30:35 -0600 (CST) -From: Alex Zarutin -X-X-Sender: zorranla@penguin.nocdirect.com -To: Tim Bunce -Cc: dbi-users-help@perl.org -Subject: Step-by-Step installation manual of DBD-Oracle-1.16 on Sparc Solaris - 9 with Oracle 9.2.0.1.0 client. -Message-ID: -MIME-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-AntiAbuse: This header was added to track abuse, please include it with any abuse report -X-AntiAbuse: Primary Hostname - penguin.nocdirect.com -X-AntiAbuse: Original Domain - pobox.com -X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] -X-AntiAbuse: Sender Address Domain - zorranlabs.com -X-Source: -X-Source-Args: -X-Source-Dir: -Status: RO -X-Status: A -Content-Length: 15603 -Lines: 426 - - -Hi Tim, - -I have spent a couple days trying to install DBD-Oracle-1.16 (all -required stuff, such as GCC, DBI, etc has been installed before ) on -Sun-Fire v240 running Spark Solaris 9 with the Oracle 9.2.0.1.0 client -installed. The installation takes a couple minutes ONLY after you spend -days trying to make it workable. - -I wrote the log of what I do, in order to do not waste my time in -future. I am pretty sure that this log will be very useful for people -installing DBD-Oracle on Solaris. I published it on my log page, and left -link on it at http://cpanratings.perl.org/d/DBD-Oracle review page. I -would recommend you to add this log to the readme file of your next -releases. Log is written very detailed (step-by-step) with highlighted -typical mistakes. - -Environment: -Hardware/OS: bash-2.05# uname -a -SunOS qadmz41 5.9 Generic_117171-08 sun4u sparc SUNW,Sun-Fire-V240 -OS is actually "standard" Solaris 9 installation came on the box from -SUN - -Oracle Client: Oracle 9.2.0.1.0 -GCC: gcc version 3.3.2, installed to /usr/local/bin as a package from -http://www.sunfreeware.com/programlistsparc9.html -PERL: perl v5.8.5 built for sun4-solaris, installed to /usr/local/bin as -a package from http://www.sunfreeware.com/programlistsparc9.html -DBI: DBI-1.45, installed from http://search.cpan.org/~timb/DBI-1.45/ - -Step-by-Step Manual: - -Step 1: In order to install "DBD-Oracle-1.16" you need to download it, -set all appropriate environment variables (see readme for details) and -run <>. -I got an error that is mostly typical for Solaris installation: - -// ************************ Error 1 ***********************/ - -.... -Found header files in rdbms/demo. - -********************************************************* -I can't find the header files I need in your Oracle installation. -You probably need to install some more Oracle components. -I'll keep going, but the compile will probably fail. -See README.clients for more information. -********************************************************* -Checking for functioning wait.ph - -System: perl5.008005 sunos 5.9 generic sun4u sparc sunw,ultra-5_10 -solaris -Compiler: gcc -B/usr/ccs/bin/ -O -fno-strict-aliasing -pipe --I/usr/local/include -I/opt/gnu/include -D_LARGEFILE_SOURCE --D_FILE_OFFSET_BITS=64 - -.... -// *****************************************************/ - -Investigating this problem, I found that error message is thrown by the -"find_headers" sub of Makefile.PL, especially in this "if -(!$h_file{'oratypes.h'} || !$h_file{'ocidfn.h'})" evaluation. -So I checked these files to make sure that they are installed, but did -not find them under $ORACLE_HOME/rdbms -In the same time, I found an article saying about the similar problem -with DBD-Oracle on Linux, -http://baroti.homedns.org/steve/lost+found/cpan-install-DBD-Oracle-9-2-l -inux.html -They mentioned about two files, and since I was not sure about second -one, ociapr.h I copied both files. You should find its public.1.1.jar -file on the Disk3 of Oracle 9i installation set. - -bash-2.05# pwd -/ora_orig/Disk3/stage/Components/oracle.rdbms.oci/9.2.0.1.0/1/DataFiles - -bash-2.05# ls -al -total 970 -drwxr-xr-x 2 2840 42424 512 Aug 21 2002 . -drwxr-xr-x 3 2840 42424 512 Aug 21 2002 .. --rwxr-xr-x 1 2840 42424 2047 May 9 2002 bin.1.1.jar --rwxr-xr-x 1 2840 42424 206 May 9 2002 build.1.1.jar --rwxr-xr-x 1 2840 42424 135034 May 9 2002 demo.1.1.jar --rwxr-xr-x 1 2840 42424 329814 May 9 2002 public.1.1.jar - -You should just (as dba:oracle) to create the directory called public, -copy public.1.1.jar there and extract all files, since I would not guess -if the rest of them are used or not - -bash-2.05# mkdir $ORACLE_HOME/rdbms/public - -bash-2.05# ls -al $ORACLE_HOME/rdbms/public -total 3404 -drwxr-xr-x 2 oracle dba 512 Dec 21 12:12 . -drwxr-xr-x 10 oracle dba 512 Dec 21 12:05 .. -... --rw-r--r-- 1 oracle dba 6055 Mar 9 2002 ociapr.h --rw-r--r-- 1 oracle dba 10694 Jun 29 2000 ocidfn.h -... - -After that run <> again, and I hope process passes -fine. At least, it was fine in my case - -Step 2: You should <> the module, and as it appears on Solaris, -you will get typical problem. See my error log: - -// ************************ Error 2 ***********************/ -.... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -ld: fatal: file -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib//libclntsh.so: -wrong ELF class: ELFCLASS64 -ld: fatal: File processing errors. No output written to -blib/arch/auto/DBD/Oracle/Oracle.so -collect2: ld returned 1 exit status -*** Error code 1 -make: Fatal error: Command failed for target -`blib/arch/auto/DBD/Oracle/Oracle.so' - -// *****************************************************/ - -So, as another set on Google' posts showed that it is a possibility of -missing libraries compiled with 64 bits and same libraries compiled with -32 bits suppoert. As I understood, all components of installation, such -as Oracle client, Perl, GCC should support only one type of libraries, -either 32 or 64 bits. I found that having all as 32 bits is easier to me -than recompile perl, gcc as 64 (may be I am wrong in this assumption). -In order to have all of them as 32 bits, I changed lib to lib32 in -Manifest file (not Manifest.PL). - -You should replace the following lines in the "MakeMaker const_loadlibs -section": - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -By their lib32 clones: - -EXTRALIBS = -L$(LIBHOME) -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -LD_RUN_PATH=/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32:/ -export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32 - -And replace this line in "MakeMaker dynamic_lib section" (~~ line 491) - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib -laio --lposix4 -lm -lthread - -By its lib32 clone: - -OTHERLDFLAGS = -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread - -I hope, that after that process passes without any errors. Here is last -part, that I got during <>: - -..... -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32: -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/rdbms/lib32" gcc --B/usr/ccs/bin/ -G -L/usr/local/lib -L/opt/gnu/lib Oracle.o dbdimp.o -oci8.o -xarch=v9 --L/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ -lclntsh -`cat /export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/ldflags` -`cat -/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32/sysliblist` --R/export/home/oracle/u01/app/oracle/product/9.2.0.1.0/lib32 -laio --lposix4 -lm -lthread -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/local/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL -ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/local/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" -blib/script/ora_explain -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oracle.3 -Manifying blib/man3/DBD::Oraperl.3 - -III. Once we build the module, we should test it, to make sure that it -works fine. You should run <> to do it: - -Check that you have ORACLE_HOME, ORACLE_USERID, ORACLE_SID environment -variables set, like this: - -ORACLE_HOME=="/export/home/oracle/u01/app/oracle/product/9.2.0.1.0 -ORACLE_USERID=STARSHIP/STARSHIP -ORACLE_SID=COLORADO - -When you run <>, you will probably get this errors: - -// ************************ Error 3 ***********************/ - -bash-2.05# make test -PERL_DL_NONLAZY=1 /usr/local/bin/perl "-MExtUtils::Command::MM" "-e" -"test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............DBI connect('','STARSHIP/STARSHIP',...) failed: -ORA-12545: Connect failed because target host or object does not exist -(DBD ERROR: OCIServerAttach) at t/10general.t line 12 -Undefined subroutine &main::BAILOUT called at t/10general.t line 15. -# Looks like your test died before it could output anything. -t/10general.............dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-31 - Failed 31/31 tests, 0.00% okay -..... - -// *****************************************************/ - -One more brainstorm, and I figured out another way to set ORACLE_USERID: - -ORACLE_USERID=STARSHIP/STARSHIP@COLORADO -ORACLE_SID=COLORADO - -Later, when tests finished, I was confirmed that it was probably -preferred way of setting ORACLE_USERID. -Tests did found correct settings, and "main" set of them returned the -following report: - -All tests successful, 1 test and 122 subtests skipped. -Files=18, Tests=1020, 24 wallclock secs (11.27 cusr + 1.34 csys = 12.61 -CPU) - -For the Extra test, less formal, but test anyway, I just commented these -two lines in test.pl file - -$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -and set the same values in the same form to the $dbuser as it was in -ORACLE_USERID , and -left $dbname empty, - -$dbname = ''; -$dbuser = 'STARSHIP/STARSHIP@COLORADO'; - -and got pretty good report: - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - -recommended) - as 'STARSHIP/STARSHIP@COLORADO' (via ORACLE_USERID env var or default - -recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -Fields: 6 -Names: 'NUM_T' 'DATE_T' 'CHAR_T' 'ROWID_T' -'RAW_T' 'NULL_T' -Lengths: 172 76 121 21 3 1 -OraTypes: 2 12 1 104 23 1 -SQLTypes: 8 93 12 -9104 -2 12 -Scale: 0 0 0 0 0 0 -Precision: 126 75 120 20 2 0 -Nullable: 1 1 1 1 1 1 -Est row width: 32 -Data rows: - fetch: '7.2', '21-DEC-04', 'STARSHIP', 'AAAADeAABAAAAZSAAA', '7D', -undef - -ora_logoff... -lda out of scope... - -Testing repetitive connect/open/close/disconnect: -If this test hangs then read the README.help file. -Expect sequence of digits, no other messages: -1 2 3 4 5 - -Test interaction of explicit close/logoff and implicit DESTROYs -Expect just 'done.', no other messages: -done. - -Testing row cache (5). -Test completed in 0 seconds. - -Test complete (0 seconds). -If the tests above have produced the 'expected' output then they have -passed. - -IV. The last part is actually target of all steps above, installing -build module. < did not surprise me, and it it passed -smoothly. - -bash-2.05# make install -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/dbdimp -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/ocitra -ce.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.h -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/mk.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.so -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/Oracle -.bs -Files found in blib/arch: installing files in blib/lib into architecture -dependent library tree -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/oraperl.ph -Installing /usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/Oraperl.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle.pm -Installing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/DBD/Oracle/GetInfo.pm -Installing /usr/local/share/man/man1/ora_explain.1 -Installing /usr/local/share/man/man3/DBD::Oracle.3 -Installing /usr/local/share/man/man3/DBD::Oraperl.3 -Installing /usr/local/bin/ora_explain -Writing -/usr/local/lib/perl5/site_perl/5.8.5/sun4-solaris/auto/DBD/Oracle/.packl -ist -Appending installation info to -/usr/local/lib/perl5/5.8.5/sun4-solaris/perllocal.pod - -V. This is actually it, and you do not need to do anything else. But -investigating different errors during the various steps, I found the -very simple "independent sanity" testdbi perl script written by Jeff -Hunter. This script is not related to standard process of -making/buildin/testing/installation. It just verifies that you can -access DB and run a couple queries against it. The code itself, -testdbi.pl can be found at -http://www.idevelopment.info/data/Oracle/DBA_tips/Programming/PROGRAMMIN -G_2.shtml - -You just should set connection information, similar to how I did it, - - $ORACLE_SID = "COLORADO"; - $ORACLE_USERID = "STARSHIP"; - $ORACLE_PASSWORD = "STARSHIP"; - - $ENV{'ORACLE_SID'} = "$ORACLE_SID"; - $ENV{'ORACLE_HOME'} = /u01/app/oracle/product/9.2.0.1.0"; - -run it as any perl script, <>, and see result: - -bash-2.05# perl testdbi.pl - -Running testdbi.pl... - - (*) Attempting Oracle Login ... - OK - (*) Creating table TEST_DBI ... - OK - (*) Insert into TEST_DBI ... - 1 rows inserted. - 1 rows inserted. - 1 rows inserted. - OK - (*) Select from TEST_DBI ... - - --> TEST_DBI_INTR_NO : 1000 - --> TEST_DBI_NAME : Jeff Hunter - - --> TEST_DBI_INTR_NO : 1001 - --> TEST_DBI_NAME : Melody Hunter - - --> TEST_DBI_INTR_NO : 1002 - --> TEST_DBI_NAME : Alex Hunter - OK - - (*) Delete from TEST_DBI ... - 3 rows deleted. - OK - - (*) Drop table TEST_DBI ... - OK - - (*) Select USER and SYSTEM ... - - --> USER : STARSHIP - --> SYSDATE : 21-DEC-2004 16:49:59 - OK - - (*) Attempting Oracle Logoff ... - OK - -Ending testdbi.pl... - -With the best regards, - -Alex Zarutin - -Software Engineer -4thpass A Motorola Company -Seattle, WA -www.4thpass.com - - - - diff --git a/err_build/err_testfailnotable.msg b/err_build/err_testfailnotable.msg deleted file mode 100644 index 687d5ed7..00000000 --- a/err_build/err_testfailnotable.msg +++ /dev/null @@ -1,97 +0,0 @@ -From SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 18:10:51 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RHAOAK026067 - for ; Wed, 27 Oct 2004 18:10:51 +0100 (BST) - (envelope-from SRS0=RhpE=NO=perl.org=dbi-dev-return-3750-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 18:10:51 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMp30-0000e2-Hh; - Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [194.217.242.77] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMp30-0000e2-Hh - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMp30-0001QS-2p - for pobox@data-plan.com; Wed, 27 Oct 2004 14:45:10 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 87C155A7D; - Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 7779A59A1 - for ; Wed, 27 Oct 2004 10:45:09 -0400 (EDT) -Received-SPF: pass (gold.pobox.com: domain of dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3750-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by gold.pobox.com (Postfix) with SMTP id DC5795A4A - for ; Wed, 27 Oct 2004 10:45:07 -0400 (EDT) -Received: (qmail 18140 invoked by uid 514); 27 Oct 2004 14:45:04 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 18131 invoked from network); 27 Oct 2004 14:45:04 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 14:45:04 -0000 -Received: (qmail 8663 invoked by uid 225); 27 Oct 2004 14:45:03 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 8659 invoked by alias); 27 Oct 2004 14:45:03 -0000 -X-Spam-Status: No, hits=-4.9 required=8.0 - tests=BAYES_00 -X-Spam-Check-By: la.mx.develooper.com -Received: from ns2.aramiska.net (HELO dmzms01.aramiska.net) (80.242.32.2) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 07:45:01 -0700 -Received: from ip-80-242-36-115.aramiska-arc.aramiska.net (ip-80-242-36-115.aramiska-arc.aramiska.net [80.242.36.115]) - by dmzms01.aramiska.net (Postfix) with ESMTP - id 9F21E1100D9; Wed, 27 Oct 2004 14:44:55 +0000 (UTC) -Received: from localhost (localhost [127.0.0.1]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id E558E7C; Wed, 27 Oct 2004 14:44:52 +0000 (UTC) -Received: from dansat.data-plan.com (ip-192-168-0-3.internal.data-plan.aramiska.net [192.168.0.3]) - by ip-80-242-36-115.aramiska-arc.aramiska.net (Postfix) with ESMTP - id D8A5E71; Wed, 27 Oct 2004 14:44:50 +0000 (UTC) -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9REioAA023212; - Wed, 27 Oct 2004 15:44:50 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i9REinmW023211; - Wed, 27 Oct 2004 15:44:49 +0100 (BST) -Date: Wed, 27 Oct 2004 15:44:49 +0100 -From: Tim Bunce -To: "H.Merijn Brand" -Cc: Tim Bunce , DBI developers -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Message-ID: <20041027144449.GB19991@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> <20041027093516.D001.H.M.BRAND@hccnet.nl> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20041027093516.D001.H.M.BRAND@hccnet.nl> -User-Agent: Mutt/1.4i -X-Virus-Scanned: by Aramiska Arc -Status: RO -Content-Length: 634 -Lines: 14 - -On Wed, Oct 27, 2004 at 09:39:33AM +0200, H.Merijn Brand wrote: -> On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> > file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> > size: 235224 bytes -> > md5: 9711550ed0ebfc743920a6a357ed717c -> -> I know you can't blame the test for not being able to create a table for the -> reason this failure shows, but there might be a more user-friendly way to fail ... - -Yeap. Some tests behave better in that situation. Looks like those -two need improving. Patches welcome! (I'd happily not touch DBD::Oracle -for a few months after the pain of the last few months :) - -Tim. - diff --git a/err_docs/err_trace.msg b/err_docs/err_trace.msg deleted file mode 100644 index 3d7500fb..00000000 --- a/err_docs/err_trace.msg +++ /dev/null @@ -1,14 +0,0 @@ -Add this to the DBD::Oracle docs as a handy note: - -$dbh->do(q{alter session set events '65285 trace name errorstack level 3'}); - -A trace file should then be generated. - -Trace files are generated in the 'user_dump_destination' specified in init.ora. - -Try $ORACLE_BASE/admin/$ORACLE_SID/udump. - -or the location returned by -select value -from v$parameter -where name like '%user_dump%' diff --git a/err_lob/err_csr_clob.msg b/err_lob/err_csr_clob.msg deleted file mode 100644 index 397d53b3..00000000 --- a/err_lob/err_csr_clob.msg +++ /dev/null @@ -1,65 +0,0 @@ -From dbi-users-bounce@isc.org Thu Sep 21 20:27:21 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id UAA18945; Thu, 21 Sep 2000 20:27:20 +0100 (BST) -Received: from tele-punt-22.mail.demon.net by oink with SMTP (PP) - id <02709-1@oink>; Mon, 21 Sep 1970 20:26:40 +0100 -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 969564156:20:26825:1; Thu, 21 Sep 2000 19:22:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-2.mail.demon.net - id aa2026778; 21 Sep 2000 19:22 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 28A613E5D; - Thu, 21 Sep 2000 12:22:17 -0700 (PDT) -Received: with LISTAR (v1.0.0; list dbi-users); - Thu, 21 Sep 2000 12:17:37 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id A59853E42 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) -Received: from wheel.cs.wisc.edu (wheel.cs.wisc.edu [128.105.121.12]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id MAA00855 - for ; - Thu, 21 Sep 2000 12:17:32 -0700 (PDT) env-from (horn@wheel.cs.wisc.edu) -Received: (from horn@localhost) by wheel.cs.wisc.edu (8.9.2/8.9.2) id OAA16413 - for dbi-users@isc.org; Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -Date: Thu, 21 Sep 2000 14:17:28 -0500 (CDT) -From: Jeffrey Horn -Message-Id: <200009211917.OAA16413@wheel.cs.wisc.edu> -To: dbi-users@isc.org -Subject: Setting ORA_TYPE after the fact... -Sender: horn@wheel.cs.wisc.edu -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: horn@cs.wisc.edu -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -X-Status: A -Content-Length: 969 -Lines: 20 - -I have a situation where I would like to return a cursor that contains a -CLOB as one of it's attributes from a PL/SQL procedure. What I get back is -a LOB locator and DBD doesn't actually read the CLOB but instead returns an -error. - -If I go through a bind/prepare/execute/fetch on a similar SQL statement all -is well. Is there any way that I can tell DBD that a given attribute of -a cursor is a CLOB once the cursor is already opened so that DBD will do the -right thing? - --- Jeff Horn - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_lob/err_loblenwide.msg b/err_lob/err_loblenwide.msg deleted file mode 100644 index 08023e97..00000000 --- a/err_lob/err_loblenwide.msg +++ /dev/null @@ -1,95 +0,0 @@ -From nobody@fsck.com Thu Dec 4 07:36:20 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hB47Y2nE066844 - for ; Thu, 4 Dec 2003 07:36:20 GMT - (envelope-from nobody@fsck.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 04 Dec 2003 07:36:20 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1ARgrA-0005O4-5M; - Wed, 03 Dec 2003 23:56:32 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1ARgrA-0005O4-5M - for pobox@dbi.demon.co.uk; Wed, 03 Dec 2003 23:56:32 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 314AB9A28F - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 188369A287 - for ; Wed, 3 Dec 2003 18:56:32 -0500 (EST) -Received: from x1.develooper.com (x1.develooper.com[63.251.223.170]) - by icicle.pobox.com (Postfix) with SMTP - for ; Wed, 3 Dec 2003 18:56:31 -0500 (EST) -Received: (qmail 3178 invoked by uid 225); 3 Dec 2003 23:56:30 -0000 -Delivered-To: TIMB@cpan.org -Received: (qmail 3174 invoked by alias); 3 Dec 2003 23:56:29 -0000 -Received: from pallas.eruditorum.org (HELO pallas.eruditorum.org) (63.251.136.85) by la.mx.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Wed, 03 Dec 2003 15:56:18 -0800 -Received: by pallas.eruditorum.org (Postfix, from userid 65534) id 91512114F1; Wed, 3 Dec 2003 18:56:07 -0500 (EST) -Subject: [cpan #4564] Perl DBI bug handling CLOBs -From: "Jay Turner via RT" -Reply-To: bug-DBI@rt.cpan.org -In-Reply-To: -Message-ID: -Precedence: bulk -X-RT-Loop-Prevention: cpan -RT-Ticket: cpan #4564 -Managed-by: RT 2.0.15 (http://bestpractical.com/rt/) -RT-Originator: J.Turner@mdl.com -To: "AdminCc of cpan Ticket #4564": ; -Date: Wed, 3 Dec 2003 18:56:07 -0500 (EST) -X-Spam-Check-By: la.mx.develooper.com -X-Spam-Status: No, hits=2.1 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,SPAM_PHRASE_01_02,TO_HAS_SPACES,TO_MALFORMED version=2.44 -Status: RO -X-Status: A -Content-Length: 1853 -Lines: 46 - - -This message about DBI was sent to you by J.Turner@mdl.com via rt.cpan.org - -Full context and any attached attachments can be found at: - - - -Date: Fri, 28 Feb 2003 16:55:28 -0800 - -It has come to my attention that PERL DBI counts on OCILobGetLength -returning BYTES. It returns CHARACTERS instead, which is the count of -variable-width characters. For multi-byte character sets this results -in errors such as: - -DBD::Oracle::st fetch failed: ORA-03130: the buffer for the next piece -to be fetched is required (DBD ERROR: OCILobGetLength) at id rmsc01.pl -line 294. - -The correct way to read CLOBs is - -1) Query the LOB locator for the CSID and CSFRM (character set ID and -form). A character set >= 800 is a mulitbyte character set and csfrm -<> 0 is CLOB. - -2) Pass the CSID and CSFRM to OCILobRead with AMT=0 and pass your -buffer address and size. - -3) Your callback routine must either be capable of completing the I/O -by allocating additional buffers, or it must notify the caller of -OCILobRead to free the lob locator, since an incomplete read jams the -locator-you can't use it for anything else without finishing the read -(attempts to reuse the locator will result in errors). - -Likewise, with OCILobWrite, you have to pass the CSID and CSFRM, with -AMT=0 and the buffer size in bytes. The callback can just say it has -zero bytes and set piece=OCI_LAST_PIECE. - -You cannot use the return value of OCILobGetLength as the size of the -data that is being read. The actual size of the data is unknown for -variable-width characters, and the buffer has to be big enough to -accomplish the translation, so you can't just double or triple the -return value from OCILobGetLength (I have seen that approach fail). - -You can simulate the effects of a foreign character set by - -$ export NLS_LANG=Japanese - diff --git a/err_lob/err_lobtesttblfail.msg b/err_lob/err_lobtesttblfail.msg deleted file mode 100644 index 1333ee88..00000000 --- a/err_lob/err_lobtesttblfail.msg +++ /dev/null @@ -1,208 +0,0 @@ -From SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com Wed Oct 27 15:22:22 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i9RELAAO018624 - for ; Wed, 27 Oct 2004 15:22:22 +0100 (BST) - (envelope-from SRS0=sbeK=NO=perl.org=dbi-dev-return-3749-Tim.Bunce=pobox.com@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 27 Oct 2004 15:22:22 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CMiQ8-0000Eo-FG; - Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CMiQ8-0000Eo-FG - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CMiQ8-0006dS-9n - for pobox@data-plan.com; Wed, 27 Oct 2004 07:40:36 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B3BB911C325; - Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9947911C2CE - for ; Wed, 27 Oct 2004 03:40:35 -0400 (EDT) -Received-SPF: pass (icicle.pobox.com: domain of dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org designates 63.251.223.186 as permitted sender) -X-SPF-Guess: pass (seems reasonable for dbi-dev-return-3749-Tim.Bunce=pobox.com@perl.org to mail through 63.251.223.186) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 63.251.223.186(x6.develooper.com) -Received: from lists.develooper.com (x6.develooper.com [63.251.223.186]) - by icicle.pobox.com (Postfix) with SMTP id 5033611C34F - for ; Wed, 27 Oct 2004 03:39:46 -0400 (EDT) -Received: (qmail 12004 invoked by uid 514); 27 Oct 2004 07:39:43 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 11995 invoked from network); 27 Oct 2004 07:39:43 -0000 -Received: from x1.develooper.com (63.251.223.170) - by lists.develooper.com with SMTP; 27 Oct 2004 07:39:43 -0000 -Received: (qmail 13565 invoked by uid 225); 27 Oct 2004 07:39:43 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 13560 invoked by alias); 27 Oct 2004 07:39:42 -0000 -X-Spam-Status: No, hits=-3.7 required=8.0 - tests=BAYES_00,LARGE_HEX -X-Spam-Check-By: la.mx.develooper.com -Received: from smtp-vbr15.xs4all.nl (HELO smtp-vbr15.xs4all.nl) (194.109.24.35) - by la.mx.develooper.com (qpsmtpd/0.27.1) with ESMTP; Wed, 27 Oct 2004 00:39:40 -0700 -Received: from [127.0.0.1] (procura.xs4all.nl [213.84.163.145]) - by smtp-vbr15.xs4all.nl (8.12.11/8.12.11) with ESMTP id i9R7dWHI013040; - Wed, 27 Oct 2004 09:39:34 +0200 (CEST) - (envelope-from h.m.brand@hccnet.nl) -Date: Wed, 27 Oct 2004 09:39:33 +0200 -From: "H.Merijn Brand" -To: Tim Bunce -Subject: Re: ANNOUNCE: DBD::Oracle 1.16 -Cc: DBI developers -In-Reply-To: <20041022213625.GA22377@dansat.data-plan.com> -References: <20041022213625.GA22377@dansat.data-plan.com> -Message-Id: <20041027093516.D001.H.M.BRAND@hccnet.nl> -MIME-Version: 1.0 -Content-Type: text/plain; charset="US-ASCII" -X-Mailer: Becky! ver. 2.11.02 [en] -X-Virus-Scanned: by XS4ALL Virus Scanner -X-Virus-Checked: Checked -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i9RELAAO018624 -Status: RO -X-Status: A -Content-Length: 7175 -Lines: 134 - -On Fri 22 Oct 2004 23:36, Tim Bunce wrote: -> file: $CPAN/authors/id/T/TI/TIMB/DBD-Oracle-1.16.tar.gz -> size: 235224 bytes -> md5: 9711550ed0ebfc743920a6a357ed717c - -I know you can't blame the test for not being able to create a table for the -reason this failure shows, but there might be a more user-friendly way to fail ... - -I'll report back when the DBA has fixed the tablespace - -HP-UX 11.11/64 (11i) + Oracle-9.2.0/64 + perl-5.8.5-dor/64 - -PERL_DL_NONLAZY=1 /pro/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, -'blib/lib', 'blib/arch')" t/*.t -t/01base................ok -t/10general.............ok -t/15nls.................ok -t/20select..............ok -t/21nchar............... Database and client versions and character sets: -Database 9.2.0.1.0 CHAR set is US7ASCII (Non-Unicode), NCHAR set is AL16UTF16 ( -nicode) -Client 9.2.0.1 NLS_LANG is '', NLS_NCHAR is '' -t/21nchar...............ok -t/22nchar_al32utf8......ok -t/22nchar_utf8..........ok -t/23wide_db.............skipped - all skipped: Database character set is not Unicode -t/23wide_db_8bit........skipped - all skipped: Database character set is not Unicode -t/23wide_db_al32utf8....skipped - all skipped: Database character set is not Unicode -t/24implicit_utf8.......ok -t/25plsql...............ok -t/30long................ok 188/470DBD::Oracle::db do failed: ORA-03237: Initial -Extent of specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: -OCIStmtExecute) [for Statement "create table dbd_ora__drop_me ( idx integer, ln - NCLOB, dt date )"] at t/nchar_test_lib.pl line 356. -t/30long................ok 189/470DBD::Oracle::st execute failed: ORA-00942: ta -le or view does not exist (DBD ERROR: error possibly near <*> indicator at char -12 in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statem -nt "insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1= -0, :p2='0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0.x.X0 -x.X...'] at t/30long.t line 153. -# Failed test (t/30long.t at line 153) -t/30long................NOK 190DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=41, -:p2='12345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -6789012345678901234567890123456789012345678901234567890123456789012345678901234 -...'] at t/30long.t line 154. -# Failed test (t/30long.t at line 154) -t/30long................NOK 191DBD::Oracle::st execute failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 12 -in 'insert into <*>dbd_ora__drop_me values (:p1, :p2, SYSDATE)') [for Statement -"insert into dbd_ora__drop_me values (?, ?, SYSDATE)" with ParamValues: :p1=42, -:p2='2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -fabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcdefabcd2bcd -...'] at t/30long.t line 155. -t/30long................NOK 192# Failed test (t/30long.t at line 155) -DBD::Oracle::st execute failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 12 in 'insert into <*>dbd_ora__dr -p_me values (:p1, :p2, SYSDATE)') [for Statement "insert into dbd_ora__drop_me -alues (?, ?, SYSDATE)" with ParamValues: :p1=43, :p2=undef] at t/30long.t line -56. -# Failed test (t/30long.t at line 156) -t/30long................NOK 193DBD::Oracle::db prepare failed: ORA-00942: table -or view does not exist (DBD ERROR: error possibly near <*> indicator at char 14 -in 'select * from <*>dbd_ora__drop_me order by idx') [for Statement "select * f -om dbd_ora__drop_me order by idx"] at t/30long.t line 170. -# Failed test (t/30long.t at line 170) -Can't call method "trace" on an undefined value at t/30long.t line 171. -t/30long................NOK 194# Looks like you planned 470 tests but only ran -94. -# Looks like your test died just after 194. -t/30long................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 190-470 - Failed 281/470 tests, 40.21% okay (less 122 skipped tests: 67 okay, 14. -6%) -t/31lob.................DBD::Oracle::db do failed: ORA-03237: Initial Extent of -specified size cannot be allocated in tablespace (PROBEV) (DBD ERROR: OCIStmtEx -cute) [for Statement " - CREATE TABLE dbd_ora__drop_me ( - id INTEGER NOT NULL, - data BLOB - ) - "] at t/31lob.t line 21. -DBD::Oracle::db do failed: ORA-00942: table or view does not exist (DBD ERROR: -rror possibly near <*> indicator at char 12 in 'INSERT INTO <*>dbd_ora__drop_me -(id,data) VALUES (1, EMPTY_BLOB())') [for Statement "INSERT INTO dbd_ora__drop_ -e (id,data) VALUES (1, EMPTY_BLOB())"] at t/31lob.t line 31. -DBD::Oracle::db prepare failed: ORA-00942: table or view does not exist (DBD ER -OR: error possibly near <*> indicator at char 17 in 'SELECT data FROM <*>dbd_or -__drop_me WHERE id = :p1') [for Statement "SELECT data FROM dbd_ora__drop_me WH -RE id = ?"] at t/31lob.t line 34. -Can't call method "bind_param" on an undefined value at t/31lob.t line 36. -# Looks like your test died before it could output anything. -t/31lob.................dubious - Test returned status 255 (wstat 65280, 0xff00) -DIED. FAILED tests 1-2 - Failed 2/2 tests, 0.00% okay -t/40ph_type.............ok -t/50cursor..............ok -t/60reauth..............ORACLE_USERID_2 not defined. Tests skipped. -skipped - all skipped: no reason given -t/70meta................ok -Failed Test Stat Wstat Total Fail Failed List of Failed -------------------------------------------------------------------------------- -t/30long.t 255 65280 470 557 118.51% 190-470 -t/31lob.t 255 65280 2 4 200.00% 1-2 -4 tests and 122 subtests skipped. -Failed 2/18 test scripts, 88.89% okay. 283/1883 subtests failed, 84.97% okay. -make: *** [test_dynamic] Error 255 - --- -H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/) -using perl-5.6.1, 5.8.0 & 633 on HP-UX 10.20 & 11.00, AIX 4.2, AIX 4.3, - WinNT 4, Win2K pro & WinCE 2.11 often with Tk800.024 &/| DBD-Unify -ftp://ftp.funet.fi/pub/languages/perl/CPAN/authors/id/H/HM/HMBRAND/ - - - - diff --git a/err_lob/err_nclob_form.msg b/err_lob/err_nclob_form.msg deleted file mode 100644 index 05587693..00000000 --- a/err_lob/err_nclob_form.msg +++ /dev/null @@ -1,189 +0,0 @@ -From dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org Tue Jul 22 07:40:59 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6M6UUD7096422 - for ; Tue, 22 Jul 2003 07:40:58 +0100 (BST) - (envelope-from dbi-users-return-19548-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 22 Jul 2003 07:40:58 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058814697:11:26523:33; Mon, 21 Jul 2003 19:11:37 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1126786; 21 Jul 2003 19:11 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E855B21C37F - for ; Mon, 21 Jul 2003 15:11:18 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 9010121C236 - for ; Mon, 21 Jul 2003 15:11:17 -0400 (EDT) -Received: (qmail 66848 invoked by uid 1005); 21 Jul 2003 19:11:15 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 66832 invoked by uid 76); 21 Jul 2003 19:11:15 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 21 Jul 2003 12:11:15 -0700 -Received: (qmail 559 invoked by uid 225); 21 Jul 2003 19:11:08 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 552 invoked by uid 507); 21 Jul 2003 19:11:07 -0000 -Received-SPF: unknown -Received: from sneakemail.com (HELO monkey.sneakemail.com) (207.106.87.13) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Mon, 21 Jul 2003 12:11:03 -0700 -Received: (qmail 22505 invoked by uid 501); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #3); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #2); 21 Jul 2003 19:10:57 -0000 -Received: (sneakemail censored 13502-46198 #1); 21 Jul 2003 19:10:57 -0000 -Date: Mon, 21 Jul 2003 21:10:53 +0200 -From: "Wolfgang Weisselberg" -To: dbi-users@perl.org -Subject: DBD::Oracle and unicode-NCLOBs leads to ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) -Message-ID: <13502-46198@sneakemail.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.4.1i -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.6 required=7.0 tests=CARRIAGE_RETURNS,FROM_ENDS_IN_NUMS,FROM_HAS_MIXED_NUMS,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_MUTT version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 6055 -Lines: 132 - -Hello all! - -Even after extensive googling and looking through the docs I fail -to fetch NCLOBs from an Oracle 9.2i database where the national -character set is unicode. - -I believe it has been done before, but I could not find anything ... -I would be grateful for any pointers. - - -NCLOBs work like CLOBs when the national character set is not -unicode, even with the old DBI 1.21 and DBD::Oracle 1.12 on an -Oracle 8 client. NVarchar2 and NChar work OK even with unicode. - -Setting NSL_LANG to AMERICAN_AMERICA.UTF8 or .AL32UTF8 does not -help, as I suspected. - -I tried using Oracle 9.2i (the DB is using 9.2i) on a Debian -Linux box. I upgraded DBI to 1.37 and DBD::Oracle to 1.14 (the -newest versions according to CPAN). I got zero errors on make -test with both. Perl is Debian's normal "perl5 (revision 5.0 -version 6 subversion 1)". - -A simple - select memo from unicode_test -(memo being the NCLOB field) fails (again, only with the national -charset being unicode). - -The relevant code snippet (RaiseError being set, of course): - -| $| = 1; -| print "DBI: $DBI::VERSION\n", -| "DBD::Oracle $DBD::Oracle::VERSION\n"; -| my $sth = $dbh->prepare("select memo from unicode_test"); -| $sth->execute(); -| -| while ( my ($memo) = $sth->fetchrow_array() ) { -| print Dumper $memo; -| } -| exit; - - -The output: - -| DBI: 1.37 -| DBD::Oracle 1.14 -| $VAR1 = ''; -| $VAR1 = ''; -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 77. - - - -Running with tracelevel 3: - [...] -| dbd_st_prepare'd sql SELECT -| dbd_describe SELECT (EXPLICIT, lb 99999999)... -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_execute SELECT (out0, lob0)... -| dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -| <- execute= '0E0' at nclobtest.pl line 79 via nclobtest.pl line 60 -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| dbd_st_fetch 1 fields SUCCESS -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -| 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x82f8e28)~INNER 'ParamValues') -| error: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| 1 <- FETCH= HASH(0x831661c)0keys at nclobtest.pl line 81 via nclobtest.pl line 60 -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. -| DBD::Oracle::st fetchrow_array failed: ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead) [for statement ``select memo from unicode_test'' with params: ]) at nclobtest.pl line 81. - - - -Tracelevel 9 (yes, it's a bit verbose :-/ ) - -[...] -| OCIDescriptorAlloc(0x831c058,0x8395228,OCI_DTYPE_LOB,0,0) -| fbh 1: 'MEMO' NO null , otype 112->112, dbsize 4000/4000, p0.s0 -| OCIAttrSet(0x8335b34,OCI_HTYPE_STMT,0xbffff30c,4,11,0x832d5a4)=SUCCESS -| OCIDefineByPos(0x8335b34,0x8395224,0x832d5a4,1,0x8395228,-1,112,0x83414e0,0x83414f0,0x8341500,0)=SUCCESS -| dbd_describe'd 1 columns (row bytes: 4000 max, 4000 est avg, cache: 6) -| <- prepare= DBI::st=HASH(0x831643c) at nclobtest.pl line 78 via nclobtest.pl line 60 -| -> execute for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -[...] -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbih_setup_fbav for 1 fields => 0x82f8e34 -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead field 2 SKIPPED: LOBlen 0, LongReadLen 99999999, BufLen 0, Got 0 -| 0 (rc=0): '' -| <- fetchrow_array= ( '' ) [1 items] row1 at nclobtest.pl line 81 via nclobtest.pl line 60 -| $VAR1 = ''; -[EXACTLY the same "-> fetchrow_array" to "<- fetchrow_array" again] -| $VAR1 = ''; -| -> fetchrow_array for DBD::Oracle::st (DBI::st=HASH(0x831643c)~0x82f8e28) -| dbd_st_fetch 1 fields... -| OCIStmtFetch(0x8335b34,0x832d5a4,1,2,0)=SUCCESS -| dbd_st_fetch 1 fields SUCCESS -| OCILobGetLength(0x832d530,0x832d5a4,0x832c69c,0xbffff31c)=SUCCESS -| OCILobRead(0x832d530,0x832d5a4,0x832c69c,0xbffff318,1,0x8394da0,24,(nil),(nil),0,1)=ERROR -| OCILobRead field 2 ERROR: LOBlen 6c, LongReadLen 99999999c, BufLen 24b, Got 6c -| OCIErrorGet(0x832d5a4,1,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=SUCCESS -| OCIErrorGet after OCILobRead (er1:ok): -1, 24806: ORA-24806: LOB form mismatch -| -| OCIErrorGet(0x832d5a4,2,"",0xbfffee88,"ORA-24806: LOB form mismatch -| ",1024,2)=NO_DATA -| 0 (rc=0): undef -| !! ERROR: 24806 'ORA-24806: LOB form mismatch (DBD ERROR: OCILobRead)' -| <- fetchrow_array= ( ) [0 items] row3 at nclobtest.pl line 81 via nclobtest.pl line 60 -[gets and prints error message] - - -Any ideas anyone? - --Wolfgang - diff --git a/err_lob/err_nulllobsegv.msg b/err_lob/err_nulllobsegv.msg deleted file mode 100644 index 6de3c99b..00000000 --- a/err_lob/err_nulllobsegv.msg +++ /dev/null @@ -1,93 +0,0 @@ -From dbi-users-return-1743-Tim.Bunce=ig.co.uk@perl.org Wed Apr 11 04:00:48 2001 -Return-Path: -Received: from oink by toad.ig.co.uk (8.8.8+Sun/SMI-SVR4) - id EAA17912; Wed, 11 Apr 2001 04:00:48 +0100 (BST) -Received: from 194.217.242.36 by oink with SMTP (PP) id <02579-1@oink>; - Sat, 11 Apr 1970 04:00:28 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 986956750:10:04398:0; Wed, 11 Apr 2001 02:39:10 GMT -Received: from tmtowtdi.perl.org ([209.85.3.25]) by punt-1.mail.demon.net - id aa1106187; 11 Apr 2001 2:39 GMT -Received: (qmail 32618 invoked by uid 508); 11 Apr 2001 02:39:06 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 32603 invoked from network); 11 Apr 2001 02:39:05 -0000 -Received: from owns.warpcore.org (216.81.249.18) by tmtowtdi.perl.org with SMTP; - 11 Apr 2001 02:39:05 -0000 -Received: (from thebrain@localhost) by owns.warpcore.org (8.11.1/8.11.1) - id f3B2cxH06298 for dbi-users@perl.org; - Tue, 10 Apr 2001 21:38:59 -0500 -Date: Tue, 10 Apr 2001 21:38:59 -0500 -From: Stephen Clouse -To: dbi-users@perl.org -Subject: Bizarre DBD::Oracle Segfault -Message-ID: <20010410213859.B2766@owns.warpcore.org> -Mail-Followup-To: dbi-users@perl.org -Mime-Version: 1.0 -Content-Type: text/plain -Content-Disposition: inline; filename="msg.pgp" -User-Agent: Mutt/1.2.5i -Status: RO -Content-Length: 1918 -Lines: 54 - ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -I sent an email to the dbi-users list about a number of DBD::Oracle CLOB -handling problems waaaaaaaaaaaaaaay back (end of January or so) that today -someone dug up and inquired if I had ever found fixes for what I had pointed -out. - -The problems outlined that day turned out to be the test script itself, which -was doing so much bizarre stuff on one statement that DBD::Oracle just went to -sleep instead (and so was the actual program that instigated the writing of the -test script). - -Well, all but one problem was the script. This, the most serious one, continues -to linger: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',undef); - -On Linux, DBI 1.15, Oracle 8.1.6, and DBD::Oracle 1.06, this segfaults on the -execute. Unfortunately this manifests itself too deep in Oracle for me to -debug. - -The bizarre part is, either of the two snippets below will work: - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',''); -$st->execute('B','B',undef); - -my $st = $db->prepare('INSERT INTO foo (col1, col2, col3) VALUES (?,?,?)'); -$st->bind_param(3,undef,{ ora_type => ORA_CLOB }); -$st->execute('A','A',$lobvalue); -$st->execute('B','B',undef); - -It's only when binding undef as the LOB value in the very first execute of a -statement that the segfault occurs. At any other time, it's kosher. That -qualifies as bizarre in my book. - -Your guess is better than mine. - -- -- -Stephen Clouse -Senior Programmer, IQ Coordinator Project Lead -The IQ Group, Inc. - ------BEGIN PGP SIGNATURE----- -Version: PGP 6.5.8 - -iQA+AwUBOtPDwgOGqGs0PadnEQLmtgCeJHTStLu8Q8oFb9UQ4995f8vhZH8Al1p6 -RD5m0FEJH2tQiY0+b6542mQ= -=L0M+ ------END PGP SIGNATURE----- - diff --git a/err_lob/err_tmplobfree.msg b/err_lob/err_tmplobfree.msg deleted file mode 100644 index 0ec8f940..00000000 --- a/err_lob/err_tmplobfree.msg +++ /dev/null @@ -1,537 +0,0 @@ -From SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com Wed Aug 25 17:53:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PGpkpQ033405 - for ; Wed, 25 Aug 2004 17:53:57 +0100 (BST) - (envelope-from SRS0=VEIf=LP=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 17:53:57 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1Bzyve-0007kY-Gp; - Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1Bzyve-0007kY-Gp - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1Bzyvd-0000zb-Lg - for pobox@data-plan.com; Wed, 25 Aug 2004 14:39:10 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id AA6D8B0635; - Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 9B2A1B0BB0 - for ; Wed, 25 Aug 2004 10:39:08 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -Received: from natnoddy.rzone.de (natnoddy.rzone.de [81.169.145.166]) - by lime.pobox.com (Postfix) with ESMTP id 2AAB1B0635 - for ; Wed, 25 Aug 2004 10:39:06 -0400 (EDT) -Received: from genericom.de (pD95195AC.dip.t-dialin.net [217.81.149.172]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7PEc05w018990 - for ; Wed, 25 Aug 2004 16:38:01 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412CA445.FC2F9EF2@genericom.de> -Date: Wed, 25 Aug 2004 16:37:57 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim.Bunce@pobox.com -Subject: DBD::Oracle: Freeing a temporary blob -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms4BC2D4519D41A502BB06559C" -Status: RO -X-Status: A -Content-Length: 4985 -Lines: 122 - -This is a cryptographically signed message in MIME format. - ---------------ms4BC2D4519D41A502BB06559C -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Dear Tim, - -first, I would really like to thank you for the great work you have done -with your DBI/DBD work. We are using it extensively in several projects -and we are highly pleased. - -Unfortunately I have now encountered a problem we need to fix urgently, -since our customer's production is seriously affected. - -We tried for many days to find a solution (google, newsgroups, -trial-and-error...), without luck. So my last chance is to contact you -directly, although I assume you have a lot work yourself. - ---- - -The problem: - -Our database contains a stored function "ReadUnitBlob()" that returns a -temporary blob: - -function ReadUnitBlob(UnitID_IN in integer) return blob -is -... -begin - ... - dbms_lob.createtemporary(retBlob, false, dbms_lob.call); - dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); - ... - return retBlob; -end; - -We call this function in Perl in a big loop to fetch a lot of blobs (~ -100000) using something like: - -my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -ora_auto_lob => 0 }); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); -my ($loc) = $sth->fetchrow_array(); -$sth->finish(); -... -while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) - ... - -Although this works, it has a big disadvantage: Oracle does not -automaticaly free the temporary blob, so it shortly runs out of temp. -space. (confirmed with "select * from v$temporary_lobs"). - -Acording to the Oracle docs this can be we solved by implicitly freeing -the temp. blob, e.g. by calling the PLSQL method -"dbms_lob.freetemporary()". I tried differnt ways to do this with -DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -locator from the my stored procedure and to pass it to a call of -"dbms_lob.freetemporary()": - -my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -ora_auto_lob => 0 }); -my $bloc; -$sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -$sth->bind_param(":unitID", $unitID); -$sth->execute(); - -obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) - -Can you help me??? Do you know a way how to free the temp. blob using -DBD::Oracle (using Oracle::OCI is not possible, since the customer is -strinctly refusing to install it). - -Otherwise, would it be possible include an additional DBD::Oracle LOB -Locator Method "ora_lob_freetemporary()" that warps -"OCILobFreeTemporary" ? - -Any help is really appreciated! - -Greeting from Germany, - - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------ms4BC2D4519D41A502BB06559C -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjUxNDM3NThaMCMGCSqG -SIb3DQEJBDEWBBS+u38esQAv19TdNkv4jgxlzsRqSzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAJQgoN5ASnyjnB7bgrv1+V7Cu4ULKe1CkHs0IEZaB -KuJcm98U7kskRyC5g6YNopuJxFbr19K3q5rrJGoUscKjiw== ---------------ms4BC2D4519D41A502BB06559C-- - - -From SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com Wed Aug 25 22:47:05 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PLjxpJ037568 - for ; Wed, 25 Aug 2004 22:47:04 +0100 (BST) - (envelope-from SRS0=SXka=LP=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 25 Aug 2004 22:47:04 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C04j1-00038v-Pz; - Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C04j1-00038v-Pz - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:31 +0000 -Received: from [208.210.124.73] (helo=gold.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C04j0-00002I-FU - for pobox@data-plan.com; Wed, 25 Aug 2004 20:50:30 +0000 -Received: from gold.pobox.com (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id AD1815463; - Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from gold (localhost [127.0.0.1]) - by gold.pobox.com (Postfix) with ESMTP id 85FFF55E7 - for ; Wed, 25 Aug 2004 16:50:29 -0400 (EDT) -Received-SPF: none (gold.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail04.svc.cra.dublin.eircom.net (mail04.svc.cra.dublin.eircom.net [159.134.118.20]) - by gold.pobox.com (Postfix) with SMTP id 14C005463 - for ; Wed, 25 Aug 2004 16:50:25 -0400 (EDT) -Received: (qmail 5678 messnum 5046341 invoked from network[213.94.228.233/unknown]); 25 Aug 2004 20:50:23 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail04.svc.cra.dublin.eircom.net (qp 5678) with SMTP; 25 Aug 2004 20:50:23 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7PKsrof034865; - Wed, 25 Aug 2004 21:54:53 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7PKsqas034864; - Wed, 25 Aug 2004 21:54:52 +0100 (BST) -Date: Wed, 25 Aug 2004 21:54:52 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim.Bunce@pobox.com -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040825205452.GC34655@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412CA445.FC2F9EF2@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 4674 -Lines: 124 - -On Wed, Aug 25, 2004 at 04:37:57PM +0200, Philipp Lang wrote: -> Dear Tim, -> -> first, I would really like to thank you for the great work you have done -> with your DBI/DBD work. We are using it extensively in several projects -> and we are highly pleased. - -Thanks Philipp! - -> Unfortunately I have now encountered a problem we need to fix urgently, -> since our customer's production is seriously affected. -> -> We tried for many days to find a solution (google, newsgroups, -> trial-and-error...), without luck. So my last chance is to contact you -> directly, although I assume you have a lot work yourself. - -I am very busy and what little spare time I have for DBD::Oracle -is going into trying to get 1.16 released (which is proving to be -hard as we're tripping over Oracle bugs when an Oracle 8 client -talks to an Oracle 9+ server.) It's a major release that will help -many people so I need to give that priority. - -Separately I am exploring ways to fund DBI and DBD::Oracle development -so I can devote more time to it. There's is much that needs to be -done and much more that could be done beyond that. - -The Perl Foundation (TPF) have setup a way for people and companies -to make donations for DBI development [as yet unannounced so please -keep to yourself]. A note on the contribution could indicate that the -donor would like it used for a particular purpose, such as DBD::Oracle. - -Anyway, to cut a long story short, it would be much easier to devote -time to this if it could be funded in some way. - -I think the TPF setup is working so it could be done that way. -Alternatively you could contract me to do the work for you. -That would be quicker and simpler for you as TPF's non-profit -status doesn't make a difference to European donors. - -My standard daily rate for add-hoc consulting is 1600 Euro. -I'd expect to be able to sort this out inside a day, and prefer -fixed-price quotes anyway, so would 1600 Euro be okay? - -Of course, if you feel your company would like to either -make a general contribution to DBI/DBD::Oracle development beyond -that, or to fund the development of specific functionality that -would be of extra value to you then I'd be happy to talk about that. - -I hate asking for money, and would much rather dig into the code and -reply with a patch, but it's just not practical for me now. Sorry. - -Tim. - -> --- -> -> The problem: -> -> Our database contains a stored function "ReadUnitBlob()" that returns a -> temporary blob: -> -> function ReadUnitBlob(UnitID_IN in integer) return blob -> is -> ... -> begin -> ... -> dbms_lob.createtemporary(retBlob, false, dbms_lob.call); -> dbms_lob.loadfromfile(retBlob, bfileIn, fileLen); -> ... -> return retBlob; -> end; -> -> We call this function in Perl in a big loop to fetch a lot of blobs (~ -> 100000) using something like: -> -> my $sth = $DBH->prepare("select ReadUnitBlob(:unitID) from dual", { -> ora_auto_lob => 0 }); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> my ($loc) = $sth->fetchrow_array(); -> $sth->finish(); -> ... -> while(my $data = $DBH->ora_lob_read($loc, $offset, $chunk_size)) -> ... -> -> Although this works, it has a big disadvantage: Oracle does not -> automaticaly free the temporary blob, so it shortly runs out of temp. -> space. (confirmed with "select * from v$temporary_lobs"). -> -> Acording to the Oracle docs this can be we solved by implicitly freeing -> the temp. blob, e.g. by calling the PLSQL method -> "dbms_lob.freetemporary()". I tried differnt ways to do this with -> DBD::Oracle, but never succeeded. I just did not manage to fetch the LOB -> locator from the my stored procedure and to pass it to a call of -> "dbms_lob.freetemporary()": -> -> my $sth = $dbh->prepare("begin :bloc := ReadUnitBlob(:unitID); end;", { -> ora_auto_lob => 0 }); -> my $bloc; -> $sth->bind_param_inout( ":bloc", \$bloc, ORA_BLOB); -> $sth->bind_param(":unitID", $unitID); -> $sth->execute(); -> -> obviously the "ORA_BLOB" type for bind_param_inout() is wrong here ;) -> -> Can you help me??? Do you know a way how to free the temp. blob using -> DBD::Oracle (using Oracle::OCI is not possible, since the customer is -> strinctly refusing to install it). -> -> Otherwise, would it be possible include an additional DBD::Oracle LOB -> Locator Method "ora_lob_freetemporary()" that warps -> "OCILobFreeTemporary" ? -> -> Any help is really appreciated! -> -> Greeting from Germany, -> -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - -From SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com Thu Aug 26 14:06:45 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QD6Som051890 - for ; Thu, 26 Aug 2004 14:06:45 +0100 (BST) - (envelope-from SRS0=eIh3=LQ=genericom.de=pl@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 14:06:45 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0HX2-0003PB-Sd; - Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [194.217.242.223] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0HX2-0003PB-Sd - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0HX2-0003BR-F8 - for pobox@data-plan.com; Thu, 26 Aug 2004 10:31:00 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id DC4BFB0D27; - Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id CE95AB0D7D - for ; Thu, 26 Aug 2004 06:30:59 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of pl@genericom.de does not designate permitted sender hosts) -X-Pobox-Antispam: dnsbl/blackholes.five-ten-sg.com returned DENY: for 81.169.145.165(natsmtp00.rzone.de) -Received: from natsmtp00.rzone.de (natsmtp00.rzone.de [81.169.145.165]) - by lime.pobox.com (Postfix) with ESMTP id 71107B0D27 - for ; Thu, 26 Aug 2004 06:30:56 -0400 (EDT) -Received: from genericom.de (pD9E61E09.dip.t-dialin.net [217.230.30.9]) - by post.webmailer.de (8.12.10/8.12.10) with ESMTP id i7QAUoTY009695 - for ; Thu, 26 Aug 2004 12:30:51 +0200 (MEST) -Sender: pl@post.webmailer.de -Message-ID: <412DBBD7.2C124831@genericom.de> -Date: Thu, 26 Aug 2004 12:30:47 +0200 -From: Philipp Lang -Organization: Genericom Software -X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.4.24 i686) -X-Accept-Language: de, en -MIME-Version: 1.0 -To: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------msB92907D67E7D4C0121D50420" -Status: O -X-Status: A -Content-Length: 3040 -Lines: 58 - -This is a cryptographically signed message in MIME format. - ---------------msB92907D67E7D4C0121D50420 -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - -Tim Bunce wrote: -> -> I hate asking for money, and would much rather dig into the code and -> reply with a patch, but it's just not practical for me now. Sorry. - -Thanks for your quick reply. I can fully understand your position in -this issue. We will need to submit this issue to our customer, and -eventually it will be their decision, since a) the problem technically -originates in external components -and b) our work is payed on a time and material basis. - -Thanks again, - Philipp - --- -Dipl. Inf. Philipp Lang Genericom Software GmbH -Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -Fax +49 (0)7031/8739-11 71065 Sindelfingen -pl@genericom.de www.genericom.de ---------------msB92907D67E7D4C0121D50420 -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" -Content-Description: S/MIME Cryptographic Signature - -MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC -Aw0wggMJMIICcqADAgECAg4WKgAAAALXCfeUwksXHjANBgkqhkiG9w0BAQQFADCBvDELMAkG -A1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoT -MVRDIFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgxIjAg -BgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0BCQEWGmNlcnRp -ZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTAzMTIwODA5NTQyNFoXDTA1MDEzMDA5NTQyNFow -RDELMAkGA1UEBhMCREUxFTATBgNVBAMTDFBoaWxpcHAgTGFuZzEeMBwGCSqGSIb3DQEJARYP -cGxAZ2VuZXJpY29tLmRlMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJqCn5ZXevTm3KgAKlKk -tOMzn1utWbcKoyrjuUSUOk9hwKXqjCtlBrNUDfVCtJIFWTU/2diijqormxUCXYr60F8CAwEA -AaOByDCBxTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAzBglghkgBhvhCAQgEJhYk -aHR0cDovL3d3dy50cnVzdGNlbnRlci5kZS9ndWlkZWxpbmVzMBEGCWCGSAGG+EIBAQQEAwIF -oDBdBglghkgBhvhCAQMEUBZOaHR0cHM6Ly93d3cudHJ1c3RjZW50ZXIuZGUvY2dpLWJpbi9j -aGVjay1yZXYuY2dpLzE2MkEwMDAwMDAwMkQ3MDlGNzk0QzI0QjE3MUU/MA0GCSqGSIb3DQEB -BAUAA4GBAI4bC7MGQQTY9Cp09FYwPychOQs8yFNKHrqYwFhXOirqVTqwo1wgxuSO5/fYWbcs -neWGio3swv0y+jn7o0gkrr/pHNbbm/YmCMuiGuwciH2y4GU2BOukFFP4Otke5UL9Yc9l13eG -Aoaf9ApqRrckhbhLhjz3+gyUM5XRYpoOZX0LMYIB6TCCAeUCAQEwgc8wgbwxCzAJBgNVBAYT -AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBU -cnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQL -ExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0 -ZUB0cnVzdGNlbnRlci5kZQIOFioAAAAC1wn3lMJLFx4wCQYFKw4DAhoFAKCBsTAYBgkqhkiG -9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNDA4MjYxMDMwNDhaMCMGCSqG -SIb3DQEJBDEWBBQbWUdl+peoD/lHpzCOnuQfzAsbJzBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqG -SIb3DQMHMA4GCCqGSIb3DQMCAgIAgDAHBgUrDgMCBzANBggqhkiG9w0DAgIBQDANBggqhkiG -9w0DAgIBKDANBgkqhkiG9w0BAQEFAARAXzFame8ymLqgf+7nZ4V7L9e9J+aG6z5ipa+iv76v -EFAg5QObdHdvTnq5QEAjEnLKgeUGvdgpS6PA0h+beEIeIA== ---------------msB92907D67E7D4C0121D50420-- - - -From SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com Thu Aug 26 16:42:55 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QFgKp1054926 - for ; Thu, 26 Aug 2004 16:42:55 +0100 (BST) - (envelope-from SRS0=T6ya=LQ=dansat.data-plan.com=timbo@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 26 Aug 2004 16:42:55 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1C0L1E-0005sL-5Z; - Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1C0L1E-0005sL-5Z - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from [208.58.1.198] (helo=lime.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1C0L1E-0001t1-Cm - for pobox@data-plan.com; Thu, 26 Aug 2004 14:14:24 +0000 -Received: from lime.pobox.com (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 541E8AFAD6; - Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from lime (localhost [127.0.0.1]) - by lime.pobox.com (Postfix) with ESMTP id 1C39FB0747 - for ; Thu, 26 Aug 2004 10:14:23 -0400 (EDT) -Received-SPF: none (lime.pobox.com: domain of timbo@dansat.data-plan.com does not designate permitted sender hosts) -Received: from mail01.svc.cra.dublin.eircom.net (mail01.svc.cra.dublin.eircom.net [159.134.118.17]) - by lime.pobox.com (Postfix) with SMTP id BFBB5AFAD6 - for ; Thu, 26 Aug 2004 10:14:19 -0400 (EDT) -Received: (qmail 12246 messnum 7731352 invoked from network[213.94.228.233/unknown]); 26 Aug 2004 14:14:17 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail01.svc.cra.dublin.eircom.net (qp 12246) with SMTP; 26 Aug 2004 14:14:17 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i7QEItof052863; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i7QEItr3052862; - Thu, 26 Aug 2004 15:18:55 +0100 (BST) -Date: Thu, 26 Aug 2004 15:18:55 +0100 -From: Tim Bunce -To: Philipp Lang -Cc: Tim Bunce -Subject: Re: DBD::Oracle: Freeing a temporary blob -Message-ID: <20040826141855.GC52359@dansat.data-plan.com> -References: <412CA445.FC2F9EF2@genericom.de> <20040825205452.GC34655@dansat.data-plan.com> <412DBBD7.2C124831@genericom.de> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <412DBBD7.2C124831@genericom.de> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 926 -Lines: 25 - -Okay. Thanks. Let me know how it turns out. - -Tim. - -On Thu, Aug 26, 2004 at 12:30:47PM +0200, Philipp Lang wrote: -> Tim Bunce wrote: -> > -> > I hate asking for money, and would much rather dig into the code and -> > reply with a patch, but it's just not practical for me now. Sorry. -> -> Thanks for your quick reply. I can fully understand your position in -> this issue. We will need to submit this issue to our customer, and -> eventually it will be their decision, since a) the problem technically -> originates in external components -> and b) our work is payed on a time and material basis. -> -> Thanks again, -> Philipp -> -> -- -> Dipl. Inf. Philipp Lang Genericom Software GmbH -> Tel. +49 (0)7031/8739-26 Tilsiter Str. 4-6 -> Fax +49 (0)7031/8739-11 71065 Sindelfingen -> pl@genericom.de www.genericom.de - - diff --git a/err_unicode/err_char.msg b/err_unicode/err_char.msg deleted file mode 100644 index d2a7a4a3..00000000 --- a/err_unicode/err_char.msg +++ /dev/null @@ -1,129 +0,0 @@ -From dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org Fri May 31 15:39:50 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g4VEdno73229 - for ; Fri, 31 May 2002 15:39:49 +0100 (BST) - (envelope-from dbi-users-return-11724-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 31 May 2002 15:39:49 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1022854157:20:06570:1; Fri, 31 May 2002 14:09:17 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2005972; 31 May 2002 14:08 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 210F42BF43 - for ; Fri, 31 May 2002 10:08:39 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (unknown [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id 8D88B2BF11 - for ; Fri, 31 May 2002 10:08:38 -0400 (EDT) -Received: (qmail 47355 invoked by uid 1005); 31 May 2002 14:07:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 47340 invoked by uid 76); 31 May 2002 14:07:41 -0000 -Received: from wsrgeh.wsr.ac.at (HELO wsrgeh.wsr.ac.at) (143.130.16.2) - by onion.perl.org (qpsmtpd/0.07b) with SMTP; Fri May 31 14:07:41 2002 -0000 -Received: from dialog.wsr.ac.at (dialog.wsr.ac.at [143.130.50.66]) - by wsrgeh.wsr.ac.at (8.11.6/8.11.6) with ESMTP id g4VE8Or11772 - for ; Fri, 31 May 2002 16:08:24 +0200 -Received: (from hjp@localhost) - by dialog.wsr.ac.at (8.11.6/8.11.6) id g4VE8Nf12538 - for dbi-users@perl.org; Fri, 31 May 2002 16:08:23 +0200 -Date: Fri, 31 May 2002 16:08:23 +0200 -From: "Peter J. Holzer" -To: dbi-users@perl.org -Subject: Re: Insert a blank value into Oracle -Message-ID: <20020531160823.F28779@wsr.ac.at> -Mail-Followup-To: "Peter J. Holzer" , - dbi-users@perl.org -References: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw> -Mime-Version: 1.0 -Content-Type: multipart/signed; micalg=pgp-md5; - protocol="application/pgp-signature"; boundary="aZoGpuMECXJckB41" -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -In-Reply-To: <1797C3D07B8BD311BC9200A0C9C85E0F0369DCCF@mail.gss.com.tw>; from larry_wu@mail.gss.com.tw on Fri, May 31, 2002 at 06:38:45PM +0800 -Status: RO -Content-Length: 2819 -Lines: 74 - ---aZoGpuMECXJckB41 -Content-Type: text/plain; charset=iso-8859-1 -Content-Disposition: inline -Content-Transfer-Encoding: quoted-printable - -On 2002-05-31 18:38:45 +0800, Larry Wu (=A7d=A4l=B7=D3) wrote: -> I encountered a problem to insert a space value ( like ' ' ) into Oracle -> database. -[...] -> Unfortunately, I have a table A contained a not allow null column -> NotNullCol. Now I want to insert a row like below: ->=20 -> $sth =3D $dbh->prepare( qq{ insert into A ( KeyCol, NotNullCol ) -> values (?,?)} ); -> $sth->bind_param(1, '1'); -> $sth->bind_param(2, ' '); -> $sth->execute; ->=20 -> When I executed this file I got an error from Oracle: Can't insert NULL -> value into ( "A"."NotNullCol") (DBD ERROR: OCIStmtExecute). -> I think the space value was truncated in the process. Could any one tell = -me -> how to keep a blank space in my bind_param ? - -use DBD::Oracle qw(:ora_types); -[...] -$sth->bind_param(2, ' ', { ora_type =3D> ORA_CHAR }); - -This is a frequently asked question here. The default type for strings, -ORA_VARCHAR2, strips trailing blanks from strings. A few months ago, -during one of the diskussuions about this feature, Tim said that he -might add a way to change the default in a future version of -DBD::Oracle. If he doesn't, maybe a paragraph like the following should -be added to the doc (not sure where - it fits below "Using DBD::Oracle -with Oracle 8 - Features and Issues" but it isn't Oracle 8 specific): - - =3Dhead2 Inserting strings with trailing spaces - - OCI provides several string types which behave differently. - Unfortunately, none of them can store arbitrary perl strings. - By default, DBD::Oracle binds string variables as ORA_VARCHAR2, - which allows embedded NUL characters but strips trailing spaces. If - you need trailing spaces, but don't need embedded NUL characters, - you can explicetly bind the param to type ORA_CHAR with: - - $sth->bind_param(($field_num, $string_value, - { ora_type =3D> ORA_CHAR }); - - =20 - hp - ---=20 - _ | Peter J. Holzer | Aeltere Sources (also solche, die schon -|_|_) | Sysadmin WSR / LUGA | aelter als 12 Stunden sind) sollte man -| | | hjp@wsr.ac.at | bei Linux generell nicht einsetzen - -__/ | http://www.hjp.at/ | Real Time Linux?? -- Gerhard Schneider - ---aZoGpuMECXJckB41 -Content-Type: application/pgp-signature -Content-Disposition: inline - ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.0.6 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -iQDQAwUBPPeD11LjemazOuKpAQEtNAXUC6rFL0C0v6MNW/K5ggXcSDY7Xvrj6Ed/ -jqjHq2Dx+h2rIMWXCDIGZVphSG74u4FL41AQF/rzGR/e56qH7aAxVmaiLdQE/DRi -zzsoOHoPEg96FhHljDtCZyxHzsz9sRJ1dfW1PELn5r2OSYPPsVzMoeR4iEXnVjvV -ZYH/OfbKRKhysIHjcNYKcyQL87GXdjzCEas3Xz+jyxW2vqzGAwUfTim4ySY9rF37 -c5vopwrTFCsi58r1LccFhQqEfw== -=Xe8d ------END PGP SIGNATURE----- - ---aZoGpuMECXJckB41-- - diff --git a/err_unicode/err_twolongstr.msg b/err_unicode/err_twolongstr.msg deleted file mode 100644 index 5d6c357d..00000000 --- a/err_unicode/err_twolongstr.msg +++ /dev/null @@ -1,1256 +0,0 @@ -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Wed Nov 17 19:08:49 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAHJ8F8P027204 - for ; Wed, 17 Nov 2004 19:08:48 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 17 Nov 2004 19:08:48 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUUU6-0001mQ-FU; - Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUUU6-0001mQ-FU - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from [207.8.226.3] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUUU6-0000DF-68 - for pobox@data-plan.com; Wed, 17 Nov 2004 18:24:50 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9D10A120BFA; - Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from icicle (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 8C898120BEF - for ; Wed, 17 Nov 2004 13:24:49 -0500 (EST) -Received-SPF: none (icicle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by icicle.pobox.com (Postfix) with ESMTP id 362C6120BEC - for ; Wed, 17 Nov 2004 13:24:46 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 9C0CC244379 - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 17196-06 for ; - Wed, 17 Nov 2004 10:24:44 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 3131324406F - for ; Wed, 17 Nov 2004 10:24:44 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 10:22:44 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_006A_01C4CC8F.60A4F6F0" -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117173321.GA6272@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTMy6HoelzJHh9WSPaTpCdfuF1C4gABpsZg -Message-Id: <20041117182444.3131324406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 16865 -Lines: 527 - -This is a multi-part message in MIME format. - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -I did - it is attached to the posting. However, I will attach it again -here. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 9:33 AM -> To: Susan Cassidy -> Cc: dbi-users@perl.org -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> If you can post a small self-contained example that demonstrates -> the problem then I'll take a look. -> -> Tim. -> -> On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > I never got any response to my question about this problem. I -> thought I'd try again. -> > -> > -> > -> > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> 5.8.5. -> > -> > -> > -> > Thanks, -> > -> > Susan -> > -> > -> > -> > --------------------------------------------------------------------- -> ----------------------------------- -> > -> > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > Sent: Friday, November 05, 2004 10:23 AM -> > To: 'dbi-users@perl.org' -> > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for -> > insert into a LONG column' when data not LONG -> > -> > -> > -> > I had an application that was processing a bunch of xml and inserting -> into a table with a bunch of -> > VARCHAR2(4000) columns. -> > -> > -> > -> > A couple of the entries I was processing caused the 'ORA-01461: can -> bind a LONG value only for insert -> > into a LONG column' error. -> > -> > -> > -> > I put checks in for the length of the data, and nothing approached -> 4000 bytes in length. -> > -> > -> > -> > I tracked down some of the entries causing problems, and on certain -> specific data, if 2 columns -> > containing specific data are inserted together, I get this error. If -> only one of the 2 is inserted, I -> > do not get the error, regardless of which one of the two I insert. -> > -> > -> > -> > The lengths of the pieces of data are 1399 and 1397 characters. -> > -> > -> > -> > The data is somewhat odd-looking (we suspect some odd data is in this -> file), but there is no reason for -> > the error message to appear. -> > -> > -> > -> > Trace shows nothing helpful - it thinks the data is the right length. -> > -> > -> > -> > We've successfully inserted thousands of other, similar entries with -> no trouble. -> > -> > -> > -> > The basics are: -> > -> > #create table test_table (item1 varchar2(4000), item2 -> varchar2(4000)); -> > -> > -> > -> > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, ?)"; -> > -> > -> > -> > $sth=$dbh->prepare($statement) || -> > -> > errexit("bad prepare for stmt $statement, error: $DBI::errstr"); -> > -> > my $rc=$sth->execute(@vals) || -> > -> > errexit("can't execute statement: error: $DBI::errstr\n"); -> > -> > -> > -> > Trace shows: -> > -> > -> > -> > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > -> > -> prepare for DBD::Oracle::db (DBI::db=HASH(0x82d4178)~0x82d6580 -> 'INSERT INTO test_table -> > (item1,item2) VALUES (?, ?) -> > -> > ') thr#8148ff0 -> > -> > dbd_preparse scanned 2 distinct placeholders -> > -> > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl line -> 40 -> > -> > -> execute for DBD::Oracle::st (DBI::st=HASH(0x82d6640)~0x8149dcc -> 'version 11.2no service -> > password-encryptionservice -> > -> > udp-small-serversservice tcp-small-servers!hostname router1!!no ip -> domain-lookupip inspect name mysite -> > ftpip inspect name -> > -> > mysite smtpip inspect name mysite tcp!interface Ethernet0ip address -> 10.10.10.2 255.255.255.0ip -> > access-group 101 inip ins -> > -> > pect mysite inip inspect mysite outno keepalive!interface Serial0no -> ip addressencapsulation -> > frame-relay...' 'version 11.2 -> > -> > no service password-encryptionservice udp-small-serversservice tcp- -> small-servers!hostname router1!!no ip -> > domain-lookupip -> > -> > inspect name mysite ftpip inspect name mysite smtpip inspect name -> mysite tcp!interface Ethernet0ip -> > address 10.10.10.2 255 -> > -> > .255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite -> outno keepalive!interface Serial0no -> > ip addressencaps -> > -> > ulation frame-relayn...') thr#8148ff0 -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (type 0) -> > -> > bind :p1 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relay...' (size -> 1399/1400/0, ptype 4, otype 1) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (type 0) -> > -> > bind :p2 <== 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostnam -> > -> > e router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface E -> > -> > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!int -> > -> > erface Serial0no ip addressencapsulation frame-relayn...' (size -> 1397/1398/0, ptype 4, otype 1) -> > -> > dbd_st_execute INSERT (out0, lob0)... -> > -> > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > <- execute= undef at test_insert_large.pl line 42 -> > -> > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> 'ParamValues') thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line 42 -> > -> > -> $DBI::errstr (&) FETCH from lasth=HASH -> > -> > >> DBD::Oracle::st::errstr -> > -> > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' -> > -> > -- DBI::END -> > -> > -> disconnect_all for DBD::Oracle::dr -> (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > -> > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > -> > Connect done -> > -> > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > -> > Size of vals is 2 -> > -> > val 1 size 1399, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysite inip inspect mysite -> > outno keepalive!i -> > -> > nterface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11 -> > -> > .2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 IETF!router eigrp 69network -> > 10.0.0.0no auto-summar -> > -> > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0. -> > -> > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permit icmp 10.10.10.0 -> > 0.0.0.255 anyaccess- -> > -> > list 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-rep -> > -> > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 ad -> > -> > ministratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp a -> > -> > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 0.0.0.255 -> > time-exceededaccess-list 102 permit tcp -> > -> > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > val 2 size 1397, is: 'version 11.2no service password- -> encryptionservice udp-small-serversservice -> > tcp-small-servers!hostna -> > -> > me router1!!no ip domain-lookupip inspect name mysite ftpip inspect -> name mysite smtpip inspect name -> > mysite tcp!interface -> > -> > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 inip -> inspect mysiteinip inspect mysite -> > outno keepalive!in -> > -> > terface Serial0no ip addressencapsulation frame-relayno fair- -> queue!interface Serial0.1 point-to-pointip -> > address 10.10.11. -> > -> > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci 200 -> IETF!router eigrp 69network -> > 10.0.0.0no auto-summary -> > -> > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 0.0.0.0 -> 10.10.11.1access-list 101 permit -> > tcp 10.10.10.0 0.0 -> > -> > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 anyaccess- -> list 101 permiticmp 10.10.10.0 -> > 0.0.0.255 anyaccess-li -> > -> > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess-list -> 102 permit icmp any 10.10.10.0 -> > 0.0.0.255 echo-reply -> > -> > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> unreachableaccess-list 102 permit icmp any -> > 10.10.10.0 0.0.0.255 admi -> > -> > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 packet-too-bigaccess-list -> > 102 permit icmp any -> > -> > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 -> 0.0.0.255 time-exceededaccess-list -> > 102 permit tcp an -> > -> > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> 0line vty 0 4login!end' -> > -> > can't execute statement: error: ORA-01461: can bind a LONG value only -> for insert into a LONG column (DBD -> > ERROR: OCIStmtEx -> > -> > ecute) -> > -> > -> > -> > ! -> DESTROY for DBD::Oracle::db (DBI::db=HASH(0x82d6580)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#0) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > -> > ! <- DESTROY= undef during global destruction -> > -> > ! -> DESTROY for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER) -> thr#8148ff0 -> > -> > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> insert into a LONG column (DBD ERROR: -> > OCIStmtExecute)' (e -> > -> > rr#1) -> > -> > ! <- DESTROY= undef during global destruction -> > -> > -> > -> > I will attach the test program. Somehow it seems to think the -> datatype is LONG instead of VARCHAR. -> > -> > -> > -> > -> > -> > Anyone with ideas? -> > -> > -> > -> > -> > -> > Thanks, -> > -> > Susan -> - - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0 -Content-Type: application/octet-stream; - name="test_insert_large.pl" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="test_insert_large.pl" - -#!/usr/local/bin/perl -w=0A= -=0A= -use DBI;=0A= -=0A= -our $dbh;=0A= -our $sth;=0A= -=0A= -$dbuser=3D"proj1";=0A= -$dbpasswd=3D"proj1";=0A= -=0A= -$dbserver=3D'oracledev';=0A= -$db_sid=3D'AL32UTF8';=0A= -=0A= -##=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D connect to database = -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=0A= -=0A= -$dbh=3D DBI->connect("dbi:Oracle:host=3D$dbserver;sid=3D$db_sid", = -$dbuser, $dbpasswd,=0A= - {PrintError =3D> 0, AutoCommit =3D> 1}) or=0A= - errexit( "Unable to connect to $dbserver: $DBI::errstr");=0A= -print "Connect done\n";=0A= -=0A= -#create table test_table (item1 varchar2(4000), item2 varchar2(4000));=0A= -=0A= -=0A= -my $statement=3D"INSERT INTO test_table (item1,item2) VALUES (?, ?)";=0A= -print "stmt: $statement\n";=0A= -=0A= -@vals=3D(=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysite inip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permit icmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= - 'version 11.2no service password-encryptionservice = -udp-small-serversservice tcp-small-servers!hostname router1!!no ip = -domain-lookupip inspect name mysite ftpip inspect name mysite smtpip = -inspect name mysite tcp!interface Ethernet0ip address 10.10.10.2 = -255.255.255.0ip access-group 101 inip inspect mysiteinip inspect mysite = -outno keepalive!interface Serial0no ip addressencapsulation = -frame-relayno fair-queue!interface Serial0.1 point-to-pointip address = -10.10.11.2 255.255.255.252ip access-group 102 inframe-relay = -interface-dlci 200 IETF!router eigrp 69network 10.0.0.0no = -auto-summary!ip default-gateway 10.10.11.1no ip classlessip route = -0.0.0.0 0.0.0.0 10.10.11.1access-list 101 permit tcp 10.10.10.0 = -0.0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 = -anyaccess-list 101 permiticmp 10.10.10.0 0.0.0.255 anyaccess-list 101 = -deny ip any anyaccess-list 102 permit eigrp any anyaccess-list 102 = -permit icmp any 10.10.10.0 0.0.0.255 echo-replyaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 unreachableaccess-list 102 permit icmp any = -10.10.10.0 0.0.0.255 administratively-prohibitedaccess-list 102 permit = -icmp any 10.10.10.0 0.0.0.255 packet-too-bigaccess-list 102 permit icmp = -any 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any 10.10.10.0 = -0.0.0.255 time-exceededaccess-list 102 permit tcp any host 10.10.10.1 eq = -smtpaccess-list 102 deny ip any any!line con 0line vty 0 4login!end',=0A= -);=0A= -=0A= -print "Size of vals is ",scalar @vals,"\n";=0A= -my $z=3D0;=0A= -foreach my $x (@vals) {=0A= - my $len=3Dlength($x);=0A= - print "val ",++$z, " size $len, is: '$x'\n";=0A= -}=0A= -=0A= -DBI->trace(2);=0A= - $sth=3D$dbh->prepare($statement) ||=0A= - errexit("bad prepare for stmt $statement, error: $DBI::errstr");=0A= - my $rc=3D$sth->execute(@vals) ||=0A= - errexit("can't execute statement: error: $DBI::errstr\n");=0A= -=0A= -print "Done\n";=0A= -exit;=0A= -=0A= -=0A= -sub errexit {=0A= - my (@msg)=3D@_;=0A= - print @msg,"\n";=0A= - exit 1;=0A= -}=0A= -=0A= -=0A= -=0A= - -------=_NextPart_000_006A_01C4CC8F.60A4F6F0-- - - -From SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 00:15:21 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI0FC8G049539 - for ; Thu, 18 Nov 2004 00:15:21 GMT - (envelope-from SRS0=YmHr=OD=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 00:15:21 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUVdd-0002Nv-CF; - Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUVdd-0002Nv-CF - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1CUVdc-0005lu-Rs - for pobox@data-plan.com; Wed, 17 Nov 2004 19:38:45 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 4A256ADD6F; - Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from boggle (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 3D82CADD64 - for ; Wed, 17 Nov 2004 14:38:44 -0500 (EST) -Received-SPF: none (boggle.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by boggle.pobox.com (Postfix) with ESMTP id B23D4ADCF6 - for ; Wed, 17 Nov 2004 14:38:15 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id 0C9DF24435B - for ; Wed, 17 Nov 2004 11:38:14 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 18475-01 for ; - Wed, 17 Nov 2004 11:38:13 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id ACF0424406F - for ; Wed, 17 Nov 2004 11:38:13 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 11:36:14 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041117192902.GA31595@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTM27+9yfJDVs3WQIWAKc6DR3EgdQAAKfgw -Message-Id: <20041117193813.ACF0424406F@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -X-Status: A -Content-Length: 14671 -Lines: 489 - -NLS_LANG=.UTF8 -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -ORACLE_HOME=/home/oracle/product/9.2.0 -ORACLE_SID=AL32UTF8 -ORACLE_BASE=/home/oracle - -NLS_NCHAR is not set, because we are not using any NVARCHAR data item, and -haven't needed it. - -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 11:29 AM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > I did - it is attached to the posting. However, I will attach it again -> > here. -> > -> > Thanks, -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 9:33 AM -> > > To: Susan Cassidy -> > > Cc: dbi-users@perl.org -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > If you can post a small self-contained example that demonstrates -> > > the problem then I'll take a look. -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 09:15:52AM -0800, Susan Cassidy wrote: -> > > > I never got any response to my question about this problem. I -> > > thought I'd try again. -> > > > -> > > > -> > > > -> > > > This is DBD::Oracle 1.16, DBI 1.45, Oracle 9i (9.2), Linux, Perl -> > > 5.8.5. -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > > -> > > > -> > > > -> > > > ----------------------------------------------------------------- -> ---- -> > > ----------------------------------- -> > > > -> > > > From: Susan Cassidy [mailto:cassidy@systransoft.com] -> > > > Sent: Friday, November 05, 2004 10:23 AM -> > > > To: 'dbi-users@perl.org' -> > > > Subject: DBD::Oracle and strange problem with Oracle error 'ORA- -> > > 01461: can bind a LONG value only for -> > > > insert into a LONG column' when data not LONG -> > > > -> > > > -> > > > -> > > > I had an application that was processing a bunch of xml and -> inserting -> > > into a table with a bunch of -> > > > VARCHAR2(4000) columns. -> > > > -> > > > -> > > > -> > > > A couple of the entries I was processing caused the 'ORA-01461: -> can -> > > bind a LONG value only for insert -> > > > into a LONG column' error. -> > > > -> > > > -> > > > -> > > > I put checks in for the length of the data, and nothing -> approached -> > > 4000 bytes in length. -> > > > -> > > > -> > > > -> > > > I tracked down some of the entries causing problems, and on -> certain -> > > specific data, if 2 columns -> > > > containing specific data are inserted together, I get this error. -> If -> > > only one of the 2 is inserted, I -> > > > do not get the error, regardless of which one of the two I -> insert. -> > > > -> > > > -> > > > -> > > > The lengths of the pieces of data are 1399 and 1397 characters. -> > > > -> > > > -> > > > -> > > > The data is somewhat odd-looking (we suspect some odd data is in -> this -> > > file), but there is no reason for -> > > > the error message to appear. -> > > > -> > > > -> > > > -> > > > Trace shows nothing helpful - it thinks the data is the right -> length. -> > > > -> > > > -> > > > -> > > > We've successfully inserted thousands of other, similar entries -> with -> > > no trouble. -> > > > -> > > > -> > > > -> > > > The basics are: -> > > > -> > > > #create table test_table (item1 varchar2(4000), item2 -> > > varchar2(4000)); -> > > > -> > > > -> > > > -> > > > my $statement="INSERT INTO test_table (item1,item2) VALUES (?, -> ?)"; -> > > > -> > > > -> > > > -> > > > $sth=$dbh->prepare($statement) || -> > > > -> > > > errexit("bad prepare for stmt $statement, error: -> $DBI::errstr"); -> > > > -> > > > my $rc=$sth->execute(@vals) || -> > > > -> > > > errexit("can't execute statement: error: $DBI::errstr\n"); -> > > > -> > > > -> > > > -> > > > Trace shows: -> > > > -> > > > -> > > > -> > > > DBI 1.45-ithread default trace level set to 0x0/2 (pid 6230) -> > > > -> > > > -> prepare for DBD::Oracle::db -> (DBI::db=HASH(0x82d4178)~0x82d6580 -> > > 'INSERT INTO test_table -> > > > (item1,item2) VALUES (?, ?) -> > > > -> > > > ') thr#8148ff0 -> > > > -> > > > dbd_preparse scanned 2 distinct placeholders -> > > > -> > > > <- prepare= DBI::st=HASH(0x82d6640) at test_insert_large.pl -> line -> > > 40 -> > > > -> > > > -> execute for DBD::Oracle::st -> (DBI::st=HASH(0x82d6640)~0x8149dcc -> > > 'version 11.2no service -> > > > password-encryptionservice -> > > > -> > > > udp-small-serversservice tcp-small-servers!hostname router1!!no -> ip -> > > domain-lookupip inspect name mysite -> > > > ftpip inspect name -> > > > -> > > > mysite smtpip inspect name mysite tcp!interface Ethernet0ip -> address -> > > 10.10.10.2 255.255.255.0ip -> > > > access-group 101 inip ins -> > > > -> > > > pect mysite inip inspect mysite outno keepalive!interface -> Serial0no -> > > ip addressencapsulation -> > > > frame-relay...' 'version 11.2 -> > > > -> > > > no service password-encryptionservice udp-small-serversservice -> tcp- -> > > small-servers!hostname router1!!no ip -> > > > domain-lookupip -> > > > -> > > > inspect name mysite ftpip inspect name mysite smtpip inspect name -> > > mysite tcp!interface Ethernet0ip -> > > > address 10.10.10.2 255 -> > > > -> > > > .255.255.0ip access-group 101 inip inspect mysiteinip inspect -> mysite -> > > outno keepalive!interface Serial0no -> > > > ip addressencaps -> > > > -> > > > ulation frame-relayn...') thr#8148ff0 -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (type -> 0) -> > > > -> > > > bind :p1 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relay...' (size -> > > 1399/1400/0, ptype 4, otype 1) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (type -> 0) -> > > > -> > > > bind :p2 <== 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostnam -> > > > -> > > > e router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface E -> > > > -> > > > thernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!int -> > > > -> > > > erface Serial0no ip addressencapsulation frame-relayn...' (size -> > > 1397/1398/0, ptype 4, otype 1) -> > > > -> > > > dbd_st_execute INSERT (out0, lob0)... -> > > > -> > > > !! ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > <- execute= undef at test_insert_large.pl line 42 -> > > > -> > > > 1 -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x8149dcc)~INNER -> > > 'ParamValues') thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > 1 <- FETCH= HASH(0x83487e0)2keys at test_insert_large.pl line -> 42 -> > > > -> > > > -> $DBI::errstr (&) FETCH from lasth=HASH -> > > > -> > > > >> DBD::Oracle::st::errstr -> > > > -> > > > <- $DBI::errstr= 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' -> > > > -> > > > -- DBI::END -> > > > -> > > > -> disconnect_all for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x824771c)~0x82d419c) thr#8148ff0 -> > > > -> > > > <- disconnect_all= (not implemented) at DBI.pm line 673 -> > > > -> > > > Connect done -> > > > -> > > > stmt: INSERT INTO test_table (item1,item2) VALUES (?, ?) -> > > > -> > > > Size of vals is 2 -> > > > -> > > > val 1 size 1399, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysite inip inspect mysite -> > > > outno keepalive!i -> > > > -> > > > nterface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11 -> > > > -> > > > .2 255.255.255.252ip access-group 102 inframe-relay interface- -> dlci -> > > 200 IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summar -> > > > -> > > > y!ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> > > 0.0.0.0 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0. -> > > > -> > > > 0.0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permit icmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess- -> > > > -> > > > list 101 deny ip any anyaccess-list 102 permit eigrp any -> anyaccess- -> > > list 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-rep -> > > > -> > > > lyaccess-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 ad -> > > > -> > > > ministratively-prohibitedaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp a -> > > > -> > > > ny 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> > > 10.10.10.0 0.0.0.255 -> > > > time-exceededaccess-list 102 permit tcp -> > > > -> > > > any host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line -> con -> > > 0line vty 0 4login!end' -> > > > -> > > > val 2 size 1397, is: 'version 11.2no service password- -> > > encryptionservice udp-small-serversservice -> > > > tcp-small-servers!hostna -> > > > -> > > > me router1!!no ip domain-lookupip inspect name mysite ftpip -> inspect -> > > name mysite smtpip inspect name -> > > > mysite tcp!interface -> > > > -> > > > Ethernet0ip address 10.10.10.2 255.255.255.0ip access-group 101 -> inip -> > > inspect mysiteinip inspect mysite -> > > > outno keepalive!in -> > > > -> > > > terface Serial0no ip addressencapsulation frame-relayno fair- -> > > queue!interface Serial0.1 point-to-pointip -> > > > address 10.10.11. -> > > > -> > > > 2 255.255.255.252ip access-group 102 inframe-relay interface-dlci -> 200 -> > > IETF!router eigrp 69network -> > > > 10.0.0.0no auto-summary -> > > > -> > > > !ip default-gateway 10.10.11.1no ip classlessip route 0.0.0.0 -> 0.0.0.0 -> > > 10.10.11.1access-list 101 permit -> > > > tcp 10.10.10.0 0.0 -> > > > -> > > > .0.255 anyaccess-list 101 permit udp 10.10.10.0 0.0.0.255 -> anyaccess- -> > > list 101 permiticmp 10.10.10.0 -> > > > 0.0.0.255 anyaccess-li -> > > > -> > > > st 101 deny ip any anyaccess-list 102 permit eigrp any anyaccess- -> list -> > > 102 permit icmp any 10.10.10.0 -> > > > 0.0.0.255 echo-reply -> > > > -> > > > access-list 102 permit icmp any 10.10.10.0 0.0.0.255 -> > > unreachableaccess-list 102 permit icmp any -> > > > 10.10.10.0 0.0.0.255 admi -> > > > -> > > > nistratively-prohibitedaccess-list 102 permit icmp any 10.10.10.0 -> > > 0.0.0.255 packet-too-bigaccess-list -> > > > 102 permit icmp any -> > > > -> > > > 10.10.10.0 0.0.0.255 echoaccess-list 102 permit icmp any -> 10.10.10.0 -> > > 0.0.0.255 time-exceededaccess-list -> > > > 102 permit tcp an -> > > > -> > > > y host 10.10.10.1 eq smtpaccess-list 102 deny ip any any!line con -> > > 0line vty 0 4login!end' -> > > > -> > > > can't execute statement: error: ORA-01461: can bind a LONG value -> only -> > > for insert into a LONG column (DBD -> > > > ERROR: OCIStmtEx -> > > > -> > > > ecute) -> > > > -> > > > -> > > > -> > > > ! -> DESTROY for DBD::Oracle::db -> (DBI::db=HASH(0x82d6580)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#0) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY in DBD::_::common for DBD::Oracle::dr -> > > (DBI::dr=HASH(0x82d419c)~INNER) thr#8148ff0 -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > ! -> DESTROY for DBD::Oracle::st -> (DBI::st=HASH(0x8149dcc)~INNER) -> > > thr#8148ff0 -> > > > -> > > > ERROR: '1461' 'ORA-01461: can bind a LONG value only for -> > > insert into a LONG column (DBD ERROR: -> > > > OCIStmtExecute)' (e -> > > > -> > > > rr#1) -> > > > -> > > > ! <- DESTROY= undef during global destruction -> > > > -> > > > -> > > > -> > > > I will attach the test program. Somehow it seems to think the -> > > datatype is LONG instead of VARCHAR. -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Anyone with ideas? -> > > > -> > > > -> > > > -> > > > -> > > > -> > > > Thanks, -> > > > -> > > > Susan -> > > -> > -> - - - -From SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com Thu Nov 18 07:11:03 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id iAI7Ar8G057950 - for ; Thu, 18 Nov 2004 07:11:03 GMT - (envelope-from SRS0=xs68=OE=systransoft.com=cassidy@bounce2.pobox.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 18 Nov 2004 07:11:03 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@data-plan.com id 1CUaCR-0002mS-7P; - Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [194.217.242.72] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1CUaCR-0002mS-7P - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1CUaCQ-0004JQ-R5 - for pobox@data-plan.com; Thu, 18 Nov 2004 00:30:59 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 17ACAA3F35; - Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from integer (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 04F8DA3EAC - for ; Wed, 17 Nov 2004 19:30:58 -0500 (EST) -Received-SPF: none (integer.pobox.com: domain of cassidy@systransoft.com does not designate permitted sender hosts) -X-SPF-Guess: pass (seems reasonable for cassidy@systransoft.com to mail through 66.185.164.3) -Received: from mailhost.systransoft.com (mailhost.systransoft.com [66.185.164.3]) - by integer.pobox.com (Postfix) with ESMTP id A9FC6A3F4D - for ; Wed, 17 Nov 2004 19:30:43 -0500 (EST) -Received: from localhost (localhost [127.0.0.1]) - by mailhost.systransoft.com (Postfix) with ESMTP id DEA102441A9 - for ; Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from mailhost.systransoft.com ([127.0.0.1]) - by localhost (mailhost.systransoft.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 22204-10 for ; - Wed, 17 Nov 2004 16:30:41 -0800 (PST) -Received: from hapax (hapax [192.168.2.186]) - by mailhost.systransoft.com (Postfix) with ESMTP id 7AD52244370 - for ; Wed, 17 Nov 2004 16:30:40 -0800 (PST) -From: "Susan Cassidy" -To: "'Tim Bunce'" -Subject: RE: FW: DBD::Oracle and strange problem with Oracle error 'ORA-01461: can bind a LONG value only for insert into a LONG column' when data not LONG -Date: Wed, 17 Nov 2004 16:28:41 -0800 -Organization: SYSTRAN Software, Inc. -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Mailer: Microsoft Office Outlook, Build 11.0.5510 -In-Reply-To: <20041118001712.GB49519@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 -Thread-Index: AcTNA/o7HZXghXaJRbyz8M5kVQMQmwAAUBjg -Message-Id: <20041118003040.7AD52244370@mailhost.systransoft.com> -X-Virus-Scanned: by amavisd-new at systransoft.com -Status: RO -Content-Length: 1789 -Lines: 63 - -Hi, - -I set NLS_LANG to .US7ASCII, ran it again, and I get the same error. - -Of course, I could not use that in production. - -The really strange part, to me, was that if I just insert one of the 2 -problematic columns, it worked, but both together failed. - -Thanks, -Susan - -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Wednesday, November 17, 2004 4:17 PM -> To: Susan Cassidy -> Cc: 'Tim Bunce' -> Subject: Re: FW: DBD::Oracle and strange problem with Oracle error 'ORA- -> 01461: can bind a LONG value only for insert into a LONG column' when data -> not LONG -> -> And does the problem go away if NLS_LANG is set to a non-unicode charset? -> -> Tim. -> -> On Wed, Nov 17, 2004 at 11:36:14AM -0800, Susan Cassidy wrote: -> > NLS_LANG=.UTF8 -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORA_NLS33=/home/oracle/product/9.2.0/ocommon/nls/admin/data -> > ORACLE_HOME=/home/oracle/product/9.2.0 -> > ORACLE_SID=AL32UTF8 -> > ORACLE_BASE=/home/oracle -> > -> > NLS_NCHAR is not set, because we are not using any NVARCHAR data item, -> and -> > haven't needed it. -> > -> > Susan -> > -> > > -----Original Message----- -> > > From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> > > Sent: Wednesday, November 17, 2004 11:29 AM -> > > To: Susan Cassidy -> > > Cc: 'Tim Bunce' -> > > Subject: Re: FW: DBD::Oracle and strange problem with Oracle error -> 'ORA- -> > > 01461: can bind a LONG value only for insert into a LONG column' when -> data -> > > not LONG -> > > -> > > Thanks. What are your client side NLS_LANG and NLS_NCHAR settings? -> > > -> > > Tim. -> > > -> > > On Wed, Nov 17, 2004 at 10:22:44AM -0800, Susan Cassidy wrote: -> > > > I did - it is attached to the posting. However, I will attach it -> again -> > > > here. -> > > > -> > > > Thanks, -> > > > Susan -> > > > - - diff --git a/err_unsorted/err_etherreal.msg b/err_unsorted/err_etherreal.msg deleted file mode 100644 index 1ad5c78e..00000000 --- a/err_unsorted/err_etherreal.msg +++ /dev/null @@ -1,90 +0,0 @@ -From dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org Tue Apr 30 14:47:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UDliR22576 - for ; Tue, 30 Apr 2002 14:47:44 +0100 (BST) - (envelope-from dbi-users-return-11185-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.23] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 14:47:44 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020172466:10:24548:59; Tue, 30 Apr 2002 13:14:26 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1023391; 30 Apr 2002 13:13 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id A94562C075 - for ; Tue, 30 Apr 2002 09:12:33 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id F24B22BFBE - for ; Tue, 30 Apr 2002 09:12:32 -0400 (EDT) -Received: (qmail 36589 invoked by uid 1005); 30 Apr 2002 13:12:28 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 36168 invoked by uid 76); 30 Apr 2002 13:10:41 -0000 -Content-Type: text/plain; - charset="iso-8859-1" -From: Calin Medianu -To: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Date: Tue, 30 Apr 2002 16:04:47 +0300 -X-Mailer: KMail [version 1.3.2] -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> <20020429233138.E16831@dansat.data-plan.com> -In-Reply-To: <20020429233138.E16831@dansat.data-plan.com> -Cc: dbi-users@perl.org -MIME-Version: 1.0 -Message-Id: <20020430131233.F24B22BFBE@dolly1.pobox.com> -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id g3UDliR22576 -Status: RO -X-Status: A -Content-Length: 1213 -Lines: 38 - -[Add note to DBD::Oracle docs about using ethereal to sniff Oracle packets] -[Not sure if this bug got fixed yet. Maybe not.] - -Me again with the slow cursors. - -I modified both queries to only return 10 rows. -I ran a sniffer (ethereal) on the NIC. It is pretty cool, it also decodes TNS. - -when I am using the SQL, it works like this, there are about 7 packets -received by my workstation to set up the session, then all 10 rows are in the -same packet, then there is another packet probably saying goodbye. - -When I am using the REF cursor, each row comes in it's own TNS packet, that -is why it is so slow! - -Any idea how to fix it? - -thanks a lot, - -Calin - -> On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> > Hello, -> > -> > I did the following. Wrote a perl script that retreves -> > data via a straight select from the database. Then I -> > wrote a stored procedure returning a ref cursor open -> > on the same select statement and retrieved the data as -> > well. Using the REF CURSOR/ sotred procedure was about -> > 3 time slower, that is 40 seconds instead of around -> > 10. -> > -> > Is this normal? Is this a problem with oracle or with -> > DBD::Oracle? -> -> DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. -> -> Get a level 3 trace and look for the "dbd_describe'd" line for the -> ref cursor. -> -> Tim. - diff --git a/err_unsorted/err_memleak2.msg b/err_unsorted/err_memleak2.msg deleted file mode 100644 index 97501852..00000000 --- a/err_unsorted/err_memleak2.msg +++ /dev/null @@ -1,476 +0,0 @@ -From mike@boom.net Fri Nov 28 22:23:33 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id hASMLLnY018698 - for ; Fri, 28 Nov 2003 22:23:33 GMT - (envelope-from mike@boom.net) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 28 Nov 2003 22:23:33 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1APmgW-0006iM-9g; - Fri, 28 Nov 2003 17:45:40 +0000 -Received: from [207.8.214.2] (helo=icicle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1APmgW-0006iM-9g - for pobox@dbi.demon.co.uk; Fri, 28 Nov 2003 17:45:40 +0000 -Received: from icicle.pobox.com (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id E82CD95E03 - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost[127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id B1EE595DFB - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: from abort.boom.net (abort.boom.net[69.36.241.24]) - by icicle.pobox.com (Postfix) with ESMTP - for ; Fri, 28 Nov 2003 12:45:38 -0500 (EST) -Received: by abort.boom.net (Postfix, from userid 530) - id E3C8B8517A; Fri, 28 Nov 2003 09:45:36 -0800 (PST) -Date: Fri, 28 Nov 2003 09:45:36 -0800 -From: Mike Hedlund -To: dbi-users@perl.org -Cc: Tim.Bunce@pobox.com -Subject: Memory leak in DBD::Oracle 1.14 ... ? -Message-ID: <20031128174536.GJ10609@boom.net> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.5.4i -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id hASMLLnY018698 -Content-Length: 24309 -Lines: 434 - -I've attached a little script which replicates the problem on my machine as well as the build session log for DBD::Oracle 1.14. - -I've tested it using DBI 1.38 and DBI 1.28 with both DBD::Oracle 1.12 and 1.14. - -Regardless of the DBI version, DBD::Oracle 1.14 leaks on my system and DBD::Oracle 1.12 does not. I've noticed the leak when calling connect_cached(), do() (or prepare()/execute()/commit/finish). - --mike - - --------------------- script --------------- -#!/usr/bin/perl -use strict; -use DBI; - -my($dbp) = "dbi:Oracle:host=weirdo.com;port=1521;sid=SID"; -my($dbu) = "username"; -my($dbpass) = "password"; - -while (1) { - my($sth); - my(@row); - my($dbh) = DBI->connect_cached($dbp,$dbu,$dbpass) || die "Couldn't connect to oracle db: $DBI::errstr\n"; - -## -## uncomment these and it just leaks faster. -## -# $sth = $dbh->prepare("SELECT * from FROM_STATS"); -# $sth->execute; -# while(@row = $sth->fetchrow_array) { - ##print "row: @row\n"; -# } -# $sth->finish; -} -exit; ------------------------- end script -------------------- - - ------------- log --------------------------------------- -Script started on Fri 28 Nov 2003 09:11:15 AM PST -[mike@commando DBD-Oracle-1.14]$ setenv ORACLE_HOME /home/orahome -[mike@commando DBD-Oracle-1.14]$ make realclean -rm -f blib/script/ora_explain -rm -rf Oracle.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm ./blib Makefile.aperl blib/arch/auto/DBD/Oracle/extralibs.all perlmain.c tmon.out mon.out so_locations pm_to_blib *.o *.a perl.exe perl perl Oracle.bs Oracle.bso Oracle.def libOracle.def Oracle.exp Oracle.x core core.*perl.*.? *perl.core -mv Makefile Makefile.old > /dev/null 2>&1 -rm -rf blib/lib/auto/DBD/Oracle blib/arch/auto/DBD/Oracle -rm -rf DBD-Oracle-1.14 -rm -f blib/arch/auto/DBD/Oracle/Oracle.so blib/arch/auto/DBD/Oracle/Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.a -rm -f blib/lib/DBD/Oracle.pm blib/arch/auto/DBD/Oracle/dbdimp.h blib/lib/oraperl.ph -rm -f blib/arch/auto/DBD/Oracle/ocitrace.h blib/lib/Oraperl.pm -rm -f blib/arch/auto/DBD/Oracle/Oracle.h blib/arch/auto/DBD/Oracle/mk.pm -rm -f blib/lib/DBD/Oracle/GetInfo.pm -rm -rf Makefile Makefile.old -[mike@commando DBD-Oracle-1.14]$ perl Makefile.PL -v -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI - - Configuring DBD::Oracle ... - ->>> Remember to actually *READ* the README file! - Especially if you have any problems. - -Using Oracle in /home/orahome - -WARNING: could not decode oracle version from -/home/orahome/orainst/inspdver, or /home/orahome/install/unix.rgs -or from ORACLE_HOME path /home/orahome. -Oracle version based logic in Makefile.PL may produce erroneous results. - -Found header files in rdbms/public rdbms/demo. -Found /home/orahome/rdbms/demo/demo_rdbms.mk -Found /home/orahome/otrace/demo/atmoci.mk -Found /home/orahome/precomp/demo/proc/demo_proc.mk -Using /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/demo/demo_rdbms.mk -Reading /home/orahome/rdbms/lib/env_rdbms.mk -Read a total of 2202 lines from /home/orahome/rdbms/lib/env_rdbms.mk (including inclusions) -Read a total of 2493 lines from /home/orahome/rdbms/demo/demo_rdbms.mk (including inclusions) -Deleted SHELL definition: SHELL=/bin/sh -Deleted LIB_EXT definition: LIB_EXT=a -Deleted OBJ_EXT definition: OBJ_EXT=o -Deleted AR definition: AR=ar -Deleted AS definition: AS=as -Deleted CC definition: CC=cc -Deleted CHMOD definition: CHMOD=chmod -Deleted CPP definition: CPP=cpp -Deleted ECHO definition: ECHO=echo -Deleted LD definition: LD=ld -Deleted PERL definition: PERL=perl -Deleted CFLAGS definition: CFLAGS=$(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) -Deleted LDFLAGS definition: LDFLAGS=-o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ -Deleted OPTIMIZE definition: OPTIMIZE=$(OPTIMIZE3) -Deleted AR definition: AR=/usr/bin/ar -Deleted AS definition: AS=/usr/bin/as -Deleted LD definition: LD=/usr/bin/ld -Deleted CPP definition: CPP=/lib/cpp -Deleted CHMOD definition: CHMOD=/bin/chmod -Deleted ASFLAGS definition: ASFLAGS= -Deleting ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS definition: ORA_NLS = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Deleting ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ - because it is not already set in the environment - and it can cause ORA-01019 errors. -Deleted ORA_NLS33 definition: ORA_NLS33 = $(ORACLE_HOME)/ocommon/nls/admin/data/ -Appending '/home/orahome/rdbms/lib/libskgxpd.a /home/orahome/rdbms/lib/libskgxpu.a /home/orahome/rdbms/lib/libskgxpt.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxp9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxp9.a' to LIBS -Appending '/home/orahome/rdbms/lib/libskgxns.a /home/orahome/rdbms/lib/libskgxnd.a /home/orahome/rdbms/lib/libskgxnr.a' to EXTRALIBS -Appending '$(LIBHOME)libskgxn9.so' to SHLIBS -Appending '/home/orahome/rdbms/lib/libskgxn9.a' to LIBS -Evaluating `cat $(LIBHOME)sysliblist` - expanded `cat /home/orahome/lib/sysliblist` - returned '-ldl -lm -lpthread -lnsl ' - -Attempting to discover Oracle OCI build rules -gcc -c -o DBD_ORA_OBJ.o DBD_ORA_OBJ.c -by executing: (make -f /home/orahome/rdbms/demo/demo_rdbms.mk build ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh' CC=echo OPTIMIZE= CCFLAGS= EXE=DBD_ORA_EXE OBJS=DBD_ORA_OBJ.o) -returned: -[echo -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh `cat /home/orahome/lib/sysliblist` -ldl -lm - -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -reduced to: -[-L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] -Oracle oci build command: - + -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -o DBD_ORA_EXE DBD_ORA_OBJ.o -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - - - -System: perl5.008 linux stripples.devel.redhat.com 2.4.21-1.1931.2.382.entsmp #1 smp wed aug 6 17:18:52 edt 2003 i686 i686 i386 gnulinux -Compiler: gcc -O2 -g -pipe -march=i386 -mcpu=i686 -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -Linker: /usr/bin/ld -Sysliblist: -ldl -lm -lpthread -lnsl -Oracle makefiles would have used these definitions but we override them: - CC: cc - - CFLAGS: $(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS)\ - $(SHARED_CFLAG) $(USRFLAGS) - [$(GFLAG) -O3 $(CDEBUG) $(CCFLAGS) -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -DLINUX -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS $(LPFLAGS) $(USRFLAGS)] - - LDFLAGS: -o $@ $(LDPATHFLAG)$(PRODLIBHOME) $(LDPATHFLAG)$(LIBHOME) $(LDPATHFLAG)$(LIBHOME)stubs/ - [-o $@ -L/home/orahome/rdbms/lib/ -L$(LIBHOME) -L$(LIBHOME)stubs/] - - -Linking with OTHERLDFLAGS = -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm - [from 'build' rule] - - -MakeMaker (v6.03) -Checking if your kit is complete... -Looks good - ABSTRACT_FROM => q[Oracle.pm] - AUTHOR => q[Tim Bunce (dbi-users@perl.org)] - DEFINE => q[ -DUTF8_SUPPORT] - DIR => [] - EXE_FILES => [q[ora_explain]] - INC => q[-I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI] - NAME => q[DBD::Oracle] - OBJECT => q[$(O_FILES)] - PREREQ_PM => { DBI=>q[0] } - VERSION_FROM => q[Oracle.pm] - clean => { FILES=>q[Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def ora_explain mk.pm] } - dist => { DIST_DEFAULT=>q[clean distcheck disttest ci tardist], COMPRESS=>q[gzip -v9], PREOP=>q[$(MAKE) -f Makefile.old distdir], SUFFIX=>q[gz] } - dynamic_lib => { OTHERLDFLAGS=>q[ -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -] } -Using PERL=/usr/bin/perl -LD_RUN_PATH=/home/orahome/lib:/home/orahome/rdbms/lib -Using DBD::Oracle 1.14. -Using DBD::Oracle 1.14. -Using DBI 1.38 installed in /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -Writing Makefile for DBD::Oracle - -*** If you have problems... - read all the log printed above, and the README and README.help files. - (Of course, you have read README by now anyway, haven't you?) - -[mike@commando DBD-Oracle-1.14]$ make -cp Oracle.pm blib/lib/DBD/Oracle.pm -cp Oracle.h blib/arch/auto/DBD/Oracle/Oracle.h -cp dbdimp.h blib/arch/auto/DBD/Oracle/dbdimp.h -cp oraperl.ph blib/lib/oraperl.ph -cp ocitrace.h blib/arch/auto/DBD/Oracle/ocitrace.h -cp Oraperl.pm blib/lib/Oraperl.pm -cp mk.pm blib/arch/auto/DBD/Oracle/mk.pm -cp lib/DBD/Oracle/GetInfo.pm blib/lib/DBD/Oracle/GetInfo.pm -/usr/bin/perl -p -e "s/~DRIVER~/Oracle/g" /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI/Driver.xst > Oracle.xsi -/usr/bin/perl /usr/lib/perl5/5.8.0/ExtUtils/xsubpp -typemap /usr/lib/perl5/5.8.0/ExtUtils/typemap Oracle.xs > Oracle.xsc && mv Oracle.xsc Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT Oracle.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT dbdimp.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci7.c -gcc -c -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/plsql/public -I/home/orahome/network/public -I/home/orahome/rdbms/demo -I/home/orahome/rdbms/public -I/home/orahome/rdbms/demo -I/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/auto/DBI -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -march=i386 -mcpu=i686 -DVERSION=\"1.14\" -DXS_VERSION=\"1.14\" -fPIC "-I/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE" -DUTF8_SUPPORT oci8.c -Running Mkbootstrap for DBD::Oracle () -chmod 644 Oracle.bs -rm -f blib/arch/auto/DBD/Oracle/Oracle.so -LD_RUN_PATH="/home/orahome/lib:/home/orahome/rdbms/lib" gcc -shared -L/usr/local/lib Oracle.o dbdimp.o oci7.o oci8.o -L/home/orahome/lib/ -L/home/orahome/rdbms/lib/ -lclntsh -ldl -lm -lpthread -lnsl -ldl -lm -o blib/arch/auto/DBD/Oracle/Oracle.so -chmod 755 blib/arch/auto/DBD/Oracle/Oracle.so -cp Oracle.bs blib/arch/auto/DBD/Oracle/Oracle.bs -chmod 644 blib/arch/auto/DBD/Oracle/Oracle.bs -/usr/bin/perl "-Iblib/arch" "-Iblib/lib" ora_explain.PL ora_explain -Extracted ora_explain from ora_explain.PL with variable substitutions. -cp ora_explain blib/script/ora_explain -/usr/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" blib/script/ora_explain -Manifying blib/man3/DBD::Oracle.3pm -Manifying blib/man1/ora_explain.1 -Manifying blib/man3/DBD::Oraperl.3pm -[mike@commando DBD-Oracle-1.14]$ make test -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t -t/base....... t/base.......ok 1/5 t/base.......ok 2/5 t/base.......ok 3/5 t/base.......ok 4/5 t/base.......ok 5/5 t/base.......ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -t/reauth.....skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.82 cusr + 0.33 csys = 4.15 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ make test TEST_VERBOSE=1 -PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1, 'blib/lib', 'blib/arch')" t/*.t -t/base.......1..5 -ok 1 -ok 2 -ok 3 -ok 4 -ok 5 -ok -t/cursor.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/general....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/general.t line 20 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/long.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/meta.......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle as scott/tiger (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/ph_type....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at t/ph_type.t line 26 -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skipped. -1..0 -skipped - all skipped: no reason given -t/plsql......oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/reauth.....ORACLE_USERID_2 not defined. -Tests skiped. -1..0 -skipped - all skipped: no reason given -t/select.....oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -Unable to connect to Oracle (ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach)) -Tests skiped. -1..0 -skipped - all skipped: no reason given -All tests successful, 8 tests skipped. -Files=9, Tests=5, 7 wallclock secs ( 3.85 cusr + 0.32 csys = 4.17 CPU) -PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl -Oraperl test application $Revision: 1.7 $ - - -Extra tests. These are less formal and you need to read the output -to see if it looks reasonable and matches what the tests says is expected. - -Oraperl emulation interface version 1.43 -DBD::Oracle 1.14 using OCI8 by Tim Bunce -DBI 1.38 by Tim Bunce - -Data sources: - - - -Connecting - to '' (from command line, else uses ORACLE_SID or TWO_TASK - recommended) - as 'scott/tiger' (via ORACLE_USERID env var or default - recommend name/passwd@dbname) -(ORACLE_SID='', TWO_TASK='') -oracle: error while loading shared libraries: libodm9.so: cannot open shared object file: No such file or directory -DBI connect('','scott/tiger',...) failed: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) at /home/mike/tmp/DBD-Oracle-1.14/blib/lib/Oraperl.pm line 104 -ora_login: 12547: ORA-12547: TNS:lost contact (DBD ERROR: OCIServerAttach) - -Generally set TWO_TASK or ORACLE_SID but not both at the same time. -Try to connect to the database using an oracle tool like sqlplus -only if that works should you suspect problems with DBD::Oracle. -Try leaving dbname value empty and set dbuser to name/passwd@dbname. - -Test aborted. -make: *** [test_dynamic] Error 255 -[mike@commando DBD-Oracle-1.14]$ perl _V-V -Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: - Platform: - osname=linux, osvers=2.4.21-1.1931.2.382.entsmp, archname=i386-linux-thread-multi - uname='linux str' - config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Dotherlibdirs=/usr/lib/perl5/5.8.0 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr' - hint=recommended, useposix=true, d_sigaction=define - usethreads=define use5005threads=undef' - useithreads=define usemultiplicity= - useperlio= d_sfio=undef uselargefiles=define usesocks=undef - use64bitint=undef use64bitall=un uselongdouble= - usemymalloc=, bincompat5005=undef - Compiler: - cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', - optimize='', - cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm' - ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)', gccosandvers='' -gccversion='3.2.2 200302' - intsize=r, longsize=r, ptrsize=5, doublesize=8, byteorder=1234 - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - ivtype='long' -k', ivsize=4' -ivtype='l, nvtype='double' -o_nonbl', nvsize=, Off_t='', lseeksize=8 - alignbytes=4, prototype=define - Linker and Libraries: - ld='gcc' -l', ldflags =' -L/u' - libpth=/usr/local/lib /lib /usr/lib - libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil - perllibs= - libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libper - gnulibc_version='2.3.2' - Dynamic Linking: - dlsrc=dl_dlopen.xs, dlext=so', d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE' - cccdlflags='-fPIC' -ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5', lddlflags='s Unicode/Normalize XS/A' - - -Characteristics of this binary (from libperl): - Compile-time options: DEBUGGING MULTIPLICITY USE_ITHREADS USE_LARGE_FILES PERL_IMPLICIT_CONTEXT - Locally applied patches: - MAINT18379 - Built under linux - Compiled at Aug 13 2003 11:47:58 - @INC: - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/site_perl/5.8.0 - /usr/lib/perl5/site_perl - /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/vendor_perl/5.8.0 - /usr/lib/perl5/vendor_perl - /usr/lib/perl5/5.8.0/i386-linux-thread-multi - /usr/lib/perl5/5.8.0 - . -[mike@commando DBD-Oracle-1.14]$ ^D -Script done on Fri 28 Nov 2003 09:16:43 AM PST ------------- end log ----------------------------------- - - diff --git a/err_unsorted/err_multiora.msg b/err_unsorted/err_multiora.msg deleted file mode 100644 index 9f7bcf6c..00000000 --- a/err_unsorted/err_multiora.msg +++ /dev/null @@ -1,470 +0,0 @@ -From dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org Mon Jan 5 10:12:58 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05ACYn1063537 - for ; Mon, 5 Jan 2004 10:12:58 GMT - (envelope-from dbi-users-return-21438-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 10:12:58 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdQXY-0007a7-IO; - Mon, 05 Jan 2004 09:18:18 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdQXY-0007a7-IO - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 08:56:48 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id C92F0282F - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id B344B2B84 - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 03:56:45 -0500 (EST) -Received: (qmail 58691 invoked by uid 1005); 5 Jan 2004 08:56:38 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 58674 invoked by uid 76); 5 Jan 2004 08:56:38 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Mon, 05 Jan 2004 00:56:38 -0800 -Received: (qmail 17937 invoked by uid 225); 5 Jan 2004 08:56:36 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 17930 invoked by uid 507); 5 Jan 2004 08:56:36 -0000 -Received: from stone.sifira.dk (HELO mail.int.sifira.dk) (217.157.24.2) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Mon, 05 Jan 2004 00:56:05 -0800 -Received: from ash.int.sifira.dk (ash.int.sifira.dk [192.168.1.7]) by mail.int.sifira.dk (Postfix) with ESMTP id F127674F58; Mon, 5 Jan 2004 09:55:58 +0100 (MET) -Sender: kn@sifira.dk -To: "Anniballi, Fran" -Cc: -Subject: Re: Help - multiple Oracle versions -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -From: Kristian Nielsen -Date: 05 Jan 2004 09:55:59 +0100 -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Message-ID: <7sllomsrj4.fsf@ash.int.sifira.dk> -User-Agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-2.5 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01,USER_AGENT,USER_AGENT_GNUS_UA version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1223 -Lines: 40 - -[Add notes to docs covering what's in this thread] - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - -From dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org Mon Jan 5 14:47:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i05Ejvo1064760 - for ; Mon, 5 Jan 2004 14:47:30 GMT - (envelope-from dbi-users-return-21441-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 05 Jan 2004 14:47:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AdVCS-0004w0-Is; - Mon, 05 Jan 2004 13:55:22 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1AdVCS-0004w0-Is - for pobox@dbi.demon.co.uk; Mon, 05 Jan 2004 13:55:21 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 548DE2C87 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 417692C81 - for ; Mon, 5 Jan 2004 08:55:20 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by integer.pobox.com (Postfix) with SMTP - for ; Mon, 5 Jan 2004 08:55:19 -0500 (EST) -Received: (qmail 91728 invoked by uid 1005); 5 Jan 2004 13:55:17 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 48614 invoked by uid 76); 5 Jan 2004 12:24:01 -0000 -Delivered-To: dbi-users@perl.org -X-MimeOLE: Produced By Microsoft Exchange V6.0.6487.1 -content-class: urn:content-classes:message -MIME-Version: 1.0 -Content-Type: text/plain; charset="iso-8859-1" -Subject: RE: Help - multiple Oracle versions -Date: Mon, 5 Jan 2004 07:23:23 -0500 -Message-ID: <6B003D25ADBDE347B5542AFE6A55B42E04537A09@tayexc13.americas.cpqcorp.net> -X-MS-Has-Attach: -X-MS-TNEF-Correlator: -Thread-Topic: Help - multiple Oracle versions -Thread-Index: AcPTac0nADA1C8LsTdSTxpcvyeSNCgAHQWGQ -From: "Anniballi, Fran" -To: -Cc: -X-OriginalArrivalTime: 05 Jan 2004 12:23:24.0525 (UTC) FILETIME=[B6F761D0:01C3D386] -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.3 required=7.0 tests=CARRIAGE_RETURNS,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id i05Ejvo1064760 -Status: RO -Content-Length: 1465 -Lines: 52 - -Thanks. Looks like this is what I'll need. - ------Original Message----- -From: kn@sifira.dk [mailto:kn@sifira.dk] -Sent: Monday, January 05, 2004 3:56 AM -To: Anniballi, Fran -Cc: dbi-users@perl.org -Subject: Re: Help - multiple Oracle versions - - -"Anniballi, Fran" writes: - -> For option two, if I have two versions of DBD:Oracle, how do I tell -> Perl which one to use? My scripts just say "/usr/bin/perl" in the -> first line. - -Basically, when you compile you use the PREFIX option: - - export ORACLE_HOME=/usr/local/oracle8 - perl Makefile.PL PREFIX=/usr/local/oracle8-perl - make - make install - - export ORACLE_HOME=/usr/local/oracle9 - perl Makefile.PL PREFIX=/usr/local/oracle9-perl - make - make install - -Then before running the perl script you should set the PERLLIB -environment variable to point to the correct location for the proper -version of DBD::Oracle. Alternatively, you could have the perl script -select the proper DBD::Oracle location based on the value of -ORACLE_HOME: - - #! /usr/bin/perl - BEGIN { - if($ENV{ORACLE_HOME} =~ /8/) { - use lib '/usr/local/oracle8-perl/REST/OF/PATH'; - } else { - use lib '/usr/local/oracle9-perl/REST/OF/PATH'; - } - } - use DBI; - -This is all from the top of my head; you will need to fiddle a bit to -get the details right (like the correct path etc). Also, I think this -has been covered in greater detail before; you might want to try -searching the archives. - - - Kristian. - - - -From dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org Tue Jan 6 17:00:29 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i06GxrnC075337 - for ; Tue, 6 Jan 2004 17:00:29 GMT - (envelope-from dbi-users-return-21449-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 06 Jan 2004 17:00:29 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Adu0c-0004RW-9d; - Tue, 06 Jan 2004 16:24:47 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Adu0c-0004RW-9d - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 16:24:47 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 21A79495C - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 08B12494B - for ; Tue, 6 Jan 2004 11:24:46 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by boggle.pobox.com (Postfix) with SMTP - for ; Tue, 6 Jan 2004 11:24:45 -0500 (EST) -Received: (qmail 25114 invoked by uid 1005); 6 Jan 2004 16:24:42 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 25095 invoked by uid 76); 6 Jan 2004 16:24:42 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Tue, 06 Jan 2004 08:24:42 -0800 -Received: (qmail 16535 invoked by uid 225); 6 Jan 2004 16:24:39 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16527 invoked by uid 507); 6 Jan 2004 16:24:39 -0000 -Received: from mail.cybcon.com (HELO mail.cybcon.com) (216.190.188.5) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Tue, 06 Jan 2004 08:24:08 -0800 -Received: from poirot (dsl2-6.cybcon.com [208.186.116.6]) by mail.cybcon.com (8.11.6/8.11.6) with ESMTP id i06GNhn08916; Tue, 6 Jan 2004 08:23:43 -0800 -Subject: RE: Help - multiple Oracle versions -From: Jared Still -To: "Anniballi, Fran" -Cc: DBI List -In-Reply-To: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -References: <6B003D25ADBDE347B5542AFE6A55B42E03227831@tayexc13.americas.cpqcorp.net> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 (1.0.8-11) -Date: 06 Jan 2004 08:25:59 -0800 -Message-Id: <1073406359.324.244.camel@poirot.jks.com> -Mime-Version: 1.0 -X-CyberConnectics-MailScanner2-Information: Spam/Virus Scanned at CyberConnectics -X-CyberConnectics-MailScanner2: Found to be clean -X-CyberConnectics-MailScanner2-SpamCheck: -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.2 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_05_08,SUPERLONG_LINE version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 4050 -Lines: 102 - -I read quickly through this thread, so my apologies if someone -already pointed this out. - -It doesn't matter which version of Oracle you compiled DBD with, -you can connect to all your 8i/9i databases on any platform with it. - -Assume you compiled with 9i libs, and you can connect to 9i db's with -no problem, but are unable to connect to 8i, getting the error you -mentioned previously. - -It appears that you are changing your Oracle environment via the -oraenv shell script to change your ORACLE_HOME to the 8i version -of Oracle. - -If so, stop doing that. Just leave your environment at 9i, and -connect to your 8i database. It will be fine. This is the way -my linux server is setup, and DBD is used to connect to Oracle -versions 7.3, 8.1.6, 8.1.7 and 9.2.0 every day. - -At our site DBD is compiled with 8i libs so that we can still -connect to the version 7 databases. If you compile with 9i libs, -you will be unable to connect to version 7 databases. - -HTH - -Jared - - -On Sun, 2004-01-04 at 05:12, Anniballi, Fran wrote: -> This is all done on one UNIX box. -> -> If I try option one, it doesn't work. I can't access an oracle8 instance with oracle9 sqlplus (or the other way around). That is the real problem. Since I can't do this I have to reassign the pointers before I access it. I can do this fine with sqlplus but with dbi/dbd I have to compile with one or the other. -> -> For option two, if I have two versions of DBD:Oracle, how do I tell Perl which one to use? My scripts just say "/usr/bin/perl" in the first line. -> -> -----Original Message----- -> From: kn@sifira.dk [mailto:kn@sifira.dk] -> Sent: Saturday, January 03, 2004 1:04 PM -> To: dbi-users@perl.org -> Cc: Anniballi, Fran -> Subject: Re: Help - multiple Oracle versions -> -> -> "Anniballi, Fran" writes: -> -> > As soon as I recompile the same DBI/DBD with it pointing to Oracle 9 -> > environment (libraries), it doesn't work. It is looking for Oracle9 -> > library files and I obviously don't have it pointing to oracle9 -> > libraries when I access an Oracle 8 instance. Oracle 9 is not -> > compatible with Oracle 8 so I have to redirect the environment -> > variables at run time. -> -> It sounds like you are confusing the Oracle client version and the -> Oracle server version. -> -> Eg. if you set ORACLE_HOME to /usr/local/oracle8 (or whatever) and use -> /usr/local/oracle8/bin/sqlplus you are using the Oracle 8 client, while -> if you set it to /usr/local/oracle9 and call -> /usr/local/oracle9/bin/sqlplus, you are using the Oracle 9 client. -> -> Which Oracle instance you access is selected by the connection string; -> for example "sqlplus scott/tiger@DB8" might access the Oracle 8 -> instance, and "scott/tiger@DB9" might access the Oracle 9 instance. -> -> What people are telling you is that you can choose client version -> independently of the server version. For example, it is possible to set -> ORACLE_HOME to /usr/local/oracle9 and call -> -> /usr/local/oracle9/bin/sqlplus scott/tiger@DB8 -> -> to access the Oracle 8 instance with the Oracle 9 client. This of course -> requires that the definition for DB8 is present in the file -> /usr/local/oracle-9.2/network/admin/tnsnames.ora. -> -> So you should either -> -> 1. Use only the Oracle 9 client, not change ORACLE_HOME, and access both -> instances with Oracle 9 sqlplus and DBD::Oracle compiled against -> Oracle 9 libraries. -> -> or -> -> 2. Compile DBD::Oracle twice (once against Oracle 8 libraries, once -> against Oracle 9 libraries, just as you have two versions of sqlplus) -> and use each one with the proper ORACLE_HOME setting. -> -> My guess is that you will find possibility 1. the easiest. -> -> > The tnsnames.ora are all set. I did what you said already. -> > -> > Example: DBI/DBD will work fine if I compile the DBI/DBD pointing to -> > Oracle 8 environment(libraries) and access an Oracle 8 instance. I -> > didn't have to change tnsnames.ora -> -> Yes you do: You need to have BOTH Oracle instances defined in EACH -> tnsnames.ora. -> -> Hope this helps, -> -> - Kristian. - - - -From andy@andyh.co.uk Wed Jan 7 07:31:57 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i077VPn8081048 - for ; Wed, 7 Jan 2004 07:31:57 GMT - (envelope-from andy@andyh.co.uk) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 07 Jan 2004 07:31:57 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1Ae0Yb-0002lT-IA; - Tue, 06 Jan 2004 23:24:17 +0000 -Received: from [208.58.1.194] (helo=integer.pobox.com) - by punt-3.mail.demon.net with esmtp id 1Ae0Yb-0002lT-IA - for pobox@dbi.demon.co.uk; Tue, 06 Jan 2004 23:24:17 +0000 -Received: from integer.pobox.com (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id 00D7C3C15 - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by integer.pobox.com (Postfix) with ESMTP id CB5813BEA - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from mta03-svc.ntlworld.com (mta03-svc.ntlworld.com [62.253.162.43]) - by integer.pobox.com (Postfix) with ESMTP - for ; Tue, 6 Jan 2004 18:24:16 -0500 (EST) -Received: from excession ([80.2.244.47]) by mta03-svc.ntlworld.com - (InterMail vM.4.01.03.37 201-229-121-137-20020806) with SMTP - id <20040106232403.NEKJ9852.mta03-svc.ntlworld.com@excession>; - Tue, 6 Jan 2004 23:24:03 +0000 -Message-ID: <00bd01c3d4ac$e5713190$6564a8c0@excession> -From: "Andy Hassall" -To: "Eric Lenio" , "Tim Bunce" -Cc: -References: <20040102143310.GC27273@lenio.net> <20040104204914.GB60357@dansat.data-plan.com> <20040105123653.GA31473@lenio.net> <20040105223121.GG66760@dansat.data-plan.com> <20040106222634.GG11531@lenio.net> <20040106223845.GE78360@dansat.data-plan.com> <20040106225722.GI11531@lenio.net> -Subject: Re: DBI primary_key tests fail: oracle 8 -Date: Tue, 6 Jan 2004 23:29:14 -0000 -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2800.1158 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 -Status: RO -X-Status: A -Content-Length: 1692 -Lines: 43 - -Eric Lenio wrote: -> OK Tim. One other note -- after reading through oracle docs, I think -> you might want to substitute 'session_user' for 'current_schema' in -> 'select sys_context(...)'. The definition of session_user is -> "returns the database -> user name by which the current user is authenticated" while -> current_schema is "returns the name of the default schema being used -> in the current session". -> Maybe it doesn't matter, I'm not an oracle guru by any stretch of the -> imagination. - -There's several usernames in the USERENV context: - -CURRENT_SCHEMA - -The schema/user used for unqualified object name resolution; by default the -user you logged in as, but alterable with 'alter session set -current_schema=x'. Useful for avoiding having to maintain loads of synonyms. - -CURRENT_USER - -The user you're currently authenticated as. Doesn't change in SQL and -anonymous PL/SQL, but changes within definer-rights PL/SQL stored procedures -to the owner of the stored procedure, since stored procs by default run with -the privileges of the owner, not the invoker. - -SESSION_USER - -Who you originally logged in as, and never changes (but see below). Looks -like the appropriate one to use. - -PROXY_USER - -I don't think DBD::Oracle supports proxy authentication so don't need to -worry about that one yet. Possibly a bit of a grey area if it does support -it in the future, since this would hold the username in the DSN, but it'd -reauthenticate and change the SESSION_USER on connect (which would probably -have to be specified as an attribute to the $dbh). - --- -Andy Hassall (andy@andyh.co.uk) icq(5747695) (http://www.andyh.co.uk) -Space: disk usage analysis tool (http://www.andyhsoftware.co.uk/space) - - diff --git a/err_unsorted/err_ora9ir2oci.msg b/err_unsorted/err_ora9ir2oci.msg deleted file mode 100644 index 7ed476e4..00000000 --- a/err_unsorted/err_ora9ir2oci.msg +++ /dev/null @@ -1,27 +0,0 @@ -http://otn.oracle.com/tech/oci/htdocs/oci9ir2_new_features - -OCI Session Pooling -Session Pooling is a new feature in Oracle 9i Database Release 2. -An application can now maintain a pool of sessions and use a session -from the pool when it needs it. This saves the time consuming process -of initiating a connection and authentication every time the process -needs a new session. Session Pooling is useful, especially when a -large number of stateless sessions are required for a very short -time. In a web scenario, where many users are connected for a short -time, and the primary operation is accessing data, it is a costly -operation to start up a new session every time. In such a scenario, -session pooling could boost up the performance. - -OCI Statement caching -Client-side statement caching is also introduced in Oracle9i Database -Release 2. This feature can be enabled at the time of session -creation. It allows users to have a cache of statements per session. -On the server, this means having cursors that ready to be used, -without the need to parse the statements again, and thus improving -performance significantly. With this feature enabled, applications -do not have to keep a track of the statements themselves, as the -OCI layer will do it for them. In addition, a tagging feature is -provided, which users can use as a key to save and search for -statements. - - diff --git a/err_unsorted/err_ref_type.msg b/err_unsorted/err_ref_type.msg deleted file mode 100644 index 26d86e14..00000000 --- a/err_unsorted/err_ref_type.msg +++ /dev/null @@ -1,115 +0,0 @@ -From dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org Wed Jul 23 18:40:02 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h6NHUUA0010501 - for ; Wed, 23 Jul 2003 18:40:02 +0100 (BST) - (envelope-from dbi-users-return-19574-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 23 Jul 2003 18:40:02 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1058948095:10:09585:8; Wed, 23 Jul 2003 08:14:55 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1116163; 23 Jul 2003 8:14 GMT -Received: from dolly1.pobox.com (localhost [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 88C1B21C024 - for ; Wed, 23 Jul 2003 04:13:51 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [64.70.54.95]) - by dolly1.pobox.com (Postfix) with SMTP id AA89B21C082 - for ; Wed, 23 Jul 2003 04:13:50 -0400 (EDT) -Received: (qmail 26606 invoked by uid 1005); 23 Jul 2003 08:13:44 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 26590 invoked by uid 76); 23 Jul 2003 08:13:43 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Wed, 23 Jul 2003 01:13:43 -0700 -Received: (qmail 16360 invoked by uid 225); 23 Jul 2003 08:13:41 -0000 -Delivered-To: dbi-users@perl.org -Received: (qmail 16355 invoked by uid 507); 23 Jul 2003 08:13:41 -0000 -Received-SPF: unknown -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with SMTP; Wed, 23 Jul 2003 01:13:41 -0700 -Received: (qmail 5378 invoked from network); 23 Jul 2003 08:54:08 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 23 Jul 2003 08:54:08 -0000 -Received: (qmail 8984 invoked from network); 23 Jul 2003 08:13:49 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 23 Jul 2003 08:13:49 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Wed, 23 Jul 2003 10:13:49 +0200 (CEST) -Subject: Re: binding to parameters of type REF -From: Hendrik =?ISO-8859-1?Q?Fu=DF?= -To: dbi-users@perl.org -In-Reply-To: <1058865345.1241.56.camel@mars> -References: <1058865345.1241.56.camel@mars> -Content-Type: text/plain -Content-Transfer-Encoding: 7bit -X-Mailer: Ximian Evolution 1.0.8 -Date: 23 Jul 2003 10:11:49 +0200 -Message-Id: <1058947909.6353.5.camel@mars> -Mime-Version: 1.0 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.3 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,LARGE_HEX,QUOTED_EMAIL_TEXT,REFERENCES,SPAM_PHRASE_00_01 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -Content-Length: 1354 -Lines: 56 - -I've also found out, that DBD::Oracle does not support type SQL_REF: -When not using DBD::Proxy I get: - - SQL type 20 for ':p1' is not fully supported, - bound as SQL_VARCHAR instead - -I even get segmentation faults when trying to fetch REF columns. :-( - -Any ideas? - -> Hi, -> -> I'm trying to bind a perl variable to an Oracle table reference with -> Oracle 9.2.0.3, DBD::Proxy and Perl::DBI 1.37 without success. I -> could'nt find help on this in the docs or list archives. I hope this is -> the right place to post. -> -> In SQL*Plus: -> -> SQL> desc getReference -> FUNCTION getReference RETURNS REF OF TABLETYPE -> -> SQL> select getReference() from dual; -> -> GETREFERENCE() -> ---------------------------------------------------------------------- -> 0000280209C229D2216EF6A5F4E030010A8D086AD3C204FC6EE0E46501E030010A8D08 -> 2CE703C0000E0000 -> -> -> My code: -> -> my $ref = undef; -> my $sth = $dbh->prepare('BEGIN ? := getReference(); END;'); -> $sth->bind_param_inout(1, \$ref, 128, SQL_REF ); -> $sth->execute(); -> -> yields: -> -> PLS-00382: expression is of wrong type -> -> -> Even fetching a reference does not work: -> -> my $sth = $dbh->prepare('SELECT getReference() FROM DUAL'); -> $sth->execute(); -> ($ref) = $sth->fetchrow_array(); -> -> yields undef in $ref. -> -> I'd very much appreciate your help. -> cheers, -> Hendrik - - - - diff --git a/err_unsorted/err_refcsr_rowcache.msg b/err_unsorted/err_refcsr_rowcache.msg deleted file mode 100644 index 5101d2ae..00000000 --- a/err_unsorted/err_refcsr_rowcache.msg +++ /dev/null @@ -1,85 +0,0 @@ -From dbi-users-bounce@isc.org Tue May 16 22:53:12 2000 -Return-Path: -Received: from oink by toad.ig.co.uk (SMI-8.6/SMI-SVR4) - id WAA29547; Tue, 16 May 2000 22:53:11 +0100 -Received: from finch-punt-12.mail.demon.net by oink with SMTP (PP) - id <04730-2@oink>; Sat, 16 May 1970 22:51:48 +0100 -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@ig.co.uk - id 958512876:10:15786:0; Tue, 16 May 2000 21:34:36 GMT -Received: from pub3.rc.vix.com ([204.152.186.34]) by punt-1.mail.demon.net - id aa1122388; 16 May 2000 21:33 GMT -Received: from pub3.rc.vix.com (pub3.rc.vix.com [204.152.186.34]) - by pub3.rc.vix.com (Postfix) with ESMTP id 661E53EC8; - Tue, 16 May 2000 14:33:38 -0700 (PDT) -Received: with LISTAR (v0.129a; list dbi-users); - Tue, 16 May 2000 14:28:31 -0700 (PDT) -Received: from isrv3.isc.org (isrv3.isc.org [204.152.184.87]) - by pub3.rc.vix.com (Postfix) with ESMTP id 7192F3E20 - for ; - Tue, 16 May 2000 14:28:27 -0700 (PDT) -Received: from anchor-post-34.mail.demon.net (anchor-post-34.mail.demon.net [194.217.242.92]) - by isrv3.isc.org (8.9.1/8.9.1) via ESMTP id OAA27204 - for ; - Tue, 16 May 2000 14:28:26 -0700 (PDT) env-from (Tim.Bunce@ig.co.uk) -Received: from ignite.demon.co.uk ([158.152.8.99] helo=oink) - by anchor-post-34.mail.demon.net with smtp (Exim 2.12 #1) - id 12rot7-000Mp4-0Y; Tue, 16 May 2000 22:28:25 +0100 -Received: from toad by oink with SMTP (PP) id <04650-0@oink>; - Sat, 16 May 1970 22:23:55 +0100 -Received: by toad.ig.co.uk (SMI-8.6/SMI-SVR4) id WAA29289; - Tue, 16 May 2000 22:23:50 +0100 -Date: Tue, 16 May 2000 22:23:50 +0100 -From: Tim Bunce -To: peter_dev@talk21.com -Cc: dbi-users@isc.org -Subject: Re: Oracle Stored Procs take longer than embedded SQL -Message-ID: <20000516222350.F28435@ig.co.uk> -References: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Mailer: Mutt 0.95.3i -In-Reply-To: <20000516174946.QLKD22548.t21mta02-app.talk21.com@t21mtaV-lrs>; from peter_dev@talk21.com on Tue, May 16, 2000 at 06:48:22PM +0100 -Organization: Paul Ingram Group, Software Systems, +44 1 483 862800 -Sender: dbi-users-bounce@isc.org -Errors-To: dbi-users-bounce@isc.org -X-original-sender: Tim.Bunce@ig.co.uk -Precedence: bulk -List-unsubscribe: -X-List-ID: -List-owner: -List-post: -Status: RO -Content-Length: 1372 -Lines: 30 - -On Tue, May 16, 2000 at 06:48:22PM +0100, peter_dev@talk21.com wrote: -> I have a problem with the fetching of data from an Oracle Ref Cursor taking longer than the same query in Embeded SQL. -> -> $ get_sp.pl -> Fetched in 0.00774896144866943 seconds -> Completed in 0.106827020645142 seconds -> -> $ get_sql.pl -> Fetched in 0.00138604640960693 seconds -> Completed in 0.380790948867798 seconds -> -> In this example (Using the SCOTT/TIGER tables), while the Stored Procedure completed first, the actual fetch of the data took considerably longer. In a real situation (e.g. bigger tables ), this is easily the longest part of the task and causes the overall execution time to increase hugely. -> -> Any Help would be appreciated -> thanks - -Possibly related to the lack of a row cache on that statement handle. -You, or some kind volunteer, could probably hack that in without too -much work. - -Tim. - - ------------------------------------------------------------------------------- -DBI HOME PAGE AND ARCHIVES: http://www.symbolstone.org/technology/perl/DBI/ -To unsubscribe from this list, please visit: http://www.isc.org/dbi-lists.html -If you are without web access, or if you are having trouble with the web page, -please send mail to dbi-users-request@isc.org with the subject line of: -'unsubscribe'. ------------------------------------------------------------------------------- - diff --git a/err_unsorted/err_refcsr_slow.msg b/err_unsorted/err_refcsr_slow.msg deleted file mode 100644 index 790d267d..00000000 --- a/err_unsorted/err_refcsr_slow.msg +++ /dev/null @@ -1,347 +0,0 @@ -From dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org Mon Apr 29 23:12:51 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TMCpR17212 - for ; Mon, 29 Apr 2002 23:12:51 +0100 (BST) - (envelope-from dbi-users-return-11175-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Mon, 29 Apr 2002 23:12:51 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020117986:10:17770:92; Mon, 29 Apr 2002 22:06:26 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1017591; 29 Apr 2002 22:06 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id 975037274A - for ; Mon, 29 Apr 2002 18:01:37 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by wormwood.pobox.com (Postfix) with SMTP id ED2897273F - for ; Mon, 29 Apr 2002 18:01:34 -0400 (EDT) -Received: (qmail 70462 invoked by uid 1005); 29 Apr 2002 21:59:33 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 20335 invoked by uid 76); 29 Apr 2002 20:18:55 -0000 -Message-ID: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Date: Mon, 29 Apr 2002 13:18:53 -0700 (PDT) -From: Calin Medianu -Reply-To: cmedianu@sfu.ca -Subject: DBD::Oracle Slow cursors -To: dbi-users@perl.org -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 568 -Lines: 21 - -Hello, - -I did the following. Wrote a perl script that retreves -data via a straight select from the database. Then I -wrote a stored procedure returning a ref cursor open -on the same select statement and retrieved the data as -well. Using the REF CURSOR/ sotred procedure was about -3 time slower, that is 40 seconds instead of around -10. - -Is this normal? Is this a problem with oracle or with -DBD::Oracle? - -Thanks, - -Calin Medianu - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org Tue Apr 30 00:06:36 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3TN6aR17980 - for ; Tue, 30 Apr 2002 00:06:36 +0100 (BST) - (envelope-from dbi-users-return-11177-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 00:06:36 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020119533:20:05733:4; Mon, 29 Apr 2002 22:32:13 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2005393; 29 Apr 2002 22:32 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 4E6B73E6BF - for ; Mon, 29 Apr 2002 18:32:00 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-1.pobox.com (Postfix) with SMTP id BF79C3E6A0 - for ; Mon, 29 Apr 2002 18:31:59 -0400 (EDT) -Received: (qmail 87860 invoked by uid 1005); 29 Apr 2002 22:31:59 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Received: (qmail 87844 invoked by uid 76); 29 Apr 2002 22:31:58 -0000 -Received: from mail01.svc.cra.dublin.eircom.net (HELO mail01.svc.cra.dublin.eircom.net) (159.134.118.17) - by onion.perl.org (qpsmtpd/0.07) with SMTP; Mon Apr 29 22:31:58 2002 -0000 -Received: (qmail 21911 messnum 119827 invoked from network[159.134.167.97/p865.as1.limerick1.eircom.net]); 29 Apr 2002 22:31:29 -0000 -Received: from p865.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.97) - by mail01.svc.cra.dublin.eircom.net (qp 21911) with SMTP; 29 Apr 2002 22:31:29 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g3TMVcR17579; - Mon, 29 Apr 2002 23:31:38 +0100 (BST) - (envelope-from timbo) -Date: Mon, 29 Apr 2002 23:31:38 +0100 -From: Tim Bunce -To: cmedianu@sfu.ca -Cc: dbi-users@perl.org -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020429233138.E16831@dansat.data-plan.com> -References: <20020429201853.52283.qmail@web10007.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020429201853.52283.qmail@web10007.mail.yahoo.com>; from calinm@yahoo.com on Mon, Apr 29, 2002 at 01:18:53PM -0700 -Content-Length: 651 -Lines: 20 - -On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin Medianu wrote: -> Hello, -> -> I did the following. Wrote a perl script that retreves -> data via a straight select from the database. Then I -> wrote a stored procedure returning a ref cursor open -> on the same select statement and retrieved the data as -> well. Using the REF CURSOR/ sotred procedure was about -> 3 time slower, that is 40 seconds instead of around -> 10. -> -> Is this normal? Is this a problem with oracle or with -> DBD::Oracle? - -DBD::Oracle. It probably isn't setting up a row cache for the ref cursor. - -Get a level 3 trace and look for the "dbd_describe'd" line for the -ref cursor. - -Tim. - -From calinm@yahoo.com Tue Apr 30 22:02:56 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL2tR26878 - for ; Tue, 30 Apr 2002 22:02:55 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:02:55 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020198219:10:21718:114; Tue, 30 Apr 2002 20:23:39 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101732; 30 Apr 2002 20:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C6B4A2BFB4 - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10004.mail.yahoo.com (web10004.mail.yahoo.com [216.136.130.40]) - by dolly1.pobox.com (Postfix) with SMTP id 527BD2BF3D - for ; Tue, 30 Apr 2002 16:23:25 -0400 (EDT) -Message-ID: <20020430202321.54825.qmail@web10004.mail.yahoo.com> -Received: from [213.157.171.169] by web10004.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 13:23:20 PDT -Date: Tue, 30 Apr 2002 13:23:20 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -Cc: dbi-users@perl.org -In-Reply-To: <20020430140517.P16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 425 -Lines: 18 - -I "Solved" the problem. For Now.. I did -perl Makefile.PL -8 - -hoping that the buggy code would be recently added, -and it was. Now both the select and the cursor return -the data at the same speed, meaning fast.. - -Am I am missing much by not using the code for Oracle -8? - -Thanks, - -Calin - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From timbo@dansat.data-plan.com Wed May 1 16:49:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g41FnsR33994 - for ; Wed, 1 May 2002 16:49:54 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 01 May 2002 16:49:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020265865:20:10671:66; Wed, 01 May 2002 15:11:05 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-2.mail.demon.net - id aa2122069; 1 May 2002 15:10 GMT -Received: from cali-3.pobox.com (cali-3.pobox.com [64.71.166.116]) - by silk.pobox.com (Postfix) with ESMTP id F29CC3FDF2 - for ; Wed, 1 May 2002 11:09:52 -0400 (EDT) -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id E3A943E689 - for ; Wed, 1 May 2002 10:57:15 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id D1F523E688 - for ; Wed, 1 May 2002 10:57:14 -0400 (EDT) -Received: (qmail 96042 messnum 564683 invoked from network[159.134.166.63/p575.as1.limerick1.eircom.net]); 1 May 2002 14:57:13 -0000 -Received: from p575.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.63) - by mail03.svc.cra.dublin.eircom.net (qp 96042) with SMTP; 1 May 2002 14:57:13 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g41EvIh33626; - Wed, 1 May 2002 15:57:18 +0100 (BST) - (envelope-from timbo) -Date: Wed, 1 May 2002 15:57:18 +0100 -From: Tim Bunce -To: Calin Medianu -Cc: Tim Bunce -Subject: Re: DBD::Oracle Slow cursors -Message-ID: <20020501155718.S16831@dansat.data-plan.com> -References: <20020430151126.Q16831@dansat.data-plan.com> <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5i -In-Reply-To: <20020430183429.33340.qmail@web10005.mail.yahoo.com>; from calinm@yahoo.com on Tue, Apr 30, 2002 at 11:34:29AM -0700 -Status: RO -Content-Length: 3111 -Lines: 111 - -Thanks. I'll take a look when I get to DBD::Oracle again. - -I think the last row of that table applies and it doesn't refer to OCIBindObject(): - REF CURSOR variables - SQLT_RSET - Allocate a statement handle, OCIStmt, and then bind its address - (OCIStmt **) using the SQLT_RSET datatype. -Note that SQLT_REF isn't the same as SQLT_RSET. - -You could always try patching it yourself! - -Tim. - - -On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin Medianu wrote: -> It says here: -> http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> -> that 2 calls are neede to bind a ref , the second is -> to OCIBindObject() which I don't see in dbdimp.c. -> -> Could this be a reason? -> -> Cheers, -> -> Calin -> -> --- Tim Bunce wrote: -> > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > Medianu wrote: -> > > Me again with the slow cursors. -> > > -> > > I modified both queries to only return 10 rows. -> > > I ran a sniffer (ethereal) on the NIC. It is -> > pretty cool, it also decodes TNS. -> > > -> > > when I am using the SQL, it works like this, there -> > are about 7 packets -> > > received by my workstation to set up the session, -> > then all 10 rows are in the -> > > same packet, then there is another packet probably -> > saying goodbye. -> > > -> > > When I am using the REF cursor, each row comes in -> > it's own TNS packet, that -> > > is why it is so slow! -> > > -> > > Any idea how to fix it? -> > -> > Do a level 9 trace to get a log of the OCI calls and -> > confirm that -> > the fragment I posted is being called (may be -> > helpful to also -> > add an extra print statement into that code since -> > parsing the -> > OCI trace can be painful). -> > -> > Assuming the code is being called then as far as I -> > can see the code is -> > doing the right thing and it's probably an Oracle -> > OCI issue. -> > -> > You'd need to talk to Oracle support. No need to -> > mention perl etc. -> > Just talk about your OCI application and provide the -> > OCI call trace. -> > -> > Let me know what you find out! -> > -> > Tim. -> > -> > > thanks a lot, -> > > -> > > Calin -> > > -> > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> > Medianu wrote: -> > > > > Hello, -> > > > > -> > > > > I did the following. Wrote a perl script that -> > retreves -> > > > > data via a straight select from the database. -> > Then I -> > > > > wrote a stored procedure returning a ref -> > cursor open -> > > > > on the same select statement and retrieved the -> > data as -> > > > > well. Using the REF CURSOR/ sotred procedure -> > was about -> > > > > 3 time slower, that is 40 seconds instead of -> > around -> > > > > 10. -> > > > > -> > > > > Is this normal? Is this a problem with oracle -> > or with -> > > > > DBD::Oracle? -> > > > -> > > > DBD::Oracle. It probably isn't setting up a row -> > cache for the ref cursor. -> > > > -> > > > Get a level 3 trace and look for the -> > "dbd_describe'd" line for the -> > > > ref cursor. -> > > > -> > > > Tim. -> -> -> __________________________________________________ -> Do You Yahoo!? -> Yahoo! Health - your guide to health and wellness -> http://health.yahoo.com - diff --git a/err_unsorted/err_slowcsr.msg b/err_unsorted/err_slowcsr.msg deleted file mode 100644 index 80c43350..00000000 --- a/err_unsorted/err_slowcsr.msg +++ /dev/null @@ -1,316 +0,0 @@ -From calinm@yahoo.com Tue Apr 30 22:03:11 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3UL3AR27018 - for ; Tue, 30 Apr 2002 22:03:10 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Tue, 30 Apr 2002 22:03:10 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020196981:10:23493:39; Tue, 30 Apr 2002 20:03:01 GMT -Received: from silk.pobox.com ([208.210.125.70]) by punt-1.mail.demon.net - id aa1108477; 30 Apr 2002 20:02 GMT -Received: from dolly1.pobox.com (dolly1.pobox.com [207.106.49.22]) - by silk.pobox.com (Postfix) with ESMTP id 915563FCE8 - for ; Tue, 30 Apr 2002 14:35:38 -0400 (EDT) -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 343702BFDD - for ; Tue, 30 Apr 2002 14:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10005.mail.yahoo.com (web10005.mail.yahoo.com [216.136.130.41]) - by dolly1.pobox.com (Postfix) with SMTP id 6AA822BFA3 - for ; Tue, 30 Apr 2002 14:34:37 -0400 (EDT) -Message-ID: <20020430183429.33340.qmail@web10005.mail.yahoo.com> -Received: from [213.157.171.169] by web10005.mail.yahoo.com via HTTP; Tue, 30 Apr 2002 11:34:29 PDT -Date: Tue, 30 Apr 2002 11:34:29 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020430151126.Q16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -X-Status: A -Content-Length: 2457 -Lines: 96 - -It says here: -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 - -that 2 calls are neede to bind a ref , the second is -to OCIBindObject() which I don't see in dbdimp.c. - -Could this be a reason? - -Cheers, - -Calin - ---- Tim Bunce wrote: -> On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> Medianu wrote: -> > Me again with the slow cursors. -> > -> > I modified both queries to only return 10 rows. -> > I ran a sniffer (ethereal) on the NIC. It is -> pretty cool, it also decodes TNS. -> > -> > when I am using the SQL, it works like this, there -> are about 7 packets -> > received by my workstation to set up the session, -> then all 10 rows are in the -> > same packet, then there is another packet probably -> saying goodbye. -> > -> > When I am using the REF cursor, each row comes in -> it's own TNS packet, that -> > is why it is so slow! -> > -> > Any idea how to fix it? -> -> Do a level 9 trace to get a log of the OCI calls and -> confirm that -> the fragment I posted is being called (may be -> helpful to also -> add an extra print statement into that code since -> parsing the -> OCI trace can be painful). -> -> Assuming the code is being called then as far as I -> can see the code is -> doing the right thing and it's probably an Oracle -> OCI issue. -> -> You'd need to talk to Oracle support. No need to -> mention perl etc. -> Just talk about your OCI application and provide the -> OCI call trace. -> -> Let me know what you find out! -> -> Tim. -> -> > thanks a lot, -> > -> > Calin -> > -> > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, Calin -> Medianu wrote: -> > > > Hello, -> > > > -> > > > I did the following. Wrote a perl script that -> retreves -> > > > data via a straight select from the database. -> Then I -> > > > wrote a stored procedure returning a ref -> cursor open -> > > > on the same select statement and retrieved the -> data as -> > > > well. Using the REF CURSOR/ sotred procedure -> was about -> > > > 3 time slower, that is 40 seconds instead of -> around -> > > > 10. -> > > > -> > > > Is this normal? Is this a problem with oracle -> or with -> > > > DBD::Oracle? -> > > -> > > DBD::Oracle. It probably isn't setting up a row -> cache for the ref cursor. -> > > -> > > Get a level 3 trace and look for the -> "dbd_describe'd" line for the -> > > ref cursor. -> > > -> > > Tim. - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - -From calinm@yahoo.com Fri May 3 13:48:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g43Cm5R50489 - for ; Fri, 3 May 2002 13:48:05 +0100 (BST) - (envelope-from calinm@yahoo.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 03 May 2002 13:48:05 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020429421:10:02019:143; Fri, 03 May 2002 12:37:01 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-1.mail.demon.net - id aa1123562; 3 May 2002 12:36 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id D7BD1725A1 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from web10008.mail.yahoo.com (web10008.mail.yahoo.com [216.136.130.44]) - by wormwood.pobox.com (Postfix) with SMTP id 3088772674 - for ; Fri, 3 May 2002 08:36:41 -0400 (EDT) -Message-ID: <20020503123640.19648.qmail@web10008.mail.yahoo.com> -Received: from [213.157.171.169] by web10008.mail.yahoo.com via HTTP; Fri, 03 May 2002 05:36:40 PDT -Date: Fri, 3 May 2002 05:36:40 -0700 (PDT) -From: Calin Medianu -Subject: Re: DBD::Oracle Slow cursors -To: Tim Bunce -In-Reply-To: <20020501155718.S16831@dansat.data-plan.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Status: RO -Content-Length: 3619 -Lines: 150 - -Sure, - -I'll give it a try next week. - -Cheers, - -Calin ---- Tim Bunce wrote: -> Thanks. I'll take a look when I get to DBD::Oracle -> again. -> -> I think the last row of that table applies and it -> doesn't refer to OCIBindObject(): -> REF CURSOR variables -> SQLT_RSET -> Allocate a statement handle, OCIStmt, and then -> bind its address -> (OCIStmt **) using the SQLT_RSET datatype. -> Note that SQLT_REF isn't the same as SQLT_RSET. -> -> You could always try patching it yourself! -> -> Tim. -> -> -> On Tue, Apr 30, 2002 at 11:34:29AM -0700, Calin -> Medianu wrote: -> > It says here: -> > -> -http://technet.oracle.com/doc/oracle8i_816/appdev.816/a76975/oci05bnd.htm#421007 -> > -> > that 2 calls are neede to bind a ref , the second -> is -> > to OCIBindObject() which I don't see in dbdimp.c. -> > -> > Could this be a reason? -> > -> > Cheers, -> > -> > Calin -> > -> > --- Tim Bunce wrote: -> > > On Tue, Apr 30, 2002 at 04:04:47PM +0300, Calin -> > > Medianu wrote: -> > > > Me again with the slow cursors. -> > > > -> > > > I modified both queries to only return 10 -> rows. -> > > > I ran a sniffer (ethereal) on the NIC. It is -> > > pretty cool, it also decodes TNS. -> > > > -> > > > when I am using the SQL, it works like this, -> there -> > > are about 7 packets -> > > > received by my workstation to set up the -> session, -> > > then all 10 rows are in the -> > > > same packet, then there is another packet -> probably -> > > saying goodbye. -> > > > -> > > > When I am using the REF cursor, each row comes -> in -> > > it's own TNS packet, that -> > > > is why it is so slow! -> > > > -> > > > Any idea how to fix it? -> > > -> > > Do a level 9 trace to get a log of the OCI calls -> and -> > > confirm that -> > > the fragment I posted is being called (may be -> > > helpful to also -> > > add an extra print statement into that code -> since -> > > parsing the -> > > OCI trace can be painful). -> > > -> > > Assuming the code is being called then as far as -> I -> > > can see the code is -> > > doing the right thing and it's probably an -> Oracle -> > > OCI issue. -> > > -> > > You'd need to talk to Oracle support. No need to -> > > mention perl etc. -> > > Just talk about your OCI application and provide -> the -> > > OCI call trace. -> > > -> > > Let me know what you find out! -> > > -> > > Tim. -> > > -> > > > thanks a lot, -> > > > -> > > > Calin -> > > > -> > > > > On Mon, Apr 29, 2002 at 01:18:53PM -0700, -> Calin -> > > Medianu wrote: -> > > > > > Hello, -> > > > > > -> > > > > > I did the following. Wrote a perl script -> that -> > > retreves -> > > > > > data via a straight select from the -> database. -> > > Then I -> > > > > > wrote a stored procedure returning a ref -> > > cursor open -> > > > > > on the same select statement and retrieved -> the -> > > data as -> > > > > > well. Using the REF CURSOR/ sotred -> procedure -> > > was about -> > > > > > 3 time slower, that is 40 seconds instead -> of -> > > around -> > > > > > 10. -> > > > > > -> > > > > > Is this normal? Is this a problem with -> oracle -> > > or with -> > > > > > DBD::Oracle? -> > > > > -> > > > > DBD::Oracle. It probably isn't setting up a -> row -> > > cache for the ref cursor. -> > > > > -> > > > > Get a level 3 trace and look for the -> > > "dbd_describe'd" line for the -> > > > > ref cursor. -> > > > > -> > > > > Tim. -> > -> > -> > __________________________________________________ -> > Do You Yahoo!? -> > Yahoo! Health - your guide to health and wellness -> > http://health.yahoo.com - - -__________________________________________________ -Do You Yahoo!? -Yahoo! Health - your guide to health and wellness -http://health.yahoo.com - diff --git a/err_unsorted/err_svrparse.msg b/err_unsorted/err_svrparse.msg deleted file mode 100644 index 16886ca8..00000000 --- a/err_unsorted/err_svrparse.msg +++ /dev/null @@ -1,4717 +0,0 @@ -From cary.millsap@hotsos.com Thu Sep 12 23:38:20 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8CMbgC02618 - for ; Thu, 12 Sep 2002 23:38:03 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 12 Sep 2002 23:38:03 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031869308:20:16258:30; Thu, 12 Sep 2002 22:21:48 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2108888; 12 Sep 2002 22:21 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id A32132F05C9 - for ; Thu, 12 Sep 2002 18:21:34 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-3.pobox.com (Postfix) with ESMTP id D71F62F056D - for ; Thu, 12 Sep 2002 18:21:31 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8CMLQn17849; - Thu, 12 Sep 2002 17:21:26 -0500 -From: "Cary Millsap" -To: -Subject: -Date: Thu, 12 Sep 2002 17:21:17 -0500 -Message-ID: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_016A_01C25A80.D1527130" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 64884 -Lines: 2025 - -This is a multi-part message in MIME format. - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: multipart/alternative; - boundary="----=_NextPart_001_016B_01C25A80.D1557E70" - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -How are you doing? I hope you've had a good two years since I saw you on -the Oracle Geek Cruise event. - - - -I've been working on a project this year to construct a book about -optimizing Oracle response time. In my research, I've discovered -something about the DBI that I didn't expect: it executes two Oracle -parse calls for every one that I would expect an efficient DBI layer to -make. I've included my Perl source (below), the Oracle level-12 trace -data that shows the sequence of calls it's receiving from the Perl -application (below), a level-9 DBI trace from the application -(attached), and our version information (below). - - - -The reason I'm bringing this to your attention in this way is that I'm -relying pretty heavily upon Perl for performance measurement tools, -examples, and simulators in the text. I love the language and I want for -the book to be an encouragement for more people to use Perl. However, -this extra-parse behavior is one of the things that the book highlights -as an important scalability barrier (some other tools do it too, -unfortunately). Of course, this is a speed bump on the road to my goal -of helping to promote Perl. - - - -I was hoping that by showing you this specific data, you could make the -problem go away. - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - -Listing [listing.sqltrace.pl]: a simple application that executes a -database query - -#!/usr/bin/perl - - - - - -# $Header: /home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 21:10:25 -cvm Exp $ - -# Cary Millsap (cary.millsap@hotsos.com) - - - - - -use strict; - -use warnings; - -use DBI; - -use DBD::Oracle; - -use Getopt::Long; - -use Term::ReadKey; - - - - - -my $sth; # Oracle statement handle - -my $hostname = ""; - -my $username = "/"; - -my $password = ""; - -my $logfile = "ex1.log"; - -my %attr = ( - - RaiseError => 1, - - AutoCommit => 0, - -); - -my %opt = ( - - pause => 0, - -); - - - - - -# Get command line options and arguments. - -GetOptions( - - "pause" => \$opt{pause}, - -); - -my $key = 37; # default query value - -$key = $ARGV[0] if $ARGV[0]; - - - - - -# Connect to Oracle. - -my $dbh = DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr); - -$dbh->trace(9, $logfile); - - - - - -# Activate tracing. - -$sth = $dbh->prepare(q(alter session set events '10046 trace name -context forever, level 12')); - -$sth->execute; - - - - - -# Allow the user to find the Oracle session and activate OS diagnostic - -# tools like strace(1) or lsof(8). - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Execute the query to trace. - -$sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -$sth->execute($key); - - - - - -# Print output header. - -my @cdefs = qw(%8d %8d %32s); # column definitions - -my @hdefs = qw(Key Fkey Value); # column headings - -my $bformat = join(" ", @cdefs) . "\n"; - -my $hformat; ($hformat = $bformat) =~ s/%(\d*)\S+/%$1s/g; - -printf $hformat, @hdefs; - -printf $hformat, do { my @h; push @h, "-" x (/(\d+)/?$1:10) for @cdefs; -@h }; - - - - - -# Print query results. - -for my $row (@{$sth->fetchall_arrayref}) { - - printf $bformat, @$row; - -} - - - - - -# Allow the user to do final OS diagnostic stuff. - -if ($opt{pause}) { - - print "Press any key to continue..."; - - 1 while not defined (my $k = ReadKey(-1)); - - print "\n"; - -} - - - - - -# Disconnect from Oracle. - -$dbh->disconnect; - - - - - -Listing [listing:sqltrace.trc]: raw SQL trace output for an execution of -our program - -/usr/local/oracle/admin/V816/udump/ora_17349.trc - -Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production - -With the Partitioning option - -JServer Release 8.1.6.0.0 - Production - -ORACLE_HOME = /usr/local/oracle/product/8.1.6 - -System name: Linux - -Node name: www.hotsos.com - -Release: 2.2.16-22enterprise - -Version: #1 SMP Tue Aug 22 16:29:32 EDT 2000 - -Machine: i686 - -Instance name: V816 - -Redo thread mounted by this instance: 1 - -Oracle process number: 8 - -Unix process pid: 17349, image: oracle@www.hotsos.com (TNS V1-V3) - - - -*** SESSION ID:(7.9) 2002-09-12 16:14:01.582 - -===================== - -PARSING IN CURSOR #1 len=69 dep=0 uid=12 oct=42 lid=12 tim=107309054 -hv=1509700594 ad='54af5e14' - -alter session set events '10046 trace name context forever, level 12' - -END OF STMT - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107309054 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -*** 2002-09-12 16:14:31.226 - -WAIT #1: nam='SQL*Net message from client' ela= 2964 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -WAIT #2: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #2: nam='SQL*Net message from client' ela= 0 p1=1650815232 p2=1 -p3=0 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -BINDS #1: - - bind 0: dty=1 mxl=32(04) mal=00 scl=00 pre=00 oacflg=25 oacfl2=10 -size=32 offset=0 - - bfp=0940e7f0 bln=32 avl=04 flg=05 - - value="8542" - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0 - -WAIT #1: nam='file open' ela= 0 p1=0 p2=0 p3=0 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6671 p3=1 - -WAIT #1: nam='db file sequential read' ela= 0 p1=1 p2=6678 p3=1 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - -*** 2002-09-12 16:14:56.200 - -WAIT #1: nam='SQL*Net message from client' ela= 2496 p1=1650815232 p2=1 -p3=0 - -XCTEND rlbk=0, rd_only=1 - -STAT #1 id=1 cnt=1 pid=0 pos=0 obj=5156 op='TABLE ACCESS BY INDEX ROWID -T ' - -STAT #1 id=2 cnt=2 pid=1 pos=1 obj=5157 op='INDEX UNIQUE SCAN ' - - - - - -$ perl -V - -Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration: - - Platform: - - osname=linux, osvers=2.2.5-22smp, archname=i386-linux - - uname='linux porky.devel.redhat.com 2.2.5-22smp #1 smp wed jun 2 -09:11:51 edt 1999 i686 unknown ' - - config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -Dcc=gcc --Dcccdlflags=-fPIC -Dinstallprefix=/usr -Dprefix=/usr --Darchname=i386-linux -Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm --Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Uuselargefiles' - - hint=recommended, useposix=true, d_sigaction=define - - usethreads=undef use5005threads=undef useithreads=undef -usemultiplicity=undef - - useperlio=undef d_sfio=undef uselargefiles=undef - - use64bitint=undef use64bitall=undef uselongdouble=undef -usesocks=undef - - Compiler: - - cc='gcc', optimize='-O2 -march=i386 -mcpu=i686', gccversion=2.96 -20000731 (experimental) - - cppflags='-fno-strict-aliasing' - - ccflags ='-fno-strict-aliasing' - - stdchar='char', d_stdstdio=define, usevfork=false - - intsize=4, longsize=4, ptrsize=4, doublesize=8 - - d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 - - ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', -lseeksize=4 - - alignbytes=4, usemymalloc=n, prototype=define - - Linker and Libraries: - - ld='gcc', ldflags =' -L/usr/local/lib' - - libpth=/usr/local/lib /lib /usr/lib - - libs=-lnsl -ldl -lm -lc -lcrypt - - libc=/lib/libc-2.1.92.so, so=so, useshrplib=false, libperl=libperl.a - - Dynamic Linking: - - dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' - - cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' - - - - - -Characteristics of this binary (from libperl): - - Compile-time options: - - Built under linux - - Compiled at Aug 7 2000 10:59:51 - - @INC: - - /usr/lib/perl5/5.6.0/i386-linux - - /usr/lib/perl5/5.6.0 - - /usr/lib/perl5/site_perl/5.6.0/i386-linux - - /usr/lib/perl5/site_perl/5.6.0 - - /usr/lib/perl5/site_perl - - . - - - - - -Other site information - -- Redhat Linux 7.0 - -- Oracle 8.1.6.1.0 - -- DBD-Oracle 1.12 - -- DBI 1.30 - - - - -------=_NextPart_001_016B_01C25A80.D1557E70 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

How are you doing? I hope you’ve had a good two = -years -since I saw you on the Oracle Geek Cruise event.

- -

 

- -

I’ve been working on a project this year to = -construct -a book about optimizing Oracle response time. In my research, I’ve -discovered something about the DBI that I didn’t expect: it = -executes two -Oracle parse calls for every one that I would expect an efficient DBI = -layer to -make. I’ve included my Perl source (below), the Oracle level-12 = -trace -data that shows the sequence of calls it’s receiving from the Perl = -application -(below), a level-9 DBI trace from the application (attached), and our = -version information -(below).

- -

 

- -

The reason I’m bringing this to your attention = -in this -way is that I’m relying pretty heavily upon Perl for performance -measurement tools, examples, and simulators in the text. I love the = -language -and I want for the book to be an encouragement for more people to use = -Perl. -However, this extra-parse behavior is one of the things that the book = -highlights -as an important scalability barrier (some other tools do it too, = -unfortunately). -Of course, this is a speed bump on the road to my goal of helping to = -promote Perl.

- -

 

- -

I was hoping that by showing you this specific data, = -you -could make the problem go away.

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -
- -

Listing [listing.sqltrace.pl]: a simple = -application that -executes a database query

- -
- -
- -

#!/usr/bin/perl

- -

- -

- -

 

- -

 

- -

# = -$Header: -/home/cvs/cvm-book1/sqltrace/ex1.pl,v 1.2 2002/09/12 = -21:10:25 cvm Exp $

- -

- -

# = -Cary Millsap (cary.millsap@hotsos.com)

- -

- -

 

- -

 

- -

use = -strict;

- -

- -

use = -warnings;

- -

- -

use = -DBI;

- -

- -

use = -DBD::Oracle;

- -

- -

use = -Getopt::Long;

- -

- -

use = -Term::ReadKey;

- -

- -

 

- -

 

- -

my -$sth;           &n= -bsp;        -# Oracle statement handle

- -

- -

my = -$hostname =3D -"";

- -

- -

my = -$username =3D -"/";

- -

- -

my = -$password =3D -"";

- -

- -

my = -$logfile  -=3D "ex1.log";

- -

- -

my = -%attr =3D (

- -

- -

    -RaiseError =3D> 1,

- -

- -

    -AutoCommit =3D> 0,

- -

- -

);

- -

- -

my = -%opt =3D (

- -

- -

    -pause   =3D> 0,

- -

- -

);

- -

- -

 

- -

 

- -

# Get = -command line -options and arguments.

- -

- -

GetOptions(

- -

- -

    -"pause" =3D> \$opt{pause},

- -

- -

);

- -

- -

my = -$key =3D -37;           &nbs= -p;  - # default query value

- -

- -

$key = -=3D $ARGV[0] if -$ARGV[0];

- -

- -

 

- -

 

- -

# = -Connect to -Oracle.

- -

- -

my = -$dbh =3D -DBI->connect("dbi:Oracle:$hostname", $username, $password, -\%attr);

- -

- -

$dbh->trace(9, -$logfile);

- -

- -

 

- -

 

- -

# = -Activate -tracing.

- -

- -

$sth = -=3D -$dbh->prepare(q(alter session set events '10046 trace name context = -forever, -level 12'));

- -

- -

$sth->execute;

- -

- -

 

- -

 

- -

# = -Allow the user -to find the Oracle session and activate OS diagnostic

- -

- -

# = -tools like -strace(1) or lsof(8).

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Execute the -query to trace.

- -

- -

$sth = -=3D -$dbh->prepare(q(select key, fkey, value from t where = -key=3D?));

- -

- -

$sth->execute($key);

- -

- -

 

- -

 

- -

# = -Print output -header.

- -

- -

my = -@cdefs =3D qw(%8d -%8d %32s);   # column definitions

- -

- -

my = -@hdefs =3D qw(Key -Fkey Value); # column headings

- -

- -

my = -$bformat =3D -join("  ", @cdefs) . "\n";

- -

- -

my = -$hformat; -($hformat =3D $bformat) =3D~ s/%(\d*)\S+/%$1s/g;

- -

- -

printf $hformat, -@hdefs;

- -

- -

printf $hformat, -do { my @h; push @h, "-" x (/(\d+)/?$1:10) for = -@cdefs; @h };

- -

- -

 

- -

 

- -

# = -Print query -results.

- -

- -

for = -my $row -(@{$sth->fetchall_arrayref}) {

- -

- -

    -printf $bformat, @$row;

- -

- -

}

- -

- -

- -

 

- -

 

- -

# = -Allow the user -to do final OS diagnostic stuff.

- -

- -

if = -($opt{pause}) {

- -

- -

    -print "Press any key to continue...";

- -

- -

    -1 while not defined (my $k =3D ReadKey(-1));

- -

- -

    -print "\n";

- -

- -

}

- -

- -

 

- -

 

- -

# = -Disconnect from -Oracle.

- -

- -

$dbh->disconnect;

- -
- -

 

- -

 

- -
- -

Listing [listing:sqltrace.trc]: raw SQL trace = -output for -an execution of our program

- -
- -
- -

/usr/local/oracle/admin/V816/udump/ora_17349.tr= -c

- -

Oracle8i Enterprise -Edition Release 8.1.6.1.0 - Production

- -

With = -the -Partitioning option

- -

JServer Release -8.1.6.0.0 - Production

- -

ORACLE_HOME =3D -/usr/local/oracle/product/8.1.6

- -

System -name:        Linux

- -

Node name:  = -www.hotsos.com

- -

Release:    = -2.2.16-22enterprise

- -

Version:    #1 -SMP Tue Aug 22 16:29:32 EDT 2000

- -

Machine:    = -i686

- -

Instance name: -V816

- -

Redo = -thread -mounted by this instance: 1

- -

Oracle process -number: 8

- -

Unix = -process pid: -17349, image: oracle@www.hotsos.com (TNS V1-V3)

- -

 

- -

*** = -SESSION -ID:(7.9) 2002-09-12 16:14:01.582

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D69 dep=3D0 uid=3D12 oct=3D42 lid=3D12 = -tim=3D107309054 hv=3D1509700594 -ad=3D'54af5e14'

- -

alter = -session set -events '10046 trace name context forever, level 12'

- -

END = -OF STMT

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -309054

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

*** = -2002-09-12 -16:14:31.226

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2964 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#2 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312018 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

WAIT = -#2: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#2: -nam=3D'SQL*Net message from client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= -=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR -#1 len=3D44 dep=3D0 uid=3D12 oct=3D3 lid=3D12 = -tim=3D107312019 hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, -value from t where key=3D:p1

- -

END = -OF STMT

- -

PARSE -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

BINDS = -#1:

- -

 bind 0: -dty=3D1 mxl=3D32(04) mal=3D00 scl=3D00 pre=3D00 oacflg=3D25 oacfl2=3D10 = -size=3D32 offset=3D0

- -

   bfp=3D0940e7f0 bln=3D32 avl=3D04 flg=3D05

- -

   -value=3D"8542"

- -

EXEC -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

WAIT = -#1: -nam=3D'SQL*Net message to client' ela=3D 0 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

WAIT = -#1: nam=3D'file -open' ela=3D 0 p1=3D0 p2=3D0 p3=3D0

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6671 p3=3D1

- -

WAIT = -#1: nam=3D'db -file sequential read' ela=3D 0 p1=3D1 p2=3D6678 p3=3D1

- -

FETCH -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

*** = -2002-09-12 -16:14:56.200

- -

WAIT = -#1: -nam=3D'SQL*Net message from client' ela=3D 2496 p1=3D1650815232 p2=3D1 = -p3=3D0

- -

XCTEND rlbk=3D0, -rd_only=3D1

- -

STAT = -#1 id=3D1 cnt=3D1 -pid=3D0 pos=3D0 obj=3D5156 op=3D'TABLE ACCESS BY INDEX ROWID T = -'

- -

STAT = -#1 id=3D2 cnt=3D2 -pid=3D1 pos=3D1 obj=3D5157 op=3D'INDEX UNIQUE SCAN '

- -
- -

 

- -

 

- -

$ perl -V

- -

Summary of my perl5 (revision 5.0 version 6 subversion 0) = -configuration:

- -

  Platform:

- -

    osname=3Dlinux, osvers=3D2.2.5-22smp, = -archname=3Di386-linux

- -

    uname=3D'linux porky.devel.redhat.com = -2.2.5-22smp #1 smp -wed jun 2 09:11:51 edt 1999 i686 unknown '

- -

    config_args=3D'-des -Doptimize=3D-O2 = --march=3Di386 -mcpu=3Di686 --Dcc=3Dgcc -Dcccdlflags=3D-fPIC -Dinstallprefix=3D/usr -Dprefix=3D/usr = --Darchname=3Di386-linux --Dd_dosuid -Dd_semctl_semun -Di_db -Di_ndbm -Di_gdbm -Di_shadow = --Di_syslog -Dman3ext=3D3pm -Uuselargefiles'

- -

    hint=3Drecommended, useposix=3Dtrue, = -d_sigaction=3Ddefine

- -

    usethreads=3Dundef use5005threads=3Dundef = -useithreads=3Dundef -usemultiplicity=3Dundef

- -

    useperlio=3Dundef d_sfio=3Dundef = -uselargefiles=3Dundef

- -

    use64bitint=3Dundef use64bitall=3Dundef = -uselongdouble=3Dundef -usesocks=3Dundef

- -

  Compiler:

- -

    cc=3D'gcc', optimize=3D'-O2 -march=3Di386 = --mcpu=3Di686', gccversion=3D2.96 -20000731 (experimental)

- -

    = -cppflags=3D'-fno-strict-aliasing'

- -

    ccflags = -=3D'-fno-strict-aliasing'

- -

    stdchar=3D'char', d_stdstdio=3Ddefine, = -usevfork=3Dfalse

- -

    intsize=3D4, longsize=3D4, ptrsize=3D4, = -doublesize=3D8

- -

    d_longlong=3Ddefine, longlongsize=3D8, = -d_longdbl=3Ddefine, -longdblsize=3D12

- -

    ivtype=3D'long', ivsize=3D4, = -nvtype=3D'double', nvsize=3D8, Off_t=3D'off_t', -lseeksize=3D4

- -

    alignbytes=3D4, usemymalloc=3Dn, = -prototype=3Ddefine

- -

  Linker and Libraries:

- -

    ld=3D'gcc', ldflags =3D' = --L/usr/local/lib'

- -

    libpth=3D/usr/local/lib /lib = -/usr/lib

- -

    libs=3D-lnsl -ldl -lm -lc = --lcrypt

- -

    libc=3D/lib/libc-2.1.92.so, so=3Dso, = -useshrplib=3Dfalse, libperl=3Dlibperl.a

- -

  Dynamic Linking:

- -

    dlsrc=3Ddl_dlopen.xs, dlext=3Dso, = -d_dlsymun=3Dundef, ccdlflags=3D'-rdynamic'

- -

    cccdlflags=3D'-fPIC', lddlflags=3D'-shared = --L/usr/local/lib'

- -

 

- -

 

- -

Characteristics of this binary (from libperl): = -

- -

  Compile-time options:

- -

  Built under linux

- -

  Compiled at Aug  7 2000 10:59:51

- -

  @INC:

- -

    = -/usr/lib/perl5/5.6.0/i386-linux

- -

    /usr/lib/perl5/5.6.0

- -

    = -/usr/lib/perl5/site_perl/5.6.0/i386-linux

- -

    = -/usr/lib/perl5/site_perl/5.6.0

- -

    /usr/lib/perl5/site_perl

- -

    .

- -

 

- -

 

- -

Other site information

- -

- Redhat Linux 7.0

- -

- Oracle 8.1.6.1.0

- -

- DBD-Oracle 1.12

- -

- DBI 1.30

- -

 

- -
- - - - - -------=_NextPart_001_016B_01C25A80.D1557E70-- - -------=_NextPart_000_016A_01C25A80.D1527130 -Content-Type: application/octet-stream; - name="ex1.log" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: attachment; - filename="ex1.log" - - DBI::db=3DHASH(0x8235a74) trace level set to 9 in DBI 1.30-nothread=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'alter session set events '10046 trace name context forever, level 12'')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240f68)=3D>DBI::st=3DHASH(0x8240f98),= - DBD::Oracle::st, 8240f74, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240f98), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= -OCIHandleAlloc(0x82465d8,0x826c948,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826bf48,0x82559ec,'alter session set events '10046 = -trace name context forever, level 12'',69,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0x826c94c,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql ALTER=0A= - dbd_describe skipped for ALTER=0A= - <- prepare=3D DBI::st=3DHASH(0x8240f68) at ex1.pl line 38=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240f68)~0x8240f98)=0A= - dbd_st_execute ALTER (out0, lob0)...=0A= -OCIStmtExecute(0x82557c4,0x826bf48,0x82559ec,1,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff654,(nil),9,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826bf48,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute ALTER returned (SUCCESS, rpc0, fn52, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 39=0A= - -> prepare for DBD::Oracle::db (DBI::db=3DHASH(0x8235b34)~0x8235a74 = -'select key, fkey, value from t where key=3D?')=0A= - = -dbih_setup_handle(DBI::st=3DHASH(0x8240fe0)=3D>DBI::st=3DHASH(0x8240fb0),= - DBD::Oracle::st, 8240fec, Null!)=0A= - dbih_make_com(DBI::db=3DHASH(0x8235a74), DBD::Oracle::st, 208) = -thr#(nil)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Err, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162bb8) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), State, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8190e58) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Errstr, = -DBI::db=3DHASH(0x8235a74)) SCALAR(0x8162ba0) (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), Debug, = -DBI::db=3DHASH(0x8235a74)) 9 (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), FetchHashKeyName, = -DBI::db=3DHASH(0x8235a74)) 'NAME' (already defined)=0A= - dbih_setup_attrib(DBI::st=3DHASH(0x8240fb0), HandleError, = -DBI::db=3DHASH(0x8235a74)) undef (not defined)=0A= - dbd_preparse scanned 1 distinct placeholders=0A= -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCCESS=0A= -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where = -key=3D:p1',44,1,0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=3DSUCCE= -SS=0A= - dbd_st_prepare'd sql SELECT=0A= - dbd_describe SELECT (EXPLICIT, lb 80)...=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3DSUCCES= -S=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3dc,(nil),18,0x82559ec)=3DSUCC= -ESS=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d1c0,1)=3DSUCCESS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d6,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d4,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1d8,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1da,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1db,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e228,OCI_DTYPE_PARAM,0x826d1e8,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 1: 'KEY' NO null , otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d200,2)=3DSUCCESS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d216,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d214,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d218,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d21b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e208,OCI_DTYPE_PARAM,0x826d228,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 2: 'FKEY' NULLable, otype 2-> 5, dbsize 22/134, p0.s0=0A= -OCIParamGet(0x826e4a0,4,0x82559ec,0x826d240,3)=3DSUCCESS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d256,(nil),2,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d254,(nil),1,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d258,(nil),5,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25a,(nil),6,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d25b,(nil),7,0x82559ec)=3DSUCCE= -SS=0A= -OCIAttrGet(0x826e1e8,OCI_DTYPE_PARAM,0x826d268,0xbffff3d8,4,0x82559ec)=3D= -SUCCESS=0A= - fbh 3: 'VALUE' NULLable, otype 1-> 5, dbsize 32/33, p32.s0=0A= -OCIAttrSet(0x826e4a0,OCI_HTYPE_STMT,0xbffff3d4,4,11,0x82559ec)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d1c4,0x82559ec,1,0x826e8d0,134,5,0x826d438,= -0x826d448,0x826d458,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d204,0x82559ec,2,0x826eaf8,134,5,0x826ca28,= -0x826ca38,0x826ca48,0)=3DSUCCESS=0A= -OCIDefineByPos(0x826e4a0,0x826d244,0x82559ec,3,0x826cbb8,33,5,0x826ca58,0= -x826cbe0,0x826cbf0,0)=3DSUCCESS=0A= - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231)=0A= - <- prepare=3D DBI::st=3DHASH(0x8240fe0) at ex1.pl line 50=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240f98)~INNER)=0A= -OCIHandleFree(0x826bf48,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef at ex1.pl line 51=0A= - -> execute for DBD::Oracle::st (DBI::st=3DHASH(0x8240fe0)~0x8240fb0 = -'8542')=0A= - bind :p1 <=3D=3D '8542' (type 0)=0A= - bind :p1 <=3D=3D '8542' (size 4/5/0, ptype 7, otype 1)=0A= - bind :p1 <=3D=3D '8542' (size 4/4, otype 1, indp 0, at_exec 1)=0A= -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb= -6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS=0A= -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da= -090)=3DSUCCESS=0A= - bind :p1 done with ftype 1=0A= - dbd_st_execute SELECT (out0, lob0)...=0A= - in ':p1' [0,0]: len 4, ind 0=0A= -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3DSUCCESS=0A= -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=3DSUCC= -ESS=0A= - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0)=0A= - <- execute=3D '0E0' at ex1.pl line 51=0A= - -> fetchall_arrayref for DBD::Oracle::st = -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0)=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DSUCCESS=0A= - dbih_setup_fbav for 3 fields =3D> 0x8240fbc=0A= - dbd_st_fetch 3 fields SUCCESS=0A= - 0 (rc=3D0): '8542'=0A= - 1 (rc=3D0): '8542'=0A= - 2 (rc=3D0): 'value'=0A= - dbd_st_fetch 3 fields...=0A= -OCIStmtFetch(0x826e4a0,0x82559ec,1,2,0)=3DNO_DATA=0A= - dbd_st_fetch no-more-data=0A= - <- fetchall_arrayref=3D [ ARRAY(0x82411f0) ] row1 at ex1.pl line 62=0A= - -> disconnect for DBD::Oracle::db = -(DBI::db=3DHASH(0x8235b34)~0x8235a74)=0A= -OCISessionEnd(0x82557c4,0x82559ec,0x826c384,0)=3DSUCCESS=0A= -OCIServerDetach(0x8255834,0x82559ec,0)=3DSUCCESS=0A= - <- disconnect=3D 1 at ex1.pl line 74=0A= - -> DESTROY for DBD::Oracle::st (DBI::st=3DHASH(0x8240fb0)~INNER)=0A= -OCIHandleFree(0x826e4a0,OCI_HTYPE_STMT)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -> DESTROY for DBD::Oracle::db (DBI::db=3DHASH(0x8235a74)~INNER)=0A= -OCIHandleFree(0x826c384,OCI_HTYPE_SESSION)=3DSUCCESS=0A= -OCIHandleFree(0x8255834,OCI_HTYPE_SERVER)=3DSUCCESS=0A= -OCIHandleFree(0x82557c4,OCI_HTYPE_SVCCTX)=3DSUCCESS=0A= -OCIHandleFree(0x82559ec,OCI_HTYPE_ERROR)=3DSUCCESS=0A= - <- DESTROY=3D undef=0A= - -------=_NextPart_000_016A_01C25A80.D1527130-- - - -From timbo@dansat.data-plan.com Fri Sep 13 07:30:31 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6UUC04053 - for ; Fri, 13 Sep 2002 07:30:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:30:30 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031871608:20:03733:55; Thu, 12 Sep 2002 23:00:08 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id ab2122693; 12 Sep 2002 23:00 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id AE0642F0B8A - for ; Thu, 12 Sep 2002 18:58:25 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-3.pobox.com (Postfix) with SMTP id 931D42F0D0A - for ; Thu, 12 Sep 2002 18:58:19 -0400 (EDT) -Received: (qmail 57270 messnum 519666 invoked from network[159.134.164.69/p69.as1.limerick1.eircom.net]); 12 Sep 2002 22:58:17 -0000 -Received: from p69.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.69) - by mail03.svc.cra.dublin.eircom.net (qp 57270) with SMTP; 12 Sep 2002 22:58:17 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8CMwEQ02798; - Thu, 12 Sep 2002 23:58:14 +0100 (BST) - (envelope-from timbo) -Date: Thu, 12 Sep 2002 23:58:14 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls -Message-ID: <20020912225814.GG539@dansat.data-plan.com> -References: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <016901c25aaa$ba287930$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 3530 -Lines: 77 - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCESS - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 '8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401da090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCESS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - -From cary.millsap@hotsos.com Fri Sep 13 07:31:55 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6VsC04590 - for ; Fri, 13 Sep 2002 07:31:54 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:31:54 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031889643:20:09494:0; Fri, 13 Sep 2002 04:00:43 GMT -Received: from wormwood.pobox.com ([208.210.125.20]) by punt-2.mail.demon.net - id aa2008866; 13 Sep 2002 4:00 GMT -Received: from wormwood.pobox.com (localhost.pobox.com [127.0.0.1]) - by wormwood.pobox.com (Postfix) with ESMTP id C94C67264F - for ; Fri, 13 Sep 2002 00:00:07 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by wormwood.pobox.com (Postfix) with ESMTP id A821072676 - for ; Fri, 13 Sep 2002 00:00:06 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D405n19404 - for ; Thu, 12 Sep 2002 23:00:05 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 22:59:56 -0500 -Message-ID: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020912225814.GG539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4825 -Lines: 129 - -Tim, - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Thursday, September 12, 2002 5:58 PM -To: Cary Millsap -Cc: tim.bunce@pobox.com -Subject: two Oracle parse calls - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> Tim, -> -> How are you doing? I hope you've had a good two years since I saw you -on -> the Oracle Geek Cruise event. - -Yes thanks. And you? - -> I've been working on a project this year to construct a book about -> optimizing Oracle response time. In my research, I've discovered -> something about the DBI that I didn't expect: it executes two Oracle -> parse calls for every one that I would expect an efficient DBI layer -to -> make. I've included my Perl source (below), the Oracle level-12 trace -> data that shows the sequence of calls it's receiving from the Perl -> application (below), a level-9 DBI trace from the application -> (attached), and our version information (below). -> -> I was hoping that by showing you this specific data, you could make -the -> problem go away. - -I can only do what OCI lets me do... but within that I'll do what I -can... - -I'm not familar with Oracle trace logs so I can't readily intrepret them -and I'll take what you say at face value. - -But I am familar with DBD::Oracle :) and the logs it writes :) - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> $sth->execute($key); - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - dbd_preparse scanned 1 distinct placeholders -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - dbd_st_prepare'd sql SELECT - dbd_describe SELECT (EXPLICIT, lb 80)... -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - bind :p1 done with ftype 1 - dbd_st_execute SELECT (out0, lob0)... - in ':p1' [0,0]: len 4, ind 0 -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - <- execute= '0E0' at ex1.pl line 51 - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -call that prepare() does. - -It doesn't do that for non-select statements so you could check if -non-selects also have two parse calls. - -Also try doing - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) -is possibly redundant and could be removed (but Oracle ought to detect -that -anyway and not make a round-trip for it, and certainly not call parse). - -If non-selects only have one parse call but ora_check_sql=>0 doesn't -fix selects, then I might be able to do a simple patch to avoid the -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - -Then the issue will be: should ora_check_sql=>0 be the default... - -Tim. - -p.s. I'd love a copy of your book when it's ready! - - -From timbo@dansat.data-plan.com Fri Sep 13 10:48:59 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D9mwC06022 - for ; Fri, 13 Sep 2002 10:48:58 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.22] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 10:48:58 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031907122:20:19599:21; Fri, 13 Sep 2002 08:52:02 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2129553; 13 Sep 2002 8:52 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 99E263E660 - for ; Fri, 13 Sep 2002 04:51:54 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail03.svc.cra.dublin.eircom.net (mail03.svc.cra.dublin.eircom.net [159.134.118.19]) - by cali-2.pobox.com (Postfix) with SMTP id 721613E637 - for ; Fri, 13 Sep 2002 04:51:53 -0400 (EDT) -Received: (qmail 29161 messnum 524631 invoked from network[159.134.167.5/p773.as1.limerick1.eircom.net]); 13 Sep 2002 08:51:51 -0000 -Received: from p773.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.167.5) - by mail03.svc.cra.dublin.eircom.net (qp 29161) with SMTP; 13 Sep 2002 08:51:51 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8D8prO05752; - Fri, 13 Sep 2002 09:51:53 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 09:51:53 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913085153.GJ539@dansat.data-plan.com> -References: <20020912225814.GG539@dansat.data-plan.com> <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <019201c25ada$093c6ac0$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 6172 -Lines: 154 - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more "official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -> key=:p1',44,1,0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - -From cary.millsap@hotsos.com Fri Sep 13 17:52:40 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DGqdC10778 - for ; Fri, 13 Sep 2002 17:52:39 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 17:52:39 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031932999:10:25604:102; Fri, 13 Sep 2002 16:03:19 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1101673; 13 Sep 2002 16:03 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id E4A692C078 - for ; Fri, 13 Sep 2002 12:02:43 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 1609E2C03F - for ; Fri, 13 Sep 2002 12:02:29 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DG2Sn24856 - for ; Fri, 13 Sep 2002 11:02:28 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Fri, 13 Sep 2002 11:02:20 -0500 -Message-ID: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913085153.GJ539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 9234 -Lines: 248 - -Tim, - -I think it's important for a developer to have the ability to turn this -on and off. But I would argue that 0 is the correct default. I think of -it as a probability times cost function. The cost of leaving the setting -at 1 accidentally in a production application is pretty high: if the app -doesn't scale (because it's parsing too much), then it jeopardizes the -business' ability to succeed with it. - -The probability of leaving the option set to 1 accidentally during -production is very high. A point in evidence is that I didn't find the -parameter until I corresponded personally with you. I in fact *still* -don't know where to find it. I've checked Descartes & Bunce, perldoc -DBI, and perldoc DBD::Oracle without finding it yet... - -If the default were 0, the probability of leaving the option set to 0 -accidentally during development would be much lower. A developer faced -with a SQL syntax problem he doesn't understand will do the research -necessary to fix that problem. He can't release his code until he does. - -The problem with the default of 1 is, in my opinion, that most -developers will never learn of the feature, and they'll accidentally -leave it turned on in production. The proportion of developers who -competently performance-test their code is, unfortunately, -microscopically small. But they all do some level of functional testing. - -I would recommend making the ora_check_sql feature a more prominently -documented feature, presumably in "perldoc DBD::Oracle". - -I did learn in a test that specifying the option in the DBI->connect() -call doesn't do anything. Is it possible that you could allow us to -specify it at the connection level? The workaround is to do something -like this: - - use Getopt::Long; - my %prepare_attr = (ora_check_sql=>0); - GetOptions("dev"=>\$dev); - $prepare_attr{ora_check_sql} = 1 if $dev; - # developer must specify the command-line flag to get the -unscalable - # behavior that's necessary for functional testing - ... - $sth = $dbh->prepare($sql, %prepare_attr); # MUST specify -%p..attr - -...But I doubt that most Oracle application developers would come up -with this without some coaching. - -I'll definitely keep an eye open for projects you might like. It would -be a hell of an opportunity for someone to have you, I think. It seems -that if you could make a list like Oracle-L (1,900 people) aware that -there's an opportunity, it would improve your chances of finding -something quickly. It's of course bad taste to advertise oneself overtly -on those lists, but there is almost always a clever way to do it anyway -without offending anyone. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:52 AM -To: Cary Millsap -Cc: 'Tim Bunce' -Subject: Re: two Oracle parse calls - -On Thu, Sep 12, 2002 at 10:59:56PM -0500, Cary Millsap wrote: -> Tim, -> -> Thanks so very much. The attribute ora_check_sql=>0 is new knowledge -to -> me; this is a nice reward for having written to you. I will test it -> either tonight or the first thing tomorrow and then inform you of the -> results immediately after that. If it solves the problem, then I will -> lobby you to make 0 the default value and probably consider the issue -> "problem solved." - -Ah, but there are down-sides to ora_check_sql=0 - it was the default -for a little while. Here's an old message that, although being out of -date in various ways, describes some of the issues: - -http://www.bitmechanic.com/mail-archives/dbi-users/Apr1999/0538.html - -In principle I don't have a fundamental objection to defering the -'describe' until execute and thus defering detection of syntax -errors until the execute. I'd probably add a new $dbh attribute to -set the desired default behaviour so you don't have to add it to -each prepare() call. - -> Things are very well, thank you. I've been at home with my family now -> for over three straight weeks, and we're having a nice time of our -lives -> these days with the business settling into stride a bit. Tonight is a -> big night for me. I've just crossed the line of accepting a -preliminary -> offer from O'Reilly. This book project has actually been underway for -> quite some time now, but as of tonight it's quite a bit more -"official." - -Congratulations. I'm sure it'll be a success. - -BTW, if you happen to come across any work opportunities that might -fit my skills I'd be interested in hearing about them (would have to -be teleworking as I've no plans to move under any circumstances). -I'd especially love to find some company that uses DBI & DBD::Oracle -heavily and would basically pay me to develop them - there's *lots* -more valuable functionality that could be added to DBD::Oracle (and -my Oracle::OCI module). - -Tim. - -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Thursday, September 12, 2002 5:58 PM -> To: Cary Millsap -> Cc: tim.bunce@pobox.com -> Subject: two Oracle parse calls -> -> On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > How are you doing? I hope you've had a good two years since I saw -you -> on -> > the Oracle Geek Cruise event. -> -> Yes thanks. And you? -> -> > I've been working on a project this year to construct a book about -> > optimizing Oracle response time. In my research, I've discovered -> > something about the DBI that I didn't expect: it executes two Oracle -> > parse calls for every one that I would expect an efficient DBI layer -> to -> > make. I've included my Perl source (below), the Oracle level-12 -trace -> > data that shows the sequence of calls it's receiving from the Perl -> > application (below), a level-9 DBI trace from the application -> > (attached), and our version information (below). -> > -> > I was hoping that by showing you this specific data, you could make -> the -> > problem go away. -> -> I can only do what OCI lets me do... but within that I'll do what I -> can... -> -> I'm not familar with Oracle trace logs so I can't readily intrepret -them -> and I'll take what you say at face value. -> -> But I am familar with DBD::Oracle :) and the logs it writes :) -> -> > $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); -> > $sth->execute($key); -> -> -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -> 'select key, fkey, value from t where key=?') -> dbd_preparse scanned 1 distinct placeholders -> OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS -> OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t -where -> key=:p1',44,1,0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -> S -> dbd_st_prepare'd sql SELECT -> dbd_describe SELECT (EXPLICIT, lb 80)... -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS -> dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: -231) -> <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 -> -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -> '8542') -> -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -> b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS -> -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -> a090)=SUCCESS -> bind :p1 done with ftype 1 -> dbd_st_execute SELECT (out0, lob0)... -> in ':p1' [0,0]: len 4, ind 0 -> -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS -> -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -> SS -> dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) -> <- execute= '0E0' at ex1.pl line 51 -> -> Given those OCI calls, what is DBD::Oracle doing that it shouldn't? -> -> I'd guess that it's something to do with the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> call that prepare() does. -> -> It doesn't do that for non-select statements so you could check if -> non-selects also have two parse calls. -> -> Also try doing -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), -{ -> ora_check_sql=> 0 }); -> -> which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the -> main OCIStmtExecute(). In that case the OCIStmtExecute(..., -> OCI_DESCRIBE_ONLY) -> is possibly redundant and could be removed (but Oracle ought to detect -> that -> anyway and not make a round-trip for it, and certainly not call -parse). -> -> If non-selects only have one parse call but ora_check_sql=>0 doesn't -> fix selects, then I might be able to do a simple patch to avoid the -> OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. -> -> Then the issue will be: should ora_check_sql=>0 be the default... -> -> Tim. -> -> p.s. I'd love a copy of your book when it's ready! -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:37 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLbC13725 - for ; Fri, 13 Sep 2002 23:21:37 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:37 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031951069:20:15816:152; Fri, 13 Sep 2002 21:04:29 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-2.mail.demon.net - id aa2120669; 13 Sep 2002 21:04 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 544863E642 - for ; Fri, 13 Sep 2002 17:04:17 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id 0AE7C3E667 - for ; Fri, 13 Sep 2002 17:04:16 -0400 (EDT) -Received: (qmail 16221 messnum 355694 invoked from network[159.134.166.226/p738.as1.limerick1.eircom.net]); 13 Sep 2002 21:04:14 -0000 -Received: from p738.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.166.226) - by mail05.svc.cra.dublin.eircom.net (qp 16221) with SMTP; 13 Sep 2002 21:04:14 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DL4Lx12642; - Fri, 13 Sep 2002 22:04:21 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:04:21 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: two Oracle parse calls -Message-ID: <20020913210421.GR539@dansat.data-plan.com> -References: <20020913085153.GJ539@dansat.data-plan.com> <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <01c501c25b3e$f3e7f440$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 3078 -Lines: 70 - -On Fri, Sep 13, 2002 at 11:02:20AM -0500, Cary Millsap wrote: -> Tim, -> -> I think it's important for a developer to have the ability to turn this -> on and off. But I would argue that 0 is the correct default. I think of -> it as a probability times cost function. The cost of leaving the setting -> at 1 accidentally in a production application is pretty high: if the app -> doesn't scale (because it's parsing too much), then it jeopardizes the -> business' ability to succeed with it. -> -> The probability of leaving the option set to 1 accidentally during -> production is very high. A point in evidence is that I didn't find the -> parameter until I corresponded personally with you. I in fact *still* -> don't know where to find it. I've checked Descartes & Bunce, perldoc -> DBI, and perldoc DBD::Oracle without finding it yet... - -It's not documented. - -As I recall it... originally DBD::Oracle defered the describe as -long as possible. But people reported very slow select performance: - - http://www.faqchest.com/prgm/dbi-l/dbi-99/dbi-9910/dbi-991005/dbi99101218_28018.html - -Turned out that the row cache logic needed the describe to try to -work out an optimal row cache size. Without the describe the row -cache wasn't getting set up. - -At some point I added code that would just set OCI_ATTR_PREFETCH_MEMORY -to a set size if ora_check_sql was 0. But I can't remember now why -I left ora_check_sql=1. - -It was possibly in relation to wanting to be able to use the -OCI_ATTR_PARSE_ERROR_OFFSET attribute to be able to highlight the -point in a query where the error was detected. But I think execute() -needs to be able to do that anyway (to catch syntax errors in -non-select statements). - -There is another problem. If the describe has been defered and the -application uses $sth->{NAME} or other similar attribute then the -describe has to be done at that point. The code is thee to do that -but the problem is how should the DBI behave if there's an error -in the SQL? It currently always croaks (rather than return undef, -in order to give a useful error message), but that's rather surprising -behaviour to many people and very unhelpful to some. - -There may well be other subtle issues that I can't recall right now. - -> I would recommend making the ora_check_sql feature a more prominently -> documented feature, presumably in "perldoc DBD::Oracle". -> -> I did learn in a test that specifying the option in the DBI->connect() -> call doesn't do anything. Is it possible that you could allow us to -> specify it at the connection level? - -By making it a database handle attribute, yes, that would be my plan. - -> I'll definitely keep an eye open for projects you might like. It would -> be a hell of an opportunity for someone to have you, I think. - -Thanks. - -> It seems that if you could make a list like Oracle-L (1,900 people) aware -> that there's an opportunity, it would improve your chances of finding -> something quickly. It's of course bad taste to advertise oneself overtly -> on those lists, but there is almost always a clever way to do it anyway -> without offending anyone. - -:-) - -Tim. - -From cary.millsap@hotsos.com Fri Sep 13 07:32:06 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8D6W1C04656 - for ; Fri, 13 Sep 2002 07:32:01 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 07:32:01 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031891038:20:04710:44; Fri, 13 Sep 2002 04:23:58 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id ab2004623; 13 Sep 2002 4:23 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 942A82BF2C - for ; Fri, 13 Sep 2002 00:23:44 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 73C982BF33 - for ; Fri, 13 Sep 2002 00:23:42 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8D4Ndn19584 - for ; Thu, 12 Sep 2002 23:23:39 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: two Oracle parse calls -Date: Thu, 12 Sep 2002 23:23:30 -0500 -Message-ID: <019301c25add$53f5dfd0$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0194_01C25AB3.6B1FD7D0" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -Content-Length: 36859 -Lines: 1209 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Well, that was easy. Setting ora_check_sql=>0 does solve the problem. - - - -I now shift into "Please make 0 the default" mode. - - - -Here are the Oracle trace files, by the way, with a splash of color to -illustrate how the Oracle kernel sees what's going on (I hope you have -an HTML mail reader)... - - - -With {ora_check_sql=>1} (or no setting at all), here's what Oracle does -for the application: - - - -===================== - -PARSING IN CURSOR #2 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312018 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312018 - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=107312019 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=107312019 - -FETCH #1:c=0,e=0,p=2,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=107312019 - - - -The PARSING IN CURSOR section tells us what SQL it is that we're -executing. Each line beginning with "PARSE" is emitted only when Oracle -executes a parse call. There are two. The first is wasted. - - - -Here's the same application with {ora_check_sql=>1} (the official new -default value, I am sure :-)): - - - -===================== - -PARSING IN CURSOR #1 len=44 dep=0 uid=12 oct=3 lid=12 tim=109776065 -hv=1997601641 ad='54af1384' - -select key, fkey, value from t where key=:p1 - -END OF STMT - -PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=109776065 - -FETCH #1:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=0,og=3,tim=109776065 - - - -One parse call; problem solved. - - - -Thank you sincerely for your help. - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- -From: Cary Millsap [mailto:cary.millsap@hotsos.com] -Sent: Thursday, September 12, 2002 11:00 PM -To: 'Tim Bunce' -Subject: RE: two Oracle parse calls - - - -Tim, - - - -Thanks so very much. The attribute ora_check_sql=>0 is new knowledge to -me; this is a nice reward for having written to you. I will test it -either tonight or the first thing tomorrow and then inform you of the -results immediately after that. If it solves the problem, then I will -lobby you to make 0 the default value and probably consider the issue -"problem solved." - - - -Things are very well, thank you. I've been at home with my family now -for over three straight weeks, and we're having a nice time of our lives -these days with the business settling into stride a bit. Tonight is a -big night for me. I've just crossed the line of accepting a preliminary -offer from O'Reilly. This book project has actually been underway for -quite some time now, but as of tonight it's quite a bit more "official." - - - - - -Cary Millsap - -Hotsos Enterprises, Ltd. - -http://www.hotsos.com - - - -Upcoming events: - -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu - -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas - -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - - - - - ------Original Message----- - -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] - -Sent: Thursday, September 12, 2002 5:58 PM - -To: Cary Millsap - -Cc: tim.bunce@pobox.com - -Subject: two Oracle parse calls - - - -On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap wrote: - -> Tim, - -> - -> How are you doing? I hope you've had a good two years since I saw you -on - -> the Oracle Geek Cruise event. - - - -Yes thanks. And you? - - - -> I've been working on a project this year to construct a book about - -> optimizing Oracle response time. In my research, I've discovered - -> something about the DBI that I didn't expect: it executes two Oracle - -> parse calls for every one that I would expect an efficient DBI layer -to - -> make. I've included my Perl source (below), the Oracle level-12 trace - -> data that shows the sequence of calls it's receiving from the Perl - -> application (below), a level-9 DBI trace from the application - -> (attached), and our version information (below). - -> - -> I was hoping that by showing you this specific data, you could make -the - -> problem go away. - - - -I can only do what OCI lets me do... but within that I'll do what I -can... - - - -I'm not familar with Oracle trace logs so I can't readily intrepret them - -and I'll take what you say at face value. - - - -But I am familar with DBD::Oracle :) and the logs it writes :) - - - -> $sth = $dbh->prepare(q(select key, fkey, value from t where key=?)); - -> $sth->execute($key); - - - - - - -> prepare for DBD::Oracle::db (DBI::db=HASH(0x8235b34)~0x8235a74 -'select key, fkey, value from t where key=?') - - dbd_preparse scanned 1 distinct placeholders - -OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=SUCCESS - -OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from t where -key=:p1',44,1,0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)=SUCCES -S - - dbd_st_prepare'd sql SELECT - - dbd_describe SELECT (EXPLICIT, lb 80)... - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=SUCCESS - - dbd_describe'd 3 columns (row bytes: 76 max, 40 est avg, cache: 231) - - <- prepare= DBI::st=HASH(0x8240fe0) at ex1.pl line 50 - - -> execute for DBD::Oracle::st (DBI::st=HASH(0x8240fe0)~0x8240fb0 -'8542') - -OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x826cd78,4,1,0x826c -b6e,(nil),0x826cb6c,0,(nil),2)=SUCCESS - -OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40,0x401d -a090)=SUCCESS - - bind :p1 done with ftype 1 - - dbd_st_execute SELECT (out0, lob0)... - - in ':p1' [0,0]: len 4, ind 0 - -OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=SUCCESS - -OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec)=SUCCE -SS - - dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0) - - <- execute= '0E0' at ex1.pl line 51 - - - -Given those OCI calls, what is DBD::Oracle doing that it shouldn't? - - - -I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -call that prepare() does. - - - -It doesn't do that for non-select statements so you could check if - -non-selects also have two parse calls. - - - -Also try doing - - $sth = $dbh->prepare(q(select key, fkey, value from t where key=?), { -ora_check_sql=> 0 }); - - - -which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till after the - -main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY) - -is possibly redundant and could be removed (but Oracle ought to detect -that - -anyway and not make a round-trip for it, and certainly not call parse). - - - -If non-selects only have one parse call but ora_check_sql=>0 doesn't - -fix selects, then I might be able to do a simple patch to avoid the - -OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if ora_check_sql=>0. - - - -Then the issue will be: should ora_check_sql=>0 be the default... - - - -Tim. - - - -p.s. I'd love a copy of your book when it's ready! - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Well, that was easy. Setting ora_check_sql=3D>0 = -does solve the -problem.

- -

 

- -

I now shift into "Please make 0 the = -default" mode.

- -

 

- -

Here are the Oracle trace files, by the way, with a = -splash -of color to illustrate how the Oracle kernel sees what’s going on = -(I hope -you have an HTML mail reader)...

- -

 

- -

With {ora_check_sql=3D>1} (or no setting at all), = -here’s -what Oracle does for the application:

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #2 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312018 = -hv=3D1997601641 ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF STMT

- -

PARSE = -#2:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312018

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 dep=3D0 uid=3D12 = -oct=3D3 lid=3D12 tim=3D107312019 = -hv=3D1997601641 -ad=3D'54af1384'

- -

select key, fkey, value from t where = -key=3D:p1

- -

END OF = -STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D107= -312019

- -

FETCH = -#1:c=3D0,e=3D0,p=3D2,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D107= -312019

- -

 

- -

The PARSING IN CURSOR section tells us what SQL it is = -that -we’re executing. Each line beginning with “PARSE” is = -emitted -only when Oracle executes a parse call. There are two. The first is = -wasted.

- -

 

- -

Here’s the same application with = -{ora_check_sql=3D>1} (the official new = -default value, I -am sure J):

- -

 

- -

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- -

PARSING IN CURSOR #1 len=3D44 = -dep=3D0 uid=3D12 -oct=3D3 lid=3D12 tim=3D109776065 hv=3D1997601641 = -ad=3D'54af1384'

- -

select key, fkey, value from = -t where -key=3D:p1

- -

END OF STMT

- -

PARSE = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

EXEC = -#1:c=3D0,e=3D0,p=3D0,cr=3D0,cu=3D0,mis=3D0,r=3D0,dep=3D0,og=3D3,tim=3D109= -776065

- -

FETCH = -#1:c=3D0,e=3D0,p=3D0,cr=3D3,cu=3D0,mis=3D0,r=3D1,dep=3D0,og=3D3,tim=3D109= -776065

- -

 

- -

One parse call; problem solved.

- -

 

- -

Thank you sincerely for your help.

- -

 

- -

 

- -

Cary = -Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System = -Performance, -Feb 9-12 Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 = -Middelfart Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----
-From: Cary Millsap [mailto:cary.millsap@hotsos.com]
-Sent: Thursday, September 12, 2002 11:00 PM
-To: 'Tim Bunce'
-Subject: RE: two Oracle parse calls

- -

 

- -

Tim,

- -

 

- -

Thanks so very much. The attribute ora_check_sql=3D>0 is new = -knowledge -to me; this is a nice reward for having written to you. I will test it = -either -tonight or the first thing tomorrow and then inform you of the results -immediately after that. If it solves the problem, then I will lobby you = -to make -0 the default value and probably consider the issue "problem = -solved."

- -

 

- -

Things are very well, thank you. I've been at home with my = -family now -for over three straight weeks, and we're having a nice time of our lives = -these -days with the business settling into stride a bit. Tonight is a big = -night for -me. I've just crossed the line of accepting a preliminary offer from = -O'Reilly. -This book project has actually been underway for quite some time now, = -but as of -tonight it's quite a bit more "official."

- -

 

- -

 

- -

Cary Millsap

- -

Hotsos Enterprises, Ltd.

- -

http://www.hotsos.com

- -

 

- -

Upcoming events:

- -

- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec = -9-11 -Honolulu

- -

- 2003 Hotsos Symposium on Oracle® System Performance, Feb = -9-12 -Dallas

- -

- Next event: Miracle Database Forum, Sep 20-22 Middelfart = -Denmark

- -

 

- -

 

- -

 

- -

-----Original Message-----

- -

From: Tim Bunce [mailto:Tim.Bunce@pobox.com]

- -

Sent: Thursday, September 12, 2002 5:58 PM

- -

To: Cary Millsap

- -

Cc: tim.bunce@pobox.com

- -

Subject: two Oracle parse calls

- -

 

- -

On Thu, Sep 12, 2002 at 05:21:17PM -0500, Cary Millsap = -wrote:

- -

> Tim,

- -

>

- -

> How are you doing? I hope you've had a good two years since = -I saw -you on

- -

> the Oracle Geek Cruise event.

- -

 

- -

Yes thanks. And you?

- -

 

- -

> I've been working on a project this year to construct a = -book about

- -

> optimizing Oracle response time. In my research, I've = -discovered

- -

> something about the DBI that I didn't expect: it executes = -two -Oracle

- -

> parse calls for every one that I would expect an efficient = -DBI -layer to

- -

> make. I've included my Perl source (below), the Oracle = -level-12 -trace

- -

> data that shows the sequence of calls it's receiving from = -the Perl

- -

> application (below), a level-9 DBI trace from the = -application

- -

> (attached), and our version information = -(below).

- -

>

- -

> I was hoping that by showing you this specific data, you = -could -make the

- -

> problem go away.

- -

 

- -

I can only do what OCI lets me do... but within that I'll do = -what I -can...

- -

 

- -

I'm not familar with Oracle trace logs so I can't readily = -intrepret -them

- -

and I'll take what you say at face value.

- -

 

- -

But I am familar with DBD::Oracle :) and the logs it writes = -:)

- -

 

- -

> $sth =3D $dbh->prepare(q(select key, fkey, value from t = -where -key=3D?));

- -

> $sth->execute($key);

- -

 

- -

 

- -

    -> prepare for DBD::Oracle::db -(DBI::db=3DHASH(0x8235b34)~0x8235a74 'select key, fkey, value from t = -where -key=3D?')

- -

    dbd_preparse scanned 1 distinct = -placeholders

- -

OCIHandleAlloc(0x82465d8,0x826cae8,OCI_HTYPE_STMT,0,(nil))=3DSUCC= -ESS

- -

OCIStmtPrepare(0x826e4a0,0x82559ec,'select key, fkey, value from = -t -where key=3D:p1',44,1,0)=3DSUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0x826caec,(nil),24,0x82559ec)= -=3DSUCCESS

- -

    dbd_st_prepare'd sql SELECT

- -

    dbd_describe SELECT (EXPLICIT, lb = -80)...

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),16)=3D= -SUCCESS

- -

    dbd_describe'd 3 columns (row bytes: 76 max, = -40 est -avg, cache: 231)

- -

    <- prepare=3D DBI::st=3DHASH(0x8240fe0) at = -ex1.pl -line 50

- -

    -> execute for DBD::Oracle::st -(DBI::st=3DHASH(0x8240fe0)~0x8240fb0 '8542')

- -

OCIBindByName(0x826e4a0,0x826cb5c,0x82559ec,":p1",3,0x8= -26cd78,4,1,0x826cb6e,(nil),0x826cb6c,0,(nil),2)=3DSUCCESS - -

OCIBindDynamic(0x826dc40,0x82559ec,0x826cb40,0x401d9f60,0x826cb40= -,0x401da090)=3DSUCCESS

- -

       bind :p1 done with ftype = -1

- -

    dbd_st_execute SELECT (out0, = -lob0)...

- -

       in  ':p1' [0,0]: = -len  4, -ind 0

- -

OCIStmtExecute(0x82557c4,0x826e4a0,0x82559ec,0,0,(nil),(nil),0)=3D= -SUCCESS

- -

OCIAttrGet(0x826e4a0,OCI_HTYPE_STMT,0xbffff65a,(nil),10,0x82559ec= -)=3DSUCCESS

- -

    dbd_st_execute SELECT returned (SUCCESS, = -rpc0, fn4, -out0)

- -

    <- execute=3D '0E0' at ex1.pl line = -51

- -

 

- -

Given those OCI calls, what is DBD::Oracle doing that it = -shouldn't?

- -

 

- -

I'd guess that it's something to do with the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

call that prepare() does.

- -

 

- -

It doesn't do that for non-select statements so you could check = -if

- -

non-selects also have two parse calls.

- -

 

- -

Also try doing

- -

  $sth =3D $dbh->prepare(q(select key, fkey, value from = -t where -key=3D?), { ora_check_sql=3D> 0 });

- -

 

- -

which refers the OCIStmtExecute(..., OCI_DESCRIBE_ONLY) till = -after the

- -

main OCIStmtExecute(). In that case the OCIStmtExecute(..., -OCI_DESCRIBE_ONLY)

- -

is possibly redundant and could be removed (but Oracle ought to = -detect -that

- -

anyway and not make a round-trip for it, and certainly not call = -parse).

- -

 

- -

If non-selects only have one parse call but = -ora_check_sql=3D>0 doesn't

- -

fix selects, then I might be able to do a simple patch to avoid = -the

- -

OCIStmtExecute(..., OCI_DESCRIBE_ONLY) if = -ora_check_sql=3D>0.

- -

 

- -

Then the issue will be: should ora_check_sql=3D>0 be the = -default...

- -

 

- -

Tim.

- -

 

- -

p.s. I'd love a copy of your book when it's = -ready!

- -
- - - - - -------=_NextPart_000_0194_01C25AB3.6B1FD7D0-- - - -From cary.millsap@hotsos.com Fri Sep 13 21:17:44 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DKHhC12417 - for ; Fri, 13 Sep 2002 21:17:43 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 21:17:43 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031946929:20:18513:70; Fri, 13 Sep 2002 19:55:29 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-2.mail.demon.net - id aa2018248; 13 Sep 2002 19:55 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 7FC402C01F - for ; Fri, 13 Sep 2002 15:55:06 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by dolly1.pobox.com (Postfix) with ESMTP id 76A5E2BFE1 - for ; Fri, 13 Sep 2002 15:55:05 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DJt4n26736 - for ; Fri, 13 Sep 2002 14:55:04 -0500 -From: "Cary Millsap" -To: "Tim Bunce" -Subject: A little more data -Date: Fri, 13 Sep 2002 14:54:56 -0500 -Message-ID: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_NextPart_000_0203_01C25B35.89729F60" -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 4948 -Lines: 166 - -This is a multi-part message in MIME format. - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit - -Tim, - - - -I hope this is helpful. I have noticed that I cannot produce the -extra-parse problem on my 8.1.7 laptop database, no matter what the -setting of ora_check_sql. All of the data I've sent you is from our -8.1.6 Linux database. If you really needed it, I could produce level-9 -DBI trace data from identical tests on both platforms, but I won't spend -the time doing that unless you say it will help... - - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic , Oct 1-3 San -Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -- 2003 Hotsos Symposium on -OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum , Sep -20-22 Middlefart Denmark - - - - -------=_NextPart_000_0203_01C25B35.89729F60 -Content-Type: text/html; - charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - - - - - - - - - - - - - - -
- -

Tim,

- -

 

- -

I hope this is helpful… I have noticed that I = -cannot -produce the extra-parse problem on my 8.1.7 laptop database, no matter = -what the -setting of ora_check_sql. All of the data I’ve sent you is from = -our 8.1.6 -Linux database. If you really needed it, I could produce level-9 DBI = -trace data -from identical tests on both platforms, but I won’t spend the time = -doing -that unless you say it will help...

- -

 

- -

Cary = -Millsap
-Hotsos Enterprises, Ltd.
-http://www.hotsos.com
-
-Upcoming events:
-- Hotsos Clinic, = -Oct -1–3
San Francisco, Oct 15–17 = -Dallas, Dec -9–11 Honolulu
-- 2003 Hotsos = -Symposium on -Oracle® System Performance, Feb 9–12 = -
Dallas
-- Next event: Miracle Database = -Forum, Sep -20–22 Middlefart
Denmark

- -

 

- -
- - - - - -------=_NextPart_000_0203_01C25B35.89729F60-- - - -From timbo@dansat.data-plan.com Fri Sep 13 22:05:30 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL5UC12942 - for ; Fri, 13 Sep 2002 22:05:30 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:05:30 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031948458:10:20432:5; Fri, 13 Sep 2002 20:20:58 GMT -Received: from cali-2.pobox.com ([64.71.166.115]) by punt-1.mail.demon.net - id aa1020174; 13 Sep 2002 20:20 GMT -Received: from cali-2.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-2.pobox.com (Postfix) with ESMTP id 8A60E3E659 - for ; Fri, 13 Sep 2002 16:20:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail05.svc.cra.dublin.eircom.net (mail05.svc.cra.dublin.eircom.net [159.134.118.21]) - by cali-2.pobox.com (Postfix) with SMTP id CAC663E685 - for ; Fri, 13 Sep 2002 16:20:36 -0400 (EDT) -Received: (qmail 37861 messnum 258096 invoked from network[159.134.164.124/p124.as1.limerick1.eircom.net]); 13 Sep 2002 20:20:35 -0000 -Received: from p124.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.124) - by mail05.svc.cra.dublin.eircom.net (qp 37861) with SMTP; 13 Sep 2002 20:20:35 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DKKhu12535; - Fri, 13 Sep 2002 21:20:43 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 21:20:43 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data -Message-ID: <20020913202043.GO539@dansat.data-plan.com> -References: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020201c25b5f$7248a760$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1098 -Lines: 34 - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - -From cary.millsap@hotsos.com Fri Sep 13 22:04:47 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DL4kC12684 - for ; Fri, 13 Sep 2002 22:04:46 +0100 (BST) - (envelope-from cary.millsap@hotsos.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 22:04:46 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031949629:20:13745:23; Fri, 13 Sep 2002 20:40:29 GMT -Received: from cali-1.pobox.com ([64.71.166.114]) by punt-2.mail.demon.net - id aa2013849; 13 Sep 2002 20:40 GMT -Received: from cali-1.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-1.pobox.com (Postfix) with ESMTP id 7D90A3E650 - for ; Fri, 13 Sep 2002 16:40:20 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from www.hotsos.com (unknown [63.145.61.17]) - by cali-1.pobox.com (Postfix) with ESMTP id 785AB3E642 - for ; Fri, 13 Sep 2002 16:40:19 -0400 (EDT) -Received: from CVMLAP01 (66-169-133-3.ftwrth.tx.charter.com [66.169.133.3]) - (authenticated (0 bits)) - by www.hotsos.com (8.11.3/8.11.0) with ESMTP id g8DKeIn27106 - for ; Fri, 13 Sep 2002 15:40:18 -0500 -From: "Cary Millsap" -To: "'Tim Bunce'" -Subject: RE: A little more data -Date: Fri, 13 Sep 2002 15:40:10 -0500 -Message-ID: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook, Build 10.0.3416 -Importance: Normal -In-Reply-To: <20020913202043.GO539@dansat.data-plan.com> -X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 -Status: RO -X-Status: A -Content-Length: 1999 -Lines: 63 - -Well, it's 1.06 on my Windows machine (the most up-to-date version -available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -but interesting that (admitting now that there's a new degree of freedom -running loose amid the test) "the older version performs better than the -newer one." :) That's certainly not a fair statement if the diff between -8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. - - -Cary Millsap -Hotsos Enterprises, Ltd. -http://www.hotsos.com - -Upcoming events: -- Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -Honolulu -- 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -- Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark - - - ------Original Message----- -From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -Sent: Friday, September 13, 2002 3:21 PM -To: Cary Millsap -Cc: Tim Bunce -Subject: Re: A little more data - -If they're using the same version of DBD::Oracle then -the change must me on the sever side. Maybe Oracle's -woken up to the fact they don't need a second parse! - -Tim. - -On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> Tim, -> -> -> -> I hope this is helpful. I have noticed that I cannot produce the -> extra-parse problem on my 8.1.7 laptop database, no matter what the -> setting of ora_check_sql. All of the data I've sent you is from our -> 8.1.6 Linux database. If you really needed it, I could produce level-9 -> DBI trace data from identical tests on both platforms, but I won't -spend -> the time doing that unless you say it will help... -> -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic , Oct 1-3 San -> Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> - 2003 Hotsos Symposium on -> OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum , Sep -> 20-22 Middlefart Denmark -> -> -> - - -From timbo@dansat.data-plan.com Fri Sep 13 23:21:32 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g8DMLWC13692 - for ; Fri, 13 Sep 2002 23:21:32 +0100 (BST) - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.58] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 13 Sep 2002 23:21:32 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1031952887:10:13297:20; Fri, 13 Sep 2002 21:34:47 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1118141; 13 Sep 2002 21:34 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id C7D482BF23 - for ; Fri, 13 Sep 2002 17:34:38 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from mail00.svc.cra.dublin.eircom.net (mail00.svc.cra.dublin.eircom.net [159.134.118.16]) - by dolly1.pobox.com (Postfix) with SMTP id 8352A2BF6C - for ; Fri, 13 Sep 2002 17:34:36 -0400 (EDT) -Received: (qmail 5093 messnum 521124 invoked from network[159.134.164.134/p134.as1.limerick1.eircom.net]); 13 Sep 2002 21:34:34 -0000 -Received: from p134.as1.limerick1.eircom.net (HELO dansat.data-plan.com) (159.134.164.134) - by mail00.svc.cra.dublin.eircom.net (qp 5093) with SMTP; 13 Sep 2002 21:34:34 -0000 -Received: (from timbo@localhost) - by dansat.data-plan.com (8.11.6/8.11.6) id g8DLYeI13070; - Fri, 13 Sep 2002 22:34:40 +0100 (BST) - (envelope-from timbo) -Date: Fri, 13 Sep 2002 22:34:40 +0100 -From: Tim Bunce -To: Cary Millsap -Cc: "'Tim Bunce'" -Subject: Re: A little more data -Message-ID: <20020913213440.GS539@dansat.data-plan.com> -References: <20020913202043.GO539@dansat.data-plan.com> <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <020d01c25b65$c4056e70$6501a8c0@CVMLAP01> -User-Agent: Mutt/1.4i -Status: O -Content-Length: 2282 -Lines: 69 - -According my RCS the default for ora_check_sql changed from 0 to 1 -around version 1.03. - -Tim. - -On Fri, Sep 13, 2002 at 03:40:10PM -0500, Cary Millsap wrote: -> Well, it's 1.06 on my Windows machine (the most up-to-date version -> available from ActiveState), and 1.12 on Linux. Not exactly a fair test, -> but interesting that (admitting now that there's a new degree of freedom -> running loose amid the test) "the older version performs better than the -> newer one." :) That's certainly not a fair statement if the diff between -> 8.1.6 and 8.1.7 OCI is the root cause of the behavior difference. -> -> -> Cary Millsap -> Hotsos Enterprises, Ltd. -> http://www.hotsos.com -> -> Upcoming events: -> - Hotsos Clinic, Oct 1-3 San Francisco, Oct 15-17 Dallas, Dec 9-11 -> Honolulu -> - 2003 Hotsos Symposium on OracleR System Performance, Feb 9-12 Dallas -> - Next event: Miracle Database Forum, Sep 20-22 Middelfart Denmark -> -> -> -> -----Original Message----- -> From: Tim Bunce [mailto:Tim.Bunce@pobox.com] -> Sent: Friday, September 13, 2002 3:21 PM -> To: Cary Millsap -> Cc: Tim Bunce -> Subject: Re: A little more data -> -> If they're using the same version of DBD::Oracle then -> the change must me on the sever side. Maybe Oracle's -> woken up to the fact they don't need a second parse! -> -> Tim. -> -> On Fri, Sep 13, 2002 at 02:54:56PM -0500, Cary Millsap wrote: -> > Tim, -> > -> > -> > -> > I hope this is helpful. I have noticed that I cannot produce the -> > extra-parse problem on my 8.1.7 laptop database, no matter what the -> > setting of ora_check_sql. All of the data I've sent you is from our -> > 8.1.6 Linux database. If you really needed it, I could produce level-9 -> > DBI trace data from identical tests on both platforms, but I won't -> spend -> > the time doing that unless you say it will help... -> > -> > -> > -> > Cary Millsap -> > Hotsos Enterprises, Ltd. -> > http://www.hotsos.com -> > -> > Upcoming events: -> > - Hotsos Clinic , Oct 1-3 San -> > Francisco, Oct 15-17 Dallas, Dec 9-11 Honolulu -> > - 2003 Hotsos Symposium on -> > OracleR System Performance, Feb 9-12 Dallas -> > - Next event: Miracle Database Forum , Sep -> > 20-22 Middlefart Denmark -> > -> > -> > -> - diff --git a/err_unsorted/err_xml.msg b/err_unsorted/err_xml.msg deleted file mode 100644 index 7a60a0cb..00000000 --- a/err_unsorted/err_xml.msg +++ /dev/null @@ -1,118 +0,0 @@ -From dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org Fri Aug 15 14:41:14 2003 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id h7FDe3MA043557 - for ; Fri, 15 Aug 2003 14:41:13 +0100 (BST) - (envelope-from dbi-users-return-19852-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 15 Aug 2003 14:41:13 +0100 (BST) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 19nc4X-0006LQ-BC; - Fri, 15 Aug 2003 10:44:41 +0000 -Received: from [207.106.49.22] (helo=dolly1.pobox.com) - by punt-3.mail.demon.net with esmtp id 19nc4X-0006LQ-BC - for pobox@dbi.demon.co.uk; Fri, 15 Aug 2003 10:44:41 +0000 -Received: from dolly1.pobox.com (localhost[127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 16F6B21C13B - for ; Fri, 15 Aug 2003 06:44:41 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.develooper.com[63.251.223.166]) - by dolly1.pobox.com (Postfix) with SMTP id 021F121C36F - for ; Fri, 15 Aug 2003 06:44:40 -0400 (EDT) -Received: (qmail 78180 invoked by uid 1005); 15 Aug 2003 10:44:34 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 71287 invoked by uid 76); 15 Aug 2003 10:32:13 -0000 -Delivered-To: dbi-users@perl.org -Received-SPF: unknown (domain of sender andyhassall@yahoo.com does not designate mailers: NXDOMAIN) -Message-ID: <20030815103200.24313.qmail@web9605.mail.yahoo.com> -Date: Fri, 15 Aug 2003 11:32:00 +0100 (BST) -From: =?iso-8859-1?q?Andy=20Hassall?= -Reply-To: andy@andyh.co.uk -Subject: Re: ERROR OCIDefineObject call needed but not implemented yet using XMLElement function -To: Susan Cassidy , dbi-users@perl.org -In-Reply-To: -MIME-Version: 1.0 -Content-Type: text/plain; charset=iso-8859-1 -X-SMTPD: qpsmtpd/0.27-dev, http://develooper.com/code/qpsmtpd/ -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=-0.8 required=7.0 tests=CARRIAGE_RETURNS,IN_REP_TO,QUOTED_EMAIL_TEXT,SPAM_PHRASE_01_02 version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Content-Transfer-Encoding: 8bit -X-MIME-Autoconverted: from quoted-printable to 8bit by dansat.data-plan.com id h7FDe3MA043557 -Status: RO -Content-Length: 2299 -Lines: 65 - - --- Susan Cassidy wrote: > I am using DBD::Oracle. -I was on version 1.12, then I installed version -> 1.14, with the same result. -> -> This is Oracle 9.2.0. -> -> I have this select statement that works fine from SQL*Plus: -> -> select XMLElement("Sequences", -> XMLElement("Sequence", -> XMLATTRIBUTES ( b.local_name AS "ic-acckey", -> b.mol_type AS "molecule", -> n.seq_name AS "title"))) -> from gcg_bioseq b, gcg_annot_seq_name a, gcg_seq_name n -> where -> b.local_name = 'K00306' and -> b.seq_status = 'D' and -> b.seq_oid = a.seq_oid and -> a.seq_name_oid = n.seq_name_oid and -> n.name_type = 'LOCUS' -> -> -> When I run it via DBI/DBD I get this (trace level 2): -> -> DBI 1.32-nothread dispatch trace level set to 2 -> Note: perl is running without the recommended perl -w option -> -> prepare for DBD::Oracle::db (DBI::db=HASH(0x1b2314)~0x122bec ' -[snip -> Field 1 has an Oracle type (108) which is not explicitly supported -> fbh 1: -> -'XMLELEMENT("SEQUENCES",XMLELEMENT("SEQUENCE",XMLATTRIBUTES(B.LOCAL_NAMEAS"IC-ACCKEY",B.MOL_TYPEAS"MOLECULE",N.SEQ_NAMEAS"TITLE")))' -[snip] -> Error: prepare failed -> at line 56, error: ERROR OCIDefineObject call needed but not -> implemented yet -> -> Is there any other workaround for this than wrapping this up in a PL/SQL -> function? - - Don't rely on the implicit conversion to a string type that is done when -SQL*Plus displays an XMLElement; add .getClobVal() to the end of the -statement to retrieve it as a CLOB rather than the XMLElement object type -(which DBD::Oracle doesn't accept). - - i.e. - -select XMLElement("Sequences", - XMLElement("Sequence", - XMLATTRIBUTES ( b.local_name AS "ic-acckey", - b.mol_type AS "molecule", - n.seq_name AS "title"))).getClobVal() - from ... - - (or getStringVal() for a VARCHAR2) - -===== --- -Andy Hassall (andy@andyh.org) icq(5747695) http://www.andyh.co.uk -http://www.andyhsoftware.co.uk/space | disk usage analysis tool - -________________________________________________________________________ -Want to chat instantly with your online friends? Get the FREE Yahoo! -Messenger http://uk.messenger.yahoo.com/ - - diff --git a/err_unsorted/err_xml2.msg b/err_unsorted/err_xml2.msg deleted file mode 100644 index 3bb291c5..00000000 --- a/err_unsorted/err_xml2.msg +++ /dev/null @@ -1,700 +0,0 @@ -From dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org Fri Jan 30 12:50:15 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UClt3q069307 - for ; Fri, 30 Jan 2004 12:50:14 GMT - (envelope-from dbi-dev-return-2935-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 12:50:14 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmWGJ-00057X-AG; - Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [194.217.242.210] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmWGJ-00057X-AG - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:35 +0000 -Received: from [207.8.214.3] (helo=puzzle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmWGI-0007XK-P3 - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 10:52:34 +0000 -Received: from puzzle.pobox.com (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 029E8701C6 - for ; Fri, 30 Jan 2004 05:52:34 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by puzzle.pobox.com (Postfix) with ESMTP id 12ABF701C1 - for ; Fri, 30 Jan 2004 05:52:30 -0500 (EST) -Received: from onion.perl.org (onion.develooper.com [63.251.223.166]) - by puzzle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 05:51:10 -0500 (EST) -Received: (qmail 33345 invoked by uid 1005); 30 Jan 2004 10:50:36 -0000 -Mailing-List: contact dbi-dev-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-dev@perl.org -Received: (qmail 33175 invoked by uid 76); 30 Jan 2004 10:50:26 -0000 -Received: from qmailr@one.develooper.com (HELO ran-out.mx.develooper.com) (64.81.84.115) by onion.perl.org (qpsmtpd/0.26) with SMTP; Fri, 30 Jan 2004 02:50:25 -0800 -Received: (qmail 21117 invoked by uid 225); 30 Jan 2004 10:48:52 -0000 -Delivered-To: dbi-dev@perl.org -Received: (qmail 21080 invoked by uid 507); 30 Jan 2004 10:48:49 -0000 -Received: from [212.89.121.1] (HELO babel.morphochem.de) (212.89.121.1) by one.develooper.com (qpsmtpd/0.27-dev) with ESMTP; Fri, 30 Jan 2004 02:48:46 -0800 -Received: (qmail 31958 invoked from network); 30 Jan 2004 11:50:38 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) by 212.89.121.1 with SMTP; 30 Jan 2004 11:50:38 -0000 -Received: (qmail 6921 invoked from network); 30 Jan 2004 10:49:58 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) (envelope-sender ) by localhost.morphochem.de (qmail-ldap-1.03) with SMTP for ; 30 Jan 2004 10:49:58 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; Fri, 30 Jan 2004 11:49:58 +0100 (CET) -Subject: DBD-Oracle and XMLType -From: Hendrik Fuss -To: "dbi-dev@perl.org" -Content-Type: multipart/mixed; boundary="=-fkyM33WAvQ5xV0uCPeSD" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 11:41:31 +0100 -Message-Id: <1075459292.7305.46.camel@mars> -Mime-Version: 1.0 -X-Spam-Check-By: one.develooper.com -X-Spam-Status: No, hits=0.5 required=7.0 tests=MIME_LONG_LINE_QP,QUOTED_EMAIL_TEXT,SPAM_PHRASE_00_01,TO_ADDRESS_EQ_REAL version=2.44 -X-SMTPD: qpsmtpd/0.26, http://develooper.com/code/qpsmtpd/ -Status: RO -X-Status: A -Content-Length: 8148 -Lines: 302 - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -Hi everyone, - -It's been a while since I last posted here. In September 2003 I was -trying to add support for binding XMLType objects to DBD-Oracle, so that -you could easily insert large (ie >4k) XML data into an XMLType table. - -Unfortunately my employer fired me in October 2003 and in the remaining -time I had to work on other projects, so I wasn't able to complete the -DBD project. Since I won't have access to an oracle database from now -on, I thought the least I can do is to provide my code as it is to the -list. Blame German economy. :-( - -The attached patch (based on DBD-Oracle 1.15) enables you to upload -XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -I added a function dbd_rebind_ph_nty for that purpose. You need to -create that XMLType object first using the C function -createxmlfromstring in xml.c. - -The XMLType object is either created from an OCIString or from a -temporary CLOB depending on the length of the source string. Have a look -at the bottom of ociap.h, all the (undocumented) XMLType functions are -there, and there are also some constants in oci.h. - -I'm not sure if the CLOB code currently works. - -Here is another code fragment: - - my $xml =3D createxml($dbh, 'Test document'); - my $sth =3D $dbh->prepare('INSERT INTO xml_type VALUES (?)'); - $sth->bind_param(1, $xml, { ora_type =3D> 108 }); # SQLT_NTY - $sth->execute(); - -Please note that this code is really just early development, which I -wouldn't publish under normal circumstances. :) I just hope it might me -useful to someone. - -Well then, time to say goodbye -thanks to Tim and everyone who contributed to dbi for a great piece of -software - -Cheers, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Description: -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - -151a152 -> case 108: /* SQLT_NTY */ -992a994,996 -> case SQL_UDT: -> return 108; /* Oracle NTY */ ->=20 -1004a1009,1072 -> static int -> dbd_rebind_ph_nty(sth, imp_sth, phs) -> SV* sth; -> imp_sth_t *imp_sth; -> phs_t *phs; -> { -> OCIType *tdo =3D NULL; -> sword status; -> SV* ptr; ->=20 -> if (phs->is_inout) -> croak("OUT binding for NTY is currently unsupported"); ->=20 -> /* ensure that the value is a support named object type */ -> /* (currently only OCIXMLType*) */ -> if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -> OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -> (CONST text*)"SYS", 3, -> (CONST text*)"XMLTYPE", 7, -> (CONST text*)0, 0, -> OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -> &tdo); ->=20 -> ptr =3D SvRV(phs->sv); -> phs->progv =3D (void*) SvIV(ptr); -> phs->maxlen =3D sizeof(OCIXMLType*); -> } -> else -> croak("Unsupported named object type for bind parameter"); ->=20 ->=20 -> /* bind by name */ ->=20 -> OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -> (text*)phs->name, (sb4)strlen(phs->name), -> (dvoid *) NULL, /* value supplied in BindObject later */ -> 0, -> (ub2)phs->ftype, 0, -> NULL, -> 0, 0, -> NULL, -> (ub4)OCI_DEFAULT, -> status -> ); ->=20 -> if (status !=3D OCI_SUCCESS) { -> oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -> return 0; -> } -> if (DBIS->debug >=3D 3) -> PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); ->=20 ->=20 -> /* bind the object */ ->=20 -> OCIBindObject(phs->bndhp, imp_sth->errhp, -> (CONST OCIType*)tdo, -> (dvoid **)&phs->progv, -> (ub4*)NULL, -> (dvoid **)NULL, -> (ub4*)NULL); ->=20 -> return 2; -> } -1309a1378,1380 -> case 108: -> done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -> break; -1331c1403 -< int at_exec =3D (phs->desc_h =3D=3D NULL); ---- -> int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); -1419c1491 -< if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) ---- -> if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQL= -T_NTY)) -1420a1493 -> /* ref allowed for OCIXMLType* */ -2219a2293 -> case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - ---=-fkyM33WAvQ5xV0uCPeSD -Content-Disposition: attachment; filename=xml.c -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; name=xml.c; charset=ISO-8859-1 - -#include "oci.h" -#include - -/* This helper function creates an XMLType object from a string source. - * - * The resulting object can be bound to a placeholder, if ora_type =3D> - * SQLT_NTY is specified. - */ - -static void checkerr(errhp, status) -OCIError *errhp; -sword status; -{ - text errbuf[512]; - ub4 buflen; - sb4 errcode; - - switch (status) - { - case OCI_SUCCESS: - break; - case OCI_SUCCESS_WITH_INFO: - printf("Error - OCI_SUCCESS_WITH_INFO\n"); - break; - case OCI_NEED_DATA: - printf("Error - OCI_NEED_DATA\n"); - break; - case OCI_NO_DATA: - printf("Error - OCI_NO_DATA\n"); - break; - case OCI_ERROR: - OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, - errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR); - printf("Error - %s\n", errbuf); - exit(1); - break; - case OCI_INVALID_HANDLE: - printf("Error - OCI_INVALID_HANDLE\n"); - break; - case OCI_STILL_EXECUTING: - printf("Error - OCI_STILL_EXECUTE\n"); - break; - case OCI_CONTINUE: - printf("Error - OCI_CONTINUE\n"); - break; - default: - break; - } -} - - -#define MAX_OCISTRING_LEN 32766 - -SV* createxmlfromstring(SV* dbh, char* source) { - OCIXMLType *xml =3D NULL; - ub4 len; - ub1 src_type; - dvoid* src_ptr =3D NULL; - D_imp_dbh(dbh); - SV* sv_dest; - - len =3D strlen(source); - if(len > MAX_OCISTRING_LEN) { - src_type =3D OCI_XMLTYPE_CREATE_CLOB; - - printf("OCIDescriptorAlloc\n"); - checkerr( imp_dbh->errhp, - OCIDescriptorAlloc((dvoid*)imp_dbh->envhp, - (dvoid **)&src_ptr, - (ub4)OCI_DTYPE_LOB, - (size_t)0, - (dvoid**)0) ); - - printf("OCILobCreateTemporary\n"); - checkerr( imp_dbh->errhp, - OCILobCreateTemporary(imp_dbh->svchp, - imp_dbh->errhp,=20 - (OCILobLocator*) src_ptr, - (ub2)0,=20 - SQLCS_IMPLICIT,=20 - OCI_TEMP_CLOB,=20 - OCI_ATTR_NOCACHE,=20 - OCI_DURATION_SESSION) ); - - printf("OCILobWrite\n"); - checkerr (imp_dbh->errhp, - OCILobWriteAppend(imp_dbh->svchp, - imp_dbh->errhp, - (OCILobLocator*) src_ptr, - &len,=20 - (ub1*)source, - len, - OCI_ONE_PIECE, - (dvoid *)0,=20 - (sb4 (*)(dvoid*,dvoid*,ub4*,ub1 *))0, - 0, - SQLCS_IMPLICIT)); - - } else { - src_type =3D OCI_XMLTYPE_CREATE_OCISTRING; - - printf("OCIStringAssignText\n"); - checkerr( imp_dbh->errhp, - OCIStringAssignText(imp_dbh->envhp, - imp_dbh->errhp,=20 - (CONST text*) source,=20 - (ub2) strlen(source), - (OCIString **) &src_ptr) - ); - } - - printf("OCIXMLTypeCreateFromSrc\n"); - checkerr( imp_dbh->errhp, - OCIXMLTypeCreateFromSrc(imp_dbh->svchp, - imp_dbh->errhp, - (OCIDuration)OCI_DURATION_CALLOUT, - (ub1)src_type, - (dvoid *)src_ptr, - (sb4)OCI_IND_NOTNULL, - &xml) - ); - - - /* free temporary resources */ - if( src_type =3D=3D OCI_XMLTYPE_CREATE_CLOB ) { - checkerr( imp_dbh->errhp, - OCILobFreeTemporary(imp_dbh->svchp, imp_dbh->errhp, - (OCILobLocator*) src_ptr) ); - - checkerr( imp_dbh->errhp, - OCIDescriptorFree((dvoid *) src_ptr, (ub4) OCI_DTYPE_LOB) ); - } - - - sv_dest =3D newSViv(0); - sv_setref_pv(sv_dest, "OCIXMLTypePtr", xml); - return sv_dest; -} - ---=-fkyM33WAvQ5xV0uCPeSD-- - - - -From hendrik.fuss@morphochem.de Fri Jan 30 16:56:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UGsO3v071338 - for ; Fri, 30 Jan 2004 16:56:27 GMT - (envelope-from hendrik.fuss@morphochem.de) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 16:56:27 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmZJF-0001wN-DK; - Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [194.217.242.211] (helo=lon1-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmZJF-0001wN-DK - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:49 +0000 -Received: from [208.58.1.193] (helo=boggle.pobox.com) - by lon1-hub.mail.demon.net with esmtp id 1AmZJE-0003GM-Bm - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 14:07:48 +0000 -Received: from boggle.pobox.com (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id 334DE30C57 - for ; Fri, 30 Jan 2004 09:07:47 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by boggle.pobox.com (Postfix) with ESMTP id E65B230C2C - for ; Fri, 30 Jan 2004 09:07:45 -0500 (EST) -Received: from babel.morphochem.de (unknown [212.89.121.1]) - by boggle.pobox.com (Postfix) with ESMTP - for ; Fri, 30 Jan 2004 09:07:04 -0500 (EST) -Received: (qmail 29768 invoked from network); 30 Jan 2004 15:10:09 -0000 -Received: from unknown (HELO mail.morphochem.de) (10.1.15.5) - by 212.89.121.1 with SMTP; 30 Jan 2004 15:10:09 -0000 -Received: (qmail 11736 invoked from network); 30 Jan 2004 14:09:30 -0000 -Received: from localhost.morphochem.de (HELO mail) ([127.0.0.1]) - (envelope-sender ) - by localhost.morphochem.de (qmail-ldap-1.03) with SMTP - for ; 30 Jan 2004 14:09:30 -0000 -Received: from mars.MORPHOCHEM.de ([10.1.8.130]) - by mail.morphochem.de (MailMonitor for SMTP v1.2.1 ) ; - Fri, 30 Jan 2004 15:09:30 +0100 (CET) -Subject: Re: DBD-Oracle and XMLType -From: Hendrik Fuss -To: Tim Bunce -Cc: "dbi-dev@perl.org" -In-Reply-To: <20040130133443.GC70215@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> - <20040130133443.GC70215@dansat.data-plan.com> -Content-Type: multipart/mixed; boundary="=-Sq1IOPDEhKoqxUKefiS3" -X-Mailer: Ximian Evolution 1.0.8 -Date: 30 Jan 2004 15:01:03 +0100 -Message-Id: <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Status: RO -X-Status: A -Content-Length: 5585 -Lines: 196 - - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -> > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.= -c -> > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > create that XMLType object first using the C function -> > createxmlfromstring in xml.c. ->=20 -> I there any chance you could post that as a context diff (diff -u ideally -> or else diff -c)? It's much safer and more useful. Thanks. - -Good idea. Here's a diff -u of dbdimp.c. - -By the way: I have thougt about general support of named types, not just -XMLType, but you need to get the type description (TDO) from somewhere. -My code just checks if the perl variable is a blessed reference of -"OCIXMLTypePtr". - -Also note that my code can't handle downloading of XMLType objects yet. - -best wishes, -Hendrik - ---=20 -hendrik fu=DF - -morphochem AG -gmunder str. 37-37a -81379 muenchen - -tel. ++49-89-78005-0 -fax ++49-89-78005-555 - -hendrik.fuss@morphochem.de -http://www.morphochem.de - ---=-Sq1IOPDEhKoqxUKefiS3 -Content-Description: Context diff for dbdimp.c -Content-Disposition: attachment; filename=dbdimp.c.diff -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=ISO-8859-1 - ---- dbdimp.c.orig 2004-01-30 14:48:55.000000000 +0100 -+++ dbdimp.c 2003-10-07 12:17:17.000000000 +0200 -@@ -1,5 +1,5 @@ - /* -- $Id: dbdimp.c,v 1.1.1.1 2003/10/02 10:45:20 hfuss Exp $ -+ $Id: dbdimp.c,v 1.3 2003/10/07 10:17:17 hfuss Exp $ -=20 - Copyright (c) 1994,1995,1996,1997,1998 Tim Bunce -=20 -@@ -149,6 +149,7 @@ - case 97: /* CHARZ */ - case 106: /* MLSLABEL */ - case 102: /* SQLT_CUR OCI 7 cursor variable */ -+ case 108: /* SQLT_NTY */ - case 112: /* SQLT_CLOB / long */ - case 113: /* SQLT_BLOB / long */ - case 116: /* SQLT_RSET OCI 8 cursor variable */ -@@ -990,6 +991,9 @@ - case SQL_LONGVARCHAR: - return 8; /* Oracle LONG */ -=20 -+ case SQL_UDT: -+ return 108; /* Oracle NTY */ -+ - case SQL_DATE: - case SQL_TIME: - case SQL_TIMESTAMP: -@@ -1002,6 +1006,70 @@ - } -=20 -=20 -+static int -+dbd_rebind_ph_nty(sth, imp_sth, phs) -+ SV* sth; -+ imp_sth_t *imp_sth; -+ phs_t *phs; -+{ -+ OCIType *tdo =3D NULL; -+ sword status; -+ SV* ptr; -+ -+ if (phs->is_inout) -+ croak("OUT binding for NTY is currently unsupported"); -+ -+ /* ensure that the value is a support named object type */ -+ /* (currently only OCIXMLType*) */ -+ if ( sv_isa(phs->sv, "OCIXMLTypePtr") ) { -+ OCITypeByName(imp_sth->envhp, imp_sth->errhp, imp_sth->svchp, -+ (CONST text*)"SYS", 3, -+ (CONST text*)"XMLTYPE", 7, -+ (CONST text*)0, 0, -+ OCI_DURATION_CALLOUT, OCI_TYPEGET_HEADER, -+ &tdo); -+ -+ ptr =3D SvRV(phs->sv); -+ phs->progv =3D (void*) SvIV(ptr); -+ phs->maxlen =3D sizeof(OCIXMLType*); -+ } -+ else -+ croak("Unsupported named object type for bind parameter"); -+ -+ -+ /* bind by name */ -+ -+ OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, -+ (text*)phs->name, (sb4)strlen(phs->name), -+ (dvoid *) NULL, /* value supplied in BindObject later */ -+ 0, -+ (ub2)phs->ftype, 0, -+ NULL, -+ 0, 0, -+ NULL, -+ (ub4)OCI_DEFAULT, -+ status -+ ); -+ -+ if (status !=3D OCI_SUCCESS) { -+ oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_NTY"); -+ return 0; -+ } -+ if (DBIS->debug >=3D 3) -+ PerlIO_printf(DBILOGFP, " pp_rebind_ph_nty: END\n"); -+ -+ -+ /* bind the object */ -+ -+ OCIBindObject(phs->bndhp, imp_sth->errhp, -+ (CONST OCIType*)tdo, -+ (dvoid **)&phs->progv, -+ (ub4*)NULL, -+ (dvoid **)NULL, -+ (ub4*)NULL); -+ -+ return 2; -+} -=20 - static int=20 - dbd_rebind_ph_char(sth, imp_sth, phs, alen_ptr_ptr)=20 -@@ -1307,6 +1375,9 @@ - case SQLT_RSET: - done =3D dbd_rebind_ph_rset(sth, imp_sth, phs); - break; -+ case 108: -+ done =3D dbd_rebind_ph_nty(sth, imp_sth, phs); -+ break; - #else - case 102: /* SQLT_CUR */ - done =3D dbd_rebind_ph_cursor(sth, imp_sth, phs); -@@ -1315,6 +1386,7 @@ - default: - done =3D dbd_rebind_ph_char(sth, imp_sth, phs, &alen_ptr); - } -+ - if (done !=3D 1) { - if (done =3D=3D 2) { /* the rebind did the OCI bind call itself successfu= -lly */ - if (DBIS->debug >=3D 3) -@@ -1328,7 +1400,7 @@ - #ifdef OCI_V8_SYNTAX - if (phs->maxlen > phs->maxlen_bound) { - sword status; -- int at_exec =3D (phs->desc_h =3D=3D NULL); -+ int at_exec =3D (phs->desc_h =3D=3D NULL) && (phs->ftype !=3D 108); - OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, (sb4)strlen(phs->name), - phs->progv, -@@ -1416,8 +1488,9 @@ - } - assert(name !=3D Nullch); -=20 -- if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) -+ if (SvROK(newvalue) && (!IS_DBI_HANDLE(newvalue)) && (sql_type!=3DSQLT= -_NTY)) - /* dbi handle allowed for cursor variables */ -+ /* ref allowed for OCIXMLType* */ - croak("Can't bind a reference (%s)", neatsvpv(newvalue,0)); - if (SvTYPE(newvalue) > SVt_PVLV) /* hook for later array logic? */ - croak("Can't bind a non-scalar value (%s)", neatsvpv(newvalue,0)); -@@ -2217,6 +2290,7 @@ - #ifdef OCI_V8_SYNTAX - case SQLT_CLOB: sql_fbh.dbtype =3D SQL_CLOB; break; - case SQLT_BLOB: sql_fbh.dbtype =3D SQL_BLOB; break; -+ case SQLT_NTY: sql_fbh.dbtype =3D SQL_UDT; break; - #endif - #ifdef SQLT_TIMESTAMP_TZ - case SQLT_TIMESTAMP_TZ: sql_fbh.dbtype =3D SQL_TIMESTAMP; break; - ---=-Sq1IOPDEhKoqxUKefiS3-- - - - -From timbo@dansat.data-plan.com Fri Jan 30 18:32:30 2004 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UIVK3f073353 - for ; Fri, 30 Jan 2004 18:32:30 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: from pop3.mail.demon.net [194.217.242.253] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Fri, 30 Jan 2004 18:32:30 +0000 (GMT) -Received: from punt-3.mail.demon.net by mailstore - for pobox@dbi.demon.co.uk id 1AmceP-000603-GP; - Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [194.217.242.71] (helo=anchor-hub.mail.demon.net) - by punt-3.mail.demon.net with esmtp id 1AmceP-000603-GP - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:53 +0000 -Received: from [208.210.124.73] (helo=icicle.pobox.com) - by anchor-hub.mail.demon.net with esmtp id 1AmceO-0006dQ-DB - for pobox@dbi.demon.co.uk; Fri, 30 Jan 2004 17:41:52 +0000 -Received: from icicle.pobox.com (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 25AEA3F13D - for ; Fri, 30 Jan 2004 12:41:51 -0500 (EST) -Delivered-To: tim.bunce@pobox.com -Received: from colander (localhost [127.0.0.1]) - by icicle.pobox.com (Postfix) with ESMTP id 9FB863F16E - for ; Fri, 30 Jan 2004 12:41:49 -0500 (EST) -Received: from mail09.svc.cra.dublin.eircom.net (mail09.svc.cra.dublin.eircom.net [159.134.118.25]) - by icicle.pobox.com (Postfix) with SMTP - for ; Fri, 30 Jan 2004 12:41:11 -0500 (EST) -Received: (qmail 9504 messnum 226571 invoked from network[213.94.228.233/unknown]); 30 Jan 2004 17:40:43 -0000 -Received: from unknown (HELO dansat.data-plan.com) (213.94.228.233) - by mail09.svc.cra.dublin.eircom.net (qp 9504) with SMTP; 30 Jan 2004 17:40:43 -0000 -Received: from dansat.data-plan.com (localhost [127.0.0.1]) - by dansat.data-plan.com (8.12.9/8.12.9) with ESMTP id i0UHf33A072739; - Fri, 30 Jan 2004 17:41:03 GMT - (envelope-from timbo@dansat.data-plan.com) -Received: (from timbo@localhost) - by dansat.data-plan.com (8.12.9/8.12.9/Submit) id i0UHf2Wr072738; - Fri, 30 Jan 2004 17:41:02 GMT -Date: Fri, 30 Jan 2004 17:41:02 +0000 -From: Tim Bunce -To: Hendrik Fuss -Cc: Tim Bunce , "dbi-dev@perl.org" -Subject: Re: DBD-Oracle and XMLType -Message-ID: <20040130174102.GB72657@dansat.data-plan.com> -References: <1075459292.7305.46.camel@mars> <20040130133443.GC70215@dansat.data-plan.com> <1075471263.7305.73.camel@mars> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <1075471263.7305.73.camel@mars> -User-Agent: Mutt/1.4i -Status: RO -Content-Length: 1129 -Lines: 29 - -On Fri, Jan 30, 2004 at 03:01:03PM +0100, Hendrik Fuss wrote: -> > > The attached patch (based on DBD-Oracle 1.15) enables you to upload -> > > XMLType objects (OCIXMLTypePtr) by binding them as SQLT_NTY. In dbdimp.c -> > > I added a function dbd_rebind_ph_nty for that purpose. You need to -> > > create that XMLType object first using the C function -> > > createxmlfromstring in xml.c. -> > -> > I there any chance you could post that as a context diff (diff -u ideally -> > or else diff -c)? It's much safer and more useful. Thanks. -> -> Good idea. Here's a diff -u of dbdimp.c. - -Thanks. - -> By the way: I have thougt about general support of named types, not just -> XMLType, but you need to get the type description (TDO) from somewhere. -> My code just checks if the perl variable is a blessed reference of -> "OCIXMLTypePtr". - -Doing the equivalent of m/^OCI(\w+)Ptr$/ and then calling OCITypeByName -with $1 uppercased might take us (or someone) a step further. - -> Also note that my code can't handle downloading of XMLType objects yet. - -I'll trust that some kind soul with an itch will send a patch :-) - -Thanks again Hendrik. - -Tim. - diff --git a/err_unsorted/err_xmltypebindplsql.msg b/err_unsorted/err_xmltypebindplsql.msg deleted file mode 100644 index 08faa725..00000000 --- a/err_unsorted/err_xmltypebindplsql.msg +++ /dev/null @@ -1,174 +0,0 @@ -From dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org Thu Apr 25 11:02:42 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g3PA2gK34525 - for ; Thu, 25 Apr 2002 11:02:42 +0100 (BST) - (envelope-from dbi-users-return-11068-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.21] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Thu, 25 Apr 2002 11:02:42 +0100 (BST) -Received: from punt-1.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1019721492:10:18778:60; Thu, 25 Apr 2002 07:58:12 GMT -Received: from dolly1.pobox.com ([207.106.49.22]) by punt-1.mail.demon.net - id aa1109782; 25 Apr 2002 7:58 GMT -Received: from dolly1.pobox.com (localhost.localdomain [127.0.0.1]) - by dolly1.pobox.com (Postfix) with ESMTP id 791692BF11 - for ; Thu, 25 Apr 2002 03:58:08 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by dolly1.pobox.com (Postfix) with SMTP id 976FB2BEE4 - for ; Thu, 25 Apr 2002 03:58:07 -0400 (EDT) -Received: (qmail 84467 invoked by uid 1005); 25 Apr 2002 07:58:05 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 77923 invoked by uid 76); 24 Apr 2002 23:08:56 -0000 -Date: Wed, 24 Apr 2002 19:08:54 -0400 -From: Mark Stillwell -To: dbi-users-help@perl.org, dbi-users@perl.org -Subject: Oracle 9 XMLTYPE insert -Message-ID: <20020424190852.C22854@byrd.biostat.ufl.edu> -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.2.5.1i -Status: RO -Content-Length: 1469 -Lines: 43 - -I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -Here is my problem, I have a table named 'test' with three fields: eid -(integer), x (SYS.XMLTYPE) and formname (text) - -I create a database handler and connect to the database just fine. - -I create a new statement handler with the following command: - -$sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -SYS.XMLTYPE.CREATEXML(?), ?"); - -I loop over some data, $eid gets and integer, $xmlvalue gets a string, -and $formname gets a string. So long as $xmlvalue is relatively short -$sth->execute($eid, $xmlvalue, $formname); works great, but as soon as -it becomes long enough to force the use of clob's I have a problem. - -So I tried the following: - -$sth->bind_param(1, $i); -$sth->bind_param(2, $xmlvalue, { ora_type => ORA_CLOB }); -$sth->bind_param(3, $intable); -$sth->execute; - -This works great if column 'x' is a normal CLOB and I omit the -sys.xmltype.createxml statement above, but when 'x' is of type -sys.xmltype I get the following error: - -nvalid LOB locator specified -ORA-06512: at "SYS.XMLTYPE", line 0 - -Right now I've hacked the setup so there is a supplemental table called -'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE test SET x -= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem like the -right way to do this. - -Is there any way to do what I want in the current version of -DBI/OracleDBD? - --- -Mark Stillwell -marklee@ufl.edu -http://plaza.ufl.edu/marklee/ - -From dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org Wed May 8 16:11:46 2002 -Received: from localhost (localhost [127.0.0.1]) - by dansat.data-plan.com (8.11.6/8.11.6) with ESMTP id g48FBjo24814 - for ; Wed, 8 May 2002 16:11:45 +0100 (BST) - (envelope-from dbi-users-return-11340-Tim.Bunce=pobox.com@perl.org) -Received: from pop3.mail.demon.net [194.217.242.59] - by localhost with POP3 (fetchmail-5.8.5) - for timbo@localhost (single-drop); Wed, 08 May 2002 16:11:45 +0100 (BST) -Received: from punt-2.mail.demon.net by mailstore for Tim.Bunce@data-plan.com - id 1020870336:20:08175:2; Wed, 08 May 2002 15:05:36 GMT -Received: from cali-3.pobox.com ([64.71.166.116]) by punt-2.mail.demon.net - id aa2109147; 8 May 2002 15:05 GMT -Received: from cali-3.pobox.com (localhost.localdomain [127.0.0.1]) - by cali-3.pobox.com (Postfix) with ESMTP id 68FE23E6D4 - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Delivered-To: tim.bunce@pobox.com -Received: from onion.perl.org (onion.valueclick.com [209.85.157.220]) - by cali-3.pobox.com (Postfix) with SMTP id 33A783E64D - for ; Wed, 8 May 2002 11:01:49 -0400 (EDT) -Received: (qmail 65232 invoked by uid 1005); 8 May 2002 15:01:47 -0000 -Mailing-List: contact dbi-users-help@perl.org; run by ezmlm -Precedence: bulk -List-Post: -List-Help: -List-Unsubscribe: -List-Subscribe: -Delivered-To: mailing list dbi-users@perl.org -Delivered-To: moderator for dbi-users@perl.org -Received: (qmail 60079 invoked by uid 76); 8 May 2002 14:50:53 -0000 -From: "Ben Middleton" -To: -Cc: -Subject: Re: Oracle 9 XMLTYPE insert -Date: Wed, 8 May 2002 15:50:47 +0100 -Message-ID: -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -X-Priority: 3 (Normal) -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0) -Importance: Normal -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -Status: RO -Content-Length: 1311 -Lines: 39 - -Hi. - -Not sure if you ever resolved this: - -> I'm using DBI 1.21 and DBD 1.12 with an oracle9i database backend. - -> Here is my problem, I have a table named 'test' with three fields: -> eid (integer), x (SYS.XMLTYPE) and formname (text) - -> I create a new statement handler with the following command: - -> $sth = $dbh->prepare("INSERT INTO test (eid, x, formname) VALUES (?, -> SYS.XMLTYPE.CREATEXML(?), ?"); - -.... - -> Invalid LOB locator specified -> ORA-06512: at "SYS.XMLTYPE", line 0 - -> Right now I've hacked the setup so there is a supplemental table -> called 'y' of type CLOB that I submit to, then I do $dbh->do("UPDATE -> test SET x= SYS.XMLTYPE.CREATEXML(y)");, which works but doesn't seem -> like the right way to do this. - -> Is there any way to do what I want in the current version of -> DBI/OracleDBD? - -I don't think that the current DBI/DBD can bind a CLOB to a PL/SQL function -(which is all the CREATEXML function is) - hence you will have to go with -the intermediate CLOB table solution. - -Incidentally, if you are using Oracle9i - have you tried using a TEMPORARY -TABLE with a CLOB column (see SQL Reference Guide)? If setup correctly, this -is automatically truncated at the end of a transaction, is managed by the -Server, and provides some efficiency benefits. We use this here quite -effectively. - -Ben. - - diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 835d42c8..8177d628 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -11,6 +11,12 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; +{ + $DBD::Oracle::VERSION = '1.43_00'; +} +BEGIN { + $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Oracle database driver for the DBI module use DBI (); @@ -117,7 +123,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::dr; # ====== DRIVER ====== +{ package DBD::Oracle::dr; +{ + $DBD::Oracle::dr::VERSION = '1.43_00'; +} +BEGIN { + $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DRIVER ====== use strict; my %dbnames = (); # holds list of known databases (oratab + tnsnames) @@ -316,7 +328,13 @@ package DBD::Oracle; } -{ package DBD::Oracle::db; # ====== DATABASE ====== +{ package DBD::Oracle::db; +{ + $DBD::Oracle::db::VERSION = '1.43_00'; +} +BEGIN { + $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== DATABASE ====== use strict; use DBI qw(:sql_types); @@ -1039,7 +1057,13 @@ SQL } # end of package DBD::Oracle::db -{ package DBD::Oracle::st; # ====== STATEMENT ====== +{ package DBD::Oracle::st; +{ + $DBD::Oracle::st::VERSION = '1.43_00'; +} +BEGIN { + $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; +} # ====== STATEMENT ====== sub bind_param_inout_array { @@ -1130,9 +1154,18 @@ SQL 1; -__END__ +=pod + +=head1 NAME + +DBD::Oracle - Oracle database driver for the DBI module + +=head1 VERSION + +version 1.43_00 + =head1 SYNOPSIS use DBI; @@ -1146,7 +1179,6 @@ __END__ # for some advanced uses you may need Oracle type values: use DBD::Oracle qw(:ora_types); - =head1 DESCRIPTION DBD::Oracle is a Perl module which works with the DBI module to provide @@ -1254,7 +1286,6 @@ If port name is not specified, 1521 is the default. If service name is not speci The following examples show several ways a connection can be created: - $dbh = DBI->connect('dbi:Oracle:DB','username','password'); $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); @@ -1585,7 +1616,6 @@ DBDOxxxx where xxxx is the current version number. This value can be retrieved on the server side using V$SESSION_CONNECT_INFO or GV$SESSION_CONNECT_INFO - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); $dbh->{ora_driver_name} = $q; @@ -1756,7 +1786,6 @@ If the previous error was from a failed C due to a syntax error, this attribute gives the offset into the C attribute where the error was found. - =head4 ora_array_chunk_size Due to OCI limitations, DBD::Oracle needs to buffer up rows of @@ -1979,7 +2008,6 @@ DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. Starts a new session against the current database using the credentials supplied. - =head2 B $hashref = $dbh->private_attribute_info(); @@ -2112,7 +2140,6 @@ DBI currently defaults this to 80. Implemented by DBI, no driver-specific impact. - =head2 B Type: boolean, inherited @@ -2121,7 +2148,6 @@ The CompatMode attribute is used by emulation layers (such as Oraperl) to enable It also has the effect of disabling the 'quick FETCH' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own FETCH method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. - =head1 ORACLE-SPECIFIC DATABASE HANDLE METHODS =head2 B @@ -2296,7 +2322,6 @@ The different types of placeholders cannot be mixed within a statement, but you use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. - =head2 B $sth = $dbh->prepare_cached($statement, \%attr); @@ -2315,7 +2340,6 @@ query was successful, returns undef if an error occurred, and returns -1 if the number of rows is unknown or not available. Note that this method will return B<0E0> instead of 0 for 'no rows were affected', in order to always return a true value if no error occurred. - =head2 B Oracle does not implement auto_increment of serial type columns it uses predefined @@ -2371,7 +2395,6 @@ If the script exits before disconnect is called (or, more precisely, if the data referenced by anything), then the database handle's DESTROY method will call the rollback() and disconnect() methods automatically. It is best to explicitly disconnect rather than rely on this behavior. - =head2 B $rv = $dbh->ping; @@ -2724,7 +2747,6 @@ Examples: ## This executes the statement with 567 (integer) and "Zool" (varchar) $sth->execute(); - These attributes may be used in the C<\%attr> parameter of the L or L statement handle methods. @@ -2819,10 +2841,8 @@ Set L to 0 in prepare() to enable this behaviour. $rv = $sth->bind_param_inout($param_num, \$scalar, 0); - DBD::Oracle fully supports bind_param_inout below are some uses for this method. - =head3 B Oracle supports an extended SQL insert syntax which will return one @@ -2996,10 +3016,6 @@ the above example, the code would look something like this : ... } - - - - =head3 B DBD::Oracle has built-in support for B @@ -3034,13 +3050,11 @@ and B datatypes. The simple example is here: =item B -=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' +=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' will only take a reference to a scalar. =back - - =head3 B SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. @@ -3149,7 +3163,6 @@ you get: DBD::Oracle supports this undocumented feature of DBI. See L for an example. - =head2 B $rv = $sth->bind_param_array($param_num, $array_ref_or_value) @@ -3159,8 +3172,6 @@ DBD::Oracle supports this undocumented feature of DBI. See L method. - - =head2 B $rv = $sth->execute(@bind_values); @@ -3427,7 +3438,6 @@ However, LOBSs, CLOBSs, and BLOBs do work as do all the regular bind, and fetch Only use scrollable cursors if you really have a good reason to. They do use up considerable more server and client resources and have poorer response times than non-scrolling cursors. - =head2 Enabling Scrollable Cursors To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; @@ -3443,7 +3453,6 @@ When the statement is executed you will then be able to use 'ora_fetch_scroll' m or you can still use any of the other fetch methods but with a poorer response time than if you used a non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. - =head2 Scrollable Cursor Methods The following driver-specific methods are used with scrollable cursors. @@ -3783,7 +3792,6 @@ You can tune this value by setting ora_oci_success_warn which will display the f In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. - =head3 Simple Fetch for CLOBs and BLOBs To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well @@ -4185,7 +4193,6 @@ Uses the Oracle OCILobTrim function. Returns the length of the LOB. Uses the Oracle OCILobGetLength function. - =item ora_lob_is_init $is_init = $dbh->ora_lob_is_init($lob_locator); @@ -4232,7 +4239,6 @@ lob_id field values, defined as follows: CREATE SEQUENCE lob_example_seq - =head3 Example: Inserting a new row with large data Unless enough memory is available to store and bind the @@ -4298,7 +4304,6 @@ can't be used effectively if AutoCommit is enabled). $offset += $length; } - In this example we demonstrate the use of ora_lob_write() interactively to append data to the columns 'bin_data' and 'char_data'. Had we used ora_lob_append(), we could have @@ -4315,7 +4320,6 @@ The scalar variables $offset and $length are no longer needed, because ora_lob_append() keeps track of the offset for us. - =head3 Example: Updating an existing row with large data In this example, we demonstrate a technique for overwriting @@ -4500,7 +4504,6 @@ WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle other than US7ASCII, requires that the NLS_LANG environment variable be set. See the L<"Oracle UTF8 is not UTF-8"> section below. - You are strongly urged to read the Oracle Internationalization documentation specifically with respect the choices and trade offs for creating a databases for use with international character sets. @@ -4607,7 +4610,6 @@ If the C attribute is given to bind_param() then that determines if the value should be assumed to be in the default (NLS_LANG) or NCHAR (NLS_NCHAR) client character set. - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); ... $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); @@ -4648,7 +4650,6 @@ and TABLE in any combination. Support is seamless and recursive, meaning you need only supply a simple SQL statement to get all the values in an embedded object. You can either get the values as an array of scalars or they can be returned into a DBD::Oracle::Object. - Array example, given this type and table; CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); @@ -4801,7 +4802,6 @@ There are some types, like BOOLEAN, that Oracle does not automatically convert to or from strings (pity). These need to be converted explicitly using SQL or PL/SQL functions. - Examples: # DATE values @@ -4856,7 +4856,6 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" - =head4 Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special @@ -5004,7 +5003,6 @@ shows: } } - The cursor returned by the function C defined in the previous section can be fetched as a nested cursor as follows: @@ -5385,7 +5383,6 @@ There is a known problem with the 11.2g Oracle client and the C PL/SQL function. See L for the details. - =head1 SEE ALSO =over @@ -5453,4 +5450,34 @@ The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. The DBD::Oracle module is free open source software; you can redistribute it and/or modify it under the same terms as Perl 5. +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + + +__END__ + + diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index edacde25..77da0d47 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,4 +1,10 @@ package DBD::Oracle::GetInfo; +{ + $DBD::Oracle::GetInfo::VERSION = '1.43_00'; +} +BEGIN { + $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; +} # ABSTRACT: Wrapper to get Oracle information use strict; @@ -279,4 +285,44 @@ our %info = ( 1; + + +=pod + +=head1 NAME + +DBD::Oracle::GetInfo - Wrapper to get Oracle information + +=head1 VERSION + +version 1.43_00 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + + __END__ diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 39a99498..7308ab1f 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,25 +1,70 @@ -package DBD::Oracle::Object; -# ABSTRACT: Wrapper for Oracle objects - -use strict; -use warnings; - -sub type_name { shift->{type_name} } - -sub attributes { @{shift->{attributes}} } - -sub attr_hash { - my $self = shift; - return $self->{attr_hash} ||= { $self->attributes }; -} - -sub attr { - my $self = shift; - if (@_) { - my $key = shift; - return $self->attr_hash->{$key}; - } - return $self->attr_hash; -} - -1; +package DBD::Oracle::Object; +{ + $DBD::Oracle::Object::VERSION = '1.43_00'; +} +BEGIN { + $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; +} +# ABSTRACT: Wrapper for Oracle objects + +use strict; +use warnings; + +sub type_name { shift->{type_name} } + +sub attributes { @{shift->{attributes}} } + +sub attr_hash { + my $self = shift; + return $self->{attr_hash} ||= { $self->attributes }; +} + +sub attr { + my $self = shift; + if (@_) { + my $key = shift; + return $self->attr_hash->{$key}; + } + return $self->attr_hash; +} + +1; + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Object - Wrapper for Oracle objects + +=head1 VERSION + +version 1.43_00 + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 37034663..feed4922 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,8 +1,24 @@ package DBD::Oracle::Troubleshooting; +{ + $DBD::Oracle::Troubleshooting::VERSION = '1.43_00'; +} +BEGIN { + $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; +} #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle + +__END__ =pod +=head1 NAME + +DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle + +=head1 VERSION + +version 1.43_00 + =head1 CONNECTING TO ORACLE If you are reading this it is assumed that you have successfully @@ -29,7 +45,6 @@ For Windows the solution is to add this value to you PATH PATH=c:\app\oracle\product\xx.x.x;%PATH% - If you get past this stage and get a ORA-12154: TNS:could not resolve the connect identifier specified @@ -77,7 +92,6 @@ L and L for more gory details. - =head1 USING THE LONG TYPES Some examples related to the use of LONG types are available in @@ -112,7 +126,6 @@ It turns out that now it is necessary to edit the same file and append this and then run "genclntsh", the libclntsh is properly generated and the linkage with DBD::Oracle proceeds properly. - =head2 cc1: invalid option `tune=pentium4'" error If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. @@ -169,7 +182,7 @@ To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY as you would for an install against 10g Standard Edition, Standard Edition One, or Enterprise Edition -=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 +=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 DBD::Oracle seems to hit some sort of bug with the above two versions of DB. The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also @@ -188,7 +201,6 @@ So far there is no patch for this but here are some work arounds or this way utf8::downgrade($parameter, 1); - =head1 CYGWIN @@ -351,4 +363,30 @@ oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + diff --git a/t/000-report-versions.t b/t/000-report-versions.t new file mode 100644 index 00000000..2d4a9a19 --- /dev/null +++ b/t/000-report-versions.t @@ -0,0 +1,446 @@ +#!perl +use warnings; +use strict; +use Test::More 0.94; + +# Include a cut-down version of YAML::Tiny so we don't introduce unnecessary +# dependencies ourselves. + +package Local::YAML::Tiny; + +use strict; +use Carp 'croak'; + +# UTF Support? +sub HAVE_UTF8 () { $] >= 5.007003 } +BEGIN { + if ( HAVE_UTF8 ) { + # The string eval helps hide this from Test::MinimumVersion + eval "require utf8;"; + die "Failed to load UTF-8 support" if $@; + } + + # Class structure + require 5.004; + $YAML::Tiny::VERSION = '1.40'; + + # Error storage + $YAML::Tiny::errstr = ''; +} + +# Printable characters for escapes +my %UNESCAPES = ( + z => "\x00", a => "\x07", t => "\x09", + n => "\x0a", v => "\x0b", f => "\x0c", + r => "\x0d", e => "\x1b", '\\' => '\\', +); + + +##################################################################### +# Implementation + +# Create an empty YAML::Tiny object +sub new { + my $class = shift; + bless [ @_ ], $class; +} + +# Create an object from a file +sub read { + my $class = ref $_[0] ? ref shift : shift; + + # Check the file + my $file = shift or return $class->_error( 'You did not specify a file name' ); + return $class->_error( "File '$file' does not exist" ) unless -e $file; + return $class->_error( "'$file' is a directory, not a file" ) unless -f _; + return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; + + # Slurp in the file + local $/ = undef; + local *CFG; + unless ( open(CFG, $file) ) { + return $class->_error("Failed to open file '$file': $!"); + } + my $contents = ; + unless ( close(CFG) ) { + return $class->_error("Failed to close file '$file': $!"); + } + + $class->read_string( $contents ); +} + +# Create an object from a string +sub read_string { + my $class = ref $_[0] ? ref shift : shift; + my $self = bless [], $class; + my $string = $_[0]; + unless ( defined $string ) { + return $self->_error("Did not provide a string to load"); + } + + # Byte order marks + # NOTE: Keeping this here to educate maintainers + # my %BOM = ( + # "\357\273\277" => 'UTF-8', + # "\376\377" => 'UTF-16BE', + # "\377\376" => 'UTF-16LE', + # "\377\376\0\0" => 'UTF-32LE' + # "\0\0\376\377" => 'UTF-32BE', + # ); + if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) { + return $self->_error("Stream has a non UTF-8 BOM"); + } else { + # Strip UTF-8 bom if found, we'll just ignore it + $string =~ s/^\357\273\277//; + } + + # Try to decode as utf8 + utf8::decode($string) if HAVE_UTF8; + + # Check for some special cases + return $self unless length $string; + unless ( $string =~ /[\012\015]+\z/ ) { + return $self->_error("Stream does not end with newline character"); + } + + # Split the file into lines + my @lines = grep { ! /^\s*(?:\#.*)?\z/ } + split /(?:\015{1,2}\012|\015|\012)/, $string; + + # Strip the initial YAML header + @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; + + # A nibbling parser + while ( @lines ) { + # Do we have a document header? + if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { + # Handle scalar documents + shift @lines; + if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { + push @$self, $self->_read_scalar( "$1", [ undef ], \@lines ); + next; + } + } + + if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { + # A naked document + push @$self, undef; + while ( @lines and $lines[0] !~ /^---/ ) { + shift @lines; + } + + } elsif ( $lines[0] =~ /^\s*\-/ ) { + # An array at the root + my $document = [ ]; + push @$self, $document; + $self->_read_array( $document, [ 0 ], \@lines ); + + } elsif ( $lines[0] =~ /^(\s*)\S/ ) { + # A hash at the root + my $document = { }; + push @$self, $document; + $self->_read_hash( $document, [ length($1) ], \@lines ); + + } else { + croak("YAML::Tiny failed to classify the line '$lines[0]'"); + } + } + + $self; +} + +# Deparse a scalar string to the actual scalar +sub _read_scalar { + my ($self, $string, $indent, $lines) = @_; + + # Trim trailing whitespace + $string =~ s/\s*\z//; + + # Explitic null/undef + return undef if $string eq '~'; + + # Quotes + if ( $string =~ /^\'(.*?)\'\z/ ) { + return '' unless defined $1; + $string = $1; + $string =~ s/\'\'/\'/g; + return $string; + } + if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) { + # Reusing the variable is a little ugly, + # but avoids a new variable and a string copy. + $string = $1; + $string =~ s/\\"/"/g; + $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; + return $string; + } + + # Special cases + if ( $string =~ /^[\'\"!&]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + return {} if $string eq '{}'; + return [] if $string eq '[]'; + + # Regular unquoted string + return $string unless $string =~ /^[>|]/; + + # Error + croak("YAML::Tiny failed to find multi-line scalar content") unless @$lines; + + # Check the indent depth + $lines->[0] =~ /^(\s*)/; + $indent->[-1] = length("$1"); + if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Pull the lines + my @multiline = (); + while ( @$lines ) { + $lines->[0] =~ /^(\s*)/; + last unless length($1) >= $indent->[-1]; + push @multiline, substr(shift(@$lines), length($1)); + } + + my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; + my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; + return join( $j, @multiline ) . $t; +} + +# Parse an array +sub _read_array { + my ($self, $array, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { + # Inline nested hash + my $indent2 = length("$1"); + $lines->[0] =~ s/-/ /; + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { + # Array entry with a value + shift @$lines; + push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines ); + + } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { + shift @$lines; + unless ( @$lines ) { + push @$array, undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)\-/ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] == $indent2 ) { + # Null array entry + push @$array, undef; + } else { + # Naked indenter + push @$array, [ ]; + $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines ); + } + + } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { + push @$array, { }; + $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines ); + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + + } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { + # This is probably a structure like the following... + # --- + # foo: + # - list + # bar: value + # + # ... so lets return and let the hash parser handle it + return 1; + + } else { + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + } + + return 1; +} + +# Parse an array +sub _read_hash { + my ($self, $hash, $indent, $lines) = @_; + + while ( @$lines ) { + # Check for a new document + if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { + while ( @$lines and $lines->[0] !~ /^---/ ) { + shift @$lines; + } + return 1; + } + + # Check the indent level + $lines->[0] =~ /^(\s*)/; + if ( length($1) < $indent->[-1] ) { + return 1; + } elsif ( length($1) > $indent->[-1] ) { + croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); + } + + # Get the key + unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { + if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { + croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); + } + croak("YAML::Tiny failed to classify line '$lines->[0]'"); + } + my $key = $1; + + # Do we have a value? + if ( length $lines->[0] ) { + # Yes + $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines ); + } else { + # An indent + shift @$lines; + unless ( @$lines ) { + $hash->{$key} = undef; + return 1; + } + if ( $lines->[0] =~ /^(\s*)-/ ) { + $hash->{$key} = []; + $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } elsif ( $lines->[0] =~ /^(\s*)./ ) { + my $indent2 = length("$1"); + if ( $indent->[-1] >= $indent2 ) { + # Null hash entry + $hash->{$key} = undef; + } else { + $hash->{$key} = {}; + $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); + } + } + } + } + + return 1; +} + +# Set error +sub _error { + $YAML::Tiny::errstr = $_[1]; + undef; +} + +# Retrieve error +sub errstr { + $YAML::Tiny::errstr; +} + + + +##################################################################### +# Use Scalar::Util if possible, otherwise emulate it + +BEGIN { + eval { + require Scalar::Util; + }; + if ( $@ ) { + # Failed to load Scalar::Util + eval <<'END_PERL'; +sub refaddr { + my $pkg = ref($_[0]) or return undef; + if (!!UNIVERSAL::can($_[0], 'can')) { + bless $_[0], 'Scalar::Util::Fake'; + } else { + $pkg = undef; + } + "$_[0]" =~ /0x(\w+)/; + my $i = do { local $^W; hex $1 }; + bless $_[0], $pkg if defined $pkg; + $i; +} +END_PERL + } else { + Scalar::Util->import('refaddr'); + } +} + + +##################################################################### +# main test +##################################################################### + +package main; + +BEGIN { + + # Skip modules that either don't want to be loaded directly, such as + # Module::Install, or that mess with the test count, such as the Test::* + # modules listed here. + # + # Moose::Role conflicts if Moose is loaded as well, but Moose::Role is in + # the Moose distribution and it's certain that someone who uses + # Moose::Role also uses Moose somewhere, so if we disallow Moose::Role, + # we'll still get the relevant version number. + + my %skip = map { $_ => 1 } qw( + App::FatPacker + Class::Accessor::Classy + Devel::Cover + Module::Install + Moose::Role + POE::Loop::Tk + Template::Test + Test::Kwalitee + Test::Pod::Coverage + Test::Portability::Files + Test::YAML::Meta + ); + + my $Test = Test::Builder->new; + + $Test->plan(skip_all => "META.yml could not be found") + unless -f 'META.yml' and -r _; + + my $meta = (Local::YAML::Tiny->read('META.yml'))->[0]; + my %requires; + for my $require_key (grep { /requires/ } keys %$meta) { + my %h = %{ $meta->{$require_key} }; + $requires{$_}++ for keys %h; + } + delete $requires{perl}; + + diag("Testing with Perl $], $^X"); + for my $module (sort keys %requires) { + if ($skip{$module}) { + note "$module doesn't want to be loaded directly, skipping"; + next; + } + local $SIG{__WARN__} = sub { note "$module: $_[0]" }; + use_ok $module or BAIL_OUT("can't load $module"); + my $version = $module->VERSION; + $version = 'undefined' unless defined $version; + diag(" $module version is $version"); + } + done_testing; +} diff --git a/xt/changes.t b/xt/changes.t deleted file mode 100644 index 27a4808a..00000000 --- a/xt/changes.t +++ /dev/null @@ -1,8 +0,0 @@ -use strict; -use warnings; - -use Test::More; - -eval 'use Test::CPAN::Changes'; -plan skip_all => 'Test::CPAN::Changes required for this test' if $@; -changes_ok(); diff --git a/xt/manifest.t b/xt/manifest.t deleted file mode 100644 index 00df9957..00000000 --- a/xt/manifest.t +++ /dev/null @@ -1,21 +0,0 @@ -use strict; -use warnings; - -use ExtUtils::Manifest qw/ fullcheck /; - -use Test::More tests => 1; - -my ( $missing, $extra ) = do { - local *STDERR; - - # hush little baby, don't you cry - open STDERR, '>', \my $stderr; - - fullcheck(); -}; - -ok @$missing + @$extra == 0, 'manifest in sync' or do { - diag "missing files:\n", map { " \t $_\n " } @$missing if @$missing; - diag "extra files: \n", map { "\t$_\n" } @$extra if @$extra; -}; - diff --git a/xt/pod.t b/xt/pod.t deleted file mode 100644 index 66481225..00000000 --- a/xt/pod.t +++ /dev/null @@ -1,11 +0,0 @@ -use Test::More; - -eval "use Test::Pod"; - -plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; - -pod_file_ok( 'Oracle.pm' ); -pod_file_ok( 'lib/DBD/Oracle/Object.pm' ); -pod_file_ok( 'lib/DBD/Oracle/GetInfo.pm' ); - -done_testing; From d8526aaf2159427fac630254cd87d1d5ac758cc1 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 30 Mar 2012 14:41:41 -0400 Subject: [PATCH 185/637] v1.43_00 [BUG FIXES] - Applied patch from Rafael Kitover (Caelum) to column_info to handle DEFAULT columns greater in length than the DBI default of 80. The DEFAULT column is a long and it is a PITA to have to set LongReadLen which you can only do on a connection handle in DBD::Oracle. The default maximum size is now 1Mb; above that you will still have to set LongReadLen (Martin J. Evans) - Fixed 70meta and rt74753-utf8-encoded to not die if you cannot connect to Oracle or you cannot install from CPAN if you have not set up a valid Oracle connection. - Fixed 75163. Bfile lobs were not being opened before fetching if ora_auto_lobs was disabled (Martin J. Evans). Note: this has a minor impact on non bfile lobs when ora_auto_lobs is not in force as an additional call to OCILobFileIsOpen will be made. - Removed all DBIS usage fixing and speeding up threaded Perls (Martin J. Evans). - Minor fix to avoid use of uninitialised variable in 31lob.t (Martin J. Evans) [DOCUMENTATION] - clarification of when StrictlyTyped/DiscardString can be used and LongReadLen (Martin J. Evans) - Documented the 3rd type of placeholder and rewrote the existing pod for placeholders (Martin J. Evans). --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index 23e47861..ad7a5bb7 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} +1.43_00 2012-03-30 + [BUG FIXES] - Applied patch from Rafael Kitover (Caelum) to column_info to handle DEFAULT columns greater in length than the DBI default of 80. The From 994281ff5dca1eddc54d9cc951a8d4d19dcf5149 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 30 Mar 2012 18:56:58 +0000 Subject: [PATCH 186/637] v1.43 release git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15254 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- META.json | 56 ++++++++++++++----------------- META.yml | 18 +++++----- README | 28 +++++++++++----- README.mkdn | 31 ++++++++++++----- lib/DBD/Oracle.pm | 10 +++--- lib/DBD/Oracle/GetInfo.pm | 4 +-- lib/DBD/Oracle/Object.pm | 4 +-- lib/DBD/Oracle/Troubleshooting.pm | 4 +-- 9 files changed, 90 insertions(+), 67 deletions(-) diff --git a/Changes b/Changes index 774b9ba7..38ea2311 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -NEXT +1.43_00 2012-03-30 [BUG FIXES] - Applied patch from Rafael Kitover (Caelum) to column_info to handle diff --git a/META.json b/META.json index d80794cf..93db2c23 100644 --- a/META.json +++ b/META.json @@ -6,7 +6,7 @@ "Yanick Champoux " ], "dynamic_config" : 0, - "generated_by" : "Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150", + "generated_by" : "Dist::Zilla version 4.300009, CPAN::Meta::Converter version 2.120630", "license" : [ "perl_5" ], @@ -23,62 +23,62 @@ }, "runtime" : { "requires" : { - "DBI" : 0, - "DynaLoader" : 0, - "Exporter" : 0, + "DBI" : "0", + "DynaLoader" : "0", + "Exporter" : "0", "perl" : "5.006", - "strict" : 0, - "warnings" : 0 + "strict" : "0", + "warnings" : "0" } }, "test" : { "requires" : { - "Carp" : 0, - "Config" : 0, - "Data::Dumper" : 0, - "Devel::Peek" : 0, - "Encode" : 0, - "Math::BigInt" : 0, - "Oraperl" : 0, - "Scalar::Util" : 0, + "Carp" : "0", + "Config" : "0", + "Data::Dumper" : "0", + "Devel::Peek" : "0", + "Encode" : "0", + "Math::BigInt" : "0", + "Oraperl" : "0", + "Scalar::Util" : "0", "Test::More" : "0.94", - "Thread::Semaphore" : 0, - "utf8" : 0, - "vars" : 0 + "Thread::Semaphore" : "0", + "utf8" : "0", + "vars" : "0" } } }, "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::Troubleshooting" : { "file" : "lib/DBD/Oracle/Troubleshooting.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.40" + "version" : "1.43_00" } }, - "release_status" : "stable", + "release_status" : "testing", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -91,11 +91,7 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, -<<<<<<< HEAD - "version" : "1.38", -======= - "version" : "1.40", ->>>>>>> build/master + "version" : "1.43_00", "x_authority" : "cpan:PYTHIAN" } diff --git a/META.yml b/META.yml index d7e0423a..93a77584 100644 --- a/META.yml +++ b/META.yml @@ -20,7 +20,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 -generated_by: 'Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150' +generated_by: 'Dist::Zilla version 4.300009, CPAN::Meta::Converter version 2.120630' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -29,25 +29,25 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::Troubleshooting: file: lib/DBD/Oracle/Troubleshooting.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.40 + version: 1.43_00 requires: DBI: 0 DynaLoader: 0 @@ -59,5 +59,5 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.40 +version: 1.43_00 x_authority: cpan:PYTHIAN diff --git a/README b/README index 6bbe76e0..5f6718ac 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.40 + version 1.43_00 SYNOPSIS use DBI; @@ -1030,15 +1030,16 @@ DATABASE HANDLE METHODS See "Row Prefetching" for more details. Placeholders - There are two types of placeholders that can be used in DBD::Oracle. The - first is the "question mark" type, in which each placeholder is + There are three types of placeholders that can be used in DBD::Oracle. + + The first is the "question mark" type, in which each placeholder is represented by a single question mark character. This is the method - recommended by the DBI specs and is the most portable. Each question - mark is internally replaced by a "dollar sign number" in the order in - which they appear in the query (important when using "bind_param"). + recommended by the DBI and is the most portable. Each question mark is + internally replaced by a "dollar sign number" in the order in which they + appear in the query (important when using "bind_param"). - The other placeholder type is "named parameters" in the format ":foo" - which is the one Oralce prefers. + The second type of placeholder is "named parameters" in the format + ":foo" which is the one Oracle prefers. $dbh->{RaiseError} = 1; # save having to check each method call $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); @@ -1046,6 +1047,17 @@ DATABASE HANDLE METHODS $sth->execute; DBI::dump_results($sth); + Note when calling bind_param with named parameters you must include the + leading colon. The advantage of this placeholder type is that you can + use the same placeholder more than once in the same SQL statement but + you only need to bind it once. + + The last placeholder type is a variation of the two above where you name + each placeholder :N (where N is a number). Like the named placeholders + above you can use the same placeholder multiple times in the SQL but + when you call bind_param you only need to pass the N (e.g., for :1 you + use bind_param(1,...) and not bind_param(':1',...). + The different types of placeholders cannot be mixed within a statement, but you may use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. diff --git a/README.mkdn b/README.mkdn index 1e07efa9..6faa9aac 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.40 +version 1.43_00 # SYNOPSIS @@ -1109,13 +1109,17 @@ See [Row Prefetching](#pod_Row Prefetching) for more details. ### __Placeholders__ -There are two types of placeholders that can be used in DBD::Oracle. The first is -the "question mark" type, in which each placeholder is represented by a single -question mark character. This is the method recommended by the DBI specs and is the most -portable. Each question mark is internally replaced by a "dollar sign number" in the order -in which they appear in the query (important when using [bind_param](#pod_bind_param)). +There are three types of placeholders that can be used in +DBD::Oracle. -The other placeholder type is "named parameters" in the format ":foo" which is the one Oralce prefers. +The first is the "question mark" type, in which each placeholder is +represented by a single question mark character. This is the method +recommended by the DBI and is the most portable. Each question +mark is internally replaced by a "dollar sign number" in the order in +which they appear in the query (important when using [bind_param](#pod_bind_param)). + +The second type of placeholder is "named parameters" in the format +":foo" which is the one Oracle prefers. $dbh->{RaiseError} = 1; # save having to check each method call $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); @@ -1123,6 +1127,17 @@ The other placeholder type is "named parameters" in the format ":foo" which is t $sth->execute; DBI::dump_results($sth); +Note when calling bind_param with named parameters you must include +the leading colon. The advantage of this placeholder type is that you +can use the same placeholder more than once in the same SQL statement +but you only need to bind it once. + +The last placeholder type is a variation of the two above where you +name each placeholder :N (where N is a number). Like the named +placeholders above you can use the same placeholder multiple times in +the SQL but when you call bind_param you only need to pass the N +(e.g., for :1 you use bind_param(1,...) and not bind_param(':1',...). + The different types of placeholders cannot be mixed within a statement, but you may use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. @@ -4234,4 +4249,4 @@ Yanick Champoux This software is copyright (c) 1994 by Tim Bunce. This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 4bb7b713..8177d628 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.40'; + $DBD::Oracle::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -125,7 +125,7 @@ BEGIN { { package DBD::Oracle::dr; { - $DBD::Oracle::dr::VERSION = '1.40'; + $DBD::Oracle::dr::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; @@ -330,7 +330,7 @@ BEGIN { { package DBD::Oracle::db; { - $DBD::Oracle::db::VERSION = '1.40'; + $DBD::Oracle::db::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; @@ -1059,7 +1059,7 @@ SQL { package DBD::Oracle::st; { - $DBD::Oracle::st::VERSION = '1.40'; + $DBD::Oracle::st::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; @@ -1164,7 +1164,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.40 +version 1.43_00 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index c61c6dd4..77da0d47 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.40'; + $DBD::Oracle::GetInfo::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.40 +version 1.43_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 642198ce..7308ab1f 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.40'; + $DBD::Oracle::Object::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.40 +version 1.43_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 6d5c973d..feed4922 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Troubleshooting; { - $DBD::Oracle::Troubleshooting::VERSION = '1.40'; + $DBD::Oracle::Troubleshooting::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; @@ -17,7 +17,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.40 +version 1.43_00 =head1 CONNECTING TO ORACLE From 212e724eb97e9a61abc004952021b1f913765066 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 30 Mar 2012 18:56:58 +0000 Subject: [PATCH 187/637] v1.43 release git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15254 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- META.json | 56 ++++++++++++++----------------- META.yml | 18 +++++----- README | 28 +++++++++++----- README.mkdn | 31 ++++++++++++----- lib/DBD/Oracle.pm | 10 +++--- lib/DBD/Oracle/GetInfo.pm | 4 +-- lib/DBD/Oracle/Object.pm | 4 +-- lib/DBD/Oracle/Troubleshooting.pm | 4 +-- 9 files changed, 90 insertions(+), 67 deletions(-) diff --git a/Changes b/Changes index 774b9ba7..38ea2311 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -NEXT +1.43_00 2012-03-30 [BUG FIXES] - Applied patch from Rafael Kitover (Caelum) to column_info to handle diff --git a/META.json b/META.json index d80794cf..93db2c23 100644 --- a/META.json +++ b/META.json @@ -6,7 +6,7 @@ "Yanick Champoux " ], "dynamic_config" : 0, - "generated_by" : "Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150", + "generated_by" : "Dist::Zilla version 4.300009, CPAN::Meta::Converter version 2.120630", "license" : [ "perl_5" ], @@ -23,62 +23,62 @@ }, "runtime" : { "requires" : { - "DBI" : 0, - "DynaLoader" : 0, - "Exporter" : 0, + "DBI" : "0", + "DynaLoader" : "0", + "Exporter" : "0", "perl" : "5.006", - "strict" : 0, - "warnings" : 0 + "strict" : "0", + "warnings" : "0" } }, "test" : { "requires" : { - "Carp" : 0, - "Config" : 0, - "Data::Dumper" : 0, - "Devel::Peek" : 0, - "Encode" : 0, - "Math::BigInt" : 0, - "Oraperl" : 0, - "Scalar::Util" : 0, + "Carp" : "0", + "Config" : "0", + "Data::Dumper" : "0", + "Devel::Peek" : "0", + "Encode" : "0", + "Math::BigInt" : "0", + "Oraperl" : "0", + "Scalar::Util" : "0", "Test::More" : "0.94", - "Thread::Semaphore" : 0, - "utf8" : 0, - "vars" : 0 + "Thread::Semaphore" : "0", + "utf8" : "0", + "vars" : "0" } } }, "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::Troubleshooting" : { "file" : "lib/DBD/Oracle/Troubleshooting.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.40" + "version" : "1.43_00" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.40" + "version" : "1.43_00" } }, - "release_status" : "stable", + "release_status" : "testing", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -91,11 +91,7 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, -<<<<<<< HEAD - "version" : "1.38", -======= - "version" : "1.40", ->>>>>>> build/master + "version" : "1.43_00", "x_authority" : "cpan:PYTHIAN" } diff --git a/META.yml b/META.yml index d7e0423a..93a77584 100644 --- a/META.yml +++ b/META.yml @@ -20,7 +20,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 -generated_by: 'Dist::Zilla version 4.300005, CPAN::Meta::Converter version 2.112150' +generated_by: 'Dist::Zilla version 4.300009, CPAN::Meta::Converter version 2.120630' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -29,25 +29,25 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::Troubleshooting: file: lib/DBD/Oracle/Troubleshooting.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.40 + version: 1.43_00 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.40 + version: 1.43_00 requires: DBI: 0 DynaLoader: 0 @@ -59,5 +59,5 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.40 +version: 1.43_00 x_authority: cpan:PYTHIAN diff --git a/README b/README index 6bbe76e0..5f6718ac 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.40 + version 1.43_00 SYNOPSIS use DBI; @@ -1030,15 +1030,16 @@ DATABASE HANDLE METHODS See "Row Prefetching" for more details. Placeholders - There are two types of placeholders that can be used in DBD::Oracle. The - first is the "question mark" type, in which each placeholder is + There are three types of placeholders that can be used in DBD::Oracle. + + The first is the "question mark" type, in which each placeholder is represented by a single question mark character. This is the method - recommended by the DBI specs and is the most portable. Each question - mark is internally replaced by a "dollar sign number" in the order in - which they appear in the query (important when using "bind_param"). + recommended by the DBI and is the most portable. Each question mark is + internally replaced by a "dollar sign number" in the order in which they + appear in the query (important when using "bind_param"). - The other placeholder type is "named parameters" in the format ":foo" - which is the one Oralce prefers. + The second type of placeholder is "named parameters" in the format + ":foo" which is the one Oracle prefers. $dbh->{RaiseError} = 1; # save having to check each method call $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); @@ -1046,6 +1047,17 @@ DATABASE HANDLE METHODS $sth->execute; DBI::dump_results($sth); + Note when calling bind_param with named parameters you must include the + leading colon. The advantage of this placeholder type is that you can + use the same placeholder more than once in the same SQL statement but + you only need to bind it once. + + The last placeholder type is a variation of the two above where you name + each placeholder :N (where N is a number). Like the named placeholders + above you can use the same placeholder multiple times in the SQL but + when you call bind_param you only need to pass the N (e.g., for :1 you + use bind_param(1,...) and not bind_param(':1',...). + The different types of placeholders cannot be mixed within a statement, but you may use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. diff --git a/README.mkdn b/README.mkdn index 1e07efa9..6faa9aac 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.40 +version 1.43_00 # SYNOPSIS @@ -1109,13 +1109,17 @@ See [Row Prefetching](#pod_Row Prefetching) for more details. ### __Placeholders__ -There are two types of placeholders that can be used in DBD::Oracle. The first is -the "question mark" type, in which each placeholder is represented by a single -question mark character. This is the method recommended by the DBI specs and is the most -portable. Each question mark is internally replaced by a "dollar sign number" in the order -in which they appear in the query (important when using [bind_param](#pod_bind_param)). +There are three types of placeholders that can be used in +DBD::Oracle. -The other placeholder type is "named parameters" in the format ":foo" which is the one Oralce prefers. +The first is the "question mark" type, in which each placeholder is +represented by a single question mark character. This is the method +recommended by the DBI and is the most portable. Each question +mark is internally replaced by a "dollar sign number" in the order in +which they appear in the query (important when using [bind_param](#pod_bind_param)). + +The second type of placeholder is "named parameters" in the format +":foo" which is the one Oracle prefers. $dbh->{RaiseError} = 1; # save having to check each method call $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); @@ -1123,6 +1127,17 @@ The other placeholder type is "named parameters" in the format ":foo" which is t $sth->execute; DBI::dump_results($sth); +Note when calling bind_param with named parameters you must include +the leading colon. The advantage of this placeholder type is that you +can use the same placeholder more than once in the same SQL statement +but you only need to bind it once. + +The last placeholder type is a variation of the two above where you +name each placeholder :N (where N is a number). Like the named +placeholders above you can use the same placeholder multiple times in +the SQL but when you call bind_param you only need to pass the N +(e.g., for :1 you use bind_param(1,...) and not bind_param(':1',...). + The different types of placeholders cannot be mixed within a statement, but you may use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. @@ -4234,4 +4249,4 @@ Yanick Champoux This software is copyright (c) 1994 by Tim Bunce. This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 4bb7b713..8177d628 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.40'; + $DBD::Oracle::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -125,7 +125,7 @@ BEGIN { { package DBD::Oracle::dr; { - $DBD::Oracle::dr::VERSION = '1.40'; + $DBD::Oracle::dr::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; @@ -330,7 +330,7 @@ BEGIN { { package DBD::Oracle::db; { - $DBD::Oracle::db::VERSION = '1.40'; + $DBD::Oracle::db::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; @@ -1059,7 +1059,7 @@ SQL { package DBD::Oracle::st; { - $DBD::Oracle::st::VERSION = '1.40'; + $DBD::Oracle::st::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; @@ -1164,7 +1164,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.40 +version 1.43_00 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index c61c6dd4..77da0d47 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.40'; + $DBD::Oracle::GetInfo::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.40 +version 1.43_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 642198ce..7308ab1f 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.40'; + $DBD::Oracle::Object::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.40 +version 1.43_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 6d5c973d..feed4922 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Troubleshooting; { - $DBD::Oracle::Troubleshooting::VERSION = '1.40'; + $DBD::Oracle::Troubleshooting::VERSION = '1.43_00'; } BEGIN { $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; @@ -17,7 +17,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.40 +version 1.43_00 =head1 CONNECTING TO ORACLE From cd280e30b45184e7450206dc1f468301f855405a Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 08:08:34 +0000 Subject: [PATCH 188/637] Fixed rt 76695 minor debug change git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15280 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 11 +++++++++++ Oracle.xs | 1 + dbdimp.c | 5 ++--- t/51scroll.t | 12 ++++++++++-- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index 38ea2311..be2110db 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,16 @@ Revision history for DBD::Oracle +NEXT + [BUG FIXES] + + - Fixed 76695 - offset passed to ora_fetch_scroll should not affect + normal fetches (Martin J. Evans) + + [MISCELLANEOUS] + + - minor change to confusing debug output for input parameters + (Martin J. Evans) + 1.43_00 2012-03-30 [BUG FIXES] diff --git a/Oracle.xs b/Oracle.xs index 2c7ffc00..6f43ceb5 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -160,6 +160,7 @@ ora_fetch_scroll(sth,fetch_orient,fetch_offset) imp_sth->fetch_orient=fetch_orient; imp_sth->fetch_offset=fetch_offset; av = dbd_st_fetch(sth,imp_sth); + imp_sth->fetch_offset = 1; /* default back to 1 for fetch */ ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &PL_sv_undef; } diff --git a/dbdimp.c b/dbdimp.c index 3c417f2b..e4480cd3 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2662,14 +2662,13 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) phs->alen = value_len + phs->alen_incnull; if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { - UV neatsvpvlen = (UV)DBIc_DBISTATE(imp_sth)->neatsvpvlen; + /*UV neatsvpvlen = (UV)DBIc_DBISTATE(imp_sth)->neatsvpvlen;*/ char *val = neatsvpv(phs->sv,10); PerlIO_printf( DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_char() (2): bind %s <== '%.*s' (size %ld/%ld, " + "dbd_rebind_ph_char() (2): bind %s <== %.1000s (size %ld/%ld, " "otype %d(%s), indp %d, at_exec %d)\n", phs->name, - (int)(phs->alen > neatsvpvlen ? neatsvpvlen : phs->alen), (phs->progv) ? val: "", (long)phs->alen, (long)phs->maxlen, phs->ftype,sql_typecode_name(phs->ftype), phs->indp, at_exec); diff --git a/t/51scroll.t b/t/51scroll.t index 1507cd81..ec538498 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -24,7 +24,7 @@ eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, AutoCommit=>1, PrintError => 0 })}; if ($dbh) { - plan tests => 32; + plan tests => 34; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -34,7 +34,7 @@ ok ($dbh->{RowCacheSize} = 10); isa_ok($dbh, "DBI::db"); my $table = table(); - +#drop_table($dbh); $dbh->do(qq{ CREATE TABLE $table ( @@ -113,6 +113,14 @@ cmp_ok($value->[0], '==', 1, '... we should get the 1st record'); cmp_ok($sth->ora_scroll_position(), '==', 1, '... we should get the 1 for the ora_scroll_position'); +# now fetch forward 2 places then just call fetch +# it should give us the 4th rcord and not the 5th + +$value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,2); +is($value->[0], 3, '... we should get the 3rd record'); +($value) = $sth->fetchrow; +is($value, 4, '... we should get the 4th record'); + $sth->finish(); drop_table($dbh); From 8f4fdc8366c07e89400ed24c9294128594a69d6c Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 08:08:34 +0000 Subject: [PATCH 189/637] Fixed rt 76695 minor debug change git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15280 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 11 +++++++++++ Oracle.xs | 1 + dbdimp.c | 5 ++--- t/51scroll.t | 12 ++++++++++-- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index 38ea2311..be2110db 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,16 @@ Revision history for DBD::Oracle +NEXT + [BUG FIXES] + + - Fixed 76695 - offset passed to ora_fetch_scroll should not affect + normal fetches (Martin J. Evans) + + [MISCELLANEOUS] + + - minor change to confusing debug output for input parameters + (Martin J. Evans) + 1.43_00 2012-03-30 [BUG FIXES] diff --git a/Oracle.xs b/Oracle.xs index 2c7ffc00..6f43ceb5 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -160,6 +160,7 @@ ora_fetch_scroll(sth,fetch_orient,fetch_offset) imp_sth->fetch_orient=fetch_orient; imp_sth->fetch_offset=fetch_offset; av = dbd_st_fetch(sth,imp_sth); + imp_sth->fetch_offset = 1; /* default back to 1 for fetch */ ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &PL_sv_undef; } diff --git a/dbdimp.c b/dbdimp.c index 3c417f2b..e4480cd3 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2662,14 +2662,13 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) phs->alen = value_len + phs->alen_incnull; if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { - UV neatsvpvlen = (UV)DBIc_DBISTATE(imp_sth)->neatsvpvlen; + /*UV neatsvpvlen = (UV)DBIc_DBISTATE(imp_sth)->neatsvpvlen;*/ char *val = neatsvpv(phs->sv,10); PerlIO_printf( DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_char() (2): bind %s <== '%.*s' (size %ld/%ld, " + "dbd_rebind_ph_char() (2): bind %s <== %.1000s (size %ld/%ld, " "otype %d(%s), indp %d, at_exec %d)\n", phs->name, - (int)(phs->alen > neatsvpvlen ? neatsvpvlen : phs->alen), (phs->progv) ? val: "", (long)phs->alen, (long)phs->maxlen, phs->ftype,sql_typecode_name(phs->ftype), phs->indp, at_exec); diff --git a/t/51scroll.t b/t/51scroll.t index 1507cd81..ec538498 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -24,7 +24,7 @@ eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, AutoCommit=>1, PrintError => 0 })}; if ($dbh) { - plan tests => 32; + plan tests => 34; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -34,7 +34,7 @@ ok ($dbh->{RowCacheSize} = 10); isa_ok($dbh, "DBI::db"); my $table = table(); - +#drop_table($dbh); $dbh->do(qq{ CREATE TABLE $table ( @@ -113,6 +113,14 @@ cmp_ok($value->[0], '==', 1, '... we should get the 1st record'); cmp_ok($sth->ora_scroll_position(), '==', 1, '... we should get the 1 for the ora_scroll_position'); +# now fetch forward 2 places then just call fetch +# it should give us the 4th rcord and not the 5th + +$value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,2); +is($value->[0], 3, '... we should get the 3rd record'); +($value) = $sth->fetchrow; +is($value, 4, '... we should get the 4th record'); + $sth->finish(); drop_table($dbh); From d7c66b4f3538b6e5246a9a8ba58f1a5e7e1a8696 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 08:19:30 +0000 Subject: [PATCH 190/637] Fixed the second part of rt 76410 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15281 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++++- Oracle.xs | 1 + t/51scroll.t | 9 ++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index be2110db..3a2981f8 100644 --- a/Changes +++ b/Changes @@ -3,9 +3,12 @@ Revision history for DBD::Oracle NEXT [BUG FIXES] - - Fixed 76695 - offset passed to ora_fetch_scroll should not affect + - Fixed RT76695 - offset passed to ora_fetch_scroll should not affect normal fetches (Martin J. Evans) + - Fixed part of RT76410 - fetch after fetch absolute always returns + the same row (Martin J. Evans); + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/Oracle.xs b/Oracle.xs index 6f43ceb5..1e9093dc 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -161,6 +161,7 @@ ora_fetch_scroll(sth,fetch_orient,fetch_offset) imp_sth->fetch_offset=fetch_offset; av = dbd_st_fetch(sth,imp_sth); imp_sth->fetch_offset = 1; /* default back to 1 for fetch */ + imp_sth->fetch_orient=OCI_FETCH_NEXT; /* default back to fetch next */ ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &PL_sv_undef; } diff --git a/t/51scroll.t b/t/51scroll.t index ec538498..6bd0a902 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -24,7 +24,7 @@ eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, AutoCommit=>1, PrintError => 0 })}; if ($dbh) { - plan tests => 34; + plan tests => 36; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -113,6 +113,7 @@ cmp_ok($value->[0], '==', 1, '... we should get the 1st record'); cmp_ok($sth->ora_scroll_position(), '==', 1, '... we should get the 1 for the ora_scroll_position'); +# rt 76695 - fetch after fetch scroll maintains offset # now fetch forward 2 places then just call fetch # it should give us the 4th rcord and not the 5th @@ -121,6 +122,12 @@ is($value->[0], 3, '... we should get the 3rd record'); ($value) = $sth->fetchrow; is($value, 4, '... we should get the 4th record'); +# rt 76410 - fetch after fetch absolute always returns the same row +$value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE, 2); +is($value->[0], 2, "... we should get the 2nd row"); +($value) = $sth->fetchrow; +is($value, 3, "... we should get the 3rd row"); + $sth->finish(); drop_table($dbh); From 30100d405eb441f3635de6f1fc9051acc6efe126 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 08:19:30 +0000 Subject: [PATCH 191/637] Fixed the second part of rt 76410 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15281 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++++- Oracle.xs | 1 + t/51scroll.t | 9 ++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index be2110db..3a2981f8 100644 --- a/Changes +++ b/Changes @@ -3,9 +3,12 @@ Revision history for DBD::Oracle NEXT [BUG FIXES] - - Fixed 76695 - offset passed to ora_fetch_scroll should not affect + - Fixed RT76695 - offset passed to ora_fetch_scroll should not affect normal fetches (Martin J. Evans) + - Fixed part of RT76410 - fetch after fetch absolute always returns + the same row (Martin J. Evans); + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/Oracle.xs b/Oracle.xs index 6f43ceb5..1e9093dc 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -161,6 +161,7 @@ ora_fetch_scroll(sth,fetch_orient,fetch_offset) imp_sth->fetch_offset=fetch_offset; av = dbd_st_fetch(sth,imp_sth); imp_sth->fetch_offset = 1; /* default back to 1 for fetch */ + imp_sth->fetch_orient=OCI_FETCH_NEXT; /* default back to fetch next */ ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &PL_sv_undef; } diff --git a/t/51scroll.t b/t/51scroll.t index ec538498..6bd0a902 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -24,7 +24,7 @@ eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, AutoCommit=>1, PrintError => 0 })}; if ($dbh) { - plan tests => 34; + plan tests => 36; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -113,6 +113,7 @@ cmp_ok($value->[0], '==', 1, '... we should get the 1st record'); cmp_ok($sth->ora_scroll_position(), '==', 1, '... we should get the 1 for the ora_scroll_position'); +# rt 76695 - fetch after fetch scroll maintains offset # now fetch forward 2 places then just call fetch # it should give us the 4th rcord and not the 5th @@ -121,6 +122,12 @@ is($value->[0], 3, '... we should get the 3rd record'); ($value) = $sth->fetchrow; is($value, 4, '... we should get the 4th record'); +# rt 76410 - fetch after fetch absolute always returns the same row +$value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE, 2); +is($value->[0], 2, "... we should get the 2nd row"); +($value) = $sth->fetchrow; +is($value, 3, "... we should get the 3rd row"); + $sth->finish(); drop_table($dbh); From 1aedf8f83cd8e0c73c87d545bb1efeef0d7ee925 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 09:04:37 +0000 Subject: [PATCH 192/637] just test string changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15282 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/51scroll.t | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/t/51scroll.t b/t/51scroll.t index 6bd0a902..0bedd9ca 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -118,15 +118,15 @@ cmp_ok($sth->ora_scroll_position(), '==', 1, '... we should get the 1 for the or # it should give us the 4th rcord and not the 5th $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,2); -is($value->[0], 3, '... we should get the 3rd record'); +is($value->[0], 3, '... we should get the 3rd record rt76695'); ($value) = $sth->fetchrow; -is($value, 4, '... we should get the 4th record'); +is($value, 4, '... we should get the 4th record rt 76695'); # rt 76410 - fetch after fetch absolute always returns the same row $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE, 2); -is($value->[0], 2, "... we should get the 2nd row"); +is($value->[0], 2, "... we should get the 2nd row rt76410_2"); ($value) = $sth->fetchrow; -is($value, 3, "... we should get the 3rd row"); +is($value, 3, "... we should get the 3rd row rt76410_2"); $sth->finish(); drop_table($dbh); From d120b7e214c7fb0af863a915460f300f0be76a66 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 09:04:37 +0000 Subject: [PATCH 193/637] just test string changes git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15282 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/51scroll.t | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/t/51scroll.t b/t/51scroll.t index 6bd0a902..0bedd9ca 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -118,15 +118,15 @@ cmp_ok($sth->ora_scroll_position(), '==', 1, '... we should get the 1 for the or # it should give us the 4th rcord and not the 5th $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,2); -is($value->[0], 3, '... we should get the 3rd record'); +is($value->[0], 3, '... we should get the 3rd record rt76695'); ($value) = $sth->fetchrow; -is($value, 4, '... we should get the 4th record'); +is($value, 4, '... we should get the 4th record rt 76695'); # rt 76410 - fetch after fetch absolute always returns the same row $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE, 2); -is($value->[0], 2, "... we should get the 2nd row"); +is($value->[0], 2, "... we should get the 2nd row rt76410_2"); ($value) = $sth->fetchrow; -is($value, 3, "... we should get the 3rd row"); +is($value, 3, "... we should get the 3rd row rt76410_2"); $sth->finish(); drop_table($dbh); From da1f2643f28a979b38a8c14f327212331ffd34e1 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 11:12:01 +0000 Subject: [PATCH 194/637] fix rt75721 - does not build with oracle 9.2 added notes to pod saying which attributes need 10.1 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15283 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++++- dbdimp.c | 21 ++++++++++++++------- lib/DBD/Oracle.pm | 8 +++++++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index 3a2981f8..3d9cc932 100644 --- a/Changes +++ b/Changes @@ -6,9 +6,12 @@ NEXT - Fixed RT76695 - offset passed to ora_fetch_scroll should not affect normal fetches (Martin J. Evans) - - Fixed part of RT76410 - fetch after fetch absolute always returns + - Fixed RT76410 - fetch after fetch absolute always returns the same row (Martin J. Evans); + - Fixed RT75721 - DBD::Oracle does not build with Oracle 9.2 + (Martin J. Evans) + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/dbdimp.c b/dbdimp.c index e4480cd3..7aaa2c01 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -437,6 +437,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } #endif /*ORA_OCI_112*/ +#ifdef OCI_ATTR_ACTION if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_action", 10)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -445,7 +446,9 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->actionl= (ub4) svp_len; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } +#endif +#ifdef OCI_ATTR_MODULE if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_module_name", 15)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -455,6 +458,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); } +#endif if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_identifier", 21)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -464,6 +468,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); } +#ifdef OCI_ATTR_CLIENT_INFO if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_info", 15)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -473,7 +478,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); } - +#endif /* TAF Events */ imp_dbh->using_taf = 0; @@ -1182,35 +1187,35 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { imp_dbh->taf_sleep = SvIV (valuesv); } +#ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action") ) { imp_dbh->action = (char *) SvPV (valuesv, vl ); imp_dbh->actionl= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } - else if (kl==10 && strEQ(key, "ora_action") ) { - imp_dbh->action = (char *) SvPV (valuesv, vl ); - imp_dbh->actionl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); - - } +#endif else if (kl==21 && strEQ(key, "ora_client_identifier") ) { imp_dbh->client_identifier = (char *) SvPV (valuesv, vl ); imp_dbh->client_identifierl= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); } +#ifdef OCI_ATTR_CLIENT_INFO else if (kl==15 && strEQ(key, "ora_client_info") ) { imp_dbh->client_info = (char *) SvPV (valuesv, vl ); imp_dbh->client_infol= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); } +#endif +#ifdef OCI_ATTR_MODULE else if (kl==15 && strEQ(key, "ora_module_name") ) { imp_dbh->module_name = (char *) SvPV (valuesv, vl ); imp_dbh->module_namel= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); } +#endif else if (kl==20 && strEQ(key, "ora_oci_success_warn") ) { oci_warn = SvIV (valuesv); } @@ -1301,9 +1306,11 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { retsv = newSViv(imp_dbh->taf_sleep); } +#ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action")) { retsv = newSVpv((char *)imp_dbh->action,0); } +#endif else if (kl==21 && strEQ(key, "ora_client_identifier")) { retsv = newSVpv((char *)imp_dbh->client_identifier,0); } diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 8177d628..8c4c2296 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1389,7 +1389,7 @@ callback with If you try to set up a callback without it being enabled DBD::Oracle will croak. -It is outside the scope of this documents to go through all of the +It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple example: @@ -1607,6 +1607,8 @@ monitoring and performance tuning purposes. For example: The maximum size is 48 bytes. +NOTE: You will need an Oracle client 10.1 or later to use this. + =head4 ora_driver_name For 11g and later you can now set the name of the driver layer using OCI. @@ -1629,6 +1631,8 @@ retrieved on the server side from the Ca view. $dbh->{ora_client_info} = "Remote2"; +NOTE: You will need an Oracle client 10.1 or later to use this. + =head4 ora_client_identifier Allows you to specify the user identifier in the session handle. @@ -1653,6 +1657,8 @@ on the server side using C view. $dbh->{ora_action} = "New Long Query 22"; +NOTE: You will need an Oracle client 10.1 or later to use this. + =head4 ora_dbh_share Requires at least Perl 5.8.0 compiled with ithreads. From 5f8165f591d6be31bd97c69c50bd1a57b57b5355 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 11:12:01 +0000 Subject: [PATCH 195/637] fix rt75721 - does not build with oracle 9.2 added notes to pod saying which attributes need 10.1 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15283 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++++- dbdimp.c | 21 ++++++++++++++------- lib/DBD/Oracle.pm | 8 +++++++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index 3a2981f8..3d9cc932 100644 --- a/Changes +++ b/Changes @@ -6,9 +6,12 @@ NEXT - Fixed RT76695 - offset passed to ora_fetch_scroll should not affect normal fetches (Martin J. Evans) - - Fixed part of RT76410 - fetch after fetch absolute always returns + - Fixed RT76410 - fetch after fetch absolute always returns the same row (Martin J. Evans); + - Fixed RT75721 - DBD::Oracle does not build with Oracle 9.2 + (Martin J. Evans) + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/dbdimp.c b/dbdimp.c index e4480cd3..7aaa2c01 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -437,6 +437,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } #endif /*ORA_OCI_112*/ +#ifdef OCI_ATTR_ACTION if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_action", 10)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -445,7 +446,9 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->actionl= (ub4) svp_len; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } +#endif +#ifdef OCI_ATTR_MODULE if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_module_name", 15)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -455,6 +458,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); } +#endif if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_identifier", 21)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -464,6 +468,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); } +#ifdef OCI_ATTR_CLIENT_INFO if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_info", 15)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -473,7 +478,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); } - +#endif /* TAF Events */ imp_dbh->using_taf = 0; @@ -1182,35 +1187,35 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { imp_dbh->taf_sleep = SvIV (valuesv); } +#ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action") ) { imp_dbh->action = (char *) SvPV (valuesv, vl ); imp_dbh->actionl= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } - else if (kl==10 && strEQ(key, "ora_action") ) { - imp_dbh->action = (char *) SvPV (valuesv, vl ); - imp_dbh->actionl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); - - } +#endif else if (kl==21 && strEQ(key, "ora_client_identifier") ) { imp_dbh->client_identifier = (char *) SvPV (valuesv, vl ); imp_dbh->client_identifierl= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); } +#ifdef OCI_ATTR_CLIENT_INFO else if (kl==15 && strEQ(key, "ora_client_info") ) { imp_dbh->client_info = (char *) SvPV (valuesv, vl ); imp_dbh->client_infol= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); } +#endif +#ifdef OCI_ATTR_MODULE else if (kl==15 && strEQ(key, "ora_module_name") ) { imp_dbh->module_name = (char *) SvPV (valuesv, vl ); imp_dbh->module_namel= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); } +#endif else if (kl==20 && strEQ(key, "ora_oci_success_warn") ) { oci_warn = SvIV (valuesv); } @@ -1301,9 +1306,11 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { retsv = newSViv(imp_dbh->taf_sleep); } +#ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action")) { retsv = newSVpv((char *)imp_dbh->action,0); } +#endif else if (kl==21 && strEQ(key, "ora_client_identifier")) { retsv = newSVpv((char *)imp_dbh->client_identifier,0); } diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 8177d628..8c4c2296 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1389,7 +1389,7 @@ callback with If you try to set up a callback without it being enabled DBD::Oracle will croak. -It is outside the scope of this documents to go through all of the +It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple example: @@ -1607,6 +1607,8 @@ monitoring and performance tuning purposes. For example: The maximum size is 48 bytes. +NOTE: You will need an Oracle client 10.1 or later to use this. + =head4 ora_driver_name For 11g and later you can now set the name of the driver layer using OCI. @@ -1629,6 +1631,8 @@ retrieved on the server side from the Ca view. $dbh->{ora_client_info} = "Remote2"; +NOTE: You will need an Oracle client 10.1 or later to use this. + =head4 ora_client_identifier Allows you to specify the user identifier in the session handle. @@ -1653,6 +1657,8 @@ on the server side using C view. $dbh->{ora_action} = "New Long Query 22"; +NOTE: You will need an Oracle client 10.1 or later to use this. + =head4 ora_dbh_share Requires at least Perl 5.8.0 compiled with ithreads. From 19babe43e7f2d28fa7e1a16def8b2140b4ee2e71 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 11:12:22 +0000 Subject: [PATCH 196/637] typo in comment git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15284 50811bd7-b8ce-0310-adc1-d9db26280581 --- oci8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oci8.c b/oci8.c index 1dfc0d10..8c8e3b97 100644 --- a/oci8.c +++ b/oci8.c @@ -3985,7 +3985,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp,1, imp_sth->fetch_orient,imp_sth->fetch_offset, status); /*this will work without a round trip so might as well open it up for all statments handles*/ - /* defualt and OCI_FETCH_NEXT are the same so this avoids miscaluation on the next value*/ + /* default and OCI_FETCH_NEXT are the same so this avoids miscaluation on the next value*/ OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->fetch_position, 0, OCI_ATTR_CURRENT_POSITION, status); if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) From c540cb9d507f6542603adfce214f72844f945536 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 11:12:22 +0000 Subject: [PATCH 197/637] typo in comment git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15284 50811bd7-b8ce-0310-adc1-d9db26280581 --- oci8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oci8.c b/oci8.c index 1dfc0d10..8c8e3b97 100644 --- a/oci8.c +++ b/oci8.c @@ -3985,7 +3985,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp,1, imp_sth->fetch_orient,imp_sth->fetch_offset, status); /*this will work without a round trip so might as well open it up for all statments handles*/ - /* defualt and OCI_FETCH_NEXT are the same so this avoids miscaluation on the next value*/ + /* default and OCI_FETCH_NEXT are the same so this avoids miscaluation on the next value*/ OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->fetch_position, 0, OCI_ATTR_CURRENT_POSITION, status); if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) From 28b4b0fafab2ee8a7935aa01e90008aeb98e3b4a Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 11:27:08 +0000 Subject: [PATCH 198/637] rt71343 - make use of OCI_ATTR_TAF_ENABLED and OCI_ATTR_RESERVED_15/16 conditional on being defined git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15285 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 ++++-- oci8.c | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 3d9cc932..30727ef0 100644 --- a/Changes +++ b/Changes @@ -9,8 +9,10 @@ NEXT - Fixed RT76410 - fetch after fetch absolute always returns the same row (Martin J. Evans); - - Fixed RT75721 - DBD::Oracle does not build with Oracle 9.2 - (Martin J. Evans) + - Fixed RT75721 - does not build with Oracle 9.2 (Martin J. Evans) + + - Fixed RT71343 - Oracle 9i does not have OCI_ATTR_TAF_ENABLED + or OCI_ATTR_RESERVED_15/16 so cannot build. [MISCELLANEOUS] diff --git a/oci8.c b/oci8.c index 8c8e3b97..3dcc95e2 100644 --- a/oci8.c +++ b/oci8.c @@ -778,9 +778,12 @@ oci_attr_name(ub4 attr) case OCI_ATTR_RESERVED_13: return "OCI_ATTR_RESERVED_13"; /* reserved */ /* OCI_ATTR_RESERVED_14 */ - +#ifdef OCI_ATTR_RESERVED_15 case OCI_ATTR_RESERVED_15: return "OCI_ATTR_RESERVED_15"; /* reserved */ +#endif +#ifdef OCI_ATTR_RESERVED_16 case OCI_ATTR_RESERVED_16: return "OCI_ATTR_RESERVED_16"; /* reserved */ +#endif } sv = sv_2mortal(newSViv((IV)attr)); From 99217d4873eb164ca5ac3ac28a9a7c1c4e07da84 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 11:27:08 +0000 Subject: [PATCH 199/637] rt71343 - make use of OCI_ATTR_TAF_ENABLED and OCI_ATTR_RESERVED_15/16 conditional on being defined git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15285 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 ++++-- oci8.c | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 3d9cc932..30727ef0 100644 --- a/Changes +++ b/Changes @@ -9,8 +9,10 @@ NEXT - Fixed RT76410 - fetch after fetch absolute always returns the same row (Martin J. Evans); - - Fixed RT75721 - DBD::Oracle does not build with Oracle 9.2 - (Martin J. Evans) + - Fixed RT75721 - does not build with Oracle 9.2 (Martin J. Evans) + + - Fixed RT71343 - Oracle 9i does not have OCI_ATTR_TAF_ENABLED + or OCI_ATTR_RESERVED_15/16 so cannot build. [MISCELLANEOUS] diff --git a/oci8.c b/oci8.c index 8c8e3b97..3dcc95e2 100644 --- a/oci8.c +++ b/oci8.c @@ -778,9 +778,12 @@ oci_attr_name(ub4 attr) case OCI_ATTR_RESERVED_13: return "OCI_ATTR_RESERVED_13"; /* reserved */ /* OCI_ATTR_RESERVED_14 */ - +#ifdef OCI_ATTR_RESERVED_15 case OCI_ATTR_RESERVED_15: return "OCI_ATTR_RESERVED_15"; /* reserved */ +#endif +#ifdef OCI_ATTR_RESERVED_16 case OCI_ATTR_RESERVED_16: return "OCI_ATTR_RESERVED_16"; /* reserved */ +#endif } sv = sv_2mortal(newSViv((IV)attr)); From 89f602fb41fbd9914c534b2f07d58ecb7c3a51ee Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 08:19:30 +0000 Subject: [PATCH 200/637] Fixed the second part of rt 76410 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15281 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 12 ++++++++++++ Oracle.xs | 2 ++ t/51scroll.t | 17 ++++++++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index ad7a5bb7..9031311d 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,18 @@ Revision history for DBD::Oracle {{$NEXT}} + [BUG FIXES] + + - Fixed RT76695 - offset passed to ora_fetch_scroll should not affect + normal fetches (Martin J. Evans) + + - Fixed part of RT76410 - fetch after fetch absolute always returns + the same row (Martin J. Evans); + + [MISCELLANEOUS] + + - minor change to confusing debug output for input parameters + (Martin J. Evans) 1.43_00 2012-03-30 diff --git a/Oracle.xs b/Oracle.xs index 2c7ffc00..1e9093dc 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -160,6 +160,8 @@ ora_fetch_scroll(sth,fetch_orient,fetch_offset) imp_sth->fetch_orient=fetch_orient; imp_sth->fetch_offset=fetch_offset; av = dbd_st_fetch(sth,imp_sth); + imp_sth->fetch_offset = 1; /* default back to 1 for fetch */ + imp_sth->fetch_orient=OCI_FETCH_NEXT; /* default back to fetch next */ ST(0) = (av) ? sv_2mortal(newRV((SV *)av)) : &PL_sv_undef; } diff --git a/t/51scroll.t b/t/51scroll.t index 1507cd81..8c34157d 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -24,7 +24,7 @@ eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, AutoCommit=>1, PrintError => 0 })}; if ($dbh) { - plan tests => 32; + plan tests => 36; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -113,6 +113,21 @@ cmp_ok($value->[0], '==', 1, '... we should get the 1st record'); cmp_ok($sth->ora_scroll_position(), '==', 1, '... we should get the 1 for the ora_scroll_position'); +# rt 76695 - fetch after fetch scroll maintains offset +# now fetch forward 2 places then just call fetch +# it should give us the 4th rcord and not the 5th + +$value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,2); +is($value->[0], 3, '... we should get the 3rd record'); +($value) = $sth->fetchrow; +is($value, 4, '... we should get the 4th record'); + +# rt 76410 - fetch after fetch absolute always returns the same row +$value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE, 2); +is($value->[0], 2, "... we should get the 2nd row"); +($value) = $sth->fetchrow; +is($value, 3, "... we should get the 3rd row"); + $sth->finish(); drop_table($dbh); From 94e8c9e827d264146c6a2832fb7397469211c341 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 11:12:01 +0000 Subject: [PATCH 201/637] fix rt75721 - does not build with oracle 9.2 added notes to pod saying which attributes need 10.1 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15283 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++++- dbdimp.c | 21 ++++++++++++++------- lib/DBD/Oracle.pm | 8 +++++++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index 9031311d..4003cac9 100644 --- a/Changes +++ b/Changes @@ -6,9 +6,12 @@ Revision history for DBD::Oracle - Fixed RT76695 - offset passed to ora_fetch_scroll should not affect normal fetches (Martin J. Evans) - - Fixed part of RT76410 - fetch after fetch absolute always returns + - Fixed RT76410 - fetch after fetch absolute always returns the same row (Martin J. Evans); + - Fixed RT75721 - DBD::Oracle does not build with Oracle 9.2 + (Martin J. Evans) + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/dbdimp.c b/dbdimp.c index 3c417f2b..a767a34c 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -437,6 +437,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } #endif /*ORA_OCI_112*/ +#ifdef OCI_ATTR_ACTION if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_action", 10)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -445,7 +446,9 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->actionl= (ub4) svp_len; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } +#endif +#ifdef OCI_ATTR_MODULE if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_module_name", 15)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -455,6 +458,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); } +#endif if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_identifier", 21)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -464,6 +468,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); } +#ifdef OCI_ATTR_CLIENT_INFO if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_info", 15)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -473,7 +478,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); } - +#endif /* TAF Events */ imp_dbh->using_taf = 0; @@ -1182,35 +1187,35 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { imp_dbh->taf_sleep = SvIV (valuesv); } +#ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action") ) { imp_dbh->action = (char *) SvPV (valuesv, vl ); imp_dbh->actionl= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); } - else if (kl==10 && strEQ(key, "ora_action") ) { - imp_dbh->action = (char *) SvPV (valuesv, vl ); - imp_dbh->actionl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); - - } +#endif else if (kl==21 && strEQ(key, "ora_client_identifier") ) { imp_dbh->client_identifier = (char *) SvPV (valuesv, vl ); imp_dbh->client_identifierl= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); } +#ifdef OCI_ATTR_CLIENT_INFO else if (kl==15 && strEQ(key, "ora_client_info") ) { imp_dbh->client_info = (char *) SvPV (valuesv, vl ); imp_dbh->client_infol= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); } +#endif +#ifdef OCI_ATTR_MODULE else if (kl==15 && strEQ(key, "ora_module_name") ) { imp_dbh->module_name = (char *) SvPV (valuesv, vl ); imp_dbh->module_namel= (ub4) vl; OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); } +#endif else if (kl==20 && strEQ(key, "ora_oci_success_warn") ) { oci_warn = SvIV (valuesv); } @@ -1301,9 +1306,11 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { retsv = newSViv(imp_dbh->taf_sleep); } +#ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action")) { retsv = newSVpv((char *)imp_dbh->action,0); } +#endif else if (kl==21 && strEQ(key, "ora_client_identifier")) { retsv = newSVpv((char *)imp_dbh->client_identifier,0); } diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 835d42c8..89b1416b 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1358,7 +1358,7 @@ callback with If you try to set up a callback without it being enabled DBD::Oracle will croak. -It is outside the scope of this documents to go through all of the +It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple example: @@ -1576,6 +1576,8 @@ monitoring and performance tuning purposes. For example: The maximum size is 48 bytes. +NOTE: You will need an Oracle client 10.1 or later to use this. + =head4 ora_driver_name For 11g and later you can now set the name of the driver layer using OCI. @@ -1599,6 +1601,8 @@ retrieved on the server side from the Ca view. $dbh->{ora_client_info} = "Remote2"; +NOTE: You will need an Oracle client 10.1 or later to use this. + =head4 ora_client_identifier Allows you to specify the user identifier in the session handle. @@ -1623,6 +1627,8 @@ on the server side using C view. $dbh->{ora_action} = "New Long Query 22"; +NOTE: You will need an Oracle client 10.1 or later to use this. + =head4 ora_dbh_share Requires at least Perl 5.8.0 compiled with ithreads. From a04099fda3753c4f1f7a93383580081094afc6e8 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 11:12:22 +0000 Subject: [PATCH 202/637] typo in comment git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15284 50811bd7-b8ce-0310-adc1-d9db26280581 --- oci8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oci8.c b/oci8.c index 1dfc0d10..8c8e3b97 100644 --- a/oci8.c +++ b/oci8.c @@ -3985,7 +3985,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp,1, imp_sth->fetch_orient,imp_sth->fetch_offset, status); /*this will work without a round trip so might as well open it up for all statments handles*/ - /* defualt and OCI_FETCH_NEXT are the same so this avoids miscaluation on the next value*/ + /* default and OCI_FETCH_NEXT are the same so this avoids miscaluation on the next value*/ OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->fetch_position, 0, OCI_ATTR_CURRENT_POSITION, status); if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) From 3ec8daea327763df1117554b8d4e7f83519d462c Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 11:27:08 +0000 Subject: [PATCH 203/637] rt71343 - make use of OCI_ATTR_TAF_ENABLED and OCI_ATTR_RESERVED_15/16 conditional on being defined git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15285 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 ++++-- oci8.c | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 4003cac9..dbd1baca 100644 --- a/Changes +++ b/Changes @@ -9,8 +9,10 @@ Revision history for DBD::Oracle - Fixed RT76410 - fetch after fetch absolute always returns the same row (Martin J. Evans); - - Fixed RT75721 - DBD::Oracle does not build with Oracle 9.2 - (Martin J. Evans) + - Fixed RT75721 - does not build with Oracle 9.2 (Martin J. Evans) + + - Fixed RT71343 - Oracle 9i does not have OCI_ATTR_TAF_ENABLED + or OCI_ATTR_RESERVED_15/16 so cannot build. [MISCELLANEOUS] diff --git a/oci8.c b/oci8.c index 8c8e3b97..3dcc95e2 100644 --- a/oci8.c +++ b/oci8.c @@ -778,9 +778,12 @@ oci_attr_name(ub4 attr) case OCI_ATTR_RESERVED_13: return "OCI_ATTR_RESERVED_13"; /* reserved */ /* OCI_ATTR_RESERVED_14 */ - +#ifdef OCI_ATTR_RESERVED_15 case OCI_ATTR_RESERVED_15: return "OCI_ATTR_RESERVED_15"; /* reserved */ +#endif +#ifdef OCI_ATTR_RESERVED_16 case OCI_ATTR_RESERVED_16: return "OCI_ATTR_RESERVED_16"; /* reserved */ +#endif } sv = sv_2mortal(newSViv((IV)attr)); From b805a83d93f299dbf4cf0d04e337f34295708609 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sun, 22 Apr 2012 11:49:19 -0400 Subject: [PATCH 204/637] bump version in dist.ini --- dist.ini | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dist.ini b/dist.ini index 78533959..7a179df7 100644 --- a/dist.ini +++ b/dist.ini @@ -6,7 +6,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.43_00 +version = 1.45_00 [Authority] authority=cpan:PYTHIAN @@ -15,12 +15,13 @@ authority=cpan:PYTHIAN [@Filter] -bundle=@YANICK --remove=Author::YANICK::NextSemanticVersion +-remove=NextVersion::Semantic -remove=ModuleBuild -remove=Authority -remove=Signature -remove=UploadToCPAN -remove=Twitter -remove=Test::Compile +-remove=Covenant [FakeRelease] From fc9118b0c2f2365381789610a5e71f2fe17b57d9 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 16:30:16 +0000 Subject: [PATCH 205/637] skip 24implicit_utf8.t if chr set is not UTF-8 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15286 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ t/24implicit_utf8.t | 13 ++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index 30727ef0..e8db3faf 100644 --- a/Changes +++ b/Changes @@ -14,6 +14,8 @@ NEXT - Fixed RT71343 - Oracle 9i does not have OCI_ATTR_TAF_ENABLED or OCI_ATTR_RESERVED_15/16 so cannot build. + - skip 24implicit_utf8.t if chr set is not UTF-8 + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/t/24implicit_utf8.t b/t/24implicit_utf8.t index 518297b1..e61b03f6 100644 --- a/t/24implicit_utf8.t +++ b/t/24implicit_utf8.t @@ -16,18 +16,17 @@ $| = 1; SKIP: { plan skip_all => "Unable to run 8bit char test, perl version is less than 5.6" unless ( $] >= 5.006 ); plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" - if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; - + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; $dbh = db_handle(); # just to check connection and db NCHAR character set - - + plan skip_all => "Unable to connect to Oracle" if not $dbh; plan skip_all => "Database NCHAR character set is not Unicode" if not db_nchar_is_utf($dbh) ; + plan skip_all => "database character set is not Unicode" unless db_ochar_is_utf($dbh); $dbh->disconnect(); # testing implicit csform (dbhimp.c sets csform implicitly) my $tdata = test_data( 'wide_nchar' ); - my $testcount = 0 + my $testcount = 0 + insert_test_count( $tdata ) + select_test_count( $tdata ) * 1; ; @@ -40,8 +39,8 @@ SKIP: { $dbh->disconnect() if $dbh; undef $dbh; # testing with NLS_NCHAR=$nchar_cset - SKIP: { - set_nls_nchar( $nchar_cset ,1 ); + SKIP: { + set_nls_nchar( $nchar_cset ,1 ); $dbh = db_handle(); show_db_charsets($dbh); skip "failed to connect to oracle with NLS_NCHAR=$nchar_cset" ,$testcount if not $dbh; From b8d5c7fd11df119b064cf65db03ddfd8d94655ed Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 16:30:16 +0000 Subject: [PATCH 206/637] skip 24implicit_utf8.t if chr set is not UTF-8 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15286 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ t/24implicit_utf8.t | 13 ++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index 30727ef0..e8db3faf 100644 --- a/Changes +++ b/Changes @@ -14,6 +14,8 @@ NEXT - Fixed RT71343 - Oracle 9i does not have OCI_ATTR_TAF_ENABLED or OCI_ATTR_RESERVED_15/16 so cannot build. + - skip 24implicit_utf8.t if chr set is not UTF-8 + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/t/24implicit_utf8.t b/t/24implicit_utf8.t index 518297b1..e61b03f6 100644 --- a/t/24implicit_utf8.t +++ b/t/24implicit_utf8.t @@ -16,18 +16,17 @@ $| = 1; SKIP: { plan skip_all => "Unable to run 8bit char test, perl version is less than 5.6" unless ( $] >= 5.006 ); plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" - if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; - + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; $dbh = db_handle(); # just to check connection and db NCHAR character set - - + plan skip_all => "Unable to connect to Oracle" if not $dbh; plan skip_all => "Database NCHAR character set is not Unicode" if not db_nchar_is_utf($dbh) ; + plan skip_all => "database character set is not Unicode" unless db_ochar_is_utf($dbh); $dbh->disconnect(); # testing implicit csform (dbhimp.c sets csform implicitly) my $tdata = test_data( 'wide_nchar' ); - my $testcount = 0 + my $testcount = 0 + insert_test_count( $tdata ) + select_test_count( $tdata ) * 1; ; @@ -40,8 +39,8 @@ SKIP: { $dbh->disconnect() if $dbh; undef $dbh; # testing with NLS_NCHAR=$nchar_cset - SKIP: { - set_nls_nchar( $nchar_cset ,1 ); + SKIP: { + set_nls_nchar( $nchar_cset ,1 ); $dbh = db_handle(); show_db_charsets($dbh); skip "failed to connect to oracle with NLS_NCHAR=$nchar_cset" ,$testcount if not $dbh; From 764144dd877b11cb6e9914af01099addd9cb6e4e Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 18:14:03 +0000 Subject: [PATCH 207/637] missing attribution git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15287 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index e8db3faf..3c2432f1 100644 --- a/Changes +++ b/Changes @@ -12,9 +12,9 @@ NEXT - Fixed RT75721 - does not build with Oracle 9.2 (Martin J. Evans) - Fixed RT71343 - Oracle 9i does not have OCI_ATTR_TAF_ENABLED - or OCI_ATTR_RESERVED_15/16 so cannot build. + or OCI_ATTR_RESERVED_15/16 so cannot build (Martin J. Evans) - - skip 24implicit_utf8.t if chr set is not UTF-8 + - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) [MISCELLANEOUS] From a3e2a68ec3279f067b3d12dc2015b72513809c3d Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 18:14:03 +0000 Subject: [PATCH 208/637] missing attribution git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15287 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index e8db3faf..3c2432f1 100644 --- a/Changes +++ b/Changes @@ -12,9 +12,9 @@ NEXT - Fixed RT75721 - does not build with Oracle 9.2 (Martin J. Evans) - Fixed RT71343 - Oracle 9i does not have OCI_ATTR_TAF_ENABLED - or OCI_ATTR_RESERVED_15/16 so cannot build. + or OCI_ATTR_RESERVED_15/16 so cannot build (Martin J. Evans) - - skip 24implicit_utf8.t if chr set is not UTF-8 + - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) [MISCELLANEOUS] From 8279456ef448cf0e3274fe23b008123d5de88c96 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 18:35:07 +0000 Subject: [PATCH 209/637] add note in pod for namespace and taf_function git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15288 50811bd7-b8ce-0310-adc1-d9db26280581 --- lib/DBD/Oracle.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 8c4c2296..8ccd7559 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1413,6 +1413,8 @@ attempts another event. #import the ora fail over constants #set up TAF on the connection + # NOTE since DBD::Oracle uses call_pv you may need to pass a full + # name space as the function e.g., 'main::handle_taf' my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function From 77af6be230f5d2deb1e20edbc841b874edae94de Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 18:35:07 +0000 Subject: [PATCH 210/637] add note in pod for namespace and taf_function git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15288 50811bd7-b8ce-0310-adc1-d9db26280581 --- lib/DBD/Oracle.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 8c4c2296..8ccd7559 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1413,6 +1413,8 @@ attempts another event. #import the ora fail over constants #set up TAF on the connection + # NOTE since DBD::Oracle uses call_pv you may need to pass a full + # name space as the function e.g., 'main::handle_taf' my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function From 658871fbd697a8941c8b5717d4e865de70c70375 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 16:30:16 +0000 Subject: [PATCH 211/637] skip 24implicit_utf8.t if chr set is not UTF-8 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15286 50811bd7-b8ce-0310-adc1-d9db26280581 Conflicts: Changes --- Changes | 2 ++ t/24implicit_utf8.t | 13 ++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index dbd1baca..4b7b685e 100644 --- a/Changes +++ b/Changes @@ -14,6 +14,8 @@ Revision history for DBD::Oracle - Fixed RT71343 - Oracle 9i does not have OCI_ATTR_TAF_ENABLED or OCI_ATTR_RESERVED_15/16 so cannot build. + - skip 24implicit_utf8.t if chr set is not UTF-8 + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/t/24implicit_utf8.t b/t/24implicit_utf8.t index 518297b1..e61b03f6 100644 --- a/t/24implicit_utf8.t +++ b/t/24implicit_utf8.t @@ -16,18 +16,17 @@ $| = 1; SKIP: { plan skip_all => "Unable to run 8bit char test, perl version is less than 5.6" unless ( $] >= 5.006 ); plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" - if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; - + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; $dbh = db_handle(); # just to check connection and db NCHAR character set - - + plan skip_all => "Unable to connect to Oracle" if not $dbh; plan skip_all => "Database NCHAR character set is not Unicode" if not db_nchar_is_utf($dbh) ; + plan skip_all => "database character set is not Unicode" unless db_ochar_is_utf($dbh); $dbh->disconnect(); # testing implicit csform (dbhimp.c sets csform implicitly) my $tdata = test_data( 'wide_nchar' ); - my $testcount = 0 + my $testcount = 0 + insert_test_count( $tdata ) + select_test_count( $tdata ) * 1; ; @@ -40,8 +39,8 @@ SKIP: { $dbh->disconnect() if $dbh; undef $dbh; # testing with NLS_NCHAR=$nchar_cset - SKIP: { - set_nls_nchar( $nchar_cset ,1 ); + SKIP: { + set_nls_nchar( $nchar_cset ,1 ); $dbh = db_handle(); show_db_charsets($dbh); skip "failed to connect to oracle with NLS_NCHAR=$nchar_cset" ,$testcount if not $dbh; From 0a2442c5d7981ef5ee218603ba855fe54a3d0f01 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 18:14:03 +0000 Subject: [PATCH 212/637] missing attribution git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15287 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 4b7b685e..38b295de 100644 --- a/Changes +++ b/Changes @@ -12,9 +12,9 @@ Revision history for DBD::Oracle - Fixed RT75721 - does not build with Oracle 9.2 (Martin J. Evans) - Fixed RT71343 - Oracle 9i does not have OCI_ATTR_TAF_ENABLED - or OCI_ATTR_RESERVED_15/16 so cannot build. + or OCI_ATTR_RESERVED_15/16 so cannot build (Martin J. Evans) - - skip 24implicit_utf8.t if chr set is not UTF-8 + - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) [MISCELLANEOUS] From b522fd892c01284538e7ea6ba31f0cdc1ddc1b0c Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 22 Apr 2012 18:35:07 +0000 Subject: [PATCH 213/637] add note in pod for namespace and taf_function git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15288 50811bd7-b8ce-0310-adc1-d9db26280581 --- lib/DBD/Oracle.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 89b1416b..299f23be 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1382,6 +1382,8 @@ attempts another event. #import the ora fail over constants #set up TAF on the connection + # NOTE since DBD::Oracle uses call_pv you may need to pass a full + # name space as the function e.g., 'main::handle_taf' my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function From 4bdf2d3f401e5be0a020ddb14b3a44907e3efe03 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 23 Apr 2012 14:53:07 -0400 Subject: [PATCH 214/637] v1.44 change stanza --- Changes | 3 +++ dist.ini | 1 + 2 files changed, 4 insertions(+) diff --git a/Changes b/Changes index 38b295de..c53d5cce 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,9 @@ Revision history for DBD::Oracle - minor change to confusing debug output for input parameters (Martin J. Evans) +1.44 2012-04-23 + - promote 1.43_00 to official release + 1.43_00 2012-03-30 [BUG FIXES] diff --git a/dist.ini b/dist.ini index 7a179df7..eacf4cad 100644 --- a/dist.ini +++ b/dist.ini @@ -16,6 +16,7 @@ authority=cpan:PYTHIAN [@Filter] -bundle=@YANICK -remove=NextVersion::Semantic +-remove=Author::YANICK::NextSemanticVersion -remove=ModuleBuild -remove=Authority -remove=Signature From d4b18c2ea5f3c5b37bc7277e172951f51cb43d83 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 23 Apr 2012 20:24:00 +0000 Subject: [PATCH 215/637] Merge branch 'build/master' into HEAD Conflicts: Changes META.json META.yml README README.mkdn lib/DBD/Oracle.pm lib/DBD/Oracle/GetInfo.pm lib/DBD/Oracle/Object.pm lib/DBD/Oracle/Troubleshooting.pm t/51scroll.t git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15292 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ META.json | 16 ++++++++-------- META.yml | 16 ++++++++-------- README | 12 ++++++++++-- README.mkdn | 14 +++++++++++--- lib/DBD/Oracle.pm | 10 +++++----- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pm | 4 ++-- 9 files changed, 51 insertions(+), 32 deletions(-) diff --git a/Changes b/Changes index 3c2432f1..ad179132 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,9 @@ NEXT - minor change to confusing debug output for input parameters (Martin J. Evans) +1.44 2012-04-23 + - promote 1.43_00 to official release + 1.43_00 2012-03-30 [BUG FIXES] diff --git a/META.json b/META.json index 93db2c23..4d5b3feb 100644 --- a/META.json +++ b/META.json @@ -51,31 +51,31 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.43_00" + "version" : "1.45_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.43_00" + "version" : "1.45_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.43_00" + "version" : "1.45_00" }, "DBD::Oracle::Troubleshooting" : { "file" : "lib/DBD/Oracle/Troubleshooting.pm", - "version" : "1.43_00" + "version" : "1.45_00" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.43_00" + "version" : "1.45_00" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.43_00" + "version" : "1.45_00" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.43_00" + "version" : "1.45_00" } }, "release_status" : "testing", @@ -91,7 +91,7 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, - "version" : "1.43_00", + "version" : "1.45_00", "x_authority" : "cpan:PYTHIAN" } diff --git a/META.yml b/META.yml index 93a77584..c9e73036 100644 --- a/META.yml +++ b/META.yml @@ -29,25 +29,25 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.43_00 + version: 1.45_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.43_00 + version: 1.45_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.43_00 + version: 1.45_00 DBD::Oracle::Troubleshooting: file: lib/DBD/Oracle/Troubleshooting.pm - version: 1.43_00 + version: 1.45_00 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.43_00 + version: 1.45_00 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.43_00 + version: 1.45_00 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.43_00 + version: 1.45_00 requires: DBI: 0 DynaLoader: 0 @@ -59,5 +59,5 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.43_00 +version: 1.45_00 x_authority: cpan:PYTHIAN diff --git a/README b/README index 5f6718ac..a02414bc 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.43_00 + version 1.45_00 SYNOPSIS use DBI; @@ -219,7 +219,7 @@ DBI CLASS METHODS If you try to set up a callback without it being enabled DBD::Oracle will croak. - It is outside the scope of this documents to go through all of the + It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple example: @@ -243,6 +243,8 @@ DBI CLASS METHODS #import the ora fail over constants #set up TAF on the connection + # NOTE since DBD::Oracle uses call_pv you may need to pass a full + # name space as the function e.g., 'main::handle_taf' my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function @@ -424,6 +426,8 @@ DBI CLASS METHODS The maximum size is 48 bytes. + NOTE: You will need an Oracle client 10.1 or later to use this. + ora_driver_name For 11g and later you can now set the name of the driver layer using OCI. Perl, Perl5, ApachePerl so on. Names starting with "ORA" are @@ -444,6 +448,8 @@ DBI CLASS METHODS $dbh->{ora_client_info} = "Remote2"; + NOTE: You will need an Oracle client 10.1 or later to use this. + ora_client_identifier Allows you to specify the user identifier in the session handle. @@ -465,6 +471,8 @@ DBI CLASS METHODS $dbh->{ora_action} = "New Long Query 22"; + NOTE: You will need an Oracle client 10.1 or later to use this. + ora_dbh_share Requires at least Perl 5.8.0 compiled with ithreads. diff --git a/README.mkdn b/README.mkdn index 6faa9aac..05e0faed 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.43_00 +version 1.45_00 # SYNOPSIS @@ -221,7 +221,7 @@ callback with If you try to set up a callback without it being enabled DBD::Oracle will croak. -It is outside the scope of this documents to go through all of the +It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple example: @@ -245,6 +245,8 @@ attempts another event. #import the ora fail over constants #set up TAF on the connection + # NOTE since DBD::Oracle uses call_pv you may need to pass a full + # name space as the function e.g., 'main::handle_taf' my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function @@ -439,6 +441,8 @@ monitoring and performance tuning purposes. For example: The maximum size is 48 bytes. +NOTE: You will need an Oracle client 10.1 or later to use this. + #### ora_driver_name For 11g and later you can now set the name of the driver layer using OCI. @@ -461,6 +465,8 @@ retrieved on the server side from the `V$SESSION`a view. $dbh->{ora_client_info} = "Remote2"; +NOTE: You will need an Oracle client 10.1 or later to use this. + #### ora_client_identifier Allows you to specify the user identifier in the session handle. @@ -485,6 +491,8 @@ on the server side using `V$SESSION` view. $dbh->{ora_action} = "New Long Query 22"; +NOTE: You will need an Oracle client 10.1 or later to use this. + #### ora_dbh_share Requires at least Perl 5.8.0 compiled with ithreads. @@ -4249,4 +4257,4 @@ Yanick Champoux This software is copyright (c) 1994 by Tim Bunce. This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. \ No newline at end of file +the same terms as the Perl 5 programming language system itself. diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 8ccd7559..614e5f11 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.43_00'; + $DBD::Oracle::VERSION = '1.45_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -125,7 +125,7 @@ BEGIN { { package DBD::Oracle::dr; { - $DBD::Oracle::dr::VERSION = '1.43_00'; + $DBD::Oracle::dr::VERSION = '1.45_00'; } BEGIN { $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; @@ -330,7 +330,7 @@ BEGIN { { package DBD::Oracle::db; { - $DBD::Oracle::db::VERSION = '1.43_00'; + $DBD::Oracle::db::VERSION = '1.45_00'; } BEGIN { $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; @@ -1059,7 +1059,7 @@ SQL { package DBD::Oracle::st; { - $DBD::Oracle::st::VERSION = '1.43_00'; + $DBD::Oracle::st::VERSION = '1.45_00'; } BEGIN { $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; @@ -1164,7 +1164,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.43_00 +version 1.45_00 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 77da0d47..cd80a9a2 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.43_00'; + $DBD::Oracle::GetInfo::VERSION = '1.45_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.43_00 +version 1.45_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 7308ab1f..1cb08569 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.43_00'; + $DBD::Oracle::Object::VERSION = '1.45_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.43_00 +version 1.45_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index feed4922..4d4532c5 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Troubleshooting; { - $DBD::Oracle::Troubleshooting::VERSION = '1.43_00'; + $DBD::Oracle::Troubleshooting::VERSION = '1.45_00'; } BEGIN { $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; @@ -17,7 +17,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.43_00 +version 1.45_00 =head1 CONNECTING TO ORACLE From 1bcd99203145ea357270e0ba5264651489142b71 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 24 Apr 2012 09:25:19 +0000 Subject: [PATCH 216/637] Export OCI_FO_RETRY in :ora_fail_over Add debug for taf function name and sleep values Fix taf example wrt taf_sleep => ora_taf_sleep In TAF don't do retries unless OCI_FO_RETRY returned from handler git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15295 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 +++++ Oracle.xs | 1 + dbdimp.c | 6 +++++- lib/DBD/Oracle.pm | 18 +++++++++++++----- oci8.c | 19 ++++++++++++++++--- 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index ad179132..54e2cd2d 100644 --- a/Changes +++ b/Changes @@ -16,6 +16,11 @@ NEXT - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) + - Fixed RT76268 - ora_taf_sleep was documented as taf_sleep by + accident. There was no way to stop the TAF reconnect attempts. + If you want to try another connect attempt in your taf handler you + now need to return OCI_FO_RETRY from it. (Martin J. Evans) + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/Oracle.xs b/Oracle.xs index 1e9093dc..4f6b1a62 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -59,6 +59,7 @@ constant(name=Nullch) OCI_FO_SESSION = OCI_FO_SESSION OCI_FO_SELECT = OCI_FO_SELECT OCI_FO_TXNAL = OCI_FO_TXNAL + OCI_FO_RETRY = OCI_FO_RETRY OCI_STMT_SCROLLABLE_READONLY = 0x08 OCI_PRELIM_AUTH = 0x00000008 OCI_DBSTARTUPFLAG_FORCE = 0x00000001 diff --git a/dbdimp.c b/dbdimp.c index 7aaa2c01..ca3841dc 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -487,7 +487,6 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->taf_sleep = 5; /* 5 second default */ DBD_ATTRIB_GET_IV( attr, "ora_taf_sleep", 13, svp, imp_dbh->taf_sleep); - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -495,6 +494,11 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->taf_function = (char *) SvPV (*svp, svp_len ); } + if (DBIc_DBISTATE(imp_dbh)->debug || dbd_verbose >= 3) + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + "taf sleep = %d, taf_function = %s\n", + imp_dbh->taf_sleep, imp_dbh->taf_function ? imp_dbh->taf_function : ""); } imp_dbh->server_version = 0; diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 614e5f11..3e8e95b9 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -39,7 +39,7 @@ BEGIN { ora_exe_modes => [ qw( OCI_STMT_SCROLLABLE_READONLY)], ora_fail_over => [ qw( OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT - OCI_FO_TXNAL)], + OCI_FO_TXNAL OCI_FO_RETRY)], ); @EXPORT_OK = qw(OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST OCI_FETCH_LAST OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE ORA_OCI SQLCS_IMPLICIT SQLCS_NCHAR ora_env_var ora_cygwin_set_env ); @@ -1251,7 +1251,7 @@ These constants are used to set the orientation of a fetch on a scrollable curso =item :ora_fail_over OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR - OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY =back @@ -1415,7 +1415,7 @@ attempts another event. #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function @@ -1444,6 +1444,9 @@ attempts another event. } elsif ($fo_event == OCI_FO_ERROR){ print " Failover error Sleeping...\n"; + # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY + # If you want to stop retrying just return 0 + return OCI_FO_RETRY; } else { printf(" Bad Failover Event: %d.\n", $fo_event); @@ -1557,10 +1560,15 @@ and the failover type. Below is an example of a TAF function return; } +Note you'll probably have to use the full name space when setting the +TAF function e.g., 'main::my_taf_function' and not just +'my_taf_function'. + =head4 ora_taf_sleep -The amount of time in seconds the OCI client will sleep between attempting -successive failover events when the event is OCI_FO_ERROR. +The amount of time in seconds DBD::Oracle will sleep between attempting +successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY +is returned from the TAF handler. =head4 ora_session_mode diff --git a/oci8.c b/oci8.c index 3dcc95e2..f61242e9 100644 --- a/oci8.c +++ b/oci8.c @@ -1308,6 +1308,8 @@ sb4 taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) { dTHX; + int return_count; + int ret; taf_callback_t *cb =(taf_callback_t*)fo_ctx; dSP; @@ -1315,8 +1317,15 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) XPUSHs(sv_2mortal(newSViv(fo_event))); XPUSHs(sv_2mortal(newSViv(fo_type))); PUTBACK; - call_pv(cb->function, G_DISCARD); + return_count = call_pv(cb->function, G_SCALAR); + SPAGAIN; + + if (return_count != 1) + croak("Expected one scalar back from taf handler"); + + ret = POPi; + switch (fo_event){ case OCI_FO_BEGIN: @@ -1328,8 +1337,10 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) } case OCI_FO_ERROR: { - sleep(cb->sleep); - return OCI_FO_RETRY; + if (ret == OCI_FO_RETRY) { + sleep(cb->sleep); + return OCI_FO_RETRY; + } break; } @@ -1338,6 +1349,8 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) break; } } + PUTBACK; + return 0; } From f77267cb324d9daa4ed889904cc1285b2be3ad51 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 24 Apr 2012 09:25:19 +0000 Subject: [PATCH 217/637] Export OCI_FO_RETRY in :ora_fail_over Add debug for taf function name and sleep values Fix taf example wrt taf_sleep => ora_taf_sleep In TAF don't do retries unless OCI_FO_RETRY returned from handler git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15295 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 +++++ Oracle.xs | 1 + dbdimp.c | 6 +++++- lib/DBD/Oracle.pm | 18 +++++++++++++----- oci8.c | 19 ++++++++++++++++--- 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index ad179132..54e2cd2d 100644 --- a/Changes +++ b/Changes @@ -16,6 +16,11 @@ NEXT - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) + - Fixed RT76268 - ora_taf_sleep was documented as taf_sleep by + accident. There was no way to stop the TAF reconnect attempts. + If you want to try another connect attempt in your taf handler you + now need to return OCI_FO_RETRY from it. (Martin J. Evans) + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/Oracle.xs b/Oracle.xs index 1e9093dc..4f6b1a62 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -59,6 +59,7 @@ constant(name=Nullch) OCI_FO_SESSION = OCI_FO_SESSION OCI_FO_SELECT = OCI_FO_SELECT OCI_FO_TXNAL = OCI_FO_TXNAL + OCI_FO_RETRY = OCI_FO_RETRY OCI_STMT_SCROLLABLE_READONLY = 0x08 OCI_PRELIM_AUTH = 0x00000008 OCI_DBSTARTUPFLAG_FORCE = 0x00000001 diff --git a/dbdimp.c b/dbdimp.c index 7aaa2c01..ca3841dc 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -487,7 +487,6 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->taf_sleep = 5; /* 5 second default */ DBD_ATTRIB_GET_IV( attr, "ora_taf_sleep", 13, svp, imp_dbh->taf_sleep); - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -495,6 +494,11 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->taf_function = (char *) SvPV (*svp, svp_len ); } + if (DBIc_DBISTATE(imp_dbh)->debug || dbd_verbose >= 3) + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + "taf sleep = %d, taf_function = %s\n", + imp_dbh->taf_sleep, imp_dbh->taf_function ? imp_dbh->taf_function : ""); } imp_dbh->server_version = 0; diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 614e5f11..3e8e95b9 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -39,7 +39,7 @@ BEGIN { ora_exe_modes => [ qw( OCI_STMT_SCROLLABLE_READONLY)], ora_fail_over => [ qw( OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT - OCI_FO_TXNAL)], + OCI_FO_TXNAL OCI_FO_RETRY)], ); @EXPORT_OK = qw(OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST OCI_FETCH_LAST OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE ORA_OCI SQLCS_IMPLICIT SQLCS_NCHAR ora_env_var ora_cygwin_set_env ); @@ -1251,7 +1251,7 @@ These constants are used to set the orientation of a fetch on a scrollable curso =item :ora_fail_over OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR - OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY =back @@ -1415,7 +1415,7 @@ attempts another event. #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function @@ -1444,6 +1444,9 @@ attempts another event. } elsif ($fo_event == OCI_FO_ERROR){ print " Failover error Sleeping...\n"; + # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY + # If you want to stop retrying just return 0 + return OCI_FO_RETRY; } else { printf(" Bad Failover Event: %d.\n", $fo_event); @@ -1557,10 +1560,15 @@ and the failover type. Below is an example of a TAF function return; } +Note you'll probably have to use the full name space when setting the +TAF function e.g., 'main::my_taf_function' and not just +'my_taf_function'. + =head4 ora_taf_sleep -The amount of time in seconds the OCI client will sleep between attempting -successive failover events when the event is OCI_FO_ERROR. +The amount of time in seconds DBD::Oracle will sleep between attempting +successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY +is returned from the TAF handler. =head4 ora_session_mode diff --git a/oci8.c b/oci8.c index 3dcc95e2..f61242e9 100644 --- a/oci8.c +++ b/oci8.c @@ -1308,6 +1308,8 @@ sb4 taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) { dTHX; + int return_count; + int ret; taf_callback_t *cb =(taf_callback_t*)fo_ctx; dSP; @@ -1315,8 +1317,15 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) XPUSHs(sv_2mortal(newSViv(fo_event))); XPUSHs(sv_2mortal(newSViv(fo_type))); PUTBACK; - call_pv(cb->function, G_DISCARD); + return_count = call_pv(cb->function, G_SCALAR); + SPAGAIN; + + if (return_count != 1) + croak("Expected one scalar back from taf handler"); + + ret = POPi; + switch (fo_event){ case OCI_FO_BEGIN: @@ -1328,8 +1337,10 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) } case OCI_FO_ERROR: { - sleep(cb->sleep); - return OCI_FO_RETRY; + if (ret == OCI_FO_RETRY) { + sleep(cb->sleep); + return OCI_FO_RETRY; + } break; } @@ -1338,6 +1349,8 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) break; } } + PUTBACK; + return 0; } From 81d9c528c380df5bf2a55db307524dba57080931 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 24 Apr 2012 09:39:07 +0000 Subject: [PATCH 218/637] reformat and fix taf_sleep in test git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15296 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/38taf.t | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/t/38taf.t b/t/38taf.t index eb09234b..b1adf93d 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -19,22 +19,26 @@ my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; -plan tests => 1; +plan tests => 1; $dbh->disconnect; if ( !$dbh->ora_can_taf ){ - - eval {$dbh = DBI->connect($dsn, $dbuser, '',{ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf'})}; - ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); - - + + eval { + $dbh = DBI->connect( + $dsn, $dbuser, '', + {ora_taf=>1, ora_taf_sleep=>15,ora_taf_function=>'taf'}) + }; + ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); + + } else { - ok $dbh = DBI->connect($dsn, $dbuser, '',{ - ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf' - }); - + ok $dbh = DBI->connect($dsn, $dbuser, '', + {ora_taf=>1, ora_taf_sleep=>15, + ora_taf_function=>'taf'}); + } $dbh->disconnect; From e69308fa1cc5bb7da876a97adab3ba6e0077913f Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 24 Apr 2012 09:39:07 +0000 Subject: [PATCH 219/637] reformat and fix taf_sleep in test git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15296 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/38taf.t | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/t/38taf.t b/t/38taf.t index eb09234b..b1adf93d 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -19,22 +19,26 @@ my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; -plan tests => 1; +plan tests => 1; $dbh->disconnect; if ( !$dbh->ora_can_taf ){ - - eval {$dbh = DBI->connect($dsn, $dbuser, '',{ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf'})}; - ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); - - + + eval { + $dbh = DBI->connect( + $dsn, $dbuser, '', + {ora_taf=>1, ora_taf_sleep=>15,ora_taf_function=>'taf'}) + }; + ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); + + } else { - ok $dbh = DBI->connect($dsn, $dbuser, '',{ - ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf' - }); - + ok $dbh = DBI->connect($dsn, $dbuser, '', + {ora_taf=>1, ora_taf_sleep=>15, + ora_taf_function=>'taf'}); + } $dbh->disconnect; From fb7bd2309c6c3d521a42de7e969970b4f949e3b2 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 24 Apr 2012 09:57:11 +0000 Subject: [PATCH 220/637] head levels were wrong in Other Data Types git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15297 50811bd7-b8ce-0310-adc1-d9db26280581 --- lib/DBD/Oracle.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 3e8e95b9..11527707 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -4872,7 +4872,7 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" -=head4 Support for Insert of XMLType (ORA_XMLTYPE) +=head2 Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For @@ -4902,7 +4902,7 @@ one can insert data using this code In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. -=head4 Binding Cursors +=head2 Binding Cursors Cursors can be returned from PL/SQL blocks, either from stored functions (or procedures with OUT parameters) or @@ -4972,7 +4972,7 @@ PL/SQL handle is re-bound, re-executed or destroyed. See the C script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. -=head4 Fetching Nested Cursors +=head2 Fetching Nested Cursors Oracle supports the use of select list expressions of type REF CURSOR. These may be explicit cursor expressions - C, or @@ -5027,7 +5027,7 @@ previous section can be fetched as a nested cursor as follows: my ($nested) = $sth->fetchrow_array; while ( my @row = $nested->fetchrow_array ) { ... } -=head4 Pre-fetching Nested Cursors +=head2 Pre-fetching Nested Cursors By default, DBD::Oracle pre-fetches rows in order to reduce the number of round trips to the server. For queries which do not involve nested cursors, From ef0cf74d56a4b66a556bfa4f572592710c58efff Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 24 Apr 2012 09:57:11 +0000 Subject: [PATCH 221/637] head levels were wrong in Other Data Types git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15297 50811bd7-b8ce-0310-adc1-d9db26280581 --- lib/DBD/Oracle.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 3e8e95b9..11527707 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -4872,7 +4872,7 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" -=head4 Support for Insert of XMLType (ORA_XMLTYPE) +=head2 Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For @@ -4902,7 +4902,7 @@ one can insert data using this code In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. -=head4 Binding Cursors +=head2 Binding Cursors Cursors can be returned from PL/SQL blocks, either from stored functions (or procedures with OUT parameters) or @@ -4972,7 +4972,7 @@ PL/SQL handle is re-bound, re-executed or destroyed. See the C script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. -=head4 Fetching Nested Cursors +=head2 Fetching Nested Cursors Oracle supports the use of select list expressions of type REF CURSOR. These may be explicit cursor expressions - C, or @@ -5027,7 +5027,7 @@ previous section can be fetched as a nested cursor as follows: my ($nested) = $sth->fetchrow_array; while ( my @row = $nested->fetchrow_array ) { ... } -=head4 Pre-fetching Nested Cursors +=head2 Pre-fetching Nested Cursors By default, DBD::Oracle pre-fetches rows in order to reduce the number of round trips to the server. For queries which do not involve nested cursors, From 10bf22031e96f88f95defd72a6bf648c43912e88 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 25 Apr 2012 18:52:04 +0000 Subject: [PATCH 222/637] add note of a change in behaviour of ora_verbose in future DBD::Oracle git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15301 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 ++++++++ lib/DBD/Oracle.pm | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/Changes b/Changes index 54e2cd2d..77307a95 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,14 @@ NEXT If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) + [CHANGE IN BEHAVIOUR] + + - In future versions of DBD::Oracle ora_verbose will be changed + so that it is simply a switch to turn DBI's DBD tracing on or off. + A true value will turn it on and a false value will turn it off. + DBI's "DBD" tracing was not available when ora_verbose was created + and ora_verbose adds an additional test to every trace test. + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 11527707..1f2cc52e 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1726,6 +1726,12 @@ or set it directly on the DB handle like this; In both cases the DBD::Oracle trace level is set to 6, which is the highest level tracing most of the calls to OCI. +NOTE: In future versions of DBD::Oracle ora_verbose will be changed so +that it is simply a switch to turn DBI's DBD tracing on or off. A +true value will turn it on and a false value will turn it off. DBI's +"DBD" tracing was not available when ora_verbose was created and +ora_verbose adds an additional test to every trace test. + =head4 ora_oci_success_warn Use this value to print otherwise silent OCI warnings that may happen From d6cd57729fdf38907fbc986d45ba5dcc24960368 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 25 Apr 2012 18:52:04 +0000 Subject: [PATCH 223/637] add note of a change in behaviour of ora_verbose in future DBD::Oracle git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15301 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 ++++++++ lib/DBD/Oracle.pm | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/Changes b/Changes index 54e2cd2d..77307a95 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,14 @@ NEXT If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) + [CHANGE IN BEHAVIOUR] + + - In future versions of DBD::Oracle ora_verbose will be changed + so that it is simply a switch to turn DBI's DBD tracing on or off. + A true value will turn it on and a false value will turn it off. + DBI's "DBD" tracing was not available when ora_verbose was created + and ora_verbose adds an additional test to every trace test. + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 11527707..1f2cc52e 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1726,6 +1726,12 @@ or set it directly on the DB handle like this; In both cases the DBD::Oracle trace level is set to 6, which is the highest level tracing most of the calls to OCI. +NOTE: In future versions of DBD::Oracle ora_verbose will be changed so +that it is simply a switch to turn DBI's DBD tracing on or off. A +true value will turn it on and a false value will turn it off. DBI's +"DBD" tracing was not available when ora_verbose was created and +ora_verbose adds an additional test to every trace test. + =head4 ora_oci_success_warn Use this value to print otherwise silent OCI warnings that may happen From 1873f42fc5a21b462e0fa6f9874dfc688769b7a9 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 25 Apr 2012 19:03:36 +0000 Subject: [PATCH 224/637] Add entry to troubleshooting guide for rt 72989 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15302 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ lib/DBD/Oracle/Troubleshooting.pm | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/Changes b/Changes index 77307a95..911ab4d5 100644 --- a/Changes +++ b/Changes @@ -34,6 +34,9 @@ NEXT - minor change to confusing debug output for input parameters (Martin J. Evans) + - RT72989 - add note to trouble shooting guide re this RT and + Module::Runtime (Martin J. Evans) + 1.44 2012-04-23 - promote 1.43_00 to official release diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 4d4532c5..4c74cf61 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -363,6 +363,18 @@ oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) +=head1 Miscellaneous + +=head2 Crash with an open connection and Module::Runtime in mod_perl2 + +See RT 72989 (https://rt.cpan.org/Ticket/Display.html?id=72989) + +Apache2 MPM Prefork with mod_perl2 will crash if Module::Runtime is +loaded, and an Oracle connection is opened through PerlRequire (before +forking). + +It looks like this was fixed in 0.012 of Module::Runtime. + =head1 AUTHORS =over 4 @@ -379,6 +391,10 @@ John Scoles Yanick Champoux +=item * + +Martin J. Evans + =back =head1 COPYRIGHT AND LICENSE From 1109df9463dd2857e36500891e89a10cb753cf8f Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 25 Apr 2012 19:03:36 +0000 Subject: [PATCH 225/637] Add entry to troubleshooting guide for rt 72989 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15302 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ lib/DBD/Oracle/Troubleshooting.pm | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/Changes b/Changes index 77307a95..911ab4d5 100644 --- a/Changes +++ b/Changes @@ -34,6 +34,9 @@ NEXT - minor change to confusing debug output for input parameters (Martin J. Evans) + - RT72989 - add note to trouble shooting guide re this RT and + Module::Runtime (Martin J. Evans) + 1.44 2012-04-23 - promote 1.43_00 to official release diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 4d4532c5..4c74cf61 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -363,6 +363,18 @@ oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) +=head1 Miscellaneous + +=head2 Crash with an open connection and Module::Runtime in mod_perl2 + +See RT 72989 (https://rt.cpan.org/Ticket/Display.html?id=72989) + +Apache2 MPM Prefork with mod_perl2 will crash if Module::Runtime is +loaded, and an Oracle connection is opened through PerlRequire (before +forking). + +It looks like this was fixed in 0.012 of Module::Runtime. + =head1 AUTHORS =over 4 @@ -379,6 +391,10 @@ John Scoles Yanick Champoux +=item * + +Martin J. Evans + =back =head1 COPYRIGHT AND LICENSE From 586c38dfa209b152d319e7c55ee8b3a78a898c81 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 24 Apr 2012 09:25:19 +0000 Subject: [PATCH 226/637] Export OCI_FO_RETRY in :ora_fail_over Add debug for taf function name and sleep values Fix taf example wrt taf_sleep => ora_taf_sleep In TAF don't do retries unless OCI_FO_RETRY returned from handler git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15295 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 +++++ Oracle.xs | 1 + dbdimp.c | 6 +++++- lib/DBD/Oracle.pm | 18 +++++++++++++----- oci8.c | 19 ++++++++++++++++--- 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index c53d5cce..c6dde73f 100644 --- a/Changes +++ b/Changes @@ -16,6 +16,11 @@ Revision history for DBD::Oracle - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) + - Fixed RT76268 - ora_taf_sleep was documented as taf_sleep by + accident. There was no way to stop the TAF reconnect attempts. + If you want to try another connect attempt in your taf handler you + now need to return OCI_FO_RETRY from it. (Martin J. Evans) + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/Oracle.xs b/Oracle.xs index 1e9093dc..4f6b1a62 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -59,6 +59,7 @@ constant(name=Nullch) OCI_FO_SESSION = OCI_FO_SESSION OCI_FO_SELECT = OCI_FO_SELECT OCI_FO_TXNAL = OCI_FO_TXNAL + OCI_FO_RETRY = OCI_FO_RETRY OCI_STMT_SCROLLABLE_READONLY = 0x08 OCI_PRELIM_AUTH = 0x00000008 OCI_DBSTARTUPFLAG_FORCE = 0x00000001 diff --git a/dbdimp.c b/dbdimp.c index a767a34c..ebe4cf1f 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -487,7 +487,6 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->taf_sleep = 5; /* 5 second default */ DBD_ATTRIB_GET_IV( attr, "ora_taf_sleep", 13, svp, imp_dbh->taf_sleep); - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { STRLEN svp_len; if (!SvPOK(*svp)) @@ -495,6 +494,11 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->taf_function = (char *) SvPV (*svp, svp_len ); } + if (DBIc_DBISTATE(imp_dbh)->debug || dbd_verbose >= 3) + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + "taf sleep = %d, taf_function = %s\n", + imp_dbh->taf_sleep, imp_dbh->taf_function ? imp_dbh->taf_function : ""); } imp_dbh->server_version = 0; diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 299f23be..60344fca 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -33,7 +33,7 @@ package DBD::Oracle; ora_exe_modes => [ qw( OCI_STMT_SCROLLABLE_READONLY)], ora_fail_over => [ qw( OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT - OCI_FO_TXNAL)], + OCI_FO_TXNAL OCI_FO_RETRY)], ); @EXPORT_OK = qw(OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST OCI_FETCH_LAST OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE ORA_OCI SQLCS_IMPLICIT SQLCS_NCHAR ora_env_var ora_cygwin_set_env ); @@ -1219,7 +1219,7 @@ These constants are used to set the orientation of a fetch on a scrollable curso =item :ora_fail_over OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR - OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY =back @@ -1384,7 +1384,7 @@ attempts another event. #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function @@ -1413,6 +1413,9 @@ attempts another event. } elsif ($fo_event == OCI_FO_ERROR){ print " Failover error Sleeping...\n"; + # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY + # If you want to stop retrying just return 0 + return OCI_FO_RETRY; } else { printf(" Bad Failover Event: %d.\n", $fo_event); @@ -1526,10 +1529,15 @@ and the failover type. Below is an example of a TAF function return; } +Note you'll probably have to use the full name space when setting the +TAF function e.g., 'main::my_taf_function' and not just +'my_taf_function'. + =head4 ora_taf_sleep -The amount of time in seconds the OCI client will sleep between attempting -successive failover events when the event is OCI_FO_ERROR. +The amount of time in seconds DBD::Oracle will sleep between attempting +successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY +is returned from the TAF handler. =head4 ora_session_mode diff --git a/oci8.c b/oci8.c index 3dcc95e2..f61242e9 100644 --- a/oci8.c +++ b/oci8.c @@ -1308,6 +1308,8 @@ sb4 taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) { dTHX; + int return_count; + int ret; taf_callback_t *cb =(taf_callback_t*)fo_ctx; dSP; @@ -1315,8 +1317,15 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) XPUSHs(sv_2mortal(newSViv(fo_event))); XPUSHs(sv_2mortal(newSViv(fo_type))); PUTBACK; - call_pv(cb->function, G_DISCARD); + return_count = call_pv(cb->function, G_SCALAR); + SPAGAIN; + + if (return_count != 1) + croak("Expected one scalar back from taf handler"); + + ret = POPi; + switch (fo_event){ case OCI_FO_BEGIN: @@ -1328,8 +1337,10 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) } case OCI_FO_ERROR: { - sleep(cb->sleep); - return OCI_FO_RETRY; + if (ret == OCI_FO_RETRY) { + sleep(cb->sleep); + return OCI_FO_RETRY; + } break; } @@ -1338,6 +1349,8 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) break; } } + PUTBACK; + return 0; } From 72cb549a95cc9a563a1e8d6379423ee8c6ce4ff1 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 24 Apr 2012 09:39:07 +0000 Subject: [PATCH 227/637] reformat and fix taf_sleep in test git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15296 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/38taf.t | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/t/38taf.t b/t/38taf.t index eb09234b..b1adf93d 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -19,22 +19,26 @@ my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; -plan tests => 1; +plan tests => 1; $dbh->disconnect; if ( !$dbh->ora_can_taf ){ - - eval {$dbh = DBI->connect($dsn, $dbuser, '',{ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf'})}; - ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); - - + + eval { + $dbh = DBI->connect( + $dsn, $dbuser, '', + {ora_taf=>1, ora_taf_sleep=>15,ora_taf_function=>'taf'}) + }; + ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); + + } else { - ok $dbh = DBI->connect($dsn, $dbuser, '',{ - ora_taf=>1,taf_sleep=>15,ora_taf_function=>'taf' - }); - + ok $dbh = DBI->connect($dsn, $dbuser, '', + {ora_taf=>1, ora_taf_sleep=>15, + ora_taf_function=>'taf'}); + } $dbh->disconnect; From 9a13c02adf43a828528a77b446fa657cb707bd27 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 21 Jun 2012 14:05:17 -0400 Subject: [PATCH 228/637] head levels were wrong in Other Data Types git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15297 50811bd7-b8ce-0310-adc1-d9db26280581 Conflicts: lib/DBD/Oracle.pm --- lib/DBD/Oracle.pm | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 60344fca..5bac91f6 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -3050,7 +3050,7 @@ and B datatypes. The simple example is here: =item B -=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' +=item Take careful note that we use '\\@arr' here because the 'bind_param_inout' will only take a reference to a scalar. =back @@ -4872,8 +4872,7 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" - -=head4 Support for Insert of XMLType (ORA_XMLTYPE) +=head2 Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For @@ -4903,7 +4902,7 @@ one can insert data using this code In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. -=head4 Binding Cursors +=head2 Binding Cursors Cursors can be returned from PL/SQL blocks, either from stored functions (or procedures with OUT parameters) or @@ -4973,7 +4972,7 @@ PL/SQL handle is re-bound, re-executed or destroyed. See the C script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. -=head4 Fetching Nested Cursors +=head2 Fetching Nested Cursors Oracle supports the use of select list expressions of type REF CURSOR. These may be explicit cursor expressions - C, or @@ -5020,7 +5019,6 @@ shows: } } - The cursor returned by the function C defined in the previous section can be fetched as a nested cursor as follows: @@ -5029,7 +5027,7 @@ previous section can be fetched as a nested cursor as follows: my ($nested) = $sth->fetchrow_array; while ( my @row = $nested->fetchrow_array ) { ... } -=head4 Pre-fetching Nested Cursors +=head2 Pre-fetching Nested Cursors By default, DBD::Oracle pre-fetches rows in order to reduce the number of round trips to the server. For queries which do not involve nested cursors, From 0993f0cc8c5bdb03121389120fff82b04bdedbbd Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 25 Apr 2012 18:52:04 +0000 Subject: [PATCH 229/637] add note of a change in behaviour of ora_verbose in future DBD::Oracle git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15301 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 ++++++++ lib/DBD/Oracle.pm | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/Changes b/Changes index c6dde73f..c05f9fca 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,14 @@ Revision history for DBD::Oracle If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) + [CHANGE IN BEHAVIOUR] + + - In future versions of DBD::Oracle ora_verbose will be changed + so that it is simply a switch to turn DBI's DBD tracing on or off. + A true value will turn it on and a false value will turn it off. + DBI's "DBD" tracing was not available when ora_verbose was created + and ora_verbose adds an additional test to every trace test. + [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 5bac91f6..efa35c80 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1696,6 +1696,12 @@ or set it directly on the DB handle like this; In both cases the DBD::Oracle trace level is set to 6, which is the highest level tracing most of the calls to OCI. +NOTE: In future versions of DBD::Oracle ora_verbose will be changed so +that it is simply a switch to turn DBI's DBD tracing on or off. A +true value will turn it on and a false value will turn it off. DBI's +"DBD" tracing was not available when ora_verbose was created and +ora_verbose adds an additional test to every trace test. + =head4 ora_oci_success_warn Use this value to print otherwise silent OCI warnings that may happen From 152498b19229718ab57f3ef8d0fe1fd5c6e70849 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 25 Apr 2012 14:03:36 -0500 Subject: [PATCH 230/637] Add entry to troubleshooting guide for rt 72989 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15302 50811bd7-b8ce-0310-adc1-d9db26280581 Conflicts: lib/DBD/Oracle/Troubleshooting.pm --- Changes | 3 +++ lib/DBD/Oracle/Troubleshooting.pm | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/Changes b/Changes index c05f9fca..1e4c5d86 100644 --- a/Changes +++ b/Changes @@ -34,6 +34,9 @@ Revision history for DBD::Oracle - minor change to confusing debug output for input parameters (Martin J. Evans) + - RT72989 - add note to trouble shooting guide re this RT and + Module::Runtime (Martin J. Evans) + 1.44 2012-04-23 - promote 1.43_00 to official release diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 37034663..7821a720 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -351,4 +351,16 @@ oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) +=head1 Miscellaneous + +=head2 Crash with an open connection and Module::Runtime in mod_perl2 + +See RT 72989 (https://rt.cpan.org/Ticket/Display.html?id=72989) + +Apache2 MPM Prefork with mod_perl2 will crash if Module::Runtime is +loaded, and an Oracle connection is opened through PerlRequire (before +forking). + +It looks like this was fixed in 0.012 of Module::Runtime. + =cut From 802baf15305fcd49e78a085030ae58f56eb92340 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 21 Jun 2012 14:00:14 -0400 Subject: [PATCH 231/637] No touchy the Changelog --- dist.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dist.ini b/dist.ini index eacf4cad..fa00a4b3 100644 --- a/dist.ini +++ b/dist.ini @@ -2,6 +2,7 @@ name = DBD-Oracle author = Tim Bunce author = John Scoles author = Yanick Champoux +author = Martin J. Evans license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 @@ -16,6 +17,7 @@ authority=cpan:PYTHIAN [@Filter] -bundle=@YANICK -remove=NextVersion::Semantic +-remove=ChangeStats::Git -remove=Author::YANICK::NextSemanticVersion -remove=ModuleBuild -remove=Authority From c16eed2f68daa6688c87eabd8db2b949df19b7e7 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 21 Jun 2012 14:11:07 -0400 Subject: [PATCH 232/637] CHANGE IN BEHAV is important, push up --- Changes | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Changes b/Changes index 1e4c5d86..7d1879a2 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,15 @@ Revision history for DBD::Oracle {{$NEXT}} + + [CHANGE IN BEHAVIOUR] + + - In future versions of DBD::Oracle ora_verbose will be changed + so that it is simply a switch to turn DBI's DBD tracing on or off. + A true value will turn it on and a false value will turn it off. + DBI's "DBD" tracing was not available when ora_verbose was created + and ora_verbose adds an additional test to every trace test. + [BUG FIXES] - Fixed RT76695 - offset passed to ora_fetch_scroll should not affect @@ -21,14 +30,6 @@ Revision history for DBD::Oracle If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) - [CHANGE IN BEHAVIOUR] - - - In future versions of DBD::Oracle ora_verbose will be changed - so that it is simply a switch to turn DBI's DBD tracing on or off. - A true value will turn it on and a false value will turn it off. - DBI's "DBD" tracing was not available when ora_verbose was created - and ora_verbose adds an additional test to every trace test. - [MISCELLANEOUS] - minor change to confusing debug output for input parameters From 7093368a8b4fc787a0b164e625f4b2695d2d8bc9 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 21 Jun 2012 15:37:34 -0400 Subject: [PATCH 233/637] missing string changes from rev15282 --- t/51scroll.t | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/t/51scroll.t b/t/51scroll.t index 8c34157d..24266bab 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -118,15 +118,15 @@ cmp_ok($sth->ora_scroll_position(), '==', 1, '... we should get the 1 for the or # it should give us the 4th rcord and not the 5th $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,2); -is($value->[0], 3, '... we should get the 3rd record'); +is($value->[0], 3, '... we should get the 3rd record rt76695'); ($value) = $sth->fetchrow; -is($value, 4, '... we should get the 4th record'); +is($value, 4, '... we should get the 4th record rt 76695'); # rt 76410 - fetch after fetch absolute always returns the same row $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE, 2); -is($value->[0], 2, "... we should get the 2nd row"); +is($value->[0], 2, "... we should get the 2nd row rt76410_2"); ($value) = $sth->fetchrow; -is($value, 3, "... we should get the 3rd row"); +is($value, 3, "... we should get the 3rd row rt76410_2"); $sth->finish(); drop_table($dbh); From 9e5f4baf85cdbf23f16967c212a14eb32b575d56 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 21 Jun 2012 15:40:46 -0400 Subject: [PATCH 234/637] Leftover from the rt 76695 fix (rev15280) --- dbdimp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index ebe4cf1f..ca3841dc 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2673,14 +2673,13 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) phs->alen = value_len + phs->alen_incnull; if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { - UV neatsvpvlen = (UV)DBIc_DBISTATE(imp_sth)->neatsvpvlen; + /*UV neatsvpvlen = (UV)DBIc_DBISTATE(imp_sth)->neatsvpvlen;*/ char *val = neatsvpv(phs->sv,10); PerlIO_printf( DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_char() (2): bind %s <== '%.*s' (size %ld/%ld, " + "dbd_rebind_ph_char() (2): bind %s <== %.1000s (size %ld/%ld, " "otype %d(%s), indp %d, at_exec %d)\n", phs->name, - (int)(phs->alen > neatsvpvlen ? neatsvpvlen : phs->alen), (phs->progv) ? val: "", (long)phs->alen, (long)phs->maxlen, phs->ftype,sql_typecode_name(phs->ftype), phs->indp, at_exec); From 1da241284513f2059bb4309f47597e25d5ab726d Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 21 Jun 2012 15:56:46 -0400 Subject: [PATCH 235/637] v1.45_00 [CHANGE IN BEHAVIOUR] - In future versions of DBD::Oracle ora_verbose will be changed so that it is simply a switch to turn DBI's DBD tracing on or off. A true value will turn it on and a false value will turn it off. DBI's "DBD" tracing was not available when ora_verbose was created and ora_verbose adds an additional test to every trace test. [BUG FIXES] - Fixed RT76695 - offset passed to ora_fetch_scroll should not affect normal fetches (Martin J. Evans) - Fixed RT76410 - fetch after fetch absolute always returns the same row (Martin J. Evans); - Fixed RT75721 - does not build with Oracle 9.2 (Martin J. Evans) - Fixed RT71343 - Oracle 9i does not have OCI_ATTR_TAF_ENABLED or OCI_ATTR_RESERVED_15/16 so cannot build (Martin J. Evans) - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) - Fixed RT76268 - ora_taf_sleep was documented as taf_sleep by accident. There was no way to stop the TAF reconnect attempts. If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) [MISCELLANEOUS] - minor change to confusing debug output for input parameters (Martin J. Evans) - RT72989 - add note to trouble shooting guide re this RT and Module::Runtime (Martin J. Evans) --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index 7d1879a2..6b915286 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} +1.45_00 2012-06-21 + [CHANGE IN BEHAVIOUR] - In future versions of DBD::Oracle ora_verbose will be changed From e7da0e3b308c6e74179f0624fcbd783dcbc9bf24 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 21 Jun 2012 20:03:23 +0000 Subject: [PATCH 236/637] release housekeeping git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15329 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 19 ++++++++++--------- META.json | 5 +++-- META.yml | 3 ++- README | 32 ++++++++++++++++++++++++-------- README.mkdn | 36 +++++++++++++++++++++++++++--------- lib/DBD/Oracle.pm | 4 ++++ lib/DBD/Oracle/GetInfo.pm | 4 ++++ lib/DBD/Oracle/Object.pm | 4 ++++ t/51scroll.t | 2 +- 9 files changed, 79 insertions(+), 30 deletions(-) diff --git a/Changes b/Changes index 911ab4d5..96ab7b27 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,15 @@ Revision history for DBD::Oracle -NEXT +1.45_00 2012-06-21 + + [CHANGE IN BEHAVIOUR] + + - In future versions of DBD::Oracle ora_verbose will be changed + so that it is simply a switch to turn DBI's DBD tracing on or off. + A true value will turn it on and a false value will turn it off. + DBI's "DBD" tracing was not available when ora_verbose was created + and ora_verbose adds an additional test to every trace test. + [BUG FIXES] - Fixed RT76695 - offset passed to ora_fetch_scroll should not affect @@ -21,14 +30,6 @@ NEXT If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) - [CHANGE IN BEHAVIOUR] - - - In future versions of DBD::Oracle ora_verbose will be changed - so that it is simply a switch to turn DBI's DBD tracing on or off. - A true value will turn it on and a false value will turn it off. - DBI's "DBD" tracing was not available when ora_verbose was created - and ora_verbose adds an additional test to every trace test. - [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/META.json b/META.json index 4d5b3feb..c53eebeb 100644 --- a/META.json +++ b/META.json @@ -3,10 +3,11 @@ "author" : [ "Tim Bunce ", "John Scoles", - "Yanick Champoux " + "Yanick Champoux ", + "Martin J. Evans " ], "dynamic_config" : 0, - "generated_by" : "Dist::Zilla version 4.300009, CPAN::Meta::Converter version 2.120630", + "generated_by" : "Dist::Zilla version 4.300016, CPAN::Meta::Converter version 2.120630", "license" : [ "perl_5" ], diff --git a/META.yml b/META.yml index c9e73036..17e78df0 100644 --- a/META.yml +++ b/META.yml @@ -4,6 +4,7 @@ author: - 'Tim Bunce ' - 'John Scoles' - 'Yanick Champoux ' + - 'Martin J. Evans ' build_requires: Carp: 0 Config: 0 @@ -20,7 +21,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 -generated_by: 'Dist::Zilla version 4.300009, CPAN::Meta::Converter version 2.120630' +generated_by: 'Dist::Zilla version 4.300016, CPAN::Meta::Converter version 2.120630' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html diff --git a/README b/README index a02414bc..67e6d338 100644 --- a/README +++ b/README @@ -75,7 +75,7 @@ CONSTANTS :ora_fail_over OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR - OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY DBI CLASS METHODS connect @@ -245,7 +245,7 @@ DBI CLASS METHODS #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function @@ -274,6 +274,9 @@ DBI CLASS METHODS } elsif ($fo_event == OCI_FO_ERROR){ print " Failover error Sleeping...\n"; + # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY + # If you want to stop retrying just return 0 + return OCI_FO_RETRY; } else { printf(" Bad Failover Event: %d.\n", $fo_event); @@ -378,9 +381,14 @@ DBI CLASS METHODS return; } + Note you'll probably have to use the full name space when setting the + TAF function e.g., 'main::my_taf_function' and not just + 'my_taf_function'. + ora_taf_sleep - The amount of time in seconds the OCI client will sleep between - attempting successive failover events when the event is OCI_FO_ERROR. + The amount of time in seconds DBD::Oracle will sleep between attempting + successive failover events when the event is OCI_FO_ERROR and + OCI_FO_RETRY is returned from the TAF handler. ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, @@ -524,6 +532,12 @@ DBI CLASS METHODS In both cases the DBD::Oracle trace level is set to 6, which is the highest level tracing most of the calls to OCI. + NOTE: In future versions of DBD::Oracle ora_verbose will be changed so + that it is simply a switch to turn DBI's DBD tracing on or off. A true + value will turn it on and a false value will turn it off. DBI's "DBD" + tracing was not available when ora_verbose was created and ora_verbose + adds an additional test to every trace test. + ora_oci_success_warn Use this value to print otherwise silent OCI warnings that may happen when an execute or fetch returns "Success With Info" or when you want to @@ -3633,7 +3647,7 @@ OTHER DATA TYPES print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" - Support for Insert of XMLType (ORA_XMLTYPE) + Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as @@ -3665,7 +3679,7 @@ OTHER DATA TYPES that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. - Binding Cursors + Binding Cursors Cursors can be returned from PL/SQL blocks, either from stored functions (or procedures with OUT parameters) or from direct "OPEN" statements, as shown below: @@ -3734,7 +3748,7 @@ OTHER DATA TYPES See the "curref.pl" script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. - Fetching Nested Cursors + Fetching Nested Cursors Oracle supports the use of select list expressions of type REF CURSOR. These may be explicit cursor expressions - "CURSOR(SELECT ...)", or calls to PL/SQL functions which return REF CURSOR values. The values of @@ -3788,7 +3802,7 @@ OTHER DATA TYPES my ($nested) = $sth->fetchrow_array; while ( my @row = $nested->fetchrow_array ) { ... } - Pre-fetching Nested Cursors + Pre-fetching Nested Cursors By default, DBD::Oracle pre-fetches rows in order to reduce the number of round trips to the server. For queries which do not involve nested cursors, the number of pre-fetched rows is controlled by the DBI @@ -4203,6 +4217,8 @@ AUTHORS * Yanick Champoux + * Martin J. Evans + COPYRIGHT AND LICENSE This software is copyright (c) 1994 by Tim Bunce. diff --git a/README.mkdn b/README.mkdn index 05e0faed..137888d0 100644 --- a/README.mkdn +++ b/README.mkdn @@ -89,7 +89,7 @@ These constants are used to set the orientation of a fetch on a scrollable curso - :ora_fail_over OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR - OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY # DBI CLASS METHODS @@ -247,7 +247,7 @@ attempts another event. #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function @@ -276,6 +276,9 @@ attempts another event. } elsif ($fo_event == OCI_FO_ERROR){ print " Failover error Sleeping...\n"; + # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY + # If you want to stop retrying just return 0 + return OCI_FO_RETRY; } else { printf(" Bad Failover Event: %d.\n", $fo_event); @@ -389,10 +392,15 @@ and the failover type. Below is an example of a TAF function return; } +Note you'll probably have to use the full name space when setting the +TAF function e.g., 'main::my_taf_function' and not just +'my_taf_function'. + #### ora_taf_sleep -The amount of time in seconds the OCI client will sleep between attempting -successive failover events when the event is OCI_FO_ERROR. +The amount of time in seconds DBD::Oracle will sleep between attempting +successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY +is returned from the TAF handler. #### ora_session_mode @@ -550,6 +558,12 @@ or set it directly on the DB handle like this; In both cases the DBD::Oracle trace level is set to 6, which is the highest level tracing most of the calls to OCI. +NOTE: In future versions of DBD::Oracle ora_verbose will be changed so +that it is simply a switch to turn DBI's DBD tracing on or off. A +true value will turn it on and a false value will turn it off. DBI's +"DBD" tracing was not available when ora_verbose was created and +ora_verbose adds an additional test to every trace test. + #### ora_oci_success_warn Use this value to print otherwise silent OCI warnings that may happen @@ -3649,7 +3663,7 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" -#### Support for Insert of XMLType (ORA_XMLTYPE) +## Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For @@ -3679,7 +3693,7 @@ one can insert data using this code In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. -#### Binding Cursors +## Binding Cursors Cursors can be returned from PL/SQL blocks, either from stored functions (or procedures with OUT parameters) or @@ -3749,7 +3763,7 @@ PL/SQL handle is re-bound, re-executed or destroyed. See the `curref.pl` script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. -#### Fetching Nested Cursors +## Fetching Nested Cursors Oracle supports the use of select list expressions of type REF CURSOR. These may be explicit cursor expressions - `CURSOR(SELECT ...)`, or @@ -3804,7 +3818,7 @@ previous section can be fetched as a nested cursor as follows: my ($nested) = $sth->fetchrow_array; while ( my @row = $nested->fetchrow_array ) { ... } -#### Pre-fetching Nested Cursors +## Pre-fetching Nested Cursors By default, DBD::Oracle pre-fetches rows in order to reduce the number of round trips to the server. For queries which do not involve nested cursors, @@ -4252,9 +4266,13 @@ John Scoles Yanick Champoux +- * + +Martin J. Evans + # COPYRIGHT AND LICENSE This software is copyright (c) 1994 by Tim Bunce. This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 1f2cc52e..cd872875 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -5488,6 +5488,10 @@ John Scoles Yanick Champoux +=item * + +Martin J. Evans + =back =head1 COPYRIGHT AND LICENSE diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index cd80a9a2..5978b122 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -313,6 +313,10 @@ John Scoles Yanick Champoux +=item * + +Martin J. Evans + =back =head1 COPYRIGHT AND LICENSE diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 1cb08569..25a905e8 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -57,6 +57,10 @@ John Scoles Yanick Champoux +=item * + +Martin J. Evans + =back =head1 COPYRIGHT AND LICENSE diff --git a/t/51scroll.t b/t/51scroll.t index 0bedd9ca..24266bab 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -34,7 +34,7 @@ ok ($dbh->{RowCacheSize} = 10); isa_ok($dbh, "DBI::db"); my $table = table(); -#drop_table($dbh); + $dbh->do(qq{ CREATE TABLE $table ( From 913da12847a91118c6fdfa1c70658d4d002f0668 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 21 Jun 2012 20:03:23 +0000 Subject: [PATCH 237/637] release housekeeping git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15329 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 19 ++++++++++--------- META.json | 5 +++-- META.yml | 3 ++- README | 32 ++++++++++++++++++++++++-------- README.mkdn | 36 +++++++++++++++++++++++++++--------- lib/DBD/Oracle.pm | 4 ++++ lib/DBD/Oracle/GetInfo.pm | 4 ++++ lib/DBD/Oracle/Object.pm | 4 ++++ t/51scroll.t | 2 +- 9 files changed, 79 insertions(+), 30 deletions(-) diff --git a/Changes b/Changes index 911ab4d5..96ab7b27 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,15 @@ Revision history for DBD::Oracle -NEXT +1.45_00 2012-06-21 + + [CHANGE IN BEHAVIOUR] + + - In future versions of DBD::Oracle ora_verbose will be changed + so that it is simply a switch to turn DBI's DBD tracing on or off. + A true value will turn it on and a false value will turn it off. + DBI's "DBD" tracing was not available when ora_verbose was created + and ora_verbose adds an additional test to every trace test. + [BUG FIXES] - Fixed RT76695 - offset passed to ora_fetch_scroll should not affect @@ -21,14 +30,6 @@ NEXT If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) - [CHANGE IN BEHAVIOUR] - - - In future versions of DBD::Oracle ora_verbose will be changed - so that it is simply a switch to turn DBI's DBD tracing on or off. - A true value will turn it on and a false value will turn it off. - DBI's "DBD" tracing was not available when ora_verbose was created - and ora_verbose adds an additional test to every trace test. - [MISCELLANEOUS] - minor change to confusing debug output for input parameters diff --git a/META.json b/META.json index 4d5b3feb..c53eebeb 100644 --- a/META.json +++ b/META.json @@ -3,10 +3,11 @@ "author" : [ "Tim Bunce ", "John Scoles", - "Yanick Champoux " + "Yanick Champoux ", + "Martin J. Evans " ], "dynamic_config" : 0, - "generated_by" : "Dist::Zilla version 4.300009, CPAN::Meta::Converter version 2.120630", + "generated_by" : "Dist::Zilla version 4.300016, CPAN::Meta::Converter version 2.120630", "license" : [ "perl_5" ], diff --git a/META.yml b/META.yml index c9e73036..17e78df0 100644 --- a/META.yml +++ b/META.yml @@ -4,6 +4,7 @@ author: - 'Tim Bunce ' - 'John Scoles' - 'Yanick Champoux ' + - 'Martin J. Evans ' build_requires: Carp: 0 Config: 0 @@ -20,7 +21,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 -generated_by: 'Dist::Zilla version 4.300009, CPAN::Meta::Converter version 2.120630' +generated_by: 'Dist::Zilla version 4.300016, CPAN::Meta::Converter version 2.120630' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html diff --git a/README b/README index a02414bc..67e6d338 100644 --- a/README +++ b/README @@ -75,7 +75,7 @@ CONSTANTS :ora_fail_over OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR - OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY DBI CLASS METHODS connect @@ -245,7 +245,7 @@ DBI CLASS METHODS #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function @@ -274,6 +274,9 @@ DBI CLASS METHODS } elsif ($fo_event == OCI_FO_ERROR){ print " Failover error Sleeping...\n"; + # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY + # If you want to stop retrying just return 0 + return OCI_FO_RETRY; } else { printf(" Bad Failover Event: %d.\n", $fo_event); @@ -378,9 +381,14 @@ DBI CLASS METHODS return; } + Note you'll probably have to use the full name space when setting the + TAF function e.g., 'main::my_taf_function' and not just + 'my_taf_function'. + ora_taf_sleep - The amount of time in seconds the OCI client will sleep between - attempting successive failover events when the event is OCI_FO_ERROR. + The amount of time in seconds DBD::Oracle will sleep between attempting + successive failover events when the event is OCI_FO_ERROR and + OCI_FO_RETRY is returned from the TAF handler. ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, @@ -524,6 +532,12 @@ DBI CLASS METHODS In both cases the DBD::Oracle trace level is set to 6, which is the highest level tracing most of the calls to OCI. + NOTE: In future versions of DBD::Oracle ora_verbose will be changed so + that it is simply a switch to turn DBI's DBD tracing on or off. A true + value will turn it on and a false value will turn it off. DBI's "DBD" + tracing was not available when ora_verbose was created and ora_verbose + adds an additional test to every trace test. + ora_oci_success_warn Use this value to print otherwise silent OCI warnings that may happen when an execute or fetch returns "Success With Info" or when you want to @@ -3633,7 +3647,7 @@ OTHER DATA TYPES print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" - Support for Insert of XMLType (ORA_XMLTYPE) + Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as @@ -3665,7 +3679,7 @@ OTHER DATA TYPES that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. - Binding Cursors + Binding Cursors Cursors can be returned from PL/SQL blocks, either from stored functions (or procedures with OUT parameters) or from direct "OPEN" statements, as shown below: @@ -3734,7 +3748,7 @@ OTHER DATA TYPES See the "curref.pl" script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. - Fetching Nested Cursors + Fetching Nested Cursors Oracle supports the use of select list expressions of type REF CURSOR. These may be explicit cursor expressions - "CURSOR(SELECT ...)", or calls to PL/SQL functions which return REF CURSOR values. The values of @@ -3788,7 +3802,7 @@ OTHER DATA TYPES my ($nested) = $sth->fetchrow_array; while ( my @row = $nested->fetchrow_array ) { ... } - Pre-fetching Nested Cursors + Pre-fetching Nested Cursors By default, DBD::Oracle pre-fetches rows in order to reduce the number of round trips to the server. For queries which do not involve nested cursors, the number of pre-fetched rows is controlled by the DBI @@ -4203,6 +4217,8 @@ AUTHORS * Yanick Champoux + * Martin J. Evans + COPYRIGHT AND LICENSE This software is copyright (c) 1994 by Tim Bunce. diff --git a/README.mkdn b/README.mkdn index 05e0faed..137888d0 100644 --- a/README.mkdn +++ b/README.mkdn @@ -89,7 +89,7 @@ These constants are used to set the orientation of a fetch on a scrollable curso - :ora_fail_over OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR - OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY # DBI CLASS METHODS @@ -247,7 +247,7 @@ attempts another event. #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taf'}); + my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); #create the perl TAF event function @@ -276,6 +276,9 @@ attempts another event. } elsif ($fo_event == OCI_FO_ERROR){ print " Failover error Sleeping...\n"; + # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY + # If you want to stop retrying just return 0 + return OCI_FO_RETRY; } else { printf(" Bad Failover Event: %d.\n", $fo_event); @@ -389,10 +392,15 @@ and the failover type. Below is an example of a TAF function return; } +Note you'll probably have to use the full name space when setting the +TAF function e.g., 'main::my_taf_function' and not just +'my_taf_function'. + #### ora_taf_sleep -The amount of time in seconds the OCI client will sleep between attempting -successive failover events when the event is OCI_FO_ERROR. +The amount of time in seconds DBD::Oracle will sleep between attempting +successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY +is returned from the TAF handler. #### ora_session_mode @@ -550,6 +558,12 @@ or set it directly on the DB handle like this; In both cases the DBD::Oracle trace level is set to 6, which is the highest level tracing most of the calls to OCI. +NOTE: In future versions of DBD::Oracle ora_verbose will be changed so +that it is simply a switch to turn DBI's DBD tracing on or off. A +true value will turn it on and a false value will turn it off. DBI's +"DBD" tracing was not available when ora_verbose was created and +ora_verbose adds an additional test to every trace test. + #### ora_oci_success_warn Use this value to print otherwise silent OCI warnings that may happen @@ -3649,7 +3663,7 @@ Examples: print "$i0 to $o0, $i1 to $o1\n"; # Result is : "'' to '(undef)', 'Something else' to '1'" -#### Support for Insert of XMLType (ORA_XMLTYPE) +## Support for Insert of XMLType (ORA_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For @@ -3679,7 +3693,7 @@ one can insert data using this code In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. -#### Binding Cursors +## Binding Cursors Cursors can be returned from PL/SQL blocks, either from stored functions (or procedures with OUT parameters) or @@ -3749,7 +3763,7 @@ PL/SQL handle is re-bound, re-executed or destroyed. See the `curref.pl` script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. -#### Fetching Nested Cursors +## Fetching Nested Cursors Oracle supports the use of select list expressions of type REF CURSOR. These may be explicit cursor expressions - `CURSOR(SELECT ...)`, or @@ -3804,7 +3818,7 @@ previous section can be fetched as a nested cursor as follows: my ($nested) = $sth->fetchrow_array; while ( my @row = $nested->fetchrow_array ) { ... } -#### Pre-fetching Nested Cursors +## Pre-fetching Nested Cursors By default, DBD::Oracle pre-fetches rows in order to reduce the number of round trips to the server. For queries which do not involve nested cursors, @@ -4252,9 +4266,13 @@ John Scoles Yanick Champoux +- * + +Martin J. Evans + # COPYRIGHT AND LICENSE This software is copyright (c) 1994 by Tim Bunce. This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. +the same terms as the Perl 5 programming language system itself. \ No newline at end of file diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 1f2cc52e..cd872875 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -5488,6 +5488,10 @@ John Scoles Yanick Champoux +=item * + +Martin J. Evans + =back =head1 COPYRIGHT AND LICENSE diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index cd80a9a2..5978b122 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -313,6 +313,10 @@ John Scoles Yanick Champoux +=item * + +Martin J. Evans + =back =head1 COPYRIGHT AND LICENSE diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 1cb08569..25a905e8 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -57,6 +57,10 @@ John Scoles Yanick Champoux +=item * + +Martin J. Evans + =back =head1 COPYRIGHT AND LICENSE diff --git a/t/51scroll.t b/t/51scroll.t index 0bedd9ca..24266bab 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -34,7 +34,7 @@ ok ($dbh->{RowCacheSize} = 10); isa_ok($dbh, "DBI::db"); my $table = table(); -#drop_table($dbh); + $dbh->do(qq{ CREATE TABLE $table ( From 6dec33f9974aebedbb29a6cc42f12b66f83618cf Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 08:47:29 +0000 Subject: [PATCH 238/637] wrong rt # git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15331 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index 96ab7b27..e0bf425b 100644 --- a/Changes +++ b/Changes @@ -25,7 +25,7 @@ Revision history for DBD::Oracle - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) - - Fixed RT76268 - ora_taf_sleep was documented as taf_sleep by + - Fixed RT76269 - ora_taf_sleep was documented as taf_sleep by accident. There was no way to stop the TAF reconnect attempts. If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) From 5eee648c48e7899dd5056a9cbac8622acc0fd678 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 08:47:29 +0000 Subject: [PATCH 239/637] wrong rt # git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15331 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index 96ab7b27..e0bf425b 100644 --- a/Changes +++ b/Changes @@ -25,7 +25,7 @@ Revision history for DBD::Oracle - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) - - Fixed RT76268 - ora_taf_sleep was documented as taf_sleep by + - Fixed RT76269 - ora_taf_sleep was documented as taf_sleep by accident. There was no way to stop the TAF reconnect attempts. If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) From 1aa6e510f591fce43222d4d9f47cd63d97bcb585 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 09:07:10 +0000 Subject: [PATCH 240/637] rt71819 - troubleshoiting entry for bound output parameters returned in wrong order git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15332 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 +++++++ lib/DBD/Oracle/Troubleshooting.pm | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/Changes b/Changes index e0bf425b..4a11684e 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,12 @@ Revision history for DBD::Oracle +1.NN next release + + [MISCELLANEOUS] + + - Added a trouble shooting entry for RT71819 - bound output + parameters may be returned in the wrong order. + 1.45_00 2012-06-21 [CHANGE IN BEHAVIOUR] diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 4c74cf61..9fb168c2 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -375,6 +375,17 @@ forking). It looks like this was fixed in 0.012 of Module::Runtime. +=head2 bin_param_inout spapping return values + +See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) + +It seems that in some older versions of Oracle Instant Client +(certainly 10.2.0.4.0) when output parameters are bound with lengths +greater than 3584 the output parameters can be returned in the wrong +placeholders. + +It is reported fixed in Instant Client 11.2.0.2.0. + =head1 AUTHORS =over 4 From b24556ff1ce2a4decdc2d6c15d9cb5ee937c95b7 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 09:07:10 +0000 Subject: [PATCH 241/637] rt71819 - troubleshoiting entry for bound output parameters returned in wrong order git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15332 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 +++++++ lib/DBD/Oracle/Troubleshooting.pm | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/Changes b/Changes index e0bf425b..4a11684e 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,12 @@ Revision history for DBD::Oracle +1.NN next release + + [MISCELLANEOUS] + + - Added a trouble shooting entry for RT71819 - bound output + parameters may be returned in the wrong order. + 1.45_00 2012-06-21 [CHANGE IN BEHAVIOUR] diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 4c74cf61..9fb168c2 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -375,6 +375,17 @@ forking). It looks like this was fixed in 0.012 of Module::Runtime. +=head2 bin_param_inout spapping return values + +See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) + +It seems that in some older versions of Oracle Instant Client +(certainly 10.2.0.4.0) when output parameters are bound with lengths +greater than 3584 the output parameters can be returned in the wrong +placeholders. + +It is reported fixed in Instant Client 11.2.0.2.0. + =head1 AUTHORS =over 4 From 177806765cac0d62179b3c184815d4d968be7ce6 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 11:14:06 +0000 Subject: [PATCH 242/637] Fixed redeclaration of $len in 31lob.t git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15333 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 +++++- t/31lob.t | 25 +++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index 4a11684e..3877ed47 100644 --- a/Changes +++ b/Changes @@ -2,10 +2,14 @@ Revision history for DBD::Oracle 1.NN next release + [BUG FIXES] + + - fixed redclaration of $len in 31lob.t - (Martin J, Evans) + [MISCELLANEOUS] - Added a trouble shooting entry for RT71819 - bound output - parameters may be returned in the wrong order. + parameters may be returned in the wrong order (Martin J. Evans) 1.45_00 2012-06-21 diff --git a/t/31lob.t b/t/31lob.t index 9f8c99a2..27d66afb 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -10,15 +10,15 @@ require 'nchar_test_lib.pl'; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - + my $dbh = DBI->connect($dsn, $dbuser, '',{ PrintError => 0, }); -plan $dbh ? ( tests => 12 ) +plan $dbh ? ( tests => 12 ) : ( skip_all => "Unable to connect to Oracle" ); my $table = table(); drop_table($dbh); - + $dbh->do( <<"END_SQL" ); CREATE TABLE $table ( id INTEGER NOT NULL, @@ -100,12 +100,21 @@ sub have_v_session { is( ref $loc, "OCILobLocatorPtr", "returned valid locator" ); is( $dbh->ora_lob_is_init($loc), 1, "returned initialized locator" ); - + # write string > 32k $large_value = 'ABCD' x 10_000; $dbh->ora_lob_write( $loc, 1, $large_value ); - is( $dbh->ora_lob_length($loc), length($large_value), "returned length" ); + eval { + $len = $dbh->ora_lob_length($loc); + }; + if ($@) { + note ("It appears your Oracle or Oracle client has problems with ora_lob_length(lob_locator). We have seen this before - see RT 69350. The test is not going to fail because of this because we have seen it before but if you are using lob locators you might want to consider upgrading your Oracle client to 11.2 where we know this test works"); + done_testing(); + } else { + is( $len, length($large_value), "returned length" ); + + } is( $dbh->ora_lob_read( $loc, 1, length($large_value) ), $large_value, "returned written value" ); @@ -135,7 +144,7 @@ sub have_v_session { if $dbh->err == 6553 || $dbh->err == 600; } - TODO: { + TODO: { local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" if ORA_OCI() =~ /^11\.2\./; @@ -164,7 +173,7 @@ sub have_v_session { LOOP buffer := DBMS_LOB.SUBSTR(p_in, 1024, pos); - DBMS_LOB.WRITEAPPEND(p_out, UTL_RAW.LENGTH(buffer), + DBMS_LOB.WRITEAPPEND(p_out, UTL_RAW.LENGTH(buffer), UTL_RAW.CAST_TO_RAW(LOWER(UTL_RAW.CAST_TO_VARCHAR2(buffer)))); DBMS_LOB.WRITEAPPEND(p_inout, UTL_RAW.LENGTH(buffer), buffer); @@ -184,7 +193,7 @@ END_SQL $sth->execute; }; - + local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" if ORA_OCI() =~ /^11\.2\./; From 7bb81d86fdfd023ec894ccfa3f68a0d309d31f12 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 11:14:06 +0000 Subject: [PATCH 243/637] Fixed redeclaration of $len in 31lob.t git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15333 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 +++++- t/31lob.t | 25 +++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index 4a11684e..3877ed47 100644 --- a/Changes +++ b/Changes @@ -2,10 +2,14 @@ Revision history for DBD::Oracle 1.NN next release + [BUG FIXES] + + - fixed redclaration of $len in 31lob.t - (Martin J, Evans) + [MISCELLANEOUS] - Added a trouble shooting entry for RT71819 - bound output - parameters may be returned in the wrong order. + parameters may be returned in the wrong order (Martin J. Evans) 1.45_00 2012-06-21 diff --git a/t/31lob.t b/t/31lob.t index 9f8c99a2..27d66afb 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -10,15 +10,15 @@ require 'nchar_test_lib.pl'; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - + my $dbh = DBI->connect($dsn, $dbuser, '',{ PrintError => 0, }); -plan $dbh ? ( tests => 12 ) +plan $dbh ? ( tests => 12 ) : ( skip_all => "Unable to connect to Oracle" ); my $table = table(); drop_table($dbh); - + $dbh->do( <<"END_SQL" ); CREATE TABLE $table ( id INTEGER NOT NULL, @@ -100,12 +100,21 @@ sub have_v_session { is( ref $loc, "OCILobLocatorPtr", "returned valid locator" ); is( $dbh->ora_lob_is_init($loc), 1, "returned initialized locator" ); - + # write string > 32k $large_value = 'ABCD' x 10_000; $dbh->ora_lob_write( $loc, 1, $large_value ); - is( $dbh->ora_lob_length($loc), length($large_value), "returned length" ); + eval { + $len = $dbh->ora_lob_length($loc); + }; + if ($@) { + note ("It appears your Oracle or Oracle client has problems with ora_lob_length(lob_locator). We have seen this before - see RT 69350. The test is not going to fail because of this because we have seen it before but if you are using lob locators you might want to consider upgrading your Oracle client to 11.2 where we know this test works"); + done_testing(); + } else { + is( $len, length($large_value), "returned length" ); + + } is( $dbh->ora_lob_read( $loc, 1, length($large_value) ), $large_value, "returned written value" ); @@ -135,7 +144,7 @@ sub have_v_session { if $dbh->err == 6553 || $dbh->err == 600; } - TODO: { + TODO: { local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" if ORA_OCI() =~ /^11\.2\./; @@ -164,7 +173,7 @@ sub have_v_session { LOOP buffer := DBMS_LOB.SUBSTR(p_in, 1024, pos); - DBMS_LOB.WRITEAPPEND(p_out, UTL_RAW.LENGTH(buffer), + DBMS_LOB.WRITEAPPEND(p_out, UTL_RAW.LENGTH(buffer), UTL_RAW.CAST_TO_RAW(LOWER(UTL_RAW.CAST_TO_VARCHAR2(buffer)))); DBMS_LOB.WRITEAPPEND(p_inout, UTL_RAW.LENGTH(buffer), buffer); @@ -184,7 +193,7 @@ END_SQL $sth->execute; }; - + local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" if ORA_OCI() =~ /^11\.2\./; From 9f4b513e20159264b1c4fb810f434c0c9f637ae4 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 11:34:06 +0000 Subject: [PATCH 244/637] RT55028 - stop seg faulting when reading emtpy lobs git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15334 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++- Oracle.xs | 93 +++++++++++++++++++++++++---------------------- lib/DBD/Oracle.pm | 6 +++ 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/Changes b/Changes index 3877ed47..563000ae 100644 --- a/Changes +++ b/Changes @@ -4,7 +4,10 @@ Revision history for DBD::Oracle [BUG FIXES] - - fixed redclaration of $len in 31lob.t - (Martin J, Evans) + - fixed redeclaration of $len in 31lob.t - (Martin J, Evans) + + - RT55028 - stop segfaulting when attempting to read empty lobs + (Martin J. Evans) [MISCELLANEOUS] diff --git a/Oracle.xs b/Oracle.xs index 4f6b1a62..0b2b6824 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -557,54 +557,61 @@ ora_lob_read(dbh, locator, offset, length) sword status; ub1 csform; CODE: + csform = SQLCS_IMPLICIT; + /* NOTE, if length is 0 this will create an empty SV of undef + see RT55028 */ dest_sv = sv_2mortal(newSV(length*4)); /*LAB: crude hack that works... tim did it else where XXX */ - SvPOK_on(dest_sv); - bufp_len = SvLEN(dest_sv); /* XXX bytes not chars? (lab: yes) */ - bufp = SvPVX(dest_sv); - amtp = length; /* if utf8 and clob/nclob: in: chars, out: bytes */ - /* http://www.lc.leidenuniv.nl/awcourse/oracle/appdev.920/a96584/oci16m40.htm#427818 */ - /* if locator is CLOB and data is UTF8 and not in bytes pragma */ - /* if (0 && SvUTF8(dest_sv) && !IN_BYTES) { amtp = sv_len_utf8(dest_sv); } */ - /* added by lab: */ - OCILobCharSetForm_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetForm"); - dest_sv = &PL_sv_undef; - return; - } - { - /* see rt 75163 */ - boolean is_open; - - OCILobFileIsOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &is_open, status); - if (status == OCI_SUCCESS && !is_open) { - OCILobFileOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, - (ub1)OCI_FILE_READONLY, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCILobFileOpen"); - dest_sv = &PL_sv_undef; + + if (length > 0) { + SvPOK_on(dest_sv); + bufp_len = SvLEN(dest_sv); /* XXX bytes not chars? (lab: yes) */ + bufp = SvPVX(dest_sv); + amtp = length; /* if utf8 and clob/nclob: in: chars, out: bytes */ + /* http://www.lc.leidenuniv.nl/awcourse/oracle/appdev.920/a96584/oci16m40.htm#427818 */ + /* if locator is CLOB and data is UTF8 and not in bytes pragma */ + /* if (0 && SvUTF8(dest_sv) && !IN_BYTES) { amtp = sv_len_utf8(dest_sv); } */ + /* added by lab: */ + OCILobCharSetForm_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetForm"); + dest_sv = &PL_sv_undef; + return; + } + { + /* see rt 75163 */ + boolean is_open; + + OCILobFileIsOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &is_open, status); + if (status == OCI_SUCCESS && !is_open) { + OCILobFileOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, + (ub1)OCI_FILE_READONLY, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCILobFileOpen"); + dest_sv = &PL_sv_undef; + } } } - } - OCILobRead_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, - &amtp, (ub4)offset, /* offset starts at 1 */ - bufp, (ub4)bufp_len, - 0, 0, (ub2)0, csform, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCILobRead"); - dest_sv = &PL_sv_undef; - } - else { - SvCUR(dest_sv) = amtp; /* always bytes here */ - *SvEND(dest_sv) = '\0'; - if (csform){ - if (CSFORM_IMPLIES_UTF8(csform)){ - SvUTF8_on(dest_sv); - } - } - } + OCILobRead_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, + &amtp, (ub4)offset, /* offset starts at 1 */ + bufp, (ub4)bufp_len, + 0, 0, (ub2)0, csform, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCILobRead"); + dest_sv = &PL_sv_undef; + } + else { + SvCUR(dest_sv) = amtp; /* always bytes here */ + *SvEND(dest_sv) = '\0'; + if (csform){ + if (CSFORM_IMPLIES_UTF8(csform)){ + SvUTF8_on(dest_sv); + } + } + } + } /* length > 0 */ + ST(0) = dest_sv; void diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index cd872875..9f667697 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -4188,6 +4188,12 @@ handle are lost, the handle is destroyed and the locators are freed. Read a portion of the LOB. $offset starts at 1. Uses the Oracle OCILobRead function. +NOTE: DBD::Oracle post 1.46 will return undef for any read lob if the +length specified in the ora_lob_read is 0. See RT 55028. This avoids +the potential problem with empty lobs (created with empty_clob) which +return a length of 0 from ora_lob_length and prior to 1.46 a call to +ora_lob_read with a 0 length would segfault. + =item ora_lob_write $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); From 000f5c42ec828ed6eb27deed22cac9e08f5f9cd7 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 11:34:06 +0000 Subject: [PATCH 245/637] RT55028 - stop seg faulting when reading emtpy lobs git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15334 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++- Oracle.xs | 93 +++++++++++++++++++++++++---------------------- lib/DBD/Oracle.pm | 6 +++ 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/Changes b/Changes index 3877ed47..563000ae 100644 --- a/Changes +++ b/Changes @@ -4,7 +4,10 @@ Revision history for DBD::Oracle [BUG FIXES] - - fixed redclaration of $len in 31lob.t - (Martin J, Evans) + - fixed redeclaration of $len in 31lob.t - (Martin J, Evans) + + - RT55028 - stop segfaulting when attempting to read empty lobs + (Martin J. Evans) [MISCELLANEOUS] diff --git a/Oracle.xs b/Oracle.xs index 4f6b1a62..0b2b6824 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -557,54 +557,61 @@ ora_lob_read(dbh, locator, offset, length) sword status; ub1 csform; CODE: + csform = SQLCS_IMPLICIT; + /* NOTE, if length is 0 this will create an empty SV of undef + see RT55028 */ dest_sv = sv_2mortal(newSV(length*4)); /*LAB: crude hack that works... tim did it else where XXX */ - SvPOK_on(dest_sv); - bufp_len = SvLEN(dest_sv); /* XXX bytes not chars? (lab: yes) */ - bufp = SvPVX(dest_sv); - amtp = length; /* if utf8 and clob/nclob: in: chars, out: bytes */ - /* http://www.lc.leidenuniv.nl/awcourse/oracle/appdev.920/a96584/oci16m40.htm#427818 */ - /* if locator is CLOB and data is UTF8 and not in bytes pragma */ - /* if (0 && SvUTF8(dest_sv) && !IN_BYTES) { amtp = sv_len_utf8(dest_sv); } */ - /* added by lab: */ - OCILobCharSetForm_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetForm"); - dest_sv = &PL_sv_undef; - return; - } - { - /* see rt 75163 */ - boolean is_open; - - OCILobFileIsOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &is_open, status); - if (status == OCI_SUCCESS && !is_open) { - OCILobFileOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, - (ub1)OCI_FILE_READONLY, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCILobFileOpen"); - dest_sv = &PL_sv_undef; + + if (length > 0) { + SvPOK_on(dest_sv); + bufp_len = SvLEN(dest_sv); /* XXX bytes not chars? (lab: yes) */ + bufp = SvPVX(dest_sv); + amtp = length; /* if utf8 and clob/nclob: in: chars, out: bytes */ + /* http://www.lc.leidenuniv.nl/awcourse/oracle/appdev.920/a96584/oci16m40.htm#427818 */ + /* if locator is CLOB and data is UTF8 and not in bytes pragma */ + /* if (0 && SvUTF8(dest_sv) && !IN_BYTES) { amtp = sv_len_utf8(dest_sv); } */ + /* added by lab: */ + OCILobCharSetForm_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, locator, &csform, status ); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCILobCharSetForm"); + dest_sv = &PL_sv_undef; + return; + } + { + /* see rt 75163 */ + boolean is_open; + + OCILobFileIsOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &is_open, status); + if (status == OCI_SUCCESS && !is_open) { + OCILobFileOpen_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, + (ub1)OCI_FILE_READONLY, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCILobFileOpen"); + dest_sv = &PL_sv_undef; + } } } - } - OCILobRead_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, - &amtp, (ub4)offset, /* offset starts at 1 */ - bufp, (ub4)bufp_len, - 0, 0, (ub2)0, csform, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCILobRead"); - dest_sv = &PL_sv_undef; - } - else { - SvCUR(dest_sv) = amtp; /* always bytes here */ - *SvEND(dest_sv) = '\0'; - if (csform){ - if (CSFORM_IMPLIES_UTF8(csform)){ - SvUTF8_on(dest_sv); - } - } - } + OCILobRead_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, + &amtp, (ub4)offset, /* offset starts at 1 */ + bufp, (ub4)bufp_len, + 0, 0, (ub2)0, csform, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCILobRead"); + dest_sv = &PL_sv_undef; + } + else { + SvCUR(dest_sv) = amtp; /* always bytes here */ + *SvEND(dest_sv) = '\0'; + if (csform){ + if (CSFORM_IMPLIES_UTF8(csform)){ + SvUTF8_on(dest_sv); + } + } + } + } /* length > 0 */ + ST(0) = dest_sv; void diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index cd872875..9f667697 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -4188,6 +4188,12 @@ handle are lost, the handle is destroyed and the locators are freed. Read a portion of the LOB. $offset starts at 1. Uses the Oracle OCILobRead function. +NOTE: DBD::Oracle post 1.46 will return undef for any read lob if the +length specified in the ora_lob_read is 0. See RT 55028. This avoids +the potential problem with empty lobs (created with empty_clob) which +return a length of 0 from ora_lob_length and prior to 1.46 a call to +ora_lob_read with a 0 length would segfault. + =item ora_lob_write $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); From 86d9171c561218c1d14c18b0e94895c6916ccbc3 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 14:49:16 +0000 Subject: [PATCH 246/637] RT69059 - OCIPing is not defined in Oracle 10.2 for AIX git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15335 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ Oracle.xs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 563000ae..7bbefc8d 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,10 @@ Revision history for DBD::Oracle - RT55028 - stop segfaulting when attempting to read empty lobs (Martin J. Evans) + - RT69059 - Despite OCIPing being documented as added in 10.2 AIX + does not seem to have it in 10.2 leading to undefined symbol - + Martin J. Evans + [MISCELLANEOUS] - Added a trouble shooting entry for RT71819 - bound output diff --git a/Oracle.xs b/Oracle.xs index 0b2b6824..cbb0b140 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -393,7 +393,9 @@ ora_ping(dbh) /*If the listener goes down it is another case as the Listener is needed to establish the connection not maintain it*/ /*so we should stay connected but we cannot get nay new connections*/ { -#if !defined(ORA_OCI_102) + /* RT 69059 - despite OCIPing being introduced in 10.2 + * it is not available in 10.2 for AIX */ +#if !defined(ORA_OCI_102) || (defined(_AIX) && !defined(ORA_OCI_112)) OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); #else vernum = ora_db_version(dbh,imp_dbh); From 2a56742b07ced295d3c7ee03379650aacd4dea72 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 14:49:16 +0000 Subject: [PATCH 247/637] RT69059 - OCIPing is not defined in Oracle 10.2 for AIX git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15335 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ Oracle.xs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 563000ae..7bbefc8d 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,10 @@ Revision history for DBD::Oracle - RT55028 - stop segfaulting when attempting to read empty lobs (Martin J. Evans) + - RT69059 - Despite OCIPing being documented as added in 10.2 AIX + does not seem to have it in 10.2 leading to undefined symbol - + Martin J. Evans + [MISCELLANEOUS] - Added a trouble shooting entry for RT71819 - bound output diff --git a/Oracle.xs b/Oracle.xs index 0b2b6824..cbb0b140 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -393,7 +393,9 @@ ora_ping(dbh) /*If the listener goes down it is another case as the Listener is needed to establish the connection not maintain it*/ /*so we should stay connected but we cannot get nay new connections*/ { -#if !defined(ORA_OCI_102) + /* RT 69059 - despite OCIPing being introduced in 10.2 + * it is not available in 10.2 for AIX */ +#if !defined(ORA_OCI_102) || (defined(_AIX) && !defined(ORA_OCI_112)) OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); #else vernum = ora_db_version(dbh,imp_dbh); From 9403ee6ab8cd4ba7fe3ead7993f475fa22d1660a Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 15:14:58 +0000 Subject: [PATCH 248/637] RT69059 - update comment to reflect the real facts on OCIPing/AIX git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15336 50811bd7-b8ce-0310-adc1-d9db26280581 --- Oracle.xs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Oracle.xs b/Oracle.xs index cbb0b140..241dae6f 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -394,7 +394,12 @@ ora_ping(dbh) /*so we should stay connected but we cannot get nay new connections*/ { /* RT 69059 - despite OCIPing being introduced in 10.2 - * it is not available in 10.2 for AIX */ + * it is not available in all versions of 10.2 for AIX + * e.g., 10.2.0.4 does not have it and 10.2.0.5 does + * see http://comments.gmane.org/gmane.comp.lang.perl.modules.dbi.general/16206 + * We don't do versions to that accuracy so for AIX you have + * to wait until 11.2 for OCIPing. + */ #if !defined(ORA_OCI_102) || (defined(_AIX) && !defined(ORA_OCI_112)) OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); #else From 06dba27655f9d26da48c3cb695705d570cf5b5e6 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 15:14:58 +0000 Subject: [PATCH 249/637] RT69059 - update comment to reflect the real facts on OCIPing/AIX git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15336 50811bd7-b8ce-0310-adc1-d9db26280581 --- Oracle.xs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Oracle.xs b/Oracle.xs index cbb0b140..241dae6f 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -394,7 +394,12 @@ ora_ping(dbh) /*so we should stay connected but we cannot get nay new connections*/ { /* RT 69059 - despite OCIPing being introduced in 10.2 - * it is not available in 10.2 for AIX */ + * it is not available in all versions of 10.2 for AIX + * e.g., 10.2.0.4 does not have it and 10.2.0.5 does + * see http://comments.gmane.org/gmane.comp.lang.perl.modules.dbi.general/16206 + * We don't do versions to that accuracy so for AIX you have + * to wait until 11.2 for OCIPing. + */ #if !defined(ORA_OCI_102) || (defined(_AIX) && !defined(ORA_OCI_112)) OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); #else From 2b61eed01fd64c610416c732fa1483a28cdd3548 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 08:47:29 +0000 Subject: [PATCH 250/637] wrong rt # git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15331 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index 6b915286..cb1e2e55 100644 --- a/Changes +++ b/Changes @@ -27,7 +27,7 @@ Revision history for DBD::Oracle - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) - - Fixed RT76268 - ora_taf_sleep was documented as taf_sleep by + - Fixed RT76269 - ora_taf_sleep was documented as taf_sleep by accident. There was no way to stop the TAF reconnect attempts. If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) From c5a2db5100eec263de78b2a738269d77a5a2e832 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 04:07:10 -0500 Subject: [PATCH 251/637] rt71819 - troubleshoiting entry for bound output parameters returned in wrong order git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15332 50811bd7-b8ce-0310-adc1-d9db26280581 Conflicts: Changes lib/DBD/Oracle/Troubleshooting.pm --- Changes | 5 +++++ lib/DBD/Oracle/Troubleshooting.pm | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/Changes b/Changes index cb1e2e55..7e07daac 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,11 @@ Revision history for DBD::Oracle {{$NEXT}} + [MISCELLANEOUS] + + - Added a troubleshooting entry for RT71819 - bound output + parameters may be returned in the wrong order. + 1.45_00 2012-06-21 [CHANGE IN BEHAVIOUR] diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 7821a720..d6a7a112 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -363,4 +363,15 @@ forking). It looks like this was fixed in 0.012 of Module::Runtime. +=head2 bin_param_inout swapping return values + +See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) + +It seems that in some older versions of Oracle Instant Client +(certainly 10.2.0.4.0) when output parameters are bound with lengths +greater than 3584 the output parameters can be returned in the wrong +placeholders. + +It is reported fixed in Instant Client 11.2.0.2.0. + =cut From 2d0510e2852f8d0b80afe463ecfb279a00718d19 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 11:14:06 +0000 Subject: [PATCH 252/637] Fixed redeclaration of $len in 31lob.t git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15333 50811bd7-b8ce-0310-adc1-d9db26280581 Conflicts: Changes --- Changes | 6 +++++- t/31lob.t | 25 +++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index 7e07daac..cd77c9e3 100644 --- a/Changes +++ b/Changes @@ -2,10 +2,14 @@ Revision history for DBD::Oracle {{$NEXT}} + [BUG FIXES] + + - fixed redeclaration of $len in 31lob.t - (Martin J, Evans) + [MISCELLANEOUS] - Added a troubleshooting entry for RT71819 - bound output - parameters may be returned in the wrong order. + parameters may be returned in the wrong order (Martin J. Evans) 1.45_00 2012-06-21 diff --git a/t/31lob.t b/t/31lob.t index 9f8c99a2..27d66afb 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -10,15 +10,15 @@ require 'nchar_test_lib.pl'; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - + my $dbh = DBI->connect($dsn, $dbuser, '',{ PrintError => 0, }); -plan $dbh ? ( tests => 12 ) +plan $dbh ? ( tests => 12 ) : ( skip_all => "Unable to connect to Oracle" ); my $table = table(); drop_table($dbh); - + $dbh->do( <<"END_SQL" ); CREATE TABLE $table ( id INTEGER NOT NULL, @@ -100,12 +100,21 @@ sub have_v_session { is( ref $loc, "OCILobLocatorPtr", "returned valid locator" ); is( $dbh->ora_lob_is_init($loc), 1, "returned initialized locator" ); - + # write string > 32k $large_value = 'ABCD' x 10_000; $dbh->ora_lob_write( $loc, 1, $large_value ); - is( $dbh->ora_lob_length($loc), length($large_value), "returned length" ); + eval { + $len = $dbh->ora_lob_length($loc); + }; + if ($@) { + note ("It appears your Oracle or Oracle client has problems with ora_lob_length(lob_locator). We have seen this before - see RT 69350. The test is not going to fail because of this because we have seen it before but if you are using lob locators you might want to consider upgrading your Oracle client to 11.2 where we know this test works"); + done_testing(); + } else { + is( $len, length($large_value), "returned length" ); + + } is( $dbh->ora_lob_read( $loc, 1, length($large_value) ), $large_value, "returned written value" ); @@ -135,7 +144,7 @@ sub have_v_session { if $dbh->err == 6553 || $dbh->err == 600; } - TODO: { + TODO: { local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" if ORA_OCI() =~ /^11\.2\./; @@ -164,7 +173,7 @@ sub have_v_session { LOOP buffer := DBMS_LOB.SUBSTR(p_in, 1024, pos); - DBMS_LOB.WRITEAPPEND(p_out, UTL_RAW.LENGTH(buffer), + DBMS_LOB.WRITEAPPEND(p_out, UTL_RAW.LENGTH(buffer), UTL_RAW.CAST_TO_RAW(LOWER(UTL_RAW.CAST_TO_VARCHAR2(buffer)))); DBMS_LOB.WRITEAPPEND(p_inout, UTL_RAW.LENGTH(buffer), buffer); @@ -184,7 +193,7 @@ END_SQL $sth->execute; }; - + local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" if ORA_OCI() =~ /^11\.2\./; From 469d9bec316daec7bb9a3a98bdc5dbd6d8c7b021 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 27 Jun 2012 08:20:39 +0000 Subject: [PATCH 253/637] Further comments added for OCIPing issue on AIX git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15340 50811bd7-b8ce-0310-adc1-d9db26280581 --- Oracle.xs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Oracle.xs b/Oracle.xs index 241dae6f..e5bce1d0 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -399,6 +399,10 @@ ora_ping(dbh) * see http://comments.gmane.org/gmane.comp.lang.perl.modules.dbi.general/16206 * We don't do versions to that accuracy so for AIX you have * to wait until 11.2 for OCIPing. + * + * Further comments on dbi-dev + * "DBD::Oracle RTs a summary and request for help" suggested it + * was Oracle bug 5759845 and fixes in 10.2.0.2. */ #if !defined(ORA_OCI_102) || (defined(_AIX) && !defined(ORA_OCI_112)) OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); From 39f53ed5db0cc97e2134d4fe30904d3accaeb3fc Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 27 Jun 2012 08:20:39 +0000 Subject: [PATCH 254/637] Further comments added for OCIPing issue on AIX git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15340 50811bd7-b8ce-0310-adc1-d9db26280581 --- Oracle.xs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Oracle.xs b/Oracle.xs index 241dae6f..e5bce1d0 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -399,6 +399,10 @@ ora_ping(dbh) * see http://comments.gmane.org/gmane.comp.lang.perl.modules.dbi.general/16206 * We don't do versions to that accuracy so for AIX you have * to wait until 11.2 for OCIPing. + * + * Further comments on dbi-dev + * "DBD::Oracle RTs a summary and request for help" suggested it + * was Oracle bug 5759845 and fixes in 10.2.0.2. */ #if !defined(ORA_OCI_102) || (defined(_AIX) && !defined(ORA_OCI_112)) OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); From d113d68b801ba6b3bcced1567dbc07ed40f4bce2 Mon Sep 17 00:00:00 2001 From: mjevans Date: Sun, 24 Jun 2012 08:47:29 +0000 Subject: [PATCH 255/637] wrong rt # git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15331 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index 6b915286..cb1e2e55 100644 --- a/Changes +++ b/Changes @@ -27,7 +27,7 @@ Revision history for DBD::Oracle - skip 24implicit_utf8.t if chr set is not UTF-8 (Martin J. Evans) - - Fixed RT76268 - ora_taf_sleep was documented as taf_sleep by + - Fixed RT76269 - ora_taf_sleep was documented as taf_sleep by accident. There was no way to stop the TAF reconnect attempts. If you want to try another connect attempt in your taf handler you now need to return OCI_FO_RETRY from it. (Martin J. Evans) From 33799a17b9ec0481f133155098f95fb24e33c325 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 11 Jul 2012 14:27:46 -0400 Subject: [PATCH 256/637] version increase --- Changes | 1 + dist.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index cb1e2e55..310baa60 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,7 @@ Revision history for DBD::Oracle {{$NEXT}} + - promote 1.45_00 to official release 1.45_00 2012-06-21 diff --git a/dist.ini b/dist.ini index fa00a4b3..03f28890 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.45_00 +version = 1.46 [Authority] authority=cpan:PYTHIAN From d22386c152aadb3bdea130cbe7c2f0f7a16e0c16 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 11 Jul 2012 14:34:20 -0400 Subject: [PATCH 257/637] v1.46 - promote 1.45_00 to official release --- Changes | 2 ++ dist.ini | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Changes b/Changes index 310baa60..ee19ccd7 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,8 @@ Revision history for DBD::Oracle {{$NEXT}} + +1.46 2012-07-11 - promote 1.45_00 to official release 1.45_00 2012-06-21 diff --git a/dist.ini b/dist.ini index 03f28890..28f4edee 100644 --- a/dist.ini +++ b/dist.ini @@ -28,3 +28,5 @@ authority=cpan:PYTHIAN -remove=Covenant [FakeRelease] +[HelpWanted] +positions = coder documentation tester From 47eea69f7349b3df15cea044d5538812c618d4dc Mon Sep 17 00:00:00 2001 From: yanick Date: Wed, 11 Jul 2012 18:50:32 +0000 Subject: [PATCH 258/637] changes related to release v1.46 Mostly bumping up the release number all over the place. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15346 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 +++++-- META.json | 25 +++++++++++++++---------- META.yml | 20 ++++++++++++-------- README | 8 +++++++- README.mkdn | 8 +++++++- lib/DBD/Oracle.pm | 10 +++++----- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pm | 6 +++--- 9 files changed, 58 insertions(+), 34 deletions(-) diff --git a/Changes b/Changes index 7bbefc8d..b851ba02 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -1.NN next release +{{$NEXT}} [BUG FIXES] @@ -15,9 +15,12 @@ Revision history for DBD::Oracle [MISCELLANEOUS] - - Added a trouble shooting entry for RT71819 - bound output + - Added a troubleshooting entry for RT71819 - bound output parameters may be returned in the wrong order (Martin J. Evans) +1.46 2012-07-11 + - promote 1.45_00 to official release + 1.45_00 2012-06-21 [CHANGE IN BEHAVIOUR] diff --git a/META.json b/META.json index c53eebeb..b64f752c 100644 --- a/META.json +++ b/META.json @@ -52,34 +52,34 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::Troubleshooting" : { "file" : "lib/DBD/Oracle/Troubleshooting.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.45_00" + "version" : "1.46" } }, - "release_status" : "testing", + "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -92,7 +92,12 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, - "version" : "1.45_00", - "x_authority" : "cpan:PYTHIAN" + "version" : "1.46", + "x_authority" : "cpan:PYTHIAN", + "x_help_wanted" : [ + "coder", + "documentation", + "tester" + ] } diff --git a/META.yml b/META.yml index 17e78df0..379da346 100644 --- a/META.yml +++ b/META.yml @@ -30,25 +30,25 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::Troubleshooting: file: lib/DBD/Oracle/Troubleshooting.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.45_00 + version: 1.46 requires: DBI: 0 DynaLoader: 0 @@ -60,5 +60,9 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.45_00 +version: 1.46 x_authority: cpan:PYTHIAN +x_help_wanted: + - coder + - documentation + - tester diff --git a/README b/README index 67e6d338..1cf1a61f 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.45_00 + version 1.46 SYNOPSIS use DBI; @@ -2976,6 +2976,12 @@ LOBS AND LONGS Read a portion of the LOB. $offset starts at 1. Uses the Oracle OCILobRead function. + NOTE: DBD::Oracle post 1.46 will return undef for any read lob if + the length specified in the ora_lob_read is 0. See RT 55028. This + avoids the potential problem with empty lobs (created with + empty_clob) which return a length of 0 from ora_lob_length and prior + to 1.46 a call to ora_lob_read with a 0 length would segfault. + ora_lob_write $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); diff --git a/README.mkdn b/README.mkdn index 137888d0..f9c0ce53 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.45_00 +version 1.46 # SYNOPSIS @@ -2975,6 +2975,12 @@ handle are lost, the handle is destroyed and the locators are freed. Read a portion of the LOB. $offset starts at 1. Uses the Oracle OCILobRead function. +NOTE: DBD::Oracle post 1.46 will return undef for any read lob if the +length specified in the ora_lob_read is 0. See RT 55028. This avoids +the potential problem with empty lobs (created with empty_clob) which +return a length of 0 from ora_lob_length and prior to 1.46 a call to +ora_lob_read with a 0 length would segfault. + - ora_lob_write $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9f667697..9f44e064 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.45_00'; + $DBD::Oracle::VERSION = '1.46'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -125,7 +125,7 @@ BEGIN { { package DBD::Oracle::dr; { - $DBD::Oracle::dr::VERSION = '1.45_00'; + $DBD::Oracle::dr::VERSION = '1.46'; } BEGIN { $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; @@ -330,7 +330,7 @@ BEGIN { { package DBD::Oracle::db; { - $DBD::Oracle::db::VERSION = '1.45_00'; + $DBD::Oracle::db::VERSION = '1.46'; } BEGIN { $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; @@ -1059,7 +1059,7 @@ SQL { package DBD::Oracle::st; { - $DBD::Oracle::st::VERSION = '1.45_00'; + $DBD::Oracle::st::VERSION = '1.46'; } BEGIN { $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; @@ -1164,7 +1164,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.45_00 +version 1.46 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 5978b122..2ed2a1f0 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.45_00'; + $DBD::Oracle::GetInfo::VERSION = '1.46'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.45_00 +version 1.46 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 25a905e8..afab5549 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.45_00'; + $DBD::Oracle::Object::VERSION = '1.46'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.45_00 +version 1.46 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 9fb168c2..96e2f7d6 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Troubleshooting; { - $DBD::Oracle::Troubleshooting::VERSION = '1.45_00'; + $DBD::Oracle::Troubleshooting::VERSION = '1.46'; } BEGIN { $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; @@ -17,7 +17,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.45_00 +version 1.46 =head1 CONNECTING TO ORACLE @@ -375,7 +375,7 @@ forking). It looks like this was fixed in 0.012 of Module::Runtime. -=head2 bin_param_inout spapping return values +=head2 bin_param_inout swapping return values See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) From d29973ecd2ea12e28ad7f6b4b017728fc486dc58 Mon Sep 17 00:00:00 2001 From: yanick Date: Wed, 11 Jul 2012 18:50:32 +0000 Subject: [PATCH 259/637] changes related to release v1.46 Mostly bumping up the release number all over the place. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15346 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 +++++-- META.json | 25 +++++++++++++++---------- META.yml | 20 ++++++++++++-------- README | 8 +++++++- README.mkdn | 8 +++++++- lib/DBD/Oracle.pm | 10 +++++----- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pm | 6 +++--- 9 files changed, 58 insertions(+), 34 deletions(-) diff --git a/Changes b/Changes index 7bbefc8d..b851ba02 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -1.NN next release +{{$NEXT}} [BUG FIXES] @@ -15,9 +15,12 @@ Revision history for DBD::Oracle [MISCELLANEOUS] - - Added a trouble shooting entry for RT71819 - bound output + - Added a troubleshooting entry for RT71819 - bound output parameters may be returned in the wrong order (Martin J. Evans) +1.46 2012-07-11 + - promote 1.45_00 to official release + 1.45_00 2012-06-21 [CHANGE IN BEHAVIOUR] diff --git a/META.json b/META.json index c53eebeb..b64f752c 100644 --- a/META.json +++ b/META.json @@ -52,34 +52,34 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::Troubleshooting" : { "file" : "lib/DBD/Oracle/Troubleshooting.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.45_00" + "version" : "1.46" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.45_00" + "version" : "1.46" } }, - "release_status" : "testing", + "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -92,7 +92,12 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, - "version" : "1.45_00", - "x_authority" : "cpan:PYTHIAN" + "version" : "1.46", + "x_authority" : "cpan:PYTHIAN", + "x_help_wanted" : [ + "coder", + "documentation", + "tester" + ] } diff --git a/META.yml b/META.yml index 17e78df0..379da346 100644 --- a/META.yml +++ b/META.yml @@ -30,25 +30,25 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::Troubleshooting: file: lib/DBD/Oracle/Troubleshooting.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.45_00 + version: 1.46 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.45_00 + version: 1.46 requires: DBI: 0 DynaLoader: 0 @@ -60,5 +60,9 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.45_00 +version: 1.46 x_authority: cpan:PYTHIAN +x_help_wanted: + - coder + - documentation + - tester diff --git a/README b/README index 67e6d338..1cf1a61f 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.45_00 + version 1.46 SYNOPSIS use DBI; @@ -2976,6 +2976,12 @@ LOBS AND LONGS Read a portion of the LOB. $offset starts at 1. Uses the Oracle OCILobRead function. + NOTE: DBD::Oracle post 1.46 will return undef for any read lob if + the length specified in the ora_lob_read is 0. See RT 55028. This + avoids the potential problem with empty lobs (created with + empty_clob) which return a length of 0 from ora_lob_length and prior + to 1.46 a call to ora_lob_read with a 0 length would segfault. + ora_lob_write $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); diff --git a/README.mkdn b/README.mkdn index 137888d0..f9c0ce53 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.45_00 +version 1.46 # SYNOPSIS @@ -2975,6 +2975,12 @@ handle are lost, the handle is destroyed and the locators are freed. Read a portion of the LOB. $offset starts at 1. Uses the Oracle OCILobRead function. +NOTE: DBD::Oracle post 1.46 will return undef for any read lob if the +length specified in the ora_lob_read is 0. See RT 55028. This avoids +the potential problem with empty lobs (created with empty_clob) which +return a length of 0 from ora_lob_length and prior to 1.46 a call to +ora_lob_read with a 0 length would segfault. + - ora_lob_write $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9f667697..9f44e064 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.45_00'; + $DBD::Oracle::VERSION = '1.46'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -125,7 +125,7 @@ BEGIN { { package DBD::Oracle::dr; { - $DBD::Oracle::dr::VERSION = '1.45_00'; + $DBD::Oracle::dr::VERSION = '1.46'; } BEGIN { $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; @@ -330,7 +330,7 @@ BEGIN { { package DBD::Oracle::db; { - $DBD::Oracle::db::VERSION = '1.45_00'; + $DBD::Oracle::db::VERSION = '1.46'; } BEGIN { $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; @@ -1059,7 +1059,7 @@ SQL { package DBD::Oracle::st; { - $DBD::Oracle::st::VERSION = '1.45_00'; + $DBD::Oracle::st::VERSION = '1.46'; } BEGIN { $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; @@ -1164,7 +1164,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.45_00 +version 1.46 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 5978b122..2ed2a1f0 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.45_00'; + $DBD::Oracle::GetInfo::VERSION = '1.46'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.45_00 +version 1.46 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 25a905e8..afab5549 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.45_00'; + $DBD::Oracle::Object::VERSION = '1.46'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.45_00 +version 1.46 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm index 9fb168c2..96e2f7d6 100644 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ b/lib/DBD/Oracle/Troubleshooting.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Troubleshooting; { - $DBD::Oracle::Troubleshooting::VERSION = '1.45_00'; + $DBD::Oracle::Troubleshooting::VERSION = '1.46'; } BEGIN { $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; @@ -17,7 +17,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.45_00 +version 1.46 =head1 CONNECTING TO ORACLE @@ -375,7 +375,7 @@ forking). It looks like this was fixed in 0.012 of Module::Runtime. -=head2 bin_param_inout spapping return values +=head2 bin_param_inout swapping return values See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) From d91ad2273f1dfded201ee91a548767e4b206030e Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 27 Jun 2012 08:20:39 +0000 Subject: [PATCH 260/637] Further comments added for OCIPing issue on AIX git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15340 50811bd7-b8ce-0310-adc1-d9db26280581 --- Oracle.xs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Oracle.xs b/Oracle.xs index 241dae6f..e5bce1d0 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -399,6 +399,10 @@ ora_ping(dbh) * see http://comments.gmane.org/gmane.comp.lang.perl.modules.dbi.general/16206 * We don't do versions to that accuracy so for AIX you have * to wait until 11.2 for OCIPing. + * + * Further comments on dbi-dev + * "DBD::Oracle RTs a summary and request for help" suggested it + * was Oracle bug 5759845 and fixes in 10.2.0.2. */ #if !defined(ORA_OCI_102) || (defined(_AIX) && !defined(ORA_OCI_112)) OCIServerVersion_log_stat(imp_dbh, imp_dbh->svchp,imp_dbh->errhp,buf,2,OCI_HTYPE_SVCCTX,status); From cf76322a5db104fc3592bb9bd2348c5cd6722c91 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 9 Mar 2012 16:38:30 -0500 Subject: [PATCH 261/637] POD all the READMEs --- MANIFEST | 22 +- README-files/hpux/Makefile-Lincoln | 223 ----------- README.64bit.txt | 272 ------------- README.aix.txt | 255 ------------ README.clients.txt | 279 ------------- README.help.txt | 133 ------ README.java.txt | 322 --------------- README.sec.txt | 142 ------- README.win32.txt | 236 ----------- lib/DBD/Oracle/Troubleshooting.pm | 377 ------------------ lib/DBD/Oracle/Troubleshooting.pod | 125 ++++++ lib/DBD/Oracle/Troubleshooting/Aix.pod | 250 ++++++++++++ lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 68 ++++ .../DBD/Oracle/Troubleshooting/Hpux.pm | 3 + lib/DBD/Oracle/Troubleshooting/Linux.pod | 108 +++++ .../DBD/Oracle/Troubleshooting/Macos.pod | 282 +++++++------ lib/DBD/Oracle/Troubleshooting/Sun.pod | 15 + lib/DBD/Oracle/Troubleshooting/Vms.pod | 87 ++++ lib/DBD/Oracle/Troubleshooting/Win32.pod | 242 +++++++++++ .../DBD/Oracle/Troubleshooting/Win64.pod | 14 +- test.pl | 319 --------------- 21 files changed, 1052 insertions(+), 2722 deletions(-) delete mode 100644 README-files/hpux/Makefile-Lincoln delete mode 100644 README.64bit.txt delete mode 100644 README.aix.txt delete mode 100644 README.clients.txt delete mode 100644 README.java.txt delete mode 100644 README.sec.txt delete mode 100644 README.win32.txt delete mode 100644 lib/DBD/Oracle/Troubleshooting.pm create mode 100644 lib/DBD/Oracle/Troubleshooting.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Aix.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Cygwin.pod rename README.hpux.txt => lib/DBD/Oracle/Troubleshooting/Hpux.pm (99%) create mode 100644 lib/DBD/Oracle/Troubleshooting/Linux.pod rename README.macosx.txt => lib/DBD/Oracle/Troubleshooting/Macos.pod (78%) create mode 100644 lib/DBD/Oracle/Troubleshooting/Sun.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Vms.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Win32.pod rename README.win64.txt => lib/DBD/Oracle/Troubleshooting/Win64.pod (97%) delete mode 100755 test.pl diff --git a/MANIFEST b/MANIFEST index 34c7a9d4..bd226508 100644 --- a/MANIFEST +++ b/MANIFEST @@ -9,18 +9,8 @@ Oracle.h Oracle.xs Oraperl.pm README -README-files/hpux/Makefile-Lincoln -README.64bit.txt -README.aix.txt -README.clients.txt README.help.txt -README.hpux.txt -README.java.txt -README.macosx.txt README.mkdn -README.sec.txt -README.win32.txt -README.win64.txt Todo dbdimp.c dbdimp.h @@ -47,7 +37,16 @@ hints/svr4.pl lib/DBD/Oracle.pm lib/DBD/Oracle/GetInfo.pm lib/DBD/Oracle/Object.pm -lib/DBD/Oracle/Troubleshooting.pm +lib/DBD/Oracle/Troubleshooting.pod +lib/DBD/Oracle/Troubleshooting/Aix.pod +lib/DBD/Oracle/Troubleshooting/Cygwin.pod +lib/DBD/Oracle/Troubleshooting/Hpux.pm +lib/DBD/Oracle/Troubleshooting/Linux.pod +lib/DBD/Oracle/Troubleshooting/Macos.pod +lib/DBD/Oracle/Troubleshooting/Sun.pod +lib/DBD/Oracle/Troubleshooting/Vms.pod +lib/DBD/Oracle/Troubleshooting/Win32.pod +lib/DBD/Oracle/Troubleshooting/Win64.pod mkta.pl oci.def oci8.c @@ -90,5 +89,4 @@ t/80ora_charset.t t/nchar_test_lib.pl t/rt13865.t t/rt74753-utf8-encoded.t -test.pl typemap diff --git a/README-files/hpux/Makefile-Lincoln b/README-files/hpux/Makefile-Lincoln deleted file mode 100644 index 0565def4..00000000 --- a/README-files/hpux/Makefile-Lincoln +++ /dev/null @@ -1,223 +0,0 @@ -# makefile for rebuilding perl and all the modules we have built -# or for rebuilding individual modules -SHELL = /usr/bin/ksh -CPAN_VERSION = 5.6.1 -FCCS_VERSION = fccs-03 -#needed for compatibility with ../build.mk: -TOOL = perl -PERL_VERSION = $(TOOL)-$(CPAN_VERSION) -TOP = /opt/oss -PERLDIR = $(PERL_VERSION)-$(FCCS_VERSION) -PERL_ROOT = $(TOP)/pkg -PREFIX = $(PERL_ROOT)/$(PERLDIR) -#needed for compatibility with ../biuld.mk: -VERSION = $(CPAN_VERSION)-$(FCCS_VERSION) - -MQS = MQSeries-1.14 -DBDORA = DBD-Oracle-1.12 -DBI = DBI-1.20 -EXPAT_VER = -1.95.2 -MQSERVER = 'PERL_CHANNEL/TCP/dsas105(1414)' - -MODULES = \ - libnet-1.0703 \ - Storable-0.7.2 \ - Time-HiRes-01.20 \ - Net-Daemon-0.35 \ - Digest-MD5-2.16 \ - Digest-SHA1-2.01 \ - Digest-HMAC-1.01 \ - MIME-Base64-2.12 \ - Net-DNS-0.19 \ - Mail-CheckUser-1.13 \ - Proc-Daemon-0.02 \ - Proc-Simple-1.14 \ - Openview-Message-0.01 \ - Business-CreditCard-0.26 \ - Data-UUID-0.06 - -XML_PARSER = XML-Parser-2.31 -XML_MODULES = \ - XML-Simple-1.05 \ - XML-Generator-0.8 -#this does not behave same as 0.8 -#XML-Generator-0.91 - -all: testOracleVar - @banner ALL_PERL - @echo "using perl PATH=$(PREFIX)/bin" - ( export PATH=$(PREFIX)/bin:$$PATH && make perl ) - ( export PATH=$(PREFIX)/bin:$$PATH && make all_modules ) - -print_macros: - @echo TOOL=$(TOOL) - @echo CPAN_VERSION=$(CPAN_VERSION) - @echo PERL_VERSION=$(PERL_VERSION) - @echo FCCS_VERSION=$(FCCS_VERSION) - @echo PREFIX=$(PREFIX) - @echo VERSION=$(VERSION) - @echo PERLDIR=$(PERLDIR) - @echo PERL_ROOT=$(PERL_ROOT) - -all_modules: modules xmlparser xml_modules dbi dbd mqs - -modules: testPath - rm -rf $(MODULES) - for m in $(MODULES); do \ - make module MODULE=$$m PREFIX=$(PREFIX) ; \ - done - -xml_modules: testPath - rm -rf $(XML_MODULES) - for m in $(XML_MODULES); do \ - make module MODULE=$$m PREFIX=$(PREFIX) ; \ - done - -dbi: testPath - make module MODULE=DBI-1.20 PREFIX=$(PREFIX) - -dbd: testPath testOracleVar dbi touch.d/$(DBDORA).tch - -touch.d: - mkdir touch.d - -xmlparser: touch.d/$(XML_PARSER).tch -touch.d/$(XML_PARSER).tch: $(XML_PARSER).tar.gz - tar -zxvf $(XML_PARSER).tar.gz - ( cd $(XML_PARSER) && \ - perl Makefile.PL EXPATLIBPATH=$(TOP)/lib \ - EXPATINCPATH=$(TOP)/include && \ - make && \ - make test && \ - make install ) - rm -rf $(XML_PARSER) - touch $@ - -#chmod +w CONFIG; -mqs_config: - ( cd $(MQS); \ - mv CONFIG CONFIG.orig; \ - cp ../$$(uname).MQS.CONFIG CONFIG \ - ) - -mqs_target: - ( export MQSERVER=$(MQSERVER); \ - cd $(MQS) ;\ - make $(MQS_TARGET) \ - ) - -mqs_build: - ( export MQSERVER=$(MQSERVER); \ - cd $(MQS) ;\ - cp ../$$(uname).MQS.CONFIG ./CONFIG; \ - perl Makefile.PL; \ - make ; \ - ) - -mqs: testPath /opt/mqm touch.d/$(MQS).tch -touch.d/$(MQS).tch: - @banner $(MQS) - rm -rf $(MQS) - gunzip -c $(MQS).tar.gz | tar -xvf - - touch $(MQS)/.LICENSE.ACCEPTED - make -s mqs_config - make -s mqs_build - make -s mqs_target MQS_TARGET=test - make -s mqs_target MQS_TARGET=install - touch $@ - - -touch.d/$(DBDORA).tch: testOracleVar - @banner $(DBDORA) - test ! -z "$(ORACLE_HOME)" - -rm -rf $(DBDORA) - gunzip -c $(DBDORA).tar.gz | tar -xf - - cd $(DBDORA) ;\ - perl Makefile.PL; \ - make ; \ - make test ; \ - make install - touch touch.d/$(DBDORA).tch - - -perl: testVar $(PERL_VERSION) touch.d/$(PERL_VERSION).tch - -touch.d/$(PERL_VERSION).tch: - @banner perl - @if ls $(PREFIX) >/dev/null 2>&1 ; \ - then \ - echo "Error: Cannot install to an existing directory" ;\ - echo "Error: Please delete or move $(PREFIX)" ;\ - exit 1;\ - fi - - cd $(PERL_VERSION); make distclean; - cd $(PERL_VERSION); \ - ./Configure -Dprefix=$(PREFIX) -Ubincompat5005 -Uuselargefiles \ - -A eval:libswanted='\"cl pthread $$libswanted\" ' -des; \ - make ; \ - make test; \ - make install - touch touch.d/$(PERL_VERSION).tch - -realclean distclean: clean_tch - -rm -rf $(PERL_VERSION) - -clean: clean_tch -clean_tch : - -rm -f touch.d/*.tch - -module: touch.d/$(MODULE).tch - -touch.d/$(MODULE).tch : - @banner $(MODULE) - -rm -rf $(MODULE) - gunzip -c $(MODULE).tar.gz | tar -xf - - cd $(MODULE); \ - perl Makefile.PL /dev/null 2>&1 ; \ - then \ - echo "Error: Cannot install to an existing directory" ;\ - echo "Error: Please delete or move $(PREFIX)" ;\ - exit 1;\ - fi - gunzip -c $(PERL_VERSION).tar.gz |tar xf - - @echo "untar of perl is done" - -testVars: testVar testPath testOracleVar - -testVar: touch.d - @echo "******** Building to: $(PREFIX) *********" - -testOracleVar: - @if test -z "$$ORACLE_HOME" ; \ - then \ - echo " Please set \"export ORACLE_HOME=\"" ;\ - exit 1; \ - else \ - echo ORACLE_HOME=$(ORACLE_HOME); \ - fi - @if test -z "$$ORACLE_USERID" ; \ - then \ - echo " Please set \"export ORACLE_USERID=\"" ;\ - exit 1; \ - else \ - echo ORACLE_USERID=$(ORACLE_USERID); \ - fi - -testPath: - @if echo $$PATH | egrep -q '^$(PREFIX)/bin:'; then \ - echo PATH is OK; \ - else \ - echo "ERROR: You must have $(PREFIX)/bin first in your path as follows:" ;\ - echo " export PATH=$(PREFIX)/bin:\$$PATH" ;\ - exit 1; \ - fi diff --git a/README.64bit.txt b/README.64bit.txt deleted file mode 100644 index 9d3ebe0f..00000000 --- a/README.64bit.txt +++ /dev/null @@ -1,272 +0,0 @@ -In general compiling DBD:Oracle for 64 bit machines has been a hit or miss operation. -The main thing to remember is you will have to compile using 32 bit Perl and compile DBD::Oracle against a 32bit client -which sort of defeats the purpose of having a 64bit box. -So until 64bit Perl comes out we will be posing in this README any success stories we have come across - --------- Original Message -------- - -Subject: Building 32bit DBD::Oracle against 64bit Oracle -From: Dennis Reso -Date: 7/9/2008 5:44 PM -Priority: Normal - -Building DBD::Oracle v1.21 against Perl 5.8.5 Oracle 9.2.0.4 Solaris 8 - -Got the dreaded "wrong ELF class" when the Oracle.so ends up built -against the 64bit library instead of the one in $ORACLE_HOME/lib32. -Use 'dump -vL Oracle.so' to see the internalized RPATH definition. - -Tried the following solution, widely posted, without success: - - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - -What worked for me (pass the LIBDIR to the Oracle make process): - - export ORACLE_HOME=/apps/Oracle9.2.0.4 - export LD_LIBRARY_PATH=$ORACLE_HOME/lib32 - perl -pi -e 's/CC=true/CC=true LIBDIR=lib32/' Makefile.PL - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - make - -The LIBDIR= is defined in $ORACLE_HOME/rdbms/lib/env_rdbms.mk which -also includes a REDEFINES32= that overrides it, but is only used by -the $ORACLE_HOME/rdbms/lib/ins_rdbms.mk. Oracle bug? - -Also repeated the same failure and success with - Oracle 9.2.0.8 Solaris 10 - Oracle 10.2.0.3 Solaris 10 - -Seems fixed in demo_rdbms32.mk (no Makefile.PL edit needed ) as of - Oracle 10.2.0.4 Solaris 10 - -Probably also fixed in some patchset newer than 9.2.0.4. - --- -Dennis Reso - --------- Original Message -------- - -Subject: DBD::Oracle 64-bit success story -From: H.Merijn Brand -Date: On Mon, 14 Apr 2008 09:48:41 -Priority: Normal - -I finally got round trying Oracle Instant Client on Linux with no -Oracle installed, connecting to a 64bit Oracle 9.2.0.8 on HP-UX -11.11/64. I had to do some fiddling with Makefile.PL (see bottom). -Sorry for this being long. Feel free to mold it into anything useful. - -1. Before you start on DBD::Oracle, make sure DBD::ODBC works. That will - assure your DSN works. Install unixODBC before anything else. - -2. Assuming you've got OIC from the rpm's, you will have it here: - - /usr/include/oracle/11.1.0.1/client - /usr/lib/oracle/11.1.0.1/client - /usr/share/oracle/11.1.0.1/client - - -3. for the 64 bit clienat we have these rpm - oracle-instantclient-basic-11.1.0.1-1.x86_64.rpm - oracle-instantclient-devel-11.1.0.1-1.x86_64.rpm - oracle-instantclient-jdbc-11.1.0.1-1.x86_64.rpm - oracle-instantclient-odbc-11.1.0.1-1.x86_64.rpm - oracle-instantclient-sqlplus-11.1.0.1-1.x86_64.rpm - - and to add to the confusement, they install to - - /usr/include/oracle/11.1.0.1/client64 - /usr/lib/oracle/11.1.0.1/client64 - /usr/share/oracle/11.1.0.1/client64 - -4. To make DBD::ODBC work, I had to create a tnsnames.ora, and I chose - - /usr/lib/oracle/11.1.0.1/admin/tnsnames.ora - - /usr/lib/oracle/11.1.0.1/admin > cat sqlnet.ora - NAMES.DIRECTORY_PATH = (TNSNAMES, ONAMES, HOSTNAME) - /usr/lib/oracle/11.1.0.1/admin > cat tnsnames.ora - ODBCO = ( - DESCRIPTION = - ( ADDRESS_LIST = - ( ADDRESS = - ( PROTOCOL = TCP ) - ( PORT = 1521 ) - ( HOST = rhost ) - ) - ) - ( CONNECT_DATA = - ( SERVICE_NAME = odbctest ) - ) - ) - /usr/lib/oracle/11.1.0.1/admin > - - Real world example changed to hide the obvious. Important bits are - "ODBCO", which is the ODBC name, and it can be anything, as long as - you use this in ORACLE_DSN too (please don't use whitespace, colons, - semicolons and/or slashes. "rhost" is the hostname of where the DB - is running, and "odbctest" is available on "rhost". To check that, - run "lsnrctl services" on "rhost". - Set the environment (TWO_TASK is not needed) - - > setenv LD_LIBRARY_PATH /usr/lib/oracle/11.1.0.1/client/lib - > setenv TNS_ADMIN /usr/lib/oracle/11.1.0.1/admin - > setenv ORACLE_HOME /usr/lib/oracle/11.1.0.1/client - > setenv ORACLE_DSN dbi:Oracle:ODBCO - > setenv ORACLE_USERID ORAUSER/ORAPASS - - Check if the connection works: - > isql -v ODBCO - - And for Oracle: - > sqlplus ORAUSER/ORAPASS@ODBCO - and - > sqlplus ORAUSER/ORAPASS@rhost/odbctest - - should both work - - -Note by JPS: - -Merijn patched the trunk version of Makeifle.PL to account for the above it will be in release 1.22 - --------- Original Message -------- - -Subject: DBD::Oracle 64-bit success story -From: "QiangLi" -Date: Thu, March 6, 2008 5:25 pm -To: pause@pythian.com -Priority: Normal - -hi, - -thanks for maintaining DBD::Oracle. I have installed DBD::Oracle against - 64-bit oracle 10g on a 64-bit solaris machine. maybe worth another -entry for the README.64bit.txt file. - -i am using gcc from sun freesoftware and also SUNWbinutils which -contains the gas (gnu assembler) - -here is the steps with comment: - -# set install target -% /usr/perl5/5.8.4/bin/perlgcc Makefile.PL PREFIX=/var/tmp/lib - -# since our perl is 32-bit, we can't build it against a 64bit oracle -install. -# edit Makefile and change reference to oracle's "lib/" to "lib32/" -% perl -pi -e 's/oracle_home\/lib/oracle_home\/lib32/g' Makefile -% perl -pi -e 's/oracle_home\/rdbms\/lib/oracle_home\/rdbms\/lib32/g' -Makefile - -% make - -# ignore error like ORA-12162: TNS:net service name is incorrectly -specified... -% make test - -% make install - -# does it work. -% perl -I'/var/tmp/lib/lib/site_perl/5.8.4/sun4-solaris-64int/' --MDBD::Oracle -e1 - -cheers, - -Qiang - - - - --------- Original Message -------- -Subject: Tip: Compiling 32bit modules against 64bit Oracle 10g on solaris -Date: Thu, 1 Nov 2007 16:41:28 -0400 -From: Edgecombe, Jason -To: -CC: - - - -Hi There, - -I just wanted to thank both of you. - -The tip from cartmanltd@hotmail.com was the trick for getting -DBD::Oracle compiled in 32bit format against the Oracle 10g client on -solaris. - -Here was the command that worked: - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - -Even though the tip was for aix, it fixed my build issue on solaris 9 -(sparc) - -I've been banging my head on this problem for a few days. - -Thanks, -Jason - -Jason Edgecombe -Solaris & Linux Administrator -Mosaic Computing Group, College of Engineering -UNC-Charlotte -Phone: (704) 687-3514 - - - -Source:Tom Reinertson -Platform:Amd64 -OS:Gentoo-amd64 - -The following instructions work for dbd::oracle 1.19 on a gentoo-amd64 installation. - -1) install the oracle libraries - - Strictly speaking you only need dev-db/oracle-instantclient-basic - for dbd::oracle, but i always like to have sql*plus lying around, - which requires the basic package, so i just install sql*plus. - - emerge dev-db/oracle-instantclient-sqlplus which also pulls in - dev-db/oracle-instantclient-basic. these packages are fetch - restricted so you will be required to follow the download instructions. - following these instructions, you should have retrieved these packages: - - instantclient-basic-linux-x86-64-10.2.0.3-20070103.zip - instantclient-sdk-linux-x86-64-10.2.0.3-20070103.zip - instantclient-sqlplus-linux-x86-64-10.2.0.3-20070103.zip - - now move them into the /usr/portage/distfiles directory. - - you should now be able to emerge dev-db/oracle-instantclient-sqlplus. - -2) install DBD::Oracle - - issue the command: - - perl -MCPAN -e'install DBD::Oracle' - - this fails with the following error: - - x86_64-pc-linux-gnu-gcc: unrecognized option '-wchar-stdc++' - x86_64-pc-linux-gnu-gcc: unrecognized option '-cxxlib-gcc' - cc1: error: /ee/dev/bastring.h: No such file or directory - - find the offending files in your cpan directory: - {~/.cpan/build/DBD-Oracle-1.19} grep -lr cxxlib * - Makefile - blib/arch/auto/DBD/Oracle/mk.pm - mk.pm - - edit these files and remove the two invalid options and the include of bastring.h. - - now build the module: - - perl Makefile.PL -l - make - # make test generates lots of errors - make test - make install - - you should now be ready to run. - - diff --git a/README.aix.txt b/README.aix.txt deleted file mode 100644 index a83bf144..00000000 --- a/README.aix.txt +++ /dev/null @@ -1,255 +0,0 @@ - -DBD::Oracle AIX-specific README - - -Using Visual Age 7 C Compiler -====================================================================================== - -- Oracle 9i is only certified as a 64-bit application on AIX 5L (5.1,5.2,5.3) with 32-bit support; - in other words, there is no 9i "32-bit" Oracle client -- Oracle 10g is certified as both a 64-bit application and a 32-bit Oracle client - -- This information only pertains to deploying - the DBI (version 1.48) - and DBD-Oracle (version 1.16): - on AIX 5.3 - using Oracle 9i (9.2.0.1/9.2.0.5) - using the existing Perl 5.8.2 (no custom-built Perl) which is 32-bit - using Visual Age 7.0 C/C++ compiler - -Install the DBI (required for the DBD-Oracle install - no issues here) -Untar the DBD-Oracle bundle -Run Makefile.PL -$ perl Makefile.PL -Edit Makefile with following commands: -1,$s?/lib/ ?/lib32/ ?g -1,$s?-q64??g -1,$s?/lib/sysliblist?/lib32/sysliblist?g -Now perform normal commands to perform the testing/making: -$ make -$ make test -$ make install - -I've tested the basics of the DBD-Oracle and it seems fully functional. - -Stephen de Vries -paulhill20@copper.net - - - -Using gcc C Compiler -====================================================================================== - - - -DBD::Oracle with gcc and Oracle Instant Client on AIX --------------------------------------------------------------------------------------- -Nathan Vonnahme Dec 15 2005, 4:28 pm Newsgroups: perl.dbi.users -See: http://groups.google.com/group/perl.dbi.users/msg/0bd9097f80f2c8a9 -[ with updates 1/31/2006 - DBD::Oracle 1.17 doesn't need makefile hacking -to work with instantclient on AIX ] - - -Yes! It eluded me last year but I finally got DBD::Oracle working on an -AIX machine using gcc. Here's the short version: - -First I had to recompile perl with gcc, using - sh Configure -de -Dcc=gcc -This apparently built a 32 bit perl, someday I will try getting it to go -64 bit. - -I was then able to install and build DBI 1.50 with the CPAN shell. - -I downloaded the base and sdk packages of the Oracle Instant Client for -AIX -- first I tried the 64 bit but that didn't work with my 32 bit perl --- the 32 bit version (still at 10.1.0.3) did the trick. I unzipped -them and moved the dir to /usr/local/oracle/instantclient10_1 and made a -symlink without the version at /usr/local/oracle/instantclient , then -set: - -export ORACLE_HOME=/usr/local/oracle/instantclient -export LIBPATH=$ORACLE_HOME - - - -Oracle wasn't providing the sqlplus package for 32 bit AIX so I -explicitly told Makefile.PL the version: - -perl Makefile.PL -V 10.1 - -make - -My test databases were on other machines so I set these environment variables -to get the tests to run: - -export ORACLE_DSN=DBI:Oracle://host/dbinstance -export ORACLE_USERID="user/password" - -make test -make install - - -NOTE: I have an older full version of Oracle on this machine, and the -ORACLE_HOME environment variable is normally set to point to that, so -my perl scripts that use DBD::Oracle have to make sure to first set - $ENV{ORACLE_HOME}='/usr/local/oracle/instantclient'; - - - - - --------------------------------------------------------------------------------------- -The following setup worked to build on AIX 5.2: -gcc-3.3.2 (32-bit) (configure opts [ --with-ld=/usr/ccs/bin/ld --with-as=/usr/ccs/bin/as]) -Oracle-9.2.0 ( full install w/32bit support) -perl-5.8.3 (built with above gcc/latest stable as of March 2004) -Followed the directions from Rafael's email below, only set ORACLE_HOME, (and -the appropriate test environmentals). -1) build perl-5.8.3 with gcc -2) install DBI -3) ORACLE_HOME="your oracle home" - ORACLE_USERID.. - ORACLE_SID .. - (I ignored ORACCENV, didn't use it.) -4) install DBD::Oracle, after perl Makefile.PL, edit the created Makefile, -changing references to Oracle's ../lib to ../lib32. and change crt0_64.o to -crt0_r.o. Remove the -q32 and/or -q64 options from the list of libraries to -link with. -5) make should be clean, make test should pass. -This setup worked with 8.1.7 w/32 bit support, and with 9.2.0 w/ 32-bit support. ---Adrian Terranova -peril99@yahoo.com - - - - -Using xlc_r C Compiler -====================================================================================== --------------------------------------------------------------------------------------- -From: Rafael Caceres -Date: 22 Jul 2003 10:05:20 -0500 -Message-Id: <1058886321.1066.13.camel@rcaceres.aasa.com.pe> - -The following sequence worked for me on AIX 5.1: - --use Perl 5.8.0 (the latest stable from CPAN) - --use the xlc_r version of IBM's compiler and build a 32 bit Perl - (which xlc_r will do by default). All tests should be successful. - --get and install DBI - --get DBD::Oracle. Edit the Makefile.PL or Makefile for DBD::Oracle, -changing references to Oracle's ../lib to ../lib32. and change crt0_64.o -to crt0_r.o. Remove the -q32 and/or -q64 options from the list of -libraries to link with. Do the make and make test. - --Set up the environment for making DBD::Oracle: - ORACLE_HOME="your oracle home" - ORACCENV = "xlc_r" - ORACLE_USERID.. - ORACLE_SID .. - --Run make, all tests should be successfull -against Oracle 9.x at least. - -You should have no problems with Oracle 8.1.7, but accessing Oracle 7.x -or previous is not possible (you'll core dump, or simply hang). The same -goes for a Linux build or a Digital build, regarding access of different -Oracle versions. - -Rafael Caceres - -On Tue, 2003-07-22 at 08:12, mpaladino@invacare.com wrote: -> -> I dont believe I compiled Oracle. During the installation it was linked -> but I am not sure it was compiled -> -> I used a xlc compiler to compile PERL. -> Got this message in the Perl Makefile.PL output -> -> Warning: You will may need to rebuild perl using the xlc_r compiler. -> You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV -> Also see the README about the -p option -> -> this probobly means I need to rebuild PERL with xlc_r?? -> -> thanx -> -> Mike Paladino -> Database Administrator - - -From: Rafael Caceres -> -> Make sure you use the same compiler to build Oracle and Perl. We have -> used xlc_r on Aix 5.1 with no problems. Your Perl build is 32 bit, so -> when building DBD::Oracle, you should use the 32bit libraries (change -> references to .../oracle/lib to .../oracle/lib32 in your Makefile). -> Remove the references to the -q64 or -q32 parameters for ld in Makefile, -> as they shouldn't be there. -> -> Rafael Caceres - - -From: "cartman ltd" -Subject: Tip for DBI and DBD::Oracle on AIX 5.1 and Oracle 9.2 -Date: Mon, 11 Aug 2003 18:15:38 +0000 -Message-ID: - -Here is a tip for compiling DBD::Oracle as a 32 bit application on AIX 5.1 -64 bit and Oracle 9.2 64 bit without editting any makefiles. I hope people -find this useful: - -First, the versions of products I used: - DBI version 1.32 - DBD::Oracle version 1.14 - Oracle 9.2.0.2 - default 64 bit application with 32 bit libraries - AIX 5.1 ML03 - 64 bit kernel - ships with Perl as a 32 bit application. - VisualAge C/C++ 5.0.2 - -Basically DBD must be compiled as 32 bit to link with Perl's 32 bit -libraries. - gunzip -c DBD-Oracle-1.14.tar.gz | tar xvf  - cd DBD-Oracle-1.14 - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - make - -NB: I think there is a bug in the Oracle 9.2.0.3 file -$ORACLE_HOME/rdbms/lib/env_rdbms.mk -I corrected this (before running the above commands) by replacing the -invalid linker option - LDFLAGS32=-q32 -with - LDFLAGS32=-b32 - -Have fun: KC. --------------------------------------------------------------------------------------- - -Date: Wed, 30 Jun 2004 23:34:24 -0500 -From: "SCHULTZ, DARYLE (SBCSI)" - -Got it to work. Using dbd 1.16 - -Perl 5.8.4 built like this, with Visual Age 6.0: - -config_args='-Dcc=xlc_r -Dusenm -Dprefix=/appl/datasync/work/perl5 --Dusethreads -Duse64bitall -des' -============================================== - -Used DBI 1.42 -============================================= -Added this to top of Oracle.h: -#define A_OSF - -#include -======================= -Set LIBPATH to point to 64bit Oracle libs first. -export LIBPATH=$ORACLE_HOME/lib:$ORACLE_HOME/lib32:/usr/lib - -Use: perl Makefile.PL -nob - -Change all references in Makefile of LD_RUN_PATH to be LIBPATH. -Change nothing else, left all flags in Makefile, including -q64. -Passed make, and all tests. - --------------------------------------------------------------------------------------- diff --git a/README.clients.txt b/README.clients.txt deleted file mode 100644 index 274ca435..00000000 --- a/README.clients.txt +++ /dev/null @@ -1,279 +0,0 @@ -This file contains some random notes relating to minimal Oracle -configurations for building and/or using DBD::Oracle / Oraperl. - - -*** ALL THE TEXT BELOW IS OLD *** -*** THE PREFERED METHOD IS TO USE Oracle Instant Client *** - - -------------------------------------------------------------------------------- -With recent versions of Oracle (specifically >= 7.3) you may be -able to build DBD::Oracle without Pro*C installed by using the Oracle -supplied oracle.mk file: - - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/oracle.mk - -(The oracle.mk file might also be found in $ORACLE_HOME/rdbms/public/) - -------------------------------------------------------------------------------- -From: James Cooper - -> [...], what do I need in addition to perl5 to access an Oracle database -> on another system from a unix box (Solaris 2.5) that doesn't have an -> oracle database running on it ? -> -> In other words are their some oracle shared objects, etc. I need ? - -I don't have experience with Solaris, but on IRIX 5.3, I simply installed -SQL*Net ($ORACLE_HOME/network/admin/*) and the OCI libraries which are in -$ORACLE_HOME/lib. You'll also need the header files from -$ORACLE_HOME/sqllib/public/*.h and $ORACLE_HOME/rdbms/demo/*.h (you won't -need them all, but you can get rid of them after DBD::Oracle compiles). - -[You'll probably need at least ocommon in addition to network. But if you -use the Oracle installer (as you always should) it'll probably install -ocommon for you.] - -So just put that stuff on your client box and install DBI and DBD::Oracle -there. Once DBD::Oracle is installed you can remove the OCI libraries and -headers (make sure to keep SQL*Net!) - -Other than that, getting it working isn't too hard. If you're not -familiar with SQL*Net, let me know. I'm no expert, but I know the basics. -The main thing is to have a good tnsnames.ora file in -$ORACLE_HOME/network/admin - -------------------------------------------------------------------------------- -From: Jon Meek - -For my compilation of DBD-Oracle/Solaris2.5/Oracle7.2.x(x=2, I think), I -just pulled the required files in the rdbms directory from the Oracle CD. -The files I needed were: - -$ ls -lR -drwxr-xr-x 2 oracle apbr 512 May 15 17:43 demo/ -drwxr-xr-x 2 oracle apbr 512 May 15 16:20 lib/ -drwxr-xr-x 2 oracle apbr 512 May 15 16:18 mesg/ -drwxr-xr-x 2 oracle apbr 512 May 15 17:38 public/ - -./demo: --r--r--r-- 1 oracle apbr 4509 Jun 29 1995 ociapr.h --r--r--r-- 1 oracle apbr 5187 Jun 29 1995 ocidfn.h --rw-rw-r-- 1 oracle apbr 6659 Jun 29 1995 oratypes.h - -./lib: --rw-r--r-- 1 oracle apbr 1132 Jul 6 1995 clntsh.mk --rwxr-xr-x 1 oracle apbr 5623 Jul 17 1995 genclntsh.sh* --rw-r--r-- 1 oracle apbr 15211 Jul 5 1995 oracle.mk --rw-r--r-- 2 oracle apbr 3137 May 15 16:20 osntab.s --rw-r--r-- 2 oracle apbr 3137 May 15 16:20 osntabst.s --rw-r--r-- 1 oracle apbr 9 May 15 16:19 psoliblist --rw-r--r-- 1 oracle apbr 39 May 15 16:21 sysliblist - -./mesg: --r--r--r-- 1 oracle apbr 183296 Jul 11 1995 oraus.msb --r--r--r-- 1 oracle apbr 878114 Jul 11 1995 oraus.msg - -./public: --r--r--r-- 1 oracle apbr 5187 Jun 29 1995 ocidfn.h - -Jon - -------------------------------------------------------------------------------- -Jon Meek Tue, 18 Feb 1997 - -This was for Oracle 7.2.2.3.0 (client side for DBD:Oracle build) and -SQL*net v2. I have heard that sqlnet.ora might not be needed. - -ls -lR oracle -oracle: -total 2 -drwxr-xr-x 3 meekj apbr 512 Nov 3 11:46 network/ - -oracle/network: -total 2 -drwxr-xr-x 2 meekj apbr 512 Nov 3 11:46 admin/ - -oracle/network/admin: -total 6 --rw-r--r-- 1 meekj apbr 309 Nov 3 11:46 sqlnet.ora --rw-r--r-- 1 meekj apbr 1989 Nov 3 11:46 tnsnames.ora - -------------------------------------------------------------------------------- - -From: Lack Mr G M -Date: Thu, 23 Jan 1997 18:24:03 +0000 - - I noticed the appended in the README.clients file of the DBD-Oracle -distribution. My experience is somewhat different (and simpler). - - On Irix5.3 (ie. what this user was using) I built DBI and DBD-Oracle -on a system with Oracle and Pro*C installed. I tested it on another -system (where I knew an oracle id). I installed it from a third (which -had write rights to the master copies of the NFS mounted directories), -but this didn't have Oracle installed. - - Having done this all of my systems (even those without a hint of -oracle on them) could access remote Oracle servers by setting TWO_TASK -appropriately. SQL*Net didn't seem to come into it. - - The dynamically-loadable library created (auto/DBD/Oracle/Oracle.so) -contains no reference to any dynamic Oracle library. - - Exactly the same happened for my Solaris systems. - - From: James Cooper - > [...], what do I need in addition to perl5 to access an Oracle database - > on another system from a unix box (Solaris 2.5) that doesn't have an - > oracle database running on it ? - > - > In other words are their some oracle shared objects, etc. I need ? - -I don't have experience with Solaris, but on IRIX 5.3, I simply installed -SQL*Net ($ORACLE_HOME/network/admin/*) and the OCI libraries which are in -$ORACLE_HOME/lib. You'll also need the header files from -$ORACLE_HOME/sqllib/public/*.h and $ORACLE_HOME/rdbms/demo/*.h (you won't -need them all, but you can get rid of them after DBD::Oracle compiles). - -So just put that stuff on your client box and install DBI and DBD::Oracle -there. Once DBD::Oracle is installed you can remove the OCI libraries and -headers (make sure to keep SQL*Net!) - -------------------------------------------------------------------------------- -OS/Oracle version: Solaris 2 and Oracle 7.3 - -Problem: DBD::Oracle works on the database machine, but not from remote -machines (via TCP). SQL*Plus, however, does work from the remote machines. - -Cause: $ORACLE_HOME/ocommon/nls/admin/data/lx1boot.nlb is missing - -Solution: Make sure $ORACLE_HOME/ocommon is available on the remote machine. - -This was the first time I had used DBD::Oracle with Oracle 7.3.2. Oracle -7.1 has a somewhat different directory structure, and seems to store files -in different places relative to $ORACLE_HOME. So I just hadn't NFS -exported all the files I needed to. I figured that as long as SQL*Plus -was happy, I had all the necessary files to run DBD::Oracle (since that -was always the case with 7.1). But I was wrong. - -James Cooper - -------------------------------------------------------------------------------- -Subject: Re: Oracle Licencing... -Date: Thu, 15 May 1997 11:54:09 -0700 -From: Mark Dedlow - -Please forgive the continuation of this somewhat off-topic issue, -but I wanted to correct/update my previous statement, and it's -probably of interest to many DBD-Oracle users. - -> > In general, as I understand it, Oracle doesn't license the client runtime -> > libraries directly, rather they get you for SQL*NET. It is typically -> > about $100 per node. You have to have that licensed on any machine -> > that runs DBD-Oracle. - -Oracle recently changed policy. sqlnet now comes with RDBMS licenses. -If you have named RDBMS licenses, you can install sqlnet on as many -client machines as you have named licenses for the server. If you -have concurrent RDBMS licenses, you can install sqlnet on as many -client machines as you like, and only use concurrently as many -as you have concurrent server RDBMS licenses. - -OCI, Pro*C, et. al. only requires you to have a development license, -per developer. The compiled apps can be distributed unlimited. -The client where the client app resides must be licensed to use -sqlnet, by the above terms, i.e. by virtue of what the licenses on -the server are that the client is connecting to. - -This means one could legitimately distribute DBD-Oracle in compiled form. -Probably not recommended :-) - -But is does mean one can compile DBD-Oracle and distribute it internally -to your org without more licensing, as long as the targets have sqlnet. - -Obviously, this is not a legal ruling. I don't work for Oracle. -But this is what my sales rep tells me as of today. - -Mark -------------------------------------------------------------------------------- - -From: Wintermute - -Ok, you may think me daft for this but I just figured out what was -necessary in using DBI/DBD:Oracle on a machine that needs to access a -remote Oracle database. - -What the docs tell you is that you just need enough of Oracle installed -to compile it. They don't say that you need to keep that "just enough" -around for the DBI to work properly!! - -So here's my predicament so that others might benefit from my bumbling. - -I needed to install Perl, DBI, and DBD:Oracle on a machine running a -Fast Track web server (hostname Leviathan) that is to access a remote -Oracle database (henceforth called Yog-Sothoth (appropriate for the -beast that it is)). Leviathan doesn't have enough space for the 500M -install that Oracle 7 for Solaris 2.5.1 wants so I had to figure out a -way to get things done. Here's a brief list of the steps I took for -Leviathan. - -1. Got the GCC binary dist for Solaris 2.6 and installed -2. Got Perl 5.004_01 source/compiled/installed -3. Got the DBI .90 compiled/installed -4. Got DBD:Oracle... - - (and here's where it gets interesting). - - I exported the /opt/oracle7 directory from Yog-Sothoth to -Leviathan in -order to compile DBD:Oracle, then umount'ed it afterwards. Tried 'make -test' after it had compiled and watched it flounder and fail. For the -life of me I couldn't figure out why this could be so, so I went back -and adjusted my TWO_TASK/ORACLE_USERID env vars. - No luck. - Wash/Rinse/Repeat. - Still no luck. -I started to get desperate about this time, so instead of screwing with -it anymore I installed the module under the Perl heirarchy just to be -done for the moment with it (figuring that the 'make test' script could -be fallible). I neglected to mention that the errors I was getting were -coming from the Oracle database on the remote machine, so I knew it -worked in part, just not well enough to hold the connection for some -reason. - -After having no luck with my own Perl connect script I tried remounting -the nfs volume with Oracle on it and setting ORACLE_HOME to it. When I -ran that very same Perl script it WORKED! Well sort of. None of the -short connection methods worked, I was forced to use the long method of -connecting IE: name/password@dbname(DESCRIPTION=(ADDRESS=(...etc.etc. - -So here I am figuring that I'm doing something right, but there's -something I'm missing. Well it turns out that it's not me, it's the -machine that's missing it. If you are going to be using the DBD:Oracle -driver with DBI, you'll need more than just it after compile time, -you'll need some Oracle files as well. - -(BTW I'm running Oracle 7.3.2.2.0) - -You'll need everything in /var/opt/oracle (on the machine that houses -Oracle), as well as $ORACLE_HOME/ocommon/nls. Why National Language -Support is needed I'll never know. ocommon/nls has to reside under the -directory your $ORACLE_HOME points to, and it's best to leave -/var/opt/oracle/'s path alone. - -When I made these adjustments on the Oracle'less box and tried the 'make - -test' again, it ran through without a hitch. I'll be doing some more -intensive things with it from here on out and if anything changes I'll -let you all know, however this seems odd that nothing is mentioned in -the documentation about what residual files need to be around after -compiling the DBD:Oracle for it to work successfully. - -Like I said, don't flame me for being stupid, but I just had to get this -story off my chest since I've been puzzling over it all day and I feel -that other people may want to do the same thing as I did, and will run -into the same problems. - --- Wintermute - -------------------------------------------------------------------------------- diff --git a/README.help.txt b/README.help.txt index cfbe9932..7e68453c 100644 --- a/README.help.txt +++ b/README.help.txt @@ -7,132 +7,6 @@ same or similar problems may exist on other systems or versions. Most of this mess is due to Oracle's fondness for changing the build/link process for OCI applications between versions. -------------------------------------------------------------------------------- -Error: 'UV' not in typemap in Oracle.xs, line ... - -You're using Perl 5.5.3. Perl 5.5.3 is very old and and upgrading -to at least 5.6.1 is recommended. The DBI itself has required -perl >= 5.6.0 since DBI 1.38, August 2003. - -Meanwhile, edit Oracle.xs and change each UV to an IV, change newSVuv to newSViv, -cross your fingers, and avoid using longer, bigger, wider than 2GB, or less than zero! -This is a hacked DBD::Oracle and not recommended for production use. - -------------------------------------------------------------------------------- -If you get compiler errors refering to Perl's own header files -(.../CORE/*.h) then there is something wrong with your installation. -It is best to use a Perl that was built on the system you are trying to -use and it's also important to use the same compiler that was used to -build the Perl you are using. - -------------------------------------------------------------------------------- -Assorted runtime problems... - -Ensure that the version of Oracle you are talking to is the same one -you used to build your DBD::Oracle module. - -Try building perl with 'usemymalloc' disabled. -Try building perl with 'threads' enabled (esp for Oracle >= 8.1.6). - -Try removing "-lthread" from $ORACLE_HOME/lib/ldflags and/or -$ORACLE_HOME/lib/sysliblist just for the duration of the DBD::Oracle build -(but I can't really recommend this approach as it may cause subtle -problems later) - -If you find a memory leak that you can isolate to DBD::Oracle, and you're -using a perl built with threading enabled, first try rebuilding perl without -support for threads. Apart from making perl run faster it may also fix the leak. -Please report memory leaks, with a small self-contained test script, -to dbi-users@perl.org. - -------------------------------------------------------------------------------- -Bad free() warnings: - -These are generally caused by problems in Oracle's own library code. -You can use this code to hide them: - - $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Bad free/ } - -If you're using an old perl version (below 5.004) then upgrading will -probably fix the warnings (since later versions can disable that warning) -and is highly recommended anyway. - -Alternatively you can rebuild Perl without perl's own malloc and/or -upgrade Oracle to a more recent version that doesn't have the problem. - -------------------------------------------------------------------------------- -Can't find libclntsh.so: - -Dave Moellenhoff : libclntsh.so is the shared -library composed of all the other Oracle libs you used to have to -statically link. -libclntsh.so should be in $ORACLE_HOME/lib. If it's missing, try -running $ORACLE_HOME/lib/genclntsh.sh and it should create it. - -Also: Never copy libclntsh.so to a different machine or Oracle version. -If DBD::Oracle was built on a machine with a different path to libclntsh.so -then you'll need to set set an environment variable, typically -LD_LIBRARY_PATH, to include the directory containing libclntsh.so. - -But: LD_LIBRARY_PATH is typically ignored if the script is running set-uid -(which is common in some httpd/CGI configurations). In this case -either rebuild with LD_RUN_PATH set to include the path to libclntsh -or create a symbolic link so that libclntsh is available via the same -path as it was when the module was built. (On Solaris the command -"ldd -s Oracle.so" can be used to see how the linker is searching for it.) - - -------------------------------------------------------------------------------- -Error while trying to retrieve text for error ...: - -From Lou Henefeld : We discovered that we needed -some files from the $ORACLE_HOME/ocommon/nls/admin/data directory: - lx00001.nlb, lx10001.nlb, lx1boot.nlb, lx20001.nlb -If your national language is different from ours (American English), -you will probably need different nls data files. - - -------------------------------------------------------------------------------- -ORA-01019: unable to allocate memory in the user side - -From Ethan Tuttle : My experience: ORA-01019 errors -occur when using Oracle 7.3.x shared libraries on a machine that -doesn't have all necessary Oracle files in $ORACLE_HOME. - -It used to be with 7.2 libraries that all one needed was the tnsnames.ora -file for a DBD-Oracle client to connect. Not so with 7.3.x. I'm not sure -exactly which additional files are needed on the client machine. - -Furthermore, from what I can tell, the path to ORACLE_HOME is resolved and -compiled into either libclntsh.so or the DBD-Oracle. Thus, copying a -minimal ORACLE_HOME onto a client machine won't work unless the path to -ORACLE_HOME is the same on the client machine as it is on the machine -where DBD-Oracle was compiled. - -ORA-01019 can also be caused by corrupt Oracle config files such as -/etc/oratab. - -ORA-01019 can also be caused by using a different version of the -message catalogs ($ORACLE_HOME/ocommon/nls/admin/data) to that used -when DBD::Oracle was compiled. - -Also try building with oracle.mk if your DBD::Oracle defaulted to proc.mk. - -------------------------------------------------------------------------------- -SCO - For general help enabling dynamic loding under SCO 5 - - http://www2.arkansas.net/~jcoy/perl5/ - -------------------------------------------------------------------------------- -AIX - warnings like these when building perl are not usually a problem: - -ld: 0711-415 WARNING: Symbol Perl_sighandler is already exported. -ld: 0711-319 WARNING: Exported symbol not defined: Perl_abs_amg - -When building on AIX check to make sure that all of bos.adt (13 pieces) -and all of bos.compat (11 pieces) are installed. - -Thanks to Mike Moran for this information. ------------------------------------------------------------------------------- AIX 4 - core dump on login and similar problems @@ -376,13 +250,6 @@ Try each of these in turn (follow each with a make && make test): perl Makefile.PL -n LIBCLNTSH let me know if any of these help. -------------------------------------------------------------------------------- -Some runtime problems might be related to perl's malloc. - -This is a long shot. If all else fails and perl -V:usemymalloc says -usemymalloc='y' then try rebuilding perl using Configure -Uusemymalloc. -If this does fix it for you then please let me know. - =============================================================================== Hang during "repetitive connect/open/close/disconnect" test: diff --git a/README.java.txt b/README.java.txt deleted file mode 100644 index 8958df27..00000000 --- a/README.java.txt +++ /dev/null @@ -1,322 +0,0 @@ -README.java.txt - -This file relates to a specific problem on Solaris platforms -for Oracle 8.1.6 (and possibly later versions) where loading -DBD::Oracle fails with an error message like: - - ``You must install a Solaris patch to run this version of - the Java runtime. - Please see the README and release notes for more information.'' - -The problem seems to be that: - -1/ By default, the Oracle shared library contains a ``Radius - authentication module'' that is implemented in Java. -2/ The Java implementation requires that the thread library is - also linked into the application. -3/ For some inexplicable reason the thread library has to be - linked to the executable that's doing the dynamic loading. - It's is not sufficient to link -lthread to DBD::Oracle. - -There are several ways to workaround this: - -1/ Remove the Radius authentication module if you don't need it. - This requires you to perform surgery on the Oracle installation. - (If the name Radius doesn't mean anything to you and you're - the person maintaining the Oracle installation then you almost - certainly don't need it.) - -2/ Use the LD_PRELOAD environment variable to force the pre-loading - of the thread library. Note that this must be set before perl - starts, you can't set it via $ENV{LD_PRELOAD} within the script. - -3/ Link the thread library to your perl binary. - You can do that either by (re)building perl with thread support - or, I believe, it should be possible to issue a magic 'ld' command - to add linkage to the thread library to an existing perl executable. - (But you'll need to work that one out yourself. If you do please let - me know so I can add the details here to share with others.) - -Most of this information comes from Andi Lamprecht, to whom I'm very -grateful indeed. - -I've included below two of his email messages, slightly edited, where -he explains the procedure for options 1 and 2 above. I've also -appended a slight reworking of option 1 from Paul Vallee. And I've later -added some more useful messages from other people. - -Tim. - ----- - - -From: andi@sunnix.sie.siemens.at - -Have managed it to get DBD to work with Oracle 8i without these nasty Java -error! It seems to be that a thing called "NAU" links in a radius -athentication module which is written in Java and this causes the -additional java libraries in the libclntsh.so. After throwing it all out -DBD tests ran successfully. - -The steps to take are: - - - shut down Oracle server if you have one running in the installation - you're about to modify. - - take a backup copy of your Oracle installation! You have been warned! - - - go to $ORACLE_HOME/network/lib (or it maybe (also?) in $ORACLE_HOME/oas/lib) - - rebuild nautab.o with: - - make -f ins_nau.mk NAU_ADAPTERS="IDENTIX KERBEROS5 SECURID" nautab.o - - This build a new nautab.o without the radius authentication module. - - - go to $ORACLE_HOME/lib - - edit file "ldflags" and delete all occurences of "-lnrad8" and "-ljava" - and "-[LR]$ORACLE_HOME/JRE/lib/sparc/native_threads" - - - go to $ORACLE_HOME/bin - - build a new libclntsh.so with: - - genclntsh - - - start up Oracle - - - go back to the DBD-* directory and build the Oracle driver with: - - perl Makefile.PL; make; make test - -This worked for me, the database is still operational, MAYBE SOME JAVA -STUFF ISN'T WORKING. Better someone else with more experience in java -finds out ... - -The problem seems to be a dynamic linking issue. Whenever java virtual -machine is loaded, some symbols are missing (with java 1.2.2_05 these -_thread_something symbols where not found, even with linked-in -libthread.so, with java 1.1.8 some _lseek or so symbols couldn't be -resolved). Seems Oracle did a good job in integration of Java in the -database ... - -Ok, should go out now 'cause its a beatiful wheater here in Vienna! - -Greetings -A. Lamprecht - ------------ - - -From: andi@sunnix.sie.siemens.at - -For some reason libthread.so.1 isn't included as dynamic object in perl -binary and so symbols aren't found. - -The interesting output of LD_DEBUG=symbols: -symbol=thr_getstate; dlsym() starting at file=/usr/local/bin/perl -symbol=thr_getstate; lookup in file=/usr/local/bin/perl [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libsocket.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libnsl.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libdl.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libm.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libc.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libcrypt_i.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libmp.so.2 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libgen.so.1 [ ELF ] -ld.so.1: /usr/local/bin/perl: fatal: thr_getstate: can't find symbol - -This list looks exactly like the one you get when ldd-ing the perl binary. -There is an option to the dynamic linker "LD_PRELOAD" and if you set it with - - LD_PRELOAD=/lib/libthread.so.1 - export LD_PRELOAD - -before starting any DBD::oracle app, the app works! (Note that this must -be set before perl starts, you can't set it via $ENV{LD_PRELOAD} within -the script.) - -It looks like after libjava and libjvm is loaded, the library search path -is somehow stripped to the one of the perl binary ... - -[That looks like a Solaris bug] - -Hope this helps. - -A. Lamprecht ------------ - - -From: Paul Vallee - -Andi is right. Three cheers for Andi!!! :-) - -Final Summary (this is mostly Andi's work summarized here) - -1. Copy your ORACLE_HOME in it's entirety to a new directory. -cp -r $ORACLE_HOME $ORACLE_HOME.nojava - -2. Set your ORACLE_HOME variable to the new one. Save the old one for reference. -export OLD_ORACLE_HOME=$ORACLE_HOME -export ORACLE_HOME=$ORACLE_HOME.nojava - -3. cd $ORACLE_HOME/network/lib (or it maybe (also?) in $ORACLE_HOME/oas/lib) -This is your new ORACLE_HOME - the temporary one that will soon be without -Java or Radius. - -4. build nautab.o with -make -f ins_nau.mk NAU_ADAPTERS="IDENTIX KERBEROS5 SECURID" nautab.o - -5. go to $ORACLE_HOME/lib -edit file "ldflags" and delete all occurences of "-lnrad8" and "-ljava" -and "-[LR]$ORACLE_HOME/JRE/lib/sparc/native_threads" -I wrote this little pipeline to do this. -sed 's/-lnrad8//g' < ldflags | \ -sed 's/-ljava//g' | \ -sed "s%-L$OLD_ORACLE_HOME/JRE/lib/sparc/native_threads%%g" | \ -sed "s%-R$OLD_ORACLE_HOME/JRE/lib/sparc/native_threads%%g" | > newldflags -If you look at newldflags, and like it, then run: -cp ldflags oldldflags; cp newldflags ldflags - -6. go to $ORACLE_HOME/bin and build a new libclntsh.so with "genclntsh" -genclntsh - -7. go to your DBD::oracle install directory and go through the regular -install process. -perl Makefile.PL; make; make install -(I find the make test less useful than my test.pl perl file.) - -8. Set LD_LIBRARY_PATH=$ORACLE_HOME/lib. -This part is very important - remember that at this stage ORACLE_HOME is set -to the nojava home. Make this permanent by explicitly setting -LD_LIBRARY_PATH to the nojava lib directory in your .profile. -This is the step that stalled me - thanks again to Andi. - -9. Test this out. I use the following command which fails -nicely if we've failed, and is very quiet if we've succeeded: - perl -MDBD::Oracle -e 0 -there should be no output. Congratulations. - -10. Get rid of everything other than libclntsh.so in your new ORACLE_HOME - -the rest is a waste of space. -cd $ORACLE_HOME; cd .. -mv $ORACLE_HOME $ORACLE_HOME.rmme -mkdir $ORACLE_HOME; mkdir $ORACLE_HOME/lib -cp $ORACLE_HOME.rmme/lib/libclntsh.so $ORACLE_HOME/lib - -11. Run test.pl again just to be sure it still works. - -12. If test.pl is still working, then we can reclaim space with -rm -fr $ORACLE_HOME.rmme - -Note that in my opinion this is a workaround - there is no reason on the -face of it that I can fathom that we shouldn't be able to use DBD::Oracle to -connect to Oracle with Java compiled in. (?) - -Enjoy, -Paul Vallee -Principal -The Pythian Group, Inc. ------------------------------------------------------------------------------- - -From: Peter Ludemann - -Here's a different way for ensuring that LD_PRELOAD has been set: - - unless (($ENV{LD_PRELOAD}||'') =~ /thread.so/) { - $ENV{LD_PRELOAD} = '/lib/libthread.so'; - exec($^X, '-w', $0, @ARGV); - } - -This hasn't been rigorously tested, but it seems to do the trick, at -least on Solaris 7 with Oracle 8. - ------------------------------------------------------------------------------- - -From: VG - -I've had luck with adding the following at the top of my program: - -use DynaLoader; -Dynaloader::db_load_file("/usr/lib/libthread.so", 0x01); - -(Others have reported this nor working for them.) - ------------------------------------------------------------------------------- - -From: daver@despair.tmok.com (Dave C.) -Subject: Re: DBI::DBD with Oracle 8i -Newsgroups: comp.lang.perl.modules - -It looks like a lot of people are having this problem.... - -I managed to solve it. I'm running Oracle 8.1.6, Solaris 8, Perl 5.6.0, -and the latest DBI/DBD modules. - -I did some experimentation and discovered that the root of the problem -was that libclntsh.so was linking with nautab.o. For some reason, -nautab.o was linked with this RADIUS authentication (?) thing that was -calling into Java (even though I don't use that particular functionality.) - -So, what I had to do was generate a libclntsh.so that linked with a -nautab.o that didn't require the radius (and thus the java). I then -forced the Oracle DBD to link with my library and installed it, and it -worked. - -Here's the step-by-step: - -To do this, first copy the "genautab" and "genclntsh" scripts to a -scratch directory. By default "genautab" apparently generates some -default network authentication stub without a lot of options (which was -okay for me.) - -I ran: - - ./genautab >nautab.s - as -P nautab.s - -After this step you should have a "nautab.o" file. - -Now, you must must modify "genclntsh" to produce your custom clntsh -library (which I called "perlclntsh" so I wouldn't mess up the original -Oracle library.) So I went into the file and modified CLNT_NAM to read -"perlclntsh". I also changed LIB_DIR to put the resulting library in -my current directory: (LIB_DIR=`pwd`) - -Also, instead of creating the library, I modified the script to just -echo the command. Search for "# Create library" and put "echo " before -{$LD} ${LD_RUNTIME}... Now, when you run "./genclntsh" you should get -a large command. Redir this command to a file "./genclntsh >t" - -Now, edit this file and remove all references to java libraries (get -rid of all "-ljava" instances, at least, and you may need to delete -other stuff, like -lnative_threads.) . Run your script: "sh ./t". -After some time you should wind up with a "libperlclntsh.so.8.0". -This is your custom library any of the java stuff linked in. - -Then copy this lib to /usr/local/lib and create a softlink -"libperlclntsh.so" to "libperlclntsh.so.8.0" (or copy it wherever you -want...) - -Then you have to force DBD to link with this library instead of linking -with the libclntsh.so provided by Oracle. - -Basically what I did was follow the normal DBD-Oracle directions. I -then edited the resulting Makefile manually and changed all references -of libclntsh.so to libperlclnt.so (ie, -lclntsh to -lperlclntsh) I -also changed the LDDLFLAGS and LDFLAGS and appended "-L/usr/local/lib --R/usr/local/lib -L/usr/ucblib -R/usr/ucblib -lucb". (for some reason -the resulting DBD wanted to link with ucb) Run "make" and rebuild the -DBD. Now "make test" should pass. - -Note that this was a fairly long (couple of hours) series of trial and -error before I finally got this to work. Your system may be different -and you may encounter your own linking problems, etc. - -Disclaimer: This may not work for you, but it worked for me. Even if it -does work for you there is no guarantee that the resulting module will -function correctly and won't hose your database, etc... - -I forgot to mention that in script resulting from genclntsh you must -tell it to use _your_ nautab.o for linking, not the oracle lib one. -Oops. - --Dave - diff --git a/README.sec.txt b/README.sec.txt deleted file mode 100644 index 72920db6..00000000 --- a/README.sec.txt +++ /dev/null @@ -1,142 +0,0 @@ -I have no intention of becoming a channel for Oracle Support Services -but this is a significant security hole and so I'm making an exception. - ------ Forwarded message from Oracle Support Services ----- - -Date: Fri, 7 May 1999 06:29:09 -0700 -From: Oracle Support Services -Subject: SUID Security Issue - -Platform: UNIX - -Distribution: Internal & External - -Problem Subject Line: SUID Security - -Product: Oracle Enterprise Manager 2.0.4 - Oracle Data Server - -Oracle Version: 8.0.3, 8.0.4, 8.0.5, 8.1.5 - -Component: Intelligent Agent - Oracle Data Server - -Component Version: 8.0.3, 8.0.4, 8.0.5, 8.1.5 - -Sub-Component: N/A - -Platform Version: All Unix Versions. - -Errors: N/A - -Revision Date: 6-March-1999 - -Problem Description: - -On UNIX platforms, some executable files have the setuid (SUID) -bit on. It may be possible for a knowledgeable user to use -these executables to bypass your system security by elevating -their operating system privileges. Oracle Corporation has -identified issues regarding executables with SUID set in -Oracle releases 8.0.3, 8.0.4, 8.0.5 and 8.1.5 on UNIX platforms -only. This problem will be fixed in Oracle releases 8.0.6 and -8.1.6. - -Depending on your Oracle installation, the available patch will 1) -correct the SUID bits on applicable files, and/or 2) delete the -oratclsh file. This shell script should be run immediately, and also -should be run after each relink of Oracle. - -You can download the patch from Oracle Support?s MetaLink website by -going to the following URL, -http://support.oracle.com/ml/plsql/mlv15.frame?call_type=download&javaFlag=JAVA. -Once you are in this page, select 'Oracle RDBMS' as the product -and then click on the 'Go' button. Then download patch named 'setuid.' - -Please contact Oracle Worldwide Support for any additional issues. - ------ End forwarded message ----- - -Date: Sat, 08 May 1999 19:12:52 -0700 -From: Mark Dedlow - -I went to the URL listed for the patch, but it appears you can't get to -it directly. It requires a Oracle Metalink account, and even then, you -have to follow a bunch of links to get it, you can't go direct (at -least I couldn't at the URL in the announcement). - -You don't really need the patch however, it's just a shell script that -in effect does chmod -s on everything in $ORACLE_HOME/bin except -'oracle' and 'dbsnmp' (needed only for OEM or SNMP). - -Also, although the patch didn't address the issue, make sure _nothing_ -below ORACLE_HOME is owned by root. There are some installations that -make certain files setuid to root (files that are trivial to compromise). - -Mark - - ------------------------------------------------------------------------------- - -From: Dan Sugalski -Date: Mon, 10 May 1999 09:13:28 -0700 - -The patch actually removes the setuid bit on a number of oracle -executables. The 'unset' list is: - -lsnrctl oemevent onrsd osslogin tnslsnr tnsping trcasst trcroute cmctl -cmadmin cmgw names namesctl otrccref otrcfmt otrcrep otrccol oracleO - -While the 'must set' list is: - -oracle dbsnmp - -The shell script to fix the bits properly was posted to the oracle list -running at telelists.com. Check the archives there for it if you want. -(www.telelists.com) I think it's also gone out to one of the BUGTRAQ -lists, and some of the CERTs might have it too. - - Dan - ------------------------------------------------------------------------------- - -Date: Wed, 12 May 1999 11:49:45 -0700 -From: Mark Dedlow - -> The patch actually removes the setuid bit on a number of oracle -> executables. The 'unset' list is: -> -> lsnrctl oemevent onrsd osslogin tnslsnr tnsping trcasst trcroute cmctl -> cmadmin cmgw names namesctl otrccref otrcfmt otrcrep otrccol oracleO - -Actually, there's a little more than that. For each item in that list, -it also looks for a version of the file with a 0 or O appended to it -(these are backups the link makefiles create), so the above list isn't -exactly complete. - -The important issues are simply: - - o *ONLY* $ORACLE_HOME/bin/oracle requires setuid bit set for - the Oracle RDBMS and tools to function. - - o *IF* you run dbsnmp, it must be setuid. (If you don't know what dbsnmp - is, you're probably not running it -- it's a remote monitoring/control - daemon) - -Armed with that knowledge, you can use any technique you like to achieve -the desired results. For example, this achieves it: - -find $ORACLE_HOME/bin -perm -2000 ! -name oracle ! -name dbsnmp | xargs chmod -s - -Mark - ------------------------------------------------------------------------------- - -One further note I'll pass on anonymously and without comment: - -> please include something like: "After removing the setuid bits, slap -> your system administrator for running root.sh as root without actually -> reading it first." -> :) - ------------------------------------------------------------------------------- diff --git a/README.win32.txt b/README.win32.txt deleted file mode 100644 index e3ad66db..00000000 --- a/README.win32.txt +++ /dev/null @@ -1,236 +0,0 @@ -In general, on Windows, it's best to just use ActiveState Perl and the -PPM package manager to install a pre-built version of DBD::Oracle however only version 1.17 is available there. - -If you built Perl with gcc, read README.wingcc.txt as well as this file. - - -Oracle Instant Client 11.1.0.6.0 Notes - -So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value -in the environment variables. - -As well IC 11 seems to have trouble finding the .ORA files. A quick fix for this is to add "TNS_ADMIN" -to the environment variables and point it to where your .ORA files are. - - ---- other information, some of which is out of date --- - -DBD-Oracle for Windows and Oracle Instantclient and 10XE (Express Edition) -By: John Scoles Scoles@ptyhian.com -The Pythian Group - -The preferred method of getting DBD::Oracle is to use a pre-built version from the ActiveState -repository, which can be installed with PPM. - -Compiling and installing DBD::Oracle 1.18 or later on a windows 2000 professional or XP OS for use -with Oracle instantClient ver 10.2.0.1 & 10.1.0.5 or Oracle XE requires only a few downloads and -a minimal number of environment setting. The procedures below were tested on a clean -Windows platform having no Oracle or other development environment installed. - -1) The first part of the process is to download and install the latest version of - Active Perl from http://www.activeperl.com/. - -2) Use the PPM application to get the latest version of DBI - -3) Download the latest DBD::Oracle from http://svn.perl.org/modules/dbd-oracle/trunk/ - -4) Download and unzip the Oracle Instant Client (10.2.0.1 or 10.1.0.5) 32 bit from - http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html - You will need all three of these products - i. Instant Client Package - Basic - ii. Instant Client Package - SQL*Plus: - iii. Instant Client Package - SDK: - or - - install oracle 10XE http://www.oracle.com/technology/products/database/xe/index.html - -5) You will now need the Microsoft Visual C++ toolkit 2003. Unfortunately this product is no longer available from Microsoft. - The file name was VCToolkitSetup.exe and is available at this mirror site http://www.filewatcher.com/m/VCToolkitSetup.exe.32952488.0.0.html at the time of writing. - Microsoft's replacement for this tool kit is Visual C++ 2005 Express Edition and all attempts to compile DBD::Oracle with this product fail. It has been successfully compiled - using a complete edition of Microsoft Visual Studio 2005. - Download and then install this product. - -6) You will also need the Windows SDK. Which can be found at - http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en - You have the choice to of either to download the entire SDK and install or run an online install from the page. - Both have been tested and proven to work. - -7) Next download and install the Microsoft .net framework 1.1 skd from - http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&displaylang=en - -8) You will also need a copy of nmake.exe which you can download here http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe - -9) Enough Downloading and installing go have a coffee. - -10) You should at this time attempt to connect to an Oracle database with the version SQL*Plus that - you installed in step 4. If you are unable to connect at this stage then any problems you encounter - later may have nothing to do with DBD::Oracle - -11) On the path where you installed Visual C++ find and edit the vcvars32.bat file as follows. You may have to modify - these path values depending where you installed the products on you computer, - - i. Add the local path to the windows platform SDK include directory to the Set INCLUDE - Command Line to include the needed files from the Windows SDK. - - e.g. "C:\Program Files\Microsoft Platform SDK\Include;" - - ii. Add the local path to the .net Vc7 lib directory to the Set LIB command - to include the needed library file from the .Net SKD - - e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; - - iii. Add the local path to the windows platform SDK Lib directory to the Set Lib command - to include the needed library files from the Windows SDK - - e.g. C:\Program Files\Microsoft Platform SDK\Lib; - -12) Open a Windows Visual C++ command window from the start menu. - -13) Add the path to the instant client to the Path command. If you are compiling aginst a 10XE db/client then you can skip steps - 12 to 14. - e.g. PATH = C:/Oracle/instantclient;%PATH% - -14) Using the "Set" command add "ORACLE_HOME=path to Instant client" to the environment variables. - e.g. Set ORACLE_HOME=C:\Oracle\instantclient - -15) Using the "Set" command add "NLS_LANG=.WE8ISO8859P15" to the environment variables. The globalization variable is required, - with this or another compatible value, by Oracle instantclient in order for it to compile correctly. - e.g. Set NLS_LANG=.WE8ISO8859P15 - -16) Using the "Set" command add "ORACLE_USERID=test/test@test" substituting test with the username/password@database - you wish to run the make test files against. - Note: it is not necessary to do this step for the compile and install to work. - However: The self-test programs included with Oracle-DBD will mostly fail. - -17) Move to the DBD-Oracle directory in the Visual C++ window DOS prompt and enter the following. - - c:\oracle-dbd\>perl Makefile.PL - - The Makefile should then run and compile Oracle-dbd without reporting any errors. - -18) From this DOS prompt enter the following command - - c:\oracle-dbd\>nmake - - The Visual C++ make executable will then build you DBD-execuable. There should be no errors at this point. - -19) You can test the compile by either entering - - c:\oracle-dbd\>nmake test - - As long as you have given a valid user name, password and database name in step 15 you will see some results. If it appears to - run but you do not get a connection check the following. - - i. User name password and DB Name - ii. Ensure the a valid TNSNAMES.ORA file is in the Instantclient directory - iii. Attempt to log into the version of SQLPLUS that comes with Instantclient. - If you manage to log on use the username password and TNS name with - the Set ORACLE_USERID = and rerun the tests. - iv If you are compiling against 10XE and have skiped steps 12 to 14 try again bu this time carry out these steps - -20) You can now install DBD-Oracle into you system by entering the following command from the Visual C++ window dos prompt; - - c:\oracle-dbd\>nmake install - -21) You should now be able to run DBD-Oracle on you system - -09/30 2006 from asu - -DBD::Oracle 1.18a - -Linux, Debian unstable ( -DBI: 1.52 -perl v5.8.8 built for i486-linux-gnu-thread-multi -) - -Oracle Instant client (10.1.0.5) - -The problem is in Makefile.PL. In line 130 the function find_oracle_home -is used to guess a value form $ORACLE_HOME if it is not set explicitely. -This value is used in line 138 to setup the environment (regardless -which client is used). - -in line 1443 (sub get_client_version) sqlplus is used to get the -version string, but for the oracle instant client you must not set -$ORACLE_HOME (it will generate an error "SP2-0642: SQL*Plus internal -error state 2165, context 4294967295:0:0") - -A solution that worked for me was to set -local $ENV{ORACLE_HOME} = ''; -in line 1463 immediately before sqlplus is called (but I cannot tell if -this fails for full client installations) - - -11/30/05 -- John Scoles -I have confirmed that this Makefile.pl will work for both Oracle InstantClient -10.2.0.1 & 10.1.0.4 using same process the Andy Hassall uses. Starting with a clean OD -One needs only to get the latest version of Active Perl 5.8.7 use PPM to get DBI and then -install Microsoft Visual C++ toolkit, Windows SDK, and the Microsoft .net -framework 1.1. and modify the vcvars32.bat in C++ dir as follows - - 1) Add the local path to the windows platform SDK include directory to the - Set INCLUDE Command Line to include the needed files from the Windows SDK. - e.g. "C:\Program Files\Microsoft Platform SDK\Include;" - 2) Add the local path to the .net Vc7 lib directory to the Set LIB - command to include the needed library files from the .Net SKD - e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; - 3) Add the local path to the windows platform SDK Lib directory to the Set Lib - command to include the needed library files from the Windows SDK - e.g. C:\Program Files\Microsoft Platform SDK\Lib; - -If one happens to have visual studio installed you may not have to download additional MS products. - -12/01/05 --- John Scoles -Oracle 10XE -No big problem here as 10XE seems to use the instantclient as well. Just ensure your - NLS_LANG and ORACLE_HOME are set to the same directory that 10XE uses - - -10/07/05 --John Scoles -Andy Hassall Kindly added some changes to the Makefile.PL -so it will work for the Instant Client 10g on Windows OSs. Below is how he set -up his environment and the steps he preformed to get it to compile. - - Setting environment for using Microsoft Visual Studio .NET 2003 tools. - (If you have another version of Visual Studio or Visual C++ installed and wish - to use its tools from the command line, run vcvars32.bat for that version.) - - C:\Documents and Settings\andyh>d: - - D:\>cd cygwin\home\andyh\src\pythian - - D:\cygwin\home\andyh\src\pythian>set ORACLE_HOME=d:\lib\instantclient_10_2 - - D:\cygwin\home\andyh\src\pythian>set NLS_LANG=.WE8ISO8859P15 - - D:\cygwin\home\andyh\src\pythian>set PATH=d:\lib\instantclient_10_2;D:\Program F - iles\Microsoft Visual Studio .NET 2003\Common7\IDE;D:\Program Files\Microsoft Vi - sual Studio .NET 2003\VC7\BIN;D:\Program Files\Microsoft Visual Studio .NET 2003 - \Common7\Tools;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ - bin\prerelease;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ - bin;D:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;C:\WINNT\Mic - rosoft.NET\Framework\v1.1.4322;d:\Perl\bin\;C:\WINNT\system32;C:\WINNT;C:\WINNT\ - System32\Wbem;D:\Program Files\Microsoft SDK\Bin;D:\Program Files\Microsoft SDK\ - Bin\WinNT - - D:\cygwin\home\andyh\src\pythian>set ORACLE_USERID=test/test@test102 - - D:\cygwin\home\andyh\src\pythian>perl Makefile.PL - - - -4/27/04 -- Jeff Urlwin - -Do not untar this distribution in a directory with spaces. This will not work. - -i.e. C:\Program Files\ORacle\DBD Oracle Distribution is bad while -c:\dev\dbd-oracle-1.15 is good ;) - -9/14/02 -- Michael Chase - -Makefile.PL uses Win32::TieRegistry or Win32::Registry to find the -current Oracle Home directory if the ORACLE_HOME environment variable -is not set. If neither module is installed, you must set ORACLE_HOME -before running Makefile.PL. Since the registry location of the current -Oracle Home is in different locations in different Oracle versions, -it is usually safer to set ORACLE_HOME before running Makefile.PL. diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm deleted file mode 100644 index d6a7a112..00000000 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ /dev/null @@ -1,377 +0,0 @@ -package DBD::Oracle::Troubleshooting; -#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle - -=pod - -=head1 CONNECTING TO ORACLE - -If you are reading this it is assumed that you have successfully -installed DBD::Oracle and you are having some problems connecting to -Oracle. - -First off you will have to tell DBD::Oracle where the binaries reside -for the Oracle client it was compiled against. This is the case when -you encounter a - - DBI connect('','system',...) failed: ERROR OCIEnvNlsCreate. - -error in Linux or in Windows when you get - - OCI.DLL not found - -The solution to this problem in the case of Linux is to ensure your -'ORACLE_HOME' (or LD_LIBRARY_PATH for InstantClient) environment -variable points to the correct directory. - - export ORACLE_HOME=/app/oracle/product/xx.x.x - -For Windows the solution is to add this value to you PATH - - PATH=c:\app\oracle\product\xx.x.x;%PATH% - - -If you get past this stage and get a - - ORA-12154: TNS:could not resolve the connect identifier specified - -error then the most likely cause is DBD::ORACLE cannot find your .ORA -(F, F, F) files. This can be -solved by setting the TNS_ADMIN environment variable to the directory -where these files can be found. - -If you get to this stage and you have either one of the following -errors; - - ORA-12560: TNS:protocol adapter error - ORA-12162: TNS:net service name is incorrectly specified - -usually means that DBD::Oracle can find the listener but the it cannot connect to the DB because the listener cannot find the DB you asked for. - -=head2 Oracle utilities - -If you are still having problems connecting then the Oracle adapters -utility may offer some help. Run these two commands: - - $ORACLE_HOME/bin/adapters - $ORACLE_HOME/bin/adapters $ORACLE_HOME/bin/sqlplus - -and check the output. The "Protocol Adapters" should include at least "IPC Protocol Adapter" and "TCP/IP -Protocol Adapter". - -If it generates any errors which look relevant then please talk to your -Oracle technical support (and not the dbi-users mailing list). - -=head2 Connecting using a bequeather - -If you are using a bequeather to connect to a server -on the same host as the client, you might have -to add - - bequeath_detach = yes - -to your sqlnet.ora file or you won't be able to safely use fork/system -functions in Perl. - -See the discussion at -L -and L -for more gory details. - - -=head1 USING THE LONG TYPES - -Some examples related to the use of LONG types are available in -the C directory of the distribution. - -=head1 LINUX - -=head2 Installing with Instantclient .rpm files. - -Nothing special with this you just have to set up you permissions as follows; - -1) Have permission for RWE on '/usr/lib/oracle/10.2.0.3/client/' or the other directory where you RPMed to - -2) Set export ORACLE_HOME=/usr/lib/oracle/10.2.0.3/client - -3) Set export LD_LIBRARY_PATH=$ORACLE_HOME/lib - -4) If you plan to use tnsnames to connect to remote servers and your tnsnames.ora file is not in $ORACLE_HOME/network/admin, you will need to Export TNS_ADMIN=dir to point DBD::Oracle to where your tnsnames.ora file is - -=head2 undefined symbol: __cmpdi2 comes up when Oracle isn't properly linked to the libgcc.a library. - -In version 8, this was correctd by changing the SYSLIBS entry in -$ORACLE_HOME/bin/genclntsh to include -"-L/usr/lib/gcc-lib/i386-redhat-linux/3.2 -lgcc". - -I had tried this with no success as when this program was then run, the -error "unable to find libgcc" was generated. Of course, this was the -library I was trying to describe! - -It turns out that now it is necessary to edit the same file and append -"`gcc -print-libgcc-file-name`" (including the backquotes!). If you do -this and then run "genclntsh", the libclntsh is properly generated and -the linkage with DBD::Oracle proceeds properly. - - -=head2 cc1: invalid option `tune=pentium4'" error - -If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. - -No real problem with the above however you will have to - -1) run Perl Makefile.PL - -2) edit the Makefile and remove the offending '-mtune=pentium4' text - -3) save and exit - -4) do the make install and it should work fine for you - -=head2 Oracle 9i Lite - -The advice is to use the regular Oracle9i not the lite version. - -Another great source of help was: http://www.puschitz.com/InstallingOracle9i.html - -just getting 9i and 9i lite installed. I use fvwm2(nvidia X driver) as -a window manager which does not work with the 9i install program, works -fine with the default Gnomish(nv X driver), it could have been the X -driver too. - -With Redhat9 it is REAL important to set LD_ASSUME_KERNEL to 2.4.1. - -I didn't try this but it may be possible to install what is needed by -only downloading the first disk saving some 1.3GB of download fun. - -I installed a custom install from the client group. The packages I -installed are the Programmers section and sqlplus. I noticed that the -Pro*C when on as a result of the checking the Programmers section I -assume. - -Once Oracle was installed properly the DBD::Oracle install went as -smooth as just about every other CPAN module. - -=head2 Oracle 10g Instantclient - -The Makefile.PL will now work for Oracle 10g Instantclient. To have both the Compile and -the test.pl to work you must first have the LD_LIBRARY_PATH correctly set to your -"instantclient" directory. (http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html) - -The present version of the make creates a link on your "instantclient" directory as follows -"ln -s libclntsh.so.10.1 libclntsh.so". It is needed for both the makefile creation and the compile -but is not need for the test.pl. It should be removed after the compile. - -If the Makefile.PL or make fails try creating this link directly in your "instantclient" directory. - -=head2 Oracle Database 10g Express Edition 10.2 - -To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY_PATH -as you would for an install against 10g Standard Edition, Standard Edition One, or -Enterprise Edition - -=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 - -DBD::Oracle seems to hit some sort of bug with the above two versions of DB. -The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also -been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. - -So far there is no patch for this but here are some work arounds - - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); - ... - $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); - - or this way - - $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders - - or this way - - utf8::downgrade($parameter, 1); - - -=head1 CYGWIN - -Makefile.PL should find and make use of OCI include -files, but you have to build an import library for -OCI.DLL and put it somewhere in library search path. -one of the possible ways to do this is issuing command - - dlltool --input-def oci.def --output-lib liboci.a - -in the directory where you unpacked DBD::Oracle distribution -archive. this will create import library for Oracle 8.0.4. - -Note: make clean removes '*.a' files, so put a copy in a safe place. - -=head2 Compiling DBD::Oracle using the Oracle Instant Client, Cygwin Perl and gcc - -=over - -=item 1 - -Download these two packages from Oracle's Instant Client for -Windows site -(http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/winsoft.html): - -Instant Client Package - Basic: All files required to run OCI, -OCCI, and JDBC-OCI applications - -Instant Client Package - SDK: Additional header files and an -example makefile for developing Oracle applications with Instant Client - -(I usually just use the latest version of the client) - -=item 2 - -Unpack both into C:\oracle\instantclient_11_1 - -=item 3 - -Download and unpack DBD::Oracle from CPAN to some place with no -spaces in the path (I used /tmp/DBD-Oracle) and cd to it. - -=item 4 - -Set up some environment variables (it didn't work until I got the -DSN right): - - ORACLE_DSN=DBI:Oracle:host=oraclehost;sid=oracledb1 - ORACLE_USERID=username/password - -=item 5 - - perl Makefile.PL - make - make test - make install - -=back - -Note, the TNS Names stuff doesn't always seem to work with the instant -client so Perl scripts need to explicitly use host/sid in the DSN, like -this: - - my $dbh = DBI->connect('dbi:Oracle:host=oraclehost;sid=oracledb1', - 'username', 'password'); - -=head2 SUN - -If you get this on a Solaris 9 and 10 box - - "Outofmemory! - Callback called exit. - END failed--call queue aborted." - -The solution may be as simple as not having you "ORACLE_HOME" Defined in the -environment. - -It seems that having it defined will prevent the error. - -=head2 VMS - -This is related to Oracle RDBMS 9.2 and later, since Oracle -made fundamental changes to oracle installation requirements -and factual installation with this release. - -Oracle's goal was to make VMS installation be more like on -*nix and Windows, with an all new Oracle Home structure too, -requiring an ODS-5 disk to install Oracle Home on instead of -the good old ODS-2. - -Another major change is the introduction of an Oracle generated -logical name table for oracle logical names like ORA_ROOT and all -its derivatives like ORA_PROGINT etc. And that this logical name -table is inserted in LNM$FILE_DEV in LNM$PROCESS_DIRECTORY. - - (LNM$PROCESS_DIRECTORY) - - "LNM$FILE_DEV" = "SERVER_810111112" - = "LNM$PROCESS" - = "LNM$JOB" - = "LNM$GROUP" - = "LNM$SYSTEM" - = "DECW$LOGICAL_NAMES" - -This ensures that any process that needs to have access to -oracle gets the environment by just adding one logical name table -to a central process specific mechanism. - -But as it is inserted at the very top of LNM$FILE_DEV it also -represents a source of misfortune - especially if a user with -enough privilege to update the oracle table does so (presumably -unintentionally), as an examble by changing NLS_LANG. - -PERL has the abillity to define, redefine and undefine (deassign) -logical names, but if not told otherwise by the user does it -in the first table in above list, and not as one would normally -expect in the process table. - -Installing DBI and DBD::Oracle has influence upon this since in -both cases a few environment variables are read or set in the -test phase. -For DBI it is the logical SYS$SCRATCH, which is a JOB logical. -For DBD-Oracle it is when testing a new feature in the Oracle -RDBMS: UTF8 and UTF16 character set functionality, and in order -to do this it sets and unsets the related environment variables -NLS_NCHAR and NLS_LANG. - -If one is not careful this changes the values set in the oracle -table - and in the worst case stays active until the next major -system reset. It can also be a very hard error to track down -since it happens in a place where one normally never looks. - -Furthermore, it is very possibly that some or all of the UTF tests -fails, since if one have a variable like NLS_LANG in his process -table, then even though 'mms test' sets it in the wrong table -it is not invoked as it is overruled by the process logical... - -The way to ensure that no logicals are set in the oracle table and -that the UTF tests get the best environment to test in, and that -DBI correctly translates the SYS$SCRATCH logical, use the -logical - - PERL_ENV_TABLES - -to ensure that PERL's behavior is to leave the oracle table alone and -use the process table instead: - - $ DEFINE PERL_ENV_TABLES LNM$PROCESS, LNM$JOB - -This tells PERL to use the LNM$PROCESS table as the default place to -set and unset variables so that only the perl users environment -is affected when installing DBD::Oracle, and ensures that the -LNM$JOB table is read when SYS$SCRATCH is to be translated. - -PERL_ENV_TABLES is well documented in the PERLVMS man page. - -Oracle8 releases are not affected, as they don't have the -oracle table implementation, and no UTF support. - -Oracle 9.0 is uncertain, since testing has not been possible yet, -but the remedy will not hurt :) - -=head1 Miscellaneous - -=head2 Crash with an open connection and Module::Runtime in mod_perl2 - -See RT 72989 (https://rt.cpan.org/Ticket/Display.html?id=72989) - -Apache2 MPM Prefork with mod_perl2 will crash if Module::Runtime is -loaded, and an Oracle connection is opened through PerlRequire (before -forking). - -It looks like this was fixed in 0.012 of Module::Runtime. - -=head2 bin_param_inout swapping return values - -See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) - -It seems that in some older versions of Oracle Instant Client -(certainly 10.2.0.4.0) when output parameters are bound with lengths -greater than 3584 the output parameters can be returned in the wrong -placeholders. - -It is reported fixed in Instant Client 11.2.0.2.0. - -=cut diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod new file mode 100644 index 00000000..1efeffc2 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -0,0 +1,125 @@ +#PODNAME: DBD::Oracle::Troubleshooting +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle + +=head1 CONNECTING TO ORACLE + +If you are reading this it is assumed that you have successfully +installed DBD::Oracle and you are having some problems connecting to +Oracle. + +First off you will have to tell DBD::Oracle where the binaries reside +for the Oracle client it was compiled against. This is the case when +you encounter a + + DBI connect('','system',...) failed: ERROR OCIEnvNlsCreate. + +error in Linux or in Windows when you get + + OCI.DLL not found + +The solution to this problem in the case of Linux is to ensure your +'ORACLE_HOME' (or LD_LIBRARY_PATH for InstantClient) environment +variable points to the correct directory. + + export ORACLE_HOME=/app/oracle/product/xx.x.x + +For Windows the solution is to add this value to you PATH + + PATH=c:\app\oracle\product\xx.x.x;%PATH% + + +If you get past this stage and get a + + ORA-12154: TNS:could not resolve the connect identifier specified + +error then the most likely cause is DBD::ORACLE cannot find your .ORA +(F, F, F) files. This can be +solved by setting the TNS_ADMIN environment variable to the directory +where these files can be found. + +If you get to this stage and you have either one of the following +errors; + + ORA-12560: TNS:protocol adapter error + ORA-12162: TNS:net service name is incorrectly specified + +usually means that DBD::Oracle can find the listener but the it cannot connect to the DB because the listener cannot find the DB you asked for. + +=head2 Oracle utilities + +If you are still having problems connecting then the Oracle adapters +utility may offer some help. Run these two commands: + + $ORACLE_HOME/bin/adapters + $ORACLE_HOME/bin/adapters $ORACLE_HOME/bin/sqlplus + +and check the output. The "Protocol Adapters" should include at least "IPC Protocol Adapter" and "TCP/IP +Protocol Adapter". + +If it generates any errors which look relevant then please talk to your +Oracle technical support (and not the dbi-users mailing list). + +=head2 Connecting using a bequeather + +If you are using a bequeather to connect to a server +on the same host as the client, you might have +to add + + bequeath_detach = yes + +to your sqlnet.ora file or you won't be able to safely use fork/system +functions in Perl. + +See the discussion at +L +and L +for more gory details. + + +=head1 USING THE LONG TYPES + +Some examples related to the use of LONG types are available in +the C directory of the distribution. + +=head1 Can't find I + +I is the shared +library composed of all the other Oracle libs you used to have to +statically link. +libclntsh.so should be in I<$ORACLE_HOME/lib>. If it's missing, try +running I<$ORACLE_HOME/lib/genclntsh.sh> and it should create it. + +Never copy I to a different machine or Oracle version. +If DBD::Oracle was built on a machine with a different path to I +then you'll need to set set an environment variable, typically +I, to include the directory containing I. + +I is typically ignored if the script is running set-uid +(which is common in some httpd/CGI configurations). In this case +either rebuild with I set to include the path to I +or create a symbolic link so that I is available via the same +path as it was when the module was built. (On Solaris the command +"ldd -s Oracle.so" can be used to see how the linker is searching for it.) + +=head1 Miscellaneous + +=head2 Crash with an open connection and Module::Runtime in mod_perl2 + +See RT 72989 (https://rt.cpan.org/Ticket/Display.html?id=72989) + +Apache2 MPM Prefork with mod_perl2 will crash if Module::Runtime is +loaded, and an Oracle connection is opened through PerlRequire (before +forking). + +It looks like this was fixed in 0.012 of Module::Runtime. + +=head2 bin_param_inout swapping return values + +See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) + +It seems that in some older versions of Oracle Instant Client +(certainly 10.2.0.4.0) when output parameters are bound with lengths +greater than 3584 the output parameters can be returned in the wrong +placeholders. + +It is reported fixed in Instant Client 11.2.0.2.0. diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod new file mode 100644 index 00000000..752ba37a --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -0,0 +1,250 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Aix +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on AIX + +=head1 Using Visual Age 7 C Compiler + +Oracle 9i is only certified as a 64-bit application on AIX 5L (5.1,5.2,5.3) with 32-bit support; +in other words, there is no 9i "32-bit" Oracle client + +Oracle 10g is certified as both a 64-bit application and a 32-bit Oracle client + +This information only pertains to deploying: + + the DBI (version 1.48) + and DBD-Oracle (version 1.16): + on AIX 5.3 + using Oracle 9i (9.2.0.1/9.2.0.5) + using the existing Perl 5.8.2 (no custom-built Perl) which is 32-bit + using Visual Age 7.0 C/C++ compiler + +Install the DBI (required for the DBD-Oracle install - no issues here) +Untar the DBD-Oracle bundle +Run Makefile.PL + + $ perl Makefile.PL + +Edit Makefile with following commands: + + 1,$s?/lib/ ?/lib32/ ?g + 1,$s?-q64??g + 1,$s?/lib/sysliblist?/lib32/sysliblist?g + +Now perform normal commands to perform the testing/making: + + $ make + $ make test + $ make install + +I've tested the basics of the DBD-Oracle and it seems fully functional. + +Stephen de Vries + + +=head1 Using gcc C Compiler + + DBD::Oracle with gcc and Oracle Instant Client on AIX + -------------------------------------------------------------------------------------- + Nathan Vonnahme Dec 15 2005, 4:28 pm Newsgroups: perl.dbi.users + See: http://groups.google.com/group/perl.dbi.users/msg/0bd9097f80f2c8a9 + [ with updates 1/31/2006 - DBD::Oracle 1.17 doesn't need makefile hacking + to work with instantclient on AIX ] + + + Yes! It eluded me last year but I finally got DBD::Oracle working on an + AIX machine using gcc. Here's the short version: + + First I had to recompile perl with gcc, using + sh Configure -de -Dcc=gcc + This apparently built a 32 bit perl, someday I will try getting it to go + 64 bit. + + I was then able to install and build DBI 1.50 with the CPAN shell. + + I downloaded the base and sdk packages of the Oracle Instant Client for + AIX -- first I tried the 64 bit but that didn't work with my 32 bit perl + -- the 32 bit version (still at 10.1.0.3) did the trick. I unzipped + them and moved the dir to /usr/local/oracle/instantclient10_1 and made a + symlink without the version at /usr/local/oracle/instantclient , then + set: + + export ORACLE_HOME=/usr/local/oracle/instantclient + export LIBPATH=$ORACLE_HOME + + + + Oracle wasn't providing the sqlplus package for 32 bit AIX so I + explicitly told Makefile.PL the version: + + perl Makefile.PL -V 10.1 + + make + + My test databases were on other machines so I set these environment variables + to get the tests to run: + + export ORACLE_DSN=DBI:Oracle://host/dbinstance + export ORACLE_USERID="user/password" + + make test + make install + + + NOTE: I have an older full version of Oracle on this machine, and the + ORACLE_HOME environment variable is normally set to point to that, so + my perl scripts that use DBD::Oracle have to make sure to first set + $ENV{ORACLE_HOME}='/usr/local/oracle/instantclient'; + + + + + + -------------------------------------------------------------------------------------- + The following setup worked to build on AIX 5.2: + gcc-3.3.2 (32-bit) (configure opts [ --with-ld=/usr/ccs/bin/ld --with-as=/usr/ccs/bin/as]) + Oracle-9.2.0 ( full install w/32bit support) + perl-5.8.3 (built with above gcc/latest stable as of March 2004) + Followed the directions from Rafael's email below, only set ORACLE_HOME, (and + the appropriate test environmentals). + 1) build perl-5.8.3 with gcc + 2) install DBI + 3) ORACLE_HOME="your oracle home" + ORACLE_USERID.. + ORACLE_SID .. + (I ignored ORACCENV, didn't use it.) + 4) install DBD::Oracle, after perl Makefile.PL, edit the created Makefile, + changing references to Oracle's ../lib to ../lib32. and change crt0_64.o to + crt0_r.o. Remove the -q32 and/or -q64 options from the list of libraries to + link with. + 5) make should be clean, make test should pass. + This setup worked with 8.1.7 w/32 bit support, and with 9.2.0 w/ 32-bit support. + --Adrian Terranova + + +=head1 Using xlc_r C Compiler + + From: Rafael Caceres + Date: 22 Jul 2003 10:05:20 -0500 + + The following sequence worked for me on AIX 5.1: + + -use Perl 5.8.0 (the latest stable from CPAN) + + -use the xlc_r version of IBM's compiler and build a 32 bit Perl + (which xlc_r will do by default). All tests should be successful. + + -get and install DBI + + -get DBD::Oracle. Edit the Makefile.PL or Makefile for DBD::Oracle, + changing references to Oracle's ../lib to ../lib32. and change crt0_64.o + to crt0_r.o. Remove the -q32 and/or -q64 options from the list of + libraries to link with. Do the make and make test. + + -Set up the environment for making DBD::Oracle: + ORACLE_HOME="your oracle home" + ORACCENV = "xlc_r" + ORACLE_USERID.. + ORACLE_SID .. + + -Run make, all tests should be successfull -against Oracle 9.x at least. + + You should have no problems with Oracle 8.1.7, but accessing Oracle 7.x + or previous is not possible (you'll core dump, or simply hang). The same + goes for a Linux build or a Digital build, regarding access of different + Oracle versions. + + Rafael Caceres + + > I dont believe I compiled Oracle. During the installation it was linked + > but I am not sure it was compiled + > + > I used a xlc compiler to compile PERL. + > Got this message in the Perl Makefile.PL output + > + > Warning: You will may need to rebuild perl using the xlc_r compiler. + > You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV + > Also see the README about the -p option + > + > this probobly means I need to rebuild PERL with xlc_r?? + > + > thanx + > + > Mike Paladino + > Database Administrator + + + From: Rafael Caceres + > + > Make sure you use the same compiler to build Oracle and Perl. We have + > used xlc_r on Aix 5.1 with no problems. Your Perl build is 32 bit, so + > when building DBD::Oracle, you should use the 32bit libraries (change + > references to .../oracle/lib to .../oracle/lib32 in your Makefile). + > Remove the references to the -q64 or -q32 parameters for ld in Makefile, + > as they shouldn't be there. + > + > Rafael Caceres + + + From: "cartman ltd" + Subject: Tip for DBI and DBD::Oracle on AIX 5.1 and Oracle 9.2 + Date: Mon, 11 Aug 2003 18:15:38 +0000 + Message-ID: + + Here is a tip for compiling DBD::Oracle as a 32 bit application on AIX 5.1 + 64 bit and Oracle 9.2 64 bit without editting any makefiles. I hope people + find this useful: + + First, the versions of products I used: + DBI version 1.32 + DBD::Oracle version 1.14 + Oracle 9.2.0.2 - default 64 bit application with 32 bit libraries + AIX 5.1 ML03 - 64 bit kernel - ships with Perl as a 32 bit application. + VisualAge C/C++ 5.0.2 + + Basically DBD must be compiled as 32 bit to link with Perl's 32 bit + libraries. + gunzip -c DBD-Oracle-1.14.tar.gz | tar xvf  + cd DBD-Oracle-1.14 + perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk + make + + NB: I think there is a bug in the Oracle 9.2.0.3 file + $ORACLE_HOME/rdbms/lib/env_rdbms.mk + I corrected this (before running the above commands) by replacing the + invalid linker option + LDFLAGS32=-q32 + with + LDFLAGS32=-b32 + + Have fun: KC. + -------------------------------------------------------------------------------------- + + Date: Wed, 30 Jun 2004 23:34:24 -0500 + From: "SCHULTZ, DARYLE (SBCSI)" + + Got it to work. Using dbd 1.16 + + Perl 5.8.4 built like this, with Visual Age 6.0: + + config_args='-Dcc=xlc_r -Dusenm -Dprefix=/appl/datasync/work/perl5 + -Dusethreads -Duse64bitall -des' + ============================================== + + Used DBI 1.42 + ============================================= + Added this to top of Oracle.h: + #define A_OSF + + #include + ======================= + Set LIBPATH to point to 64bit Oracle libs first. + export LIBPATH=$ORACLE_HOME/lib:$ORACLE_HOME/lib32:/usr/lib + + Use: perl Makefile.PL -nob + + Change all references in Makefile of LD_RUN_PATH to be LIBPATH. + Change nothing else, left all flags in Makefile, including -q64. + Passed make, and all tests. + + -------------------------------------------------------------------------------------- + + diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod new file mode 100644 index 00000000..e994bd77 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -0,0 +1,68 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Cygwin +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Cygwin + +=head1 General Info + +Makefile.PL should find and make use of OCI include +files, but you have to build an import library for +OCI.DLL and put it somewhere in library search path. +one of the possible ways to do this is issuing command + + dlltool --input-def oci.def --output-lib liboci.a + +in the directory where you unpacked DBD::Oracle distribution +archive. this will create import library for Oracle 8.0.4. + +Note: make clean removes '*.a' files, so put a copy in a safe place. + +=head1 Compiling DBD::Oracle using the Oracle Instant Client, Cygwin Perl and gcc + +=over + +=item 1 + +Download these two packages from Oracle's Instant Client for +Windows site +(http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/winsoft.html): + +Instant Client Package - Basic: All files required to run OCI, +OCCI, and JDBC-OCI applications + +Instant Client Package - SDK: Additional header files and an +example makefile for developing Oracle applications with Instant Client + +(I usually just use the latest version of the client) + +=item 2 + +Unpack both into C:\oracle\instantclient_11_1 + +=item 3 + +Download and unpack DBD::Oracle from CPAN to some place with no +spaces in the path (I used /tmp/DBD-Oracle) and cd to it. + +=item 4 + +Set up some environment variables (it didn't work until I got the +DSN right): + + ORACLE_DSN=DBI:Oracle:host=oraclehost;sid=oracledb1 + ORACLE_USERID=username/password + +=item 5 + + perl Makefile.PL + make + make test + make install + +=back + +Note, the TNS Names stuff doesn't always seem to work with the instant +client so Perl scripts need to explicitly use host/sid in the DSN, like +this: + + my $dbh = DBI->connect('dbi:Oracle:host=oraclehost;sid=oracledb1', + 'username', 'password'); + diff --git a/README.hpux.txt b/lib/DBD/Oracle/Troubleshooting/Hpux.pm similarity index 99% rename from README.hpux.txt rename to lib/DBD/Oracle/Troubleshooting/Hpux.pm index 0c483d00..2e759c5d 100644 --- a/README.hpux.txt +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pm @@ -1,3 +1,6 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Hpux +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on HP-UX + =head1 INTRODUCTION Building a working dynamically linked version of the Oracle DBD driver diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod new file mode 100644 index 00000000..659d8848 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -0,0 +1,108 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Linux +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Linux + +=head1 Installing with Instantclient .rpm files. + +Nothing special with this you just have to set up you permissions as follows; + +1) Have permission for RWE on '/usr/lib/oracle/10.2.0.3/client/' or the other directory where you RPMed to + +2) Set export ORACLE_HOME=/usr/lib/oracle/10.2.0.3/client + +3) Set export LD_LIBRARY_PATH=$ORACLE_HOME/lib + +4) If you plan to use tnsnames to connect to remote servers and your tnsnames.ora file is not in $ORACLE_HOME/network/admin, you will need to Export TNS_ADMIN=dir to point DBD::Oracle to where your tnsnames.ora file is + +=head1 undefined symbol: __cmpdi2 comes up when Oracle isn't properly linked to the libgcc.a library. + +In version 8, this was correctd by changing the SYSLIBS entry in +$ORACLE_HOME/bin/genclntsh to include +"-L/usr/lib/gcc-lib/i386-redhat-linux/3.2 -lgcc". + +I had tried this with no success as when this program was then run, the +error "unable to find libgcc" was generated. Of course, this was the +library I was trying to describe! + +It turns out that now it is necessary to edit the same file and append +"`gcc -print-libgcc-file-name`" (including the backquotes!). If you do +this and then run "genclntsh", the libclntsh is properly generated and +the linkage with DBD::Oracle proceeds properly. + + +=head1 cc1: invalid option `tune=pentium4'" error + +If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. + +No real problem with the above however you will have to + +1) run Perl Makefile.PL + +2) edit the Makefile and remove the offending '-mtune=pentium4' text + +3) save and exit + +4) do the make install and it should work fine for you + +=head1 Oracle 9i Lite + +The advice is to use the regular Oracle9i not the lite version. + +Another great source of help was: http://www.puschitz.com/InstallingOracle9i.html + +just getting 9i and 9i lite installed. I use fvwm2(nvidia X driver) as +a window manager which does not work with the 9i install program, works +fine with the default Gnomish(nv X driver), it could have been the X +driver too. + +With Redhat9 it is REAL important to set LD_ASSUME_KERNEL to 2.4.1. + +I didn't try this but it may be possible to install what is needed by +only downloading the first disk saving some 1.3GB of download fun. + +I installed a custom install from the client group. The packages I +installed are the Programmers section and sqlplus. I noticed that the +Pro*C when on as a result of the checking the Programmers section I +assume. + +Once Oracle was installed properly the DBD::Oracle install went as +smooth as just about every other CPAN module. + +=head1 Oracle 10g Instantclient + +The Makefile.PL will now work for Oracle 10g Instantclient. To have both the Compile and +the test.pl to work you must first have the LD_LIBRARY_PATH correctly set to your +"instantclient" directory. (http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html) + +The present version of the make creates a link on your "instantclient" directory as follows +"ln -s libclntsh.so.10.1 libclntsh.so". It is needed for both the makefile creation and the compile +but is not need for the test.pl. It should be removed after the compile. + +If the Makefile.PL or make fails try creating this link directly in your "instantclient" directory. + +=head1 Oracle Database 10g Express Edition 10.2 + +To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY_PATH +as you would for an install against 10g Standard Edition, Standard Edition One, or +Enterprise Edition + +=head1 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 + +DBD::Oracle seems to hit some sort of bug with the above two versions of DB. +The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also +been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. + +So far there is no patch for this but here are some work arounds + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or this way + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + or this way + + utf8::downgrade($parameter, 1); + + diff --git a/README.macosx.txt b/lib/DBD/Oracle/Troubleshooting/Macos.pod similarity index 78% rename from README.macosx.txt rename to lib/DBD/Oracle/Troubleshooting/Macos.pod index 57801dad..36b78b60 100644 --- a/README.macosx.txt +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -1,3 +1,8 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Macos +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on MacOs + +=head1 General Info + These instructions allow for the compilation and successful testing of DBD::Oracle on MacOS X 10.2.4 and higher, using Oracle 9iR2 DR (Release 9.2.0.1.0) or the 10g Instant Client release (10.1.0.3 at the @@ -47,8 +52,7 @@ if you are on 10.3 (Panther) and you do not intend to run the Oracle database server on your MacOSX box. See below (Instructions for 10.3.x) for details. -====================================================================== -Instructions for 10.7.x (Lion) +=head1 Instructions for 10.7.x (Lion) Because the 64 bit instantclient (version 10gr2)is currently [incompatible with Lion][], DBD::Oracle can only be compiled with the @@ -62,8 +66,8 @@ is released. If you have a 32-bit Perl, however, then the following steps should work: * Download and install the 32-bit basic, sqlplus, and sdk instantclient - libraries and install them in a central location, such as - `/usr/oracle_instantclient`. [Downloads here][]. +libraries and install them in a central location, such as +`/usr/oracle_instantclient`. [Downloads here][]. [Downloads here]: http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html @@ -81,8 +85,7 @@ If you have a 32-bit Perl, however, then the following steps should work: cpan DBD::Oracle -====================================================================== -Instructions for 10.6.x (Snow Leopard) +=head1 Instructions for 10.6.x (Snow Leopard) These are taken from a stackoverflow answer by "nickisfat" who gave his/her permission for its inclusion here. You can see the original @@ -171,8 +174,7 @@ install DBI Now you're all set - enjoy your perly oracley new life -====================================================================== -Instructions for 10.2.x (Jaguar) +=head1 Instructions for 10.2.x (Jaguar) 1) Install Oracle exactly per Oracle documentation. If you change install locations, then you'll need to modify paths accordingly. @@ -227,102 +229,102 @@ follow nonetheless. compile with Perl 5.6.0; they may not be necessary with other versions of IO and Perl, respectively. -+=+=+=+=+=+=+= Cut after this line -diff -c ../IO-orig/IO-1.20/IO.xs ./IO.xs -*** ../IO-orig/IO-1.20/IO.xs Mon Jul 13 23:36:24 1998 ---- ./IO.xs Sat May 10 15:20:02 2003 -*************** -*** 205,211 **** - ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); - } - else { -! ST(0) = &sv_undef; - errno = EINVAL; - } - ---- 205,211 ---- - ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); - } - else { -! ST(0) = &PL_sv_undef; - errno = EINVAL; - } - -*************** -*** 249,255 **** - SvREFCNT_dec(gv); /* undo increment in newRV() */ - } - else { -! ST(0) = &sv_undef; - SvREFCNT_dec(gv); - } - ---- 249,255 ---- - SvREFCNT_dec(gv); /* undo increment in newRV() */ - } - else { -! ST(0) = &PL_sv_undef; - SvREFCNT_dec(gv); - } - -*************** -*** 272,278 **** - i++; - fds[j].revents = 0; - } -! if((ret = poll(fds,nfd,timeout)) >= 0) { - for(i=1, j=0 ; j < nfd ; j++) { - sv_setiv(ST(i), fds[j].fd); i++; - sv_setiv(ST(i), fds[j].revents); i++; ---- 272,278 ---- - i++; - fds[j].revents = 0; - } -! if((ret = io_poll(fds,nfd,timeout)) >= 0) { - for(i=1, j=0 ; j < nfd ; j++) { - sv_setiv(ST(i), fds[j].fd); i++; - sv_setiv(ST(i), fds[j].revents); i++; -diff -c ../IO-orig/IO-1.20/poll.c ./poll.c -*** ../IO-orig/IO-1.20/poll.c Wed Mar 18 21:34:00 1998 ---- ./poll.c Sat May 10 14:28:22 2003 -*************** -*** 35,41 **** - # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) - - int -! poll(fds, nfds, timeout) - struct pollfd *fds; - unsigned long nfds; - int timeout; ---- 35,41 ---- - # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) - - int -! io_poll(fds, nfds, timeout) - struct pollfd *fds; - unsigned long nfds; - int timeout; -diff -c ../IO-orig/IO-1.20/poll.h ./poll.h -*** ../IO-orig/IO-1.20/poll.h Wed Apr 15 20:33:02 1998 ---- ./poll.h Sat May 10 14:29:11 2003 -*************** -*** 44,50 **** - #define POLLHUP 0x0010 - #define POLLNVAL 0x0020 - -! int poll _((struct pollfd *, unsigned long, int)); - - #ifndef HAS_POLL - # define HAS_POLL ---- 44,50 ---- - #define POLLHUP 0x0010 - #define POLLNVAL 0x0020 - -! int io_poll _((struct pollfd *, unsigned long, int)); - - #ifndef HAS_POLL - # define HAS_POLL -+=+=+=+=+=+=+= Cut to the previous line + +=+=+=+=+=+=+= Cut after this line + diff -c ../IO-orig/IO-1.20/IO.xs ./IO.xs + *** ../IO-orig/IO-1.20/IO.xs Mon Jul 13 23:36:24 1998 + --- ./IO.xs Sat May 10 15:20:02 2003 + *************** + *** 205,211 **** + ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); + } + else { + ! ST(0) = &sv_undef; + errno = EINVAL; + } + + --- 205,211 ---- + ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); + } + else { + ! ST(0) = &PL_sv_undef; + errno = EINVAL; + } + + *************** + *** 249,255 **** + SvREFCNT_dec(gv); /* undo increment in newRV() */ + } + else { + ! ST(0) = &sv_undef; + SvREFCNT_dec(gv); + } + + --- 249,255 ---- + SvREFCNT_dec(gv); /* undo increment in newRV() */ + } + else { + ! ST(0) = &PL_sv_undef; + SvREFCNT_dec(gv); + } + + *************** + *** 272,278 **** + i++; + fds[j].revents = 0; + } + ! if((ret = poll(fds,nfd,timeout)) >= 0) { + for(i=1, j=0 ; j < nfd ; j++) { + sv_setiv(ST(i), fds[j].fd); i++; + sv_setiv(ST(i), fds[j].revents); i++; + --- 272,278 ---- + i++; + fds[j].revents = 0; + } + ! if((ret = io_poll(fds,nfd,timeout)) >= 0) { + for(i=1, j=0 ; j < nfd ; j++) { + sv_setiv(ST(i), fds[j].fd); i++; + sv_setiv(ST(i), fds[j].revents); i++; + diff -c ../IO-orig/IO-1.20/poll.c ./poll.c + *** ../IO-orig/IO-1.20/poll.c Wed Mar 18 21:34:00 1998 + --- ./poll.c Sat May 10 14:28:22 2003 + *************** + *** 35,41 **** + # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) + + int + ! poll(fds, nfds, timeout) + struct pollfd *fds; + unsigned long nfds; + int timeout; + --- 35,41 ---- + # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) + + int + ! io_poll(fds, nfds, timeout) + struct pollfd *fds; + unsigned long nfds; + int timeout; + diff -c ../IO-orig/IO-1.20/poll.h ./poll.h + *** ../IO-orig/IO-1.20/poll.h Wed Apr 15 20:33:02 1998 + --- ./poll.h Sat May 10 14:29:11 2003 + *************** + *** 44,50 **** + #define POLLHUP 0x0010 + #define POLLNVAL 0x0020 + + ! int poll _((struct pollfd *, unsigned long, int)); + + #ifndef HAS_POLL + # define HAS_POLL + --- 44,50 ---- + #define POLLHUP 0x0010 + #define POLLNVAL 0x0020 + + ! int io_poll _((struct pollfd *, unsigned long, int)); + + #ifndef HAS_POLL + # define HAS_POLL + +=+=+=+=+=+=+= Cut to the previous line - compile and install as you usually would, making sure that existing but conflicting modules get removed: @@ -344,8 +346,7 @@ diff -c ../IO-orig/IO-1.20/poll.h ./poll.h $ make test $ make install -====================================================================== -Instructions for 10.3.x (Panther) +=head1 Instructions for 10.3.x (Panther) I highly recommend you install and use the Oracle 10g Instant Client for MacOSX 10.3. Compared to traditional Oracle client installations @@ -389,34 +390,34 @@ That said, here are the details. Here is the patch: -+=+=+=+=+=+=+= Cut after this line -*** Makefile.PL.orig Fri Oct 22 02:07:04 2004 ---- Makefile.PL Fri May 13 14:28:53 2005 -*************** -*** 1252,1257 **** ---- 1252,1258 ---- - print "Found $dir/$_\n" if $::opt_d; - }, "$OH/rdbms", - "$OH/plsql", # oratypes.h sometimes here (eg HPUX 11.23 Itanium Oracle 9.2.0) -+ "$OH/sdk", # Oracle Instant Client default location (10g) - ); - @h_dir = keys %h_dir; - print "Found header files in @h_dir.\n" if @h_dir; -*************** -*** 1286,1292 **** ---- 1287,1297 ---- - open FH, ">define.sql" or warn "Can't create define.sql: $!"; - print FH "DEFINE _SQLPLUS_RELEASE\nQUIT\n"; - close FH; -+ # we need to temporarily disable login sql scripts -+ my $sqlpath = $ENV{SQLPATH}; -+ delete $ENV{SQLPATH}; - my $sqlplus_release = `$sqlplus_exe -S /nolog \@define.sql 2>&1`; -+ $ENV{SQLPATH} = $sqlpath if $sqlpath; - unlink "define.sql"; - print $sqlplus_release; - if ($sqlplus_release =~ /^DEFINE _SQLPLUS_RELEASE = "(\d?\d)(\d\d)(\d\d)(\d\d)(\d\d)"/) { -+=+=+=+=+=+=+= Cut to the previous line + +=+=+=+=+=+=+= Cut after this line + *** Makefile.PL.orig Fri Oct 22 02:07:04 2004 + --- Makefile.PL Fri May 13 14:28:53 2005 + *************** + *** 1252,1257 **** + --- 1252,1258 ---- + print "Found $dir/$_\n" if $::opt_d; + }, "$OH/rdbms", + "$OH/plsql", # oratypes.h sometimes here (eg HPUX 11.23 Itanium Oracle 9.2.0) + + "$OH/sdk", # Oracle Instant Client default location (10g) + ); + @h_dir = keys %h_dir; + print "Found header files in @h_dir.\n" if @h_dir; + *************** + *** 1286,1292 **** + --- 1287,1297 ---- + open FH, ">define.sql" or warn "Can't create define.sql: $!"; + print FH "DEFINE _SQLPLUS_RELEASE\nQUIT\n"; + close FH; + + # we need to temporarily disable login sql scripts + + my $sqlpath = $ENV{SQLPATH}; + + delete $ENV{SQLPATH}; + my $sqlplus_release = `$sqlplus_exe -S /nolog \@define.sql 2>&1`; + + $ENV{SQLPATH} = $sqlpath if $sqlpath; + unlink "define.sql"; + print $sqlplus_release; + if ($sqlplus_release =~ /^DEFINE _SQLPLUS_RELEASE = "(\d?\d)(\d\d)(\d\d)(\d\d)(\d\d)"/) { + +=+=+=+=+=+=+= Cut to the previous line The first hunk allows Makefile.PL to find the header files which are in a subdirectory sdk, and the second temporarily disables any @@ -499,16 +500,14 @@ instructions, and the Perl IO patch is credit to Hilmar Lapp, hlapp at gmx.net. Earlier and original instructions thanks to: - Andy Lester - Steve Sapovits - Tom Mornini + Andy Lester + Steve Sapovits + Tom Mornini Date: Tue, 15 Apr 2003 16:02:17 +1000 Subject: Compilation bug in DBI on OSX with threaded Perl 5.8.0 -From: Danial Pearce -To: -Message-ID: +From: Danial Pearce In regards to a previous message on this list: @@ -547,6 +546,3 @@ anything Apple are going to do about it. cheers Danial - -PS: Personal replies please, I have not subscribed to this list. - diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod new file mode 100644 index 00000000..5f48840e --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -0,0 +1,15 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Sun +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Sun + +=head1 General Info + +If you get this on a Solaris 9 and 10 box + + "Outofmemory! + Callback called exit. + END failed--call queue aborted." + +The solution may be as simple as not having you "ORACLE_HOME" Defined in the +environment. + +It seems that having it defined will prevent the error. diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod new file mode 100644 index 00000000..ff7ec012 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -0,0 +1,87 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Vms +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Vms + +=head1 General Info + +This is related to Oracle RDBMS 9.2 and later, since Oracle +made fundamental changes to oracle installation requirements +and factual installation with this release. + +Oracle's goal was to make VMS installation be more like on +*nix and Windows, with an all new Oracle Home structure too, +requiring an ODS-5 disk to install Oracle Home on instead of +the good old ODS-2. + +Another major change is the introduction of an Oracle generated +logical name table for oracle logical names like ORA_ROOT and all +its derivatives like ORA_PROGINT etc. And that this logical name +table is inserted in LNM$FILE_DEV in LNM$PROCESS_DIRECTORY. + + (LNM$PROCESS_DIRECTORY) + + "LNM$FILE_DEV" = "SERVER_810111112" + = "LNM$PROCESS" + = "LNM$JOB" + = "LNM$GROUP" + = "LNM$SYSTEM" + = "DECW$LOGICAL_NAMES" + +This ensures that any process that needs to have access to +oracle gets the environment by just adding one logical name table +to a central process specific mechanism. + +But as it is inserted at the very top of LNM$FILE_DEV it also +represents a source of misfortune - especially if a user with +enough privilege to update the oracle table does so (presumably +unintentionally), as an examble by changing NLS_LANG. + +PERL has the abillity to define, redefine and undefine (deassign) +logical names, but if not told otherwise by the user does it +in the first table in above list, and not as one would normally +expect in the process table. + +Installing DBI and DBD::Oracle has influence upon this since in +both cases a few environment variables are read or set in the +test phase. +For DBI it is the logical SYS$SCRATCH, which is a JOB logical. +For DBD-Oracle it is when testing a new feature in the Oracle +RDBMS: UTF8 and UTF16 character set functionality, and in order +to do this it sets and unsets the related environment variables +NLS_NCHAR and NLS_LANG. + +If one is not careful this changes the values set in the oracle +table - and in the worst case stays active until the next major +system reset. It can also be a very hard error to track down +since it happens in a place where one normally never looks. + +Furthermore, it is very possibly that some or all of the UTF tests +fails, since if one have a variable like NLS_LANG in his process +table, then even though 'mms test' sets it in the wrong table +it is not invoked as it is overruled by the process logical... + +The way to ensure that no logicals are set in the oracle table and +that the UTF tests get the best environment to test in, and that +DBI correctly translates the SYS$SCRATCH logical, use the +logical + + PERL_ENV_TABLES + +to ensure that PERL's behavior is to leave the oracle table alone and +use the process table instead: + + $ DEFINE PERL_ENV_TABLES LNM$PROCESS, LNM$JOB + +This tells PERL to use the LNM$PROCESS table as the default place to +set and unset variables so that only the perl users environment +is affected when installing DBD::Oracle, and ensures that the +LNM$JOB table is read when SYS$SCRATCH is to be translated. + +PERL_ENV_TABLES is well documented in the PERLVMS man page. + +Oracle8 releases are not affected, as they don't have the +oracle table implementation, and no UTF support. + +Oracle 9.0 is uncertain, since testing has not been possible yet, +but the remedy will not hurt :) + + diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod new file mode 100644 index 00000000..abe00447 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -0,0 +1,242 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Win32 +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Win32 + +=head1 GENERAL INFO + +In general, on Windows, it's best to just use ActiveState Perl and the +PPM package manager to install a pre-built version of DBD::Oracle however only version 1.17 is available there. + +If you built Perl with gcc, read README.wingcc.txt as well as this file. + + +=head1 Oracle Instant Client 11.1.0.6.0 Notes + +So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value +in the environment variables. + +As well IC 11 seems to have trouble finding the .ORA files. A quick fix for this is to add "TNS_ADMIN" +to the environment variables and point it to where your .ORA files are. + +=head1 Other information, some of which is out of date --- + + DBD-Oracle for Windows and Oracle Instantclient and 10XE (Express Edition) + By: John Scoles + The Pythian Group + +The preferred method of getting DBD::Oracle is to use a pre-built version from the ActiveState +repository, which can be installed with PPM. + +Compiling and installing DBD::Oracle 1.18 or later on a windows 2000 professional or XP OS for use +with Oracle instantClient ver 10.2.0.1 & 10.1.0.5 or Oracle XE requires only a few downloads and +a minimal number of environment setting. The procedures below were tested on a clean +Windows platform having no Oracle or other development environment installed. + + 1) The first part of the process is to download and install the latest version of + Active Perl from http://www.activeperl.com/. + + 2) Use the PPM application to get the latest version of DBI + + 3) Download the latest DBD::Oracle from http://svn.perl.org/modules/dbd-oracle/trunk/ + + 4) Download and unzip the Oracle Instant Client (10.2.0.1 or 10.1.0.5) 32 bit from + http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html + You will need all three of these products + i. Instant Client Package - Basic + ii. Instant Client Package - SQL*Plus: + iii. Instant Client Package - SDK: + or + + install oracle 10XE http://www.oracle.com/technology/products/database/xe/index.html + + 5) You will now need the Microsoft Visual C++ toolkit 2003. Unfortunately this product is no longer available from Microsoft. + The file name was VCToolkitSetup.exe and is available at this mirror site http://www.filewatcher.com/m/VCToolkitSetup.exe.32952488.0.0.html at the time of writing. + Microsoft's replacement for this tool kit is Visual C++ 2005 Express Edition and all attempts to compile DBD::Oracle with this product fail. It has been successfully compiled + using a complete edition of Microsoft Visual Studio 2005. + Download and then install this product. + + 6) You will also need the Windows SDK. Which can be found at + http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en + You have the choice to of either to download the entire SDK and install or run an online install from the page. + Both have been tested and proven to work. + + 7) Next download and install the Microsoft .net framework 1.1 skd from + http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&displaylang=en + + 8) You will also need a copy of nmake.exe which you can download here http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe + + 9) Enough Downloading and installing go have a coffee. + + 10) You should at this time attempt to connect to an Oracle database with the version SQL*Plus that + you installed in step 4. If you are unable to connect at this stage then any problems you encounter + later may have nothing to do with DBD::Oracle + + 11) On the path where you installed Visual C++ find and edit the vcvars32.bat file as follows. You may have to modify + these path values depending where you installed the products on you computer, + + i. Add the local path to the windows platform SDK include directory to the Set INCLUDE + Command Line to include the needed files from the Windows SDK. + + e.g. "C:\Program Files\Microsoft Platform SDK\Include;" + + ii. Add the local path to the .net Vc7 lib directory to the Set LIB command + to include the needed library file from the .Net SKD + + e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; + + iii. Add the local path to the windows platform SDK Lib directory to the Set Lib command + to include the needed library files from the Windows SDK + + e.g. C:\Program Files\Microsoft Platform SDK\Lib; + + 12) Open a Windows Visual C++ command window from the start menu. + + 13) Add the path to the instant client to the Path command. If you are compiling aginst a 10XE db/client then you can skip steps + 12 to 14. + e.g. PATH = C:/Oracle/instantclient;%PATH% + + 14) Using the "Set" command add "ORACLE_HOME=path to Instant client" to the environment variables. + e.g. Set ORACLE_HOME=C:\Oracle\instantclient + + 15) Using the "Set" command add "NLS_LANG=.WE8ISO8859P15" to the environment variables. The globalization variable is required, + with this or another compatible value, by Oracle instantclient in order for it to compile correctly. + e.g. Set NLS_LANG=.WE8ISO8859P15 + + 16) Using the "Set" command add "ORACLE_USERID=test/test@test" substituting test with the username/password@database + you wish to run the make test files against. + Note: it is not necessary to do this step for the compile and install to work. + However: The self-test programs included with Oracle-DBD will mostly fail. + + 17) Move to the DBD-Oracle directory in the Visual C++ window DOS prompt and enter the following. + + c:\oracle-dbd\>perl Makefile.PL + + The Makefile should then run and compile Oracle-dbd without reporting any errors. + + 18) From this DOS prompt enter the following command + + c:\oracle-dbd\>nmake + + The Visual C++ make executable will then build you DBD-execuable. There should be no errors at this point. + + 19) You can test the compile by either entering + + c:\oracle-dbd\>nmake test + + As long as you have given a valid user name, password and database name in step 15 you will see some results. If it appears to + run but you do not get a connection check the following. + + i. User name password and DB Name + ii. Ensure the a valid TNSNAMES.ORA file is in the Instantclient directory + iii. Attempt to log into the version of SQLPLUS that comes with Instantclient. + If you manage to log on use the username password and TNS name with + the Set ORACLE_USERID = and rerun the tests. + iv If you are compiling against 10XE and have skiped steps 12 to 14 try again bu this time carry out these steps + + 20) You can now install DBD-Oracle into you system by entering the following command from the Visual C++ window dos prompt; + + c:\oracle-dbd\>nmake install + + 21) You should now be able to run DBD-Oracle on you system + + +=head1 09/30 2006 from asu + +DBD::Oracle 1.18a + +Linux, Debian unstable ( +DBI: 1.52 +perl v5.8.8 built for i486-linux-gnu-thread-multi +) + +Oracle Instant client (10.1.0.5) + +The problem is in Makefile.PL. In line 130 the function find_oracle_home +is used to guess a value form $ORACLE_HOME if it is not set explicitely. +This value is used in line 138 to setup the environment (regardless +which client is used). + +in line 1443 (sub get_client_version) sqlplus is used to get the +version string, but for the oracle instant client you must not set +$ORACLE_HOME (it will generate an error "SP2-0642: SQL*Plus internal +error state 2165, context 4294967295:0:0") + +A solution that worked for me was to set +local $ENV{ORACLE_HOME} = ''; +in line 1463 immediately before sqlplus is called (but I cannot tell if +this fails for full client installations) + + +11/30/05 -- John Scoles +I have confirmed that this Makefile.pl will work for both Oracle InstantClient +10.2.0.1 & 10.1.0.4 using same process the Andy Hassall uses. Starting with a clean OD +One needs only to get the latest version of Active Perl 5.8.7 use PPM to get DBI and then +install Microsoft Visual C++ toolkit, Windows SDK, and the Microsoft .net +framework 1.1. and modify the vcvars32.bat in C++ dir as follows + + 1) Add the local path to the windows platform SDK include directory to the + Set INCLUDE Command Line to include the needed files from the Windows SDK. + e.g. "C:\Program Files\Microsoft Platform SDK\Include;" + 2) Add the local path to the .net Vc7 lib directory to the Set LIB + command to include the needed library files from the .Net SKD + e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; + 3) Add the local path to the windows platform SDK Lib directory to the Set Lib + command to include the needed library files from the Windows SDK + e.g. C:\Program Files\Microsoft Platform SDK\Lib; + +If one happens to have visual studio installed you may not have to download additional MS products. + +12/01/05 --- John Scoles +Oracle 10XE +No big problem here as 10XE seems to use the instantclient as well. Just ensure your + NLS_LANG and ORACLE_HOME are set to the same directory that 10XE uses + + +10/07/05 --John Scoles +Andy Hassall kindly added some changes to the Makefile.PL +so it will work for the Instant Client 10g on Windows OSs. Below is how he set +up his environment and the steps he preformed to get it to compile. + + Setting environment for using Microsoft Visual Studio .NET 2003 tools. + (If you have another version of Visual Studio or Visual C++ installed and wish + to use its tools from the command line, run vcvars32.bat for that version.) + + C:\Documents and Settings\andyh>d: + + D:\>cd cygwin\home\andyh\src\pythian + + D:\cygwin\home\andyh\src\pythian>set ORACLE_HOME=d:\lib\instantclient_10_2 + + D:\cygwin\home\andyh\src\pythian>set NLS_LANG=.WE8ISO8859P15 + + D:\cygwin\home\andyh\src\pythian>set PATH=d:\lib\instantclient_10_2;D:\Program F + iles\Microsoft Visual Studio .NET 2003\Common7\IDE;D:\Program Files\Microsoft Vi + sual Studio .NET 2003\VC7\BIN;D:\Program Files\Microsoft Visual Studio .NET 2003 + \Common7\Tools;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ + bin\prerelease;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ + bin;D:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;C:\WINNT\Mic + rosoft.NET\Framework\v1.1.4322;d:\Perl\bin\;C:\WINNT\system32;C:\WINNT;C:\WINNT\ + System32\Wbem;D:\Program Files\Microsoft SDK\Bin;D:\Program Files\Microsoft SDK\ + Bin\WinNT + + D:\cygwin\home\andyh\src\pythian>set ORACLE_USERID=test/test@test102 + + D:\cygwin\home\andyh\src\pythian>perl Makefile.PL + + + +4/27/04 -- Jeff Urlwin + +Do not untar this distribution in a directory with spaces. This will not work. + + i.e. C:\Program Files\ORacle\DBD Oracle Distribution is bad while + c:\dev\dbd-oracle-1.15 is good ;) + +9/14/02 -- Michael Chase + +Makefile.PL uses Win32::TieRegistry or Win32::Registry to find the +current Oracle Home directory if the ORACLE_HOME environment variable +is not set. If neither module is installed, you must set ORACLE_HOME +before running Makefile.PL. Since the registry location of the current +Oracle Home is in different locations in different Oracle versions, +it is usually safer to set ORACLE_HOME before running Makefile.PL. + diff --git a/README.win64.txt b/lib/DBD/Oracle/Troubleshooting/Win64.pod similarity index 97% rename from README.win64.txt rename to lib/DBD/Oracle/Troubleshooting/Win64.pod index 7f423e2b..16d16063 100644 --- a/README.win64.txt +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -1,4 +1,7 @@ -DBD::Oracle and Windows 64bit +#PODNAME: DBD::Oracle::Troubleshooting::Win64 +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Win64 + +=head1 DBD::Oracle and Windows 64bit I have successfully compiled and installed DBD::Oracle on Windows 2008 server 64bit operating system today. @@ -115,6 +118,7 @@ The main thing to remember is you will have to compile using 32 bit Perl and com which sort of defeats the purpose of having a 64bit box. So until 64bit Perl comes out we will be posing in this README any success stories we have come across + -------- Original Message -------- From: Alex Buttery, OCA, MCTS Director, Database Architecture and Operations @@ -161,11 +165,3 @@ else to support this configuration). SET PATH=%ORACLE_HOME%\bin;%PATH% <== Add 32-bit Oracle Home to beginning of default PATH - - -Hopefully, you will be able to include these instructions in the next build of DBD::Oracle to help out other poor souls that are fighting -this same battle. - - - - diff --git a/test.pl b/test.pl deleted file mode 100755 index 94830576..00000000 --- a/test.pl +++ /dev/null @@ -1,319 +0,0 @@ -#!/usr/local/bin/perl -w - -use ExtUtils::testlib; - -die "Use 'perl -Mblib test.pl' or 'make test' to run test.pl\n" - unless "@INC" =~ /\bblib\b/; - -# Copyright (c) 1995-2004, Tim Bunce -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -# XXX -# XXX PLEASE NOTE THAT THIS CODE IS A RANDOM HOTCH-POTCH OF TESTS AND -# XXX TEST FRAMEWORKS AND IS IN *NO WAY* A TO BE USED AS A STYLE GUIDE! -# XXX - -$| = 1; - -use Getopt::Long; -use Config; - -my $os = $Config{osname}; - -GetOptions( - 'm!' => \my $opt_m, # do mem leak test - 'n=i' => \my $opt_n, # num loops for some tests - 'c=i' => \my $opt_c, # RowCacheSize for some tests - 'f=i' => \my $opt_f, # fetch test - 'p!' => \my $opt_p, # perf test -) or die; -$opt_n ||= 10; - -# skip this old set of half-baked oddities if ORACLE_DSN env var is set -exit 0 if $ENV{ORACLE_DSN}; - -$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -use Oraperl; - -exit test_extfetch_perf($opt_f) if $opt_f; - -exit test_leak(10 * $opt_n) if $opt_m; - -&ora_version; - -my @data_sources = DBI->data_sources('Oracle'); -print "Data sources:\n\t", join("\n\t",@data_sources),"\n"; - -print "Connecting\n", - " to '$dbname' (from command line, else uses ORACLE_SID or TWO_TASK - recommended)\n"; -print " as '$dbuser' (via ORACLE_USERID env var or default - recommend name/passwd\@dbname)\n"; -printf("(ORACLE_SID='%s', TWO_TASK='%s')\n", $ENV{ORACLE_SID}||'', $ENV{TWO_TASK}||''); -printf("(LOCAL='%s', REMOTE='%s')\n", $ENV{LOCAL}||'', $ENV{REMOTE}||'') if $os eq 'MSWin32'; - -{ # test connect works first - local($l) = &ora_login($dbname, $dbuser, ''); - unless($l) { - $ora_errno = 0 unless defined $ora_errno; - $ora_errstr = '' unless defined $ora_errstr; - warn "ora_login: $ora_errno: $ora_errstr\n"; - # Try to help dumb users who don't know how to connect to oracle... - warn "\nHave you set the environment variable ORACLE_USERID ?\n" - if ($ora_errno == 1017); # ORA-01017: invalid username/password - warn "\nHave you included your password in ORACLE_USERID ? (e.g., 'user/passwd')\n" - if ($ora_errno == 1017 and $dbuser !~ m:/:); - warn "\nHave you set the environment variable ORACLE_SID or TWO_TASK?\n" - if ($ora_errno == 2700); # error translating ORACLE_SID - warn "\nORACLE_SID or TWO_TASK possibly not right, or server not running.\n" - if ($ora_errno == 1034); # ORA-01034: ORACLE not available - warn "\nTWO_TASK possibly not set correctly right.\n" - if ($ora_errno == 12545); - warn "\n"; - warn "Generally set TWO_TASK or ORACLE_SID but not both at the same time.\n"; - warn "Try to connect to the database using an oracle tool like sqlplus\n"; - warn "only if that works should you suspect problems with DBD::Oracle.\n"; - warn "Try leaving dbname value empty and set dbuser to name/passwd\@dbname.\n"; - warn "\nTest aborted cannot connect.\n"; - exit 0; - } - if ($os ne 'MSWin32' and $os ne 'VMS') { - my $backtick = `sleep 1; echo Backticks OK`; - unless ($backtick) { # $! == Interrupted system call - print "Warning: Oracle's SIGCHLD signal handler breaks perl ", - "`backticks` commands: $!\n(d_sigaction=$Config{d_sigaction})\n"; - } - } - #test_bind_csr($l); - #test_auto_reprepare($l); - &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; - -} - -&test_intfetch_perf() if $opt_p; - -&test1(); - -print "\nRepetitive connect/open/close/disconnect:\n"; -#print "If this test hangs then read the README.help.txt file.\n"; -#print "Expect sequence of digits, no other messages:\n"; -# likely to fail with: ORA-12516: TNS:listener could not find available handler with matching protocol stack (DBD ERROR: OCIServerAttach) -# in default configurations if the number of iterations is high (>~20) -my $connect_loop_start = DBI::dbi_time(); -foreach(1..$opt_n) { print "$_ "; &test2(); } -my $dur = DBI::dbi_time() - $connect_loop_start; -printf "(~%.3f seconds each)\n", $dur / $opt_n; - -print "test.pl complete.\n\n"; - -exit 0; - - -sub test1 { - local($lda) = &ora_login($dbname, $dbuser, '') - || die "ora_login: $ora_errno: $ora_errstr\n"; - - &ora_commit($lda) || warn "ora_commit($lda): $ora_errno: $ora_errstr\n"; - &ora_rollback($lda) || warn "ora_rollback($lda): $ora_errno: $ora_errstr\n"; - &ora_autocommit($lda, 1); - &ora_autocommit($lda, 0); - - # Test ora_do with harmless non-select statement - &ora_do($lda, "set transaction read only ") - || warn "ora_do: $ora_errno: $ora_errstr"; - - # DBI::dump_results($lda->tables()); - - # $lda->debug(2); - - { - #$lda->trace(2); - local($csr) = &ora_open($lda, - "select to_number('7.2', '9D9', - 'NLS_NUMERIC_CHARACTERS =''.,''' - ) num_t, - SYSDATE date_t, - USER char_t, - ROWID rowid_t, - HEXTORAW('7D') raw_t, - NULL null_t - from dual") || die "ora_open: $ora_errno: $ora_errstr\n"; - $csr->{RaiseError} = 1; - - print "Fields: ",scalar(&ora_fetch($csr)),"\n"; - die "ora_fetch in scalar context error" unless &ora_fetch($csr)==6; - print "Names: \t",join("\t", &ora_titles($csr)),"\n"; - print "Lengths: \t",DBI::neat_list([&ora_lengths($csr)],0,"\t"),"\n"; - print "OraTypes: \t",DBI::neat_list([&ora_types($csr)], 0,"\t"),"\n"; - print "SQLTypes: \t",DBI::neat_list($csr->{TYPE}, 0,"\t"),"\n"; - print "Scale: \t",DBI::neat_list($csr->{SCALE}, 0,"\t"),"\n"; - print "Precision: \t",DBI::neat_list($csr->{PRECISION}, 0,"\t"),"\n"; - print "Nullable: \t",DBI::neat_list($csr->{NULLABLE}, 0,"\t"),"\n"; - print "Est row width:\t$csr->{ora_est_row_width}\n"; - print "Prefetch cache: $csr->{RowsInCache}\n" if $csr->{RowsInCache}; - - print "Data rows:\n"; - #$csr->debug(2); - while(@fields = $csr->fetchrow_array) { - die "ora_fetch returned ".@fields." fields instead of 6!" - if @fields != 6; - die "Perl list/scalar context error" if @fields==1; - print " fetch: ", DBI::neat_list(\@fields),"\n"; - } - &ora_close($csr) || warn "ora_close($csr): $ora_errno: $ora_errstr\n"; - } - &ora_logoff($lda) || warn "ora_logoff($lda): $ora_errno: $ora_errstr\n"; -} - - -sub test2 { # also used by test_leak() - my $execute_sth = shift; - my $dbh = DBI->connect("dbi:Oracle:$dbname", $dbuser, '', { RaiseError=>1 }); - if ($execute_sth) { - my $sth = $dbh->prepare("select 42,'foo',sysdate from dual where ? >= 1"); - while ($execute_sth-- > 0) { - $sth->execute(1); - my @row = $sth->fetchrow_array; - $sth->finish; - } - } - $dbh->disconnect; -} - - -sub test_leak { - local($count) = @_; - local($ps) = (-d '/proc') ? "ps -lp " : "ps -l"; - local($i) = 0; - my $execute_sth = 100; - print "\nMemory leak test: (execute $execute_sth):\n"; - while(++$i <= $count) { - &test2($execute_sth); - system("echo $i; $ps$$") if (($i % 10) == 1); - } - system("echo $i; $ps$$"); - print "Done.\n\n"; -} - - -sub count_fetch { - local($csr) = @_; - local($rows) = 0; - # while((@row) = &ora_fetch($csr)) { - while((@row) = $csr->fetchrow_array) { - ++$rows; - } - die "count_fetch $ora_errstr" if $ora_errno; - return $rows; -} - - -sub test_intfetch_perf { - print "\nTesting internal row fetch overhead.\n"; - local($lda) = &ora_login($dbname, $dbuser, '') - || die "ora_login: $ora_errno: $ora_errstr\n"; - DBI->trace(0); - $lda->trace(0); - local($csr) = &ora_open($lda,"select 0,1,2,3,4,5,6,7,8,9 from dual"); - local($max) = 50000; - $csr->{ora_fetchtest} = $max; - require Benchmark; - $t0 = new Benchmark; - 1 while $csr->fetchrow_arrayref; - $td = Benchmark::timediff((new Benchmark), $t0); - $csr->{ora_fetchtest} = 0; - printf("$max fetches: ".Benchmark::timestr($td)."\n"); - printf("%d per clock second, %d per cpu second\n\n", - $max/($td->real ? $td->real : 1), - $max/($td->cpu_a ? $td->cpu_a : 1)); -} - -sub test_extfetch_perf { - my $max = shift; - print "\nTesting external row fetch overhead.\n"; - my $rows = 0; - my $dbh = DBI->connect("dbi:Oracle:$dbname", $dbuser, '', { RaiseError => 1 }); - #$dbh->trace(2); - $dbh->{RowCacheSize} = $::opt_c if defined $::opt_c; - my $fields = (0) ? "*" : "object_name, status, object_type"; - my $sth = $dbh->prepare(q{ - select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - --, all_objects o2 - --where o1.object_id <= 400 and o2.object_id <= 400 - }, { ora_check_sql => 1 }); - - require Benchmark; - $t0 = new Benchmark; - $sth->execute; - $sth->trace(0); - $sth->fetchrow_arrayref; # fetch one before starting timer - $td = Benchmark::timediff((new Benchmark), $t0); - printf("Execute: ".Benchmark::timestr($td)."\n"); - - print "Fetching data with RowCacheSize $dbh->{RowCacheSize}...\n"; - $t1 = new Benchmark; - 1 while $sth->fetchrow_arrayref && ++$rows < $max; - $td = Benchmark::timediff((new Benchmark), $t1); - printf("$rows fetches: ".Benchmark::timestr($td)."\n"); - printf("%d per clock second, %d per cpu second\n", - $rows/($td->real ? $td->real : 1), - $rows/($td->cpu_a ? $td->cpu_a : 1)); - my $ps = (-d '/proc') ? "ps -lp " : "ps -l"; - system("echo Process memory size; $ps$$"); - print "\n"; - $sth->finish; - $dbh->disconnect; - exit 1; -} - - -sub test_bind_csr { - local($lda) = @_; -$lda->{RaiseError} =1; -$lda->trace(2); -my $out_csr = $lda->prepare(q{select 42 from dual}); # sacrificial csr XXX -$csr = $lda->prepare(q{ - begin - OPEN :csr_var FOR select * from all_tables; - end; -}); -$csr->bind_param_inout(':csr_var', \$out_csr, 100, { ora_type => 102 }); -$csr->execute(); -# at this point $out_csr should be a handle on a new oracle cursor -@row = $out_csr->fetchrow_array; - - exit 1; -} - -sub test_auto_reprepare { - local($dbh) = @_; - $dbh->do(q{drop table timbo}); - $dbh->{RaiseError} =1; - #$dbh->trace(2); - $dbh->do(q{create table timbo ( foo integer)}); - $dbh->do(q{insert into timbo values (91)}); - $dbh->do(q{insert into timbo values (92)}); - $dbh->do(q{insert into timbo values (93)}); - $dbh->commit; - $Oraperl::ora_cache = $Oraperl::ora_cache = 1; - my $sth = $dbh->prepare(q{select * from timbo for update}); - $sth->execute; $sth->dump_results; - $sth->execute; - print $sth->fetchrow_array,"\n"; - $dbh->commit; - print $sth->fetchrow_array,"\n"; - $dbh->do(q{drop table timbo}); - exit 1; -} - -# end. From c78792448f63966fcd5559dbff115fb9c47f699b Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 11 Jul 2012 15:18:28 -0400 Subject: [PATCH 262/637] preps for v1.47 --- Changes | 4 +++- dist.ini | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index b851ba02..2d854c71 100644 --- a/Changes +++ b/Changes @@ -13,7 +13,9 @@ Revision history for DBD::Oracle does not seem to have it in 10.2 leading to undefined symbol - Martin J. Evans - [MISCELLANEOUS] + [DOCUMENTATION] + - Promoted the troubleshooting for the different architectures to + POD documents, for easier/prettier access. - Added a troubleshooting entry for RT71819 - bound output parameters may be returned in the wrong order (Martin J. Evans) diff --git a/dist.ini b/dist.ini index 28f4edee..e3830372 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.46 +version = 1.47_00 [Authority] authority=cpan:PYTHIAN From 8fd4b7b35bef04fcca1361dd950cc6027e677f61 Mon Sep 17 00:00:00 2001 From: yanick Date: Wed, 11 Jul 2012 19:25:29 +0000 Subject: [PATCH 263/637] POD all the READMEs git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15347 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 +- MANIFEST | 22 +- META.json | 20 +- META.yml | 17 +- README | 2 +- README-files/hpux/Makefile-Lincoln | 223 ---------- README.64bit.txt | 272 ------------ README.aix.txt | 255 ----------- README.clients.txt | 279 ------------ README.help.txt | 133 ------ README.java.txt | 322 -------------- README.mkdn | 2 +- README.sec.txt | 142 ------ README.win32.txt | 236 ---------- lib/DBD/Oracle.pm | 10 +- lib/DBD/Oracle/GetInfo.pm | 4 +- lib/DBD/Oracle/Object.pm | 4 +- lib/DBD/Oracle/Troubleshooting.pm | 419 ------------------ lib/DBD/Oracle/Troubleshooting.pod | 167 +++++++ lib/DBD/Oracle/Troubleshooting/Aix.pod | 290 ++++++++++++ lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 111 +++++ .../DBD/Oracle/Troubleshooting/Hpux.pm | 60 ++- lib/DBD/Oracle/Troubleshooting/Linux.pod | 149 +++++++ .../DBD/Oracle/Troubleshooting/Macos.pod | 326 ++++++++------ lib/DBD/Oracle/Troubleshooting/Sun.pod | 59 +++ lib/DBD/Oracle/Troubleshooting/Vms.pod | 129 ++++++ lib/DBD/Oracle/Troubleshooting/Win32.pod | 279 ++++++++++++ .../DBD/Oracle/Troubleshooting/Win64.pod | 64 ++- test.pl | 319 ------------- 29 files changed, 1501 insertions(+), 2818 deletions(-) delete mode 100644 README-files/hpux/Makefile-Lincoln delete mode 100644 README.64bit.txt delete mode 100644 README.aix.txt delete mode 100644 README.clients.txt delete mode 100644 README.java.txt delete mode 100644 README.sec.txt delete mode 100644 README.win32.txt delete mode 100644 lib/DBD/Oracle/Troubleshooting.pm create mode 100644 lib/DBD/Oracle/Troubleshooting.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Aix.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Cygwin.pod rename README.hpux.txt => lib/DBD/Oracle/Troubleshooting/Hpux.pm (97%) create mode 100644 lib/DBD/Oracle/Troubleshooting/Linux.pod rename README.macosx.txt => lib/DBD/Oracle/Troubleshooting/Macos.pod (76%) create mode 100644 lib/DBD/Oracle/Troubleshooting/Sun.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Vms.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Win32.pod rename README.win64.txt => lib/DBD/Oracle/Troubleshooting/Win64.pod (91%) delete mode 100755 test.pl diff --git a/Changes b/Changes index b851ba02..2d854c71 100644 --- a/Changes +++ b/Changes @@ -13,7 +13,9 @@ Revision history for DBD::Oracle does not seem to have it in 10.2 leading to undefined symbol - Martin J. Evans - [MISCELLANEOUS] + [DOCUMENTATION] + - Promoted the troubleshooting for the different architectures to + POD documents, for easier/prettier access. - Added a troubleshooting entry for RT71819 - bound output parameters may be returned in the wrong order (Martin J. Evans) diff --git a/MANIFEST b/MANIFEST index 34c7a9d4..bd226508 100644 --- a/MANIFEST +++ b/MANIFEST @@ -9,18 +9,8 @@ Oracle.h Oracle.xs Oraperl.pm README -README-files/hpux/Makefile-Lincoln -README.64bit.txt -README.aix.txt -README.clients.txt README.help.txt -README.hpux.txt -README.java.txt -README.macosx.txt README.mkdn -README.sec.txt -README.win32.txt -README.win64.txt Todo dbdimp.c dbdimp.h @@ -47,7 +37,16 @@ hints/svr4.pl lib/DBD/Oracle.pm lib/DBD/Oracle/GetInfo.pm lib/DBD/Oracle/Object.pm -lib/DBD/Oracle/Troubleshooting.pm +lib/DBD/Oracle/Troubleshooting.pod +lib/DBD/Oracle/Troubleshooting/Aix.pod +lib/DBD/Oracle/Troubleshooting/Cygwin.pod +lib/DBD/Oracle/Troubleshooting/Hpux.pm +lib/DBD/Oracle/Troubleshooting/Linux.pod +lib/DBD/Oracle/Troubleshooting/Macos.pod +lib/DBD/Oracle/Troubleshooting/Sun.pod +lib/DBD/Oracle/Troubleshooting/Vms.pod +lib/DBD/Oracle/Troubleshooting/Win32.pod +lib/DBD/Oracle/Troubleshooting/Win64.pod mkta.pl oci.def oci8.c @@ -90,5 +89,4 @@ t/80ora_charset.t t/nchar_test_lib.pl t/rt13865.t t/rt74753-utf8-encoded.t -test.pl typemap diff --git a/META.json b/META.json index b64f752c..5f4887ca 100644 --- a/META.json +++ b/META.json @@ -52,34 +52,30 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.46" + "version" : "1.47_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.46" + "version" : "1.47_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.46" - }, - "DBD::Oracle::Troubleshooting" : { - "file" : "lib/DBD/Oracle/Troubleshooting.pm", - "version" : "1.46" + "version" : "1.47_00" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.46" + "version" : "1.47_00" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.46" + "version" : "1.47_00" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.46" + "version" : "1.47_00" } }, - "release_status" : "stable", + "release_status" : "testing", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -92,7 +88,7 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, - "version" : "1.46", + "version" : "1.47_00", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index 379da346..de8b99e6 100644 --- a/META.yml +++ b/META.yml @@ -30,25 +30,22 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.46 + version: 1.47_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.46 + version: 1.47_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.46 - DBD::Oracle::Troubleshooting: - file: lib/DBD/Oracle/Troubleshooting.pm - version: 1.46 + version: 1.47_00 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.46 + version: 1.47_00 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.46 + version: 1.47_00 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.46 + version: 1.47_00 requires: DBI: 0 DynaLoader: 0 @@ -60,7 +57,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.46 +version: 1.47_00 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 1cf1a61f..0697b8dd 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.46 + version 1.47_00 SYNOPSIS use DBI; diff --git a/README-files/hpux/Makefile-Lincoln b/README-files/hpux/Makefile-Lincoln deleted file mode 100644 index 0565def4..00000000 --- a/README-files/hpux/Makefile-Lincoln +++ /dev/null @@ -1,223 +0,0 @@ -# makefile for rebuilding perl and all the modules we have built -# or for rebuilding individual modules -SHELL = /usr/bin/ksh -CPAN_VERSION = 5.6.1 -FCCS_VERSION = fccs-03 -#needed for compatibility with ../build.mk: -TOOL = perl -PERL_VERSION = $(TOOL)-$(CPAN_VERSION) -TOP = /opt/oss -PERLDIR = $(PERL_VERSION)-$(FCCS_VERSION) -PERL_ROOT = $(TOP)/pkg -PREFIX = $(PERL_ROOT)/$(PERLDIR) -#needed for compatibility with ../biuld.mk: -VERSION = $(CPAN_VERSION)-$(FCCS_VERSION) - -MQS = MQSeries-1.14 -DBDORA = DBD-Oracle-1.12 -DBI = DBI-1.20 -EXPAT_VER = -1.95.2 -MQSERVER = 'PERL_CHANNEL/TCP/dsas105(1414)' - -MODULES = \ - libnet-1.0703 \ - Storable-0.7.2 \ - Time-HiRes-01.20 \ - Net-Daemon-0.35 \ - Digest-MD5-2.16 \ - Digest-SHA1-2.01 \ - Digest-HMAC-1.01 \ - MIME-Base64-2.12 \ - Net-DNS-0.19 \ - Mail-CheckUser-1.13 \ - Proc-Daemon-0.02 \ - Proc-Simple-1.14 \ - Openview-Message-0.01 \ - Business-CreditCard-0.26 \ - Data-UUID-0.06 - -XML_PARSER = XML-Parser-2.31 -XML_MODULES = \ - XML-Simple-1.05 \ - XML-Generator-0.8 -#this does not behave same as 0.8 -#XML-Generator-0.91 - -all: testOracleVar - @banner ALL_PERL - @echo "using perl PATH=$(PREFIX)/bin" - ( export PATH=$(PREFIX)/bin:$$PATH && make perl ) - ( export PATH=$(PREFIX)/bin:$$PATH && make all_modules ) - -print_macros: - @echo TOOL=$(TOOL) - @echo CPAN_VERSION=$(CPAN_VERSION) - @echo PERL_VERSION=$(PERL_VERSION) - @echo FCCS_VERSION=$(FCCS_VERSION) - @echo PREFIX=$(PREFIX) - @echo VERSION=$(VERSION) - @echo PERLDIR=$(PERLDIR) - @echo PERL_ROOT=$(PERL_ROOT) - -all_modules: modules xmlparser xml_modules dbi dbd mqs - -modules: testPath - rm -rf $(MODULES) - for m in $(MODULES); do \ - make module MODULE=$$m PREFIX=$(PREFIX) ; \ - done - -xml_modules: testPath - rm -rf $(XML_MODULES) - for m in $(XML_MODULES); do \ - make module MODULE=$$m PREFIX=$(PREFIX) ; \ - done - -dbi: testPath - make module MODULE=DBI-1.20 PREFIX=$(PREFIX) - -dbd: testPath testOracleVar dbi touch.d/$(DBDORA).tch - -touch.d: - mkdir touch.d - -xmlparser: touch.d/$(XML_PARSER).tch -touch.d/$(XML_PARSER).tch: $(XML_PARSER).tar.gz - tar -zxvf $(XML_PARSER).tar.gz - ( cd $(XML_PARSER) && \ - perl Makefile.PL EXPATLIBPATH=$(TOP)/lib \ - EXPATINCPATH=$(TOP)/include && \ - make && \ - make test && \ - make install ) - rm -rf $(XML_PARSER) - touch $@ - -#chmod +w CONFIG; -mqs_config: - ( cd $(MQS); \ - mv CONFIG CONFIG.orig; \ - cp ../$$(uname).MQS.CONFIG CONFIG \ - ) - -mqs_target: - ( export MQSERVER=$(MQSERVER); \ - cd $(MQS) ;\ - make $(MQS_TARGET) \ - ) - -mqs_build: - ( export MQSERVER=$(MQSERVER); \ - cd $(MQS) ;\ - cp ../$$(uname).MQS.CONFIG ./CONFIG; \ - perl Makefile.PL; \ - make ; \ - ) - -mqs: testPath /opt/mqm touch.d/$(MQS).tch -touch.d/$(MQS).tch: - @banner $(MQS) - rm -rf $(MQS) - gunzip -c $(MQS).tar.gz | tar -xvf - - touch $(MQS)/.LICENSE.ACCEPTED - make -s mqs_config - make -s mqs_build - make -s mqs_target MQS_TARGET=test - make -s mqs_target MQS_TARGET=install - touch $@ - - -touch.d/$(DBDORA).tch: testOracleVar - @banner $(DBDORA) - test ! -z "$(ORACLE_HOME)" - -rm -rf $(DBDORA) - gunzip -c $(DBDORA).tar.gz | tar -xf - - cd $(DBDORA) ;\ - perl Makefile.PL; \ - make ; \ - make test ; \ - make install - touch touch.d/$(DBDORA).tch - - -perl: testVar $(PERL_VERSION) touch.d/$(PERL_VERSION).tch - -touch.d/$(PERL_VERSION).tch: - @banner perl - @if ls $(PREFIX) >/dev/null 2>&1 ; \ - then \ - echo "Error: Cannot install to an existing directory" ;\ - echo "Error: Please delete or move $(PREFIX)" ;\ - exit 1;\ - fi - - cd $(PERL_VERSION); make distclean; - cd $(PERL_VERSION); \ - ./Configure -Dprefix=$(PREFIX) -Ubincompat5005 -Uuselargefiles \ - -A eval:libswanted='\"cl pthread $$libswanted\" ' -des; \ - make ; \ - make test; \ - make install - touch touch.d/$(PERL_VERSION).tch - -realclean distclean: clean_tch - -rm -rf $(PERL_VERSION) - -clean: clean_tch -clean_tch : - -rm -f touch.d/*.tch - -module: touch.d/$(MODULE).tch - -touch.d/$(MODULE).tch : - @banner $(MODULE) - -rm -rf $(MODULE) - gunzip -c $(MODULE).tar.gz | tar -xf - - cd $(MODULE); \ - perl Makefile.PL /dev/null 2>&1 ; \ - then \ - echo "Error: Cannot install to an existing directory" ;\ - echo "Error: Please delete or move $(PREFIX)" ;\ - exit 1;\ - fi - gunzip -c $(PERL_VERSION).tar.gz |tar xf - - @echo "untar of perl is done" - -testVars: testVar testPath testOracleVar - -testVar: touch.d - @echo "******** Building to: $(PREFIX) *********" - -testOracleVar: - @if test -z "$$ORACLE_HOME" ; \ - then \ - echo " Please set \"export ORACLE_HOME=\"" ;\ - exit 1; \ - else \ - echo ORACLE_HOME=$(ORACLE_HOME); \ - fi - @if test -z "$$ORACLE_USERID" ; \ - then \ - echo " Please set \"export ORACLE_USERID=\"" ;\ - exit 1; \ - else \ - echo ORACLE_USERID=$(ORACLE_USERID); \ - fi - -testPath: - @if echo $$PATH | egrep -q '^$(PREFIX)/bin:'; then \ - echo PATH is OK; \ - else \ - echo "ERROR: You must have $(PREFIX)/bin first in your path as follows:" ;\ - echo " export PATH=$(PREFIX)/bin:\$$PATH" ;\ - exit 1; \ - fi diff --git a/README.64bit.txt b/README.64bit.txt deleted file mode 100644 index 9d3ebe0f..00000000 --- a/README.64bit.txt +++ /dev/null @@ -1,272 +0,0 @@ -In general compiling DBD:Oracle for 64 bit machines has been a hit or miss operation. -The main thing to remember is you will have to compile using 32 bit Perl and compile DBD::Oracle against a 32bit client -which sort of defeats the purpose of having a 64bit box. -So until 64bit Perl comes out we will be posing in this README any success stories we have come across - --------- Original Message -------- - -Subject: Building 32bit DBD::Oracle against 64bit Oracle -From: Dennis Reso -Date: 7/9/2008 5:44 PM -Priority: Normal - -Building DBD::Oracle v1.21 against Perl 5.8.5 Oracle 9.2.0.4 Solaris 8 - -Got the dreaded "wrong ELF class" when the Oracle.so ends up built -against the 64bit library instead of the one in $ORACLE_HOME/lib32. -Use 'dump -vL Oracle.so' to see the internalized RPATH definition. - -Tried the following solution, widely posted, without success: - - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - -What worked for me (pass the LIBDIR to the Oracle make process): - - export ORACLE_HOME=/apps/Oracle9.2.0.4 - export LD_LIBRARY_PATH=$ORACLE_HOME/lib32 - perl -pi -e 's/CC=true/CC=true LIBDIR=lib32/' Makefile.PL - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - make - -The LIBDIR= is defined in $ORACLE_HOME/rdbms/lib/env_rdbms.mk which -also includes a REDEFINES32= that overrides it, but is only used by -the $ORACLE_HOME/rdbms/lib/ins_rdbms.mk. Oracle bug? - -Also repeated the same failure and success with - Oracle 9.2.0.8 Solaris 10 - Oracle 10.2.0.3 Solaris 10 - -Seems fixed in demo_rdbms32.mk (no Makefile.PL edit needed ) as of - Oracle 10.2.0.4 Solaris 10 - -Probably also fixed in some patchset newer than 9.2.0.4. - --- -Dennis Reso - --------- Original Message -------- - -Subject: DBD::Oracle 64-bit success story -From: H.Merijn Brand -Date: On Mon, 14 Apr 2008 09:48:41 -Priority: Normal - -I finally got round trying Oracle Instant Client on Linux with no -Oracle installed, connecting to a 64bit Oracle 9.2.0.8 on HP-UX -11.11/64. I had to do some fiddling with Makefile.PL (see bottom). -Sorry for this being long. Feel free to mold it into anything useful. - -1. Before you start on DBD::Oracle, make sure DBD::ODBC works. That will - assure your DSN works. Install unixODBC before anything else. - -2. Assuming you've got OIC from the rpm's, you will have it here: - - /usr/include/oracle/11.1.0.1/client - /usr/lib/oracle/11.1.0.1/client - /usr/share/oracle/11.1.0.1/client - - -3. for the 64 bit clienat we have these rpm - oracle-instantclient-basic-11.1.0.1-1.x86_64.rpm - oracle-instantclient-devel-11.1.0.1-1.x86_64.rpm - oracle-instantclient-jdbc-11.1.0.1-1.x86_64.rpm - oracle-instantclient-odbc-11.1.0.1-1.x86_64.rpm - oracle-instantclient-sqlplus-11.1.0.1-1.x86_64.rpm - - and to add to the confusement, they install to - - /usr/include/oracle/11.1.0.1/client64 - /usr/lib/oracle/11.1.0.1/client64 - /usr/share/oracle/11.1.0.1/client64 - -4. To make DBD::ODBC work, I had to create a tnsnames.ora, and I chose - - /usr/lib/oracle/11.1.0.1/admin/tnsnames.ora - - /usr/lib/oracle/11.1.0.1/admin > cat sqlnet.ora - NAMES.DIRECTORY_PATH = (TNSNAMES, ONAMES, HOSTNAME) - /usr/lib/oracle/11.1.0.1/admin > cat tnsnames.ora - ODBCO = ( - DESCRIPTION = - ( ADDRESS_LIST = - ( ADDRESS = - ( PROTOCOL = TCP ) - ( PORT = 1521 ) - ( HOST = rhost ) - ) - ) - ( CONNECT_DATA = - ( SERVICE_NAME = odbctest ) - ) - ) - /usr/lib/oracle/11.1.0.1/admin > - - Real world example changed to hide the obvious. Important bits are - "ODBCO", which is the ODBC name, and it can be anything, as long as - you use this in ORACLE_DSN too (please don't use whitespace, colons, - semicolons and/or slashes. "rhost" is the hostname of where the DB - is running, and "odbctest" is available on "rhost". To check that, - run "lsnrctl services" on "rhost". - Set the environment (TWO_TASK is not needed) - - > setenv LD_LIBRARY_PATH /usr/lib/oracle/11.1.0.1/client/lib - > setenv TNS_ADMIN /usr/lib/oracle/11.1.0.1/admin - > setenv ORACLE_HOME /usr/lib/oracle/11.1.0.1/client - > setenv ORACLE_DSN dbi:Oracle:ODBCO - > setenv ORACLE_USERID ORAUSER/ORAPASS - - Check if the connection works: - > isql -v ODBCO - - And for Oracle: - > sqlplus ORAUSER/ORAPASS@ODBCO - and - > sqlplus ORAUSER/ORAPASS@rhost/odbctest - - should both work - - -Note by JPS: - -Merijn patched the trunk version of Makeifle.PL to account for the above it will be in release 1.22 - --------- Original Message -------- - -Subject: DBD::Oracle 64-bit success story -From: "QiangLi" -Date: Thu, March 6, 2008 5:25 pm -To: pause@pythian.com -Priority: Normal - -hi, - -thanks for maintaining DBD::Oracle. I have installed DBD::Oracle against - 64-bit oracle 10g on a 64-bit solaris machine. maybe worth another -entry for the README.64bit.txt file. - -i am using gcc from sun freesoftware and also SUNWbinutils which -contains the gas (gnu assembler) - -here is the steps with comment: - -# set install target -% /usr/perl5/5.8.4/bin/perlgcc Makefile.PL PREFIX=/var/tmp/lib - -# since our perl is 32-bit, we can't build it against a 64bit oracle -install. -# edit Makefile and change reference to oracle's "lib/" to "lib32/" -% perl -pi -e 's/oracle_home\/lib/oracle_home\/lib32/g' Makefile -% perl -pi -e 's/oracle_home\/rdbms\/lib/oracle_home\/rdbms\/lib32/g' -Makefile - -% make - -# ignore error like ORA-12162: TNS:net service name is incorrectly -specified... -% make test - -% make install - -# does it work. -% perl -I'/var/tmp/lib/lib/site_perl/5.8.4/sun4-solaris-64int/' --MDBD::Oracle -e1 - -cheers, - -Qiang - - - - --------- Original Message -------- -Subject: Tip: Compiling 32bit modules against 64bit Oracle 10g on solaris -Date: Thu, 1 Nov 2007 16:41:28 -0400 -From: Edgecombe, Jason -To: -CC: - - - -Hi There, - -I just wanted to thank both of you. - -The tip from cartmanltd@hotmail.com was the trick for getting -DBD::Oracle compiled in 32bit format against the Oracle 10g client on -solaris. - -Here was the command that worked: - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - -Even though the tip was for aix, it fixed my build issue on solaris 9 -(sparc) - -I've been banging my head on this problem for a few days. - -Thanks, -Jason - -Jason Edgecombe -Solaris & Linux Administrator -Mosaic Computing Group, College of Engineering -UNC-Charlotte -Phone: (704) 687-3514 - - - -Source:Tom Reinertson -Platform:Amd64 -OS:Gentoo-amd64 - -The following instructions work for dbd::oracle 1.19 on a gentoo-amd64 installation. - -1) install the oracle libraries - - Strictly speaking you only need dev-db/oracle-instantclient-basic - for dbd::oracle, but i always like to have sql*plus lying around, - which requires the basic package, so i just install sql*plus. - - emerge dev-db/oracle-instantclient-sqlplus which also pulls in - dev-db/oracle-instantclient-basic. these packages are fetch - restricted so you will be required to follow the download instructions. - following these instructions, you should have retrieved these packages: - - instantclient-basic-linux-x86-64-10.2.0.3-20070103.zip - instantclient-sdk-linux-x86-64-10.2.0.3-20070103.zip - instantclient-sqlplus-linux-x86-64-10.2.0.3-20070103.zip - - now move them into the /usr/portage/distfiles directory. - - you should now be able to emerge dev-db/oracle-instantclient-sqlplus. - -2) install DBD::Oracle - - issue the command: - - perl -MCPAN -e'install DBD::Oracle' - - this fails with the following error: - - x86_64-pc-linux-gnu-gcc: unrecognized option '-wchar-stdc++' - x86_64-pc-linux-gnu-gcc: unrecognized option '-cxxlib-gcc' - cc1: error: /ee/dev/bastring.h: No such file or directory - - find the offending files in your cpan directory: - {~/.cpan/build/DBD-Oracle-1.19} grep -lr cxxlib * - Makefile - blib/arch/auto/DBD/Oracle/mk.pm - mk.pm - - edit these files and remove the two invalid options and the include of bastring.h. - - now build the module: - - perl Makefile.PL -l - make - # make test generates lots of errors - make test - make install - - you should now be ready to run. - - diff --git a/README.aix.txt b/README.aix.txt deleted file mode 100644 index a83bf144..00000000 --- a/README.aix.txt +++ /dev/null @@ -1,255 +0,0 @@ - -DBD::Oracle AIX-specific README - - -Using Visual Age 7 C Compiler -====================================================================================== - -- Oracle 9i is only certified as a 64-bit application on AIX 5L (5.1,5.2,5.3) with 32-bit support; - in other words, there is no 9i "32-bit" Oracle client -- Oracle 10g is certified as both a 64-bit application and a 32-bit Oracle client - -- This information only pertains to deploying - the DBI (version 1.48) - and DBD-Oracle (version 1.16): - on AIX 5.3 - using Oracle 9i (9.2.0.1/9.2.0.5) - using the existing Perl 5.8.2 (no custom-built Perl) which is 32-bit - using Visual Age 7.0 C/C++ compiler - -Install the DBI (required for the DBD-Oracle install - no issues here) -Untar the DBD-Oracle bundle -Run Makefile.PL -$ perl Makefile.PL -Edit Makefile with following commands: -1,$s?/lib/ ?/lib32/ ?g -1,$s?-q64??g -1,$s?/lib/sysliblist?/lib32/sysliblist?g -Now perform normal commands to perform the testing/making: -$ make -$ make test -$ make install - -I've tested the basics of the DBD-Oracle and it seems fully functional. - -Stephen de Vries -paulhill20@copper.net - - - -Using gcc C Compiler -====================================================================================== - - - -DBD::Oracle with gcc and Oracle Instant Client on AIX --------------------------------------------------------------------------------------- -Nathan Vonnahme Dec 15 2005, 4:28 pm Newsgroups: perl.dbi.users -See: http://groups.google.com/group/perl.dbi.users/msg/0bd9097f80f2c8a9 -[ with updates 1/31/2006 - DBD::Oracle 1.17 doesn't need makefile hacking -to work with instantclient on AIX ] - - -Yes! It eluded me last year but I finally got DBD::Oracle working on an -AIX machine using gcc. Here's the short version: - -First I had to recompile perl with gcc, using - sh Configure -de -Dcc=gcc -This apparently built a 32 bit perl, someday I will try getting it to go -64 bit. - -I was then able to install and build DBI 1.50 with the CPAN shell. - -I downloaded the base and sdk packages of the Oracle Instant Client for -AIX -- first I tried the 64 bit but that didn't work with my 32 bit perl --- the 32 bit version (still at 10.1.0.3) did the trick. I unzipped -them and moved the dir to /usr/local/oracle/instantclient10_1 and made a -symlink without the version at /usr/local/oracle/instantclient , then -set: - -export ORACLE_HOME=/usr/local/oracle/instantclient -export LIBPATH=$ORACLE_HOME - - - -Oracle wasn't providing the sqlplus package for 32 bit AIX so I -explicitly told Makefile.PL the version: - -perl Makefile.PL -V 10.1 - -make - -My test databases were on other machines so I set these environment variables -to get the tests to run: - -export ORACLE_DSN=DBI:Oracle://host/dbinstance -export ORACLE_USERID="user/password" - -make test -make install - - -NOTE: I have an older full version of Oracle on this machine, and the -ORACLE_HOME environment variable is normally set to point to that, so -my perl scripts that use DBD::Oracle have to make sure to first set - $ENV{ORACLE_HOME}='/usr/local/oracle/instantclient'; - - - - - --------------------------------------------------------------------------------------- -The following setup worked to build on AIX 5.2: -gcc-3.3.2 (32-bit) (configure opts [ --with-ld=/usr/ccs/bin/ld --with-as=/usr/ccs/bin/as]) -Oracle-9.2.0 ( full install w/32bit support) -perl-5.8.3 (built with above gcc/latest stable as of March 2004) -Followed the directions from Rafael's email below, only set ORACLE_HOME, (and -the appropriate test environmentals). -1) build perl-5.8.3 with gcc -2) install DBI -3) ORACLE_HOME="your oracle home" - ORACLE_USERID.. - ORACLE_SID .. - (I ignored ORACCENV, didn't use it.) -4) install DBD::Oracle, after perl Makefile.PL, edit the created Makefile, -changing references to Oracle's ../lib to ../lib32. and change crt0_64.o to -crt0_r.o. Remove the -q32 and/or -q64 options from the list of libraries to -link with. -5) make should be clean, make test should pass. -This setup worked with 8.1.7 w/32 bit support, and with 9.2.0 w/ 32-bit support. ---Adrian Terranova -peril99@yahoo.com - - - - -Using xlc_r C Compiler -====================================================================================== --------------------------------------------------------------------------------------- -From: Rafael Caceres -Date: 22 Jul 2003 10:05:20 -0500 -Message-Id: <1058886321.1066.13.camel@rcaceres.aasa.com.pe> - -The following sequence worked for me on AIX 5.1: - --use Perl 5.8.0 (the latest stable from CPAN) - --use the xlc_r version of IBM's compiler and build a 32 bit Perl - (which xlc_r will do by default). All tests should be successful. - --get and install DBI - --get DBD::Oracle. Edit the Makefile.PL or Makefile for DBD::Oracle, -changing references to Oracle's ../lib to ../lib32. and change crt0_64.o -to crt0_r.o. Remove the -q32 and/or -q64 options from the list of -libraries to link with. Do the make and make test. - --Set up the environment for making DBD::Oracle: - ORACLE_HOME="your oracle home" - ORACCENV = "xlc_r" - ORACLE_USERID.. - ORACLE_SID .. - --Run make, all tests should be successfull -against Oracle 9.x at least. - -You should have no problems with Oracle 8.1.7, but accessing Oracle 7.x -or previous is not possible (you'll core dump, or simply hang). The same -goes for a Linux build or a Digital build, regarding access of different -Oracle versions. - -Rafael Caceres - -On Tue, 2003-07-22 at 08:12, mpaladino@invacare.com wrote: -> -> I dont believe I compiled Oracle. During the installation it was linked -> but I am not sure it was compiled -> -> I used a xlc compiler to compile PERL. -> Got this message in the Perl Makefile.PL output -> -> Warning: You will may need to rebuild perl using the xlc_r compiler. -> You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV -> Also see the README about the -p option -> -> this probobly means I need to rebuild PERL with xlc_r?? -> -> thanx -> -> Mike Paladino -> Database Administrator - - -From: Rafael Caceres -> -> Make sure you use the same compiler to build Oracle and Perl. We have -> used xlc_r on Aix 5.1 with no problems. Your Perl build is 32 bit, so -> when building DBD::Oracle, you should use the 32bit libraries (change -> references to .../oracle/lib to .../oracle/lib32 in your Makefile). -> Remove the references to the -q64 or -q32 parameters for ld in Makefile, -> as they shouldn't be there. -> -> Rafael Caceres - - -From: "cartman ltd" -Subject: Tip for DBI and DBD::Oracle on AIX 5.1 and Oracle 9.2 -Date: Mon, 11 Aug 2003 18:15:38 +0000 -Message-ID: - -Here is a tip for compiling DBD::Oracle as a 32 bit application on AIX 5.1 -64 bit and Oracle 9.2 64 bit without editting any makefiles. I hope people -find this useful: - -First, the versions of products I used: - DBI version 1.32 - DBD::Oracle version 1.14 - Oracle 9.2.0.2 - default 64 bit application with 32 bit libraries - AIX 5.1 ML03 - 64 bit kernel - ships with Perl as a 32 bit application. - VisualAge C/C++ 5.0.2 - -Basically DBD must be compiled as 32 bit to link with Perl's 32 bit -libraries. - gunzip -c DBD-Oracle-1.14.tar.gz | tar xvf  - cd DBD-Oracle-1.14 - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - make - -NB: I think there is a bug in the Oracle 9.2.0.3 file -$ORACLE_HOME/rdbms/lib/env_rdbms.mk -I corrected this (before running the above commands) by replacing the -invalid linker option - LDFLAGS32=-q32 -with - LDFLAGS32=-b32 - -Have fun: KC. --------------------------------------------------------------------------------------- - -Date: Wed, 30 Jun 2004 23:34:24 -0500 -From: "SCHULTZ, DARYLE (SBCSI)" - -Got it to work. Using dbd 1.16 - -Perl 5.8.4 built like this, with Visual Age 6.0: - -config_args='-Dcc=xlc_r -Dusenm -Dprefix=/appl/datasync/work/perl5 --Dusethreads -Duse64bitall -des' -============================================== - -Used DBI 1.42 -============================================= -Added this to top of Oracle.h: -#define A_OSF - -#include -======================= -Set LIBPATH to point to 64bit Oracle libs first. -export LIBPATH=$ORACLE_HOME/lib:$ORACLE_HOME/lib32:/usr/lib - -Use: perl Makefile.PL -nob - -Change all references in Makefile of LD_RUN_PATH to be LIBPATH. -Change nothing else, left all flags in Makefile, including -q64. -Passed make, and all tests. - --------------------------------------------------------------------------------------- diff --git a/README.clients.txt b/README.clients.txt deleted file mode 100644 index 274ca435..00000000 --- a/README.clients.txt +++ /dev/null @@ -1,279 +0,0 @@ -This file contains some random notes relating to minimal Oracle -configurations for building and/or using DBD::Oracle / Oraperl. - - -*** ALL THE TEXT BELOW IS OLD *** -*** THE PREFERED METHOD IS TO USE Oracle Instant Client *** - - -------------------------------------------------------------------------------- -With recent versions of Oracle (specifically >= 7.3) you may be -able to build DBD::Oracle without Pro*C installed by using the Oracle -supplied oracle.mk file: - - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/oracle.mk - -(The oracle.mk file might also be found in $ORACLE_HOME/rdbms/public/) - -------------------------------------------------------------------------------- -From: James Cooper - -> [...], what do I need in addition to perl5 to access an Oracle database -> on another system from a unix box (Solaris 2.5) that doesn't have an -> oracle database running on it ? -> -> In other words are their some oracle shared objects, etc. I need ? - -I don't have experience with Solaris, but on IRIX 5.3, I simply installed -SQL*Net ($ORACLE_HOME/network/admin/*) and the OCI libraries which are in -$ORACLE_HOME/lib. You'll also need the header files from -$ORACLE_HOME/sqllib/public/*.h and $ORACLE_HOME/rdbms/demo/*.h (you won't -need them all, but you can get rid of them after DBD::Oracle compiles). - -[You'll probably need at least ocommon in addition to network. But if you -use the Oracle installer (as you always should) it'll probably install -ocommon for you.] - -So just put that stuff on your client box and install DBI and DBD::Oracle -there. Once DBD::Oracle is installed you can remove the OCI libraries and -headers (make sure to keep SQL*Net!) - -Other than that, getting it working isn't too hard. If you're not -familiar with SQL*Net, let me know. I'm no expert, but I know the basics. -The main thing is to have a good tnsnames.ora file in -$ORACLE_HOME/network/admin - -------------------------------------------------------------------------------- -From: Jon Meek - -For my compilation of DBD-Oracle/Solaris2.5/Oracle7.2.x(x=2, I think), I -just pulled the required files in the rdbms directory from the Oracle CD. -The files I needed were: - -$ ls -lR -drwxr-xr-x 2 oracle apbr 512 May 15 17:43 demo/ -drwxr-xr-x 2 oracle apbr 512 May 15 16:20 lib/ -drwxr-xr-x 2 oracle apbr 512 May 15 16:18 mesg/ -drwxr-xr-x 2 oracle apbr 512 May 15 17:38 public/ - -./demo: --r--r--r-- 1 oracle apbr 4509 Jun 29 1995 ociapr.h --r--r--r-- 1 oracle apbr 5187 Jun 29 1995 ocidfn.h --rw-rw-r-- 1 oracle apbr 6659 Jun 29 1995 oratypes.h - -./lib: --rw-r--r-- 1 oracle apbr 1132 Jul 6 1995 clntsh.mk --rwxr-xr-x 1 oracle apbr 5623 Jul 17 1995 genclntsh.sh* --rw-r--r-- 1 oracle apbr 15211 Jul 5 1995 oracle.mk --rw-r--r-- 2 oracle apbr 3137 May 15 16:20 osntab.s --rw-r--r-- 2 oracle apbr 3137 May 15 16:20 osntabst.s --rw-r--r-- 1 oracle apbr 9 May 15 16:19 psoliblist --rw-r--r-- 1 oracle apbr 39 May 15 16:21 sysliblist - -./mesg: --r--r--r-- 1 oracle apbr 183296 Jul 11 1995 oraus.msb --r--r--r-- 1 oracle apbr 878114 Jul 11 1995 oraus.msg - -./public: --r--r--r-- 1 oracle apbr 5187 Jun 29 1995 ocidfn.h - -Jon - -------------------------------------------------------------------------------- -Jon Meek Tue, 18 Feb 1997 - -This was for Oracle 7.2.2.3.0 (client side for DBD:Oracle build) and -SQL*net v2. I have heard that sqlnet.ora might not be needed. - -ls -lR oracle -oracle: -total 2 -drwxr-xr-x 3 meekj apbr 512 Nov 3 11:46 network/ - -oracle/network: -total 2 -drwxr-xr-x 2 meekj apbr 512 Nov 3 11:46 admin/ - -oracle/network/admin: -total 6 --rw-r--r-- 1 meekj apbr 309 Nov 3 11:46 sqlnet.ora --rw-r--r-- 1 meekj apbr 1989 Nov 3 11:46 tnsnames.ora - -------------------------------------------------------------------------------- - -From: Lack Mr G M -Date: Thu, 23 Jan 1997 18:24:03 +0000 - - I noticed the appended in the README.clients file of the DBD-Oracle -distribution. My experience is somewhat different (and simpler). - - On Irix5.3 (ie. what this user was using) I built DBI and DBD-Oracle -on a system with Oracle and Pro*C installed. I tested it on another -system (where I knew an oracle id). I installed it from a third (which -had write rights to the master copies of the NFS mounted directories), -but this didn't have Oracle installed. - - Having done this all of my systems (even those without a hint of -oracle on them) could access remote Oracle servers by setting TWO_TASK -appropriately. SQL*Net didn't seem to come into it. - - The dynamically-loadable library created (auto/DBD/Oracle/Oracle.so) -contains no reference to any dynamic Oracle library. - - Exactly the same happened for my Solaris systems. - - From: James Cooper - > [...], what do I need in addition to perl5 to access an Oracle database - > on another system from a unix box (Solaris 2.5) that doesn't have an - > oracle database running on it ? - > - > In other words are their some oracle shared objects, etc. I need ? - -I don't have experience with Solaris, but on IRIX 5.3, I simply installed -SQL*Net ($ORACLE_HOME/network/admin/*) and the OCI libraries which are in -$ORACLE_HOME/lib. You'll also need the header files from -$ORACLE_HOME/sqllib/public/*.h and $ORACLE_HOME/rdbms/demo/*.h (you won't -need them all, but you can get rid of them after DBD::Oracle compiles). - -So just put that stuff on your client box and install DBI and DBD::Oracle -there. Once DBD::Oracle is installed you can remove the OCI libraries and -headers (make sure to keep SQL*Net!) - -------------------------------------------------------------------------------- -OS/Oracle version: Solaris 2 and Oracle 7.3 - -Problem: DBD::Oracle works on the database machine, but not from remote -machines (via TCP). SQL*Plus, however, does work from the remote machines. - -Cause: $ORACLE_HOME/ocommon/nls/admin/data/lx1boot.nlb is missing - -Solution: Make sure $ORACLE_HOME/ocommon is available on the remote machine. - -This was the first time I had used DBD::Oracle with Oracle 7.3.2. Oracle -7.1 has a somewhat different directory structure, and seems to store files -in different places relative to $ORACLE_HOME. So I just hadn't NFS -exported all the files I needed to. I figured that as long as SQL*Plus -was happy, I had all the necessary files to run DBD::Oracle (since that -was always the case with 7.1). But I was wrong. - -James Cooper - -------------------------------------------------------------------------------- -Subject: Re: Oracle Licencing... -Date: Thu, 15 May 1997 11:54:09 -0700 -From: Mark Dedlow - -Please forgive the continuation of this somewhat off-topic issue, -but I wanted to correct/update my previous statement, and it's -probably of interest to many DBD-Oracle users. - -> > In general, as I understand it, Oracle doesn't license the client runtime -> > libraries directly, rather they get you for SQL*NET. It is typically -> > about $100 per node. You have to have that licensed on any machine -> > that runs DBD-Oracle. - -Oracle recently changed policy. sqlnet now comes with RDBMS licenses. -If you have named RDBMS licenses, you can install sqlnet on as many -client machines as you have named licenses for the server. If you -have concurrent RDBMS licenses, you can install sqlnet on as many -client machines as you like, and only use concurrently as many -as you have concurrent server RDBMS licenses. - -OCI, Pro*C, et. al. only requires you to have a development license, -per developer. The compiled apps can be distributed unlimited. -The client where the client app resides must be licensed to use -sqlnet, by the above terms, i.e. by virtue of what the licenses on -the server are that the client is connecting to. - -This means one could legitimately distribute DBD-Oracle in compiled form. -Probably not recommended :-) - -But is does mean one can compile DBD-Oracle and distribute it internally -to your org without more licensing, as long as the targets have sqlnet. - -Obviously, this is not a legal ruling. I don't work for Oracle. -But this is what my sales rep tells me as of today. - -Mark -------------------------------------------------------------------------------- - -From: Wintermute - -Ok, you may think me daft for this but I just figured out what was -necessary in using DBI/DBD:Oracle on a machine that needs to access a -remote Oracle database. - -What the docs tell you is that you just need enough of Oracle installed -to compile it. They don't say that you need to keep that "just enough" -around for the DBI to work properly!! - -So here's my predicament so that others might benefit from my bumbling. - -I needed to install Perl, DBI, and DBD:Oracle on a machine running a -Fast Track web server (hostname Leviathan) that is to access a remote -Oracle database (henceforth called Yog-Sothoth (appropriate for the -beast that it is)). Leviathan doesn't have enough space for the 500M -install that Oracle 7 for Solaris 2.5.1 wants so I had to figure out a -way to get things done. Here's a brief list of the steps I took for -Leviathan. - -1. Got the GCC binary dist for Solaris 2.6 and installed -2. Got Perl 5.004_01 source/compiled/installed -3. Got the DBI .90 compiled/installed -4. Got DBD:Oracle... - - (and here's where it gets interesting). - - I exported the /opt/oracle7 directory from Yog-Sothoth to -Leviathan in -order to compile DBD:Oracle, then umount'ed it afterwards. Tried 'make -test' after it had compiled and watched it flounder and fail. For the -life of me I couldn't figure out why this could be so, so I went back -and adjusted my TWO_TASK/ORACLE_USERID env vars. - No luck. - Wash/Rinse/Repeat. - Still no luck. -I started to get desperate about this time, so instead of screwing with -it anymore I installed the module under the Perl heirarchy just to be -done for the moment with it (figuring that the 'make test' script could -be fallible). I neglected to mention that the errors I was getting were -coming from the Oracle database on the remote machine, so I knew it -worked in part, just not well enough to hold the connection for some -reason. - -After having no luck with my own Perl connect script I tried remounting -the nfs volume with Oracle on it and setting ORACLE_HOME to it. When I -ran that very same Perl script it WORKED! Well sort of. None of the -short connection methods worked, I was forced to use the long method of -connecting IE: name/password@dbname(DESCRIPTION=(ADDRESS=(...etc.etc. - -So here I am figuring that I'm doing something right, but there's -something I'm missing. Well it turns out that it's not me, it's the -machine that's missing it. If you are going to be using the DBD:Oracle -driver with DBI, you'll need more than just it after compile time, -you'll need some Oracle files as well. - -(BTW I'm running Oracle 7.3.2.2.0) - -You'll need everything in /var/opt/oracle (on the machine that houses -Oracle), as well as $ORACLE_HOME/ocommon/nls. Why National Language -Support is needed I'll never know. ocommon/nls has to reside under the -directory your $ORACLE_HOME points to, and it's best to leave -/var/opt/oracle/'s path alone. - -When I made these adjustments on the Oracle'less box and tried the 'make - -test' again, it ran through without a hitch. I'll be doing some more -intensive things with it from here on out and if anything changes I'll -let you all know, however this seems odd that nothing is mentioned in -the documentation about what residual files need to be around after -compiling the DBD:Oracle for it to work successfully. - -Like I said, don't flame me for being stupid, but I just had to get this -story off my chest since I've been puzzling over it all day and I feel -that other people may want to do the same thing as I did, and will run -into the same problems. - --- Wintermute - -------------------------------------------------------------------------------- diff --git a/README.help.txt b/README.help.txt index cfbe9932..7e68453c 100644 --- a/README.help.txt +++ b/README.help.txt @@ -7,132 +7,6 @@ same or similar problems may exist on other systems or versions. Most of this mess is due to Oracle's fondness for changing the build/link process for OCI applications between versions. -------------------------------------------------------------------------------- -Error: 'UV' not in typemap in Oracle.xs, line ... - -You're using Perl 5.5.3. Perl 5.5.3 is very old and and upgrading -to at least 5.6.1 is recommended. The DBI itself has required -perl >= 5.6.0 since DBI 1.38, August 2003. - -Meanwhile, edit Oracle.xs and change each UV to an IV, change newSVuv to newSViv, -cross your fingers, and avoid using longer, bigger, wider than 2GB, or less than zero! -This is a hacked DBD::Oracle and not recommended for production use. - -------------------------------------------------------------------------------- -If you get compiler errors refering to Perl's own header files -(.../CORE/*.h) then there is something wrong with your installation. -It is best to use a Perl that was built on the system you are trying to -use and it's also important to use the same compiler that was used to -build the Perl you are using. - -------------------------------------------------------------------------------- -Assorted runtime problems... - -Ensure that the version of Oracle you are talking to is the same one -you used to build your DBD::Oracle module. - -Try building perl with 'usemymalloc' disabled. -Try building perl with 'threads' enabled (esp for Oracle >= 8.1.6). - -Try removing "-lthread" from $ORACLE_HOME/lib/ldflags and/or -$ORACLE_HOME/lib/sysliblist just for the duration of the DBD::Oracle build -(but I can't really recommend this approach as it may cause subtle -problems later) - -If you find a memory leak that you can isolate to DBD::Oracle, and you're -using a perl built with threading enabled, first try rebuilding perl without -support for threads. Apart from making perl run faster it may also fix the leak. -Please report memory leaks, with a small self-contained test script, -to dbi-users@perl.org. - -------------------------------------------------------------------------------- -Bad free() warnings: - -These are generally caused by problems in Oracle's own library code. -You can use this code to hide them: - - $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Bad free/ } - -If you're using an old perl version (below 5.004) then upgrading will -probably fix the warnings (since later versions can disable that warning) -and is highly recommended anyway. - -Alternatively you can rebuild Perl without perl's own malloc and/or -upgrade Oracle to a more recent version that doesn't have the problem. - -------------------------------------------------------------------------------- -Can't find libclntsh.so: - -Dave Moellenhoff : libclntsh.so is the shared -library composed of all the other Oracle libs you used to have to -statically link. -libclntsh.so should be in $ORACLE_HOME/lib. If it's missing, try -running $ORACLE_HOME/lib/genclntsh.sh and it should create it. - -Also: Never copy libclntsh.so to a different machine or Oracle version. -If DBD::Oracle was built on a machine with a different path to libclntsh.so -then you'll need to set set an environment variable, typically -LD_LIBRARY_PATH, to include the directory containing libclntsh.so. - -But: LD_LIBRARY_PATH is typically ignored if the script is running set-uid -(which is common in some httpd/CGI configurations). In this case -either rebuild with LD_RUN_PATH set to include the path to libclntsh -or create a symbolic link so that libclntsh is available via the same -path as it was when the module was built. (On Solaris the command -"ldd -s Oracle.so" can be used to see how the linker is searching for it.) - - -------------------------------------------------------------------------------- -Error while trying to retrieve text for error ...: - -From Lou Henefeld : We discovered that we needed -some files from the $ORACLE_HOME/ocommon/nls/admin/data directory: - lx00001.nlb, lx10001.nlb, lx1boot.nlb, lx20001.nlb -If your national language is different from ours (American English), -you will probably need different nls data files. - - -------------------------------------------------------------------------------- -ORA-01019: unable to allocate memory in the user side - -From Ethan Tuttle : My experience: ORA-01019 errors -occur when using Oracle 7.3.x shared libraries on a machine that -doesn't have all necessary Oracle files in $ORACLE_HOME. - -It used to be with 7.2 libraries that all one needed was the tnsnames.ora -file for a DBD-Oracle client to connect. Not so with 7.3.x. I'm not sure -exactly which additional files are needed on the client machine. - -Furthermore, from what I can tell, the path to ORACLE_HOME is resolved and -compiled into either libclntsh.so or the DBD-Oracle. Thus, copying a -minimal ORACLE_HOME onto a client machine won't work unless the path to -ORACLE_HOME is the same on the client machine as it is on the machine -where DBD-Oracle was compiled. - -ORA-01019 can also be caused by corrupt Oracle config files such as -/etc/oratab. - -ORA-01019 can also be caused by using a different version of the -message catalogs ($ORACLE_HOME/ocommon/nls/admin/data) to that used -when DBD::Oracle was compiled. - -Also try building with oracle.mk if your DBD::Oracle defaulted to proc.mk. - -------------------------------------------------------------------------------- -SCO - For general help enabling dynamic loding under SCO 5 - - http://www2.arkansas.net/~jcoy/perl5/ - -------------------------------------------------------------------------------- -AIX - warnings like these when building perl are not usually a problem: - -ld: 0711-415 WARNING: Symbol Perl_sighandler is already exported. -ld: 0711-319 WARNING: Exported symbol not defined: Perl_abs_amg - -When building on AIX check to make sure that all of bos.adt (13 pieces) -and all of bos.compat (11 pieces) are installed. - -Thanks to Mike Moran for this information. ------------------------------------------------------------------------------- AIX 4 - core dump on login and similar problems @@ -376,13 +250,6 @@ Try each of these in turn (follow each with a make && make test): perl Makefile.PL -n LIBCLNTSH let me know if any of these help. -------------------------------------------------------------------------------- -Some runtime problems might be related to perl's malloc. - -This is a long shot. If all else fails and perl -V:usemymalloc says -usemymalloc='y' then try rebuilding perl using Configure -Uusemymalloc. -If this does fix it for you then please let me know. - =============================================================================== Hang during "repetitive connect/open/close/disconnect" test: diff --git a/README.java.txt b/README.java.txt deleted file mode 100644 index 8958df27..00000000 --- a/README.java.txt +++ /dev/null @@ -1,322 +0,0 @@ -README.java.txt - -This file relates to a specific problem on Solaris platforms -for Oracle 8.1.6 (and possibly later versions) where loading -DBD::Oracle fails with an error message like: - - ``You must install a Solaris patch to run this version of - the Java runtime. - Please see the README and release notes for more information.'' - -The problem seems to be that: - -1/ By default, the Oracle shared library contains a ``Radius - authentication module'' that is implemented in Java. -2/ The Java implementation requires that the thread library is - also linked into the application. -3/ For some inexplicable reason the thread library has to be - linked to the executable that's doing the dynamic loading. - It's is not sufficient to link -lthread to DBD::Oracle. - -There are several ways to workaround this: - -1/ Remove the Radius authentication module if you don't need it. - This requires you to perform surgery on the Oracle installation. - (If the name Radius doesn't mean anything to you and you're - the person maintaining the Oracle installation then you almost - certainly don't need it.) - -2/ Use the LD_PRELOAD environment variable to force the pre-loading - of the thread library. Note that this must be set before perl - starts, you can't set it via $ENV{LD_PRELOAD} within the script. - -3/ Link the thread library to your perl binary. - You can do that either by (re)building perl with thread support - or, I believe, it should be possible to issue a magic 'ld' command - to add linkage to the thread library to an existing perl executable. - (But you'll need to work that one out yourself. If you do please let - me know so I can add the details here to share with others.) - -Most of this information comes from Andi Lamprecht, to whom I'm very -grateful indeed. - -I've included below two of his email messages, slightly edited, where -he explains the procedure for options 1 and 2 above. I've also -appended a slight reworking of option 1 from Paul Vallee. And I've later -added some more useful messages from other people. - -Tim. - ----- - - -From: andi@sunnix.sie.siemens.at - -Have managed it to get DBD to work with Oracle 8i without these nasty Java -error! It seems to be that a thing called "NAU" links in a radius -athentication module which is written in Java and this causes the -additional java libraries in the libclntsh.so. After throwing it all out -DBD tests ran successfully. - -The steps to take are: - - - shut down Oracle server if you have one running in the installation - you're about to modify. - - take a backup copy of your Oracle installation! You have been warned! - - - go to $ORACLE_HOME/network/lib (or it maybe (also?) in $ORACLE_HOME/oas/lib) - - rebuild nautab.o with: - - make -f ins_nau.mk NAU_ADAPTERS="IDENTIX KERBEROS5 SECURID" nautab.o - - This build a new nautab.o without the radius authentication module. - - - go to $ORACLE_HOME/lib - - edit file "ldflags" and delete all occurences of "-lnrad8" and "-ljava" - and "-[LR]$ORACLE_HOME/JRE/lib/sparc/native_threads" - - - go to $ORACLE_HOME/bin - - build a new libclntsh.so with: - - genclntsh - - - start up Oracle - - - go back to the DBD-* directory and build the Oracle driver with: - - perl Makefile.PL; make; make test - -This worked for me, the database is still operational, MAYBE SOME JAVA -STUFF ISN'T WORKING. Better someone else with more experience in java -finds out ... - -The problem seems to be a dynamic linking issue. Whenever java virtual -machine is loaded, some symbols are missing (with java 1.2.2_05 these -_thread_something symbols where not found, even with linked-in -libthread.so, with java 1.1.8 some _lseek or so symbols couldn't be -resolved). Seems Oracle did a good job in integration of Java in the -database ... - -Ok, should go out now 'cause its a beatiful wheater here in Vienna! - -Greetings -A. Lamprecht - ------------ - - -From: andi@sunnix.sie.siemens.at - -For some reason libthread.so.1 isn't included as dynamic object in perl -binary and so symbols aren't found. - -The interesting output of LD_DEBUG=symbols: -symbol=thr_getstate; dlsym() starting at file=/usr/local/bin/perl -symbol=thr_getstate; lookup in file=/usr/local/bin/perl [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libsocket.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libnsl.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libdl.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libm.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libc.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libcrypt_i.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libmp.so.2 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libgen.so.1 [ ELF ] -ld.so.1: /usr/local/bin/perl: fatal: thr_getstate: can't find symbol - -This list looks exactly like the one you get when ldd-ing the perl binary. -There is an option to the dynamic linker "LD_PRELOAD" and if you set it with - - LD_PRELOAD=/lib/libthread.so.1 - export LD_PRELOAD - -before starting any DBD::oracle app, the app works! (Note that this must -be set before perl starts, you can't set it via $ENV{LD_PRELOAD} within -the script.) - -It looks like after libjava and libjvm is loaded, the library search path -is somehow stripped to the one of the perl binary ... - -[That looks like a Solaris bug] - -Hope this helps. - -A. Lamprecht ------------ - - -From: Paul Vallee - -Andi is right. Three cheers for Andi!!! :-) - -Final Summary (this is mostly Andi's work summarized here) - -1. Copy your ORACLE_HOME in it's entirety to a new directory. -cp -r $ORACLE_HOME $ORACLE_HOME.nojava - -2. Set your ORACLE_HOME variable to the new one. Save the old one for reference. -export OLD_ORACLE_HOME=$ORACLE_HOME -export ORACLE_HOME=$ORACLE_HOME.nojava - -3. cd $ORACLE_HOME/network/lib (or it maybe (also?) in $ORACLE_HOME/oas/lib) -This is your new ORACLE_HOME - the temporary one that will soon be without -Java or Radius. - -4. build nautab.o with -make -f ins_nau.mk NAU_ADAPTERS="IDENTIX KERBEROS5 SECURID" nautab.o - -5. go to $ORACLE_HOME/lib -edit file "ldflags" and delete all occurences of "-lnrad8" and "-ljava" -and "-[LR]$ORACLE_HOME/JRE/lib/sparc/native_threads" -I wrote this little pipeline to do this. -sed 's/-lnrad8//g' < ldflags | \ -sed 's/-ljava//g' | \ -sed "s%-L$OLD_ORACLE_HOME/JRE/lib/sparc/native_threads%%g" | \ -sed "s%-R$OLD_ORACLE_HOME/JRE/lib/sparc/native_threads%%g" | > newldflags -If you look at newldflags, and like it, then run: -cp ldflags oldldflags; cp newldflags ldflags - -6. go to $ORACLE_HOME/bin and build a new libclntsh.so with "genclntsh" -genclntsh - -7. go to your DBD::oracle install directory and go through the regular -install process. -perl Makefile.PL; make; make install -(I find the make test less useful than my test.pl perl file.) - -8. Set LD_LIBRARY_PATH=$ORACLE_HOME/lib. -This part is very important - remember that at this stage ORACLE_HOME is set -to the nojava home. Make this permanent by explicitly setting -LD_LIBRARY_PATH to the nojava lib directory in your .profile. -This is the step that stalled me - thanks again to Andi. - -9. Test this out. I use the following command which fails -nicely if we've failed, and is very quiet if we've succeeded: - perl -MDBD::Oracle -e 0 -there should be no output. Congratulations. - -10. Get rid of everything other than libclntsh.so in your new ORACLE_HOME - -the rest is a waste of space. -cd $ORACLE_HOME; cd .. -mv $ORACLE_HOME $ORACLE_HOME.rmme -mkdir $ORACLE_HOME; mkdir $ORACLE_HOME/lib -cp $ORACLE_HOME.rmme/lib/libclntsh.so $ORACLE_HOME/lib - -11. Run test.pl again just to be sure it still works. - -12. If test.pl is still working, then we can reclaim space with -rm -fr $ORACLE_HOME.rmme - -Note that in my opinion this is a workaround - there is no reason on the -face of it that I can fathom that we shouldn't be able to use DBD::Oracle to -connect to Oracle with Java compiled in. (?) - -Enjoy, -Paul Vallee -Principal -The Pythian Group, Inc. ------------------------------------------------------------------------------- - -From: Peter Ludemann - -Here's a different way for ensuring that LD_PRELOAD has been set: - - unless (($ENV{LD_PRELOAD}||'') =~ /thread.so/) { - $ENV{LD_PRELOAD} = '/lib/libthread.so'; - exec($^X, '-w', $0, @ARGV); - } - -This hasn't been rigorously tested, but it seems to do the trick, at -least on Solaris 7 with Oracle 8. - ------------------------------------------------------------------------------- - -From: VG - -I've had luck with adding the following at the top of my program: - -use DynaLoader; -Dynaloader::db_load_file("/usr/lib/libthread.so", 0x01); - -(Others have reported this nor working for them.) - ------------------------------------------------------------------------------- - -From: daver@despair.tmok.com (Dave C.) -Subject: Re: DBI::DBD with Oracle 8i -Newsgroups: comp.lang.perl.modules - -It looks like a lot of people are having this problem.... - -I managed to solve it. I'm running Oracle 8.1.6, Solaris 8, Perl 5.6.0, -and the latest DBI/DBD modules. - -I did some experimentation and discovered that the root of the problem -was that libclntsh.so was linking with nautab.o. For some reason, -nautab.o was linked with this RADIUS authentication (?) thing that was -calling into Java (even though I don't use that particular functionality.) - -So, what I had to do was generate a libclntsh.so that linked with a -nautab.o that didn't require the radius (and thus the java). I then -forced the Oracle DBD to link with my library and installed it, and it -worked. - -Here's the step-by-step: - -To do this, first copy the "genautab" and "genclntsh" scripts to a -scratch directory. By default "genautab" apparently generates some -default network authentication stub without a lot of options (which was -okay for me.) - -I ran: - - ./genautab >nautab.s - as -P nautab.s - -After this step you should have a "nautab.o" file. - -Now, you must must modify "genclntsh" to produce your custom clntsh -library (which I called "perlclntsh" so I wouldn't mess up the original -Oracle library.) So I went into the file and modified CLNT_NAM to read -"perlclntsh". I also changed LIB_DIR to put the resulting library in -my current directory: (LIB_DIR=`pwd`) - -Also, instead of creating the library, I modified the script to just -echo the command. Search for "# Create library" and put "echo " before -{$LD} ${LD_RUNTIME}... Now, when you run "./genclntsh" you should get -a large command. Redir this command to a file "./genclntsh >t" - -Now, edit this file and remove all references to java libraries (get -rid of all "-ljava" instances, at least, and you may need to delete -other stuff, like -lnative_threads.) . Run your script: "sh ./t". -After some time you should wind up with a "libperlclntsh.so.8.0". -This is your custom library any of the java stuff linked in. - -Then copy this lib to /usr/local/lib and create a softlink -"libperlclntsh.so" to "libperlclntsh.so.8.0" (or copy it wherever you -want...) - -Then you have to force DBD to link with this library instead of linking -with the libclntsh.so provided by Oracle. - -Basically what I did was follow the normal DBD-Oracle directions. I -then edited the resulting Makefile manually and changed all references -of libclntsh.so to libperlclnt.so (ie, -lclntsh to -lperlclntsh) I -also changed the LDDLFLAGS and LDFLAGS and appended "-L/usr/local/lib --R/usr/local/lib -L/usr/ucblib -R/usr/ucblib -lucb". (for some reason -the resulting DBD wanted to link with ucb) Run "make" and rebuild the -DBD. Now "make test" should pass. - -Note that this was a fairly long (couple of hours) series of trial and -error before I finally got this to work. Your system may be different -and you may encounter your own linking problems, etc. - -Disclaimer: This may not work for you, but it worked for me. Even if it -does work for you there is no guarantee that the resulting module will -function correctly and won't hose your database, etc... - -I forgot to mention that in script resulting from genclntsh you must -tell it to use _your_ nautab.o for linking, not the oracle lib one. -Oops. - --Dave - diff --git a/README.mkdn b/README.mkdn index f9c0ce53..9df11205 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.46 +version 1.47_00 # SYNOPSIS diff --git a/README.sec.txt b/README.sec.txt deleted file mode 100644 index 72920db6..00000000 --- a/README.sec.txt +++ /dev/null @@ -1,142 +0,0 @@ -I have no intention of becoming a channel for Oracle Support Services -but this is a significant security hole and so I'm making an exception. - ------ Forwarded message from Oracle Support Services ----- - -Date: Fri, 7 May 1999 06:29:09 -0700 -From: Oracle Support Services -Subject: SUID Security Issue - -Platform: UNIX - -Distribution: Internal & External - -Problem Subject Line: SUID Security - -Product: Oracle Enterprise Manager 2.0.4 - Oracle Data Server - -Oracle Version: 8.0.3, 8.0.4, 8.0.5, 8.1.5 - -Component: Intelligent Agent - Oracle Data Server - -Component Version: 8.0.3, 8.0.4, 8.0.5, 8.1.5 - -Sub-Component: N/A - -Platform Version: All Unix Versions. - -Errors: N/A - -Revision Date: 6-March-1999 - -Problem Description: - -On UNIX platforms, some executable files have the setuid (SUID) -bit on. It may be possible for a knowledgeable user to use -these executables to bypass your system security by elevating -their operating system privileges. Oracle Corporation has -identified issues regarding executables with SUID set in -Oracle releases 8.0.3, 8.0.4, 8.0.5 and 8.1.5 on UNIX platforms -only. This problem will be fixed in Oracle releases 8.0.6 and -8.1.6. - -Depending on your Oracle installation, the available patch will 1) -correct the SUID bits on applicable files, and/or 2) delete the -oratclsh file. This shell script should be run immediately, and also -should be run after each relink of Oracle. - -You can download the patch from Oracle Support?s MetaLink website by -going to the following URL, -http://support.oracle.com/ml/plsql/mlv15.frame?call_type=download&javaFlag=JAVA. -Once you are in this page, select 'Oracle RDBMS' as the product -and then click on the 'Go' button. Then download patch named 'setuid.' - -Please contact Oracle Worldwide Support for any additional issues. - ------ End forwarded message ----- - -Date: Sat, 08 May 1999 19:12:52 -0700 -From: Mark Dedlow - -I went to the URL listed for the patch, but it appears you can't get to -it directly. It requires a Oracle Metalink account, and even then, you -have to follow a bunch of links to get it, you can't go direct (at -least I couldn't at the URL in the announcement). - -You don't really need the patch however, it's just a shell script that -in effect does chmod -s on everything in $ORACLE_HOME/bin except -'oracle' and 'dbsnmp' (needed only for OEM or SNMP). - -Also, although the patch didn't address the issue, make sure _nothing_ -below ORACLE_HOME is owned by root. There are some installations that -make certain files setuid to root (files that are trivial to compromise). - -Mark - - ------------------------------------------------------------------------------- - -From: Dan Sugalski -Date: Mon, 10 May 1999 09:13:28 -0700 - -The patch actually removes the setuid bit on a number of oracle -executables. The 'unset' list is: - -lsnrctl oemevent onrsd osslogin tnslsnr tnsping trcasst trcroute cmctl -cmadmin cmgw names namesctl otrccref otrcfmt otrcrep otrccol oracleO - -While the 'must set' list is: - -oracle dbsnmp - -The shell script to fix the bits properly was posted to the oracle list -running at telelists.com. Check the archives there for it if you want. -(www.telelists.com) I think it's also gone out to one of the BUGTRAQ -lists, and some of the CERTs might have it too. - - Dan - ------------------------------------------------------------------------------- - -Date: Wed, 12 May 1999 11:49:45 -0700 -From: Mark Dedlow - -> The patch actually removes the setuid bit on a number of oracle -> executables. The 'unset' list is: -> -> lsnrctl oemevent onrsd osslogin tnslsnr tnsping trcasst trcroute cmctl -> cmadmin cmgw names namesctl otrccref otrcfmt otrcrep otrccol oracleO - -Actually, there's a little more than that. For each item in that list, -it also looks for a version of the file with a 0 or O appended to it -(these are backups the link makefiles create), so the above list isn't -exactly complete. - -The important issues are simply: - - o *ONLY* $ORACLE_HOME/bin/oracle requires setuid bit set for - the Oracle RDBMS and tools to function. - - o *IF* you run dbsnmp, it must be setuid. (If you don't know what dbsnmp - is, you're probably not running it -- it's a remote monitoring/control - daemon) - -Armed with that knowledge, you can use any technique you like to achieve -the desired results. For example, this achieves it: - -find $ORACLE_HOME/bin -perm -2000 ! -name oracle ! -name dbsnmp | xargs chmod -s - -Mark - ------------------------------------------------------------------------------- - -One further note I'll pass on anonymously and without comment: - -> please include something like: "After removing the setuid bits, slap -> your system administrator for running root.sh as root without actually -> reading it first." -> :) - ------------------------------------------------------------------------------- diff --git a/README.win32.txt b/README.win32.txt deleted file mode 100644 index e3ad66db..00000000 --- a/README.win32.txt +++ /dev/null @@ -1,236 +0,0 @@ -In general, on Windows, it's best to just use ActiveState Perl and the -PPM package manager to install a pre-built version of DBD::Oracle however only version 1.17 is available there. - -If you built Perl with gcc, read README.wingcc.txt as well as this file. - - -Oracle Instant Client 11.1.0.6.0 Notes - -So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value -in the environment variables. - -As well IC 11 seems to have trouble finding the .ORA files. A quick fix for this is to add "TNS_ADMIN" -to the environment variables and point it to where your .ORA files are. - - ---- other information, some of which is out of date --- - -DBD-Oracle for Windows and Oracle Instantclient and 10XE (Express Edition) -By: John Scoles Scoles@ptyhian.com -The Pythian Group - -The preferred method of getting DBD::Oracle is to use a pre-built version from the ActiveState -repository, which can be installed with PPM. - -Compiling and installing DBD::Oracle 1.18 or later on a windows 2000 professional or XP OS for use -with Oracle instantClient ver 10.2.0.1 & 10.1.0.5 or Oracle XE requires only a few downloads and -a minimal number of environment setting. The procedures below were tested on a clean -Windows platform having no Oracle or other development environment installed. - -1) The first part of the process is to download and install the latest version of - Active Perl from http://www.activeperl.com/. - -2) Use the PPM application to get the latest version of DBI - -3) Download the latest DBD::Oracle from http://svn.perl.org/modules/dbd-oracle/trunk/ - -4) Download and unzip the Oracle Instant Client (10.2.0.1 or 10.1.0.5) 32 bit from - http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html - You will need all three of these products - i. Instant Client Package - Basic - ii. Instant Client Package - SQL*Plus: - iii. Instant Client Package - SDK: - or - - install oracle 10XE http://www.oracle.com/technology/products/database/xe/index.html - -5) You will now need the Microsoft Visual C++ toolkit 2003. Unfortunately this product is no longer available from Microsoft. - The file name was VCToolkitSetup.exe and is available at this mirror site http://www.filewatcher.com/m/VCToolkitSetup.exe.32952488.0.0.html at the time of writing. - Microsoft's replacement for this tool kit is Visual C++ 2005 Express Edition and all attempts to compile DBD::Oracle with this product fail. It has been successfully compiled - using a complete edition of Microsoft Visual Studio 2005. - Download and then install this product. - -6) You will also need the Windows SDK. Which can be found at - http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en - You have the choice to of either to download the entire SDK and install or run an online install from the page. - Both have been tested and proven to work. - -7) Next download and install the Microsoft .net framework 1.1 skd from - http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&displaylang=en - -8) You will also need a copy of nmake.exe which you can download here http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe - -9) Enough Downloading and installing go have a coffee. - -10) You should at this time attempt to connect to an Oracle database with the version SQL*Plus that - you installed in step 4. If you are unable to connect at this stage then any problems you encounter - later may have nothing to do with DBD::Oracle - -11) On the path where you installed Visual C++ find and edit the vcvars32.bat file as follows. You may have to modify - these path values depending where you installed the products on you computer, - - i. Add the local path to the windows platform SDK include directory to the Set INCLUDE - Command Line to include the needed files from the Windows SDK. - - e.g. "C:\Program Files\Microsoft Platform SDK\Include;" - - ii. Add the local path to the .net Vc7 lib directory to the Set LIB command - to include the needed library file from the .Net SKD - - e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; - - iii. Add the local path to the windows platform SDK Lib directory to the Set Lib command - to include the needed library files from the Windows SDK - - e.g. C:\Program Files\Microsoft Platform SDK\Lib; - -12) Open a Windows Visual C++ command window from the start menu. - -13) Add the path to the instant client to the Path command. If you are compiling aginst a 10XE db/client then you can skip steps - 12 to 14. - e.g. PATH = C:/Oracle/instantclient;%PATH% - -14) Using the "Set" command add "ORACLE_HOME=path to Instant client" to the environment variables. - e.g. Set ORACLE_HOME=C:\Oracle\instantclient - -15) Using the "Set" command add "NLS_LANG=.WE8ISO8859P15" to the environment variables. The globalization variable is required, - with this or another compatible value, by Oracle instantclient in order for it to compile correctly. - e.g. Set NLS_LANG=.WE8ISO8859P15 - -16) Using the "Set" command add "ORACLE_USERID=test/test@test" substituting test with the username/password@database - you wish to run the make test files against. - Note: it is not necessary to do this step for the compile and install to work. - However: The self-test programs included with Oracle-DBD will mostly fail. - -17) Move to the DBD-Oracle directory in the Visual C++ window DOS prompt and enter the following. - - c:\oracle-dbd\>perl Makefile.PL - - The Makefile should then run and compile Oracle-dbd without reporting any errors. - -18) From this DOS prompt enter the following command - - c:\oracle-dbd\>nmake - - The Visual C++ make executable will then build you DBD-execuable. There should be no errors at this point. - -19) You can test the compile by either entering - - c:\oracle-dbd\>nmake test - - As long as you have given a valid user name, password and database name in step 15 you will see some results. If it appears to - run but you do not get a connection check the following. - - i. User name password and DB Name - ii. Ensure the a valid TNSNAMES.ORA file is in the Instantclient directory - iii. Attempt to log into the version of SQLPLUS that comes with Instantclient. - If you manage to log on use the username password and TNS name with - the Set ORACLE_USERID = and rerun the tests. - iv If you are compiling against 10XE and have skiped steps 12 to 14 try again bu this time carry out these steps - -20) You can now install DBD-Oracle into you system by entering the following command from the Visual C++ window dos prompt; - - c:\oracle-dbd\>nmake install - -21) You should now be able to run DBD-Oracle on you system - -09/30 2006 from asu - -DBD::Oracle 1.18a - -Linux, Debian unstable ( -DBI: 1.52 -perl v5.8.8 built for i486-linux-gnu-thread-multi -) - -Oracle Instant client (10.1.0.5) - -The problem is in Makefile.PL. In line 130 the function find_oracle_home -is used to guess a value form $ORACLE_HOME if it is not set explicitely. -This value is used in line 138 to setup the environment (regardless -which client is used). - -in line 1443 (sub get_client_version) sqlplus is used to get the -version string, but for the oracle instant client you must not set -$ORACLE_HOME (it will generate an error "SP2-0642: SQL*Plus internal -error state 2165, context 4294967295:0:0") - -A solution that worked for me was to set -local $ENV{ORACLE_HOME} = ''; -in line 1463 immediately before sqlplus is called (but I cannot tell if -this fails for full client installations) - - -11/30/05 -- John Scoles -I have confirmed that this Makefile.pl will work for both Oracle InstantClient -10.2.0.1 & 10.1.0.4 using same process the Andy Hassall uses. Starting with a clean OD -One needs only to get the latest version of Active Perl 5.8.7 use PPM to get DBI and then -install Microsoft Visual C++ toolkit, Windows SDK, and the Microsoft .net -framework 1.1. and modify the vcvars32.bat in C++ dir as follows - - 1) Add the local path to the windows platform SDK include directory to the - Set INCLUDE Command Line to include the needed files from the Windows SDK. - e.g. "C:\Program Files\Microsoft Platform SDK\Include;" - 2) Add the local path to the .net Vc7 lib directory to the Set LIB - command to include the needed library files from the .Net SKD - e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; - 3) Add the local path to the windows platform SDK Lib directory to the Set Lib - command to include the needed library files from the Windows SDK - e.g. C:\Program Files\Microsoft Platform SDK\Lib; - -If one happens to have visual studio installed you may not have to download additional MS products. - -12/01/05 --- John Scoles -Oracle 10XE -No big problem here as 10XE seems to use the instantclient as well. Just ensure your - NLS_LANG and ORACLE_HOME are set to the same directory that 10XE uses - - -10/07/05 --John Scoles -Andy Hassall Kindly added some changes to the Makefile.PL -so it will work for the Instant Client 10g on Windows OSs. Below is how he set -up his environment and the steps he preformed to get it to compile. - - Setting environment for using Microsoft Visual Studio .NET 2003 tools. - (If you have another version of Visual Studio or Visual C++ installed and wish - to use its tools from the command line, run vcvars32.bat for that version.) - - C:\Documents and Settings\andyh>d: - - D:\>cd cygwin\home\andyh\src\pythian - - D:\cygwin\home\andyh\src\pythian>set ORACLE_HOME=d:\lib\instantclient_10_2 - - D:\cygwin\home\andyh\src\pythian>set NLS_LANG=.WE8ISO8859P15 - - D:\cygwin\home\andyh\src\pythian>set PATH=d:\lib\instantclient_10_2;D:\Program F - iles\Microsoft Visual Studio .NET 2003\Common7\IDE;D:\Program Files\Microsoft Vi - sual Studio .NET 2003\VC7\BIN;D:\Program Files\Microsoft Visual Studio .NET 2003 - \Common7\Tools;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ - bin\prerelease;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ - bin;D:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;C:\WINNT\Mic - rosoft.NET\Framework\v1.1.4322;d:\Perl\bin\;C:\WINNT\system32;C:\WINNT;C:\WINNT\ - System32\Wbem;D:\Program Files\Microsoft SDK\Bin;D:\Program Files\Microsoft SDK\ - Bin\WinNT - - D:\cygwin\home\andyh\src\pythian>set ORACLE_USERID=test/test@test102 - - D:\cygwin\home\andyh\src\pythian>perl Makefile.PL - - - -4/27/04 -- Jeff Urlwin - -Do not untar this distribution in a directory with spaces. This will not work. - -i.e. C:\Program Files\ORacle\DBD Oracle Distribution is bad while -c:\dev\dbd-oracle-1.15 is good ;) - -9/14/02 -- Michael Chase - -Makefile.PL uses Win32::TieRegistry or Win32::Registry to find the -current Oracle Home directory if the ORACLE_HOME environment variable -is not set. If neither module is installed, you must set ORACLE_HOME -before running Makefile.PL. Since the registry location of the current -Oracle Home is in different locations in different Oracle versions, -it is usually safer to set ORACLE_HOME before running Makefile.PL. diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9f44e064..25a6c851 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.46'; + $DBD::Oracle::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -125,7 +125,7 @@ BEGIN { { package DBD::Oracle::dr; { - $DBD::Oracle::dr::VERSION = '1.46'; + $DBD::Oracle::dr::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; @@ -330,7 +330,7 @@ BEGIN { { package DBD::Oracle::db; { - $DBD::Oracle::db::VERSION = '1.46'; + $DBD::Oracle::db::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; @@ -1059,7 +1059,7 @@ SQL { package DBD::Oracle::st; { - $DBD::Oracle::st::VERSION = '1.46'; + $DBD::Oracle::st::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; @@ -1164,7 +1164,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.46 +version 1.47_00 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 2ed2a1f0..1dc84996 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.46'; + $DBD::Oracle::GetInfo::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.46 +version 1.47_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index afab5549..e4680021 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.46'; + $DBD::Oracle::Object::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.46 +version 1.47_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm deleted file mode 100644 index 96e2f7d6..00000000 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ /dev/null @@ -1,419 +0,0 @@ -package DBD::Oracle::Troubleshooting; -{ - $DBD::Oracle::Troubleshooting::VERSION = '1.46'; -} -BEGIN { - $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; -} -#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle - - -__END__ -=pod - -=head1 NAME - -DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle - -=head1 VERSION - -version 1.46 - -=head1 CONNECTING TO ORACLE - -If you are reading this it is assumed that you have successfully -installed DBD::Oracle and you are having some problems connecting to -Oracle. - -First off you will have to tell DBD::Oracle where the binaries reside -for the Oracle client it was compiled against. This is the case when -you encounter a - - DBI connect('','system',...) failed: ERROR OCIEnvNlsCreate. - -error in Linux or in Windows when you get - - OCI.DLL not found - -The solution to this problem in the case of Linux is to ensure your -'ORACLE_HOME' (or LD_LIBRARY_PATH for InstantClient) environment -variable points to the correct directory. - - export ORACLE_HOME=/app/oracle/product/xx.x.x - -For Windows the solution is to add this value to you PATH - - PATH=c:\app\oracle\product\xx.x.x;%PATH% - -If you get past this stage and get a - - ORA-12154: TNS:could not resolve the connect identifier specified - -error then the most likely cause is DBD::ORACLE cannot find your .ORA -(F, F, F) files. This can be -solved by setting the TNS_ADMIN environment variable to the directory -where these files can be found. - -If you get to this stage and you have either one of the following -errors; - - ORA-12560: TNS:protocol adapter error - ORA-12162: TNS:net service name is incorrectly specified - -usually means that DBD::Oracle can find the listener but the it cannot connect to the DB because the listener cannot find the DB you asked for. - -=head2 Oracle utilities - -If you are still having problems connecting then the Oracle adapters -utility may offer some help. Run these two commands: - - $ORACLE_HOME/bin/adapters - $ORACLE_HOME/bin/adapters $ORACLE_HOME/bin/sqlplus - -and check the output. The "Protocol Adapters" should include at least "IPC Protocol Adapter" and "TCP/IP -Protocol Adapter". - -If it generates any errors which look relevant then please talk to your -Oracle technical support (and not the dbi-users mailing list). - -=head2 Connecting using a bequeather - -If you are using a bequeather to connect to a server -on the same host as the client, you might have -to add - - bequeath_detach = yes - -to your sqlnet.ora file or you won't be able to safely use fork/system -functions in Perl. - -See the discussion at -L -and L -for more gory details. - -=head1 USING THE LONG TYPES - -Some examples related to the use of LONG types are available in -the C directory of the distribution. - -=head1 LINUX - -=head2 Installing with Instantclient .rpm files. - -Nothing special with this you just have to set up you permissions as follows; - -1) Have permission for RWE on '/usr/lib/oracle/10.2.0.3/client/' or the other directory where you RPMed to - -2) Set export ORACLE_HOME=/usr/lib/oracle/10.2.0.3/client - -3) Set export LD_LIBRARY_PATH=$ORACLE_HOME/lib - -4) If you plan to use tnsnames to connect to remote servers and your tnsnames.ora file is not in $ORACLE_HOME/network/admin, you will need to Export TNS_ADMIN=dir to point DBD::Oracle to where your tnsnames.ora file is - -=head2 undefined symbol: __cmpdi2 comes up when Oracle isn't properly linked to the libgcc.a library. - -In version 8, this was correctd by changing the SYSLIBS entry in -$ORACLE_HOME/bin/genclntsh to include -"-L/usr/lib/gcc-lib/i386-redhat-linux/3.2 -lgcc". - -I had tried this with no success as when this program was then run, the -error "unable to find libgcc" was generated. Of course, this was the -library I was trying to describe! - -It turns out that now it is necessary to edit the same file and append -"`gcc -print-libgcc-file-name`" (including the backquotes!). If you do -this and then run "genclntsh", the libclntsh is properly generated and -the linkage with DBD::Oracle proceeds properly. - -=head2 cc1: invalid option `tune=pentium4'" error - -If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. - -No real problem with the above however you will have to - -1) run Perl Makefile.PL - -2) edit the Makefile and remove the offending '-mtune=pentium4' text - -3) save and exit - -4) do the make install and it should work fine for you - -=head2 Oracle 9i Lite - -The advice is to use the regular Oracle9i not the lite version. - -Another great source of help was: http://www.puschitz.com/InstallingOracle9i.html - -just getting 9i and 9i lite installed. I use fvwm2(nvidia X driver) as -a window manager which does not work with the 9i install program, works -fine with the default Gnomish(nv X driver), it could have been the X -driver too. - -With Redhat9 it is REAL important to set LD_ASSUME_KERNEL to 2.4.1. - -I didn't try this but it may be possible to install what is needed by -only downloading the first disk saving some 1.3GB of download fun. - -I installed a custom install from the client group. The packages I -installed are the Programmers section and sqlplus. I noticed that the -Pro*C when on as a result of the checking the Programmers section I -assume. - -Once Oracle was installed properly the DBD::Oracle install went as -smooth as just about every other CPAN module. - -=head2 Oracle 10g Instantclient - -The Makefile.PL will now work for Oracle 10g Instantclient. To have both the Compile and -the test.pl to work you must first have the LD_LIBRARY_PATH correctly set to your -"instantclient" directory. (http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html) - -The present version of the make creates a link on your "instantclient" directory as follows -"ln -s libclntsh.so.10.1 libclntsh.so". It is needed for both the makefile creation and the compile -but is not need for the test.pl. It should be removed after the compile. - -If the Makefile.PL or make fails try creating this link directly in your "instantclient" directory. - -=head2 Oracle Database 10g Express Edition 10.2 - -To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY_PATH -as you would for an install against 10g Standard Edition, Standard Edition One, or -Enterprise Edition - -=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 - -DBD::Oracle seems to hit some sort of bug with the above two versions of DB. -The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also -been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. - -So far there is no patch for this but here are some work arounds - - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); - ... - $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); - - or this way - - $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders - - or this way - - utf8::downgrade($parameter, 1); - -=head1 CYGWIN - -Makefile.PL should find and make use of OCI include -files, but you have to build an import library for -OCI.DLL and put it somewhere in library search path. -one of the possible ways to do this is issuing command - - dlltool --input-def oci.def --output-lib liboci.a - -in the directory where you unpacked DBD::Oracle distribution -archive. this will create import library for Oracle 8.0.4. - -Note: make clean removes '*.a' files, so put a copy in a safe place. - -=head2 Compiling DBD::Oracle using the Oracle Instant Client, Cygwin Perl and gcc - -=over - -=item 1 - -Download these two packages from Oracle's Instant Client for -Windows site -(http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/winsoft.html): - -Instant Client Package - Basic: All files required to run OCI, -OCCI, and JDBC-OCI applications - -Instant Client Package - SDK: Additional header files and an -example makefile for developing Oracle applications with Instant Client - -(I usually just use the latest version of the client) - -=item 2 - -Unpack both into C:\oracle\instantclient_11_1 - -=item 3 - -Download and unpack DBD::Oracle from CPAN to some place with no -spaces in the path (I used /tmp/DBD-Oracle) and cd to it. - -=item 4 - -Set up some environment variables (it didn't work until I got the -DSN right): - - ORACLE_DSN=DBI:Oracle:host=oraclehost;sid=oracledb1 - ORACLE_USERID=username/password - -=item 5 - - perl Makefile.PL - make - make test - make install - -=back - -Note, the TNS Names stuff doesn't always seem to work with the instant -client so Perl scripts need to explicitly use host/sid in the DSN, like -this: - - my $dbh = DBI->connect('dbi:Oracle:host=oraclehost;sid=oracledb1', - 'username', 'password'); - -=head2 SUN - -If you get this on a Solaris 9 and 10 box - - "Outofmemory! - Callback called exit. - END failed--call queue aborted." - -The solution may be as simple as not having you "ORACLE_HOME" Defined in the -environment. - -It seems that having it defined will prevent the error. - -=head2 VMS - -This is related to Oracle RDBMS 9.2 and later, since Oracle -made fundamental changes to oracle installation requirements -and factual installation with this release. - -Oracle's goal was to make VMS installation be more like on -*nix and Windows, with an all new Oracle Home structure too, -requiring an ODS-5 disk to install Oracle Home on instead of -the good old ODS-2. - -Another major change is the introduction of an Oracle generated -logical name table for oracle logical names like ORA_ROOT and all -its derivatives like ORA_PROGINT etc. And that this logical name -table is inserted in LNM$FILE_DEV in LNM$PROCESS_DIRECTORY. - - (LNM$PROCESS_DIRECTORY) - - "LNM$FILE_DEV" = "SERVER_810111112" - = "LNM$PROCESS" - = "LNM$JOB" - = "LNM$GROUP" - = "LNM$SYSTEM" - = "DECW$LOGICAL_NAMES" - -This ensures that any process that needs to have access to -oracle gets the environment by just adding one logical name table -to a central process specific mechanism. - -But as it is inserted at the very top of LNM$FILE_DEV it also -represents a source of misfortune - especially if a user with -enough privilege to update the oracle table does so (presumably -unintentionally), as an examble by changing NLS_LANG. - -PERL has the abillity to define, redefine and undefine (deassign) -logical names, but if not told otherwise by the user does it -in the first table in above list, and not as one would normally -expect in the process table. - -Installing DBI and DBD::Oracle has influence upon this since in -both cases a few environment variables are read or set in the -test phase. -For DBI it is the logical SYS$SCRATCH, which is a JOB logical. -For DBD-Oracle it is when testing a new feature in the Oracle -RDBMS: UTF8 and UTF16 character set functionality, and in order -to do this it sets and unsets the related environment variables -NLS_NCHAR and NLS_LANG. - -If one is not careful this changes the values set in the oracle -table - and in the worst case stays active until the next major -system reset. It can also be a very hard error to track down -since it happens in a place where one normally never looks. - -Furthermore, it is very possibly that some or all of the UTF tests -fails, since if one have a variable like NLS_LANG in his process -table, then even though 'mms test' sets it in the wrong table -it is not invoked as it is overruled by the process logical... - -The way to ensure that no logicals are set in the oracle table and -that the UTF tests get the best environment to test in, and that -DBI correctly translates the SYS$SCRATCH logical, use the -logical - - PERL_ENV_TABLES - -to ensure that PERL's behavior is to leave the oracle table alone and -use the process table instead: - - $ DEFINE PERL_ENV_TABLES LNM$PROCESS, LNM$JOB - -This tells PERL to use the LNM$PROCESS table as the default place to -set and unset variables so that only the perl users environment -is affected when installing DBD::Oracle, and ensures that the -LNM$JOB table is read when SYS$SCRATCH is to be translated. - -PERL_ENV_TABLES is well documented in the PERLVMS man page. - -Oracle8 releases are not affected, as they don't have the -oracle table implementation, and no UTF support. - -Oracle 9.0 is uncertain, since testing has not been possible yet, -but the remedy will not hurt :) - -=head1 Miscellaneous - -=head2 Crash with an open connection and Module::Runtime in mod_perl2 - -See RT 72989 (https://rt.cpan.org/Ticket/Display.html?id=72989) - -Apache2 MPM Prefork with mod_perl2 will crash if Module::Runtime is -loaded, and an Oracle connection is opened through PerlRequire (before -forking). - -It looks like this was fixed in 0.012 of Module::Runtime. - -=head2 bin_param_inout swapping return values - -See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) - -It seems that in some older versions of Oracle Instant Client -(certainly 10.2.0.4.0) when output parameters are bound with lengths -greater than 3584 the output parameters can be returned in the wrong -placeholders. - -It is reported fixed in Instant Client 11.2.0.2.0. - -=head1 AUTHORS - -=over 4 - -=item * - -Tim Bunce - -=item * - -John Scoles - -=item * - -Yanick Champoux - -=item * - -Martin J. Evans - -=back - -=head1 COPYRIGHT AND LICENSE - -This software is copyright (c) 1994 by Tim Bunce. - -This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. - -=cut - diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod new file mode 100644 index 00000000..7b4e6cd3 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -0,0 +1,167 @@ +#PODNAME: DBD::Oracle::Troubleshooting +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle + +=head1 VERSION + +version 1.47_00 + +=head1 CONNECTING TO ORACLE + +If you are reading this it is assumed that you have successfully +installed DBD::Oracle and you are having some problems connecting to +Oracle. + +First off you will have to tell DBD::Oracle where the binaries reside +for the Oracle client it was compiled against. This is the case when +you encounter a + + DBI connect('','system',...) failed: ERROR OCIEnvNlsCreate. + +error in Linux or in Windows when you get + + OCI.DLL not found + +The solution to this problem in the case of Linux is to ensure your +'ORACLE_HOME' (or LD_LIBRARY_PATH for InstantClient) environment +variable points to the correct directory. + + export ORACLE_HOME=/app/oracle/product/xx.x.x + +For Windows the solution is to add this value to you PATH + + PATH=c:\app\oracle\product\xx.x.x;%PATH% + +If you get past this stage and get a + + ORA-12154: TNS:could not resolve the connect identifier specified + +error then the most likely cause is DBD::ORACLE cannot find your .ORA +(F, F, F) files. This can be +solved by setting the TNS_ADMIN environment variable to the directory +where these files can be found. + +If you get to this stage and you have either one of the following +errors; + + ORA-12560: TNS:protocol adapter error + ORA-12162: TNS:net service name is incorrectly specified + +usually means that DBD::Oracle can find the listener but the it cannot connect to the DB because the listener cannot find the DB you asked for. + +=head2 Oracle utilities + +If you are still having problems connecting then the Oracle adapters +utility may offer some help. Run these two commands: + + $ORACLE_HOME/bin/adapters + $ORACLE_HOME/bin/adapters $ORACLE_HOME/bin/sqlplus + +and check the output. The "Protocol Adapters" should include at least "IPC Protocol Adapter" and "TCP/IP +Protocol Adapter". + +If it generates any errors which look relevant then please talk to your +Oracle technical support (and not the dbi-users mailing list). + +=head2 Connecting using a bequeather + +If you are using a bequeather to connect to a server +on the same host as the client, you might have +to add + + bequeath_detach = yes + +to your sqlnet.ora file or you won't be able to safely use fork/system +functions in Perl. + +See the discussion at +L +and L +for more gory details. + +=head1 USING THE LONG TYPES + +Some examples related to the use of LONG types are available in +the C directory of the distribution. + +=head1 Can't find I + +I is the shared +library composed of all the other Oracle libs you used to have to +statically link. +libclntsh.so should be in I<$ORACLE_HOME/lib>. If it's missing, try +running I<$ORACLE_HOME/lib/genclntsh.sh> and it should create it. + +Never copy I to a different machine or Oracle version. +If DBD::Oracle was built on a machine with a different path to I +then you'll need to set set an environment variable, typically +I, to include the directory containing I. + +I is typically ignored if the script is running set-uid +(which is common in some httpd/CGI configurations). In this case +either rebuild with I set to include the path to I +or create a symbolic link so that I is available via the same +path as it was when the module was built. (On Solaris the command +"ldd -s Oracle.so" can be used to see how the linker is searching for it.) + +=head1 Miscellaneous + +=head2 Crash with an open connection and Module::Runtime in mod_perl2 + +See RT 72989 (https://rt.cpan.org/Ticket/Display.html?id=72989) + +Apache2 MPM Prefork with mod_perl2 will crash if Module::Runtime is +loaded, and an Oracle connection is opened through PerlRequire (before +forking). + +It looks like this was fixed in 0.012 of Module::Runtime. + +=head2 bin_param_inout swapping return values + +See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) + +It seems that in some older versions of Oracle Instant Client +(certainly 10.2.0.4.0) when output parameters are bound with lengths +greater than 3584 the output parameters can be returned in the wrong +placeholders. + +It is reported fixed in Instant Client 11.2.0.2.0. + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod new file mode 100644 index 00000000..55f35d6c --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -0,0 +1,290 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Aix +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on AIX + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle on AIX + +=head1 VERSION + +version 1.47_00 + +=head1 Using Visual Age 7 C Compiler + +Oracle 9i is only certified as a 64-bit application on AIX 5L (5.1,5.2,5.3) with 32-bit support; +in other words, there is no 9i "32-bit" Oracle client + +Oracle 10g is certified as both a 64-bit application and a 32-bit Oracle client + +This information only pertains to deploying: + + the DBI (version 1.48) + and DBD-Oracle (version 1.16): + on AIX 5.3 + using Oracle 9i (9.2.0.1/9.2.0.5) + using the existing Perl 5.8.2 (no custom-built Perl) which is 32-bit + using Visual Age 7.0 C/C++ compiler + +Install the DBI (required for the DBD-Oracle install - no issues here) +Untar the DBD-Oracle bundle +Run Makefile.PL + + $ perl Makefile.PL + +Edit Makefile with following commands: + + 1,$s?/lib/ ?/lib32/ ?g + 1,$s?-q64??g + 1,$s?/lib/sysliblist?/lib32/sysliblist?g + +Now perform normal commands to perform the testing/making: + + $ make + $ make test + $ make install + +I've tested the basics of the DBD-Oracle and it seems fully functional. + +Stephen de Vries + +=head1 Using gcc C Compiler + + DBD::Oracle with gcc and Oracle Instant Client on AIX + -------------------------------------------------------------------------------------- + Nathan Vonnahme Dec 15 2005, 4:28 pm Newsgroups: perl.dbi.users + See: http://groups.google.com/group/perl.dbi.users/msg/0bd9097f80f2c8a9 + [ with updates 1/31/2006 - DBD::Oracle 1.17 doesn't need makefile hacking + to work with instantclient on AIX ] + + + Yes! It eluded me last year but I finally got DBD::Oracle working on an + AIX machine using gcc. Here's the short version: + + First I had to recompile perl with gcc, using + sh Configure -de -Dcc=gcc + This apparently built a 32 bit perl, someday I will try getting it to go + 64 bit. + + I was then able to install and build DBI 1.50 with the CPAN shell. + + I downloaded the base and sdk packages of the Oracle Instant Client for + AIX -- first I tried the 64 bit but that didn't work with my 32 bit perl + -- the 32 bit version (still at 10.1.0.3) did the trick. I unzipped + them and moved the dir to /usr/local/oracle/instantclient10_1 and made a + symlink without the version at /usr/local/oracle/instantclient , then + set: + + export ORACLE_HOME=/usr/local/oracle/instantclient + export LIBPATH=$ORACLE_HOME + + + + Oracle wasn't providing the sqlplus package for 32 bit AIX so I + explicitly told Makefile.PL the version: + + perl Makefile.PL -V 10.1 + + make + + My test databases were on other machines so I set these environment variables + to get the tests to run: + + export ORACLE_DSN=DBI:Oracle://host/dbinstance + export ORACLE_USERID="user/password" + + make test + make install + + + NOTE: I have an older full version of Oracle on this machine, and the + ORACLE_HOME environment variable is normally set to point to that, so + my perl scripts that use DBD::Oracle have to make sure to first set + $ENV{ORACLE_HOME}='/usr/local/oracle/instantclient'; + + + + + + -------------------------------------------------------------------------------------- + The following setup worked to build on AIX 5.2: + gcc-3.3.2 (32-bit) (configure opts [ --with-ld=/usr/ccs/bin/ld --with-as=/usr/ccs/bin/as]) + Oracle-9.2.0 ( full install w/32bit support) + perl-5.8.3 (built with above gcc/latest stable as of March 2004) + Followed the directions from Rafael's email below, only set ORACLE_HOME, (and + the appropriate test environmentals). + 1) build perl-5.8.3 with gcc + 2) install DBI + 3) ORACLE_HOME="your oracle home" + ORACLE_USERID.. + ORACLE_SID .. + (I ignored ORACCENV, didn't use it.) + 4) install DBD::Oracle, after perl Makefile.PL, edit the created Makefile, + changing references to Oracle's ../lib to ../lib32. and change crt0_64.o to + crt0_r.o. Remove the -q32 and/or -q64 options from the list of libraries to + link with. + 5) make should be clean, make test should pass. + This setup worked with 8.1.7 w/32 bit support, and with 9.2.0 w/ 32-bit support. + --Adrian Terranova + +=head1 Using xlc_r C Compiler + + From: Rafael Caceres + Date: 22 Jul 2003 10:05:20 -0500 + + The following sequence worked for me on AIX 5.1: + + -use Perl 5.8.0 (the latest stable from CPAN) + + -use the xlc_r version of IBM's compiler and build a 32 bit Perl + (which xlc_r will do by default). All tests should be successful. + + -get and install DBI + + -get DBD::Oracle. Edit the Makefile.PL or Makefile for DBD::Oracle, + changing references to Oracle's ../lib to ../lib32. and change crt0_64.o + to crt0_r.o. Remove the -q32 and/or -q64 options from the list of + libraries to link with. Do the make and make test. + + -Set up the environment for making DBD::Oracle: + ORACLE_HOME="your oracle home" + ORACCENV = "xlc_r" + ORACLE_USERID.. + ORACLE_SID .. + + -Run make, all tests should be successfull -against Oracle 9.x at least. + + You should have no problems with Oracle 8.1.7, but accessing Oracle 7.x + or previous is not possible (you'll core dump, or simply hang). The same + goes for a Linux build or a Digital build, regarding access of different + Oracle versions. + + Rafael Caceres + + > I dont believe I compiled Oracle. During the installation it was linked + > but I am not sure it was compiled + > + > I used a xlc compiler to compile PERL. + > Got this message in the Perl Makefile.PL output + > + > Warning: You will may need to rebuild perl using the xlc_r compiler. + > You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV + > Also see the README about the -p option + > + > this probobly means I need to rebuild PERL with xlc_r?? + > + > thanx + > + > Mike Paladino + > Database Administrator + + + From: Rafael Caceres + > + > Make sure you use the same compiler to build Oracle and Perl. We have + > used xlc_r on Aix 5.1 with no problems. Your Perl build is 32 bit, so + > when building DBD::Oracle, you should use the 32bit libraries (change + > references to .../oracle/lib to .../oracle/lib32 in your Makefile). + > Remove the references to the -q64 or -q32 parameters for ld in Makefile, + > as they shouldn't be there. + > + > Rafael Caceres + + + From: "cartman ltd" + Subject: Tip for DBI and DBD::Oracle on AIX 5.1 and Oracle 9.2 + Date: Mon, 11 Aug 2003 18:15:38 +0000 + Message-ID: + + Here is a tip for compiling DBD::Oracle as a 32 bit application on AIX 5.1 + 64 bit and Oracle 9.2 64 bit without editting any makefiles. I hope people + find this useful: + + First, the versions of products I used: + DBI version 1.32 + DBD::Oracle version 1.14 + Oracle 9.2.0.2 - default 64 bit application with 32 bit libraries + AIX 5.1 ML03 - 64 bit kernel - ships with Perl as a 32 bit application. + VisualAge C/C++ 5.0.2 + + Basically DBD must be compiled as 32 bit to link with Perl's 32 bit + libraries. + gunzip -c DBD-Oracle-1.14.tar.gz | tar xvf  + cd DBD-Oracle-1.14 + perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk + make + + NB: I think there is a bug in the Oracle 9.2.0.3 file + $ORACLE_HOME/rdbms/lib/env_rdbms.mk + I corrected this (before running the above commands) by replacing the + invalid linker option + LDFLAGS32=-q32 + with + LDFLAGS32=-b32 + + Have fun: KC. + -------------------------------------------------------------------------------------- + + Date: Wed, 30 Jun 2004 23:34:24 -0500 + From: "SCHULTZ, DARYLE (SBCSI)" + + Got it to work. Using dbd 1.16 + + Perl 5.8.4 built like this, with Visual Age 6.0: + + config_args='-Dcc=xlc_r -Dusenm -Dprefix=/appl/datasync/work/perl5 + -Dusethreads -Duse64bitall -des' + ============================================== + + Used DBI 1.42 + ============================================= + Added this to top of Oracle.h: + #define A_OSF + + #include + ======================= + Set LIBPATH to point to 64bit Oracle libs first. + export LIBPATH=$ORACLE_HOME/lib:$ORACLE_HOME/lib32:/usr/lib + + Use: perl Makefile.PL -nob + + Change all references in Makefile of LD_RUN_PATH to be LIBPATH. + Change nothing else, left all flags in Makefile, including -q64. + Passed make, and all tests. + + -------------------------------------------------------------------------------------- + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod new file mode 100644 index 00000000..c98b5bdd --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -0,0 +1,111 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Cygwin +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Cygwin + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracle on Cygwin + +=head1 VERSION + +version 1.47_00 + +=head1 General Info + +Makefile.PL should find and make use of OCI include +files, but you have to build an import library for +OCI.DLL and put it somewhere in library search path. +one of the possible ways to do this is issuing command + + dlltool --input-def oci.def --output-lib liboci.a + +in the directory where you unpacked DBD::Oracle distribution +archive. this will create import library for Oracle 8.0.4. + +Note: make clean removes '*.a' files, so put a copy in a safe place. + +=head1 Compiling DBD::Oracle using the Oracle Instant Client, Cygwin Perl and gcc + +=over + +=item 1 + +Download these two packages from Oracle's Instant Client for +Windows site +(http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/winsoft.html): + +Instant Client Package - Basic: All files required to run OCI, +OCCI, and JDBC-OCI applications + +Instant Client Package - SDK: Additional header files and an +example makefile for developing Oracle applications with Instant Client + +(I usually just use the latest version of the client) + +=item 2 + +Unpack both into C:\oracle\instantclient_11_1 + +=item 3 + +Download and unpack DBD::Oracle from CPAN to some place with no +spaces in the path (I used /tmp/DBD-Oracle) and cd to it. + +=item 4 + +Set up some environment variables (it didn't work until I got the +DSN right): + + ORACLE_DSN=DBI:Oracle:host=oraclehost;sid=oracledb1 + ORACLE_USERID=username/password + +=item 5 + + perl Makefile.PL + make + make test + make install + +=back + +Note, the TNS Names stuff doesn't always seem to work with the instant +client so Perl scripts need to explicitly use host/sid in the DSN, like +this: + + my $dbh = DBI->connect('dbi:Oracle:host=oraclehost;sid=oracledb1', + 'username', 'password'); + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/README.hpux.txt b/lib/DBD/Oracle/Troubleshooting/Hpux.pm similarity index 97% rename from README.hpux.txt rename to lib/DBD/Oracle/Troubleshooting/Hpux.pm index 0c483d00..3b7f3114 100644 --- a/README.hpux.txt +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pm @@ -1,3 +1,18 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Hpux +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on HP-UX + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle on HP-UX + +=head1 VERSION + +version 1.47_00 + =head1 INTRODUCTION Building a working dynamically linked version of the Oracle DBD driver @@ -23,7 +38,7 @@ See L for exact build configurations used by me an others. For HPUX 11 on Itanium see also http://www.nntp.perl.org/group/perl.dbi.users/23840 -=head1 First things First: Introduction +=head1 First things First: Introduction The reason you are even reading this file is because you want to connect to an Oracle database from your perl program using the DBD::Oracle DBI @@ -59,8 +74,7 @@ this file. -- Lincoln - -=head1 Build your own Perl +=head1 Build your own Perl HP's default Perl is no good (and antique). @@ -330,9 +344,9 @@ If you have trouble, see the L instructions below, for hints of what might be wrong... and send me a note, describing your configuration, and what you did to fix it. -=head1 Trouble Shooting +=head1 Trouble Shooting -=head2 "Unresolved symbol" +=head2 "Unresolved symbol" In general, find the symbols, edit the Makefile, and make test. @@ -413,7 +427,7 @@ You can edit the Makefile in 2 ways: Perform a make test, if symbols are still unresolved repeat the editing of the Makefile and make test again. -=head1 DBD-Oracle-1.06 +=head1 DBD-Oracle-1.06 You are strongly urged to upgrade. However here is what you may need to know to get it or work, if you insist on using an earlier version. @@ -955,14 +969,14 @@ To work around this problem, complete the following procedure: $ORACLE_HOME/rdbms/admin/shrept.lst =itme 3 Add the following line: - + rdbms:OCILobLocatorAssign =item 4 (optional) Add the names of any other missing functions needed by applications, other than WebLogic Server 7.0, that you want to execute. Note: The OCILobLocatorAssign function is not the only missing function that WebLogic Server 7.0 should be able to call, but it is the only missing function that WebLogic Server 7.0 requires. Other functions that WebLogic Server should be able to call, such as OCIEnvCreate and OCIerminate, are also missing. If these functions are required by other applications that you plan to run, you must add them to your environment by specifying them, too, in $ORACLE_HOME/rdbms/admin/shrept.lst. =item 5 Rebuild the shared client library: - + $ cd $ORACLE_HOME/rdbms/lib $ make -f ins_rdbms.mk client_sharedlib @@ -980,4 +994,34 @@ Because OCILobLocatorAssign is now visible in libclntsh.so, WebLogic Server can =back +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod new file mode 100644 index 00000000..7964170e --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -0,0 +1,149 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Linux +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Linux + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle on Linux + +=head1 VERSION + +version 1.47_00 + +=head1 Installing with Instantclient .rpm files. + +Nothing special with this you just have to set up you permissions as follows; + +1) Have permission for RWE on '/usr/lib/oracle/10.2.0.3/client/' or the other directory where you RPMed to + +2) Set export ORACLE_HOME=/usr/lib/oracle/10.2.0.3/client + +3) Set export LD_LIBRARY_PATH=$ORACLE_HOME/lib + +4) If you plan to use tnsnames to connect to remote servers and your tnsnames.ora file is not in $ORACLE_HOME/network/admin, you will need to Export TNS_ADMIN=dir to point DBD::Oracle to where your tnsnames.ora file is + +=head1 undefined symbol: __cmpdi2 comes up when Oracle isn't properly linked to the libgcc.a library. + +In version 8, this was correctd by changing the SYSLIBS entry in +$ORACLE_HOME/bin/genclntsh to include +"-L/usr/lib/gcc-lib/i386-redhat-linux/3.2 -lgcc". + +I had tried this with no success as when this program was then run, the +error "unable to find libgcc" was generated. Of course, this was the +library I was trying to describe! + +It turns out that now it is necessary to edit the same file and append +"`gcc -print-libgcc-file-name`" (including the backquotes!). If you do +this and then run "genclntsh", the libclntsh is properly generated and +the linkage with DBD::Oracle proceeds properly. + +=head1 cc1: invalid option `tune=pentium4'" error + +If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. + +No real problem with the above however you will have to + +1) run Perl Makefile.PL + +2) edit the Makefile and remove the offending '-mtune=pentium4' text + +3) save and exit + +4) do the make install and it should work fine for you + +=head1 Oracle 9i Lite + +The advice is to use the regular Oracle9i not the lite version. + +Another great source of help was: http://www.puschitz.com/InstallingOracle9i.html + +just getting 9i and 9i lite installed. I use fvwm2(nvidia X driver) as +a window manager which does not work with the 9i install program, works +fine with the default Gnomish(nv X driver), it could have been the X +driver too. + +With Redhat9 it is REAL important to set LD_ASSUME_KERNEL to 2.4.1. + +I didn't try this but it may be possible to install what is needed by +only downloading the first disk saving some 1.3GB of download fun. + +I installed a custom install from the client group. The packages I +installed are the Programmers section and sqlplus. I noticed that the +Pro*C when on as a result of the checking the Programmers section I +assume. + +Once Oracle was installed properly the DBD::Oracle install went as +smooth as just about every other CPAN module. + +=head1 Oracle 10g Instantclient + +The Makefile.PL will now work for Oracle 10g Instantclient. To have both the Compile and +the test.pl to work you must first have the LD_LIBRARY_PATH correctly set to your +"instantclient" directory. (http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html) + +The present version of the make creates a link on your "instantclient" directory as follows +"ln -s libclntsh.so.10.1 libclntsh.so". It is needed for both the makefile creation and the compile +but is not need for the test.pl. It should be removed after the compile. + +If the Makefile.PL or make fails try creating this link directly in your "instantclient" directory. + +=head1 Oracle Database 10g Express Edition 10.2 + +To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY_PATH +as you would for an install against 10g Standard Edition, Standard Edition One, or +Enterprise Edition + +=head1 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 + +DBD::Oracle seems to hit some sort of bug with the above two versions of DB. +The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also +been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. + +So far there is no patch for this but here are some work arounds + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or this way + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + or this way + + utf8::downgrade($parameter, 1); + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/README.macosx.txt b/lib/DBD/Oracle/Troubleshooting/Macos.pod similarity index 76% rename from README.macosx.txt rename to lib/DBD/Oracle/Troubleshooting/Macos.pod index 57801dad..1b56c48c 100644 --- a/README.macosx.txt +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -1,3 +1,20 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Macos +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on MacOs + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle on MacOs + +=head1 VERSION + +version 1.47_00 + +=head1 General Info + These instructions allow for the compilation and successful testing of DBD::Oracle on MacOS X 10.2.4 and higher, using Oracle 9iR2 DR (Release 9.2.0.1.0) or the 10g Instant Client release (10.1.0.3 at the @@ -47,8 +64,7 @@ if you are on 10.3 (Panther) and you do not intend to run the Oracle database server on your MacOSX box. See below (Instructions for 10.3.x) for details. -====================================================================== -Instructions for 10.7.x (Lion) +=head1 Instructions for 10.7.x (Lion) Because the 64 bit instantclient (version 10gr2)is currently [incompatible with Lion][], DBD::Oracle can only be compiled with the @@ -62,9 +78,9 @@ is released. If you have a 32-bit Perl, however, then the following steps should work: * Download and install the 32-bit basic, sqlplus, and sdk instantclient - libraries and install them in a central location, such as - `/usr/oracle_instantclient`. [Downloads here][]. - +libraries and install them in a central location, such as +`/usr/oracle_instantclient`. [Downloads here][]. + [Downloads here]: http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html * Create a symlink from `libclntsh.dylib.10.1` to `libclntsh.dylib`: @@ -81,8 +97,7 @@ If you have a 32-bit Perl, however, then the following steps should work: cpan DBD::Oracle -====================================================================== -Instructions for 10.6.x (Snow Leopard) +=head1 Instructions for 10.6.x (Snow Leopard) These are taken from a stackoverflow answer by "nickisfat" who gave his/her permission for its inclusion here. You can see the original @@ -170,9 +185,7 @@ install DBI Now you're all set - enjoy your perly oracley new life - -====================================================================== -Instructions for 10.2.x (Jaguar) +=head1 Instructions for 10.2.x (Jaguar) 1) Install Oracle exactly per Oracle documentation. If you change install locations, then you'll need to modify paths accordingly. @@ -227,102 +240,102 @@ follow nonetheless. compile with Perl 5.6.0; they may not be necessary with other versions of IO and Perl, respectively. -+=+=+=+=+=+=+= Cut after this line -diff -c ../IO-orig/IO-1.20/IO.xs ./IO.xs -*** ../IO-orig/IO-1.20/IO.xs Mon Jul 13 23:36:24 1998 ---- ./IO.xs Sat May 10 15:20:02 2003 -*************** -*** 205,211 **** - ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); - } - else { -! ST(0) = &sv_undef; - errno = EINVAL; - } - ---- 205,211 ---- - ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); - } - else { -! ST(0) = &PL_sv_undef; - errno = EINVAL; - } - -*************** -*** 249,255 **** - SvREFCNT_dec(gv); /* undo increment in newRV() */ - } - else { -! ST(0) = &sv_undef; - SvREFCNT_dec(gv); - } - ---- 249,255 ---- - SvREFCNT_dec(gv); /* undo increment in newRV() */ - } - else { -! ST(0) = &PL_sv_undef; - SvREFCNT_dec(gv); - } - -*************** -*** 272,278 **** - i++; - fds[j].revents = 0; - } -! if((ret = poll(fds,nfd,timeout)) >= 0) { - for(i=1, j=0 ; j < nfd ; j++) { - sv_setiv(ST(i), fds[j].fd); i++; - sv_setiv(ST(i), fds[j].revents); i++; ---- 272,278 ---- - i++; - fds[j].revents = 0; - } -! if((ret = io_poll(fds,nfd,timeout)) >= 0) { - for(i=1, j=0 ; j < nfd ; j++) { - sv_setiv(ST(i), fds[j].fd); i++; - sv_setiv(ST(i), fds[j].revents); i++; -diff -c ../IO-orig/IO-1.20/poll.c ./poll.c -*** ../IO-orig/IO-1.20/poll.c Wed Mar 18 21:34:00 1998 ---- ./poll.c Sat May 10 14:28:22 2003 -*************** -*** 35,41 **** - # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) - - int -! poll(fds, nfds, timeout) - struct pollfd *fds; - unsigned long nfds; - int timeout; ---- 35,41 ---- - # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) - - int -! io_poll(fds, nfds, timeout) - struct pollfd *fds; - unsigned long nfds; - int timeout; -diff -c ../IO-orig/IO-1.20/poll.h ./poll.h -*** ../IO-orig/IO-1.20/poll.h Wed Apr 15 20:33:02 1998 ---- ./poll.h Sat May 10 14:29:11 2003 -*************** -*** 44,50 **** - #define POLLHUP 0x0010 - #define POLLNVAL 0x0020 - -! int poll _((struct pollfd *, unsigned long, int)); - - #ifndef HAS_POLL - # define HAS_POLL ---- 44,50 ---- - #define POLLHUP 0x0010 - #define POLLNVAL 0x0020 - -! int io_poll _((struct pollfd *, unsigned long, int)); - - #ifndef HAS_POLL - # define HAS_POLL -+=+=+=+=+=+=+= Cut to the previous line + +=+=+=+=+=+=+= Cut after this line + diff -c ../IO-orig/IO-1.20/IO.xs ./IO.xs + *** ../IO-orig/IO-1.20/IO.xs Mon Jul 13 23:36:24 1998 + --- ./IO.xs Sat May 10 15:20:02 2003 + *************** + *** 205,211 **** + ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); + } + else { + ! ST(0) = &sv_undef; + errno = EINVAL; + } + + --- 205,211 ---- + ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); + } + else { + ! ST(0) = &PL_sv_undef; + errno = EINVAL; + } + + *************** + *** 249,255 **** + SvREFCNT_dec(gv); /* undo increment in newRV() */ + } + else { + ! ST(0) = &sv_undef; + SvREFCNT_dec(gv); + } + + --- 249,255 ---- + SvREFCNT_dec(gv); /* undo increment in newRV() */ + } + else { + ! ST(0) = &PL_sv_undef; + SvREFCNT_dec(gv); + } + + *************** + *** 272,278 **** + i++; + fds[j].revents = 0; + } + ! if((ret = poll(fds,nfd,timeout)) >= 0) { + for(i=1, j=0 ; j < nfd ; j++) { + sv_setiv(ST(i), fds[j].fd); i++; + sv_setiv(ST(i), fds[j].revents); i++; + --- 272,278 ---- + i++; + fds[j].revents = 0; + } + ! if((ret = io_poll(fds,nfd,timeout)) >= 0) { + for(i=1, j=0 ; j < nfd ; j++) { + sv_setiv(ST(i), fds[j].fd); i++; + sv_setiv(ST(i), fds[j].revents); i++; + diff -c ../IO-orig/IO-1.20/poll.c ./poll.c + *** ../IO-orig/IO-1.20/poll.c Wed Mar 18 21:34:00 1998 + --- ./poll.c Sat May 10 14:28:22 2003 + *************** + *** 35,41 **** + # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) + + int + ! poll(fds, nfds, timeout) + struct pollfd *fds; + unsigned long nfds; + int timeout; + --- 35,41 ---- + # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) + + int + ! io_poll(fds, nfds, timeout) + struct pollfd *fds; + unsigned long nfds; + int timeout; + diff -c ../IO-orig/IO-1.20/poll.h ./poll.h + *** ../IO-orig/IO-1.20/poll.h Wed Apr 15 20:33:02 1998 + --- ./poll.h Sat May 10 14:29:11 2003 + *************** + *** 44,50 **** + #define POLLHUP 0x0010 + #define POLLNVAL 0x0020 + + ! int poll _((struct pollfd *, unsigned long, int)); + + #ifndef HAS_POLL + # define HAS_POLL + --- 44,50 ---- + #define POLLHUP 0x0010 + #define POLLNVAL 0x0020 + + ! int io_poll _((struct pollfd *, unsigned long, int)); + + #ifndef HAS_POLL + # define HAS_POLL + +=+=+=+=+=+=+= Cut to the previous line - compile and install as you usually would, making sure that existing but conflicting modules get removed: @@ -344,8 +357,7 @@ diff -c ../IO-orig/IO-1.20/poll.h ./poll.h $ make test $ make install -====================================================================== -Instructions for 10.3.x (Panther) +=head1 Instructions for 10.3.x (Panther) I highly recommend you install and use the Oracle 10g Instant Client for MacOSX 10.3. Compared to traditional Oracle client installations @@ -389,34 +401,34 @@ That said, here are the details. Here is the patch: -+=+=+=+=+=+=+= Cut after this line -*** Makefile.PL.orig Fri Oct 22 02:07:04 2004 ---- Makefile.PL Fri May 13 14:28:53 2005 -*************** -*** 1252,1257 **** ---- 1252,1258 ---- - print "Found $dir/$_\n" if $::opt_d; - }, "$OH/rdbms", - "$OH/plsql", # oratypes.h sometimes here (eg HPUX 11.23 Itanium Oracle 9.2.0) -+ "$OH/sdk", # Oracle Instant Client default location (10g) - ); - @h_dir = keys %h_dir; - print "Found header files in @h_dir.\n" if @h_dir; -*************** -*** 1286,1292 **** ---- 1287,1297 ---- - open FH, ">define.sql" or warn "Can't create define.sql: $!"; - print FH "DEFINE _SQLPLUS_RELEASE\nQUIT\n"; - close FH; -+ # we need to temporarily disable login sql scripts -+ my $sqlpath = $ENV{SQLPATH}; -+ delete $ENV{SQLPATH}; - my $sqlplus_release = `$sqlplus_exe -S /nolog \@define.sql 2>&1`; -+ $ENV{SQLPATH} = $sqlpath if $sqlpath; - unlink "define.sql"; - print $sqlplus_release; - if ($sqlplus_release =~ /^DEFINE _SQLPLUS_RELEASE = "(\d?\d)(\d\d)(\d\d)(\d\d)(\d\d)"/) { -+=+=+=+=+=+=+= Cut to the previous line + +=+=+=+=+=+=+= Cut after this line + *** Makefile.PL.orig Fri Oct 22 02:07:04 2004 + --- Makefile.PL Fri May 13 14:28:53 2005 + *************** + *** 1252,1257 **** + --- 1252,1258 ---- + print "Found $dir/$_\n" if $::opt_d; + }, "$OH/rdbms", + "$OH/plsql", # oratypes.h sometimes here (eg HPUX 11.23 Itanium Oracle 9.2.0) + + "$OH/sdk", # Oracle Instant Client default location (10g) + ); + @h_dir = keys %h_dir; + print "Found header files in @h_dir.\n" if @h_dir; + *************** + *** 1286,1292 **** + --- 1287,1297 ---- + open FH, ">define.sql" or warn "Can't create define.sql: $!"; + print FH "DEFINE _SQLPLUS_RELEASE\nQUIT\n"; + close FH; + + # we need to temporarily disable login sql scripts + + my $sqlpath = $ENV{SQLPATH}; + + delete $ENV{SQLPATH}; + my $sqlplus_release = `$sqlplus_exe -S /nolog \@define.sql 2>&1`; + + $ENV{SQLPATH} = $sqlpath if $sqlpath; + unlink "define.sql"; + print $sqlplus_release; + if ($sqlplus_release =~ /^DEFINE _SQLPLUS_RELEASE = "(\d?\d)(\d\d)(\d\d)(\d\d)(\d\d)"/) { + +=+=+=+=+=+=+= Cut to the previous line The first hunk allows Makefile.PL to find the header files which are in a subdirectory sdk, and the second temporarily disables any @@ -499,16 +511,13 @@ instructions, and the Perl IO patch is credit to Hilmar Lapp, hlapp at gmx.net. Earlier and original instructions thanks to: - Andy Lester - Steve Sapovits - Tom Mornini - + Andy Lester + Steve Sapovits + Tom Mornini Date: Tue, 15 Apr 2003 16:02:17 +1000 Subject: Compilation bug in DBI on OSX with threaded Perl 5.8.0 -From: Danial Pearce -To: -Message-ID: +From: Danial Pearce In regards to a previous message on this list: @@ -548,5 +557,34 @@ anything Apple are going to do about it. cheers Danial -PS: Personal replies please, I have not subscribed to this list. +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod new file mode 100644 index 00000000..82d14be8 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -0,0 +1,59 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Sun +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Sun + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle on Sun + +=head1 VERSION + +version 1.47_00 + +=head1 General Info + +If you get this on a Solaris 9 and 10 box + + "Outofmemory! + Callback called exit. + END failed--call queue aborted." + +The solution may be as simple as not having you "ORACLE_HOME" Defined in the +environment. + +It seems that having it defined will prevent the error. + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod new file mode 100644 index 00000000..b689f080 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -0,0 +1,129 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Vms +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Vms + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle on Vms + +=head1 VERSION + +version 1.47_00 + +=head1 General Info + +This is related to Oracle RDBMS 9.2 and later, since Oracle +made fundamental changes to oracle installation requirements +and factual installation with this release. + +Oracle's goal was to make VMS installation be more like on +*nix and Windows, with an all new Oracle Home structure too, +requiring an ODS-5 disk to install Oracle Home on instead of +the good old ODS-2. + +Another major change is the introduction of an Oracle generated +logical name table for oracle logical names like ORA_ROOT and all +its derivatives like ORA_PROGINT etc. And that this logical name +table is inserted in LNM$FILE_DEV in LNM$PROCESS_DIRECTORY. + + (LNM$PROCESS_DIRECTORY) + + "LNM$FILE_DEV" = "SERVER_810111112" + = "LNM$PROCESS" + = "LNM$JOB" + = "LNM$GROUP" + = "LNM$SYSTEM" + = "DECW$LOGICAL_NAMES" + +This ensures that any process that needs to have access to +oracle gets the environment by just adding one logical name table +to a central process specific mechanism. + +But as it is inserted at the very top of LNM$FILE_DEV it also +represents a source of misfortune - especially if a user with +enough privilege to update the oracle table does so (presumably +unintentionally), as an examble by changing NLS_LANG. + +PERL has the abillity to define, redefine and undefine (deassign) +logical names, but if not told otherwise by the user does it +in the first table in above list, and not as one would normally +expect in the process table. + +Installing DBI and DBD::Oracle has influence upon this since in +both cases a few environment variables are read or set in the +test phase. +For DBI it is the logical SYS$SCRATCH, which is a JOB logical. +For DBD-Oracle it is when testing a new feature in the Oracle +RDBMS: UTF8 and UTF16 character set functionality, and in order +to do this it sets and unsets the related environment variables +NLS_NCHAR and NLS_LANG. + +If one is not careful this changes the values set in the oracle +table - and in the worst case stays active until the next major +system reset. It can also be a very hard error to track down +since it happens in a place where one normally never looks. + +Furthermore, it is very possibly that some or all of the UTF tests +fails, since if one have a variable like NLS_LANG in his process +table, then even though 'mms test' sets it in the wrong table +it is not invoked as it is overruled by the process logical... + +The way to ensure that no logicals are set in the oracle table and +that the UTF tests get the best environment to test in, and that +DBI correctly translates the SYS$SCRATCH logical, use the +logical + + PERL_ENV_TABLES + +to ensure that PERL's behavior is to leave the oracle table alone and +use the process table instead: + + $ DEFINE PERL_ENV_TABLES LNM$PROCESS, LNM$JOB + +This tells PERL to use the LNM$PROCESS table as the default place to +set and unset variables so that only the perl users environment +is affected when installing DBD::Oracle, and ensures that the +LNM$JOB table is read when SYS$SCRATCH is to be translated. + +PERL_ENV_TABLES is well documented in the PERLVMS man page. + +Oracle8 releases are not affected, as they don't have the +oracle table implementation, and no UTF support. + +Oracle 9.0 is uncertain, since testing has not been possible yet, +but the remedy will not hurt :) + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod new file mode 100644 index 00000000..9acaf51c --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -0,0 +1,279 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Win32 +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Win32 + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle on Win32 + +=head1 VERSION + +version 1.47_00 + +=head1 GENERAL INFO + +In general, on Windows, it's best to just use ActiveState Perl and the +PPM package manager to install a pre-built version of DBD::Oracle however only version 1.17 is available there. + +If you built Perl with gcc, read README.wingcc.txt as well as this file. + +=head1 Oracle Instant Client 11.1.0.6.0 Notes + +So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value +in the environment variables. + +As well IC 11 seems to have trouble finding the .ORA files. A quick fix for this is to add "TNS_ADMIN" +to the environment variables and point it to where your .ORA files are. + +=head1 Other information, some of which is out of date --- + + DBD-Oracle for Windows and Oracle Instantclient and 10XE (Express Edition) + By: John Scoles + The Pythian Group + +The preferred method of getting DBD::Oracle is to use a pre-built version from the ActiveState +repository, which can be installed with PPM. + +Compiling and installing DBD::Oracle 1.18 or later on a windows 2000 professional or XP OS for use +with Oracle instantClient ver 10.2.0.1 & 10.1.0.5 or Oracle XE requires only a few downloads and +a minimal number of environment setting. The procedures below were tested on a clean +Windows platform having no Oracle or other development environment installed. + + 1) The first part of the process is to download and install the latest version of + Active Perl from http://www.activeperl.com/. + + 2) Use the PPM application to get the latest version of DBI + + 3) Download the latest DBD::Oracle from http://svn.perl.org/modules/dbd-oracle/trunk/ + + 4) Download and unzip the Oracle Instant Client (10.2.0.1 or 10.1.0.5) 32 bit from + http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html + You will need all three of these products + i. Instant Client Package - Basic + ii. Instant Client Package - SQL*Plus: + iii. Instant Client Package - SDK: + or + + install oracle 10XE http://www.oracle.com/technology/products/database/xe/index.html + + 5) You will now need the Microsoft Visual C++ toolkit 2003. Unfortunately this product is no longer available from Microsoft. + The file name was VCToolkitSetup.exe and is available at this mirror site http://www.filewatcher.com/m/VCToolkitSetup.exe.32952488.0.0.html at the time of writing. + Microsoft's replacement for this tool kit is Visual C++ 2005 Express Edition and all attempts to compile DBD::Oracle with this product fail. It has been successfully compiled + using a complete edition of Microsoft Visual Studio 2005. + Download and then install this product. + + 6) You will also need the Windows SDK. Which can be found at + http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en + You have the choice to of either to download the entire SDK and install or run an online install from the page. + Both have been tested and proven to work. + + 7) Next download and install the Microsoft .net framework 1.1 skd from + http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&displaylang=en + + 8) You will also need a copy of nmake.exe which you can download here http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe + + 9) Enough Downloading and installing go have a coffee. + + 10) You should at this time attempt to connect to an Oracle database with the version SQL*Plus that + you installed in step 4. If you are unable to connect at this stage then any problems you encounter + later may have nothing to do with DBD::Oracle + + 11) On the path where you installed Visual C++ find and edit the vcvars32.bat file as follows. You may have to modify + these path values depending where you installed the products on you computer, + + i. Add the local path to the windows platform SDK include directory to the Set INCLUDE + Command Line to include the needed files from the Windows SDK. + + e.g. "C:\Program Files\Microsoft Platform SDK\Include;" + + ii. Add the local path to the .net Vc7 lib directory to the Set LIB command + to include the needed library file from the .Net SKD + + e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; + + iii. Add the local path to the windows platform SDK Lib directory to the Set Lib command + to include the needed library files from the Windows SDK + + e.g. C:\Program Files\Microsoft Platform SDK\Lib; + + 12) Open a Windows Visual C++ command window from the start menu. + + 13) Add the path to the instant client to the Path command. If you are compiling aginst a 10XE db/client then you can skip steps + 12 to 14. + e.g. PATH = C:/Oracle/instantclient;%PATH% + + 14) Using the "Set" command add "ORACLE_HOME=path to Instant client" to the environment variables. + e.g. Set ORACLE_HOME=C:\Oracle\instantclient + + 15) Using the "Set" command add "NLS_LANG=.WE8ISO8859P15" to the environment variables. The globalization variable is required, + with this or another compatible value, by Oracle instantclient in order for it to compile correctly. + e.g. Set NLS_LANG=.WE8ISO8859P15 + + 16) Using the "Set" command add "ORACLE_USERID=test/test@test" substituting test with the username/password@database + you wish to run the make test files against. + Note: it is not necessary to do this step for the compile and install to work. + However: The self-test programs included with Oracle-DBD will mostly fail. + + 17) Move to the DBD-Oracle directory in the Visual C++ window DOS prompt and enter the following. + + c:\oracle-dbd\>perl Makefile.PL + + The Makefile should then run and compile Oracle-dbd without reporting any errors. + + 18) From this DOS prompt enter the following command + + c:\oracle-dbd\>nmake + + The Visual C++ make executable will then build you DBD-execuable. There should be no errors at this point. + + 19) You can test the compile by either entering + + c:\oracle-dbd\>nmake test + + As long as you have given a valid user name, password and database name in step 15 you will see some results. If it appears to + run but you do not get a connection check the following. + + i. User name password and DB Name + ii. Ensure the a valid TNSNAMES.ORA file is in the Instantclient directory + iii. Attempt to log into the version of SQLPLUS that comes with Instantclient. + If you manage to log on use the username password and TNS name with + the Set ORACLE_USERID = and rerun the tests. + iv If you are compiling against 10XE and have skiped steps 12 to 14 try again bu this time carry out these steps + + 20) You can now install DBD-Oracle into you system by entering the following command from the Visual C++ window dos prompt; + + c:\oracle-dbd\>nmake install + + 21) You should now be able to run DBD-Oracle on you system + +=head1 09/30 2006 from asu + +DBD::Oracle 1.18a + +Linux, Debian unstable ( +DBI: 1.52 +perl v5.8.8 built for i486-linux-gnu-thread-multi +) + +Oracle Instant client (10.1.0.5) + +The problem is in Makefile.PL. In line 130 the function find_oracle_home +is used to guess a value form $ORACLE_HOME if it is not set explicitely. +This value is used in line 138 to setup the environment (regardless +which client is used). + +in line 1443 (sub get_client_version) sqlplus is used to get the +version string, but for the oracle instant client you must not set +$ORACLE_HOME (it will generate an error "SP2-0642: SQL*Plus internal +error state 2165, context 4294967295:0:0") + +A solution that worked for me was to set +local $ENV{ORACLE_HOME} = ''; +in line 1463 immediately before sqlplus is called (but I cannot tell if +this fails for full client installations) + +11/30/05 -- John Scoles +I have confirmed that this Makefile.pl will work for both Oracle InstantClient +10.2.0.1 & 10.1.0.4 using same process the Andy Hassall uses. Starting with a clean OD +One needs only to get the latest version of Active Perl 5.8.7 use PPM to get DBI and then +install Microsoft Visual C++ toolkit, Windows SDK, and the Microsoft .net +framework 1.1. and modify the vcvars32.bat in C++ dir as follows + + 1) Add the local path to the windows platform SDK include directory to the + Set INCLUDE Command Line to include the needed files from the Windows SDK. + e.g. "C:\Program Files\Microsoft Platform SDK\Include;" + 2) Add the local path to the .net Vc7 lib directory to the Set LIB + command to include the needed library files from the .Net SKD + e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; + 3) Add the local path to the windows platform SDK Lib directory to the Set Lib + command to include the needed library files from the Windows SDK + e.g. C:\Program Files\Microsoft Platform SDK\Lib; + +If one happens to have visual studio installed you may not have to download additional MS products. + +12/01/05 --- John Scoles +Oracle 10XE +No big problem here as 10XE seems to use the instantclient as well. Just ensure your + NLS_LANG and ORACLE_HOME are set to the same directory that 10XE uses + +10/07/05 --John Scoles +Andy Hassall kindly added some changes to the Makefile.PL +so it will work for the Instant Client 10g on Windows OSs. Below is how he set +up his environment and the steps he preformed to get it to compile. + + Setting environment for using Microsoft Visual Studio .NET 2003 tools. + (If you have another version of Visual Studio or Visual C++ installed and wish + to use its tools from the command line, run vcvars32.bat for that version.) + + C:\Documents and Settings\andyh>d: + + D:\>cd cygwin\home\andyh\src\pythian + + D:\cygwin\home\andyh\src\pythian>set ORACLE_HOME=d:\lib\instantclient_10_2 + + D:\cygwin\home\andyh\src\pythian>set NLS_LANG=.WE8ISO8859P15 + + D:\cygwin\home\andyh\src\pythian>set PATH=d:\lib\instantclient_10_2;D:\Program F + iles\Microsoft Visual Studio .NET 2003\Common7\IDE;D:\Program Files\Microsoft Vi + sual Studio .NET 2003\VC7\BIN;D:\Program Files\Microsoft Visual Studio .NET 2003 + \Common7\Tools;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ + bin\prerelease;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ + bin;D:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;C:\WINNT\Mic + rosoft.NET\Framework\v1.1.4322;d:\Perl\bin\;C:\WINNT\system32;C:\WINNT;C:\WINNT\ + System32\Wbem;D:\Program Files\Microsoft SDK\Bin;D:\Program Files\Microsoft SDK\ + Bin\WinNT + + D:\cygwin\home\andyh\src\pythian>set ORACLE_USERID=test/test@test102 + + D:\cygwin\home\andyh\src\pythian>perl Makefile.PL + +4/27/04 -- Jeff Urlwin + +Do not untar this distribution in a directory with spaces. This will not work. + + i.e. C:\Program Files\ORacle\DBD Oracle Distribution is bad while + c:\dev\dbd-oracle-1.15 is good ;) + +9/14/02 -- Michael Chase + +Makefile.PL uses Win32::TieRegistry or Win32::Registry to find the +current Oracle Home directory if the ORACLE_HOME environment variable +is not set. If neither module is installed, you must set ORACLE_HOME +before running Makefile.PL. Since the registry location of the current +Oracle Home is in different locations in different Oracle versions, +it is usually safer to set ORACLE_HOME before running Makefile.PL. + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/README.win64.txt b/lib/DBD/Oracle/Troubleshooting/Win64.pod similarity index 91% rename from README.win64.txt rename to lib/DBD/Oracle/Troubleshooting/Win64.pod index 7f423e2b..4a85b9a1 100644 --- a/README.win64.txt +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -1,4 +1,19 @@ -DBD::Oracle and Windows 64bit +#PODNAME: DBD::Oracle::Troubleshooting::Win64 +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Win64 + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle on Win64 + +=head1 VERSION + +version 1.47_00 + +=head1 DBD::Oracle and Windows 64bit I have successfully compiled and installed DBD::Oracle on Windows 2008 server 64bit operating system today. @@ -7,12 +22,10 @@ version 11.2.0.1.0 for 64bit windows of Oracle's Instant Client Package - Basic along with the Instant Client Package - SQL*Plus and finally the Instant Client Package - SDK. - To get it to Make and compile correctly I had to download Microsoft's Visual Studio Ultimate which should contain all the files you need. It is rather portly at 2+gb so you might want to grab lunch while you are downloading it. - After all the above downloading DBB::Oracle installed right out of the box. All one has to do is select 'Start Menu->All Programs->Microsoft Visual Studio 2010->Visual Studio Tools->Visual Studio x64 Win64 Command Prompt (2010)' @@ -38,10 +51,8 @@ and then a c:\DBD-Oracle>nmake install - Which will produce a whole of warnings (the make you can ignore them for now as they do not seem to effect DBD::Oracle at all) and near the end it should output something like this; - Generating code Finished generating code if exist blib\arch\auto\DBD\Oracle\Oracle.dll.manifest mt -nologo -manifest blib\arch\auto\DBD\Oracle\Oracle.dll.manifest -outputresource:blib\arch\auto @@ -65,16 +76,12 @@ You will need a TNSNAMES.ORA file that points to a valid DB in the Instant Clien Next you will need to set the ORACLE_USER_ID to a valid user - c:\DBD-Oracle>set ORACLE_USER_ID=system/system@XE - You will have to set up TNS_ADMIN to point to the Instant Client Directory - c:\DBD-Oracle>set TNS_ADMIN=c:\IC_11 - Most importantly you will have to add the Instant Client directory to your path like this c:\DBD-Oracle>path = c:\IC_11;%path% @@ -89,7 +96,6 @@ What is actually going on is that Perl cannot find oci.dll (or one of the other are just a false trails. For more info on this check out this page Oracle Troubleshooter' by Alexander Foken. It is rather dated but the facts of why perl did not find a dll are still valid. - now you can do this c:\DBD-Oracle>nmake test @@ -106,10 +112,6 @@ That is about it. At this point you might want to add the Instant Client directory permanently to your path so you will not run into the Dynaloader error again. - - - - In general compiling DBD:Oracle for 64 bit machines has been a hit or miss operation. The main thing to remember is you will have to compile using 32 bit Perl and compile DBD::Oracle against a 32bit client which sort of defeats the purpose of having a 64bit box. @@ -120,7 +122,6 @@ From: Alex Buttery, OCA, MCTS Director, Database Architecture and Operations Impact Rx, Inc. - I needed to get perl working on a 64-bit Windows Server so I got creative. Since I was unable to build DBD::Oracle on the Windows Server (even with Visual Studio 6 installed), I decided that I would try another approach. Here are the steps I took to get it working (yes, this is a hack and I'm not even sure that it does not violate someone's license agreements but I'm not going to be asking anyone @@ -161,11 +162,34 @@ else to support this configuration). SET PATH=%ORACLE_HOME%\bin;%PATH% <== Add 32-bit Oracle Home to beginning of default PATH - +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. -Hopefully, you will be able to include these instructions in the next build of DBD::Oracle to help out other poor souls that are fighting -this same battle. +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. - +=cut - diff --git a/test.pl b/test.pl deleted file mode 100755 index 94830576..00000000 --- a/test.pl +++ /dev/null @@ -1,319 +0,0 @@ -#!/usr/local/bin/perl -w - -use ExtUtils::testlib; - -die "Use 'perl -Mblib test.pl' or 'make test' to run test.pl\n" - unless "@INC" =~ /\bblib\b/; - -# Copyright (c) 1995-2004, Tim Bunce -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -# XXX -# XXX PLEASE NOTE THAT THIS CODE IS A RANDOM HOTCH-POTCH OF TESTS AND -# XXX TEST FRAMEWORKS AND IS IN *NO WAY* A TO BE USED AS A STYLE GUIDE! -# XXX - -$| = 1; - -use Getopt::Long; -use Config; - -my $os = $Config{osname}; - -GetOptions( - 'm!' => \my $opt_m, # do mem leak test - 'n=i' => \my $opt_n, # num loops for some tests - 'c=i' => \my $opt_c, # RowCacheSize for some tests - 'f=i' => \my $opt_f, # fetch test - 'p!' => \my $opt_p, # perf test -) or die; -$opt_n ||= 10; - -# skip this old set of half-baked oddities if ORACLE_DSN env var is set -exit 0 if $ENV{ORACLE_DSN}; - -$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -use Oraperl; - -exit test_extfetch_perf($opt_f) if $opt_f; - -exit test_leak(10 * $opt_n) if $opt_m; - -&ora_version; - -my @data_sources = DBI->data_sources('Oracle'); -print "Data sources:\n\t", join("\n\t",@data_sources),"\n"; - -print "Connecting\n", - " to '$dbname' (from command line, else uses ORACLE_SID or TWO_TASK - recommended)\n"; -print " as '$dbuser' (via ORACLE_USERID env var or default - recommend name/passwd\@dbname)\n"; -printf("(ORACLE_SID='%s', TWO_TASK='%s')\n", $ENV{ORACLE_SID}||'', $ENV{TWO_TASK}||''); -printf("(LOCAL='%s', REMOTE='%s')\n", $ENV{LOCAL}||'', $ENV{REMOTE}||'') if $os eq 'MSWin32'; - -{ # test connect works first - local($l) = &ora_login($dbname, $dbuser, ''); - unless($l) { - $ora_errno = 0 unless defined $ora_errno; - $ora_errstr = '' unless defined $ora_errstr; - warn "ora_login: $ora_errno: $ora_errstr\n"; - # Try to help dumb users who don't know how to connect to oracle... - warn "\nHave you set the environment variable ORACLE_USERID ?\n" - if ($ora_errno == 1017); # ORA-01017: invalid username/password - warn "\nHave you included your password in ORACLE_USERID ? (e.g., 'user/passwd')\n" - if ($ora_errno == 1017 and $dbuser !~ m:/:); - warn "\nHave you set the environment variable ORACLE_SID or TWO_TASK?\n" - if ($ora_errno == 2700); # error translating ORACLE_SID - warn "\nORACLE_SID or TWO_TASK possibly not right, or server not running.\n" - if ($ora_errno == 1034); # ORA-01034: ORACLE not available - warn "\nTWO_TASK possibly not set correctly right.\n" - if ($ora_errno == 12545); - warn "\n"; - warn "Generally set TWO_TASK or ORACLE_SID but not both at the same time.\n"; - warn "Try to connect to the database using an oracle tool like sqlplus\n"; - warn "only if that works should you suspect problems with DBD::Oracle.\n"; - warn "Try leaving dbname value empty and set dbuser to name/passwd\@dbname.\n"; - warn "\nTest aborted cannot connect.\n"; - exit 0; - } - if ($os ne 'MSWin32' and $os ne 'VMS') { - my $backtick = `sleep 1; echo Backticks OK`; - unless ($backtick) { # $! == Interrupted system call - print "Warning: Oracle's SIGCHLD signal handler breaks perl ", - "`backticks` commands: $!\n(d_sigaction=$Config{d_sigaction})\n"; - } - } - #test_bind_csr($l); - #test_auto_reprepare($l); - &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; - -} - -&test_intfetch_perf() if $opt_p; - -&test1(); - -print "\nRepetitive connect/open/close/disconnect:\n"; -#print "If this test hangs then read the README.help.txt file.\n"; -#print "Expect sequence of digits, no other messages:\n"; -# likely to fail with: ORA-12516: TNS:listener could not find available handler with matching protocol stack (DBD ERROR: OCIServerAttach) -# in default configurations if the number of iterations is high (>~20) -my $connect_loop_start = DBI::dbi_time(); -foreach(1..$opt_n) { print "$_ "; &test2(); } -my $dur = DBI::dbi_time() - $connect_loop_start; -printf "(~%.3f seconds each)\n", $dur / $opt_n; - -print "test.pl complete.\n\n"; - -exit 0; - - -sub test1 { - local($lda) = &ora_login($dbname, $dbuser, '') - || die "ora_login: $ora_errno: $ora_errstr\n"; - - &ora_commit($lda) || warn "ora_commit($lda): $ora_errno: $ora_errstr\n"; - &ora_rollback($lda) || warn "ora_rollback($lda): $ora_errno: $ora_errstr\n"; - &ora_autocommit($lda, 1); - &ora_autocommit($lda, 0); - - # Test ora_do with harmless non-select statement - &ora_do($lda, "set transaction read only ") - || warn "ora_do: $ora_errno: $ora_errstr"; - - # DBI::dump_results($lda->tables()); - - # $lda->debug(2); - - { - #$lda->trace(2); - local($csr) = &ora_open($lda, - "select to_number('7.2', '9D9', - 'NLS_NUMERIC_CHARACTERS =''.,''' - ) num_t, - SYSDATE date_t, - USER char_t, - ROWID rowid_t, - HEXTORAW('7D') raw_t, - NULL null_t - from dual") || die "ora_open: $ora_errno: $ora_errstr\n"; - $csr->{RaiseError} = 1; - - print "Fields: ",scalar(&ora_fetch($csr)),"\n"; - die "ora_fetch in scalar context error" unless &ora_fetch($csr)==6; - print "Names: \t",join("\t", &ora_titles($csr)),"\n"; - print "Lengths: \t",DBI::neat_list([&ora_lengths($csr)],0,"\t"),"\n"; - print "OraTypes: \t",DBI::neat_list([&ora_types($csr)], 0,"\t"),"\n"; - print "SQLTypes: \t",DBI::neat_list($csr->{TYPE}, 0,"\t"),"\n"; - print "Scale: \t",DBI::neat_list($csr->{SCALE}, 0,"\t"),"\n"; - print "Precision: \t",DBI::neat_list($csr->{PRECISION}, 0,"\t"),"\n"; - print "Nullable: \t",DBI::neat_list($csr->{NULLABLE}, 0,"\t"),"\n"; - print "Est row width:\t$csr->{ora_est_row_width}\n"; - print "Prefetch cache: $csr->{RowsInCache}\n" if $csr->{RowsInCache}; - - print "Data rows:\n"; - #$csr->debug(2); - while(@fields = $csr->fetchrow_array) { - die "ora_fetch returned ".@fields." fields instead of 6!" - if @fields != 6; - die "Perl list/scalar context error" if @fields==1; - print " fetch: ", DBI::neat_list(\@fields),"\n"; - } - &ora_close($csr) || warn "ora_close($csr): $ora_errno: $ora_errstr\n"; - } - &ora_logoff($lda) || warn "ora_logoff($lda): $ora_errno: $ora_errstr\n"; -} - - -sub test2 { # also used by test_leak() - my $execute_sth = shift; - my $dbh = DBI->connect("dbi:Oracle:$dbname", $dbuser, '', { RaiseError=>1 }); - if ($execute_sth) { - my $sth = $dbh->prepare("select 42,'foo',sysdate from dual where ? >= 1"); - while ($execute_sth-- > 0) { - $sth->execute(1); - my @row = $sth->fetchrow_array; - $sth->finish; - } - } - $dbh->disconnect; -} - - -sub test_leak { - local($count) = @_; - local($ps) = (-d '/proc') ? "ps -lp " : "ps -l"; - local($i) = 0; - my $execute_sth = 100; - print "\nMemory leak test: (execute $execute_sth):\n"; - while(++$i <= $count) { - &test2($execute_sth); - system("echo $i; $ps$$") if (($i % 10) == 1); - } - system("echo $i; $ps$$"); - print "Done.\n\n"; -} - - -sub count_fetch { - local($csr) = @_; - local($rows) = 0; - # while((@row) = &ora_fetch($csr)) { - while((@row) = $csr->fetchrow_array) { - ++$rows; - } - die "count_fetch $ora_errstr" if $ora_errno; - return $rows; -} - - -sub test_intfetch_perf { - print "\nTesting internal row fetch overhead.\n"; - local($lda) = &ora_login($dbname, $dbuser, '') - || die "ora_login: $ora_errno: $ora_errstr\n"; - DBI->trace(0); - $lda->trace(0); - local($csr) = &ora_open($lda,"select 0,1,2,3,4,5,6,7,8,9 from dual"); - local($max) = 50000; - $csr->{ora_fetchtest} = $max; - require Benchmark; - $t0 = new Benchmark; - 1 while $csr->fetchrow_arrayref; - $td = Benchmark::timediff((new Benchmark), $t0); - $csr->{ora_fetchtest} = 0; - printf("$max fetches: ".Benchmark::timestr($td)."\n"); - printf("%d per clock second, %d per cpu second\n\n", - $max/($td->real ? $td->real : 1), - $max/($td->cpu_a ? $td->cpu_a : 1)); -} - -sub test_extfetch_perf { - my $max = shift; - print "\nTesting external row fetch overhead.\n"; - my $rows = 0; - my $dbh = DBI->connect("dbi:Oracle:$dbname", $dbuser, '', { RaiseError => 1 }); - #$dbh->trace(2); - $dbh->{RowCacheSize} = $::opt_c if defined $::opt_c; - my $fields = (0) ? "*" : "object_name, status, object_type"; - my $sth = $dbh->prepare(q{ - select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - --, all_objects o2 - --where o1.object_id <= 400 and o2.object_id <= 400 - }, { ora_check_sql => 1 }); - - require Benchmark; - $t0 = new Benchmark; - $sth->execute; - $sth->trace(0); - $sth->fetchrow_arrayref; # fetch one before starting timer - $td = Benchmark::timediff((new Benchmark), $t0); - printf("Execute: ".Benchmark::timestr($td)."\n"); - - print "Fetching data with RowCacheSize $dbh->{RowCacheSize}...\n"; - $t1 = new Benchmark; - 1 while $sth->fetchrow_arrayref && ++$rows < $max; - $td = Benchmark::timediff((new Benchmark), $t1); - printf("$rows fetches: ".Benchmark::timestr($td)."\n"); - printf("%d per clock second, %d per cpu second\n", - $rows/($td->real ? $td->real : 1), - $rows/($td->cpu_a ? $td->cpu_a : 1)); - my $ps = (-d '/proc') ? "ps -lp " : "ps -l"; - system("echo Process memory size; $ps$$"); - print "\n"; - $sth->finish; - $dbh->disconnect; - exit 1; -} - - -sub test_bind_csr { - local($lda) = @_; -$lda->{RaiseError} =1; -$lda->trace(2); -my $out_csr = $lda->prepare(q{select 42 from dual}); # sacrificial csr XXX -$csr = $lda->prepare(q{ - begin - OPEN :csr_var FOR select * from all_tables; - end; -}); -$csr->bind_param_inout(':csr_var', \$out_csr, 100, { ora_type => 102 }); -$csr->execute(); -# at this point $out_csr should be a handle on a new oracle cursor -@row = $out_csr->fetchrow_array; - - exit 1; -} - -sub test_auto_reprepare { - local($dbh) = @_; - $dbh->do(q{drop table timbo}); - $dbh->{RaiseError} =1; - #$dbh->trace(2); - $dbh->do(q{create table timbo ( foo integer)}); - $dbh->do(q{insert into timbo values (91)}); - $dbh->do(q{insert into timbo values (92)}); - $dbh->do(q{insert into timbo values (93)}); - $dbh->commit; - $Oraperl::ora_cache = $Oraperl::ora_cache = 1; - my $sth = $dbh->prepare(q{select * from timbo for update}); - $sth->execute; $sth->dump_results; - $sth->execute; - print $sth->fetchrow_array,"\n"; - $dbh->commit; - print $sth->fetchrow_array,"\n"; - $dbh->do(q{drop table timbo}); - exit 1; -} - -# end. From 8aa317275f6818a99530d4f347a7637e8aaae5e9 Mon Sep 17 00:00:00 2001 From: yanick Date: Wed, 11 Jul 2012 19:25:29 +0000 Subject: [PATCH 264/637] POD all the READMEs git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15347 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 +- MANIFEST | 22 +- META.json | 20 +- META.yml | 17 +- README | 2 +- README-files/hpux/Makefile-Lincoln | 223 ---------- README.64bit.txt | 272 ------------ README.aix.txt | 255 ----------- README.clients.txt | 279 ------------ README.help.txt | 133 ------ README.java.txt | 322 -------------- README.mkdn | 2 +- README.sec.txt | 142 ------ README.win32.txt | 236 ---------- lib/DBD/Oracle.pm | 10 +- lib/DBD/Oracle/GetInfo.pm | 4 +- lib/DBD/Oracle/Object.pm | 4 +- lib/DBD/Oracle/Troubleshooting.pm | 419 ------------------ lib/DBD/Oracle/Troubleshooting.pod | 167 +++++++ lib/DBD/Oracle/Troubleshooting/Aix.pod | 290 ++++++++++++ lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 111 +++++ .../DBD/Oracle/Troubleshooting/Hpux.pm | 60 ++- lib/DBD/Oracle/Troubleshooting/Linux.pod | 149 +++++++ .../DBD/Oracle/Troubleshooting/Macos.pod | 326 ++++++++------ lib/DBD/Oracle/Troubleshooting/Sun.pod | 59 +++ lib/DBD/Oracle/Troubleshooting/Vms.pod | 129 ++++++ lib/DBD/Oracle/Troubleshooting/Win32.pod | 279 ++++++++++++ .../DBD/Oracle/Troubleshooting/Win64.pod | 64 ++- test.pl | 319 ------------- 29 files changed, 1501 insertions(+), 2818 deletions(-) delete mode 100644 README-files/hpux/Makefile-Lincoln delete mode 100644 README.64bit.txt delete mode 100644 README.aix.txt delete mode 100644 README.clients.txt delete mode 100644 README.java.txt delete mode 100644 README.sec.txt delete mode 100644 README.win32.txt delete mode 100644 lib/DBD/Oracle/Troubleshooting.pm create mode 100644 lib/DBD/Oracle/Troubleshooting.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Aix.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Cygwin.pod rename README.hpux.txt => lib/DBD/Oracle/Troubleshooting/Hpux.pm (97%) create mode 100644 lib/DBD/Oracle/Troubleshooting/Linux.pod rename README.macosx.txt => lib/DBD/Oracle/Troubleshooting/Macos.pod (76%) create mode 100644 lib/DBD/Oracle/Troubleshooting/Sun.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Vms.pod create mode 100644 lib/DBD/Oracle/Troubleshooting/Win32.pod rename README.win64.txt => lib/DBD/Oracle/Troubleshooting/Win64.pod (91%) delete mode 100755 test.pl diff --git a/Changes b/Changes index b851ba02..2d854c71 100644 --- a/Changes +++ b/Changes @@ -13,7 +13,9 @@ Revision history for DBD::Oracle does not seem to have it in 10.2 leading to undefined symbol - Martin J. Evans - [MISCELLANEOUS] + [DOCUMENTATION] + - Promoted the troubleshooting for the different architectures to + POD documents, for easier/prettier access. - Added a troubleshooting entry for RT71819 - bound output parameters may be returned in the wrong order (Martin J. Evans) diff --git a/MANIFEST b/MANIFEST index 34c7a9d4..bd226508 100644 --- a/MANIFEST +++ b/MANIFEST @@ -9,18 +9,8 @@ Oracle.h Oracle.xs Oraperl.pm README -README-files/hpux/Makefile-Lincoln -README.64bit.txt -README.aix.txt -README.clients.txt README.help.txt -README.hpux.txt -README.java.txt -README.macosx.txt README.mkdn -README.sec.txt -README.win32.txt -README.win64.txt Todo dbdimp.c dbdimp.h @@ -47,7 +37,16 @@ hints/svr4.pl lib/DBD/Oracle.pm lib/DBD/Oracle/GetInfo.pm lib/DBD/Oracle/Object.pm -lib/DBD/Oracle/Troubleshooting.pm +lib/DBD/Oracle/Troubleshooting.pod +lib/DBD/Oracle/Troubleshooting/Aix.pod +lib/DBD/Oracle/Troubleshooting/Cygwin.pod +lib/DBD/Oracle/Troubleshooting/Hpux.pm +lib/DBD/Oracle/Troubleshooting/Linux.pod +lib/DBD/Oracle/Troubleshooting/Macos.pod +lib/DBD/Oracle/Troubleshooting/Sun.pod +lib/DBD/Oracle/Troubleshooting/Vms.pod +lib/DBD/Oracle/Troubleshooting/Win32.pod +lib/DBD/Oracle/Troubleshooting/Win64.pod mkta.pl oci.def oci8.c @@ -90,5 +89,4 @@ t/80ora_charset.t t/nchar_test_lib.pl t/rt13865.t t/rt74753-utf8-encoded.t -test.pl typemap diff --git a/META.json b/META.json index b64f752c..5f4887ca 100644 --- a/META.json +++ b/META.json @@ -52,34 +52,30 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.46" + "version" : "1.47_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.46" + "version" : "1.47_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.46" - }, - "DBD::Oracle::Troubleshooting" : { - "file" : "lib/DBD/Oracle/Troubleshooting.pm", - "version" : "1.46" + "version" : "1.47_00" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.46" + "version" : "1.47_00" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.46" + "version" : "1.47_00" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.46" + "version" : "1.47_00" } }, - "release_status" : "stable", + "release_status" : "testing", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -92,7 +88,7 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, - "version" : "1.46", + "version" : "1.47_00", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index 379da346..de8b99e6 100644 --- a/META.yml +++ b/META.yml @@ -30,25 +30,22 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.46 + version: 1.47_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.46 + version: 1.47_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.46 - DBD::Oracle::Troubleshooting: - file: lib/DBD/Oracle/Troubleshooting.pm - version: 1.46 + version: 1.47_00 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.46 + version: 1.47_00 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.46 + version: 1.47_00 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.46 + version: 1.47_00 requires: DBI: 0 DynaLoader: 0 @@ -60,7 +57,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.46 +version: 1.47_00 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 1cf1a61f..0697b8dd 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.46 + version 1.47_00 SYNOPSIS use DBI; diff --git a/README-files/hpux/Makefile-Lincoln b/README-files/hpux/Makefile-Lincoln deleted file mode 100644 index 0565def4..00000000 --- a/README-files/hpux/Makefile-Lincoln +++ /dev/null @@ -1,223 +0,0 @@ -# makefile for rebuilding perl and all the modules we have built -# or for rebuilding individual modules -SHELL = /usr/bin/ksh -CPAN_VERSION = 5.6.1 -FCCS_VERSION = fccs-03 -#needed for compatibility with ../build.mk: -TOOL = perl -PERL_VERSION = $(TOOL)-$(CPAN_VERSION) -TOP = /opt/oss -PERLDIR = $(PERL_VERSION)-$(FCCS_VERSION) -PERL_ROOT = $(TOP)/pkg -PREFIX = $(PERL_ROOT)/$(PERLDIR) -#needed for compatibility with ../biuld.mk: -VERSION = $(CPAN_VERSION)-$(FCCS_VERSION) - -MQS = MQSeries-1.14 -DBDORA = DBD-Oracle-1.12 -DBI = DBI-1.20 -EXPAT_VER = -1.95.2 -MQSERVER = 'PERL_CHANNEL/TCP/dsas105(1414)' - -MODULES = \ - libnet-1.0703 \ - Storable-0.7.2 \ - Time-HiRes-01.20 \ - Net-Daemon-0.35 \ - Digest-MD5-2.16 \ - Digest-SHA1-2.01 \ - Digest-HMAC-1.01 \ - MIME-Base64-2.12 \ - Net-DNS-0.19 \ - Mail-CheckUser-1.13 \ - Proc-Daemon-0.02 \ - Proc-Simple-1.14 \ - Openview-Message-0.01 \ - Business-CreditCard-0.26 \ - Data-UUID-0.06 - -XML_PARSER = XML-Parser-2.31 -XML_MODULES = \ - XML-Simple-1.05 \ - XML-Generator-0.8 -#this does not behave same as 0.8 -#XML-Generator-0.91 - -all: testOracleVar - @banner ALL_PERL - @echo "using perl PATH=$(PREFIX)/bin" - ( export PATH=$(PREFIX)/bin:$$PATH && make perl ) - ( export PATH=$(PREFIX)/bin:$$PATH && make all_modules ) - -print_macros: - @echo TOOL=$(TOOL) - @echo CPAN_VERSION=$(CPAN_VERSION) - @echo PERL_VERSION=$(PERL_VERSION) - @echo FCCS_VERSION=$(FCCS_VERSION) - @echo PREFIX=$(PREFIX) - @echo VERSION=$(VERSION) - @echo PERLDIR=$(PERLDIR) - @echo PERL_ROOT=$(PERL_ROOT) - -all_modules: modules xmlparser xml_modules dbi dbd mqs - -modules: testPath - rm -rf $(MODULES) - for m in $(MODULES); do \ - make module MODULE=$$m PREFIX=$(PREFIX) ; \ - done - -xml_modules: testPath - rm -rf $(XML_MODULES) - for m in $(XML_MODULES); do \ - make module MODULE=$$m PREFIX=$(PREFIX) ; \ - done - -dbi: testPath - make module MODULE=DBI-1.20 PREFIX=$(PREFIX) - -dbd: testPath testOracleVar dbi touch.d/$(DBDORA).tch - -touch.d: - mkdir touch.d - -xmlparser: touch.d/$(XML_PARSER).tch -touch.d/$(XML_PARSER).tch: $(XML_PARSER).tar.gz - tar -zxvf $(XML_PARSER).tar.gz - ( cd $(XML_PARSER) && \ - perl Makefile.PL EXPATLIBPATH=$(TOP)/lib \ - EXPATINCPATH=$(TOP)/include && \ - make && \ - make test && \ - make install ) - rm -rf $(XML_PARSER) - touch $@ - -#chmod +w CONFIG; -mqs_config: - ( cd $(MQS); \ - mv CONFIG CONFIG.orig; \ - cp ../$$(uname).MQS.CONFIG CONFIG \ - ) - -mqs_target: - ( export MQSERVER=$(MQSERVER); \ - cd $(MQS) ;\ - make $(MQS_TARGET) \ - ) - -mqs_build: - ( export MQSERVER=$(MQSERVER); \ - cd $(MQS) ;\ - cp ../$$(uname).MQS.CONFIG ./CONFIG; \ - perl Makefile.PL; \ - make ; \ - ) - -mqs: testPath /opt/mqm touch.d/$(MQS).tch -touch.d/$(MQS).tch: - @banner $(MQS) - rm -rf $(MQS) - gunzip -c $(MQS).tar.gz | tar -xvf - - touch $(MQS)/.LICENSE.ACCEPTED - make -s mqs_config - make -s mqs_build - make -s mqs_target MQS_TARGET=test - make -s mqs_target MQS_TARGET=install - touch $@ - - -touch.d/$(DBDORA).tch: testOracleVar - @banner $(DBDORA) - test ! -z "$(ORACLE_HOME)" - -rm -rf $(DBDORA) - gunzip -c $(DBDORA).tar.gz | tar -xf - - cd $(DBDORA) ;\ - perl Makefile.PL; \ - make ; \ - make test ; \ - make install - touch touch.d/$(DBDORA).tch - - -perl: testVar $(PERL_VERSION) touch.d/$(PERL_VERSION).tch - -touch.d/$(PERL_VERSION).tch: - @banner perl - @if ls $(PREFIX) >/dev/null 2>&1 ; \ - then \ - echo "Error: Cannot install to an existing directory" ;\ - echo "Error: Please delete or move $(PREFIX)" ;\ - exit 1;\ - fi - - cd $(PERL_VERSION); make distclean; - cd $(PERL_VERSION); \ - ./Configure -Dprefix=$(PREFIX) -Ubincompat5005 -Uuselargefiles \ - -A eval:libswanted='\"cl pthread $$libswanted\" ' -des; \ - make ; \ - make test; \ - make install - touch touch.d/$(PERL_VERSION).tch - -realclean distclean: clean_tch - -rm -rf $(PERL_VERSION) - -clean: clean_tch -clean_tch : - -rm -f touch.d/*.tch - -module: touch.d/$(MODULE).tch - -touch.d/$(MODULE).tch : - @banner $(MODULE) - -rm -rf $(MODULE) - gunzip -c $(MODULE).tar.gz | tar -xf - - cd $(MODULE); \ - perl Makefile.PL /dev/null 2>&1 ; \ - then \ - echo "Error: Cannot install to an existing directory" ;\ - echo "Error: Please delete or move $(PREFIX)" ;\ - exit 1;\ - fi - gunzip -c $(PERL_VERSION).tar.gz |tar xf - - @echo "untar of perl is done" - -testVars: testVar testPath testOracleVar - -testVar: touch.d - @echo "******** Building to: $(PREFIX) *********" - -testOracleVar: - @if test -z "$$ORACLE_HOME" ; \ - then \ - echo " Please set \"export ORACLE_HOME=\"" ;\ - exit 1; \ - else \ - echo ORACLE_HOME=$(ORACLE_HOME); \ - fi - @if test -z "$$ORACLE_USERID" ; \ - then \ - echo " Please set \"export ORACLE_USERID=\"" ;\ - exit 1; \ - else \ - echo ORACLE_USERID=$(ORACLE_USERID); \ - fi - -testPath: - @if echo $$PATH | egrep -q '^$(PREFIX)/bin:'; then \ - echo PATH is OK; \ - else \ - echo "ERROR: You must have $(PREFIX)/bin first in your path as follows:" ;\ - echo " export PATH=$(PREFIX)/bin:\$$PATH" ;\ - exit 1; \ - fi diff --git a/README.64bit.txt b/README.64bit.txt deleted file mode 100644 index 9d3ebe0f..00000000 --- a/README.64bit.txt +++ /dev/null @@ -1,272 +0,0 @@ -In general compiling DBD:Oracle for 64 bit machines has been a hit or miss operation. -The main thing to remember is you will have to compile using 32 bit Perl and compile DBD::Oracle against a 32bit client -which sort of defeats the purpose of having a 64bit box. -So until 64bit Perl comes out we will be posing in this README any success stories we have come across - --------- Original Message -------- - -Subject: Building 32bit DBD::Oracle against 64bit Oracle -From: Dennis Reso -Date: 7/9/2008 5:44 PM -Priority: Normal - -Building DBD::Oracle v1.21 against Perl 5.8.5 Oracle 9.2.0.4 Solaris 8 - -Got the dreaded "wrong ELF class" when the Oracle.so ends up built -against the 64bit library instead of the one in $ORACLE_HOME/lib32. -Use 'dump -vL Oracle.so' to see the internalized RPATH definition. - -Tried the following solution, widely posted, without success: - - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - -What worked for me (pass the LIBDIR to the Oracle make process): - - export ORACLE_HOME=/apps/Oracle9.2.0.4 - export LD_LIBRARY_PATH=$ORACLE_HOME/lib32 - perl -pi -e 's/CC=true/CC=true LIBDIR=lib32/' Makefile.PL - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - make - -The LIBDIR= is defined in $ORACLE_HOME/rdbms/lib/env_rdbms.mk which -also includes a REDEFINES32= that overrides it, but is only used by -the $ORACLE_HOME/rdbms/lib/ins_rdbms.mk. Oracle bug? - -Also repeated the same failure and success with - Oracle 9.2.0.8 Solaris 10 - Oracle 10.2.0.3 Solaris 10 - -Seems fixed in demo_rdbms32.mk (no Makefile.PL edit needed ) as of - Oracle 10.2.0.4 Solaris 10 - -Probably also fixed in some patchset newer than 9.2.0.4. - --- -Dennis Reso - --------- Original Message -------- - -Subject: DBD::Oracle 64-bit success story -From: H.Merijn Brand -Date: On Mon, 14 Apr 2008 09:48:41 -Priority: Normal - -I finally got round trying Oracle Instant Client on Linux with no -Oracle installed, connecting to a 64bit Oracle 9.2.0.8 on HP-UX -11.11/64. I had to do some fiddling with Makefile.PL (see bottom). -Sorry for this being long. Feel free to mold it into anything useful. - -1. Before you start on DBD::Oracle, make sure DBD::ODBC works. That will - assure your DSN works. Install unixODBC before anything else. - -2. Assuming you've got OIC from the rpm's, you will have it here: - - /usr/include/oracle/11.1.0.1/client - /usr/lib/oracle/11.1.0.1/client - /usr/share/oracle/11.1.0.1/client - - -3. for the 64 bit clienat we have these rpm - oracle-instantclient-basic-11.1.0.1-1.x86_64.rpm - oracle-instantclient-devel-11.1.0.1-1.x86_64.rpm - oracle-instantclient-jdbc-11.1.0.1-1.x86_64.rpm - oracle-instantclient-odbc-11.1.0.1-1.x86_64.rpm - oracle-instantclient-sqlplus-11.1.0.1-1.x86_64.rpm - - and to add to the confusement, they install to - - /usr/include/oracle/11.1.0.1/client64 - /usr/lib/oracle/11.1.0.1/client64 - /usr/share/oracle/11.1.0.1/client64 - -4. To make DBD::ODBC work, I had to create a tnsnames.ora, and I chose - - /usr/lib/oracle/11.1.0.1/admin/tnsnames.ora - - /usr/lib/oracle/11.1.0.1/admin > cat sqlnet.ora - NAMES.DIRECTORY_PATH = (TNSNAMES, ONAMES, HOSTNAME) - /usr/lib/oracle/11.1.0.1/admin > cat tnsnames.ora - ODBCO = ( - DESCRIPTION = - ( ADDRESS_LIST = - ( ADDRESS = - ( PROTOCOL = TCP ) - ( PORT = 1521 ) - ( HOST = rhost ) - ) - ) - ( CONNECT_DATA = - ( SERVICE_NAME = odbctest ) - ) - ) - /usr/lib/oracle/11.1.0.1/admin > - - Real world example changed to hide the obvious. Important bits are - "ODBCO", which is the ODBC name, and it can be anything, as long as - you use this in ORACLE_DSN too (please don't use whitespace, colons, - semicolons and/or slashes. "rhost" is the hostname of where the DB - is running, and "odbctest" is available on "rhost". To check that, - run "lsnrctl services" on "rhost". - Set the environment (TWO_TASK is not needed) - - > setenv LD_LIBRARY_PATH /usr/lib/oracle/11.1.0.1/client/lib - > setenv TNS_ADMIN /usr/lib/oracle/11.1.0.1/admin - > setenv ORACLE_HOME /usr/lib/oracle/11.1.0.1/client - > setenv ORACLE_DSN dbi:Oracle:ODBCO - > setenv ORACLE_USERID ORAUSER/ORAPASS - - Check if the connection works: - > isql -v ODBCO - - And for Oracle: - > sqlplus ORAUSER/ORAPASS@ODBCO - and - > sqlplus ORAUSER/ORAPASS@rhost/odbctest - - should both work - - -Note by JPS: - -Merijn patched the trunk version of Makeifle.PL to account for the above it will be in release 1.22 - --------- Original Message -------- - -Subject: DBD::Oracle 64-bit success story -From: "QiangLi" -Date: Thu, March 6, 2008 5:25 pm -To: pause@pythian.com -Priority: Normal - -hi, - -thanks for maintaining DBD::Oracle. I have installed DBD::Oracle against - 64-bit oracle 10g on a 64-bit solaris machine. maybe worth another -entry for the README.64bit.txt file. - -i am using gcc from sun freesoftware and also SUNWbinutils which -contains the gas (gnu assembler) - -here is the steps with comment: - -# set install target -% /usr/perl5/5.8.4/bin/perlgcc Makefile.PL PREFIX=/var/tmp/lib - -# since our perl is 32-bit, we can't build it against a 64bit oracle -install. -# edit Makefile and change reference to oracle's "lib/" to "lib32/" -% perl -pi -e 's/oracle_home\/lib/oracle_home\/lib32/g' Makefile -% perl -pi -e 's/oracle_home\/rdbms\/lib/oracle_home\/rdbms\/lib32/g' -Makefile - -% make - -# ignore error like ORA-12162: TNS:net service name is incorrectly -specified... -% make test - -% make install - -# does it work. -% perl -I'/var/tmp/lib/lib/site_perl/5.8.4/sun4-solaris-64int/' --MDBD::Oracle -e1 - -cheers, - -Qiang - - - - --------- Original Message -------- -Subject: Tip: Compiling 32bit modules against 64bit Oracle 10g on solaris -Date: Thu, 1 Nov 2007 16:41:28 -0400 -From: Edgecombe, Jason -To: -CC: - - - -Hi There, - -I just wanted to thank both of you. - -The tip from cartmanltd@hotmail.com was the trick for getting -DBD::Oracle compiled in 32bit format against the Oracle 10g client on -solaris. - -Here was the command that worked: - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - -Even though the tip was for aix, it fixed my build issue on solaris 9 -(sparc) - -I've been banging my head on this problem for a few days. - -Thanks, -Jason - -Jason Edgecombe -Solaris & Linux Administrator -Mosaic Computing Group, College of Engineering -UNC-Charlotte -Phone: (704) 687-3514 - - - -Source:Tom Reinertson -Platform:Amd64 -OS:Gentoo-amd64 - -The following instructions work for dbd::oracle 1.19 on a gentoo-amd64 installation. - -1) install the oracle libraries - - Strictly speaking you only need dev-db/oracle-instantclient-basic - for dbd::oracle, but i always like to have sql*plus lying around, - which requires the basic package, so i just install sql*plus. - - emerge dev-db/oracle-instantclient-sqlplus which also pulls in - dev-db/oracle-instantclient-basic. these packages are fetch - restricted so you will be required to follow the download instructions. - following these instructions, you should have retrieved these packages: - - instantclient-basic-linux-x86-64-10.2.0.3-20070103.zip - instantclient-sdk-linux-x86-64-10.2.0.3-20070103.zip - instantclient-sqlplus-linux-x86-64-10.2.0.3-20070103.zip - - now move them into the /usr/portage/distfiles directory. - - you should now be able to emerge dev-db/oracle-instantclient-sqlplus. - -2) install DBD::Oracle - - issue the command: - - perl -MCPAN -e'install DBD::Oracle' - - this fails with the following error: - - x86_64-pc-linux-gnu-gcc: unrecognized option '-wchar-stdc++' - x86_64-pc-linux-gnu-gcc: unrecognized option '-cxxlib-gcc' - cc1: error: /ee/dev/bastring.h: No such file or directory - - find the offending files in your cpan directory: - {~/.cpan/build/DBD-Oracle-1.19} grep -lr cxxlib * - Makefile - blib/arch/auto/DBD/Oracle/mk.pm - mk.pm - - edit these files and remove the two invalid options and the include of bastring.h. - - now build the module: - - perl Makefile.PL -l - make - # make test generates lots of errors - make test - make install - - you should now be ready to run. - - diff --git a/README.aix.txt b/README.aix.txt deleted file mode 100644 index a83bf144..00000000 --- a/README.aix.txt +++ /dev/null @@ -1,255 +0,0 @@ - -DBD::Oracle AIX-specific README - - -Using Visual Age 7 C Compiler -====================================================================================== - -- Oracle 9i is only certified as a 64-bit application on AIX 5L (5.1,5.2,5.3) with 32-bit support; - in other words, there is no 9i "32-bit" Oracle client -- Oracle 10g is certified as both a 64-bit application and a 32-bit Oracle client - -- This information only pertains to deploying - the DBI (version 1.48) - and DBD-Oracle (version 1.16): - on AIX 5.3 - using Oracle 9i (9.2.0.1/9.2.0.5) - using the existing Perl 5.8.2 (no custom-built Perl) which is 32-bit - using Visual Age 7.0 C/C++ compiler - -Install the DBI (required for the DBD-Oracle install - no issues here) -Untar the DBD-Oracle bundle -Run Makefile.PL -$ perl Makefile.PL -Edit Makefile with following commands: -1,$s?/lib/ ?/lib32/ ?g -1,$s?-q64??g -1,$s?/lib/sysliblist?/lib32/sysliblist?g -Now perform normal commands to perform the testing/making: -$ make -$ make test -$ make install - -I've tested the basics of the DBD-Oracle and it seems fully functional. - -Stephen de Vries -paulhill20@copper.net - - - -Using gcc C Compiler -====================================================================================== - - - -DBD::Oracle with gcc and Oracle Instant Client on AIX --------------------------------------------------------------------------------------- -Nathan Vonnahme Dec 15 2005, 4:28 pm Newsgroups: perl.dbi.users -See: http://groups.google.com/group/perl.dbi.users/msg/0bd9097f80f2c8a9 -[ with updates 1/31/2006 - DBD::Oracle 1.17 doesn't need makefile hacking -to work with instantclient on AIX ] - - -Yes! It eluded me last year but I finally got DBD::Oracle working on an -AIX machine using gcc. Here's the short version: - -First I had to recompile perl with gcc, using - sh Configure -de -Dcc=gcc -This apparently built a 32 bit perl, someday I will try getting it to go -64 bit. - -I was then able to install and build DBI 1.50 with the CPAN shell. - -I downloaded the base and sdk packages of the Oracle Instant Client for -AIX -- first I tried the 64 bit but that didn't work with my 32 bit perl --- the 32 bit version (still at 10.1.0.3) did the trick. I unzipped -them and moved the dir to /usr/local/oracle/instantclient10_1 and made a -symlink without the version at /usr/local/oracle/instantclient , then -set: - -export ORACLE_HOME=/usr/local/oracle/instantclient -export LIBPATH=$ORACLE_HOME - - - -Oracle wasn't providing the sqlplus package for 32 bit AIX so I -explicitly told Makefile.PL the version: - -perl Makefile.PL -V 10.1 - -make - -My test databases were on other machines so I set these environment variables -to get the tests to run: - -export ORACLE_DSN=DBI:Oracle://host/dbinstance -export ORACLE_USERID="user/password" - -make test -make install - - -NOTE: I have an older full version of Oracle on this machine, and the -ORACLE_HOME environment variable is normally set to point to that, so -my perl scripts that use DBD::Oracle have to make sure to first set - $ENV{ORACLE_HOME}='/usr/local/oracle/instantclient'; - - - - - --------------------------------------------------------------------------------------- -The following setup worked to build on AIX 5.2: -gcc-3.3.2 (32-bit) (configure opts [ --with-ld=/usr/ccs/bin/ld --with-as=/usr/ccs/bin/as]) -Oracle-9.2.0 ( full install w/32bit support) -perl-5.8.3 (built with above gcc/latest stable as of March 2004) -Followed the directions from Rafael's email below, only set ORACLE_HOME, (and -the appropriate test environmentals). -1) build perl-5.8.3 with gcc -2) install DBI -3) ORACLE_HOME="your oracle home" - ORACLE_USERID.. - ORACLE_SID .. - (I ignored ORACCENV, didn't use it.) -4) install DBD::Oracle, after perl Makefile.PL, edit the created Makefile, -changing references to Oracle's ../lib to ../lib32. and change crt0_64.o to -crt0_r.o. Remove the -q32 and/or -q64 options from the list of libraries to -link with. -5) make should be clean, make test should pass. -This setup worked with 8.1.7 w/32 bit support, and with 9.2.0 w/ 32-bit support. ---Adrian Terranova -peril99@yahoo.com - - - - -Using xlc_r C Compiler -====================================================================================== --------------------------------------------------------------------------------------- -From: Rafael Caceres -Date: 22 Jul 2003 10:05:20 -0500 -Message-Id: <1058886321.1066.13.camel@rcaceres.aasa.com.pe> - -The following sequence worked for me on AIX 5.1: - --use Perl 5.8.0 (the latest stable from CPAN) - --use the xlc_r version of IBM's compiler and build a 32 bit Perl - (which xlc_r will do by default). All tests should be successful. - --get and install DBI - --get DBD::Oracle. Edit the Makefile.PL or Makefile for DBD::Oracle, -changing references to Oracle's ../lib to ../lib32. and change crt0_64.o -to crt0_r.o. Remove the -q32 and/or -q64 options from the list of -libraries to link with. Do the make and make test. - --Set up the environment for making DBD::Oracle: - ORACLE_HOME="your oracle home" - ORACCENV = "xlc_r" - ORACLE_USERID.. - ORACLE_SID .. - --Run make, all tests should be successfull -against Oracle 9.x at least. - -You should have no problems with Oracle 8.1.7, but accessing Oracle 7.x -or previous is not possible (you'll core dump, or simply hang). The same -goes for a Linux build or a Digital build, regarding access of different -Oracle versions. - -Rafael Caceres - -On Tue, 2003-07-22 at 08:12, mpaladino@invacare.com wrote: -> -> I dont believe I compiled Oracle. During the installation it was linked -> but I am not sure it was compiled -> -> I used a xlc compiler to compile PERL. -> Got this message in the Perl Makefile.PL output -> -> Warning: You will may need to rebuild perl using the xlc_r compiler. -> You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV -> Also see the README about the -p option -> -> this probobly means I need to rebuild PERL with xlc_r?? -> -> thanx -> -> Mike Paladino -> Database Administrator - - -From: Rafael Caceres -> -> Make sure you use the same compiler to build Oracle and Perl. We have -> used xlc_r on Aix 5.1 with no problems. Your Perl build is 32 bit, so -> when building DBD::Oracle, you should use the 32bit libraries (change -> references to .../oracle/lib to .../oracle/lib32 in your Makefile). -> Remove the references to the -q64 or -q32 parameters for ld in Makefile, -> as they shouldn't be there. -> -> Rafael Caceres - - -From: "cartman ltd" -Subject: Tip for DBI and DBD::Oracle on AIX 5.1 and Oracle 9.2 -Date: Mon, 11 Aug 2003 18:15:38 +0000 -Message-ID: - -Here is a tip for compiling DBD::Oracle as a 32 bit application on AIX 5.1 -64 bit and Oracle 9.2 64 bit without editting any makefiles. I hope people -find this useful: - -First, the versions of products I used: - DBI version 1.32 - DBD::Oracle version 1.14 - Oracle 9.2.0.2 - default 64 bit application with 32 bit libraries - AIX 5.1 ML03 - 64 bit kernel - ships with Perl as a 32 bit application. - VisualAge C/C++ 5.0.2 - -Basically DBD must be compiled as 32 bit to link with Perl's 32 bit -libraries. - gunzip -c DBD-Oracle-1.14.tar.gz | tar xvf  - cd DBD-Oracle-1.14 - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk - make - -NB: I think there is a bug in the Oracle 9.2.0.3 file -$ORACLE_HOME/rdbms/lib/env_rdbms.mk -I corrected this (before running the above commands) by replacing the -invalid linker option - LDFLAGS32=-q32 -with - LDFLAGS32=-b32 - -Have fun: KC. --------------------------------------------------------------------------------------- - -Date: Wed, 30 Jun 2004 23:34:24 -0500 -From: "SCHULTZ, DARYLE (SBCSI)" - -Got it to work. Using dbd 1.16 - -Perl 5.8.4 built like this, with Visual Age 6.0: - -config_args='-Dcc=xlc_r -Dusenm -Dprefix=/appl/datasync/work/perl5 --Dusethreads -Duse64bitall -des' -============================================== - -Used DBI 1.42 -============================================= -Added this to top of Oracle.h: -#define A_OSF - -#include -======================= -Set LIBPATH to point to 64bit Oracle libs first. -export LIBPATH=$ORACLE_HOME/lib:$ORACLE_HOME/lib32:/usr/lib - -Use: perl Makefile.PL -nob - -Change all references in Makefile of LD_RUN_PATH to be LIBPATH. -Change nothing else, left all flags in Makefile, including -q64. -Passed make, and all tests. - --------------------------------------------------------------------------------------- diff --git a/README.clients.txt b/README.clients.txt deleted file mode 100644 index 274ca435..00000000 --- a/README.clients.txt +++ /dev/null @@ -1,279 +0,0 @@ -This file contains some random notes relating to minimal Oracle -configurations for building and/or using DBD::Oracle / Oraperl. - - -*** ALL THE TEXT BELOW IS OLD *** -*** THE PREFERED METHOD IS TO USE Oracle Instant Client *** - - -------------------------------------------------------------------------------- -With recent versions of Oracle (specifically >= 7.3) you may be -able to build DBD::Oracle without Pro*C installed by using the Oracle -supplied oracle.mk file: - - perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/oracle.mk - -(The oracle.mk file might also be found in $ORACLE_HOME/rdbms/public/) - -------------------------------------------------------------------------------- -From: James Cooper - -> [...], what do I need in addition to perl5 to access an Oracle database -> on another system from a unix box (Solaris 2.5) that doesn't have an -> oracle database running on it ? -> -> In other words are their some oracle shared objects, etc. I need ? - -I don't have experience with Solaris, but on IRIX 5.3, I simply installed -SQL*Net ($ORACLE_HOME/network/admin/*) and the OCI libraries which are in -$ORACLE_HOME/lib. You'll also need the header files from -$ORACLE_HOME/sqllib/public/*.h and $ORACLE_HOME/rdbms/demo/*.h (you won't -need them all, but you can get rid of them after DBD::Oracle compiles). - -[You'll probably need at least ocommon in addition to network. But if you -use the Oracle installer (as you always should) it'll probably install -ocommon for you.] - -So just put that stuff on your client box and install DBI and DBD::Oracle -there. Once DBD::Oracle is installed you can remove the OCI libraries and -headers (make sure to keep SQL*Net!) - -Other than that, getting it working isn't too hard. If you're not -familiar with SQL*Net, let me know. I'm no expert, but I know the basics. -The main thing is to have a good tnsnames.ora file in -$ORACLE_HOME/network/admin - -------------------------------------------------------------------------------- -From: Jon Meek - -For my compilation of DBD-Oracle/Solaris2.5/Oracle7.2.x(x=2, I think), I -just pulled the required files in the rdbms directory from the Oracle CD. -The files I needed were: - -$ ls -lR -drwxr-xr-x 2 oracle apbr 512 May 15 17:43 demo/ -drwxr-xr-x 2 oracle apbr 512 May 15 16:20 lib/ -drwxr-xr-x 2 oracle apbr 512 May 15 16:18 mesg/ -drwxr-xr-x 2 oracle apbr 512 May 15 17:38 public/ - -./demo: --r--r--r-- 1 oracle apbr 4509 Jun 29 1995 ociapr.h --r--r--r-- 1 oracle apbr 5187 Jun 29 1995 ocidfn.h --rw-rw-r-- 1 oracle apbr 6659 Jun 29 1995 oratypes.h - -./lib: --rw-r--r-- 1 oracle apbr 1132 Jul 6 1995 clntsh.mk --rwxr-xr-x 1 oracle apbr 5623 Jul 17 1995 genclntsh.sh* --rw-r--r-- 1 oracle apbr 15211 Jul 5 1995 oracle.mk --rw-r--r-- 2 oracle apbr 3137 May 15 16:20 osntab.s --rw-r--r-- 2 oracle apbr 3137 May 15 16:20 osntabst.s --rw-r--r-- 1 oracle apbr 9 May 15 16:19 psoliblist --rw-r--r-- 1 oracle apbr 39 May 15 16:21 sysliblist - -./mesg: --r--r--r-- 1 oracle apbr 183296 Jul 11 1995 oraus.msb --r--r--r-- 1 oracle apbr 878114 Jul 11 1995 oraus.msg - -./public: --r--r--r-- 1 oracle apbr 5187 Jun 29 1995 ocidfn.h - -Jon - -------------------------------------------------------------------------------- -Jon Meek Tue, 18 Feb 1997 - -This was for Oracle 7.2.2.3.0 (client side for DBD:Oracle build) and -SQL*net v2. I have heard that sqlnet.ora might not be needed. - -ls -lR oracle -oracle: -total 2 -drwxr-xr-x 3 meekj apbr 512 Nov 3 11:46 network/ - -oracle/network: -total 2 -drwxr-xr-x 2 meekj apbr 512 Nov 3 11:46 admin/ - -oracle/network/admin: -total 6 --rw-r--r-- 1 meekj apbr 309 Nov 3 11:46 sqlnet.ora --rw-r--r-- 1 meekj apbr 1989 Nov 3 11:46 tnsnames.ora - -------------------------------------------------------------------------------- - -From: Lack Mr G M -Date: Thu, 23 Jan 1997 18:24:03 +0000 - - I noticed the appended in the README.clients file of the DBD-Oracle -distribution. My experience is somewhat different (and simpler). - - On Irix5.3 (ie. what this user was using) I built DBI and DBD-Oracle -on a system with Oracle and Pro*C installed. I tested it on another -system (where I knew an oracle id). I installed it from a third (which -had write rights to the master copies of the NFS mounted directories), -but this didn't have Oracle installed. - - Having done this all of my systems (even those without a hint of -oracle on them) could access remote Oracle servers by setting TWO_TASK -appropriately. SQL*Net didn't seem to come into it. - - The dynamically-loadable library created (auto/DBD/Oracle/Oracle.so) -contains no reference to any dynamic Oracle library. - - Exactly the same happened for my Solaris systems. - - From: James Cooper - > [...], what do I need in addition to perl5 to access an Oracle database - > on another system from a unix box (Solaris 2.5) that doesn't have an - > oracle database running on it ? - > - > In other words are their some oracle shared objects, etc. I need ? - -I don't have experience with Solaris, but on IRIX 5.3, I simply installed -SQL*Net ($ORACLE_HOME/network/admin/*) and the OCI libraries which are in -$ORACLE_HOME/lib. You'll also need the header files from -$ORACLE_HOME/sqllib/public/*.h and $ORACLE_HOME/rdbms/demo/*.h (you won't -need them all, but you can get rid of them after DBD::Oracle compiles). - -So just put that stuff on your client box and install DBI and DBD::Oracle -there. Once DBD::Oracle is installed you can remove the OCI libraries and -headers (make sure to keep SQL*Net!) - -------------------------------------------------------------------------------- -OS/Oracle version: Solaris 2 and Oracle 7.3 - -Problem: DBD::Oracle works on the database machine, but not from remote -machines (via TCP). SQL*Plus, however, does work from the remote machines. - -Cause: $ORACLE_HOME/ocommon/nls/admin/data/lx1boot.nlb is missing - -Solution: Make sure $ORACLE_HOME/ocommon is available on the remote machine. - -This was the first time I had used DBD::Oracle with Oracle 7.3.2. Oracle -7.1 has a somewhat different directory structure, and seems to store files -in different places relative to $ORACLE_HOME. So I just hadn't NFS -exported all the files I needed to. I figured that as long as SQL*Plus -was happy, I had all the necessary files to run DBD::Oracle (since that -was always the case with 7.1). But I was wrong. - -James Cooper - -------------------------------------------------------------------------------- -Subject: Re: Oracle Licencing... -Date: Thu, 15 May 1997 11:54:09 -0700 -From: Mark Dedlow - -Please forgive the continuation of this somewhat off-topic issue, -but I wanted to correct/update my previous statement, and it's -probably of interest to many DBD-Oracle users. - -> > In general, as I understand it, Oracle doesn't license the client runtime -> > libraries directly, rather they get you for SQL*NET. It is typically -> > about $100 per node. You have to have that licensed on any machine -> > that runs DBD-Oracle. - -Oracle recently changed policy. sqlnet now comes with RDBMS licenses. -If you have named RDBMS licenses, you can install sqlnet on as many -client machines as you have named licenses for the server. If you -have concurrent RDBMS licenses, you can install sqlnet on as many -client machines as you like, and only use concurrently as many -as you have concurrent server RDBMS licenses. - -OCI, Pro*C, et. al. only requires you to have a development license, -per developer. The compiled apps can be distributed unlimited. -The client where the client app resides must be licensed to use -sqlnet, by the above terms, i.e. by virtue of what the licenses on -the server are that the client is connecting to. - -This means one could legitimately distribute DBD-Oracle in compiled form. -Probably not recommended :-) - -But is does mean one can compile DBD-Oracle and distribute it internally -to your org without more licensing, as long as the targets have sqlnet. - -Obviously, this is not a legal ruling. I don't work for Oracle. -But this is what my sales rep tells me as of today. - -Mark -------------------------------------------------------------------------------- - -From: Wintermute - -Ok, you may think me daft for this but I just figured out what was -necessary in using DBI/DBD:Oracle on a machine that needs to access a -remote Oracle database. - -What the docs tell you is that you just need enough of Oracle installed -to compile it. They don't say that you need to keep that "just enough" -around for the DBI to work properly!! - -So here's my predicament so that others might benefit from my bumbling. - -I needed to install Perl, DBI, and DBD:Oracle on a machine running a -Fast Track web server (hostname Leviathan) that is to access a remote -Oracle database (henceforth called Yog-Sothoth (appropriate for the -beast that it is)). Leviathan doesn't have enough space for the 500M -install that Oracle 7 for Solaris 2.5.1 wants so I had to figure out a -way to get things done. Here's a brief list of the steps I took for -Leviathan. - -1. Got the GCC binary dist for Solaris 2.6 and installed -2. Got Perl 5.004_01 source/compiled/installed -3. Got the DBI .90 compiled/installed -4. Got DBD:Oracle... - - (and here's where it gets interesting). - - I exported the /opt/oracle7 directory from Yog-Sothoth to -Leviathan in -order to compile DBD:Oracle, then umount'ed it afterwards. Tried 'make -test' after it had compiled and watched it flounder and fail. For the -life of me I couldn't figure out why this could be so, so I went back -and adjusted my TWO_TASK/ORACLE_USERID env vars. - No luck. - Wash/Rinse/Repeat. - Still no luck. -I started to get desperate about this time, so instead of screwing with -it anymore I installed the module under the Perl heirarchy just to be -done for the moment with it (figuring that the 'make test' script could -be fallible). I neglected to mention that the errors I was getting were -coming from the Oracle database on the remote machine, so I knew it -worked in part, just not well enough to hold the connection for some -reason. - -After having no luck with my own Perl connect script I tried remounting -the nfs volume with Oracle on it and setting ORACLE_HOME to it. When I -ran that very same Perl script it WORKED! Well sort of. None of the -short connection methods worked, I was forced to use the long method of -connecting IE: name/password@dbname(DESCRIPTION=(ADDRESS=(...etc.etc. - -So here I am figuring that I'm doing something right, but there's -something I'm missing. Well it turns out that it's not me, it's the -machine that's missing it. If you are going to be using the DBD:Oracle -driver with DBI, you'll need more than just it after compile time, -you'll need some Oracle files as well. - -(BTW I'm running Oracle 7.3.2.2.0) - -You'll need everything in /var/opt/oracle (on the machine that houses -Oracle), as well as $ORACLE_HOME/ocommon/nls. Why National Language -Support is needed I'll never know. ocommon/nls has to reside under the -directory your $ORACLE_HOME points to, and it's best to leave -/var/opt/oracle/'s path alone. - -When I made these adjustments on the Oracle'less box and tried the 'make - -test' again, it ran through without a hitch. I'll be doing some more -intensive things with it from here on out and if anything changes I'll -let you all know, however this seems odd that nothing is mentioned in -the documentation about what residual files need to be around after -compiling the DBD:Oracle for it to work successfully. - -Like I said, don't flame me for being stupid, but I just had to get this -story off my chest since I've been puzzling over it all day and I feel -that other people may want to do the same thing as I did, and will run -into the same problems. - --- Wintermute - -------------------------------------------------------------------------------- diff --git a/README.help.txt b/README.help.txt index cfbe9932..7e68453c 100644 --- a/README.help.txt +++ b/README.help.txt @@ -7,132 +7,6 @@ same or similar problems may exist on other systems or versions. Most of this mess is due to Oracle's fondness for changing the build/link process for OCI applications between versions. -------------------------------------------------------------------------------- -Error: 'UV' not in typemap in Oracle.xs, line ... - -You're using Perl 5.5.3. Perl 5.5.3 is very old and and upgrading -to at least 5.6.1 is recommended. The DBI itself has required -perl >= 5.6.0 since DBI 1.38, August 2003. - -Meanwhile, edit Oracle.xs and change each UV to an IV, change newSVuv to newSViv, -cross your fingers, and avoid using longer, bigger, wider than 2GB, or less than zero! -This is a hacked DBD::Oracle and not recommended for production use. - -------------------------------------------------------------------------------- -If you get compiler errors refering to Perl's own header files -(.../CORE/*.h) then there is something wrong with your installation. -It is best to use a Perl that was built on the system you are trying to -use and it's also important to use the same compiler that was used to -build the Perl you are using. - -------------------------------------------------------------------------------- -Assorted runtime problems... - -Ensure that the version of Oracle you are talking to is the same one -you used to build your DBD::Oracle module. - -Try building perl with 'usemymalloc' disabled. -Try building perl with 'threads' enabled (esp for Oracle >= 8.1.6). - -Try removing "-lthread" from $ORACLE_HOME/lib/ldflags and/or -$ORACLE_HOME/lib/sysliblist just for the duration of the DBD::Oracle build -(but I can't really recommend this approach as it may cause subtle -problems later) - -If you find a memory leak that you can isolate to DBD::Oracle, and you're -using a perl built with threading enabled, first try rebuilding perl without -support for threads. Apart from making perl run faster it may also fix the leak. -Please report memory leaks, with a small self-contained test script, -to dbi-users@perl.org. - -------------------------------------------------------------------------------- -Bad free() warnings: - -These are generally caused by problems in Oracle's own library code. -You can use this code to hide them: - - $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /^Bad free/ } - -If you're using an old perl version (below 5.004) then upgrading will -probably fix the warnings (since later versions can disable that warning) -and is highly recommended anyway. - -Alternatively you can rebuild Perl without perl's own malloc and/or -upgrade Oracle to a more recent version that doesn't have the problem. - -------------------------------------------------------------------------------- -Can't find libclntsh.so: - -Dave Moellenhoff : libclntsh.so is the shared -library composed of all the other Oracle libs you used to have to -statically link. -libclntsh.so should be in $ORACLE_HOME/lib. If it's missing, try -running $ORACLE_HOME/lib/genclntsh.sh and it should create it. - -Also: Never copy libclntsh.so to a different machine or Oracle version. -If DBD::Oracle was built on a machine with a different path to libclntsh.so -then you'll need to set set an environment variable, typically -LD_LIBRARY_PATH, to include the directory containing libclntsh.so. - -But: LD_LIBRARY_PATH is typically ignored if the script is running set-uid -(which is common in some httpd/CGI configurations). In this case -either rebuild with LD_RUN_PATH set to include the path to libclntsh -or create a symbolic link so that libclntsh is available via the same -path as it was when the module was built. (On Solaris the command -"ldd -s Oracle.so" can be used to see how the linker is searching for it.) - - -------------------------------------------------------------------------------- -Error while trying to retrieve text for error ...: - -From Lou Henefeld : We discovered that we needed -some files from the $ORACLE_HOME/ocommon/nls/admin/data directory: - lx00001.nlb, lx10001.nlb, lx1boot.nlb, lx20001.nlb -If your national language is different from ours (American English), -you will probably need different nls data files. - - -------------------------------------------------------------------------------- -ORA-01019: unable to allocate memory in the user side - -From Ethan Tuttle : My experience: ORA-01019 errors -occur when using Oracle 7.3.x shared libraries on a machine that -doesn't have all necessary Oracle files in $ORACLE_HOME. - -It used to be with 7.2 libraries that all one needed was the tnsnames.ora -file for a DBD-Oracle client to connect. Not so with 7.3.x. I'm not sure -exactly which additional files are needed on the client machine. - -Furthermore, from what I can tell, the path to ORACLE_HOME is resolved and -compiled into either libclntsh.so or the DBD-Oracle. Thus, copying a -minimal ORACLE_HOME onto a client machine won't work unless the path to -ORACLE_HOME is the same on the client machine as it is on the machine -where DBD-Oracle was compiled. - -ORA-01019 can also be caused by corrupt Oracle config files such as -/etc/oratab. - -ORA-01019 can also be caused by using a different version of the -message catalogs ($ORACLE_HOME/ocommon/nls/admin/data) to that used -when DBD::Oracle was compiled. - -Also try building with oracle.mk if your DBD::Oracle defaulted to proc.mk. - -------------------------------------------------------------------------------- -SCO - For general help enabling dynamic loding under SCO 5 - - http://www2.arkansas.net/~jcoy/perl5/ - -------------------------------------------------------------------------------- -AIX - warnings like these when building perl are not usually a problem: - -ld: 0711-415 WARNING: Symbol Perl_sighandler is already exported. -ld: 0711-319 WARNING: Exported symbol not defined: Perl_abs_amg - -When building on AIX check to make sure that all of bos.adt (13 pieces) -and all of bos.compat (11 pieces) are installed. - -Thanks to Mike Moran for this information. ------------------------------------------------------------------------------- AIX 4 - core dump on login and similar problems @@ -376,13 +250,6 @@ Try each of these in turn (follow each with a make && make test): perl Makefile.PL -n LIBCLNTSH let me know if any of these help. -------------------------------------------------------------------------------- -Some runtime problems might be related to perl's malloc. - -This is a long shot. If all else fails and perl -V:usemymalloc says -usemymalloc='y' then try rebuilding perl using Configure -Uusemymalloc. -If this does fix it for you then please let me know. - =============================================================================== Hang during "repetitive connect/open/close/disconnect" test: diff --git a/README.java.txt b/README.java.txt deleted file mode 100644 index 8958df27..00000000 --- a/README.java.txt +++ /dev/null @@ -1,322 +0,0 @@ -README.java.txt - -This file relates to a specific problem on Solaris platforms -for Oracle 8.1.6 (and possibly later versions) where loading -DBD::Oracle fails with an error message like: - - ``You must install a Solaris patch to run this version of - the Java runtime. - Please see the README and release notes for more information.'' - -The problem seems to be that: - -1/ By default, the Oracle shared library contains a ``Radius - authentication module'' that is implemented in Java. -2/ The Java implementation requires that the thread library is - also linked into the application. -3/ For some inexplicable reason the thread library has to be - linked to the executable that's doing the dynamic loading. - It's is not sufficient to link -lthread to DBD::Oracle. - -There are several ways to workaround this: - -1/ Remove the Radius authentication module if you don't need it. - This requires you to perform surgery on the Oracle installation. - (If the name Radius doesn't mean anything to you and you're - the person maintaining the Oracle installation then you almost - certainly don't need it.) - -2/ Use the LD_PRELOAD environment variable to force the pre-loading - of the thread library. Note that this must be set before perl - starts, you can't set it via $ENV{LD_PRELOAD} within the script. - -3/ Link the thread library to your perl binary. - You can do that either by (re)building perl with thread support - or, I believe, it should be possible to issue a magic 'ld' command - to add linkage to the thread library to an existing perl executable. - (But you'll need to work that one out yourself. If you do please let - me know so I can add the details here to share with others.) - -Most of this information comes from Andi Lamprecht, to whom I'm very -grateful indeed. - -I've included below two of his email messages, slightly edited, where -he explains the procedure for options 1 and 2 above. I've also -appended a slight reworking of option 1 from Paul Vallee. And I've later -added some more useful messages from other people. - -Tim. - ----- - - -From: andi@sunnix.sie.siemens.at - -Have managed it to get DBD to work with Oracle 8i without these nasty Java -error! It seems to be that a thing called "NAU" links in a radius -athentication module which is written in Java and this causes the -additional java libraries in the libclntsh.so. After throwing it all out -DBD tests ran successfully. - -The steps to take are: - - - shut down Oracle server if you have one running in the installation - you're about to modify. - - take a backup copy of your Oracle installation! You have been warned! - - - go to $ORACLE_HOME/network/lib (or it maybe (also?) in $ORACLE_HOME/oas/lib) - - rebuild nautab.o with: - - make -f ins_nau.mk NAU_ADAPTERS="IDENTIX KERBEROS5 SECURID" nautab.o - - This build a new nautab.o without the radius authentication module. - - - go to $ORACLE_HOME/lib - - edit file "ldflags" and delete all occurences of "-lnrad8" and "-ljava" - and "-[LR]$ORACLE_HOME/JRE/lib/sparc/native_threads" - - - go to $ORACLE_HOME/bin - - build a new libclntsh.so with: - - genclntsh - - - start up Oracle - - - go back to the DBD-* directory and build the Oracle driver with: - - perl Makefile.PL; make; make test - -This worked for me, the database is still operational, MAYBE SOME JAVA -STUFF ISN'T WORKING. Better someone else with more experience in java -finds out ... - -The problem seems to be a dynamic linking issue. Whenever java virtual -machine is loaded, some symbols are missing (with java 1.2.2_05 these -_thread_something symbols where not found, even with linked-in -libthread.so, with java 1.1.8 some _lseek or so symbols couldn't be -resolved). Seems Oracle did a good job in integration of Java in the -database ... - -Ok, should go out now 'cause its a beatiful wheater here in Vienna! - -Greetings -A. Lamprecht - ------------ - - -From: andi@sunnix.sie.siemens.at - -For some reason libthread.so.1 isn't included as dynamic object in perl -binary and so symbols aren't found. - -The interesting output of LD_DEBUG=symbols: -symbol=thr_getstate; dlsym() starting at file=/usr/local/bin/perl -symbol=thr_getstate; lookup in file=/usr/local/bin/perl [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libsocket.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libnsl.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libdl.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libm.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libc.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libcrypt_i.so.1 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libmp.so.2 [ ELF ] -symbol=thr_getstate; lookup in file=/lib/libgen.so.1 [ ELF ] -ld.so.1: /usr/local/bin/perl: fatal: thr_getstate: can't find symbol - -This list looks exactly like the one you get when ldd-ing the perl binary. -There is an option to the dynamic linker "LD_PRELOAD" and if you set it with - - LD_PRELOAD=/lib/libthread.so.1 - export LD_PRELOAD - -before starting any DBD::oracle app, the app works! (Note that this must -be set before perl starts, you can't set it via $ENV{LD_PRELOAD} within -the script.) - -It looks like after libjava and libjvm is loaded, the library search path -is somehow stripped to the one of the perl binary ... - -[That looks like a Solaris bug] - -Hope this helps. - -A. Lamprecht ------------ - - -From: Paul Vallee - -Andi is right. Three cheers for Andi!!! :-) - -Final Summary (this is mostly Andi's work summarized here) - -1. Copy your ORACLE_HOME in it's entirety to a new directory. -cp -r $ORACLE_HOME $ORACLE_HOME.nojava - -2. Set your ORACLE_HOME variable to the new one. Save the old one for reference. -export OLD_ORACLE_HOME=$ORACLE_HOME -export ORACLE_HOME=$ORACLE_HOME.nojava - -3. cd $ORACLE_HOME/network/lib (or it maybe (also?) in $ORACLE_HOME/oas/lib) -This is your new ORACLE_HOME - the temporary one that will soon be without -Java or Radius. - -4. build nautab.o with -make -f ins_nau.mk NAU_ADAPTERS="IDENTIX KERBEROS5 SECURID" nautab.o - -5. go to $ORACLE_HOME/lib -edit file "ldflags" and delete all occurences of "-lnrad8" and "-ljava" -and "-[LR]$ORACLE_HOME/JRE/lib/sparc/native_threads" -I wrote this little pipeline to do this. -sed 's/-lnrad8//g' < ldflags | \ -sed 's/-ljava//g' | \ -sed "s%-L$OLD_ORACLE_HOME/JRE/lib/sparc/native_threads%%g" | \ -sed "s%-R$OLD_ORACLE_HOME/JRE/lib/sparc/native_threads%%g" | > newldflags -If you look at newldflags, and like it, then run: -cp ldflags oldldflags; cp newldflags ldflags - -6. go to $ORACLE_HOME/bin and build a new libclntsh.so with "genclntsh" -genclntsh - -7. go to your DBD::oracle install directory and go through the regular -install process. -perl Makefile.PL; make; make install -(I find the make test less useful than my test.pl perl file.) - -8. Set LD_LIBRARY_PATH=$ORACLE_HOME/lib. -This part is very important - remember that at this stage ORACLE_HOME is set -to the nojava home. Make this permanent by explicitly setting -LD_LIBRARY_PATH to the nojava lib directory in your .profile. -This is the step that stalled me - thanks again to Andi. - -9. Test this out. I use the following command which fails -nicely if we've failed, and is very quiet if we've succeeded: - perl -MDBD::Oracle -e 0 -there should be no output. Congratulations. - -10. Get rid of everything other than libclntsh.so in your new ORACLE_HOME - -the rest is a waste of space. -cd $ORACLE_HOME; cd .. -mv $ORACLE_HOME $ORACLE_HOME.rmme -mkdir $ORACLE_HOME; mkdir $ORACLE_HOME/lib -cp $ORACLE_HOME.rmme/lib/libclntsh.so $ORACLE_HOME/lib - -11. Run test.pl again just to be sure it still works. - -12. If test.pl is still working, then we can reclaim space with -rm -fr $ORACLE_HOME.rmme - -Note that in my opinion this is a workaround - there is no reason on the -face of it that I can fathom that we shouldn't be able to use DBD::Oracle to -connect to Oracle with Java compiled in. (?) - -Enjoy, -Paul Vallee -Principal -The Pythian Group, Inc. ------------------------------------------------------------------------------- - -From: Peter Ludemann - -Here's a different way for ensuring that LD_PRELOAD has been set: - - unless (($ENV{LD_PRELOAD}||'') =~ /thread.so/) { - $ENV{LD_PRELOAD} = '/lib/libthread.so'; - exec($^X, '-w', $0, @ARGV); - } - -This hasn't been rigorously tested, but it seems to do the trick, at -least on Solaris 7 with Oracle 8. - ------------------------------------------------------------------------------- - -From: VG - -I've had luck with adding the following at the top of my program: - -use DynaLoader; -Dynaloader::db_load_file("/usr/lib/libthread.so", 0x01); - -(Others have reported this nor working for them.) - ------------------------------------------------------------------------------- - -From: daver@despair.tmok.com (Dave C.) -Subject: Re: DBI::DBD with Oracle 8i -Newsgroups: comp.lang.perl.modules - -It looks like a lot of people are having this problem.... - -I managed to solve it. I'm running Oracle 8.1.6, Solaris 8, Perl 5.6.0, -and the latest DBI/DBD modules. - -I did some experimentation and discovered that the root of the problem -was that libclntsh.so was linking with nautab.o. For some reason, -nautab.o was linked with this RADIUS authentication (?) thing that was -calling into Java (even though I don't use that particular functionality.) - -So, what I had to do was generate a libclntsh.so that linked with a -nautab.o that didn't require the radius (and thus the java). I then -forced the Oracle DBD to link with my library and installed it, and it -worked. - -Here's the step-by-step: - -To do this, first copy the "genautab" and "genclntsh" scripts to a -scratch directory. By default "genautab" apparently generates some -default network authentication stub without a lot of options (which was -okay for me.) - -I ran: - - ./genautab >nautab.s - as -P nautab.s - -After this step you should have a "nautab.o" file. - -Now, you must must modify "genclntsh" to produce your custom clntsh -library (which I called "perlclntsh" so I wouldn't mess up the original -Oracle library.) So I went into the file and modified CLNT_NAM to read -"perlclntsh". I also changed LIB_DIR to put the resulting library in -my current directory: (LIB_DIR=`pwd`) - -Also, instead of creating the library, I modified the script to just -echo the command. Search for "# Create library" and put "echo " before -{$LD} ${LD_RUNTIME}... Now, when you run "./genclntsh" you should get -a large command. Redir this command to a file "./genclntsh >t" - -Now, edit this file and remove all references to java libraries (get -rid of all "-ljava" instances, at least, and you may need to delete -other stuff, like -lnative_threads.) . Run your script: "sh ./t". -After some time you should wind up with a "libperlclntsh.so.8.0". -This is your custom library any of the java stuff linked in. - -Then copy this lib to /usr/local/lib and create a softlink -"libperlclntsh.so" to "libperlclntsh.so.8.0" (or copy it wherever you -want...) - -Then you have to force DBD to link with this library instead of linking -with the libclntsh.so provided by Oracle. - -Basically what I did was follow the normal DBD-Oracle directions. I -then edited the resulting Makefile manually and changed all references -of libclntsh.so to libperlclnt.so (ie, -lclntsh to -lperlclntsh) I -also changed the LDDLFLAGS and LDFLAGS and appended "-L/usr/local/lib --R/usr/local/lib -L/usr/ucblib -R/usr/ucblib -lucb". (for some reason -the resulting DBD wanted to link with ucb) Run "make" and rebuild the -DBD. Now "make test" should pass. - -Note that this was a fairly long (couple of hours) series of trial and -error before I finally got this to work. Your system may be different -and you may encounter your own linking problems, etc. - -Disclaimer: This may not work for you, but it worked for me. Even if it -does work for you there is no guarantee that the resulting module will -function correctly and won't hose your database, etc... - -I forgot to mention that in script resulting from genclntsh you must -tell it to use _your_ nautab.o for linking, not the oracle lib one. -Oops. - --Dave - diff --git a/README.mkdn b/README.mkdn index f9c0ce53..9df11205 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.46 +version 1.47_00 # SYNOPSIS diff --git a/README.sec.txt b/README.sec.txt deleted file mode 100644 index 72920db6..00000000 --- a/README.sec.txt +++ /dev/null @@ -1,142 +0,0 @@ -I have no intention of becoming a channel for Oracle Support Services -but this is a significant security hole and so I'm making an exception. - ------ Forwarded message from Oracle Support Services ----- - -Date: Fri, 7 May 1999 06:29:09 -0700 -From: Oracle Support Services -Subject: SUID Security Issue - -Platform: UNIX - -Distribution: Internal & External - -Problem Subject Line: SUID Security - -Product: Oracle Enterprise Manager 2.0.4 - Oracle Data Server - -Oracle Version: 8.0.3, 8.0.4, 8.0.5, 8.1.5 - -Component: Intelligent Agent - Oracle Data Server - -Component Version: 8.0.3, 8.0.4, 8.0.5, 8.1.5 - -Sub-Component: N/A - -Platform Version: All Unix Versions. - -Errors: N/A - -Revision Date: 6-March-1999 - -Problem Description: - -On UNIX platforms, some executable files have the setuid (SUID) -bit on. It may be possible for a knowledgeable user to use -these executables to bypass your system security by elevating -their operating system privileges. Oracle Corporation has -identified issues regarding executables with SUID set in -Oracle releases 8.0.3, 8.0.4, 8.0.5 and 8.1.5 on UNIX platforms -only. This problem will be fixed in Oracle releases 8.0.6 and -8.1.6. - -Depending on your Oracle installation, the available patch will 1) -correct the SUID bits on applicable files, and/or 2) delete the -oratclsh file. This shell script should be run immediately, and also -should be run after each relink of Oracle. - -You can download the patch from Oracle Support?s MetaLink website by -going to the following URL, -http://support.oracle.com/ml/plsql/mlv15.frame?call_type=download&javaFlag=JAVA. -Once you are in this page, select 'Oracle RDBMS' as the product -and then click on the 'Go' button. Then download patch named 'setuid.' - -Please contact Oracle Worldwide Support for any additional issues. - ------ End forwarded message ----- - -Date: Sat, 08 May 1999 19:12:52 -0700 -From: Mark Dedlow - -I went to the URL listed for the patch, but it appears you can't get to -it directly. It requires a Oracle Metalink account, and even then, you -have to follow a bunch of links to get it, you can't go direct (at -least I couldn't at the URL in the announcement). - -You don't really need the patch however, it's just a shell script that -in effect does chmod -s on everything in $ORACLE_HOME/bin except -'oracle' and 'dbsnmp' (needed only for OEM or SNMP). - -Also, although the patch didn't address the issue, make sure _nothing_ -below ORACLE_HOME is owned by root. There are some installations that -make certain files setuid to root (files that are trivial to compromise). - -Mark - - ------------------------------------------------------------------------------- - -From: Dan Sugalski -Date: Mon, 10 May 1999 09:13:28 -0700 - -The patch actually removes the setuid bit on a number of oracle -executables. The 'unset' list is: - -lsnrctl oemevent onrsd osslogin tnslsnr tnsping trcasst trcroute cmctl -cmadmin cmgw names namesctl otrccref otrcfmt otrcrep otrccol oracleO - -While the 'must set' list is: - -oracle dbsnmp - -The shell script to fix the bits properly was posted to the oracle list -running at telelists.com. Check the archives there for it if you want. -(www.telelists.com) I think it's also gone out to one of the BUGTRAQ -lists, and some of the CERTs might have it too. - - Dan - ------------------------------------------------------------------------------- - -Date: Wed, 12 May 1999 11:49:45 -0700 -From: Mark Dedlow - -> The patch actually removes the setuid bit on a number of oracle -> executables. The 'unset' list is: -> -> lsnrctl oemevent onrsd osslogin tnslsnr tnsping trcasst trcroute cmctl -> cmadmin cmgw names namesctl otrccref otrcfmt otrcrep otrccol oracleO - -Actually, there's a little more than that. For each item in that list, -it also looks for a version of the file with a 0 or O appended to it -(these are backups the link makefiles create), so the above list isn't -exactly complete. - -The important issues are simply: - - o *ONLY* $ORACLE_HOME/bin/oracle requires setuid bit set for - the Oracle RDBMS and tools to function. - - o *IF* you run dbsnmp, it must be setuid. (If you don't know what dbsnmp - is, you're probably not running it -- it's a remote monitoring/control - daemon) - -Armed with that knowledge, you can use any technique you like to achieve -the desired results. For example, this achieves it: - -find $ORACLE_HOME/bin -perm -2000 ! -name oracle ! -name dbsnmp | xargs chmod -s - -Mark - ------------------------------------------------------------------------------- - -One further note I'll pass on anonymously and without comment: - -> please include something like: "After removing the setuid bits, slap -> your system administrator for running root.sh as root without actually -> reading it first." -> :) - ------------------------------------------------------------------------------- diff --git a/README.win32.txt b/README.win32.txt deleted file mode 100644 index e3ad66db..00000000 --- a/README.win32.txt +++ /dev/null @@ -1,236 +0,0 @@ -In general, on Windows, it's best to just use ActiveState Perl and the -PPM package manager to install a pre-built version of DBD::Oracle however only version 1.17 is available there. - -If you built Perl with gcc, read README.wingcc.txt as well as this file. - - -Oracle Instant Client 11.1.0.6.0 Notes - -So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value -in the environment variables. - -As well IC 11 seems to have trouble finding the .ORA files. A quick fix for this is to add "TNS_ADMIN" -to the environment variables and point it to where your .ORA files are. - - ---- other information, some of which is out of date --- - -DBD-Oracle for Windows and Oracle Instantclient and 10XE (Express Edition) -By: John Scoles Scoles@ptyhian.com -The Pythian Group - -The preferred method of getting DBD::Oracle is to use a pre-built version from the ActiveState -repository, which can be installed with PPM. - -Compiling and installing DBD::Oracle 1.18 or later on a windows 2000 professional or XP OS for use -with Oracle instantClient ver 10.2.0.1 & 10.1.0.5 or Oracle XE requires only a few downloads and -a minimal number of environment setting. The procedures below were tested on a clean -Windows platform having no Oracle or other development environment installed. - -1) The first part of the process is to download and install the latest version of - Active Perl from http://www.activeperl.com/. - -2) Use the PPM application to get the latest version of DBI - -3) Download the latest DBD::Oracle from http://svn.perl.org/modules/dbd-oracle/trunk/ - -4) Download and unzip the Oracle Instant Client (10.2.0.1 or 10.1.0.5) 32 bit from - http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html - You will need all three of these products - i. Instant Client Package - Basic - ii. Instant Client Package - SQL*Plus: - iii. Instant Client Package - SDK: - or - - install oracle 10XE http://www.oracle.com/technology/products/database/xe/index.html - -5) You will now need the Microsoft Visual C++ toolkit 2003. Unfortunately this product is no longer available from Microsoft. - The file name was VCToolkitSetup.exe and is available at this mirror site http://www.filewatcher.com/m/VCToolkitSetup.exe.32952488.0.0.html at the time of writing. - Microsoft's replacement for this tool kit is Visual C++ 2005 Express Edition and all attempts to compile DBD::Oracle with this product fail. It has been successfully compiled - using a complete edition of Microsoft Visual Studio 2005. - Download and then install this product. - -6) You will also need the Windows SDK. Which can be found at - http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en - You have the choice to of either to download the entire SDK and install or run an online install from the page. - Both have been tested and proven to work. - -7) Next download and install the Microsoft .net framework 1.1 skd from - http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&displaylang=en - -8) You will also need a copy of nmake.exe which you can download here http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe - -9) Enough Downloading and installing go have a coffee. - -10) You should at this time attempt to connect to an Oracle database with the version SQL*Plus that - you installed in step 4. If you are unable to connect at this stage then any problems you encounter - later may have nothing to do with DBD::Oracle - -11) On the path where you installed Visual C++ find and edit the vcvars32.bat file as follows. You may have to modify - these path values depending where you installed the products on you computer, - - i. Add the local path to the windows platform SDK include directory to the Set INCLUDE - Command Line to include the needed files from the Windows SDK. - - e.g. "C:\Program Files\Microsoft Platform SDK\Include;" - - ii. Add the local path to the .net Vc7 lib directory to the Set LIB command - to include the needed library file from the .Net SKD - - e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; - - iii. Add the local path to the windows platform SDK Lib directory to the Set Lib command - to include the needed library files from the Windows SDK - - e.g. C:\Program Files\Microsoft Platform SDK\Lib; - -12) Open a Windows Visual C++ command window from the start menu. - -13) Add the path to the instant client to the Path command. If you are compiling aginst a 10XE db/client then you can skip steps - 12 to 14. - e.g. PATH = C:/Oracle/instantclient;%PATH% - -14) Using the "Set" command add "ORACLE_HOME=path to Instant client" to the environment variables. - e.g. Set ORACLE_HOME=C:\Oracle\instantclient - -15) Using the "Set" command add "NLS_LANG=.WE8ISO8859P15" to the environment variables. The globalization variable is required, - with this or another compatible value, by Oracle instantclient in order for it to compile correctly. - e.g. Set NLS_LANG=.WE8ISO8859P15 - -16) Using the "Set" command add "ORACLE_USERID=test/test@test" substituting test with the username/password@database - you wish to run the make test files against. - Note: it is not necessary to do this step for the compile and install to work. - However: The self-test programs included with Oracle-DBD will mostly fail. - -17) Move to the DBD-Oracle directory in the Visual C++ window DOS prompt and enter the following. - - c:\oracle-dbd\>perl Makefile.PL - - The Makefile should then run and compile Oracle-dbd without reporting any errors. - -18) From this DOS prompt enter the following command - - c:\oracle-dbd\>nmake - - The Visual C++ make executable will then build you DBD-execuable. There should be no errors at this point. - -19) You can test the compile by either entering - - c:\oracle-dbd\>nmake test - - As long as you have given a valid user name, password and database name in step 15 you will see some results. If it appears to - run but you do not get a connection check the following. - - i. User name password and DB Name - ii. Ensure the a valid TNSNAMES.ORA file is in the Instantclient directory - iii. Attempt to log into the version of SQLPLUS that comes with Instantclient. - If you manage to log on use the username password and TNS name with - the Set ORACLE_USERID = and rerun the tests. - iv If you are compiling against 10XE and have skiped steps 12 to 14 try again bu this time carry out these steps - -20) You can now install DBD-Oracle into you system by entering the following command from the Visual C++ window dos prompt; - - c:\oracle-dbd\>nmake install - -21) You should now be able to run DBD-Oracle on you system - -09/30 2006 from asu - -DBD::Oracle 1.18a - -Linux, Debian unstable ( -DBI: 1.52 -perl v5.8.8 built for i486-linux-gnu-thread-multi -) - -Oracle Instant client (10.1.0.5) - -The problem is in Makefile.PL. In line 130 the function find_oracle_home -is used to guess a value form $ORACLE_HOME if it is not set explicitely. -This value is used in line 138 to setup the environment (regardless -which client is used). - -in line 1443 (sub get_client_version) sqlplus is used to get the -version string, but for the oracle instant client you must not set -$ORACLE_HOME (it will generate an error "SP2-0642: SQL*Plus internal -error state 2165, context 4294967295:0:0") - -A solution that worked for me was to set -local $ENV{ORACLE_HOME} = ''; -in line 1463 immediately before sqlplus is called (but I cannot tell if -this fails for full client installations) - - -11/30/05 -- John Scoles -I have confirmed that this Makefile.pl will work for both Oracle InstantClient -10.2.0.1 & 10.1.0.4 using same process the Andy Hassall uses. Starting with a clean OD -One needs only to get the latest version of Active Perl 5.8.7 use PPM to get DBI and then -install Microsoft Visual C++ toolkit, Windows SDK, and the Microsoft .net -framework 1.1. and modify the vcvars32.bat in C++ dir as follows - - 1) Add the local path to the windows platform SDK include directory to the - Set INCLUDE Command Line to include the needed files from the Windows SDK. - e.g. "C:\Program Files\Microsoft Platform SDK\Include;" - 2) Add the local path to the .net Vc7 lib directory to the Set LIB - command to include the needed library files from the .Net SKD - e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; - 3) Add the local path to the windows platform SDK Lib directory to the Set Lib - command to include the needed library files from the Windows SDK - e.g. C:\Program Files\Microsoft Platform SDK\Lib; - -If one happens to have visual studio installed you may not have to download additional MS products. - -12/01/05 --- John Scoles -Oracle 10XE -No big problem here as 10XE seems to use the instantclient as well. Just ensure your - NLS_LANG and ORACLE_HOME are set to the same directory that 10XE uses - - -10/07/05 --John Scoles -Andy Hassall Kindly added some changes to the Makefile.PL -so it will work for the Instant Client 10g on Windows OSs. Below is how he set -up his environment and the steps he preformed to get it to compile. - - Setting environment for using Microsoft Visual Studio .NET 2003 tools. - (If you have another version of Visual Studio or Visual C++ installed and wish - to use its tools from the command line, run vcvars32.bat for that version.) - - C:\Documents and Settings\andyh>d: - - D:\>cd cygwin\home\andyh\src\pythian - - D:\cygwin\home\andyh\src\pythian>set ORACLE_HOME=d:\lib\instantclient_10_2 - - D:\cygwin\home\andyh\src\pythian>set NLS_LANG=.WE8ISO8859P15 - - D:\cygwin\home\andyh\src\pythian>set PATH=d:\lib\instantclient_10_2;D:\Program F - iles\Microsoft Visual Studio .NET 2003\Common7\IDE;D:\Program Files\Microsoft Vi - sual Studio .NET 2003\VC7\BIN;D:\Program Files\Microsoft Visual Studio .NET 2003 - \Common7\Tools;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ - bin\prerelease;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ - bin;D:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;C:\WINNT\Mic - rosoft.NET\Framework\v1.1.4322;d:\Perl\bin\;C:\WINNT\system32;C:\WINNT;C:\WINNT\ - System32\Wbem;D:\Program Files\Microsoft SDK\Bin;D:\Program Files\Microsoft SDK\ - Bin\WinNT - - D:\cygwin\home\andyh\src\pythian>set ORACLE_USERID=test/test@test102 - - D:\cygwin\home\andyh\src\pythian>perl Makefile.PL - - - -4/27/04 -- Jeff Urlwin - -Do not untar this distribution in a directory with spaces. This will not work. - -i.e. C:\Program Files\ORacle\DBD Oracle Distribution is bad while -c:\dev\dbd-oracle-1.15 is good ;) - -9/14/02 -- Michael Chase - -Makefile.PL uses Win32::TieRegistry or Win32::Registry to find the -current Oracle Home directory if the ORACLE_HOME environment variable -is not set. If neither module is installed, you must set ORACLE_HOME -before running Makefile.PL. Since the registry location of the current -Oracle Home is in different locations in different Oracle versions, -it is usually safer to set ORACLE_HOME before running Makefile.PL. diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9f44e064..25a6c851 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.46'; + $DBD::Oracle::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -125,7 +125,7 @@ BEGIN { { package DBD::Oracle::dr; { - $DBD::Oracle::dr::VERSION = '1.46'; + $DBD::Oracle::dr::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; @@ -330,7 +330,7 @@ BEGIN { { package DBD::Oracle::db; { - $DBD::Oracle::db::VERSION = '1.46'; + $DBD::Oracle::db::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; @@ -1059,7 +1059,7 @@ SQL { package DBD::Oracle::st; { - $DBD::Oracle::st::VERSION = '1.46'; + $DBD::Oracle::st::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; @@ -1164,7 +1164,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.46 +version 1.47_00 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 2ed2a1f0..1dc84996 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.46'; + $DBD::Oracle::GetInfo::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.46 +version 1.47_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index afab5549..e4680021 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.46'; + $DBD::Oracle::Object::VERSION = '1.47_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.46 +version 1.47_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pm b/lib/DBD/Oracle/Troubleshooting.pm deleted file mode 100644 index 96e2f7d6..00000000 --- a/lib/DBD/Oracle/Troubleshooting.pm +++ /dev/null @@ -1,419 +0,0 @@ -package DBD::Oracle::Troubleshooting; -{ - $DBD::Oracle::Troubleshooting::VERSION = '1.46'; -} -BEGIN { - $DBD::Oracle::Troubleshooting::AUTHORITY = 'cpan:PYTHIAN'; -} -#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle - - -__END__ -=pod - -=head1 NAME - -DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle - -=head1 VERSION - -version 1.46 - -=head1 CONNECTING TO ORACLE - -If you are reading this it is assumed that you have successfully -installed DBD::Oracle and you are having some problems connecting to -Oracle. - -First off you will have to tell DBD::Oracle where the binaries reside -for the Oracle client it was compiled against. This is the case when -you encounter a - - DBI connect('','system',...) failed: ERROR OCIEnvNlsCreate. - -error in Linux or in Windows when you get - - OCI.DLL not found - -The solution to this problem in the case of Linux is to ensure your -'ORACLE_HOME' (or LD_LIBRARY_PATH for InstantClient) environment -variable points to the correct directory. - - export ORACLE_HOME=/app/oracle/product/xx.x.x - -For Windows the solution is to add this value to you PATH - - PATH=c:\app\oracle\product\xx.x.x;%PATH% - -If you get past this stage and get a - - ORA-12154: TNS:could not resolve the connect identifier specified - -error then the most likely cause is DBD::ORACLE cannot find your .ORA -(F, F, F) files. This can be -solved by setting the TNS_ADMIN environment variable to the directory -where these files can be found. - -If you get to this stage and you have either one of the following -errors; - - ORA-12560: TNS:protocol adapter error - ORA-12162: TNS:net service name is incorrectly specified - -usually means that DBD::Oracle can find the listener but the it cannot connect to the DB because the listener cannot find the DB you asked for. - -=head2 Oracle utilities - -If you are still having problems connecting then the Oracle adapters -utility may offer some help. Run these two commands: - - $ORACLE_HOME/bin/adapters - $ORACLE_HOME/bin/adapters $ORACLE_HOME/bin/sqlplus - -and check the output. The "Protocol Adapters" should include at least "IPC Protocol Adapter" and "TCP/IP -Protocol Adapter". - -If it generates any errors which look relevant then please talk to your -Oracle technical support (and not the dbi-users mailing list). - -=head2 Connecting using a bequeather - -If you are using a bequeather to connect to a server -on the same host as the client, you might have -to add - - bequeath_detach = yes - -to your sqlnet.ora file or you won't be able to safely use fork/system -functions in Perl. - -See the discussion at -L -and L -for more gory details. - -=head1 USING THE LONG TYPES - -Some examples related to the use of LONG types are available in -the C directory of the distribution. - -=head1 LINUX - -=head2 Installing with Instantclient .rpm files. - -Nothing special with this you just have to set up you permissions as follows; - -1) Have permission for RWE on '/usr/lib/oracle/10.2.0.3/client/' or the other directory where you RPMed to - -2) Set export ORACLE_HOME=/usr/lib/oracle/10.2.0.3/client - -3) Set export LD_LIBRARY_PATH=$ORACLE_HOME/lib - -4) If you plan to use tnsnames to connect to remote servers and your tnsnames.ora file is not in $ORACLE_HOME/network/admin, you will need to Export TNS_ADMIN=dir to point DBD::Oracle to where your tnsnames.ora file is - -=head2 undefined symbol: __cmpdi2 comes up when Oracle isn't properly linked to the libgcc.a library. - -In version 8, this was correctd by changing the SYSLIBS entry in -$ORACLE_HOME/bin/genclntsh to include -"-L/usr/lib/gcc-lib/i386-redhat-linux/3.2 -lgcc". - -I had tried this with no success as when this program was then run, the -error "unable to find libgcc" was generated. Of course, this was the -library I was trying to describe! - -It turns out that now it is necessary to edit the same file and append -"`gcc -print-libgcc-file-name`" (including the backquotes!). If you do -this and then run "genclntsh", the libclntsh is properly generated and -the linkage with DBD::Oracle proceeds properly. - -=head2 cc1: invalid option `tune=pentium4'" error - -If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. - -No real problem with the above however you will have to - -1) run Perl Makefile.PL - -2) edit the Makefile and remove the offending '-mtune=pentium4' text - -3) save and exit - -4) do the make install and it should work fine for you - -=head2 Oracle 9i Lite - -The advice is to use the regular Oracle9i not the lite version. - -Another great source of help was: http://www.puschitz.com/InstallingOracle9i.html - -just getting 9i and 9i lite installed. I use fvwm2(nvidia X driver) as -a window manager which does not work with the 9i install program, works -fine with the default Gnomish(nv X driver), it could have been the X -driver too. - -With Redhat9 it is REAL important to set LD_ASSUME_KERNEL to 2.4.1. - -I didn't try this but it may be possible to install what is needed by -only downloading the first disk saving some 1.3GB of download fun. - -I installed a custom install from the client group. The packages I -installed are the Programmers section and sqlplus. I noticed that the -Pro*C when on as a result of the checking the Programmers section I -assume. - -Once Oracle was installed properly the DBD::Oracle install went as -smooth as just about every other CPAN module. - -=head2 Oracle 10g Instantclient - -The Makefile.PL will now work for Oracle 10g Instantclient. To have both the Compile and -the test.pl to work you must first have the LD_LIBRARY_PATH correctly set to your -"instantclient" directory. (http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html) - -The present version of the make creates a link on your "instantclient" directory as follows -"ln -s libclntsh.so.10.1 libclntsh.so". It is needed for both the makefile creation and the compile -but is not need for the test.pl. It should be removed after the compile. - -If the Makefile.PL or make fails try creating this link directly in your "instantclient" directory. - -=head2 Oracle Database 10g Express Edition 10.2 - -To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY_PATH -as you would for an install against 10g Standard Edition, Standard Edition One, or -Enterprise Edition - -=head2 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 - -DBD::Oracle seems to hit some sort of bug with the above two versions of DB. -The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also -been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. - -So far there is no patch for this but here are some work arounds - - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); - ... - $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); - - or this way - - $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders - - or this way - - utf8::downgrade($parameter, 1); - -=head1 CYGWIN - -Makefile.PL should find and make use of OCI include -files, but you have to build an import library for -OCI.DLL and put it somewhere in library search path. -one of the possible ways to do this is issuing command - - dlltool --input-def oci.def --output-lib liboci.a - -in the directory where you unpacked DBD::Oracle distribution -archive. this will create import library for Oracle 8.0.4. - -Note: make clean removes '*.a' files, so put a copy in a safe place. - -=head2 Compiling DBD::Oracle using the Oracle Instant Client, Cygwin Perl and gcc - -=over - -=item 1 - -Download these two packages from Oracle's Instant Client for -Windows site -(http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/winsoft.html): - -Instant Client Package - Basic: All files required to run OCI, -OCCI, and JDBC-OCI applications - -Instant Client Package - SDK: Additional header files and an -example makefile for developing Oracle applications with Instant Client - -(I usually just use the latest version of the client) - -=item 2 - -Unpack both into C:\oracle\instantclient_11_1 - -=item 3 - -Download and unpack DBD::Oracle from CPAN to some place with no -spaces in the path (I used /tmp/DBD-Oracle) and cd to it. - -=item 4 - -Set up some environment variables (it didn't work until I got the -DSN right): - - ORACLE_DSN=DBI:Oracle:host=oraclehost;sid=oracledb1 - ORACLE_USERID=username/password - -=item 5 - - perl Makefile.PL - make - make test - make install - -=back - -Note, the TNS Names stuff doesn't always seem to work with the instant -client so Perl scripts need to explicitly use host/sid in the DSN, like -this: - - my $dbh = DBI->connect('dbi:Oracle:host=oraclehost;sid=oracledb1', - 'username', 'password'); - -=head2 SUN - -If you get this on a Solaris 9 and 10 box - - "Outofmemory! - Callback called exit. - END failed--call queue aborted." - -The solution may be as simple as not having you "ORACLE_HOME" Defined in the -environment. - -It seems that having it defined will prevent the error. - -=head2 VMS - -This is related to Oracle RDBMS 9.2 and later, since Oracle -made fundamental changes to oracle installation requirements -and factual installation with this release. - -Oracle's goal was to make VMS installation be more like on -*nix and Windows, with an all new Oracle Home structure too, -requiring an ODS-5 disk to install Oracle Home on instead of -the good old ODS-2. - -Another major change is the introduction of an Oracle generated -logical name table for oracle logical names like ORA_ROOT and all -its derivatives like ORA_PROGINT etc. And that this logical name -table is inserted in LNM$FILE_DEV in LNM$PROCESS_DIRECTORY. - - (LNM$PROCESS_DIRECTORY) - - "LNM$FILE_DEV" = "SERVER_810111112" - = "LNM$PROCESS" - = "LNM$JOB" - = "LNM$GROUP" - = "LNM$SYSTEM" - = "DECW$LOGICAL_NAMES" - -This ensures that any process that needs to have access to -oracle gets the environment by just adding one logical name table -to a central process specific mechanism. - -But as it is inserted at the very top of LNM$FILE_DEV it also -represents a source of misfortune - especially if a user with -enough privilege to update the oracle table does so (presumably -unintentionally), as an examble by changing NLS_LANG. - -PERL has the abillity to define, redefine and undefine (deassign) -logical names, but if not told otherwise by the user does it -in the first table in above list, and not as one would normally -expect in the process table. - -Installing DBI and DBD::Oracle has influence upon this since in -both cases a few environment variables are read or set in the -test phase. -For DBI it is the logical SYS$SCRATCH, which is a JOB logical. -For DBD-Oracle it is when testing a new feature in the Oracle -RDBMS: UTF8 and UTF16 character set functionality, and in order -to do this it sets and unsets the related environment variables -NLS_NCHAR and NLS_LANG. - -If one is not careful this changes the values set in the oracle -table - and in the worst case stays active until the next major -system reset. It can also be a very hard error to track down -since it happens in a place where one normally never looks. - -Furthermore, it is very possibly that some or all of the UTF tests -fails, since if one have a variable like NLS_LANG in his process -table, then even though 'mms test' sets it in the wrong table -it is not invoked as it is overruled by the process logical... - -The way to ensure that no logicals are set in the oracle table and -that the UTF tests get the best environment to test in, and that -DBI correctly translates the SYS$SCRATCH logical, use the -logical - - PERL_ENV_TABLES - -to ensure that PERL's behavior is to leave the oracle table alone and -use the process table instead: - - $ DEFINE PERL_ENV_TABLES LNM$PROCESS, LNM$JOB - -This tells PERL to use the LNM$PROCESS table as the default place to -set and unset variables so that only the perl users environment -is affected when installing DBD::Oracle, and ensures that the -LNM$JOB table is read when SYS$SCRATCH is to be translated. - -PERL_ENV_TABLES is well documented in the PERLVMS man page. - -Oracle8 releases are not affected, as they don't have the -oracle table implementation, and no UTF support. - -Oracle 9.0 is uncertain, since testing has not been possible yet, -but the remedy will not hurt :) - -=head1 Miscellaneous - -=head2 Crash with an open connection and Module::Runtime in mod_perl2 - -See RT 72989 (https://rt.cpan.org/Ticket/Display.html?id=72989) - -Apache2 MPM Prefork with mod_perl2 will crash if Module::Runtime is -loaded, and an Oracle connection is opened through PerlRequire (before -forking). - -It looks like this was fixed in 0.012 of Module::Runtime. - -=head2 bin_param_inout swapping return values - -See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) - -It seems that in some older versions of Oracle Instant Client -(certainly 10.2.0.4.0) when output parameters are bound with lengths -greater than 3584 the output parameters can be returned in the wrong -placeholders. - -It is reported fixed in Instant Client 11.2.0.2.0. - -=head1 AUTHORS - -=over 4 - -=item * - -Tim Bunce - -=item * - -John Scoles - -=item * - -Yanick Champoux - -=item * - -Martin J. Evans - -=back - -=head1 COPYRIGHT AND LICENSE - -This software is copyright (c) 1994 by Tim Bunce. - -This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. - -=cut - diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod new file mode 100644 index 00000000..7b4e6cd3 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -0,0 +1,167 @@ +#PODNAME: DBD::Oracle::Troubleshooting +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle + +=head1 VERSION + +version 1.47_00 + +=head1 CONNECTING TO ORACLE + +If you are reading this it is assumed that you have successfully +installed DBD::Oracle and you are having some problems connecting to +Oracle. + +First off you will have to tell DBD::Oracle where the binaries reside +for the Oracle client it was compiled against. This is the case when +you encounter a + + DBI connect('','system',...) failed: ERROR OCIEnvNlsCreate. + +error in Linux or in Windows when you get + + OCI.DLL not found + +The solution to this problem in the case of Linux is to ensure your +'ORACLE_HOME' (or LD_LIBRARY_PATH for InstantClient) environment +variable points to the correct directory. + + export ORACLE_HOME=/app/oracle/product/xx.x.x + +For Windows the solution is to add this value to you PATH + + PATH=c:\app\oracle\product\xx.x.x;%PATH% + +If you get past this stage and get a + + ORA-12154: TNS:could not resolve the connect identifier specified + +error then the most likely cause is DBD::ORACLE cannot find your .ORA +(F, F, F) files. This can be +solved by setting the TNS_ADMIN environment variable to the directory +where these files can be found. + +If you get to this stage and you have either one of the following +errors; + + ORA-12560: TNS:protocol adapter error + ORA-12162: TNS:net service name is incorrectly specified + +usually means that DBD::Oracle can find the listener but the it cannot connect to the DB because the listener cannot find the DB you asked for. + +=head2 Oracle utilities + +If you are still having problems connecting then the Oracle adapters +utility may offer some help. Run these two commands: + + $ORACLE_HOME/bin/adapters + $ORACLE_HOME/bin/adapters $ORACLE_HOME/bin/sqlplus + +and check the output. The "Protocol Adapters" should include at least "IPC Protocol Adapter" and "TCP/IP +Protocol Adapter". + +If it generates any errors which look relevant then please talk to your +Oracle technical support (and not the dbi-users mailing list). + +=head2 Connecting using a bequeather + +If you are using a bequeather to connect to a server +on the same host as the client, you might have +to add + + bequeath_detach = yes + +to your sqlnet.ora file or you won't be able to safely use fork/system +functions in Perl. + +See the discussion at +L +and L +for more gory details. + +=head1 USING THE LONG TYPES + +Some examples related to the use of LONG types are available in +the C directory of the distribution. + +=head1 Can't find I + +I is the shared +library composed of all the other Oracle libs you used to have to +statically link. +libclntsh.so should be in I<$ORACLE_HOME/lib>. If it's missing, try +running I<$ORACLE_HOME/lib/genclntsh.sh> and it should create it. + +Never copy I to a different machine or Oracle version. +If DBD::Oracle was built on a machine with a different path to I +then you'll need to set set an environment variable, typically +I, to include the directory containing I. + +I is typically ignored if the script is running set-uid +(which is common in some httpd/CGI configurations). In this case +either rebuild with I set to include the path to I +or create a symbolic link so that I is available via the same +path as it was when the module was built. (On Solaris the command +"ldd -s Oracle.so" can be used to see how the linker is searching for it.) + +=head1 Miscellaneous + +=head2 Crash with an open connection and Module::Runtime in mod_perl2 + +See RT 72989 (https://rt.cpan.org/Ticket/Display.html?id=72989) + +Apache2 MPM Prefork with mod_perl2 will crash if Module::Runtime is +loaded, and an Oracle connection is opened through PerlRequire (before +forking). + +It looks like this was fixed in 0.012 of Module::Runtime. + +=head2 bin_param_inout swapping return values + +See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) + +It seems that in some older versions of Oracle Instant Client +(certainly 10.2.0.4.0) when output parameters are bound with lengths +greater than 3584 the output parameters can be returned in the wrong +placeholders. + +It is reported fixed in Instant Client 11.2.0.2.0. + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod new file mode 100644 index 00000000..55f35d6c --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -0,0 +1,290 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Aix +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on AIX + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle on AIX + +=head1 VERSION + +version 1.47_00 + +=head1 Using Visual Age 7 C Compiler + +Oracle 9i is only certified as a 64-bit application on AIX 5L (5.1,5.2,5.3) with 32-bit support; +in other words, there is no 9i "32-bit" Oracle client + +Oracle 10g is certified as both a 64-bit application and a 32-bit Oracle client + +This information only pertains to deploying: + + the DBI (version 1.48) + and DBD-Oracle (version 1.16): + on AIX 5.3 + using Oracle 9i (9.2.0.1/9.2.0.5) + using the existing Perl 5.8.2 (no custom-built Perl) which is 32-bit + using Visual Age 7.0 C/C++ compiler + +Install the DBI (required for the DBD-Oracle install - no issues here) +Untar the DBD-Oracle bundle +Run Makefile.PL + + $ perl Makefile.PL + +Edit Makefile with following commands: + + 1,$s?/lib/ ?/lib32/ ?g + 1,$s?-q64??g + 1,$s?/lib/sysliblist?/lib32/sysliblist?g + +Now perform normal commands to perform the testing/making: + + $ make + $ make test + $ make install + +I've tested the basics of the DBD-Oracle and it seems fully functional. + +Stephen de Vries + +=head1 Using gcc C Compiler + + DBD::Oracle with gcc and Oracle Instant Client on AIX + -------------------------------------------------------------------------------------- + Nathan Vonnahme Dec 15 2005, 4:28 pm Newsgroups: perl.dbi.users + See: http://groups.google.com/group/perl.dbi.users/msg/0bd9097f80f2c8a9 + [ with updates 1/31/2006 - DBD::Oracle 1.17 doesn't need makefile hacking + to work with instantclient on AIX ] + + + Yes! It eluded me last year but I finally got DBD::Oracle working on an + AIX machine using gcc. Here's the short version: + + First I had to recompile perl with gcc, using + sh Configure -de -Dcc=gcc + This apparently built a 32 bit perl, someday I will try getting it to go + 64 bit. + + I was then able to install and build DBI 1.50 with the CPAN shell. + + I downloaded the base and sdk packages of the Oracle Instant Client for + AIX -- first I tried the 64 bit but that didn't work with my 32 bit perl + -- the 32 bit version (still at 10.1.0.3) did the trick. I unzipped + them and moved the dir to /usr/local/oracle/instantclient10_1 and made a + symlink without the version at /usr/local/oracle/instantclient , then + set: + + export ORACLE_HOME=/usr/local/oracle/instantclient + export LIBPATH=$ORACLE_HOME + + + + Oracle wasn't providing the sqlplus package for 32 bit AIX so I + explicitly told Makefile.PL the version: + + perl Makefile.PL -V 10.1 + + make + + My test databases were on other machines so I set these environment variables + to get the tests to run: + + export ORACLE_DSN=DBI:Oracle://host/dbinstance + export ORACLE_USERID="user/password" + + make test + make install + + + NOTE: I have an older full version of Oracle on this machine, and the + ORACLE_HOME environment variable is normally set to point to that, so + my perl scripts that use DBD::Oracle have to make sure to first set + $ENV{ORACLE_HOME}='/usr/local/oracle/instantclient'; + + + + + + -------------------------------------------------------------------------------------- + The following setup worked to build on AIX 5.2: + gcc-3.3.2 (32-bit) (configure opts [ --with-ld=/usr/ccs/bin/ld --with-as=/usr/ccs/bin/as]) + Oracle-9.2.0 ( full install w/32bit support) + perl-5.8.3 (built with above gcc/latest stable as of March 2004) + Followed the directions from Rafael's email below, only set ORACLE_HOME, (and + the appropriate test environmentals). + 1) build perl-5.8.3 with gcc + 2) install DBI + 3) ORACLE_HOME="your oracle home" + ORACLE_USERID.. + ORACLE_SID .. + (I ignored ORACCENV, didn't use it.) + 4) install DBD::Oracle, after perl Makefile.PL, edit the created Makefile, + changing references to Oracle's ../lib to ../lib32. and change crt0_64.o to + crt0_r.o. Remove the -q32 and/or -q64 options from the list of libraries to + link with. + 5) make should be clean, make test should pass. + This setup worked with 8.1.7 w/32 bit support, and with 9.2.0 w/ 32-bit support. + --Adrian Terranova + +=head1 Using xlc_r C Compiler + + From: Rafael Caceres + Date: 22 Jul 2003 10:05:20 -0500 + + The following sequence worked for me on AIX 5.1: + + -use Perl 5.8.0 (the latest stable from CPAN) + + -use the xlc_r version of IBM's compiler and build a 32 bit Perl + (which xlc_r will do by default). All tests should be successful. + + -get and install DBI + + -get DBD::Oracle. Edit the Makefile.PL or Makefile for DBD::Oracle, + changing references to Oracle's ../lib to ../lib32. and change crt0_64.o + to crt0_r.o. Remove the -q32 and/or -q64 options from the list of + libraries to link with. Do the make and make test. + + -Set up the environment for making DBD::Oracle: + ORACLE_HOME="your oracle home" + ORACCENV = "xlc_r" + ORACLE_USERID.. + ORACLE_SID .. + + -Run make, all tests should be successfull -against Oracle 9.x at least. + + You should have no problems with Oracle 8.1.7, but accessing Oracle 7.x + or previous is not possible (you'll core dump, or simply hang). The same + goes for a Linux build or a Digital build, regarding access of different + Oracle versions. + + Rafael Caceres + + > I dont believe I compiled Oracle. During the installation it was linked + > but I am not sure it was compiled + > + > I used a xlc compiler to compile PERL. + > Got this message in the Perl Makefile.PL output + > + > Warning: You will may need to rebuild perl using the xlc_r compiler. + > You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV + > Also see the README about the -p option + > + > this probobly means I need to rebuild PERL with xlc_r?? + > + > thanx + > + > Mike Paladino + > Database Administrator + + + From: Rafael Caceres + > + > Make sure you use the same compiler to build Oracle and Perl. We have + > used xlc_r on Aix 5.1 with no problems. Your Perl build is 32 bit, so + > when building DBD::Oracle, you should use the 32bit libraries (change + > references to .../oracle/lib to .../oracle/lib32 in your Makefile). + > Remove the references to the -q64 or -q32 parameters for ld in Makefile, + > as they shouldn't be there. + > + > Rafael Caceres + + + From: "cartman ltd" + Subject: Tip for DBI and DBD::Oracle on AIX 5.1 and Oracle 9.2 + Date: Mon, 11 Aug 2003 18:15:38 +0000 + Message-ID: + + Here is a tip for compiling DBD::Oracle as a 32 bit application on AIX 5.1 + 64 bit and Oracle 9.2 64 bit without editting any makefiles. I hope people + find this useful: + + First, the versions of products I used: + DBI version 1.32 + DBD::Oracle version 1.14 + Oracle 9.2.0.2 - default 64 bit application with 32 bit libraries + AIX 5.1 ML03 - 64 bit kernel - ships with Perl as a 32 bit application. + VisualAge C/C++ 5.0.2 + + Basically DBD must be compiled as 32 bit to link with Perl's 32 bit + libraries. + gunzip -c DBD-Oracle-1.14.tar.gz | tar xvf  + cd DBD-Oracle-1.14 + perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk + make + + NB: I think there is a bug in the Oracle 9.2.0.3 file + $ORACLE_HOME/rdbms/lib/env_rdbms.mk + I corrected this (before running the above commands) by replacing the + invalid linker option + LDFLAGS32=-q32 + with + LDFLAGS32=-b32 + + Have fun: KC. + -------------------------------------------------------------------------------------- + + Date: Wed, 30 Jun 2004 23:34:24 -0500 + From: "SCHULTZ, DARYLE (SBCSI)" + + Got it to work. Using dbd 1.16 + + Perl 5.8.4 built like this, with Visual Age 6.0: + + config_args='-Dcc=xlc_r -Dusenm -Dprefix=/appl/datasync/work/perl5 + -Dusethreads -Duse64bitall -des' + ============================================== + + Used DBI 1.42 + ============================================= + Added this to top of Oracle.h: + #define A_OSF + + #include + ======================= + Set LIBPATH to point to 64bit Oracle libs first. + export LIBPATH=$ORACLE_HOME/lib:$ORACLE_HOME/lib32:/usr/lib + + Use: perl Makefile.PL -nob + + Change all references in Makefile of LD_RUN_PATH to be LIBPATH. + Change nothing else, left all flags in Makefile, including -q64. + Passed make, and all tests. + + -------------------------------------------------------------------------------------- + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod new file mode 100644 index 00000000..c98b5bdd --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -0,0 +1,111 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Cygwin +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Cygwin + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracle on Cygwin + +=head1 VERSION + +version 1.47_00 + +=head1 General Info + +Makefile.PL should find and make use of OCI include +files, but you have to build an import library for +OCI.DLL and put it somewhere in library search path. +one of the possible ways to do this is issuing command + + dlltool --input-def oci.def --output-lib liboci.a + +in the directory where you unpacked DBD::Oracle distribution +archive. this will create import library for Oracle 8.0.4. + +Note: make clean removes '*.a' files, so put a copy in a safe place. + +=head1 Compiling DBD::Oracle using the Oracle Instant Client, Cygwin Perl and gcc + +=over + +=item 1 + +Download these two packages from Oracle's Instant Client for +Windows site +(http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/winsoft.html): + +Instant Client Package - Basic: All files required to run OCI, +OCCI, and JDBC-OCI applications + +Instant Client Package - SDK: Additional header files and an +example makefile for developing Oracle applications with Instant Client + +(I usually just use the latest version of the client) + +=item 2 + +Unpack both into C:\oracle\instantclient_11_1 + +=item 3 + +Download and unpack DBD::Oracle from CPAN to some place with no +spaces in the path (I used /tmp/DBD-Oracle) and cd to it. + +=item 4 + +Set up some environment variables (it didn't work until I got the +DSN right): + + ORACLE_DSN=DBI:Oracle:host=oraclehost;sid=oracledb1 + ORACLE_USERID=username/password + +=item 5 + + perl Makefile.PL + make + make test + make install + +=back + +Note, the TNS Names stuff doesn't always seem to work with the instant +client so Perl scripts need to explicitly use host/sid in the DSN, like +this: + + my $dbh = DBI->connect('dbi:Oracle:host=oraclehost;sid=oracledb1', + 'username', 'password'); + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/README.hpux.txt b/lib/DBD/Oracle/Troubleshooting/Hpux.pm similarity index 97% rename from README.hpux.txt rename to lib/DBD/Oracle/Troubleshooting/Hpux.pm index 0c483d00..3b7f3114 100644 --- a/README.hpux.txt +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pm @@ -1,3 +1,18 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Hpux +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on HP-UX + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle on HP-UX + +=head1 VERSION + +version 1.47_00 + =head1 INTRODUCTION Building a working dynamically linked version of the Oracle DBD driver @@ -23,7 +38,7 @@ See L for exact build configurations used by me an others. For HPUX 11 on Itanium see also http://www.nntp.perl.org/group/perl.dbi.users/23840 -=head1 First things First: Introduction +=head1 First things First: Introduction The reason you are even reading this file is because you want to connect to an Oracle database from your perl program using the DBD::Oracle DBI @@ -59,8 +74,7 @@ this file. -- Lincoln - -=head1 Build your own Perl +=head1 Build your own Perl HP's default Perl is no good (and antique). @@ -330,9 +344,9 @@ If you have trouble, see the L instructions below, for hints of what might be wrong... and send me a note, describing your configuration, and what you did to fix it. -=head1 Trouble Shooting +=head1 Trouble Shooting -=head2 "Unresolved symbol" +=head2 "Unresolved symbol" In general, find the symbols, edit the Makefile, and make test. @@ -413,7 +427,7 @@ You can edit the Makefile in 2 ways: Perform a make test, if symbols are still unresolved repeat the editing of the Makefile and make test again. -=head1 DBD-Oracle-1.06 +=head1 DBD-Oracle-1.06 You are strongly urged to upgrade. However here is what you may need to know to get it or work, if you insist on using an earlier version. @@ -955,14 +969,14 @@ To work around this problem, complete the following procedure: $ORACLE_HOME/rdbms/admin/shrept.lst =itme 3 Add the following line: - + rdbms:OCILobLocatorAssign =item 4 (optional) Add the names of any other missing functions needed by applications, other than WebLogic Server 7.0, that you want to execute. Note: The OCILobLocatorAssign function is not the only missing function that WebLogic Server 7.0 should be able to call, but it is the only missing function that WebLogic Server 7.0 requires. Other functions that WebLogic Server should be able to call, such as OCIEnvCreate and OCIerminate, are also missing. If these functions are required by other applications that you plan to run, you must add them to your environment by specifying them, too, in $ORACLE_HOME/rdbms/admin/shrept.lst. =item 5 Rebuild the shared client library: - + $ cd $ORACLE_HOME/rdbms/lib $ make -f ins_rdbms.mk client_sharedlib @@ -980,4 +994,34 @@ Because OCILobLocatorAssign is now visible in libclntsh.so, WebLogic Server can =back +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + =cut + diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod new file mode 100644 index 00000000..7964170e --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -0,0 +1,149 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Linux +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Linux + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle on Linux + +=head1 VERSION + +version 1.47_00 + +=head1 Installing with Instantclient .rpm files. + +Nothing special with this you just have to set up you permissions as follows; + +1) Have permission for RWE on '/usr/lib/oracle/10.2.0.3/client/' or the other directory where you RPMed to + +2) Set export ORACLE_HOME=/usr/lib/oracle/10.2.0.3/client + +3) Set export LD_LIBRARY_PATH=$ORACLE_HOME/lib + +4) If you plan to use tnsnames to connect to remote servers and your tnsnames.ora file is not in $ORACLE_HOME/network/admin, you will need to Export TNS_ADMIN=dir to point DBD::Oracle to where your tnsnames.ora file is + +=head1 undefined symbol: __cmpdi2 comes up when Oracle isn't properly linked to the libgcc.a library. + +In version 8, this was correctd by changing the SYSLIBS entry in +$ORACLE_HOME/bin/genclntsh to include +"-L/usr/lib/gcc-lib/i386-redhat-linux/3.2 -lgcc". + +I had tried this with no success as when this program was then run, the +error "unable to find libgcc" was generated. Of course, this was the +library I was trying to describe! + +It turns out that now it is necessary to edit the same file and append +"`gcc -print-libgcc-file-name`" (including the backquotes!). If you do +this and then run "genclntsh", the libclntsh is properly generated and +the linkage with DBD::Oracle proceeds properly. + +=head1 cc1: invalid option `tune=pentium4'" error + +If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. + +No real problem with the above however you will have to + +1) run Perl Makefile.PL + +2) edit the Makefile and remove the offending '-mtune=pentium4' text + +3) save and exit + +4) do the make install and it should work fine for you + +=head1 Oracle 9i Lite + +The advice is to use the regular Oracle9i not the lite version. + +Another great source of help was: http://www.puschitz.com/InstallingOracle9i.html + +just getting 9i and 9i lite installed. I use fvwm2(nvidia X driver) as +a window manager which does not work with the 9i install program, works +fine with the default Gnomish(nv X driver), it could have been the X +driver too. + +With Redhat9 it is REAL important to set LD_ASSUME_KERNEL to 2.4.1. + +I didn't try this but it may be possible to install what is needed by +only downloading the first disk saving some 1.3GB of download fun. + +I installed a custom install from the client group. The packages I +installed are the Programmers section and sqlplus. I noticed that the +Pro*C when on as a result of the checking the Programmers section I +assume. + +Once Oracle was installed properly the DBD::Oracle install went as +smooth as just about every other CPAN module. + +=head1 Oracle 10g Instantclient + +The Makefile.PL will now work for Oracle 10g Instantclient. To have both the Compile and +the test.pl to work you must first have the LD_LIBRARY_PATH correctly set to your +"instantclient" directory. (http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html) + +The present version of the make creates a link on your "instantclient" directory as follows +"ln -s libclntsh.so.10.1 libclntsh.so". It is needed for both the makefile creation and the compile +but is not need for the test.pl. It should be removed after the compile. + +If the Makefile.PL or make fails try creating this link directly in your "instantclient" directory. + +=head1 Oracle Database 10g Express Edition 10.2 + +To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY_PATH +as you would for an install against 10g Standard Edition, Standard Edition One, or +Enterprise Edition + +=head1 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 + +DBD::Oracle seems to hit some sort of bug with the above two versions of DB. +The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also +been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. + +So far there is no patch for this but here are some work arounds + + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + + or this way + + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + + or this way + + utf8::downgrade($parameter, 1); + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/README.macosx.txt b/lib/DBD/Oracle/Troubleshooting/Macos.pod similarity index 76% rename from README.macosx.txt rename to lib/DBD/Oracle/Troubleshooting/Macos.pod index 57801dad..1b56c48c 100644 --- a/README.macosx.txt +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -1,3 +1,20 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Macos +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on MacOs + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle on MacOs + +=head1 VERSION + +version 1.47_00 + +=head1 General Info + These instructions allow for the compilation and successful testing of DBD::Oracle on MacOS X 10.2.4 and higher, using Oracle 9iR2 DR (Release 9.2.0.1.0) or the 10g Instant Client release (10.1.0.3 at the @@ -47,8 +64,7 @@ if you are on 10.3 (Panther) and you do not intend to run the Oracle database server on your MacOSX box. See below (Instructions for 10.3.x) for details. -====================================================================== -Instructions for 10.7.x (Lion) +=head1 Instructions for 10.7.x (Lion) Because the 64 bit instantclient (version 10gr2)is currently [incompatible with Lion][], DBD::Oracle can only be compiled with the @@ -62,9 +78,9 @@ is released. If you have a 32-bit Perl, however, then the following steps should work: * Download and install the 32-bit basic, sqlplus, and sdk instantclient - libraries and install them in a central location, such as - `/usr/oracle_instantclient`. [Downloads here][]. - +libraries and install them in a central location, such as +`/usr/oracle_instantclient`. [Downloads here][]. + [Downloads here]: http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html * Create a symlink from `libclntsh.dylib.10.1` to `libclntsh.dylib`: @@ -81,8 +97,7 @@ If you have a 32-bit Perl, however, then the following steps should work: cpan DBD::Oracle -====================================================================== -Instructions for 10.6.x (Snow Leopard) +=head1 Instructions for 10.6.x (Snow Leopard) These are taken from a stackoverflow answer by "nickisfat" who gave his/her permission for its inclusion here. You can see the original @@ -170,9 +185,7 @@ install DBI Now you're all set - enjoy your perly oracley new life - -====================================================================== -Instructions for 10.2.x (Jaguar) +=head1 Instructions for 10.2.x (Jaguar) 1) Install Oracle exactly per Oracle documentation. If you change install locations, then you'll need to modify paths accordingly. @@ -227,102 +240,102 @@ follow nonetheless. compile with Perl 5.6.0; they may not be necessary with other versions of IO and Perl, respectively. -+=+=+=+=+=+=+= Cut after this line -diff -c ../IO-orig/IO-1.20/IO.xs ./IO.xs -*** ../IO-orig/IO-1.20/IO.xs Mon Jul 13 23:36:24 1998 ---- ./IO.xs Sat May 10 15:20:02 2003 -*************** -*** 205,211 **** - ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); - } - else { -! ST(0) = &sv_undef; - errno = EINVAL; - } - ---- 205,211 ---- - ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); - } - else { -! ST(0) = &PL_sv_undef; - errno = EINVAL; - } - -*************** -*** 249,255 **** - SvREFCNT_dec(gv); /* undo increment in newRV() */ - } - else { -! ST(0) = &sv_undef; - SvREFCNT_dec(gv); - } - ---- 249,255 ---- - SvREFCNT_dec(gv); /* undo increment in newRV() */ - } - else { -! ST(0) = &PL_sv_undef; - SvREFCNT_dec(gv); - } - -*************** -*** 272,278 **** - i++; - fds[j].revents = 0; - } -! if((ret = poll(fds,nfd,timeout)) >= 0) { - for(i=1, j=0 ; j < nfd ; j++) { - sv_setiv(ST(i), fds[j].fd); i++; - sv_setiv(ST(i), fds[j].revents); i++; ---- 272,278 ---- - i++; - fds[j].revents = 0; - } -! if((ret = io_poll(fds,nfd,timeout)) >= 0) { - for(i=1, j=0 ; j < nfd ; j++) { - sv_setiv(ST(i), fds[j].fd); i++; - sv_setiv(ST(i), fds[j].revents); i++; -diff -c ../IO-orig/IO-1.20/poll.c ./poll.c -*** ../IO-orig/IO-1.20/poll.c Wed Mar 18 21:34:00 1998 ---- ./poll.c Sat May 10 14:28:22 2003 -*************** -*** 35,41 **** - # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) - - int -! poll(fds, nfds, timeout) - struct pollfd *fds; - unsigned long nfds; - int timeout; ---- 35,41 ---- - # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) - - int -! io_poll(fds, nfds, timeout) - struct pollfd *fds; - unsigned long nfds; - int timeout; -diff -c ../IO-orig/IO-1.20/poll.h ./poll.h -*** ../IO-orig/IO-1.20/poll.h Wed Apr 15 20:33:02 1998 ---- ./poll.h Sat May 10 14:29:11 2003 -*************** -*** 44,50 **** - #define POLLHUP 0x0010 - #define POLLNVAL 0x0020 - -! int poll _((struct pollfd *, unsigned long, int)); - - #ifndef HAS_POLL - # define HAS_POLL ---- 44,50 ---- - #define POLLHUP 0x0010 - #define POLLNVAL 0x0020 - -! int io_poll _((struct pollfd *, unsigned long, int)); - - #ifndef HAS_POLL - # define HAS_POLL -+=+=+=+=+=+=+= Cut to the previous line + +=+=+=+=+=+=+= Cut after this line + diff -c ../IO-orig/IO-1.20/IO.xs ./IO.xs + *** ../IO-orig/IO-1.20/IO.xs Mon Jul 13 23:36:24 1998 + --- ./IO.xs Sat May 10 15:20:02 2003 + *************** + *** 205,211 **** + ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); + } + else { + ! ST(0) = &sv_undef; + errno = EINVAL; + } + + --- 205,211 ---- + ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t))); + } + else { + ! ST(0) = &PL_sv_undef; + errno = EINVAL; + } + + *************** + *** 249,255 **** + SvREFCNT_dec(gv); /* undo increment in newRV() */ + } + else { + ! ST(0) = &sv_undef; + SvREFCNT_dec(gv); + } + + --- 249,255 ---- + SvREFCNT_dec(gv); /* undo increment in newRV() */ + } + else { + ! ST(0) = &PL_sv_undef; + SvREFCNT_dec(gv); + } + + *************** + *** 272,278 **** + i++; + fds[j].revents = 0; + } + ! if((ret = poll(fds,nfd,timeout)) >= 0) { + for(i=1, j=0 ; j < nfd ; j++) { + sv_setiv(ST(i), fds[j].fd); i++; + sv_setiv(ST(i), fds[j].revents); i++; + --- 272,278 ---- + i++; + fds[j].revents = 0; + } + ! if((ret = io_poll(fds,nfd,timeout)) >= 0) { + for(i=1, j=0 ; j < nfd ; j++) { + sv_setiv(ST(i), fds[j].fd); i++; + sv_setiv(ST(i), fds[j].revents); i++; + diff -c ../IO-orig/IO-1.20/poll.c ./poll.c + *** ../IO-orig/IO-1.20/poll.c Wed Mar 18 21:34:00 1998 + --- ./poll.c Sat May 10 14:28:22 2003 + *************** + *** 35,41 **** + # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) + + int + ! poll(fds, nfds, timeout) + struct pollfd *fds; + unsigned long nfds; + int timeout; + --- 35,41 ---- + # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) + + int + ! io_poll(fds, nfds, timeout) + struct pollfd *fds; + unsigned long nfds; + int timeout; + diff -c ../IO-orig/IO-1.20/poll.h ./poll.h + *** ../IO-orig/IO-1.20/poll.h Wed Apr 15 20:33:02 1998 + --- ./poll.h Sat May 10 14:29:11 2003 + *************** + *** 44,50 **** + #define POLLHUP 0x0010 + #define POLLNVAL 0x0020 + + ! int poll _((struct pollfd *, unsigned long, int)); + + #ifndef HAS_POLL + # define HAS_POLL + --- 44,50 ---- + #define POLLHUP 0x0010 + #define POLLNVAL 0x0020 + + ! int io_poll _((struct pollfd *, unsigned long, int)); + + #ifndef HAS_POLL + # define HAS_POLL + +=+=+=+=+=+=+= Cut to the previous line - compile and install as you usually would, making sure that existing but conflicting modules get removed: @@ -344,8 +357,7 @@ diff -c ../IO-orig/IO-1.20/poll.h ./poll.h $ make test $ make install -====================================================================== -Instructions for 10.3.x (Panther) +=head1 Instructions for 10.3.x (Panther) I highly recommend you install and use the Oracle 10g Instant Client for MacOSX 10.3. Compared to traditional Oracle client installations @@ -389,34 +401,34 @@ That said, here are the details. Here is the patch: -+=+=+=+=+=+=+= Cut after this line -*** Makefile.PL.orig Fri Oct 22 02:07:04 2004 ---- Makefile.PL Fri May 13 14:28:53 2005 -*************** -*** 1252,1257 **** ---- 1252,1258 ---- - print "Found $dir/$_\n" if $::opt_d; - }, "$OH/rdbms", - "$OH/plsql", # oratypes.h sometimes here (eg HPUX 11.23 Itanium Oracle 9.2.0) -+ "$OH/sdk", # Oracle Instant Client default location (10g) - ); - @h_dir = keys %h_dir; - print "Found header files in @h_dir.\n" if @h_dir; -*************** -*** 1286,1292 **** ---- 1287,1297 ---- - open FH, ">define.sql" or warn "Can't create define.sql: $!"; - print FH "DEFINE _SQLPLUS_RELEASE\nQUIT\n"; - close FH; -+ # we need to temporarily disable login sql scripts -+ my $sqlpath = $ENV{SQLPATH}; -+ delete $ENV{SQLPATH}; - my $sqlplus_release = `$sqlplus_exe -S /nolog \@define.sql 2>&1`; -+ $ENV{SQLPATH} = $sqlpath if $sqlpath; - unlink "define.sql"; - print $sqlplus_release; - if ($sqlplus_release =~ /^DEFINE _SQLPLUS_RELEASE = "(\d?\d)(\d\d)(\d\d)(\d\d)(\d\d)"/) { -+=+=+=+=+=+=+= Cut to the previous line + +=+=+=+=+=+=+= Cut after this line + *** Makefile.PL.orig Fri Oct 22 02:07:04 2004 + --- Makefile.PL Fri May 13 14:28:53 2005 + *************** + *** 1252,1257 **** + --- 1252,1258 ---- + print "Found $dir/$_\n" if $::opt_d; + }, "$OH/rdbms", + "$OH/plsql", # oratypes.h sometimes here (eg HPUX 11.23 Itanium Oracle 9.2.0) + + "$OH/sdk", # Oracle Instant Client default location (10g) + ); + @h_dir = keys %h_dir; + print "Found header files in @h_dir.\n" if @h_dir; + *************** + *** 1286,1292 **** + --- 1287,1297 ---- + open FH, ">define.sql" or warn "Can't create define.sql: $!"; + print FH "DEFINE _SQLPLUS_RELEASE\nQUIT\n"; + close FH; + + # we need to temporarily disable login sql scripts + + my $sqlpath = $ENV{SQLPATH}; + + delete $ENV{SQLPATH}; + my $sqlplus_release = `$sqlplus_exe -S /nolog \@define.sql 2>&1`; + + $ENV{SQLPATH} = $sqlpath if $sqlpath; + unlink "define.sql"; + print $sqlplus_release; + if ($sqlplus_release =~ /^DEFINE _SQLPLUS_RELEASE = "(\d?\d)(\d\d)(\d\d)(\d\d)(\d\d)"/) { + +=+=+=+=+=+=+= Cut to the previous line The first hunk allows Makefile.PL to find the header files which are in a subdirectory sdk, and the second temporarily disables any @@ -499,16 +511,13 @@ instructions, and the Perl IO patch is credit to Hilmar Lapp, hlapp at gmx.net. Earlier and original instructions thanks to: - Andy Lester - Steve Sapovits - Tom Mornini - + Andy Lester + Steve Sapovits + Tom Mornini Date: Tue, 15 Apr 2003 16:02:17 +1000 Subject: Compilation bug in DBI on OSX with threaded Perl 5.8.0 -From: Danial Pearce -To: -Message-ID: +From: Danial Pearce In regards to a previous message on this list: @@ -548,5 +557,34 @@ anything Apple are going to do about it. cheers Danial -PS: Personal replies please, I have not subscribed to this list. +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod new file mode 100644 index 00000000..82d14be8 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -0,0 +1,59 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Sun +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Sun + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle on Sun + +=head1 VERSION + +version 1.47_00 + +=head1 General Info + +If you get this on a Solaris 9 and 10 box + + "Outofmemory! + Callback called exit. + END failed--call queue aborted." + +The solution may be as simple as not having you "ORACLE_HOME" Defined in the +environment. + +It seems that having it defined will prevent the error. + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod new file mode 100644 index 00000000..b689f080 --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -0,0 +1,129 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Vms +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Vms + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle on Vms + +=head1 VERSION + +version 1.47_00 + +=head1 General Info + +This is related to Oracle RDBMS 9.2 and later, since Oracle +made fundamental changes to oracle installation requirements +and factual installation with this release. + +Oracle's goal was to make VMS installation be more like on +*nix and Windows, with an all new Oracle Home structure too, +requiring an ODS-5 disk to install Oracle Home on instead of +the good old ODS-2. + +Another major change is the introduction of an Oracle generated +logical name table for oracle logical names like ORA_ROOT and all +its derivatives like ORA_PROGINT etc. And that this logical name +table is inserted in LNM$FILE_DEV in LNM$PROCESS_DIRECTORY. + + (LNM$PROCESS_DIRECTORY) + + "LNM$FILE_DEV" = "SERVER_810111112" + = "LNM$PROCESS" + = "LNM$JOB" + = "LNM$GROUP" + = "LNM$SYSTEM" + = "DECW$LOGICAL_NAMES" + +This ensures that any process that needs to have access to +oracle gets the environment by just adding one logical name table +to a central process specific mechanism. + +But as it is inserted at the very top of LNM$FILE_DEV it also +represents a source of misfortune - especially if a user with +enough privilege to update the oracle table does so (presumably +unintentionally), as an examble by changing NLS_LANG. + +PERL has the abillity to define, redefine and undefine (deassign) +logical names, but if not told otherwise by the user does it +in the first table in above list, and not as one would normally +expect in the process table. + +Installing DBI and DBD::Oracle has influence upon this since in +both cases a few environment variables are read or set in the +test phase. +For DBI it is the logical SYS$SCRATCH, which is a JOB logical. +For DBD-Oracle it is when testing a new feature in the Oracle +RDBMS: UTF8 and UTF16 character set functionality, and in order +to do this it sets and unsets the related environment variables +NLS_NCHAR and NLS_LANG. + +If one is not careful this changes the values set in the oracle +table - and in the worst case stays active until the next major +system reset. It can also be a very hard error to track down +since it happens in a place where one normally never looks. + +Furthermore, it is very possibly that some or all of the UTF tests +fails, since if one have a variable like NLS_LANG in his process +table, then even though 'mms test' sets it in the wrong table +it is not invoked as it is overruled by the process logical... + +The way to ensure that no logicals are set in the oracle table and +that the UTF tests get the best environment to test in, and that +DBI correctly translates the SYS$SCRATCH logical, use the +logical + + PERL_ENV_TABLES + +to ensure that PERL's behavior is to leave the oracle table alone and +use the process table instead: + + $ DEFINE PERL_ENV_TABLES LNM$PROCESS, LNM$JOB + +This tells PERL to use the LNM$PROCESS table as the default place to +set and unset variables so that only the perl users environment +is affected when installing DBD::Oracle, and ensures that the +LNM$JOB table is read when SYS$SCRATCH is to be translated. + +PERL_ENV_TABLES is well documented in the PERLVMS man page. + +Oracle8 releases are not affected, as they don't have the +oracle table implementation, and no UTF support. + +Oracle 9.0 is uncertain, since testing has not been possible yet, +but the remedy will not hurt :) + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod new file mode 100644 index 00000000..9acaf51c --- /dev/null +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -0,0 +1,279 @@ +#PODNAME: DBD::Oracle::Troubleshooting::Win32 +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Win32 + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle on Win32 + +=head1 VERSION + +version 1.47_00 + +=head1 GENERAL INFO + +In general, on Windows, it's best to just use ActiveState Perl and the +PPM package manager to install a pre-built version of DBD::Oracle however only version 1.17 is available there. + +If you built Perl with gcc, read README.wingcc.txt as well as this file. + +=head1 Oracle Instant Client 11.1.0.6.0 Notes + +So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value +in the environment variables. + +As well IC 11 seems to have trouble finding the .ORA files. A quick fix for this is to add "TNS_ADMIN" +to the environment variables and point it to where your .ORA files are. + +=head1 Other information, some of which is out of date --- + + DBD-Oracle for Windows and Oracle Instantclient and 10XE (Express Edition) + By: John Scoles + The Pythian Group + +The preferred method of getting DBD::Oracle is to use a pre-built version from the ActiveState +repository, which can be installed with PPM. + +Compiling and installing DBD::Oracle 1.18 or later on a windows 2000 professional or XP OS for use +with Oracle instantClient ver 10.2.0.1 & 10.1.0.5 or Oracle XE requires only a few downloads and +a minimal number of environment setting. The procedures below were tested on a clean +Windows platform having no Oracle or other development environment installed. + + 1) The first part of the process is to download and install the latest version of + Active Perl from http://www.activeperl.com/. + + 2) Use the PPM application to get the latest version of DBI + + 3) Download the latest DBD::Oracle from http://svn.perl.org/modules/dbd-oracle/trunk/ + + 4) Download and unzip the Oracle Instant Client (10.2.0.1 or 10.1.0.5) 32 bit from + http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html + You will need all three of these products + i. Instant Client Package - Basic + ii. Instant Client Package - SQL*Plus: + iii. Instant Client Package - SDK: + or + + install oracle 10XE http://www.oracle.com/technology/products/database/xe/index.html + + 5) You will now need the Microsoft Visual C++ toolkit 2003. Unfortunately this product is no longer available from Microsoft. + The file name was VCToolkitSetup.exe and is available at this mirror site http://www.filewatcher.com/m/VCToolkitSetup.exe.32952488.0.0.html at the time of writing. + Microsoft's replacement for this tool kit is Visual C++ 2005 Express Edition and all attempts to compile DBD::Oracle with this product fail. It has been successfully compiled + using a complete edition of Microsoft Visual Studio 2005. + Download and then install this product. + + 6) You will also need the Windows SDK. Which can be found at + http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en + You have the choice to of either to download the entire SDK and install or run an online install from the page. + Both have been tested and proven to work. + + 7) Next download and install the Microsoft .net framework 1.1 skd from + http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&displaylang=en + + 8) You will also need a copy of nmake.exe which you can download here http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe + + 9) Enough Downloading and installing go have a coffee. + + 10) You should at this time attempt to connect to an Oracle database with the version SQL*Plus that + you installed in step 4. If you are unable to connect at this stage then any problems you encounter + later may have nothing to do with DBD::Oracle + + 11) On the path where you installed Visual C++ find and edit the vcvars32.bat file as follows. You may have to modify + these path values depending where you installed the products on you computer, + + i. Add the local path to the windows platform SDK include directory to the Set INCLUDE + Command Line to include the needed files from the Windows SDK. + + e.g. "C:\Program Files\Microsoft Platform SDK\Include;" + + ii. Add the local path to the .net Vc7 lib directory to the Set LIB command + to include the needed library file from the .Net SKD + + e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; + + iii. Add the local path to the windows platform SDK Lib directory to the Set Lib command + to include the needed library files from the Windows SDK + + e.g. C:\Program Files\Microsoft Platform SDK\Lib; + + 12) Open a Windows Visual C++ command window from the start menu. + + 13) Add the path to the instant client to the Path command. If you are compiling aginst a 10XE db/client then you can skip steps + 12 to 14. + e.g. PATH = C:/Oracle/instantclient;%PATH% + + 14) Using the "Set" command add "ORACLE_HOME=path to Instant client" to the environment variables. + e.g. Set ORACLE_HOME=C:\Oracle\instantclient + + 15) Using the "Set" command add "NLS_LANG=.WE8ISO8859P15" to the environment variables. The globalization variable is required, + with this or another compatible value, by Oracle instantclient in order for it to compile correctly. + e.g. Set NLS_LANG=.WE8ISO8859P15 + + 16) Using the "Set" command add "ORACLE_USERID=test/test@test" substituting test with the username/password@database + you wish to run the make test files against. + Note: it is not necessary to do this step for the compile and install to work. + However: The self-test programs included with Oracle-DBD will mostly fail. + + 17) Move to the DBD-Oracle directory in the Visual C++ window DOS prompt and enter the following. + + c:\oracle-dbd\>perl Makefile.PL + + The Makefile should then run and compile Oracle-dbd without reporting any errors. + + 18) From this DOS prompt enter the following command + + c:\oracle-dbd\>nmake + + The Visual C++ make executable will then build you DBD-execuable. There should be no errors at this point. + + 19) You can test the compile by either entering + + c:\oracle-dbd\>nmake test + + As long as you have given a valid user name, password and database name in step 15 you will see some results. If it appears to + run but you do not get a connection check the following. + + i. User name password and DB Name + ii. Ensure the a valid TNSNAMES.ORA file is in the Instantclient directory + iii. Attempt to log into the version of SQLPLUS that comes with Instantclient. + If you manage to log on use the username password and TNS name with + the Set ORACLE_USERID = and rerun the tests. + iv If you are compiling against 10XE and have skiped steps 12 to 14 try again bu this time carry out these steps + + 20) You can now install DBD-Oracle into you system by entering the following command from the Visual C++ window dos prompt; + + c:\oracle-dbd\>nmake install + + 21) You should now be able to run DBD-Oracle on you system + +=head1 09/30 2006 from asu + +DBD::Oracle 1.18a + +Linux, Debian unstable ( +DBI: 1.52 +perl v5.8.8 built for i486-linux-gnu-thread-multi +) + +Oracle Instant client (10.1.0.5) + +The problem is in Makefile.PL. In line 130 the function find_oracle_home +is used to guess a value form $ORACLE_HOME if it is not set explicitely. +This value is used in line 138 to setup the environment (regardless +which client is used). + +in line 1443 (sub get_client_version) sqlplus is used to get the +version string, but for the oracle instant client you must not set +$ORACLE_HOME (it will generate an error "SP2-0642: SQL*Plus internal +error state 2165, context 4294967295:0:0") + +A solution that worked for me was to set +local $ENV{ORACLE_HOME} = ''; +in line 1463 immediately before sqlplus is called (but I cannot tell if +this fails for full client installations) + +11/30/05 -- John Scoles +I have confirmed that this Makefile.pl will work for both Oracle InstantClient +10.2.0.1 & 10.1.0.4 using same process the Andy Hassall uses. Starting with a clean OD +One needs only to get the latest version of Active Perl 5.8.7 use PPM to get DBI and then +install Microsoft Visual C++ toolkit, Windows SDK, and the Microsoft .net +framework 1.1. and modify the vcvars32.bat in C++ dir as follows + + 1) Add the local path to the windows platform SDK include directory to the + Set INCLUDE Command Line to include the needed files from the Windows SDK. + e.g. "C:\Program Files\Microsoft Platform SDK\Include;" + 2) Add the local path to the .net Vc7 lib directory to the Set LIB + command to include the needed library files from the .Net SKD + e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; + 3) Add the local path to the windows platform SDK Lib directory to the Set Lib + command to include the needed library files from the Windows SDK + e.g. C:\Program Files\Microsoft Platform SDK\Lib; + +If one happens to have visual studio installed you may not have to download additional MS products. + +12/01/05 --- John Scoles +Oracle 10XE +No big problem here as 10XE seems to use the instantclient as well. Just ensure your + NLS_LANG and ORACLE_HOME are set to the same directory that 10XE uses + +10/07/05 --John Scoles +Andy Hassall kindly added some changes to the Makefile.PL +so it will work for the Instant Client 10g on Windows OSs. Below is how he set +up his environment and the steps he preformed to get it to compile. + + Setting environment for using Microsoft Visual Studio .NET 2003 tools. + (If you have another version of Visual Studio or Visual C++ installed and wish + to use its tools from the command line, run vcvars32.bat for that version.) + + C:\Documents and Settings\andyh>d: + + D:\>cd cygwin\home\andyh\src\pythian + + D:\cygwin\home\andyh\src\pythian>set ORACLE_HOME=d:\lib\instantclient_10_2 + + D:\cygwin\home\andyh\src\pythian>set NLS_LANG=.WE8ISO8859P15 + + D:\cygwin\home\andyh\src\pythian>set PATH=d:\lib\instantclient_10_2;D:\Program F + iles\Microsoft Visual Studio .NET 2003\Common7\IDE;D:\Program Files\Microsoft Vi + sual Studio .NET 2003\VC7\BIN;D:\Program Files\Microsoft Visual Studio .NET 2003 + \Common7\Tools;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ + bin\prerelease;D:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\ + bin;D:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;C:\WINNT\Mic + rosoft.NET\Framework\v1.1.4322;d:\Perl\bin\;C:\WINNT\system32;C:\WINNT;C:\WINNT\ + System32\Wbem;D:\Program Files\Microsoft SDK\Bin;D:\Program Files\Microsoft SDK\ + Bin\WinNT + + D:\cygwin\home\andyh\src\pythian>set ORACLE_USERID=test/test@test102 + + D:\cygwin\home\andyh\src\pythian>perl Makefile.PL + +4/27/04 -- Jeff Urlwin + +Do not untar this distribution in a directory with spaces. This will not work. + + i.e. C:\Program Files\ORacle\DBD Oracle Distribution is bad while + c:\dev\dbd-oracle-1.15 is good ;) + +9/14/02 -- Michael Chase + +Makefile.PL uses Win32::TieRegistry or Win32::Registry to find the +current Oracle Home directory if the ORACLE_HOME environment variable +is not set. If neither module is installed, you must set ORACLE_HOME +before running Makefile.PL. Since the registry location of the current +Oracle Home is in different locations in different Oracle versions, +it is usually safer to set ORACLE_HOME before running Makefile.PL. + +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/README.win64.txt b/lib/DBD/Oracle/Troubleshooting/Win64.pod similarity index 91% rename from README.win64.txt rename to lib/DBD/Oracle/Troubleshooting/Win64.pod index 7f423e2b..4a85b9a1 100644 --- a/README.win64.txt +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -1,4 +1,19 @@ -DBD::Oracle and Windows 64bit +#PODNAME: DBD::Oracle::Troubleshooting::Win64 +#ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Win64 + + +__END__ +=pod + +=head1 NAME + +DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle on Win64 + +=head1 VERSION + +version 1.47_00 + +=head1 DBD::Oracle and Windows 64bit I have successfully compiled and installed DBD::Oracle on Windows 2008 server 64bit operating system today. @@ -7,12 +22,10 @@ version 11.2.0.1.0 for 64bit windows of Oracle's Instant Client Package - Basic along with the Instant Client Package - SQL*Plus and finally the Instant Client Package - SDK. - To get it to Make and compile correctly I had to download Microsoft's Visual Studio Ultimate which should contain all the files you need. It is rather portly at 2+gb so you might want to grab lunch while you are downloading it. - After all the above downloading DBB::Oracle installed right out of the box. All one has to do is select 'Start Menu->All Programs->Microsoft Visual Studio 2010->Visual Studio Tools->Visual Studio x64 Win64 Command Prompt (2010)' @@ -38,10 +51,8 @@ and then a c:\DBD-Oracle>nmake install - Which will produce a whole of warnings (the make you can ignore them for now as they do not seem to effect DBD::Oracle at all) and near the end it should output something like this; - Generating code Finished generating code if exist blib\arch\auto\DBD\Oracle\Oracle.dll.manifest mt -nologo -manifest blib\arch\auto\DBD\Oracle\Oracle.dll.manifest -outputresource:blib\arch\auto @@ -65,16 +76,12 @@ You will need a TNSNAMES.ORA file that points to a valid DB in the Instant Clien Next you will need to set the ORACLE_USER_ID to a valid user - c:\DBD-Oracle>set ORACLE_USER_ID=system/system@XE - You will have to set up TNS_ADMIN to point to the Instant Client Directory - c:\DBD-Oracle>set TNS_ADMIN=c:\IC_11 - Most importantly you will have to add the Instant Client directory to your path like this c:\DBD-Oracle>path = c:\IC_11;%path% @@ -89,7 +96,6 @@ What is actually going on is that Perl cannot find oci.dll (or one of the other are just a false trails. For more info on this check out this page Oracle Troubleshooter' by Alexander Foken. It is rather dated but the facts of why perl did not find a dll are still valid. - now you can do this c:\DBD-Oracle>nmake test @@ -106,10 +112,6 @@ That is about it. At this point you might want to add the Instant Client directory permanently to your path so you will not run into the Dynaloader error again. - - - - In general compiling DBD:Oracle for 64 bit machines has been a hit or miss operation. The main thing to remember is you will have to compile using 32 bit Perl and compile DBD::Oracle against a 32bit client which sort of defeats the purpose of having a 64bit box. @@ -120,7 +122,6 @@ From: Alex Buttery, OCA, MCTS Director, Database Architecture and Operations Impact Rx, Inc. - I needed to get perl working on a 64-bit Windows Server so I got creative. Since I was unable to build DBD::Oracle on the Windows Server (even with Visual Studio 6 installed), I decided that I would try another approach. Here are the steps I took to get it working (yes, this is a hack and I'm not even sure that it does not violate someone's license agreements but I'm not going to be asking anyone @@ -161,11 +162,34 @@ else to support this configuration). SET PATH=%ORACLE_HOME%\bin;%PATH% <== Add 32-bit Oracle Home to beginning of default PATH - +=head1 AUTHORS + +=over 4 + +=item * + +Tim Bunce + +=item * + +John Scoles + +=item * + +Yanick Champoux + +=item * + +Martin J. Evans + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 1994 by Tim Bunce. -Hopefully, you will be able to include these instructions in the next build of DBD::Oracle to help out other poor souls that are fighting -this same battle. +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. - +=cut - diff --git a/test.pl b/test.pl deleted file mode 100755 index 94830576..00000000 --- a/test.pl +++ /dev/null @@ -1,319 +0,0 @@ -#!/usr/local/bin/perl -w - -use ExtUtils::testlib; - -die "Use 'perl -Mblib test.pl' or 'make test' to run test.pl\n" - unless "@INC" =~ /\bblib\b/; - -# Copyright (c) 1995-2004, Tim Bunce -# -# You may distribute under the terms of either the GNU General Public -# License or the Artistic License, as specified in the Perl README file. - -# XXX -# XXX PLEASE NOTE THAT THIS CODE IS A RANDOM HOTCH-POTCH OF TESTS AND -# XXX TEST FRAMEWORKS AND IS IN *NO WAY* A TO BE USED AS A STYLE GUIDE! -# XXX - -$| = 1; - -use Getopt::Long; -use Config; - -my $os = $Config{osname}; - -GetOptions( - 'm!' => \my $opt_m, # do mem leak test - 'n=i' => \my $opt_n, # num loops for some tests - 'c=i' => \my $opt_c, # RowCacheSize for some tests - 'f=i' => \my $opt_f, # fetch test - 'p!' => \my $opt_p, # perf test -) or die; -$opt_n ||= 10; - -# skip this old set of half-baked oddities if ORACLE_DSN env var is set -exit 0 if $ENV{ORACLE_DSN}; - -$dbname = $ARGV[0] || ''; # if '' it'll use TWO_TASK/ORACLE_SID -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -use Oraperl; - -exit test_extfetch_perf($opt_f) if $opt_f; - -exit test_leak(10 * $opt_n) if $opt_m; - -&ora_version; - -my @data_sources = DBI->data_sources('Oracle'); -print "Data sources:\n\t", join("\n\t",@data_sources),"\n"; - -print "Connecting\n", - " to '$dbname' (from command line, else uses ORACLE_SID or TWO_TASK - recommended)\n"; -print " as '$dbuser' (via ORACLE_USERID env var or default - recommend name/passwd\@dbname)\n"; -printf("(ORACLE_SID='%s', TWO_TASK='%s')\n", $ENV{ORACLE_SID}||'', $ENV{TWO_TASK}||''); -printf("(LOCAL='%s', REMOTE='%s')\n", $ENV{LOCAL}||'', $ENV{REMOTE}||'') if $os eq 'MSWin32'; - -{ # test connect works first - local($l) = &ora_login($dbname, $dbuser, ''); - unless($l) { - $ora_errno = 0 unless defined $ora_errno; - $ora_errstr = '' unless defined $ora_errstr; - warn "ora_login: $ora_errno: $ora_errstr\n"; - # Try to help dumb users who don't know how to connect to oracle... - warn "\nHave you set the environment variable ORACLE_USERID ?\n" - if ($ora_errno == 1017); # ORA-01017: invalid username/password - warn "\nHave you included your password in ORACLE_USERID ? (e.g., 'user/passwd')\n" - if ($ora_errno == 1017 and $dbuser !~ m:/:); - warn "\nHave you set the environment variable ORACLE_SID or TWO_TASK?\n" - if ($ora_errno == 2700); # error translating ORACLE_SID - warn "\nORACLE_SID or TWO_TASK possibly not right, or server not running.\n" - if ($ora_errno == 1034); # ORA-01034: ORACLE not available - warn "\nTWO_TASK possibly not set correctly right.\n" - if ($ora_errno == 12545); - warn "\n"; - warn "Generally set TWO_TASK or ORACLE_SID but not both at the same time.\n"; - warn "Try to connect to the database using an oracle tool like sqlplus\n"; - warn "only if that works should you suspect problems with DBD::Oracle.\n"; - warn "Try leaving dbname value empty and set dbuser to name/passwd\@dbname.\n"; - warn "\nTest aborted cannot connect.\n"; - exit 0; - } - if ($os ne 'MSWin32' and $os ne 'VMS') { - my $backtick = `sleep 1; echo Backticks OK`; - unless ($backtick) { # $! == Interrupted system call - print "Warning: Oracle's SIGCHLD signal handler breaks perl ", - "`backticks` commands: $!\n(d_sigaction=$Config{d_sigaction})\n"; - } - } - #test_bind_csr($l); - #test_auto_reprepare($l); - &ora_logoff($l) || warn "ora_logoff($l): $ora_errno: $ora_errstr\n"; - -} - -&test_intfetch_perf() if $opt_p; - -&test1(); - -print "\nRepetitive connect/open/close/disconnect:\n"; -#print "If this test hangs then read the README.help.txt file.\n"; -#print "Expect sequence of digits, no other messages:\n"; -# likely to fail with: ORA-12516: TNS:listener could not find available handler with matching protocol stack (DBD ERROR: OCIServerAttach) -# in default configurations if the number of iterations is high (>~20) -my $connect_loop_start = DBI::dbi_time(); -foreach(1..$opt_n) { print "$_ "; &test2(); } -my $dur = DBI::dbi_time() - $connect_loop_start; -printf "(~%.3f seconds each)\n", $dur / $opt_n; - -print "test.pl complete.\n\n"; - -exit 0; - - -sub test1 { - local($lda) = &ora_login($dbname, $dbuser, '') - || die "ora_login: $ora_errno: $ora_errstr\n"; - - &ora_commit($lda) || warn "ora_commit($lda): $ora_errno: $ora_errstr\n"; - &ora_rollback($lda) || warn "ora_rollback($lda): $ora_errno: $ora_errstr\n"; - &ora_autocommit($lda, 1); - &ora_autocommit($lda, 0); - - # Test ora_do with harmless non-select statement - &ora_do($lda, "set transaction read only ") - || warn "ora_do: $ora_errno: $ora_errstr"; - - # DBI::dump_results($lda->tables()); - - # $lda->debug(2); - - { - #$lda->trace(2); - local($csr) = &ora_open($lda, - "select to_number('7.2', '9D9', - 'NLS_NUMERIC_CHARACTERS =''.,''' - ) num_t, - SYSDATE date_t, - USER char_t, - ROWID rowid_t, - HEXTORAW('7D') raw_t, - NULL null_t - from dual") || die "ora_open: $ora_errno: $ora_errstr\n"; - $csr->{RaiseError} = 1; - - print "Fields: ",scalar(&ora_fetch($csr)),"\n"; - die "ora_fetch in scalar context error" unless &ora_fetch($csr)==6; - print "Names: \t",join("\t", &ora_titles($csr)),"\n"; - print "Lengths: \t",DBI::neat_list([&ora_lengths($csr)],0,"\t"),"\n"; - print "OraTypes: \t",DBI::neat_list([&ora_types($csr)], 0,"\t"),"\n"; - print "SQLTypes: \t",DBI::neat_list($csr->{TYPE}, 0,"\t"),"\n"; - print "Scale: \t",DBI::neat_list($csr->{SCALE}, 0,"\t"),"\n"; - print "Precision: \t",DBI::neat_list($csr->{PRECISION}, 0,"\t"),"\n"; - print "Nullable: \t",DBI::neat_list($csr->{NULLABLE}, 0,"\t"),"\n"; - print "Est row width:\t$csr->{ora_est_row_width}\n"; - print "Prefetch cache: $csr->{RowsInCache}\n" if $csr->{RowsInCache}; - - print "Data rows:\n"; - #$csr->debug(2); - while(@fields = $csr->fetchrow_array) { - die "ora_fetch returned ".@fields." fields instead of 6!" - if @fields != 6; - die "Perl list/scalar context error" if @fields==1; - print " fetch: ", DBI::neat_list(\@fields),"\n"; - } - &ora_close($csr) || warn "ora_close($csr): $ora_errno: $ora_errstr\n"; - } - &ora_logoff($lda) || warn "ora_logoff($lda): $ora_errno: $ora_errstr\n"; -} - - -sub test2 { # also used by test_leak() - my $execute_sth = shift; - my $dbh = DBI->connect("dbi:Oracle:$dbname", $dbuser, '', { RaiseError=>1 }); - if ($execute_sth) { - my $sth = $dbh->prepare("select 42,'foo',sysdate from dual where ? >= 1"); - while ($execute_sth-- > 0) { - $sth->execute(1); - my @row = $sth->fetchrow_array; - $sth->finish; - } - } - $dbh->disconnect; -} - - -sub test_leak { - local($count) = @_; - local($ps) = (-d '/proc') ? "ps -lp " : "ps -l"; - local($i) = 0; - my $execute_sth = 100; - print "\nMemory leak test: (execute $execute_sth):\n"; - while(++$i <= $count) { - &test2($execute_sth); - system("echo $i; $ps$$") if (($i % 10) == 1); - } - system("echo $i; $ps$$"); - print "Done.\n\n"; -} - - -sub count_fetch { - local($csr) = @_; - local($rows) = 0; - # while((@row) = &ora_fetch($csr)) { - while((@row) = $csr->fetchrow_array) { - ++$rows; - } - die "count_fetch $ora_errstr" if $ora_errno; - return $rows; -} - - -sub test_intfetch_perf { - print "\nTesting internal row fetch overhead.\n"; - local($lda) = &ora_login($dbname, $dbuser, '') - || die "ora_login: $ora_errno: $ora_errstr\n"; - DBI->trace(0); - $lda->trace(0); - local($csr) = &ora_open($lda,"select 0,1,2,3,4,5,6,7,8,9 from dual"); - local($max) = 50000; - $csr->{ora_fetchtest} = $max; - require Benchmark; - $t0 = new Benchmark; - 1 while $csr->fetchrow_arrayref; - $td = Benchmark::timediff((new Benchmark), $t0); - $csr->{ora_fetchtest} = 0; - printf("$max fetches: ".Benchmark::timestr($td)."\n"); - printf("%d per clock second, %d per cpu second\n\n", - $max/($td->real ? $td->real : 1), - $max/($td->cpu_a ? $td->cpu_a : 1)); -} - -sub test_extfetch_perf { - my $max = shift; - print "\nTesting external row fetch overhead.\n"; - my $rows = 0; - my $dbh = DBI->connect("dbi:Oracle:$dbname", $dbuser, '', { RaiseError => 1 }); - #$dbh->trace(2); - $dbh->{RowCacheSize} = $::opt_c if defined $::opt_c; - my $fields = (0) ? "*" : "object_name, status, object_type"; - my $sth = $dbh->prepare(q{ - select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - union all select all * from all_objects o1 - --, all_objects o2 - --where o1.object_id <= 400 and o2.object_id <= 400 - }, { ora_check_sql => 1 }); - - require Benchmark; - $t0 = new Benchmark; - $sth->execute; - $sth->trace(0); - $sth->fetchrow_arrayref; # fetch one before starting timer - $td = Benchmark::timediff((new Benchmark), $t0); - printf("Execute: ".Benchmark::timestr($td)."\n"); - - print "Fetching data with RowCacheSize $dbh->{RowCacheSize}...\n"; - $t1 = new Benchmark; - 1 while $sth->fetchrow_arrayref && ++$rows < $max; - $td = Benchmark::timediff((new Benchmark), $t1); - printf("$rows fetches: ".Benchmark::timestr($td)."\n"); - printf("%d per clock second, %d per cpu second\n", - $rows/($td->real ? $td->real : 1), - $rows/($td->cpu_a ? $td->cpu_a : 1)); - my $ps = (-d '/proc') ? "ps -lp " : "ps -l"; - system("echo Process memory size; $ps$$"); - print "\n"; - $sth->finish; - $dbh->disconnect; - exit 1; -} - - -sub test_bind_csr { - local($lda) = @_; -$lda->{RaiseError} =1; -$lda->trace(2); -my $out_csr = $lda->prepare(q{select 42 from dual}); # sacrificial csr XXX -$csr = $lda->prepare(q{ - begin - OPEN :csr_var FOR select * from all_tables; - end; -}); -$csr->bind_param_inout(':csr_var', \$out_csr, 100, { ora_type => 102 }); -$csr->execute(); -# at this point $out_csr should be a handle on a new oracle cursor -@row = $out_csr->fetchrow_array; - - exit 1; -} - -sub test_auto_reprepare { - local($dbh) = @_; - $dbh->do(q{drop table timbo}); - $dbh->{RaiseError} =1; - #$dbh->trace(2); - $dbh->do(q{create table timbo ( foo integer)}); - $dbh->do(q{insert into timbo values (91)}); - $dbh->do(q{insert into timbo values (92)}); - $dbh->do(q{insert into timbo values (93)}); - $dbh->commit; - $Oraperl::ora_cache = $Oraperl::ora_cache = 1; - my $sth = $dbh->prepare(q{select * from timbo for update}); - $sth->execute; $sth->dump_results; - $sth->execute; - print $sth->fetchrow_array,"\n"; - $dbh->commit; - print $sth->fetchrow_array,"\n"; - $dbh->do(q{drop table timbo}); - exit 1; -} - -# end. From 5198b430d674057f2d165542575a2e3ba23fed59 Mon Sep 17 00:00:00 2001 From: yanick Date: Wed, 11 Jul 2012 19:25:33 +0000 Subject: [PATCH 265/637] preps for v1.47_00 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15348 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index 2d854c71..37295fa0 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.47_00 2012-07-11 [BUG FIXES] From 463f19ef8adbfe5fc3e7525c5a093908d0cfcea8 Mon Sep 17 00:00:00 2001 From: yanick Date: Wed, 11 Jul 2012 19:25:33 +0000 Subject: [PATCH 266/637] preps for v1.47_00 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15348 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index 2d854c71..37295fa0 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.47_00 2012-07-11 [BUG FIXES] From 95609f60af2b000acf4f6fc3b7839207c9c84724 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 11 Jul 2012 15:31:34 -0400 Subject: [PATCH 267/637] v1.47_00 [BUG FIXES] - fixed redeclaration of $len in 31lob.t - (Martin J, Evans) - RT55028 - stop segfaulting when attempting to read empty lobs (Martin J. Evans) - RT69059 - Despite OCIPing being documented as added in 10.2 AIX does not seem to have it in 10.2 leading to undefined symbol - Martin J. Evans [DOCUMENTATION] - Promoted the troubleshooting for the different architectures to POD documents, for easier/prettier access. - Added a troubleshooting entry for RT71819 - bound output parameters may be returned in the wrong order (Martin J. Evans) --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index 2d854c71..58cc09ed 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} +1.47_00 2012-07-11 + [BUG FIXES] - fixed redeclaration of $len in 31lob.t - (Martin J, Evans) From 64b5d2855072274df6a55fe1253a85bd80a577c8 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 10:30:51 +0000 Subject: [PATCH 268/637] fix serious memory corription in TAF handling hide some lower packages from PAUSE git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15355 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 12 +++++++++++- lib/DBD/Oracle.pm | 23 +++++++++++++---------- oci8.c | 10 +++++----- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/Changes b/Changes index 37295fa0..51089554 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,15 @@ Revision history for DBD::Oracle +NEXTRELEASE + + [BUG FIXES] + + - fix serious memory corruption in TAF support (Martin J. Evans) + + [MISCELLANEOUS] + + - hide dr, db and st packages from PAUSE + 1.47_00 2012-07-11 [BUG FIXES] @@ -14,7 +24,7 @@ Revision history for DBD::Oracle Martin J. Evans [DOCUMENTATION] - - Promoted the troubleshooting for the different architectures to + - Promoted the troubleshooting for the different architectures to POD documents, for easier/prettier access. - Added a troubleshooting entry for RT71819 - bound output diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 25a6c851..a3bf1da7 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -123,7 +123,8 @@ BEGIN { } -{ package DBD::Oracle::dr; +{ package # hide from PAUSE + DBD::Oracle::dr; { $DBD::Oracle::dr::VERSION = '1.47_00'; } @@ -328,7 +329,8 @@ BEGIN { } -{ package DBD::Oracle::db; +{ package # hide from PAUSE + DBD::Oracle::db; { $DBD::Oracle::db::VERSION = '1.47_00'; } @@ -753,7 +755,7 @@ SQL } } $SQL .= " ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION\n"; - + # Since DATA_DEFAULT is a LONG, DEFAULT values longer than 80 chars will # throw an ORA-24345 by default; so we check if LongReadLen is set at @@ -1057,7 +1059,8 @@ SQL } # end of package DBD::Oracle::db -{ package DBD::Oracle::st; +{ package # hide from PAUSE + DBD::Oracle::st; { $DBD::Oracle::st::VERSION = '1.47_00'; } @@ -1134,19 +1137,19 @@ BEGIN { return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_count errors") if $err_count; - return wantarray + return wantarray ? ($tuple_count, defined $row_count ? $row_count : undef) : $tuple_count; } sub private_attribute_info { - return { map { $_ => undef } qw/ - ora_lengths - ora_types + return { map { $_ => undef } qw/ + ora_lengths + ora_types ora_rowid - ora_est_row_width - ora_type + ora_est_row_width + ora_type ora_fail_over / }; } diff --git a/oci8.c b/oci8.c index f61242e9..e8ff928d 100644 --- a/oci8.c +++ b/oci8.c @@ -1144,7 +1144,7 @@ dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, /* MJE commented out as we are avoiding DBIS now but as this is an Oracle callback there is no way to pass something non OCI into this func. - + if (DBIS->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBILOGFP, " in '%s' [%lu,%lu]: len %2lu, ind %d%s, value=%s\n", phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), phs->indp, @@ -1320,12 +1320,12 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) return_count = call_pv(cb->function, G_SCALAR); SPAGAIN; - + if (return_count != 1) croak("Expected one scalar back from taf handler"); ret = POPi; - + switch (fo_event){ case OCI_FO_BEGIN: @@ -1350,7 +1350,7 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) } } PUTBACK; - + return 0; } @@ -1364,7 +1364,7 @@ reg_taf_callback( imp_dbh_t *imp_dbh) taf_callback_t *cb = NULL; /*allocate space for the callback */ Newz(1, cb, 1, taf_callback_t); - cb->function= (char*)safemalloc(strlen(imp_dbh->taf_function)); + cb->function= (char*)safemalloc(strlen(imp_dbh->taf_function) + 1); cb->sleep = imp_dbh->taf_sleep; strcpy((char *)cb->function,imp_dbh->taf_function); From c687eb5d11a742ad0f72d50a9a4bb0b6e3c3b6f3 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 10:30:51 +0000 Subject: [PATCH 269/637] fix serious memory corription in TAF handling hide some lower packages from PAUSE git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15355 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 12 +++++++++++- lib/DBD/Oracle.pm | 23 +++++++++++++---------- oci8.c | 10 +++++----- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/Changes b/Changes index 37295fa0..51089554 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,15 @@ Revision history for DBD::Oracle +NEXTRELEASE + + [BUG FIXES] + + - fix serious memory corruption in TAF support (Martin J. Evans) + + [MISCELLANEOUS] + + - hide dr, db and st packages from PAUSE + 1.47_00 2012-07-11 [BUG FIXES] @@ -14,7 +24,7 @@ Revision history for DBD::Oracle Martin J. Evans [DOCUMENTATION] - - Promoted the troubleshooting for the different architectures to + - Promoted the troubleshooting for the different architectures to POD documents, for easier/prettier access. - Added a troubleshooting entry for RT71819 - bound output diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 25a6c851..a3bf1da7 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -123,7 +123,8 @@ BEGIN { } -{ package DBD::Oracle::dr; +{ package # hide from PAUSE + DBD::Oracle::dr; { $DBD::Oracle::dr::VERSION = '1.47_00'; } @@ -328,7 +329,8 @@ BEGIN { } -{ package DBD::Oracle::db; +{ package # hide from PAUSE + DBD::Oracle::db; { $DBD::Oracle::db::VERSION = '1.47_00'; } @@ -753,7 +755,7 @@ SQL } } $SQL .= " ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION\n"; - + # Since DATA_DEFAULT is a LONG, DEFAULT values longer than 80 chars will # throw an ORA-24345 by default; so we check if LongReadLen is set at @@ -1057,7 +1059,8 @@ SQL } # end of package DBD::Oracle::db -{ package DBD::Oracle::st; +{ package # hide from PAUSE + DBD::Oracle::st; { $DBD::Oracle::st::VERSION = '1.47_00'; } @@ -1134,19 +1137,19 @@ BEGIN { return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_count errors") if $err_count; - return wantarray + return wantarray ? ($tuple_count, defined $row_count ? $row_count : undef) : $tuple_count; } sub private_attribute_info { - return { map { $_ => undef } qw/ - ora_lengths - ora_types + return { map { $_ => undef } qw/ + ora_lengths + ora_types ora_rowid - ora_est_row_width - ora_type + ora_est_row_width + ora_type ora_fail_over / }; } diff --git a/oci8.c b/oci8.c index f61242e9..e8ff928d 100644 --- a/oci8.c +++ b/oci8.c @@ -1144,7 +1144,7 @@ dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, /* MJE commented out as we are avoiding DBIS now but as this is an Oracle callback there is no way to pass something non OCI into this func. - + if (DBIS->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBILOGFP, " in '%s' [%lu,%lu]: len %2lu, ind %d%s, value=%s\n", phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), phs->indp, @@ -1320,12 +1320,12 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) return_count = call_pv(cb->function, G_SCALAR); SPAGAIN; - + if (return_count != 1) croak("Expected one scalar back from taf handler"); ret = POPi; - + switch (fo_event){ case OCI_FO_BEGIN: @@ -1350,7 +1350,7 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) } } PUTBACK; - + return 0; } @@ -1364,7 +1364,7 @@ reg_taf_callback( imp_dbh_t *imp_dbh) taf_callback_t *cb = NULL; /*allocate space for the callback */ Newz(1, cb, 1, taf_callback_t); - cb->function= (char*)safemalloc(strlen(imp_dbh->taf_function)); + cb->function= (char*)safemalloc(strlen(imp_dbh->taf_function) + 1); cb->sleep = imp_dbh->taf_sleep; strcpy((char *)cb->function,imp_dbh->taf_function); From c379ae13abf403626c2a4848666685a2be499974 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 10:50:58 +0000 Subject: [PATCH 270/637] Fix issue finding client on machine with client and server and diff architectures git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15356 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ Makefile.PL | 36 ++++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Changes b/Changes index 51089554..7e893527 100644 --- a/Changes +++ b/Changes @@ -6,6 +6,9 @@ NEXTRELEASE - fix serious memory corruption in TAF support (Martin J. Evans) + - fix finding client in situation where client and server both + installed but different architectures (patch by H.Merijn Brand) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE diff --git a/Makefile.PL b/Makefile.PL index e59a97f1..3f322a01 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1525,7 +1525,7 @@ sub find_headers { # compensate for case where final .0 isn't in the install directory name (my $client_version_trim = $client_version_full) =~ s/\.0$//; - my @try = ( # search the ORACLE_HOME we're using first + my @try = grep { -d $_ } ( # search the ORACLE_HOME we're using first # --- Traditional full-install locations "$OH/rdbms/public", # prefer public over others "$OH/rdbms", @@ -1533,19 +1533,23 @@ sub find_headers { # --- Oracle SDK Instant Client locations "$OH/sdk/include", # --- Oracle RPM Instant Client locations - "/usr/include/oracle/$client_version_full/client", # Instant Client for RedHat FC4 - "/usr/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC4 - "/include/oracle/$client_version_full/client", # Instant Client for RedHat FC3 - "/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC3 - "/usr/include/oracle/$client_version/client", # Instant Client 11.1 and up - "/usr/include/oracle/$client_version/client64", # Instant Client 11.1 and up - "/usr/include/oracle/$client_version_trim/client64", # Instant Client 64 - "/usr/include/oracle/$client_version_full/client64", # Instant Client 64 - + map { ( $_, $_."64" ) } + map { ( $_, "/usr$_" ) } + map { "/include/oracle/$_/client" } + $client_version, + $client_version_trim, + $client_version_full, + + #"/include/oracle/$client_version_full/client", # Instant Client for RedHat FC3 + #"/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC3 + #"/usr/include/oracle/$client_version/client64", # Instant Client 11.1 and up + #"/usr/include/oracle/$client_version/client", # Instant Client 11.1 and up + #"/usr/include/oracle/$client_version_full/client64", # Instant Client 64 + #"/usr/include/oracle/$client_version_full/client", # Instant Client for RedHat FC4 + #"/usr/include/oracle/$client_version_trim/client64", # Instant Client 64 + #"/usr/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC4 ); - - # Add /usr/include/oracle based on the oracle home location if oracle home is under # /usr/lib/oracle ( Linux RPM install ). The 11g instant client reports # client_version as 11.1.0.6 from sqlplus, but installs under 11.1.0.1. @@ -1809,10 +1813,10 @@ You have an old copy which you should delete when installing this one.\n"; my ($ldrp) = $self->{LD_RUN_PATH}; # remove redundant /lib or /usr/lib as it can cause problems $ldrp =~ s!:(/usr)?/lib$!! if $ldrp; - # if it's empty then set it manually - #Lincoln: if pick the right library path - my $libdir = main::ora_libdir(); - $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; + # if it's empty then set it manually + #Lincoln: if pick the right library path + my $libdir = main::ora_libdir(); + $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; $self->{LD_RUN_PATH} = $ldrp; local($_) = $self->SUPER::const_loadlibs(@_); From a8d20b9bbe9492407b5e806ee41973f04444ae7b Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 10:50:58 +0000 Subject: [PATCH 271/637] Fix issue finding client on machine with client and server and diff architectures git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15356 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ Makefile.PL | 36 ++++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Changes b/Changes index 51089554..7e893527 100644 --- a/Changes +++ b/Changes @@ -6,6 +6,9 @@ NEXTRELEASE - fix serious memory corruption in TAF support (Martin J. Evans) + - fix finding client in situation where client and server both + installed but different architectures (patch by H.Merijn Brand) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE diff --git a/Makefile.PL b/Makefile.PL index e59a97f1..3f322a01 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1525,7 +1525,7 @@ sub find_headers { # compensate for case where final .0 isn't in the install directory name (my $client_version_trim = $client_version_full) =~ s/\.0$//; - my @try = ( # search the ORACLE_HOME we're using first + my @try = grep { -d $_ } ( # search the ORACLE_HOME we're using first # --- Traditional full-install locations "$OH/rdbms/public", # prefer public over others "$OH/rdbms", @@ -1533,19 +1533,23 @@ sub find_headers { # --- Oracle SDK Instant Client locations "$OH/sdk/include", # --- Oracle RPM Instant Client locations - "/usr/include/oracle/$client_version_full/client", # Instant Client for RedHat FC4 - "/usr/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC4 - "/include/oracle/$client_version_full/client", # Instant Client for RedHat FC3 - "/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC3 - "/usr/include/oracle/$client_version/client", # Instant Client 11.1 and up - "/usr/include/oracle/$client_version/client64", # Instant Client 11.1 and up - "/usr/include/oracle/$client_version_trim/client64", # Instant Client 64 - "/usr/include/oracle/$client_version_full/client64", # Instant Client 64 - + map { ( $_, $_."64" ) } + map { ( $_, "/usr$_" ) } + map { "/include/oracle/$_/client" } + $client_version, + $client_version_trim, + $client_version_full, + + #"/include/oracle/$client_version_full/client", # Instant Client for RedHat FC3 + #"/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC3 + #"/usr/include/oracle/$client_version/client64", # Instant Client 11.1 and up + #"/usr/include/oracle/$client_version/client", # Instant Client 11.1 and up + #"/usr/include/oracle/$client_version_full/client64", # Instant Client 64 + #"/usr/include/oracle/$client_version_full/client", # Instant Client for RedHat FC4 + #"/usr/include/oracle/$client_version_trim/client64", # Instant Client 64 + #"/usr/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC4 ); - - # Add /usr/include/oracle based on the oracle home location if oracle home is under # /usr/lib/oracle ( Linux RPM install ). The 11g instant client reports # client_version as 11.1.0.6 from sqlplus, but installs under 11.1.0.1. @@ -1809,10 +1813,10 @@ You have an old copy which you should delete when installing this one.\n"; my ($ldrp) = $self->{LD_RUN_PATH}; # remove redundant /lib or /usr/lib as it can cause problems $ldrp =~ s!:(/usr)?/lib$!! if $ldrp; - # if it's empty then set it manually - #Lincoln: if pick the right library path - my $libdir = main::ora_libdir(); - $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; + # if it's empty then set it manually + #Lincoln: if pick the right library path + my $libdir = main::ora_libdir(); + $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; $self->{LD_RUN_PATH} = $ldrp; local($_) = $self->SUPER::const_loadlibs(@_); From 51d33f33807f19de15f2f1c983d80660f47b81e2 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 13:53:08 +0000 Subject: [PATCH 272/637] Fix memory leak in TAF support - the TAF function is leaked If the taf_function is passed as a scalar which has gone out of scope TAF support will probably break badly why oh why wasn't taf_function a code ref instead of a string :-( git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15357 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 ++++++ dbdimp.c | 14 +++++++++++--- oci8.c | 11 ++++------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Changes b/Changes index 7e893527..3805166d 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,12 @@ NEXTRELEASE - fix finding client in situation where client and server both installed but different architectures (patch by H.Merijn Brand) + - fix memeory leak in TAF handling - the TAF function was leaked + (Martin J. Evans) + + - fix issue with taf_function being set to a scalar which goes + out of scope before the callback is made (Martin J. Evans) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE diff --git a/dbdimp.c b/dbdimp.c index ca3841dc..bece1488 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -33,7 +33,7 @@ DBISTATE_DECLARE; -int ora_fetchtest; /* intrnal test only, not thread safe */ +int ora_fetchtest; /* internal test only, not thread safe */ int is_extproc = 0; /* not ProC but ExtProc.pm */ int dbd_verbose = 0; /* DBD only debugging*/ int oci_warn = 0; /* show oci warnings */ @@ -489,10 +489,13 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S DBD_ATTRIB_GET_IV( attr, "ora_taf_sleep", 13, svp, imp_dbh->taf_sleep); if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { STRLEN svp_len; + char *fn; + if (!SvPOK(*svp)) croak("ora_taf_function is not a string"); - imp_dbh->taf_function = (char *) SvPV (*svp, svp_len ); - + fn = SvPV(*svp, svp_len); + imp_dbh->taf_function = (char *)safemalloc(svp_len + 1); + strcpy(imp_dbh->taf_function, fn); } if (DBIc_DBISTATE(imp_dbh)->debug || dbd_verbose >= 3) PerlIO_printf( @@ -1121,6 +1124,11 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); } + if (imp_dbh->taf_function) { + Safefree(imp_dbh->taf_function); + imp_dbh->taf_function = NULL; + } + #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { OCIHandleFree_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION,status); diff --git a/oci8.c b/oci8.c index e8ff928d..c8c4f93c 100644 --- a/oci8.c +++ b/oci8.c @@ -1361,19 +1361,16 @@ reg_taf_callback( imp_dbh_t *imp_dbh) dTHX; OCIFocbkStruct tafailover; sword status; - taf_callback_t *cb = NULL; -/*allocate space for the callback */ - Newz(1, cb, 1, taf_callback_t); - cb->function= (char*)safemalloc(strlen(imp_dbh->taf_function) + 1); - cb->sleep = imp_dbh->taf_sleep; - strcpy((char *)cb->function,imp_dbh->taf_function); + + imp_dbh->taf_ctx.function = imp_dbh->taf_function; + imp_dbh->taf_ctx.sleep = imp_dbh->taf_sleep; if (dbd_verbose >= 5 ) { PerlIO_printf(DBIc_LOGPIO(imp_dbh), " In reg_taf_callback\n"); } /* set the context up as a pointer to the taf callback struct*/ - tafailover.fo_ctx = cb; + tafailover.fo_ctx = &imp_dbh->taf_ctx; tafailover.callback_function = &taf_cbk; /* register the callback */ From dfcfbc5744b0b67fd0a36a4f2bf7a0206c31e938 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 13:53:08 +0000 Subject: [PATCH 273/637] Fix memory leak in TAF support - the TAF function is leaked If the taf_function is passed as a scalar which has gone out of scope TAF support will probably break badly why oh why wasn't taf_function a code ref instead of a string :-( git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15357 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 ++++++ dbdimp.c | 14 +++++++++++--- oci8.c | 11 ++++------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Changes b/Changes index 7e893527..3805166d 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,12 @@ NEXTRELEASE - fix finding client in situation where client and server both installed but different architectures (patch by H.Merijn Brand) + - fix memeory leak in TAF handling - the TAF function was leaked + (Martin J. Evans) + + - fix issue with taf_function being set to a scalar which goes + out of scope before the callback is made (Martin J. Evans) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE diff --git a/dbdimp.c b/dbdimp.c index ca3841dc..bece1488 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -33,7 +33,7 @@ DBISTATE_DECLARE; -int ora_fetchtest; /* intrnal test only, not thread safe */ +int ora_fetchtest; /* internal test only, not thread safe */ int is_extproc = 0; /* not ProC but ExtProc.pm */ int dbd_verbose = 0; /* DBD only debugging*/ int oci_warn = 0; /* show oci warnings */ @@ -489,10 +489,13 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S DBD_ATTRIB_GET_IV( attr, "ora_taf_sleep", 13, svp, imp_dbh->taf_sleep); if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { STRLEN svp_len; + char *fn; + if (!SvPOK(*svp)) croak("ora_taf_function is not a string"); - imp_dbh->taf_function = (char *) SvPV (*svp, svp_len ); - + fn = SvPV(*svp, svp_len); + imp_dbh->taf_function = (char *)safemalloc(svp_len + 1); + strcpy(imp_dbh->taf_function, fn); } if (DBIc_DBISTATE(imp_dbh)->debug || dbd_verbose >= 3) PerlIO_printf( @@ -1121,6 +1124,11 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); } + if (imp_dbh->taf_function) { + Safefree(imp_dbh->taf_function); + imp_dbh->taf_function = NULL; + } + #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { OCIHandleFree_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION,status); diff --git a/oci8.c b/oci8.c index e8ff928d..c8c4f93c 100644 --- a/oci8.c +++ b/oci8.c @@ -1361,19 +1361,16 @@ reg_taf_callback( imp_dbh_t *imp_dbh) dTHX; OCIFocbkStruct tafailover; sword status; - taf_callback_t *cb = NULL; -/*allocate space for the callback */ - Newz(1, cb, 1, taf_callback_t); - cb->function= (char*)safemalloc(strlen(imp_dbh->taf_function) + 1); - cb->sleep = imp_dbh->taf_sleep; - strcpy((char *)cb->function,imp_dbh->taf_function); + + imp_dbh->taf_ctx.function = imp_dbh->taf_function; + imp_dbh->taf_ctx.sleep = imp_dbh->taf_sleep; if (dbd_verbose >= 5 ) { PerlIO_printf(DBIc_LOGPIO(imp_dbh), " In reg_taf_callback\n"); } /* set the context up as a pointer to the taf callback struct*/ - tafailover.fo_ctx = cb; + tafailover.fo_ctx = &imp_dbh->taf_ctx; tafailover.callback_function = &taf_cbk; /* register the callback */ From ad7de4603bd314f4f120747eef56742962c4c35e Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 14:18:09 +0000 Subject: [PATCH 274/637] Fix RT 46739 - do not reuse an env handle after connection is broken git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15358 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ dbdimp.c | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/Changes b/Changes index 3805166d..582cd0c2 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,9 @@ NEXTRELEASE - fix issue with taf_function being set to a scalar which goes out of scope before the callback is made (Martin J. Evans) + - fix RT46739 if a connection breaks the environment handle is + not thrown away (Martin J. Evans) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE diff --git a/dbdimp.c b/dbdimp.c index bece1488..d183262c 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -594,6 +594,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S forced_new_environment = 1; } } + /* RT46739 */ + if (imp_dbh->envhp) { + OCIError *errhp; + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &errhp, OCI_HTYPE_ERROR, status); + if (status != OCI_SUCCESS) { + imp_dbh->envhp = NULL; + } else { + OCIHandleFree_log_stat(imp_dbh, errhp, OCI_HTYPE_ERROR, status); + } + } + if (!imp_dbh->envhp ) { SV **init_mode_sv; ub4 init_mode = OCI_OBJECT; /* needed for LOBs (8.0.4) */ From a3396c000a56d65331b5632fe2e8068a4da816b1 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 14:18:09 +0000 Subject: [PATCH 275/637] Fix RT 46739 - do not reuse an env handle after connection is broken git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15358 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ dbdimp.c | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/Changes b/Changes index 3805166d..582cd0c2 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,9 @@ NEXTRELEASE - fix issue with taf_function being set to a scalar which goes out of scope before the callback is made (Martin J. Evans) + - fix RT46739 if a connection breaks the environment handle is + not thrown away (Martin J. Evans) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE diff --git a/dbdimp.c b/dbdimp.c index bece1488..d183262c 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -594,6 +594,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S forced_new_environment = 1; } } + /* RT46739 */ + if (imp_dbh->envhp) { + OCIError *errhp; + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &errhp, OCI_HTYPE_ERROR, status); + if (status != OCI_SUCCESS) { + imp_dbh->envhp = NULL; + } else { + OCIHandleFree_log_stat(imp_dbh, errhp, OCI_HTYPE_ERROR, status); + } + } + if (!imp_dbh->envhp ) { SV **init_mode_sv; ub4 init_mode = OCI_OBJECT; /* needed for LOBs (8.0.4) */ From 46fc657d3e256a3589ba972b83ec7dfda38002a1 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 14:44:02 +0000 Subject: [PATCH 276/637] add more some simple TAF tests continue fix for taf_function leaking and corruption - should be ok now added note that taf_sleep will be withdrawn added note that TAF only works at connect time and reported as RT 78811 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15359 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 9 ++++++++- dbdimp.c | 11 ++++++++++- lib/DBD/Oracle.pm | 20 ++++++++++++++++---- t/38taf.t | 8 +++++--- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index 582cd0c2..95632fec 100644 --- a/Changes +++ b/Changes @@ -18,9 +18,16 @@ NEXTRELEASE - fix RT46739 if a connection breaks the environment handle is not thrown away (Martin J. Evans) + [CHANGE IN BEHAVIOUR] + + - In future versions taf_sleep will be withdrawn as you can simply + sleep in your own callback. + [MISCELLANEOUS] - - hide dr, db and st packages from PAUSE + - hide dr, db and st packages from PAUSE (Martin J. Evans) + + - added a few more simple TAF tests (Martin J. Evans) 1.47_00 2012-07-11 diff --git a/dbdimp.c b/dbdimp.c index d183262c..4c4b3445 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1205,7 +1205,16 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) imp_dbh->using_taf = 1; } else if (kl==16 && strEQ(key, "ora_taf_function") ) { - imp_dbh->taf_function = (char *) SvPV (valuesv, vl ); + STRLEN svp_len; + char *fn; + + if (imp_dbh->taf_function) { + Safefree(imp_dbh->taf_function); + } + + fn = SvPV(valuesv, svp_len); + imp_dbh->taf_function = (char *)safemalloc(svp_len + 1); + strcpy(imp_dbh->taf_function, fn); } else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { imp_dbh->taf_sleep = SvIV (valuesv); diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index a3bf1da7..6b6e0b91 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1380,9 +1380,9 @@ allows for clients to automatically reconnect to an instance in the event of a failure of the instance. The reconnect happens automatically from within the OCI (Oracle Call Interface) library. DBD::Oracle now supports a callback function that will fire when a TAF -event takes place. The main use of the callback is to give your -program the opportunity to inform the user that a failover is taking -place. +event takes place. You may use the callback to inform the +user a failover is taking place or to setup the session again +once the failover has succeeded. You will have to set up TAF on your instance before you can use this callback. You can test your instance to see if you can use TAF @@ -1390,7 +1390,11 @@ callback with $dbh->ora_can_taf(); -If you try to set up a callback without it being enabled DBD::Oracle will croak. +If you try to set up a callback without it being enabled DBD::Oracle +will croak. + +NOTE: Currently, you must enable TAF during DBI's connect. However +once enabled you can change the TAF settings. It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple @@ -1548,6 +1552,10 @@ variable. If your Oracle instance has been configured to use TAF events you can enable the TAF callback by setting this option to any I value. +NOTE: All the ora_taf* attributes must currently be set in the connect +method if you want TAF enabled at the moment i.e., after connect you +can change the callback but you cannot disable TAF. + =head4 ora_taf_function The name of the Perl subroutine that will be called from OCI when a @@ -1573,6 +1581,10 @@ The amount of time in seconds DBD::Oracle will sleep between attempting successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY is returned from the TAF handler. +NOTE: This attribute will be withdrawn in the future so I suggest you +don't use it and if you want to sleep, add it to your own callback +sub. + =head4 ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, diff --git a/t/38taf.t b/t/38taf.t index b1adf93d..a3f2190f 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -19,8 +19,6 @@ my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; -plan tests => 1; - $dbh->disconnect; if ( !$dbh->ora_can_taf ){ @@ -38,7 +36,11 @@ else { ok $dbh = DBI->connect($dsn, $dbuser, '', {ora_taf=>1, ora_taf_sleep=>15, ora_taf_function=>'taf'}); - + is($dbh->{ora_taf}, 1, 'TAF enabled'); + is($dbh->{ora_taf_sleep}, 15, 'TAF sleep set'); + is($dbh->{ora_taf_function}, 'taf', 'TAF callback'); } $dbh->disconnect; + +done_testing(); From af703dad9888137227f3438342fa0ff7628a0943 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 14:44:02 +0000 Subject: [PATCH 277/637] add more some simple TAF tests continue fix for taf_function leaking and corruption - should be ok now added note that taf_sleep will be withdrawn added note that TAF only works at connect time and reported as RT 78811 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15359 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 9 ++++++++- dbdimp.c | 11 ++++++++++- lib/DBD/Oracle.pm | 20 ++++++++++++++++---- t/38taf.t | 8 +++++--- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index 582cd0c2..95632fec 100644 --- a/Changes +++ b/Changes @@ -18,9 +18,16 @@ NEXTRELEASE - fix RT46739 if a connection breaks the environment handle is not thrown away (Martin J. Evans) + [CHANGE IN BEHAVIOUR] + + - In future versions taf_sleep will be withdrawn as you can simply + sleep in your own callback. + [MISCELLANEOUS] - - hide dr, db and st packages from PAUSE + - hide dr, db and st packages from PAUSE (Martin J. Evans) + + - added a few more simple TAF tests (Martin J. Evans) 1.47_00 2012-07-11 diff --git a/dbdimp.c b/dbdimp.c index d183262c..4c4b3445 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1205,7 +1205,16 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) imp_dbh->using_taf = 1; } else if (kl==16 && strEQ(key, "ora_taf_function") ) { - imp_dbh->taf_function = (char *) SvPV (valuesv, vl ); + STRLEN svp_len; + char *fn; + + if (imp_dbh->taf_function) { + Safefree(imp_dbh->taf_function); + } + + fn = SvPV(valuesv, svp_len); + imp_dbh->taf_function = (char *)safemalloc(svp_len + 1); + strcpy(imp_dbh->taf_function, fn); } else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { imp_dbh->taf_sleep = SvIV (valuesv); diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index a3bf1da7..6b6e0b91 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1380,9 +1380,9 @@ allows for clients to automatically reconnect to an instance in the event of a failure of the instance. The reconnect happens automatically from within the OCI (Oracle Call Interface) library. DBD::Oracle now supports a callback function that will fire when a TAF -event takes place. The main use of the callback is to give your -program the opportunity to inform the user that a failover is taking -place. +event takes place. You may use the callback to inform the +user a failover is taking place or to setup the session again +once the failover has succeeded. You will have to set up TAF on your instance before you can use this callback. You can test your instance to see if you can use TAF @@ -1390,7 +1390,11 @@ callback with $dbh->ora_can_taf(); -If you try to set up a callback without it being enabled DBD::Oracle will croak. +If you try to set up a callback without it being enabled DBD::Oracle +will croak. + +NOTE: Currently, you must enable TAF during DBI's connect. However +once enabled you can change the TAF settings. It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple @@ -1548,6 +1552,10 @@ variable. If your Oracle instance has been configured to use TAF events you can enable the TAF callback by setting this option to any I value. +NOTE: All the ora_taf* attributes must currently be set in the connect +method if you want TAF enabled at the moment i.e., after connect you +can change the callback but you cannot disable TAF. + =head4 ora_taf_function The name of the Perl subroutine that will be called from OCI when a @@ -1573,6 +1581,10 @@ The amount of time in seconds DBD::Oracle will sleep between attempting successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY is returned from the TAF handler. +NOTE: This attribute will be withdrawn in the future so I suggest you +don't use it and if you want to sleep, add it to your own callback +sub. + =head4 ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, diff --git a/t/38taf.t b/t/38taf.t index b1adf93d..a3f2190f 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -19,8 +19,6 @@ my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; -plan tests => 1; - $dbh->disconnect; if ( !$dbh->ora_can_taf ){ @@ -38,7 +36,11 @@ else { ok $dbh = DBI->connect($dsn, $dbuser, '', {ora_taf=>1, ora_taf_sleep=>15, ora_taf_function=>'taf'}); - + is($dbh->{ora_taf}, 1, 'TAF enabled'); + is($dbh->{ora_taf_sleep}, 15, 'TAF sleep set'); + is($dbh->{ora_taf_function}, 'taf', 'TAF callback'); } $dbh->disconnect; + +done_testing(); From cc01b5fbc71de83738c39a39dc390982227c10f8 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 9 Aug 2012 11:00:51 -0400 Subject: [PATCH 278/637] v1.48 - promote 1.47_00 to official release --- Changes | 3 +++ dist.ini | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 58cc09ed..a2913e06 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,9 @@ Revision history for DBD::Oracle {{$NEXT}} +1.48 2012-08-09 + - promote 1.47_00 to official release + 1.47_00 2012-07-11 [BUG FIXES] diff --git a/dist.ini b/dist.ini index e3830372..c0bbd599 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.47_00 +version = 1.48 [Authority] authority=cpan:PYTHIAN From 6c7c84422ab963f5ea8fd9772682fd219d3dd70e Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 10:30:51 +0000 Subject: [PATCH 279/637] fix serious memory corruption in TAF handling hide some lower packages from PAUSE git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15355 50811bd7-b8ce-0310-adc1-d9db26280581 Conflicts: Changes lib/DBD/Oracle.pm --- Changes | 10 +++++++++- lib/DBD/Oracle.pm | 23 +++++++++++++---------- oci8.c | 10 +++++----- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/Changes b/Changes index a2913e06..f4688255 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,14 @@ Revision history for DBD::Oracle {{$NEXT}} + [BUG FIXES] + + - fix serious memory corruption in TAF support (Martin J. Evans) + + [MISCELLANEOUS] + + - hide dr, db and st packages from PAUSE + 1.48 2012-08-09 - promote 1.47_00 to official release @@ -19,7 +27,7 @@ Revision history for DBD::Oracle Martin J. Evans [DOCUMENTATION] - - Promoted the troubleshooting for the different architectures to + - Promoted the troubleshooting for the different architectures to POD documents, for easier/prettier access. - Added a troubleshooting entry for RT71819 - bound output diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 7b4031e3..52792051 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -117,7 +117,8 @@ package DBD::Oracle; } -{ package DBD::Oracle::dr; # ====== DRIVER ====== +{ package # hide from PAUSE + DBD::Oracle::dr; # ====== DRIVER ====== use strict; my %dbnames = (); # holds list of known databases (oratab + tnsnames) @@ -316,7 +317,8 @@ package DBD::Oracle; } -{ package DBD::Oracle::db; # ====== DATABASE ====== +{ package # hide from PAUSE + DBD::Oracle::db; # ====== DATABASE ====== use strict; use DBI qw(:sql_types); @@ -735,7 +737,7 @@ SQL } } $SQL .= " ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION\n"; - + # Since DATA_DEFAULT is a LONG, DEFAULT values longer than 80 chars will # throw an ORA-24345 by default; so we check if LongReadLen is set at @@ -1039,7 +1041,8 @@ SQL } # end of package DBD::Oracle::db -{ package DBD::Oracle::st; # ====== STATEMENT ====== +{ package # hide from PAUSE + DBD::Oracle::st; # ====== STATEMENT ====== sub bind_param_inout_array { @@ -1110,19 +1113,19 @@ SQL return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_count errors") if $err_count; - return wantarray + return wantarray ? ($tuple_count, defined $row_count ? $row_count : undef) : $tuple_count; } sub private_attribute_info { - return { map { $_ => undef } qw/ - ora_lengths - ora_types + return { map { $_ => undef } qw/ + ora_lengths + ora_types ora_rowid - ora_est_row_width - ora_type + ora_est_row_width + ora_type ora_fail_over / }; } diff --git a/oci8.c b/oci8.c index f61242e9..e8ff928d 100644 --- a/oci8.c +++ b/oci8.c @@ -1144,7 +1144,7 @@ dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, /* MJE commented out as we are avoiding DBIS now but as this is an Oracle callback there is no way to pass something non OCI into this func. - + if (DBIS->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf(DBILOGFP, " in '%s' [%lu,%lu]: len %2lu, ind %d%s, value=%s\n", phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), phs->indp, @@ -1320,12 +1320,12 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) return_count = call_pv(cb->function, G_SCALAR); SPAGAIN; - + if (return_count != 1) croak("Expected one scalar back from taf handler"); ret = POPi; - + switch (fo_event){ case OCI_FO_BEGIN: @@ -1350,7 +1350,7 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) } } PUTBACK; - + return 0; } @@ -1364,7 +1364,7 @@ reg_taf_callback( imp_dbh_t *imp_dbh) taf_callback_t *cb = NULL; /*allocate space for the callback */ Newz(1, cb, 1, taf_callback_t); - cb->function= (char*)safemalloc(strlen(imp_dbh->taf_function)); + cb->function= (char*)safemalloc(strlen(imp_dbh->taf_function) + 1); cb->sleep = imp_dbh->taf_sleep; strcpy((char *)cb->function,imp_dbh->taf_function); From 672d5520bc95fcb13fe0dc3829e736d9786a51ec Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 10:50:58 +0000 Subject: [PATCH 280/637] Fix issue finding client on machine with client and server and diff architectures git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15356 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ Makefile.PL | 36 ++++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Changes b/Changes index f4688255..d697b118 100644 --- a/Changes +++ b/Changes @@ -6,6 +6,9 @@ Revision history for DBD::Oracle - fix serious memory corruption in TAF support (Martin J. Evans) + - fix finding client in situation where client and server both + installed but different architectures (patch by H.Merijn Brand) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE diff --git a/Makefile.PL b/Makefile.PL index e59a97f1..3f322a01 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1525,7 +1525,7 @@ sub find_headers { # compensate for case where final .0 isn't in the install directory name (my $client_version_trim = $client_version_full) =~ s/\.0$//; - my @try = ( # search the ORACLE_HOME we're using first + my @try = grep { -d $_ } ( # search the ORACLE_HOME we're using first # --- Traditional full-install locations "$OH/rdbms/public", # prefer public over others "$OH/rdbms", @@ -1533,19 +1533,23 @@ sub find_headers { # --- Oracle SDK Instant Client locations "$OH/sdk/include", # --- Oracle RPM Instant Client locations - "/usr/include/oracle/$client_version_full/client", # Instant Client for RedHat FC4 - "/usr/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC4 - "/include/oracle/$client_version_full/client", # Instant Client for RedHat FC3 - "/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC3 - "/usr/include/oracle/$client_version/client", # Instant Client 11.1 and up - "/usr/include/oracle/$client_version/client64", # Instant Client 11.1 and up - "/usr/include/oracle/$client_version_trim/client64", # Instant Client 64 - "/usr/include/oracle/$client_version_full/client64", # Instant Client 64 - + map { ( $_, $_."64" ) } + map { ( $_, "/usr$_" ) } + map { "/include/oracle/$_/client" } + $client_version, + $client_version_trim, + $client_version_full, + + #"/include/oracle/$client_version_full/client", # Instant Client for RedHat FC3 + #"/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC3 + #"/usr/include/oracle/$client_version/client64", # Instant Client 11.1 and up + #"/usr/include/oracle/$client_version/client", # Instant Client 11.1 and up + #"/usr/include/oracle/$client_version_full/client64", # Instant Client 64 + #"/usr/include/oracle/$client_version_full/client", # Instant Client for RedHat FC4 + #"/usr/include/oracle/$client_version_trim/client64", # Instant Client 64 + #"/usr/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC4 ); - - # Add /usr/include/oracle based on the oracle home location if oracle home is under # /usr/lib/oracle ( Linux RPM install ). The 11g instant client reports # client_version as 11.1.0.6 from sqlplus, but installs under 11.1.0.1. @@ -1809,10 +1813,10 @@ You have an old copy which you should delete when installing this one.\n"; my ($ldrp) = $self->{LD_RUN_PATH}; # remove redundant /lib or /usr/lib as it can cause problems $ldrp =~ s!:(/usr)?/lib$!! if $ldrp; - # if it's empty then set it manually - #Lincoln: if pick the right library path - my $libdir = main::ora_libdir(); - $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; + # if it's empty then set it manually + #Lincoln: if pick the right library path + my $libdir = main::ora_libdir(); + $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; $self->{LD_RUN_PATH} = $ldrp; local($_) = $self->SUPER::const_loadlibs(@_); From f609bce1f1396c299c841284b340984aa9f27779 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 13:53:08 +0000 Subject: [PATCH 281/637] Fix memory leak in TAF support - the TAF function is leaked If the taf_function is passed as a scalar which has gone out of scope TAF support will probably break badly why oh why wasn't taf_function a code ref instead of a string :-( git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15357 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 ++++++ dbdimp.c | 14 +++++++++++--- oci8.c | 11 ++++------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Changes b/Changes index d697b118..7629ad82 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,12 @@ Revision history for DBD::Oracle - fix finding client in situation where client and server both installed but different architectures (patch by H.Merijn Brand) + - fix memeory leak in TAF handling - the TAF function was leaked + (Martin J. Evans) + + - fix issue with taf_function being set to a scalar which goes + out of scope before the callback is made (Martin J. Evans) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE diff --git a/dbdimp.c b/dbdimp.c index ca3841dc..bece1488 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -33,7 +33,7 @@ DBISTATE_DECLARE; -int ora_fetchtest; /* intrnal test only, not thread safe */ +int ora_fetchtest; /* internal test only, not thread safe */ int is_extproc = 0; /* not ProC but ExtProc.pm */ int dbd_verbose = 0; /* DBD only debugging*/ int oci_warn = 0; /* show oci warnings */ @@ -489,10 +489,13 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S DBD_ATTRIB_GET_IV( attr, "ora_taf_sleep", 13, svp, imp_dbh->taf_sleep); if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { STRLEN svp_len; + char *fn; + if (!SvPOK(*svp)) croak("ora_taf_function is not a string"); - imp_dbh->taf_function = (char *) SvPV (*svp, svp_len ); - + fn = SvPV(*svp, svp_len); + imp_dbh->taf_function = (char *)safemalloc(svp_len + 1); + strcpy(imp_dbh->taf_function, fn); } if (DBIc_DBISTATE(imp_dbh)->debug || dbd_verbose >= 3) PerlIO_printf( @@ -1121,6 +1124,11 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); } + if (imp_dbh->taf_function) { + Safefree(imp_dbh->taf_function); + imp_dbh->taf_function = NULL; + } + #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { OCIHandleFree_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION,status); diff --git a/oci8.c b/oci8.c index e8ff928d..c8c4f93c 100644 --- a/oci8.c +++ b/oci8.c @@ -1361,19 +1361,16 @@ reg_taf_callback( imp_dbh_t *imp_dbh) dTHX; OCIFocbkStruct tafailover; sword status; - taf_callback_t *cb = NULL; -/*allocate space for the callback */ - Newz(1, cb, 1, taf_callback_t); - cb->function= (char*)safemalloc(strlen(imp_dbh->taf_function) + 1); - cb->sleep = imp_dbh->taf_sleep; - strcpy((char *)cb->function,imp_dbh->taf_function); + + imp_dbh->taf_ctx.function = imp_dbh->taf_function; + imp_dbh->taf_ctx.sleep = imp_dbh->taf_sleep; if (dbd_verbose >= 5 ) { PerlIO_printf(DBIc_LOGPIO(imp_dbh), " In reg_taf_callback\n"); } /* set the context up as a pointer to the taf callback struct*/ - tafailover.fo_ctx = cb; + tafailover.fo_ctx = &imp_dbh->taf_ctx; tafailover.callback_function = &taf_cbk; /* register the callback */ From 95ae6f0f46e82a32b39cb2c95cdfa2f9c3c54abe Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 14:18:09 +0000 Subject: [PATCH 282/637] Fix RT 46739 - do not reuse an env handle after connection is broken git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15358 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ dbdimp.c | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/Changes b/Changes index 7629ad82..c275d7dc 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,9 @@ Revision history for DBD::Oracle - fix issue with taf_function being set to a scalar which goes out of scope before the callback is made (Martin J. Evans) + - fix RT46739 if a connection breaks the environment handle is + not thrown away (Martin J. Evans) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE diff --git a/dbdimp.c b/dbdimp.c index bece1488..d183262c 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -594,6 +594,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S forced_new_environment = 1; } } + /* RT46739 */ + if (imp_dbh->envhp) { + OCIError *errhp; + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &errhp, OCI_HTYPE_ERROR, status); + if (status != OCI_SUCCESS) { + imp_dbh->envhp = NULL; + } else { + OCIHandleFree_log_stat(imp_dbh, errhp, OCI_HTYPE_ERROR, status); + } + } + if (!imp_dbh->envhp ) { SV **init_mode_sv; ub4 init_mode = OCI_OBJECT; /* needed for LOBs (8.0.4) */ From 3097c22295bac282fdc7af6a115bbc3771582a3e Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 6 Aug 2012 14:44:02 +0000 Subject: [PATCH 283/637] add more some simple TAF tests continue fix for taf_function leaking and corruption - should be ok now added note that taf_sleep will be withdrawn added note that TAF only works at connect time and reported as RT 78811 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15359 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 9 ++++++++- dbdimp.c | 11 ++++++++++- lib/DBD/Oracle.pm | 20 ++++++++++++++++---- t/38taf.t | 8 +++++--- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index c275d7dc..eb6dcaba 100644 --- a/Changes +++ b/Changes @@ -18,9 +18,16 @@ Revision history for DBD::Oracle - fix RT46739 if a connection breaks the environment handle is not thrown away (Martin J. Evans) + [CHANGE IN BEHAVIOUR] + + - In future versions taf_sleep will be withdrawn as you can simply + sleep in your own callback. + [MISCELLANEOUS] - - hide dr, db and st packages from PAUSE + - hide dr, db and st packages from PAUSE (Martin J. Evans) + + - added a few more simple TAF tests (Martin J. Evans) 1.48 2012-08-09 - promote 1.47_00 to official release diff --git a/dbdimp.c b/dbdimp.c index d183262c..4c4b3445 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1205,7 +1205,16 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) imp_dbh->using_taf = 1; } else if (kl==16 && strEQ(key, "ora_taf_function") ) { - imp_dbh->taf_function = (char *) SvPV (valuesv, vl ); + STRLEN svp_len; + char *fn; + + if (imp_dbh->taf_function) { + Safefree(imp_dbh->taf_function); + } + + fn = SvPV(valuesv, svp_len); + imp_dbh->taf_function = (char *)safemalloc(svp_len + 1); + strcpy(imp_dbh->taf_function, fn); } else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { imp_dbh->taf_sleep = SvIV (valuesv); diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 52792051..defce65d 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1349,9 +1349,9 @@ allows for clients to automatically reconnect to an instance in the event of a failure of the instance. The reconnect happens automatically from within the OCI (Oracle Call Interface) library. DBD::Oracle now supports a callback function that will fire when a TAF -event takes place. The main use of the callback is to give your -program the opportunity to inform the user that a failover is taking -place. +event takes place. You may use the callback to inform the +user a failover is taking place or to setup the session again +once the failover has succeeded. You will have to set up TAF on your instance before you can use this callback. You can test your instance to see if you can use TAF @@ -1359,7 +1359,11 @@ callback with $dbh->ora_can_taf(); -If you try to set up a callback without it being enabled DBD::Oracle will croak. +If you try to set up a callback without it being enabled DBD::Oracle +will croak. + +NOTE: Currently, you must enable TAF during DBI's connect. However +once enabled you can change the TAF settings. It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple @@ -1517,6 +1521,10 @@ variable. If your Oracle instance has been configured to use TAF events you can enable the TAF callback by setting this option to any I value. +NOTE: All the ora_taf* attributes must currently be set in the connect +method if you want TAF enabled at the moment i.e., after connect you +can change the callback but you cannot disable TAF. + =head4 ora_taf_function The name of the Perl subroutine that will be called from OCI when a @@ -1542,6 +1550,10 @@ The amount of time in seconds DBD::Oracle will sleep between attempting successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY is returned from the TAF handler. +NOTE: This attribute will be withdrawn in the future so I suggest you +don't use it and if you want to sleep, add it to your own callback +sub. + =head4 ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, diff --git a/t/38taf.t b/t/38taf.t index b1adf93d..a3f2190f 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -19,8 +19,6 @@ my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; -plan tests => 1; - $dbh->disconnect; if ( !$dbh->ora_can_taf ){ @@ -38,7 +36,11 @@ else { ok $dbh = DBI->connect($dsn, $dbuser, '', {ora_taf=>1, ora_taf_sleep=>15, ora_taf_function=>'taf'}); - + is($dbh->{ora_taf}, 1, 'TAF enabled'); + is($dbh->{ora_taf_sleep}, 15, 'TAF sleep set'); + is($dbh->{ora_taf_function}, 'taf', 'TAF callback'); } $dbh->disconnect; + +done_testing(); From 71463915c43b13f1c96d3616c7468cc5f64ebe5c Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 9 Aug 2012 15:23:50 +0000 Subject: [PATCH 284/637] merging the bump to v1.48 (and v1.49_00 for dev) git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15363 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ META.json | 14 ++++++------ META.yml | 14 ++++++------ README | 18 +++++++++++---- README.mkdn | 22 ++++++++++++++---- lib/DBD/Oracle.pm | 28 ++++------------------- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pm | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 18 files changed, 67 insertions(+), 60 deletions(-) diff --git a/Changes b/Changes index 95632fec..25c12d8e 100644 --- a/Changes +++ b/Changes @@ -29,6 +29,9 @@ NEXTRELEASE - added a few more simple TAF tests (Martin J. Evans) +1.48 2012-08-09 + - promote 1.47_00 to official release + 1.47_00 2012-07-11 [BUG FIXES] diff --git a/META.json b/META.json index 5f4887ca..9468ddbe 100644 --- a/META.json +++ b/META.json @@ -52,27 +52,27 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.47_00" + "version" : "1.49_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.47_00" + "version" : "1.49_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.47_00" + "version" : "1.49_00" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.47_00" + "version" : "1.49_00" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.47_00" + "version" : "1.49_00" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.47_00" + "version" : "1.49_00" } }, "release_status" : "testing", @@ -88,7 +88,7 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, - "version" : "1.47_00", + "version" : "1.49_00", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index de8b99e6..b0bd602d 100644 --- a/META.yml +++ b/META.yml @@ -30,22 +30,22 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.47_00 + version: 1.49_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.47_00 + version: 1.49_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.47_00 + version: 1.49_00 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.47_00 + version: 1.49_00 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.47_00 + version: 1.49_00 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.47_00 + version: 1.49_00 requires: DBI: 0 DynaLoader: 0 @@ -57,7 +57,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.47_00 +version: 1.49_00 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 0697b8dd..1fd564ee 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.47_00 + version 1.49_00 SYNOPSIS use DBI; @@ -206,9 +206,9 @@ DBI CLASS METHODS for clients to automatically reconnect to an instance in the event of a failure of the instance. The reconnect happens automatically from within the OCI (Oracle Call Interface) library. DBD::Oracle now supports a - callback function that will fire when a TAF event takes place. The main - use of the callback is to give your program the opportunity to inform - the user that a failover is taking place. + callback function that will fire when a TAF event takes place. You may + use the callback to inform the user a failover is taking place or to + setup the session again once the failover has succeeded. You will have to set up TAF on your instance before you can use this callback. You can test your instance to see if you can use TAF callback @@ -219,6 +219,9 @@ DBI CLASS METHODS If you try to set up a callback without it being enabled DBD::Oracle will croak. + NOTE: Currently, you must enable TAF during DBI's connect. However once + enabled you can change the TAF settings. + It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple example: @@ -367,6 +370,10 @@ DBI CLASS METHODS If your Oracle instance has been configured to use TAF events you can enable the TAF callback by setting this option to any *true* value. + NOTE: All the ora_taf* attributes must currently be set in the connect + method if you want TAF enabled at the moment i.e., after connect you can + change the callback but you cannot disable TAF. + ora_taf_function The name of the Perl subroutine that will be called from OCI when a TAF event occurs. You must supply a perl function to use the callback and it @@ -390,6 +397,9 @@ DBI CLASS METHODS successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY is returned from the TAF handler. + NOTE: This attribute will be withdrawn in the future so I suggest you + don't use it and if you want to sleep, add it to your own callback sub. + ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, SYSOPER and ORA_SYSASM authorization. The ORA_SYSDBA, ORA_SYSOPER and diff --git a/README.mkdn b/README.mkdn index 9df11205..f2e4535e 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.47_00 +version 1.49_00 # SYNOPSIS @@ -209,9 +209,9 @@ allows for clients to automatically reconnect to an instance in the event of a failure of the instance. The reconnect happens automatically from within the OCI (Oracle Call Interface) library. DBD::Oracle now supports a callback function that will fire when a TAF -event takes place. The main use of the callback is to give your -program the opportunity to inform the user that a failover is taking -place. +event takes place. You may use the callback to inform the +user a failover is taking place or to setup the session again +once the failover has succeeded. You will have to set up TAF on your instance before you can use this callback. You can test your instance to see if you can use TAF @@ -219,7 +219,11 @@ callback with $dbh->ora_can_taf(); -If you try to set up a callback without it being enabled DBD::Oracle will croak. +If you try to set up a callback without it being enabled DBD::Oracle +will croak. + +NOTE: Currently, you must enable TAF during DBI's connect. However +once enabled you can change the TAF settings. It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple @@ -377,6 +381,10 @@ variable. If your Oracle instance has been configured to use TAF events you can enable the TAF callback by setting this option to any _true_ value. +NOTE: All the ora_taf* attributes must currently be set in the connect +method if you want TAF enabled at the moment i.e., after connect you +can change the callback but you cannot disable TAF. + #### ora_taf_function The name of the Perl subroutine that will be called from OCI when a @@ -402,6 +410,10 @@ The amount of time in seconds DBD::Oracle will sleep between attempting successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY is returned from the TAF handler. +NOTE: This attribute will be withdrawn in the future so I suggest you +don't use it and if you want to sleep, add it to your own callback +sub. + #### ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 6b6e0b91..a6727eef 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.47_00'; + $DBD::Oracle::VERSION = '1.49_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -124,13 +124,7 @@ BEGIN { { package # hide from PAUSE - DBD::Oracle::dr; -{ - $DBD::Oracle::dr::VERSION = '1.47_00'; -} -BEGIN { - $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; -} # ====== DRIVER ====== + DBD::Oracle::dr; # ====== DRIVER ====== use strict; my %dbnames = (); # holds list of known databases (oratab + tnsnames) @@ -330,13 +324,7 @@ BEGIN { { package # hide from PAUSE - DBD::Oracle::db; -{ - $DBD::Oracle::db::VERSION = '1.47_00'; -} -BEGIN { - $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; -} # ====== DATABASE ====== + DBD::Oracle::db; # ====== DATABASE ====== use strict; use DBI qw(:sql_types); @@ -1060,13 +1048,7 @@ SQL { package # hide from PAUSE - DBD::Oracle::st; -{ - $DBD::Oracle::st::VERSION = '1.47_00'; -} -BEGIN { - $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; -} # ====== STATEMENT ====== + DBD::Oracle::st; # ====== STATEMENT ====== sub bind_param_inout_array { @@ -1167,7 +1149,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 1dc84996..0f48c2a6 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.47_00'; + $DBD::Oracle::GetInfo::VERSION = '1.49_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index e4680021..ba950f5c 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.47_00'; + $DBD::Oracle::Object::VERSION = '1.49_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 7b4e6cd3..87ed8785 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index 55f35d6c..9bcd3947 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index c98b5bdd..aae9023a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pm b/lib/DBD/Oracle/Troubleshooting/Hpux.pm index 3b7f3114..32a5fc0d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pm +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pm @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 7964170e..44755c62 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 1b56c48c..d00358be 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index 82d14be8..c5fdf7c8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index b689f080..5d48431d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index 9acaf51c..fd2418a5 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 4a85b9a1..cde25565 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 DBD::Oracle and Windows 64bit From 25dfe971948489165618b7acf4a039daa37a2e62 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 9 Aug 2012 15:23:50 +0000 Subject: [PATCH 285/637] merging the bump to v1.48 (and v1.49_00 for dev) git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15363 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ META.json | 14 ++++++------ META.yml | 14 ++++++------ README | 18 +++++++++++---- README.mkdn | 22 ++++++++++++++---- lib/DBD/Oracle.pm | 28 ++++------------------- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pm | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 18 files changed, 67 insertions(+), 60 deletions(-) diff --git a/Changes b/Changes index 95632fec..25c12d8e 100644 --- a/Changes +++ b/Changes @@ -29,6 +29,9 @@ NEXTRELEASE - added a few more simple TAF tests (Martin J. Evans) +1.48 2012-08-09 + - promote 1.47_00 to official release + 1.47_00 2012-07-11 [BUG FIXES] diff --git a/META.json b/META.json index 5f4887ca..9468ddbe 100644 --- a/META.json +++ b/META.json @@ -52,27 +52,27 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.47_00" + "version" : "1.49_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.47_00" + "version" : "1.49_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.47_00" + "version" : "1.49_00" }, "DBD::Oracle::db" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.47_00" + "version" : "1.49_00" }, "DBD::Oracle::dr" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.47_00" + "version" : "1.49_00" }, "DBD::Oracle::st" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.47_00" + "version" : "1.49_00" } }, "release_status" : "testing", @@ -88,7 +88,7 @@ "web" : "http://github.com/yanick/DBD-Oracle/tree" } }, - "version" : "1.47_00", + "version" : "1.49_00", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index de8b99e6..b0bd602d 100644 --- a/META.yml +++ b/META.yml @@ -30,22 +30,22 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.47_00 + version: 1.49_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.47_00 + version: 1.49_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.47_00 + version: 1.49_00 DBD::Oracle::db: file: lib/DBD/Oracle.pm - version: 1.47_00 + version: 1.49_00 DBD::Oracle::dr: file: lib/DBD/Oracle.pm - version: 1.47_00 + version: 1.49_00 DBD::Oracle::st: file: lib/DBD/Oracle.pm - version: 1.47_00 + version: 1.49_00 requires: DBI: 0 DynaLoader: 0 @@ -57,7 +57,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: git://github.com/yanick/DBD-Oracle.git -version: 1.47_00 +version: 1.49_00 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 0697b8dd..1fd564ee 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.47_00 + version 1.49_00 SYNOPSIS use DBI; @@ -206,9 +206,9 @@ DBI CLASS METHODS for clients to automatically reconnect to an instance in the event of a failure of the instance. The reconnect happens automatically from within the OCI (Oracle Call Interface) library. DBD::Oracle now supports a - callback function that will fire when a TAF event takes place. The main - use of the callback is to give your program the opportunity to inform - the user that a failover is taking place. + callback function that will fire when a TAF event takes place. You may + use the callback to inform the user a failover is taking place or to + setup the session again once the failover has succeeded. You will have to set up TAF on your instance before you can use this callback. You can test your instance to see if you can use TAF callback @@ -219,6 +219,9 @@ DBI CLASS METHODS If you try to set up a callback without it being enabled DBD::Oracle will croak. + NOTE: Currently, you must enable TAF during DBI's connect. However once + enabled you can change the TAF settings. + It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple example: @@ -367,6 +370,10 @@ DBI CLASS METHODS If your Oracle instance has been configured to use TAF events you can enable the TAF callback by setting this option to any *true* value. + NOTE: All the ora_taf* attributes must currently be set in the connect + method if you want TAF enabled at the moment i.e., after connect you can + change the callback but you cannot disable TAF. + ora_taf_function The name of the Perl subroutine that will be called from OCI when a TAF event occurs. You must supply a perl function to use the callback and it @@ -390,6 +397,9 @@ DBI CLASS METHODS successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY is returned from the TAF handler. + NOTE: This attribute will be withdrawn in the future so I suggest you + don't use it and if you want to sleep, add it to your own callback sub. + ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, SYSOPER and ORA_SYSASM authorization. The ORA_SYSDBA, ORA_SYSOPER and diff --git a/README.mkdn b/README.mkdn index 9df11205..f2e4535e 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.47_00 +version 1.49_00 # SYNOPSIS @@ -209,9 +209,9 @@ allows for clients to automatically reconnect to an instance in the event of a failure of the instance. The reconnect happens automatically from within the OCI (Oracle Call Interface) library. DBD::Oracle now supports a callback function that will fire when a TAF -event takes place. The main use of the callback is to give your -program the opportunity to inform the user that a failover is taking -place. +event takes place. You may use the callback to inform the +user a failover is taking place or to setup the session again +once the failover has succeeded. You will have to set up TAF on your instance before you can use this callback. You can test your instance to see if you can use TAF @@ -219,7 +219,11 @@ callback with $dbh->ora_can_taf(); -If you try to set up a callback without it being enabled DBD::Oracle will croak. +If you try to set up a callback without it being enabled DBD::Oracle +will croak. + +NOTE: Currently, you must enable TAF during DBI's connect. However +once enabled you can change the TAF settings. It is outside the scope of this document to go through all of the possible TAF situations you might want to set up but here is a simple @@ -377,6 +381,10 @@ variable. If your Oracle instance has been configured to use TAF events you can enable the TAF callback by setting this option to any _true_ value. +NOTE: All the ora_taf* attributes must currently be set in the connect +method if you want TAF enabled at the moment i.e., after connect you +can change the callback but you cannot disable TAF. + #### ora_taf_function The name of the Perl subroutine that will be called from OCI when a @@ -402,6 +410,10 @@ The amount of time in seconds DBD::Oracle will sleep between attempting successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY is returned from the TAF handler. +NOTE: This attribute will be withdrawn in the future so I suggest you +don't use it and if you want to sleep, add it to your own callback +sub. + #### ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 6b6e0b91..a6727eef 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.47_00'; + $DBD::Oracle::VERSION = '1.49_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -124,13 +124,7 @@ BEGIN { { package # hide from PAUSE - DBD::Oracle::dr; -{ - $DBD::Oracle::dr::VERSION = '1.47_00'; -} -BEGIN { - $DBD::Oracle::dr::AUTHORITY = 'cpan:PYTHIAN'; -} # ====== DRIVER ====== + DBD::Oracle::dr; # ====== DRIVER ====== use strict; my %dbnames = (); # holds list of known databases (oratab + tnsnames) @@ -330,13 +324,7 @@ BEGIN { { package # hide from PAUSE - DBD::Oracle::db; -{ - $DBD::Oracle::db::VERSION = '1.47_00'; -} -BEGIN { - $DBD::Oracle::db::AUTHORITY = 'cpan:PYTHIAN'; -} # ====== DATABASE ====== + DBD::Oracle::db; # ====== DATABASE ====== use strict; use DBI qw(:sql_types); @@ -1060,13 +1048,7 @@ SQL { package # hide from PAUSE - DBD::Oracle::st; -{ - $DBD::Oracle::st::VERSION = '1.47_00'; -} -BEGIN { - $DBD::Oracle::st::AUTHORITY = 'cpan:PYTHIAN'; -} # ====== STATEMENT ====== + DBD::Oracle::st; # ====== STATEMENT ====== sub bind_param_inout_array { @@ -1167,7 +1149,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 1dc84996..0f48c2a6 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.47_00'; + $DBD::Oracle::GetInfo::VERSION = '1.49_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index e4680021..ba950f5c 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.47_00'; + $DBD::Oracle::Object::VERSION = '1.49_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 7b4e6cd3..87ed8785 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index 55f35d6c..9bcd3947 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index c98b5bdd..aae9023a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pm b/lib/DBD/Oracle/Troubleshooting/Hpux.pm index 3b7f3114..32a5fc0d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pm +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pm @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 7964170e..44755c62 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 1b56c48c..d00358be 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index 82d14be8..c5fdf7c8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index b689f080..5d48431d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index 9acaf51c..fd2418a5 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 4a85b9a1..cde25565 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.47_00 +version 1.49_00 =head1 DBD::Oracle and Windows 64bit From 42729f0d435b587b19cf7d8308eecd1267ae1385 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 9 Aug 2012 16:46:43 +0000 Subject: [PATCH 286/637] loads of TAF changes more tests for attributes removed loads of code duplicated in connect for attributes which are set in STORE by default git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15364 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 17 ++++++- dbdimp.c | 140 +++++++++++++++++++---------------------------------- dbdimp.h | 11 ++--- oci8.c | 7 ++- t/38taf.t | 18 ++++++- t/39attr.t | 57 ++++++++++++++++++++++ 6 files changed, 149 insertions(+), 101 deletions(-) create mode 100755 t/39attr.t diff --git a/Changes b/Changes index 25c12d8e..d93fa05b 100644 --- a/Changes +++ b/Changes @@ -9,7 +9,7 @@ NEXTRELEASE - fix finding client in situation where client and server both installed but different architectures (patch by H.Merijn Brand) - - fix memeory leak in TAF handling - the TAF function was leaked + - fix memory leak in TAF handling - the TAF function was leaked (Martin J. Evans) - fix issue with taf_function being set to a scalar which goes @@ -18,6 +18,21 @@ NEXTRELEASE - fix RT46739 if a connection breaks the environment handle is not thrown away (Martin J. Evans) + - ora_driver_name was not defaulted to the correct DBD::Oracle + version (Martin J. Evans) + + - ora_driver_name, ora_client_info, ora_client_identifier, + ora_action and ora_oci_success_warn were set twice (if specified) + on connect as they were not deleted from the connect attributes + once handled. Code now leaves the setting to the later STORE DBI + calls (Martin J. Evans) + + - ora_taf_function can now be a code reference as well as a string + (Martin J. Evans) + + - the ora_taf_function is now passed a third argument of the + connection handle (Martin J. Evans) + [CHANGE IN BEHAVIOUR] - In future versions taf_sleep will be withdrawn as you can simply diff --git a/dbdimp.c b/dbdimp.c index 4c4b3445..88611788 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -20,8 +20,6 @@ #include "Oracle.h" - - /* XXX DBI should provide a better version of this */ #define IS_DBI_HANDLE(h) \ (SvROK(h) && SvTYPE(SvRV(h)) == SVt_PVHV && \ @@ -422,63 +420,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S DBD_ATTRIB_GET_IV( attr, "ora_drcp_max", 12, svp, imp_dbh->pool_max); if (DBD_ATTRIB_TRUE(attr,"ora_drcp_incr",13,svp)) DBD_ATTRIB_GET_IV( attr, "ora_drcp_incr", 13, svp, imp_dbh->pool_incr); - - - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_driver_name", 15)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_driver_name is not a string"); - imp_dbh->driver_name = (char *) SvPV (*svp, svp_len ); - imp_dbh->driver_namel= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); - } - else { - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION,(text*)"DBDO1.28",7,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); - } -#endif /*ORA_OCI_112*/ - -#ifdef OCI_ATTR_ACTION - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_action", 10)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_action is not a string"); - imp_dbh->action = (char *) SvPV (*svp, svp_len ); - imp_dbh->actionl= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); - } #endif -#ifdef OCI_ATTR_MODULE - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_module_name", 15)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_module_name is not a string"); - imp_dbh->module_name = (char *) SvPV (*svp, svp_len ); - imp_dbh->module_namel= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); + imp_dbh->driver_name = "DBD01.47_00"; - } +#ifdef ORA_OCI_112 + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, + imp_dbh->driver_name, + (ub4)strlen(imp_dbh->driver_name), + OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); #endif - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_identifier", 21)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_client_identifier is not a string"); - imp_dbh->client_identifier = (char *) SvPV (*svp, svp_len ); - imp_dbh->client_identifierl= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); - } -#ifdef OCI_ATTR_CLIENT_INFO - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_info", 15)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_client_info is not a string"); - imp_dbh->client_info = (char *) SvPV (*svp, svp_len ); - imp_dbh->client_infol= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); - - } -#endif /* TAF Events */ imp_dbh->using_taf = 0; @@ -486,22 +438,37 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->using_taf = 1; imp_dbh->taf_sleep = 5; /* 5 second default */ + /* avoid later STORE: */ + /* See DBI::DBB problem with ATTRIBI_DELETE until DBI 1.607 */ + /* DBD_ATTRIB_DELETE(attr, "ora_taf", 7); */ + (void)hv_delete((HV*)SvRV(attr), "ora_taf", 7, G_DISCARD); + DBD_ATTRIB_GET_IV( attr, "ora_taf_sleep", 13, svp, imp_dbh->taf_sleep); + /* avoid later STORE: */ + /* See DBI::DBB problem with ATTRIBI_DELETE until DBI 1.607 */ + /* DBD_ATTRIB_DELETE(attr, "ora_taf_sleep", 13); */ + (void)hv_delete((HV*)SvRV(attr), "ora_taf_sleep", 13, G_DISCARD); + if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { - STRLEN svp_len; - char *fn; - - if (!SvPOK(*svp)) - croak("ora_taf_function is not a string"); - fn = SvPV(*svp, svp_len); - imp_dbh->taf_function = (char *)safemalloc(svp_len + 1); - strcpy(imp_dbh->taf_function, fn); + if ((SvROK(*svp) && (SvTYPE(SvRV(*svp)) == SVt_PVCV)) || + (SvPOK(*svp))) { + imp_dbh->taf_function = newSVsv(*svp); + } else { + croak("ora_taf_function needs to be a string or code reference"); + } + /* avoid later STORE: */ + /* See DBI::DBB problem with ATTRIB_DELETE until DBI 1.607 */ + /* DBD_ATTRIB_DELETE(attr, "ora_taf_function", 16); */ + (void)hv_delete((HV*)SvRV(attr), "ora_taf_function", 16, G_DISCARD); } +#ifdef DONT_DO_NOW if (DBIc_DBISTATE(imp_dbh)->debug || dbd_verbose >= 3) PerlIO_printf( DBIc_LOGPIO(imp_dbh), "taf sleep = %d, taf_function = %s\n", - imp_dbh->taf_sleep, imp_dbh->taf_function ? imp_dbh->taf_function : ""); + imp_dbh->taf_sleep, + (imp_dbh->taf_function ? imp_dbh->taf_function : ""); +#endif } imp_dbh->server_version = 0; @@ -512,18 +479,6 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (DBD_ATTRIB_TRUE(attr,"ora_verbose",11,svp)) DBD_ATTRIB_GET_IV( attr, "ora_verbose", 11, svp, dbd_verbose); - - /* check to see if success_warn is set. This will */ - /* warn after some sucessfull operations for tuning results */ - if (DBD_ATTRIB_TRUE(attr,"ora_oci_success_warn",20,svp)) - DBD_ATTRIB_GET_IV( attr, "ora_oci_success_warn", 20, svp, oci_warn); - - /* check to see if ora_objects set*/ - /* with this set any embedded types will go into a DBD::Oracle::Object */ - /* rather than just an ref array */ - if (DBD_ATTRIB_TRUE(attr,"ora_objects",11,svp)) - DBD_ATTRIB_GET_IV( attr, "ora_objects",11, svp, ora_objects); - if (DBIc_DBISTATE(imp_dbh)->debug >= 6 || dbd_verbose >= 6 ) dump_env_to_trace(imp_dbh); @@ -945,14 +900,15 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!can_taf){ croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); } - +#ifdef DONT_DO_KNOW if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { PerlIO_printf( DBIc_LOGPIO(imp_dbh), "Setting up TAF with wait time of %d seconds\n", imp_dbh->taf_sleep); } - status = reg_taf_callback(imp_dbh); +#endif + status = reg_taf_callback(dbh, imp_dbh); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "Setting TAF Callback Failed! "); @@ -1135,10 +1091,16 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); } + if (imp_dbh->taf_function) { - Safefree(imp_dbh->taf_function); + SvREFCNT_dec(imp_dbh->taf_function); imp_dbh->taf_function = NULL; } + if (imp_dbh->taf_ctx.dbh_ref) { + SvREFCNT_dec(SvRV(imp_dbh->taf_ctx.dbh_ref)); + imp_dbh->taf_ctx.dbh_ref = NULL; + } + #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { @@ -1180,8 +1142,9 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) #ifdef ORA_OCI_112 else if (kl==15 && strEQ(key, "ora_driver_name") ) { imp_dbh->driver_name = (char *) SvPV (valuesv, vl ); - imp_dbh->driver_namel= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); + OCIAttrSet_log_stat( + imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, imp_dbh->driver_name, + (ub4)vl, OCI_ATTR_DRIVER_NAME, imp_dbh->errhp, status); } else if (kl==8 && strEQ(key, "ora_drcp") ) { imp_dbh->using_drcp = 1; @@ -1205,16 +1168,9 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) imp_dbh->using_taf = 1; } else if (kl==16 && strEQ(key, "ora_taf_function") ) { - STRLEN svp_len; - char *fn; - - if (imp_dbh->taf_function) { - Safefree(imp_dbh->taf_function); - } - - fn = SvPV(valuesv, svp_len); - imp_dbh->taf_function = (char *)safemalloc(svp_len + 1); - strcpy(imp_dbh->taf_function, fn); + if (imp_dbh->taf_function) + SvREFCNT_dec(imp_dbh->taf_function); + imp_dbh->taf_function = newSVsv(valuesv); } else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { imp_dbh->taf_sleep = SvIV (valuesv); @@ -1333,7 +1289,9 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) retsv = newSViv(imp_dbh->using_taf); } else if (kl==16 && strEQ(key, "ora_taf_function") ) { - retsv = newSVpv((char *)imp_dbh->taf_function,0); + if (imp_dbh->taf_function) { + retsv = newSVsv(imp_dbh->taf_function); + } } else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { retsv = newSViv(imp_dbh->taf_sleep); diff --git a/dbdimp.h b/dbdimp.h index 19e6e176..a23f9546 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -11,8 +11,9 @@ typedef struct taf_callback_st taf_callback_t; struct taf_callback_st { - char *function; /*User supplied TAF functiomn*/ + SV *function; /*User supplied TAF functiomn*/ int sleep; + SV *dbh_ref; }; typedef struct imp_fbh_st imp_fbh_t; @@ -27,7 +28,6 @@ struct imp_drh_st { SV *ora_cache_o; /* for ora_open() cache override */ }; - /* Define dbh implementor data structure */ struct imp_dbh_st { dbih_dbc_t com; /* MUST be first element in structure */ @@ -56,12 +56,11 @@ struct imp_dbh_st { ub4 pool_max; ub4 pool_incr; char *driver_name;/*driver name user defined*/ - ub4 driver_namel; #endif - taf_callback_t *taf_callback; bool using_taf; /*TAF stuff*/ - char *taf_function; /*User supplied TAF functiomn*/ + SV *taf_function; /*User supplied TAF functiomn*/ int taf_sleep; + taf_callback_t taf_ctx; char *client_info; /*user defined*/ ub4 client_infol; char *module_name; /*module user defined */ @@ -393,7 +392,7 @@ void fb_ary_free(fb_ary_t *fb_ary); void rs_array_init(imp_sth_t *imp_sth); ub4 ora_db_version _((SV *dbh, imp_dbh_t *imp_dbh)); -sb4 reg_taf_callback _((imp_dbh_t *imp_dbh)); +sb4 reg_taf_callback _((SV *dbh, imp_dbh_t *imp_dbh)); /* These defines avoid name clashes for multiple statically linked DBD's */ diff --git a/oci8.c b/oci8.c index c8c4f93c..c222653a 100644 --- a/oci8.c +++ b/oci8.c @@ -1316,8 +1316,10 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) PUSHMARK(SP); XPUSHs(sv_2mortal(newSViv(fo_event))); XPUSHs(sv_2mortal(newSViv(fo_type))); + XPUSHs(SvRV(cb->dbh_ref)); + PUTBACK; - return_count = call_pv(cb->function, G_SCALAR); + return_count = call_sv(cb->function, G_SCALAR); SPAGAIN; @@ -1356,7 +1358,7 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) sb4 -reg_taf_callback( imp_dbh_t *imp_dbh) +reg_taf_callback(SV *dbh, imp_dbh_t *imp_dbh) { dTHX; OCIFocbkStruct tafailover; @@ -1364,6 +1366,7 @@ reg_taf_callback( imp_dbh_t *imp_dbh) imp_dbh->taf_ctx.function = imp_dbh->taf_function; imp_dbh->taf_ctx.sleep = imp_dbh->taf_sleep; + imp_dbh->taf_ctx.dbh_ref = newRV_inc(dbh); if (dbd_verbose >= 5 ) { PerlIO_printf(DBIc_LOGPIO(imp_dbh), " In reg_taf_callback\n"); diff --git a/t/38taf.t b/t/38taf.t index a3f2190f..d38e51a4 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -1,9 +1,10 @@ #!perl -w +# $Id$ use DBI; use DBD::Oracle(qw(:ora_fail_over)); use strict; -use Data::Dumper; +#use Devel::Peek qw(SvREFCNT Dump); use Test::More; unshift @INC ,'t'; @@ -36,9 +37,24 @@ else { ok $dbh = DBI->connect($dsn, $dbuser, '', {ora_taf=>1, ora_taf_sleep=>15, ora_taf_function=>'taf'}); + is($dbh->{ora_taf}, 1, 'TAF enabled'); is($dbh->{ora_taf_sleep}, 15, 'TAF sleep set'); is($dbh->{ora_taf_function}, 'taf', 'TAF callback'); + + $dbh->{ora_taf} = 0; + is($dbh->{ora_taf}, 0, 'TAF disabled'); + + $dbh->{ora_taf_sleep} = 10; + is($dbh->{ora_taf_sleep}, 10, 'TAF sleep set'); + + my $x = sub {}; +# diag(SvREFCNT($x)); +# diag(Dump($x)); + $dbh->{ora_taf_function} = $x; + is(ref($dbh->{ora_taf_function}), 'CODE', 'TAF code ref'); + +# diag(SvREFCNT($x)); } $dbh->disconnect; diff --git a/t/39attr.t b/t/39attr.t new file mode 100755 index 00000000..64af90bd --- /dev/null +++ b/t/39attr.t @@ -0,0 +1,57 @@ +#!perl -w +# $Id$ +# +# Test you can set and retrieve some attributes after connect +# MJE wrote this after discovering the code to set these attributes +# was duplicated in connect/login6 and STORE and it did not need to be +# because DBI passes attributes to STORE for you. +# +use DBI; +use DBD::Oracle(qw(:ora_fail_over)); +use strict; +#use Devel::Peek qw(SvREFCNT Dump); + +use Test::More; +unshift @INC ,'t'; +require 'nchar_test_lib.pl'; + +$| = 1; + +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; + +#use Devel::Leak; +#use Test::LeakTrace; + +#no_leaks_ok { + do_it(); +#} -verbose; + +sub do_it { + #my $handle; + #my $count = Devel::Leak::NoteSV($handle); + + my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } + or plan skip_all => "Unable to connect to Oracle"; + + like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); + foreach my $attr (qw(ora_module_name + ora_driver_name + ora_client_info + ora_client_identifier + ora_action)) { + $dbh->{$attr} = 'fred'; + is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); + } + + foreach my $attr (qw(ora_oci_success_warn + ora_objects)) { + $dbh->{$attr} = 1; + is($dbh->{$attr}, 1, "attribute $attr set and retrieved"); + } + + $dbh->disconnect; + #Devel::Leak::CheckSV($handle); +} + +done_testing(); From 0926d4889faf9634fa473038ae1832cf2f3561cc Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 9 Aug 2012 16:46:43 +0000 Subject: [PATCH 287/637] loads of TAF changes more tests for attributes removed loads of code duplicated in connect for attributes which are set in STORE by default git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15364 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 17 ++++++- dbdimp.c | 140 +++++++++++++++++++---------------------------------- dbdimp.h | 11 ++--- oci8.c | 7 ++- t/38taf.t | 18 ++++++- t/39attr.t | 57 ++++++++++++++++++++++ 6 files changed, 149 insertions(+), 101 deletions(-) create mode 100755 t/39attr.t diff --git a/Changes b/Changes index 25c12d8e..d93fa05b 100644 --- a/Changes +++ b/Changes @@ -9,7 +9,7 @@ NEXTRELEASE - fix finding client in situation where client and server both installed but different architectures (patch by H.Merijn Brand) - - fix memeory leak in TAF handling - the TAF function was leaked + - fix memory leak in TAF handling - the TAF function was leaked (Martin J. Evans) - fix issue with taf_function being set to a scalar which goes @@ -18,6 +18,21 @@ NEXTRELEASE - fix RT46739 if a connection breaks the environment handle is not thrown away (Martin J. Evans) + - ora_driver_name was not defaulted to the correct DBD::Oracle + version (Martin J. Evans) + + - ora_driver_name, ora_client_info, ora_client_identifier, + ora_action and ora_oci_success_warn were set twice (if specified) + on connect as they were not deleted from the connect attributes + once handled. Code now leaves the setting to the later STORE DBI + calls (Martin J. Evans) + + - ora_taf_function can now be a code reference as well as a string + (Martin J. Evans) + + - the ora_taf_function is now passed a third argument of the + connection handle (Martin J. Evans) + [CHANGE IN BEHAVIOUR] - In future versions taf_sleep will be withdrawn as you can simply diff --git a/dbdimp.c b/dbdimp.c index 4c4b3445..88611788 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -20,8 +20,6 @@ #include "Oracle.h" - - /* XXX DBI should provide a better version of this */ #define IS_DBI_HANDLE(h) \ (SvROK(h) && SvTYPE(SvRV(h)) == SVt_PVHV && \ @@ -422,63 +420,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S DBD_ATTRIB_GET_IV( attr, "ora_drcp_max", 12, svp, imp_dbh->pool_max); if (DBD_ATTRIB_TRUE(attr,"ora_drcp_incr",13,svp)) DBD_ATTRIB_GET_IV( attr, "ora_drcp_incr", 13, svp, imp_dbh->pool_incr); - - - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_driver_name", 15)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_driver_name is not a string"); - imp_dbh->driver_name = (char *) SvPV (*svp, svp_len ); - imp_dbh->driver_namel= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); - } - else { - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION,(text*)"DBDO1.28",7,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); - } -#endif /*ORA_OCI_112*/ - -#ifdef OCI_ATTR_ACTION - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_action", 10)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_action is not a string"); - imp_dbh->action = (char *) SvPV (*svp, svp_len ); - imp_dbh->actionl= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); - } #endif -#ifdef OCI_ATTR_MODULE - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_module_name", 15)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_module_name is not a string"); - imp_dbh->module_name = (char *) SvPV (*svp, svp_len ); - imp_dbh->module_namel= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); + imp_dbh->driver_name = "DBD01.47_00"; - } +#ifdef ORA_OCI_112 + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, + imp_dbh->driver_name, + (ub4)strlen(imp_dbh->driver_name), + OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); #endif - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_identifier", 21)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_client_identifier is not a string"); - imp_dbh->client_identifier = (char *) SvPV (*svp, svp_len ); - imp_dbh->client_identifierl= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); - } -#ifdef OCI_ATTR_CLIENT_INFO - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_client_info", 15)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_client_info is not a string"); - imp_dbh->client_info = (char *) SvPV (*svp, svp_len ); - imp_dbh->client_infol= (ub4) svp_len; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); - - } -#endif /* TAF Events */ imp_dbh->using_taf = 0; @@ -486,22 +438,37 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->using_taf = 1; imp_dbh->taf_sleep = 5; /* 5 second default */ + /* avoid later STORE: */ + /* See DBI::DBB problem with ATTRIBI_DELETE until DBI 1.607 */ + /* DBD_ATTRIB_DELETE(attr, "ora_taf", 7); */ + (void)hv_delete((HV*)SvRV(attr), "ora_taf", 7, G_DISCARD); + DBD_ATTRIB_GET_IV( attr, "ora_taf_sleep", 13, svp, imp_dbh->taf_sleep); + /* avoid later STORE: */ + /* See DBI::DBB problem with ATTRIBI_DELETE until DBI 1.607 */ + /* DBD_ATTRIB_DELETE(attr, "ora_taf_sleep", 13); */ + (void)hv_delete((HV*)SvRV(attr), "ora_taf_sleep", 13, G_DISCARD); + if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { - STRLEN svp_len; - char *fn; - - if (!SvPOK(*svp)) - croak("ora_taf_function is not a string"); - fn = SvPV(*svp, svp_len); - imp_dbh->taf_function = (char *)safemalloc(svp_len + 1); - strcpy(imp_dbh->taf_function, fn); + if ((SvROK(*svp) && (SvTYPE(SvRV(*svp)) == SVt_PVCV)) || + (SvPOK(*svp))) { + imp_dbh->taf_function = newSVsv(*svp); + } else { + croak("ora_taf_function needs to be a string or code reference"); + } + /* avoid later STORE: */ + /* See DBI::DBB problem with ATTRIB_DELETE until DBI 1.607 */ + /* DBD_ATTRIB_DELETE(attr, "ora_taf_function", 16); */ + (void)hv_delete((HV*)SvRV(attr), "ora_taf_function", 16, G_DISCARD); } +#ifdef DONT_DO_NOW if (DBIc_DBISTATE(imp_dbh)->debug || dbd_verbose >= 3) PerlIO_printf( DBIc_LOGPIO(imp_dbh), "taf sleep = %d, taf_function = %s\n", - imp_dbh->taf_sleep, imp_dbh->taf_function ? imp_dbh->taf_function : ""); + imp_dbh->taf_sleep, + (imp_dbh->taf_function ? imp_dbh->taf_function : ""); +#endif } imp_dbh->server_version = 0; @@ -512,18 +479,6 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (DBD_ATTRIB_TRUE(attr,"ora_verbose",11,svp)) DBD_ATTRIB_GET_IV( attr, "ora_verbose", 11, svp, dbd_verbose); - - /* check to see if success_warn is set. This will */ - /* warn after some sucessfull operations for tuning results */ - if (DBD_ATTRIB_TRUE(attr,"ora_oci_success_warn",20,svp)) - DBD_ATTRIB_GET_IV( attr, "ora_oci_success_warn", 20, svp, oci_warn); - - /* check to see if ora_objects set*/ - /* with this set any embedded types will go into a DBD::Oracle::Object */ - /* rather than just an ref array */ - if (DBD_ATTRIB_TRUE(attr,"ora_objects",11,svp)) - DBD_ATTRIB_GET_IV( attr, "ora_objects",11, svp, ora_objects); - if (DBIc_DBISTATE(imp_dbh)->debug >= 6 || dbd_verbose >= 6 ) dump_env_to_trace(imp_dbh); @@ -945,14 +900,15 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!can_taf){ croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); } - +#ifdef DONT_DO_KNOW if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { PerlIO_printf( DBIc_LOGPIO(imp_dbh), "Setting up TAF with wait time of %d seconds\n", imp_dbh->taf_sleep); } - status = reg_taf_callback(imp_dbh); +#endif + status = reg_taf_callback(dbh, imp_dbh); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "Setting TAF Callback Failed! "); @@ -1135,10 +1091,16 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); } + if (imp_dbh->taf_function) { - Safefree(imp_dbh->taf_function); + SvREFCNT_dec(imp_dbh->taf_function); imp_dbh->taf_function = NULL; } + if (imp_dbh->taf_ctx.dbh_ref) { + SvREFCNT_dec(SvRV(imp_dbh->taf_ctx.dbh_ref)); + imp_dbh->taf_ctx.dbh_ref = NULL; + } + #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { @@ -1180,8 +1142,9 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) #ifdef ORA_OCI_112 else if (kl==15 && strEQ(key, "ora_driver_name") ) { imp_dbh->driver_name = (char *) SvPV (valuesv, vl ); - imp_dbh->driver_namel= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->driver_name,imp_dbh->driver_namel,OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); + OCIAttrSet_log_stat( + imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, imp_dbh->driver_name, + (ub4)vl, OCI_ATTR_DRIVER_NAME, imp_dbh->errhp, status); } else if (kl==8 && strEQ(key, "ora_drcp") ) { imp_dbh->using_drcp = 1; @@ -1205,16 +1168,9 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) imp_dbh->using_taf = 1; } else if (kl==16 && strEQ(key, "ora_taf_function") ) { - STRLEN svp_len; - char *fn; - - if (imp_dbh->taf_function) { - Safefree(imp_dbh->taf_function); - } - - fn = SvPV(valuesv, svp_len); - imp_dbh->taf_function = (char *)safemalloc(svp_len + 1); - strcpy(imp_dbh->taf_function, fn); + if (imp_dbh->taf_function) + SvREFCNT_dec(imp_dbh->taf_function); + imp_dbh->taf_function = newSVsv(valuesv); } else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { imp_dbh->taf_sleep = SvIV (valuesv); @@ -1333,7 +1289,9 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) retsv = newSViv(imp_dbh->using_taf); } else if (kl==16 && strEQ(key, "ora_taf_function") ) { - retsv = newSVpv((char *)imp_dbh->taf_function,0); + if (imp_dbh->taf_function) { + retsv = newSVsv(imp_dbh->taf_function); + } } else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { retsv = newSViv(imp_dbh->taf_sleep); diff --git a/dbdimp.h b/dbdimp.h index 19e6e176..a23f9546 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -11,8 +11,9 @@ typedef struct taf_callback_st taf_callback_t; struct taf_callback_st { - char *function; /*User supplied TAF functiomn*/ + SV *function; /*User supplied TAF functiomn*/ int sleep; + SV *dbh_ref; }; typedef struct imp_fbh_st imp_fbh_t; @@ -27,7 +28,6 @@ struct imp_drh_st { SV *ora_cache_o; /* for ora_open() cache override */ }; - /* Define dbh implementor data structure */ struct imp_dbh_st { dbih_dbc_t com; /* MUST be first element in structure */ @@ -56,12 +56,11 @@ struct imp_dbh_st { ub4 pool_max; ub4 pool_incr; char *driver_name;/*driver name user defined*/ - ub4 driver_namel; #endif - taf_callback_t *taf_callback; bool using_taf; /*TAF stuff*/ - char *taf_function; /*User supplied TAF functiomn*/ + SV *taf_function; /*User supplied TAF functiomn*/ int taf_sleep; + taf_callback_t taf_ctx; char *client_info; /*user defined*/ ub4 client_infol; char *module_name; /*module user defined */ @@ -393,7 +392,7 @@ void fb_ary_free(fb_ary_t *fb_ary); void rs_array_init(imp_sth_t *imp_sth); ub4 ora_db_version _((SV *dbh, imp_dbh_t *imp_dbh)); -sb4 reg_taf_callback _((imp_dbh_t *imp_dbh)); +sb4 reg_taf_callback _((SV *dbh, imp_dbh_t *imp_dbh)); /* These defines avoid name clashes for multiple statically linked DBD's */ diff --git a/oci8.c b/oci8.c index c8c4f93c..c222653a 100644 --- a/oci8.c +++ b/oci8.c @@ -1316,8 +1316,10 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) PUSHMARK(SP); XPUSHs(sv_2mortal(newSViv(fo_event))); XPUSHs(sv_2mortal(newSViv(fo_type))); + XPUSHs(SvRV(cb->dbh_ref)); + PUTBACK; - return_count = call_pv(cb->function, G_SCALAR); + return_count = call_sv(cb->function, G_SCALAR); SPAGAIN; @@ -1356,7 +1358,7 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) sb4 -reg_taf_callback( imp_dbh_t *imp_dbh) +reg_taf_callback(SV *dbh, imp_dbh_t *imp_dbh) { dTHX; OCIFocbkStruct tafailover; @@ -1364,6 +1366,7 @@ reg_taf_callback( imp_dbh_t *imp_dbh) imp_dbh->taf_ctx.function = imp_dbh->taf_function; imp_dbh->taf_ctx.sleep = imp_dbh->taf_sleep; + imp_dbh->taf_ctx.dbh_ref = newRV_inc(dbh); if (dbd_verbose >= 5 ) { PerlIO_printf(DBIc_LOGPIO(imp_dbh), " In reg_taf_callback\n"); diff --git a/t/38taf.t b/t/38taf.t index a3f2190f..d38e51a4 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -1,9 +1,10 @@ #!perl -w +# $Id$ use DBI; use DBD::Oracle(qw(:ora_fail_over)); use strict; -use Data::Dumper; +#use Devel::Peek qw(SvREFCNT Dump); use Test::More; unshift @INC ,'t'; @@ -36,9 +37,24 @@ else { ok $dbh = DBI->connect($dsn, $dbuser, '', {ora_taf=>1, ora_taf_sleep=>15, ora_taf_function=>'taf'}); + is($dbh->{ora_taf}, 1, 'TAF enabled'); is($dbh->{ora_taf_sleep}, 15, 'TAF sleep set'); is($dbh->{ora_taf_function}, 'taf', 'TAF callback'); + + $dbh->{ora_taf} = 0; + is($dbh->{ora_taf}, 0, 'TAF disabled'); + + $dbh->{ora_taf_sleep} = 10; + is($dbh->{ora_taf_sleep}, 10, 'TAF sleep set'); + + my $x = sub {}; +# diag(SvREFCNT($x)); +# diag(Dump($x)); + $dbh->{ora_taf_function} = $x; + is(ref($dbh->{ora_taf_function}), 'CODE', 'TAF code ref'); + +# diag(SvREFCNT($x)); } $dbh->disconnect; diff --git a/t/39attr.t b/t/39attr.t new file mode 100755 index 00000000..64af90bd --- /dev/null +++ b/t/39attr.t @@ -0,0 +1,57 @@ +#!perl -w +# $Id$ +# +# Test you can set and retrieve some attributes after connect +# MJE wrote this after discovering the code to set these attributes +# was duplicated in connect/login6 and STORE and it did not need to be +# because DBI passes attributes to STORE for you. +# +use DBI; +use DBD::Oracle(qw(:ora_fail_over)); +use strict; +#use Devel::Peek qw(SvREFCNT Dump); + +use Test::More; +unshift @INC ,'t'; +require 'nchar_test_lib.pl'; + +$| = 1; + +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; + +#use Devel::Leak; +#use Test::LeakTrace; + +#no_leaks_ok { + do_it(); +#} -verbose; + +sub do_it { + #my $handle; + #my $count = Devel::Leak::NoteSV($handle); + + my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } + or plan skip_all => "Unable to connect to Oracle"; + + like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); + foreach my $attr (qw(ora_module_name + ora_driver_name + ora_client_info + ora_client_identifier + ora_action)) { + $dbh->{$attr} = 'fred'; + is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); + } + + foreach my $attr (qw(ora_oci_success_warn + ora_objects)) { + $dbh->{$attr} = 1; + is($dbh->{$attr}, 1, "attribute $attr set and retrieved"); + } + + $dbh->disconnect; + #Devel::Leak::CheckSV($handle); +} + +done_testing(); From aacfeda33aa1d4b54cac949094dfcc910d046f14 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 10 Aug 2012 09:53:25 +0000 Subject: [PATCH 288/637] Fix some internal links document 1.49_00 ora_taf_function can be a sub ref and dbh is passed to TAF callback git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15365 50811bd7-b8ce-0310-adc1-d9db26280581 --- lib/DBD/Oracle.pm | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index a6727eef..0000bde0 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1404,12 +1404,18 @@ attempts another event. #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); + # NOTE from 1.49_00 ora_taf_function can accept a code ref as well + # as a sub name as it now uses call_sv + my $dbh = DBI->connect('dbi:Oracle:XE', 'hr', 'hr', + {ora_taf => 1, + ora_taf_sleep => 5, + ora_taf_function => 'main::handle_taf'}); #create the perl TAF event function sub handle_taf { - my ($fo_event,$fo_type) = @_; + # NOTE from 1.49_00 the $dbh handle was passed to your callback + my ($fo_event,$fo_type, $dbh) = @_; if ($fo_event == OCI_FO_BEGIN){ print " Instance Unavailable Please stand by!! \n"; @@ -1540,22 +1546,25 @@ can change the callback but you cannot disable TAF. =head4 ora_taf_function -The name of the Perl subroutine that will be called from OCI when a -TAF event occurs. You must supply a perl function to use the callback -and it will always receive two parameters, the failover event value -and the failover type. Below is an example of a TAF function +The name of the Perl subroutine (or a code ref from 1.49_00) that will +be called from OCI when a TAF event occurs. You must supply a perl +function to use the callback and it will always receive at least two +parameters; the failover event value and the failover type. From +1.49_00 the dbh is passed as the third argument. Below is an example +of a TAF function sub taf_event{ - my ($event, $type) = @_; + # NOTE from 1.49_00 the $dbh handle is passed to the callback + my ($event, $type, $dbh) = @_; print "My TAF event=$event\n"; print "My TAF type=$type\n"; return; } -Note you'll probably have to use the full name space when setting the -TAF function e.g., 'main::my_taf_function' and not just -'my_taf_function'. +Note if passing a sub name you will probably have to use the full name +space when setting the TAF function e.g., 'main::my_taf_function' and +not just 'my_taf_function'. =head4 ora_taf_sleep @@ -2243,7 +2252,7 @@ If true (the default), fetching retrieves the contents of the CLOB or BLOB column in most circumstances. If false, fetching retrieves the Oracle "LOB Locator" of the CLOB or BLOB value. -See L for more details. +See L for more details. See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how to use LOB Locators. @@ -2283,7 +2292,7 @@ only one mode is supported; OCI_STMT_SCROLLABLE_READONLY - make result set scrollable -See L
for more details. +See L
for more details. =item ora_prefetch_rows @@ -2797,13 +2806,13 @@ Additional values when DBD::Oracle was built using OCI 9.2 and later: See L for the correct way to use ORA_RSET. -See L for how to use ORA_CLOB and ORA_BLOB. +See L for how to use ORA_CLOB and ORA_BLOB. See L for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. See L for the correct way to use SQLT_CHR and SQLT_BIN. -See L for more information. +See L for more information. See also L. From ef96e2b29b915bbef783d9a3d2794dbe20cffaae Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 10 Aug 2012 09:53:25 +0000 Subject: [PATCH 289/637] Fix some internal links document 1.49_00 ora_taf_function can be a sub ref and dbh is passed to TAF callback git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15365 50811bd7-b8ce-0310-adc1-d9db26280581 --- lib/DBD/Oracle.pm | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index a6727eef..0000bde0 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1404,12 +1404,18 @@ attempts another event. #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); + # NOTE from 1.49_00 ora_taf_function can accept a code ref as well + # as a sub name as it now uses call_sv + my $dbh = DBI->connect('dbi:Oracle:XE', 'hr', 'hr', + {ora_taf => 1, + ora_taf_sleep => 5, + ora_taf_function => 'main::handle_taf'}); #create the perl TAF event function sub handle_taf { - my ($fo_event,$fo_type) = @_; + # NOTE from 1.49_00 the $dbh handle was passed to your callback + my ($fo_event,$fo_type, $dbh) = @_; if ($fo_event == OCI_FO_BEGIN){ print " Instance Unavailable Please stand by!! \n"; @@ -1540,22 +1546,25 @@ can change the callback but you cannot disable TAF. =head4 ora_taf_function -The name of the Perl subroutine that will be called from OCI when a -TAF event occurs. You must supply a perl function to use the callback -and it will always receive two parameters, the failover event value -and the failover type. Below is an example of a TAF function +The name of the Perl subroutine (or a code ref from 1.49_00) that will +be called from OCI when a TAF event occurs. You must supply a perl +function to use the callback and it will always receive at least two +parameters; the failover event value and the failover type. From +1.49_00 the dbh is passed as the third argument. Below is an example +of a TAF function sub taf_event{ - my ($event, $type) = @_; + # NOTE from 1.49_00 the $dbh handle is passed to the callback + my ($event, $type, $dbh) = @_; print "My TAF event=$event\n"; print "My TAF type=$type\n"; return; } -Note you'll probably have to use the full name space when setting the -TAF function e.g., 'main::my_taf_function' and not just -'my_taf_function'. +Note if passing a sub name you will probably have to use the full name +space when setting the TAF function e.g., 'main::my_taf_function' and +not just 'my_taf_function'. =head4 ora_taf_sleep @@ -2243,7 +2252,7 @@ If true (the default), fetching retrieves the contents of the CLOB or BLOB column in most circumstances. If false, fetching retrieves the Oracle "LOB Locator" of the CLOB or BLOB value. -See L for more details. +See L for more details. See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how to use LOB Locators. @@ -2283,7 +2292,7 @@ only one mode is supported; OCI_STMT_SCROLLABLE_READONLY - make result set scrollable -See L for more details. +See L for more details. =item ora_prefetch_rows @@ -2797,13 +2806,13 @@ Additional values when DBD::Oracle was built using OCI 9.2 and later: See L for the correct way to use ORA_RSET. -See L for how to use ORA_CLOB and ORA_BLOB. +See L for how to use ORA_CLOB and ORA_BLOB. See L for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. See L for the correct way to use SQLT_CHR and SQLT_BIN. -See L for more information. +See L for more information. See also L. From 6e1b9d0a8736418370671332e736fda1dac7fbc1 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 15 Aug 2012 13:07:30 -0400 Subject: [PATCH 290/637] remove calls to oraperl (RT78965) --- Changes | 1 + dist.ini | 2 +- t/10general.t | 5 +---- t/34pres_lobs.t | 1 - 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index a2913e06..db53a107 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,7 @@ Revision history for DBD::Oracle {{$NEXT}} + - RT78965 - Remove Oraperl tests (which were forcing a require on Oraperl) 1.48 2012-08-09 - promote 1.47_00 to official release diff --git a/dist.ini b/dist.ini index c0bbd599..08a3b99b 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.48 +version = 1.50 [Authority] authority=cpan:PYTHIAN diff --git a/t/10general.t b/t/10general.t index 1e492db0..7098ff0f 100644 --- a/t/10general.t +++ b/t/10general.t @@ -4,7 +4,6 @@ use warnings; use Test::More; use DBI; -use Oraperl; use Config; use DBD::Oracle qw(ORA_OCI); @@ -22,7 +21,7 @@ my $dbh = DBI->connect($dsn, $dbuser, '', }); if ($dbh) { - plan tests => 30; + plan tests => 28; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -114,8 +113,6 @@ ok($@ =~ /DBD::Oracle::db do failed:/, "eval error: ``$@'' expected 'do faile #print "''$warn''"; ok($warn =~ /DBD::Oracle::db do failed:/, "warn error: ``$warn'' expected 'do failed:'"); ok($DBI::err, 'err defined'); -ok($ora_errno, 'ora_errno defined'); -is($ora_errno, $DBI::err, 'ora_errno and err equal'); $dbh->{RaiseError} = 0; $dbh->{PrintError} = 0; # --- diff --git a/t/34pres_lobs.t b/t/34pres_lobs.t index d0135e11..213c4f0d 100644 --- a/t/34pres_lobs.t +++ b/t/34pres_lobs.t @@ -3,7 +3,6 @@ use Test::More; use DBI; -use Oraperl; use Config; use DBD::Oracle qw(:ora_types); From 61a96dbe8ade49cc38cd56a267315cfa68c5ee17 Mon Sep 17 00:00:00 2001 From: David Perry Date: Wed, 15 Aug 2012 16:13:53 -0400 Subject: [PATCH 291/637] Preparing for 1.50 release removing ReadmeMarkdownFromPod temporarily due to odd \_ bug --- MANIFEST | 1 - dist.ini | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST b/MANIFEST index bd226508..9a6c9e40 100644 --- a/MANIFEST +++ b/MANIFEST @@ -10,7 +10,6 @@ Oracle.xs Oraperl.pm README README.help.txt -README.mkdn Todo dbdimp.c dbdimp.h diff --git a/dist.ini b/dist.ini index 08a3b99b..bf02717c 100644 --- a/dist.ini +++ b/dist.ini @@ -26,6 +26,7 @@ authority=cpan:PYTHIAN -remove=Twitter -remove=Test::Compile -remove=Covenant +-remove=ReadmeMarkdownFromPod [FakeRelease] [HelpWanted] From 2b19862b8b1a2640687d3ecca063a7f421cf3774 Mon Sep 17 00:00:00 2001 From: David Perry Date: Wed, 15 Aug 2012 16:16:42 -0400 Subject: [PATCH 292/637] v1.50 - RT78965 - Remove Oraperl tests (which were forcing a require on Oraperl) --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index db53a107..b272905a 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,8 @@ Revision history for DBD::Oracle {{$NEXT}} + +1.50 2012-08-15 - RT78965 - Remove Oraperl tests (which were forcing a require on Oraperl) 1.48 2012-08-09 From 9512f4e95abd2e92d8dfead09974519df11a3e2f Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 16 Aug 2012 09:43:39 +0000 Subject: [PATCH 293/637] Remove ora_taf and ora_taf_sleep, reorg TAF support and fix some bugs t/38taf.t: change to unix line endings and set eol-style oci8.c: remove sleep in taf callback - sleep can be done in user callback now dbdimp.h: remove sleep from taf_callback_st remove using_taf from dbh_st remove taf_sleep from dbh_st dbdimp.c: wrote enable_taf and disable_taf in connect change all the taf stuff to just handle ora_taf_function and delete it so it does not end up in STORE also call enable_taf if someone sets ora_taf_function in destroy disable taf if enabled in dbh STORE enable or disable taf depending on what ora_taf_function is set to Oracle.pm: update for all of above git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15366 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 19 ++++-- dbdimp.c | 144 ++++++++++++++++++++-------------------------- dbdimp.h | 3 - lib/DBD/Oracle.pm | 32 ++++------- oci8.c | 2 - t/38taf.t | 114 +++++++++++++++++------------------- 6 files changed, 137 insertions(+), 177 deletions(-) diff --git a/Changes b/Changes index d93fa05b..6d36b086 100644 --- a/Changes +++ b/Changes @@ -27,16 +27,25 @@ NEXTRELEASE once handled. Code now leaves the setting to the later STORE DBI calls (Martin J. Evans) + [CHANGE IN BEHAVIOUR] + + - ora_taf and ora_taf_sleep were redundant and have been removed. + To enable/disable TAF simply set ora_taf_function and if you + want to sleep do it in your callback (Martin J. Evans) + - ora_taf_function can now be a code reference as well as a string (Martin J. Evans) - - the ora_taf_function is now passed a third argument of the - connection handle (Martin J. Evans) + [ENHANCEMENTS] - [CHANGE IN BEHAVIOUR] + - the ora_can_taf method was virtually useless since you can only + call it after connecting and to enable TAF you had to do it in the + connect call. Now you enable and disable TAF at any time by + simply setting or clearing the ora_taf_function (see RT78811) + (Martin J. Evans) - - In future versions taf_sleep will be withdrawn as you can simply - sleep in your own callback. + - the ora_taf_function is now passed a third argument of the + connection handle (Martin J. Evans) [MISCELLANEOUS] diff --git a/dbdimp.c b/dbdimp.c index 88611788..55ac4436 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -59,6 +59,8 @@ struct sql_fbh_st { int scale; }; static sql_fbh_t ora2sql_type _((imp_fbh_t* fbh)); +static void disable_taf(imp_dbh_t *imp_dbh); +static int enable_taf(SV *dbh, imp_dbh_t *imp_dbh); void ora_free_phs_contents _((imp_sth_t *imp_sth, phs_t *phs)); static void dump_env_to_trace(imp_dbh_t *imp_dbh); @@ -432,43 +434,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S #endif /* TAF Events */ - imp_dbh->using_taf = 0; - - if (DBD_ATTRIB_TRUE(attr,"ora_taf",7,svp)){ - imp_dbh->using_taf = 1; - imp_dbh->taf_sleep = 5; /* 5 second default */ - - /* avoid later STORE: */ - /* See DBI::DBB problem with ATTRIBI_DELETE until DBI 1.607 */ - /* DBD_ATTRIB_DELETE(attr, "ora_taf", 7); */ - (void)hv_delete((HV*)SvRV(attr), "ora_taf", 7, G_DISCARD); - - DBD_ATTRIB_GET_IV( attr, "ora_taf_sleep", 13, svp, imp_dbh->taf_sleep); + if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { + if ((SvROK(*svp) && (SvTYPE(SvRV(*svp)) == SVt_PVCV)) || + (SvPOK(*svp))) { + imp_dbh->taf_function = newSVsv(*svp); + } else { + croak("ora_taf_function needs to be a string or code reference"); + } /* avoid later STORE: */ - /* See DBI::DBB problem with ATTRIBI_DELETE until DBI 1.607 */ - /* DBD_ATTRIB_DELETE(attr, "ora_taf_sleep", 13); */ - (void)hv_delete((HV*)SvRV(attr), "ora_taf_sleep", 13, G_DISCARD); - - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { - if ((SvROK(*svp) && (SvTYPE(SvRV(*svp)) == SVt_PVCV)) || - (SvPOK(*svp))) { - imp_dbh->taf_function = newSVsv(*svp); - } else { - croak("ora_taf_function needs to be a string or code reference"); - } - /* avoid later STORE: */ - /* See DBI::DBB problem with ATTRIB_DELETE until DBI 1.607 */ - /* DBD_ATTRIB_DELETE(attr, "ora_taf_function", 16); */ - (void)hv_delete((HV*)SvRV(attr), "ora_taf_function", 16, G_DISCARD); - } -#ifdef DONT_DO_NOW - if (DBIc_DBISTATE(imp_dbh)->debug || dbd_verbose >= 3) - PerlIO_printf( - DBIc_LOGPIO(imp_dbh), - "taf sleep = %d, taf_function = %s\n", - imp_dbh->taf_sleep, - (imp_dbh->taf_function ? imp_dbh->taf_function : ""); -#endif + /* See DBI::DBB problem with ATTRIB_DELETE until DBI 1.607 */ + /* DBD_ATTRIB_DELETE(attr, "ora_taf_function", 16); */ + (void)hv_delete((HV*)SvRV(attr), "ora_taf_function", 16, G_DISCARD); } imp_dbh->server_version = 0; @@ -887,33 +863,8 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S /* set up TAF callback if wanted */ - - if (imp_dbh->using_taf){ - bool can_taf; - can_taf = 0; - -#ifdef OCI_ATTR_TAF_ENABLED - OCIAttrGet_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, - OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); -#endif - - if (!can_taf){ - croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); - } -#ifdef DONT_DO_KNOW - if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf( - DBIc_LOGPIO(imp_dbh), - "Setting up TAF with wait time of %d seconds\n", - imp_dbh->taf_sleep); - } -#endif - status = reg_taf_callback(dbh, imp_dbh); - if (status != OCI_SUCCESS) { - oci_error(dbh, NULL, status, - "Setting TAF Callback Failed! "); - return 0; - } + if (imp_dbh->taf_function){ + if (enable_taf(dbh, imp_dbh) == 0) return 0; } return 1; @@ -1082,14 +1033,8 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) if (is_extproc) goto dbd_db_destroy_out; - if (imp_dbh->using_taf){ - OCIFocbkStruct tafailover; - tafailover.fo_ctx = NULL; - tafailover.callback_function = NULL; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, - (dvoid *) &tafailover, (ub4) 0, - (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); - + if (imp_dbh->taf_function){ + disable_taf(imp_dbh); } if (imp_dbh->taf_function) { @@ -1164,16 +1109,16 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) imp_dbh->pool_incr = SvIV (valuesv); } #endif - else if (kl==7 && strEQ(key, "ora_taf") ) { - imp_dbh->using_taf = 1; - } else if (kl==16 && strEQ(key, "ora_taf_function") ) { if (imp_dbh->taf_function) SvREFCNT_dec(imp_dbh->taf_function); imp_dbh->taf_function = newSVsv(valuesv); - } - else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { - imp_dbh->taf_sleep = SvIV (valuesv); + + if (SvTRUE(valuesv)) { + enable_taf(dbh, imp_dbh); + } else { + disable_taf(imp_dbh); + } } #ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action") ) { @@ -1285,17 +1230,11 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) retsv = newSViv(imp_dbh->pool_incr); } #endif - else if (kl==7 && strEQ(key, "ora_taf") ) { - retsv = newSViv(imp_dbh->using_taf); - } else if (kl==16 && strEQ(key, "ora_taf_function") ) { if (imp_dbh->taf_function) { retsv = newSVsv(imp_dbh->taf_function); } } - else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { - retsv = newSViv(imp_dbh->taf_sleep); - } #ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action")) { retsv = newSVpv((char *)imp_dbh->action,0); @@ -4511,3 +4450,42 @@ dump_env_to_trace(imp_dbh_t *imp_dbh) { } while ((char*)environ[i] != '\0'); } +static void disable_taf( + imp_dbh_t *imp_dbh) { + + sword status; + OCIFocbkStruct tafailover; + + tafailover.fo_ctx = NULL; + tafailover.callback_function = NULL; + OCIAttrSet_log_stat(imp_dbh, imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, + (dvoid *) &tafailover, (ub4) 0, + (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); + return; +} + +static int enable_taf( + SV *dbh, + imp_dbh_t *imp_dbh) { + + bool can_taf = 0; + sword status; + +#ifdef OCI_ATTR_TAF_ENABLED + OCIAttrGet_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, + OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); +#endif + + if (!can_taf){ + croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); + } + + status = reg_taf_callback(dbh, imp_dbh); + if (status != OCI_SUCCESS) { + oci_error(dbh, NULL, status, "Setting TAF Callback Failed! "); + return 0; + } + return 1; +} + + diff --git a/dbdimp.h b/dbdimp.h index a23f9546..ab893a42 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -12,7 +12,6 @@ typedef struct taf_callback_st taf_callback_t; struct taf_callback_st { SV *function; /*User supplied TAF functiomn*/ - int sleep; SV *dbh_ref; }; @@ -57,9 +56,7 @@ struct imp_dbh_st { ub4 pool_incr; char *driver_name;/*driver name user defined*/ #endif - bool using_taf; /*TAF stuff*/ SV *taf_function; /*User supplied TAF functiomn*/ - int taf_sleep; taf_callback_t taf_ctx; char *client_info; /*user defined*/ ub4 client_infol; diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 0000bde0..4b76143c 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -401,10 +401,7 @@ BEGIN { ora_client_info => undef, ora_client_identifier => undef, ora_action => undef, - ora_taf => undef, ora_taf_function => undef, - ora_taf_sleep => undef, - }; } @@ -1407,9 +1404,7 @@ attempts another event. # NOTE from 1.49_00 ora_taf_function can accept a code ref as well # as a sub name as it now uses call_sv my $dbh = DBI->connect('dbi:Oracle:XE', 'hr', 'hr', - {ora_taf => 1, - ora_taf_sleep => 5, - ora_taf_function => 'main::handle_taf'}); + {ora_taf_function => 'main::handle_taf'}); #create the perl TAF event function @@ -1438,9 +1433,8 @@ attempts another event. print " Failed over user. Resuming services\n"; } elsif ($fo_event == OCI_FO_ERROR){ - print " Failover error Sleeping...\n"; - # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY - # If you want to stop retrying just return 0 + print " Failover error ...\n"; + sleep 5; # sleep before having another go return OCI_FO_RETRY; } else { @@ -1537,15 +1531,14 @@ variable. =head4 ora_taf -If your Oracle instance has been configured to use TAF events you can -enable the TAF callback by setting this option to any I value. - -NOTE: All the ora_taf* attributes must currently be set in the connect -method if you want TAF enabled at the moment i.e., after connect you -can change the callback but you cannot disable TAF. +This attribute was removed in 1.49_00 as it was redundant. To +enable TAF simply set L. =head4 ora_taf_function +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option. + The name of the Perl subroutine (or a code ref from 1.49_00) that will be called from OCI when a TAF event occurs. You must supply a perl function to use the callback and it will always receive at least two @@ -1568,13 +1561,8 @@ not just 'my_taf_function'. =head4 ora_taf_sleep -The amount of time in seconds DBD::Oracle will sleep between attempting -successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY -is returned from the TAF handler. - -NOTE: This attribute will be withdrawn in the future so I suggest you -don't use it and if you want to sleep, add it to your own callback -sub. +This attribute was removed in 1.49_00 as it was redundant. If you want +to sleep between retries simple add a sleep to your callback sub. =head4 ora_session_mode diff --git a/oci8.c b/oci8.c index c222653a..bf4fef49 100644 --- a/oci8.c +++ b/oci8.c @@ -1340,7 +1340,6 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) case OCI_FO_ERROR: { if (ret == OCI_FO_RETRY) { - sleep(cb->sleep); return OCI_FO_RETRY; } break; @@ -1365,7 +1364,6 @@ reg_taf_callback(SV *dbh, imp_dbh_t *imp_dbh) sword status; imp_dbh->taf_ctx.function = imp_dbh->taf_function; - imp_dbh->taf_ctx.sleep = imp_dbh->taf_sleep; imp_dbh->taf_ctx.dbh_ref = newRV_inc(dbh); if (dbd_verbose >= 5 ) { diff --git a/t/38taf.t b/t/38taf.t index d38e51a4..22477e70 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -1,62 +1,52 @@ -#!perl -w -# $Id$ - -use DBI; -use DBD::Oracle(qw(:ora_fail_over)); -use strict; -#use Devel::Peek qw(SvREFCNT Dump); - -use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - -$| = 1; - - -# create a database handle -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } - or plan skip_all => "Unable to connect to Oracle"; - -$dbh->disconnect; - -if ( !$dbh->ora_can_taf ){ - - eval { - $dbh = DBI->connect( - $dsn, $dbuser, '', - {ora_taf=>1, ora_taf_sleep=>15,ora_taf_function=>'taf'}) - }; - ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); - - -} -else { - ok $dbh = DBI->connect($dsn, $dbuser, '', - {ora_taf=>1, ora_taf_sleep=>15, - ora_taf_function=>'taf'}); - - is($dbh->{ora_taf}, 1, 'TAF enabled'); - is($dbh->{ora_taf_sleep}, 15, 'TAF sleep set'); - is($dbh->{ora_taf_function}, 'taf', 'TAF callback'); - - $dbh->{ora_taf} = 0; - is($dbh->{ora_taf}, 0, 'TAF disabled'); - - $dbh->{ora_taf_sleep} = 10; - is($dbh->{ora_taf_sleep}, 10, 'TAF sleep set'); - - my $x = sub {}; -# diag(SvREFCNT($x)); -# diag(Dump($x)); - $dbh->{ora_taf_function} = $x; - is(ref($dbh->{ora_taf_function}), 'CODE', 'TAF code ref'); - -# diag(SvREFCNT($x)); -} - -$dbh->disconnect; - -done_testing(); +#!perl -w +# $Id$ + +use DBI; +use DBD::Oracle(qw(:ora_fail_over)); +use strict; +#use Devel::Peek qw(SvREFCNT Dump); + +use Test::More; +unshift @INC ,'t'; +require 'nchar_test_lib.pl'; + +$| = 1; + +# create a database handle +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; + +my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } + or plan skip_all => "Unable to connect to Oracle"; + +$dbh->disconnect; + +if ( !$dbh->ora_can_taf ){ + + eval { + $dbh = DBI->connect( + $dsn, $dbuser, '', + {ora_taf_function=>'taf'}) + }; + ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); + + +} +else { + ok $dbh = DBI->connect($dsn, $dbuser, '', + {ora_taf_function=>'taf'}); + + is($dbh->{ora_taf_function}, 'taf', 'TAF callback'); + + my $x = sub {}; +# diag(SvREFCNT($x)); +# diag(Dump($x)); + $dbh->{ora_taf_function} = $x; + is(ref($dbh->{ora_taf_function}), 'CODE', 'TAF code ref'); + +# diag(SvREFCNT($x)); +} + +$dbh->disconnect; + +done_testing(); From 44c2d0ac2ceb019f19e4a26511f7b08f65d7490c Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 16 Aug 2012 09:43:39 +0000 Subject: [PATCH 294/637] Remove ora_taf and ora_taf_sleep, reorg TAF support and fix some bugs t/38taf.t: change to unix line endings and set eol-style oci8.c: remove sleep in taf callback - sleep can be done in user callback now dbdimp.h: remove sleep from taf_callback_st remove using_taf from dbh_st remove taf_sleep from dbh_st dbdimp.c: wrote enable_taf and disable_taf in connect change all the taf stuff to just handle ora_taf_function and delete it so it does not end up in STORE also call enable_taf if someone sets ora_taf_function in destroy disable taf if enabled in dbh STORE enable or disable taf depending on what ora_taf_function is set to Oracle.pm: update for all of above git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15366 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 19 ++++-- dbdimp.c | 144 ++++++++++++++++++++-------------------------- dbdimp.h | 3 - lib/DBD/Oracle.pm | 32 ++++------- oci8.c | 2 - t/38taf.t | 114 +++++++++++++++++------------------- 6 files changed, 137 insertions(+), 177 deletions(-) diff --git a/Changes b/Changes index d93fa05b..6d36b086 100644 --- a/Changes +++ b/Changes @@ -27,16 +27,25 @@ NEXTRELEASE once handled. Code now leaves the setting to the later STORE DBI calls (Martin J. Evans) + [CHANGE IN BEHAVIOUR] + + - ora_taf and ora_taf_sleep were redundant and have been removed. + To enable/disable TAF simply set ora_taf_function and if you + want to sleep do it in your callback (Martin J. Evans) + - ora_taf_function can now be a code reference as well as a string (Martin J. Evans) - - the ora_taf_function is now passed a third argument of the - connection handle (Martin J. Evans) + [ENHANCEMENTS] - [CHANGE IN BEHAVIOUR] + - the ora_can_taf method was virtually useless since you can only + call it after connecting and to enable TAF you had to do it in the + connect call. Now you enable and disable TAF at any time by + simply setting or clearing the ora_taf_function (see RT78811) + (Martin J. Evans) - - In future versions taf_sleep will be withdrawn as you can simply - sleep in your own callback. + - the ora_taf_function is now passed a third argument of the + connection handle (Martin J. Evans) [MISCELLANEOUS] diff --git a/dbdimp.c b/dbdimp.c index 88611788..55ac4436 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -59,6 +59,8 @@ struct sql_fbh_st { int scale; }; static sql_fbh_t ora2sql_type _((imp_fbh_t* fbh)); +static void disable_taf(imp_dbh_t *imp_dbh); +static int enable_taf(SV *dbh, imp_dbh_t *imp_dbh); void ora_free_phs_contents _((imp_sth_t *imp_sth, phs_t *phs)); static void dump_env_to_trace(imp_dbh_t *imp_dbh); @@ -432,43 +434,17 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S #endif /* TAF Events */ - imp_dbh->using_taf = 0; - - if (DBD_ATTRIB_TRUE(attr,"ora_taf",7,svp)){ - imp_dbh->using_taf = 1; - imp_dbh->taf_sleep = 5; /* 5 second default */ - - /* avoid later STORE: */ - /* See DBI::DBB problem with ATTRIBI_DELETE until DBI 1.607 */ - /* DBD_ATTRIB_DELETE(attr, "ora_taf", 7); */ - (void)hv_delete((HV*)SvRV(attr), "ora_taf", 7, G_DISCARD); - - DBD_ATTRIB_GET_IV( attr, "ora_taf_sleep", 13, svp, imp_dbh->taf_sleep); + if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { + if ((SvROK(*svp) && (SvTYPE(SvRV(*svp)) == SVt_PVCV)) || + (SvPOK(*svp))) { + imp_dbh->taf_function = newSVsv(*svp); + } else { + croak("ora_taf_function needs to be a string or code reference"); + } /* avoid later STORE: */ - /* See DBI::DBB problem with ATTRIBI_DELETE until DBI 1.607 */ - /* DBD_ATTRIB_DELETE(attr, "ora_taf_sleep", 13); */ - (void)hv_delete((HV*)SvRV(attr), "ora_taf_sleep", 13, G_DISCARD); - - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { - if ((SvROK(*svp) && (SvTYPE(SvRV(*svp)) == SVt_PVCV)) || - (SvPOK(*svp))) { - imp_dbh->taf_function = newSVsv(*svp); - } else { - croak("ora_taf_function needs to be a string or code reference"); - } - /* avoid later STORE: */ - /* See DBI::DBB problem with ATTRIB_DELETE until DBI 1.607 */ - /* DBD_ATTRIB_DELETE(attr, "ora_taf_function", 16); */ - (void)hv_delete((HV*)SvRV(attr), "ora_taf_function", 16, G_DISCARD); - } -#ifdef DONT_DO_NOW - if (DBIc_DBISTATE(imp_dbh)->debug || dbd_verbose >= 3) - PerlIO_printf( - DBIc_LOGPIO(imp_dbh), - "taf sleep = %d, taf_function = %s\n", - imp_dbh->taf_sleep, - (imp_dbh->taf_function ? imp_dbh->taf_function : ""); -#endif + /* See DBI::DBB problem with ATTRIB_DELETE until DBI 1.607 */ + /* DBD_ATTRIB_DELETE(attr, "ora_taf_function", 16); */ + (void)hv_delete((HV*)SvRV(attr), "ora_taf_function", 16, G_DISCARD); } imp_dbh->server_version = 0; @@ -887,33 +863,8 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S /* set up TAF callback if wanted */ - - if (imp_dbh->using_taf){ - bool can_taf; - can_taf = 0; - -#ifdef OCI_ATTR_TAF_ENABLED - OCIAttrGet_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, - OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); -#endif - - if (!can_taf){ - croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); - } -#ifdef DONT_DO_KNOW - if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf( - DBIc_LOGPIO(imp_dbh), - "Setting up TAF with wait time of %d seconds\n", - imp_dbh->taf_sleep); - } -#endif - status = reg_taf_callback(dbh, imp_dbh); - if (status != OCI_SUCCESS) { - oci_error(dbh, NULL, status, - "Setting TAF Callback Failed! "); - return 0; - } + if (imp_dbh->taf_function){ + if (enable_taf(dbh, imp_dbh) == 0) return 0; } return 1; @@ -1082,14 +1033,8 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) if (is_extproc) goto dbd_db_destroy_out; - if (imp_dbh->using_taf){ - OCIFocbkStruct tafailover; - tafailover.fo_ctx = NULL; - tafailover.callback_function = NULL; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, - (dvoid *) &tafailover, (ub4) 0, - (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); - + if (imp_dbh->taf_function){ + disable_taf(imp_dbh); } if (imp_dbh->taf_function) { @@ -1164,16 +1109,16 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) imp_dbh->pool_incr = SvIV (valuesv); } #endif - else if (kl==7 && strEQ(key, "ora_taf") ) { - imp_dbh->using_taf = 1; - } else if (kl==16 && strEQ(key, "ora_taf_function") ) { if (imp_dbh->taf_function) SvREFCNT_dec(imp_dbh->taf_function); imp_dbh->taf_function = newSVsv(valuesv); - } - else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { - imp_dbh->taf_sleep = SvIV (valuesv); + + if (SvTRUE(valuesv)) { + enable_taf(dbh, imp_dbh); + } else { + disable_taf(imp_dbh); + } } #ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action") ) { @@ -1285,17 +1230,11 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) retsv = newSViv(imp_dbh->pool_incr); } #endif - else if (kl==7 && strEQ(key, "ora_taf") ) { - retsv = newSViv(imp_dbh->using_taf); - } else if (kl==16 && strEQ(key, "ora_taf_function") ) { if (imp_dbh->taf_function) { retsv = newSVsv(imp_dbh->taf_function); } } - else if (kl==13 && strEQ(key, "ora_taf_sleep") ) { - retsv = newSViv(imp_dbh->taf_sleep); - } #ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action")) { retsv = newSVpv((char *)imp_dbh->action,0); @@ -4511,3 +4450,42 @@ dump_env_to_trace(imp_dbh_t *imp_dbh) { } while ((char*)environ[i] != '\0'); } +static void disable_taf( + imp_dbh_t *imp_dbh) { + + sword status; + OCIFocbkStruct tafailover; + + tafailover.fo_ctx = NULL; + tafailover.callback_function = NULL; + OCIAttrSet_log_stat(imp_dbh, imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER, + (dvoid *) &tafailover, (ub4) 0, + (ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status); + return; +} + +static int enable_taf( + SV *dbh, + imp_dbh_t *imp_dbh) { + + bool can_taf = 0; + sword status; + +#ifdef OCI_ATTR_TAF_ENABLED + OCIAttrGet_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL, + OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); +#endif + + if (!can_taf){ + croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); + } + + status = reg_taf_callback(dbh, imp_dbh); + if (status != OCI_SUCCESS) { + oci_error(dbh, NULL, status, "Setting TAF Callback Failed! "); + return 0; + } + return 1; +} + + diff --git a/dbdimp.h b/dbdimp.h index a23f9546..ab893a42 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -12,7 +12,6 @@ typedef struct taf_callback_st taf_callback_t; struct taf_callback_st { SV *function; /*User supplied TAF functiomn*/ - int sleep; SV *dbh_ref; }; @@ -57,9 +56,7 @@ struct imp_dbh_st { ub4 pool_incr; char *driver_name;/*driver name user defined*/ #endif - bool using_taf; /*TAF stuff*/ SV *taf_function; /*User supplied TAF functiomn*/ - int taf_sleep; taf_callback_t taf_ctx; char *client_info; /*user defined*/ ub4 client_infol; diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 0000bde0..4b76143c 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -401,10 +401,7 @@ BEGIN { ora_client_info => undef, ora_client_identifier => undef, ora_action => undef, - ora_taf => undef, ora_taf_function => undef, - ora_taf_sleep => undef, - }; } @@ -1407,9 +1404,7 @@ attempts another event. # NOTE from 1.49_00 ora_taf_function can accept a code ref as well # as a sub name as it now uses call_sv my $dbh = DBI->connect('dbi:Oracle:XE', 'hr', 'hr', - {ora_taf => 1, - ora_taf_sleep => 5, - ora_taf_function => 'main::handle_taf'}); + {ora_taf_function => 'main::handle_taf'}); #create the perl TAF event function @@ -1438,9 +1433,8 @@ attempts another event. print " Failed over user. Resuming services\n"; } elsif ($fo_event == OCI_FO_ERROR){ - print " Failover error Sleeping...\n"; - # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY - # If you want to stop retrying just return 0 + print " Failover error ...\n"; + sleep 5; # sleep before having another go return OCI_FO_RETRY; } else { @@ -1537,15 +1531,14 @@ variable. =head4 ora_taf -If your Oracle instance has been configured to use TAF events you can -enable the TAF callback by setting this option to any I value. - -NOTE: All the ora_taf* attributes must currently be set in the connect -method if you want TAF enabled at the moment i.e., after connect you -can change the callback but you cannot disable TAF. +This attribute was removed in 1.49_00 as it was redundant. To +enable TAF simply set L. =head4 ora_taf_function +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option. + The name of the Perl subroutine (or a code ref from 1.49_00) that will be called from OCI when a TAF event occurs. You must supply a perl function to use the callback and it will always receive at least two @@ -1568,13 +1561,8 @@ not just 'my_taf_function'. =head4 ora_taf_sleep -The amount of time in seconds DBD::Oracle will sleep between attempting -successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY -is returned from the TAF handler. - -NOTE: This attribute will be withdrawn in the future so I suggest you -don't use it and if you want to sleep, add it to your own callback -sub. +This attribute was removed in 1.49_00 as it was redundant. If you want +to sleep between retries simple add a sleep to your callback sub. =head4 ora_session_mode diff --git a/oci8.c b/oci8.c index c222653a..bf4fef49 100644 --- a/oci8.c +++ b/oci8.c @@ -1340,7 +1340,6 @@ taf_cbk(dvoid *svchp, dvoid *envhp, dvoid *fo_ctx,ub4 fo_type, ub4 fo_event ) case OCI_FO_ERROR: { if (ret == OCI_FO_RETRY) { - sleep(cb->sleep); return OCI_FO_RETRY; } break; @@ -1365,7 +1364,6 @@ reg_taf_callback(SV *dbh, imp_dbh_t *imp_dbh) sword status; imp_dbh->taf_ctx.function = imp_dbh->taf_function; - imp_dbh->taf_ctx.sleep = imp_dbh->taf_sleep; imp_dbh->taf_ctx.dbh_ref = newRV_inc(dbh); if (dbd_verbose >= 5 ) { diff --git a/t/38taf.t b/t/38taf.t index d38e51a4..22477e70 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -1,62 +1,52 @@ -#!perl -w -# $Id$ - -use DBI; -use DBD::Oracle(qw(:ora_fail_over)); -use strict; -#use Devel::Peek qw(SvREFCNT Dump); - -use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - -$| = 1; - - -# create a database handle -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } - or plan skip_all => "Unable to connect to Oracle"; - -$dbh->disconnect; - -if ( !$dbh->ora_can_taf ){ - - eval { - $dbh = DBI->connect( - $dsn, $dbuser, '', - {ora_taf=>1, ora_taf_sleep=>15,ora_taf_function=>'taf'}) - }; - ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); - - -} -else { - ok $dbh = DBI->connect($dsn, $dbuser, '', - {ora_taf=>1, ora_taf_sleep=>15, - ora_taf_function=>'taf'}); - - is($dbh->{ora_taf}, 1, 'TAF enabled'); - is($dbh->{ora_taf_sleep}, 15, 'TAF sleep set'); - is($dbh->{ora_taf_function}, 'taf', 'TAF callback'); - - $dbh->{ora_taf} = 0; - is($dbh->{ora_taf}, 0, 'TAF disabled'); - - $dbh->{ora_taf_sleep} = 10; - is($dbh->{ora_taf_sleep}, 10, 'TAF sleep set'); - - my $x = sub {}; -# diag(SvREFCNT($x)); -# diag(Dump($x)); - $dbh->{ora_taf_function} = $x; - is(ref($dbh->{ora_taf_function}), 'CODE', 'TAF code ref'); - -# diag(SvREFCNT($x)); -} - -$dbh->disconnect; - -done_testing(); +#!perl -w +# $Id$ + +use DBI; +use DBD::Oracle(qw(:ora_fail_over)); +use strict; +#use Devel::Peek qw(SvREFCNT Dump); + +use Test::More; +unshift @INC ,'t'; +require 'nchar_test_lib.pl'; + +$| = 1; + +# create a database handle +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; + +my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } + or plan skip_all => "Unable to connect to Oracle"; + +$dbh->disconnect; + +if ( !$dbh->ora_can_taf ){ + + eval { + $dbh = DBI->connect( + $dsn, $dbuser, '', + {ora_taf_function=>'taf'}) + }; + ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); + + +} +else { + ok $dbh = DBI->connect($dsn, $dbuser, '', + {ora_taf_function=>'taf'}); + + is($dbh->{ora_taf_function}, 'taf', 'TAF callback'); + + my $x = sub {}; +# diag(SvREFCNT($x)); +# diag(Dump($x)); + $dbh->{ora_taf_function} = $x; + is(ref($dbh->{ora_taf_function}), 'CODE', 'TAF code ref'); + +# diag(SvREFCNT($x)); +} + +$dbh->disconnect; + +done_testing(); From fc7f8f155721aaf89436f700eba1de2950942824 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 16 Aug 2012 10:03:24 +0000 Subject: [PATCH 295/637] add 39attr.t test git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15367 50811bd7-b8ce-0310-adc1-d9db26280581 --- MANIFEST | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST b/MANIFEST index bd226508..14c29087 100644 --- a/MANIFEST +++ b/MANIFEST @@ -77,6 +77,7 @@ t/32xmltype.t t/34pres_lobs.t t/36lob_leak.t t/38taf.t +t/39attr.t t/40ph_type.t t/50cursor.t t/51scroll.t From dcde71db7eb9de4b12c66e7bd704d4ff7a9e7415 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 16 Aug 2012 10:03:24 +0000 Subject: [PATCH 296/637] add 39attr.t test git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15367 50811bd7-b8ce-0310-adc1-d9db26280581 --- MANIFEST | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST b/MANIFEST index bd226508..14c29087 100644 --- a/MANIFEST +++ b/MANIFEST @@ -77,6 +77,7 @@ t/32xmltype.t t/34pres_lobs.t t/36lob_leak.t t/38taf.t +t/39attr.t t/40ph_type.t t/50cursor.t t/51scroll.t From a7d81e4ebca002d1662f7d3d6c44906d6b4729e3 Mon Sep 17 00:00:00 2001 From: David Perry Date: Fri, 17 Aug 2012 10:44:50 -0400 Subject: [PATCH 297/637] Re-add README.mkdn generation --- dist.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/dist.ini b/dist.ini index bf02717c..08a3b99b 100644 --- a/dist.ini +++ b/dist.ini @@ -26,7 +26,6 @@ authority=cpan:PYTHIAN -remove=Twitter -remove=Test::Compile -remove=Covenant --remove=ReadmeMarkdownFromPod [FakeRelease] [HelpWanted] From 0d06a93b3f31b5c5cf5a1afc8a274e0dda5dc2e2 Mon Sep 17 00:00:00 2001 From: David Perry Date: Fri, 17 Aug 2012 10:53:05 -0400 Subject: [PATCH 298/637] Remove all oraperl files --- Changes | 3 + Makefile.PL | 12 - Oraperl.pm | 881 ---------------------------------------------------- oraperl.ph | 53 ---- 4 files changed, 3 insertions(+), 946 deletions(-) delete mode 100644 Oraperl.pm delete mode 100644 oraperl.ph diff --git a/Changes b/Changes index 5ed2523e..91c5428b 100644 --- a/Changes +++ b/Changes @@ -38,6 +38,9 @@ Revision history for DBD::Oracle - In future versions taf_sleep will be withdrawn as you can simply sleep in your own callback. + - RT78987 - removed Oraperl.pm and oraperl.ph; these files will be available + in a separate distribution named "Oraperl" (David Perry) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE (Martin J. Evans) diff --git a/Makefile.PL b/Makefile.PL index 3f322a01..356f5639 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1753,22 +1753,10 @@ sub symbol_search { sub post_initialize { my $self = shift; - if (-f "$Config{installprivlib}/DBD/Oraperl.pm"){ # very old now - print " -Please note: the Oraperl.pm installation location has changed. -It was: $Config{installprivlib}/DBD/Oraperl.pm -Is now: $Config{installprivlib}/Oraperl.pm -You have an old copy which you should delete when installing this one.\n"; - } - print "\nNote: \$ORACLE_HOME/lib must be added to your $need_ldlp_env environment variable\n", "before running \"make test\" and whenever DBD::Oracle is used.\n\n" if $need_ldlp_env && ($ENV{$need_ldlp_env}||'') !~ m:\Q$OH/lib\b:; - # Ensure Oraperl.pm and oraperl.ph are installed into top lib dir - $self->{PM}->{'Oraperl.pm'} = '$(INST_LIB)/Oraperl.pm'; - $self->{PM}->{'oraperl.ph'} = '$(INST_LIB)/oraperl.ph'; - eval { # This chunk is for Oracle::OCI require Data::Dumper; print main::MK_PM Data::Dumper->Purity(1)->Terse(0)->Indent(1)->Useqq(1) diff --git a/Oraperl.pm b/Oraperl.pm deleted file mode 100644 index e3796002..00000000 --- a/Oraperl.pm +++ /dev/null @@ -1,881 +0,0 @@ -# Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI -# -# Oraperl.pm -# -# Copyright (c) 1994,1995 Tim Bunce -# -# See the COPYRIGHT section in the Oracle.pm file for terms. -# -# To use this interface use one of the following invocations: -# -# use Oraperl; -# or -# eval 'use Oraperl; 1;' || die $@ if $] >= 5; -# -# The second form allows oraperl scripts to be used with -# both oraperl and perl 5. - -package Oraperl; - -require 5.004; - -use DBI 1.22; -use Exporter; - -$VERSION = substr(q$Revision: 1.44 $, 10); - -@ISA = qw(Exporter); - -@EXPORT = qw( - &ora_login &ora_open &ora_bind &ora_fetch &ora_close - &ora_logoff &ora_do &ora_titles &ora_lengths &ora_types - &ora_commit &ora_rollback &ora_autocommit &ora_version - &ora_readblob - $ora_cache $ora_long $ora_trunc $ora_errno $ora_errstr - $ora_verno $ora_debug -); - -$debug = 0 unless defined $debug; -$debugdbi = 0; -# $safe # set true/false before 'use Oraperl' if needed. -$safe = 1 unless defined $safe; - -# Help those who get core dumps from non-'safe' Oraperl (bad cursors) -use sigtrap qw(ILL); -if (!$safe) { - $SIG{BUS} = $SIG{SEGV} = sub { - print STDERR "Add BEGIN { \$Oraperl::safe=1 } above 'use Oraperl'.\n" - unless $safe; - goto &sigtrap::trap; - }; -} - - -# Install Driver (use of install_driver is a special case here) -$drh = DBI->install_driver('Oracle'); -if ($drh) { - print "DBD::Oracle driver installed as $drh\n" if $debug; - $drh->trace($debug); - $drh->{CompatMode} = 1; - $drh->{Warn} = 0; -} - - -use strict; - -sub _func_ref { - my $name = shift; - my $pkg = ($Oraperl::safe) ? "DBI" : "DBD::Oracle"; - \&{"${pkg}::$name"}; -} - -sub _warn { - my $prev_warn = shift; - if ($_[0] =~ /^(Bad|Duplicate) free/) { - return unless $ENV{PERL_DBD_DUMP} eq 'dump'; - print STDERR "Aborting with a core dump for diagnostics (PERL_DBD_DUMP)\n"; - CORE::dump; - } - $prev_warn ? &$prev_warn(@_) : warn @_; -} - - -# ----------------------------------------------------------------- -# -# $lda = &ora_login($system_id, $name, $password) -# &ora_logoff($lda) - -sub ora_login { - my($system_id, $name, $password) = @_; - local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local - local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; - return DBI->connect("dbi:Oracle:$system_id", $name, $password, { - PrintError => 0, AutoCommit => 0 - }); -} -sub ora_logoff { - my($dbh) = @_; - return if !$dbh; - local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local - local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; - $dbh->disconnect(); -} - - - -# ----------------------------------------------------------------- -# -# $csr = &ora_open($lda, $stmt [, $cache]) -# &ora_bind($csr, $var, ...) -# &ora_fetch($csr [, $trunc]) -# &ora_do($lda, $stmt) -# &ora_close($csr) - -sub ora_open { - my($lda, $stmt) = @_; - $Oraperl::ora_cache_o = $_[2]; # temp hack to pass cache through - - my $csr = $lda->prepare($stmt) or return undef; - - # only execute here if no bind vars specified - $csr->execute or return undef unless $csr->{NUM_OF_PARAMS}; - - $csr; -} - -*ora_bind = _func_ref('st::execute'); -*ora_fetch = \&{"DBD::Oracle::st::ora_fetch"}; -*ora_close = _func_ref('st::finish'); - -sub ora_do { - # error => undef - # 0 => "0E0" (0 but true) - # >0 => >0 - my($lda, $stmt, @params) = @_; # @params are an extension to the original Oraperl. - - return $lda->do($stmt, undef, @params); # SEE DEFAULT METHOD IN DBI.pm - - # OLD CODE: - # $csr is local, cursor will be closed on exit - my $csr = $lda->prepare($stmt) or return undef; - # Oracle OCI will automatically execute DDL statements in prepare()! - # We must be carefull not to execute them again! This needs careful - # examination and thought. - # Perhaps oracle is smart enough not to execute them again? - my $ret = $csr->execute(@params); - my $rows = $csr->rows; - ($rows == 0) ? "0E0" : $rows; -} - - -# ----------------------------------------------------------------- -# -# &ora_titles($csr [, $truncate]) -# &ora_lengths($csr) -# &ora_types($csr) - -sub ora_titles{ - my($csr, $trunc) = @_; - warn "ora_titles: truncate option not implemented" if $trunc; - @{$csr->{'NAME'}}; -} -sub ora_lengths{ - @{shift->{'ora_lengths'}} # oracle specific -} -sub ora_types{ - @{shift->{'ora_types'}} # oracle specific -} - - -# ----------------------------------------------------------------- -# -# &ora_commit($lda) -# &ora_rollback($lda) -# &ora_autocommit($lda, $on_off) -# &ora_version - -*ora_commit = _func_ref('db::commit'); -*ora_rollback = _func_ref('db::rollback'); - -sub ora_autocommit { - my($lda, $mode) = @_; - $lda->{AutoCommit} = $mode; - "0E0"; -} -sub ora_version { - my($sw) = DBI->internal; - print "\n"; - print "Oraperl emulation interface version $Oraperl::VERSION\n"; - print "$Oraperl::drh->{Attribution}\n"; - print "$sw->{Attribution}\n\n"; -} - - -# ----------------------------------------------------------------- -# -# $ora_errno -# $ora_errstr -*Oraperl::ora_errno = \$DBI::err; -*Oraperl::ora_errstr = \$DBI::errstr; - - -# ----------------------------------------------------------------- -# -# $ora_verno -# $ora_debug not supported, use $h->debug(2) where $h is $lda or $csr -# $ora_cache not supported -# $ora_long used at ora_open() -# $ora_trunc used at ora_open() - -$Oraperl::ora_verno = '3.000'; # to distinguish it from oraperl 2.4 - -# ora_long is left unset so that the DBI $h->{LongReadLen} attrib will be used -# by default. If ora_long is set then LongReadLen will be ignored (sadly) but -# that behaviour may change later to only apply to oraperl mode handles. -#$Oraperl::ora_long = 80; # 80, oraperl default -$Oraperl::ora_trunc = 0; # long trunc is error, oraperl default - - -# ----------------------------------------------------------------- -# -# Non-oraperl extensions added here to make it easy to still run -# script using oraperl (by avoiding $csr->blob_read(...)) - -*ora_readblob = _func_ref('st::blob_read'); - - -1; -__END__ - -=head1 NAME - -Oraperl - [DEPRECATED] Perl access to Oracle databases for old oraperl scripts - -=head1 SYNOPSIS - - eval 'use Oraperl; 1;' || die $@ if $] >= 5; # ADD THIS LINE TO OLD SCRIPTS - - $lda = &ora_login($system_id, $name, $password) - $csr = &ora_open($lda, $stmt [, $cache]) - &ora_bind($csr, $var, ...) - &ora_fetch($csr [, $trunc]) - &ora_close($csr) - &ora_logoff($lda) - - &ora_do($lda, $stmt) - - &ora_titles($csr) - &ora_lengths($csr) - &ora_types($csr) - &ora_commit($lda) - &ora_rollback($lda) - &ora_autocommit($lda, $on_off) - &ora_version() - - $ora_cache - $ora_long - $ora_trunc - $ora_errno - $ora_errstr - $ora_verno - - $ora_debug - -=head1 DESCRIPTION - -Oraperl is an extension to Perl which allows access to Oracle databases. - -The original oraperl was a Perl 4 binary with Oracle OCI compiled into it. -The Perl 5 Oraperl module described here is distributed with L -(a database driver what operates within L) and adds an extra layer over -L method calls. -The Oraperl module should only be used to allow existing Perl 4 oraperl scripts -to run with minimal changes; any new development should use L directly. - -The functions which make up this extension are described in the -following sections. All functions return a false or undefined (in the -Perl sense) value to indicate failure. You do not need to understand -the references to OCI in these descriptions. They are here to help -those who wish to extend the routines or to port them to new machines. - -The text in this document is largely unchanged from the original Perl4 -oraperl manual written by Kevin Stock . Any comments -specific to the DBD::Oracle Oraperl emulation are prefixed by B. -See the DBD::Oracle and DBI manuals for more information. - -B In order to make the oraperl function definitions available in -perl5 you need to arrange to 'use' the Oraperl.pm module in each file -or package which uses them. You can do this by simply adding S> in each file or package. If you need to make the scripts work -with both the perl4 oraperl and perl5 you should add add the following -text instead: - - eval 'use Oraperl; 1;' || die $@ if $] >= 5; - - -The use of I is deprecated in favor of L, -and will be removed from the I distribution as of -1.38. - -=head2 Principal Functions - -The main functions for database access are &ora_login(), &ora_open(), -&ora_bind(), &ora_fetch(), &ora_close(), &ora_do() and &ora_logoff(). - -=over 2 - -=item * ora_login - - $lda = &ora_login($system_id, $username, $password) - -In order to access information held within an Oracle database, a -program must first log in to it by calling the &ora_login() function. -This function is called with three parameters, the system ID (see -below) of the Oracle database to be used, and the Oracle username and -password. The value returned is a login identifier (actually an Oracle -Login Data Area) referred to below as $lda. - -Multiple logins may be active simultaneously. This allows a simple -mechanism for correlating or transferring data between databases. - -Most Oracle programs (for example, SQL*Plus or SQL*Forms) examine the -environment variable ORACLE_SID or TWO_TASK to determine which database -to connect to. In an environment which uses several different -databases, it is easy to make a mistake, and attempt to run a program -on the wrong one. Also, it is cumbersome to create a program which -works with more than one database simultaneously. Therefore, Oraperl -requires the system ID to be passed as a parameter. However, if the -system ID parameter is an empty string then oracle will use the -existing value of ORACLE_SID or TWO_TASK in the usual manner. - -Example: - - $lda = &ora_login('personnel', 'scott', 'tiger') || die $ora_errstr; - -This function is equivalent to the OCI olon and orlon functions. - -B note that a name is assumed to be a TNS alias if it does not -appear as the name of a SID in /etc/oratab or /var/opt/oracle/oratab. -See the code in Oracle.pm for the full logic of database name handling. - -B Since the returned $lda is a Perl5 reference the database login -identifier is now automatically released if $lda is overwritten or goes -out of scope. - -=item * ora_open - - $csr = &ora_open($lda, $statement [, $cache]) - -To specify an SQL statement to be executed, the program must call the -&ora_open() function. This function takes at least two parameters: a -login identifier (obtained from &ora_login()) and the SQL statement to -be executed. An optional third parameter specifies the size of the row -cache to be used for a SELECT statement. The value returned from -&ora_open() is a statement identifier (actually an ORACLE Cursor) -referred to below as $csr. - -If the row cache size is not specified, a default size is -used. As distributed, the default is five rows, but this -may have been changed at your installation (see the -&ora_version() function and $ora_cache variable below). - -Examples: - - $csr = &ora_open($lda, 'select ename, sal from emp order by ename', 10); - - $csr = &ora_open($lda, 'insert into dept values(:1, :2, :3)'); - -This function is equivalent to the OCI oopen and oparse functions. For -statements which do not contain substitution variables (see the section -Substitution Variables below), it also uses of the oexec function. For -SELECT statements, it also makes use of the odescr and odefin functions -to allocate memory for the values to be returned from the database. - -=item * ora_bind - - &ora_bind($csr, $var, ...) - -If an SQL statement contains substitution variables (see the section -Substitution Variables below), &ora_bind() is used to assign actual -values to them. This function takes a statement identifier (obtained -from &ora_open()) as its first parameter, followed by as many -parameters as are required by the statement. - -Example: - - &ora_bind($csr, 50, 'management', 'Paris'); - -This function is equivalent to the OCI obndrn and oexec statements. - -The OCI obndrn function does not allow empty strings to be bound. As -distributed, $ora_bind therefore replaces empty strings with a single -space. However, a compilation option allows this substitution to be -suppressed, causing &ora_bind() to fail. The output from the -&ora_version() function specifies which is the case at your installation. - -=item * ora_fetch - - $nfields = &ora_fetch($csr) - - @data = &ora_fetch($csr [, $trunc]) - -The &ora_fetch() function is used in conjunction with a SQL SELECT -statement to retrieve information from a database. This function takes -one mandatory parameter, a statement identifier (obtained from -&ora_open()). - -Used in a scalar context, the function returns the number of fields -returned by the query but no data is actually fetched. This may be -useful in a program which allows a user to enter a statement interactively. - -Example: - - $nfields = &ora_fetch($csr); - -Used in an array context, the value returned is an array containing the -data, one element per field. Note that this will not work as expected: - - @data = &ora_fetch($csr) || die "..."; # WRONG - -The || forces a scalar context so ora_fetch returns the number of fields. - -An optional second parameter may be supplied to indicate whether the -truncation of a LONG or LONG RAW field is to be permitted (non-zero) or -considered an error (zero). If this parameter is not specified, the -value of the global variable $ora_trunc is used instead. Truncation of -other datatypes is always considered a error. - -B The optional second parameter to ora_fetch is not supported. -A DBI usage error will be generated if a second parameter is supplied. -Use the global variable $ora_trunc instead. Also note that the -experimental DBI blob_read method can be used to retrieve a long: - - $csr->blob_read($field, $offset, $len [, \$dest, $destoffset]); - -If truncation occurs, $ora_errno will be set to 1406. &ora_fetch() -will complete successfully if truncation is permitted, otherwise it -will fail. - -&ora_fetch() will fail at the end of the data or if an error occurs. It -is possible to distinguish between these cases by testing the value of -the variable $ora_errno. This will be zero for end of data, non-zero if -an error has occurred. - -Example: - - while (($deptno, $dname, $loc) = &ora_fetch($csr)) - { - warn "Truncated!!!" if $ora_errno == 1406; - # do something with the data - } - warn $ora_errstr if $ora_errno; - -This function is equivalent to the OCI ofetch function. - -=item * ora_close - - &ora_close($csr) - -If an SQL statement is no longer required (for example, all the data -selected has been processed, or no more rows are to be inserted) then -the statement identifier should be released. This is done by calling -the &ora_close() function with the statement identifier as its only -parameter. - -This function is equivalent to the OCI oclose function. - -B Since $csr is a Perl5 reference the statement/cursor is now -automatically closed if $csr is overwritten or goes out of scope. - - -=item * ora_do - - &ora_do($lda, $statement) - -Not all SQL statements return data or contain substitution -variables. In these cases the &ora_do() function may be -used as an alternative to &ora_open() and &ora_close(). -This function takes two parameters, a login identifier and -the statement to be executed. - -Example: - - &ora_do($lda, 'drop table employee'); - -This function is roughly equivalent to - - &ora_close( &ora_open($lda, $statement) ) - -B oraperl v2 used to return the string 'OK' to indicate -success with a zero numeric value. The Oraperl emulation now -uses the string '0E0' to achieve the same effect since it does -not cause any C<-w> warnings when used in a numeric context. - -=item * ora_logoff - - &ora_logoff($lda) - -When the program no longer needs to access a given database, the login -identifier should be released using the &ora_logoff() function. - -This function is equivalent to the OCI ologoff function. - -B Since $lda is a Perl5 reference the database login identifier -is now automatically released if $lda is overwritten or goes out of scope. - -=back - -=head2 Ancillary Functions - -Additional functions available are: &ora_titles(), -&ora_lengths(), &ora_types(), &ora_autocommit(), -&ora_commit(), &ora_rollback() and &ora_version(). - -The first three are of most use within a program which -allows statements to be entered interactively. See, for -example, the sample program sql which is supplied with -Oraperl and may have been installed at your site. - -=over 2 - -=item * ora_titles - - @titles = &ora_titles($csr) - -A program may determine the field titles of an executed -query by calling &ora_titles(). This function takes a -single parameter, a statement identifier (obtained from -&ora_open()) indicating the query for which the titles are -required. The titles are returned as an array of strings, -one for each column. - -Titles are truncated to the length of the field, as reported -by the &ora_lengths() function. - -B oraperl v2.2 actually changed the behaviour such that the -titles were not truncated unless an optional second parameter was -true. This was not reflected in the oraperl manual. The Oraperl -emulation adopts the non truncating behaviour and doesn't support the -truncate parameter. - - -=item * ora_lengths - - @lengths = &ora_lengths($csr) - -A program may determine the length of each of the fields -returned by a query by calling the &ora_lengths() function. -This function takes a single parameter, a statement -identifier (obtained from &ora_open()) indicating the query -for which the lengths are required. The lengths are -returned as an array of integers, one for each column. - - -=item * ora_types - - @types = &ora_types($csr) - -A program may determine the type of each of the fields returned by a -query by calling the &ora_types() function. This function takes a -single parameter, a statement identifier (obtained from &ora_open()) -indicating the query for which the lengths are required. The types are -returned as an array of integers, one for each field. - -These types are defined in your OCI documentation. The correct -interpretation for Oracle v6 is given in the file oraperl.ph. - - -=item * ora_autocommit - - &ora_autocommit($lda, $on_or_off) - -Autocommit mode (in which each transaction is committed immediately, -without waiting for an explicit commit) may be enabled or disabled -using &ora_autocommit(). This function takes two parameters, a login -identifier (obtained from &ora_login()) and a true/false value -indicating whether autocommit is to be enabled (non-zero) or disabled -(zero). By default, autocommit is off. - -Note that autocommit can only be set per login, not per statement. If -you need to control autocommit by statement (for example, to allow -deletions to be rolled back, but insertions to be committed -immediately) you should make multiple calls to &ora_login() and use a -separate login identifier for each statement. - - -=item * ora_commit, ora_rollback - - &ora_commit($lda) - &ora_rollback($lda) - -Modifications to a database may be committed or rolled back using the -&ora_commit() and &ora_rollback() functions. These functions take a -single parameter, a login identifier obtained from &ora_login(). - -Transactions which have been committed (either explicitly by a call to -&ora_commit() or implicitly through the use of &ora_autocommit()) -cannot be subsequently rolled back. - -Note that commit and rollback can only be used per login, not per -statement. If you need to commit or rollback by statement you should -make multiple calls to &ora_login() and use a separate login identifier -for each statement. - - -=item * ora_version - - &ora_version() - -The &ora_version() function prints the version number and -copyright information concerning Oraperl. It also prints -the values of various compilation time options. It does not -return any value, and should not normally be used in a -program. - -Example: - - perl -MOraperl -e 'ora_version()' - - This is Oraperl, version 2, patch level 0. - - Debugging is available, including the -D flag. - Default fetch row cache size is 5. - Empty bind values are replaced by a space. - - Perl is copyright by Larry Wall; type oraperl -v for details. - Additions for oraperl: Copyright 1991, 1992, Kevin Stock. - - Oraperl may be distributed under the same conditions as Perl. - -This function is the equivalent of Perl's C<-v> flag. - -B The Oraperl emulation printout is similar but not identical. - -=back - -=head1 VARIABLES - -Six special variables are provided, $ora_cache, $ora_long, -$ora_trunc, $ora_errno, $ora_errstr and $ora_verno. - -=head2 Customisation Variables - -These variables are used to dictate the behaviour of Oraperl -under certain conditions. - -=over 2 - -=item * $ora_cache - -The $ora_cache variable determines the default cache size used by the -&ora_open() function for SELECT statements if an explicit cache size is -not given. - -It is initialised to the default value reported by &ora_version() but -may be set within a program to apply to all subsequent calls to -&ora_open(). Cursors which are already open are not affected. As -distributed, the default value is five, but may have been altered at -your installation. - -As a special case, assigning zero to $ora_cache resets it to the -default value. Attempting to set $ora_cache to a negative value results -in a warning. - - -=item * $ora_long - -Normally, Oraperl interrogates the database to determine the length of -each field and allocates buffer space accordingly. This is not -possible for fields of type LONG or LONGRAW. To allocate space -according to the maximum possible length (65535 bytes) would obviously -be extremely wasteful of memory. - -Therefore, when &ora_open() determines that a field is a LONG type, it -allocates the amount of space indicated by the $ora_long variable. This -is initially set to 80 (for compatibility with Oracle products) but may -be set within a program to whatever size is required. - -$ora_long is only used when fetching data, not when inserting it. - - -=item * $ora_trunc - -Since Oraperl cannot determine exactly the maximum length of a LONG -field, it is possible that the length indicated by $ora_long is not -sufficient to store the data fetched. In such a case, the optional -second parameter to &ora_fetch() indicates whether the truncation -should be allowed or should provoke an error. - -If this second parameter is not specified, the value of $ora_trunc is -used as a default. This only applies to LONG and LONGRAW data types. -Truncation of a field of any other type is always considered an error -(principally because it indicates a bug in Oraperl). - -=back - -=head2 Status Variables - -These variables report information about error conditions or about -Oraperl itself. They may only be read; a fatal error occurs if a -program attempts to change them. - -=over 2 - -=item * $ora_errno - -$ora_errno contains the Oracle error code provoked by the last function -call. - -There are two cases of particular interest concerning &ora_fetch(). If -a LONG or LONGRAW field is truncated (and truncation is allowed) then -&ora_fetch() will complete successfully but $ora_errno will be set to -1406 to indicate the truncation. When &ora_fetch() fails, $ora_errno -will be set to zero if this was due to the end of data or an error code -if it was due to an actual error. - - -=item * $ora_errstr - -The $ora_errstr variable contains the Oracle error message -corresponding to the current value of $ora_errno. - - -=item * $ora_verno - -The $ora_verno variable contains the version number of Oraperl in the -form v.ppp where v is the major version number and ppp is the -patchlevel. For example, in Oraperl version 3, patch level 142, -$ora_verno would contain the value 3.142 (more or less, allowing for -floating point error). - -=back - - -=head1 SUBSTITUTION VARIABLES - -Oraperl allows an SQL statement to contain substitution variables. -These consist of a colon followed by a number. For example, a program -which added records to a telephone list might use the following call to -&ora_open(): - - $csr = &ora_open($csr, "insert into telno values(:1, :2)"); - -The two names :1 and :2 are called substitution variables. The -function &ora_bind() is used to assign values to these variables. For -example, the following statements would add two new people to the -list: - - &ora_bind($csr, "Annette", "472-8836"); - &ora_bind($csr, "Brian", "937-1823"); - -Note that the substitution variables must be assigned consecutively -beginning from 1 for each SQL statement, as &ora_bind() assigns its -parameters in this order. Named substitution variables (for example, -:NAME, :TELNO) are not permitted. - -B Substitution variables are now bound as type 1 (VARCHAR2) -and not type 5 (STRING) by default. This can alter the behaviour of -SQL code which compares a char field with a substitution variable. -See the String Comparison section in the Datatypes chapter of the -Oracle OCI manual for more details. - -You can work around this by using DBD::Oracle's ability to specify -the Oracle type to be used on a per field basis: - - $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) - $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); - $csr->bind_param(1, $value_x, $char_attrib); - $csr->bind_param(2, $value_y, $char_attrib); - ora_bind($csr); # bind with no parameters since we've done bind_param()'s - - -=head1 DEBUGGING - -B The Oraperl $ora_debug variable is not supported. However -detailed debugging can be enabled at any time by executing - - $h->debug(2); - -where $h is either a $lda or a $csr. If debugging is enabled on an -$lda then it is automatically passed on to any cursors returned by -&ora_open(). - -=head1 EXAMPLE - - format STDOUT_TOP = - Name Phone - ==== ===== - . - - format STDOUT = - @<<<<<<<<<< @>>>>>>>>>> - $name, $phone - . - - die "You should use oraperl, not perl\n" unless defined &ora_login; - $ora_debug = shift if $ARGV[0] =~ /^\-#/; - - $lda = &ora_login('t', 'kstock', 'kstock') - || die $ora_errstr; - $csr = &ora_open($lda, 'select * from telno order by name') - || die $ora_errstr; - - $nfields = &ora_fetch($csr); - print "Query will return $nfields fields\n\n"; - - while (($name, $phone) = &ora_fetch($csr)) { write; } - warn $ora_errstr if $ora_errno; - - die "fetch error: $ora_errstr" if $ora_errno; - - do ora_close($csr) || die "can't close cursor"; - do ora_logoff($lda) || die "can't log off Oracle"; - - -=head1 NOTES - -In keeping with the philosophy of Perl, there is no pre-defined limit -to the number of simultaneous logins or SQL statements which may be -active, nor to the number of data fields which may be returned by a -query. The only limits are those imposed by the amount of memory -available, or by Oracle. - - -=head1 WARNINGS - -The Oraperl emulation software shares no code with the original -oraperl. It is built on top of the new Perl5 DBI and DBD::Oracle -modules. These modules are still evolving. (One of the goals of -the Oraperl emulation software is to allow useful work to be done -with the DBI and DBD::Oracle modules whilst insulating users from -the ongoing changes in their interfaces.) - -It is quite possible, indeed probable, that some differences in -behaviour will exist. These are probably confined to error handling. - -B differences in behaviour which are not documented here should be -reported to to dbi-users@perl.org. - - -=head1 SEE ALSO - -=over 2 - -=item Oracle Documentation - -SQL Language Reference Manual. -Programmer's Guide to the Oracle Call Interfaces. - -=item Books - -Programming Perl by Larry Wall and Randal Schwartz. -Learning Perl by Randal Schwartz. - -=item Manual Pages - -perl(1) - -=back - -=head1 AUTHOR - -Original Oraperl 2.4 code and documentation -by Kevin Stock . - -DBI and Oraperl emulation using DBD::Oracle by Tim Bunce. - -=head1 MAINTAINER - -As of DBD::Oracle release 1.17 in February 2006 The Pythian Group, Inc. -(L) are taking the lead in maintaining DBD::Oracle with -my assistance and gratitude. - -=head1 COPYRIGHT - -Copyright (c) 1994-2006 Tim Bunce. Ireland. -Copyright (c) 2006-2008 John Scoles (The Pythian Group). Canada. - -The DBD::Oracle module is free open source software; you can -redistribute it and/or modify it under the same terms as Perl 5. - -=cut diff --git a/oraperl.ph b/oraperl.ph deleted file mode 100644 index 99f62994..00000000 --- a/oraperl.ph +++ /dev/null @@ -1,53 +0,0 @@ -# DBD::Oracle Oraperl emulation. This file is not relevant to the -# emulation but is included for completeness only. -# I have updated %ora_types in case it's used. Tim Bunce. - -# oraperl.ph -# -# Various constants which may be useful in oraperl programs -# -# Author: Kevin Stock -# Date: 28th October 1991 -# Last Change: 8th April 1992 - - -# Oraperl error codes, set in $ora_errno - -$ORAP_NOMEM = 100001; # out of memory -$ORAP_INVCSR = 100002; # invalid cursor supplied -$ORAP_INVLDA = 100003; # invalid lda supplied -$ORAP_NOSID = 100004; # couldn't set ORACLE_SID -$ORAP_BADVAR = 100005; # bad colon variable sequence -$ORAP_NUMVARS = 100006; # wrong number of colon variables -$ORAP_NODATA = 100007; # statement does not return data - - -# Oraperl debugging codes for $ora_debug -# From version 2, you shouldn't really use these. - -$ODBG_EXEC = 8; # program execution -$ODBG_STRNUM = 32; # string/numeric conversions -$ODBG_MALLOC = 128; # memory allocation/release - -# Oracle datatypes -# I don't know whether these are valid for all versions. - -%ora_types = -( - 1, 'character array', - 2, 'number', - 3, 'signed integer', - 4, 'float', - 7, 'packed decimal', - 8, 'long string', - 9, 'varchar', - 11, 'rowid', - 12, 'date', - 15, 'varraw', - 23, 'raw', - 24, 'long raw', - 96, 'char', - 106,'mlslabel', -); - -1; From 412a4b101292e6901fe1118cc006307359182878 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 17 Aug 2012 11:30:44 -0400 Subject: [PATCH 299/637] update MANIFEST --- MANIFEST | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MANIFEST b/MANIFEST index 5e7ee1ed..a385559d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -7,9 +7,9 @@ META.yml Makefile.PL Oracle.h Oracle.xs -Oraperl.pm README README.help.txt +README.mkdn Todo dbdimp.c dbdimp.h @@ -50,7 +50,6 @@ mkta.pl oci.def oci8.c ocitrace.h -oraperl.ph t/000-report-versions.t t/00versions.t t/01base.t From 57a358b0e9eed644c2cbca7bd78b54b49fda22c9 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 17 Aug 2012 15:35:55 +0000 Subject: [PATCH 300/637] remove mention of Oraperl in tests (rel v1.50) git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15370 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 + LICENSE | 22 +- META.json | 29 +- META.yml | 22 +- README | 73 +- README.mkdn | 2964 ++++++++++----------- lib/DBD/Oracle.pm | 4 +- lib/DBD/Oracle/GetInfo.pm | 4 +- lib/DBD/Oracle/Object.pm | 4 +- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pm | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- t/000-report-versions.t | 3 +- t/10general.t | 5 +- t/34pres_lobs.t | 1 - 22 files changed, 1560 insertions(+), 1594 deletions(-) diff --git a/Changes b/Changes index 6d36b086..6d0a38ae 100644 --- a/Changes +++ b/Changes @@ -53,6 +53,9 @@ NEXTRELEASE - added a few more simple TAF tests (Martin J. Evans) +1.50 2012-08-15 + - RT78965 - Remove Oraperl tests (which were forcing a require on Oraperl) + 1.48 2012-08-09 - promote 1.47_00 to official release diff --git a/LICENSE b/LICENSE index a6a371c0..e5580c3f 100644 --- a/LICENSE +++ b/LICENSE @@ -18,15 +18,16 @@ This is free software, licensed under: The GNU General Public License, Version 1, February 1989 - GNU GENERAL PUBLIC LICENSE - Version 1, February 1989 + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA + Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public @@ -67,7 +68,7 @@ authors' reputations. The precise terms and conditions for copying, distribution and modification follow. - GNU GENERAL PUBLIC LICENSE + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which @@ -185,7 +186,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -207,9 +208,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS - Appendix: How to Apply These Terms to Your New Programs + Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it @@ -235,8 +236,9 @@ the exclusion of warranty; and each file should have at least the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA + Also add information on how to contact you by electronic and paper mail. diff --git a/META.json b/META.json index 9468ddbe..79df4c5b 100644 --- a/META.json +++ b/META.json @@ -7,7 +7,7 @@ "Martin J. Evans " ], "dynamic_config" : 0, - "generated_by" : "Dist::Zilla version 4.300016, CPAN::Meta::Converter version 2.120630", + "generated_by" : "Dist::Zilla version 4.300021, CPAN::Meta::Converter version 2.120921", "license" : [ "perl_5" ], @@ -40,7 +40,6 @@ "Devel::Peek" : "0", "Encode" : "0", "Math::BigInt" : "0", - "Oraperl" : "0", "Scalar::Util" : "0", "Test::More" : "0.94", "Thread::Semaphore" : "0", @@ -52,30 +51,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.49_00" + "version" : "1.50" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.49_00" + "version" : "1.50" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.49_00" - }, - "DBD::Oracle::db" : { - "file" : "lib/DBD/Oracle.pm", - "version" : "1.49_00" - }, - "DBD::Oracle::dr" : { - "file" : "lib/DBD/Oracle.pm", - "version" : "1.49_00" - }, - "DBD::Oracle::st" : { - "file" : "lib/DBD/Oracle.pm", - "version" : "1.49_00" + "version" : "1.50" } }, - "release_status" : "testing", + "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -84,11 +71,11 @@ "homepage" : "http://search.cpan.org/dist/DBD-Oracle/", "repository" : { "type" : "git", - "url" : "git://github.com/yanick/DBD-Oracle.git", - "web" : "http://github.com/yanick/DBD-Oracle/tree" + "url" : "https://github.com/yanick/DBD-Oracle.git", + "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.49_00", + "version" : "1.50", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index b0bd602d..a4b1deb6 100644 --- a/META.yml +++ b/META.yml @@ -12,7 +12,6 @@ build_requires: Devel::Peek: 0 Encode: 0 Math::BigInt: 0 - Oraperl: 0 Scalar::Util: 0 Test::More: 0.94 Thread::Semaphore: 0 @@ -21,7 +20,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 -generated_by: 'Dist::Zilla version 4.300016, CPAN::Meta::Converter version 2.120630' +generated_by: 'Dist::Zilla version 4.300021, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -30,22 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.49_00 + version: 1.50 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.49_00 + version: 1.50 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.49_00 - DBD::Oracle::db: - file: lib/DBD/Oracle.pm - version: 1.49_00 - DBD::Oracle::dr: - file: lib/DBD/Oracle.pm - version: 1.49_00 - DBD::Oracle::st: - file: lib/DBD/Oracle.pm - version: 1.49_00 + version: 1.50 requires: DBI: 0 DynaLoader: 0 @@ -56,8 +46,8 @@ requires: resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ - repository: git://github.com/yanick/DBD-Oracle.git -version: 1.49_00 + repository: https://github.com/yanick/DBD-Oracle.git +version: 1.50 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 1fd564ee..bf4cd15d 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.49_00 + version 1.50 SYNOPSIS use DBI; @@ -248,12 +248,16 @@ DBI CLASS METHODS #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); + # NOTE from 1.49_00 ora_taf_function can accept a code ref as well + # as a sub name as it now uses call_sv + my $dbh = DBI->connect('dbi:Oracle:XE', 'hr', 'hr', + {ora_taf_function => 'main::handle_taf'}); #create the perl TAF event function sub handle_taf { - my ($fo_event,$fo_type) = @_; + # NOTE from 1.49_00 the $dbh handle was passed to your callback + my ($fo_event,$fo_type, $dbh) = @_; if ($fo_event == OCI_FO_BEGIN){ print " Instance Unavailable Please stand by!! \n"; @@ -276,9 +280,8 @@ DBI CLASS METHODS print " Failed over user. Resuming services\n"; } elsif ($fo_event == OCI_FO_ERROR){ - print " Failover error Sleeping...\n"; - # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY - # If you want to stop retrying just return 0 + print " Failover error ...\n"; + sleep 5; # sleep before having another go return OCI_FO_RETRY; } else { @@ -367,38 +370,36 @@ DBI CLASS METHODS variable. ora_taf - If your Oracle instance has been configured to use TAF events you can - enable the TAF callback by setting this option to any *true* value. - - NOTE: All the ora_taf* attributes must currently be set in the connect - method if you want TAF enabled at the moment i.e., after connect you can - change the callback but you cannot disable TAF. + This attribute was removed in 1.49_00 as it was redundant. To enable TAF + simply set "ora_taf_function". ora_taf_function - The name of the Perl subroutine that will be called from OCI when a TAF - event occurs. You must supply a perl function to use the callback and it - will always receive two parameters, the failover event value and the - failover type. Below is an example of a TAF function + If your Oracle instance has been configured to use TAF events you can + enable the TAF callback by setting this option. + + The name of the Perl subroutine (or a code ref from 1.49_00) that will + be called from OCI when a TAF event occurs. You must supply a perl + function to use the callback and it will always receive at least two + parameters; the failover event value and the failover type. From 1.49_00 + the dbh is passed as the third argument. Below is an example of a TAF + function sub taf_event{ - my ($event, $type) = @_; + # NOTE from 1.49_00 the $dbh handle is passed to the callback + my ($event, $type, $dbh) = @_; print "My TAF event=$event\n"; print "My TAF type=$type\n"; return; } - Note you'll probably have to use the full name space when setting the - TAF function e.g., 'main::my_taf_function' and not just - 'my_taf_function'. + Note if passing a sub name you will probably have to use the full name + space when setting the TAF function e.g., 'main::my_taf_function' and + not just 'my_taf_function'. ora_taf_sleep - The amount of time in seconds DBD::Oracle will sleep between attempting - successive failover events when the event is OCI_FO_ERROR and - OCI_FO_RETRY is returned from the TAF handler. - - NOTE: This attribute will be withdrawn in the future so I suggest you - don't use it and if you want to sleep, add it to your own callback sub. + This attribute was removed in 1.49_00 as it was redundant. If you want + to sleep between retries simple add a sleep to your callback sub. ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, @@ -1007,7 +1008,7 @@ DATABASE HANDLE METHODS or BLOB column in most circumstances. If false, fetching retrieves the Oracle "LOB Locator" of the CLOB or BLOB value. - See "LOBs and LONGs" for more details. + See "LOBS AND LONGS" for more details. See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how to use LOB Locators. @@ -1043,7 +1044,7 @@ DATABASE HANDLE METHODS OCI_STMT_SCROLLABLE_READONLY - make result set scrollable - See "Scrollable Cursors" for more details. + See "SCROLLABLE CURSORS" for more details. ora_prefetch_rows Sets the number of rows to be prefetched. If it is not set, then the @@ -1399,8 +1400,8 @@ DATABASE HANDLE ATTRIBUTES $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); In the above example 10 rows will be prefetched up to a maximum of 10000 - bytes of data. The Oracle® Call Interface Programmer's Guide, suggests - a good row cache value for a scrollable cursor is about 20% of expected + bytes of data. The Oracle® Call Interface Programmer's Guide, suggests a + good row cache value for a scrollable cursor is about 20% of expected size of the record set. The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) @@ -1547,7 +1548,7 @@ DBI STATEMENT HANDLE OBJECT METHODS See "Binding Cursors" for the correct way to use ORA_RSET. - See "LOBs and LONGs" for how to use ORA_CLOB and ORA_BLOB. + See "LOBS AND LONGS" for how to use ORA_CLOB and ORA_BLOB. See "SYS.DBMS_SQL datatypes" for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. @@ -1555,7 +1556,7 @@ DBI STATEMENT HANDLE OBJECT METHODS See "Data Interface for Persistent LOBs" for the correct way to use SQLT_CHR and SQLT_BIN. - See "Other Data Types" for more information. + See "OTHER DATA TYPES" for more information. See also "Placeholders and Bind Values" in DBI. @@ -4241,3 +4242,11 @@ COPYRIGHT AND LICENSE This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. +POD ERRORS + Hey! The above document had some coding errors, which are explained + below: + + Around line 2655: + Non-ASCII character seen before =encoding in 'Oracle®'. Assuming + UTF-8 + diff --git a/README.mkdn b/README.mkdn index f2e4535e..4015e6a4 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,20 +4,20 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.49_00 +version 1.50 # SYNOPSIS - use DBI; + use DBI; - $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); - $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); - # See the DBI module documentation for full details + # See the DBI module documentation for full details - # for some advanced uses you may need Oracle type values: - use DBD::Oracle qw(:ora_types); + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); # DESCRIPTION @@ -30,66 +30,62 @@ consult the [DBI](http://search.cpan.org/perldoc?DBI) documentation first! # CONSTANTS -- :ora_session_modes - -ORA_SYSDBA ORA_SYSOPER ORA_SYSASM - -- :ora_types +- :ora\_session\_modes - ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW - ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB - ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI - SQLT_CHR SQLT_BIN +ORA\_SYSDBA ORA\_SYSOPER ORA\_SYSASM -- SQLCS_IMPLICIT +- :ora\_types -- SQLCS_NCHAR + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN +- SQLCS\_IMPLICIT +- SQLCS\_NCHAR -SQLCS_IMPLICIT and SQLCS_NCHAR are _character set form_ values. +SQLCS\_IMPLICIT and SQLCS\_NCHAR are _character set form_ values. See notes about Unicode elsewhere in this document. -- SQLT_INT - -- SQLT_FLT +- SQLT\_INT +- SQLT\_FLT These types are used only internally, and may be specified as internal -bind type for ORA_NUMBER_TABLE. See notes about ORA_NUMBER_TABLE elsewhere +bind type for ORA\_NUMBER\_TABLE. See notes about ORA\_NUMBER\_TABLE elsewhere in this document -- ORA_OCI +- ORA\_OCI Oracle doesn't provide a formal API for determining the exact version number of the OCI client library used, so DBD::Oracle has to go digging -(and sometimes has to more or less guess). The ORA_OCI constant +(and sometimes has to more or less guess). The ORA\_OCI constant holds the result of that process. -In string context ORA_OCI returns the full "A.B.C.D" version string. +In string context ORA\_OCI returns the full "A.B.C.D" version string. -In numeric context ORA_OCI returns the major.minor version number +In numeric context ORA\_OCI returns the major.minor version number (8.1, 9.2, 10.0 etc). But note that version numbers are not actually floating point and so if Oracle ever makes a release that has a two digit minor version, such as `9.10` it will have a lower numeric value than the preceding `9.9` release. So use with care. -The contents and format of ORA_OCI are subject to change (it may, +The contents and format of ORA\_OCI are subject to change (it may, for example, become a _version object_ in later releases). I recommend that you avoid checking for exact values. -- :ora_fetch_orient +- :ora\_fetch\_orient - OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST - OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE These constants are used to set the orientation of a fetch on a scrollable cursor. -- :ora_exe_modes - - OCI_STMT_SCROLLABLE_READONLY +- :ora\_exe\_modes -- :ora_fail_over + OCI_STMT_SCROLLABLE_READONLY +- :ora\_fail\_over - OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR - OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY # DBI CLASS METHODS @@ -112,30 +108,30 @@ If the database is defined in a TNSNAMES.ORA file, you can use the service name - 3 To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: -//host[:port][/service_name] +//host\[:port\]\[/service\_name\] If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. The following examples show several ways a connection can be created: - $dbh = DBI->connect('dbi:Oracle:DB','username','password'); + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); - $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); - $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); - $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); ### OS authentication To connect to a local database with a user which has been set up to authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): - $dbh = DBI->connect('dbi:Oracle:','/',''); + $dbh = DBI->connect('dbi:Oracle:','/',''); -Note the lack of a connection name (use the ORACLE_SID environment +Note the lack of a connection name (use the ORACLE\_SID environment variable). If an explicit SID is used you will probably get an ORA-01004 error. That only works for local databases. (Authentication to remote Oracle @@ -144,15 +140,15 @@ but it is not secure and not recommended so not documented here. ### Oracle Environment Variables -To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. -In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). +To use DBD::ORACLE to connect to an Oracle database, ORACLE\_HOME environment variable should be set correctly. +In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE\_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD\_LIBRARY\_PATH, ldconfig, or similar on Unix). -Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. +Oracle can use two environment variables to specify default connections: ORACLE\_SID and TWO\_TASK. To use them, specify either a local SID or service name, or a service name that is specified in the TNSNAMES.ORA file. -Note that if you have *both* local and remote databases, and you have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully -qualified connect string on the command line, TWO_TASK takes precedence over ORACLE_SID (i.e. you get connected to remote system). +Note that if you have \*both\* local and remote databases, and you have ORACLE\_SID \*and\* TWO\_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO\_TASK takes precedence over ORACLE\_SID (i.e. you get connected to remote system). It is highly recommended not to rely on environment variables and to always explicitly specify the SID in the connection string. This can prevent serious mistakes such as dropping a schema in the wrong database, and generally makes debugging and troubleshooting easier. @@ -160,7 +156,7 @@ Also remember that depending on the operating system you are using the differing ### Timezones -If the query is run through SQL*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. +If the query is run through SQL\*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. If the query is run locally, Oracle will return the time zone based on the "TZ" environment variable setting of the user running the query. @@ -173,29 +169,29 @@ issue the UNIX "date" command. DBD::Oracle supports DRCP (Database Resident Connection Pool) so if you have an 11.2 database and DRCP is enabled you can direct all of your connections to it by adding ':POOLED' to the SID or -setting a connection attribute of ora_drcp, or set the SERVER=POOLED +setting a connection attribute of ora\_drcp, or set the SERVER=POOLED when using a TNSENTRY style connection or even by setting an -environment variable ORA_DRCP. All of which are demonstrated below; +environment variable ORA\_DRCP. All of which are demonstrated below; - $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') - $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') - $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) - $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, - ora_drcp_class=>'my_app', - ora_drcp_min =>10}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) - $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') - $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= - (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) - (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") - if the ORA_DRCP environment variable is set then just this + if the ORA_DRCP environment variable is set then just this - $dbh = DBI->connect('dbi:Oracle:DB','username','password') + $dbh = DBI->connect('dbi:Oracle:DB','username','password') You can find a white paper on setting up DRCP and its advantages at [http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf](http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf). @@ -217,7 +213,7 @@ You will have to set up TAF on your instance before you can use this callback. You can test your instance to see if you can use TAF callback with - $dbh->ora_can_taf(); + $dbh->ora_can_taf(); If you try to set up a callback without it being enabled DBD::Oracle will croak. @@ -230,13 +226,13 @@ possible TAF situations you might want to set up but here is a simple example: The TNS entry for the instance has had the following added to the -CONNECT_DATA section +CONNECT\_DATA section - (FAILOVER_MODE= - (TYPE=select) - (METHOD=basic) - (RETRIES=10) - (DELAY=10)) + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) You will also have to create your own perl function that will be called from the client. You can name it anything you want and it will @@ -245,19 +241,23 @@ failover type. You can also set a sleep value in case of failover error and the OCI client will sleep for the specified seconds before it attempts another event. - use DBD::Oracle(qw(:ora_fail_over)); - #import the ora fail over constants + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants - #set up TAF on the connection - # NOTE since DBD::Oracle uses call_pv you may need to pass a full - # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); + #set up TAF on the connection + # NOTE since DBD::Oracle uses call_pv you may need to pass a full + # name space as the function e.g., 'main::handle_taf' + # NOTE from 1.49_00 ora_taf_function can accept a code ref as well + # as a sub name as it now uses call_sv + my $dbh = DBI->connect('dbi:Oracle:XE', 'hr', 'hr', + {ora_taf_function => 'main::handle_taf'}); - #create the perl TAF event function + #create the perl TAF event function - sub handle_taf { - my ($fo_event,$fo_type) = @_; - if ($fo_event == OCI_FO_BEGIN){ + sub handle_taf { + # NOTE from 1.49_00 the $dbh handle was passed to your callback + my ($fo_event,$fo_type, $dbh) = @_; + if ($fo_event == OCI_FO_BEGIN){ print " Instance Unavailable Please stand by!! \n"; printf(" Your TAF type is %s \n", @@ -279,36 +279,35 @@ attempts another event. print " Failed over user. Resuming services\n"; } elsif ($fo_event == OCI_FO_ERROR){ - print " Failover error Sleeping...\n"; - # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY - # If you want to stop retrying just return 0 + print " Failover error ...\n"; + sleep 5; # sleep before having another go return OCI_FO_RETRY; } else { printf(" Bad Failover Event: %d.\n", $fo_event); + } + return 0; } - return 0; - } The TAF types are as follows - OCI_FO_SESSION indicates the user has requested only session failover. - OCI_FO_SELECT indicates the user has requested select failover. - OCI_FO_NONE indicates the user has not requested a failover type. - OCI_FO_TXNAL indicates the user has requested a transaction failover. + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. The TAF events are as follows - OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. - OCI_FO_END indicates successful completion of failover. - OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. - OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. - OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). ### Connect Attributes -#### ora_ncs_buff_mtpl +#### ora\_ncs\_buff\_mtpl You can customize the size of the buffer when selecting LOBs with the built-in AUTO Lob. The default value is 4 which is probably @@ -320,27 +319,27 @@ This value can also be specified with the `ORA_DBD_NCS_BUFFER` environment variable in which case it sets the value at the connect stage. -#### ora_drcp +#### ora\_drcp For Oracle 11.2 or greater. Set to _1_ to enable DRCP. Can also be set via the `ORA_DRCP` environment variable. -#### ora_drcp_class +#### ora\_drcp\_class -If you are using DRCP, you can set a CONNECTION_CLASS for your pools +If you are using DRCP, you can set a CONNECTION\_CLASS for your pools as well. As sessions from a DRCP cannot be shared by users, you can use this setting to identify the same user across different applications. OCI will ensure that sessions belonging to a 'class' are not shared outside the class'. -The values for ora_drcp_class cannot contain a '*' and must be less +The values for ora\_drcp\_class cannot contain a '\*' and must be less than 1024 characters. This value can be also be specified with the `ORA_DRCP_CLASS` environment variable. -#### ora_drcp_min +#### ora\_drcp\_min This optional value specifies the minimum number of sessions that are initially opened. New sessions are only opened after this value has @@ -354,140 +353,137 @@ application is planning or expecting to run. This value can also be specified with the `ORA_DRCP_MIN` environment variable. -#### ora_drcp_max +#### ora\_drcp\_max This optional value specifies the maximum number of sessions that can be open at one time. Once reached no more sessions can be opened until one becomes free. The default value is 40 and any value above 1 -is valid. You should not set this value lower than ora_drcp_min as +is valid. You should not set this value lower than ora\_drcp\_min as that will just waste resources. This value can also be specified with the `ORA_DRCP_MAX` environment variable. -#### ora_drcp_incr +#### ora\_drcp\_incr This optional value specifies the next increment for sessions to be started if the current number of sessions are less than -ora_drcp_max. The default value is 2 and any value above 0 is -valid as long as the value of ora_drcp_min + ora_drcp_incr is not -greater than ora_drcp_max. +ora\_drcp\_max. The default value is 2 and any value above 0 is +valid as long as the value of ora\_drcp\_min + ora\_drcp\_incr is not +greater than ora\_drcp\_max. This value can also be specified with the `ORA_DRCP_INCR` environment variable. -#### ora_taf - -If your Oracle instance has been configured to use TAF events you can -enable the TAF callback by setting this option to any _true_ value. - -NOTE: All the ora_taf* attributes must currently be set in the connect -method if you want TAF enabled at the moment i.e., after connect you -can change the callback but you cannot disable TAF. - -#### ora_taf_function - -The name of the Perl subroutine that will be called from OCI when a -TAF event occurs. You must supply a perl function to use the callback -and it will always receive two parameters, the failover event value -and the failover type. Below is an example of a TAF function +#### ora\_taf - sub taf_event{ - my ($event, $type) = @_; +This attribute was removed in 1.49\_00 as it was redundant. To +enable TAF simply set ["ora\_taf\_function"](#ora\_taf\_function). - print "My TAF event=$event\n"; - print "My TAF type=$type\n"; - return; - } +#### ora\_taf\_function -Note you'll probably have to use the full name space when setting the -TAF function e.g., 'main::my_taf_function' and not just -'my_taf_function'. +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option. + +The name of the Perl subroutine (or a code ref from 1.49\_00) that will +be called from OCI when a TAF event occurs. You must supply a perl +function to use the callback and it will always receive at least two +parameters; the failover event value and the failover type. From +1.49\_00 the dbh is passed as the third argument. Below is an example +of a TAF function + + sub taf_event{ + # NOTE from 1.49_00 the $dbh handle is passed to the callback + my ($event, $type, $dbh) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } -#### ora_taf_sleep +Note if passing a sub name you will probably have to use the full name +space when setting the TAF function e.g., 'main::my\_taf\_function' and +not just 'my\_taf\_function'. -The amount of time in seconds DBD::Oracle will sleep between attempting -successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY -is returned from the TAF handler. +#### ora\_taf\_sleep -NOTE: This attribute will be withdrawn in the future so I suggest you -don't use it and if you want to sleep, add it to your own callback -sub. +This attribute was removed in 1.49\_00 as it was redundant. If you want +to sleep between retries simple add a sleep to your callback sub. -#### ora_session_mode +#### ora\_session\_mode -The ora_session_mode attribute can be used to connect with SYSDBA, -SYSOPER and ORA_SYSASM authorization. -The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using +The ora\_session\_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA\_SYSASM authorization. +The ORA\_SYSDBA, ORA\_SYSOPER and ORA\_SYSASM constants can be imported using - use DBD::Oracle qw(:ora_session_modes); + use DBD::Oracle qw(:ora_session_modes); -This is one case where setting ORACLE_SID may be useful since -connecting as SYSDBA or SYSOPER via SQL*Net is frequently disabled +This is one case where setting ORACLE\_SID may be useful since +connecting as SYSDBA or SYSOPER via SQL\*Net is frequently disabled for security reasons. Example: - $dsn = "dbi:Oracle:"; # no dbname here - $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed - delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set - $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); It has been reported that this only works if `$dsn` does not contain -a SID so that Oracle then uses the value of ORACLE_SID (not -TWO_TASK) environment variable to connect to a local instance. Also +a SID so that Oracle then uses the value of ORACLE\_SID (not +TWO\_TASK) environment variable to connect to a local instance. Also the username and password should be empty, and the user executing the script needs to be part of the dba group or osdba group. -#### ora_oratab_orahome +#### ora\_oratab\_orahome -Passing a true value for the ora_oratab_orahome attribute will make +Passing a true value for the ora\_oratab\_orahome attribute will make DBD::Oracle change `$ENV{ORACLE_HOME}` to make the Oracle home directory that specified in the `/etc/oratab` file _if_ the database to connect to is specified as a SID that exists in the oratab file, and DBD::Oracle was built to use the Oracle 7 OCI API (not Oracle 8+). -#### ora_module_name +#### ora\_module\_name After connecting to the database the value of this attribute is passed -to the SET_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL +to the SET\_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL package. This can be used to identify the application to the DBA for monitoring and performance tuning purposes. For example: - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); - $dbh->{ora_module_name} = $y; + $dbh->{ora_module_name} = $y; The maximum size is 48 bytes. NOTE: You will need an Oracle client 10.1 or later to use this. -#### ora_driver_name +#### ora\_driver\_name For 11g and later you can now set the name of the driver layer using OCI. Perl, Perl5, ApachePerl so on. Names starting with "ORA" are reserved. You can enter up to 8 characters. If none is enter then this will default to DBDOxxxx where xxxx is the current version number. This value can be -retrieved on the server side using V$SESSION_CONNECT_INFO or -GV$SESSION_CONNECT_INFO +retrieved on the server side using V$SESSION\_CONNECT\_INFO or +GV$SESSION\_CONNECT\_INFO - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); - $dbh->{ora_driver_name} = $q; + $dbh->{ora_driver_name} = $q; -#### ora_client_info +#### ora\_client\_info Allows you to add any value (up to 64 bytes) to your session and it can be retrieved on the server side from the `V$SESSION`a view. - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); - $dbh->{ora_client_info} = "Remote2"; + $dbh->{ora_client_info} = "Remote2"; NOTE: You will need an Oracle client 10.1 or later to use this. -#### ora_client_identifier +#### ora\_client\_identifier Allows you to specify the user identifier in the session handle. @@ -498,93 +494,93 @@ reasons and the first character of the identifier should not be ':'. This value can be retrieved on the server side using `V$SESSION` view. - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); - $dbh->{ora_client_identifier} = $local_user; + $dbh->{ora_client_identifier} = $local_user; -#### ora_action +#### ora\_action Allows you to specify any string up to 32 bytes which may be retrieved on the server side using `V$SESSION` view. - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); - $dbh->{ora_action} = "New Long Query 22"; + $dbh->{ora_action} = "New Long Query 22"; NOTE: You will need an Oracle client 10.1 or later to use this. -#### ora_dbh_share +#### ora\_dbh\_share Requires at least Perl 5.8.0 compiled with ithreads. Allows you to share database connections between threads. The first connect will make the -connection, all following calls to connect with the same ora_dbh_share +connection, all following calls to connect with the same ora\_dbh\_share attribute will use the same database connection. The value must be a reference to a already shared scalar which is initialized to an empty string. - our $orashr : shared = '' ; + our $orashr : shared = '' ; - $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; -#### ora_envhp +#### ora\_envhp The first time a connection is made a new OCI 'environment' is created by DBD::Oracle and stored in the driver handle. Subsequent connects reuse (share) that same OCI environment by default. -The ora_envhp attribute can be used to disable the reuse of the OCI +The ora\_envhp attribute can be used to disable the reuse of the OCI environment from a previous connect. If the value is `0` then a new OCI environment is allocated and used for this connection. The OCI environment holds information about the client side context, such as the local NLS environment. By altering `%ENV` and setting -ora_envhp to 0 you can create connections with different NLS +ora\_envhp to 0 you can create connections with different NLS settings. This is most useful for testing. -#### ora_charset, ora_ncharset +#### ora\_charset, ora\_ncharset For oracle versions >= 9.2 you can specify the client charset and -ncharset with the ora_charset and ora_ncharset attributes. You +ncharset with the ora\_charset and ora\_ncharset attributes. You still need to pass `ora_envhp = 0` for all but the first connect. These attributes override the settings from environment variables. - $dbh = DBI->connect ($dsn, $user, $passwd, - {ora_charset => 'AL32UTF8'}); + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); -#### ora_verbose +#### ora\_verbose Use this value to enable DBD::Oracle only tracing. Simply either set -the ora_verbose attribute on the connect() method to the trace level +the ora\_verbose attribute on the connect() method to the trace level you desire like this - my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); or set it directly on the DB handle like this; - $dbh->{ora_verbose} =6; + $dbh->{ora_verbose} =6; In both cases the DBD::Oracle trace level is set to 6, which is the highest level tracing most of the calls to OCI. -NOTE: In future versions of DBD::Oracle ora_verbose will be changed so +NOTE: In future versions of DBD::Oracle ora\_verbose will be changed so that it is simply a switch to turn DBI's DBD tracing on or off. A true value will turn it on and a false value will turn it off. DBI's -"DBD" tracing was not available when ora_verbose was created and -ora_verbose adds an additional test to every trace test. +"DBD" tracing was not available when ora\_verbose was created and +ora\_verbose adds an additional test to every trace test. -#### ora_oci_success_warn +#### ora\_oci\_success\_warn Use this value to print otherwise silent OCI warnings that may happen when an execute or fetch returns "Success With Info" or when you want to tune RowCaching and LOB Reads - $dbh->{ora_oci_success_warn} = 1; + $dbh->{ora_oci_success_warn} = 1; -#### ora_objects +#### ora\_objects Use this value to enable extended embedded oracle objects mode. In extended: @@ -596,55 +592,55 @@ Embedded objects are returned as instance (including type- Determine object type for each instance. All object attributes are returned (not only super-type's attributes). - $dbh->{ora_objects} = 1; + $dbh->{ora_objects} = 1; -#### ora_ph_type +#### ora\_ph\_type The default placeholder datatype for the database session. -The `TYPE` or [ora_type](#pod_ora_type) attributes to L and -L override the datatype for individual placeholders. +The `TYPE` or ["ora\_type"](#ora\_type) attributes to ["bind\_param" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param) and +["bind\_param\_inout" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param\_inout) override the datatype for individual placeholders. The most frequent reason for using this attribute is to permit trailing spaces in values passed by placeholders. Constants for the values allowed for this attribute can be imported using - use DBD::Oracle qw(:ora_types); + use DBD::Oracle qw(:ora_types); Only the following values are permitted for this attribute. -- ORA_VARCHAR2 +- ORA\_VARCHAR2 -Oracle clients using OCI 8 will strip trailing spaces and allow embedded \0 bytes. -Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \0 bytes. +Oracle clients using OCI 8 will strip trailing spaces and allow embedded \\0 bytes. +Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \\0 bytes. This is the normal default placeholder type. -- ORA_STRING +- ORA\_STRING -Do not strip trailing spaces and end the string at the first \0. +Do not strip trailing spaces and end the string at the first \\0. -- ORA_CHAR +- ORA\_CHAR -Do not strip trailing spaces and allow embedded \0. +Do not strip trailing spaces and allow embedded \\0. Force 'blank-padded comparison semantics'. For example: - use DBD::Oracle qw(:ora_types); + use DBD::Oracle qw(:ora_types); - $SQL="select username from all_users where username = ?"; - #username is a char(8) - $sth=$dbh->prepare($SQL)"; - $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); Will pad bloggs out to 8 characters and return the username. -#### ora_parse_error_offset +#### ora\_parse\_error\_offset If the previous error was from a failed `prepare` due to a syntax error, this attribute gives the offset into the `Statement` attribute where the error was found. -#### ora_array_chunk_size +#### ora\_array\_chunk\_size Due to OCI limitations, DBD::Oracle needs to buffer up rows of bind values in its `execute_for_fetch` implementation. This attribute @@ -658,7 +654,7 @@ used to limit or extend the number of rows processed at a time. Note that this attribute also applies to `execute_array`, since that method is implemented using `execute_for_fetch`. -#### ora_connect_with_default_signals +#### ora\_connect\_with\_default\_signals Sometimes the Oracle client seems to change some of the signal handlers of the process during the connect phase. For instance, some @@ -671,36 +667,36 @@ previous state. For example: - $dbh = DBI->connect ($dsn, $user, $passwd, - {ora_connect_with_default_signals => [ 'INT' ] }); + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); NOTE disabling the signal handlers the OCI library sets up may affect functionality in the OCI library. -NOTE If you are using connect_cached then the above example will lead +NOTE If you are using connect\_cached then the above example will lead to DBI thinking each connection is different as an anonymous array reference -is being used. To avoid this when using connect_cached you are advised +is being used. To avoid this when using connect\_cached you are advised to use: - my @ora_default_signals = (...); - $dbh = DBI->connect($dsn, $user, $passwd, - {ora_connect_with_default_signals => \@ora_default_signals}); + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); In more recent Perl versions you could possibly make use of new state variables. -## __connect_cached__ +## __connect\_cached__ Implemented by DBI, no driver-specific impact. -Please note that connect_cached as not been tested with DRCP. +Please note that connect\_cached as not been tested with DRCP. -## __data_sources__ +## __data\_sources__ - @data_sources = DBI->data_sources('Oracle'); - @data_sources = $dbh->data_sources(); + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); -Returns a list of available databases. You will have to set either the 'ORACLE_HOME' or -'TNS_ADMIN' environment value to retrieve this list. It will read these values from +Returns a list of available databases. You will have to set either the 'ORACLE\_HOME' or +'TNS\_ADMIN' environment value to retrieve this list. It will read these values from TNSNAMES.ORA file entries. # METHODS COMMON TO ALL HANDLES @@ -712,19 +708,19 @@ common variable used in this documentation is $_rv_, which stands for "return va ## __err__ - $rv = $h->err; + $rv = $h->err; Returns the error code from the last method called. ## __errstr__ - $str = $h->errstr; + $str = $h->errstr; Returns the last error that was reported by Oracle. Starting with "ORA-00000" code followed by the error message. ## __state__ - $str = $h->state; + $str = $h->state; Oracle hasn't supported SQLSTATE since the early versions OCI. It will return empty when the command succeeds and 'S1000' (General Error) for all other errors. @@ -736,11 +732,11 @@ is usually clearer to always use `$dbh->state`. Implemented by DBI, no driver-specific impact. -## __trace_msg__ +## __trace\_msg__ Implemented by DBI, no driver-specific impact. -## __parse_trace_flag__ and __parse_trace_flags__ +## __parse\_trace\_flag__ and __parse\_trace\_flags__ Implemented by DBI, no driver-specific impact. @@ -751,15 +747,15 @@ DBD::Oracle uses the `func` method to support a variety of functions. ## __Private database handle functions__ Some of these functions are called through the method func() -which is described in the DBI documentation. Any function that begins with ora_ +which is described in the DBI documentation. Any function that begins with ora\_ can be called directly. -## __plsql_errstr__ +## __plsql\_errstr__ This function returns a string which describes the errors from the most recent PL/SQL function, procedure, package, or package body compile in a format similar to the output -of the SQL*Plus command 'show errors'. +of the SQL\*Plus command 'show errors'. The function returns undef if the error string could not be retrieved due to a database error. @@ -784,70 +780,70 @@ Example: die $msg if $msg; } -## __dbms_output_enable / dbms_output_put / dbms_output_get__ +## __dbms\_output\_enable / dbms\_output\_put / dbms\_output\_get__ -These functions use the PL/SQL DBMS_OUTPUT package to store and -retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer -by dbms_output_put or any PL/SQL block can be retrieved by -dbms_output_get or any PL/SQL block connected to the same database +These functions use the PL/SQL DBMS\_OUTPUT package to store and +retrieve text using the DBMS\_OUTPUT buffer. Text stored in this buffer +by dbms\_output\_put or any PL/SQL block can be retrieved by +dbms\_output\_get or any PL/SQL block connected to the same database session. -Stored text is not available until after dbms_output_put or the PL/SQL +Stored text is not available until after dbms\_output\_put or the PL/SQL block that saved it completes its execution. This means you __CAN NOT__ use these functions to monitor long running PL/SQL procedures. Example 1: - # Enable DBMS_OUTPUT and set the buffer size - $dbh->{RaiseError} = 1; - $dbh->func( 1000000, 'dbms_output_enable' ); + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); - # Put text in the buffer . . . - $dbh->func( @text, 'dbms_output_put' ); + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); - # . . . and retrieve it later - @text = $dbh->func( 'dbms_output_get' ); + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); Example 2: - $dbh->{RaiseError} = 1; - $sth = $dbh->prepare(q{ - DECLARE tmp VARCHAR2(50); - BEGIN - SELECT SYSDATE INTO tmp FROM DUAL; - dbms_output.put_line('The date is '||tmp); - END; - }); - $sth->execute; + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; - # retrieve the string - $date_string = $dbh->func( 'dbms_output_get' ); + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); -## __dbms_output_enable ( [ buffer_size ] )__ +## __dbms\_output\_enable ( \[ buffer\_size \] )__ -This function calls DBMS_OUTPUT.ENABLE to enable calls to package -DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to -these procedures are ignored unless DBMS_OUTPUT.ENABLE is called +This function calls DBMS\_OUTPUT.ENABLE to enable calls to package +DBMS\_OUTPUT procedures GET, GET\_LINE, PUT, and PUT\_LINE. Calls to +these procedures are ignored unless DBMS\_OUTPUT.ENABLE is called first. -The buffer_size is the maximum amount of text that can be saved in the -buffer and must be between 2000 and 1,000,000. If buffer_size is not +The buffer\_size is the maximum amount of text that can be saved in the +buffer and must be between 2000 and 1,000,000. If buffer\_size is not given, the default is 20,000 bytes. -## __dbms_output_put ( [ @lines ] )__ +## __dbms\_output\_put ( \[ @lines \] )__ -This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. +This function calls DBMS\_OUTPUT.PUT\_LINE to add lines to the buffer. If all lines were saved successfully the function returns 1. Depending on the context, an empty list or undef is returned for failure. -If any line causes buffer_size to be exceeded, a buffer overflow error +If any line causes buffer\_size to be exceeded, a buffer overflow error is raised and the function call fails. Some of the text might be in the buffer. -## __dbms_output_get__ +## __dbms\_output\_get__ -This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from +This function calls DBMS\_OUTPUT.GET\_LINE to retrieve lines of text from the buffer. In an array context, all complete lines are removed from the buffer and @@ -857,19 +853,19 @@ returned. In a scalar context, the first complete line is removed from the buffer and returned. If there are no complete lines, undef is returned. -Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or -DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, -DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. +Any text in the buffer after a call to DBMS\_OUTPUT.GET\_LINE or +DBMS\_OUTPUT.GET is discarded by the next call to DBMS\_OUTPUT.PUT\_LINE, +DBMS\_OUTPUT.PUT, or DBMS\_OUTPUT.NEW\_LINE. ## __reauthenticate ( $username, $password )__ Starts a new session against the current database using the credentials supplied. -## __private_attribute_info__ +## __private\_attribute\_info__ - $hashref = $dbh->private_attribute_info(); - $hashref = $sth->private_attribute_info(); + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); Returns a hash of all private attributes used by DBD::Oracle, for either a database or a statement handle. Currently, all the hash values are undef. @@ -889,7 +885,7 @@ manually, which is easy to forget to do. ## __PrintError__ (boolean, inherited) Forces database errors to also generate warnings, which can then be filtered with methods such as -locally redefining _$SIG{__WARN__}_ or using modules such as `CGI::Carp`. This attribute is on +locally redefining _$SIG{\_\_WARN\_\_}_ or using modules such as `CGI::Carp`. This attribute is on by default. ## __ShowErrorStatement__ (boolean, inherited) @@ -904,15 +900,15 @@ for a short a time only when absolutely needed. ## __Executed__ (boolean, read-only) -Indicates if a handle has been executed. For database handles, this value is true after the [do](#pod_do) method has been called, or -when one of the child statement handles has issued an [execute](#pod_execute). Issuing a [commit](#pod_commit) or [rollback](#pod_rollback) always resets the -attribute to false for database handles. For statement handles, any call to [execute](#pod_execute) or its variants will flip the value to +Indicates if a handle has been executed. For database handles, this value is true after the ["do"](#do) method has been called, or +when one of the child statement handles has issued an ["execute"](#execute). Issuing a ["commit"](#commit) or ["rollback"](#rollback) always resets the +attribute to false for database handles. For statement handles, any call to ["execute"](#execute) or its variants will flip the value to true for the lifetime of the statement handle. ## __TraceLevel__ (integer, inherited) -Sets the trace level, similar to the [trace](#pod_trace) method. See the sections on -[trace](#pod_trace) and [parse_trace_flag](#pod_parse_trace_flag) for more details. +Sets the trace level, similar to the ["trace"](#trace) method. See the sections on +["trace"](#trace) and ["parse\_trace\_flag"](#parse\_trace\_flag) for more details. ## __Active__ (boolean, read-only) @@ -933,7 +929,7 @@ Same as `Kids`, but only returns those that are active. ## __CachedKids__ (hash ref) Returns a hashref of handles. If called on a database handle, returns all statement handles created by use of the -`prepare_cached` method. If called on a driver handle, returns all database handles created by the [connect_cached](#pod_connect_cached) +`prepare_cached` method. If called on a driver handle, returns all database handles created by the ["connect\_cached"](#connect\_cached) method. ## __ChildHandles__ (array ref) @@ -1008,10 +1004,10 @@ It also has the effect of disabling the 'quick FETCH' of attribute values from t # ORACLE-SPECIFIC DATABASE HANDLE METHODS -## __ora_can_unicode ( [ $refresh ] )__ +## __ora\_can\_unicode ( \[ $refresh \] )__ Returns a number indicating whether either of the database character sets -is a Unicode encoding. Calls ora_nls_parameters() and passes the optional +is a Unicode encoding. Calls ora\_nls\_parameters() and passes the optional $refresh parameter to it. 0 = Neither character set is a Unicode encoding. @@ -1022,37 +1018,37 @@ $refresh parameter to it. 3 = Both character sets are Unicode encodings. -## __ora_can_taf__ +## __ora\_can\_taf__ Returns true if the current connection supports TAF events. False if otherise. -## __ora_nls_parameters ( [ $refresh ] )__ +## __ora\_nls\_parameters ( \[ $refresh \] )__ Returns a hash reference containing the current NLS parameters, as given -by the v$nls_parameters view. The values fetched are cached between calls. +by the v$nls\_parameters view. The values fetched are cached between calls. To cause the latest values to be fetched, pass a true value to the function. # DATABASE HANDLE METHODS -## __selectall_arrayref__ +## __selectall\_arrayref__ - $ary_ref = $dbh->selectall_arrayref($sql); - $ary_ref = $dbh->selectall_arrayref($sql, \%attr); - $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); Returns a reference to an array containing the rows returned by preparing and executing the SQL string. See the DBI documentation for full details. -## __selectall_hashref__ +## __selectall\_hashref__ - $hash_ref = $dbh->selectall_hashref($sql, $key_field); + $hash_ref = $dbh->selectall_hashref($sql, $key_field); Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. See the DBI documentation for full details. -## __selectcol_arrayref__ +## __selectcol\_arrayref__ - $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); Returns a reference to an array containing the first column from each rows returned by preparing and executing the SQL string. It is possible to specify exactly @@ -1060,86 +1056,83 @@ which columns to return. See the DBI documentation for full details. ## __prepare__ - $sth = $dbh->prepare($statement, \%attr); + $sth = $dbh->prepare($statement, \%attr); Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. ### __Prepare Attributes__ These attributes may be used in the `\%attr` parameter of the -L database handle method. +["prepare" in DBI](http://search.cpan.org/perldoc?DBI#prepare) database handle method. -- ora_placeholders +- ora\_placeholders Set to false to disable processing of placeholders. Used mainly for loading a PL/SQL package that has been _wrapped_ with Oracle's `wrap` utility. -- ora_auto_lob +- ora\_auto\_lob If true (the default), fetching retrieves the contents of the CLOB or BLOB column in most circumstances. If false, fetching retrieves the Oracle "LOB Locator" of the CLOB or BLOB value. -See [LOBs and LONGs](#pod_LOBs and LONGs) for more details. +See ["LOBS AND LONGS"](#LOBS AND LONGS) for more details. See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how to use LOB Locators. -- ora_pers_lob +- ora\_pers\_lob -If true the [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) method for the [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) will be -used for LOBs rather than the default method [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators). +If true the ["Simple Fetch for CLOBs and BLOBs"](#Simple Fetch for CLOBs and BLOBs) method for the ["Data Interface for Persistent LOBs"](#Data Interface for Persistent LOBs) will be +used for LOBs rather than the default method ["Data Interface for LOB Locators"](#Data Interface for LOB Locators). -- ora_clbk_lob +- ora\_clbk\_lob -If true the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) method for the L will be used for LOBs. +If true the ["Piecewise Fetch with Callback"](#Piecewise Fetch with Callback) method for the ["Data Interface for Persistent LOBs"](#Data Interface for Persistent LOBs) will be used for LOBs. -- ora_piece_lob +- ora\_piece\_lob -If true the [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) method for the L will be used for LOBs. +If true the ["Piecewise Fetch with Polling"](#Piecewise Fetch with Polling) method for the ["Data Interface for Persistent LOBs"](#Data Interface for Persistent LOBs) will be used for LOBs. -- ora_piece_size +- ora\_piece\_size -This is the max piece size for the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) -and [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) methods, in chars for CLOBS, and +This is the max piece size for the ["Piecewise Fetch with Callback"](#Piecewise Fetch with Callback) +and ["Piecewise Fetch with Polling"](#Piecewise Fetch with Polling) methods, in chars for CLOBS, and bytes for BLOBS. -- ora_check_sql +- ora\_check\_sql If 1 (default), force SELECT statements to be described in prepare(). If 0, allow SELECT statements to defer describe until execute(). -See [Prepare Postponed Till Execute](#pod_Prepare Postponed Till Execute) for more information. +See ["Prepare Postponed Till Execute"](#Prepare Postponed Till Execute) for more information. -- ora_exe_mode +- ora\_exe\_mode This will set the execute mode of the current statement. Presently only one mode is supported; - OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable -See [Scrollable Cursors](#pod_Scrollable Cursors) for more details. +See ["SCROLLABLE CURSORS"](#SCROLLABLE CURSORS) for more details. -- ora_prefetch_rows +- ora\_prefetch\_rows Sets the number of rows to be prefetched. If it is not set, then the -default value is 1. See [Row Prefetching](#pod_Row Prefetching) for more details. +default value is 1. See ["Row Prefetching"](#Row Prefetching) for more details. -- ora_prefetch_memory +- ora\_prefetch\_memory Sets the memory level for rows to be prefetched. The application then -fetches as many rows as will fit into that much memory. See L for more details. +fetches as many rows as will fit into that much memory. See ["Row Prefetching"](#Row Prefetching) for more details. -- ora_row_cache_off +- ora\_row\_cache\_off By default DBD::Oracle will use a row cache when fetching to cut down the number of round trips to the server. If you do not want to use an array fetch set this value to any value other than 0; -See [Row Prefetching](#pod_Row Prefetching) for more details. +See ["Row Prefetching"](#Row Prefetching) for more details. ### __Placeholders__ @@ -1150,18 +1143,18 @@ The first is the "question mark" type, in which each placeholder is represented by a single question mark character. This is the method recommended by the DBI and is the most portable. Each question mark is internally replaced by a "dollar sign number" in the order in -which they appear in the query (important when using [bind_param](#pod_bind_param)). +which they appear in the query (important when using ["bind\_param"](#bind\_param)). The second type of placeholder is "named parameters" in the format ":foo" which is the one Oracle prefers. - $dbh->{RaiseError} = 1; # save having to check each method call - $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); - $sth->bind_param(':name', "John%"); - $sth->execute; - DBI::dump_results($sth); + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); -Note when calling bind_param with named parameters you must include +Note when calling bind\_param with named parameters you must include the leading colon. The advantage of this placeholder type is that you can use the same placeholder more than once in the same SQL statement but you only need to bind it once. @@ -1169,55 +1162,55 @@ but you only need to bind it once. The last placeholder type is a variation of the two above where you name each placeholder :N (where N is a number). Like the named placeholders above you can use the same placeholder multiple times in -the SQL but when you call bind_param you only need to pass the N -(e.g., for :1 you use bind_param(1,...) and not bind_param(':1',...). +the SQL but when you call bind\_param you only need to pass the N +(e.g., for :1 you use bind\_param(1,...) and not bind\_param(':1',...). The different types of placeholders cannot be mixed within a statement, but you may use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. -## __prepare_cached__ +## __prepare\_cached__ - $sth = $dbh->prepare_cached($statement, \%attr); + $sth = $dbh->prepare_cached($statement, \%attr); Implemented by DBI, no driver-specific impact. This method is most useful if the same query is used over and over as it will cut down round trips to the server. ## __do__ - $rv = $dbh->do($statement); - $rv = $dbh->do($statement, \%attr); - $rv = $dbh->do($statement, \%attr, @bind_values); + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); Prepare and execute a single statement. Returns the number of rows affected if the query was successful, returns undef if an error occurred, and returns -1 if the number of rows is unknown or not available. Note that this method will return __0E0__ instead of 0 for 'no rows were affected', in order to always return a true value if no error occurred. -## __last_insert_id__ +## __last\_insert\_id__ -Oracle does not implement auto_increment of serial type columns it uses predefined +Oracle does not implement auto\_increment of serial type columns it uses predefined sequences where the id numbers are either selected before insert, at insert time with a trigger, or as part of the query. Below is an example of you to use the latter with the SQL returning clause to get the ID number back -on insert with the bind_param_inout method. +on insert with the bind\_param\_inout method. . - $dbh->do('CREATE SEQUENCE lii_seq START 1'); - $dbh->do(q{CREATE TABLE lii ( - foobar INTEGER NOT NULL UNIQUE, - baz VARCHAR)}); - $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; - $sth = $dbh->prepare($SQL); - my $p_new_id='-1'; - $sth->bind_param_inout(":p_new_id",\$p_new_id,38); - $sth->execute(); - $db->commit(); + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); ## __commit__ - $rv = $dbh->commit; + $rv = $dbh->commit; Issues a COMMIT to the server, indicating that the current transaction is finished and that all changes made will be visible to other processes. If AutoCommit is enabled, then @@ -1225,21 +1218,21 @@ a warning is given and no COMMIT is issued. Returns true on success, false on er ## __rollback__ - $rv = $dbh->rollback; + $rv = $dbh->rollback; Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and false on error. -## __begin_work__ +## __begin\_work__ -This method turns on transactions until the next call to [commit](#pod_commit) or [rollback](#pod_rollback), if [AutoCommit](#pod_AutoCommit) is -currently enabled. If it is not enabled, calling begin_work will issue an error. Note that the -transaction will not actually begin until the first statement after begin_work is called. +This method turns on transactions until the next call to ["commit"](#commit) or ["rollback"](#rollback), if ["AutoCommit"](#AutoCommit) is +currently enabled. If it is not enabled, calling begin\_work will issue an error. Note that the +transaction will not actually begin until the first statement after begin\_work is called. ## __disconnect__ - $rv = $dbh->disconnect; + $rv = $dbh->disconnect; Disconnects from the Oracle database. Any uncommitted changes will be rolled back upon disconnection. It's good policy to always explicitly call commit or rollback at some point before disconnecting, rather than @@ -1251,42 +1244,42 @@ methods automatically. It is best to explicitly disconnect rather than rely on t ## __ping__ - $rv = $dbh->ping; + $rv = $dbh->ping; This `ping` method is used to check the validity of a database handle. The value returned is either 0, indicating that the connection is no longer valid, or 1, indicating the connection is valid. This function does 1 round trip to the Oracle Server. -## __get_info()__ +## __get\_info()__ - $value = $dbh->get_info($info_type); + $value = $dbh->get_info($info_type); DBD::Oracle supports `get_info()`, but (currently) only a few info types. -## __table_info()__ +## __table\_info()__ DBD::Oracle supports attributes for `table_info()`. In Oracle, the concept of _user_ and _schema_ is (currently) the same. Because database objects are owned by an user, the owner names in the data dictionary views correspond to schema names. -Oracle does not support catalogues so TABLE_CAT is ignored as +Oracle does not support catalogues so TABLE\_CAT is ignored as selection criterion. -Search patterns are supported for TABLE_SCHEM and TABLE_NAME. +Search patterns are supported for TABLE\_SCHEM and TABLE\_NAME. -TABLE_TYPE may contain a comma-separated list of table types. +TABLE\_TYPE may contain a comma-separated list of table types. The following table types are supported: - TABLE - VIEW - SYNONYM - SEQUENCE + TABLE + VIEW + SYNONYM + SEQUENCE -The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. +The result set is ordered by TABLE\_TYPE, TABLE\_SCHEM, TABLE\_NAME. The special enumerations of catalogues, schemas and table types are -supported. However, TABLE_CAT is always NULL. +supported. However, TABLE\_CAT is always NULL. An identifier is passed _as is_, i.e. as the user provides or Oracle returns it. @@ -1300,124 +1293,124 @@ upper case). Oracle stores and returns it as given. `table_info()` has no special quote handling, neither adds nor removes quotes. -## __primary_key_info()__ +## __primary\_key\_info()__ -Oracle does not support catalogues so TABLE_CAT is ignored as +Oracle does not support catalogues so TABLE\_CAT is ignored as selection criterion. -The TABLE_CAT field of a fetched row is always NULL (undef). -See [table_info()](#pod_table_info()) for more detailed information. +The TABLE\_CAT field of a fetched row is always NULL (undef). +See ["table\_info()"](#table\_info()) for more detailed information. If the primary key constraint was created without an identifier, -PK_NAME contains a system generated name with the form SYS_Cn. +PK\_NAME contains a system generated name with the form SYS\_Cn. -The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. +The result set is ordered by TABLE\_SCHEM, TABLE\_NAME, KEY\_SEQ. An identifier is passed _as is_, i.e. as the user provides or Oracle returns it. -See [table_info()](#pod_table_info()) for more detailed information. +See ["table\_info()"](#table\_info()) for more detailed information. -## __foreign_key_info()__ +## __foreign\_key\_info()__ This method (currently) supports the extended behaviour of SQL/CLI, i.e. the result set contains foreign keys that refer to primary __and__ alternate keys. -The field UNIQUE_OR_PRIMARY distinguishes these keys. +The field UNIQUE\_OR\_PRIMARY distinguishes these keys. Oracle does not support catalogues, so `$pk_catalog` and `$fk_catalog` are ignored as selection criteria (in the new style interface). -The UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always +The UK\_TABLE\_CAT and FK\_TABLE\_CAT fields of a fetched row are always NULL (undef). -See [table_info()](#pod_table_info()) for more detailed information. +See ["table\_info()"](#table\_info()) for more detailed information. If the primary or foreign key constraints were created without an identifier, -UK_NAME or FK_NAME contains a system generated name with the form SYS_Cn. +UK\_NAME or FK\_NAME contains a system generated name with the form SYS\_Cn. -The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle (currently) +The UPDATE\_RULE field is always 3 ('NO ACTION'), because Oracle (currently) does not support other actions. -The DELETE_RULE field may contain wrong values. This is a known Bug (#1271663) +The DELETE\_RULE field may contain wrong values. This is a known Bug (\#1271663) in Oracle's data dictionary views. Currently (as of 8.1.7), 'RESTRICT' and 'SET DEFAULT' are not supported, 'CASCADE' is mapped correctly and all other actions (incl. 'SET NULL') appear as 'NO ACTION'. The DEFERABILITY field is always NULL, because this columns is -not present in the ALL_CONSTRAINTS view of older Oracle releases. +not present in the ALL\_CONSTRAINTS view of older Oracle releases. -The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, -FK_TABLE_NAME, ORDINAL_POSITION. +The result set is ordered by UK\_TABLE\_SCHEM, UK\_TABLE\_NAME, FK\_TABLE\_SCHEM, +FK\_TABLE\_NAME, ORDINAL\_POSITION. An identifier is passed _as is_, i.e. as the user provides or Oracle returns it. -See [table_info()](#pod_table_info()) for more detailed information. +See ["table\_info()"](#table\_info()) for more detailed information. -## __column_info()__ +## __column\_info()__ -Oracle does not support catalogues so TABLE_CAT is ignored as +Oracle does not support catalogues so TABLE\_CAT is ignored as selection criterion. -The TABLE_CAT field of a fetched row is always NULL (undef). -See [table_info()](#pod_table_info()) for more detailed information. +The TABLE\_CAT field of a fetched row is always NULL (undef). +See ["table\_info()"](#table\_info()) for more detailed information. -The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). +The CHAR\_OCTET\_LENGTH field is (currently) always NULL (undef). -Don't rely on the values of the BUFFER_LENGTH field! +Don't rely on the values of the BUFFER\_LENGTH field! Especially the length of FLOATs may be wrong. Datatype codes for non-standard types are subject to change. -Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG so you +Attention! The DATA\_DEFAULT (COLUMN\_DEF) column is of type LONG so you may have to set LongReadLen on the connection handle before calling -column_info if you have a large default column. After DBD::Oracle 1.40 -LongReadLen is set automatically to 1Mb when calling column_info and +column\_info if you have a large default column. After DBD::Oracle 1.40 +LongReadLen is set automatically to 1Mb when calling column\_info and reset aftwerwards. -The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. +The result set is ordered by TABLE\_SCHEM, TABLE\_NAME, ORDINAL\_POSITION. An identifier is passed _as is_, i.e. as the user provides or Oracle returns it. -See [table_info()](#pod_table_info()) for more detailed information. +See ["table\_info()"](#table\_info()) for more detailed information. It is possible with Oracle to make the names of the various DB objects (table,column,index etc) case sensitive. - alter table bloggind add ("Bla_BLA" NUMBER) + alter table bloggind add ("Bla_BLA" NUMBER) -So in the example the exact case "Bla_BLA" must be used to get it info on the column. While this +So in the example the exact case "Bla\_BLA" must be used to get it info on the column. While this - alter table bloggind add (Bla_BLA NUMBER) + alter table bloggind add (Bla_BLA NUMBER) any case can be used to get info on the column. -## __selectrow_array__ +## __selectrow\_array__ - @row_ary = $dbh->selectrow_array($sql); - @row_ary = $dbh->selectrow_array($sql, \%attr); - @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); Returns an array of row information after preparing and executing the provided SQL string. The rows are returned -by calling [fetchrow_array](#pod_fetchrow_array). The string can also be a statement handle generated by a previous prepare. Note that +by calling ["fetchrow\_array"](#fetchrow\_array). The string can also be a statement handle generated by a previous prepare. Note that only the first row of data is returned. If called in a scalar context, only the first column of the first row is returned. Because this is not portable, it is not recommended that you use this method in that way. -## __selectrow_arrayref__ +## __selectrow\_arrayref__ - $ary_ref = $dbh->selectrow_arrayref($statement); - $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); - $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); -Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an array, by internal use of -the [fetchrow_arrayref](#pod_fetchrow_arrayref) method. +Exactly the same as ["selectrow\_array"](#selectrow\_array), except that it returns a reference to an array, by internal use of +the ["fetchrow\_arrayref"](#fetchrow\_arrayref) method. -## __selectrow_hashref__ +## __selectrow\_hashref__ - $hash_ref = $dbh->selectrow_hashref($sql); - $hash_ref = $dbh->selectrow_hashref($sql, \%attr); - $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); -Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an hash, by internal use of -the [fetchrow_hashref](#pod_fetchrow_hashref) method. +Exactly the same as ["selectrow\_array"](#selectrow\_array), except that it returns a reference to an hash, by internal use of +the ["fetchrow\_hashref"](#fetchrow\_hashref) method. ## __clone__ - $other_dbh = $dbh->clone(); + $other_dbh = $dbh->clone(); Creates a copy of the database handle by connecting with the same parameters as the original handle, then trying to merge the attributes. See the DBI documentation for complete usage. @@ -1428,11 +1421,11 @@ handle, then trying to merge the attributes. See the DBI documentation for compl Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change in the future, so it is highly recommended that you explicitly set it when -calling [connect](#pod_connect). +calling ["connect"](#connect). ## __ReadOnly__ (boolean) - $dbh->{ReadOnly} = 1; + $dbh->{ReadOnly} = 1; Specifies if the current database connection should be in read-only mode or not. @@ -1456,7 +1449,7 @@ Returns the name of the user connected to the database. Holds the handle of the parent driver. The only recommended use for this is to find the name of the driver using: - $dbh->{Driver}->{Name} + $dbh->{Driver}->{Name} ## __RowCacheSize__ @@ -1485,46 +1478,46 @@ caching still works. If you are only selecting a LOB Locator then Row Caching w ### Row Prefetching Row prefetching occurs on the server side and uses the DBI database handle attribute `RowCacheSize` and or the -Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improved performance. +Prepare Attribute 'ora\_prefetch\_memory'. Tweaking these values may yield improved performance. - $dbh->{RowCacheSize} = 100; - $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first -fetch that sets the current_positon to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are +fetch that sets the current\_positon to any value other than 0. In the above example if we do a OCI\_FETCH\_FIRST the first 10 rows are loaded into the buffer and DBD::Oracle will not have to go back to the server for more rows. When record 11 is fetched DBD::Oracle fetches and returns this row and the next 9 rows are loaded into the buffer. In this case if you fetch backwards from 10 to 1 no server round trips are made. With large record sets it is best not to attempt to go to the last record as this may take some time, A large buffer size might even slow down -the fetch. If you must get the number of rows in a large record set you might try using an few large OCI_FETCH_ABSOLUTEs and then an OCI_FETCH_LAST, -this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. +the fetch. If you must get the number of rows in a large record set you might try using an few large OCI\_FETCH\_ABSOLUTEs and then an OCI\_FETCH\_LAST, +this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI\_FETCH\_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. If one requires only the first few rows there is no need to set a large prefetch value. -If the ora_prefetch_memory less than 1 or not present then memory size is not included in computing the +If the ora\_prefetch\_memory less than 1 or not present then memory size is not included in computing the number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it is not included in the computing of the prefetch rows. # ORACLE-SPECIFIC STATEMENT HANDLE METHODS -## __ora_stmt_type__ +## __ora\_stmt\_type__ Returns the OCI Statement Type number for the SQL of a statement handle. -## __ora_stmt_type_name__ +## __ora\_stmt\_type\_name__ Returns the OCI Statement Type name for the SQL of a statement handle. # DBI STATEMENT HANDLE OBJECT METHODS -## __bind_param__ +## __bind\_param__ - $rv = $sth->bind_param($param_num, $bind_value); - $rv = $sth->bind_param($param_num, $bind_value, $bind_type); - $rv = $sth->bind_param($param_num, $bind_value, \%attr); + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); Allows the user to bind a value and/or a data type to a placeholder. @@ -1540,26 +1533,26 @@ The default value is "varchar". If you need something else, you must use one of the values provided by DBI or by DBD::Pg. To use a SQL value, modify your "use DBI" statement at the top of your script as follows: - use DBI qw(:sql_types); + use DBI qw(:sql_types); This will import some constants into your script. You can plug those -directly into the [bind_param](#pod_bind_param) call. Some common ones that you will +directly into the ["bind\_param"](#bind\_param) call. Some common ones that you will encounter are: - SQL_INTEGER + SQL_INTEGER To use Oracle SQL data types, import the list of values like this: - use DBD::Pg qw(:ora_types); + use DBD::Pg qw(:ora_types); You can then set the data types by setting the value of the `ora_type` -key in the hash passed to [bind_param](#pod_bind_param). +key in the hash passed to ["bind\_param"](#bind\_param). The current list of Oracle data types exported is: - ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW - ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB - ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI - SQLT_CHR SQLT_BIN + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN Data types are "sticky," in that once a data type is set to a certain placeholder, it will remain for that placeholder, unless it is explicitly set to something @@ -1569,42 +1562,42 @@ doing the next execute. Examples: - use DBI qw(:sql_types); - use DBD::Pg qw(:ora_types); + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); - $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; - $sth = $dbh->prepare($SQL); + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); - ## Both arguments below are bound to placeholders as "varchar" - $sth->execute(123, "Merk"); + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); - ## Reset the datatype for the first placeholder to an integer - $sth->bind_param(1, undef, SQL_INTEGER); + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); - ## The "undef" bound above is not used, since we supply params to execute - $sth->execute(123, "Merk"); + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); - ## Set the first placeholder's value and data type - $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); - ## Set the second placeholder's value and data type. - ## We don't send a third argument, so the default "varchar" is used - $sth->bind_param('$2', "Zool"); + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); - ## We realize that the wrong data type was set above, so we change it: - $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); - ## We also got the wrong value, so we change that as well. - ## Because the data type is sticky, we don't need to change it - $sth->bind_param(1, 567); + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); - ## This executes the statement with 567 (integer) and "Zool" (varchar) - $sth->execute(); + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); These attributes may be used in the `\%attr` parameter of the -L or L statement handle methods. +["bind\_param" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param) or ["bind\_param\_inout" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param\_inout) statement handle methods. -- ora_type +- ora\_type Specify the placeholder's datatype using an Oracle datatype. A fatal error is raised if `ora_type` and the DBI `TYPE` attribute @@ -1613,61 +1606,61 @@ Some of these types are not supported by the current version of DBD::Oracle and will cause a fatal error if used. Constants for the Oracle datatypes may be imported using - use DBD::Oracle qw(:ora_types); + use DBD::Oracle qw(:ora_types); Potentially useful values when DBD::Oracle was built using OCI 7 and later: - ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, - ORA_CHAR, ORA_MLSLABEL, ORA_RSET + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET Additional values when DBD::Oracle was built using OCI 8 and later: - ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE Additional values when DBD::Oracle was built using OCI 9.2 and later: - SQLT_CHR, SQLT_BIN + SQLT_CHR, SQLT_BIN -See [Binding Cursors](#pod_Binding Cursors) for the correct way to use ORA_RSET. +See ["Binding Cursors"](#Binding Cursors) for the correct way to use ORA\_RSET. -See [LOBs and LONGs](#pod_LOBs and LONGs) for how to use ORA_CLOB and ORA_BLOB. +See ["LOBS AND LONGS"](#LOBS AND LONGS) for how to use ORA\_CLOB and ORA\_BLOB. -See [SYS.DBMS_SQL datatypes](#pod_SYS.DBMS_SQL datatypes) for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. +See ["SYS.DBMS\_SQL datatypes"](#SYS.DBMS\_SQL datatypes) for ORA\_VARCHAR2\_TABLE, ORA\_NUMBER\_TABLE. -See [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) for the correct way to use SQLT_CHR and SQLT_BIN. +See ["Data Interface for Persistent LOBs"](#Data Interface for Persistent LOBs) for the correct way to use SQLT\_CHR and SQLT\_BIN. -See [Other Data Types](#pod_Other Data Types) for more information. +See ["OTHER DATA TYPES"](#OTHER DATA TYPES) for more information. -See also L. +See also ["Placeholders and Bind Values" in DBI](http://search.cpan.org/perldoc?DBI#Placeholders and Bind Values). -- ora_csform +- ora\_csform -Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values -are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can +Specify the OCI\_ATTR\_CHARSET\_FORM for the bind value. Valid values +are SQLCS\_IMPLICIT (1) and SQLCS\_NCHAR (2). Both those constants can be imported from the DBD::Oracle module. Rarely needed. -- ora_csid +- ora\_csid -Specify the _integer_ OCI_ATTR_CHARSET_ID for the bind value. +Specify the _integer_ OCI\_ATTR\_CHARSET\_ID for the bind value. Character set names can't be used currently. -- ora_maxdata_size +- ora\_maxdata\_size -Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. +Specify the integer OCI\_ATTR\_MAXDATA\_SIZE for the bind value. May be needed if a character set conversion from client to server causes the data to use more space and so fail with a truncation error. -- ora_maxarray_numentries +- ora\_maxarray\_numentries Specify the maximum number of array entries to allocate. Used with -ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of +ORA\_VARCHAR2\_TABLE, ORA\_NUMBER\_TABLE. Define the maximum number of array entries Oracle can pass back to you in OUT variable of type TABLE OF ... . -- ora_internal_type +- ora\_internal\_type Specify internal data representation. Currently is supported only for -ORA_NUMBER_TABLE. +ORA\_NUMBER\_TABLE. ### Optimizing Results @@ -1677,7 +1670,7 @@ The DBD::Oracle module can avoid an explicit 'describe' operation prior to the execution of the statement unless the application requests information about the results (such as $sth->{NAME}). This reduces communication with the server and increases performance (reducing the -number of PARSE_CALLS inside the server). +number of PARSE\_CALLS inside the server). However, it also means that SQL errors are not detected until `execute()` (or $sth->{NAME} etc) is called instead of when @@ -1685,13 +1678,13 @@ However, it also means that SQL errors are not detected until use of $sth->{NAME} or a similar attribute and the describe fails then _an exception is thrown_ even if `RaiseError` is false! -Set [ora_check_sql](#pod_ora_check_sql) to 0 in prepare() to enable this behaviour. +Set ["ora\_check\_sql"](#ora\_check\_sql) to 0 in prepare() to enable this behaviour. -## __bind_param_inout__ +## __bind\_param\_inout__ - $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); -DBD::Oracle fully supports bind_param_inout below are some uses for this method. +DBD::Oracle fully supports bind\_param\_inout below are some uses for this method. ### __Returning A Value from an INSERT__ @@ -1700,50 +1693,47 @@ or more of the values inserted. This can be particularly useful for single-pass insertion of values with re-used sequence values (avoiding a separate "select seq.nextval from dual" step). - $sth = $dbh->prepare(qq{ - INSERT INTO foo (id, bar) - VALUES (foo_id_seq.nextval, :bar) - RETURNING id INTO :id - }); - $sth->bind_param(":bar", 42); - $sth->bind_param_inout(":id", \my $new_id, 99); - $sth->execute; - print "The id of the new record is $new_id\n"; + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; If you have many columns to bind you can use code like this: - @params = (... column values for record to be inserted ...); - $sth->bind_param($_, $params[$_-1]) for (1..@params); - $sth->bind_param_inout(@params+1, \my $new_id, 99); - $sth->execute; + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; If you have many rows to insert you can take advantage of Oracle's built in execute array feature with code like this: - my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); - my @out_values; - my @status; - my $sth = $dbh->prepare(qq{ - INSERT INTO foo (id, bar) - VALUES (foo_id_seq.nextval, ?) - RETURNING id INTO ? - }); - $sth->bind_param_array(1,\@in_values); - $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); - $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; - foreach my $id (@out_values){ + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ print 'returned id='.$id.'\n'; - } + } -Which will return all the ids into @out_values. +Which will return all the ids into @out\_values. - __Note:__ - - This will only work for numbered (?) placeholders, - -- The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle - -- The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. +- The third parameter of bind\_param\_inout\_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle +- The "ora\_type" attribute is not needed but only ORA\_VARCHAR2 will work. ### Returning A Recordset @@ -1755,90 +1745,90 @@ or later, you can make use of table (or pipelined) functions. For example, assume you have the existing PL/SQL Package : - CREATE OR REPLACE PACKAGE Array_Example AS + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS -- - TYPE tRec IS RECORD ( - Col1 NUMBER, - Col2 VARCHAR2 (10), - Col3 DATE) ; + FUNCTION Array_Func RETURN taRec AS -- - TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + l_Ret taRec ; -- - FUNCTION Array_Func RETURN taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; -- - END Array_Example ; - - CREATE OR REPLACE PACKAGE BODY Array_Example AS - -- - FUNCTION Array_Func RETURN taRec AS - -- - l_Ret taRec ; - -- - BEGIN - FOR i IN 1 .. 5 LOOP - l_Ret (i).Col1 := i ; - l_Ret (i).Col2 := 'Row : ' || i ; - l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; - END LOOP ; - RETURN l_Ret ; - END ; - -- - END Array_Example ; - / + END Array_Example ; + / Currently, there is no way to directly call the function -Array_Example.Array_Func from DBI. However, by making the following relatively +Array\_Example.Array\_Func from DBI. However, by making the following relatively painless additions, its not only possible, but extremely efficient. First, you need to create database object types that correspond to the record and table types in the package. From the above example, these would be : - CREATE OR REPLACE TYPE tArray_Example__taRec - AS OBJECT ( - Col1 NUMBER, - Col2 VARCHAR2 (10), - Col3 DATE - ) ; + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; - CREATE OR REPLACE TYPE taArray_Example__taRec - AS TABLE OF tArray_Example__taRec ; + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; Now, assuming the existing function needs to remain unchanged (it is probably being called from other PL/SQL code), we need to add a new function to the package. Here's the new package specification and body : - CREATE OR REPLACE PACKAGE Array_Example AS - -- - TYPE tRec IS RECORD ( + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( Col1 NUMBER, Col2 VARCHAR2 (10), Col3 DATE) ; - -- - TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; - -- - FUNCTION Array_Func RETURN taRec ; - FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; - -- - END Array_Example ; - - CREATE OR REPLACE PACKAGE BODY Array_Example AS - -- - FUNCTION Array_Func RETURN taRec AS - l_Ret taRec ; - BEGIN - FOR i IN 1 .. 5 LOOP + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP l_Ret (i).Col1 := i ; l_Ret (i).Col2 := 'Row : ' || i ; l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; - END LOOP ; - RETURN l_Ret ; - END ; + END LOOP ; + RETURN l_Ret ; + END ; - FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS - l_Set taRec ; - BEGIN - l_Set := Array_Func ; - FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP PIPE ROW ( tArray_Example__taRec ( l_Set (i).Col1, @@ -1846,26 +1836,26 @@ package. Here's the new package specification and body : l_Set (i).Col3 ) ) ; - END LOOP ; - RETURN ; - END ; - -- - END Array_Example ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; As you can see, the new function is very simple. Now, it is a simple matter of calling the function as a straight-forward SELECT from your DBI code. From the above example, the code would look something like this : - my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); - $sth->execute; - while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { - ... - } + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } -### __SYS.DBMS_SQL datatypes__ +### __SYS.DBMS\_SQL datatypes__ -DBD::Oracle has built-in support for __SYS.DBMS_SQL.VARCHAR2_TABLE__ -and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: +DBD::Oracle has built-in support for __SYS.DBMS\_SQL.VARCHAR2\_TABLE__ +and __SYS.DBMS\_SQL.NUMBER\_TABLE__ datatypes. The simple example is here: my $statement=' DECLARE @@ -1893,43 +1883,42 @@ and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; - __Note:__ - -- Take careful note that we use '\\@arr' here because the 'bind_param_inout' +- Take careful note that we use '\\\\@arr' here because the 'bind\_param\_inout' will only take a reference to a scalar. -### __ORA_VARCHAR2_TABLE__ +### __ORA\_VARCHAR2\_TABLE__ -SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. -( in bind_param() and bind_param_inout() ). When you bind array, you need +SYS.DBMS\_SQL.VARCHAR2\_TABLE object is always bound to array reference. +( in bind\_param() and bind\_param\_inout() ). When you bind array, you need to specify full buffer size for OUT data. So, there are two parameters: -_max_len_ (specified as 3rd argument of bind_param_inout() ), -and _ora_maxarray_numentries_. They define maximum array entry length and +_max\_len_ (specified as 3rd argument of bind\_param\_inout() ), +and _ora\_maxarray\_numentries_. They define maximum array entry length and maximum rows, that can be passed to Oracle and back to you. In this example we send array with 1 element with length=3, but allocate space for 100 Oracle array entries with maximum length 10 of each. So, you can get no more than 100 array entries with length <= 10. -If you set _max_len_ to zero, maximum array entry length is calculated -as maximum length of entry of array bound. If 0 < _max_len_ < length( $some_element ), +If you set _max\_len_ to zero, maximum array entry length is calculated +as maximum length of entry of array bound. If 0 < _max\_len_ < length( $some\_element ), truncation occur. -If you set _ora_maxarray_numentries_ to zero, current (at bind time) bound -array length is used as maximum. If 0 < _ora_maxarray_numentries_ < scalar(@array), +If you set _ora\_maxarray\_numentries_ to zero, current (at bind time) bound +array length is used as maximum. If 0 < _ora\_maxarray\_numentries_ < scalar(@array), not all array entries are bound. -### __ORA_NUMBER_TABLE__ +### __ORA\_NUMBER\_TABLE__ -SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. +SYS.DBMS\_SQL.NUMBER\_TABLE object handling is much alike ORA\_VARCHAR2\_TABLE. The main difference is internal data representation. Currently 2 types of bind is allowed : as C-integer, or as C-double type. To select one of them, -you may specify additional bind parameter _ora_internal_type_ as either -__SQLT_INT__ or __SQLT_FLT__ for C-integer and C-double types. +you may specify additional bind parameter _ora\_internal\_type_ as either +__SQLT\_INT__ or __SQLT\_FLT__ for C-integer and C-double types. Integer size is architecture-specific and is usually 32 or 64 bit. Double is standard IEEE 754 type. -_ora_internal_type_ defaults to double (SQLT_FLT). +_ora\_internal\_type_ defaults to double (SQLT\_FLT). -_max_len_ is ignored for OCI_NUMBER_TABLE. +_max\_len_ is ignored for OCI\_NUMBER\_TABLE. Currently, you cannot bind full native Oracle NUMBER(38). If you really need, send request to dbi-dev list. @@ -1986,7 +1975,7 @@ The result is like: '-2' ]; -If you change bind type to __SQLT_INT__, like: +If you change bind type to __SQLT\_INT__, like: ora_internal_type => SQLT_INT @@ -2001,135 +1990,135 @@ you get: -2 ]; -## __bind_param_inout_array__ +## __bind\_param\_inout\_array__ -DBD::Oracle supports this undocumented feature of DBI. See [Returning A Value from an INSERT](#pod_Returning A Value from an INSERT) for an example. +DBD::Oracle supports this undocumented feature of DBI. See ["Returning A Value from an INSERT"](#Returning A Value from an INSERT) for an example. -## __bind_param_array__ +## __bind\_param\_array__ - $rv = $sth->bind_param_array($param_num, $array_ref_or_value) - $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) - $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) Binds an array of values to a placeholder, so that each is used in turn by a call -to the [execute_array](#pod_execute_array) method. +to the ["execute\_array"](#execute\_array) method. ## __execute__ - $rv = $sth->execute(@bind_values); + $rv = $sth->execute(@bind_values); Perform whatever processing is necessary to execute the prepared statement. -## __execute_array__ +## __execute\_array__ - $tuples = $sth->execute_array() or die $sth->errstr; - $tuples = $sth->execute_array(\%attr) or die $sth->errstr; - $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; - ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; - ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; Execute a prepared statement once for each item in a passed-in hashref, or items that -were previously bound via the [bind_param_array](#pod_bind_param_array) method. See the DBI documentation +were previously bound via the ["bind\_param\_array"](#bind\_param\_array) method. See the DBI documentation for more details. DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very quickly. -## __execute_for_fetch__ +## __execute\_for\_fetch__ - $tuples = $sth->execute_for_fetch($fetch_tuple_sub); - $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); - ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); - ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); -Used internally by the [execute_array](#pod_execute_array) method, and rarely used directly. See the +Used internally by the ["execute\_array"](#execute\_array) method, and rarely used directly. See the DBI documentation for more details. -## __fetchrow_arrayref__ +## __fetchrow\_arrayref__ - $ary_ref = $sth->fetchrow_arrayref; + $ary_ref = $sth->fetchrow_arrayref; Fetches the next row of data from the statement handle, and returns a reference to an array holding the column values. Any columns that are NULL are returned as undef within the array. If there are no more rows or if an error occurs, the this method return undef. You should -check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +check `$sth->err` afterwards (or use the ["RaiseError"](#RaiseError) attribute) to discover if the undef returned was due to an error. Note that the same array reference is returned for each fetch, so don't store the reference and then use it after a later fetch. Also, the elements of the array are also reused for each row, -so take care if you want to take a reference to an element. See also [bind_columns](#pod_bind_columns). +so take care if you want to take a reference to an element. See also ["bind\_columns"](#bind\_columns). -## __fetchrow_array__ +## __fetchrow\_array__ - @ary = $sth->fetchrow_array; + @ary = $sth->fetchrow_array; -Similar to the [fetchrow_arrayref](#pod_fetchrow_arrayref) method, but returns a list of column information rather than +Similar to the ["fetchrow\_arrayref"](#fetchrow\_arrayref) method, but returns a list of column information rather than a reference to a list. Do not use this in a scalar context. -## __fetchrow_hashref__ +## __fetchrow\_hashref__ - $hash_ref = $sth->fetchrow_hashref; - $hash_ref = $sth->fetchrow_hashref($name); + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); Fetches the next row of data and returns a hashref containing the name of the columns as the keys and the data itself as the values. Any NULL value is returned as as undef value. If there are no more rows or if an error occurs, the this method return undef. You should -check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +check `$sth->err` afterwards (or use the ["RaiseError"](#RaiseError) attribute) to discover if the undef returned was due to an error. The optional `$name` argument should be either `NAME`, `NAME_lc` or `NAME_uc`, and indicates what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. -## __fetchall_arrayref__ +## __fetchall\_arrayref__ - $tbl_ary_ref = $sth->fetchall_arrayref(); - $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); - $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, the data read in so far will be returned. Because of this, you should always check `$sth->err` after -calling this method, unless [RaiseError](#pod_RaiseError) has been enabled. +calling this method, unless ["RaiseError"](#RaiseError) has been enabled. -If `$slice` is an array reference, fetchall_arrayref uses the [fetchrow_arrayref](#pod_fetchrow_arrayref) method to fetch each +If `$slice` is an array reference, fetchall\_arrayref uses the ["fetchrow\_arrayref"](#fetchrow\_arrayref) method to fetch each row as an array ref. If the `$slice` array is not empty then it is used as a slice to select individual columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). -With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. +With no parameters, or if $slice is undefined, fetchall\_arrayref acts as if passed an empty array ref. -If `$slice` is a hash reference, fetchall_arrayref uses [fetchrow_hashref](#pod_fetchrow_hashref) to fetch each row as a hash reference. +If `$slice` is a hash reference, fetchall\_arrayref uses ["fetchrow\_hashref"](#fetchrow\_hashref) to fetch each row as a hash reference. See the DBI documentation for a complete discussion. -## __fetchall_hashref__ +## __fetchall\_hashref__ - $hash_ref = $sth->fetchall_hashref( $key_field ); + $hash_ref = $sth->fetchall_hashref( $key_field ); Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for a full discussion. ## __finish__ - $rv = $sth->finish; + $rv = $sth->finish; Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed when you have not fetched all the possible rows. ## __rows__ - $rv = $sth->rows; + $rv = $sth->rows; Returns the number of rows affected for updates, deletes and inserts and -1 for selects. -## __bind_col__ +## __bind\_col__ - $rv = $sth->bind_col($column_number, \$var_to_bind); - $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); - $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); Binds a Perl variable and/or some attributes to an output column of a SELECT statement. Column numbers count up from 1. You do not need to bind output columns in order to fetch data. @@ -2142,15 +2131,15 @@ retrieved. See the DBI documentation for a discussion of the optional parameters `\%attr` and `$bind_type` -## __bind_columns__ +## __bind\_columns__ - $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); -Calls the [bind_col](#pod_bind_col) method for each column in the SELECT statement, using the supplied list. +Calls the ["bind\_col"](#bind\_col) method for each column in the SELECT statement, using the supplied list. -## __dump_results__ +## __dump\_results__ - $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); Fetches all the rows from the statement handle, calls `DBI::neat_list` for each row, and prints the results to `$fh` (which defaults to `STDOUT`). Rows are separated by `$lsep` (which defaults @@ -2158,19 +2147,19 @@ to a newline). Columns are separated by `$fsep` (which defaults to a comma). The how wide the output can be, and defaults to 35. This method is designed as a handy utility for prototyping and testing queries. Since it uses -"neat_list" to format and edit the string for reading by humans, it is not recommended +"neat\_list" to format and edit the string for reading by humans, it is not recommended for data transfer applications. # STATEMENT HANDLE ATTRIBUTES -## __NUM_OF_FIELDS__ (integer, read-only) +## __NUM\_OF\_FIELDS__ (integer, read-only) Returns the number of columns returned by the current statement. A number will only be returned for SELECT statements for INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. This method returns undef if called before `execute()`. -## __NUM_OF_PARAMS__ (integer, read-only) +## __NUM\_OF\_PARAMS__ (integer, read-only) Returns the number of placeholders in the current statement. @@ -2181,25 +2170,25 @@ method will only work for SELECT statements, for SHOW statements, and for INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. This method returns undef if called before `execute()`. -## __NAME_lc__ (arrayref, read-only) +## __NAME\_lc__ (arrayref, read-only) The same as the `NAME` attribute, except that all column names are forced to lower case. -## __NAME_uc__ (arrayref, read-only) +## __NAME\_uc__ (arrayref, read-only) The same as the `NAME` attribute, except that all column names are forced to upper case. -## __NAME_hash__ (hashref, read-only) +## __NAME\_hash__ (hashref, read-only) Similar to the `NAME` attribute, but returns a hashref of column names instead of an arrayref. The names of the columns are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. This method returns undef if called before `execute()`. -## __NAME_lc_hash__ (hashref, read-only) +## __NAME\_lc\_hash__ (hashref, read-only) The same as the `NAME_hash` attribute, except that all column names are forced to lower case. -## __NAME_uc_hash__ (hashref, read-only) +## __NAME\_uc\_hash__ (hashref, read-only) The same as the `NAME_hash` attribute, except that all column names are forced to lower case. @@ -2240,17 +2229,17 @@ placeholders (without the colon). If the "dollar sign numbers" type of placehold be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, starting at one and increasing for every placeholder. -If this method is called before [execute](#pod_execute), the literal values passed in are returned. If called after -[execute](#pod_execute), then the quoted versions of the values are returned. +If this method is called before ["execute"](#execute), the literal values passed in are returned. If called after +["execute"](#execute), then the quoted versions of the values are returned. ## __ParamTypes__ (hash ref, read-only) Returns a reference to a hash containing the type names currently bound to placeholders. The keys are the same as returned by the ParamValues method. The values are hashrefs containing a single key value -pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can +pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg\_type' if the type can only be expressed by a Postgres type. The value is the internal number corresponding to the type originally passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of -ParamTypes to be passed back to the [bind_param](#pod_bind_param) method. +ParamTypes to be passed back to the ["bind\_param"](#bind\_param) method. ## __Statement__ (string, read-only) @@ -2284,14 +2273,14 @@ more server and client resources and have poorer response times than non-scrolli To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; - use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); -Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the -statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; +Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora\_exe\_mode attribute on the +statement handle to 'OCI\_STMT\_SCROLLABLE\_READONLY' with the prepare method; - $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); -When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row +When the statement is executed you will then be able to use 'ora\_fetch\_scroll' method to get a row or you can still use any of the other fetch methods but with a poorer response time than if you used a non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. @@ -2299,199 +2288,199 @@ non-scrolling cursor. As well scrollable cursors are compatible with any applica The following driver-specific methods are used with scrollable cursors. -- ora_scroll_position +- ora\_scroll\_position - $position = $sth->ora_scroll_position(); + $position = $sth->ora_scroll_position(); This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. -- ora_fetch_scroll +- ora\_fetch\_scroll - $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); -Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset +Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch\_offset value which will then determine the row that will be fetched. It returns the row as a list containing the field values. Null fields are returned as _undef_ values in the list. The valid orientation constant and fetch offset values combination are detailed below - OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. - OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value - is ignored. - OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. - OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. - OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset - value is ignored. - - OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. - - OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. - OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. - - OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the - fetch offset value. - - OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. - OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. - -The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. - - OCI_FETCH_CURRENT, has no effect on the current_positon attribute. - OCI_FETCH_NEXT, increments current_positon attribute by 1 - OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon - attribute, it is equivalent to a OCI_FETCH_CURRENT - OCI_FETCH_FIRST, sets the current_positon attribute to 1. - OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the - record set. - OCI_FETCH_PRIOR, decrements current_positon attribute by 1. - OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon - attribute, it is equivalent to a OCI_FETCH_CURRENT. - - OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. - OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change - current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in - the record set, does not change current_positon attribute, it is - equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + - fetch offset value). - OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, - does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records - in the record set, does not change fetch offset value so it is equivalent - to a OCI_FETCH_CURRENT. - -The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. - - OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. - OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. - OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon - attribute to the total number of rows in the record set. - OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. - OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. - - OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a - OCI_FETCH_CURRENT. - OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of - records in the record set is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent - to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number - of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + +The effect that a ora\_fetch\_scroll method call has on the current\_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + +The effects of the differing orientation constants on the first fetch (current\_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. ## Scrollable Cursor Usage Given a simple code like this: - use DBI; - use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); - my $dbh = DBI->connect($dsn, $dbuser, ''); - my $SQL = "select id, - first_name, - last_name - from employee"; - my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); - $sth->execute(); - my $value; - -and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + +and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora\_fetch\_scroll method; - Fetching the Last Row - $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +The current\_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, if the record set is large this could take some time. - Fetching the Current Row - $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will still be 20 after this snippet. +The current\_positon attribute will still be 20 after this snippet. - Fetching the First Row - $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 1 after this snippet. +The current\_positon attribute will be 1 after this snippet. - Fetching the Next Row - for(my $i=0;$i<=3;$i++){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 5 after this snippet. +The current\_positon attribute will be 5 after this snippet. - Fetching the Prior Row - for(my $i=0;$i<=3;$i++){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 1 after this snippet. +The current\_positon attribute will be 1 after this snippet. - Fetching the 10th Row - $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 10 after this snippet. +The current\_positon attribute will be 10 after this snippet. - Fetching the 10th to 14th Row - for(my $i=10;$i<15;$i++){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 14 after this snippet. +The current\_positon attribute will be 14 after this snippet. - Fetching the 14th to 10th Row - for(my $i=14;$i>9;$i--){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 10 after this snippet. +The current\_positon attribute will be 10 after this snippet. - Fetching the 5th Row From the Present Position. - $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 15 after this snippet. +The current\_positon attribute will be 15 after this snippet. - Fetching the 9th Row Prior From the Present Position - $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 6 after this snippet. +The current\_positon attribute will be 6 after this snippet. - Use Finish - $sth->finish(); + $sth->finish(); When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. @@ -2505,16 +2494,16 @@ functionality than CLOB or BLOB fields. DBD::Oracle now offers three interfaces to LOB and LONG data, -- [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) +- ["Data Interface for Persistent LOBs"](#Data Interface for Persistent LOBs) With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. -- [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) +- ["Data Interface for LOB Locators"](#Data Interface for LOB Locators) With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. -- [LOB Locator Method Interface](#pod_LOB Locator Method Interface) +- ["LOB Locator Method Interface"](#LOB Locator Method Interface) This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. @@ -2528,15 +2517,15 @@ One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB colum The table cell is created, but the cell holds no locator or value. If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a - DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr error when working with a LOB. -You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; +You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY\_BLOB or EMPTY\_CLOB as in this example; - UPDATE lob_example - SET bindata=EMPTY_BLOB() - WHERE bindata IS NULL. + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. - Empty @@ -2563,64 +2552,64 @@ an 'ORA-01062: unable to allocate memory for define buffer' error. One solution For example give this table; - CREATE TABLE test_long ( - id NUMBER, + CREATE TABLE test_long ( + id NUMBER, long1 long) this code; - $dbh->{LongReadLen} = 2*1024*1024; #2 meg - $SQL='select p_id,long1 from test_long'; - $sth=$dbh->prepare($SQL); - $sth->execute(); - while (my ( $p_id,$long )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "long=".$long."\n"; - } + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; - $dbh->{LongTruncOk}=1; + $dbh->{LongTruncOk}=1; before the execute will return all the long1 fields but they will be truncated at 2MBs. -### Using ora_ncs_buff_mtpl +### Using ora\_ncs\_buff\_mtpl When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. -Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. +Thus if you set your LongReadLen buffer to 10\_000\_000 you will get up to 10\_000\_000 char. However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer -value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes -but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes +value is set to 4 \* LONG\_READ\_LEN which was very wasteful as you might only be asking for 10\_000\_000 bytes +but you were actually using 40\_000\_000 bytes of buffer under the hood. You would still get 10\_000\_000 bytes (maybe less characters though) but you are using allot more memory that you need. -You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can -also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. +You can now customize the size of the buffer by setting the 'ora\_ncs\_buff\_mtpl' either on the connection or statement handle. You can +also set this as 'ORA\_DBD\_NCS\_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the -ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. +ora\_ncs\_buff\_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; - ORA-03127: no new operations allowed until the active operation ends + ORA-03127: no new operations allowed until the active operation ends This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) -If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. +If you get this, simply increment the ora\_ncs\_buff\_mtpl by one until it goes away. This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. -You can tune this value by setting ora_oci_success_warn which will display the following +You can tune this value by setting ora\_oci\_success\_warn which will display the following - OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen - 20(characters), BufLen 80(characters), Got 28(characters) + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) -In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. +In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora\_ncs\_buff\_mtpl=>2 (20\*2=40) thus saving 40bytes of memory. ### Simple Fetch for CLOBs and BLOBs -To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well +To use this interface for CLOBs and LOBs datatypes set the 'ora\_pers\_lob' attribute of the statement handle to '1' with the prepare method, as well set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. @@ -2632,155 +2621,155 @@ It seems with BLOBs you are not limited by the 64k. For example give this table; - CREATE TABLE test_lob (id NUMBER, - clob1 CLOB, - clob2 CLOB, - blob1 BLOB, - blob2 BLOB) + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) this code; - $dbh->{LongReadLen} = 2*1024*1024; #2 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; - $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; - $dbh->{LongTruncOk}=1; + $dbh->{LongTruncOk}=1; before the execute will return all the lobs but they will be truncated at 2MBs. ### Piecewise Fetch with Callback With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. -To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +To use this interface set the 'ora\_clbk\_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora\_piece\_size' to the size of the piece that you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected -size of the LOB. Like the [Simple Fetch for LONGs and LONG RAWs](#pod_Simple Fetch for LONGs and LONG RAWs) and [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB -or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on -the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is +size of the LOB. Like the ["Simple Fetch for LONGs and LONG RAWs"](#Simple Fetch for LONGs and LONG RAWs) and ["Simple Fetch for CLOBs and BLOBs"](#Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora\_piece\_size' seems to be constrained by the same memory limit as found on +the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora\_piece\_size' to a smaller value. The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. Using the table from the last example this code; - $dbh->{LongReadLen} = 20*1024*1024; #20 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; - $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } - -Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora\_piece\_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4\*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. Using the table from the first example (LONG) this code; - $dbh->{LongReadLen} = 20*1024*1024; #2 meg - $SQL='select p_id,long1 from test_long'; - $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$long )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "long=".$long."\n"; - } + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } -Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora\_piece\_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4\*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. #### Piecewise Fetch with Polling -With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' -attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora\_piece\_lob' +attribute of the statement handle to '1' with the prepare method. Next set the 'ora\_piece\_size' to the size of the piece that you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected -size of the LOB. Like the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB -or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on -the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback). +size of the LOB. Like the ["Piecewise Fetch with Callback"](#Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora\_piece\_size' seems to be constrained by the same memory limit as found on +the ["Piecewise Fetch with Callback"](#Piecewise Fetch with Callback). Using the table from the example above this code; - $dbh->{LongReadLen} = 20*1024*1024; #20 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; - $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } - -Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora\_piece\_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4\*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. Finally with this code; - $dbh->{LongReadLen} = 20*1024*1024; #2 meg - $SQL='select p_id,long1 from test_long'; - $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$long )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "long=".$long."\n"; - } + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } -Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora\_piece\_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4\*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. ### Binding for Updates and Inserts for CLOBs and BLOBs To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method -'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; - - my $in_clob = "\n"; - $in_clob .= " $_\n" for 1 .. 10_000; - $in_clob .= "\n"; - my $in_blob ="0101" for 1 .. 10_000; - - $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; - $sth=$dbh->prepare($SQL ); - $sth->bind_param(1,3); - $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); - $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); - $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); - $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); - $sth->execute(); +'ora\_type' attribute to 'SQLT\_CHR' in the case of CLOBs and NCLOBs or 'SQLT\_BIN' in the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. ### Support for Remote LOBs; -Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; +Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob\_test' that has a 'LINK' defined like this; - CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; -to a remote database called 'test_lobs', the following code will work; +to a remote database called 'test\_lobs', the following code will work; - $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); - $dbh->{LongReadLen} = 2*1024*1024; #2 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; - $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } Below are the limitations of Remote LOBs; @@ -2788,25 +2777,25 @@ Below are the limitations of Remote LOBs; so the following returns an error: - SELECT t1.lobcol, - a2.lobcol - FROM t1, - t2.lobcol@dbs2 a2 W - WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); as does: - SELECT t1.lobcol - FROM t1@dbs1 - UNION ALL - SELECT t2.lobcol - FROM t2@dbs2; + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; - DDL commands are not supported; so the following returns an error: - CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; - Only binds and defines for data going into remote persistent LOBs are supported. @@ -2814,19 +2803,19 @@ so that parameter passing in PL/SQL where CHAR data is bound or defined for remo These statements all produce errors: - SELECT foo() FROM table1@dbs2; + SELECT foo() FROM table1@dbs2; - SELECT foo()@dbs INTO char_val FROM DUAL; + SELECT foo()@dbs INTO char_val FROM DUAL; - SELECT XMLType().getclobval FROM table1@dbs2; + SELECT XMLType().getclobval FROM table1@dbs2; - If the remote object is a view such as - CREATE VIEW v AS SELECT foo() FROM ... + CREATE VIEW v AS SELECT foo() FROM ... the following would not work: - SELECT * FROM v@dbs2; + SELECT * FROM v@dbs2; - Limited PL/SQL parameter passing @@ -2837,7 +2826,7 @@ and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. so the following returns an error: - SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test ## Locator Data Interface @@ -2858,11 +2847,11 @@ time being, only single-row LOB updates are supported. To insert or update a large LOB using a placeholder, DBD::Oracle has to know in advance that it is a LOB type. So you need to say: - $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); -The ORA_CLOB and ORA_BLOB constants can be imported using +The ORA\_CLOB and ORA\_BLOB constants can be imported using - use DBD::Oracle qw(:ora_types); + use DBD::Oracle qw(:ora_types); or use the corresponding integer values (112 and 113). @@ -2872,23 +2861,23 @@ In all cases where it can possibly work it out for itself, it does, however, if there are multiple LOB fields of the same type in the table then you need to tell it which field each LOB param relates to: - $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); There are some limitations inherent in the way DBD::Oracle makes typical LOB operations simple by hiding the LOB Locator processing: - - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) - - To INSERT a LOB, you need UPDATE privilege. + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. The alternative is to disable the automatic LOB Locator processing. -If [ora_auto_lob](#pod_ora_auto_lob) is 0 in prepare(), you can fetch the LOB Locators and -do all the work yourself using the ora_lob_*() methods. -See the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) section below. +If ["ora\_auto\_lob"](#ora\_auto\_lob) is 0 in prepare(), you can fetch the LOB Locators and +do all the work yourself using the ora\_lob\_\*() methods. +See the ["Data Interface for LOB Locators"](#Data Interface for LOB Locators) section below. ### LOB support in PL/SQL LOB Locators can be passed to PL/SQL calls by binding them to placeholders -with the proper `ora_type`. If [ora_auto_lob](#pod_ora_auto_lob) is true, output LOB +with the proper `ora_type`. If ["ora\_auto\_lob"](#ora\_auto\_lob) is true, output LOB parameters will be automatically returned as strings. If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), @@ -2896,8 +2885,8 @@ strings can be bound to input LOB placeholders and will be automatically converted to LOBs. Example: - # Build a large XML document, bind it as a CLOB, - # extract elements through PL/SQL and return as a CLOB + \# Build a large XML document, bind it as a CLOB, + \# extract elements through PL/SQL and return as a CLOB # $dbh is a connected database handle # output will be large @@ -2931,7 +2920,7 @@ Example: If you ever get an - ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. @@ -2957,12 +2946,12 @@ the Callback or Polling piecewise fetches to get all of the data. Not all of the Persistent interface has been implemented yet, the following are not supported; - 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. - 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. -Most of the time you should just use the [Locator Data Interface](#pod_Locator Data Interface) as this is in one that has the best combination of speed and size. +Most of the time you should just use the ["Locator Data Interface"](#Locator Data Interface) as this is in one that has the best combination of speed and size. -All this being said if you are doing some critical programming I would use the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) as this gives you very +All this being said if you are doing some critical programming I would use the ["Data Interface for LOB Locators"](#Data Interface for LOB Locators) as this gives you very fine grain control of your LOBs, of course the code for this will be somewhat more involved. ## Data Interface for LOB Locators @@ -2980,57 +2969,57 @@ Note that LOB locators are only valid while the statement handle that created them is valid. When all references to the original statement handle are lost, the handle is destroyed and the locators are freed. -- ora_lob_read +- ora\_lob\_read - $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); Read a portion of the LOB. $offset starts at 1. Uses the Oracle OCILobRead function. NOTE: DBD::Oracle post 1.46 will return undef for any read lob if the -length specified in the ora_lob_read is 0. See RT 55028. This avoids -the potential problem with empty lobs (created with empty_clob) which -return a length of 0 from ora_lob_length and prior to 1.46 a call to -ora_lob_read with a 0 length would segfault. +length specified in the ora\_lob\_read is 0. See RT 55028. This avoids +the potential problem with empty lobs (created with empty\_clob) which +return a length of 0 from ora\_lob\_length and prior to 1.46 a call to +ora\_lob\_read with a 0 length would segfault. -- ora_lob_write +- ora\_lob\_write - $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); Write/overwrite a portion of the LOB. $offset starts at 1. Uses the Oracle OCILobWrite function. -- ora_lob_append +- ora\_lob\_append - $rc = $dbh->ora_lob_append($lob_locator, $data); + $rc = $dbh->ora_lob_append($lob_locator, $data); Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. -- ora_lob_trim +- ora\_lob\_trim - $rc = $dbh->ora_lob_trim($lob_locator, $length); + $rc = $dbh->ora_lob_trim($lob_locator, $length); Trims the length of the LOB to $length. Uses the Oracle OCILobTrim function. -- ora_lob_length +- ora\_lob\_length - $length = $dbh->ora_lob_length($lob_locator); + $length = $dbh->ora_lob_length($lob_locator); Returns the length of the LOB. Uses the Oracle OCILobGetLength function. -- ora_lob_is_init +- ora\_lob\_is\_init - $is_init = $dbh->ora_lob_is_init($lob_locator); + $is_init = $dbh->ora_lob_is_init($lob_locator); Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' if there is an error. Uses the Oracle OCILobLocatorIsInit function. -- ora_lob_chunk_size +- ora\_lob\_chunk\_size - $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); Returns the chunk size of the LOB. Uses the Oracle OCILobGetChunkSize function. @@ -3053,16 +3042,16 @@ The following examples assume a table containing two large object columns, one binary and one character, with a primary key column, defined as follows: - CREATE TABLE lob_example ( - lob_id INTEGER PRIMARY KEY, - bindata BLOB, - chardata CLOB - ) + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) It also assumes a sequence for use in generating unique -lob_id field values, defined as follows: +lob\_id field values, defined as follows: - CREATE SEQUENCE lob_example_seq + CREATE SEQUENCE lob_example_seq ### Example: Inserting a new row with large data @@ -3085,64 +3074,64 @@ statement containing the clause 'FOR UPDATE' (LOB locators are only valid within the transaction that fetched them, so can't be used effectively if AutoCommit is enabled). - my $lob_id = $dbh->selectrow_array( <<" SQL" ); - SELECT lob_example_seq.nextval FROM DUAL - SQL - - my $sth = $dbh->prepare( <<" SQL" ); - INSERT INTO lob_example - ( lob_id, bindata, chardata ) - VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) - SQL - $sth->execute( $lob_id ); - - $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT bindata, chardata - FROM lob_example - WHERE lob_id = ? - FOR UPDATE - SQL - $sth->execute( $lob_id ); - my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); - $sth->finish(); - - open BIN_FH, "/binary/data/source" or die; - open CHAR_FH, "/character/data/source" or die; - my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); - - # BEGIN WRITING BIN_DATA COLUMN - my $offset = 1; # Offsets start at 1, not 0 - my $length = 0; - my $buffer = ''; - while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { - $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); - $offset += $length; - } - - # BEGIN WRITING CHAR_DATA COLUMN - $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); - $offset = 1; # Offsets start at 1, not 0 - $length = 0; - $buffer = ''; - while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { - $dbh->ora_lob_write( $char_locator, $offset, $buffer ); - $offset += $length; - } - -In this example we demonstrate the use of ora_lob_write() -interactively to append data to the columns 'bin_data' and -'char_data'. Had we used ora_lob_append(), we could have + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + +In this example we demonstrate the use of ora\_lob\_write() +interactively to append data to the columns 'bin\_data' and +'char\_data'. Had we used ora\_lob\_append(), we could have saved ourselves the trouble of keeping track of the offset into the lobs. The snippet of code beneath the comment -'BEGIN WRITING BIN_DATA COLUMN' could look as follows: +'BEGIN WRITING BIN\_DATA COLUMN' could look as follows: - my $buffer = ''; - while ( read( BIN_FH, $buffer, $chunk_size ) ) { - $dbh->ora_lob_append( $bin_locator, $buffer ); - } + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } The scalar variables $offset and $length are no longer -needed, because ora_lob_append() keeps track of the offset +needed, because ora\_lob\_append() keeps track of the offset for us. ### Example: Updating an existing row with large data @@ -3153,23 +3142,23 @@ data before and after the section overwritten remains unchanged. Hence, this technique could be used for updating fixed length subfields embedded in a binary field. - my $lob_id = 5; # Arbitrary row identifier, for example + my $lob_id = 5; # Arbitrary row identifier, for example - $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT bindata - FROM lob_example - WHERE lob_id = ? - FOR UPDATE - SQL - $sth->execute( $lob_id ); - my ( $bin_locator ) = $sth->fetchrow_array(); + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); - my $offset = 100234; - my $data = "This string will overwrite a portion of the blob"; - $dbh->ora_lob_write( $bin_locator, $offset, $data ); + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); -After running this code, the row where lob_id = 5 will -contain, starting at position 100234 in the bin_data column, +After running this code, the row where lob\_id = 5 will +contain, starting at position 100234 in the bin\_data column, the string "This string will overwrite a portion of the blob". ### Example: Streaming character data from the database @@ -3179,24 +3168,24 @@ data from the database to a file handle, in this case STDOUT. This allows more data to be read in and written out than could be stored in memory at a given time. - my $lob_id = 17; # Arbitrary row identifier, for example - - $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT chardata - FROM lob_example - WHERE lob_id = ? - SQL - $sth->execute( $lob_id ); - my ( $char_locator ) = $sth->fetchrow_array(); - - my $chunk_size = 1034; # Arbitrary chunk size, for example - my $offset = 1; # Offsets start at 1, not 0 - while(1) { - my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); - last unless length $data; - print STDOUT $data; - $offset += $chunk_size; - } + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } Notice that the select statement does not contain the phrase "FOR UPDATE". Because we are only reading from the LOB @@ -3204,13 +3193,13 @@ Locator returned, and not modifying the LOB it refers to, the select statement does not require the "FOR UPDATE" clause. -A word of caution when using the data returned from an ora_lob_read in a conditional statement. +A word of caution when using the data returned from an ora\_lob\_read in a conditional statement. for example if the code below; - while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { - print STDOUT $data; - $offset += $chunk_size; - } + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte @@ -3225,21 +3214,21 @@ its previous length. After acquiring a LOB Locator for the column, we query its length, then we trim the length by half. Because we modify -the large objects with the call to ora_lob_trim(), we must +the large objects with the call to ora\_lob\_trim(), we must select the LOB locators 'FOR UPDATE'. - my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT bindata - FROM lob_example - FOR UPATE - SQL - $sth->execute(); - while( my ( $bin_locator ) = $sth->fetchrow_array() ) { - my $binlength = $dbh->ora_lob_length( $bin_locator ); - if( $binlength > 0 ) { - $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); - } - } + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } # SPACES AND PADDING @@ -3255,10 +3244,10 @@ Comparison Semantics in Oracle's SQL Reference or Server SQL Reference for more details. To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, -either change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or the placeholder -type for a particular call to L or L -with [ora_type](#pod_ora_type) or `TYPE`. -Using [ORA_CHAR](http://search.cpan.org/perldoc?ORA_CHAR) with [ora_type](http://search.cpan.org/perldoc?ora_type) or `SQL_CHAR` with `TYPE` +either change the default placeholder type with ["ora\_ph\_type"](#ora\_ph\_type) or the placeholder +type for a particular call to ["bind" in DBI](http://search.cpan.org/perldoc?DBI#bind) or ["bind\_param\_inout" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param\_inout) +with ["ora\_type"](#ora\_type) or `TYPE`. +Using [ORA\_CHAR](http://search.cpan.org/perldoc?ORA\_CHAR) with [ora\_type](http://search.cpan.org/perldoc?ora\_type) or `SQL_CHAR` with `TYPE` allows the placeholder to be used with Padded Comparison Semantics if the value it is being compared to is a CHAR, NCHAR, or literal. @@ -3271,10 +3260,10 @@ Oracle Clients that use OCI 9.2 do not strip trailing spaces. ## Padded Char Fields Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. -As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will -have to change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or placeholder -type for a particular call with L or L -with [ORA_CHAR](#pod_ORA_CHAR). +As the default placeholder type value in DBD::Oracle is ORA\_VARCHAR2 to access this behaviour you will +have to change the default placeholder type with ["ora\_ph\_type"](#ora\_ph\_type) or placeholder +type for a particular call with ["bind" in DBI](http://search.cpan.org/perldoc?DBI#bind) or ["bind\_param\_inout" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param\_inout) +with ["ORA\_CHAR"](#ORA\_CHAR). # UNICODE @@ -3296,8 +3285,8 @@ did not mature until version 5.8 and later. If you plan to use Unicode you are _strongly_ urged to use Perl 5.8.2 or later and to _carefully_ read the Perl documentation on Unicode: - perldoc perluniintro # in Perl 5.8 or later - perldoc perlunicode + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode And then read it again. @@ -3309,47 +3298,47 @@ which corresponds to the Oracle character set called AL32UTF8. Oracle supports many characters sets, including several different forms of Unicode. These include: - AL16UTF16 => valid for NCHAR columns (CSID=2000) - UTF8 => valid for NCHAR columns (CSID=871), deprecated - AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) When you create an Oracle database, you must specify the DATABASE character set (used for DDL, DML and CHAR datatypes) and the NATIONAL character set (used for NCHAR and NCLOB types). The character sets used in your database can be found using: - $hash_ref = $dbh->ora_nls_parameters() - $database_charset = $hash_ref->{NLS_CHARACTERSET}; - $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; The Oracle 9.2 and later default for the national character set is AL16UTF16. The default for the database character set is often US7ASCII. Although many experienced DBAs will consider an 8bit character set like WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle -other than US7ASCII, requires that the NLS_LANG environment variable be set. -See the L<"Oracle UTF8 is not UTF-8"> section below. +other than US7ASCII, requires that the NLS\_LANG environment variable be set. +See the ["Oracle UTF8 is not UTF-8"](#Oracle UTF8 is not UTF-8) section below. You are strongly urged to read the Oracle Internationalization documentation specifically with respect the choices and trade offs for creating a databases for use with international character sets. -Oracle uses the NLS_LANG environment variable to indicate what +Oracle uses the NLS\_LANG environment variable to indicate what character set is being used on the client. When fetching data Oracle will convert from whatever the database character set is to the client -character set specified by NLS_LANG. Similarly, when sending data to +character set specified by NLS\_LANG. Similarly, when sending data to the database Oracle will convert from the character set specified by -NLS_LANG to the database character set. +NLS\_LANG to the database character set. -The NLS_NCHAR environment variable can be used to define a different +The NLS\_NCHAR environment variable can be used to define a different character set for 'national' (NCHAR) character types. -Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. +Both UTF8 and AL32UTF8 can be used in NLS\_LANG and NLS\_NCHAR. For example: - NLS_LANG=AMERICAN_AMERICA.UTF8 - NLS_LANG=AMERICAN_AMERICA.AL32UTF8 - NLS_NCHAR=UTF8 - NLS_NCHAR=AL32UTF8 + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 ## Oracle UTF8 is not UTF-8 @@ -3364,17 +3353,17 @@ conform to the UTF-8 standard in its handling of surrogate characters. Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". Here are a couple of extracts from [http://www.unicode.org/reports/tr26/](http://www.unicode.org/reports/tr26/): - CESU-8 is useful in 8-bit processing environments where binary - collation with UTF-16 is required. It is designed and recommended - for use only within products requiring this UTF-16 binary collation - equivalence. It is not intended nor recommended for open interchange. + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. - As a very small percentage of characters in a typical data stream - are expected to be supplementary characters, there is a strong - possibility that CESU-8 data may be misinterpreted as UTF-8. - Therefore, all use of CESU-8 outside closed implementations is - strongly discouraged, such as the emittance of CESU-8 in output - files, markup language or other open transmission forms. + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. Oracle uses this internally because it collates (sorts) in the same order as UTF16, which is the basis of Oracle's internal collation definitions. @@ -3403,59 +3392,59 @@ Any data returned from Oracle to DBD::Oracle in the AL32UTF8 character set will be marked as UTF-8 to ensure correct handling by Perl. For Oracle to return data in the AL32UTF8 character set the -NLS_LANG or NLS_NCHAR environment variable _must_ be set as described +NLS\_LANG or NLS\_NCHAR environment variable _must_ be set as described in the previous section. When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle -will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR -is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. +will set the Perl UTF-8 flag on the returned data if either NLS\_NCHAR +is AL32UTF8, or NLS\_NCHAR is not set and NLS\_LANG is AL32UTF8. When fetching other character data from Oracle, DBD::Oracle -will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. +will set the Perl UTF-8 flag on the returned data if NLS\_LANG is AL32UTF8. __Sending Data using Placeholders__ Data bound to a placeholder is assumed to be in the default client -character set (specified by NLS_LANG) except for a few special +character set (specified by NLS\_LANG) except for a few special cases. These are listed here with the highest precedence first: -If the `ora_csid` attribute is given to bind_param() then that +If the `ora_csid` attribute is given to bind\_param() then that is passed to Oracle and takes precedence. If the value is a Perl Unicode string (UTF-8) then DBD::Oracle ensures that Oracle uses the Unicode character set, regardless of -the NLS_LANG and NLS_NCHAR settings. +the NLS\_LANG and NLS\_NCHAR settings. -If the placeholder is for inserting an NCLOB then the client NLS_NCHAR +If the placeholder is for inserting an NCLOB then the client NLS\_NCHAR character set is used. (That's useful but inconsistent with the other behaviour so may change. Best to be explicit by using the `ora_csform` attribute.) -If the `ora_csform` attribute is given to bind_param() then that +If the `ora_csform` attribute is given to bind\_param() then that determines if the value should be assumed to be in the default -(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. +(NLS\_LANG) or NCHAR (NLS\_NCHAR) client character set. - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); - ... - $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); or - $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders -Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to +Binding with bind\_param\_array and execute\_array is also UTF-8 compatible in the same way. If you attempt to insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert will still happen but a error code of 0 will be returned with the following warning; - DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. - The Query charset id=1, name=US7ASCII + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII The warning will report the parameter number and the NCHAR setting that the query is running. __Sending Data using SQL__ Oracle assumes the SQL statement is in the default client character -set (as specified by NLS_LANG). So Unicode strings containing +set (as specified by NLS\_LANG). So Unicode strings containing non-ASCII characters should not be used unless the default client character set is AL32UTF8. @@ -3477,114 +3466,114 @@ You can either get the values as an array of scalars or they can be returned int Array example, given this type and table; - CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); - CREATE TABLE "CONTACT" - ( "COMPANYNAME" VARCHAR2(40), - "ADDRESS" VARCHAR2(100), - "PHONE_NUMBERS" "PHONE_NUMBERS" - ) + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) The code to access all the data in the table could be something like this; - my $sth = $dbh->prepare('SELECT * FROM CONTACT'); - $sth->execute; - while ( my ($company, $address, $phone) = $sth->fetchrow()) { - print "Company: ".$company."\n"; - print "Address: ".$address."\n"; - print "Phone #: "; + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; - foreach my $items (@$phone){ - print $items.", "; - } - print "\n"; - } + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } -Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. +Note that values in PHONE\_NUMBERS are returned as an array reference '@$phone'. As stated before DBD::Oracle will automatically drill into the embedded object and extract all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an SQL TABLE; - CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; - CREATE OR REPLACE TYPE STUDENT AS OBJECT( - NAME VARCHAR2(60), - SOME_GRADES GRADELIST); + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); - CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; - CREATE TABLE GROUPS( - GRP_ID NUMBER(4), - GRP_NAME VARCHAR2(10), - STUDENTS STUDENTS_T) - NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB - (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); The following code will access all of the embedded data; - $SQL='select grp_id,grp_name,students as my_students_test from groups'; - $sth=$dbh->prepare($SQL); - $sth->execute(); - while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ - print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; - foreach my $student (@$students){ - print "Name:".$student->[0]."\n"; - print "Marks:"; - foreach my $grades (@$student->[1]){ - foreach my $marks (@$grades){ - print $marks.","; - } - } - print "\n"; - } - print "\n"; - } + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } Object example, given this object and table; - CREATE OR REPLACE TYPE Person AS OBJECT ( - name VARCHAR2(20), - age INTEGER) - ) NOT FINAL; + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; - CREATE TYPE Employee UNDER Person ( - salary NUMERIC(8,2) - ); + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); - CREATE TABLE people (id INTEGER, obj Person); + CREATE TABLE people (id INTEGER, obj Person); - INSERT INTO people VALUES (1, Person('Black', 25)); - INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); The following code will access the data; - $dbh{'ora_objects'} =>1; + $dbh{'ora_objects'} =>1; - $sth = $dbh->prepare("select * from people order by id"); - $sth->execute(); + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); - # object are fetched as instance of DBD::Oracle::Object - my ($id1, $obj1) = $sth->fetchrow(); - my ($id2, $obj2) = $sth->fetchrow(); + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); - # get full type-name of object - print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed - print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed - # get attribute NAME from object - print $obj1->attr('NAME')."3\n"; # 'Black' is printed - print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed - # get all atributes as hash reference - my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} - my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, - # 'SALARY' => 5000 } + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } - # get all attributes (names and values) as array - my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) - my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, - # 'SALARY', 5000 ) + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables nested to 10 levels. @@ -3608,7 +3597,7 @@ control the default parsing of strings into DATE values. An error will be generated if the contents of the string don't match the NLS format. If you're dealing in dates which don't match the default NLS format then you can either change the default NLS format or, more -commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") +commonly, use TO\_CHAR(field, "format") and TO\_DATE(?, "format") to explicitly specify formats for converting to and from strings. A slightly more subtle problem can occur with NUMBER types. The @@ -3617,11 +3606,11 @@ to separate thousands and a comma ("`,`") as the decimal point. Perl will generate warnings and use incorrect values when numbers, returned and formatted as strings in this way by Oracle, are used in a numeric context. You could explicitly convert each numeric -value using the TO_CHAR(...) function but that gets tedious very +value using the TO\_CHAR(...) function but that gets tedious very quickly. The best fix is to change the NLS settings. That can be done for an individual connection by doing: - $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); There are some types, like BOOLEAN, that Oracle does not automatically convert to or from strings (pity). These need to be converted @@ -3629,70 +3618,70 @@ explicitly using SQL or PL/SQL functions. Examples: - # DATE values - my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) - SQL_END - $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); - - # BOOLEAN values - my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); - $sth2->bind_param( ":i1", $i1 ); - $sth2->bind_param_inout( ":o0", \$o0, 32 ); - $sth2->bind_param_inout( ":o1", \$o1, 32 ); - $sth2->execute(); - foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { - $_ = "(undef)" if ! defined $_; - } - print "$i0 to $o0, $i1 to $o1\n"; - # Result is : "'' to '(undef)', 'Something else' to '1'" - -## Support for Insert of XMLType (ORA_XMLTYPE) + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + +## Support for Insert of XMLType (ORA\_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special -requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For +requirement is the use of bind\_param() with an attribute hash parameter that specifies ora\_type as ORA\_XMLTYPE. For example with a table like this; - create table books (book_id number, book_xml XMLType); + create table books (book_id number, book_xml XMLType); one can insert data using this code - $SQL='insert into books values (1,:p_xml)'; - $xml= ' + $SQL='insert into books values (1,:p_xml)'; + $xml= ' Programming the Perl DBI The Cheetah Book @@ -3704,9 +3693,9 @@ one can insert data using this code ... '; - my $sth =$dbh-> prepare($SQL); - $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); - $sth-> execute(); + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. @@ -3717,21 +3706,21 @@ Cursors can be returned from PL/SQL blocks, either from stored functions (or procedures with OUT parameters) or from direct `OPEN` statements, as shown below: - use DBI; - use DBD::Oracle qw(:ora_types); - my $dbh = DBI->connect(...); - my $sth1 = $dbh->prepare(q{ - BEGIN OPEN :cursor FOR - SELECT table_name, tablespace_name - FROM user_tables WHERE tablespace_name = :space; - END; - }); - $sth1->bind_param(":space", "USERS"); - my $sth2; - $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); - $sth1->execute; - # $sth2 is now a valid DBI statement handle for the cursor - while ( my @row = $sth2->fetchrow_array ) { ... } + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } The only special requirement is the use of `bind_param_inout()` with an attribute hash parameter that specifies `ora_type` as `ORA_RSET`. @@ -3741,34 +3730,34 @@ arguments in call to ...". Here's an alternative form using a function that returns a cursor. This example uses the pre-defined weak (or generic) REF CURSOR type -SYS_REFCURSOR. This is an Oracle 9 feature. +SYS\_REFCURSOR. This is an Oracle 9 feature. - # Create the function that returns a cursor - $dbh->do(q{ - CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR - AS l_cursor SYS_REFCURSOR; - BEGIN - OPEN l_cursor FOR select ename, empno from emp - ORDER BY ename; - RETURN l_cursor; - END; - }); + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); - # Use the function that returns a cursor - my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); - my $sth2; - $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); - $sth1->execute; - # $sth2 is now a valid DBI statement handle for the cursor - while ( my @row = $sth2->fetchrow_array ) { ... } + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } A cursor obtained from PL/SQL as above may be passed back to PL/SQL by binding for input, as shown in this example, which explicitly closes a cursor: - my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); - $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); - $sth3->execute; + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; It is not normally necessary to close a cursor explicitly in this way. Oracle will close the cursor automatically @@ -3859,13 +3848,13 @@ is 0, which disables pre-fetching for queries involving nested cursors. Most of these PL/SQL examples come from: Eric Bartley . - /* - * PL/SQL to create package with stored procedures invoked by - * Perl examples. Execute using sqlplus. - * - * Use of "... OR REPLACE" prevents failure in the event that the - * package already exists. - */ + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ CREATE OR REPLACE PACKAGE plsql_example IS @@ -3883,8 +3872,8 @@ Most of these PL/SQL examples come from: Eric Bartley . FUNCTION func_np RETURN VARCHAR2; - END plsql_example; - / + END plsql_example; + / CREATE OR REPLACE PACKAGE BODY plsql_example IS @@ -3921,126 +3910,126 @@ Most of these PL/SQL examples come from: Eric Bartley . RETURN ret_val; END; - END plsql_example; - / - /* End PL/SQL for example package creation. */ + END plsql_example; + / + /* End PL/SQL for example package creation. */ - use DBI; + use DBI; - my($db, $csr, $ret_val); + my($db, $csr, $ret_val); - $db = DBI->connect('dbi:Oracle:database','user','password') - or die "Unable to connect: $DBI::errstr"; + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; - # So we don't have to check every DBI call we set RaiseError. - # See the DBI docs now if you're not familiar with RaiseError. - $db->{RaiseError} = 1; + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; - # Example 1 Eric Bartley - # - # Calling a PLSQL procedure that takes no parameters. This shows you the - # basic's of what you need to execute a PLSQL procedure. Just wrap your - # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. - # - # p.s. If you've used SQL*Plus's exec command all it does is wrap the - # command in a BEGIN END; block for you. + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. - $csr = $db->prepare(q{ - BEGIN - PLSQL_EXAMPLE.PROC_NP; - END; - }); - $csr->execute; + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; - # Example 2 Eric Bartley - # - # Now we call a procedure that has 1 IN parameter. Here we use bind_param - # to bind out parameter to the prepared statement just like you might - # do for an INSERT, UPDATE, DELETE, or SELECT statement. - # - # I could have used positional placeholders (e.g. :1, :2, etc.) or - # ODBC style placeholders (e.g. ?), but I prefer Oracle's named - # placeholders (but few DBI drivers support them so they're not portable). + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). - my $err_code = -20001; + my $err_code = -20001; - $csr = $db->prepare(q{ - BEGIN - PLSQL_EXAMPLE.PROC_IN(:err_code); - END; - }); + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); - $csr->bind_param(":err_code", $err_code); + $csr->bind_param(":err_code", $err_code); - # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. - # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. - eval { - $csr->execute; - }; - print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; - # Example 3 Eric Bartley - # - # Building on the last example, I've added 1 IN OUT parameter. We still - # use a placeholders in the call to prepare, the difference is that - # we now call bind_param_inout to bind the value to the place holder. - # - # Note that the third parameter to bind_param_inout is the maximum size - # of the variable. You normally make this slightly larger than necessary. - # But note that the Perl variable will have that much memory assigned to - # it even if the actual value returned is shorter. + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. - my $test_num = 5; - my $is_odd; + my $test_num = 5; + my $is_odd; - $csr = $db->prepare(q{ - BEGIN - PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); - END; - }); + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); - # The value of $test_num is _copied_ here - $csr->bind_param(":test_num", $test_num); + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); - $csr->bind_param_inout(":is_odd", \$is_odd, 1); + $csr->bind_param_inout(":is_odd", \$is_odd, 1); - # The execute will automagically update the value of $is_odd - $csr->execute; + # The execute will automagically update the value of $is_odd + $csr->execute; - print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; - # Example 4 Eric Bartley - # - # What about the return value of a PLSQL function? Well treat it the same - # as you would a call to a function from SQL*Plus. We add a placeholder - # for the return value and bind it with a call to bind_param_inout so - # we can access it's value after execute. + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. - my $whoami = ""; + my $whoami = ""; - $csr = $db->prepare(q{ - BEGIN - :whoami := PLSQL_EXAMPLE.FUNC_NP; - END; - }); + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); - $csr->bind_param_inout(":whoami", \$whoami, 20); - $csr->execute; - print "Your database user name is $whoami\n"; + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; - $db->disconnect; + $db->disconnect; You can find more examples in the t/plsql.t file in the DBD::Oracle source directory. Oracle 9.2 appears to have a bug where a variable bound -with bind_param_inout() that isn't assigned to by the executed +with bind\_param\_inout() that isn't assigned to by the executed PL/SQL block may contain garbage. See [http://www.mail-archive.com/dbi-users@perl.org/msg18835.html](http://www.mail-archive.com/dbi-users@perl.org/msg18835.html) @@ -4052,7 +4041,7 @@ DBD::Oracle will not raise an exception in some case. Specifically if you use ignored and returned as null. According to Oracle support this is part of the same mechanism where; - select (select * from dual where 0=1) from dual + select (select * from dual where 0=1) from dual returns a null value rather than an exception. @@ -4069,7 +4058,7 @@ for CVS, see [http://subversion.tigris.org/](http://subversion.tigris.org/)). To you'll need to install a Subversion client. Then, to get the source code, do: - svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk If it prompts for a username and password use your perl.org account if you have one, else just 'guest' and 'guest'. The source code will @@ -4082,12 +4071,12 @@ change log message and diff of each change checked-in to the source. After making your changes you can generate a patch file, but before you do, make sure your source is still upto date using: - svn update + svn update If you get any conflicts reported you'll need to fix them first. Then generate the patch file from within the `trunk` directory using: - svn diff > foo.patch + svn diff > foo.patch Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. @@ -4095,30 +4084,30 @@ Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. Unpack a fresh copy of the distribution: - tar xfz DBD-Oracle-1.40.tar.gz + tar xfz DBD-Oracle-1.40.tar.gz Rename the newly created top level directory: - mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo -Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you want. +Edit the contents of DBD-Oracle-1.40.your\_foo/\* till it does what you want. Test your changes and then remove all temporary files: - make test && make distclean + make test && make distclean Go back to the directory you originally unpacked the distribution: - cd .. + cd .. Unpack _another_ copy of the original distribution you started with: - tar xfz DBD-Oracle-1.40.tar.gz + tar xfz DBD-Oracle-1.40.tar.gz Then create a patch file by performing a recursive `diff` on the two top level directories: - diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch ## Speak before you patch @@ -4131,7 +4120,7 @@ you may not be aware of. ## GitHub repository A git mirror of the subversion is also available at -`https://github.com/yanick/DBD-Oracle`. +\`https://github.com/yanick/DBD-Oracle\`. # Oracle Related Links @@ -4142,25 +4131,25 @@ From version 1.25 onwards DBD::Oracle only support Oracle clients If you are still stuck with an older version of Oracle or its client you might want to look at the table below. - +---------------------+-----------------------------------------------------+ - | | Oracle Version | - +---------------------+----+-------------+---------+------+--------+--------+ - | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | - +---------------------+----+-------------+---------+------+--------+--------+ - | 0.1~16 | Y | Y | Y | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.17 | Y | Y | Y | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.18 | N | N | N | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.19 | N | N | N | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.20 | N | N | N | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.21~1.24 | N | N | N | N | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.25+ | N | N | N | N | N | Y | - +---------------------+----+-------------+---------+------+--------+--------+ + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ As there are dozens of different versions of Oracle's clients this list does not include all of them, just the major released versions of @@ -4229,7 +4218,7 @@ http://www.ixora.com.au/ - Free Oracle Tools and Links -ora_explain supplied and installed with DBD::Oracle. +ora\_explain supplied and installed with DBD::Oracle. http://www.orafaq.com/ @@ -4272,25 +4261,14 @@ redistribute it and/or modify it under the same terms as Perl 5. # AUTHORS -- * - -Tim Bunce - -- * - -John Scoles - -- * - -Yanick Champoux - -- * - -Martin J. Evans +- Tim Bunce +- John Scoles +- Yanick Champoux +- Martin J. Evans # COPYRIGHT AND LICENSE This software is copyright (c) 1994 by Tim Bunce. This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. \ No newline at end of file +the same terms as the Perl 5 programming language system itself. diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 4b76143c..6b85731f 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.49_00'; + $DBD::Oracle::VERSION = '1.50'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1146,7 +1146,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.49_00 +version 1.50 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 0f48c2a6..21539965 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.49_00'; + $DBD::Oracle::GetInfo::VERSION = '1.50'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.49_00 +version 1.50 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index ba950f5c..5f314dbd 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.49_00'; + $DBD::Oracle::Object::VERSION = '1.50'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.49_00 +version 1.50 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 87ed8785..912ce571 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index 9bcd3947..c24abdc5 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.49_00 +version 1.50 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index aae9023a..ab82dcc4 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.49_00 +version 1.50 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pm b/lib/DBD/Oracle/Troubleshooting/Hpux.pm index 32a5fc0d..7d95e299 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pm +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pm @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 44755c62..5737ebfe 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index d00358be..5aacb224 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index c5fdf7c8..ebfd936f 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.49_00 +version 1.50 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 5d48431d..0dc054c2 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.49_00 +version 1.50 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index fd2418a5..d401973a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index cde25565..3a056878 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 DBD::Oracle and Windows 64bit diff --git a/t/000-report-versions.t b/t/000-report-versions.t index 2d4a9a19..04c53948 100644 --- a/t/000-report-versions.t +++ b/t/000-report-versions.t @@ -415,6 +415,7 @@ BEGIN { Test::Pod::Coverage Test::Portability::Files Test::YAML::Meta + open ); my $Test = Test::Builder->new; @@ -437,7 +438,7 @@ BEGIN { next; } local $SIG{__WARN__} = sub { note "$module: $_[0]" }; - use_ok $module or BAIL_OUT("can't load $module"); + require_ok $module or BAIL_OUT("can't load $module"); my $version = $module->VERSION; $version = 'undefined' unless defined $version; diag(" $module version is $version"); diff --git a/t/10general.t b/t/10general.t index 1e492db0..7098ff0f 100644 --- a/t/10general.t +++ b/t/10general.t @@ -4,7 +4,6 @@ use warnings; use Test::More; use DBI; -use Oraperl; use Config; use DBD::Oracle qw(ORA_OCI); @@ -22,7 +21,7 @@ my $dbh = DBI->connect($dsn, $dbuser, '', }); if ($dbh) { - plan tests => 30; + plan tests => 28; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -114,8 +113,6 @@ ok($@ =~ /DBD::Oracle::db do failed:/, "eval error: ``$@'' expected 'do faile #print "''$warn''"; ok($warn =~ /DBD::Oracle::db do failed:/, "warn error: ``$warn'' expected 'do failed:'"); ok($DBI::err, 'err defined'); -ok($ora_errno, 'ora_errno defined'); -is($ora_errno, $DBI::err, 'ora_errno and err equal'); $dbh->{RaiseError} = 0; $dbh->{PrintError} = 0; # --- diff --git a/t/34pres_lobs.t b/t/34pres_lobs.t index d0135e11..213c4f0d 100644 --- a/t/34pres_lobs.t +++ b/t/34pres_lobs.t @@ -3,7 +3,6 @@ use Test::More; use DBI; -use Oraperl; use Config; use DBD::Oracle qw(:ora_types); From 9293e8ccacae0cd7c69e0bc4d5fdb9859665ebdf Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 17 Aug 2012 15:35:55 +0000 Subject: [PATCH 301/637] remove mention of Oraperl in tests (rel v1.50) git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15370 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 + LICENSE | 22 +- META.json | 29 +- META.yml | 22 +- README | 73 +- README.mkdn | 2964 ++++++++++----------- lib/DBD/Oracle.pm | 4 +- lib/DBD/Oracle/GetInfo.pm | 4 +- lib/DBD/Oracle/Object.pm | 4 +- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pm | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- t/000-report-versions.t | 3 +- t/10general.t | 5 +- t/34pres_lobs.t | 1 - 22 files changed, 1560 insertions(+), 1594 deletions(-) diff --git a/Changes b/Changes index 6d36b086..6d0a38ae 100644 --- a/Changes +++ b/Changes @@ -53,6 +53,9 @@ NEXTRELEASE - added a few more simple TAF tests (Martin J. Evans) +1.50 2012-08-15 + - RT78965 - Remove Oraperl tests (which were forcing a require on Oraperl) + 1.48 2012-08-09 - promote 1.47_00 to official release diff --git a/LICENSE b/LICENSE index a6a371c0..e5580c3f 100644 --- a/LICENSE +++ b/LICENSE @@ -18,15 +18,16 @@ This is free software, licensed under: The GNU General Public License, Version 1, February 1989 - GNU GENERAL PUBLIC LICENSE - Version 1, February 1989 + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA + Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public @@ -67,7 +68,7 @@ authors' reputations. The precise terms and conditions for copying, distribution and modification follow. - GNU GENERAL PUBLIC LICENSE + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which @@ -185,7 +186,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -207,9 +208,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS - Appendix: How to Apply These Terms to Your New Programs + Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it @@ -235,8 +236,9 @@ the exclusion of warranty; and each file should have at least the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA + Also add information on how to contact you by electronic and paper mail. diff --git a/META.json b/META.json index 9468ddbe..79df4c5b 100644 --- a/META.json +++ b/META.json @@ -7,7 +7,7 @@ "Martin J. Evans " ], "dynamic_config" : 0, - "generated_by" : "Dist::Zilla version 4.300016, CPAN::Meta::Converter version 2.120630", + "generated_by" : "Dist::Zilla version 4.300021, CPAN::Meta::Converter version 2.120921", "license" : [ "perl_5" ], @@ -40,7 +40,6 @@ "Devel::Peek" : "0", "Encode" : "0", "Math::BigInt" : "0", - "Oraperl" : "0", "Scalar::Util" : "0", "Test::More" : "0.94", "Thread::Semaphore" : "0", @@ -52,30 +51,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.49_00" + "version" : "1.50" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.49_00" + "version" : "1.50" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.49_00" - }, - "DBD::Oracle::db" : { - "file" : "lib/DBD/Oracle.pm", - "version" : "1.49_00" - }, - "DBD::Oracle::dr" : { - "file" : "lib/DBD/Oracle.pm", - "version" : "1.49_00" - }, - "DBD::Oracle::st" : { - "file" : "lib/DBD/Oracle.pm", - "version" : "1.49_00" + "version" : "1.50" } }, - "release_status" : "testing", + "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -84,11 +71,11 @@ "homepage" : "http://search.cpan.org/dist/DBD-Oracle/", "repository" : { "type" : "git", - "url" : "git://github.com/yanick/DBD-Oracle.git", - "web" : "http://github.com/yanick/DBD-Oracle/tree" + "url" : "https://github.com/yanick/DBD-Oracle.git", + "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.49_00", + "version" : "1.50", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index b0bd602d..a4b1deb6 100644 --- a/META.yml +++ b/META.yml @@ -12,7 +12,6 @@ build_requires: Devel::Peek: 0 Encode: 0 Math::BigInt: 0 - Oraperl: 0 Scalar::Util: 0 Test::More: 0.94 Thread::Semaphore: 0 @@ -21,7 +20,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 -generated_by: 'Dist::Zilla version 4.300016, CPAN::Meta::Converter version 2.120630' +generated_by: 'Dist::Zilla version 4.300021, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -30,22 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.49_00 + version: 1.50 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.49_00 + version: 1.50 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.49_00 - DBD::Oracle::db: - file: lib/DBD/Oracle.pm - version: 1.49_00 - DBD::Oracle::dr: - file: lib/DBD/Oracle.pm - version: 1.49_00 - DBD::Oracle::st: - file: lib/DBD/Oracle.pm - version: 1.49_00 + version: 1.50 requires: DBI: 0 DynaLoader: 0 @@ -56,8 +46,8 @@ requires: resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ - repository: git://github.com/yanick/DBD-Oracle.git -version: 1.49_00 + repository: https://github.com/yanick/DBD-Oracle.git +version: 1.50 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 1fd564ee..bf4cd15d 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.49_00 + version 1.50 SYNOPSIS use DBI; @@ -248,12 +248,16 @@ DBI CLASS METHODS #set up TAF on the connection # NOTE since DBD::Oracle uses call_pv you may need to pass a full # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); + # NOTE from 1.49_00 ora_taf_function can accept a code ref as well + # as a sub name as it now uses call_sv + my $dbh = DBI->connect('dbi:Oracle:XE', 'hr', 'hr', + {ora_taf_function => 'main::handle_taf'}); #create the perl TAF event function sub handle_taf { - my ($fo_event,$fo_type) = @_; + # NOTE from 1.49_00 the $dbh handle was passed to your callback + my ($fo_event,$fo_type, $dbh) = @_; if ($fo_event == OCI_FO_BEGIN){ print " Instance Unavailable Please stand by!! \n"; @@ -276,9 +280,8 @@ DBI CLASS METHODS print " Failed over user. Resuming services\n"; } elsif ($fo_event == OCI_FO_ERROR){ - print " Failover error Sleeping...\n"; - # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY - # If you want to stop retrying just return 0 + print " Failover error ...\n"; + sleep 5; # sleep before having another go return OCI_FO_RETRY; } else { @@ -367,38 +370,36 @@ DBI CLASS METHODS variable. ora_taf - If your Oracle instance has been configured to use TAF events you can - enable the TAF callback by setting this option to any *true* value. - - NOTE: All the ora_taf* attributes must currently be set in the connect - method if you want TAF enabled at the moment i.e., after connect you can - change the callback but you cannot disable TAF. + This attribute was removed in 1.49_00 as it was redundant. To enable TAF + simply set "ora_taf_function". ora_taf_function - The name of the Perl subroutine that will be called from OCI when a TAF - event occurs. You must supply a perl function to use the callback and it - will always receive two parameters, the failover event value and the - failover type. Below is an example of a TAF function + If your Oracle instance has been configured to use TAF events you can + enable the TAF callback by setting this option. + + The name of the Perl subroutine (or a code ref from 1.49_00) that will + be called from OCI when a TAF event occurs. You must supply a perl + function to use the callback and it will always receive at least two + parameters; the failover event value and the failover type. From 1.49_00 + the dbh is passed as the third argument. Below is an example of a TAF + function sub taf_event{ - my ($event, $type) = @_; + # NOTE from 1.49_00 the $dbh handle is passed to the callback + my ($event, $type, $dbh) = @_; print "My TAF event=$event\n"; print "My TAF type=$type\n"; return; } - Note you'll probably have to use the full name space when setting the - TAF function e.g., 'main::my_taf_function' and not just - 'my_taf_function'. + Note if passing a sub name you will probably have to use the full name + space when setting the TAF function e.g., 'main::my_taf_function' and + not just 'my_taf_function'. ora_taf_sleep - The amount of time in seconds DBD::Oracle will sleep between attempting - successive failover events when the event is OCI_FO_ERROR and - OCI_FO_RETRY is returned from the TAF handler. - - NOTE: This attribute will be withdrawn in the future so I suggest you - don't use it and if you want to sleep, add it to your own callback sub. + This attribute was removed in 1.49_00 as it was redundant. If you want + to sleep between retries simple add a sleep to your callback sub. ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, @@ -1007,7 +1008,7 @@ DATABASE HANDLE METHODS or BLOB column in most circumstances. If false, fetching retrieves the Oracle "LOB Locator" of the CLOB or BLOB value. - See "LOBs and LONGs" for more details. + See "LOBS AND LONGS" for more details. See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how to use LOB Locators. @@ -1043,7 +1044,7 @@ DATABASE HANDLE METHODS OCI_STMT_SCROLLABLE_READONLY - make result set scrollable - See "Scrollable Cursors" for more details. + See "SCROLLABLE CURSORS" for more details. ora_prefetch_rows Sets the number of rows to be prefetched. If it is not set, then the @@ -1399,8 +1400,8 @@ DATABASE HANDLE ATTRIBUTES $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); In the above example 10 rows will be prefetched up to a maximum of 10000 - bytes of data. The Oracle® Call Interface Programmer's Guide, suggests - a good row cache value for a scrollable cursor is about 20% of expected + bytes of data. The Oracle® Call Interface Programmer's Guide, suggests a + good row cache value for a scrollable cursor is about 20% of expected size of the record set. The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) @@ -1547,7 +1548,7 @@ DBI STATEMENT HANDLE OBJECT METHODS See "Binding Cursors" for the correct way to use ORA_RSET. - See "LOBs and LONGs" for how to use ORA_CLOB and ORA_BLOB. + See "LOBS AND LONGS" for how to use ORA_CLOB and ORA_BLOB. See "SYS.DBMS_SQL datatypes" for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. @@ -1555,7 +1556,7 @@ DBI STATEMENT HANDLE OBJECT METHODS See "Data Interface for Persistent LOBs" for the correct way to use SQLT_CHR and SQLT_BIN. - See "Other Data Types" for more information. + See "OTHER DATA TYPES" for more information. See also "Placeholders and Bind Values" in DBI. @@ -4241,3 +4242,11 @@ COPYRIGHT AND LICENSE This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. +POD ERRORS + Hey! The above document had some coding errors, which are explained + below: + + Around line 2655: + Non-ASCII character seen before =encoding in 'Oracle®'. Assuming + UTF-8 + diff --git a/README.mkdn b/README.mkdn index f2e4535e..4015e6a4 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,20 +4,20 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.49_00 +version 1.50 # SYNOPSIS - use DBI; + use DBI; - $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); + $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); - $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); + $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid", $user, $passwd); - # See the DBI module documentation for full details + # See the DBI module documentation for full details - # for some advanced uses you may need Oracle type values: - use DBD::Oracle qw(:ora_types); + # for some advanced uses you may need Oracle type values: + use DBD::Oracle qw(:ora_types); # DESCRIPTION @@ -30,66 +30,62 @@ consult the [DBI](http://search.cpan.org/perldoc?DBI) documentation first! # CONSTANTS -- :ora_session_modes - -ORA_SYSDBA ORA_SYSOPER ORA_SYSASM - -- :ora_types +- :ora\_session\_modes - ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW - ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB - ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI - SQLT_CHR SQLT_BIN +ORA\_SYSDBA ORA\_SYSOPER ORA\_SYSASM -- SQLCS_IMPLICIT +- :ora\_types -- SQLCS_NCHAR + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN +- SQLCS\_IMPLICIT +- SQLCS\_NCHAR -SQLCS_IMPLICIT and SQLCS_NCHAR are _character set form_ values. +SQLCS\_IMPLICIT and SQLCS\_NCHAR are _character set form_ values. See notes about Unicode elsewhere in this document. -- SQLT_INT - -- SQLT_FLT +- SQLT\_INT +- SQLT\_FLT These types are used only internally, and may be specified as internal -bind type for ORA_NUMBER_TABLE. See notes about ORA_NUMBER_TABLE elsewhere +bind type for ORA\_NUMBER\_TABLE. See notes about ORA\_NUMBER\_TABLE elsewhere in this document -- ORA_OCI +- ORA\_OCI Oracle doesn't provide a formal API for determining the exact version number of the OCI client library used, so DBD::Oracle has to go digging -(and sometimes has to more or less guess). The ORA_OCI constant +(and sometimes has to more or less guess). The ORA\_OCI constant holds the result of that process. -In string context ORA_OCI returns the full "A.B.C.D" version string. +In string context ORA\_OCI returns the full "A.B.C.D" version string. -In numeric context ORA_OCI returns the major.minor version number +In numeric context ORA\_OCI returns the major.minor version number (8.1, 9.2, 10.0 etc). But note that version numbers are not actually floating point and so if Oracle ever makes a release that has a two digit minor version, such as `9.10` it will have a lower numeric value than the preceding `9.9` release. So use with care. -The contents and format of ORA_OCI are subject to change (it may, +The contents and format of ORA\_OCI are subject to change (it may, for example, become a _version object_ in later releases). I recommend that you avoid checking for exact values. -- :ora_fetch_orient +- :ora\_fetch\_orient - OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST - OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE + OCI_FETCH_CURRENT OCI_FETCH_NEXT OCI_FETCH_FIRST OCI_FETCH_LAST + OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE These constants are used to set the orientation of a fetch on a scrollable cursor. -- :ora_exe_modes - - OCI_STMT_SCROLLABLE_READONLY +- :ora\_exe\_modes -- :ora_fail_over + OCI_STMT_SCROLLABLE_READONLY +- :ora\_fail\_over - OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR - OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY + OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR + OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL OCI_FO_RETRY # DBI CLASS METHODS @@ -112,30 +108,30 @@ If the database is defined in a TNSNAMES.ORA file, you can use the service name - 3 To connect without TNSNAMES.ORA file, you can use an EZCONNECT url, of the form: -//host[:port][/service_name] +//host\[:port\]\[/service\_name\] If port name is not specified, 1521 is the default. If service name is not specified, the hostname will be used as a service name. The following examples show several ways a connection can be created: - $dbh = DBI->connect('dbi:Oracle:DB','username','password'); + $dbh = DBI->connect('dbi:Oracle:DB','username','password'); - $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); + $dbh = DBI->connect('dbi:Oracle:DB','username/password',''); - $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); + $dbh = DBI->connect('dbi:Oracle:','username@DB','password'); - $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=DB;port=1521', 'scott/tiger', ''); - $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); + $dbh = DBI->connect("dbi:Oracle://myhost:1522/ORCL",'username', 'password'); ### OS authentication To connect to a local database with a user which has been set up to authenticate via the OS ("ALTER USER username IDENTIFIED EXTERNALLY"): - $dbh = DBI->connect('dbi:Oracle:','/',''); + $dbh = DBI->connect('dbi:Oracle:','/',''); -Note the lack of a connection name (use the ORACLE_SID environment +Note the lack of a connection name (use the ORACLE\_SID environment variable). If an explicit SID is used you will probably get an ORA-01004 error. That only works for local databases. (Authentication to remote Oracle @@ -144,15 +140,15 @@ but it is not secure and not recommended so not documented here. ### Oracle Environment Variables -To use DBD::ORACLE to connect to an Oracle database, ORACLE_HOME environment variable should be set correctly. -In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD_LIBRARY_PATH, ldconfig, or similar on Unix). +To use DBD::ORACLE to connect to an Oracle database, ORACLE\_HOME environment variable should be set correctly. +In general, the value used should match the version of Oracle that was used to build DBD::Oracle. If using dynamic linking then ORACLE\_HOME should match the version of Oracle that will be used to load in the Oracle client libraries (via LD\_LIBRARY\_PATH, ldconfig, or similar on Unix). -Oracle can use two environment variables to specify default connections: ORACLE_SID and TWO_TASK. +Oracle can use two environment variables to specify default connections: ORACLE\_SID and TWO\_TASK. To use them, specify either a local SID or service name, or a service name that is specified in the TNSNAMES.ORA file. -Note that if you have *both* local and remote databases, and you have ORACLE_SID *and* TWO_TASK set, and you don't specify a fully -qualified connect string on the command line, TWO_TASK takes precedence over ORACLE_SID (i.e. you get connected to remote system). +Note that if you have \*both\* local and remote databases, and you have ORACLE\_SID \*and\* TWO\_TASK set, and you don't specify a fully +qualified connect string on the command line, TWO\_TASK takes precedence over ORACLE\_SID (i.e. you get connected to remote system). It is highly recommended not to rely on environment variables and to always explicitly specify the SID in the connection string. This can prevent serious mistakes such as dropping a schema in the wrong database, and generally makes debugging and troubleshooting easier. @@ -160,7 +156,7 @@ Also remember that depending on the operating system you are using the differing ### Timezones -If the query is run through SQL*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. +If the query is run through SQL\*Net (mostly queries that are executed on remote servers), Oracle will return the time zone based on the setting of the UNIX environment variable "TZ" for the user who started the listener. If the query is run locally, Oracle will return the time zone based on the "TZ" environment variable setting of the user running the query. @@ -173,29 +169,29 @@ issue the UNIX "date" command. DBD::Oracle supports DRCP (Database Resident Connection Pool) so if you have an 11.2 database and DRCP is enabled you can direct all of your connections to it by adding ':POOLED' to the SID or -setting a connection attribute of ora_drcp, or set the SERVER=POOLED +setting a connection attribute of ora\_drcp, or set the SERVER=POOLED when using a TNSENTRY style connection or even by setting an -environment variable ORA_DRCP. All of which are demonstrated below; +environment variable ORA\_DRCP. All of which are demonstrated below; - $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') + $dbh = DBI->connect('dbi:Oracle:DB:POOLED','username','password') - $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') + $dbh = DBI->connect('dbi:Oracle:','username@DB:POOLED','password') - $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1}) - $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, - ora_drcp_class=>'my_app', - ora_drcp_min =>10}) + $dbh = DBI->connect('dbi:Oracle:DB','username','password',{ora_drcp=>1, + ora_drcp_class=>'my_app', + ora_drcp_min =>10}) - $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') + $dbh = DBI->connect('dbi:Oracle:host=foobar;sid=ORCL;port=1521;SERVER=POOLED', 'scott/tiger', '') - $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= - (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) - (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") + $dbh = DBI->connect('dbi:Oracle:', q{scott/tiger@(DESCRIPTION= + (ADDRESS=(PROTOCOL=TCP)(HOST= foobar)(PORT=1521)) + (CONNECT_DATA=(SID=ORCL)(SERVER=POOLED)))}, "") - if the ORA_DRCP environment variable is set then just this + if the ORA_DRCP environment variable is set then just this - $dbh = DBI->connect('dbi:Oracle:DB','username','password') + $dbh = DBI->connect('dbi:Oracle:DB','username','password') You can find a white paper on setting up DRCP and its advantages at [http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf](http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf). @@ -217,7 +213,7 @@ You will have to set up TAF on your instance before you can use this callback. You can test your instance to see if you can use TAF callback with - $dbh->ora_can_taf(); + $dbh->ora_can_taf(); If you try to set up a callback without it being enabled DBD::Oracle will croak. @@ -230,13 +226,13 @@ possible TAF situations you might want to set up but here is a simple example: The TNS entry for the instance has had the following added to the -CONNECT_DATA section +CONNECT\_DATA section - (FAILOVER_MODE= - (TYPE=select) - (METHOD=basic) - (RETRIES=10) - (DELAY=10)) + (FAILOVER_MODE= + (TYPE=select) + (METHOD=basic) + (RETRIES=10) + (DELAY=10)) You will also have to create your own perl function that will be called from the client. You can name it anything you want and it will @@ -245,19 +241,23 @@ failover type. You can also set a sleep value in case of failover error and the OCI client will sleep for the specified seconds before it attempts another event. - use DBD::Oracle(qw(:ora_fail_over)); - #import the ora fail over constants + use DBD::Oracle(qw(:ora_fail_over)); + #import the ora fail over constants - #set up TAF on the connection - # NOTE since DBD::Oracle uses call_pv you may need to pass a full - # name space as the function e.g., 'main::handle_taf' - my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,ora_taf_sleep=>5,ora_taf_function=>'handle_taf'}); + #set up TAF on the connection + # NOTE since DBD::Oracle uses call_pv you may need to pass a full + # name space as the function e.g., 'main::handle_taf' + # NOTE from 1.49_00 ora_taf_function can accept a code ref as well + # as a sub name as it now uses call_sv + my $dbh = DBI->connect('dbi:Oracle:XE', 'hr', 'hr', + {ora_taf_function => 'main::handle_taf'}); - #create the perl TAF event function + #create the perl TAF event function - sub handle_taf { - my ($fo_event,$fo_type) = @_; - if ($fo_event == OCI_FO_BEGIN){ + sub handle_taf { + # NOTE from 1.49_00 the $dbh handle was passed to your callback + my ($fo_event,$fo_type, $dbh) = @_; + if ($fo_event == OCI_FO_BEGIN){ print " Instance Unavailable Please stand by!! \n"; printf(" Your TAF type is %s \n", @@ -279,36 +279,35 @@ attempts another event. print " Failed over user. Resuming services\n"; } elsif ($fo_event == OCI_FO_ERROR){ - print " Failover error Sleeping...\n"; - # DBD::Oracle will sleep for ora_taf_sleep if you return OCI_FO_RETRY - # If you want to stop retrying just return 0 + print " Failover error ...\n"; + sleep 5; # sleep before having another go return OCI_FO_RETRY; } else { printf(" Bad Failover Event: %d.\n", $fo_event); + } + return 0; } - return 0; - } The TAF types are as follows - OCI_FO_SESSION indicates the user has requested only session failover. - OCI_FO_SELECT indicates the user has requested select failover. - OCI_FO_NONE indicates the user has not requested a failover type. - OCI_FO_TXNAL indicates the user has requested a transaction failover. + OCI_FO_SESSION indicates the user has requested only session failover. + OCI_FO_SELECT indicates the user has requested select failover. + OCI_FO_NONE indicates the user has not requested a failover type. + OCI_FO_TXNAL indicates the user has requested a transaction failover. The TAF events are as follows - OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. - OCI_FO_END indicates successful completion of failover. - OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. - OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. - OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). + OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting. + OCI_FO_END indicates successful completion of failover. + OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying. + OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover. + OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter). ### Connect Attributes -#### ora_ncs_buff_mtpl +#### ora\_ncs\_buff\_mtpl You can customize the size of the buffer when selecting LOBs with the built-in AUTO Lob. The default value is 4 which is probably @@ -320,27 +319,27 @@ This value can also be specified with the `ORA_DBD_NCS_BUFFER` environment variable in which case it sets the value at the connect stage. -#### ora_drcp +#### ora\_drcp For Oracle 11.2 or greater. Set to _1_ to enable DRCP. Can also be set via the `ORA_DRCP` environment variable. -#### ora_drcp_class +#### ora\_drcp\_class -If you are using DRCP, you can set a CONNECTION_CLASS for your pools +If you are using DRCP, you can set a CONNECTION\_CLASS for your pools as well. As sessions from a DRCP cannot be shared by users, you can use this setting to identify the same user across different applications. OCI will ensure that sessions belonging to a 'class' are not shared outside the class'. -The values for ora_drcp_class cannot contain a '*' and must be less +The values for ora\_drcp\_class cannot contain a '\*' and must be less than 1024 characters. This value can be also be specified with the `ORA_DRCP_CLASS` environment variable. -#### ora_drcp_min +#### ora\_drcp\_min This optional value specifies the minimum number of sessions that are initially opened. New sessions are only opened after this value has @@ -354,140 +353,137 @@ application is planning or expecting to run. This value can also be specified with the `ORA_DRCP_MIN` environment variable. -#### ora_drcp_max +#### ora\_drcp\_max This optional value specifies the maximum number of sessions that can be open at one time. Once reached no more sessions can be opened until one becomes free. The default value is 40 and any value above 1 -is valid. You should not set this value lower than ora_drcp_min as +is valid. You should not set this value lower than ora\_drcp\_min as that will just waste resources. This value can also be specified with the `ORA_DRCP_MAX` environment variable. -#### ora_drcp_incr +#### ora\_drcp\_incr This optional value specifies the next increment for sessions to be started if the current number of sessions are less than -ora_drcp_max. The default value is 2 and any value above 0 is -valid as long as the value of ora_drcp_min + ora_drcp_incr is not -greater than ora_drcp_max. +ora\_drcp\_max. The default value is 2 and any value above 0 is +valid as long as the value of ora\_drcp\_min + ora\_drcp\_incr is not +greater than ora\_drcp\_max. This value can also be specified with the `ORA_DRCP_INCR` environment variable. -#### ora_taf - -If your Oracle instance has been configured to use TAF events you can -enable the TAF callback by setting this option to any _true_ value. - -NOTE: All the ora_taf* attributes must currently be set in the connect -method if you want TAF enabled at the moment i.e., after connect you -can change the callback but you cannot disable TAF. - -#### ora_taf_function - -The name of the Perl subroutine that will be called from OCI when a -TAF event occurs. You must supply a perl function to use the callback -and it will always receive two parameters, the failover event value -and the failover type. Below is an example of a TAF function +#### ora\_taf - sub taf_event{ - my ($event, $type) = @_; +This attribute was removed in 1.49\_00 as it was redundant. To +enable TAF simply set ["ora\_taf\_function"](#ora\_taf\_function). - print "My TAF event=$event\n"; - print "My TAF type=$type\n"; - return; - } +#### ora\_taf\_function -Note you'll probably have to use the full name space when setting the -TAF function e.g., 'main::my_taf_function' and not just -'my_taf_function'. +If your Oracle instance has been configured to use TAF events you can +enable the TAF callback by setting this option. + +The name of the Perl subroutine (or a code ref from 1.49\_00) that will +be called from OCI when a TAF event occurs. You must supply a perl +function to use the callback and it will always receive at least two +parameters; the failover event value and the failover type. From +1.49\_00 the dbh is passed as the third argument. Below is an example +of a TAF function + + sub taf_event{ + # NOTE from 1.49_00 the $dbh handle is passed to the callback + my ($event, $type, $dbh) = @_; + + print "My TAF event=$event\n"; + print "My TAF type=$type\n"; + return; + } -#### ora_taf_sleep +Note if passing a sub name you will probably have to use the full name +space when setting the TAF function e.g., 'main::my\_taf\_function' and +not just 'my\_taf\_function'. -The amount of time in seconds DBD::Oracle will sleep between attempting -successive failover events when the event is OCI_FO_ERROR and OCI_FO_RETRY -is returned from the TAF handler. +#### ora\_taf\_sleep -NOTE: This attribute will be withdrawn in the future so I suggest you -don't use it and if you want to sleep, add it to your own callback -sub. +This attribute was removed in 1.49\_00 as it was redundant. If you want +to sleep between retries simple add a sleep to your callback sub. -#### ora_session_mode +#### ora\_session\_mode -The ora_session_mode attribute can be used to connect with SYSDBA, -SYSOPER and ORA_SYSASM authorization. -The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using +The ora\_session\_mode attribute can be used to connect with SYSDBA, +SYSOPER and ORA\_SYSASM authorization. +The ORA\_SYSDBA, ORA\_SYSOPER and ORA\_SYSASM constants can be imported using - use DBD::Oracle qw(:ora_session_modes); + use DBD::Oracle qw(:ora_session_modes); -This is one case where setting ORACLE_SID may be useful since -connecting as SYSDBA or SYSOPER via SQL*Net is frequently disabled +This is one case where setting ORACLE\_SID may be useful since +connecting as SYSDBA or SYSOPER via SQL\*Net is frequently disabled for security reasons. Example: - $dsn = "dbi:Oracle:"; # no dbname here - $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed - delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set + $dsn = "dbi:Oracle:"; # no dbname here + $ENV{ORACLE_SID} = "orcl"; # set ORACLE_SID as needed + delete $ENV{TWO_TASK}; # make sure TWO_TASK isn't set - $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); + $dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA }); It has been reported that this only works if `$dsn` does not contain -a SID so that Oracle then uses the value of ORACLE_SID (not -TWO_TASK) environment variable to connect to a local instance. Also +a SID so that Oracle then uses the value of ORACLE\_SID (not +TWO\_TASK) environment variable to connect to a local instance. Also the username and password should be empty, and the user executing the script needs to be part of the dba group or osdba group. -#### ora_oratab_orahome +#### ora\_oratab\_orahome -Passing a true value for the ora_oratab_orahome attribute will make +Passing a true value for the ora\_oratab\_orahome attribute will make DBD::Oracle change `$ENV{ORACLE_HOME}` to make the Oracle home directory that specified in the `/etc/oratab` file _if_ the database to connect to is specified as a SID that exists in the oratab file, and DBD::Oracle was built to use the Oracle 7 OCI API (not Oracle 8+). -#### ora_module_name +#### ora\_module\_name After connecting to the database the value of this attribute is passed -to the SET_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL +to the SET\_MODULE() function in the `DBMS_APPLICATION_INFO` PL/SQL package. This can be used to identify the application to the DBA for monitoring and performance tuning purposes. For example: - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_module_name => $0 }); - $dbh->{ora_module_name} = $y; + $dbh->{ora_module_name} = $y; The maximum size is 48 bytes. NOTE: You will need an Oracle client 10.1 or later to use this. -#### ora_driver_name +#### ora\_driver\_name For 11g and later you can now set the name of the driver layer using OCI. Perl, Perl5, ApachePerl so on. Names starting with "ORA" are reserved. You can enter up to 8 characters. If none is enter then this will default to DBDOxxxx where xxxx is the current version number. This value can be -retrieved on the server side using V$SESSION_CONNECT_INFO or -GV$SESSION_CONNECT_INFO +retrieved on the server side using V$SESSION\_CONNECT\_INFO or +GV$SESSION\_CONNECT\_INFO - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_driver_name => 'ModPerl_1' }); - $dbh->{ora_driver_name} = $q; + $dbh->{ora_driver_name} = $q; -#### ora_client_info +#### ora\_client\_info Allows you to add any value (up to 64 bytes) to your session and it can be retrieved on the server side from the `V$SESSION`a view. - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_info => 'Remote2' }); - $dbh->{ora_client_info} = "Remote2"; + $dbh->{ora_client_info} = "Remote2"; NOTE: You will need an Oracle client 10.1 or later to use this. -#### ora_client_identifier +#### ora\_client\_identifier Allows you to specify the user identifier in the session handle. @@ -498,93 +494,93 @@ reasons and the first character of the identifier should not be ':'. This value can be retrieved on the server side using `V$SESSION` view. - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_client_identifier => $some_web_user }); - $dbh->{ora_client_identifier} = $local_user; + $dbh->{ora_client_identifier} = $local_user; -#### ora_action +#### ora\_action Allows you to specify any string up to 32 bytes which may be retrieved on the server side using `V$SESSION` view. - my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); + my $dbh = DBI->connect($dsn, $user, $passwd, { ora_action => "Login"}); - $dbh->{ora_action} = "New Long Query 22"; + $dbh->{ora_action} = "New Long Query 22"; NOTE: You will need an Oracle client 10.1 or later to use this. -#### ora_dbh_share +#### ora\_dbh\_share Requires at least Perl 5.8.0 compiled with ithreads. Allows you to share database connections between threads. The first connect will make the -connection, all following calls to connect with the same ora_dbh_share +connection, all following calls to connect with the same ora\_dbh\_share attribute will use the same database connection. The value must be a reference to a already shared scalar which is initialized to an empty string. - our $orashr : shared = '' ; + our $orashr : shared = '' ; - $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; + $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; -#### ora_envhp +#### ora\_envhp The first time a connection is made a new OCI 'environment' is created by DBD::Oracle and stored in the driver handle. Subsequent connects reuse (share) that same OCI environment by default. -The ora_envhp attribute can be used to disable the reuse of the OCI +The ora\_envhp attribute can be used to disable the reuse of the OCI environment from a previous connect. If the value is `0` then a new OCI environment is allocated and used for this connection. The OCI environment holds information about the client side context, such as the local NLS environment. By altering `%ENV` and setting -ora_envhp to 0 you can create connections with different NLS +ora\_envhp to 0 you can create connections with different NLS settings. This is most useful for testing. -#### ora_charset, ora_ncharset +#### ora\_charset, ora\_ncharset For oracle versions >= 9.2 you can specify the client charset and -ncharset with the ora_charset and ora_ncharset attributes. You +ncharset with the ora\_charset and ora\_ncharset attributes. You still need to pass `ora_envhp = 0` for all but the first connect. These attributes override the settings from environment variables. - $dbh = DBI->connect ($dsn, $user, $passwd, - {ora_charset => 'AL32UTF8'}); + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_charset => 'AL32UTF8'}); -#### ora_verbose +#### ora\_verbose Use this value to enable DBD::Oracle only tracing. Simply either set -the ora_verbose attribute on the connect() method to the trace level +the ora\_verbose attribute on the connect() method to the trace level you desire like this - my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); + my $dbh = DBI->connect($dsn, "", "", {ora_verbose=>6}); or set it directly on the DB handle like this; - $dbh->{ora_verbose} =6; + $dbh->{ora_verbose} =6; In both cases the DBD::Oracle trace level is set to 6, which is the highest level tracing most of the calls to OCI. -NOTE: In future versions of DBD::Oracle ora_verbose will be changed so +NOTE: In future versions of DBD::Oracle ora\_verbose will be changed so that it is simply a switch to turn DBI's DBD tracing on or off. A true value will turn it on and a false value will turn it off. DBI's -"DBD" tracing was not available when ora_verbose was created and -ora_verbose adds an additional test to every trace test. +"DBD" tracing was not available when ora\_verbose was created and +ora\_verbose adds an additional test to every trace test. -#### ora_oci_success_warn +#### ora\_oci\_success\_warn Use this value to print otherwise silent OCI warnings that may happen when an execute or fetch returns "Success With Info" or when you want to tune RowCaching and LOB Reads - $dbh->{ora_oci_success_warn} = 1; + $dbh->{ora_oci_success_warn} = 1; -#### ora_objects +#### ora\_objects Use this value to enable extended embedded oracle objects mode. In extended: @@ -596,55 +592,55 @@ Embedded objects are returned as instance (including type- Determine object type for each instance. All object attributes are returned (not only super-type's attributes). - $dbh->{ora_objects} = 1; + $dbh->{ora_objects} = 1; -#### ora_ph_type +#### ora\_ph\_type The default placeholder datatype for the database session. -The `TYPE` or [ora_type](#pod_ora_type) attributes to L and -L override the datatype for individual placeholders. +The `TYPE` or ["ora\_type"](#ora\_type) attributes to ["bind\_param" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param) and +["bind\_param\_inout" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param\_inout) override the datatype for individual placeholders. The most frequent reason for using this attribute is to permit trailing spaces in values passed by placeholders. Constants for the values allowed for this attribute can be imported using - use DBD::Oracle qw(:ora_types); + use DBD::Oracle qw(:ora_types); Only the following values are permitted for this attribute. -- ORA_VARCHAR2 +- ORA\_VARCHAR2 -Oracle clients using OCI 8 will strip trailing spaces and allow embedded \0 bytes. -Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \0 bytes. +Oracle clients using OCI 8 will strip trailing spaces and allow embedded \\0 bytes. +Oracle clients using OCI 9.2 do not strip trailing spaces and allow embedded \\0 bytes. This is the normal default placeholder type. -- ORA_STRING +- ORA\_STRING -Do not strip trailing spaces and end the string at the first \0. +Do not strip trailing spaces and end the string at the first \\0. -- ORA_CHAR +- ORA\_CHAR -Do not strip trailing spaces and allow embedded \0. +Do not strip trailing spaces and allow embedded \\0. Force 'blank-padded comparison semantics'. For example: - use DBD::Oracle qw(:ora_types); + use DBD::Oracle qw(:ora_types); - $SQL="select username from all_users where username = ?"; - #username is a char(8) - $sth=$dbh->prepare($SQL)"; - $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); + $SQL="select username from all_users where username = ?"; + #username is a char(8) + $sth=$dbh->prepare($SQL)"; + $sth->bind_param(1,'bloggs',{ ora_type => ORA_CHAR}); Will pad bloggs out to 8 characters and return the username. -#### ora_parse_error_offset +#### ora\_parse\_error\_offset If the previous error was from a failed `prepare` due to a syntax error, this attribute gives the offset into the `Statement` attribute where the error was found. -#### ora_array_chunk_size +#### ora\_array\_chunk\_size Due to OCI limitations, DBD::Oracle needs to buffer up rows of bind values in its `execute_for_fetch` implementation. This attribute @@ -658,7 +654,7 @@ used to limit or extend the number of rows processed at a time. Note that this attribute also applies to `execute_array`, since that method is implemented using `execute_for_fetch`. -#### ora_connect_with_default_signals +#### ora\_connect\_with\_default\_signals Sometimes the Oracle client seems to change some of the signal handlers of the process during the connect phase. For instance, some @@ -671,36 +667,36 @@ previous state. For example: - $dbh = DBI->connect ($dsn, $user, $passwd, - {ora_connect_with_default_signals => [ 'INT' ] }); + $dbh = DBI->connect ($dsn, $user, $passwd, + {ora_connect_with_default_signals => [ 'INT' ] }); NOTE disabling the signal handlers the OCI library sets up may affect functionality in the OCI library. -NOTE If you are using connect_cached then the above example will lead +NOTE If you are using connect\_cached then the above example will lead to DBI thinking each connection is different as an anonymous array reference -is being used. To avoid this when using connect_cached you are advised +is being used. To avoid this when using connect\_cached you are advised to use: - my @ora_default_signals = (...); - $dbh = DBI->connect($dsn, $user, $passwd, - {ora_connect_with_default_signals => \@ora_default_signals}); + my @ora_default_signals = (...); + $dbh = DBI->connect($dsn, $user, $passwd, + {ora_connect_with_default_signals => \@ora_default_signals}); In more recent Perl versions you could possibly make use of new state variables. -## __connect_cached__ +## __connect\_cached__ Implemented by DBI, no driver-specific impact. -Please note that connect_cached as not been tested with DRCP. +Please note that connect\_cached as not been tested with DRCP. -## __data_sources__ +## __data\_sources__ - @data_sources = DBI->data_sources('Oracle'); - @data_sources = $dbh->data_sources(); + @data_sources = DBI->data_sources('Oracle'); + @data_sources = $dbh->data_sources(); -Returns a list of available databases. You will have to set either the 'ORACLE_HOME' or -'TNS_ADMIN' environment value to retrieve this list. It will read these values from +Returns a list of available databases. You will have to set either the 'ORACLE\_HOME' or +'TNS\_ADMIN' environment value to retrieve this list. It will read these values from TNSNAMES.ORA file entries. # METHODS COMMON TO ALL HANDLES @@ -712,19 +708,19 @@ common variable used in this documentation is $_rv_, which stands for "return va ## __err__ - $rv = $h->err; + $rv = $h->err; Returns the error code from the last method called. ## __errstr__ - $str = $h->errstr; + $str = $h->errstr; Returns the last error that was reported by Oracle. Starting with "ORA-00000" code followed by the error message. ## __state__ - $str = $h->state; + $str = $h->state; Oracle hasn't supported SQLSTATE since the early versions OCI. It will return empty when the command succeeds and 'S1000' (General Error) for all other errors. @@ -736,11 +732,11 @@ is usually clearer to always use `$dbh->state`. Implemented by DBI, no driver-specific impact. -## __trace_msg__ +## __trace\_msg__ Implemented by DBI, no driver-specific impact. -## __parse_trace_flag__ and __parse_trace_flags__ +## __parse\_trace\_flag__ and __parse\_trace\_flags__ Implemented by DBI, no driver-specific impact. @@ -751,15 +747,15 @@ DBD::Oracle uses the `func` method to support a variety of functions. ## __Private database handle functions__ Some of these functions are called through the method func() -which is described in the DBI documentation. Any function that begins with ora_ +which is described in the DBI documentation. Any function that begins with ora\_ can be called directly. -## __plsql_errstr__ +## __plsql\_errstr__ This function returns a string which describes the errors from the most recent PL/SQL function, procedure, package, or package body compile in a format similar to the output -of the SQL*Plus command 'show errors'. +of the SQL\*Plus command 'show errors'. The function returns undef if the error string could not be retrieved due to a database error. @@ -784,70 +780,70 @@ Example: die $msg if $msg; } -## __dbms_output_enable / dbms_output_put / dbms_output_get__ +## __dbms\_output\_enable / dbms\_output\_put / dbms\_output\_get__ -These functions use the PL/SQL DBMS_OUTPUT package to store and -retrieve text using the DBMS_OUTPUT buffer. Text stored in this buffer -by dbms_output_put or any PL/SQL block can be retrieved by -dbms_output_get or any PL/SQL block connected to the same database +These functions use the PL/SQL DBMS\_OUTPUT package to store and +retrieve text using the DBMS\_OUTPUT buffer. Text stored in this buffer +by dbms\_output\_put or any PL/SQL block can be retrieved by +dbms\_output\_get or any PL/SQL block connected to the same database session. -Stored text is not available until after dbms_output_put or the PL/SQL +Stored text is not available until after dbms\_output\_put or the PL/SQL block that saved it completes its execution. This means you __CAN NOT__ use these functions to monitor long running PL/SQL procedures. Example 1: - # Enable DBMS_OUTPUT and set the buffer size - $dbh->{RaiseError} = 1; - $dbh->func( 1000000, 'dbms_output_enable' ); + # Enable DBMS_OUTPUT and set the buffer size + $dbh->{RaiseError} = 1; + $dbh->func( 1000000, 'dbms_output_enable' ); - # Put text in the buffer . . . - $dbh->func( @text, 'dbms_output_put' ); + # Put text in the buffer . . . + $dbh->func( @text, 'dbms_output_put' ); - # . . . and retrieve it later - @text = $dbh->func( 'dbms_output_get' ); + # . . . and retrieve it later + @text = $dbh->func( 'dbms_output_get' ); Example 2: - $dbh->{RaiseError} = 1; - $sth = $dbh->prepare(q{ - DECLARE tmp VARCHAR2(50); - BEGIN - SELECT SYSDATE INTO tmp FROM DUAL; - dbms_output.put_line('The date is '||tmp); - END; - }); - $sth->execute; + $dbh->{RaiseError} = 1; + $sth = $dbh->prepare(q{ + DECLARE tmp VARCHAR2(50); + BEGIN + SELECT SYSDATE INTO tmp FROM DUAL; + dbms_output.put_line('The date is '||tmp); + END; + }); + $sth->execute; - # retrieve the string - $date_string = $dbh->func( 'dbms_output_get' ); + # retrieve the string + $date_string = $dbh->func( 'dbms_output_get' ); -## __dbms_output_enable ( [ buffer_size ] )__ +## __dbms\_output\_enable ( \[ buffer\_size \] )__ -This function calls DBMS_OUTPUT.ENABLE to enable calls to package -DBMS_OUTPUT procedures GET, GET_LINE, PUT, and PUT_LINE. Calls to -these procedures are ignored unless DBMS_OUTPUT.ENABLE is called +This function calls DBMS\_OUTPUT.ENABLE to enable calls to package +DBMS\_OUTPUT procedures GET, GET\_LINE, PUT, and PUT\_LINE. Calls to +these procedures are ignored unless DBMS\_OUTPUT.ENABLE is called first. -The buffer_size is the maximum amount of text that can be saved in the -buffer and must be between 2000 and 1,000,000. If buffer_size is not +The buffer\_size is the maximum amount of text that can be saved in the +buffer and must be between 2000 and 1,000,000. If buffer\_size is not given, the default is 20,000 bytes. -## __dbms_output_put ( [ @lines ] )__ +## __dbms\_output\_put ( \[ @lines \] )__ -This function calls DBMS_OUTPUT.PUT_LINE to add lines to the buffer. +This function calls DBMS\_OUTPUT.PUT\_LINE to add lines to the buffer. If all lines were saved successfully the function returns 1. Depending on the context, an empty list or undef is returned for failure. -If any line causes buffer_size to be exceeded, a buffer overflow error +If any line causes buffer\_size to be exceeded, a buffer overflow error is raised and the function call fails. Some of the text might be in the buffer. -## __dbms_output_get__ +## __dbms\_output\_get__ -This function calls DBMS_OUTPUT.GET_LINE to retrieve lines of text from +This function calls DBMS\_OUTPUT.GET\_LINE to retrieve lines of text from the buffer. In an array context, all complete lines are removed from the buffer and @@ -857,19 +853,19 @@ returned. In a scalar context, the first complete line is removed from the buffer and returned. If there are no complete lines, undef is returned. -Any text in the buffer after a call to DBMS_OUTPUT.GET_LINE or -DBMS_OUTPUT.GET is discarded by the next call to DBMS_OUTPUT.PUT_LINE, -DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. +Any text in the buffer after a call to DBMS\_OUTPUT.GET\_LINE or +DBMS\_OUTPUT.GET is discarded by the next call to DBMS\_OUTPUT.PUT\_LINE, +DBMS\_OUTPUT.PUT, or DBMS\_OUTPUT.NEW\_LINE. ## __reauthenticate ( $username, $password )__ Starts a new session against the current database using the credentials supplied. -## __private_attribute_info__ +## __private\_attribute\_info__ - $hashref = $dbh->private_attribute_info(); - $hashref = $sth->private_attribute_info(); + $hashref = $dbh->private_attribute_info(); + $hashref = $sth->private_attribute_info(); Returns a hash of all private attributes used by DBD::Oracle, for either a database or a statement handle. Currently, all the hash values are undef. @@ -889,7 +885,7 @@ manually, which is easy to forget to do. ## __PrintError__ (boolean, inherited) Forces database errors to also generate warnings, which can then be filtered with methods such as -locally redefining _$SIG{__WARN__}_ or using modules such as `CGI::Carp`. This attribute is on +locally redefining _$SIG{\_\_WARN\_\_}_ or using modules such as `CGI::Carp`. This attribute is on by default. ## __ShowErrorStatement__ (boolean, inherited) @@ -904,15 +900,15 @@ for a short a time only when absolutely needed. ## __Executed__ (boolean, read-only) -Indicates if a handle has been executed. For database handles, this value is true after the [do](#pod_do) method has been called, or -when one of the child statement handles has issued an [execute](#pod_execute). Issuing a [commit](#pod_commit) or [rollback](#pod_rollback) always resets the -attribute to false for database handles. For statement handles, any call to [execute](#pod_execute) or its variants will flip the value to +Indicates if a handle has been executed. For database handles, this value is true after the ["do"](#do) method has been called, or +when one of the child statement handles has issued an ["execute"](#execute). Issuing a ["commit"](#commit) or ["rollback"](#rollback) always resets the +attribute to false for database handles. For statement handles, any call to ["execute"](#execute) or its variants will flip the value to true for the lifetime of the statement handle. ## __TraceLevel__ (integer, inherited) -Sets the trace level, similar to the [trace](#pod_trace) method. See the sections on -[trace](#pod_trace) and [parse_trace_flag](#pod_parse_trace_flag) for more details. +Sets the trace level, similar to the ["trace"](#trace) method. See the sections on +["trace"](#trace) and ["parse\_trace\_flag"](#parse\_trace\_flag) for more details. ## __Active__ (boolean, read-only) @@ -933,7 +929,7 @@ Same as `Kids`, but only returns those that are active. ## __CachedKids__ (hash ref) Returns a hashref of handles. If called on a database handle, returns all statement handles created by use of the -`prepare_cached` method. If called on a driver handle, returns all database handles created by the [connect_cached](#pod_connect_cached) +`prepare_cached` method. If called on a driver handle, returns all database handles created by the ["connect\_cached"](#connect\_cached) method. ## __ChildHandles__ (array ref) @@ -1008,10 +1004,10 @@ It also has the effect of disabling the 'quick FETCH' of attribute values from t # ORACLE-SPECIFIC DATABASE HANDLE METHODS -## __ora_can_unicode ( [ $refresh ] )__ +## __ora\_can\_unicode ( \[ $refresh \] )__ Returns a number indicating whether either of the database character sets -is a Unicode encoding. Calls ora_nls_parameters() and passes the optional +is a Unicode encoding. Calls ora\_nls\_parameters() and passes the optional $refresh parameter to it. 0 = Neither character set is a Unicode encoding. @@ -1022,37 +1018,37 @@ $refresh parameter to it. 3 = Both character sets are Unicode encodings. -## __ora_can_taf__ +## __ora\_can\_taf__ Returns true if the current connection supports TAF events. False if otherise. -## __ora_nls_parameters ( [ $refresh ] )__ +## __ora\_nls\_parameters ( \[ $refresh \] )__ Returns a hash reference containing the current NLS parameters, as given -by the v$nls_parameters view. The values fetched are cached between calls. +by the v$nls\_parameters view. The values fetched are cached between calls. To cause the latest values to be fetched, pass a true value to the function. # DATABASE HANDLE METHODS -## __selectall_arrayref__ +## __selectall\_arrayref__ - $ary_ref = $dbh->selectall_arrayref($sql); - $ary_ref = $dbh->selectall_arrayref($sql, \%attr); - $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); + $ary_ref = $dbh->selectall_arrayref($sql); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr); + $ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values); Returns a reference to an array containing the rows returned by preparing and executing the SQL string. See the DBI documentation for full details. -## __selectall_hashref__ +## __selectall\_hashref__ - $hash_ref = $dbh->selectall_hashref($sql, $key_field); + $hash_ref = $dbh->selectall_hashref($sql, $key_field); Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. See the DBI documentation for full details. -## __selectcol_arrayref__ +## __selectcol\_arrayref__ - $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); + $ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values); Returns a reference to an array containing the first column from each rows returned by preparing and executing the SQL string. It is possible to specify exactly @@ -1060,86 +1056,83 @@ which columns to return. See the DBI documentation for full details. ## __prepare__ - $sth = $dbh->prepare($statement, \%attr); + $sth = $dbh->prepare($statement, \%attr); Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. ### __Prepare Attributes__ These attributes may be used in the `\%attr` parameter of the -L database handle method. +["prepare" in DBI](http://search.cpan.org/perldoc?DBI#prepare) database handle method. -- ora_placeholders +- ora\_placeholders Set to false to disable processing of placeholders. Used mainly for loading a PL/SQL package that has been _wrapped_ with Oracle's `wrap` utility. -- ora_auto_lob +- ora\_auto\_lob If true (the default), fetching retrieves the contents of the CLOB or BLOB column in most circumstances. If false, fetching retrieves the Oracle "LOB Locator" of the CLOB or BLOB value. -See [LOBs and LONGs](#pod_LOBs and LONGs) for more details. +See ["LOBS AND LONGS"](#LOBS AND LONGS) for more details. See also the LOB tests in 05dbi.t of Oracle::OCI for examples of how to use LOB Locators. -- ora_pers_lob +- ora\_pers\_lob -If true the [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) method for the [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) will be -used for LOBs rather than the default method [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators). +If true the ["Simple Fetch for CLOBs and BLOBs"](#Simple Fetch for CLOBs and BLOBs) method for the ["Data Interface for Persistent LOBs"](#Data Interface for Persistent LOBs) will be +used for LOBs rather than the default method ["Data Interface for LOB Locators"](#Data Interface for LOB Locators). -- ora_clbk_lob +- ora\_clbk\_lob -If true the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) method for the L will be used for LOBs. +If true the ["Piecewise Fetch with Callback"](#Piecewise Fetch with Callback) method for the ["Data Interface for Persistent LOBs"](#Data Interface for Persistent LOBs) will be used for LOBs. -- ora_piece_lob +- ora\_piece\_lob -If true the [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) method for the L will be used for LOBs. +If true the ["Piecewise Fetch with Polling"](#Piecewise Fetch with Polling) method for the ["Data Interface for Persistent LOBs"](#Data Interface for Persistent LOBs) will be used for LOBs. -- ora_piece_size +- ora\_piece\_size -This is the max piece size for the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) -and [Piecewise Fetch with Polling](#pod_Piecewise Fetch with Polling) methods, in chars for CLOBS, and +This is the max piece size for the ["Piecewise Fetch with Callback"](#Piecewise Fetch with Callback) +and ["Piecewise Fetch with Polling"](#Piecewise Fetch with Polling) methods, in chars for CLOBS, and bytes for BLOBS. -- ora_check_sql +- ora\_check\_sql If 1 (default), force SELECT statements to be described in prepare(). If 0, allow SELECT statements to defer describe until execute(). -See [Prepare Postponed Till Execute](#pod_Prepare Postponed Till Execute) for more information. +See ["Prepare Postponed Till Execute"](#Prepare Postponed Till Execute) for more information. -- ora_exe_mode +- ora\_exe\_mode This will set the execute mode of the current statement. Presently only one mode is supported; - OCI_STMT_SCROLLABLE_READONLY - make result set scrollable + OCI_STMT_SCROLLABLE_READONLY - make result set scrollable -See [Scrollable Cursors](#pod_Scrollable Cursors) for more details. +See ["SCROLLABLE CURSORS"](#SCROLLABLE CURSORS) for more details. -- ora_prefetch_rows +- ora\_prefetch\_rows Sets the number of rows to be prefetched. If it is not set, then the -default value is 1. See [Row Prefetching](#pod_Row Prefetching) for more details. +default value is 1. See ["Row Prefetching"](#Row Prefetching) for more details. -- ora_prefetch_memory +- ora\_prefetch\_memory Sets the memory level for rows to be prefetched. The application then -fetches as many rows as will fit into that much memory. See L for more details. +fetches as many rows as will fit into that much memory. See ["Row Prefetching"](#Row Prefetching) for more details. -- ora_row_cache_off +- ora\_row\_cache\_off By default DBD::Oracle will use a row cache when fetching to cut down the number of round trips to the server. If you do not want to use an array fetch set this value to any value other than 0; -See [Row Prefetching](#pod_Row Prefetching) for more details. +See ["Row Prefetching"](#Row Prefetching) for more details. ### __Placeholders__ @@ -1150,18 +1143,18 @@ The first is the "question mark" type, in which each placeholder is represented by a single question mark character. This is the method recommended by the DBI and is the most portable. Each question mark is internally replaced by a "dollar sign number" in the order in -which they appear in the query (important when using [bind_param](#pod_bind_param)). +which they appear in the query (important when using ["bind\_param"](#bind\_param)). The second type of placeholder is "named parameters" in the format ":foo" which is the one Oracle prefers. - $dbh->{RaiseError} = 1; # save having to check each method call - $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); - $sth->bind_param(':name', "John%"); - $sth->execute; - DBI::dump_results($sth); + $dbh->{RaiseError} = 1; # save having to check each method call + $sth = $dbh->prepare("SELECT name, age FROM people WHERE name LIKE :name"); + $sth->bind_param(':name', "John%"); + $sth->execute; + DBI::dump_results($sth); -Note when calling bind_param with named parameters you must include +Note when calling bind\_param with named parameters you must include the leading colon. The advantage of this placeholder type is that you can use the same placeholder more than once in the same SQL statement but you only need to bind it once. @@ -1169,55 +1162,55 @@ but you only need to bind it once. The last placeholder type is a variation of the two above where you name each placeholder :N (where N is a number). Like the named placeholders above you can use the same placeholder multiple times in -the SQL but when you call bind_param you only need to pass the N -(e.g., for :1 you use bind_param(1,...) and not bind_param(':1',...). +the SQL but when you call bind\_param you only need to pass the N +(e.g., for :1 you use bind\_param(1,...) and not bind\_param(':1',...). The different types of placeholders cannot be mixed within a statement, but you may use different ones for each statement handle you have. This is confusing at best, so stick to one style within your program. -## __prepare_cached__ +## __prepare\_cached__ - $sth = $dbh->prepare_cached($statement, \%attr); + $sth = $dbh->prepare_cached($statement, \%attr); Implemented by DBI, no driver-specific impact. This method is most useful if the same query is used over and over as it will cut down round trips to the server. ## __do__ - $rv = $dbh->do($statement); - $rv = $dbh->do($statement, \%attr); - $rv = $dbh->do($statement, \%attr, @bind_values); + $rv = $dbh->do($statement); + $rv = $dbh->do($statement, \%attr); + $rv = $dbh->do($statement, \%attr, @bind_values); Prepare and execute a single statement. Returns the number of rows affected if the query was successful, returns undef if an error occurred, and returns -1 if the number of rows is unknown or not available. Note that this method will return __0E0__ instead of 0 for 'no rows were affected', in order to always return a true value if no error occurred. -## __last_insert_id__ +## __last\_insert\_id__ -Oracle does not implement auto_increment of serial type columns it uses predefined +Oracle does not implement auto\_increment of serial type columns it uses predefined sequences where the id numbers are either selected before insert, at insert time with a trigger, or as part of the query. Below is an example of you to use the latter with the SQL returning clause to get the ID number back -on insert with the bind_param_inout method. +on insert with the bind\_param\_inout method. . - $dbh->do('CREATE SEQUENCE lii_seq START 1'); - $dbh->do(q{CREATE TABLE lii ( - foobar INTEGER NOT NULL UNIQUE, - baz VARCHAR)}); - $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; - $sth = $dbh->prepare($SQL); - my $p_new_id='-1'; - $sth->bind_param_inout(":p_new_id",\$p_new_id,38); - $sth->execute(); - $db->commit(); + $dbh->do('CREATE SEQUENCE lii_seq START 1'); + $dbh->do(q{CREATE TABLE lii ( + foobar INTEGER NOT NULL UNIQUE, + baz VARCHAR)}); + $SQL = "INSERT INTO lii (foobar,baz) VALUES (lii_seq.nextval,'XX') returning foobar into :p_new_id";"; + $sth = $dbh->prepare($SQL); + my $p_new_id='-1'; + $sth->bind_param_inout(":p_new_id",\$p_new_id,38); + $sth->execute(); + $db->commit(); ## __commit__ - $rv = $dbh->commit; + $rv = $dbh->commit; Issues a COMMIT to the server, indicating that the current transaction is finished and that all changes made will be visible to other processes. If AutoCommit is enabled, then @@ -1225,21 +1218,21 @@ a warning is given and no COMMIT is issued. Returns true on success, false on er ## __rollback__ - $rv = $dbh->rollback; + $rv = $dbh->rollback; Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and false on error. -## __begin_work__ +## __begin\_work__ -This method turns on transactions until the next call to [commit](#pod_commit) or [rollback](#pod_rollback), if [AutoCommit](#pod_AutoCommit) is -currently enabled. If it is not enabled, calling begin_work will issue an error. Note that the -transaction will not actually begin until the first statement after begin_work is called. +This method turns on transactions until the next call to ["commit"](#commit) or ["rollback"](#rollback), if ["AutoCommit"](#AutoCommit) is +currently enabled. If it is not enabled, calling begin\_work will issue an error. Note that the +transaction will not actually begin until the first statement after begin\_work is called. ## __disconnect__ - $rv = $dbh->disconnect; + $rv = $dbh->disconnect; Disconnects from the Oracle database. Any uncommitted changes will be rolled back upon disconnection. It's good policy to always explicitly call commit or rollback at some point before disconnecting, rather than @@ -1251,42 +1244,42 @@ methods automatically. It is best to explicitly disconnect rather than rely on t ## __ping__ - $rv = $dbh->ping; + $rv = $dbh->ping; This `ping` method is used to check the validity of a database handle. The value returned is either 0, indicating that the connection is no longer valid, or 1, indicating the connection is valid. This function does 1 round trip to the Oracle Server. -## __get_info()__ +## __get\_info()__ - $value = $dbh->get_info($info_type); + $value = $dbh->get_info($info_type); DBD::Oracle supports `get_info()`, but (currently) only a few info types. -## __table_info()__ +## __table\_info()__ DBD::Oracle supports attributes for `table_info()`. In Oracle, the concept of _user_ and _schema_ is (currently) the same. Because database objects are owned by an user, the owner names in the data dictionary views correspond to schema names. -Oracle does not support catalogues so TABLE_CAT is ignored as +Oracle does not support catalogues so TABLE\_CAT is ignored as selection criterion. -Search patterns are supported for TABLE_SCHEM and TABLE_NAME. +Search patterns are supported for TABLE\_SCHEM and TABLE\_NAME. -TABLE_TYPE may contain a comma-separated list of table types. +TABLE\_TYPE may contain a comma-separated list of table types. The following table types are supported: - TABLE - VIEW - SYNONYM - SEQUENCE + TABLE + VIEW + SYNONYM + SEQUENCE -The result set is ordered by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME. +The result set is ordered by TABLE\_TYPE, TABLE\_SCHEM, TABLE\_NAME. The special enumerations of catalogues, schemas and table types are -supported. However, TABLE_CAT is always NULL. +supported. However, TABLE\_CAT is always NULL. An identifier is passed _as is_, i.e. as the user provides or Oracle returns it. @@ -1300,124 +1293,124 @@ upper case). Oracle stores and returns it as given. `table_info()` has no special quote handling, neither adds nor removes quotes. -## __primary_key_info()__ +## __primary\_key\_info()__ -Oracle does not support catalogues so TABLE_CAT is ignored as +Oracle does not support catalogues so TABLE\_CAT is ignored as selection criterion. -The TABLE_CAT field of a fetched row is always NULL (undef). -See [table_info()](#pod_table_info()) for more detailed information. +The TABLE\_CAT field of a fetched row is always NULL (undef). +See ["table\_info()"](#table\_info()) for more detailed information. If the primary key constraint was created without an identifier, -PK_NAME contains a system generated name with the form SYS_Cn. +PK\_NAME contains a system generated name with the form SYS\_Cn. -The result set is ordered by TABLE_SCHEM, TABLE_NAME, KEY_SEQ. +The result set is ordered by TABLE\_SCHEM, TABLE\_NAME, KEY\_SEQ. An identifier is passed _as is_, i.e. as the user provides or Oracle returns it. -See [table_info()](#pod_table_info()) for more detailed information. +See ["table\_info()"](#table\_info()) for more detailed information. -## __foreign_key_info()__ +## __foreign\_key\_info()__ This method (currently) supports the extended behaviour of SQL/CLI, i.e. the result set contains foreign keys that refer to primary __and__ alternate keys. -The field UNIQUE_OR_PRIMARY distinguishes these keys. +The field UNIQUE\_OR\_PRIMARY distinguishes these keys. Oracle does not support catalogues, so `$pk_catalog` and `$fk_catalog` are ignored as selection criteria (in the new style interface). -The UK_TABLE_CAT and FK_TABLE_CAT fields of a fetched row are always +The UK\_TABLE\_CAT and FK\_TABLE\_CAT fields of a fetched row are always NULL (undef). -See [table_info()](#pod_table_info()) for more detailed information. +See ["table\_info()"](#table\_info()) for more detailed information. If the primary or foreign key constraints were created without an identifier, -UK_NAME or FK_NAME contains a system generated name with the form SYS_Cn. +UK\_NAME or FK\_NAME contains a system generated name with the form SYS\_Cn. -The UPDATE_RULE field is always 3 ('NO ACTION'), because Oracle (currently) +The UPDATE\_RULE field is always 3 ('NO ACTION'), because Oracle (currently) does not support other actions. -The DELETE_RULE field may contain wrong values. This is a known Bug (#1271663) +The DELETE\_RULE field may contain wrong values. This is a known Bug (\#1271663) in Oracle's data dictionary views. Currently (as of 8.1.7), 'RESTRICT' and 'SET DEFAULT' are not supported, 'CASCADE' is mapped correctly and all other actions (incl. 'SET NULL') appear as 'NO ACTION'. The DEFERABILITY field is always NULL, because this columns is -not present in the ALL_CONSTRAINTS view of older Oracle releases. +not present in the ALL\_CONSTRAINTS view of older Oracle releases. -The result set is ordered by UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, -FK_TABLE_NAME, ORDINAL_POSITION. +The result set is ordered by UK\_TABLE\_SCHEM, UK\_TABLE\_NAME, FK\_TABLE\_SCHEM, +FK\_TABLE\_NAME, ORDINAL\_POSITION. An identifier is passed _as is_, i.e. as the user provides or Oracle returns it. -See [table_info()](#pod_table_info()) for more detailed information. +See ["table\_info()"](#table\_info()) for more detailed information. -## __column_info()__ +## __column\_info()__ -Oracle does not support catalogues so TABLE_CAT is ignored as +Oracle does not support catalogues so TABLE\_CAT is ignored as selection criterion. -The TABLE_CAT field of a fetched row is always NULL (undef). -See [table_info()](#pod_table_info()) for more detailed information. +The TABLE\_CAT field of a fetched row is always NULL (undef). +See ["table\_info()"](#table\_info()) for more detailed information. -The CHAR_OCTET_LENGTH field is (currently) always NULL (undef). +The CHAR\_OCTET\_LENGTH field is (currently) always NULL (undef). -Don't rely on the values of the BUFFER_LENGTH field! +Don't rely on the values of the BUFFER\_LENGTH field! Especially the length of FLOATs may be wrong. Datatype codes for non-standard types are subject to change. -Attention! The DATA_DEFAULT (COLUMN_DEF) column is of type LONG so you +Attention! The DATA\_DEFAULT (COLUMN\_DEF) column is of type LONG so you may have to set LongReadLen on the connection handle before calling -column_info if you have a large default column. After DBD::Oracle 1.40 -LongReadLen is set automatically to 1Mb when calling column_info and +column\_info if you have a large default column. After DBD::Oracle 1.40 +LongReadLen is set automatically to 1Mb when calling column\_info and reset aftwerwards. -The result set is ordered by TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION. +The result set is ordered by TABLE\_SCHEM, TABLE\_NAME, ORDINAL\_POSITION. An identifier is passed _as is_, i.e. as the user provides or Oracle returns it. -See [table_info()](#pod_table_info()) for more detailed information. +See ["table\_info()"](#table\_info()) for more detailed information. It is possible with Oracle to make the names of the various DB objects (table,column,index etc) case sensitive. - alter table bloggind add ("Bla_BLA" NUMBER) + alter table bloggind add ("Bla_BLA" NUMBER) -So in the example the exact case "Bla_BLA" must be used to get it info on the column. While this +So in the example the exact case "Bla\_BLA" must be used to get it info on the column. While this - alter table bloggind add (Bla_BLA NUMBER) + alter table bloggind add (Bla_BLA NUMBER) any case can be used to get info on the column. -## __selectrow_array__ +## __selectrow\_array__ - @row_ary = $dbh->selectrow_array($sql); - @row_ary = $dbh->selectrow_array($sql, \%attr); - @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); + @row_ary = $dbh->selectrow_array($sql); + @row_ary = $dbh->selectrow_array($sql, \%attr); + @row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values); Returns an array of row information after preparing and executing the provided SQL string. The rows are returned -by calling [fetchrow_array](#pod_fetchrow_array). The string can also be a statement handle generated by a previous prepare. Note that +by calling ["fetchrow\_array"](#fetchrow\_array). The string can also be a statement handle generated by a previous prepare. Note that only the first row of data is returned. If called in a scalar context, only the first column of the first row is returned. Because this is not portable, it is not recommended that you use this method in that way. -## __selectrow_arrayref__ +## __selectrow\_arrayref__ - $ary_ref = $dbh->selectrow_arrayref($statement); - $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); - $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); + $ary_ref = $dbh->selectrow_arrayref($statement); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr); + $ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values); -Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an array, by internal use of -the [fetchrow_arrayref](#pod_fetchrow_arrayref) method. +Exactly the same as ["selectrow\_array"](#selectrow\_array), except that it returns a reference to an array, by internal use of +the ["fetchrow\_arrayref"](#fetchrow\_arrayref) method. -## __selectrow_hashref__ +## __selectrow\_hashref__ - $hash_ref = $dbh->selectrow_hashref($sql); - $hash_ref = $dbh->selectrow_hashref($sql, \%attr); - $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); + $hash_ref = $dbh->selectrow_hashref($sql); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr); + $hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values); -Exactly the same as [selectrow_array](#pod_selectrow_array), except that it returns a reference to an hash, by internal use of -the [fetchrow_hashref](#pod_fetchrow_hashref) method. +Exactly the same as ["selectrow\_array"](#selectrow\_array), except that it returns a reference to an hash, by internal use of +the ["fetchrow\_hashref"](#fetchrow\_hashref) method. ## __clone__ - $other_dbh = $dbh->clone(); + $other_dbh = $dbh->clone(); Creates a copy of the database handle by connecting with the same parameters as the original handle, then trying to merge the attributes. See the DBI documentation for complete usage. @@ -1428,11 +1421,11 @@ handle, then trying to merge the attributes. See the DBI documentation for compl Supported by DBD::Oracle as proposed by DBI.The default of AutoCommit is on, but this may change in the future, so it is highly recommended that you explicitly set it when -calling [connect](#pod_connect). +calling ["connect"](#connect). ## __ReadOnly__ (boolean) - $dbh->{ReadOnly} = 1; + $dbh->{ReadOnly} = 1; Specifies if the current database connection should be in read-only mode or not. @@ -1456,7 +1449,7 @@ Returns the name of the user connected to the database. Holds the handle of the parent driver. The only recommended use for this is to find the name of the driver using: - $dbh->{Driver}->{Name} + $dbh->{Driver}->{Name} ## __RowCacheSize__ @@ -1485,46 +1478,46 @@ caching still works. If you are only selecting a LOB Locator then Row Caching w ### Row Prefetching Row prefetching occurs on the server side and uses the DBI database handle attribute `RowCacheSize` and or the -Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improved performance. +Prepare Attribute 'ora\_prefetch\_memory'. Tweaking these values may yield improved performance. - $dbh->{RowCacheSize} = 100; - $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); + $dbh->{RowCacheSize} = 100; + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first -fetch that sets the current_positon to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are +fetch that sets the current\_positon to any value other than 0. In the above example if we do a OCI\_FETCH\_FIRST the first 10 rows are loaded into the buffer and DBD::Oracle will not have to go back to the server for more rows. When record 11 is fetched DBD::Oracle fetches and returns this row and the next 9 rows are loaded into the buffer. In this case if you fetch backwards from 10 to 1 no server round trips are made. With large record sets it is best not to attempt to go to the last record as this may take some time, A large buffer size might even slow down -the fetch. If you must get the number of rows in a large record set you might try using an few large OCI_FETCH_ABSOLUTEs and then an OCI_FETCH_LAST, -this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI_FETCH_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. +the fetch. If you must get the number of rows in a large record set you might try using an few large OCI\_FETCH\_ABSOLUTEs and then an OCI\_FETCH\_LAST, +this might save some time. So if you had a record set of 10000 rows and you set the buffer to 5000 and did a OCI\_FETCH\_LAST one would fetch the first 5000 rows into the buffer then the next 5000 rows. If one requires only the first few rows there is no need to set a large prefetch value. -If the ora_prefetch_memory less than 1 or not present then memory size is not included in computing the +If the ora\_prefetch\_memory less than 1 or not present then memory size is not included in computing the number of rows to prefetch otherwise the number of rows will be limited to memory size. Likewise if the RowCacheSize is less than 1 it is not included in the computing of the prefetch rows. # ORACLE-SPECIFIC STATEMENT HANDLE METHODS -## __ora_stmt_type__ +## __ora\_stmt\_type__ Returns the OCI Statement Type number for the SQL of a statement handle. -## __ora_stmt_type_name__ +## __ora\_stmt\_type\_name__ Returns the OCI Statement Type name for the SQL of a statement handle. # DBI STATEMENT HANDLE OBJECT METHODS -## __bind_param__ +## __bind\_param__ - $rv = $sth->bind_param($param_num, $bind_value); - $rv = $sth->bind_param($param_num, $bind_value, $bind_type); - $rv = $sth->bind_param($param_num, $bind_value, \%attr); + $rv = $sth->bind_param($param_num, $bind_value); + $rv = $sth->bind_param($param_num, $bind_value, $bind_type); + $rv = $sth->bind_param($param_num, $bind_value, \%attr); Allows the user to bind a value and/or a data type to a placeholder. @@ -1540,26 +1533,26 @@ The default value is "varchar". If you need something else, you must use one of the values provided by DBI or by DBD::Pg. To use a SQL value, modify your "use DBI" statement at the top of your script as follows: - use DBI qw(:sql_types); + use DBI qw(:sql_types); This will import some constants into your script. You can plug those -directly into the [bind_param](#pod_bind_param) call. Some common ones that you will +directly into the ["bind\_param"](#bind\_param) call. Some common ones that you will encounter are: - SQL_INTEGER + SQL_INTEGER To use Oracle SQL data types, import the list of values like this: - use DBD::Pg qw(:ora_types); + use DBD::Pg qw(:ora_types); You can then set the data types by setting the value of the `ora_type` -key in the hash passed to [bind_param](#pod_bind_param). +key in the hash passed to ["bind\_param"](#bind\_param). The current list of Oracle data types exported is: - ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW - ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB - ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI - SQLT_CHR SQLT_BIN + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE ORA_RAW + ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE ORA_CLOB ORA_BLOB + ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI + SQLT_CHR SQLT_BIN Data types are "sticky," in that once a data type is set to a certain placeholder, it will remain for that placeholder, unless it is explicitly set to something @@ -1569,42 +1562,42 @@ doing the next execute. Examples: - use DBI qw(:sql_types); - use DBD::Pg qw(:ora_types); + use DBI qw(:sql_types); + use DBD::Pg qw(:ora_types); - $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; - $sth = $dbh->prepare($SQL); + $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; + $sth = $dbh->prepare($SQL); - ## Both arguments below are bound to placeholders as "varchar" - $sth->execute(123, "Merk"); + ## Both arguments below are bound to placeholders as "varchar" + $sth->execute(123, "Merk"); - ## Reset the datatype for the first placeholder to an integer - $sth->bind_param(1, undef, SQL_INTEGER); + ## Reset the datatype for the first placeholder to an integer + $sth->bind_param(1, undef, SQL_INTEGER); - ## The "undef" bound above is not used, since we supply params to execute - $sth->execute(123, "Merk"); + ## The "undef" bound above is not used, since we supply params to execute + $sth->execute(123, "Merk"); - ## Set the first placeholder's value and data type - $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); + ## Set the first placeholder's value and data type + $sth->bind_param(1, 234, { pg_type => ORA_NUMBER }); - ## Set the second placeholder's value and data type. - ## We don't send a third argument, so the default "varchar" is used - $sth->bind_param('$2', "Zool"); + ## Set the second placeholder's value and data type. + ## We don't send a third argument, so the default "varchar" is used + $sth->bind_param('$2', "Zool"); - ## We realize that the wrong data type was set above, so we change it: - $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); + ## We realize that the wrong data type was set above, so we change it: + $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER }); - ## We also got the wrong value, so we change that as well. - ## Because the data type is sticky, we don't need to change it - $sth->bind_param(1, 567); + ## We also got the wrong value, so we change that as well. + ## Because the data type is sticky, we don't need to change it + $sth->bind_param(1, 567); - ## This executes the statement with 567 (integer) and "Zool" (varchar) - $sth->execute(); + ## This executes the statement with 567 (integer) and "Zool" (varchar) + $sth->execute(); These attributes may be used in the `\%attr` parameter of the -L or L statement handle methods. +["bind\_param" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param) or ["bind\_param\_inout" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param\_inout) statement handle methods. -- ora_type +- ora\_type Specify the placeholder's datatype using an Oracle datatype. A fatal error is raised if `ora_type` and the DBI `TYPE` attribute @@ -1613,61 +1606,61 @@ Some of these types are not supported by the current version of DBD::Oracle and will cause a fatal error if used. Constants for the Oracle datatypes may be imported using - use DBD::Oracle qw(:ora_types); + use DBD::Oracle qw(:ora_types); Potentially useful values when DBD::Oracle was built using OCI 7 and later: - ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, - ORA_CHAR, ORA_MLSLABEL, ORA_RSET + ORA_VARCHAR2, ORA_STRING, ORA_LONG, ORA_RAW, ORA_LONGRAW, + ORA_CHAR, ORA_MLSLABEL, ORA_RSET Additional values when DBD::Oracle was built using OCI 8 and later: - ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE + ORA_CLOB, ORA_BLOB, ORA_XMLTYPE, ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE Additional values when DBD::Oracle was built using OCI 9.2 and later: - SQLT_CHR, SQLT_BIN + SQLT_CHR, SQLT_BIN -See [Binding Cursors](#pod_Binding Cursors) for the correct way to use ORA_RSET. +See ["Binding Cursors"](#Binding Cursors) for the correct way to use ORA\_RSET. -See [LOBs and LONGs](#pod_LOBs and LONGs) for how to use ORA_CLOB and ORA_BLOB. +See ["LOBS AND LONGS"](#LOBS AND LONGS) for how to use ORA\_CLOB and ORA\_BLOB. -See [SYS.DBMS_SQL datatypes](#pod_SYS.DBMS_SQL datatypes) for ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. +See ["SYS.DBMS\_SQL datatypes"](#SYS.DBMS\_SQL datatypes) for ORA\_VARCHAR2\_TABLE, ORA\_NUMBER\_TABLE. -See [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) for the correct way to use SQLT_CHR and SQLT_BIN. +See ["Data Interface for Persistent LOBs"](#Data Interface for Persistent LOBs) for the correct way to use SQLT\_CHR and SQLT\_BIN. -See [Other Data Types](#pod_Other Data Types) for more information. +See ["OTHER DATA TYPES"](#OTHER DATA TYPES) for more information. -See also L. +See also ["Placeholders and Bind Values" in DBI](http://search.cpan.org/perldoc?DBI#Placeholders and Bind Values). -- ora_csform +- ora\_csform -Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values -are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can +Specify the OCI\_ATTR\_CHARSET\_FORM for the bind value. Valid values +are SQLCS\_IMPLICIT (1) and SQLCS\_NCHAR (2). Both those constants can be imported from the DBD::Oracle module. Rarely needed. -- ora_csid +- ora\_csid -Specify the _integer_ OCI_ATTR_CHARSET_ID for the bind value. +Specify the _integer_ OCI\_ATTR\_CHARSET\_ID for the bind value. Character set names can't be used currently. -- ora_maxdata_size +- ora\_maxdata\_size -Specify the integer OCI_ATTR_MAXDATA_SIZE for the bind value. +Specify the integer OCI\_ATTR\_MAXDATA\_SIZE for the bind value. May be needed if a character set conversion from client to server causes the data to use more space and so fail with a truncation error. -- ora_maxarray_numentries +- ora\_maxarray\_numentries Specify the maximum number of array entries to allocate. Used with -ORA_VARCHAR2_TABLE, ORA_NUMBER_TABLE. Define the maximum number of +ORA\_VARCHAR2\_TABLE, ORA\_NUMBER\_TABLE. Define the maximum number of array entries Oracle can pass back to you in OUT variable of type TABLE OF ... . -- ora_internal_type +- ora\_internal\_type Specify internal data representation. Currently is supported only for -ORA_NUMBER_TABLE. +ORA\_NUMBER\_TABLE. ### Optimizing Results @@ -1677,7 +1670,7 @@ The DBD::Oracle module can avoid an explicit 'describe' operation prior to the execution of the statement unless the application requests information about the results (such as $sth->{NAME}). This reduces communication with the server and increases performance (reducing the -number of PARSE_CALLS inside the server). +number of PARSE\_CALLS inside the server). However, it also means that SQL errors are not detected until `execute()` (or $sth->{NAME} etc) is called instead of when @@ -1685,13 +1678,13 @@ However, it also means that SQL errors are not detected until use of $sth->{NAME} or a similar attribute and the describe fails then _an exception is thrown_ even if `RaiseError` is false! -Set [ora_check_sql](#pod_ora_check_sql) to 0 in prepare() to enable this behaviour. +Set ["ora\_check\_sql"](#ora\_check\_sql) to 0 in prepare() to enable this behaviour. -## __bind_param_inout__ +## __bind\_param\_inout__ - $rv = $sth->bind_param_inout($param_num, \$scalar, 0); + $rv = $sth->bind_param_inout($param_num, \$scalar, 0); -DBD::Oracle fully supports bind_param_inout below are some uses for this method. +DBD::Oracle fully supports bind\_param\_inout below are some uses for this method. ### __Returning A Value from an INSERT__ @@ -1700,50 +1693,47 @@ or more of the values inserted. This can be particularly useful for single-pass insertion of values with re-used sequence values (avoiding a separate "select seq.nextval from dual" step). - $sth = $dbh->prepare(qq{ - INSERT INTO foo (id, bar) - VALUES (foo_id_seq.nextval, :bar) - RETURNING id INTO :id - }); - $sth->bind_param(":bar", 42); - $sth->bind_param_inout(":id", \my $new_id, 99); - $sth->execute; - print "The id of the new record is $new_id\n"; + $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, :bar) + RETURNING id INTO :id + }); + $sth->bind_param(":bar", 42); + $sth->bind_param_inout(":id", \my $new_id, 99); + $sth->execute; + print "The id of the new record is $new_id\n"; If you have many columns to bind you can use code like this: - @params = (... column values for record to be inserted ...); - $sth->bind_param($_, $params[$_-1]) for (1..@params); - $sth->bind_param_inout(@params+1, \my $new_id, 99); - $sth->execute; + @params = (... column values for record to be inserted ...); + $sth->bind_param($_, $params[$_-1]) for (1..@params); + $sth->bind_param_inout(@params+1, \my $new_id, 99); + $sth->execute; If you have many rows to insert you can take advantage of Oracle's built in execute array feature with code like this: - my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); - my @out_values; - my @status; - my $sth = $dbh->prepare(qq{ - INSERT INTO foo (id, bar) - VALUES (foo_id_seq.nextval, ?) - RETURNING id INTO ? - }); - $sth->bind_param_array(1,\@in_values); - $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); - $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; - foreach my $id (@out_values){ + my @in_values=('1',2,'3','4',5,'6',7,'8',9,'10'); + my @out_values; + my @status; + my $sth = $dbh->prepare(qq{ + INSERT INTO foo (id, bar) + VALUES (foo_id_seq.nextval, ?) + RETURNING id INTO ? + }); + $sth->bind_param_array(1,\@in_values); + $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); + $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; + foreach my $id (@out_values){ print 'returned id='.$id.'\n'; - } + } -Which will return all the ids into @out_values. +Which will return all the ids into @out\_values. - __Note:__ - - This will only work for numbered (?) placeholders, - -- The third parameter of bind_param_inout_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle - -- The "ora_type" attribute is not needed but only ORA_VARCHAR2 will work. +- The third parameter of bind\_param\_inout\_array, (0 in the example), "maxlen" is required by DBI but not used by DBD::Oracle +- The "ora\_type" attribute is not needed but only ORA\_VARCHAR2 will work. ### Returning A Recordset @@ -1755,90 +1745,90 @@ or later, you can make use of table (or pipelined) functions. For example, assume you have the existing PL/SQL Package : - CREATE OR REPLACE PACKAGE Array_Example AS + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS -- - TYPE tRec IS RECORD ( - Col1 NUMBER, - Col2 VARCHAR2 (10), - Col3 DATE) ; + FUNCTION Array_Func RETURN taRec AS -- - TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + l_Ret taRec ; -- - FUNCTION Array_Func RETURN taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + END LOOP ; + RETURN l_Ret ; + END ; -- - END Array_Example ; - - CREATE OR REPLACE PACKAGE BODY Array_Example AS - -- - FUNCTION Array_Func RETURN taRec AS - -- - l_Ret taRec ; - -- - BEGIN - FOR i IN 1 .. 5 LOOP - l_Ret (i).Col1 := i ; - l_Ret (i).Col2 := 'Row : ' || i ; - l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; - END LOOP ; - RETURN l_Ret ; - END ; - -- - END Array_Example ; - / + END Array_Example ; + / Currently, there is no way to directly call the function -Array_Example.Array_Func from DBI. However, by making the following relatively +Array\_Example.Array\_Func from DBI. However, by making the following relatively painless additions, its not only possible, but extremely efficient. First, you need to create database object types that correspond to the record and table types in the package. From the above example, these would be : - CREATE OR REPLACE TYPE tArray_Example__taRec - AS OBJECT ( - Col1 NUMBER, - Col2 VARCHAR2 (10), - Col3 DATE - ) ; + CREATE OR REPLACE TYPE tArray_Example__taRec + AS OBJECT ( + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE + ) ; - CREATE OR REPLACE TYPE taArray_Example__taRec - AS TABLE OF tArray_Example__taRec ; + CREATE OR REPLACE TYPE taArray_Example__taRec + AS TABLE OF tArray_Example__taRec ; Now, assuming the existing function needs to remain unchanged (it is probably being called from other PL/SQL code), we need to add a new function to the package. Here's the new package specification and body : - CREATE OR REPLACE PACKAGE Array_Example AS - -- - TYPE tRec IS RECORD ( + CREATE OR REPLACE PACKAGE Array_Example AS + -- + TYPE tRec IS RECORD ( Col1 NUMBER, Col2 VARCHAR2 (10), Col3 DATE) ; - -- - TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; - -- - FUNCTION Array_Func RETURN taRec ; - FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; - -- - END Array_Example ; - - CREATE OR REPLACE PACKAGE BODY Array_Example AS - -- - FUNCTION Array_Func RETURN taRec AS - l_Ret taRec ; - BEGIN - FOR i IN 1 .. 5 LOOP + -- + TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; + -- + FUNCTION Array_Func RETURN taRec ; + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED ; + -- + END Array_Example ; + + CREATE OR REPLACE PACKAGE BODY Array_Example AS + -- + FUNCTION Array_Func RETURN taRec AS + l_Ret taRec ; + BEGIN + FOR i IN 1 .. 5 LOOP l_Ret (i).Col1 := i ; l_Ret (i).Col2 := 'Row : ' || i ; l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; - END LOOP ; - RETURN l_Ret ; - END ; + END LOOP ; + RETURN l_Ret ; + END ; - FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS - l_Set taRec ; - BEGIN - l_Set := Array_Func ; - FOR i IN l_Set.FIRST .. l_Set.LAST LOOP + FUNCTION Array_Func_DBI RETURN taArray_Example__taRec PIPELINED AS + l_Set taRec ; + BEGIN + l_Set := Array_Func ; + FOR i IN l_Set.FIRST .. l_Set.LAST LOOP PIPE ROW ( tArray_Example__taRec ( l_Set (i).Col1, @@ -1846,26 +1836,26 @@ package. Here's the new package specification and body : l_Set (i).Col3 ) ) ; - END LOOP ; - RETURN ; - END ; - -- - END Array_Example ; + END LOOP ; + RETURN ; + END ; + -- + END Array_Example ; As you can see, the new function is very simple. Now, it is a simple matter of calling the function as a straight-forward SELECT from your DBI code. From the above example, the code would look something like this : - my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); - $sth->execute; - while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { - ... - } + my $sth = $dbh->prepare('SELECT * FROM TABLE(Array_Example.Array_Func_DBI)'); + $sth->execute; + while ( my ($col1, $col2, $col3) = $sth->fetchrow_array { + ... + } -### __SYS.DBMS_SQL datatypes__ +### __SYS.DBMS\_SQL datatypes__ -DBD::Oracle has built-in support for __SYS.DBMS_SQL.VARCHAR2_TABLE__ -and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: +DBD::Oracle has built-in support for __SYS.DBMS\_SQL.VARCHAR2\_TABLE__ +and __SYS.DBMS\_SQL.NUMBER\_TABLE__ datatypes. The simple example is here: my $statement=' DECLARE @@ -1893,43 +1883,42 @@ and __SYS.DBMS_SQL.NUMBER_TABLE__ datatypes. The simple example is here: "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; - __Note:__ - -- Take careful note that we use '\\@arr' here because the 'bind_param_inout' +- Take careful note that we use '\\\\@arr' here because the 'bind\_param\_inout' will only take a reference to a scalar. -### __ORA_VARCHAR2_TABLE__ +### __ORA\_VARCHAR2\_TABLE__ -SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. -( in bind_param() and bind_param_inout() ). When you bind array, you need +SYS.DBMS\_SQL.VARCHAR2\_TABLE object is always bound to array reference. +( in bind\_param() and bind\_param\_inout() ). When you bind array, you need to specify full buffer size for OUT data. So, there are two parameters: -_max_len_ (specified as 3rd argument of bind_param_inout() ), -and _ora_maxarray_numentries_. They define maximum array entry length and +_max\_len_ (specified as 3rd argument of bind\_param\_inout() ), +and _ora\_maxarray\_numentries_. They define maximum array entry length and maximum rows, that can be passed to Oracle and back to you. In this example we send array with 1 element with length=3, but allocate space for 100 Oracle array entries with maximum length 10 of each. So, you can get no more than 100 array entries with length <= 10. -If you set _max_len_ to zero, maximum array entry length is calculated -as maximum length of entry of array bound. If 0 < _max_len_ < length( $some_element ), +If you set _max\_len_ to zero, maximum array entry length is calculated +as maximum length of entry of array bound. If 0 < _max\_len_ < length( $some\_element ), truncation occur. -If you set _ora_maxarray_numentries_ to zero, current (at bind time) bound -array length is used as maximum. If 0 < _ora_maxarray_numentries_ < scalar(@array), +If you set _ora\_maxarray\_numentries_ to zero, current (at bind time) bound +array length is used as maximum. If 0 < _ora\_maxarray\_numentries_ < scalar(@array), not all array entries are bound. -### __ORA_NUMBER_TABLE__ +### __ORA\_NUMBER\_TABLE__ -SYS.DBMS_SQL.NUMBER_TABLE object handling is much alike ORA_VARCHAR2_TABLE. +SYS.DBMS\_SQL.NUMBER\_TABLE object handling is much alike ORA\_VARCHAR2\_TABLE. The main difference is internal data representation. Currently 2 types of bind is allowed : as C-integer, or as C-double type. To select one of them, -you may specify additional bind parameter _ora_internal_type_ as either -__SQLT_INT__ or __SQLT_FLT__ for C-integer and C-double types. +you may specify additional bind parameter _ora\_internal\_type_ as either +__SQLT\_INT__ or __SQLT\_FLT__ for C-integer and C-double types. Integer size is architecture-specific and is usually 32 or 64 bit. Double is standard IEEE 754 type. -_ora_internal_type_ defaults to double (SQLT_FLT). +_ora\_internal\_type_ defaults to double (SQLT\_FLT). -_max_len_ is ignored for OCI_NUMBER_TABLE. +_max\_len_ is ignored for OCI\_NUMBER\_TABLE. Currently, you cannot bind full native Oracle NUMBER(38). If you really need, send request to dbi-dev list. @@ -1986,7 +1975,7 @@ The result is like: '-2' ]; -If you change bind type to __SQLT_INT__, like: +If you change bind type to __SQLT\_INT__, like: ora_internal_type => SQLT_INT @@ -2001,135 +1990,135 @@ you get: -2 ]; -## __bind_param_inout_array__ +## __bind\_param\_inout\_array__ -DBD::Oracle supports this undocumented feature of DBI. See [Returning A Value from an INSERT](#pod_Returning A Value from an INSERT) for an example. +DBD::Oracle supports this undocumented feature of DBI. See ["Returning A Value from an INSERT"](#Returning A Value from an INSERT) for an example. -## __bind_param_array__ +## __bind\_param\_array__ - $rv = $sth->bind_param_array($param_num, $array_ref_or_value) - $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) - $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type) + $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr) Binds an array of values to a placeholder, so that each is used in turn by a call -to the [execute_array](#pod_execute_array) method. +to the ["execute\_array"](#execute\_array) method. ## __execute__ - $rv = $sth->execute(@bind_values); + $rv = $sth->execute(@bind_values); Perform whatever processing is necessary to execute the prepared statement. -## __execute_array__ +## __execute\_array__ - $tuples = $sth->execute_array() or die $sth->errstr; - $tuples = $sth->execute_array(\%attr) or die $sth->errstr; - $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + $tuples = $sth->execute_array() or die $sth->errstr; + $tuples = $sth->execute_array(\%attr) or die $sth->errstr; + $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; - ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; - ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr; + ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr; Execute a prepared statement once for each item in a passed-in hashref, or items that -were previously bound via the [bind_param_array](#pod_bind_param_array) method. See the DBI documentation +were previously bound via the ["bind\_param\_array"](#bind\_param\_array) method. See the DBI documentation for more details. DBD::Oracle takes full advantage of OCI's array interface so inserts and updates using this interface will run very quickly. -## __execute_for_fetch__ +## __execute\_for\_fetch__ - $tuples = $sth->execute_for_fetch($fetch_tuple_sub); - $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub); + $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); - ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); - ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub); + ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status); -Used internally by the [execute_array](#pod_execute_array) method, and rarely used directly. See the +Used internally by the ["execute\_array"](#execute\_array) method, and rarely used directly. See the DBI documentation for more details. -## __fetchrow_arrayref__ +## __fetchrow\_arrayref__ - $ary_ref = $sth->fetchrow_arrayref; + $ary_ref = $sth->fetchrow_arrayref; Fetches the next row of data from the statement handle, and returns a reference to an array holding the column values. Any columns that are NULL are returned as undef within the array. If there are no more rows or if an error occurs, the this method return undef. You should -check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +check `$sth->err` afterwards (or use the ["RaiseError"](#RaiseError) attribute) to discover if the undef returned was due to an error. Note that the same array reference is returned for each fetch, so don't store the reference and then use it after a later fetch. Also, the elements of the array are also reused for each row, -so take care if you want to take a reference to an element. See also [bind_columns](#pod_bind_columns). +so take care if you want to take a reference to an element. See also ["bind\_columns"](#bind\_columns). -## __fetchrow_array__ +## __fetchrow\_array__ - @ary = $sth->fetchrow_array; + @ary = $sth->fetchrow_array; -Similar to the [fetchrow_arrayref](#pod_fetchrow_arrayref) method, but returns a list of column information rather than +Similar to the ["fetchrow\_arrayref"](#fetchrow\_arrayref) method, but returns a list of column information rather than a reference to a list. Do not use this in a scalar context. -## __fetchrow_hashref__ +## __fetchrow\_hashref__ - $hash_ref = $sth->fetchrow_hashref; - $hash_ref = $sth->fetchrow_hashref($name); + $hash_ref = $sth->fetchrow_hashref; + $hash_ref = $sth->fetchrow_hashref($name); Fetches the next row of data and returns a hashref containing the name of the columns as the keys and the data itself as the values. Any NULL value is returned as as undef value. If there are no more rows or if an error occurs, the this method return undef. You should -check `$sth->err` afterwards (or use the [RaiseError](#pod_RaiseError) attribute) to discover if the undef returned +check `$sth->err` afterwards (or use the ["RaiseError"](#RaiseError) attribute) to discover if the undef returned was due to an error. The optional `$name` argument should be either `NAME`, `NAME_lc` or `NAME_uc`, and indicates what sort of transformation to make to the keys in the hash. By default Oracle uses upper case. -## __fetchall_arrayref__ +## __fetchall\_arrayref__ - $tbl_ary_ref = $sth->fetchall_arrayref(); - $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); - $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); + $tbl_ary_ref = $sth->fetchall_arrayref(); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice ); + $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows ); Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, the data read in so far will be returned. Because of this, you should always check `$sth->err` after -calling this method, unless [RaiseError](#pod_RaiseError) has been enabled. +calling this method, unless ["RaiseError"](#RaiseError) has been enabled. -If `$slice` is an array reference, fetchall_arrayref uses the [fetchrow_arrayref](#pod_fetchrow_arrayref) method to fetch each +If `$slice` is an array reference, fetchall\_arrayref uses the ["fetchrow\_arrayref"](#fetchrow\_arrayref) method to fetch each row as an array ref. If the `$slice` array is not empty then it is used as a slice to select individual columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). -With no parameters, or if $slice is undefined, fetchall_arrayref acts as if passed an empty array ref. +With no parameters, or if $slice is undefined, fetchall\_arrayref acts as if passed an empty array ref. -If `$slice` is a hash reference, fetchall_arrayref uses [fetchrow_hashref](#pod_fetchrow_hashref) to fetch each row as a hash reference. +If `$slice` is a hash reference, fetchall\_arrayref uses ["fetchrow\_hashref"](#fetchrow\_hashref) to fetch each row as a hash reference. See the DBI documentation for a complete discussion. -## __fetchall_hashref__ +## __fetchall\_hashref__ - $hash_ref = $sth->fetchall_hashref( $key_field ); + $hash_ref = $sth->fetchall_hashref( $key_field ); Returns a hashref containing all rows to be fetched from the statement handle. See the DBI documentation for a full discussion. ## __finish__ - $rv = $sth->finish; + $rv = $sth->finish; Indicates to DBI that you are finished with the statement handle and are not going to use it again. Only needed when you have not fetched all the possible rows. ## __rows__ - $rv = $sth->rows; + $rv = $sth->rows; Returns the number of rows affected for updates, deletes and inserts and -1 for selects. -## __bind_col__ +## __bind\_col__ - $rv = $sth->bind_col($column_number, \$var_to_bind); - $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); - $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); + $rv = $sth->bind_col($column_number, \$var_to_bind); + $rv = $sth->bind_col($column_number, \$var_to_bind, \%attr ); + $rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type ); Binds a Perl variable and/or some attributes to an output column of a SELECT statement. Column numbers count up from 1. You do not need to bind output columns in order to fetch data. @@ -2142,15 +2131,15 @@ retrieved. See the DBI documentation for a discussion of the optional parameters `\%attr` and `$bind_type` -## __bind_columns__ +## __bind\_columns__ - $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); + $rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind); -Calls the [bind_col](#pod_bind_col) method for each column in the SELECT statement, using the supplied list. +Calls the ["bind\_col"](#bind\_col) method for each column in the SELECT statement, using the supplied list. -## __dump_results__ +## __dump\_results__ - $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); + $rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh); Fetches all the rows from the statement handle, calls `DBI::neat_list` for each row, and prints the results to `$fh` (which defaults to `STDOUT`). Rows are separated by `$lsep` (which defaults @@ -2158,19 +2147,19 @@ to a newline). Columns are separated by `$fsep` (which defaults to a comma). The how wide the output can be, and defaults to 35. This method is designed as a handy utility for prototyping and testing queries. Since it uses -"neat_list" to format and edit the string for reading by humans, it is not recommended +"neat\_list" to format and edit the string for reading by humans, it is not recommended for data transfer applications. # STATEMENT HANDLE ATTRIBUTES -## __NUM_OF_FIELDS__ (integer, read-only) +## __NUM\_OF\_FIELDS__ (integer, read-only) Returns the number of columns returned by the current statement. A number will only be returned for SELECT statements for INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. This method returns undef if called before `execute()`. -## __NUM_OF_PARAMS__ (integer, read-only) +## __NUM\_OF\_PARAMS__ (integer, read-only) Returns the number of placeholders in the current statement. @@ -2181,25 +2170,25 @@ method will only work for SELECT statements, for SHOW statements, and for INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. This method returns undef if called before `execute()`. -## __NAME_lc__ (arrayref, read-only) +## __NAME\_lc__ (arrayref, read-only) The same as the `NAME` attribute, except that all column names are forced to lower case. -## __NAME_uc__ (arrayref, read-only) +## __NAME\_uc__ (arrayref, read-only) The same as the `NAME` attribute, except that all column names are forced to upper case. -## __NAME_hash__ (hashref, read-only) +## __NAME\_hash__ (hashref, read-only) Similar to the `NAME` attribute, but returns a hashref of column names instead of an arrayref. The names of the columns are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. This method returns undef if called before `execute()`. -## __NAME_lc_hash__ (hashref, read-only) +## __NAME\_lc\_hash__ (hashref, read-only) The same as the `NAME_hash` attribute, except that all column names are forced to lower case. -## __NAME_uc_hash__ (hashref, read-only) +## __NAME\_uc\_hash__ (hashref, read-only) The same as the `NAME_hash` attribute, except that all column names are forced to lower case. @@ -2240,17 +2229,17 @@ placeholders (without the colon). If the "dollar sign numbers" type of placehold be the numbers, without the dollar signs. If the "question mark" type is used, integer numbers will be returned, starting at one and increasing for every placeholder. -If this method is called before [execute](#pod_execute), the literal values passed in are returned. If called after -[execute](#pod_execute), then the quoted versions of the values are returned. +If this method is called before ["execute"](#execute), the literal values passed in are returned. If called after +["execute"](#execute), then the quoted versions of the values are returned. ## __ParamTypes__ (hash ref, read-only) Returns a reference to a hash containing the type names currently bound to placeholders. The keys are the same as returned by the ParamValues method. The values are hashrefs containing a single key value -pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can +pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg\_type' if the type can only be expressed by a Postgres type. The value is the internal number corresponding to the type originally passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of -ParamTypes to be passed back to the [bind_param](#pod_bind_param) method. +ParamTypes to be passed back to the ["bind\_param"](#bind\_param) method. ## __Statement__ (string, read-only) @@ -2284,14 +2273,14 @@ more server and client resources and have poorer response times than non-scrolli To enable this functionality you must first import the 'Fetch Orientation' and the 'Execution Mode' constants by using; - use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); + use DBD::Oracle qw(:ora_fetch_orient :ora_exe_modes); -Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora_exe_mode attribute on the -statement handle to 'OCI_STMT_SCROLLABLE_READONLY' with the prepare method; +Next you will have to tell DBD::Oracle that you will be using scrolling by setting the ora\_exe\_mode attribute on the +statement handle to 'OCI\_STMT\_SCROLLABLE\_READONLY' with the prepare method; - $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); -When the statement is executed you will then be able to use 'ora_fetch_scroll' method to get a row +When the statement is executed you will then be able to use 'ora\_fetch\_scroll' method to get a row or you can still use any of the other fetch methods but with a poorer response time than if you used a non-scrolling cursor. As well scrollable cursors are compatible with any applicable bind methods. @@ -2299,199 +2288,199 @@ non-scrolling cursor. As well scrollable cursors are compatible with any applica The following driver-specific methods are used with scrollable cursors. -- ora_scroll_position +- ora\_scroll\_position - $position = $sth->ora_scroll_position(); + $position = $sth->ora_scroll_position(); This method returns the current position (row number) attribute of the result set. Prior to the first fetch this value is 0. This is the only time this value will be 0 after the first fetch the value will be set, so you can use this value to test if any rows have been fetched. The minimum value will always be 1 after the first fetch. The maximum value will always be the total number of rows in the record set. -- ora_fetch_scroll +- ora\_fetch\_scroll - $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); + $ary_ref = $sth->ora_fetch_scroll($fetch_orient,$fetch_offset); -Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch_offset +Works the same as `fetchrow_arrayref`, excepts one passes in a 'Fetch Orientation' constant and a fetch\_offset value which will then determine the row that will be fetched. It returns the row as a list containing the field values. Null fields are returned as _undef_ values in the list. The valid orientation constant and fetch offset values combination are detailed below - OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. - OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value - is ignored. - OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. - OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. - OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset - value is ignored. - - OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. - - OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. - OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. - - OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the - fetch offset value. - - OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. - OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. - -The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. - - OCI_FETCH_CURRENT, has no effect on the current_positon attribute. - OCI_FETCH_NEXT, increments current_positon attribute by 1 - OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon - attribute, it is equivalent to a OCI_FETCH_CURRENT - OCI_FETCH_FIRST, sets the current_positon attribute to 1. - OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the - record set. - OCI_FETCH_PRIOR, decrements current_positon attribute by 1. - OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon - attribute, it is equivalent to a OCI_FETCH_CURRENT. - - OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. - OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change - current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in - the record set, does not change current_positon attribute, it is - equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + - fetch offset value). - OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, - does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records - in the record set, does not change fetch offset value so it is equivalent - to a OCI_FETCH_CURRENT. - -The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. - - OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. - OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. - OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon - attribute to the total number of rows in the record set. - OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. - OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. - - OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a - OCI_FETCH_CURRENT. - OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of - records in the record set is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent - to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number - of records in the record set, is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_CURRENT, fetches the current row, the fetch offset value is ignored. + OCI_FETCH_NEXT, fetches the next row from the current position, the fetch offset value + is ignored. + OCI_FETCH_FIRST, fetches the first row, the fetch offset value is ignored. + OCI_FETCH_LAST, fetches the last row, the fetch offset value is ignored. + OCI_FETCH_PRIOR, fetches the previous row from the current position, the fetch offset + value is ignored. + + OCI_FETCH_ABSOLUTE, fetches the row that is specified by the fetch offset value. + + OCI_FETCH_ABSOLUTE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_ABSOLUTE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_RELATIVE, fetches the row relative from the current position as specified by the + fetch offset value. + + OCI_FETCH_RELATIVE, and a fetch offset value of 0 is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. + OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. + +The effect that a ora\_fetch\_scroll method call has on the current\_positon attribute is detailed below. + + OCI_FETCH_CURRENT, has no effect on the current_positon attribute. + OCI_FETCH_NEXT, increments current_positon attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT + OCI_FETCH_FIRST, sets the current_positon attribute to 1. + OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + record set. + OCI_FETCH_PRIOR, decrements current_positon attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + attribute, it is equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change + current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in + the record set, does not change current_positon attribute, it is + equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + fetch offset value). + OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, + does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number of records + in the record set, does not change fetch offset value so it is equivalent + to a OCI_FETCH_CURRENT. + +The effects of the differing orientation constants on the first fetch (current\_postion attribute at 0) are as follows. + + OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + attribute to the total number of rows in the record set. + OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. + OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. + + OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 is equivalent to a + OCI_FETCH_CURRENT. + OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of + records in the record set is equivalent to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that is less than 1 is equivalent + to a OCI_FETCH_CURRENT. + OCI_FETCH_RELATIVE, and a fetch offset value that makes it greater than the number + of records in the record set, is equivalent to a OCI_FETCH_CURRENT. ## Scrollable Cursor Usage Given a simple code like this: - use DBI; - use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); - my $dbh = DBI->connect($dsn, $dbuser, ''); - my $SQL = "select id, - first_name, - last_name - from employee"; - my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); - $sth->execute(); - my $value; - -and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora_fetch_scroll + use DBI; + use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); + my $dbh = DBI->connect($dsn, $dbuser, ''); + my $SQL = "select id, + first_name, + last_name + from employee"; + my $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY}); + $sth->execute(); + my $value; + +and one assumes that the number of rows returned from the query is 20, the code snippets below will illustrate the use of ora\_fetch\_scroll method; - Fetching the Last Row - $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +The current\_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, if the record set is large this could take some time. - Fetching the Current Row - $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will still be 20 after this snippet. +The current\_positon attribute will still be 20 after this snippet. - Fetching the First Row - $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 1 after this snippet. +The current\_positon attribute will be 1 after this snippet. - Fetching the Next Row - for(my $i=0;$i<=3;$i++){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 5 after this snippet. +The current\_positon attribute will be 5 after this snippet. - Fetching the Prior Row - for(my $i=0;$i<=3;$i++){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; + for(my $i=0;$i<=3;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 1 after this snippet. +The current\_positon attribute will be 1 after this snippet. - Fetching the 10th Row - $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,10); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 10 after this snippet. +The current\_positon attribute will be 10 after this snippet. - Fetching the 10th to 14th Row - for(my $i=10;$i<15;$i++){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; + for(my $i=10;$i<15;$i++){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 14 after this snippet. +The current\_positon attribute will be 14 after this snippet. - Fetching the 14th to 10th Row - for(my $i=14;$i>9;$i--){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - } - print "current scroll position=".$sth->ora_scroll_position()."\n"; + for(my $i=14;$i>9;$i--){ + $value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,$i); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + } + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 10 after this snippet. +The current\_positon attribute will be 10 after this snippet. - Fetching the 5th Row From the Present Position. - $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,5); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 15 after this snippet. +The current\_positon attribute will be 15 after this snippet. - Fetching the 9th Row Prior From the Present Position - $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); - print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; - print "current scroll position=".$sth->ora_scroll_position()."\n"; + $value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-9); + print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; + print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 6 after this snippet. +The current\_positon attribute will be 6 after this snippet. - Use Finish - $sth->finish(); + $sth->finish(); When using scrollable cursors it is required that you use the $sth->finish() method when you are done with the cursor as this type of cursor has to be explicitly cancelled on the server. If you do not do this you may cause resource problems on your database. @@ -2505,16 +2494,16 @@ functionality than CLOB or BLOB fields. DBD::Oracle now offers three interfaces to LOB and LONG data, -- [Data Interface for Persistent LOBs](#pod_Data Interface for Persistent LOBs) +- ["Data Interface for Persistent LOBs"](#Data Interface for Persistent LOBs) With this interface DBD::Oracle handles your data directly utilizing regular OCI calls, Oracle itself takes care of the LOB Locator operations in the case of BLOBs and CLOBs treating them exactly as if they were the same as the legacy LONG or LONG RAW types. -- [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) +- ["Data Interface for LOB Locators"](#Data Interface for LOB Locators) With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. -- [LOB Locator Method Interface](#pod_LOB Locator Method Interface) +- ["LOB Locator Method Interface"](#LOB Locator Method Interface) This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. @@ -2528,15 +2517,15 @@ One point to remember when working with LOBs (CLOBs, BLOBs) is if your LOB colum The table cell is created, but the cell holds no locator or value. If your LOB field is in this state then there is no LOB Locator that DBD::Oracle can work so if your encounter a - DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr + DBD::Oracle::db::ora_lob_read: locator is not of type OCILobLocatorPtr error when working with a LOB. -You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY_BLOB or EMPTY_CLOB as in this example; +You can correct this by using an SQL UPDATE statement to reset the LOB column to a non-NULL (or empty LOB) value with either EMPTY\_BLOB or EMPTY\_CLOB as in this example; - UPDATE lob_example - SET bindata=EMPTY_BLOB() - WHERE bindata IS NULL. + UPDATE lob_example + SET bindata=EMPTY_BLOB() + WHERE bindata IS NULL. - Empty @@ -2563,64 +2552,64 @@ an 'ORA-01062: unable to allocate memory for define buffer' error. One solution For example give this table; - CREATE TABLE test_long ( - id NUMBER, + CREATE TABLE test_long ( + id NUMBER, long1 long) this code; - $dbh->{LongReadLen} = 2*1024*1024; #2 meg - $SQL='select p_id,long1 from test_long'; - $sth=$dbh->prepare($SQL); - $sth->execute(); - while (my ( $p_id,$long )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "long=".$long."\n"; - } + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } Will select out all of the long1 fields in the table as long as they are all under 2MB in length. A value in long1 longer than this will throw an error. Adding this line; - $dbh->{LongTruncOk}=1; + $dbh->{LongTruncOk}=1; before the execute will return all the long1 fields but they will be truncated at 2MBs. -### Using ora_ncs_buff_mtpl +### Using ora\_ncs\_buff\_mtpl When getting CLOBs and NCLOBs in or out of Oracle, the Server will translate from the Server's NCharSet to the Client's. If they happen to be the same or at least compatible then all of these actions are a 1 char to 1 char bases. -Thus if you set your LongReadLen buffer to 10_000_000 you will get up to 10_000_000 char. +Thus if you set your LongReadLen buffer to 10\_000\_000 you will get up to 10\_000\_000 char. However if the Server has to translate from one NCharSet to another it will use bytes for conversion. The buffer -value is set to 4 * LONG_READ_LEN which was very wasteful as you might only be asking for 10_000_000 bytes -but you were actually using 40_000_000 bytes of buffer under the hood. You would still get 10_000_000 bytes +value is set to 4 \* LONG\_READ\_LEN which was very wasteful as you might only be asking for 10\_000\_000 bytes +but you were actually using 40\_000\_000 bytes of buffer under the hood. You would still get 10\_000\_000 bytes (maybe less characters though) but you are using allot more memory that you need. -You can now customize the size of the buffer by setting the 'ora_ncs_buff_mtpl' either on the connection or statement handle. You can -also set this as 'ORA_DBD_NCS_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. +You can now customize the size of the buffer by setting the 'ora\_ncs\_buff\_mtpl' either on the connection or statement handle. You can +also set this as 'ORA\_DBD\_NCS\_BUFFER' OS environment variable so you will have to go back and change all your code if you are getting into trouble. The default value is still set to 4 for backward compatibility. You can lower this value and thus increase the amount of data you can retrieve. If the -ora_ncs_buff_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. +ora\_ncs\_buff\_mtpl is too small DBD::Oracle will throw and error telling you to increase this buffer by one. If the error is not captured then you may get at some random point later on, usually at a finish() or disconnect() or even a fetch() this error; - ORA-03127: no new operations allowed until the active operation ends + ORA-03127: no new operations allowed until the active operation ends This is one of the more obscure ORA errors (have some fun and report it to Meta-Link they will scratch their heads for hours) -If you get this, simply increment the ora_ncs_buff_mtpl by one until it goes away. +If you get this, simply increment the ora\_ncs\_buff\_mtpl by one until it goes away. This should greatly increase your ability to select very large CLOBs or NCLOBs, by freeing up a large block of memory. -You can tune this value by setting ora_oci_success_warn which will display the following +You can tune this value by setting ora\_oci\_success\_warn which will display the following - OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen - 20(characters), BufLen 80(characters), Got 28(characters) + OCILobRead field 2 of 3 SUCCESS: csform 1 (SQLCS_IMPLICIT), LOBlen 10240(characters), LongReadLen + 20(characters), BufLen 80(characters), Got 28(characters) -In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora_ncs_buff_mtpl=>2 (20*2=40) thus saving 40bytes of memory. +In the case above the query Got 28 characters (well really only 20 characters of 28 bytes) so we could use ora\_ncs\_buff\_mtpl=>2 (20\*2=40) thus saving 40bytes of memory. ### Simple Fetch for CLOBs and BLOBs -To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well +To use this interface for CLOBs and LOBs datatypes set the 'ora\_pers\_lob' attribute of the statement handle to '1' with the prepare method, as well set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. @@ -2632,155 +2621,155 @@ It seems with BLOBs you are not limited by the 64k. For example give this table; - CREATE TABLE test_lob (id NUMBER, - clob1 CLOB, - clob2 CLOB, - blob1 BLOB, - blob2 BLOB) + CREATE TABLE test_lob (id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) this code; - $dbh->{LongReadLen} = 2*1024*1024; #2 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; - $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } Will select out all of the LOBs in the table as long as they are all under 2MB in length. Longer lobs will throw an error. Adding this line; - $dbh->{LongTruncOk}=1; + $dbh->{LongTruncOk}=1; before the execute will return all the lobs but they will be truncated at 2MBs. ### Piecewise Fetch with Callback With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. -To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +To use this interface set the 'ora\_clbk\_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora\_piece\_size' to the size of the piece that you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected -size of the LOB. Like the [Simple Fetch for LONGs and LONG RAWs](#pod_Simple Fetch for LONGs and LONG RAWs) and [Simple Fetch for CLOBs and BLOBs](#pod_Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB -or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on -the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is +size of the LOB. Like the ["Simple Fetch for LONGs and LONG RAWs"](#Simple Fetch for LONGs and LONG RAWs) and ["Simple Fetch for CLOBs and BLOBs"](#Simple Fetch for CLOBs and BLOBs) the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora\_piece\_size' seems to be constrained by the same memory limit as found on +the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora\_piece\_size' to a smaller value. The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. Using the table from the last example this code; - $dbh->{LongReadLen} = 20*1024*1024; #20 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; - $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } - -Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora\_piece\_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4\*5MB=20MB). Like the Simple Fetch examples Lobs longer than 20MB will throw an error. Using the table from the first example (LONG) this code; - $dbh->{LongReadLen} = 20*1024*1024; #2 meg - $SQL='select p_id,long1 from test_long'; - $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$long )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "long=".$long."\n"; - } + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_clbk_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } -Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 filed is longer than 5MB (ora\_piece\_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4\*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. #### Piecewise Fetch with Polling -With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' -attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that +With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora\_piece\_lob' +attribute of the statement handle to '1' with the prepare method. Next set the 'ora\_piece\_size' to the size of the piece that you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected -size of the LOB. Like the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB -or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on -the [Piecewise Fetch with Callback](#pod_Piecewise Fetch with Callback). +size of the LOB. Like the ["Piecewise Fetch with Callback"](#Piecewise Fetch with Callback) and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set the 'LongReadLen' to a higher value. With this interface the value of 'ora\_piece\_size' seems to be constrained by the same memory limit as found on +the ["Piecewise Fetch with Callback"](#Piecewise Fetch with Callback). Using the table from the example above this code; - $dbh->{LongReadLen} = 20*1024*1024; #20 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; - $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } - -Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. + $dbh->{LongReadLen} = 20*1024*1024; #20 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } + +Will select out all of the LOBs in the table as long as they are all under 20MB in length. If the LOB is longer than 5MB (ora\_piece\_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4\*5MB=20MB). Like the other fetch methods LOBs longer than 20MB will throw an error. Finally with this code; - $dbh->{LongReadLen} = 20*1024*1024; #2 meg - $SQL='select p_id,long1 from test_long'; - $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); - $sth->execute(); - while (my ( $p_id,$long )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "long=".$long."\n"; - } + $dbh->{LongReadLen} = 20*1024*1024; #2 meg + $SQL='select p_id,long1 from test_long'; + $sth=$dbh->prepare($SQL,{ora_piece_lob=>1,ora_piece_size=>5*1024*1024}); + $sth->execute(); + while (my ( $p_id,$long )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "long=".$long."\n"; + } -Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora_piece_size) DBD::Oracle will fetch it in at least 2 pieces to a -maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. +Will select all of the long1 fields from table as long as they are is under 20MB in length. If the long1 field is longer than 5MB (ora\_piece\_size) DBD::Oracle will fetch it in at least 2 pieces to a +maximum of 4 pieces (4\*5MB=20MB). Like the other examples long1 fields longer than 20MB will throw an error. ### Binding for Updates and Inserts for CLOBs and BLOBs To bind for updates and inserts all that is required to use this interface is to set the statement handle's prepare method -'ora_type' attribute to 'SQLT_CHR' in the case of CLOBs and NCLOBs or 'SQLT_BIN' in the case of BLOBs as in this example for an insert; - - my $in_clob = "\n"; - $in_clob .= " $_\n" for 1 .. 10_000; - $in_clob .= "\n"; - my $in_blob ="0101" for 1 .. 10_000; - - $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; - $sth=$dbh->prepare($SQL ); - $sth->bind_param(1,3); - $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); - $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); - $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); - $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); - $sth->execute(); +'ora\_type' attribute to 'SQLT\_CHR' in the case of CLOBs and NCLOBs or 'SQLT\_BIN' in the case of BLOBs as in this example for an insert; + + my $in_clob = "\n"; + $in_clob .= " $_\n" for 1 .. 10_000; + $in_clob .= "\n"; + my $in_blob ="0101" for 1 .. 10_000; + + $SQL='insert into test_lob3@tpgtest (id,clob1,clob2, blob1,blob2) values(?,?,?,?,?)'; + $sth=$dbh->prepare($SQL ); + $sth->bind_param(1,3); + $sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}); + $sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}); + $sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}); + $sth->execute(); So far the only limit reached with this form of insert is the LOBs must be under 2GB in size. ### Support for Remote LOBs; -Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob_test' that has a 'LINK' defined like this; +Starting with Oracle 10gR2 the interface for Persistent LOBs was expanded to support remote LOBs (access over a dblink). Given a database called 'lob\_test' that has a 'LINK' defined like this; - CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; + CREATE DATABASE LINK link_test CONNECT TO test_lobs IDENTIFIED BY tester USING 'lob_test'; -to a remote database called 'test_lobs', the following code will work; +to a remote database called 'test\_lobs', the following code will work; - $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); - $dbh->{LongReadLen} = 2*1024*1024; #2 meg - $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; - $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); - $sth->execute(); - while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ - print "p_id=".$p_id."\n"; - print "clob1=".$clob1."\n"; - print "clob2=".$clob2."\n"; - print "blob1=".$blob2."\n"; - print "blob2=".$blob2."\n"; - } + $dbh = DBI->connect('dbi:Oracle:','test@lob_test','test'); + $dbh->{LongReadLen} = 2*1024*1024; #2 meg + $SQL='select p_id,lob_1,lob_2,blob_2 from test_lobs@link_test'; + $sth=$dbh->prepare($SQL,{ora_pers_lob=>1}); + $sth->execute(); + while (my ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow()){ + print "p_id=".$p_id."\n"; + print "clob1=".$clob1."\n"; + print "clob2=".$clob2."\n"; + print "blob1=".$blob2."\n"; + print "blob2=".$blob2."\n"; + } Below are the limitations of Remote LOBs; @@ -2788,25 +2777,25 @@ Below are the limitations of Remote LOBs; so the following returns an error: - SELECT t1.lobcol, - a2.lobcol - FROM t1, - t2.lobcol@dbs2 a2 W - WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); + SELECT t1.lobcol, + a2.lobcol + FROM t1, + t2.lobcol@dbs2 a2 W + WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); as does: - SELECT t1.lobcol - FROM t1@dbs1 - UNION ALL - SELECT t2.lobcol - FROM t2@dbs2; + SELECT t1.lobcol + FROM t1@dbs1 + UNION ALL + SELECT t2.lobcol + FROM t2@dbs2; - DDL commands are not supported; so the following returns an error: - CREATE VIEW v AS SELECT lob_col FROM tab@dbs; + CREATE VIEW v AS SELECT lob_col FROM tab@dbs; - Only binds and defines for data going into remote persistent LOBs are supported. @@ -2814,19 +2803,19 @@ so that parameter passing in PL/SQL where CHAR data is bound or defined for remo These statements all produce errors: - SELECT foo() FROM table1@dbs2; + SELECT foo() FROM table1@dbs2; - SELECT foo()@dbs INTO char_val FROM DUAL; + SELECT foo()@dbs INTO char_val FROM DUAL; - SELECT XMLType().getclobval FROM table1@dbs2; + SELECT XMLType().getclobval FROM table1@dbs2; - If the remote object is a view such as - CREATE VIEW v AS SELECT foo() FROM ... + CREATE VIEW v AS SELECT foo() FROM ... the following would not work: - SELECT * FROM v@dbs2; + SELECT * FROM v@dbs2; - Limited PL/SQL parameter passing @@ -2837,7 +2826,7 @@ and the remote argument is one of VARCHAR2, NVARCHAR2, CHAR, NCHAR, or RAW. so the following returns an error: - SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test + SELECT t1.lobcol as test, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 RETURNING test ## Locator Data Interface @@ -2858,11 +2847,11 @@ time being, only single-row LOB updates are supported. To insert or update a large LOB using a placeholder, DBD::Oracle has to know in advance that it is a LOB type. So you need to say: - $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); + $sth->bind_param($field_num, $lob_value, { ora_type => ORA_CLOB }); -The ORA_CLOB and ORA_BLOB constants can be imported using +The ORA\_CLOB and ORA\_BLOB constants can be imported using - use DBD::Oracle qw(:ora_types); + use DBD::Oracle qw(:ora_types); or use the corresponding integer values (112 and 113). @@ -2872,23 +2861,23 @@ In all cases where it can possibly work it out for itself, it does, however, if there are multiple LOB fields of the same type in the table then you need to tell it which field each LOB param relates to: - $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); + $sth->bind_param($idx, $value, { ora_type=>ORA_CLOB, ora_field=>'foo' }); There are some limitations inherent in the way DBD::Oracle makes typical LOB operations simple by hiding the LOB Locator processing: - - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) - - To INSERT a LOB, you need UPDATE privilege. + - Can't read/write LOBs in chunks (except via DBMS_LOB.WRITEAPPEND in PL/SQL) + - To INSERT a LOB, you need UPDATE privilege. The alternative is to disable the automatic LOB Locator processing. -If [ora_auto_lob](#pod_ora_auto_lob) is 0 in prepare(), you can fetch the LOB Locators and -do all the work yourself using the ora_lob_*() methods. -See the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) section below. +If ["ora\_auto\_lob"](#ora\_auto\_lob) is 0 in prepare(), you can fetch the LOB Locators and +do all the work yourself using the ora\_lob\_\*() methods. +See the ["Data Interface for LOB Locators"](#Data Interface for LOB Locators) section below. ### LOB support in PL/SQL LOB Locators can be passed to PL/SQL calls by binding them to placeholders -with the proper `ora_type`. If [ora_auto_lob](#pod_ora_auto_lob) is true, output LOB +with the proper `ora_type`. If ["ora\_auto\_lob"](#ora\_auto\_lob) is true, output LOB parameters will be automatically returned as strings. If the Oracle driver has support for temporary LOBs (Oracle 9i and higher), @@ -2896,8 +2885,8 @@ strings can be bound to input LOB placeholders and will be automatically converted to LOBs. Example: - # Build a large XML document, bind it as a CLOB, - # extract elements through PL/SQL and return as a CLOB + \# Build a large XML document, bind it as a CLOB, + \# extract elements through PL/SQL and return as a CLOB # $dbh is a connected database handle # output will be large @@ -2931,7 +2920,7 @@ Example: If you ever get an - ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt + ORA-01691 unable to extend lob segment sss.ggg by nnn in tablespace ttt error, while attempting to insert a LOB, this means the Oracle user has insufficient space for LOB you are trying to insert. One solution it to use "alter database datafile 'sss.ggg' resize Mnnn" to increase the available memory for LOBs. @@ -2957,12 +2946,12 @@ the Callback or Polling piecewise fetches to get all of the data. Not all of the Persistent interface has been implemented yet, the following are not supported; - 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. - 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. + 1) Piecewise, polling and callback binds for INSERT and UPDATE operations. + 2) Piecewise array binds for SELECT, INSERT and UPDATE operations. -Most of the time you should just use the [Locator Data Interface](#pod_Locator Data Interface) as this is in one that has the best combination of speed and size. +Most of the time you should just use the ["Locator Data Interface"](#Locator Data Interface) as this is in one that has the best combination of speed and size. -All this being said if you are doing some critical programming I would use the [Data Interface for LOB Locators](#pod_Data Interface for LOB Locators) as this gives you very +All this being said if you are doing some critical programming I would use the ["Data Interface for LOB Locators"](#Data Interface for LOB Locators) as this gives you very fine grain control of your LOBs, of course the code for this will be somewhat more involved. ## Data Interface for LOB Locators @@ -2980,57 +2969,57 @@ Note that LOB locators are only valid while the statement handle that created them is valid. When all references to the original statement handle are lost, the handle is destroyed and the locators are freed. -- ora_lob_read +- ora\_lob\_read - $data = $dbh->ora_lob_read($lob_locator, $offset, $length); + $data = $dbh->ora_lob_read($lob_locator, $offset, $length); Read a portion of the LOB. $offset starts at 1. Uses the Oracle OCILobRead function. NOTE: DBD::Oracle post 1.46 will return undef for any read lob if the -length specified in the ora_lob_read is 0. See RT 55028. This avoids -the potential problem with empty lobs (created with empty_clob) which -return a length of 0 from ora_lob_length and prior to 1.46 a call to -ora_lob_read with a 0 length would segfault. +length specified in the ora\_lob\_read is 0. See RT 55028. This avoids +the potential problem with empty lobs (created with empty\_clob) which +return a length of 0 from ora\_lob\_length and prior to 1.46 a call to +ora\_lob\_read with a 0 length would segfault. -- ora_lob_write +- ora\_lob\_write - $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); + $rc = $dbh->ora_lob_write($lob_locator, $offset, $data); Write/overwrite a portion of the LOB. $offset starts at 1. Uses the Oracle OCILobWrite function. -- ora_lob_append +- ora\_lob\_append - $rc = $dbh->ora_lob_append($lob_locator, $data); + $rc = $dbh->ora_lob_append($lob_locator, $data); Append $data to the LOB. Uses the Oracle OCILobWriteAppend function. -- ora_lob_trim +- ora\_lob\_trim - $rc = $dbh->ora_lob_trim($lob_locator, $length); + $rc = $dbh->ora_lob_trim($lob_locator, $length); Trims the length of the LOB to $length. Uses the Oracle OCILobTrim function. -- ora_lob_length +- ora\_lob\_length - $length = $dbh->ora_lob_length($lob_locator); + $length = $dbh->ora_lob_length($lob_locator); Returns the length of the LOB. Uses the Oracle OCILobGetLength function. -- ora_lob_is_init +- ora\_lob\_is\_init - $is_init = $dbh->ora_lob_is_init($lob_locator); + $is_init = $dbh->ora_lob_is_init($lob_locator); Returns true(1) if the Lob Locator is initialized false(0) if it is not, or 'undef' if there is an error. Uses the Oracle OCILobLocatorIsInit function. -- ora_lob_chunk_size +- ora\_lob\_chunk\_size - $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); + $chunk_size = $dbh->ora_lob_chunk_size($lob_locator); Returns the chunk size of the LOB. Uses the Oracle OCILobGetChunkSize function. @@ -3053,16 +3042,16 @@ The following examples assume a table containing two large object columns, one binary and one character, with a primary key column, defined as follows: - CREATE TABLE lob_example ( - lob_id INTEGER PRIMARY KEY, - bindata BLOB, - chardata CLOB - ) + CREATE TABLE lob_example ( + lob_id INTEGER PRIMARY KEY, + bindata BLOB, + chardata CLOB + ) It also assumes a sequence for use in generating unique -lob_id field values, defined as follows: +lob\_id field values, defined as follows: - CREATE SEQUENCE lob_example_seq + CREATE SEQUENCE lob_example_seq ### Example: Inserting a new row with large data @@ -3085,64 +3074,64 @@ statement containing the clause 'FOR UPDATE' (LOB locators are only valid within the transaction that fetched them, so can't be used effectively if AutoCommit is enabled). - my $lob_id = $dbh->selectrow_array( <<" SQL" ); - SELECT lob_example_seq.nextval FROM DUAL - SQL - - my $sth = $dbh->prepare( <<" SQL" ); - INSERT INTO lob_example - ( lob_id, bindata, chardata ) - VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) - SQL - $sth->execute( $lob_id ); - - $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT bindata, chardata - FROM lob_example - WHERE lob_id = ? - FOR UPDATE - SQL - $sth->execute( $lob_id ); - my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); - $sth->finish(); - - open BIN_FH, "/binary/data/source" or die; - open CHAR_FH, "/character/data/source" or die; - my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); - - # BEGIN WRITING BIN_DATA COLUMN - my $offset = 1; # Offsets start at 1, not 0 - my $length = 0; - my $buffer = ''; - while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { - $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); - $offset += $length; - } - - # BEGIN WRITING CHAR_DATA COLUMN - $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); - $offset = 1; # Offsets start at 1, not 0 - $length = 0; - $buffer = ''; - while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { - $dbh->ora_lob_write( $char_locator, $offset, $buffer ); - $offset += $length; - } - -In this example we demonstrate the use of ora_lob_write() -interactively to append data to the columns 'bin_data' and -'char_data'. Had we used ora_lob_append(), we could have + my $lob_id = $dbh->selectrow_array( <<" SQL" ); + SELECT lob_example_seq.nextval FROM DUAL + SQL + + my $sth = $dbh->prepare( <<" SQL" ); + INSERT INTO lob_example + ( lob_id, bindata, chardata ) + VALUES ( ?, EMPTY_BLOB(),EMPTY_CLOB() ) + SQL + $sth->execute( $lob_id ); + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata, chardata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator, $char_locator ) = $sth->fetchrow_array(); + $sth->finish(); + + open BIN_FH, "/binary/data/source" or die; + open CHAR_FH, "/character/data/source" or die; + my $chunk_size = $dbh->ora_lob_chunk_size( $bin_locator ); + + # BEGIN WRITING BIN_DATA COLUMN + my $offset = 1; # Offsets start at 1, not 0 + my $length = 0; + my $buffer = ''; + while( $length = read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $bin_locator, $offset, $buffer ); + $offset += $length; + } + + # BEGIN WRITING CHAR_DATA COLUMN + $chunk_size = $dbh->ora_lob_chunk_size( $char_locator ); + $offset = 1; # Offsets start at 1, not 0 + $length = 0; + $buffer = ''; + while( $length = read( CHAR_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_write( $char_locator, $offset, $buffer ); + $offset += $length; + } + +In this example we demonstrate the use of ora\_lob\_write() +interactively to append data to the columns 'bin\_data' and +'char\_data'. Had we used ora\_lob\_append(), we could have saved ourselves the trouble of keeping track of the offset into the lobs. The snippet of code beneath the comment -'BEGIN WRITING BIN_DATA COLUMN' could look as follows: +'BEGIN WRITING BIN\_DATA COLUMN' could look as follows: - my $buffer = ''; - while ( read( BIN_FH, $buffer, $chunk_size ) ) { - $dbh->ora_lob_append( $bin_locator, $buffer ); - } + my $buffer = ''; + while ( read( BIN_FH, $buffer, $chunk_size ) ) { + $dbh->ora_lob_append( $bin_locator, $buffer ); + } The scalar variables $offset and $length are no longer -needed, because ora_lob_append() keeps track of the offset +needed, because ora\_lob\_append() keeps track of the offset for us. ### Example: Updating an existing row with large data @@ -3153,23 +3142,23 @@ data before and after the section overwritten remains unchanged. Hence, this technique could be used for updating fixed length subfields embedded in a binary field. - my $lob_id = 5; # Arbitrary row identifier, for example + my $lob_id = 5; # Arbitrary row identifier, for example - $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT bindata - FROM lob_example - WHERE lob_id = ? - FOR UPDATE - SQL - $sth->execute( $lob_id ); - my ( $bin_locator ) = $sth->fetchrow_array(); + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + WHERE lob_id = ? + FOR UPDATE + SQL + $sth->execute( $lob_id ); + my ( $bin_locator ) = $sth->fetchrow_array(); - my $offset = 100234; - my $data = "This string will overwrite a portion of the blob"; - $dbh->ora_lob_write( $bin_locator, $offset, $data ); + my $offset = 100234; + my $data = "This string will overwrite a portion of the blob"; + $dbh->ora_lob_write( $bin_locator, $offset, $data ); -After running this code, the row where lob_id = 5 will -contain, starting at position 100234 in the bin_data column, +After running this code, the row where lob\_id = 5 will +contain, starting at position 100234 in the bin\_data column, the string "This string will overwrite a portion of the blob". ### Example: Streaming character data from the database @@ -3179,24 +3168,24 @@ data from the database to a file handle, in this case STDOUT. This allows more data to be read in and written out than could be stored in memory at a given time. - my $lob_id = 17; # Arbitrary row identifier, for example - - $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT chardata - FROM lob_example - WHERE lob_id = ? - SQL - $sth->execute( $lob_id ); - my ( $char_locator ) = $sth->fetchrow_array(); - - my $chunk_size = 1034; # Arbitrary chunk size, for example - my $offset = 1; # Offsets start at 1, not 0 - while(1) { - my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); - last unless length $data; - print STDOUT $data; - $offset += $chunk_size; - } + my $lob_id = 17; # Arbitrary row identifier, for example + + $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT chardata + FROM lob_example + WHERE lob_id = ? + SQL + $sth->execute( $lob_id ); + my ( $char_locator ) = $sth->fetchrow_array(); + + my $chunk_size = 1034; # Arbitrary chunk size, for example + my $offset = 1; # Offsets start at 1, not 0 + while(1) { + my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ); + last unless length $data; + print STDOUT $data; + $offset += $chunk_size; + } Notice that the select statement does not contain the phrase "FOR UPDATE". Because we are only reading from the LOB @@ -3204,13 +3193,13 @@ Locator returned, and not modifying the LOB it refers to, the select statement does not require the "FOR UPDATE" clause. -A word of caution when using the data returned from an ora_lob_read in a conditional statement. +A word of caution when using the data returned from an ora\_lob\_read in a conditional statement. for example if the code below; - while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { - print STDOUT $data; - $offset += $chunk_size; - } + while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) { + print STDOUT $data; + $offset += $chunk_size; + } was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte @@ -3225,21 +3214,21 @@ its previous length. After acquiring a LOB Locator for the column, we query its length, then we trim the length by half. Because we modify -the large objects with the call to ora_lob_trim(), we must +the large objects with the call to ora\_lob\_trim(), we must select the LOB locators 'FOR UPDATE'. - my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); - SELECT bindata - FROM lob_example - FOR UPATE - SQL - $sth->execute(); - while( my ( $bin_locator ) = $sth->fetchrow_array() ) { - my $binlength = $dbh->ora_lob_length( $bin_locator ); - if( $binlength > 0 ) { - $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); - } - } + my $sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } ); + SELECT bindata + FROM lob_example + FOR UPATE + SQL + $sth->execute(); + while( my ( $bin_locator ) = $sth->fetchrow_array() ) { + my $binlength = $dbh->ora_lob_length( $bin_locator ); + if( $binlength > 0 ) { + $dbh->ora_lob_trim( $bin_locator, $binlength/2 ); + } + } # SPACES AND PADDING @@ -3255,10 +3244,10 @@ Comparison Semantics in Oracle's SQL Reference or Server SQL Reference for more details. To preserve trailing spaces in placeholder values for Oracle clients that use OCI 8, -either change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or the placeholder -type for a particular call to L or L -with [ora_type](#pod_ora_type) or `TYPE`. -Using [ORA_CHAR](http://search.cpan.org/perldoc?ORA_CHAR) with [ora_type](http://search.cpan.org/perldoc?ora_type) or `SQL_CHAR` with `TYPE` +either change the default placeholder type with ["ora\_ph\_type"](#ora\_ph\_type) or the placeholder +type for a particular call to ["bind" in DBI](http://search.cpan.org/perldoc?DBI#bind) or ["bind\_param\_inout" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param\_inout) +with ["ora\_type"](#ora\_type) or `TYPE`. +Using [ORA\_CHAR](http://search.cpan.org/perldoc?ORA\_CHAR) with [ora\_type](http://search.cpan.org/perldoc?ora\_type) or `SQL_CHAR` with `TYPE` allows the placeholder to be used with Padded Comparison Semantics if the value it is being compared to is a CHAR, NCHAR, or literal. @@ -3271,10 +3260,10 @@ Oracle Clients that use OCI 9.2 do not strip trailing spaces. ## Padded Char Fields Oracle Clients after OCI 9.2 will automatically pad CHAR placeholder values to the size of the CHAR. -As the default placeholder type value in DBD::Oracle is ORA_VARCHAR2 to access this behaviour you will -have to change the default placeholder type with [ora_ph_type](#pod_ora_ph_type) or placeholder -type for a particular call with L or L -with [ORA_CHAR](#pod_ORA_CHAR). +As the default placeholder type value in DBD::Oracle is ORA\_VARCHAR2 to access this behaviour you will +have to change the default placeholder type with ["ora\_ph\_type"](#ora\_ph\_type) or placeholder +type for a particular call with ["bind" in DBI](http://search.cpan.org/perldoc?DBI#bind) or ["bind\_param\_inout" in DBI](http://search.cpan.org/perldoc?DBI#bind\_param\_inout) +with ["ORA\_CHAR"](#ORA\_CHAR). # UNICODE @@ -3296,8 +3285,8 @@ did not mature until version 5.8 and later. If you plan to use Unicode you are _strongly_ urged to use Perl 5.8.2 or later and to _carefully_ read the Perl documentation on Unicode: - perldoc perluniintro # in Perl 5.8 or later - perldoc perlunicode + perldoc perluniintro # in Perl 5.8 or later + perldoc perlunicode And then read it again. @@ -3309,47 +3298,47 @@ which corresponds to the Oracle character set called AL32UTF8. Oracle supports many characters sets, including several different forms of Unicode. These include: - AL16UTF16 => valid for NCHAR columns (CSID=2000) - UTF8 => valid for NCHAR columns (CSID=871), deprecated - AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) + AL16UTF16 => valid for NCHAR columns (CSID=2000) + UTF8 => valid for NCHAR columns (CSID=871), deprecated + AL32UTF8 => valid for NCHAR and CHAR columns (CSID=873) When you create an Oracle database, you must specify the DATABASE character set (used for DDL, DML and CHAR datatypes) and the NATIONAL character set (used for NCHAR and NCLOB types). The character sets used in your database can be found using: - $hash_ref = $dbh->ora_nls_parameters() - $database_charset = $hash_ref->{NLS_CHARACTERSET}; - $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; + $hash_ref = $dbh->ora_nls_parameters() + $database_charset = $hash_ref->{NLS_CHARACTERSET}; + $national_charset = $hash_ref->{NLS_NCHAR_CHARACTERSET}; The Oracle 9.2 and later default for the national character set is AL16UTF16. The default for the database character set is often US7ASCII. Although many experienced DBAs will consider an 8bit character set like WE8ISO8859P1 or WE8MSWIN1252. To use any character set with Oracle -other than US7ASCII, requires that the NLS_LANG environment variable be set. -See the L<"Oracle UTF8 is not UTF-8"> section below. +other than US7ASCII, requires that the NLS\_LANG environment variable be set. +See the ["Oracle UTF8 is not UTF-8"](#Oracle UTF8 is not UTF-8) section below. You are strongly urged to read the Oracle Internationalization documentation specifically with respect the choices and trade offs for creating a databases for use with international character sets. -Oracle uses the NLS_LANG environment variable to indicate what +Oracle uses the NLS\_LANG environment variable to indicate what character set is being used on the client. When fetching data Oracle will convert from whatever the database character set is to the client -character set specified by NLS_LANG. Similarly, when sending data to +character set specified by NLS\_LANG. Similarly, when sending data to the database Oracle will convert from the character set specified by -NLS_LANG to the database character set. +NLS\_LANG to the database character set. -The NLS_NCHAR environment variable can be used to define a different +The NLS\_NCHAR environment variable can be used to define a different character set for 'national' (NCHAR) character types. -Both UTF8 and AL32UTF8 can be used in NLS_LANG and NLS_NCHAR. +Both UTF8 and AL32UTF8 can be used in NLS\_LANG and NLS\_NCHAR. For example: - NLS_LANG=AMERICAN_AMERICA.UTF8 - NLS_LANG=AMERICAN_AMERICA.AL32UTF8 - NLS_NCHAR=UTF8 - NLS_NCHAR=AL32UTF8 + NLS_LANG=AMERICAN_AMERICA.UTF8 + NLS_LANG=AMERICAN_AMERICA.AL32UTF8 + NLS_NCHAR=UTF8 + NLS_NCHAR=AL32UTF8 ## Oracle UTF8 is not UTF-8 @@ -3364,17 +3353,17 @@ conform to the UTF-8 standard in its handling of surrogate characters. Technically the encoding that Oracle calls "UTF8" is known as "CESU-8". Here are a couple of extracts from [http://www.unicode.org/reports/tr26/](http://www.unicode.org/reports/tr26/): - CESU-8 is useful in 8-bit processing environments where binary - collation with UTF-16 is required. It is designed and recommended - for use only within products requiring this UTF-16 binary collation - equivalence. It is not intended nor recommended for open interchange. + CESU-8 is useful in 8-bit processing environments where binary + collation with UTF-16 is required. It is designed and recommended + for use only within products requiring this UTF-16 binary collation + equivalence. It is not intended nor recommended for open interchange. - As a very small percentage of characters in a typical data stream - are expected to be supplementary characters, there is a strong - possibility that CESU-8 data may be misinterpreted as UTF-8. - Therefore, all use of CESU-8 outside closed implementations is - strongly discouraged, such as the emittance of CESU-8 in output - files, markup language or other open transmission forms. + As a very small percentage of characters in a typical data stream + are expected to be supplementary characters, there is a strong + possibility that CESU-8 data may be misinterpreted as UTF-8. + Therefore, all use of CESU-8 outside closed implementations is + strongly discouraged, such as the emittance of CESU-8 in output + files, markup language or other open transmission forms. Oracle uses this internally because it collates (sorts) in the same order as UTF16, which is the basis of Oracle's internal collation definitions. @@ -3403,59 +3392,59 @@ Any data returned from Oracle to DBD::Oracle in the AL32UTF8 character set will be marked as UTF-8 to ensure correct handling by Perl. For Oracle to return data in the AL32UTF8 character set the -NLS_LANG or NLS_NCHAR environment variable _must_ be set as described +NLS\_LANG or NLS\_NCHAR environment variable _must_ be set as described in the previous section. When fetching NCHAR, NVARCHAR, or NCLOB data from Oracle, DBD::Oracle -will set the Perl UTF-8 flag on the returned data if either NLS_NCHAR -is AL32UTF8, or NLS_NCHAR is not set and NLS_LANG is AL32UTF8. +will set the Perl UTF-8 flag on the returned data if either NLS\_NCHAR +is AL32UTF8, or NLS\_NCHAR is not set and NLS\_LANG is AL32UTF8. When fetching other character data from Oracle, DBD::Oracle -will set the Perl UTF-8 flag on the returned data if NLS_LANG is AL32UTF8. +will set the Perl UTF-8 flag on the returned data if NLS\_LANG is AL32UTF8. __Sending Data using Placeholders__ Data bound to a placeholder is assumed to be in the default client -character set (specified by NLS_LANG) except for a few special +character set (specified by NLS\_LANG) except for a few special cases. These are listed here with the highest precedence first: -If the `ora_csid` attribute is given to bind_param() then that +If the `ora_csid` attribute is given to bind\_param() then that is passed to Oracle and takes precedence. If the value is a Perl Unicode string (UTF-8) then DBD::Oracle ensures that Oracle uses the Unicode character set, regardless of -the NLS_LANG and NLS_NCHAR settings. +the NLS\_LANG and NLS\_NCHAR settings. -If the placeholder is for inserting an NCLOB then the client NLS_NCHAR +If the placeholder is for inserting an NCLOB then the client NLS\_NCHAR character set is used. (That's useful but inconsistent with the other behaviour so may change. Best to be explicit by using the `ora_csform` attribute.) -If the `ora_csform` attribute is given to bind_param() then that +If the `ora_csform` attribute is given to bind\_param() then that determines if the value should be assumed to be in the default -(NLS_LANG) or NCHAR (NLS_NCHAR) client character set. +(NLS\_LANG) or NCHAR (NLS\_NCHAR) client character set. - use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); - ... - $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); + use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); + ... + $sth->bind_param(1, $value, { ora_csform => SQLCS_NCHAR }); or - $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders + $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders -Binding with bind_param_array and execute_array is also UTF-8 compatible in the same way. If you attempt to +Binding with bind\_param\_array and execute\_array is also UTF-8 compatible in the same way. If you attempt to insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR or NVARCHAR the insert will still happen but a error code of 0 will be returned with the following warning; - DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. - The Query charset id=1, name=US7ASCII + DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in parameter#1. This may result in corrupt data. + The Query charset id=1, name=US7ASCII The warning will report the parameter number and the NCHAR setting that the query is running. __Sending Data using SQL__ Oracle assumes the SQL statement is in the default client character -set (as specified by NLS_LANG). So Unicode strings containing +set (as specified by NLS\_LANG). So Unicode strings containing non-ASCII characters should not be used unless the default client character set is AL32UTF8. @@ -3477,114 +3466,114 @@ You can either get the values as an array of scalars or they can be returned int Array example, given this type and table; - CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); + CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); - CREATE TABLE "CONTACT" - ( "COMPANYNAME" VARCHAR2(40), - "ADDRESS" VARCHAR2(100), - "PHONE_NUMBERS" "PHONE_NUMBERS" - ) + CREATE TABLE "CONTACT" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" + ) The code to access all the data in the table could be something like this; - my $sth = $dbh->prepare('SELECT * FROM CONTACT'); - $sth->execute; - while ( my ($company, $address, $phone) = $sth->fetchrow()) { - print "Company: ".$company."\n"; - print "Address: ".$address."\n"; - print "Phone #: "; + my $sth = $dbh->prepare('SELECT * FROM CONTACT'); + $sth->execute; + while ( my ($company, $address, $phone) = $sth->fetchrow()) { + print "Company: ".$company."\n"; + print "Address: ".$address."\n"; + print "Phone #: "; - foreach my $items (@$phone){ - print $items.", "; - } - print "\n"; - } + foreach my $items (@$phone){ + print $items.", "; + } + print "\n"; + } -Note that values in PHONE_NUMBERS are returned as an array reference '@$phone'. +Note that values in PHONE\_NUMBERS are returned as an array reference '@$phone'. As stated before DBD::Oracle will automatically drill into the embedded object and extract all of the data as reference arrays of scalars. The example below has OBJECT type embedded in a TABLE type embedded in an SQL TABLE; - CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; + CREATE OR REPLACE TYPE GRADELIST AS TABLE OF NUMBER; - CREATE OR REPLACE TYPE STUDENT AS OBJECT( - NAME VARCHAR2(60), - SOME_GRADES GRADELIST); + CREATE OR REPLACE TYPE STUDENT AS OBJECT( + NAME VARCHAR2(60), + SOME_GRADES GRADELIST); - CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; + CREATE OR REPLACE TYPE STUDENTS_T AS TABLE OF STUDENT; - CREATE TABLE GROUPS( - GRP_ID NUMBER(4), - GRP_NAME VARCHAR2(10), - STUDENTS STUDENTS_T) - NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB - (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); + CREATE TABLE GROUPS( + GRP_ID NUMBER(4), + GRP_NAME VARCHAR2(10), + STUDENTS STUDENTS_T) + NESTED TABLE STUDENTS STORE AS GROUP_STUDENTS_TAB + (NESTED TABLE SOME_GRADES STORE AS GROUP_STUDENT_GRADES_TAB); The following code will access all of the embedded data; - $SQL='select grp_id,grp_name,students as my_students_test from groups'; - $sth=$dbh->prepare($SQL); - $sth->execute(); - while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ - print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; - foreach my $student (@$students){ - print "Name:".$student->[0]."\n"; - print "Marks:"; - foreach my $grades (@$student->[1]){ - foreach my $marks (@$grades){ - print $marks.","; - } - } - print "\n"; - } - print "\n"; - } + $SQL='select grp_id,grp_name,students as my_students_test from groups'; + $sth=$dbh->prepare($SQL); + $sth->execute(); + while (my ($grp_id,$grp_name,$students)=$sth->fetchrow()){ + print "Group ID#".$grp_id." Group Name =".$grp_name."\n"; + foreach my $student (@$students){ + print "Name:".$student->[0]."\n"; + print "Marks:"; + foreach my $grades (@$student->[1]){ + foreach my $marks (@$grades){ + print $marks.","; + } + } + print "\n"; + } + print "\n"; + } Object example, given this object and table; - CREATE OR REPLACE TYPE Person AS OBJECT ( - name VARCHAR2(20), - age INTEGER) - ) NOT FINAL; + CREATE OR REPLACE TYPE Person AS OBJECT ( + name VARCHAR2(20), + age INTEGER) + ) NOT FINAL; - CREATE TYPE Employee UNDER Person ( - salary NUMERIC(8,2) - ); + CREATE TYPE Employee UNDER Person ( + salary NUMERIC(8,2) + ); - CREATE TABLE people (id INTEGER, obj Person); + CREATE TABLE people (id INTEGER, obj Person); - INSERT INTO people VALUES (1, Person('Black', 25)); - INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); + INSERT INTO people VALUES (1, Person('Black', 25)); + INSERT INTO people VALUES (2, Employee('Smith', 44, 5000)); The following code will access the data; - $dbh{'ora_objects'} =>1; + $dbh{'ora_objects'} =>1; - $sth = $dbh->prepare("select * from people order by id"); - $sth->execute(); + $sth = $dbh->prepare("select * from people order by id"); + $sth->execute(); - # object are fetched as instance of DBD::Oracle::Object - my ($id1, $obj1) = $sth->fetchrow(); - my ($id2, $obj2) = $sth->fetchrow(); + # object are fetched as instance of DBD::Oracle::Object + my ($id1, $obj1) = $sth->fetchrow(); + my ($id2, $obj2) = $sth->fetchrow(); - # get full type-name of object - print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed - print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed + # get full type-name of object + print $obj1->type_name."44\n"; # 'TEST.PERSON' is printed + print $obj2->type_name."4\n"; # 'TEST.EMPLOYEE' is printed - # get attribute NAME from object - print $obj1->attr('NAME')."3\n"; # 'Black' is printed - print $obj2->attr('NAME')."3\n"; # 'Smith' is printed + # get attribute NAME from object + print $obj1->attr('NAME')."3\n"; # 'Black' is printed + print $obj2->attr('NAME')."3\n"; # 'Smith' is printed - # get all atributes as hash reference - my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} - my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, - # 'SALARY' => 5000 } + # get all atributes as hash reference + my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} + my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, + # 'SALARY' => 5000 } - # get all attributes (names and values) as array - my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) - my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, - # 'SALARY', 5000 ) + # get all attributes (names and values) as array + my @a1 = $obj1->attributes; # returns ('NAME', 'Black', 'AGE', 25) + my @a2 = $obj2->attributes; # returns ('NAME', 'Smith', 'AGE', 44, + # 'SALARY', 5000 ) So far DBD::Oracle has been tested on a table with 20 embedded Objects, Varrays and Tables nested to 10 levels. @@ -3608,7 +3597,7 @@ control the default parsing of strings into DATE values. An error will be generated if the contents of the string don't match the NLS format. If you're dealing in dates which don't match the default NLS format then you can either change the default NLS format or, more -commonly, use TO_CHAR(field, "format") and TO_DATE(?, "format") +commonly, use TO\_CHAR(field, "format") and TO\_DATE(?, "format") to explicitly specify formats for converting to and from strings. A slightly more subtle problem can occur with NUMBER types. The @@ -3617,11 +3606,11 @@ to separate thousands and a comma ("`,`") as the decimal point. Perl will generate warnings and use incorrect values when numbers, returned and formatted as strings in this way by Oracle, are used in a numeric context. You could explicitly convert each numeric -value using the TO_CHAR(...) function but that gets tedious very +value using the TO\_CHAR(...) function but that gets tedious very quickly. The best fix is to change the NLS settings. That can be done for an individual connection by doing: - $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); + $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"); There are some types, like BOOLEAN, that Oracle does not automatically convert to or from strings (pity). These need to be converted @@ -3629,70 +3618,70 @@ explicitly using SQL or PL/SQL functions. Examples: - # DATE values - my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) - SQL_END - $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); - - # BOOLEAN values - my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); - $sth2->bind_param( ":i1", $i1 ); - $sth2->bind_param_inout( ":o0", \$o0, 32 ); - $sth2->bind_param_inout( ":o1", \$o1, 32 ); - $sth2->execute(); - foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { - $_ = "(undef)" if ! defined $_; - } - print "$i0 to $o0, $i1 to $o1\n"; - # Result is : "'' to '(undef)', 'Something else' to '1'" - -## Support for Insert of XMLType (ORA_XMLTYPE) + # DATE values + my $sth0 = $dbh->prepare( <= TO_DATE( ?, ? ) + SQL_END + $sth0->execute( 'YYYY-MM-DD HH24:MI:SS', "2003", 'YYYY' ); + + # BOOLEAN values + my $sth2 = $dbh->prepare( <bind_param( ":i0", $i0 ); + $sth2->bind_param( ":i1", $i1 ); + $sth2->bind_param_inout( ":o0", \$o0, 32 ); + $sth2->bind_param_inout( ":o1", \$o1, 32 ); + $sth2->execute(); + foreach ( $i0, $b0, $o0, $i1, $b1, $o1 ) { + $_ = "(undef)" if ! defined $_; + } + print "$i0 to $o0, $i1 to $o1\n"; + # Result is : "'' to '(undef)', 'Something else' to '1'" + +## Support for Insert of XMLType (ORA\_XMLTYPE) Inserting large XML data sets into tables with XMLType fields is now supported by DBD::Oracle. The only special -requirement is the use of bind_param() with an attribute hash parameter that specifies ora_type as ORA_XMLTYPE. For +requirement is the use of bind\_param() with an attribute hash parameter that specifies ora\_type as ORA\_XMLTYPE. For example with a table like this; - create table books (book_id number, book_xml XMLType); + create table books (book_id number, book_xml XMLType); one can insert data using this code - $SQL='insert into books values (1,:p_xml)'; - $xml= ' + $SQL='insert into books values (1,:p_xml)'; + $xml= ' Programming the Perl DBI The Cheetah Book @@ -3704,9 +3693,9 @@ one can insert data using this code ... '; - my $sth =$dbh-> prepare($SQL); - $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); - $sth-> execute(); + my $sth =$dbh-> prepare($SQL); + $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); + $sth-> execute(); In the above case we will assume that $xml has 10000 Book nodes and is over 32k in size and is well formed XML. This will also work for XML that is smaller than 32k as well. Attempting to insert malformed XML will cause an error. @@ -3717,21 +3706,21 @@ Cursors can be returned from PL/SQL blocks, either from stored functions (or procedures with OUT parameters) or from direct `OPEN` statements, as shown below: - use DBI; - use DBD::Oracle qw(:ora_types); - my $dbh = DBI->connect(...); - my $sth1 = $dbh->prepare(q{ - BEGIN OPEN :cursor FOR - SELECT table_name, tablespace_name - FROM user_tables WHERE tablespace_name = :space; - END; - }); - $sth1->bind_param(":space", "USERS"); - my $sth2; - $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); - $sth1->execute; - # $sth2 is now a valid DBI statement handle for the cursor - while ( my @row = $sth2->fetchrow_array ) { ... } + use DBI; + use DBD::Oracle qw(:ora_types); + my $dbh = DBI->connect(...); + my $sth1 = $dbh->prepare(q{ + BEGIN OPEN :cursor FOR + SELECT table_name, tablespace_name + FROM user_tables WHERE tablespace_name = :space; + END; + }); + $sth1->bind_param(":space", "USERS"); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } The only special requirement is the use of `bind_param_inout()` with an attribute hash parameter that specifies `ora_type` as `ORA_RSET`. @@ -3741,34 +3730,34 @@ arguments in call to ...". Here's an alternative form using a function that returns a cursor. This example uses the pre-defined weak (or generic) REF CURSOR type -SYS_REFCURSOR. This is an Oracle 9 feature. +SYS\_REFCURSOR. This is an Oracle 9 feature. - # Create the function that returns a cursor - $dbh->do(q{ - CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR - AS l_cursor SYS_REFCURSOR; - BEGIN - OPEN l_cursor FOR select ename, empno from emp - ORDER BY ename; - RETURN l_cursor; - END; - }); + # Create the function that returns a cursor + $dbh->do(q{ + CREATE OR REPLACE FUNCTION sp_ListEmp RETURN SYS_REFCURSOR + AS l_cursor SYS_REFCURSOR; + BEGIN + OPEN l_cursor FOR select ename, empno from emp + ORDER BY ename; + RETURN l_cursor; + END; + }); - # Use the function that returns a cursor - my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); - my $sth2; - $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); - $sth1->execute; - # $sth2 is now a valid DBI statement handle for the cursor - while ( my @row = $sth2->fetchrow_array ) { ... } + # Use the function that returns a cursor + my $sth1 = $dbh->prepare(q{BEGIN :cursor := sp_ListEmp; END;}); + my $sth2; + $sth1->bind_param_inout(":cursor", \$sth2, 0, { ora_type => ORA_RSET } ); + $sth1->execute; + # $sth2 is now a valid DBI statement handle for the cursor + while ( my @row = $sth2->fetchrow_array ) { ... } A cursor obtained from PL/SQL as above may be passed back to PL/SQL by binding for input, as shown in this example, which explicitly closes a cursor: - my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); - $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); - $sth3->execute; + my $sth3 = $dbh->prepare("BEGIN CLOSE :cursor; END;"); + $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); + $sth3->execute; It is not normally necessary to close a cursor explicitly in this way. Oracle will close the cursor automatically @@ -3859,13 +3848,13 @@ is 0, which disables pre-fetching for queries involving nested cursors. Most of these PL/SQL examples come from: Eric Bartley . - /* - * PL/SQL to create package with stored procedures invoked by - * Perl examples. Execute using sqlplus. - * - * Use of "... OR REPLACE" prevents failure in the event that the - * package already exists. - */ + /* + * PL/SQL to create package with stored procedures invoked by + * Perl examples. Execute using sqlplus. + * + * Use of "... OR REPLACE" prevents failure in the event that the + * package already exists. + */ CREATE OR REPLACE PACKAGE plsql_example IS @@ -3883,8 +3872,8 @@ Most of these PL/SQL examples come from: Eric Bartley . FUNCTION func_np RETURN VARCHAR2; - END plsql_example; - / + END plsql_example; + / CREATE OR REPLACE PACKAGE BODY plsql_example IS @@ -3921,126 +3910,126 @@ Most of these PL/SQL examples come from: Eric Bartley . RETURN ret_val; END; - END plsql_example; - / - /* End PL/SQL for example package creation. */ + END plsql_example; + / + /* End PL/SQL for example package creation. */ - use DBI; + use DBI; - my($db, $csr, $ret_val); + my($db, $csr, $ret_val); - $db = DBI->connect('dbi:Oracle:database','user','password') - or die "Unable to connect: $DBI::errstr"; + $db = DBI->connect('dbi:Oracle:database','user','password') + or die "Unable to connect: $DBI::errstr"; - # So we don't have to check every DBI call we set RaiseError. - # See the DBI docs now if you're not familiar with RaiseError. - $db->{RaiseError} = 1; + # So we don't have to check every DBI call we set RaiseError. + # See the DBI docs now if you're not familiar with RaiseError. + $db->{RaiseError} = 1; - # Example 1 Eric Bartley - # - # Calling a PLSQL procedure that takes no parameters. This shows you the - # basic's of what you need to execute a PLSQL procedure. Just wrap your - # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. - # - # p.s. If you've used SQL*Plus's exec command all it does is wrap the - # command in a BEGIN END; block for you. + # Example 1 Eric Bartley + # + # Calling a PLSQL procedure that takes no parameters. This shows you the + # basic's of what you need to execute a PLSQL procedure. Just wrap your + # procedure call in a BEGIN END; block just like you'd do in SQL*Plus. + # + # p.s. If you've used SQL*Plus's exec command all it does is wrap the + # command in a BEGIN END; block for you. - $csr = $db->prepare(q{ - BEGIN - PLSQL_EXAMPLE.PROC_NP; - END; - }); - $csr->execute; + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_NP; + END; + }); + $csr->execute; - # Example 2 Eric Bartley - # - # Now we call a procedure that has 1 IN parameter. Here we use bind_param - # to bind out parameter to the prepared statement just like you might - # do for an INSERT, UPDATE, DELETE, or SELECT statement. - # - # I could have used positional placeholders (e.g. :1, :2, etc.) or - # ODBC style placeholders (e.g. ?), but I prefer Oracle's named - # placeholders (but few DBI drivers support them so they're not portable). + # Example 2 Eric Bartley + # + # Now we call a procedure that has 1 IN parameter. Here we use bind_param + # to bind out parameter to the prepared statement just like you might + # do for an INSERT, UPDATE, DELETE, or SELECT statement. + # + # I could have used positional placeholders (e.g. :1, :2, etc.) or + # ODBC style placeholders (e.g. ?), but I prefer Oracle's named + # placeholders (but few DBI drivers support them so they're not portable). - my $err_code = -20001; + my $err_code = -20001; - $csr = $db->prepare(q{ - BEGIN - PLSQL_EXAMPLE.PROC_IN(:err_code); - END; - }); + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; + }); - $csr->bind_param(":err_code", $err_code); + $csr->bind_param(":err_code", $err_code); - # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. - # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. - eval { - $csr->execute; - }; - print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; + # PROC_IN will RAISE_APPLICATION_ERROR which will cause the execute to 'fail'. + # Because we set RaiseError, the DBI will croak (die) so we catch that with eval. + eval { + $csr->execute; + }; + print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; - # Example 3 Eric Bartley - # - # Building on the last example, I've added 1 IN OUT parameter. We still - # use a placeholders in the call to prepare, the difference is that - # we now call bind_param_inout to bind the value to the place holder. - # - # Note that the third parameter to bind_param_inout is the maximum size - # of the variable. You normally make this slightly larger than necessary. - # But note that the Perl variable will have that much memory assigned to - # it even if the actual value returned is shorter. + # Example 3 Eric Bartley + # + # Building on the last example, I've added 1 IN OUT parameter. We still + # use a placeholders in the call to prepare, the difference is that + # we now call bind_param_inout to bind the value to the place holder. + # + # Note that the third parameter to bind_param_inout is the maximum size + # of the variable. You normally make this slightly larger than necessary. + # But note that the Perl variable will have that much memory assigned to + # it even if the actual value returned is shorter. - my $test_num = 5; - my $is_odd; + my $test_num = 5; + my $is_odd; - $csr = $db->prepare(q{ - BEGIN - PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); - END; - }); + $csr = $db->prepare(q{ + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; + }); - # The value of $test_num is _copied_ here - $csr->bind_param(":test_num", $test_num); + # The value of $test_num is _copied_ here + $csr->bind_param(":test_num", $test_num); - $csr->bind_param_inout(":is_odd", \$is_odd, 1); + $csr->bind_param_inout(":is_odd", \$is_odd, 1); - # The execute will automagically update the value of $is_odd - $csr->execute; + # The execute will automagically update the value of $is_odd + $csr->execute; - print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; + print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; - # Example 4 Eric Bartley - # - # What about the return value of a PLSQL function? Well treat it the same - # as you would a call to a function from SQL*Plus. We add a placeholder - # for the return value and bind it with a call to bind_param_inout so - # we can access it's value after execute. + # Example 4 Eric Bartley + # + # What about the return value of a PLSQL function? Well treat it the same + # as you would a call to a function from SQL*Plus. We add a placeholder + # for the return value and bind it with a call to bind_param_inout so + # we can access it's value after execute. - my $whoami = ""; + my $whoami = ""; - $csr = $db->prepare(q{ - BEGIN - :whoami := PLSQL_EXAMPLE.FUNC_NP; - END; - }); + $csr = $db->prepare(q{ + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; + }); - $csr->bind_param_inout(":whoami", \$whoami, 20); - $csr->execute; - print "Your database user name is $whoami\n"; + $csr->bind_param_inout(":whoami", \$whoami, 20); + $csr->execute; + print "Your database user name is $whoami\n"; - $db->disconnect; + $db->disconnect; You can find more examples in the t/plsql.t file in the DBD::Oracle source directory. Oracle 9.2 appears to have a bug where a variable bound -with bind_param_inout() that isn't assigned to by the executed +with bind\_param\_inout() that isn't assigned to by the executed PL/SQL block may contain garbage. See [http://www.mail-archive.com/dbi-users@perl.org/msg18835.html](http://www.mail-archive.com/dbi-users@perl.org/msg18835.html) @@ -4052,7 +4041,7 @@ DBD::Oracle will not raise an exception in some case. Specifically if you use ignored and returned as null. According to Oracle support this is part of the same mechanism where; - select (select * from dual where 0=1) from dual + select (select * from dual where 0=1) from dual returns a null value rather than an exception. @@ -4069,7 +4058,7 @@ for CVS, see [http://subversion.tigris.org/](http://subversion.tigris.org/)). To you'll need to install a Subversion client. Then, to get the source code, do: - svn checkout http://svn.perl.org/modules/dbd-oracle/trunk + svn checkout http://svn.perl.org/modules/dbd-oracle/trunk If it prompts for a username and password use your perl.org account if you have one, else just 'guest' and 'guest'. The source code will @@ -4082,12 +4071,12 @@ change log message and diff of each change checked-in to the source. After making your changes you can generate a patch file, but before you do, make sure your source is still upto date using: - svn update + svn update If you get any conflicts reported you'll need to fix them first. Then generate the patch file from within the `trunk` directory using: - svn diff > foo.patch + svn diff > foo.patch Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. @@ -4095,30 +4084,30 @@ Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. Unpack a fresh copy of the distribution: - tar xfz DBD-Oracle-1.40.tar.gz + tar xfz DBD-Oracle-1.40.tar.gz Rename the newly created top level directory: - mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo + mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo -Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you want. +Edit the contents of DBD-Oracle-1.40.your\_foo/\* till it does what you want. Test your changes and then remove all temporary files: - make test && make distclean + make test && make distclean Go back to the directory you originally unpacked the distribution: - cd .. + cd .. Unpack _another_ copy of the original distribution you started with: - tar xfz DBD-Oracle-1.40.tar.gz + tar xfz DBD-Oracle-1.40.tar.gz Then create a patch file by performing a recursive `diff` on the two top level directories: - diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch + diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch ## Speak before you patch @@ -4131,7 +4120,7 @@ you may not be aware of. ## GitHub repository A git mirror of the subversion is also available at -`https://github.com/yanick/DBD-Oracle`. +\`https://github.com/yanick/DBD-Oracle\`. # Oracle Related Links @@ -4142,25 +4131,25 @@ From version 1.25 onwards DBD::Oracle only support Oracle clients If you are still stuck with an older version of Oracle or its client you might want to look at the table below. - +---------------------+-----------------------------------------------------+ - | | Oracle Version | - +---------------------+----+-------------+---------+------+--------+--------+ - | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | - +---------------------+----+-------------+---------+------+--------+--------+ - | 0.1~16 | Y | Y | Y | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.17 | Y | Y | Y | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.18 | N | N | N | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.19 | N | N | N | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.20 | N | N | N | Y | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.21~1.24 | N | N | N | N | Y | Y | - +---------------------+----+-------------+---------+------+--------+--------+ - | 1.25+ | N | N | N | N | N | Y | - +---------------------+----+-------------+---------+------+--------+--------+ + +---------------------+-----------------------------------------------------+ + | | Oracle Version | + +---------------------+----+-------------+---------+------+--------+--------+ + | DBD::Oracle Version | <8 | 8.0.3~8.0.6 | 8iR1~R2 | 8iR3 | 9i | 9.2~11 | + +---------------------+----+-------------+---------+------+--------+--------+ + | 0.1~16 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.17 | Y | Y | Y | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.18 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.19 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.20 | N | N | N | Y | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.21~1.24 | N | N | N | N | Y | Y | + +---------------------+----+-------------+---------+------+--------+--------+ + | 1.25+ | N | N | N | N | N | Y | + +---------------------+----+-------------+---------+------+--------+--------+ As there are dozens of different versions of Oracle's clients this list does not include all of them, just the major released versions of @@ -4229,7 +4218,7 @@ http://www.ixora.com.au/ - Free Oracle Tools and Links -ora_explain supplied and installed with DBD::Oracle. +ora\_explain supplied and installed with DBD::Oracle. http://www.orafaq.com/ @@ -4272,25 +4261,14 @@ redistribute it and/or modify it under the same terms as Perl 5. # AUTHORS -- * - -Tim Bunce - -- * - -John Scoles - -- * - -Yanick Champoux - -- * - -Martin J. Evans +- Tim Bunce +- John Scoles +- Yanick Champoux +- Martin J. Evans # COPYRIGHT AND LICENSE This software is copyright (c) 1994 by Tim Bunce. This is free software; you can redistribute it and/or modify it under -the same terms as the Perl 5 programming language system itself. \ No newline at end of file +the same terms as the Perl 5 programming language system itself. diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 4b76143c..6b85731f 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.49_00'; + $DBD::Oracle::VERSION = '1.50'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1146,7 +1146,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.49_00 +version 1.50 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 0f48c2a6..21539965 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.49_00'; + $DBD::Oracle::GetInfo::VERSION = '1.50'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.49_00 +version 1.50 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index ba950f5c..5f314dbd 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.49_00'; + $DBD::Oracle::Object::VERSION = '1.50'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.49_00 +version 1.50 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 87ed8785..912ce571 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index 9bcd3947..c24abdc5 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.49_00 +version 1.50 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index aae9023a..ab82dcc4 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.49_00 +version 1.50 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pm b/lib/DBD/Oracle/Troubleshooting/Hpux.pm index 32a5fc0d..7d95e299 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pm +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pm @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 44755c62..5737ebfe 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index d00358be..5aacb224 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index c5fdf7c8..ebfd936f 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.49_00 +version 1.50 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 5d48431d..0dc054c2 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.49_00 +version 1.50 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index fd2418a5..d401973a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index cde25565..3a056878 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.49_00 +version 1.50 =head1 DBD::Oracle and Windows 64bit diff --git a/t/000-report-versions.t b/t/000-report-versions.t index 2d4a9a19..04c53948 100644 --- a/t/000-report-versions.t +++ b/t/000-report-versions.t @@ -415,6 +415,7 @@ BEGIN { Test::Pod::Coverage Test::Portability::Files Test::YAML::Meta + open ); my $Test = Test::Builder->new; @@ -437,7 +438,7 @@ BEGIN { next; } local $SIG{__WARN__} = sub { note "$module: $_[0]" }; - use_ok $module or BAIL_OUT("can't load $module"); + require_ok $module or BAIL_OUT("can't load $module"); my $version = $module->VERSION; $version = 'undefined' unless defined $version; diag(" $module version is $version"); diff --git a/t/10general.t b/t/10general.t index 1e492db0..7098ff0f 100644 --- a/t/10general.t +++ b/t/10general.t @@ -4,7 +4,6 @@ use warnings; use Test::More; use DBI; -use Oraperl; use Config; use DBD::Oracle qw(ORA_OCI); @@ -22,7 +21,7 @@ my $dbh = DBI->connect($dsn, $dbuser, '', }); if ($dbh) { - plan tests => 30; + plan tests => 28; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -114,8 +113,6 @@ ok($@ =~ /DBD::Oracle::db do failed:/, "eval error: ``$@'' expected 'do faile #print "''$warn''"; ok($warn =~ /DBD::Oracle::db do failed:/, "warn error: ``$warn'' expected 'do failed:'"); ok($DBI::err, 'err defined'); -ok($ora_errno, 'ora_errno defined'); -is($ora_errno, $DBI::err, 'ora_errno and err equal'); $dbh->{RaiseError} = 0; $dbh->{PrintError} = 0; # --- diff --git a/t/34pres_lobs.t b/t/34pres_lobs.t index d0135e11..213c4f0d 100644 --- a/t/34pres_lobs.t +++ b/t/34pres_lobs.t @@ -3,7 +3,6 @@ use Test::More; use DBI; -use Oraperl; use Config; use DBD::Oracle qw(:ora_types); From 6860e00157b1737778f7ce3e769a1aefbfb825d5 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 17 Aug 2012 15:36:00 +0000 Subject: [PATCH 302/637] removing Oraperl files git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15371 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 + MANIFEST | 2 - Makefile.PL | 12 - Oraperl.pm | 881 ---------------------------------------------------- oraperl.ph | 53 ---- 5 files changed, 3 insertions(+), 948 deletions(-) delete mode 100644 Oraperl.pm delete mode 100644 oraperl.ph diff --git a/Changes b/Changes index 6d0a38ae..50f5230d 100644 --- a/Changes +++ b/Changes @@ -47,6 +47,9 @@ NEXTRELEASE - the ora_taf_function is now passed a third argument of the connection handle (Martin J. Evans) + - RT78987 - removed Oraperl.pm and oraperl.ph; these files will be available + in a separate distribution named "Oraperl" (David Perry) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE (Martin J. Evans) diff --git a/MANIFEST b/MANIFEST index 14c29087..a385559d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -7,7 +7,6 @@ META.yml Makefile.PL Oracle.h Oracle.xs -Oraperl.pm README README.help.txt README.mkdn @@ -51,7 +50,6 @@ mkta.pl oci.def oci8.c ocitrace.h -oraperl.ph t/000-report-versions.t t/00versions.t t/01base.t diff --git a/Makefile.PL b/Makefile.PL index 3f322a01..356f5639 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1753,22 +1753,10 @@ sub symbol_search { sub post_initialize { my $self = shift; - if (-f "$Config{installprivlib}/DBD/Oraperl.pm"){ # very old now - print " -Please note: the Oraperl.pm installation location has changed. -It was: $Config{installprivlib}/DBD/Oraperl.pm -Is now: $Config{installprivlib}/Oraperl.pm -You have an old copy which you should delete when installing this one.\n"; - } - print "\nNote: \$ORACLE_HOME/lib must be added to your $need_ldlp_env environment variable\n", "before running \"make test\" and whenever DBD::Oracle is used.\n\n" if $need_ldlp_env && ($ENV{$need_ldlp_env}||'') !~ m:\Q$OH/lib\b:; - # Ensure Oraperl.pm and oraperl.ph are installed into top lib dir - $self->{PM}->{'Oraperl.pm'} = '$(INST_LIB)/Oraperl.pm'; - $self->{PM}->{'oraperl.ph'} = '$(INST_LIB)/oraperl.ph'; - eval { # This chunk is for Oracle::OCI require Data::Dumper; print main::MK_PM Data::Dumper->Purity(1)->Terse(0)->Indent(1)->Useqq(1) diff --git a/Oraperl.pm b/Oraperl.pm deleted file mode 100644 index e3796002..00000000 --- a/Oraperl.pm +++ /dev/null @@ -1,881 +0,0 @@ -# Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI -# -# Oraperl.pm -# -# Copyright (c) 1994,1995 Tim Bunce -# -# See the COPYRIGHT section in the Oracle.pm file for terms. -# -# To use this interface use one of the following invocations: -# -# use Oraperl; -# or -# eval 'use Oraperl; 1;' || die $@ if $] >= 5; -# -# The second form allows oraperl scripts to be used with -# both oraperl and perl 5. - -package Oraperl; - -require 5.004; - -use DBI 1.22; -use Exporter; - -$VERSION = substr(q$Revision: 1.44 $, 10); - -@ISA = qw(Exporter); - -@EXPORT = qw( - &ora_login &ora_open &ora_bind &ora_fetch &ora_close - &ora_logoff &ora_do &ora_titles &ora_lengths &ora_types - &ora_commit &ora_rollback &ora_autocommit &ora_version - &ora_readblob - $ora_cache $ora_long $ora_trunc $ora_errno $ora_errstr - $ora_verno $ora_debug -); - -$debug = 0 unless defined $debug; -$debugdbi = 0; -# $safe # set true/false before 'use Oraperl' if needed. -$safe = 1 unless defined $safe; - -# Help those who get core dumps from non-'safe' Oraperl (bad cursors) -use sigtrap qw(ILL); -if (!$safe) { - $SIG{BUS} = $SIG{SEGV} = sub { - print STDERR "Add BEGIN { \$Oraperl::safe=1 } above 'use Oraperl'.\n" - unless $safe; - goto &sigtrap::trap; - }; -} - - -# Install Driver (use of install_driver is a special case here) -$drh = DBI->install_driver('Oracle'); -if ($drh) { - print "DBD::Oracle driver installed as $drh\n" if $debug; - $drh->trace($debug); - $drh->{CompatMode} = 1; - $drh->{Warn} = 0; -} - - -use strict; - -sub _func_ref { - my $name = shift; - my $pkg = ($Oraperl::safe) ? "DBI" : "DBD::Oracle"; - \&{"${pkg}::$name"}; -} - -sub _warn { - my $prev_warn = shift; - if ($_[0] =~ /^(Bad|Duplicate) free/) { - return unless $ENV{PERL_DBD_DUMP} eq 'dump'; - print STDERR "Aborting with a core dump for diagnostics (PERL_DBD_DUMP)\n"; - CORE::dump; - } - $prev_warn ? &$prev_warn(@_) : warn @_; -} - - -# ----------------------------------------------------------------- -# -# $lda = &ora_login($system_id, $name, $password) -# &ora_logoff($lda) - -sub ora_login { - my($system_id, $name, $password) = @_; - local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local - local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; - return DBI->connect("dbi:Oracle:$system_id", $name, $password, { - PrintError => 0, AutoCommit => 0 - }); -} -sub ora_logoff { - my($dbh) = @_; - return if !$dbh; - local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local - local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; - $dbh->disconnect(); -} - - - -# ----------------------------------------------------------------- -# -# $csr = &ora_open($lda, $stmt [, $cache]) -# &ora_bind($csr, $var, ...) -# &ora_fetch($csr [, $trunc]) -# &ora_do($lda, $stmt) -# &ora_close($csr) - -sub ora_open { - my($lda, $stmt) = @_; - $Oraperl::ora_cache_o = $_[2]; # temp hack to pass cache through - - my $csr = $lda->prepare($stmt) or return undef; - - # only execute here if no bind vars specified - $csr->execute or return undef unless $csr->{NUM_OF_PARAMS}; - - $csr; -} - -*ora_bind = _func_ref('st::execute'); -*ora_fetch = \&{"DBD::Oracle::st::ora_fetch"}; -*ora_close = _func_ref('st::finish'); - -sub ora_do { - # error => undef - # 0 => "0E0" (0 but true) - # >0 => >0 - my($lda, $stmt, @params) = @_; # @params are an extension to the original Oraperl. - - return $lda->do($stmt, undef, @params); # SEE DEFAULT METHOD IN DBI.pm - - # OLD CODE: - # $csr is local, cursor will be closed on exit - my $csr = $lda->prepare($stmt) or return undef; - # Oracle OCI will automatically execute DDL statements in prepare()! - # We must be carefull not to execute them again! This needs careful - # examination and thought. - # Perhaps oracle is smart enough not to execute them again? - my $ret = $csr->execute(@params); - my $rows = $csr->rows; - ($rows == 0) ? "0E0" : $rows; -} - - -# ----------------------------------------------------------------- -# -# &ora_titles($csr [, $truncate]) -# &ora_lengths($csr) -# &ora_types($csr) - -sub ora_titles{ - my($csr, $trunc) = @_; - warn "ora_titles: truncate option not implemented" if $trunc; - @{$csr->{'NAME'}}; -} -sub ora_lengths{ - @{shift->{'ora_lengths'}} # oracle specific -} -sub ora_types{ - @{shift->{'ora_types'}} # oracle specific -} - - -# ----------------------------------------------------------------- -# -# &ora_commit($lda) -# &ora_rollback($lda) -# &ora_autocommit($lda, $on_off) -# &ora_version - -*ora_commit = _func_ref('db::commit'); -*ora_rollback = _func_ref('db::rollback'); - -sub ora_autocommit { - my($lda, $mode) = @_; - $lda->{AutoCommit} = $mode; - "0E0"; -} -sub ora_version { - my($sw) = DBI->internal; - print "\n"; - print "Oraperl emulation interface version $Oraperl::VERSION\n"; - print "$Oraperl::drh->{Attribution}\n"; - print "$sw->{Attribution}\n\n"; -} - - -# ----------------------------------------------------------------- -# -# $ora_errno -# $ora_errstr -*Oraperl::ora_errno = \$DBI::err; -*Oraperl::ora_errstr = \$DBI::errstr; - - -# ----------------------------------------------------------------- -# -# $ora_verno -# $ora_debug not supported, use $h->debug(2) where $h is $lda or $csr -# $ora_cache not supported -# $ora_long used at ora_open() -# $ora_trunc used at ora_open() - -$Oraperl::ora_verno = '3.000'; # to distinguish it from oraperl 2.4 - -# ora_long is left unset so that the DBI $h->{LongReadLen} attrib will be used -# by default. If ora_long is set then LongReadLen will be ignored (sadly) but -# that behaviour may change later to only apply to oraperl mode handles. -#$Oraperl::ora_long = 80; # 80, oraperl default -$Oraperl::ora_trunc = 0; # long trunc is error, oraperl default - - -# ----------------------------------------------------------------- -# -# Non-oraperl extensions added here to make it easy to still run -# script using oraperl (by avoiding $csr->blob_read(...)) - -*ora_readblob = _func_ref('st::blob_read'); - - -1; -__END__ - -=head1 NAME - -Oraperl - [DEPRECATED] Perl access to Oracle databases for old oraperl scripts - -=head1 SYNOPSIS - - eval 'use Oraperl; 1;' || die $@ if $] >= 5; # ADD THIS LINE TO OLD SCRIPTS - - $lda = &ora_login($system_id, $name, $password) - $csr = &ora_open($lda, $stmt [, $cache]) - &ora_bind($csr, $var, ...) - &ora_fetch($csr [, $trunc]) - &ora_close($csr) - &ora_logoff($lda) - - &ora_do($lda, $stmt) - - &ora_titles($csr) - &ora_lengths($csr) - &ora_types($csr) - &ora_commit($lda) - &ora_rollback($lda) - &ora_autocommit($lda, $on_off) - &ora_version() - - $ora_cache - $ora_long - $ora_trunc - $ora_errno - $ora_errstr - $ora_verno - - $ora_debug - -=head1 DESCRIPTION - -Oraperl is an extension to Perl which allows access to Oracle databases. - -The original oraperl was a Perl 4 binary with Oracle OCI compiled into it. -The Perl 5 Oraperl module described here is distributed with L -(a database driver what operates within L) and adds an extra layer over -L method calls. -The Oraperl module should only be used to allow existing Perl 4 oraperl scripts -to run with minimal changes; any new development should use L directly. - -The functions which make up this extension are described in the -following sections. All functions return a false or undefined (in the -Perl sense) value to indicate failure. You do not need to understand -the references to OCI in these descriptions. They are here to help -those who wish to extend the routines or to port them to new machines. - -The text in this document is largely unchanged from the original Perl4 -oraperl manual written by Kevin Stock . Any comments -specific to the DBD::Oracle Oraperl emulation are prefixed by B. -See the DBD::Oracle and DBI manuals for more information. - -B In order to make the oraperl function definitions available in -perl5 you need to arrange to 'use' the Oraperl.pm module in each file -or package which uses them. You can do this by simply adding S> in each file or package. If you need to make the scripts work -with both the perl4 oraperl and perl5 you should add add the following -text instead: - - eval 'use Oraperl; 1;' || die $@ if $] >= 5; - - -The use of I is deprecated in favor of L, -and will be removed from the I distribution as of -1.38. - -=head2 Principal Functions - -The main functions for database access are &ora_login(), &ora_open(), -&ora_bind(), &ora_fetch(), &ora_close(), &ora_do() and &ora_logoff(). - -=over 2 - -=item * ora_login - - $lda = &ora_login($system_id, $username, $password) - -In order to access information held within an Oracle database, a -program must first log in to it by calling the &ora_login() function. -This function is called with three parameters, the system ID (see -below) of the Oracle database to be used, and the Oracle username and -password. The value returned is a login identifier (actually an Oracle -Login Data Area) referred to below as $lda. - -Multiple logins may be active simultaneously. This allows a simple -mechanism for correlating or transferring data between databases. - -Most Oracle programs (for example, SQL*Plus or SQL*Forms) examine the -environment variable ORACLE_SID or TWO_TASK to determine which database -to connect to. In an environment which uses several different -databases, it is easy to make a mistake, and attempt to run a program -on the wrong one. Also, it is cumbersome to create a program which -works with more than one database simultaneously. Therefore, Oraperl -requires the system ID to be passed as a parameter. However, if the -system ID parameter is an empty string then oracle will use the -existing value of ORACLE_SID or TWO_TASK in the usual manner. - -Example: - - $lda = &ora_login('personnel', 'scott', 'tiger') || die $ora_errstr; - -This function is equivalent to the OCI olon and orlon functions. - -B note that a name is assumed to be a TNS alias if it does not -appear as the name of a SID in /etc/oratab or /var/opt/oracle/oratab. -See the code in Oracle.pm for the full logic of database name handling. - -B Since the returned $lda is a Perl5 reference the database login -identifier is now automatically released if $lda is overwritten or goes -out of scope. - -=item * ora_open - - $csr = &ora_open($lda, $statement [, $cache]) - -To specify an SQL statement to be executed, the program must call the -&ora_open() function. This function takes at least two parameters: a -login identifier (obtained from &ora_login()) and the SQL statement to -be executed. An optional third parameter specifies the size of the row -cache to be used for a SELECT statement. The value returned from -&ora_open() is a statement identifier (actually an ORACLE Cursor) -referred to below as $csr. - -If the row cache size is not specified, a default size is -used. As distributed, the default is five rows, but this -may have been changed at your installation (see the -&ora_version() function and $ora_cache variable below). - -Examples: - - $csr = &ora_open($lda, 'select ename, sal from emp order by ename', 10); - - $csr = &ora_open($lda, 'insert into dept values(:1, :2, :3)'); - -This function is equivalent to the OCI oopen and oparse functions. For -statements which do not contain substitution variables (see the section -Substitution Variables below), it also uses of the oexec function. For -SELECT statements, it also makes use of the odescr and odefin functions -to allocate memory for the values to be returned from the database. - -=item * ora_bind - - &ora_bind($csr, $var, ...) - -If an SQL statement contains substitution variables (see the section -Substitution Variables below), &ora_bind() is used to assign actual -values to them. This function takes a statement identifier (obtained -from &ora_open()) as its first parameter, followed by as many -parameters as are required by the statement. - -Example: - - &ora_bind($csr, 50, 'management', 'Paris'); - -This function is equivalent to the OCI obndrn and oexec statements. - -The OCI obndrn function does not allow empty strings to be bound. As -distributed, $ora_bind therefore replaces empty strings with a single -space. However, a compilation option allows this substitution to be -suppressed, causing &ora_bind() to fail. The output from the -&ora_version() function specifies which is the case at your installation. - -=item * ora_fetch - - $nfields = &ora_fetch($csr) - - @data = &ora_fetch($csr [, $trunc]) - -The &ora_fetch() function is used in conjunction with a SQL SELECT -statement to retrieve information from a database. This function takes -one mandatory parameter, a statement identifier (obtained from -&ora_open()). - -Used in a scalar context, the function returns the number of fields -returned by the query but no data is actually fetched. This may be -useful in a program which allows a user to enter a statement interactively. - -Example: - - $nfields = &ora_fetch($csr); - -Used in an array context, the value returned is an array containing the -data, one element per field. Note that this will not work as expected: - - @data = &ora_fetch($csr) || die "..."; # WRONG - -The || forces a scalar context so ora_fetch returns the number of fields. - -An optional second parameter may be supplied to indicate whether the -truncation of a LONG or LONG RAW field is to be permitted (non-zero) or -considered an error (zero). If this parameter is not specified, the -value of the global variable $ora_trunc is used instead. Truncation of -other datatypes is always considered a error. - -B The optional second parameter to ora_fetch is not supported. -A DBI usage error will be generated if a second parameter is supplied. -Use the global variable $ora_trunc instead. Also note that the -experimental DBI blob_read method can be used to retrieve a long: - - $csr->blob_read($field, $offset, $len [, \$dest, $destoffset]); - -If truncation occurs, $ora_errno will be set to 1406. &ora_fetch() -will complete successfully if truncation is permitted, otherwise it -will fail. - -&ora_fetch() will fail at the end of the data or if an error occurs. It -is possible to distinguish between these cases by testing the value of -the variable $ora_errno. This will be zero for end of data, non-zero if -an error has occurred. - -Example: - - while (($deptno, $dname, $loc) = &ora_fetch($csr)) - { - warn "Truncated!!!" if $ora_errno == 1406; - # do something with the data - } - warn $ora_errstr if $ora_errno; - -This function is equivalent to the OCI ofetch function. - -=item * ora_close - - &ora_close($csr) - -If an SQL statement is no longer required (for example, all the data -selected has been processed, or no more rows are to be inserted) then -the statement identifier should be released. This is done by calling -the &ora_close() function with the statement identifier as its only -parameter. - -This function is equivalent to the OCI oclose function. - -B Since $csr is a Perl5 reference the statement/cursor is now -automatically closed if $csr is overwritten or goes out of scope. - - -=item * ora_do - - &ora_do($lda, $statement) - -Not all SQL statements return data or contain substitution -variables. In these cases the &ora_do() function may be -used as an alternative to &ora_open() and &ora_close(). -This function takes two parameters, a login identifier and -the statement to be executed. - -Example: - - &ora_do($lda, 'drop table employee'); - -This function is roughly equivalent to - - &ora_close( &ora_open($lda, $statement) ) - -B oraperl v2 used to return the string 'OK' to indicate -success with a zero numeric value. The Oraperl emulation now -uses the string '0E0' to achieve the same effect since it does -not cause any C<-w> warnings when used in a numeric context. - -=item * ora_logoff - - &ora_logoff($lda) - -When the program no longer needs to access a given database, the login -identifier should be released using the &ora_logoff() function. - -This function is equivalent to the OCI ologoff function. - -B Since $lda is a Perl5 reference the database login identifier -is now automatically released if $lda is overwritten or goes out of scope. - -=back - -=head2 Ancillary Functions - -Additional functions available are: &ora_titles(), -&ora_lengths(), &ora_types(), &ora_autocommit(), -&ora_commit(), &ora_rollback() and &ora_version(). - -The first three are of most use within a program which -allows statements to be entered interactively. See, for -example, the sample program sql which is supplied with -Oraperl and may have been installed at your site. - -=over 2 - -=item * ora_titles - - @titles = &ora_titles($csr) - -A program may determine the field titles of an executed -query by calling &ora_titles(). This function takes a -single parameter, a statement identifier (obtained from -&ora_open()) indicating the query for which the titles are -required. The titles are returned as an array of strings, -one for each column. - -Titles are truncated to the length of the field, as reported -by the &ora_lengths() function. - -B oraperl v2.2 actually changed the behaviour such that the -titles were not truncated unless an optional second parameter was -true. This was not reflected in the oraperl manual. The Oraperl -emulation adopts the non truncating behaviour and doesn't support the -truncate parameter. - - -=item * ora_lengths - - @lengths = &ora_lengths($csr) - -A program may determine the length of each of the fields -returned by a query by calling the &ora_lengths() function. -This function takes a single parameter, a statement -identifier (obtained from &ora_open()) indicating the query -for which the lengths are required. The lengths are -returned as an array of integers, one for each column. - - -=item * ora_types - - @types = &ora_types($csr) - -A program may determine the type of each of the fields returned by a -query by calling the &ora_types() function. This function takes a -single parameter, a statement identifier (obtained from &ora_open()) -indicating the query for which the lengths are required. The types are -returned as an array of integers, one for each field. - -These types are defined in your OCI documentation. The correct -interpretation for Oracle v6 is given in the file oraperl.ph. - - -=item * ora_autocommit - - &ora_autocommit($lda, $on_or_off) - -Autocommit mode (in which each transaction is committed immediately, -without waiting for an explicit commit) may be enabled or disabled -using &ora_autocommit(). This function takes two parameters, a login -identifier (obtained from &ora_login()) and a true/false value -indicating whether autocommit is to be enabled (non-zero) or disabled -(zero). By default, autocommit is off. - -Note that autocommit can only be set per login, not per statement. If -you need to control autocommit by statement (for example, to allow -deletions to be rolled back, but insertions to be committed -immediately) you should make multiple calls to &ora_login() and use a -separate login identifier for each statement. - - -=item * ora_commit, ora_rollback - - &ora_commit($lda) - &ora_rollback($lda) - -Modifications to a database may be committed or rolled back using the -&ora_commit() and &ora_rollback() functions. These functions take a -single parameter, a login identifier obtained from &ora_login(). - -Transactions which have been committed (either explicitly by a call to -&ora_commit() or implicitly through the use of &ora_autocommit()) -cannot be subsequently rolled back. - -Note that commit and rollback can only be used per login, not per -statement. If you need to commit or rollback by statement you should -make multiple calls to &ora_login() and use a separate login identifier -for each statement. - - -=item * ora_version - - &ora_version() - -The &ora_version() function prints the version number and -copyright information concerning Oraperl. It also prints -the values of various compilation time options. It does not -return any value, and should not normally be used in a -program. - -Example: - - perl -MOraperl -e 'ora_version()' - - This is Oraperl, version 2, patch level 0. - - Debugging is available, including the -D flag. - Default fetch row cache size is 5. - Empty bind values are replaced by a space. - - Perl is copyright by Larry Wall; type oraperl -v for details. - Additions for oraperl: Copyright 1991, 1992, Kevin Stock. - - Oraperl may be distributed under the same conditions as Perl. - -This function is the equivalent of Perl's C<-v> flag. - -B The Oraperl emulation printout is similar but not identical. - -=back - -=head1 VARIABLES - -Six special variables are provided, $ora_cache, $ora_long, -$ora_trunc, $ora_errno, $ora_errstr and $ora_verno. - -=head2 Customisation Variables - -These variables are used to dictate the behaviour of Oraperl -under certain conditions. - -=over 2 - -=item * $ora_cache - -The $ora_cache variable determines the default cache size used by the -&ora_open() function for SELECT statements if an explicit cache size is -not given. - -It is initialised to the default value reported by &ora_version() but -may be set within a program to apply to all subsequent calls to -&ora_open(). Cursors which are already open are not affected. As -distributed, the default value is five, but may have been altered at -your installation. - -As a special case, assigning zero to $ora_cache resets it to the -default value. Attempting to set $ora_cache to a negative value results -in a warning. - - -=item * $ora_long - -Normally, Oraperl interrogates the database to determine the length of -each field and allocates buffer space accordingly. This is not -possible for fields of type LONG or LONGRAW. To allocate space -according to the maximum possible length (65535 bytes) would obviously -be extremely wasteful of memory. - -Therefore, when &ora_open() determines that a field is a LONG type, it -allocates the amount of space indicated by the $ora_long variable. This -is initially set to 80 (for compatibility with Oracle products) but may -be set within a program to whatever size is required. - -$ora_long is only used when fetching data, not when inserting it. - - -=item * $ora_trunc - -Since Oraperl cannot determine exactly the maximum length of a LONG -field, it is possible that the length indicated by $ora_long is not -sufficient to store the data fetched. In such a case, the optional -second parameter to &ora_fetch() indicates whether the truncation -should be allowed or should provoke an error. - -If this second parameter is not specified, the value of $ora_trunc is -used as a default. This only applies to LONG and LONGRAW data types. -Truncation of a field of any other type is always considered an error -(principally because it indicates a bug in Oraperl). - -=back - -=head2 Status Variables - -These variables report information about error conditions or about -Oraperl itself. They may only be read; a fatal error occurs if a -program attempts to change them. - -=over 2 - -=item * $ora_errno - -$ora_errno contains the Oracle error code provoked by the last function -call. - -There are two cases of particular interest concerning &ora_fetch(). If -a LONG or LONGRAW field is truncated (and truncation is allowed) then -&ora_fetch() will complete successfully but $ora_errno will be set to -1406 to indicate the truncation. When &ora_fetch() fails, $ora_errno -will be set to zero if this was due to the end of data or an error code -if it was due to an actual error. - - -=item * $ora_errstr - -The $ora_errstr variable contains the Oracle error message -corresponding to the current value of $ora_errno. - - -=item * $ora_verno - -The $ora_verno variable contains the version number of Oraperl in the -form v.ppp where v is the major version number and ppp is the -patchlevel. For example, in Oraperl version 3, patch level 142, -$ora_verno would contain the value 3.142 (more or less, allowing for -floating point error). - -=back - - -=head1 SUBSTITUTION VARIABLES - -Oraperl allows an SQL statement to contain substitution variables. -These consist of a colon followed by a number. For example, a program -which added records to a telephone list might use the following call to -&ora_open(): - - $csr = &ora_open($csr, "insert into telno values(:1, :2)"); - -The two names :1 and :2 are called substitution variables. The -function &ora_bind() is used to assign values to these variables. For -example, the following statements would add two new people to the -list: - - &ora_bind($csr, "Annette", "472-8836"); - &ora_bind($csr, "Brian", "937-1823"); - -Note that the substitution variables must be assigned consecutively -beginning from 1 for each SQL statement, as &ora_bind() assigns its -parameters in this order. Named substitution variables (for example, -:NAME, :TELNO) are not permitted. - -B Substitution variables are now bound as type 1 (VARCHAR2) -and not type 5 (STRING) by default. This can alter the behaviour of -SQL code which compares a char field with a substitution variable. -See the String Comparison section in the Datatypes chapter of the -Oracle OCI manual for more details. - -You can work around this by using DBD::Oracle's ability to specify -the Oracle type to be used on a per field basis: - - $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) - $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); - $csr->bind_param(1, $value_x, $char_attrib); - $csr->bind_param(2, $value_y, $char_attrib); - ora_bind($csr); # bind with no parameters since we've done bind_param()'s - - -=head1 DEBUGGING - -B The Oraperl $ora_debug variable is not supported. However -detailed debugging can be enabled at any time by executing - - $h->debug(2); - -where $h is either a $lda or a $csr. If debugging is enabled on an -$lda then it is automatically passed on to any cursors returned by -&ora_open(). - -=head1 EXAMPLE - - format STDOUT_TOP = - Name Phone - ==== ===== - . - - format STDOUT = - @<<<<<<<<<< @>>>>>>>>>> - $name, $phone - . - - die "You should use oraperl, not perl\n" unless defined &ora_login; - $ora_debug = shift if $ARGV[0] =~ /^\-#/; - - $lda = &ora_login('t', 'kstock', 'kstock') - || die $ora_errstr; - $csr = &ora_open($lda, 'select * from telno order by name') - || die $ora_errstr; - - $nfields = &ora_fetch($csr); - print "Query will return $nfields fields\n\n"; - - while (($name, $phone) = &ora_fetch($csr)) { write; } - warn $ora_errstr if $ora_errno; - - die "fetch error: $ora_errstr" if $ora_errno; - - do ora_close($csr) || die "can't close cursor"; - do ora_logoff($lda) || die "can't log off Oracle"; - - -=head1 NOTES - -In keeping with the philosophy of Perl, there is no pre-defined limit -to the number of simultaneous logins or SQL statements which may be -active, nor to the number of data fields which may be returned by a -query. The only limits are those imposed by the amount of memory -available, or by Oracle. - - -=head1 WARNINGS - -The Oraperl emulation software shares no code with the original -oraperl. It is built on top of the new Perl5 DBI and DBD::Oracle -modules. These modules are still evolving. (One of the goals of -the Oraperl emulation software is to allow useful work to be done -with the DBI and DBD::Oracle modules whilst insulating users from -the ongoing changes in their interfaces.) - -It is quite possible, indeed probable, that some differences in -behaviour will exist. These are probably confined to error handling. - -B differences in behaviour which are not documented here should be -reported to to dbi-users@perl.org. - - -=head1 SEE ALSO - -=over 2 - -=item Oracle Documentation - -SQL Language Reference Manual. -Programmer's Guide to the Oracle Call Interfaces. - -=item Books - -Programming Perl by Larry Wall and Randal Schwartz. -Learning Perl by Randal Schwartz. - -=item Manual Pages - -perl(1) - -=back - -=head1 AUTHOR - -Original Oraperl 2.4 code and documentation -by Kevin Stock . - -DBI and Oraperl emulation using DBD::Oracle by Tim Bunce. - -=head1 MAINTAINER - -As of DBD::Oracle release 1.17 in February 2006 The Pythian Group, Inc. -(L) are taking the lead in maintaining DBD::Oracle with -my assistance and gratitude. - -=head1 COPYRIGHT - -Copyright (c) 1994-2006 Tim Bunce. Ireland. -Copyright (c) 2006-2008 John Scoles (The Pythian Group). Canada. - -The DBD::Oracle module is free open source software; you can -redistribute it and/or modify it under the same terms as Perl 5. - -=cut diff --git a/oraperl.ph b/oraperl.ph deleted file mode 100644 index 99f62994..00000000 --- a/oraperl.ph +++ /dev/null @@ -1,53 +0,0 @@ -# DBD::Oracle Oraperl emulation. This file is not relevant to the -# emulation but is included for completeness only. -# I have updated %ora_types in case it's used. Tim Bunce. - -# oraperl.ph -# -# Various constants which may be useful in oraperl programs -# -# Author: Kevin Stock -# Date: 28th October 1991 -# Last Change: 8th April 1992 - - -# Oraperl error codes, set in $ora_errno - -$ORAP_NOMEM = 100001; # out of memory -$ORAP_INVCSR = 100002; # invalid cursor supplied -$ORAP_INVLDA = 100003; # invalid lda supplied -$ORAP_NOSID = 100004; # couldn't set ORACLE_SID -$ORAP_BADVAR = 100005; # bad colon variable sequence -$ORAP_NUMVARS = 100006; # wrong number of colon variables -$ORAP_NODATA = 100007; # statement does not return data - - -# Oraperl debugging codes for $ora_debug -# From version 2, you shouldn't really use these. - -$ODBG_EXEC = 8; # program execution -$ODBG_STRNUM = 32; # string/numeric conversions -$ODBG_MALLOC = 128; # memory allocation/release - -# Oracle datatypes -# I don't know whether these are valid for all versions. - -%ora_types = -( - 1, 'character array', - 2, 'number', - 3, 'signed integer', - 4, 'float', - 7, 'packed decimal', - 8, 'long string', - 9, 'varchar', - 11, 'rowid', - 12, 'date', - 15, 'varraw', - 23, 'raw', - 24, 'long raw', - 96, 'char', - 106,'mlslabel', -); - -1; From 2d23d1e929db1a468d20779e68283f30f3d3f5fe Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 17 Aug 2012 15:36:00 +0000 Subject: [PATCH 303/637] removing Oraperl files git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15371 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 + MANIFEST | 2 - Makefile.PL | 12 - Oraperl.pm | 881 ---------------------------------------------------- oraperl.ph | 53 ---- 5 files changed, 3 insertions(+), 948 deletions(-) delete mode 100644 Oraperl.pm delete mode 100644 oraperl.ph diff --git a/Changes b/Changes index 6d0a38ae..50f5230d 100644 --- a/Changes +++ b/Changes @@ -47,6 +47,9 @@ NEXTRELEASE - the ora_taf_function is now passed a third argument of the connection handle (Martin J. Evans) + - RT78987 - removed Oraperl.pm and oraperl.ph; these files will be available + in a separate distribution named "Oraperl" (David Perry) + [MISCELLANEOUS] - hide dr, db and st packages from PAUSE (Martin J. Evans) diff --git a/MANIFEST b/MANIFEST index 14c29087..a385559d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -7,7 +7,6 @@ META.yml Makefile.PL Oracle.h Oracle.xs -Oraperl.pm README README.help.txt README.mkdn @@ -51,7 +50,6 @@ mkta.pl oci.def oci8.c ocitrace.h -oraperl.ph t/000-report-versions.t t/00versions.t t/01base.t diff --git a/Makefile.PL b/Makefile.PL index 3f322a01..356f5639 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1753,22 +1753,10 @@ sub symbol_search { sub post_initialize { my $self = shift; - if (-f "$Config{installprivlib}/DBD/Oraperl.pm"){ # very old now - print " -Please note: the Oraperl.pm installation location has changed. -It was: $Config{installprivlib}/DBD/Oraperl.pm -Is now: $Config{installprivlib}/Oraperl.pm -You have an old copy which you should delete when installing this one.\n"; - } - print "\nNote: \$ORACLE_HOME/lib must be added to your $need_ldlp_env environment variable\n", "before running \"make test\" and whenever DBD::Oracle is used.\n\n" if $need_ldlp_env && ($ENV{$need_ldlp_env}||'') !~ m:\Q$OH/lib\b:; - # Ensure Oraperl.pm and oraperl.ph are installed into top lib dir - $self->{PM}->{'Oraperl.pm'} = '$(INST_LIB)/Oraperl.pm'; - $self->{PM}->{'oraperl.ph'} = '$(INST_LIB)/oraperl.ph'; - eval { # This chunk is for Oracle::OCI require Data::Dumper; print main::MK_PM Data::Dumper->Purity(1)->Terse(0)->Indent(1)->Useqq(1) diff --git a/Oraperl.pm b/Oraperl.pm deleted file mode 100644 index e3796002..00000000 --- a/Oraperl.pm +++ /dev/null @@ -1,881 +0,0 @@ -# Oraperl Emulation Interface for Perl 5 DBD::Oracle DBI -# -# Oraperl.pm -# -# Copyright (c) 1994,1995 Tim Bunce -# -# See the COPYRIGHT section in the Oracle.pm file for terms. -# -# To use this interface use one of the following invocations: -# -# use Oraperl; -# or -# eval 'use Oraperl; 1;' || die $@ if $] >= 5; -# -# The second form allows oraperl scripts to be used with -# both oraperl and perl 5. - -package Oraperl; - -require 5.004; - -use DBI 1.22; -use Exporter; - -$VERSION = substr(q$Revision: 1.44 $, 10); - -@ISA = qw(Exporter); - -@EXPORT = qw( - &ora_login &ora_open &ora_bind &ora_fetch &ora_close - &ora_logoff &ora_do &ora_titles &ora_lengths &ora_types - &ora_commit &ora_rollback &ora_autocommit &ora_version - &ora_readblob - $ora_cache $ora_long $ora_trunc $ora_errno $ora_errstr - $ora_verno $ora_debug -); - -$debug = 0 unless defined $debug; -$debugdbi = 0; -# $safe # set true/false before 'use Oraperl' if needed. -$safe = 1 unless defined $safe; - -# Help those who get core dumps from non-'safe' Oraperl (bad cursors) -use sigtrap qw(ILL); -if (!$safe) { - $SIG{BUS} = $SIG{SEGV} = sub { - print STDERR "Add BEGIN { \$Oraperl::safe=1 } above 'use Oraperl'.\n" - unless $safe; - goto &sigtrap::trap; - }; -} - - -# Install Driver (use of install_driver is a special case here) -$drh = DBI->install_driver('Oracle'); -if ($drh) { - print "DBD::Oracle driver installed as $drh\n" if $debug; - $drh->trace($debug); - $drh->{CompatMode} = 1; - $drh->{Warn} = 0; -} - - -use strict; - -sub _func_ref { - my $name = shift; - my $pkg = ($Oraperl::safe) ? "DBI" : "DBD::Oracle"; - \&{"${pkg}::$name"}; -} - -sub _warn { - my $prev_warn = shift; - if ($_[0] =~ /^(Bad|Duplicate) free/) { - return unless $ENV{PERL_DBD_DUMP} eq 'dump'; - print STDERR "Aborting with a core dump for diagnostics (PERL_DBD_DUMP)\n"; - CORE::dump; - } - $prev_warn ? &$prev_warn(@_) : warn @_; -} - - -# ----------------------------------------------------------------- -# -# $lda = &ora_login($system_id, $name, $password) -# &ora_logoff($lda) - -sub ora_login { - my($system_id, $name, $password) = @_; - local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local - local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; - return DBI->connect("dbi:Oracle:$system_id", $name, $password, { - PrintError => 0, AutoCommit => 0 - }); -} -sub ora_logoff { - my($dbh) = @_; - return if !$dbh; - local($Oraperl::prev_warn) = $SIG{'__WARN__'} || 0; # must be local - local($SIG{'__WARN__'}) = sub { _warn($Oraperl::prev_warn, @_) }; - $dbh->disconnect(); -} - - - -# ----------------------------------------------------------------- -# -# $csr = &ora_open($lda, $stmt [, $cache]) -# &ora_bind($csr, $var, ...) -# &ora_fetch($csr [, $trunc]) -# &ora_do($lda, $stmt) -# &ora_close($csr) - -sub ora_open { - my($lda, $stmt) = @_; - $Oraperl::ora_cache_o = $_[2]; # temp hack to pass cache through - - my $csr = $lda->prepare($stmt) or return undef; - - # only execute here if no bind vars specified - $csr->execute or return undef unless $csr->{NUM_OF_PARAMS}; - - $csr; -} - -*ora_bind = _func_ref('st::execute'); -*ora_fetch = \&{"DBD::Oracle::st::ora_fetch"}; -*ora_close = _func_ref('st::finish'); - -sub ora_do { - # error => undef - # 0 => "0E0" (0 but true) - # >0 => >0 - my($lda, $stmt, @params) = @_; # @params are an extension to the original Oraperl. - - return $lda->do($stmt, undef, @params); # SEE DEFAULT METHOD IN DBI.pm - - # OLD CODE: - # $csr is local, cursor will be closed on exit - my $csr = $lda->prepare($stmt) or return undef; - # Oracle OCI will automatically execute DDL statements in prepare()! - # We must be carefull not to execute them again! This needs careful - # examination and thought. - # Perhaps oracle is smart enough not to execute them again? - my $ret = $csr->execute(@params); - my $rows = $csr->rows; - ($rows == 0) ? "0E0" : $rows; -} - - -# ----------------------------------------------------------------- -# -# &ora_titles($csr [, $truncate]) -# &ora_lengths($csr) -# &ora_types($csr) - -sub ora_titles{ - my($csr, $trunc) = @_; - warn "ora_titles: truncate option not implemented" if $trunc; - @{$csr->{'NAME'}}; -} -sub ora_lengths{ - @{shift->{'ora_lengths'}} # oracle specific -} -sub ora_types{ - @{shift->{'ora_types'}} # oracle specific -} - - -# ----------------------------------------------------------------- -# -# &ora_commit($lda) -# &ora_rollback($lda) -# &ora_autocommit($lda, $on_off) -# &ora_version - -*ora_commit = _func_ref('db::commit'); -*ora_rollback = _func_ref('db::rollback'); - -sub ora_autocommit { - my($lda, $mode) = @_; - $lda->{AutoCommit} = $mode; - "0E0"; -} -sub ora_version { - my($sw) = DBI->internal; - print "\n"; - print "Oraperl emulation interface version $Oraperl::VERSION\n"; - print "$Oraperl::drh->{Attribution}\n"; - print "$sw->{Attribution}\n\n"; -} - - -# ----------------------------------------------------------------- -# -# $ora_errno -# $ora_errstr -*Oraperl::ora_errno = \$DBI::err; -*Oraperl::ora_errstr = \$DBI::errstr; - - -# ----------------------------------------------------------------- -# -# $ora_verno -# $ora_debug not supported, use $h->debug(2) where $h is $lda or $csr -# $ora_cache not supported -# $ora_long used at ora_open() -# $ora_trunc used at ora_open() - -$Oraperl::ora_verno = '3.000'; # to distinguish it from oraperl 2.4 - -# ora_long is left unset so that the DBI $h->{LongReadLen} attrib will be used -# by default. If ora_long is set then LongReadLen will be ignored (sadly) but -# that behaviour may change later to only apply to oraperl mode handles. -#$Oraperl::ora_long = 80; # 80, oraperl default -$Oraperl::ora_trunc = 0; # long trunc is error, oraperl default - - -# ----------------------------------------------------------------- -# -# Non-oraperl extensions added here to make it easy to still run -# script using oraperl (by avoiding $csr->blob_read(...)) - -*ora_readblob = _func_ref('st::blob_read'); - - -1; -__END__ - -=head1 NAME - -Oraperl - [DEPRECATED] Perl access to Oracle databases for old oraperl scripts - -=head1 SYNOPSIS - - eval 'use Oraperl; 1;' || die $@ if $] >= 5; # ADD THIS LINE TO OLD SCRIPTS - - $lda = &ora_login($system_id, $name, $password) - $csr = &ora_open($lda, $stmt [, $cache]) - &ora_bind($csr, $var, ...) - &ora_fetch($csr [, $trunc]) - &ora_close($csr) - &ora_logoff($lda) - - &ora_do($lda, $stmt) - - &ora_titles($csr) - &ora_lengths($csr) - &ora_types($csr) - &ora_commit($lda) - &ora_rollback($lda) - &ora_autocommit($lda, $on_off) - &ora_version() - - $ora_cache - $ora_long - $ora_trunc - $ora_errno - $ora_errstr - $ora_verno - - $ora_debug - -=head1 DESCRIPTION - -Oraperl is an extension to Perl which allows access to Oracle databases. - -The original oraperl was a Perl 4 binary with Oracle OCI compiled into it. -The Perl 5 Oraperl module described here is distributed with L -(a database driver what operates within L) and adds an extra layer over -L method calls. -The Oraperl module should only be used to allow existing Perl 4 oraperl scripts -to run with minimal changes; any new development should use L directly. - -The functions which make up this extension are described in the -following sections. All functions return a false or undefined (in the -Perl sense) value to indicate failure. You do not need to understand -the references to OCI in these descriptions. They are here to help -those who wish to extend the routines or to port them to new machines. - -The text in this document is largely unchanged from the original Perl4 -oraperl manual written by Kevin Stock . Any comments -specific to the DBD::Oracle Oraperl emulation are prefixed by B. -See the DBD::Oracle and DBI manuals for more information. - -B In order to make the oraperl function definitions available in -perl5 you need to arrange to 'use' the Oraperl.pm module in each file -or package which uses them. You can do this by simply adding S> in each file or package. If you need to make the scripts work -with both the perl4 oraperl and perl5 you should add add the following -text instead: - - eval 'use Oraperl; 1;' || die $@ if $] >= 5; - - -The use of I is deprecated in favor of L, -and will be removed from the I distribution as of -1.38. - -=head2 Principal Functions - -The main functions for database access are &ora_login(), &ora_open(), -&ora_bind(), &ora_fetch(), &ora_close(), &ora_do() and &ora_logoff(). - -=over 2 - -=item * ora_login - - $lda = &ora_login($system_id, $username, $password) - -In order to access information held within an Oracle database, a -program must first log in to it by calling the &ora_login() function. -This function is called with three parameters, the system ID (see -below) of the Oracle database to be used, and the Oracle username and -password. The value returned is a login identifier (actually an Oracle -Login Data Area) referred to below as $lda. - -Multiple logins may be active simultaneously. This allows a simple -mechanism for correlating or transferring data between databases. - -Most Oracle programs (for example, SQL*Plus or SQL*Forms) examine the -environment variable ORACLE_SID or TWO_TASK to determine which database -to connect to. In an environment which uses several different -databases, it is easy to make a mistake, and attempt to run a program -on the wrong one. Also, it is cumbersome to create a program which -works with more than one database simultaneously. Therefore, Oraperl -requires the system ID to be passed as a parameter. However, if the -system ID parameter is an empty string then oracle will use the -existing value of ORACLE_SID or TWO_TASK in the usual manner. - -Example: - - $lda = &ora_login('personnel', 'scott', 'tiger') || die $ora_errstr; - -This function is equivalent to the OCI olon and orlon functions. - -B note that a name is assumed to be a TNS alias if it does not -appear as the name of a SID in /etc/oratab or /var/opt/oracle/oratab. -See the code in Oracle.pm for the full logic of database name handling. - -B Since the returned $lda is a Perl5 reference the database login -identifier is now automatically released if $lda is overwritten or goes -out of scope. - -=item * ora_open - - $csr = &ora_open($lda, $statement [, $cache]) - -To specify an SQL statement to be executed, the program must call the -&ora_open() function. This function takes at least two parameters: a -login identifier (obtained from &ora_login()) and the SQL statement to -be executed. An optional third parameter specifies the size of the row -cache to be used for a SELECT statement. The value returned from -&ora_open() is a statement identifier (actually an ORACLE Cursor) -referred to below as $csr. - -If the row cache size is not specified, a default size is -used. As distributed, the default is five rows, but this -may have been changed at your installation (see the -&ora_version() function and $ora_cache variable below). - -Examples: - - $csr = &ora_open($lda, 'select ename, sal from emp order by ename', 10); - - $csr = &ora_open($lda, 'insert into dept values(:1, :2, :3)'); - -This function is equivalent to the OCI oopen and oparse functions. For -statements which do not contain substitution variables (see the section -Substitution Variables below), it also uses of the oexec function. For -SELECT statements, it also makes use of the odescr and odefin functions -to allocate memory for the values to be returned from the database. - -=item * ora_bind - - &ora_bind($csr, $var, ...) - -If an SQL statement contains substitution variables (see the section -Substitution Variables below), &ora_bind() is used to assign actual -values to them. This function takes a statement identifier (obtained -from &ora_open()) as its first parameter, followed by as many -parameters as are required by the statement. - -Example: - - &ora_bind($csr, 50, 'management', 'Paris'); - -This function is equivalent to the OCI obndrn and oexec statements. - -The OCI obndrn function does not allow empty strings to be bound. As -distributed, $ora_bind therefore replaces empty strings with a single -space. However, a compilation option allows this substitution to be -suppressed, causing &ora_bind() to fail. The output from the -&ora_version() function specifies which is the case at your installation. - -=item * ora_fetch - - $nfields = &ora_fetch($csr) - - @data = &ora_fetch($csr [, $trunc]) - -The &ora_fetch() function is used in conjunction with a SQL SELECT -statement to retrieve information from a database. This function takes -one mandatory parameter, a statement identifier (obtained from -&ora_open()). - -Used in a scalar context, the function returns the number of fields -returned by the query but no data is actually fetched. This may be -useful in a program which allows a user to enter a statement interactively. - -Example: - - $nfields = &ora_fetch($csr); - -Used in an array context, the value returned is an array containing the -data, one element per field. Note that this will not work as expected: - - @data = &ora_fetch($csr) || die "..."; # WRONG - -The || forces a scalar context so ora_fetch returns the number of fields. - -An optional second parameter may be supplied to indicate whether the -truncation of a LONG or LONG RAW field is to be permitted (non-zero) or -considered an error (zero). If this parameter is not specified, the -value of the global variable $ora_trunc is used instead. Truncation of -other datatypes is always considered a error. - -B The optional second parameter to ora_fetch is not supported. -A DBI usage error will be generated if a second parameter is supplied. -Use the global variable $ora_trunc instead. Also note that the -experimental DBI blob_read method can be used to retrieve a long: - - $csr->blob_read($field, $offset, $len [, \$dest, $destoffset]); - -If truncation occurs, $ora_errno will be set to 1406. &ora_fetch() -will complete successfully if truncation is permitted, otherwise it -will fail. - -&ora_fetch() will fail at the end of the data or if an error occurs. It -is possible to distinguish between these cases by testing the value of -the variable $ora_errno. This will be zero for end of data, non-zero if -an error has occurred. - -Example: - - while (($deptno, $dname, $loc) = &ora_fetch($csr)) - { - warn "Truncated!!!" if $ora_errno == 1406; - # do something with the data - } - warn $ora_errstr if $ora_errno; - -This function is equivalent to the OCI ofetch function. - -=item * ora_close - - &ora_close($csr) - -If an SQL statement is no longer required (for example, all the data -selected has been processed, or no more rows are to be inserted) then -the statement identifier should be released. This is done by calling -the &ora_close() function with the statement identifier as its only -parameter. - -This function is equivalent to the OCI oclose function. - -B Since $csr is a Perl5 reference the statement/cursor is now -automatically closed if $csr is overwritten or goes out of scope. - - -=item * ora_do - - &ora_do($lda, $statement) - -Not all SQL statements return data or contain substitution -variables. In these cases the &ora_do() function may be -used as an alternative to &ora_open() and &ora_close(). -This function takes two parameters, a login identifier and -the statement to be executed. - -Example: - - &ora_do($lda, 'drop table employee'); - -This function is roughly equivalent to - - &ora_close( &ora_open($lda, $statement) ) - -B oraperl v2 used to return the string 'OK' to indicate -success with a zero numeric value. The Oraperl emulation now -uses the string '0E0' to achieve the same effect since it does -not cause any C<-w> warnings when used in a numeric context. - -=item * ora_logoff - - &ora_logoff($lda) - -When the program no longer needs to access a given database, the login -identifier should be released using the &ora_logoff() function. - -This function is equivalent to the OCI ologoff function. - -B Since $lda is a Perl5 reference the database login identifier -is now automatically released if $lda is overwritten or goes out of scope. - -=back - -=head2 Ancillary Functions - -Additional functions available are: &ora_titles(), -&ora_lengths(), &ora_types(), &ora_autocommit(), -&ora_commit(), &ora_rollback() and &ora_version(). - -The first three are of most use within a program which -allows statements to be entered interactively. See, for -example, the sample program sql which is supplied with -Oraperl and may have been installed at your site. - -=over 2 - -=item * ora_titles - - @titles = &ora_titles($csr) - -A program may determine the field titles of an executed -query by calling &ora_titles(). This function takes a -single parameter, a statement identifier (obtained from -&ora_open()) indicating the query for which the titles are -required. The titles are returned as an array of strings, -one for each column. - -Titles are truncated to the length of the field, as reported -by the &ora_lengths() function. - -B oraperl v2.2 actually changed the behaviour such that the -titles were not truncated unless an optional second parameter was -true. This was not reflected in the oraperl manual. The Oraperl -emulation adopts the non truncating behaviour and doesn't support the -truncate parameter. - - -=item * ora_lengths - - @lengths = &ora_lengths($csr) - -A program may determine the length of each of the fields -returned by a query by calling the &ora_lengths() function. -This function takes a single parameter, a statement -identifier (obtained from &ora_open()) indicating the query -for which the lengths are required. The lengths are -returned as an array of integers, one for each column. - - -=item * ora_types - - @types = &ora_types($csr) - -A program may determine the type of each of the fields returned by a -query by calling the &ora_types() function. This function takes a -single parameter, a statement identifier (obtained from &ora_open()) -indicating the query for which the lengths are required. The types are -returned as an array of integers, one for each field. - -These types are defined in your OCI documentation. The correct -interpretation for Oracle v6 is given in the file oraperl.ph. - - -=item * ora_autocommit - - &ora_autocommit($lda, $on_or_off) - -Autocommit mode (in which each transaction is committed immediately, -without waiting for an explicit commit) may be enabled or disabled -using &ora_autocommit(). This function takes two parameters, a login -identifier (obtained from &ora_login()) and a true/false value -indicating whether autocommit is to be enabled (non-zero) or disabled -(zero). By default, autocommit is off. - -Note that autocommit can only be set per login, not per statement. If -you need to control autocommit by statement (for example, to allow -deletions to be rolled back, but insertions to be committed -immediately) you should make multiple calls to &ora_login() and use a -separate login identifier for each statement. - - -=item * ora_commit, ora_rollback - - &ora_commit($lda) - &ora_rollback($lda) - -Modifications to a database may be committed or rolled back using the -&ora_commit() and &ora_rollback() functions. These functions take a -single parameter, a login identifier obtained from &ora_login(). - -Transactions which have been committed (either explicitly by a call to -&ora_commit() or implicitly through the use of &ora_autocommit()) -cannot be subsequently rolled back. - -Note that commit and rollback can only be used per login, not per -statement. If you need to commit or rollback by statement you should -make multiple calls to &ora_login() and use a separate login identifier -for each statement. - - -=item * ora_version - - &ora_version() - -The &ora_version() function prints the version number and -copyright information concerning Oraperl. It also prints -the values of various compilation time options. It does not -return any value, and should not normally be used in a -program. - -Example: - - perl -MOraperl -e 'ora_version()' - - This is Oraperl, version 2, patch level 0. - - Debugging is available, including the -D flag. - Default fetch row cache size is 5. - Empty bind values are replaced by a space. - - Perl is copyright by Larry Wall; type oraperl -v for details. - Additions for oraperl: Copyright 1991, 1992, Kevin Stock. - - Oraperl may be distributed under the same conditions as Perl. - -This function is the equivalent of Perl's C<-v> flag. - -B The Oraperl emulation printout is similar but not identical. - -=back - -=head1 VARIABLES - -Six special variables are provided, $ora_cache, $ora_long, -$ora_trunc, $ora_errno, $ora_errstr and $ora_verno. - -=head2 Customisation Variables - -These variables are used to dictate the behaviour of Oraperl -under certain conditions. - -=over 2 - -=item * $ora_cache - -The $ora_cache variable determines the default cache size used by the -&ora_open() function for SELECT statements if an explicit cache size is -not given. - -It is initialised to the default value reported by &ora_version() but -may be set within a program to apply to all subsequent calls to -&ora_open(). Cursors which are already open are not affected. As -distributed, the default value is five, but may have been altered at -your installation. - -As a special case, assigning zero to $ora_cache resets it to the -default value. Attempting to set $ora_cache to a negative value results -in a warning. - - -=item * $ora_long - -Normally, Oraperl interrogates the database to determine the length of -each field and allocates buffer space accordingly. This is not -possible for fields of type LONG or LONGRAW. To allocate space -according to the maximum possible length (65535 bytes) would obviously -be extremely wasteful of memory. - -Therefore, when &ora_open() determines that a field is a LONG type, it -allocates the amount of space indicated by the $ora_long variable. This -is initially set to 80 (for compatibility with Oracle products) but may -be set within a program to whatever size is required. - -$ora_long is only used when fetching data, not when inserting it. - - -=item * $ora_trunc - -Since Oraperl cannot determine exactly the maximum length of a LONG -field, it is possible that the length indicated by $ora_long is not -sufficient to store the data fetched. In such a case, the optional -second parameter to &ora_fetch() indicates whether the truncation -should be allowed or should provoke an error. - -If this second parameter is not specified, the value of $ora_trunc is -used as a default. This only applies to LONG and LONGRAW data types. -Truncation of a field of any other type is always considered an error -(principally because it indicates a bug in Oraperl). - -=back - -=head2 Status Variables - -These variables report information about error conditions or about -Oraperl itself. They may only be read; a fatal error occurs if a -program attempts to change them. - -=over 2 - -=item * $ora_errno - -$ora_errno contains the Oracle error code provoked by the last function -call. - -There are two cases of particular interest concerning &ora_fetch(). If -a LONG or LONGRAW field is truncated (and truncation is allowed) then -&ora_fetch() will complete successfully but $ora_errno will be set to -1406 to indicate the truncation. When &ora_fetch() fails, $ora_errno -will be set to zero if this was due to the end of data or an error code -if it was due to an actual error. - - -=item * $ora_errstr - -The $ora_errstr variable contains the Oracle error message -corresponding to the current value of $ora_errno. - - -=item * $ora_verno - -The $ora_verno variable contains the version number of Oraperl in the -form v.ppp where v is the major version number and ppp is the -patchlevel. For example, in Oraperl version 3, patch level 142, -$ora_verno would contain the value 3.142 (more or less, allowing for -floating point error). - -=back - - -=head1 SUBSTITUTION VARIABLES - -Oraperl allows an SQL statement to contain substitution variables. -These consist of a colon followed by a number. For example, a program -which added records to a telephone list might use the following call to -&ora_open(): - - $csr = &ora_open($csr, "insert into telno values(:1, :2)"); - -The two names :1 and :2 are called substitution variables. The -function &ora_bind() is used to assign values to these variables. For -example, the following statements would add two new people to the -list: - - &ora_bind($csr, "Annette", "472-8836"); - &ora_bind($csr, "Brian", "937-1823"); - -Note that the substitution variables must be assigned consecutively -beginning from 1 for each SQL statement, as &ora_bind() assigns its -parameters in this order. Named substitution variables (for example, -:NAME, :TELNO) are not permitted. - -B Substitution variables are now bound as type 1 (VARCHAR2) -and not type 5 (STRING) by default. This can alter the behaviour of -SQL code which compares a char field with a substitution variable. -See the String Comparison section in the Datatypes chapter of the -Oracle OCI manual for more details. - -You can work around this by using DBD::Oracle's ability to specify -the Oracle type to be used on a per field basis: - - $char_attrib = { ora_type => 5 }; # 5 = STRING (ala oraperl2.4) - $csr = ora_open($dbh, "select foo from bar where x=:1 and y=:2"); - $csr->bind_param(1, $value_x, $char_attrib); - $csr->bind_param(2, $value_y, $char_attrib); - ora_bind($csr); # bind with no parameters since we've done bind_param()'s - - -=head1 DEBUGGING - -B The Oraperl $ora_debug variable is not supported. However -detailed debugging can be enabled at any time by executing - - $h->debug(2); - -where $h is either a $lda or a $csr. If debugging is enabled on an -$lda then it is automatically passed on to any cursors returned by -&ora_open(). - -=head1 EXAMPLE - - format STDOUT_TOP = - Name Phone - ==== ===== - . - - format STDOUT = - @<<<<<<<<<< @>>>>>>>>>> - $name, $phone - . - - die "You should use oraperl, not perl\n" unless defined &ora_login; - $ora_debug = shift if $ARGV[0] =~ /^\-#/; - - $lda = &ora_login('t', 'kstock', 'kstock') - || die $ora_errstr; - $csr = &ora_open($lda, 'select * from telno order by name') - || die $ora_errstr; - - $nfields = &ora_fetch($csr); - print "Query will return $nfields fields\n\n"; - - while (($name, $phone) = &ora_fetch($csr)) { write; } - warn $ora_errstr if $ora_errno; - - die "fetch error: $ora_errstr" if $ora_errno; - - do ora_close($csr) || die "can't close cursor"; - do ora_logoff($lda) || die "can't log off Oracle"; - - -=head1 NOTES - -In keeping with the philosophy of Perl, there is no pre-defined limit -to the number of simultaneous logins or SQL statements which may be -active, nor to the number of data fields which may be returned by a -query. The only limits are those imposed by the amount of memory -available, or by Oracle. - - -=head1 WARNINGS - -The Oraperl emulation software shares no code with the original -oraperl. It is built on top of the new Perl5 DBI and DBD::Oracle -modules. These modules are still evolving. (One of the goals of -the Oraperl emulation software is to allow useful work to be done -with the DBI and DBD::Oracle modules whilst insulating users from -the ongoing changes in their interfaces.) - -It is quite possible, indeed probable, that some differences in -behaviour will exist. These are probably confined to error handling. - -B differences in behaviour which are not documented here should be -reported to to dbi-users@perl.org. - - -=head1 SEE ALSO - -=over 2 - -=item Oracle Documentation - -SQL Language Reference Manual. -Programmer's Guide to the Oracle Call Interfaces. - -=item Books - -Programming Perl by Larry Wall and Randal Schwartz. -Learning Perl by Randal Schwartz. - -=item Manual Pages - -perl(1) - -=back - -=head1 AUTHOR - -Original Oraperl 2.4 code and documentation -by Kevin Stock . - -DBI and Oraperl emulation using DBD::Oracle by Tim Bunce. - -=head1 MAINTAINER - -As of DBD::Oracle release 1.17 in February 2006 The Pythian Group, Inc. -(L) are taking the lead in maintaining DBD::Oracle with -my assistance and gratitude. - -=head1 COPYRIGHT - -Copyright (c) 1994-2006 Tim Bunce. Ireland. -Copyright (c) 2006-2008 John Scoles (The Pythian Group). Canada. - -The DBD::Oracle module is free open source software; you can -redistribute it and/or modify it under the same terms as Perl 5. - -=cut diff --git a/oraperl.ph b/oraperl.ph deleted file mode 100644 index 99f62994..00000000 --- a/oraperl.ph +++ /dev/null @@ -1,53 +0,0 @@ -# DBD::Oracle Oraperl emulation. This file is not relevant to the -# emulation but is included for completeness only. -# I have updated %ora_types in case it's used. Tim Bunce. - -# oraperl.ph -# -# Various constants which may be useful in oraperl programs -# -# Author: Kevin Stock -# Date: 28th October 1991 -# Last Change: 8th April 1992 - - -# Oraperl error codes, set in $ora_errno - -$ORAP_NOMEM = 100001; # out of memory -$ORAP_INVCSR = 100002; # invalid cursor supplied -$ORAP_INVLDA = 100003; # invalid lda supplied -$ORAP_NOSID = 100004; # couldn't set ORACLE_SID -$ORAP_BADVAR = 100005; # bad colon variable sequence -$ORAP_NUMVARS = 100006; # wrong number of colon variables -$ORAP_NODATA = 100007; # statement does not return data - - -# Oraperl debugging codes for $ora_debug -# From version 2, you shouldn't really use these. - -$ODBG_EXEC = 8; # program execution -$ODBG_STRNUM = 32; # string/numeric conversions -$ODBG_MALLOC = 128; # memory allocation/release - -# Oracle datatypes -# I don't know whether these are valid for all versions. - -%ora_types = -( - 1, 'character array', - 2, 'number', - 3, 'signed integer', - 4, 'float', - 7, 'packed decimal', - 8, 'long string', - 9, 'varchar', - 11, 'rowid', - 12, 'date', - 15, 'varraw', - 23, 'raw', - 24, 'long raw', - 96, 'char', - 106,'mlslabel', -); - -1; From fafacc282c725809d6ed4bade159dbe4389f7e95 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 6 Sep 2012 15:50:30 +0000 Subject: [PATCH 304/637] fix some compiler warnings git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15379 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ dbdimp.c | 11 +++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 50f5230d..b6108074 100644 --- a/Changes +++ b/Changes @@ -27,6 +27,8 @@ NEXTRELEASE once handled. Code now leaves the setting to the later STORE DBI calls (Martin J. Evans) + - fixed some compiler warnings for %lf (Martin J. Evans) + [CHANGE IN BEHAVIOUR] - ora_taf and ora_taf_sleep were redundant and have been removed. diff --git a/dbdimp.c b/dbdimp.c index 55ac4436..e2a34ab4 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2245,7 +2245,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=%lf - NOT NULL\n", + "let (double) array[%d]=%f - NOT NULL\n", i, val); } }else{ @@ -2280,7 +2280,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "(double) array[%d]=%lf%s\n", + "(double) array[%d]=%f%s\n", i, *(double*)(phs->array_buf+phs->maxlen*i), phs->array_indicators[i] ? " (NULL)" : "" ); } @@ -2437,7 +2437,7 @@ int dbd_phs_number_table_post_exe(imp_sth_t *imp_sth, phs_t *phs){ case SQLT_FLT: if (trace_level >= 4 || dbd_verbose >= 4 ){ PerlIO_printf(DBIc_LOGPIO(imp_sth), - "dbd_phs_number_table_post_exe(): (double) set arr[%d] = %lf \n", + "dbd_phs_number_table_post_exe(): (double) set arr[%d] = %f \n", i, *(double*)(phs->array_buf+phs->maxlen*i) ); } @@ -2465,7 +2465,7 @@ int dbd_phs_number_table_post_exe(imp_sth_t *imp_sth, phs_t *phs){ case SQLT_FLT: if (trace_level >= 4 || dbd_verbose >= 4 ){ PerlIO_printf(DBIc_LOGPIO(imp_sth), - "dbd_phs_number_table_post_exe(): (double) store new arr[%d] = %lf \n", + "dbd_phs_number_table_post_exe(): (double) store new arr[%d] = %f \n", i, *(double*)(phs->array_buf+phs->maxlen*i) ); } @@ -3210,8 +3210,7 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ sv_setsv(phs->sv, newvalue); if (SvAMAGIC(phs->sv)) /* overloaded. XXX hack, logic ought to be pushed deeper */ sv_pvn_force(phs->sv, &PL_na); - } - else if (newvalue != phs->sv) { + } else if (newvalue != phs->sv) { if (phs->sv) SvREFCNT_dec(phs->sv); From 655cec58d33e87da93a7ea6fad44337e9162f86f Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 6 Sep 2012 15:50:30 +0000 Subject: [PATCH 305/637] fix some compiler warnings git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15379 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ dbdimp.c | 11 +++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 50f5230d..b6108074 100644 --- a/Changes +++ b/Changes @@ -27,6 +27,8 @@ NEXTRELEASE once handled. Code now leaves the setting to the later STORE DBI calls (Martin J. Evans) + - fixed some compiler warnings for %lf (Martin J. Evans) + [CHANGE IN BEHAVIOUR] - ora_taf and ora_taf_sleep were redundant and have been removed. diff --git a/dbdimp.c b/dbdimp.c index 55ac4436..e2a34ab4 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2245,7 +2245,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=%lf - NOT NULL\n", + "let (double) array[%d]=%f - NOT NULL\n", i, val); } }else{ @@ -2280,7 +2280,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "(double) array[%d]=%lf%s\n", + "(double) array[%d]=%f%s\n", i, *(double*)(phs->array_buf+phs->maxlen*i), phs->array_indicators[i] ? " (NULL)" : "" ); } @@ -2437,7 +2437,7 @@ int dbd_phs_number_table_post_exe(imp_sth_t *imp_sth, phs_t *phs){ case SQLT_FLT: if (trace_level >= 4 || dbd_verbose >= 4 ){ PerlIO_printf(DBIc_LOGPIO(imp_sth), - "dbd_phs_number_table_post_exe(): (double) set arr[%d] = %lf \n", + "dbd_phs_number_table_post_exe(): (double) set arr[%d] = %f \n", i, *(double*)(phs->array_buf+phs->maxlen*i) ); } @@ -2465,7 +2465,7 @@ int dbd_phs_number_table_post_exe(imp_sth_t *imp_sth, phs_t *phs){ case SQLT_FLT: if (trace_level >= 4 || dbd_verbose >= 4 ){ PerlIO_printf(DBIc_LOGPIO(imp_sth), - "dbd_phs_number_table_post_exe(): (double) store new arr[%d] = %lf \n", + "dbd_phs_number_table_post_exe(): (double) store new arr[%d] = %f \n", i, *(double*)(phs->array_buf+phs->maxlen*i) ); } @@ -3210,8 +3210,7 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ sv_setsv(phs->sv, newvalue); if (SvAMAGIC(phs->sv)) /* overloaded. XXX hack, logic ought to be pushed deeper */ sv_pvn_force(phs->sv, &PL_na); - } - else if (newvalue != phs->sv) { + } else if (newvalue != phs->sv) { if (phs->sv) SvREFCNT_dec(phs->sv); From f8529fa8976c31c63a6fb669209d6bc0f0ecc031 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 10 Sep 2012 09:01:28 +0000 Subject: [PATCH 306/637] Added fixes for rt 78700 from Douglas Wilson git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15381 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ lib/DBD/Oracle.pm | 3 +++ t/rt13865.t | 36 ++++++++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Changes b/Changes index b6108074..d4e8abe3 100644 --- a/Changes +++ b/Changes @@ -29,6 +29,9 @@ NEXTRELEASE - fixed some compiler warnings for %lf (Martin J. Evans) + - fixed RT78700 - column_info reports wrong size for char semantic + char type columns (Douglas Wilson). + [CHANGE IN BEHAVIOUR] - ora_taf and ora_taf_sleep were redundant and have been removed. diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 6b85731f..7144a791 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -662,6 +662,9 @@ SELECT * , 'FLOAT' , tc.DATA_PRECISION , 'DATE' , 19 , 'VARCHAR2' , tc.CHAR_LENGTH + , 'CHAR' , tc.CHAR_LENGTH + , 'NVARCHAR2', tc.CHAR_LENGTH + , 'NCHAR' , tc.CHAR_LENGTH , tc.DATA_LENGTH ) COLUMN_SIZE , decode( tc.DATA_TYPE diff --git a/t/rt13865.t b/t/rt13865.t index 7edee833..273b85be 100644 --- a/t/rt13865.t +++ b/t/rt13865.t @@ -1,3 +1,4 @@ +# $Id$ use strict; use DBI; @@ -17,7 +18,7 @@ unless ( ( $priv{'CREATE TABLE'} or $priv{'CREATE ANY TABLE'} ) plan skip_all => q{requires permissions 'CREATE TABLE' and 'DROP TABLE'}; } -plan tests => 5; +plan tests => 9; $dbh->do( 'DROP TABLE RT13865' ); @@ -29,31 +30,50 @@ CREATE TABLE RT13865( COL_DECIMAL NUMBER(9,2), COL_FLOAT FLOAT(126), COL_VC2 VARCHAR2(67), - COL_VC2_69CHAR VARCHAR2(69 CHAR) -) + COL_VC2_69CHAR VARCHAR2(69 CHAR), + COL_NVC2 NVARCHAR2(69), + COL_NC NCHAR(69), + COL_CHAR CHAR(67), + COL_CHAR_69CHAR CHAR(69 CHAR) +) END_SQL my $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_INTEGER' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 38, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 38, "INTEGER is alias for NUMBER(38)"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NUMBER_37' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 37, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 37, "NUMBER(37)"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NUMBER' ); -cmp_ok $col_h->fetchrow_hashref->{COLUMN_SIZE}, '>', 0, +cmp_ok $col_h->fetchrow_hashref->{COLUMN_SIZE}, '>', 0, "NUMBER"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_VC2' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, "VARCHAR(67)"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_VC2_69CHAR' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, "VARCHAR(69)"; +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NVC2' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, + "NVARCHAR2(69)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NC' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, + "NCHAR(69)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_CHAR' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, + "CHAR(67)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_CHAR_69CHAR' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, + "CHAR(69)"; $dbh->do( 'DROP TABLE RT13865' ); From 8d5e6a460548c116f1264eb4b5a026e2312e852a Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 10 Sep 2012 09:01:28 +0000 Subject: [PATCH 307/637] Added fixes for rt 78700 from Douglas Wilson git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15381 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ lib/DBD/Oracle.pm | 3 +++ t/rt13865.t | 36 ++++++++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Changes b/Changes index b6108074..d4e8abe3 100644 --- a/Changes +++ b/Changes @@ -29,6 +29,9 @@ NEXTRELEASE - fixed some compiler warnings for %lf (Martin J. Evans) + - fixed RT78700 - column_info reports wrong size for char semantic + char type columns (Douglas Wilson). + [CHANGE IN BEHAVIOUR] - ora_taf and ora_taf_sleep were redundant and have been removed. diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 6b85731f..7144a791 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -662,6 +662,9 @@ SELECT * , 'FLOAT' , tc.DATA_PRECISION , 'DATE' , 19 , 'VARCHAR2' , tc.CHAR_LENGTH + , 'CHAR' , tc.CHAR_LENGTH + , 'NVARCHAR2', tc.CHAR_LENGTH + , 'NCHAR' , tc.CHAR_LENGTH , tc.DATA_LENGTH ) COLUMN_SIZE , decode( tc.DATA_TYPE diff --git a/t/rt13865.t b/t/rt13865.t index 7edee833..273b85be 100644 --- a/t/rt13865.t +++ b/t/rt13865.t @@ -1,3 +1,4 @@ +# $Id$ use strict; use DBI; @@ -17,7 +18,7 @@ unless ( ( $priv{'CREATE TABLE'} or $priv{'CREATE ANY TABLE'} ) plan skip_all => q{requires permissions 'CREATE TABLE' and 'DROP TABLE'}; } -plan tests => 5; +plan tests => 9; $dbh->do( 'DROP TABLE RT13865' ); @@ -29,31 +30,50 @@ CREATE TABLE RT13865( COL_DECIMAL NUMBER(9,2), COL_FLOAT FLOAT(126), COL_VC2 VARCHAR2(67), - COL_VC2_69CHAR VARCHAR2(69 CHAR) -) + COL_VC2_69CHAR VARCHAR2(69 CHAR), + COL_NVC2 NVARCHAR2(69), + COL_NC NCHAR(69), + COL_CHAR CHAR(67), + COL_CHAR_69CHAR CHAR(69 CHAR) +) END_SQL my $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_INTEGER' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 38, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 38, "INTEGER is alias for NUMBER(38)"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NUMBER_37' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 37, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 37, "NUMBER(37)"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NUMBER' ); -cmp_ok $col_h->fetchrow_hashref->{COLUMN_SIZE}, '>', 0, +cmp_ok $col_h->fetchrow_hashref->{COLUMN_SIZE}, '>', 0, "NUMBER"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_VC2' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, "VARCHAR(67)"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_VC2_69CHAR' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, "VARCHAR(69)"; +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NVC2' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, + "NVARCHAR2(69)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NC' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, + "NCHAR(69)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_CHAR' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, + "CHAR(67)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_CHAR_69CHAR' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, + "CHAR(69)"; $dbh->do( 'DROP TABLE RT13865' ); From dedae76e939423015fcab911e1f1196f12a612f3 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 10 Sep 2012 09:11:21 +0000 Subject: [PATCH 308/637] a few typos git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15382 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index d4e8abe3..5ec29056 100644 --- a/Changes +++ b/Changes @@ -45,15 +45,15 @@ NEXTRELEASE - the ora_can_taf method was virtually useless since you can only call it after connecting and to enable TAF you had to do it in the - connect call. Now you enable and disable TAF at any time by + connect call. Now you can enable and disable TAF at any time by simply setting or clearing the ora_taf_function (see RT78811) (Martin J. Evans) - the ora_taf_function is now passed a third argument of the connection handle (Martin J. Evans) - - RT78987 - removed Oraperl.pm and oraperl.ph; these files will be available - in a separate distribution named "Oraperl" (David Perry) + - RT78987 - removed Oraperl.pm and oraperl.ph; these files will be + available in a separate distribution named "Oraperl" (David Perry) [MISCELLANEOUS] From 054da77ecfa5b02d1a0bd342b48d33873292e768 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 10 Sep 2012 09:11:21 +0000 Subject: [PATCH 309/637] a few typos git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15382 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index d4e8abe3..5ec29056 100644 --- a/Changes +++ b/Changes @@ -45,15 +45,15 @@ NEXTRELEASE - the ora_can_taf method was virtually useless since you can only call it after connecting and to enable TAF you had to do it in the - connect call. Now you enable and disable TAF at any time by + connect call. Now you can enable and disable TAF at any time by simply setting or clearing the ora_taf_function (see RT78811) (Martin J. Evans) - the ora_taf_function is now passed a third argument of the connection handle (Martin J. Evans) - - RT78987 - removed Oraperl.pm and oraperl.ph; these files will be available - in a separate distribution named "Oraperl" (David Perry) + - RT78987 - removed Oraperl.pm and oraperl.ph; these files will be + available in a separate distribution named "Oraperl" (David Perry) [MISCELLANEOUS] From 096cd77c007ade4167ac22b3156460cca7287e9b Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 6 Sep 2012 15:50:30 +0000 Subject: [PATCH 310/637] fix some compiler warnings git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15379 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ dbdimp.c | 11 +++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 6886b9e1..c40bdeca 100644 --- a/Changes +++ b/Changes @@ -27,6 +27,8 @@ Revision history for DBD::Oracle once handled. Code now leaves the setting to the later STORE DBI calls (Martin J. Evans) + - fixed some compiler warnings for %lf (Martin J. Evans) + [CHANGE IN BEHAVIOUR] - ora_taf and ora_taf_sleep were redundant and have been removed. diff --git a/dbdimp.c b/dbdimp.c index 55ac4436..e2a34ab4 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2245,7 +2245,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=%lf - NOT NULL\n", + "let (double) array[%d]=%f - NOT NULL\n", i, val); } }else{ @@ -2280,7 +2280,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "(double) array[%d]=%lf%s\n", + "(double) array[%d]=%f%s\n", i, *(double*)(phs->array_buf+phs->maxlen*i), phs->array_indicators[i] ? " (NULL)" : "" ); } @@ -2437,7 +2437,7 @@ int dbd_phs_number_table_post_exe(imp_sth_t *imp_sth, phs_t *phs){ case SQLT_FLT: if (trace_level >= 4 || dbd_verbose >= 4 ){ PerlIO_printf(DBIc_LOGPIO(imp_sth), - "dbd_phs_number_table_post_exe(): (double) set arr[%d] = %lf \n", + "dbd_phs_number_table_post_exe(): (double) set arr[%d] = %f \n", i, *(double*)(phs->array_buf+phs->maxlen*i) ); } @@ -2465,7 +2465,7 @@ int dbd_phs_number_table_post_exe(imp_sth_t *imp_sth, phs_t *phs){ case SQLT_FLT: if (trace_level >= 4 || dbd_verbose >= 4 ){ PerlIO_printf(DBIc_LOGPIO(imp_sth), - "dbd_phs_number_table_post_exe(): (double) store new arr[%d] = %lf \n", + "dbd_phs_number_table_post_exe(): (double) store new arr[%d] = %f \n", i, *(double*)(phs->array_buf+phs->maxlen*i) ); } @@ -3210,8 +3210,7 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ sv_setsv(phs->sv, newvalue); if (SvAMAGIC(phs->sv)) /* overloaded. XXX hack, logic ought to be pushed deeper */ sv_pvn_force(phs->sv, &PL_na); - } - else if (newvalue != phs->sv) { + } else if (newvalue != phs->sv) { if (phs->sv) SvREFCNT_dec(phs->sv); From 3f2321c0d9502fdcd80f5c4f101045fe4301e48d Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 10 Sep 2012 09:01:28 +0000 Subject: [PATCH 311/637] Added fixes for rt 78700 from Douglas Wilson git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15381 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ lib/DBD/Oracle.pm | 3 +++ t/rt13865.t | 36 ++++++++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Changes b/Changes index c40bdeca..b58f0266 100644 --- a/Changes +++ b/Changes @@ -29,6 +29,9 @@ Revision history for DBD::Oracle - fixed some compiler warnings for %lf (Martin J. Evans) + - fixed RT78700 - column_info reports wrong size for char semantic + char type columns (Douglas Wilson). + [CHANGE IN BEHAVIOUR] - ora_taf and ora_taf_sleep were redundant and have been removed. diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 6317a993..528d6d80 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -656,6 +656,9 @@ SELECT * , 'FLOAT' , tc.DATA_PRECISION , 'DATE' , 19 , 'VARCHAR2' , tc.CHAR_LENGTH + , 'CHAR' , tc.CHAR_LENGTH + , 'NVARCHAR2', tc.CHAR_LENGTH + , 'NCHAR' , tc.CHAR_LENGTH , tc.DATA_LENGTH ) COLUMN_SIZE , decode( tc.DATA_TYPE diff --git a/t/rt13865.t b/t/rt13865.t index 7edee833..273b85be 100644 --- a/t/rt13865.t +++ b/t/rt13865.t @@ -1,3 +1,4 @@ +# $Id$ use strict; use DBI; @@ -17,7 +18,7 @@ unless ( ( $priv{'CREATE TABLE'} or $priv{'CREATE ANY TABLE'} ) plan skip_all => q{requires permissions 'CREATE TABLE' and 'DROP TABLE'}; } -plan tests => 5; +plan tests => 9; $dbh->do( 'DROP TABLE RT13865' ); @@ -29,31 +30,50 @@ CREATE TABLE RT13865( COL_DECIMAL NUMBER(9,2), COL_FLOAT FLOAT(126), COL_VC2 VARCHAR2(67), - COL_VC2_69CHAR VARCHAR2(69 CHAR) -) + COL_VC2_69CHAR VARCHAR2(69 CHAR), + COL_NVC2 NVARCHAR2(69), + COL_NC NCHAR(69), + COL_CHAR CHAR(67), + COL_CHAR_69CHAR CHAR(69 CHAR) +) END_SQL my $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_INTEGER' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 38, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 38, "INTEGER is alias for NUMBER(38)"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NUMBER_37' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 37, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 37, "NUMBER(37)"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NUMBER' ); -cmp_ok $col_h->fetchrow_hashref->{COLUMN_SIZE}, '>', 0, +cmp_ok $col_h->fetchrow_hashref->{COLUMN_SIZE}, '>', 0, "NUMBER"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_VC2' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, "VARCHAR(67)"; $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_VC2_69CHAR' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, "VARCHAR(69)"; +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NVC2' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, + "NVARCHAR2(69)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NC' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, + "NCHAR(69)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_CHAR' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, + "CHAR(67)"; + +$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_CHAR_69CHAR' ); +is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, + "CHAR(69)"; $dbh->do( 'DROP TABLE RT13865' ); From 21a7b0e573fc737064ba1ce84649ea56289ed198 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 10 Sep 2012 09:11:21 +0000 Subject: [PATCH 312/637] a few typos git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15382 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index b58f0266..052b49bf 100644 --- a/Changes +++ b/Changes @@ -45,15 +45,15 @@ Revision history for DBD::Oracle - the ora_can_taf method was virtually useless since you can only call it after connecting and to enable TAF you had to do it in the - connect call. Now you enable and disable TAF at any time by + connect call. Now you can enable and disable TAF at any time by simply setting or clearing the ora_taf_function (see RT78811) (Martin J. Evans) - the ora_taf_function is now passed a third argument of the connection handle (Martin J. Evans) - - RT78987 - removed Oraperl.pm and oraperl.ph; these files will be available - in a separate distribution named "Oraperl" (David Perry) + - RT78987 - removed Oraperl.pm and oraperl.ph; these files will be + available in a separate distribution named "Oraperl" (David Perry) [MISCELLANEOUS] From 5c749ba2c4549b9730f2bfa8ef987f9c46cb9d94 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 13 Sep 2012 09:55:56 -0400 Subject: [PATCH 313/637] bumping version to 1.51_00 --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 08a3b99b..93bb665e 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.50 +version = 1.51_00 [Authority] authority=cpan:PYTHIAN From a52bb7eacb25d055f546c66787e13d55277f6065 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 13 Sep 2012 09:57:24 -0400 Subject: [PATCH 314/637] documentation is .pod, not .pm --- lib/DBD/Oracle/Troubleshooting/{Hpux.pm => Hpux.pod} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/DBD/Oracle/Troubleshooting/{Hpux.pm => Hpux.pod} (100%) diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pm b/lib/DBD/Oracle/Troubleshooting/Hpux.pod similarity index 100% rename from lib/DBD/Oracle/Troubleshooting/Hpux.pm rename to lib/DBD/Oracle/Troubleshooting/Hpux.pod From c3349dff92aa4866fb8a3d25d27eeef432cfa82b Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 14 Sep 2012 07:54:38 +0000 Subject: [PATCH 315/637] I mistakenly moved some code referencing driver_name outside of ORA_OCI_112 Yanick - NOTE line around dbdimp.c/427 contains the driver version which now says 01.50_00 - not sure if your distzilla cleaverness can automate this. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15384 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index e2a34ab4..eded2ab3 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -422,9 +422,9 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S DBD_ATTRIB_GET_IV( attr, "ora_drcp_max", 12, svp, imp_dbh->pool_max); if (DBD_ATTRIB_TRUE(attr,"ora_drcp_incr",13,svp)) DBD_ATTRIB_GET_IV( attr, "ora_drcp_incr", 13, svp, imp_dbh->pool_incr); -#endif - imp_dbh->driver_name = "DBD01.47_00"; + imp_dbh->driver_name = "DBD01.50_00"; +#endif #ifdef ORA_OCI_112 OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, From fa730f21cb4d0fadf0f6f0eb6917b27368aaf026 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 14 Sep 2012 07:54:38 +0000 Subject: [PATCH 316/637] I mistakenly moved some code referencing driver_name outside of ORA_OCI_112 Yanick - NOTE line around dbdimp.c/427 contains the driver version which now says 01.50_00 - not sure if your distzilla cleaverness can automate this. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15384 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index e2a34ab4..eded2ab3 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -422,9 +422,9 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S DBD_ATTRIB_GET_IV( attr, "ora_drcp_max", 12, svp, imp_dbh->pool_max); if (DBD_ATTRIB_TRUE(attr,"ora_drcp_incr",13,svp)) DBD_ATTRIB_GET_IV( attr, "ora_drcp_incr", 13, svp, imp_dbh->pool_incr); -#endif - imp_dbh->driver_name = "DBD01.47_00"; + imp_dbh->driver_name = "DBD01.50_00"; +#endif #ifdef ORA_OCI_112 OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, From 5afb53d7a97921087b70b65e90b69f90af46f30a Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 17 Sep 2012 09:06:10 +0000 Subject: [PATCH 317/637] Some tests expected Oracle 11 minor taf test tweak to look into rt72577 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15385 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/38taf.t | 7 +++---- t/39attr.t | 30 +++++++++++++++++++----------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/t/38taf.t b/t/38taf.t index 22477e70..8f40d868 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -26,11 +26,10 @@ if ( !$dbh->ora_can_taf ){ eval { $dbh = DBI->connect( $dsn, $dbuser, '', - {ora_taf_function=>'taf'}) + {ora_taf_function => 'taf'}) }; - ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); - - + my $ev = $@; + like($ev, qr/You are attempting to enable TAF/, "'$ev' (expected)"); } else { ok $dbh = DBI->connect($dsn, $dbuser, '', diff --git a/t/39attr.t b/t/39attr.t index 64af90bd..a352977e 100755 --- a/t/39attr.t +++ b/t/39attr.t @@ -7,7 +7,7 @@ # because DBI passes attributes to STORE for you. # use DBI; -use DBD::Oracle(qw(:ora_fail_over)); +use DBD::Oracle(qw(ORA_OCI)); use strict; #use Devel::Peek qw(SvREFCNT Dump); @@ -19,7 +19,6 @@ $| = 1; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - #use Devel::Leak; #use Test::LeakTrace; @@ -34,15 +33,24 @@ sub do_it { my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; - like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); - foreach my $attr (qw(ora_module_name - ora_driver_name - ora_client_info - ora_client_identifier - ora_action)) { - $dbh->{$attr} = 'fred'; - is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); - } + SKIP: { + my @attrs = (qw(ora_module_name + ora_driver_name + ora_client_info + ora_client_identifier + ora_action)); + skip('Oracle OCI too old', 1 + @attrs) if ORA_OCI() < 11; + + like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); + foreach my $attr (qw(ora_module_name + ora_driver_name + ora_client_info + ora_client_identifier + ora_action)) { + $dbh->{$attr} = 'fred'; + is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); + } + }; foreach my $attr (qw(ora_oci_success_warn ora_objects)) { From 3db55bf381f4c686acfd98b01f2956ff06bcf614 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 17 Sep 2012 09:06:10 +0000 Subject: [PATCH 318/637] Some tests expected Oracle 11 minor taf test tweak to look into rt72577 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15385 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/38taf.t | 7 +++---- t/39attr.t | 30 +++++++++++++++++++----------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/t/38taf.t b/t/38taf.t index 22477e70..8f40d868 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -26,11 +26,10 @@ if ( !$dbh->ora_can_taf ){ eval { $dbh = DBI->connect( $dsn, $dbuser, '', - {ora_taf_function=>'taf'}) + {ora_taf_function => 'taf'}) }; - ok($@ =~ /You are attempting to enable TAF/, "'$@' expected! "); - - + my $ev = $@; + like($ev, qr/You are attempting to enable TAF/, "'$ev' (expected)"); } else { ok $dbh = DBI->connect($dsn, $dbuser, '', diff --git a/t/39attr.t b/t/39attr.t index 64af90bd..a352977e 100755 --- a/t/39attr.t +++ b/t/39attr.t @@ -7,7 +7,7 @@ # because DBI passes attributes to STORE for you. # use DBI; -use DBD::Oracle(qw(:ora_fail_over)); +use DBD::Oracle(qw(ORA_OCI)); use strict; #use Devel::Peek qw(SvREFCNT Dump); @@ -19,7 +19,6 @@ $| = 1; my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - #use Devel::Leak; #use Test::LeakTrace; @@ -34,15 +33,24 @@ sub do_it { my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; - like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); - foreach my $attr (qw(ora_module_name - ora_driver_name - ora_client_info - ora_client_identifier - ora_action)) { - $dbh->{$attr} = 'fred'; - is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); - } + SKIP: { + my @attrs = (qw(ora_module_name + ora_driver_name + ora_client_info + ora_client_identifier + ora_action)); + skip('Oracle OCI too old', 1 + @attrs) if ORA_OCI() < 11; + + like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); + foreach my $attr (qw(ora_module_name + ora_driver_name + ora_client_info + ora_client_identifier + ora_action)) { + $dbh->{$attr} = 'fred'; + is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); + } + }; foreach my $attr (qw(ora_oci_success_warn ora_objects)) { From 93716ed239307a51303ca0f0ab052ff10469b0ee Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 28 Sep 2012 16:25:38 -0400 Subject: [PATCH 319/637] utf8 confuses pod --- MANIFEST | 2 +- lib/DBD/Oracle.pm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MANIFEST b/MANIFEST index a385559d..0061de6e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -39,7 +39,7 @@ lib/DBD/Oracle/Object.pm lib/DBD/Oracle/Troubleshooting.pod lib/DBD/Oracle/Troubleshooting/Aix.pod lib/DBD/Oracle/Troubleshooting/Cygwin.pod -lib/DBD/Oracle/Troubleshooting/Hpux.pm +lib/DBD/Oracle/Troubleshooting/Hpux.pod lib/DBD/Oracle/Troubleshooting/Linux.pod lib/DBD/Oracle/Troubleshooting/Macos.pod lib/DBD/Oracle/Troubleshooting/Sun.pod diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 528d6d80..6aa04cea 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -2650,7 +2650,7 @@ Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improve $dbh->{RowCacheSize} = 100; $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); -In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle Call Interface Programmer's Guide, suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first From 56f24423c6e96af830238bcc2823c8e87dd1a51c Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 28 Sep 2012 16:31:38 -0400 Subject: [PATCH 320/637] v1.51_00 [BUG FIXES] - fix serious memory corruption in TAF support (Martin J. Evans) - fix finding client in situation where client and server both installed but different architectures (patch by H.Merijn Brand) - fix memory leak in TAF handling - the TAF function was leaked (Martin J. Evans) - fix issue with taf_function being set to a scalar which goes out of scope before the callback is made (Martin J. Evans) - fix RT46739 if a connection breaks the environment handle is not thrown away (Martin J. Evans) - ora_driver_name was not defaulted to the correct DBD::Oracle version (Martin J. Evans) - ora_driver_name, ora_client_info, ora_client_identifier, ora_action and ora_oci_success_warn were set twice (if specified) on connect as they were not deleted from the connect attributes once handled. Code now leaves the setting to the later STORE DBI calls (Martin J. Evans) - fixed some compiler warnings for %lf (Martin J. Evans) - fixed RT78700 - column_info reports wrong size for char semantic char type columns (Douglas Wilson). [CHANGE IN BEHAVIOUR] - ora_taf and ora_taf_sleep were redundant and have been removed. To enable/disable TAF simply set ora_taf_function and if you want to sleep do it in your callback (Martin J. Evans) - ora_taf_function can now be a code reference as well as a string (Martin J. Evans) [ENHANCEMENTS] - the ora_can_taf method was virtually useless since you can only call it after connecting and to enable TAF you had to do it in the connect call. Now you can enable and disable TAF at any time by simply setting or clearing the ora_taf_function (see RT78811) (Martin J. Evans) - the ora_taf_function is now passed a third argument of the connection handle (Martin J. Evans) - RT78987 - removed Oraperl.pm and oraperl.ph; these files will be available in a separate distribution named "Oraperl" (David Perry) [MISCELLANEOUS] - hide dr, db and st packages from PAUSE (Martin J. Evans) - added a few more simple TAF tests (Martin J. Evans) --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index 052b49bf..51b3f7d3 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} +1.51_00 2012-09-28 + [BUG FIXES] - fix serious memory corruption in TAF support (Martin J. Evans) From 2485752645dbaf97fd9394aeb58b09b0597a5634 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 28 Sep 2012 20:39:26 +0000 Subject: [PATCH 321/637] bumping version to 1.51_00 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15399 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- MANIFEST | 2 +- META.json | 10 +++++----- META.yml | 8 ++++---- README | 12 ++---------- README.mkdn | 4 ++-- lib/DBD/Oracle.pm | 6 +++--- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/{Hpux.pm => Hpux.pod} | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 19 files changed, 32 insertions(+), 40 deletions(-) rename lib/DBD/Oracle/Troubleshooting/{Hpux.pm => Hpux.pod} (99%) diff --git a/Changes b/Changes index 5ec29056..031e6cab 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -NEXTRELEASE +1.51_00 2012-09-28 [BUG FIXES] diff --git a/MANIFEST b/MANIFEST index a385559d..0061de6e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -39,7 +39,7 @@ lib/DBD/Oracle/Object.pm lib/DBD/Oracle/Troubleshooting.pod lib/DBD/Oracle/Troubleshooting/Aix.pod lib/DBD/Oracle/Troubleshooting/Cygwin.pod -lib/DBD/Oracle/Troubleshooting/Hpux.pm +lib/DBD/Oracle/Troubleshooting/Hpux.pod lib/DBD/Oracle/Troubleshooting/Linux.pod lib/DBD/Oracle/Troubleshooting/Macos.pod lib/DBD/Oracle/Troubleshooting/Sun.pod diff --git a/META.json b/META.json index 79df4c5b..65b5e51f 100644 --- a/META.json +++ b/META.json @@ -51,18 +51,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.50" + "version" : "1.51_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.50" + "version" : "1.51_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.50" + "version" : "1.51_00" } }, - "release_status" : "stable", + "release_status" : "testing", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -75,7 +75,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.50", + "version" : "1.51_00", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index a4b1deb6..0761ee37 100644 --- a/META.yml +++ b/META.yml @@ -29,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.50 + version: 1.51_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.50 + version: 1.51_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.50 + version: 1.51_00 requires: DBI: 0 DynaLoader: 0 @@ -47,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.50 +version: 1.51_00 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index bf4cd15d..0efcfba3 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.50 + version 1.51_00 SYNOPSIS use DBI; @@ -1400,7 +1400,7 @@ DATABASE HANDLE ATTRIBUTES $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); In the above example 10 rows will be prefetched up to a maximum of 10000 - bytes of data. The Oracle® Call Interface Programmer's Guide, suggests a + bytes of data. The Oracle Call Interface Programmer's Guide, suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. @@ -4242,11 +4242,3 @@ COPYRIGHT AND LICENSE This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. -POD ERRORS - Hey! The above document had some coding errors, which are explained - below: - - Around line 2655: - Non-ASCII character seen before =encoding in 'Oracle®'. Assuming - UTF-8 - diff --git a/README.mkdn b/README.mkdn index 4015e6a4..0df66bed 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.50 +version 1.51\_00 # SYNOPSIS @@ -1483,7 +1483,7 @@ Prepare Attribute 'ora\_prefetch\_memory'. Tweaking these values may yield impro $dbh->{RowCacheSize} = 100; $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); -In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle Call Interface Programmer's Guide, suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 7144a791..fb670673 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.50'; + $DBD::Oracle::VERSION = '1.51_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1149,7 +1149,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.50 +version 1.51_00 =head1 SYNOPSIS @@ -2655,7 +2655,7 @@ Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improve $dbh->{RowCacheSize} = 100; $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); -In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle Call Interface Programmer's Guide, suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 21539965..266cb3b3 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.50'; + $DBD::Oracle::GetInfo::VERSION = '1.51_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.50 +version 1.51_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 5f314dbd..c93d7223 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.50'; + $DBD::Oracle::Object::VERSION = '1.51_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.50 +version 1.51_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 912ce571..b349293a 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index c24abdc5..e910a71a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.50 +version 1.51_00 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index ab82dcc4..09466cf7 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.50 +version 1.51_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pm b/lib/DBD/Oracle/Troubleshooting/Hpux.pod similarity index 99% rename from lib/DBD/Oracle/Troubleshooting/Hpux.pm rename to lib/DBD/Oracle/Troubleshooting/Hpux.pod index 7d95e299..b2455154 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pm +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 5737ebfe..e0f76d49 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 5aacb224..e4440f94 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index ebfd936f..47d26f5f 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.50 +version 1.51_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 0dc054c2..471fce99 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.50 +version 1.51_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index d401973a..a73656f8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 3a056878..7b69e17c 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 DBD::Oracle and Windows 64bit From ec06a6859aa12971ec0ce4c06b3baf55eaabd876 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 28 Sep 2012 20:39:26 +0000 Subject: [PATCH 322/637] bumping version to 1.51_00 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15399 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- MANIFEST | 2 +- META.json | 10 +++++----- META.yml | 8 ++++---- README | 12 ++---------- README.mkdn | 4 ++-- lib/DBD/Oracle.pm | 6 +++--- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/{Hpux.pm => Hpux.pod} | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 19 files changed, 32 insertions(+), 40 deletions(-) rename lib/DBD/Oracle/Troubleshooting/{Hpux.pm => Hpux.pod} (99%) diff --git a/Changes b/Changes index 5ec29056..031e6cab 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -NEXTRELEASE +1.51_00 2012-09-28 [BUG FIXES] diff --git a/MANIFEST b/MANIFEST index a385559d..0061de6e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -39,7 +39,7 @@ lib/DBD/Oracle/Object.pm lib/DBD/Oracle/Troubleshooting.pod lib/DBD/Oracle/Troubleshooting/Aix.pod lib/DBD/Oracle/Troubleshooting/Cygwin.pod -lib/DBD/Oracle/Troubleshooting/Hpux.pm +lib/DBD/Oracle/Troubleshooting/Hpux.pod lib/DBD/Oracle/Troubleshooting/Linux.pod lib/DBD/Oracle/Troubleshooting/Macos.pod lib/DBD/Oracle/Troubleshooting/Sun.pod diff --git a/META.json b/META.json index 79df4c5b..65b5e51f 100644 --- a/META.json +++ b/META.json @@ -51,18 +51,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.50" + "version" : "1.51_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.50" + "version" : "1.51_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.50" + "version" : "1.51_00" } }, - "release_status" : "stable", + "release_status" : "testing", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -75,7 +75,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.50", + "version" : "1.51_00", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index a4b1deb6..0761ee37 100644 --- a/META.yml +++ b/META.yml @@ -29,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.50 + version: 1.51_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.50 + version: 1.51_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.50 + version: 1.51_00 requires: DBI: 0 DynaLoader: 0 @@ -47,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.50 +version: 1.51_00 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index bf4cd15d..0efcfba3 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.50 + version 1.51_00 SYNOPSIS use DBI; @@ -1400,7 +1400,7 @@ DATABASE HANDLE ATTRIBUTES $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); In the above example 10 rows will be prefetched up to a maximum of 10000 - bytes of data. The Oracle® Call Interface Programmer's Guide, suggests a + bytes of data. The Oracle Call Interface Programmer's Guide, suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. @@ -4242,11 +4242,3 @@ COPYRIGHT AND LICENSE This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. -POD ERRORS - Hey! The above document had some coding errors, which are explained - below: - - Around line 2655: - Non-ASCII character seen before =encoding in 'Oracle®'. Assuming - UTF-8 - diff --git a/README.mkdn b/README.mkdn index 4015e6a4..0df66bed 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.50 +version 1.51\_00 # SYNOPSIS @@ -1483,7 +1483,7 @@ Prepare Attribute 'ora\_prefetch\_memory'. Tweaking these values may yield impro $dbh->{RowCacheSize} = 100; $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); -In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle Call Interface Programmer's Guide, suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 7144a791..fb670673 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.50'; + $DBD::Oracle::VERSION = '1.51_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1149,7 +1149,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.50 +version 1.51_00 =head1 SYNOPSIS @@ -2655,7 +2655,7 @@ Prepare Attribute 'ora_prefetch_memory'. Tweaking these values may yield improve $dbh->{RowCacheSize} = 100; $sth=$dbh->prepare($SQL,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>10000}); -In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle® Call Interface Programmer's Guide, +In the above example 10 rows will be prefetched up to a maximum of 10000 bytes of data. The Oracle Call Interface Programmer's Guide, suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 21539965..266cb3b3 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.50'; + $DBD::Oracle::GetInfo::VERSION = '1.51_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.50 +version 1.51_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 5f314dbd..c93d7223 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.50'; + $DBD::Oracle::Object::VERSION = '1.51_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -39,7 +39,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.50 +version 1.51_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 912ce571..b349293a 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index c24abdc5..e910a71a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.50 +version 1.51_00 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index ab82dcc4..09466cf7 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.50 +version 1.51_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pm b/lib/DBD/Oracle/Troubleshooting/Hpux.pod similarity index 99% rename from lib/DBD/Oracle/Troubleshooting/Hpux.pm rename to lib/DBD/Oracle/Troubleshooting/Hpux.pod index 7d95e299..b2455154 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pm +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 5737ebfe..e0f76d49 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 5aacb224..e4440f94 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index ebfd936f..47d26f5f 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.50 +version 1.51_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 0dc054c2..471fce99 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.50 +version 1.51_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index d401973a..a73656f8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 3a056878..7b69e17c 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.50 +version 1.51_00 =head1 DBD::Oracle and Windows 64bit From 30e09fbaaaee4aaa0416dd707bc5f0fd63d0b3e1 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 19 Oct 2012 11:07:16 -0400 Subject: [PATCH 323/637] Bump version to v1.52 --- .gitignore | 1 + Changes | 2 ++ MANIFEST.SKIP | 1 + dist.ini | 2 +- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 15e927c8..27c12ccb 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ dbdimp.o mk.pm oci8.o DBD-Oracle* +project.vim diff --git a/Changes b/Changes index 51b3f7d3..df61fc35 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} + - promote 1.51_00 to official release + 1.51_00 2012-09-28 [BUG FIXES] diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index c7db4c66..be8ec702 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -30,3 +30,4 @@ Oracle.xsi pm_to_blib dist.ini +project.vim diff --git a/dist.ini b/dist.ini index 93bb665e..718edb31 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.51_00 +version = 1.52 [Authority] authority=cpan:PYTHIAN From 6ab1d8fe9b77138910f11793fc064f4916720f30 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 19 Oct 2012 11:43:09 -0400 Subject: [PATCH 324/637] v1.52 - promote 1.51_00 to official release --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index df61fc35..c5e82ba7 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} +1.52 2012-10-19 + - promote 1.51_00 to official release 1.51_00 2012-09-28 From d5fc8861eeecefe9e5ccb450b166f5b323941fe6 Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 19 Oct 2012 15:45:45 +0000 Subject: [PATCH 325/637] Bumping version to 1.52 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15443 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ META.json | 12 ++++++------ META.yml | 10 +++++----- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 11 +++-------- lib/DBD/Oracle/GetInfo.pm | 9 +++------ lib/DBD/Oracle/Object.pm | 6 +++--- lib/DBD/Oracle/Troubleshooting.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Aix.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Linux.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Macos.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Sun.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Vms.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Win32.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Win64.pod | 5 ++--- 18 files changed, 46 insertions(+), 60 deletions(-) diff --git a/Changes b/Changes index 031e6cab..ad21cb41 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,9 @@ Revision history for DBD::Oracle +1.52 2012-10-19 + + - promote 1.51_00 to official release + 1.51_00 2012-09-28 [BUG FIXES] diff --git a/META.json b/META.json index 65b5e51f..e25b4114 100644 --- a/META.json +++ b/META.json @@ -7,7 +7,7 @@ "Martin J. Evans " ], "dynamic_config" : 0, - "generated_by" : "Dist::Zilla version 4.300021, CPAN::Meta::Converter version 2.120921", + "generated_by" : "Dist::Zilla version 4.300027, CPAN::Meta::Converter version 2.120921", "license" : [ "perl_5" ], @@ -51,18 +51,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.51_00" + "version" : "1.52" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.51_00" + "version" : "1.52" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.51_00" + "version" : "1.52" } }, - "release_status" : "testing", + "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -75,7 +75,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.51_00", + "version" : "1.52", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index 0761ee37..2bc02600 100644 --- a/META.yml +++ b/META.yml @@ -20,7 +20,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 -generated_by: 'Dist::Zilla version 4.300021, CPAN::Meta::Converter version 2.120921' +generated_by: 'Dist::Zilla version 4.300027, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -29,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.51_00 + version: 1.52 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.51_00 + version: 1.52 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.51_00 + version: 1.52 requires: DBI: 0 DynaLoader: 0 @@ -47,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.51_00 +version: 1.52 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 0efcfba3..c30268b6 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.51_00 + version 1.52 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index 0df66bed..1fd96542 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.51\_00 +version 1.52 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index fb670673..9e429b00 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.51_00'; + $DBD::Oracle::VERSION = '1.52'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1139,7 +1139,7 @@ SQL 1; - +__END__ =pod @@ -1149,7 +1149,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.51_00 +version 1.52 =head1 SYNOPSIS @@ -5505,8 +5505,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - - -__END__ - - diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 266cb3b3..15c77bc6 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.51_00'; + $DBD::Oracle::GetInfo::VERSION = '1.52'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -285,7 +285,7 @@ our %info = ( 1; - +__END__ =pod @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.51_00 +version 1.52 =head1 AUTHORS @@ -327,6 +327,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - - -__END__ diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index c93d7223..c495fc77 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.51_00'; + $DBD::Oracle::Object::VERSION = '1.52'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -31,6 +31,7 @@ sub attr { 1; __END__ + =pod =head1 NAME @@ -39,7 +40,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.51_00 +version 1.52 =head1 AUTHORS @@ -71,4 +72,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index b349293a..f97f62e5 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 CONNECTING TO ORACLE @@ -164,4 +164,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index e910a71a..7bebe180 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Aix #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on AIX - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.51_00 +version 1.52 =head1 Using Visual Age 7 C Compiler @@ -287,4 +287,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index 09466cf7..a65e7f1e 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Cygwin #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Cygwin - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.51_00 +version 1.52 =head1 General Info @@ -108,4 +108,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index b2455154..927e0be9 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Hpux #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on HP-UX - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 INTRODUCTION @@ -1024,4 +1024,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index e0f76d49..57f28b4a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Linux #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Linux - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 Installing with Instantclient .rpm files. @@ -146,4 +146,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index e4440f94..3ec94819 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Macos #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on MacOs - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 General Info @@ -587,4 +587,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index 47d26f5f..16995073 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Sun #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Sun - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.51_00 +version 1.52 =head1 General Info @@ -56,4 +56,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 471fce99..7474e52f 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Vms #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Vms - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.51_00 +version 1.52 =head1 General Info @@ -126,4 +126,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index a73656f8..d0ff8edc 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Win32 #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Win32 - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 GENERAL INFO @@ -276,4 +276,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 7b69e17c..ca2b5a47 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Win64 #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Win64 - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 DBD::Oracle and Windows 64bit @@ -192,4 +192,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - From fd085a77763037e9f85c45066cda38ac1405d2ff Mon Sep 17 00:00:00 2001 From: yanick Date: Fri, 19 Oct 2012 15:45:45 +0000 Subject: [PATCH 326/637] Bumping version to 1.52 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15443 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ META.json | 12 ++++++------ META.yml | 10 +++++----- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 11 +++-------- lib/DBD/Oracle/GetInfo.pm | 9 +++------ lib/DBD/Oracle/Object.pm | 6 +++--- lib/DBD/Oracle/Troubleshooting.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Aix.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Linux.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Macos.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Sun.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Vms.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Win32.pod | 5 ++--- lib/DBD/Oracle/Troubleshooting/Win64.pod | 5 ++--- 18 files changed, 46 insertions(+), 60 deletions(-) diff --git a/Changes b/Changes index 031e6cab..ad21cb41 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,9 @@ Revision history for DBD::Oracle +1.52 2012-10-19 + + - promote 1.51_00 to official release + 1.51_00 2012-09-28 [BUG FIXES] diff --git a/META.json b/META.json index 65b5e51f..e25b4114 100644 --- a/META.json +++ b/META.json @@ -7,7 +7,7 @@ "Martin J. Evans " ], "dynamic_config" : 0, - "generated_by" : "Dist::Zilla version 4.300021, CPAN::Meta::Converter version 2.120921", + "generated_by" : "Dist::Zilla version 4.300027, CPAN::Meta::Converter version 2.120921", "license" : [ "perl_5" ], @@ -51,18 +51,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.51_00" + "version" : "1.52" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.51_00" + "version" : "1.52" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.51_00" + "version" : "1.52" } }, - "release_status" : "testing", + "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -75,7 +75,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.51_00", + "version" : "1.52", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index 0761ee37..2bc02600 100644 --- a/META.yml +++ b/META.yml @@ -20,7 +20,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 -generated_by: 'Dist::Zilla version 4.300021, CPAN::Meta::Converter version 2.120921' +generated_by: 'Dist::Zilla version 4.300027, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -29,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.51_00 + version: 1.52 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.51_00 + version: 1.52 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.51_00 + version: 1.52 requires: DBI: 0 DynaLoader: 0 @@ -47,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.51_00 +version: 1.52 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 0efcfba3..c30268b6 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.51_00 + version 1.52 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index 0df66bed..1fd96542 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.51\_00 +version 1.52 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index fb670673..9e429b00 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.51_00'; + $DBD::Oracle::VERSION = '1.52'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1139,7 +1139,7 @@ SQL 1; - +__END__ =pod @@ -1149,7 +1149,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.51_00 +version 1.52 =head1 SYNOPSIS @@ -5505,8 +5505,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - - -__END__ - - diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 266cb3b3..15c77bc6 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.51_00'; + $DBD::Oracle::GetInfo::VERSION = '1.52'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -285,7 +285,7 @@ our %info = ( 1; - +__END__ =pod @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.51_00 +version 1.52 =head1 AUTHORS @@ -327,6 +327,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - - -__END__ diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index c93d7223..c495fc77 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.51_00'; + $DBD::Oracle::Object::VERSION = '1.52'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -31,6 +31,7 @@ sub attr { 1; __END__ + =pod =head1 NAME @@ -39,7 +40,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.51_00 +version 1.52 =head1 AUTHORS @@ -71,4 +72,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index b349293a..f97f62e5 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 CONNECTING TO ORACLE @@ -164,4 +164,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index e910a71a..7bebe180 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Aix #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on AIX - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.51_00 +version 1.52 =head1 Using Visual Age 7 C Compiler @@ -287,4 +287,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index 09466cf7..a65e7f1e 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Cygwin #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Cygwin - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.51_00 +version 1.52 =head1 General Info @@ -108,4 +108,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index b2455154..927e0be9 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Hpux #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on HP-UX - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 INTRODUCTION @@ -1024,4 +1024,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index e0f76d49..57f28b4a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Linux #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Linux - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 Installing with Instantclient .rpm files. @@ -146,4 +146,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index e4440f94..3ec94819 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Macos #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on MacOs - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 General Info @@ -587,4 +587,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index 47d26f5f..16995073 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Sun #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Sun - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.51_00 +version 1.52 =head1 General Info @@ -56,4 +56,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 471fce99..7474e52f 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Vms #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Vms - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.51_00 +version 1.52 =head1 General Info @@ -126,4 +126,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index a73656f8..d0ff8edc 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Win32 #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Win32 - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 GENERAL INFO @@ -276,4 +276,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 7b69e17c..ca2b5a47 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -1,8 +1,8 @@ #PODNAME: DBD::Oracle::Troubleshooting::Win64 #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Win64 - __END__ + =pod =head1 NAME @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.51_00 +version 1.52 =head1 DBD::Oracle and Windows 64bit @@ -192,4 +192,3 @@ This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut - From 475d9d314ed8237a150cbe02d96d84298236687f Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 23 Oct 2012 12:32:20 +0000 Subject: [PATCH 327/637] Apply patch for RT80349 from Steffen. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15449 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 ++++++++ lib/DBD/Oracle.pm | 8 +++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index ad21cb41..ef35ec0d 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,13 @@ Revision history for DBD::Oracle +NEXT_VERSION + + [BUG FIXES] + + - Fix RT80349 - The error message in execute_for_fetch when a row fails + can contain the wrong error count. Thanks to Steffen Goeldner for + RT and patch. + 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9e429b00..c076760f 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1076,7 +1076,7 @@ SQL sub execute_for_fetch { my ($sth, $fetch_tuple_sub, $tuple_status) = @_; my $row_count = 0; - my $err_count = 0; + my $err_total = 0; my $tuple_count="0E0"; my $tuple_batch_status; my $dbh = $sth->{Database}; @@ -1096,6 +1096,7 @@ SQL } last unless @tuple_batch; + my $err_count = 0; my $res = ora_execute_array($sth, \@tuple_batch, scalar(@tuple_batch), @@ -1108,6 +1109,7 @@ SQL $row_count = undef; } + $err_total += $err_count; $tuple_count+=@$tuple_batch_status; push @$tuple_status, @$tuple_batch_status if defined($tuple_status); @@ -1116,8 +1118,8 @@ SQL } #error check here - return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_count errors") - if $err_count; + return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_total errors") + if $err_total; return wantarray ? ($tuple_count, defined $row_count ? $row_count : undef) From 3a520d168ecaf3388ce5ca176cd1ece341f2c3b5 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 23 Oct 2012 12:32:20 +0000 Subject: [PATCH 328/637] Apply patch for RT80349 from Steffen. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15449 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 ++++++++ lib/DBD/Oracle.pm | 8 +++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index ad21cb41..ef35ec0d 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,13 @@ Revision history for DBD::Oracle +NEXT_VERSION + + [BUG FIXES] + + - Fix RT80349 - The error message in execute_for_fetch when a row fails + can contain the wrong error count. Thanks to Steffen Goeldner for + RT and patch. + 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9e429b00..c076760f 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1076,7 +1076,7 @@ SQL sub execute_for_fetch { my ($sth, $fetch_tuple_sub, $tuple_status) = @_; my $row_count = 0; - my $err_count = 0; + my $err_total = 0; my $tuple_count="0E0"; my $tuple_batch_status; my $dbh = $sth->{Database}; @@ -1096,6 +1096,7 @@ SQL } last unless @tuple_batch; + my $err_count = 0; my $res = ora_execute_array($sth, \@tuple_batch, scalar(@tuple_batch), @@ -1108,6 +1109,7 @@ SQL $row_count = undef; } + $err_total += $err_count; $tuple_count+=@$tuple_batch_status; push @$tuple_status, @$tuple_batch_status if defined($tuple_status); @@ -1116,8 +1118,8 @@ SQL } #error check here - return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_count errors") - if $err_count; + return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_total errors") + if $err_total; return wantarray ? ($tuple_count, defined $row_count ? $row_count : undef) From de06f31ad1fd5591fab521f2f5aa11bf70b13bd1 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 26 Oct 2012 12:16:05 +0000 Subject: [PATCH 329/637] Improve tests in ExecuteArray (espcially to ensure things work when ArrayTupleStatus is not specified) Rewrote 26exe_array.t to be more like the one in DBD::ODBC (from where it came originally) and copied new ExecuteArray module. Fixes from Stefen for execute_array when no ArrayTupleStatus git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15454 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 14 ++ MANIFEST | 1 + dbdimp.c | 315 +++++++++++++------------- lib/DBD/Oracle.pm | 3 +- oci8.c | 558 +++++++++++++++++++++++----------------------- t/26exe_array.t | 479 ++++----------------------------------- t/ExecuteArray.pm | 519 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1013 insertions(+), 876 deletions(-) create mode 100644 t/ExecuteArray.pm diff --git a/Changes b/Changes index ef35ec0d..0e53c81d 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,20 @@ NEXT_VERSION can contain the wrong error count. Thanks to Steffen Goeldner for RT and patch. + - Fix RT80375 - no exception when execute_for_fetch fails and + ArrayTupleStatus is not specified. Also the tuple count calculation + resulted in an undefined warning. Thanks to Steffen Goeldner for + RT and patches. + + [MISCELLANEOUS] + + - The original 26exe_array test was replaced some time ago with a + copy of the one from DBD::ODBC. Since then I've fixed issues in + the DBD::ODBC one and added more tests (like tests for some RTs + above). To make keeping them in synch easier I've modularised the + tests. Hence new ExecuteArray.pm. (Martin J. Evans) + + 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/MANIFEST b/MANIFEST index 0061de6e..d1564f89 100644 --- a/MANIFEST +++ b/MANIFEST @@ -67,6 +67,7 @@ t/23wide_db_al32utf8.t t/24implicit_utf8.t t/25plsql.t t/26exe_array.t +t/ExecuteArray.pm t/28array_bind.t t/30long.t t/31lob.t diff --git a/dbdimp.c b/dbdimp.c index eded2ab3..91099bbd 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2070,19 +2070,19 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /*int flag_data_is_utf8=0;*/ if( ( ! SvROK(phs->sv) ) || (SvTYPE(SvRV(phs->sv))!=SVt_PVAV) ) { /* Allow only array binds */ - croak("dbd_rebind_ph_number_table(): bad bind variable. ARRAY reference required, but got %s for '%s'.", - neatsvpv(phs->sv,0), phs->name); + croak("dbd_rebind_ph_number_table(): bad bind variable. ARRAY reference required, but got %s for '%s'.", + neatsvpv(phs->sv,0), phs->name); } /* Default bind type for number table is double. */ if( ! phs->ora_internal_type ){ - phs->ora_internal_type=SQLT_FLT; + phs->ora_internal_type=SQLT_FLT; }else{ - if( (phs->ora_internal_type != SQLT_FLT) && - (phs->ora_internal_type != SQLT_INT) ){ - croak("dbd_rebind_ph_number_table(): Specified internal bind type %d unsupported. " - "SYS.DBMS_SQL.NUMBER_TABLE can be bound only to SQLT_FLT or SQLT_INT datatypes.", - phs->ora_internal_type); - } + if( (phs->ora_internal_type != SQLT_FLT) && + (phs->ora_internal_type != SQLT_INT) ){ + croak("dbd_rebind_ph_number_table(): Specified internal bind type %d unsupported. " + "SYS.DBMS_SQL.NUMBER_TABLE can be bound only to SQLT_FLT or SQLT_INT datatypes.", + phs->ora_internal_type); + } } arr=(AV*)(SvRV(phs->sv)); @@ -2112,11 +2112,11 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { * maxlen(double) = sizeof(double); */ switch( phs->ora_internal_type ){ - case SQLT_INT: + case SQLT_INT: phs->maxlen=sizeof(int); break; - case SQLT_FLT: - default: + case SQLT_FLT: + default: phs->maxlen=sizeof(double); } if (trace_level >= 2 || dbd_verbose >= 3 ){ @@ -2131,7 +2131,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { phs->array_numstruct=1; } if( phs->ora_maxarray_numentries== 0 ){ - /* Zero means "use current array length". */ + /* Zero means "use current array length". */ phs->ora_maxarray_numentries=phs->array_numstruct; if (trace_level >= 2 || dbd_verbose >= 3 ){ @@ -2153,7 +2153,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { need_allocate_rows=phs->ora_maxarray_numentries; if( need_allocate_rows< phs->array_numstruct ){ - need_allocate_rows=phs->array_numstruct; + need_allocate_rows=phs->array_numstruct; } buflen=need_allocate_rows* phs->maxlen; /* We need buffer for at least ora_maxarray_numentries entries */ @@ -2179,160 +2179,160 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /* Fill array buffer with data */ { - int i; /* Not to require C99 mode */ - for(i=0;iora_internal_type ){ - case SQLT_INT: - { - int ival =0; - int val_found=0; - /* Double values are converted as int(val) */ - if( SvOK( item ) && ! SvIOK( item ) ){ - double val=SvNVx( item ); - if( SvNOK( item ) ){ - ival=(int) val; - val_found=1; - } - } - /* Convert item, if possible. */ - if( (!val_found) && SvOK( item ) && ! SvIOK( item ) ){ - SvIVx( item ); - } - if( SvIOK( item ) || val_found ){ - if( ! val_found ){ - ival=SvIV( item ); - } - /* as phs->array_buf=malloc(), proper alignment is guaranteed */ - *(int*)(phs->array_buf+phs->maxlen*i)=ival; - phs->array_indicators[i]=0; - }else{ - if( SvOK( item ) ){ - /* Defined NaN assumed =0 */ - *(int*)(phs->array_buf+phs->maxlen*i)=0; - phs->array_indicators[i]=0; - }else{ - /* NULL */ - phs->array_indicators[i]=1; - } - } - phs->array_lengths[i]=sizeof(int); - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "(integer) array[%d]=%d%s\n", - i, *(int*)(phs->array_buf+phs->maxlen*i), - phs->array_indicators[i] ? " (NULL)" : "" ); - } - } - break; - case SQLT_FLT: - default: - { - phs->ora_internal_type=SQLT_FLT; /* Just in case */ - /* Convert item, if possible. */ - if( SvOK( item ) && ! SvNOK( item ) ){ - SvNVx( item ); - } - if( SvNOK( item ) ){ - double val=SvNVx( item ); - /* as phs->array_buf=malloc(), proper alignment is guaranteed */ - *(double*)(phs->array_buf+phs->maxlen*i)=val; - phs->array_indicators[i]=0; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=%f - NOT NULL\n", - i, val); - } - }else{ - if( SvOK( item ) ){ - /* Defined NaN assumed =0 */ - *(double*)(phs->array_buf+phs->maxlen*i)=0; - phs->array_indicators[i]=0; - if (trace_level >= 2 || dbd_verbose >= 3 ){ - STRLEN l; - char *p=SvPV(item,l); - - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=\"%s\" =NaN. Set =0 - NOT NULL\n", - i, p ? p : "" ); - } - }else{ - /* NULL */ - phs->array_indicators[i]=1; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "let (double) array[%d] NULL\n", - i); - } - } - } - phs->array_lengths[i]=sizeof(double); - if (trace_level >= 3 || dbd_verbose >= 3 ){ + int i; /* Not to require C99 mode */ + for(i=0;iora_internal_type ){ + case SQLT_INT: + { + int ival =0; + int val_found=0; + /* Double values are converted as int(val) */ + if( SvOK( item ) && ! SvIOK( item ) ){ + double val=SvNVx( item ); + if( SvNOK( item ) ){ + ival=(int) val; + val_found=1; + } + } + /* Convert item, if possible. */ + if( (!val_found) && SvOK( item ) && ! SvIOK( item ) ){ + SvIVx( item ); + } + if( SvIOK( item ) || val_found ){ + if( ! val_found ){ + ival=SvIV( item ); + } + /* as phs->array_buf=malloc(), proper alignment is guaranteed */ + *(int*)(phs->array_buf+phs->maxlen*i)=ival; + phs->array_indicators[i]=0; + }else{ + if( SvOK( item ) ){ + /* Defined NaN assumed =0 */ + *(int*)(phs->array_buf+phs->maxlen*i)=0; + phs->array_indicators[i]=0; + }else{ + /* NULL */ + phs->array_indicators[i]=1; + } + } + phs->array_lengths[i]=sizeof(int); + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " + "(integer) array[%d]=%d%s\n", + i, *(int*)(phs->array_buf+phs->maxlen*i), + phs->array_indicators[i] ? " (NULL)" : "" ); + } + } + break; + case SQLT_FLT: + default: + { + phs->ora_internal_type=SQLT_FLT; /* Just in case */ + /* Convert item, if possible. */ + if( SvOK( item ) && ! SvNOK( item ) ){ + SvNVx( item ); + } + if( SvNOK( item ) ){ + double val=SvNVx( item ); + /* as phs->array_buf=malloc(), proper alignment is guaranteed */ + *(double*)(phs->array_buf+phs->maxlen*i)=val; + phs->array_indicators[i]=0; + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d]=%f - NOT NULL\n", + i, val); + } + }else{ + if( SvOK( item ) ){ + /* Defined NaN assumed =0 */ + *(double*)(phs->array_buf+phs->maxlen*i)=0; + phs->array_indicators[i]=0; + if (trace_level >= 2 || dbd_verbose >= 3 ){ + STRLEN l; + char *p=SvPV(item,l); + + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d]=\"%s\" =NaN. Set =0 - NOT NULL\n", + i, p ? p : "" ); + } + }else{ + /* NULL */ + phs->array_indicators[i]=1; + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d] NULL\n", + i); + } + } + } + phs->array_lengths[i]=sizeof(double); + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "(double) array[%d]=%f%s\n", + i, *(double*)(phs->array_buf+phs->maxlen*i), + phs->array_indicators[i] ? " (NULL)" : "" ); + } + } + break; + } + }else{ + /* item not defined, mark NULL */ + phs->array_indicators[i]=1; + if (trace_level >= 3 || dbd_verbose >= 3 ){ PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "(double) array[%d]=%f%s\n", - i, *(double*)(phs->array_buf+phs->maxlen*i), - phs->array_indicators[i] ? " (NULL)" : "" ); - } - } - break; - } - }else{ - /* item not defined, mark NULL */ - phs->array_indicators[i]=1; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "Copying length=? array[%d]=NULL av_fetch failed.\n", i); - } - } - } + "Copying length=? array[%d]=NULL av_fetch failed.\n", i); + } + } + } } /* Do actual bind */ OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, (sb4)strlen(phs->name), - phs->array_buf, - phs->maxlen, - (ub2)phs->ora_internal_type, phs->array_indicators, - phs->array_lengths, - (ub2)0, - (ub4)phs->ora_maxarray_numentries, /* max elements that can fit in allocated array */ - (ub4 *)&(phs->array_numstruct), /* (ptr to) current number of elements in array */ - OCI_DEFAULT, /* OCI_DATA_AT_EXEC (bind with callbacks) or OCI_DEFAULT */ - status - ); + (text*)phs->name, (sb4)strlen(phs->name), + phs->array_buf, + phs->maxlen, + (ub2)phs->ora_internal_type, phs->array_indicators, + phs->array_lengths, + (ub2)0, + (ub4)phs->ora_maxarray_numentries, /* max elements that can fit in allocated array */ + (ub4 *)&(phs->array_numstruct), /* (ptr to) current number of elements in array */ + OCI_DEFAULT, /* OCI_DATA_AT_EXEC (bind with callbacks) or OCI_DEFAULT */ + status + ); if (status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); - return 0; + oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); + return 0; } OCIBindArrayOfStruct_log_stat(imp_sth, phs->bndhp, imp_sth->errhp, - (unsigned)phs->maxlen, /* Skip parameter for the next data value */ - (unsigned)sizeof(OCIInd), /* Skip parameter for the next indicator value */ - (unsigned)sizeof(unsigned short), /* Skip parameter for the next actual length value */ - 0, /* Skip parameter for the next column-level error code */ - status); + (unsigned)phs->maxlen, /* Skip parameter for the next data value */ + (unsigned)sizeof(OCIInd), /* Skip parameter for the next indicator value */ + (unsigned)sizeof(unsigned short), /* Skip parameter for the next actual length value */ + 0, /* Skip parameter for the next column-level error code */ + status); if (status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, status, "OCIBindArrayOfStruct"); - return 0; + oci_error(sth, imp_sth->errhp, status, "OCIBindArrayOfStruct"); + return 0; } if (phs->maxdata_size) { OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4)OCI_HTYPE_BIND, - phs->array_buf, (ub4)phs->array_buflen, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); - if ( status != OCI_SUCCESS ) { - oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); - return 0; - } + phs->array_buf, (ub4)phs->array_buflen, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); + if ( status != OCI_SUCCESS ) { + oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); + return 0; + } } return 2; @@ -3882,6 +3882,9 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er DBIc_LOGPIO(imp_sth), " ora_st_execute_array %d errors in batch.\n", num_errs); + if (num_errs) { + sv_setiv(err_count,num_errs); + } if(num_errs && tuples_status_av) { OCIError *row_errhp, *tmp_errhp; @@ -3889,7 +3892,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er SV *err_svs[3]; /*AV *err_av;*/ sb4 err_code; - sv_setiv(err_count,num_errs); + err_svs[0] = newSViv((IV)0); err_svs[1] = newSVpvn("", 0); err_svs[2] = newSVpvn("S1000",5); diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index c076760f..adba4527 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1110,7 +1110,8 @@ SQL } $err_total += $err_count; - $tuple_count+=@$tuple_batch_status; + + $tuple_count+=@tuple_batch; push @$tuple_status, @$tuple_batch_status if defined($tuple_status); diff --git a/oci8.c b/oci8.c index bf4fef49..dafc74ba 100644 --- a/oci8.c +++ b/oci8.c @@ -3423,7 +3423,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) /* long_readlen: length for long/longraw (if >0), else 80 (ora app dflt) */ /* Ought to be for COMPAT mode only but was relaxed before LongReadLen existed */ long_readlen = (SvOK(imp_drh -> ora_long) && SvUV(imp_drh->ora_long)>0) - ? SvUV(imp_drh->ora_long) : DBIc_LongReadLen(imp_sth); + ? SvUV(imp_drh->ora_long) : DBIc_LongReadLen(imp_sth); /* set long_readlen for SELECT or PL/SQL with output placeholders */ imp_sth->long_readlen = long_readlen; @@ -3435,7 +3435,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) DBIc_LOGPIO(imp_sth), " dbd_describe skipped for %s\n", oci_stmt_type_name(imp_sth->stmt_type)); - /* imp_sth memory was cleared when created so no setup required here */ + /* imp_sth memory was cleared when created so no setup required here */ return 1; } @@ -3451,12 +3451,12 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if ( !DBIc_ACTIVE(imp_sth) ) { OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, - 0, 0, 0, 0, OCI_DESCRIBE_ONLY, status); + 0, 0, 0, 0, OCI_DESCRIBE_ONLY, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, - ora_sql_error(imp_sth, "OCIStmtExecute/Describe")); + ora_sql_error(imp_sth, "OCIStmtExecute/Describe")); if (status != OCI_SUCCESS_WITH_INFO) - return 0; + return 0; } } OCIAttrGet_stmhp_stat(imp_sth, &num_fields, 0, OCI_ATTR_PARAM_COUNT, status); @@ -3478,7 +3478,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) Newz(42, imp_sth->fbh, num_fields, imp_fbh_t); /* Get number of fields and space needed for field names */ -/* loop though the fields and get all the fileds and thier types to get back*/ + /* loop though the fields and get all the fileds and thier types to get back*/ for(i = 1; i <= num_fields; ++i) { /*start define of filed struct[i] fbh */ char *p; @@ -3490,7 +3490,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->define_mode = OCI_DEFAULT; OCIParamGet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, - (dvoid**)&fbh->parmdp, (ub4)i, status); + (dvoid**)&fbh->parmdp, (ub4)i, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIParamGet"); @@ -3513,7 +3513,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->csid, 0, OCI_ATTR_CHARSET_ID, status); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->csform, 0, OCI_ATTR_CHARSET_FORM, status); #endif - /* OCI_ATTR_PRECISION returns 0 for most types including some numbers */ + /* OCI_ATTR_PRECISION returns 0 for most types including some numbers */ OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->prec, 0, OCI_ATTR_PRECISION, status); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->scale, 0, OCI_ATTR_SCALE, status); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->nullok, 0, OCI_ATTR_IS_NULL, status); @@ -3528,6 +3528,8 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->name = SvPVX(fbh->name_sv); fbh->ftype = 5; /* default: return as null terminated string */ + /* TO_DO there is something wrong with the tracing below as sql_typecode_name + returns NVARCHAR2 for type 2 and ORA_NUMBER is 2 */ if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), @@ -3535,283 +3537,283 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) i,fbh->dbtype,sql_typecode_name(fbh->dbtype)); switch (fbh->dbtype) { - /* the simple types */ - case ORA_VARCHAR2: /* VARCHAR2 */ - - if (fbh->dbsize == 0){ - fbh->dbsize=4000; - } - avg_width = fbh->dbsize / 2; - /* FALLTHRU */ - case ORA_CHAR: /* CHAR */ - if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) - fbh->disize = fbh->dbsize * 4; - else - fbh->disize = fbh->dbsize; - - fbh->prec = fbh->disize; - break; - case ORA_RAW: /* RAW */ - fbh->disize = fbh->dbsize * 2; - fbh->prec = fbh->disize; - break; - case ORA_NUMBER: /* NUMBER */ - case 21: /* BINARY FLOAT os-endian */ - case 22: /* BINARY DOUBLE os-endian */ - case 100: /* BINARY FLOAT oracle-endian */ - case 101: /* BINARY DOUBLE oracle-endian */ - fbh->disize = 130+38+3; /* worst case */ - avg_width = 4; /* NUMBER approx +/- 1_000_000 */ - break; - - case ORA_DATE: /* DATE */ - /* actually dependent on NLS default date format*/ - fbh->disize = 75; /* a generous default */ - fbh->prec = fbh->disize; - avg_width = 8; /* size in SQL*Net packet */ - break; - - case ORA_LONG: /* LONG */ - imp_sth->row_cache_off = 1; - has_longs++; - if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - - fbh->clbk_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - - fbh->ftype = SQLT_CHR; - fbh->fetch_func = fetch_clbk_lob; - - } - else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ - - fbh->piece_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + /* the simple types */ + case ORA_VARCHAR2: /* VARCHAR2 */ - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - fbh->ftype = SQLT_CHR; - fbh->fetch_func = fetch_get_piece; - } - else { + if (fbh->dbsize == 0){ + fbh->dbsize=4000; + } + avg_width = fbh->dbsize / 2; + /* FALLTHRU */ + case ORA_CHAR: /* CHAR */ + if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) + fbh->disize = fbh->dbsize * 4; + else + fbh->disize = fbh->dbsize; + + fbh->prec = fbh->disize; + break; + case ORA_RAW: /* RAW */ + fbh->disize = fbh->dbsize * 2; + fbh->prec = fbh->disize; + break; + case ORA_NUMBER: /* NUMBER */ + case 21: /* BINARY FLOAT os-endian */ + case 22: /* BINARY DOUBLE os-endian */ + case 100: /* BINARY FLOAT oracle-endian */ + case 101: /* BINARY DOUBLE oracle-endian */ + fbh->disize = 130+38+3; /* worst case */ + avg_width = 4; /* NUMBER approx +/- 1_000_000 */ + break; + + case ORA_DATE: /* DATE */ + /* actually dependent on NLS default date format*/ + fbh->disize = 75; /* a generous default */ + fbh->prec = fbh->disize; + avg_width = 8; /* size in SQL*Net packet */ + break; + + case ORA_LONG: /* LONG */ + imp_sth->row_cache_off = 1; + has_longs++; + if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ + + fbh->clbk_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + + fbh->ftype = SQLT_CHR; + fbh->fetch_func = fetch_clbk_lob; - if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) - fbh->disize = long_readlen * 4; - else - fbh->disize = long_readlen; + } + else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + + fbh->piece_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + fbh->ftype = SQLT_CHR; + fbh->fetch_func = fetch_get_piece; + } + else { - /* not governed by else: */ - fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; - fbh->ftype = 94; /* VAR form */ - fbh->fetch_func = fetch_func_varfield; + if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) + fbh->disize = long_readlen * 4; + else + fbh->disize = long_readlen; - } - break; - case ORA_LONGRAW: /* LONG RAW */ - has_longs++; - if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - - fbh->clbk_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } + /* not governed by else: */ + fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; + fbh->ftype = 94; /* VAR form */ + fbh->fetch_func = fetch_func_varfield; - fbh->ftype = SQLT_BIN; - fbh->fetch_func = fetch_clbk_lob; + } + break; + case ORA_LONGRAW: /* LONG RAW */ + has_longs++; + if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - } - else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + fbh->clbk_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - fbh->piece_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - fbh->ftype = SQLT_BIN; - fbh->fetch_func = fetch_get_piece; - } - else { - fbh->disize = long_readlen * 2; - fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; - fbh->ftype = 95; /* VAR form */ - fbh->fetch_func = fetch_func_varfield; - } - break; - - case ORA_ROWID: /* ROWID */ - case 104: /* ROWID Desc */ - fbh->disize = 20; - fbh->prec = fbh->disize; - break; - case 108: /* some sort of embedded object */ - imp_sth->row_cache_off = 1;/* cant fetch more thatn one at a time */ - fbh->ftype = fbh->dbtype; /*varray or alike */ - fbh->fetch_func = fetch_func_oci_object; /* need a new fetch function for it */ - fbh->fetch_cleanup = fetch_cleanup_oci_object; /* clean up any AV from the fetch*/ - fbh->desc_t = SQLT_NTY; - if (!imp_sth->dschp){ - OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); - if (status != OCI_SUCCESS) { - oci_error(h,imp_sth->errhp, status, "OCIHandleAlloc"); - ++num_errors; - } - } - break; - case ORA_CLOB: /* CLOB & NCLOB */ - case ORA_BLOB: /* BLOB */ - case ORA_BFILE: /* BFILE */ - has_longs++; - fbh->ftype = fbh->dbtype; - imp_sth->ret_lobs = 1; - imp_sth->row_cache_off = 1; /* Cannot use mulit fetch for a lob*/ - /* Unless they are just getting the locator */ - - if (imp_sth->pers_lob){ /*get as one peice fasted but limited to 64k big you can get.*/ - - fbh->pers_lob = 1; - - if (long_readlen){ - fbh->disize =long_readlen;/*user set max value for the fetch*/ - } - else { - fbh->disize = fbh->dbsize*10; /*default size*/ - } + fbh->ftype = SQLT_BIN; + fbh->fetch_func = fetch_clbk_lob; + } + else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + + fbh->piece_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + fbh->ftype = SQLT_BIN; + fbh->fetch_func = fetch_get_piece; + } + else { + fbh->disize = long_readlen * 2; + fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; + fbh->ftype = 95; /* VAR form */ + fbh->fetch_func = fetch_func_varfield; + } + break; + + case ORA_ROWID: /* ROWID */ + case 104: /* ROWID Desc */ + fbh->disize = 20; + fbh->prec = fbh->disize; + break; + case 108: /* some sort of embedded object */ + imp_sth->row_cache_off = 1;/* cant fetch more thatn one at a time */ + fbh->ftype = fbh->dbtype; /*varray or alike */ + fbh->fetch_func = fetch_func_oci_object; /* need a new fetch function for it */ + fbh->fetch_cleanup = fetch_cleanup_oci_object; /* clean up any AV from the fetch*/ + fbh->desc_t = SQLT_NTY; + if (!imp_sth->dschp){ + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + if (status != OCI_SUCCESS) { + oci_error(h,imp_sth->errhp, status, "OCIHandleAlloc"); + ++num_errors; + } + } + break; + case ORA_CLOB: /* CLOB & NCLOB */ + case ORA_BLOB: /* BLOB */ + case ORA_BFILE: /* BFILE */ + has_longs++; + fbh->ftype = fbh->dbtype; + imp_sth->ret_lobs = 1; + imp_sth->row_cache_off = 1; /* Cannot use mulit fetch for a lob*/ + /* Unless they are just getting the locator */ + + if (imp_sth->pers_lob){ /*get as one peice fasted but limited to 64k big you can get.*/ + + fbh->pers_lob = 1; + + if (long_readlen){ + fbh->disize =long_readlen;/*user set max value for the fetch*/ + } + else { + fbh->disize = fbh->dbsize*10; /*default size*/ + } + + + if (fbh->dbtype == ORA_CLOB){ + fbh->ftype = SQLT_CHR;/*SQLT_LNG*/ + } + else { + fbh->ftype = SQLT_LVB; /*Binary form seems this is the only value where we can get the length correctly*/ + } + } + else if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ + fbh->clbk_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + if (fbh->dbtype == ORA_CLOB){ + fbh->ftype = SQLT_CHR; + } else { + fbh->ftype = SQLT_BIN; /*other Binary*/ + } + fbh->fetch_func = fetch_clbk_lob; - if (fbh->dbtype == ORA_CLOB){ - fbh->ftype = SQLT_CHR;/*SQLT_LNG*/ - } - else { - fbh->ftype = SQLT_LVB; /*Binary form seems this is the only value where we can get the length correctly*/ - } - } - else if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - fbh->clbk_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - if (fbh->dbtype == ORA_CLOB){ - fbh->ftype = SQLT_CHR; - } else { - fbh->ftype = SQLT_BIN; /*other Binary*/ - } - fbh->fetch_func = fetch_clbk_lob; - - } - else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ - fbh->piece_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - if (fbh->dbtype == ORA_CLOB){ - fbh->ftype = SQLT_CHR; - } - else { - fbh->ftype = SQLT_BIN; /*other Binary */ - } - fbh->fetch_func = fetch_get_piece; + } + else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + fbh->piece_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + if (fbh->dbtype == ORA_CLOB){ + fbh->ftype = SQLT_CHR; + } + else { + fbh->ftype = SQLT_BIN; /*other Binary */ + } + fbh->fetch_func = fetch_get_piece; - } - else { /*auto lob fetch with locator by far the fastest*/ - fbh->disize = sizeof(OCILobLocator*);/* Size of the lob locator ar we do not really get the lob! */ - if (imp_sth->auto_lob) { - fbh->fetch_func = fetch_func_autolob; - } - else { - fbh->fetch_func = fetch_func_getrefpv; - } + } + else { /*auto lob fetch with locator by far the fastest*/ + fbh->disize = sizeof(OCILobLocator*);/* Size of the lob locator ar we do not really get the lob! */ + if (imp_sth->auto_lob) { + fbh->fetch_func = fetch_func_autolob; + } + else { + fbh->fetch_func = fetch_func_getrefpv; + } - fbh->bless = "OCILobLocatorPtr"; - fbh->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &fbh->desc_h, fbh->desc_t); + fbh->bless = "OCILobLocatorPtr"; + fbh->desc_t = OCI_DTYPE_LOB; + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &fbh->desc_h, fbh->desc_t); - } + } - break; + break; #ifdef OCI_DTYPE_REF - case 111: /* REF */ - fbh_setup_getrefpv(imp_sth, fbh, OCI_DTYPE_REF, "OCIRefPtr"); - break; + case 111: /* REF */ + fbh_setup_getrefpv(imp_sth, fbh, OCI_DTYPE_REF, "OCIRefPtr"); + break; #endif - case ORA_RSET: /* RSET */ - fbh->ftype = fbh->dbtype; - fbh->disize = sizeof(OCIStmt *); - fbh->fetch_func = fetch_func_rset; - fbh->fetch_cleanup = fetch_cleanup_rset; - nested_cursors++; - break; - - case 182: /* INTERVAL YEAR TO MONTH */ - case 183: /* INTERVAL DAY TO SECOND */ - case 185: /* TIME (ocidfn.h) */ - case 186: /* TIME WITH TIME ZONE (ocidfn.h) */ - case 187: /* TIMESTAMP */ - case 188: /* TIMESTAMP WITH TIME ZONE */ - case 189: /* INTERVAL YEAR TO MONTH (ocidfn.h) */ - case 190: /* INTERVAL DAY TO SECOND */ - case 232: /* TIMESTAMP WITH LOCAL TIME ZONE */ - /* actually dependent on NLS default date format*/ - fbh->disize = 75; /* XXX */ - break; - - default: + case ORA_RSET: /* RSET */ + fbh->ftype = fbh->dbtype; + fbh->disize = sizeof(OCIStmt *); + fbh->fetch_func = fetch_func_rset; + fbh->fetch_cleanup = fetch_cleanup_rset; + nested_cursors++; + break; + + case 182: /* INTERVAL YEAR TO MONTH */ + case 183: /* INTERVAL DAY TO SECOND */ + case 185: /* TIME (ocidfn.h) */ + case 186: /* TIME WITH TIME ZONE (ocidfn.h) */ + case 187: /* TIMESTAMP */ + case 188: /* TIMESTAMP WITH TIME ZONE */ + case 189: /* INTERVAL YEAR TO MONTH (ocidfn.h) */ + case 190: /* INTERVAL DAY TO SECOND */ + case 232: /* TIMESTAMP WITH LOCAL TIME ZONE */ + /* actually dependent on NLS default date format*/ + fbh->disize = 75; /* XXX */ + break; + + default: /* XXX unhandled type may lead to errors or worse */ - fbh->ftype = fbh->dbtype; - fbh->disize = fbh->dbsize; - p = "Field %d has an Oracle type (%d) which is not explicitly supported%s"; - if (DBIc_DBISTATE(imp_sth)->debug >= 1 || dbd_verbose >= 3 ) - PerlIO_printf(DBIc_LOGPIO(imp_sth), p, i, fbh->dbtype, "\n"); - if (PL_dowarn) - warn(p, i, fbh->dbtype, ""); - break; + fbh->ftype = fbh->dbtype; + fbh->disize = fbh->dbsize; + p = "Field %d has an Oracle type (%d) which is not explicitly supported%s"; + if (DBIc_DBISTATE(imp_sth)->debug >= 1 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_sth), p, i, fbh->dbtype, "\n"); + if (PL_dowarn) + warn(p, i, fbh->dbtype, ""); + break; } if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, " - "name %s\n : dbsize %d, char_used %d, char_size %d, " - "csid %d, csform %d(%s), disize %d\n", - i, fbh->dbtype, sql_typecode_name(fbh->dbtype), fbh->scale, - fbh->prec, fbh->nullok, fbh->name, fbh->dbsize, - fbh->len_char_used, fbh->len_char_size, - fbh->csid,fbh->csform,oci_csform_name(fbh->csform), fbh->disize); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, " + "name %s\n : dbsize %d, char_used %d, char_size %d, " + "csid %d, csform %d(%s), disize %d\n", + i, fbh->dbtype, sql_typecode_name(fbh->dbtype), fbh->scale, + fbh->prec, fbh->nullok, fbh->name, fbh->dbsize, + fbh->len_char_used, fbh->len_char_size, + fbh->csid,fbh->csform,oci_csform_name(fbh->csform), fbh->disize); if (fbh->ftype == 5) /* XXX need to handle wide chars somehow */ fbh->disize += 1; /* allow for null terminator */ - /* dbsize can be zero for 'select NULL ...' */ + /* dbsize can be zero for 'select NULL ...' */ imp_sth->t_dbsize += fbh->dbsize; @@ -3828,8 +3830,8 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) imp_sth->est_width = est_width; sth_set_row_cache(h, imp_sth, - (imp_dbh->max_nested_cursors) ? 0 :nested_cursors , - (int)num_fields, has_longs ); + (imp_dbh->max_nested_cursors) ? 0 :nested_cursors , + (int)num_fields, has_longs ); /* Initialise cache counters */ imp_sth->in_cache = 0; imp_sth->eod_errno = 0; @@ -3861,26 +3863,26 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (fbh->ftype == ORA_RSET) { /* RSET */ OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, - (dvoid*)&((OCIStmt **)fb_ary->abuf)[0], - OCI_HTYPE_STMT, status); + (dvoid*)&((OCIStmt **)fb_ary->abuf)[0], + OCI_HTYPE_STMT, status); } OCIDefineByPos_log_stat(imp_sth, imp_sth->stmhp, - &fbh->defnp, - imp_sth->errhp, - (ub4) i, - (fbh->desc_h) ? (dvoid*)&fbh->desc_h : fbh->clbk_lob ? (dvoid *) 0: fbh->piece_lob ? (dvoid *) 0:(dvoid*)fb_ary->abuf, - (fbh->desc_h) ? 0 : define_len, - (ub2)fbh->ftype, - fb_ary->aindp, - (ftype==94||ftype==95) ? NULL : fb_ary->arlen, - fb_ary->arcode, - fbh->define_mode, - status); + &fbh->defnp, + imp_sth->errhp, + (ub4) i, + (fbh->desc_h) ? (dvoid*)&fbh->desc_h : fbh->clbk_lob ? (dvoid *) 0: fbh->piece_lob ? (dvoid *) 0:(dvoid*)fb_ary->abuf, + (fbh->desc_h) ? 0 : define_len, + (ub2)fbh->ftype, + fb_ary->aindp, + (ftype==94||ftype==95) ? NULL : fb_ary->arlen, + fb_ary->arcode, + fbh->define_mode, + status); if (fbh->clbk_lob){ - /* use a dynamic callback for persistent binary and char lobs*/ + /* use a dynamic callback for persistent binary and char lobs*/ OCIDefineDynamic_log_stat(imp_sth, fbh->defnp,imp_sth->errhp,(dvoid *) fbh,status); } @@ -3917,14 +3919,14 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) #ifdef OCI_ATTR_CHARSET_FORM if ( (fbh->dbtype == 1) && fbh->csform ) { - /* csform may be 0 when talking to Oracle 8.0 database*/ + /* csform may be 0 when talking to Oracle 8.0 database*/ if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " calling OCIAttrSet OCI_ATTR_CHARSET_FORM with csform=%d (%s)\n", fbh->csform,oci_csform_name(fbh->csform) ); OCIAttrSet_log_stat(imp_sth, fbh->defnp, (ub4) OCI_HTYPE_DEFINE, (dvoid *) &fbh->csform, - (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status ); + (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status ); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_CHARSET_FORM"); ++num_errors; @@ -4016,7 +4018,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_sth->rs_array_idx=0; } - else { /*Array Fetch the New Noraml Super speedy and very nice*/ + else { /*Array Fetch the New Normal Super speedy and very nice*/ imp_sth->rs_array_idx++; @@ -4161,7 +4163,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ char errstr[256]; sts = DBIc_DBISTATE(imp_sth)->sql_type_cast_svpv( - aTHX_ sv, fbh->req_type, fbh->bind_flags, NULL); + aTHX_ sv, fbh->req_type, fbh->bind_flags, NULL); if (sts == 0) { sprintf(errstr, diff --git a/t/26exe_array.t b/t/26exe_array.t index 52107a96..8a4519fe 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -1,15 +1,9 @@ -#!/usr/bin/perl -w -I./t - -## ---------------------------------------------------------------------------- -## 26exe_array.t this is a completly new one -## By Martin J. Evans orgianlly called 70execute_array.t for the ODBC DBD driver -## and adatped into DBD::Oracle (in a very minor way) by John Scoles, The Pythian Group -## ---------------------------------------------------------------------------- -## loads of execute_array and execute_for_fetch tests -## tests both insert and update and row fetching -## with RaiseError on and off and AutoCommit on and off -## ---------------------------------------------------------------------------- - +# $Id$ +# Completely new test for DBD::Oracle which came from DBD::ODBC +# Author: Martin J. Evans +# +# loads of execute_array and execute_for_fetch tests using DBI's methods +# use Test::More; use strict; use Data::Dumper; @@ -17,25 +11,30 @@ require 'nchar_test_lib.pl'; $| = 1; +my $has_test_nowarnings = 1; +eval "require Test::NoWarnings"; +$has_test_nowarnings = undef if $@; + +my ($dbh, $ea); -my $table = 'PERL_DBD_execute_array'; -my $table2 = 'PERL_DBD_execute_array2'; -my @captured_error; # values captured in error handler +use DBI qw(:sql_types); +use ExecuteArray; +END { + if ($dbh && $ea) { + $ea->drop_table($dbh); + $dbh->disconnect(); + } + Test::NoWarnings::had_no_warnings() + if ($has_test_nowarnings); + done_testing(); +} -# create a database handle my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; $ENV{NLS_NCHAR} = "US7ASCII"; $ENV{NLS_LANG} = "AMERICAN"; -my $dbh; -my @p1 = (1,2,3,4,5); -my @p2 = qw(one two three four five); -my $fetch_row = 0; - -use DBI qw(:sql_types); - eval { $dbh = DBI->connect($dsn, $dbuser, '', {PrintError => 0}); }; @@ -43,426 +42,24 @@ eval { if (!$dbh) { plan skip_all => "Unable to connect to Oracle"; } -#$dbh->{PrintError} = 1; -my $has_test_nowarnings = 1; -eval "require Test::NoWarnings"; -$has_test_nowarnings = undef if $@; -use_ok('Data::Dumper'); - -END { - if ($dbh) { - drop_table_local($dbh); - } - Test::NoWarnings::had_no_warnings() - if ($has_test_nowarnings); - done_testing(); -} - -sub error_handler -{ - @captured_error = @_; - note("***** error handler called *****"); - 0; # pass errors on -} - -sub create_table_local -{ - my $dbh = shift; - - eval { - $dbh->do(qq/create table $table (a int primary key, b char(20))/); - }; - if ($@) { - diag("Failed to create test table $table - $@"); - return 0; - } - eval { - $dbh->do(qq/create table $table2 (a int primary key, b char(20))/); - }; - if ($@) { - diag("Failed to create test table $table2 - $@"); - return 0; - } - my $sth = $dbh->prepare(qq/insert into $table2 values(?,?)/); - for (my $row = 0; $row < @p1; $row++) { - $sth->execute($p1[$row], $p2[$row]); - } - 1; -} - -sub drop_table_local -{ - my $dbh = shift; - - eval { - local $dbh->{PrintError} = 0; - local $dbh->{PrintWarn} = 0; - $dbh->do(qq/drop table $table/); - $dbh->do(qq/drop table $table2/); - }; - note("Table dropped"); -} - -# clear the named table of rows -sub clear_table -{ - $_[0]->do(qq/delete from $_[1]/); -} - -# check $table contains the data in $c1, $c2 which are arrayrefs of values -sub check_data -{ - my ($dbh, $c1, $c2) = @_; - - my $data = $dbh->selectall_arrayref(qq/select * from $table order by a/); - my $row = 0; - foreach (@$data) { - is($_->[0], $c1->[$row], "row $row p1 data"); - is($_->[1], $c2->[$row], "row $row p2 data"); - $row++; - } -} - -sub check_tuple_status -{ - my ($tsts, $expected) = @_; - - note(Data::Dumper->Dump([$tsts], [qw(ArrayTupleStatus)])); - my $row = 0; - foreach my $s (@$tsts) { - if (ref($expected->[$row])) { - is(ref($s), 'ARRAY', 'array in array tuple status'); - is(scalar(@$s), 3, '3 elements in array tuple status error'); - } else { - if ($s == -1) { - pass("row $row tuple status unknown"); - } else { - is($s, $expected->[$row], "row $row tuple status"); - } - } - $row++ - } -} - -# insert might return 'mas' which means the caller said the test -# required Multiple Active Statements and the driver appeared to not -# support MAS. -sub insert -{ - my ($dbh, $sth, $ref) = @_; - - die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); - note("insert " . join(", ", map {"$_ = ". DBI::neat($ref->{$_})} keys %$ref )); - # DBD::Oracle supports MAS don't compensate for it not - if ($ref->{requires_mas} && $dbh->{Driver}->{Name} eq 'Oracle') { - delete $ref->{requires_mas}; - } - @captured_error = (); - - if ($ref->{raise}) { - $sth->{RaiseError} = 1; - } else { - $sth->{RaiseError} = 0; - } - - my (@tuple_status, $sts, $total_affected); - $sts = 999999; # to ensure it is overwritten - $total_affected = 999998; - if ($ref->{array_context}) { - eval { - if ($ref->{params}) { - ($sts, $total_affected) = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}, - @{$ref->{params}}); - } elsif ($ref->{fetch}) { - ($sts, $total_affected) = - $sth->execute_array( - {ArrayTupleStatus => \@tuple_status, - ArrayTupleFetch => $ref->{fetch}}); - } else { - ($sts, $total_affected) = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}); - } - }; - } else { - eval { - if ($ref->{params}) { - $sts = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}, - @{$ref->{params}}); - } else { - $sts = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}); - } - }; - } - if ($ref->{error} && $ref->{raise}) { - ok($@, 'error in execute_array eval'); - } else { - if ($ref->{requires_mas} && $@) { - diag("\nThis test died with $@"); - diag("It requires multiple active statement support in the driver and I cannot easily determine if your driver supports MAS. Ignoring the rest of this test."); - foreach (@tuple_status) { - if (ref($_)) { - diag(join(",", @$_)); - } - } - return 'mas'; - } - ok(!$@, 'no error in execute_array eval') or note($@); - } - $dbh->commit if $ref->{commit}; - - if (!$ref->{raise} || ($ref->{error} == 0)) { - if (exists($ref->{sts})) { - is($sts, $ref->{sts}, - "execute_array returned " . DBI::neat($sts) . " rows executed"); - } - if (exists($ref->{affected}) && $ref->{array_context}) { - is($total_affected, $ref->{affected}, - "total affected " . DBI::neat($total_affected)) - } - } - if ($ref->{raise}) { - if ($ref->{error}) { - ok(scalar(@captured_error) > 0, "error captured"); - } else { - is(scalar(@captured_error), 0, "no error captured"); - } - } - if ($ref->{sts}) { - is(scalar(@tuple_status), (($ref->{sts} eq '0E0') ? 0 : $ref->{sts}), - "$ref->{sts} rows in tuple_status"); - } - if ($ref->{tuple}) { - check_tuple_status(\@tuple_status, $ref->{tuple}); - } - return; -} -# simple test on ensure execute_array with no errors: -# o checks returned status and affected is correct -# o checks ArrayTupleStatus is correct -# o checks no error is raised -# o checks rows are inserted -# o run twice with AutoCommit on/off -# o checks if less values are specified for one parameter the right number -# of rows are still inserted and NULLs are placed in the missing rows -# checks binding via bind_param_array and adding params to execute_array -# checks binding no parameters at all -sub simple -{ - my ($dbh, $ref) = @_; - - note('simple tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); - - note(" all param arrays the same size"); - foreach my $commit (1,0) { - note(" Autocommit: $commit"); - clear_table($dbh, $table); - $dbh->begin_work if !$commit; - - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - $sth->bind_param_array(1, \@p1); - $sth->bind_param_array(2, \@p2); - insert($dbh, $sth, - { commit => !$commit, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref}); - check_data($dbh, \@p1, \@p2); - } - - note " Not all param arrays the same size"; - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - - $sth->bind_param_array(1, \@p1); - $sth->bind_param_array(2, [qw(one)]); - insert($dbh, $sth, {commit => 0, error => 0, - raise => 1, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref}); - check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); - - note " Not all param arrays the same size with bind on execute_array"; - clear_table($dbh, $table); - $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - - insert($dbh, $sth, {commit => 0, error => 0, - raise => 1, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - params => [\@p1, [qw(one)]]}); - check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); - - note " no parameters"; - clear_table($dbh, $table); - $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - - insert($dbh, $sth, {commit => 0, error => 0, - raise => 1, sts => '0E0', affected => 0, - tuple => [], %$ref, - params => [[], []]}); - check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); -} - -# error test to ensure correct behavior for execute_array when it errors: -# o execute_array of 5 inserts with last one failing -# o check it raises an error -# o check caught error is passed on from handler for eval -# o check returned status and affected rows -# o check ArrayTupleStatus -# o check valid inserts are inserted -# o execute_array of 5 inserts with 2nd last one failing -# o check it raises an error -# o check caught error is passed on from handler for eval -# o check returned status and affected rows -# o check ArrayTupleStatus -# o check valid inserts are inserted -sub error -{ - my ($dbh, $ref) = @_; - - die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); - - note('error tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); - { - note("Last row in error"); - - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - my @pe1 = @p1; - $pe1[-1] = 1; - $sth->bind_param_array(1, \@pe1); - $sth->bind_param_array(2, \@p2); - insert($dbh, $sth, {commit => 0, error => 1, sts => undef, - affected => undef, tuple => [1, 1, 1, 1, []], - %$ref}); - check_data($dbh, [@pe1[0..4]], [@p2[0..4]]); - } - - { - note("2nd last row in error"); - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - my @pe1 = @p1; - $pe1[-2] = 1; - $sth->bind_param_array(1, \@pe1); - $sth->bind_param_array(2, \@p2); - insert($dbh, $sth, {commit => 0, error => 1, sts => undef, - affected => undef, tuple => [1, 1, 1, [], 1], %$ref}); - check_data($dbh, [@pe1[0..2],$pe1[4]], [@p2[0..2], $p2[4]]); - } -} - -sub fetch_sub -{ - note("fetch_sub $fetch_row"); - if ($fetch_row == @p1) { - note('returning undef'); - $fetch_row = 0; - return; - } - - return [$p1[$fetch_row], $p2[$fetch_row++]]; -} - -# test insertion via execute_array and ArrayTupleFetch -sub row_wise -{ - my ($dbh, $ref) = @_; - - note("row_size via execute_for_fetch"); - - $fetch_row = 0; - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - fetch => \&fetch_sub}); - - # NOTE: I'd like to do the following test but it requires Multiple - # Active Statements and although I can find ODBC drivers which do this - # it is not easy (if at all possible) to know if an ODBC driver can - # handle MAS or not. If it errors the driver probably does not have MAS - # so the error is ignored and a diagnostic is output. - note("row_size via select"); - clear_table($dbh, $table); - $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - my $sth2 = $dbh->prepare(qq/select * from $table2/); - ok($sth2->execute, 'execute on second table') or diag($sth2->errstr); - ok($sth2->{Executed}, 'second statement is in executed state'); - my $res = insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - fetch => $sth2, requires_mas => 1}); - return if $res && $res eq 'mas'; # aborted , does not seem to support MAS - check_data($dbh, \@p1, \@p2); - #my $res = $dbh->selectall_arrayref("select * from $table2"); - #print Dumper($res); -} - -# test updates -sub update -{ - my ($dbh, $ref) = @_; - - note("update test"); - - $fetch_row = 0; - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - fetch => \&fetch_sub}); - check_data($dbh, \@p1, \@p2); - - $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); - # NOTE, this also checks you can pass a scalar to bind_param_array - $sth->bind_param_array(1, 'fred'); - $sth->bind_param_array(2, \@p1); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref}); - check_data($dbh, \@p1, [qw(fred fred fred fred fred)]); - - $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); - # NOTE, this also checks you can pass a scalar to bind_param_array - $sth->bind_param_array(1, 'dave'); - my @pe1 = @p1; - $pe1[-1] = 10; # non-existant row - $sth->bind_param_array(2, \@pe1); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 4, - tuple => [1, 1, 1, 1, '0E0'], %$ref}); - check_data($dbh, \@p1, [qw(dave dave dave dave fred)]); - - $sth = $dbh->prepare(qq/update $table set b = ? where b like ?/); - # NOTE, this also checks you can pass a scalar to bind_param_array - $sth->bind_param_array(1, 'pete'); - $sth->bind_param_array(2, ['dave%', 'fred%']); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 2, affected => 5, - tuple => [4, 1], %$ref}); - check_data($dbh, \@p1, [qw(pete pete pete pete pete)]); - - -} -$dbh->{RaiseError} = 1; -$dbh->{PrintError} = 0; -$dbh->{ChopBlanks} = 1; -$dbh->{HandleError} = \&error_handler; -$dbh->{AutoCommit} = 1; +$ea = ExecuteArray->new($dbh, 1); # set odbc_disable_array_operations +$dbh = $ea->dbh; -eval {drop_table_local($dbh)}; +$ea->drop_table($dbh); +ok($ea->create_table($dbh), "create test table") or exit 1; +$ea->simple($dbh, {array_context => 1, raise => 1}); +$ea->simple($dbh, {array_context => 0, raise => 1}); +$ea->error($dbh, {array_context => 1, raise => 1}); +$ea->error($dbh, {array_context => 0, raise => 1}); +$ea->error($dbh, {array_context => 1, raise => 0}); +$ea->error($dbh, {array_context => 0, raise => 0}); -ok(create_table_local($dbh), "create test table") or exit 1; -simple($dbh, {array_context => 1, raise => 1}); -simple($dbh, {array_context => 0, raise => 1}); -error($dbh, {array_context => 1, raise => 1}); -error($dbh, {array_context => 0, raise => 1}); -error($dbh, {array_context => 1, raise => 0}); -error($dbh, {array_context => 0, raise => 0}); +$ea->row_wise($dbh, {array_context => 1, raise => 1}); -row_wise($dbh, {array_context => 1, raise => 1}); +$ea->update($dbh, {array_context => 1, raise => 1}); -update($dbh, {array_context => 1, raise => 1}); +$ea->error($dbh, {array_context => 1, raise => 1, notuplestatus => 1}); +$ea->error($dbh, {array_context => 0, raise => 1, notuplestatus => 1}); +$ea->error($dbh, {array_context => 1, raise => 0, notuplestatus => 1}); +$ea->error($dbh, {array_context => 0, raise => 0, notuplestatus => 1}); diff --git a/t/ExecuteArray.pm b/t/ExecuteArray.pm new file mode 100644 index 00000000..268641f0 --- /dev/null +++ b/t/ExecuteArray.pm @@ -0,0 +1,519 @@ +# $Id$ +# Author: Martin J. Evans +# This should be an exact copy of the same file in DBD::ODBC +# If you change this file please let me know. +package ExecuteArray; +use Test::More; +use Data::Dumper; +use DBI; +our $VERSION = '0.01'; + +my $table = 'PERL_DBD_execute_array'; +my $table2 = 'PERL_DBD_execute_array2'; +my @p1 = (1,2,3,4,5); +my @p2 = qw(one two three four five); +my $fetch_row = 0; +my @captured_error; # values captured in error handler + +sub error_handler +{ + @captured_error = @_; + note("***** error handler called *****"); + 0; # pass errors on +} + +sub new { + my ($class, $dbh, $dbi_version) = @_; + my $self = {}; + + $dbh = setup($dbh, $dbi_version); + $self->{_dbh} = $dbh; + + # find out how the driver supports row counts and parameter status + $self->{_param_array_row_counts} = $dbh->get_info(153); + # a return of 1 is SQL_PARC_BATCH which means: + # Individual row counts are available for each set of parameters. This is + # conceptually equivalent to the driver generating a batch of SQL + # statements, one for each parameter set in the array. Extended error + # information can be retrieved by using the SQL_PARAM_STATUS_PTR + # descriptor field. + # a return of 2 is SQL_PARC_NO_BATCH which means: + # There is only one row count available, which is the cumulative row + # count resulting from the execution of the statement for the entire + # array of parameters. This is conceptually equivalent to treating + # the statement together with the complete parameter array as one + # atomic unit. Errors are handled the same as if one statement + # were executed. + return bless ($self, $class); +} + +sub dbh { + my $self = shift; + return $self->{_dbh}; +} + +sub setup { + my ($dbh, $dbi_version) = @_; + + $dbh = enable_mars($dbh, $native); + $dbh->{HandleError} = \&error_handler; + if ($dbi_version) { + $dbh->{odbc_disable_array_operations} = 1; + } + #$dbh->{ora_verbose} = 5; + $dbh->{RaiseError} = 1; + $dbh->{PrintError} = 0; + $dbh->{ChopBlanks} = 1; + $dbh->{AutoCommit} = 1; + + return $dbh; +} + +sub create_table +{ + my ($self, $dbh) = @_; + + eval { + $dbh->do(qq/create table $table (a integer not null primary key, b char(20))/); + }; + if ($@) { + diag("Failed to create test table $table - $@"); + return 0; + } + eval { + $dbh->do(qq/create table $table2 (a integer not null primary key, b char(20))/); + }; + if ($@) { + diag("Failed to create test table $table2 - $@"); + return 0; + } + my $sth = $dbh->prepare(qq/insert into $table2 values(?,?)/); + for (my $row = 0; $row < @p1; $row++) { + $sth->execute($p1[$row], $p2[$row]); + } + 1; +} + +sub drop_table +{ + my ($self, $dbh) = @_; + + eval { + local $dbh->{PrintError} = 0; + local $dbh->{PrintWarn} = 0; + $dbh->do(qq/drop table $table/); + $dbh->do(qq/drop table $table2/); + }; + note("Table dropped"); +} + +# clear the named table of rows +sub clear_table +{ + $_[0]->do(qq/delete from $_[1]/); +} + +# check $table contains the data in $c1, $c2 which are arrayrefs of values +sub check_data +{ + my ($dbh, $c1, $c2) = @_; + + my $data = $dbh->selectall_arrayref(qq/select * from $table order by a/); + my $row = 0; + foreach (@$data) { + is($_->[0], $c1->[$row], "row $row p1 data"); + is($_->[1], $c2->[$row], "row $row p2 data"); + $row++; + } +} + +sub check_tuple_status +{ + my ($self, $tsts, $expected) = @_; + + note(Data::Dumper->Dump([$tsts], [qw(ArrayTupleStatus)])); + + BAIL_OUT('expected data must be specified') + if (!$expected || (ref($expected) ne 'ARRAY')); + + is(ref($tsts), 'ARRAY', 'tuple status is an array') or return; + if (!is(scalar(@$tsts), scalar(@$expected), 'status arrays same size')) { + diag(Dumper($tsts)); + diag(Dumper($expected)); + return; + } + + my $row = 0; + foreach my $s (@$expected) { + if (ref($s)) { + unless ($self->{_param_array_row_counts} == 2) { + is(ref($tsts->[$row]), 'ARRAY', 'array in array tuple status'); + is(scalar(@{$tsts->[$row]}), 3, '3 elements in array tuple status error'); + } + } else { + if ($tsts->[$row] == -1) { + pass("row $row tuple status unknown"); + } else { + is($tsts->[$row], $s, "row $row tuple status"); + } + } + $row++; + } + return; +} + +# insert might return 'mas' which means the caller said the test +# required Multiple Active Statements and the driver appeared to not +# support MAS. +# +# ref is a hash ref: +# error (0|1) whether we expect an error +# raise (0|1) means set RaiseError to this +# commit (0|1) do the inserts in a txn +# tuple arrayref of what we expect in the tuple status +# e.g., [1,1,1,1,[]] +# where the empty [] signifies we expect an error for this row +# where 1 signifies we the expect row count for this row +# affected - the total number of rows affected for insert/update +# +sub insert +{ + my ($self, $dbh, $sth, $ref) = @_; + + die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); + note("insert " . join(", ", map {"$_ = ". DBI::neat($ref->{$_})} keys %$ref )); + # DBD::Oracle supports MAS don't compensate for it not + if ($ref->{requires_mas} && $dbh->{Driver}->{Name} eq 'Oracle') { + delete $ref->{requires_mas}; + } + @captured_error = (); + + if ($ref->{raise}) { + $sth->{RaiseError} = 1; + } else { + $sth->{RaiseError} = 0; + } + + my (@tuple_status, $sts, $total_affected); + my $tuple_status_arg = {}; + $tuple_status_arg->{ArrayTupleStatus} = \@tuple_status unless $ref->{notuplestatus}; + + $sts = 999999; # to ensure it is overwritten + $total_affected = 999998; + if ($ref->{array_context}) { + eval { + if ($ref->{params}) { + ($sts, $total_affected) = + $sth->execute_array($tuple_status_arg, + @{$ref->{params}}); + } elsif ($ref->{fetch}) { + ($sts, $total_affected) = + $sth->execute_array( + {%{$tuple_status_arg}, + ArrayTupleFetch => $ref->{fetch}}); + } else { + ($sts, $total_affected) = + $sth->execute_array($tuple_status_arg); + } + }; + } else { + eval { + if ($ref->{params}) { + $sts = + $sth->execute_array($tuple_status_arg, + @{$ref->{params}}); + } else { + $sts = + $sth->execute_array($tuple_status_arg); + } + }; + } + if ($ref->{error} && $ref->{raise}) { + ok($@, 'error in execute_array eval'); + } else { + if ($ref->{requires_mas} && $@) { + diag("\nThis test died with $@"); + diag("It requires multiple active statement support in the driver and I cannot easily determine if your driver supports MAS. Ignoring the rest of this test."); + foreach (@tuple_status) { + if (ref($_)) { + diag(join(",", @$_)); + } + } + return 'mas'; + } + ok(!$@, 'no error in execute_array eval') or note($@); + } + $dbh->commit if $ref->{commit}; + + if (!$ref->{raise} || ($ref->{error} == 0)) { + if (exists($ref->{sts})) { + is($sts, $ref->{sts}, + "execute_array returned " . DBI::neat($sts) . " rows executed"); + } + if (exists($ref->{affected}) && $ref->{array_context}) { + is($total_affected, $ref->{affected}, + "total affected " . DBI::neat($total_affected)) + } + } + if ($ref->{raise}) { + if ($ref->{error}) { + ok(scalar(@captured_error) > 0, "error captured"); + } else { + is(scalar(@captured_error), 0, "no error captured"); + } + } + if ($ref->{sts}) { + is(scalar(@tuple_status), (($ref->{sts} eq '0E0') ? 0 : $ref->{sts}), + "$ref->{sts} rows in tuple_status"); + } + if ($ref->{tuple} && !exists($ref->{notuplestatus})) { + $self->check_tuple_status(\@tuple_status, $ref->{tuple}); + } + return; +} +# simple test on ensure execute_array with no errors: +# o checks returned status and affected is correct +# o checks ArrayTupleStatus is correct +# o checks no error is raised +# o checks rows are inserted +# o run twice with AutoCommit on/off +# o checks if less values are specified for one parameter the right number +# of rows are still inserted and NULLs are placed in the missing rows +# checks binding via bind_param_array and adding params to execute_array +# checks binding no parameters at all +sub simple +{ + my ($self, $dbh, $ref) = @_; + + note('simple tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); + + note(" all param arrays the same size"); + foreach my $commit (1,0) { + note(" Autocommit: $commit"); + clear_table($dbh, $table); + $dbh->begin_work if !$commit; + + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + $sth->bind_param_array(1, \@p1); + $sth->bind_param_array(2, \@p2); + $self->insert($dbh, $sth, + { commit => !$commit, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref}); + check_data($dbh, \@p1, \@p2); + } + + note " Not all param arrays the same size"; + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + + $sth->bind_param_array(1, \@p1); + $sth->bind_param_array(2, [qw(one)]); + $self->insert($dbh, $sth, {commit => 0, error => 0, + raise => 1, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref}); + check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); + + note " Not all param arrays the same size with bind on execute_array"; + clear_table($dbh, $table); + $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + + $self->insert($dbh, $sth, {commit => 0, error => 0, + raise => 1, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + params => [\@p1, [qw(one)]]}); + check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); + + note " no parameters"; + clear_table($dbh, $table); + $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + + $self->insert($dbh, $sth, {commit => 0, error => 0, + raise => 1, sts => '0E0', affected => 0, + tuple => [], %$ref, + params => [[], []]}); + check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); +} + +# error test to ensure correct behavior for execute_array when it errors: +# o execute_array of 5 inserts with last one failing +# o check it raises an error +# o check caught error is passed on from handler for eval +# o check returned status and affected rows +# o check ArrayTupleStatus +# o check valid inserts are inserted +# o execute_array of 5 inserts with 2nd last one failing +# o check it raises an error +# o check caught error is passed on from handler for eval +# o check returned status and affected rows +# o check ArrayTupleStatus +# o check valid inserts are inserted +sub error +{ + my ($self, $dbh, $ref) = @_; + + die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); + + note('error tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); + { + note("Last row in error"); + + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + my @pe1 = @p1; + $pe1[-1] = 1; + $sth->bind_param_array(1, \@pe1); + $sth->bind_param_array(2, \@p2); + $self->insert($dbh, $sth, {commit => 0, error => 1, sts => undef, + affected => undef, tuple => [1, 1, 1, 1, []], + %$ref}); + check_data($dbh, [@pe1[0..4]], [@p2[0..4]]); + } + + { + note("2nd last row in error"); + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + my @pe1 = @p1; + $pe1[-2] = 1; + $sth->bind_param_array(1, \@pe1); + $sth->bind_param_array(2, \@p2); + $self->insert($dbh, $sth, {commit => 0, error => 1, sts => undef, + affected => undef, tuple => [1, 1, 1, [], 1], %$ref}); + check_data($dbh, [@pe1[0..2],$pe1[4]], [@p2[0..2], $p2[4]]); + } +} + +sub fetch_sub +{ + note("fetch_sub $fetch_row"); + if ($fetch_row == @p1) { + note('returning undef'); + $fetch_row = 0; + return; + } + + return [$p1[$fetch_row], $p2[$fetch_row++]]; +} + +# test insertion via execute_array and ArrayTupleFetch +sub row_wise +{ + my ($self, $dbh, $ref) = @_; + + note("row_size via execute_for_fetch"); + + # Populate the first table via a ArrayTupleFetch which points to a sub + # returning rows + $fetch_row = 0; # reset fetch_sub to start with first row + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + fetch => \&fetch_sub}); + + # NOTE: The following test requires Multiple Active Statements. Although + # I can find ODBC drivers which do this it is not easy (if at all possible) + # to know if an ODBC driver can handle MAS or not. If it errors the + # driver probably does not have MAS so the error is ignored and a + # diagnostic is output. Exceptions are DBD::Oracle which definitely does + # support MAS. + # The data pushed into the first table is retrieved via ArrayTupleFetch + # from the second table by passing an executed select statement handle into + # execute_array. + note("row_size via select"); + clear_table($dbh, $table); + $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + my $sth2 = $dbh->prepare(qq/select * from $table2/); + # some drivers issue warnings when mas fails and this causes + # Test::NoWarnings to output something when we already found + # the test failed and captured it. + # e.g., some ODBC drivers cannot do MAS and this test is then expected to + # fail but we ignore the failure. Unfortunately in failing DBD::ODBC will + # issue a warning in addition to the fail + $sth->{Warn} = 0; + $sth->{Warn} = 0; + ok($sth2->execute, 'execute on second table') or diag($sth2->errstr); + ok($sth2->{Executed}, 'second statement is in executed state'); + my $res = $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + fetch => $sth2, requires_mas => 1}); + return if $res && $res eq 'mas'; # aborted , does not seem to support MAS + check_data($dbh, \@p1, \@p2); +} + +# test updates +# updates are special as you can update more rows than there are parameter rows +sub update +{ + my ($self, $dbh, $ref) = @_; + + note("update test"); + + # populate the first table with the default 5 rows using a ArrayTupleFetch + $fetch_row = 0; + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + fetch => \&fetch_sub}); + check_data($dbh, \@p1, \@p2); + + # update all rows b column to 'fred' checking rows affected is 5 + $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); + # NOTE, this also checks you can pass a scalar to bind_param_array + $sth->bind_param_array(1, 'fred'); + $sth->bind_param_array(2, \@p1); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref}); + check_data($dbh, \@p1, [qw(fred fred fred fred fred)]); + + # update 4 rows column b to 'dave' checking rows affected is 4 + $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); + # NOTE, this also checks you can pass a scalar to bind_param_array + $sth->bind_param_array(1, 'dave'); + my @pe1 = @p1; + $pe1[-1] = 10; # non-existant row + $sth->bind_param_array(2, \@pe1); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 4, + tuple => [1, 1, 1, 1, '0E0'], %$ref}); + check_data($dbh, \@p1, [qw(dave dave dave dave fred)]); + + # now change all rows b column to 'pete' - this will change all 5 + # rows even though we have 2 rows of parameters so we can see if + # the rows affected is > parameter rows + $sth = $dbh->prepare(qq/update $table set b = ? where b like ?/); + # NOTE, this also checks you can pass a scalar to bind_param_array + $sth->bind_param_array(1, 'pete'); + $sth->bind_param_array(2, ['dave%', 'fred%']); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 2, affected => 5, + tuple => [4, 1], %$ref}); + check_data($dbh, \@p1, [qw(pete pete pete pete pete)]); +} + +sub enable_mars { + my $dbh = shift; + + # this test uses multiple active statements + # if we recognise the driver and it supports MAS enable it + my $driver_name = $dbh->get_info(6) || ''; + if (($driver_name eq 'libessqlsrv.so') || + ($driver_name =~ /libsqlncli/)) { + my $dsn = $ENV{DBI_DSN}; + if ($dsn !~ /^dbi:ODBC:DSN=/ && $dsn !~ /DRIVER=/i) { + my @a = split(q/:/, $ENV{DBI_DSN}); + $dsn = join(q/:/, @a[0..($#a - 1)]) . ":DSN=" . $a[-1]; + } + $dsn .= ";MARS_Connection=yes"; + $dbh->disconnect; + $dbh = DBI->connect($dsn, $ENV{DBI_USER}, $ENV{DBI_PASS}); + } + return $dbh; +} + +1; From 2f4f73643333cb4c4d09947f4f68afac304a449c Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 26 Oct 2012 12:16:05 +0000 Subject: [PATCH 330/637] Improve tests in ExecuteArray (espcially to ensure things work when ArrayTupleStatus is not specified) Rewrote 26exe_array.t to be more like the one in DBD::ODBC (from where it came originally) and copied new ExecuteArray module. Fixes from Stefen for execute_array when no ArrayTupleStatus git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15454 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 14 ++ MANIFEST | 1 + dbdimp.c | 315 +++++++++++++------------- lib/DBD/Oracle.pm | 3 +- oci8.c | 558 +++++++++++++++++++++++----------------------- t/26exe_array.t | 479 ++++----------------------------------- t/ExecuteArray.pm | 519 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1013 insertions(+), 876 deletions(-) create mode 100644 t/ExecuteArray.pm diff --git a/Changes b/Changes index ef35ec0d..0e53c81d 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,20 @@ NEXT_VERSION can contain the wrong error count. Thanks to Steffen Goeldner for RT and patch. + - Fix RT80375 - no exception when execute_for_fetch fails and + ArrayTupleStatus is not specified. Also the tuple count calculation + resulted in an undefined warning. Thanks to Steffen Goeldner for + RT and patches. + + [MISCELLANEOUS] + + - The original 26exe_array test was replaced some time ago with a + copy of the one from DBD::ODBC. Since then I've fixed issues in + the DBD::ODBC one and added more tests (like tests for some RTs + above). To make keeping them in synch easier I've modularised the + tests. Hence new ExecuteArray.pm. (Martin J. Evans) + + 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/MANIFEST b/MANIFEST index 0061de6e..d1564f89 100644 --- a/MANIFEST +++ b/MANIFEST @@ -67,6 +67,7 @@ t/23wide_db_al32utf8.t t/24implicit_utf8.t t/25plsql.t t/26exe_array.t +t/ExecuteArray.pm t/28array_bind.t t/30long.t t/31lob.t diff --git a/dbdimp.c b/dbdimp.c index eded2ab3..91099bbd 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2070,19 +2070,19 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /*int flag_data_is_utf8=0;*/ if( ( ! SvROK(phs->sv) ) || (SvTYPE(SvRV(phs->sv))!=SVt_PVAV) ) { /* Allow only array binds */ - croak("dbd_rebind_ph_number_table(): bad bind variable. ARRAY reference required, but got %s for '%s'.", - neatsvpv(phs->sv,0), phs->name); + croak("dbd_rebind_ph_number_table(): bad bind variable. ARRAY reference required, but got %s for '%s'.", + neatsvpv(phs->sv,0), phs->name); } /* Default bind type for number table is double. */ if( ! phs->ora_internal_type ){ - phs->ora_internal_type=SQLT_FLT; + phs->ora_internal_type=SQLT_FLT; }else{ - if( (phs->ora_internal_type != SQLT_FLT) && - (phs->ora_internal_type != SQLT_INT) ){ - croak("dbd_rebind_ph_number_table(): Specified internal bind type %d unsupported. " - "SYS.DBMS_SQL.NUMBER_TABLE can be bound only to SQLT_FLT or SQLT_INT datatypes.", - phs->ora_internal_type); - } + if( (phs->ora_internal_type != SQLT_FLT) && + (phs->ora_internal_type != SQLT_INT) ){ + croak("dbd_rebind_ph_number_table(): Specified internal bind type %d unsupported. " + "SYS.DBMS_SQL.NUMBER_TABLE can be bound only to SQLT_FLT or SQLT_INT datatypes.", + phs->ora_internal_type); + } } arr=(AV*)(SvRV(phs->sv)); @@ -2112,11 +2112,11 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { * maxlen(double) = sizeof(double); */ switch( phs->ora_internal_type ){ - case SQLT_INT: + case SQLT_INT: phs->maxlen=sizeof(int); break; - case SQLT_FLT: - default: + case SQLT_FLT: + default: phs->maxlen=sizeof(double); } if (trace_level >= 2 || dbd_verbose >= 3 ){ @@ -2131,7 +2131,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { phs->array_numstruct=1; } if( phs->ora_maxarray_numentries== 0 ){ - /* Zero means "use current array length". */ + /* Zero means "use current array length". */ phs->ora_maxarray_numentries=phs->array_numstruct; if (trace_level >= 2 || dbd_verbose >= 3 ){ @@ -2153,7 +2153,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { need_allocate_rows=phs->ora_maxarray_numentries; if( need_allocate_rows< phs->array_numstruct ){ - need_allocate_rows=phs->array_numstruct; + need_allocate_rows=phs->array_numstruct; } buflen=need_allocate_rows* phs->maxlen; /* We need buffer for at least ora_maxarray_numentries entries */ @@ -2179,160 +2179,160 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /* Fill array buffer with data */ { - int i; /* Not to require C99 mode */ - for(i=0;iora_internal_type ){ - case SQLT_INT: - { - int ival =0; - int val_found=0; - /* Double values are converted as int(val) */ - if( SvOK( item ) && ! SvIOK( item ) ){ - double val=SvNVx( item ); - if( SvNOK( item ) ){ - ival=(int) val; - val_found=1; - } - } - /* Convert item, if possible. */ - if( (!val_found) && SvOK( item ) && ! SvIOK( item ) ){ - SvIVx( item ); - } - if( SvIOK( item ) || val_found ){ - if( ! val_found ){ - ival=SvIV( item ); - } - /* as phs->array_buf=malloc(), proper alignment is guaranteed */ - *(int*)(phs->array_buf+phs->maxlen*i)=ival; - phs->array_indicators[i]=0; - }else{ - if( SvOK( item ) ){ - /* Defined NaN assumed =0 */ - *(int*)(phs->array_buf+phs->maxlen*i)=0; - phs->array_indicators[i]=0; - }else{ - /* NULL */ - phs->array_indicators[i]=1; - } - } - phs->array_lengths[i]=sizeof(int); - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "(integer) array[%d]=%d%s\n", - i, *(int*)(phs->array_buf+phs->maxlen*i), - phs->array_indicators[i] ? " (NULL)" : "" ); - } - } - break; - case SQLT_FLT: - default: - { - phs->ora_internal_type=SQLT_FLT; /* Just in case */ - /* Convert item, if possible. */ - if( SvOK( item ) && ! SvNOK( item ) ){ - SvNVx( item ); - } - if( SvNOK( item ) ){ - double val=SvNVx( item ); - /* as phs->array_buf=malloc(), proper alignment is guaranteed */ - *(double*)(phs->array_buf+phs->maxlen*i)=val; - phs->array_indicators[i]=0; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=%f - NOT NULL\n", - i, val); - } - }else{ - if( SvOK( item ) ){ - /* Defined NaN assumed =0 */ - *(double*)(phs->array_buf+phs->maxlen*i)=0; - phs->array_indicators[i]=0; - if (trace_level >= 2 || dbd_verbose >= 3 ){ - STRLEN l; - char *p=SvPV(item,l); - - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=\"%s\" =NaN. Set =0 - NOT NULL\n", - i, p ? p : "" ); - } - }else{ - /* NULL */ - phs->array_indicators[i]=1; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "let (double) array[%d] NULL\n", - i); - } - } - } - phs->array_lengths[i]=sizeof(double); - if (trace_level >= 3 || dbd_verbose >= 3 ){ + int i; /* Not to require C99 mode */ + for(i=0;iora_internal_type ){ + case SQLT_INT: + { + int ival =0; + int val_found=0; + /* Double values are converted as int(val) */ + if( SvOK( item ) && ! SvIOK( item ) ){ + double val=SvNVx( item ); + if( SvNOK( item ) ){ + ival=(int) val; + val_found=1; + } + } + /* Convert item, if possible. */ + if( (!val_found) && SvOK( item ) && ! SvIOK( item ) ){ + SvIVx( item ); + } + if( SvIOK( item ) || val_found ){ + if( ! val_found ){ + ival=SvIV( item ); + } + /* as phs->array_buf=malloc(), proper alignment is guaranteed */ + *(int*)(phs->array_buf+phs->maxlen*i)=ival; + phs->array_indicators[i]=0; + }else{ + if( SvOK( item ) ){ + /* Defined NaN assumed =0 */ + *(int*)(phs->array_buf+phs->maxlen*i)=0; + phs->array_indicators[i]=0; + }else{ + /* NULL */ + phs->array_indicators[i]=1; + } + } + phs->array_lengths[i]=sizeof(int); + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " + "(integer) array[%d]=%d%s\n", + i, *(int*)(phs->array_buf+phs->maxlen*i), + phs->array_indicators[i] ? " (NULL)" : "" ); + } + } + break; + case SQLT_FLT: + default: + { + phs->ora_internal_type=SQLT_FLT; /* Just in case */ + /* Convert item, if possible. */ + if( SvOK( item ) && ! SvNOK( item ) ){ + SvNVx( item ); + } + if( SvNOK( item ) ){ + double val=SvNVx( item ); + /* as phs->array_buf=malloc(), proper alignment is guaranteed */ + *(double*)(phs->array_buf+phs->maxlen*i)=val; + phs->array_indicators[i]=0; + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d]=%f - NOT NULL\n", + i, val); + } + }else{ + if( SvOK( item ) ){ + /* Defined NaN assumed =0 */ + *(double*)(phs->array_buf+phs->maxlen*i)=0; + phs->array_indicators[i]=0; + if (trace_level >= 2 || dbd_verbose >= 3 ){ + STRLEN l; + char *p=SvPV(item,l); + + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d]=\"%s\" =NaN. Set =0 - NOT NULL\n", + i, p ? p : "" ); + } + }else{ + /* NULL */ + phs->array_indicators[i]=1; + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d] NULL\n", + i); + } + } + } + phs->array_lengths[i]=sizeof(double); + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "(double) array[%d]=%f%s\n", + i, *(double*)(phs->array_buf+phs->maxlen*i), + phs->array_indicators[i] ? " (NULL)" : "" ); + } + } + break; + } + }else{ + /* item not defined, mark NULL */ + phs->array_indicators[i]=1; + if (trace_level >= 3 || dbd_verbose >= 3 ){ PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "(double) array[%d]=%f%s\n", - i, *(double*)(phs->array_buf+phs->maxlen*i), - phs->array_indicators[i] ? " (NULL)" : "" ); - } - } - break; - } - }else{ - /* item not defined, mark NULL */ - phs->array_indicators[i]=1; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "Copying length=? array[%d]=NULL av_fetch failed.\n", i); - } - } - } + "Copying length=? array[%d]=NULL av_fetch failed.\n", i); + } + } + } } /* Do actual bind */ OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, (sb4)strlen(phs->name), - phs->array_buf, - phs->maxlen, - (ub2)phs->ora_internal_type, phs->array_indicators, - phs->array_lengths, - (ub2)0, - (ub4)phs->ora_maxarray_numentries, /* max elements that can fit in allocated array */ - (ub4 *)&(phs->array_numstruct), /* (ptr to) current number of elements in array */ - OCI_DEFAULT, /* OCI_DATA_AT_EXEC (bind with callbacks) or OCI_DEFAULT */ - status - ); + (text*)phs->name, (sb4)strlen(phs->name), + phs->array_buf, + phs->maxlen, + (ub2)phs->ora_internal_type, phs->array_indicators, + phs->array_lengths, + (ub2)0, + (ub4)phs->ora_maxarray_numentries, /* max elements that can fit in allocated array */ + (ub4 *)&(phs->array_numstruct), /* (ptr to) current number of elements in array */ + OCI_DEFAULT, /* OCI_DATA_AT_EXEC (bind with callbacks) or OCI_DEFAULT */ + status + ); if (status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); - return 0; + oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); + return 0; } OCIBindArrayOfStruct_log_stat(imp_sth, phs->bndhp, imp_sth->errhp, - (unsigned)phs->maxlen, /* Skip parameter for the next data value */ - (unsigned)sizeof(OCIInd), /* Skip parameter for the next indicator value */ - (unsigned)sizeof(unsigned short), /* Skip parameter for the next actual length value */ - 0, /* Skip parameter for the next column-level error code */ - status); + (unsigned)phs->maxlen, /* Skip parameter for the next data value */ + (unsigned)sizeof(OCIInd), /* Skip parameter for the next indicator value */ + (unsigned)sizeof(unsigned short), /* Skip parameter for the next actual length value */ + 0, /* Skip parameter for the next column-level error code */ + status); if (status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, status, "OCIBindArrayOfStruct"); - return 0; + oci_error(sth, imp_sth->errhp, status, "OCIBindArrayOfStruct"); + return 0; } if (phs->maxdata_size) { OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4)OCI_HTYPE_BIND, - phs->array_buf, (ub4)phs->array_buflen, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); - if ( status != OCI_SUCCESS ) { - oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); - return 0; - } + phs->array_buf, (ub4)phs->array_buflen, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); + if ( status != OCI_SUCCESS ) { + oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); + return 0; + } } return 2; @@ -3882,6 +3882,9 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er DBIc_LOGPIO(imp_sth), " ora_st_execute_array %d errors in batch.\n", num_errs); + if (num_errs) { + sv_setiv(err_count,num_errs); + } if(num_errs && tuples_status_av) { OCIError *row_errhp, *tmp_errhp; @@ -3889,7 +3892,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er SV *err_svs[3]; /*AV *err_av;*/ sb4 err_code; - sv_setiv(err_count,num_errs); + err_svs[0] = newSViv((IV)0); err_svs[1] = newSVpvn("", 0); err_svs[2] = newSVpvn("S1000",5); diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index c076760f..adba4527 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1110,7 +1110,8 @@ SQL } $err_total += $err_count; - $tuple_count+=@$tuple_batch_status; + + $tuple_count+=@tuple_batch; push @$tuple_status, @$tuple_batch_status if defined($tuple_status); diff --git a/oci8.c b/oci8.c index bf4fef49..dafc74ba 100644 --- a/oci8.c +++ b/oci8.c @@ -3423,7 +3423,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) /* long_readlen: length for long/longraw (if >0), else 80 (ora app dflt) */ /* Ought to be for COMPAT mode only but was relaxed before LongReadLen existed */ long_readlen = (SvOK(imp_drh -> ora_long) && SvUV(imp_drh->ora_long)>0) - ? SvUV(imp_drh->ora_long) : DBIc_LongReadLen(imp_sth); + ? SvUV(imp_drh->ora_long) : DBIc_LongReadLen(imp_sth); /* set long_readlen for SELECT or PL/SQL with output placeholders */ imp_sth->long_readlen = long_readlen; @@ -3435,7 +3435,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) DBIc_LOGPIO(imp_sth), " dbd_describe skipped for %s\n", oci_stmt_type_name(imp_sth->stmt_type)); - /* imp_sth memory was cleared when created so no setup required here */ + /* imp_sth memory was cleared when created so no setup required here */ return 1; } @@ -3451,12 +3451,12 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if ( !DBIc_ACTIVE(imp_sth) ) { OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, - 0, 0, 0, 0, OCI_DESCRIBE_ONLY, status); + 0, 0, 0, 0, OCI_DESCRIBE_ONLY, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, - ora_sql_error(imp_sth, "OCIStmtExecute/Describe")); + ora_sql_error(imp_sth, "OCIStmtExecute/Describe")); if (status != OCI_SUCCESS_WITH_INFO) - return 0; + return 0; } } OCIAttrGet_stmhp_stat(imp_sth, &num_fields, 0, OCI_ATTR_PARAM_COUNT, status); @@ -3478,7 +3478,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) Newz(42, imp_sth->fbh, num_fields, imp_fbh_t); /* Get number of fields and space needed for field names */ -/* loop though the fields and get all the fileds and thier types to get back*/ + /* loop though the fields and get all the fileds and thier types to get back*/ for(i = 1; i <= num_fields; ++i) { /*start define of filed struct[i] fbh */ char *p; @@ -3490,7 +3490,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->define_mode = OCI_DEFAULT; OCIParamGet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, - (dvoid**)&fbh->parmdp, (ub4)i, status); + (dvoid**)&fbh->parmdp, (ub4)i, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIParamGet"); @@ -3513,7 +3513,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->csid, 0, OCI_ATTR_CHARSET_ID, status); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->csform, 0, OCI_ATTR_CHARSET_FORM, status); #endif - /* OCI_ATTR_PRECISION returns 0 for most types including some numbers */ + /* OCI_ATTR_PRECISION returns 0 for most types including some numbers */ OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->prec, 0, OCI_ATTR_PRECISION, status); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->scale, 0, OCI_ATTR_SCALE, status); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->nullok, 0, OCI_ATTR_IS_NULL, status); @@ -3528,6 +3528,8 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->name = SvPVX(fbh->name_sv); fbh->ftype = 5; /* default: return as null terminated string */ + /* TO_DO there is something wrong with the tracing below as sql_typecode_name + returns NVARCHAR2 for type 2 and ORA_NUMBER is 2 */ if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), @@ -3535,283 +3537,283 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) i,fbh->dbtype,sql_typecode_name(fbh->dbtype)); switch (fbh->dbtype) { - /* the simple types */ - case ORA_VARCHAR2: /* VARCHAR2 */ - - if (fbh->dbsize == 0){ - fbh->dbsize=4000; - } - avg_width = fbh->dbsize / 2; - /* FALLTHRU */ - case ORA_CHAR: /* CHAR */ - if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) - fbh->disize = fbh->dbsize * 4; - else - fbh->disize = fbh->dbsize; - - fbh->prec = fbh->disize; - break; - case ORA_RAW: /* RAW */ - fbh->disize = fbh->dbsize * 2; - fbh->prec = fbh->disize; - break; - case ORA_NUMBER: /* NUMBER */ - case 21: /* BINARY FLOAT os-endian */ - case 22: /* BINARY DOUBLE os-endian */ - case 100: /* BINARY FLOAT oracle-endian */ - case 101: /* BINARY DOUBLE oracle-endian */ - fbh->disize = 130+38+3; /* worst case */ - avg_width = 4; /* NUMBER approx +/- 1_000_000 */ - break; - - case ORA_DATE: /* DATE */ - /* actually dependent on NLS default date format*/ - fbh->disize = 75; /* a generous default */ - fbh->prec = fbh->disize; - avg_width = 8; /* size in SQL*Net packet */ - break; - - case ORA_LONG: /* LONG */ - imp_sth->row_cache_off = 1; - has_longs++; - if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - - fbh->clbk_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - - fbh->ftype = SQLT_CHR; - fbh->fetch_func = fetch_clbk_lob; - - } - else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ - - fbh->piece_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + /* the simple types */ + case ORA_VARCHAR2: /* VARCHAR2 */ - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - fbh->ftype = SQLT_CHR; - fbh->fetch_func = fetch_get_piece; - } - else { + if (fbh->dbsize == 0){ + fbh->dbsize=4000; + } + avg_width = fbh->dbsize / 2; + /* FALLTHRU */ + case ORA_CHAR: /* CHAR */ + if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) + fbh->disize = fbh->dbsize * 4; + else + fbh->disize = fbh->dbsize; + + fbh->prec = fbh->disize; + break; + case ORA_RAW: /* RAW */ + fbh->disize = fbh->dbsize * 2; + fbh->prec = fbh->disize; + break; + case ORA_NUMBER: /* NUMBER */ + case 21: /* BINARY FLOAT os-endian */ + case 22: /* BINARY DOUBLE os-endian */ + case 100: /* BINARY FLOAT oracle-endian */ + case 101: /* BINARY DOUBLE oracle-endian */ + fbh->disize = 130+38+3; /* worst case */ + avg_width = 4; /* NUMBER approx +/- 1_000_000 */ + break; + + case ORA_DATE: /* DATE */ + /* actually dependent on NLS default date format*/ + fbh->disize = 75; /* a generous default */ + fbh->prec = fbh->disize; + avg_width = 8; /* size in SQL*Net packet */ + break; + + case ORA_LONG: /* LONG */ + imp_sth->row_cache_off = 1; + has_longs++; + if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ + + fbh->clbk_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + + fbh->ftype = SQLT_CHR; + fbh->fetch_func = fetch_clbk_lob; - if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) - fbh->disize = long_readlen * 4; - else - fbh->disize = long_readlen; + } + else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + + fbh->piece_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + fbh->ftype = SQLT_CHR; + fbh->fetch_func = fetch_get_piece; + } + else { - /* not governed by else: */ - fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; - fbh->ftype = 94; /* VAR form */ - fbh->fetch_func = fetch_func_varfield; + if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) + fbh->disize = long_readlen * 4; + else + fbh->disize = long_readlen; - } - break; - case ORA_LONGRAW: /* LONG RAW */ - has_longs++; - if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - - fbh->clbk_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } + /* not governed by else: */ + fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; + fbh->ftype = 94; /* VAR form */ + fbh->fetch_func = fetch_func_varfield; - fbh->ftype = SQLT_BIN; - fbh->fetch_func = fetch_clbk_lob; + } + break; + case ORA_LONGRAW: /* LONG RAW */ + has_longs++; + if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - } - else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + fbh->clbk_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - fbh->piece_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - fbh->ftype = SQLT_BIN; - fbh->fetch_func = fetch_get_piece; - } - else { - fbh->disize = long_readlen * 2; - fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; - fbh->ftype = 95; /* VAR form */ - fbh->fetch_func = fetch_func_varfield; - } - break; - - case ORA_ROWID: /* ROWID */ - case 104: /* ROWID Desc */ - fbh->disize = 20; - fbh->prec = fbh->disize; - break; - case 108: /* some sort of embedded object */ - imp_sth->row_cache_off = 1;/* cant fetch more thatn one at a time */ - fbh->ftype = fbh->dbtype; /*varray or alike */ - fbh->fetch_func = fetch_func_oci_object; /* need a new fetch function for it */ - fbh->fetch_cleanup = fetch_cleanup_oci_object; /* clean up any AV from the fetch*/ - fbh->desc_t = SQLT_NTY; - if (!imp_sth->dschp){ - OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); - if (status != OCI_SUCCESS) { - oci_error(h,imp_sth->errhp, status, "OCIHandleAlloc"); - ++num_errors; - } - } - break; - case ORA_CLOB: /* CLOB & NCLOB */ - case ORA_BLOB: /* BLOB */ - case ORA_BFILE: /* BFILE */ - has_longs++; - fbh->ftype = fbh->dbtype; - imp_sth->ret_lobs = 1; - imp_sth->row_cache_off = 1; /* Cannot use mulit fetch for a lob*/ - /* Unless they are just getting the locator */ - - if (imp_sth->pers_lob){ /*get as one peice fasted but limited to 64k big you can get.*/ - - fbh->pers_lob = 1; - - if (long_readlen){ - fbh->disize =long_readlen;/*user set max value for the fetch*/ - } - else { - fbh->disize = fbh->dbsize*10; /*default size*/ - } + fbh->ftype = SQLT_BIN; + fbh->fetch_func = fetch_clbk_lob; + } + else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + + fbh->piece_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + fbh->ftype = SQLT_BIN; + fbh->fetch_func = fetch_get_piece; + } + else { + fbh->disize = long_readlen * 2; + fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; + fbh->ftype = 95; /* VAR form */ + fbh->fetch_func = fetch_func_varfield; + } + break; + + case ORA_ROWID: /* ROWID */ + case 104: /* ROWID Desc */ + fbh->disize = 20; + fbh->prec = fbh->disize; + break; + case 108: /* some sort of embedded object */ + imp_sth->row_cache_off = 1;/* cant fetch more thatn one at a time */ + fbh->ftype = fbh->dbtype; /*varray or alike */ + fbh->fetch_func = fetch_func_oci_object; /* need a new fetch function for it */ + fbh->fetch_cleanup = fetch_cleanup_oci_object; /* clean up any AV from the fetch*/ + fbh->desc_t = SQLT_NTY; + if (!imp_sth->dschp){ + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + if (status != OCI_SUCCESS) { + oci_error(h,imp_sth->errhp, status, "OCIHandleAlloc"); + ++num_errors; + } + } + break; + case ORA_CLOB: /* CLOB & NCLOB */ + case ORA_BLOB: /* BLOB */ + case ORA_BFILE: /* BFILE */ + has_longs++; + fbh->ftype = fbh->dbtype; + imp_sth->ret_lobs = 1; + imp_sth->row_cache_off = 1; /* Cannot use mulit fetch for a lob*/ + /* Unless they are just getting the locator */ + + if (imp_sth->pers_lob){ /*get as one peice fasted but limited to 64k big you can get.*/ + + fbh->pers_lob = 1; + + if (long_readlen){ + fbh->disize =long_readlen;/*user set max value for the fetch*/ + } + else { + fbh->disize = fbh->dbsize*10; /*default size*/ + } + + + if (fbh->dbtype == ORA_CLOB){ + fbh->ftype = SQLT_CHR;/*SQLT_LNG*/ + } + else { + fbh->ftype = SQLT_LVB; /*Binary form seems this is the only value where we can get the length correctly*/ + } + } + else if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ + fbh->clbk_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + if (fbh->dbtype == ORA_CLOB){ + fbh->ftype = SQLT_CHR; + } else { + fbh->ftype = SQLT_BIN; /*other Binary*/ + } + fbh->fetch_func = fetch_clbk_lob; - if (fbh->dbtype == ORA_CLOB){ - fbh->ftype = SQLT_CHR;/*SQLT_LNG*/ - } - else { - fbh->ftype = SQLT_LVB; /*Binary form seems this is the only value where we can get the length correctly*/ - } - } - else if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - fbh->clbk_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - if (fbh->dbtype == ORA_CLOB){ - fbh->ftype = SQLT_CHR; - } else { - fbh->ftype = SQLT_BIN; /*other Binary*/ - } - fbh->fetch_func = fetch_clbk_lob; - - } - else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ - fbh->piece_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - if (fbh->dbtype == ORA_CLOB){ - fbh->ftype = SQLT_CHR; - } - else { - fbh->ftype = SQLT_BIN; /*other Binary */ - } - fbh->fetch_func = fetch_get_piece; + } + else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + fbh->piece_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + if (fbh->dbtype == ORA_CLOB){ + fbh->ftype = SQLT_CHR; + } + else { + fbh->ftype = SQLT_BIN; /*other Binary */ + } + fbh->fetch_func = fetch_get_piece; - } - else { /*auto lob fetch with locator by far the fastest*/ - fbh->disize = sizeof(OCILobLocator*);/* Size of the lob locator ar we do not really get the lob! */ - if (imp_sth->auto_lob) { - fbh->fetch_func = fetch_func_autolob; - } - else { - fbh->fetch_func = fetch_func_getrefpv; - } + } + else { /*auto lob fetch with locator by far the fastest*/ + fbh->disize = sizeof(OCILobLocator*);/* Size of the lob locator ar we do not really get the lob! */ + if (imp_sth->auto_lob) { + fbh->fetch_func = fetch_func_autolob; + } + else { + fbh->fetch_func = fetch_func_getrefpv; + } - fbh->bless = "OCILobLocatorPtr"; - fbh->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &fbh->desc_h, fbh->desc_t); + fbh->bless = "OCILobLocatorPtr"; + fbh->desc_t = OCI_DTYPE_LOB; + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &fbh->desc_h, fbh->desc_t); - } + } - break; + break; #ifdef OCI_DTYPE_REF - case 111: /* REF */ - fbh_setup_getrefpv(imp_sth, fbh, OCI_DTYPE_REF, "OCIRefPtr"); - break; + case 111: /* REF */ + fbh_setup_getrefpv(imp_sth, fbh, OCI_DTYPE_REF, "OCIRefPtr"); + break; #endif - case ORA_RSET: /* RSET */ - fbh->ftype = fbh->dbtype; - fbh->disize = sizeof(OCIStmt *); - fbh->fetch_func = fetch_func_rset; - fbh->fetch_cleanup = fetch_cleanup_rset; - nested_cursors++; - break; - - case 182: /* INTERVAL YEAR TO MONTH */ - case 183: /* INTERVAL DAY TO SECOND */ - case 185: /* TIME (ocidfn.h) */ - case 186: /* TIME WITH TIME ZONE (ocidfn.h) */ - case 187: /* TIMESTAMP */ - case 188: /* TIMESTAMP WITH TIME ZONE */ - case 189: /* INTERVAL YEAR TO MONTH (ocidfn.h) */ - case 190: /* INTERVAL DAY TO SECOND */ - case 232: /* TIMESTAMP WITH LOCAL TIME ZONE */ - /* actually dependent on NLS default date format*/ - fbh->disize = 75; /* XXX */ - break; - - default: + case ORA_RSET: /* RSET */ + fbh->ftype = fbh->dbtype; + fbh->disize = sizeof(OCIStmt *); + fbh->fetch_func = fetch_func_rset; + fbh->fetch_cleanup = fetch_cleanup_rset; + nested_cursors++; + break; + + case 182: /* INTERVAL YEAR TO MONTH */ + case 183: /* INTERVAL DAY TO SECOND */ + case 185: /* TIME (ocidfn.h) */ + case 186: /* TIME WITH TIME ZONE (ocidfn.h) */ + case 187: /* TIMESTAMP */ + case 188: /* TIMESTAMP WITH TIME ZONE */ + case 189: /* INTERVAL YEAR TO MONTH (ocidfn.h) */ + case 190: /* INTERVAL DAY TO SECOND */ + case 232: /* TIMESTAMP WITH LOCAL TIME ZONE */ + /* actually dependent on NLS default date format*/ + fbh->disize = 75; /* XXX */ + break; + + default: /* XXX unhandled type may lead to errors or worse */ - fbh->ftype = fbh->dbtype; - fbh->disize = fbh->dbsize; - p = "Field %d has an Oracle type (%d) which is not explicitly supported%s"; - if (DBIc_DBISTATE(imp_sth)->debug >= 1 || dbd_verbose >= 3 ) - PerlIO_printf(DBIc_LOGPIO(imp_sth), p, i, fbh->dbtype, "\n"); - if (PL_dowarn) - warn(p, i, fbh->dbtype, ""); - break; + fbh->ftype = fbh->dbtype; + fbh->disize = fbh->dbsize; + p = "Field %d has an Oracle type (%d) which is not explicitly supported%s"; + if (DBIc_DBISTATE(imp_sth)->debug >= 1 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_sth), p, i, fbh->dbtype, "\n"); + if (PL_dowarn) + warn(p, i, fbh->dbtype, ""); + break; } if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, " - "name %s\n : dbsize %d, char_used %d, char_size %d, " - "csid %d, csform %d(%s), disize %d\n", - i, fbh->dbtype, sql_typecode_name(fbh->dbtype), fbh->scale, - fbh->prec, fbh->nullok, fbh->name, fbh->dbsize, - fbh->len_char_used, fbh->len_char_size, - fbh->csid,fbh->csform,oci_csform_name(fbh->csform), fbh->disize); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, " + "name %s\n : dbsize %d, char_used %d, char_size %d, " + "csid %d, csform %d(%s), disize %d\n", + i, fbh->dbtype, sql_typecode_name(fbh->dbtype), fbh->scale, + fbh->prec, fbh->nullok, fbh->name, fbh->dbsize, + fbh->len_char_used, fbh->len_char_size, + fbh->csid,fbh->csform,oci_csform_name(fbh->csform), fbh->disize); if (fbh->ftype == 5) /* XXX need to handle wide chars somehow */ fbh->disize += 1; /* allow for null terminator */ - /* dbsize can be zero for 'select NULL ...' */ + /* dbsize can be zero for 'select NULL ...' */ imp_sth->t_dbsize += fbh->dbsize; @@ -3828,8 +3830,8 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) imp_sth->est_width = est_width; sth_set_row_cache(h, imp_sth, - (imp_dbh->max_nested_cursors) ? 0 :nested_cursors , - (int)num_fields, has_longs ); + (imp_dbh->max_nested_cursors) ? 0 :nested_cursors , + (int)num_fields, has_longs ); /* Initialise cache counters */ imp_sth->in_cache = 0; imp_sth->eod_errno = 0; @@ -3861,26 +3863,26 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (fbh->ftype == ORA_RSET) { /* RSET */ OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, - (dvoid*)&((OCIStmt **)fb_ary->abuf)[0], - OCI_HTYPE_STMT, status); + (dvoid*)&((OCIStmt **)fb_ary->abuf)[0], + OCI_HTYPE_STMT, status); } OCIDefineByPos_log_stat(imp_sth, imp_sth->stmhp, - &fbh->defnp, - imp_sth->errhp, - (ub4) i, - (fbh->desc_h) ? (dvoid*)&fbh->desc_h : fbh->clbk_lob ? (dvoid *) 0: fbh->piece_lob ? (dvoid *) 0:(dvoid*)fb_ary->abuf, - (fbh->desc_h) ? 0 : define_len, - (ub2)fbh->ftype, - fb_ary->aindp, - (ftype==94||ftype==95) ? NULL : fb_ary->arlen, - fb_ary->arcode, - fbh->define_mode, - status); + &fbh->defnp, + imp_sth->errhp, + (ub4) i, + (fbh->desc_h) ? (dvoid*)&fbh->desc_h : fbh->clbk_lob ? (dvoid *) 0: fbh->piece_lob ? (dvoid *) 0:(dvoid*)fb_ary->abuf, + (fbh->desc_h) ? 0 : define_len, + (ub2)fbh->ftype, + fb_ary->aindp, + (ftype==94||ftype==95) ? NULL : fb_ary->arlen, + fb_ary->arcode, + fbh->define_mode, + status); if (fbh->clbk_lob){ - /* use a dynamic callback for persistent binary and char lobs*/ + /* use a dynamic callback for persistent binary and char lobs*/ OCIDefineDynamic_log_stat(imp_sth, fbh->defnp,imp_sth->errhp,(dvoid *) fbh,status); } @@ -3917,14 +3919,14 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) #ifdef OCI_ATTR_CHARSET_FORM if ( (fbh->dbtype == 1) && fbh->csform ) { - /* csform may be 0 when talking to Oracle 8.0 database*/ + /* csform may be 0 when talking to Oracle 8.0 database*/ if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " calling OCIAttrSet OCI_ATTR_CHARSET_FORM with csform=%d (%s)\n", fbh->csform,oci_csform_name(fbh->csform) ); OCIAttrSet_log_stat(imp_sth, fbh->defnp, (ub4) OCI_HTYPE_DEFINE, (dvoid *) &fbh->csform, - (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status ); + (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status ); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_CHARSET_FORM"); ++num_errors; @@ -4016,7 +4018,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_sth->rs_array_idx=0; } - else { /*Array Fetch the New Noraml Super speedy and very nice*/ + else { /*Array Fetch the New Normal Super speedy and very nice*/ imp_sth->rs_array_idx++; @@ -4161,7 +4163,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ char errstr[256]; sts = DBIc_DBISTATE(imp_sth)->sql_type_cast_svpv( - aTHX_ sv, fbh->req_type, fbh->bind_flags, NULL); + aTHX_ sv, fbh->req_type, fbh->bind_flags, NULL); if (sts == 0) { sprintf(errstr, diff --git a/t/26exe_array.t b/t/26exe_array.t index 52107a96..8a4519fe 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -1,15 +1,9 @@ -#!/usr/bin/perl -w -I./t - -## ---------------------------------------------------------------------------- -## 26exe_array.t this is a completly new one -## By Martin J. Evans orgianlly called 70execute_array.t for the ODBC DBD driver -## and adatped into DBD::Oracle (in a very minor way) by John Scoles, The Pythian Group -## ---------------------------------------------------------------------------- -## loads of execute_array and execute_for_fetch tests -## tests both insert and update and row fetching -## with RaiseError on and off and AutoCommit on and off -## ---------------------------------------------------------------------------- - +# $Id$ +# Completely new test for DBD::Oracle which came from DBD::ODBC +# Author: Martin J. Evans +# +# loads of execute_array and execute_for_fetch tests using DBI's methods +# use Test::More; use strict; use Data::Dumper; @@ -17,25 +11,30 @@ require 'nchar_test_lib.pl'; $| = 1; +my $has_test_nowarnings = 1; +eval "require Test::NoWarnings"; +$has_test_nowarnings = undef if $@; + +my ($dbh, $ea); -my $table = 'PERL_DBD_execute_array'; -my $table2 = 'PERL_DBD_execute_array2'; -my @captured_error; # values captured in error handler +use DBI qw(:sql_types); +use ExecuteArray; +END { + if ($dbh && $ea) { + $ea->drop_table($dbh); + $dbh->disconnect(); + } + Test::NoWarnings::had_no_warnings() + if ($has_test_nowarnings); + done_testing(); +} -# create a database handle my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; $ENV{NLS_NCHAR} = "US7ASCII"; $ENV{NLS_LANG} = "AMERICAN"; -my $dbh; -my @p1 = (1,2,3,4,5); -my @p2 = qw(one two three four five); -my $fetch_row = 0; - -use DBI qw(:sql_types); - eval { $dbh = DBI->connect($dsn, $dbuser, '', {PrintError => 0}); }; @@ -43,426 +42,24 @@ eval { if (!$dbh) { plan skip_all => "Unable to connect to Oracle"; } -#$dbh->{PrintError} = 1; -my $has_test_nowarnings = 1; -eval "require Test::NoWarnings"; -$has_test_nowarnings = undef if $@; -use_ok('Data::Dumper'); - -END { - if ($dbh) { - drop_table_local($dbh); - } - Test::NoWarnings::had_no_warnings() - if ($has_test_nowarnings); - done_testing(); -} - -sub error_handler -{ - @captured_error = @_; - note("***** error handler called *****"); - 0; # pass errors on -} - -sub create_table_local -{ - my $dbh = shift; - - eval { - $dbh->do(qq/create table $table (a int primary key, b char(20))/); - }; - if ($@) { - diag("Failed to create test table $table - $@"); - return 0; - } - eval { - $dbh->do(qq/create table $table2 (a int primary key, b char(20))/); - }; - if ($@) { - diag("Failed to create test table $table2 - $@"); - return 0; - } - my $sth = $dbh->prepare(qq/insert into $table2 values(?,?)/); - for (my $row = 0; $row < @p1; $row++) { - $sth->execute($p1[$row], $p2[$row]); - } - 1; -} - -sub drop_table_local -{ - my $dbh = shift; - - eval { - local $dbh->{PrintError} = 0; - local $dbh->{PrintWarn} = 0; - $dbh->do(qq/drop table $table/); - $dbh->do(qq/drop table $table2/); - }; - note("Table dropped"); -} - -# clear the named table of rows -sub clear_table -{ - $_[0]->do(qq/delete from $_[1]/); -} - -# check $table contains the data in $c1, $c2 which are arrayrefs of values -sub check_data -{ - my ($dbh, $c1, $c2) = @_; - - my $data = $dbh->selectall_arrayref(qq/select * from $table order by a/); - my $row = 0; - foreach (@$data) { - is($_->[0], $c1->[$row], "row $row p1 data"); - is($_->[1], $c2->[$row], "row $row p2 data"); - $row++; - } -} - -sub check_tuple_status -{ - my ($tsts, $expected) = @_; - - note(Data::Dumper->Dump([$tsts], [qw(ArrayTupleStatus)])); - my $row = 0; - foreach my $s (@$tsts) { - if (ref($expected->[$row])) { - is(ref($s), 'ARRAY', 'array in array tuple status'); - is(scalar(@$s), 3, '3 elements in array tuple status error'); - } else { - if ($s == -1) { - pass("row $row tuple status unknown"); - } else { - is($s, $expected->[$row], "row $row tuple status"); - } - } - $row++ - } -} - -# insert might return 'mas' which means the caller said the test -# required Multiple Active Statements and the driver appeared to not -# support MAS. -sub insert -{ - my ($dbh, $sth, $ref) = @_; - - die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); - note("insert " . join(", ", map {"$_ = ". DBI::neat($ref->{$_})} keys %$ref )); - # DBD::Oracle supports MAS don't compensate for it not - if ($ref->{requires_mas} && $dbh->{Driver}->{Name} eq 'Oracle') { - delete $ref->{requires_mas}; - } - @captured_error = (); - - if ($ref->{raise}) { - $sth->{RaiseError} = 1; - } else { - $sth->{RaiseError} = 0; - } - - my (@tuple_status, $sts, $total_affected); - $sts = 999999; # to ensure it is overwritten - $total_affected = 999998; - if ($ref->{array_context}) { - eval { - if ($ref->{params}) { - ($sts, $total_affected) = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}, - @{$ref->{params}}); - } elsif ($ref->{fetch}) { - ($sts, $total_affected) = - $sth->execute_array( - {ArrayTupleStatus => \@tuple_status, - ArrayTupleFetch => $ref->{fetch}}); - } else { - ($sts, $total_affected) = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}); - } - }; - } else { - eval { - if ($ref->{params}) { - $sts = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}, - @{$ref->{params}}); - } else { - $sts = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}); - } - }; - } - if ($ref->{error} && $ref->{raise}) { - ok($@, 'error in execute_array eval'); - } else { - if ($ref->{requires_mas} && $@) { - diag("\nThis test died with $@"); - diag("It requires multiple active statement support in the driver and I cannot easily determine if your driver supports MAS. Ignoring the rest of this test."); - foreach (@tuple_status) { - if (ref($_)) { - diag(join(",", @$_)); - } - } - return 'mas'; - } - ok(!$@, 'no error in execute_array eval') or note($@); - } - $dbh->commit if $ref->{commit}; - - if (!$ref->{raise} || ($ref->{error} == 0)) { - if (exists($ref->{sts})) { - is($sts, $ref->{sts}, - "execute_array returned " . DBI::neat($sts) . " rows executed"); - } - if (exists($ref->{affected}) && $ref->{array_context}) { - is($total_affected, $ref->{affected}, - "total affected " . DBI::neat($total_affected)) - } - } - if ($ref->{raise}) { - if ($ref->{error}) { - ok(scalar(@captured_error) > 0, "error captured"); - } else { - is(scalar(@captured_error), 0, "no error captured"); - } - } - if ($ref->{sts}) { - is(scalar(@tuple_status), (($ref->{sts} eq '0E0') ? 0 : $ref->{sts}), - "$ref->{sts} rows in tuple_status"); - } - if ($ref->{tuple}) { - check_tuple_status(\@tuple_status, $ref->{tuple}); - } - return; -} -# simple test on ensure execute_array with no errors: -# o checks returned status and affected is correct -# o checks ArrayTupleStatus is correct -# o checks no error is raised -# o checks rows are inserted -# o run twice with AutoCommit on/off -# o checks if less values are specified for one parameter the right number -# of rows are still inserted and NULLs are placed in the missing rows -# checks binding via bind_param_array and adding params to execute_array -# checks binding no parameters at all -sub simple -{ - my ($dbh, $ref) = @_; - - note('simple tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); - - note(" all param arrays the same size"); - foreach my $commit (1,0) { - note(" Autocommit: $commit"); - clear_table($dbh, $table); - $dbh->begin_work if !$commit; - - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - $sth->bind_param_array(1, \@p1); - $sth->bind_param_array(2, \@p2); - insert($dbh, $sth, - { commit => !$commit, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref}); - check_data($dbh, \@p1, \@p2); - } - - note " Not all param arrays the same size"; - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - - $sth->bind_param_array(1, \@p1); - $sth->bind_param_array(2, [qw(one)]); - insert($dbh, $sth, {commit => 0, error => 0, - raise => 1, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref}); - check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); - - note " Not all param arrays the same size with bind on execute_array"; - clear_table($dbh, $table); - $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - - insert($dbh, $sth, {commit => 0, error => 0, - raise => 1, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - params => [\@p1, [qw(one)]]}); - check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); - - note " no parameters"; - clear_table($dbh, $table); - $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - - insert($dbh, $sth, {commit => 0, error => 0, - raise => 1, sts => '0E0', affected => 0, - tuple => [], %$ref, - params => [[], []]}); - check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); -} - -# error test to ensure correct behavior for execute_array when it errors: -# o execute_array of 5 inserts with last one failing -# o check it raises an error -# o check caught error is passed on from handler for eval -# o check returned status and affected rows -# o check ArrayTupleStatus -# o check valid inserts are inserted -# o execute_array of 5 inserts with 2nd last one failing -# o check it raises an error -# o check caught error is passed on from handler for eval -# o check returned status and affected rows -# o check ArrayTupleStatus -# o check valid inserts are inserted -sub error -{ - my ($dbh, $ref) = @_; - - die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); - - note('error tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); - { - note("Last row in error"); - - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - my @pe1 = @p1; - $pe1[-1] = 1; - $sth->bind_param_array(1, \@pe1); - $sth->bind_param_array(2, \@p2); - insert($dbh, $sth, {commit => 0, error => 1, sts => undef, - affected => undef, tuple => [1, 1, 1, 1, []], - %$ref}); - check_data($dbh, [@pe1[0..4]], [@p2[0..4]]); - } - - { - note("2nd last row in error"); - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - my @pe1 = @p1; - $pe1[-2] = 1; - $sth->bind_param_array(1, \@pe1); - $sth->bind_param_array(2, \@p2); - insert($dbh, $sth, {commit => 0, error => 1, sts => undef, - affected => undef, tuple => [1, 1, 1, [], 1], %$ref}); - check_data($dbh, [@pe1[0..2],$pe1[4]], [@p2[0..2], $p2[4]]); - } -} - -sub fetch_sub -{ - note("fetch_sub $fetch_row"); - if ($fetch_row == @p1) { - note('returning undef'); - $fetch_row = 0; - return; - } - - return [$p1[$fetch_row], $p2[$fetch_row++]]; -} - -# test insertion via execute_array and ArrayTupleFetch -sub row_wise -{ - my ($dbh, $ref) = @_; - - note("row_size via execute_for_fetch"); - - $fetch_row = 0; - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - fetch => \&fetch_sub}); - - # NOTE: I'd like to do the following test but it requires Multiple - # Active Statements and although I can find ODBC drivers which do this - # it is not easy (if at all possible) to know if an ODBC driver can - # handle MAS or not. If it errors the driver probably does not have MAS - # so the error is ignored and a diagnostic is output. - note("row_size via select"); - clear_table($dbh, $table); - $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - my $sth2 = $dbh->prepare(qq/select * from $table2/); - ok($sth2->execute, 'execute on second table') or diag($sth2->errstr); - ok($sth2->{Executed}, 'second statement is in executed state'); - my $res = insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - fetch => $sth2, requires_mas => 1}); - return if $res && $res eq 'mas'; # aborted , does not seem to support MAS - check_data($dbh, \@p1, \@p2); - #my $res = $dbh->selectall_arrayref("select * from $table2"); - #print Dumper($res); -} - -# test updates -sub update -{ - my ($dbh, $ref) = @_; - - note("update test"); - - $fetch_row = 0; - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - fetch => \&fetch_sub}); - check_data($dbh, \@p1, \@p2); - - $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); - # NOTE, this also checks you can pass a scalar to bind_param_array - $sth->bind_param_array(1, 'fred'); - $sth->bind_param_array(2, \@p1); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref}); - check_data($dbh, \@p1, [qw(fred fred fred fred fred)]); - - $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); - # NOTE, this also checks you can pass a scalar to bind_param_array - $sth->bind_param_array(1, 'dave'); - my @pe1 = @p1; - $pe1[-1] = 10; # non-existant row - $sth->bind_param_array(2, \@pe1); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 4, - tuple => [1, 1, 1, 1, '0E0'], %$ref}); - check_data($dbh, \@p1, [qw(dave dave dave dave fred)]); - - $sth = $dbh->prepare(qq/update $table set b = ? where b like ?/); - # NOTE, this also checks you can pass a scalar to bind_param_array - $sth->bind_param_array(1, 'pete'); - $sth->bind_param_array(2, ['dave%', 'fred%']); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 2, affected => 5, - tuple => [4, 1], %$ref}); - check_data($dbh, \@p1, [qw(pete pete pete pete pete)]); - - -} -$dbh->{RaiseError} = 1; -$dbh->{PrintError} = 0; -$dbh->{ChopBlanks} = 1; -$dbh->{HandleError} = \&error_handler; -$dbh->{AutoCommit} = 1; +$ea = ExecuteArray->new($dbh, 1); # set odbc_disable_array_operations +$dbh = $ea->dbh; -eval {drop_table_local($dbh)}; +$ea->drop_table($dbh); +ok($ea->create_table($dbh), "create test table") or exit 1; +$ea->simple($dbh, {array_context => 1, raise => 1}); +$ea->simple($dbh, {array_context => 0, raise => 1}); +$ea->error($dbh, {array_context => 1, raise => 1}); +$ea->error($dbh, {array_context => 0, raise => 1}); +$ea->error($dbh, {array_context => 1, raise => 0}); +$ea->error($dbh, {array_context => 0, raise => 0}); -ok(create_table_local($dbh), "create test table") or exit 1; -simple($dbh, {array_context => 1, raise => 1}); -simple($dbh, {array_context => 0, raise => 1}); -error($dbh, {array_context => 1, raise => 1}); -error($dbh, {array_context => 0, raise => 1}); -error($dbh, {array_context => 1, raise => 0}); -error($dbh, {array_context => 0, raise => 0}); +$ea->row_wise($dbh, {array_context => 1, raise => 1}); -row_wise($dbh, {array_context => 1, raise => 1}); +$ea->update($dbh, {array_context => 1, raise => 1}); -update($dbh, {array_context => 1, raise => 1}); +$ea->error($dbh, {array_context => 1, raise => 1, notuplestatus => 1}); +$ea->error($dbh, {array_context => 0, raise => 1, notuplestatus => 1}); +$ea->error($dbh, {array_context => 1, raise => 0, notuplestatus => 1}); +$ea->error($dbh, {array_context => 0, raise => 0, notuplestatus => 1}); diff --git a/t/ExecuteArray.pm b/t/ExecuteArray.pm new file mode 100644 index 00000000..268641f0 --- /dev/null +++ b/t/ExecuteArray.pm @@ -0,0 +1,519 @@ +# $Id$ +# Author: Martin J. Evans +# This should be an exact copy of the same file in DBD::ODBC +# If you change this file please let me know. +package ExecuteArray; +use Test::More; +use Data::Dumper; +use DBI; +our $VERSION = '0.01'; + +my $table = 'PERL_DBD_execute_array'; +my $table2 = 'PERL_DBD_execute_array2'; +my @p1 = (1,2,3,4,5); +my @p2 = qw(one two three four five); +my $fetch_row = 0; +my @captured_error; # values captured in error handler + +sub error_handler +{ + @captured_error = @_; + note("***** error handler called *****"); + 0; # pass errors on +} + +sub new { + my ($class, $dbh, $dbi_version) = @_; + my $self = {}; + + $dbh = setup($dbh, $dbi_version); + $self->{_dbh} = $dbh; + + # find out how the driver supports row counts and parameter status + $self->{_param_array_row_counts} = $dbh->get_info(153); + # a return of 1 is SQL_PARC_BATCH which means: + # Individual row counts are available for each set of parameters. This is + # conceptually equivalent to the driver generating a batch of SQL + # statements, one for each parameter set in the array. Extended error + # information can be retrieved by using the SQL_PARAM_STATUS_PTR + # descriptor field. + # a return of 2 is SQL_PARC_NO_BATCH which means: + # There is only one row count available, which is the cumulative row + # count resulting from the execution of the statement for the entire + # array of parameters. This is conceptually equivalent to treating + # the statement together with the complete parameter array as one + # atomic unit. Errors are handled the same as if one statement + # were executed. + return bless ($self, $class); +} + +sub dbh { + my $self = shift; + return $self->{_dbh}; +} + +sub setup { + my ($dbh, $dbi_version) = @_; + + $dbh = enable_mars($dbh, $native); + $dbh->{HandleError} = \&error_handler; + if ($dbi_version) { + $dbh->{odbc_disable_array_operations} = 1; + } + #$dbh->{ora_verbose} = 5; + $dbh->{RaiseError} = 1; + $dbh->{PrintError} = 0; + $dbh->{ChopBlanks} = 1; + $dbh->{AutoCommit} = 1; + + return $dbh; +} + +sub create_table +{ + my ($self, $dbh) = @_; + + eval { + $dbh->do(qq/create table $table (a integer not null primary key, b char(20))/); + }; + if ($@) { + diag("Failed to create test table $table - $@"); + return 0; + } + eval { + $dbh->do(qq/create table $table2 (a integer not null primary key, b char(20))/); + }; + if ($@) { + diag("Failed to create test table $table2 - $@"); + return 0; + } + my $sth = $dbh->prepare(qq/insert into $table2 values(?,?)/); + for (my $row = 0; $row < @p1; $row++) { + $sth->execute($p1[$row], $p2[$row]); + } + 1; +} + +sub drop_table +{ + my ($self, $dbh) = @_; + + eval { + local $dbh->{PrintError} = 0; + local $dbh->{PrintWarn} = 0; + $dbh->do(qq/drop table $table/); + $dbh->do(qq/drop table $table2/); + }; + note("Table dropped"); +} + +# clear the named table of rows +sub clear_table +{ + $_[0]->do(qq/delete from $_[1]/); +} + +# check $table contains the data in $c1, $c2 which are arrayrefs of values +sub check_data +{ + my ($dbh, $c1, $c2) = @_; + + my $data = $dbh->selectall_arrayref(qq/select * from $table order by a/); + my $row = 0; + foreach (@$data) { + is($_->[0], $c1->[$row], "row $row p1 data"); + is($_->[1], $c2->[$row], "row $row p2 data"); + $row++; + } +} + +sub check_tuple_status +{ + my ($self, $tsts, $expected) = @_; + + note(Data::Dumper->Dump([$tsts], [qw(ArrayTupleStatus)])); + + BAIL_OUT('expected data must be specified') + if (!$expected || (ref($expected) ne 'ARRAY')); + + is(ref($tsts), 'ARRAY', 'tuple status is an array') or return; + if (!is(scalar(@$tsts), scalar(@$expected), 'status arrays same size')) { + diag(Dumper($tsts)); + diag(Dumper($expected)); + return; + } + + my $row = 0; + foreach my $s (@$expected) { + if (ref($s)) { + unless ($self->{_param_array_row_counts} == 2) { + is(ref($tsts->[$row]), 'ARRAY', 'array in array tuple status'); + is(scalar(@{$tsts->[$row]}), 3, '3 elements in array tuple status error'); + } + } else { + if ($tsts->[$row] == -1) { + pass("row $row tuple status unknown"); + } else { + is($tsts->[$row], $s, "row $row tuple status"); + } + } + $row++; + } + return; +} + +# insert might return 'mas' which means the caller said the test +# required Multiple Active Statements and the driver appeared to not +# support MAS. +# +# ref is a hash ref: +# error (0|1) whether we expect an error +# raise (0|1) means set RaiseError to this +# commit (0|1) do the inserts in a txn +# tuple arrayref of what we expect in the tuple status +# e.g., [1,1,1,1,[]] +# where the empty [] signifies we expect an error for this row +# where 1 signifies we the expect row count for this row +# affected - the total number of rows affected for insert/update +# +sub insert +{ + my ($self, $dbh, $sth, $ref) = @_; + + die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); + note("insert " . join(", ", map {"$_ = ". DBI::neat($ref->{$_})} keys %$ref )); + # DBD::Oracle supports MAS don't compensate for it not + if ($ref->{requires_mas} && $dbh->{Driver}->{Name} eq 'Oracle') { + delete $ref->{requires_mas}; + } + @captured_error = (); + + if ($ref->{raise}) { + $sth->{RaiseError} = 1; + } else { + $sth->{RaiseError} = 0; + } + + my (@tuple_status, $sts, $total_affected); + my $tuple_status_arg = {}; + $tuple_status_arg->{ArrayTupleStatus} = \@tuple_status unless $ref->{notuplestatus}; + + $sts = 999999; # to ensure it is overwritten + $total_affected = 999998; + if ($ref->{array_context}) { + eval { + if ($ref->{params}) { + ($sts, $total_affected) = + $sth->execute_array($tuple_status_arg, + @{$ref->{params}}); + } elsif ($ref->{fetch}) { + ($sts, $total_affected) = + $sth->execute_array( + {%{$tuple_status_arg}, + ArrayTupleFetch => $ref->{fetch}}); + } else { + ($sts, $total_affected) = + $sth->execute_array($tuple_status_arg); + } + }; + } else { + eval { + if ($ref->{params}) { + $sts = + $sth->execute_array($tuple_status_arg, + @{$ref->{params}}); + } else { + $sts = + $sth->execute_array($tuple_status_arg); + } + }; + } + if ($ref->{error} && $ref->{raise}) { + ok($@, 'error in execute_array eval'); + } else { + if ($ref->{requires_mas} && $@) { + diag("\nThis test died with $@"); + diag("It requires multiple active statement support in the driver and I cannot easily determine if your driver supports MAS. Ignoring the rest of this test."); + foreach (@tuple_status) { + if (ref($_)) { + diag(join(",", @$_)); + } + } + return 'mas'; + } + ok(!$@, 'no error in execute_array eval') or note($@); + } + $dbh->commit if $ref->{commit}; + + if (!$ref->{raise} || ($ref->{error} == 0)) { + if (exists($ref->{sts})) { + is($sts, $ref->{sts}, + "execute_array returned " . DBI::neat($sts) . " rows executed"); + } + if (exists($ref->{affected}) && $ref->{array_context}) { + is($total_affected, $ref->{affected}, + "total affected " . DBI::neat($total_affected)) + } + } + if ($ref->{raise}) { + if ($ref->{error}) { + ok(scalar(@captured_error) > 0, "error captured"); + } else { + is(scalar(@captured_error), 0, "no error captured"); + } + } + if ($ref->{sts}) { + is(scalar(@tuple_status), (($ref->{sts} eq '0E0') ? 0 : $ref->{sts}), + "$ref->{sts} rows in tuple_status"); + } + if ($ref->{tuple} && !exists($ref->{notuplestatus})) { + $self->check_tuple_status(\@tuple_status, $ref->{tuple}); + } + return; +} +# simple test on ensure execute_array with no errors: +# o checks returned status and affected is correct +# o checks ArrayTupleStatus is correct +# o checks no error is raised +# o checks rows are inserted +# o run twice with AutoCommit on/off +# o checks if less values are specified for one parameter the right number +# of rows are still inserted and NULLs are placed in the missing rows +# checks binding via bind_param_array and adding params to execute_array +# checks binding no parameters at all +sub simple +{ + my ($self, $dbh, $ref) = @_; + + note('simple tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); + + note(" all param arrays the same size"); + foreach my $commit (1,0) { + note(" Autocommit: $commit"); + clear_table($dbh, $table); + $dbh->begin_work if !$commit; + + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + $sth->bind_param_array(1, \@p1); + $sth->bind_param_array(2, \@p2); + $self->insert($dbh, $sth, + { commit => !$commit, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref}); + check_data($dbh, \@p1, \@p2); + } + + note " Not all param arrays the same size"; + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + + $sth->bind_param_array(1, \@p1); + $sth->bind_param_array(2, [qw(one)]); + $self->insert($dbh, $sth, {commit => 0, error => 0, + raise => 1, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref}); + check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); + + note " Not all param arrays the same size with bind on execute_array"; + clear_table($dbh, $table); + $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + + $self->insert($dbh, $sth, {commit => 0, error => 0, + raise => 1, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + params => [\@p1, [qw(one)]]}); + check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); + + note " no parameters"; + clear_table($dbh, $table); + $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + + $self->insert($dbh, $sth, {commit => 0, error => 0, + raise => 1, sts => '0E0', affected => 0, + tuple => [], %$ref, + params => [[], []]}); + check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); +} + +# error test to ensure correct behavior for execute_array when it errors: +# o execute_array of 5 inserts with last one failing +# o check it raises an error +# o check caught error is passed on from handler for eval +# o check returned status and affected rows +# o check ArrayTupleStatus +# o check valid inserts are inserted +# o execute_array of 5 inserts with 2nd last one failing +# o check it raises an error +# o check caught error is passed on from handler for eval +# o check returned status and affected rows +# o check ArrayTupleStatus +# o check valid inserts are inserted +sub error +{ + my ($self, $dbh, $ref) = @_; + + die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); + + note('error tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); + { + note("Last row in error"); + + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + my @pe1 = @p1; + $pe1[-1] = 1; + $sth->bind_param_array(1, \@pe1); + $sth->bind_param_array(2, \@p2); + $self->insert($dbh, $sth, {commit => 0, error => 1, sts => undef, + affected => undef, tuple => [1, 1, 1, 1, []], + %$ref}); + check_data($dbh, [@pe1[0..4]], [@p2[0..4]]); + } + + { + note("2nd last row in error"); + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + my @pe1 = @p1; + $pe1[-2] = 1; + $sth->bind_param_array(1, \@pe1); + $sth->bind_param_array(2, \@p2); + $self->insert($dbh, $sth, {commit => 0, error => 1, sts => undef, + affected => undef, tuple => [1, 1, 1, [], 1], %$ref}); + check_data($dbh, [@pe1[0..2],$pe1[4]], [@p2[0..2], $p2[4]]); + } +} + +sub fetch_sub +{ + note("fetch_sub $fetch_row"); + if ($fetch_row == @p1) { + note('returning undef'); + $fetch_row = 0; + return; + } + + return [$p1[$fetch_row], $p2[$fetch_row++]]; +} + +# test insertion via execute_array and ArrayTupleFetch +sub row_wise +{ + my ($self, $dbh, $ref) = @_; + + note("row_size via execute_for_fetch"); + + # Populate the first table via a ArrayTupleFetch which points to a sub + # returning rows + $fetch_row = 0; # reset fetch_sub to start with first row + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + fetch => \&fetch_sub}); + + # NOTE: The following test requires Multiple Active Statements. Although + # I can find ODBC drivers which do this it is not easy (if at all possible) + # to know if an ODBC driver can handle MAS or not. If it errors the + # driver probably does not have MAS so the error is ignored and a + # diagnostic is output. Exceptions are DBD::Oracle which definitely does + # support MAS. + # The data pushed into the first table is retrieved via ArrayTupleFetch + # from the second table by passing an executed select statement handle into + # execute_array. + note("row_size via select"); + clear_table($dbh, $table); + $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + my $sth2 = $dbh->prepare(qq/select * from $table2/); + # some drivers issue warnings when mas fails and this causes + # Test::NoWarnings to output something when we already found + # the test failed and captured it. + # e.g., some ODBC drivers cannot do MAS and this test is then expected to + # fail but we ignore the failure. Unfortunately in failing DBD::ODBC will + # issue a warning in addition to the fail + $sth->{Warn} = 0; + $sth->{Warn} = 0; + ok($sth2->execute, 'execute on second table') or diag($sth2->errstr); + ok($sth2->{Executed}, 'second statement is in executed state'); + my $res = $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + fetch => $sth2, requires_mas => 1}); + return if $res && $res eq 'mas'; # aborted , does not seem to support MAS + check_data($dbh, \@p1, \@p2); +} + +# test updates +# updates are special as you can update more rows than there are parameter rows +sub update +{ + my ($self, $dbh, $ref) = @_; + + note("update test"); + + # populate the first table with the default 5 rows using a ArrayTupleFetch + $fetch_row = 0; + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + fetch => \&fetch_sub}); + check_data($dbh, \@p1, \@p2); + + # update all rows b column to 'fred' checking rows affected is 5 + $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); + # NOTE, this also checks you can pass a scalar to bind_param_array + $sth->bind_param_array(1, 'fred'); + $sth->bind_param_array(2, \@p1); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref}); + check_data($dbh, \@p1, [qw(fred fred fred fred fred)]); + + # update 4 rows column b to 'dave' checking rows affected is 4 + $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); + # NOTE, this also checks you can pass a scalar to bind_param_array + $sth->bind_param_array(1, 'dave'); + my @pe1 = @p1; + $pe1[-1] = 10; # non-existant row + $sth->bind_param_array(2, \@pe1); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 4, + tuple => [1, 1, 1, 1, '0E0'], %$ref}); + check_data($dbh, \@p1, [qw(dave dave dave dave fred)]); + + # now change all rows b column to 'pete' - this will change all 5 + # rows even though we have 2 rows of parameters so we can see if + # the rows affected is > parameter rows + $sth = $dbh->prepare(qq/update $table set b = ? where b like ?/); + # NOTE, this also checks you can pass a scalar to bind_param_array + $sth->bind_param_array(1, 'pete'); + $sth->bind_param_array(2, ['dave%', 'fred%']); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 2, affected => 5, + tuple => [4, 1], %$ref}); + check_data($dbh, \@p1, [qw(pete pete pete pete pete)]); +} + +sub enable_mars { + my $dbh = shift; + + # this test uses multiple active statements + # if we recognise the driver and it supports MAS enable it + my $driver_name = $dbh->get_info(6) || ''; + if (($driver_name eq 'libessqlsrv.so') || + ($driver_name =~ /libsqlncli/)) { + my $dsn = $ENV{DBI_DSN}; + if ($dsn !~ /^dbi:ODBC:DSN=/ && $dsn !~ /DRIVER=/i) { + my @a = split(q/:/, $ENV{DBI_DSN}); + $dsn = join(q/:/, @a[0..($#a - 1)]) . ":DSN=" . $a[-1]; + } + $dsn .= ";MARS_Connection=yes"; + $dbh->disconnect; + $dbh = DBI->connect($dsn, $ENV{DBI_USER}, $ENV{DBI_PASS}); + } + return $dbh; +} + +1; From 0596be0cd6d280736785b4a78d88f9fd46731668 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 30 Oct 2012 13:12:45 +0000 Subject: [PATCH 331/637] rt 80487 - skip xmltype test when oracle < 9 fix newly introduced issue in 26exe_array.t - forget to update INC to pickup new pm git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15461 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ t/26exe_array.t | 2 ++ t/32xmltype.t | 8 +++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 0e53c81d..0c17753c 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,9 @@ NEXT_VERSION resulted in an undefined warning. Thanks to Steffen Goeldner for RT and patches. + - Fix RT80487. Skip XMLType tests if Oracle less than V9. Thanks to + Steffen Goeldner. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a diff --git a/t/26exe_array.t b/t/26exe_array.t index 8a4519fe..1b4f0e66 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -9,6 +9,8 @@ use strict; use Data::Dumper; require 'nchar_test_lib.pl'; +use lib './t'; + $| = 1; my $has_test_nowarnings = 1; diff --git a/t/32xmltype.t b/t/32xmltype.t index 98544b97..7f413fb3 100644 --- a/t/32xmltype.t +++ b/t/32xmltype.t @@ -13,7 +13,7 @@ require 'nchar_test_lib.pl'; ## By John Scoles, The Pythian Group ## ---------------------------------------------------------------------------- ## Just a few checks to see if one can insert small and large xml files -## Nothing fancy. +## Nothing fancy. ## ---------------------------------------------------------------------------- # create a database handle @@ -21,11 +21,13 @@ my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, +eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, AutoCommit=>1, PrintError => 0 })}; if ($dbh) { + plan skip_all => "XMLTYPE new in Oracle 9" + if $dbh->func('ora_server_version')->[0] < 9; plan tests => 3; } else { plan skip_all => "Unable to connect to Oracle" @@ -65,7 +67,7 @@ $large_xml=$large_xml.""; $stmt = "INSERT INTO ".$table." VALUES (1,?)"; $sth =$dbh-> prepare($stmt); - + $sth-> bind_param(1, $small_xml, { ora_type => ORA_XMLTYPE }); ok ($sth->execute(), '... execute for small XML return true'); From 93cf2080f0feae1325168bee9032afdcdc12fd44 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 30 Oct 2012 13:12:45 +0000 Subject: [PATCH 332/637] rt 80487 - skip xmltype test when oracle < 9 fix newly introduced issue in 26exe_array.t - forget to update INC to pickup new pm git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15461 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ t/26exe_array.t | 2 ++ t/32xmltype.t | 8 +++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 0e53c81d..0c17753c 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,9 @@ NEXT_VERSION resulted in an undefined warning. Thanks to Steffen Goeldner for RT and patches. + - Fix RT80487. Skip XMLType tests if Oracle less than V9. Thanks to + Steffen Goeldner. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a diff --git a/t/26exe_array.t b/t/26exe_array.t index 8a4519fe..1b4f0e66 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -9,6 +9,8 @@ use strict; use Data::Dumper; require 'nchar_test_lib.pl'; +use lib './t'; + $| = 1; my $has_test_nowarnings = 1; diff --git a/t/32xmltype.t b/t/32xmltype.t index 98544b97..7f413fb3 100644 --- a/t/32xmltype.t +++ b/t/32xmltype.t @@ -13,7 +13,7 @@ require 'nchar_test_lib.pl'; ## By John Scoles, The Pythian Group ## ---------------------------------------------------------------------------- ## Just a few checks to see if one can insert small and large xml files -## Nothing fancy. +## Nothing fancy. ## ---------------------------------------------------------------------------- # create a database handle @@ -21,11 +21,13 @@ my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, +eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, AutoCommit=>1, PrintError => 0 })}; if ($dbh) { + plan skip_all => "XMLTYPE new in Oracle 9" + if $dbh->func('ora_server_version')->[0] < 9; plan tests => 3; } else { plan skip_all => "Unable to connect to Oracle" @@ -65,7 +67,7 @@ $large_xml=$large_xml.""; $stmt = "INSERT INTO ".$table." VALUES (1,?)"; $sth =$dbh-> prepare($stmt); - + $sth-> bind_param(1, $small_xml, { ora_type => ORA_XMLTYPE }); ok ($sth->execute(), '... execute for small XML return true'); From a3996202b734a16b411257e33d1ac0d0679df0c8 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 30 Oct 2012 13:17:25 +0000 Subject: [PATCH 333/637] Improved 31lob_extended.t which supports Oracle 8. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15462 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ t/31lob_extended.t | 40 ++++++++++++---------------------------- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/Changes b/Changes index 0c17753c..8bce3b8b 100644 --- a/Changes +++ b/Changes @@ -16,6 +16,10 @@ NEXT_VERSION - Fix RT80487. Skip XMLType tests if Oracle less than V9. Thanks to Steffen Goeldner. + - Fix RT80486 for 31lob_extended.t. In old old Oracle8, + SYS_REFCURSOR is not defined. Instead of CREATE/DROP PROCEDURE, + use anonymous block. Thanks to Steffen Goeldner. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a diff --git a/t/31lob_extended.t b/t/31lob_extended.t index 3c084065..f507fd24 100644 --- a/t/31lob_extended.t +++ b/t/31lob_extended.t @@ -30,7 +30,7 @@ my $dbh = DBI->connect($dsn, $dbuser, '',{ }); if ($dbh) { - plan tests => 31; + plan tests => 30; $dbh->{LongReadLen} = 7000; } else { plan skip_all => "Unable to connect to Oracle"; @@ -39,6 +39,14 @@ if ($dbh) { my ($table, $data0, $data1) = setup_test($dbh); +my $PLSQL = <<"PLSQL"; +BEGIN + OPEN ? FOR SELECT x FROM $table; +END; +PLSQL + +$dbh->{RaiseError} = 1; + # # bug in DBD::Oracle 1.21 where if ora_auto_lobs is not set and we attempt to # fetch from a table containing lobs which has more than one row @@ -49,9 +57,7 @@ my ($table, $data0, $data1) = setup_test($dbh); my ($sth1, $ev); - eval {$sth1 = $dbh->prepare( - q/begin p_DBD_Oracle_drop_me(?); end;/, {ora_auto_lob => 0}); - }; + eval {$sth1 = $dbh->prepare($PLSQL, {ora_auto_lob => 0});}; ok(!$@, "$testname - prepare call proc"); my $sth2; ok($sth1->bind_param_inout(1, \$sth2, 500, {ora_type => ORA_RSET}), @@ -80,10 +86,8 @@ my ($table, $data0, $data1) = setup_test($dbh); my ($sth1, $ev, $lob); - eval {$sth1 = $dbh->prepare( - # ora_auto_lobs is supposed to default to set - q/begin p_DBD_Oracle_drop_me(?); end;/); - }; + # ora_auto_lobs is supposed to default to set + eval {$sth1 = $dbh->prepare($PLSQL);}; ok(!$@, "$testname prepare call proc"); my $sth2; ok($sth1->bind_param_inout(1, \$sth2, 500, {ora_type => ORA_RSET}), @@ -153,20 +157,6 @@ sub setup_test BAIL_OUT("Failed to insert test data into $table - $@") if $@; ok(!$ev, "created test data"); - my $createproc = << "EOT"; -CREATE OR REPLACE PROCEDURE p_DBD_Oracle_drop_me(pc OUT SYS_REFCURSOR) AS -l_cursor SYS_REFCURSOR; -BEGIN -OPEN l_cursor FOR - SELECT x from $table; -pc := l_cursor; -END; -EOT - - eval {$h->do($createproc);}; - BAIL_OUT("Failed to create test procedure - $@") if $@; - ok(!$ev, "created test procedure"); - return ($table, $data0, $data1); } @@ -176,12 +166,6 @@ END { local $dbh->{PrintError} = 0; local $dbh->{RaiseError} = 1; - eval {$dbh->do(q/drop procedure p_DBD_Oracle_drop_me/);}; - if ($@) { - diag("procedure p_DBD_Oracle_drop_me possibly not dropped" . - "- check - $@\n") if $dbh->err ne '4043'; - } - eval {drop_table($dbh);}; if ($@) { diag("table $table possibly not dropped - check - $@\n") From 480e068f260ec8c70d90155e5b9c110ea957e0c1 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 30 Oct 2012 13:17:25 +0000 Subject: [PATCH 334/637] Improved 31lob_extended.t which supports Oracle 8. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15462 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ t/31lob_extended.t | 40 ++++++++++++---------------------------- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/Changes b/Changes index 0c17753c..8bce3b8b 100644 --- a/Changes +++ b/Changes @@ -16,6 +16,10 @@ NEXT_VERSION - Fix RT80487. Skip XMLType tests if Oracle less than V9. Thanks to Steffen Goeldner. + - Fix RT80486 for 31lob_extended.t. In old old Oracle8, + SYS_REFCURSOR is not defined. Instead of CREATE/DROP PROCEDURE, + use anonymous block. Thanks to Steffen Goeldner. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a diff --git a/t/31lob_extended.t b/t/31lob_extended.t index 3c084065..f507fd24 100644 --- a/t/31lob_extended.t +++ b/t/31lob_extended.t @@ -30,7 +30,7 @@ my $dbh = DBI->connect($dsn, $dbuser, '',{ }); if ($dbh) { - plan tests => 31; + plan tests => 30; $dbh->{LongReadLen} = 7000; } else { plan skip_all => "Unable to connect to Oracle"; @@ -39,6 +39,14 @@ if ($dbh) { my ($table, $data0, $data1) = setup_test($dbh); +my $PLSQL = <<"PLSQL"; +BEGIN + OPEN ? FOR SELECT x FROM $table; +END; +PLSQL + +$dbh->{RaiseError} = 1; + # # bug in DBD::Oracle 1.21 where if ora_auto_lobs is not set and we attempt to # fetch from a table containing lobs which has more than one row @@ -49,9 +57,7 @@ my ($table, $data0, $data1) = setup_test($dbh); my ($sth1, $ev); - eval {$sth1 = $dbh->prepare( - q/begin p_DBD_Oracle_drop_me(?); end;/, {ora_auto_lob => 0}); - }; + eval {$sth1 = $dbh->prepare($PLSQL, {ora_auto_lob => 0});}; ok(!$@, "$testname - prepare call proc"); my $sth2; ok($sth1->bind_param_inout(1, \$sth2, 500, {ora_type => ORA_RSET}), @@ -80,10 +86,8 @@ my ($table, $data0, $data1) = setup_test($dbh); my ($sth1, $ev, $lob); - eval {$sth1 = $dbh->prepare( - # ora_auto_lobs is supposed to default to set - q/begin p_DBD_Oracle_drop_me(?); end;/); - }; + # ora_auto_lobs is supposed to default to set + eval {$sth1 = $dbh->prepare($PLSQL);}; ok(!$@, "$testname prepare call proc"); my $sth2; ok($sth1->bind_param_inout(1, \$sth2, 500, {ora_type => ORA_RSET}), @@ -153,20 +157,6 @@ sub setup_test BAIL_OUT("Failed to insert test data into $table - $@") if $@; ok(!$ev, "created test data"); - my $createproc = << "EOT"; -CREATE OR REPLACE PROCEDURE p_DBD_Oracle_drop_me(pc OUT SYS_REFCURSOR) AS -l_cursor SYS_REFCURSOR; -BEGIN -OPEN l_cursor FOR - SELECT x from $table; -pc := l_cursor; -END; -EOT - - eval {$h->do($createproc);}; - BAIL_OUT("Failed to create test procedure - $@") if $@; - ok(!$ev, "created test procedure"); - return ($table, $data0, $data1); } @@ -176,12 +166,6 @@ END { local $dbh->{PrintError} = 0; local $dbh->{RaiseError} = 1; - eval {$dbh->do(q/drop procedure p_DBD_Oracle_drop_me/);}; - if ($@) { - diag("procedure p_DBD_Oracle_drop_me possibly not dropped" . - "- check - $@\n") if $dbh->err ne '4043'; - } - eval {drop_table($dbh);}; if ($@) { diag("table $table possibly not dropped - check - $@\n") From cb896b7d92cbe94c3558bbb5d88b45606e9b144f Mon Sep 17 00:00:00 2001 From: byterock Date: Tue, 30 Oct 2012 23:50:07 +0000 Subject: [PATCH 335/637] fix memory leak in execute array (John Scoles, Pierre-Alain Blanc) git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15463 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ dbdimp.c | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 8bce3b8b..a01954a8 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,8 @@ Revision history for DBD::Oracle NEXT_VERSION [BUG FIXES] + + - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails can contain the wrong error count. Thanks to Steffen Goeldner for diff --git a/dbdimp.c b/dbdimp.c index 91099bbd..a69aa4ea 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3684,15 +3684,16 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er STRLEN len; int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0; int *utf8_flgs; - tuples_utf8_av=newAV(); + tuples_utf8_av = newAV(); + sv_2mortal((SV*)tuples_utf8_av); if (debug >= 2 || dbd_verbose >= 3 ) PerlIO_printf( - DBIc_LOGPIO(imp_sth), - " ora_st_execute_array %s count=%d (%s %s %s)...\n", - oci_stmt_type_name(imp_sth->stmt_type), exe_count, - neatsvpv(tuples,0), neatsvpv(tuples_status,0), - neatsvpv(columns, 0)); + DBIc_LOGPIO(imp_sth), + " ora_st_execute_array %s count=%d (%s %s %s)...\n", + oci_stmt_type_name(imp_sth->stmt_type), exe_count, + neatsvpv(tuples,0), neatsvpv(tuples_status,0), + neatsvpv(columns, 0)); if (is_select) { croak("ora_st_execute_array(): SELECT statement not supported " From 00166a4e26f5e94ddf6a558fe37ddf96c4cacd51 Mon Sep 17 00:00:00 2001 From: byterock Date: Tue, 30 Oct 2012 23:50:07 +0000 Subject: [PATCH 336/637] fix memory leak in execute array (John Scoles, Pierre-Alain Blanc) git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15463 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ dbdimp.c | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 8bce3b8b..a01954a8 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,8 @@ Revision history for DBD::Oracle NEXT_VERSION [BUG FIXES] + + - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails can contain the wrong error count. Thanks to Steffen Goeldner for diff --git a/dbdimp.c b/dbdimp.c index 91099bbd..a69aa4ea 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3684,15 +3684,16 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er STRLEN len; int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0; int *utf8_flgs; - tuples_utf8_av=newAV(); + tuples_utf8_av = newAV(); + sv_2mortal((SV*)tuples_utf8_av); if (debug >= 2 || dbd_verbose >= 3 ) PerlIO_printf( - DBIc_LOGPIO(imp_sth), - " ora_st_execute_array %s count=%d (%s %s %s)...\n", - oci_stmt_type_name(imp_sth->stmt_type), exe_count, - neatsvpv(tuples,0), neatsvpv(tuples_status,0), - neatsvpv(columns, 0)); + DBIc_LOGPIO(imp_sth), + " ora_st_execute_array %s count=%d (%s %s %s)...\n", + oci_stmt_type_name(imp_sth->stmt_type), exe_count, + neatsvpv(tuples,0), neatsvpv(tuples_status,0), + neatsvpv(columns, 0)); if (is_select) { croak("ora_st_execute_array(): SELECT statement not supported " From 8afe961008739dcc215eae4a81ce480082e9af11 Mon Sep 17 00:00:00 2001 From: byterock Date: Wed, 31 Oct 2012 00:09:56 +0000 Subject: [PATCH 337/637] simple code clean up, replacing 3 uses of safemalloc with Newz git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15464 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ dbdimp.c | 10 +++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index a01954a8..c52fed89 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,8 @@ NEXT_VERSION [BUG FIXES] + - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) + - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails diff --git a/dbdimp.c b/dbdimp.c index a69aa4ea..1eb8a36d 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1411,7 +1411,7 @@ phs_t *phs; /* allocate room for copy of statement with spare capacity */ /* for editing '?' or ':1' into ':p1' so we can use obndrv. */ /* XXX should use SV and append to it */ - imp_sth->statement = (char*)safemalloc(strlen(statement) * 10); + Newz(0,imp_sth->statement,strlen(statement) * 10,char); /* initialise phs ready to be cloned per placeholder */ memset(&phs_tpl, 0, sizeof(phs_tpl)); @@ -3746,10 +3746,8 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er Still ensures proper OCIBindByName*/ param_count=DBIc_NUM_PARAMS(imp_sth); - phs = safemalloc(param_count*sizeof(*phs)); - utf8_flgs = safemalloc(param_count*sizeof(int)); - memset(phs, 0, param_count*sizeof(*phs)); - memset(utf8_flgs, 0, param_count*sizeof(int)); + Newz(0,phs,param_count*sizeof(*phs),phs_t *); + Newz(0,utf8_flgs,param_count*sizeof(int),int); for(j = 0; (unsigned int) j < exe_count; j++) { /* Fill in 'unknown' exe count in every element (know not how to get @@ -3838,8 +3836,6 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er } } } - Safefree(phs); - Safefree(utf8_flgs); /* Store array of bind typles, for use in OCIBindDynamic() callback. */ imp_sth->bind_tuples = tuples_av; imp_sth->rowwise = (columns_av == NULL); From c8a7c2ddecb65aef23485f5f9c9f6f0fcdf4f5cc Mon Sep 17 00:00:00 2001 From: byterock Date: Wed, 31 Oct 2012 00:09:56 +0000 Subject: [PATCH 338/637] simple code clean up, replacing 3 uses of safemalloc with Newz git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15464 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ dbdimp.c | 10 +++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index a01954a8..c52fed89 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,8 @@ NEXT_VERSION [BUG FIXES] + - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) + - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails diff --git a/dbdimp.c b/dbdimp.c index a69aa4ea..1eb8a36d 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1411,7 +1411,7 @@ phs_t *phs; /* allocate room for copy of statement with spare capacity */ /* for editing '?' or ':1' into ':p1' so we can use obndrv. */ /* XXX should use SV and append to it */ - imp_sth->statement = (char*)safemalloc(strlen(statement) * 10); + Newz(0,imp_sth->statement,strlen(statement) * 10,char); /* initialise phs ready to be cloned per placeholder */ memset(&phs_tpl, 0, sizeof(phs_tpl)); @@ -3746,10 +3746,8 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er Still ensures proper OCIBindByName*/ param_count=DBIc_NUM_PARAMS(imp_sth); - phs = safemalloc(param_count*sizeof(*phs)); - utf8_flgs = safemalloc(param_count*sizeof(int)); - memset(phs, 0, param_count*sizeof(*phs)); - memset(utf8_flgs, 0, param_count*sizeof(int)); + Newz(0,phs,param_count*sizeof(*phs),phs_t *); + Newz(0,utf8_flgs,param_count*sizeof(int),int); for(j = 0; (unsigned int) j < exe_count; j++) { /* Fill in 'unknown' exe count in every element (know not how to get @@ -3838,8 +3836,6 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er } } } - Safefree(phs); - Safefree(utf8_flgs); /* Store array of bind typles, for use in OCIBindDynamic() callback. */ imp_sth->bind_tuples = tuples_av; imp_sth->rowwise = (columns_av == NULL); From 0a1b2b878344c5f175b0093aba3bd88312ccaf91 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 31 Oct 2012 09:04:53 +0000 Subject: [PATCH 339/637] 39attr.t could fail if using oracle client > 11 but not >= 11.2 minor code formatting changes in Oracle.pm document ora_server_version remove empty h1 in Oracle.pm git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15465 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 12 +++++++++--- lib/DBD/Oracle.pm | 45 ++++++++++++++++++++++++++------------------- t/39attr.t | 34 ++++++++++++++++++++++------------ 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/Changes b/Changes index c52fed89..6b9c6297 100644 --- a/Changes +++ b/Changes @@ -3,9 +3,7 @@ Revision history for DBD::Oracle NEXT_VERSION [BUG FIXES] - - - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) - + - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails @@ -24,6 +22,11 @@ NEXT_VERSION SYS_REFCURSOR is not defined. Instead of CREATE/DROP PROCEDURE, use anonymous block. Thanks to Steffen Goeldner. + - Fix bug in 39attr.t which could fail if using an Oracle Client > + 11 but not >= 11.2 (Martin J. Evans) + + - ora_server_version was not documented. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a @@ -32,6 +35,9 @@ NEXT_VERSION above). To make keeping them in synch easier I've modularised the tests. Hence new ExecuteArray.pm. (Martin J. Evans) + - simple code clean up, replacing 3 uses of safemalloc with Newz + (John Scoles) + 1.52 2012-10-19 diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index adba4527..9700b04b 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -982,30 +982,29 @@ SQL } sub dbms_msgpipe_ack { - my $dbh = shift; - my $msg = shift; - my $sth = $dbh->prepare_cached(q{ - begin dbms_msgpipe.acknowledge(:returnpipe, :errormsg, :param); end; - }) or return; - $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); - $sth->bind_param_inout(":proc", \$msg->[1], 30); - $sth->bind_param_inout(":param", \$msg->[2], 4000); - $sth->execute or return undef; - return 1; + my $dbh = shift; + my $msg = shift; + my $sth = $dbh->prepare_cached(q{ + begin dbms_msgpipe.acknowledge(:returnpipe, :errormsg, :param); end;}) or return; + $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); + $sth->bind_param_inout(":proc", \$msg->[1], 30); + $sth->bind_param_inout(":param", \$msg->[2], 4000); + $sth->execute or return undef; + return 1; } sub ora_server_version { - my $dbh = shift; - return $dbh->{ora_server_version} if defined $dbh->{ora_server_version}; - my $banner = $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%'); + my $dbh = shift; + return $dbh->{ora_server_version} if defined $dbh->{ora_server_version}; + my $banner = $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%'); SELECT banner FROM v$version WHERE banner LIKE ? OR banner LIKE ? SQL - if (defined $banner) { - my @version = $banner =~ /(?:^|\s)(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\s|$)/; - $dbh->{ora_server_version} = \@version if @version; - } + if (defined $banner) { + my @version = $banner =~ /(?:^|\s)(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\s|$)/; + $dbh->{ora_server_version} = \@version if @version; + } } sub ora_nls_parameters { @@ -2196,6 +2195,16 @@ Returns a hash reference containing the current NLS parameters, as given by the v$nls_parameters view. The values fetched are cached between calls. To cause the latest values to be fetched, pass a true value to the function. +=head1 ORACLE-SPECIFIC DATABASE FUNCTIONS + +=head2 B + + $versions = $dbh->func('ora_server_version'); + +Returns an array reference of server version strings e.g., + + [11,2,0,2,0] + =head1 DATABASE HANDLE METHODS =head2 B @@ -5333,8 +5342,6 @@ you may not be aware of. A git mirror of the subversion is also available at `https://github.com/yanick/DBD-Oracle`. -=head1 Oracle Related Links - =head1 WHICH VERSION OF DBD::ORACLE IS FOR ME? From version 1.25 onwards DBD::Oracle only support Oracle clients diff --git a/t/39attr.t b/t/39attr.t index a352977e..12a5a669 100755 --- a/t/39attr.t +++ b/t/39attr.t @@ -33,23 +33,33 @@ sub do_it { my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; + diag("Oracle version: " . join(".", @{$dbh->func('ora_server_version')})); + diag("client version: " . ORA_OCI()); + SKIP: { my @attrs = (qw(ora_module_name - ora_driver_name - ora_client_info - ora_client_identifier - ora_action)); - skip('Oracle OCI too old', 1 + @attrs) if ORA_OCI() < 11; - - like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); - foreach my $attr (qw(ora_module_name - ora_driver_name - ora_client_info - ora_client_identifier - ora_action)) { + ora_client_info + ora_client_identifier + ora_action)); + my @attrs112 = (qw(ora_driver_name)); + + skip('Oracle OCI too old', 1 + @attrs + @attrs112) if ORA_OCI() < 11; + + foreach my $attr (@attrs) { $dbh->{$attr} = 'fred'; is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); } + + SKIP: { + skip 'Oracle OCI too old', 1 + @attrs112 if ORA_OCI() < 11.2; + + like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); + + foreach my $attr (@attrs) { + $dbh->{$attr} = 'fred'; + is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); + } + } }; foreach my $attr (qw(ora_oci_success_warn From 0ff47f9371d89c6b3bf1b803933f1bfb705008b5 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 31 Oct 2012 09:04:53 +0000 Subject: [PATCH 340/637] 39attr.t could fail if using oracle client > 11 but not >= 11.2 minor code formatting changes in Oracle.pm document ora_server_version remove empty h1 in Oracle.pm git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15465 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 12 +++++++++--- lib/DBD/Oracle.pm | 45 ++++++++++++++++++++++++++------------------- t/39attr.t | 34 ++++++++++++++++++++++------------ 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/Changes b/Changes index c52fed89..6b9c6297 100644 --- a/Changes +++ b/Changes @@ -3,9 +3,7 @@ Revision history for DBD::Oracle NEXT_VERSION [BUG FIXES] - - - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) - + - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails @@ -24,6 +22,11 @@ NEXT_VERSION SYS_REFCURSOR is not defined. Instead of CREATE/DROP PROCEDURE, use anonymous block. Thanks to Steffen Goeldner. + - Fix bug in 39attr.t which could fail if using an Oracle Client > + 11 but not >= 11.2 (Martin J. Evans) + + - ora_server_version was not documented. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a @@ -32,6 +35,9 @@ NEXT_VERSION above). To make keeping them in synch easier I've modularised the tests. Hence new ExecuteArray.pm. (Martin J. Evans) + - simple code clean up, replacing 3 uses of safemalloc with Newz + (John Scoles) + 1.52 2012-10-19 diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index adba4527..9700b04b 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -982,30 +982,29 @@ SQL } sub dbms_msgpipe_ack { - my $dbh = shift; - my $msg = shift; - my $sth = $dbh->prepare_cached(q{ - begin dbms_msgpipe.acknowledge(:returnpipe, :errormsg, :param); end; - }) or return; - $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); - $sth->bind_param_inout(":proc", \$msg->[1], 30); - $sth->bind_param_inout(":param", \$msg->[2], 4000); - $sth->execute or return undef; - return 1; + my $dbh = shift; + my $msg = shift; + my $sth = $dbh->prepare_cached(q{ + begin dbms_msgpipe.acknowledge(:returnpipe, :errormsg, :param); end;}) or return; + $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); + $sth->bind_param_inout(":proc", \$msg->[1], 30); + $sth->bind_param_inout(":param", \$msg->[2], 4000); + $sth->execute or return undef; + return 1; } sub ora_server_version { - my $dbh = shift; - return $dbh->{ora_server_version} if defined $dbh->{ora_server_version}; - my $banner = $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%'); + my $dbh = shift; + return $dbh->{ora_server_version} if defined $dbh->{ora_server_version}; + my $banner = $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%'); SELECT banner FROM v$version WHERE banner LIKE ? OR banner LIKE ? SQL - if (defined $banner) { - my @version = $banner =~ /(?:^|\s)(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\s|$)/; - $dbh->{ora_server_version} = \@version if @version; - } + if (defined $banner) { + my @version = $banner =~ /(?:^|\s)(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\s|$)/; + $dbh->{ora_server_version} = \@version if @version; + } } sub ora_nls_parameters { @@ -2196,6 +2195,16 @@ Returns a hash reference containing the current NLS parameters, as given by the v$nls_parameters view. The values fetched are cached between calls. To cause the latest values to be fetched, pass a true value to the function. +=head1 ORACLE-SPECIFIC DATABASE FUNCTIONS + +=head2 B + + $versions = $dbh->func('ora_server_version'); + +Returns an array reference of server version strings e.g., + + [11,2,0,2,0] + =head1 DATABASE HANDLE METHODS =head2 B @@ -5333,8 +5342,6 @@ you may not be aware of. A git mirror of the subversion is also available at `https://github.com/yanick/DBD-Oracle`. -=head1 Oracle Related Links - =head1 WHICH VERSION OF DBD::ORACLE IS FOR ME? From version 1.25 onwards DBD::Oracle only support Oracle clients diff --git a/t/39attr.t b/t/39attr.t index a352977e..12a5a669 100755 --- a/t/39attr.t +++ b/t/39attr.t @@ -33,23 +33,33 @@ sub do_it { my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; + diag("Oracle version: " . join(".", @{$dbh->func('ora_server_version')})); + diag("client version: " . ORA_OCI()); + SKIP: { my @attrs = (qw(ora_module_name - ora_driver_name - ora_client_info - ora_client_identifier - ora_action)); - skip('Oracle OCI too old', 1 + @attrs) if ORA_OCI() < 11; - - like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); - foreach my $attr (qw(ora_module_name - ora_driver_name - ora_client_info - ora_client_identifier - ora_action)) { + ora_client_info + ora_client_identifier + ora_action)); + my @attrs112 = (qw(ora_driver_name)); + + skip('Oracle OCI too old', 1 + @attrs + @attrs112) if ORA_OCI() < 11; + + foreach my $attr (@attrs) { $dbh->{$attr} = 'fred'; is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); } + + SKIP: { + skip 'Oracle OCI too old', 1 + @attrs112 if ORA_OCI() < 11.2; + + like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); + + foreach my $attr (@attrs) { + $dbh->{$attr} = 'fred'; + is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); + } + } }; foreach my $attr (qw(ora_oci_success_warn From 6d87b4de60b35a2e8c270ac222338efe1b0b5a52 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 23 Oct 2012 12:32:20 +0000 Subject: [PATCH 341/637] Apply patch for RT80349 from Steffen. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15449 50811bd7-b8ce-0310-adc1-d9db26280581 Conflicts: Changes --- Changes | 8 +++++++- lib/DBD/Oracle.pm | 8 +++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index c5e82ba7..ef35ec0d 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,12 @@ Revision history for DBD::Oracle -{{$NEXT}} +NEXT_VERSION + + [BUG FIXES] + + - Fix RT80349 - The error message in execute_for_fetch when a row fails + can contain the wrong error count. Thanks to Steffen Goeldner for + RT and patch. 1.52 2012-10-19 diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 6aa04cea..629a80a3 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1070,7 +1070,7 @@ SQL sub execute_for_fetch { my ($sth, $fetch_tuple_sub, $tuple_status) = @_; my $row_count = 0; - my $err_count = 0; + my $err_total = 0; my $tuple_count="0E0"; my $tuple_batch_status; my $dbh = $sth->{Database}; @@ -1090,6 +1090,7 @@ SQL } last unless @tuple_batch; + my $err_count = 0; my $res = ora_execute_array($sth, \@tuple_batch, scalar(@tuple_batch), @@ -1102,6 +1103,7 @@ SQL $row_count = undef; } + $err_total += $err_count; $tuple_count+=@$tuple_batch_status; push @$tuple_status, @$tuple_batch_status if defined($tuple_status); @@ -1110,8 +1112,8 @@ SQL } #error check here - return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_count errors") - if $err_count; + return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_total errors") + if $err_total; return wantarray ? ($tuple_count, defined $row_count ? $row_count : undef) From ad0c98ba4160064052dfe990e67dbdccc62c2a3f Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 26 Oct 2012 12:16:05 +0000 Subject: [PATCH 342/637] Improve tests in ExecuteArray (espcially to ensure things work when ArrayTupleStatus is not specified) Rewrote 26exe_array.t to be more like the one in DBD::ODBC (from where it came originally) and copied new ExecuteArray module. Fixes from Stefen for execute_array when no ArrayTupleStatus git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15454 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 14 ++ MANIFEST | 1 + dbdimp.c | 315 +++++++++++++------------- lib/DBD/Oracle.pm | 3 +- oci8.c | 558 +++++++++++++++++++++++----------------------- t/26exe_array.t | 479 ++++----------------------------------- t/ExecuteArray.pm | 519 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1013 insertions(+), 876 deletions(-) create mode 100644 t/ExecuteArray.pm diff --git a/Changes b/Changes index ef35ec0d..0e53c81d 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,20 @@ NEXT_VERSION can contain the wrong error count. Thanks to Steffen Goeldner for RT and patch. + - Fix RT80375 - no exception when execute_for_fetch fails and + ArrayTupleStatus is not specified. Also the tuple count calculation + resulted in an undefined warning. Thanks to Steffen Goeldner for + RT and patches. + + [MISCELLANEOUS] + + - The original 26exe_array test was replaced some time ago with a + copy of the one from DBD::ODBC. Since then I've fixed issues in + the DBD::ODBC one and added more tests (like tests for some RTs + above). To make keeping them in synch easier I've modularised the + tests. Hence new ExecuteArray.pm. (Martin J. Evans) + + 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/MANIFEST b/MANIFEST index 0061de6e..d1564f89 100644 --- a/MANIFEST +++ b/MANIFEST @@ -67,6 +67,7 @@ t/23wide_db_al32utf8.t t/24implicit_utf8.t t/25plsql.t t/26exe_array.t +t/ExecuteArray.pm t/28array_bind.t t/30long.t t/31lob.t diff --git a/dbdimp.c b/dbdimp.c index eded2ab3..91099bbd 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2070,19 +2070,19 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /*int flag_data_is_utf8=0;*/ if( ( ! SvROK(phs->sv) ) || (SvTYPE(SvRV(phs->sv))!=SVt_PVAV) ) { /* Allow only array binds */ - croak("dbd_rebind_ph_number_table(): bad bind variable. ARRAY reference required, but got %s for '%s'.", - neatsvpv(phs->sv,0), phs->name); + croak("dbd_rebind_ph_number_table(): bad bind variable. ARRAY reference required, but got %s for '%s'.", + neatsvpv(phs->sv,0), phs->name); } /* Default bind type for number table is double. */ if( ! phs->ora_internal_type ){ - phs->ora_internal_type=SQLT_FLT; + phs->ora_internal_type=SQLT_FLT; }else{ - if( (phs->ora_internal_type != SQLT_FLT) && - (phs->ora_internal_type != SQLT_INT) ){ - croak("dbd_rebind_ph_number_table(): Specified internal bind type %d unsupported. " - "SYS.DBMS_SQL.NUMBER_TABLE can be bound only to SQLT_FLT or SQLT_INT datatypes.", - phs->ora_internal_type); - } + if( (phs->ora_internal_type != SQLT_FLT) && + (phs->ora_internal_type != SQLT_INT) ){ + croak("dbd_rebind_ph_number_table(): Specified internal bind type %d unsupported. " + "SYS.DBMS_SQL.NUMBER_TABLE can be bound only to SQLT_FLT or SQLT_INT datatypes.", + phs->ora_internal_type); + } } arr=(AV*)(SvRV(phs->sv)); @@ -2112,11 +2112,11 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { * maxlen(double) = sizeof(double); */ switch( phs->ora_internal_type ){ - case SQLT_INT: + case SQLT_INT: phs->maxlen=sizeof(int); break; - case SQLT_FLT: - default: + case SQLT_FLT: + default: phs->maxlen=sizeof(double); } if (trace_level >= 2 || dbd_verbose >= 3 ){ @@ -2131,7 +2131,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { phs->array_numstruct=1; } if( phs->ora_maxarray_numentries== 0 ){ - /* Zero means "use current array length". */ + /* Zero means "use current array length". */ phs->ora_maxarray_numentries=phs->array_numstruct; if (trace_level >= 2 || dbd_verbose >= 3 ){ @@ -2153,7 +2153,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { need_allocate_rows=phs->ora_maxarray_numentries; if( need_allocate_rows< phs->array_numstruct ){ - need_allocate_rows=phs->array_numstruct; + need_allocate_rows=phs->array_numstruct; } buflen=need_allocate_rows* phs->maxlen; /* We need buffer for at least ora_maxarray_numentries entries */ @@ -2179,160 +2179,160 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { /* Fill array buffer with data */ { - int i; /* Not to require C99 mode */ - for(i=0;iora_internal_type ){ - case SQLT_INT: - { - int ival =0; - int val_found=0; - /* Double values are converted as int(val) */ - if( SvOK( item ) && ! SvIOK( item ) ){ - double val=SvNVx( item ); - if( SvNOK( item ) ){ - ival=(int) val; - val_found=1; - } - } - /* Convert item, if possible. */ - if( (!val_found) && SvOK( item ) && ! SvIOK( item ) ){ - SvIVx( item ); - } - if( SvIOK( item ) || val_found ){ - if( ! val_found ){ - ival=SvIV( item ); - } - /* as phs->array_buf=malloc(), proper alignment is guaranteed */ - *(int*)(phs->array_buf+phs->maxlen*i)=ival; - phs->array_indicators[i]=0; - }else{ - if( SvOK( item ) ){ - /* Defined NaN assumed =0 */ - *(int*)(phs->array_buf+phs->maxlen*i)=0; - phs->array_indicators[i]=0; - }else{ - /* NULL */ - phs->array_indicators[i]=1; - } - } - phs->array_lengths[i]=sizeof(int); - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "(integer) array[%d]=%d%s\n", - i, *(int*)(phs->array_buf+phs->maxlen*i), - phs->array_indicators[i] ? " (NULL)" : "" ); - } - } - break; - case SQLT_FLT: - default: - { - phs->ora_internal_type=SQLT_FLT; /* Just in case */ - /* Convert item, if possible. */ - if( SvOK( item ) && ! SvNOK( item ) ){ - SvNVx( item ); - } - if( SvNOK( item ) ){ - double val=SvNVx( item ); - /* as phs->array_buf=malloc(), proper alignment is guaranteed */ - *(double*)(phs->array_buf+phs->maxlen*i)=val; - phs->array_indicators[i]=0; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=%f - NOT NULL\n", - i, val); - } - }else{ - if( SvOK( item ) ){ - /* Defined NaN assumed =0 */ - *(double*)(phs->array_buf+phs->maxlen*i)=0; - phs->array_indicators[i]=0; - if (trace_level >= 2 || dbd_verbose >= 3 ){ - STRLEN l; - char *p=SvPV(item,l); - - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "let (double) array[%d]=\"%s\" =NaN. Set =0 - NOT NULL\n", - i, p ? p : "" ); - } - }else{ - /* NULL */ - phs->array_indicators[i]=1; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "let (double) array[%d] NULL\n", - i); - } - } - } - phs->array_lengths[i]=sizeof(double); - if (trace_level >= 3 || dbd_verbose >= 3 ){ + int i; /* Not to require C99 mode */ + for(i=0;iora_internal_type ){ + case SQLT_INT: + { + int ival =0; + int val_found=0; + /* Double values are converted as int(val) */ + if( SvOK( item ) && ! SvIOK( item ) ){ + double val=SvNVx( item ); + if( SvNOK( item ) ){ + ival=(int) val; + val_found=1; + } + } + /* Convert item, if possible. */ + if( (!val_found) && SvOK( item ) && ! SvIOK( item ) ){ + SvIVx( item ); + } + if( SvIOK( item ) || val_found ){ + if( ! val_found ){ + ival=SvIV( item ); + } + /* as phs->array_buf=malloc(), proper alignment is guaranteed */ + *(int*)(phs->array_buf+phs->maxlen*i)=ival; + phs->array_indicators[i]=0; + }else{ + if( SvOK( item ) ){ + /* Defined NaN assumed =0 */ + *(int*)(phs->array_buf+phs->maxlen*i)=0; + phs->array_indicators[i]=0; + }else{ + /* NULL */ + phs->array_indicators[i]=1; + } + } + phs->array_lengths[i]=sizeof(int); + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " + "(integer) array[%d]=%d%s\n", + i, *(int*)(phs->array_buf+phs->maxlen*i), + phs->array_indicators[i] ? " (NULL)" : "" ); + } + } + break; + case SQLT_FLT: + default: + { + phs->ora_internal_type=SQLT_FLT; /* Just in case */ + /* Convert item, if possible. */ + if( SvOK( item ) && ! SvNOK( item ) ){ + SvNVx( item ); + } + if( SvNOK( item ) ){ + double val=SvNVx( item ); + /* as phs->array_buf=malloc(), proper alignment is guaranteed */ + *(double*)(phs->array_buf+phs->maxlen*i)=val; + phs->array_indicators[i]=0; + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d]=%f - NOT NULL\n", + i, val); + } + }else{ + if( SvOK( item ) ){ + /* Defined NaN assumed =0 */ + *(double*)(phs->array_buf+phs->maxlen*i)=0; + phs->array_indicators[i]=0; + if (trace_level >= 2 || dbd_verbose >= 3 ){ + STRLEN l; + char *p=SvPV(item,l); + + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d]=\"%s\" =NaN. Set =0 - NOT NULL\n", + i, p ? p : "" ); + } + }else{ + /* NULL */ + phs->array_indicators[i]=1; + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "let (double) array[%d] NULL\n", + i); + } + } + } + phs->array_lengths[i]=sizeof(double); + if (trace_level >= 3 || dbd_verbose >= 3 ){ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "dbd_rebind_ph_number_table(): " + "(double) array[%d]=%f%s\n", + i, *(double*)(phs->array_buf+phs->maxlen*i), + phs->array_indicators[i] ? " (NULL)" : "" ); + } + } + break; + } + }else{ + /* item not defined, mark NULL */ + phs->array_indicators[i]=1; + if (trace_level >= 3 || dbd_verbose >= 3 ){ PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_rebind_ph_number_table(): " - "(double) array[%d]=%f%s\n", - i, *(double*)(phs->array_buf+phs->maxlen*i), - phs->array_indicators[i] ? " (NULL)" : "" ); - } - } - break; - } - }else{ - /* item not defined, mark NULL */ - phs->array_indicators[i]=1; - if (trace_level >= 3 || dbd_verbose >= 3 ){ - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "dbd_rebind_ph_number_table(): " - "Copying length=? array[%d]=NULL av_fetch failed.\n", i); - } - } - } + "Copying length=? array[%d]=NULL av_fetch failed.\n", i); + } + } + } } /* Do actual bind */ OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, - (text*)phs->name, (sb4)strlen(phs->name), - phs->array_buf, - phs->maxlen, - (ub2)phs->ora_internal_type, phs->array_indicators, - phs->array_lengths, - (ub2)0, - (ub4)phs->ora_maxarray_numentries, /* max elements that can fit in allocated array */ - (ub4 *)&(phs->array_numstruct), /* (ptr to) current number of elements in array */ - OCI_DEFAULT, /* OCI_DATA_AT_EXEC (bind with callbacks) or OCI_DEFAULT */ - status - ); + (text*)phs->name, (sb4)strlen(phs->name), + phs->array_buf, + phs->maxlen, + (ub2)phs->ora_internal_type, phs->array_indicators, + phs->array_lengths, + (ub2)0, + (ub4)phs->ora_maxarray_numentries, /* max elements that can fit in allocated array */ + (ub4 *)&(phs->array_numstruct), /* (ptr to) current number of elements in array */ + OCI_DEFAULT, /* OCI_DATA_AT_EXEC (bind with callbacks) or OCI_DEFAULT */ + status + ); if (status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); - return 0; + oci_error(sth, imp_sth->errhp, status, "OCIBindByName"); + return 0; } OCIBindArrayOfStruct_log_stat(imp_sth, phs->bndhp, imp_sth->errhp, - (unsigned)phs->maxlen, /* Skip parameter for the next data value */ - (unsigned)sizeof(OCIInd), /* Skip parameter for the next indicator value */ - (unsigned)sizeof(unsigned short), /* Skip parameter for the next actual length value */ - 0, /* Skip parameter for the next column-level error code */ - status); + (unsigned)phs->maxlen, /* Skip parameter for the next data value */ + (unsigned)sizeof(OCIInd), /* Skip parameter for the next indicator value */ + (unsigned)sizeof(unsigned short), /* Skip parameter for the next actual length value */ + 0, /* Skip parameter for the next column-level error code */ + status); if (status != OCI_SUCCESS) { - oci_error(sth, imp_sth->errhp, status, "OCIBindArrayOfStruct"); - return 0; + oci_error(sth, imp_sth->errhp, status, "OCIBindArrayOfStruct"); + return 0; } if (phs->maxdata_size) { OCIAttrSet_log_stat(imp_sth, phs->bndhp, (ub4)OCI_HTYPE_BIND, - phs->array_buf, (ub4)phs->array_buflen, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); - if ( status != OCI_SUCCESS ) { - oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); - return 0; - } + phs->array_buf, (ub4)phs->array_buflen, (ub4)OCI_ATTR_MAXDATA_SIZE, imp_sth->errhp, status); + if ( status != OCI_SUCCESS ) { + oci_error(sth, imp_sth->errhp, status, ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_MAXDATA_SIZE)")); + return 0; + } } return 2; @@ -3882,6 +3882,9 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er DBIc_LOGPIO(imp_sth), " ora_st_execute_array %d errors in batch.\n", num_errs); + if (num_errs) { + sv_setiv(err_count,num_errs); + } if(num_errs && tuples_status_av) { OCIError *row_errhp, *tmp_errhp; @@ -3889,7 +3892,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er SV *err_svs[3]; /*AV *err_av;*/ sb4 err_code; - sv_setiv(err_count,num_errs); + err_svs[0] = newSViv((IV)0); err_svs[1] = newSVpvn("", 0); err_svs[2] = newSVpvn("S1000",5); diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 629a80a3..e1f4f06a 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1104,7 +1104,8 @@ SQL } $err_total += $err_count; - $tuple_count+=@$tuple_batch_status; + + $tuple_count+=@tuple_batch; push @$tuple_status, @$tuple_batch_status if defined($tuple_status); diff --git a/oci8.c b/oci8.c index bf4fef49..dafc74ba 100644 --- a/oci8.c +++ b/oci8.c @@ -3423,7 +3423,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) /* long_readlen: length for long/longraw (if >0), else 80 (ora app dflt) */ /* Ought to be for COMPAT mode only but was relaxed before LongReadLen existed */ long_readlen = (SvOK(imp_drh -> ora_long) && SvUV(imp_drh->ora_long)>0) - ? SvUV(imp_drh->ora_long) : DBIc_LongReadLen(imp_sth); + ? SvUV(imp_drh->ora_long) : DBIc_LongReadLen(imp_sth); /* set long_readlen for SELECT or PL/SQL with output placeholders */ imp_sth->long_readlen = long_readlen; @@ -3435,7 +3435,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) DBIc_LOGPIO(imp_sth), " dbd_describe skipped for %s\n", oci_stmt_type_name(imp_sth->stmt_type)); - /* imp_sth memory was cleared when created so no setup required here */ + /* imp_sth memory was cleared when created so no setup required here */ return 1; } @@ -3451,12 +3451,12 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if ( !DBIc_ACTIVE(imp_sth) ) { OCIStmtExecute_log_stat(imp_sth, imp_sth->svchp, imp_sth->stmhp, imp_sth->errhp, - 0, 0, 0, 0, OCI_DESCRIBE_ONLY, status); + 0, 0, 0, 0, OCI_DESCRIBE_ONLY, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, - ora_sql_error(imp_sth, "OCIStmtExecute/Describe")); + ora_sql_error(imp_sth, "OCIStmtExecute/Describe")); if (status != OCI_SUCCESS_WITH_INFO) - return 0; + return 0; } } OCIAttrGet_stmhp_stat(imp_sth, &num_fields, 0, OCI_ATTR_PARAM_COUNT, status); @@ -3478,7 +3478,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) Newz(42, imp_sth->fbh, num_fields, imp_fbh_t); /* Get number of fields and space needed for field names */ -/* loop though the fields and get all the fileds and thier types to get back*/ + /* loop though the fields and get all the fileds and thier types to get back*/ for(i = 1; i <= num_fields; ++i) { /*start define of filed struct[i] fbh */ char *p; @@ -3490,7 +3490,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->define_mode = OCI_DEFAULT; OCIParamGet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, imp_sth->errhp, - (dvoid**)&fbh->parmdp, (ub4)i, status); + (dvoid**)&fbh->parmdp, (ub4)i, status); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIParamGet"); @@ -3513,7 +3513,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->csid, 0, OCI_ATTR_CHARSET_ID, status); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->csform, 0, OCI_ATTR_CHARSET_FORM, status); #endif - /* OCI_ATTR_PRECISION returns 0 for most types including some numbers */ + /* OCI_ATTR_PRECISION returns 0 for most types including some numbers */ OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->prec, 0, OCI_ATTR_PRECISION, status); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->scale, 0, OCI_ATTR_SCALE, status); OCIAttrGet_parmdp(imp_sth, fbh->parmdp, &fbh->nullok, 0, OCI_ATTR_IS_NULL, status); @@ -3528,6 +3528,8 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) fbh->name = SvPVX(fbh->name_sv); fbh->ftype = 5; /* default: return as null terminated string */ + /* TO_DO there is something wrong with the tracing below as sql_typecode_name + returns NVARCHAR2 for type 2 and ORA_NUMBER is 2 */ if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), @@ -3535,283 +3537,283 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) i,fbh->dbtype,sql_typecode_name(fbh->dbtype)); switch (fbh->dbtype) { - /* the simple types */ - case ORA_VARCHAR2: /* VARCHAR2 */ - - if (fbh->dbsize == 0){ - fbh->dbsize=4000; - } - avg_width = fbh->dbsize / 2; - /* FALLTHRU */ - case ORA_CHAR: /* CHAR */ - if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) - fbh->disize = fbh->dbsize * 4; - else - fbh->disize = fbh->dbsize; - - fbh->prec = fbh->disize; - break; - case ORA_RAW: /* RAW */ - fbh->disize = fbh->dbsize * 2; - fbh->prec = fbh->disize; - break; - case ORA_NUMBER: /* NUMBER */ - case 21: /* BINARY FLOAT os-endian */ - case 22: /* BINARY DOUBLE os-endian */ - case 100: /* BINARY FLOAT oracle-endian */ - case 101: /* BINARY DOUBLE oracle-endian */ - fbh->disize = 130+38+3; /* worst case */ - avg_width = 4; /* NUMBER approx +/- 1_000_000 */ - break; - - case ORA_DATE: /* DATE */ - /* actually dependent on NLS default date format*/ - fbh->disize = 75; /* a generous default */ - fbh->prec = fbh->disize; - avg_width = 8; /* size in SQL*Net packet */ - break; - - case ORA_LONG: /* LONG */ - imp_sth->row_cache_off = 1; - has_longs++; - if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - - fbh->clbk_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - - fbh->ftype = SQLT_CHR; - fbh->fetch_func = fetch_clbk_lob; - - } - else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ - - fbh->piece_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + /* the simple types */ + case ORA_VARCHAR2: /* VARCHAR2 */ - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - fbh->ftype = SQLT_CHR; - fbh->fetch_func = fetch_get_piece; - } - else { + if (fbh->dbsize == 0){ + fbh->dbsize=4000; + } + avg_width = fbh->dbsize / 2; + /* FALLTHRU */ + case ORA_CHAR: /* CHAR */ + if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) + fbh->disize = fbh->dbsize * 4; + else + fbh->disize = fbh->dbsize; + + fbh->prec = fbh->disize; + break; + case ORA_RAW: /* RAW */ + fbh->disize = fbh->dbsize * 2; + fbh->prec = fbh->disize; + break; + case ORA_NUMBER: /* NUMBER */ + case 21: /* BINARY FLOAT os-endian */ + case 22: /* BINARY DOUBLE os-endian */ + case 100: /* BINARY FLOAT oracle-endian */ + case 101: /* BINARY DOUBLE oracle-endian */ + fbh->disize = 130+38+3; /* worst case */ + avg_width = 4; /* NUMBER approx +/- 1_000_000 */ + break; + + case ORA_DATE: /* DATE */ + /* actually dependent on NLS default date format*/ + fbh->disize = 75; /* a generous default */ + fbh->prec = fbh->disize; + avg_width = 8; /* size in SQL*Net packet */ + break; + + case ORA_LONG: /* LONG */ + imp_sth->row_cache_off = 1; + has_longs++; + if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ + + fbh->clbk_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + + fbh->ftype = SQLT_CHR; + fbh->fetch_func = fetch_clbk_lob; - if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) - fbh->disize = long_readlen * 4; - else - fbh->disize = long_readlen; + } + else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + + fbh->piece_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + fbh->ftype = SQLT_CHR; + fbh->fetch_func = fetch_get_piece; + } + else { - /* not governed by else: */ - fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; - fbh->ftype = 94; /* VAR form */ - fbh->fetch_func = fetch_func_varfield; + if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) + fbh->disize = long_readlen * 4; + else + fbh->disize = long_readlen; - } - break; - case ORA_LONGRAW: /* LONG RAW */ - has_longs++; - if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - - fbh->clbk_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } + /* not governed by else: */ + fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; + fbh->ftype = 94; /* VAR form */ + fbh->fetch_func = fetch_func_varfield; - fbh->ftype = SQLT_BIN; - fbh->fetch_func = fetch_clbk_lob; + } + break; + case ORA_LONGRAW: /* LONG RAW */ + has_longs++; + if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - } - else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + fbh->clbk_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - fbh->piece_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - fbh->ftype = SQLT_BIN; - fbh->fetch_func = fetch_get_piece; - } - else { - fbh->disize = long_readlen * 2; - fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; - fbh->ftype = 95; /* VAR form */ - fbh->fetch_func = fetch_func_varfield; - } - break; - - case ORA_ROWID: /* ROWID */ - case 104: /* ROWID Desc */ - fbh->disize = 20; - fbh->prec = fbh->disize; - break; - case 108: /* some sort of embedded object */ - imp_sth->row_cache_off = 1;/* cant fetch more thatn one at a time */ - fbh->ftype = fbh->dbtype; /*varray or alike */ - fbh->fetch_func = fetch_func_oci_object; /* need a new fetch function for it */ - fbh->fetch_cleanup = fetch_cleanup_oci_object; /* clean up any AV from the fetch*/ - fbh->desc_t = SQLT_NTY; - if (!imp_sth->dschp){ - OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); - if (status != OCI_SUCCESS) { - oci_error(h,imp_sth->errhp, status, "OCIHandleAlloc"); - ++num_errors; - } - } - break; - case ORA_CLOB: /* CLOB & NCLOB */ - case ORA_BLOB: /* BLOB */ - case ORA_BFILE: /* BFILE */ - has_longs++; - fbh->ftype = fbh->dbtype; - imp_sth->ret_lobs = 1; - imp_sth->row_cache_off = 1; /* Cannot use mulit fetch for a lob*/ - /* Unless they are just getting the locator */ - - if (imp_sth->pers_lob){ /*get as one peice fasted but limited to 64k big you can get.*/ - - fbh->pers_lob = 1; - - if (long_readlen){ - fbh->disize =long_readlen;/*user set max value for the fetch*/ - } - else { - fbh->disize = fbh->dbsize*10; /*default size*/ - } + fbh->ftype = SQLT_BIN; + fbh->fetch_func = fetch_clbk_lob; + } + else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + + fbh->piece_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + fbh->ftype = SQLT_BIN; + fbh->fetch_func = fetch_get_piece; + } + else { + fbh->disize = long_readlen * 2; + fbh->dbsize = (fbh->disize>65535) ? 65535 : fbh->disize; + fbh->ftype = 95; /* VAR form */ + fbh->fetch_func = fetch_func_varfield; + } + break; + + case ORA_ROWID: /* ROWID */ + case 104: /* ROWID Desc */ + fbh->disize = 20; + fbh->prec = fbh->disize; + break; + case 108: /* some sort of embedded object */ + imp_sth->row_cache_off = 1;/* cant fetch more thatn one at a time */ + fbh->ftype = fbh->dbtype; /*varray or alike */ + fbh->fetch_func = fetch_func_oci_object; /* need a new fetch function for it */ + fbh->fetch_cleanup = fetch_cleanup_oci_object; /* clean up any AV from the fetch*/ + fbh->desc_t = SQLT_NTY; + if (!imp_sth->dschp){ + OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &imp_sth->dschp, OCI_HTYPE_DESCRIBE, status); + if (status != OCI_SUCCESS) { + oci_error(h,imp_sth->errhp, status, "OCIHandleAlloc"); + ++num_errors; + } + } + break; + case ORA_CLOB: /* CLOB & NCLOB */ + case ORA_BLOB: /* BLOB */ + case ORA_BFILE: /* BFILE */ + has_longs++; + fbh->ftype = fbh->dbtype; + imp_sth->ret_lobs = 1; + imp_sth->row_cache_off = 1; /* Cannot use mulit fetch for a lob*/ + /* Unless they are just getting the locator */ + + if (imp_sth->pers_lob){ /*get as one peice fasted but limited to 64k big you can get.*/ + + fbh->pers_lob = 1; + + if (long_readlen){ + fbh->disize =long_readlen;/*user set max value for the fetch*/ + } + else { + fbh->disize = fbh->dbsize*10; /*default size*/ + } + + + if (fbh->dbtype == ORA_CLOB){ + fbh->ftype = SQLT_CHR;/*SQLT_LNG*/ + } + else { + fbh->ftype = SQLT_LVB; /*Binary form seems this is the only value where we can get the length correctly*/ + } + } + else if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ + fbh->clbk_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + if (fbh->dbtype == ORA_CLOB){ + fbh->ftype = SQLT_CHR; + } else { + fbh->ftype = SQLT_BIN; /*other Binary*/ + } + fbh->fetch_func = fetch_clbk_lob; - if (fbh->dbtype == ORA_CLOB){ - fbh->ftype = SQLT_CHR;/*SQLT_LNG*/ - } - else { - fbh->ftype = SQLT_LVB; /*Binary form seems this is the only value where we can get the length correctly*/ - } - } - else if (imp_sth->clbk_lob){ /*get by peice with callback a slow*/ - fbh->clbk_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - if (fbh->dbtype == ORA_CLOB){ - fbh->ftype = SQLT_CHR; - } else { - fbh->ftype = SQLT_BIN; /*other Binary*/ - } - fbh->fetch_func = fetch_clbk_lob; - - } - else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ - fbh->piece_lob = 1; - fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ - fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ - fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ - fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ - if (!imp_sth->piece_size){ /*if not set use max value*/ - imp_sth->piece_size=imp_sth->long_readlen; - } - if (fbh->dbtype == ORA_CLOB){ - fbh->ftype = SQLT_CHR; - } - else { - fbh->ftype = SQLT_BIN; /*other Binary */ - } - fbh->fetch_func = fetch_get_piece; + } + else if (imp_sth->piece_lob){ /*get by peice with polling slowest*/ + fbh->piece_lob = 1; + fbh->define_mode = OCI_DYNAMIC_FETCH; /* piecwise fetch*/ + fbh->disize = imp_sth->long_readlen; /*user set max value for the fetch*/ + fbh->piece_size = imp_sth->piece_size; /*the size for each piece*/ + fbh->fetch_cleanup = fetch_cleanup_pres_lobs; /* clean up buffer before each fetch*/ + if (!imp_sth->piece_size){ /*if not set use max value*/ + imp_sth->piece_size=imp_sth->long_readlen; + } + if (fbh->dbtype == ORA_CLOB){ + fbh->ftype = SQLT_CHR; + } + else { + fbh->ftype = SQLT_BIN; /*other Binary */ + } + fbh->fetch_func = fetch_get_piece; - } - else { /*auto lob fetch with locator by far the fastest*/ - fbh->disize = sizeof(OCILobLocator*);/* Size of the lob locator ar we do not really get the lob! */ - if (imp_sth->auto_lob) { - fbh->fetch_func = fetch_func_autolob; - } - else { - fbh->fetch_func = fetch_func_getrefpv; - } + } + else { /*auto lob fetch with locator by far the fastest*/ + fbh->disize = sizeof(OCILobLocator*);/* Size of the lob locator ar we do not really get the lob! */ + if (imp_sth->auto_lob) { + fbh->fetch_func = fetch_func_autolob; + } + else { + fbh->fetch_func = fetch_func_getrefpv; + } - fbh->bless = "OCILobLocatorPtr"; - fbh->desc_t = OCI_DTYPE_LOB; - OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &fbh->desc_h, fbh->desc_t); + fbh->bless = "OCILobLocatorPtr"; + fbh->desc_t = OCI_DTYPE_LOB; + OCIDescriptorAlloc_ok(imp_sth, imp_sth->envhp, &fbh->desc_h, fbh->desc_t); - } + } - break; + break; #ifdef OCI_DTYPE_REF - case 111: /* REF */ - fbh_setup_getrefpv(imp_sth, fbh, OCI_DTYPE_REF, "OCIRefPtr"); - break; + case 111: /* REF */ + fbh_setup_getrefpv(imp_sth, fbh, OCI_DTYPE_REF, "OCIRefPtr"); + break; #endif - case ORA_RSET: /* RSET */ - fbh->ftype = fbh->dbtype; - fbh->disize = sizeof(OCIStmt *); - fbh->fetch_func = fetch_func_rset; - fbh->fetch_cleanup = fetch_cleanup_rset; - nested_cursors++; - break; - - case 182: /* INTERVAL YEAR TO MONTH */ - case 183: /* INTERVAL DAY TO SECOND */ - case 185: /* TIME (ocidfn.h) */ - case 186: /* TIME WITH TIME ZONE (ocidfn.h) */ - case 187: /* TIMESTAMP */ - case 188: /* TIMESTAMP WITH TIME ZONE */ - case 189: /* INTERVAL YEAR TO MONTH (ocidfn.h) */ - case 190: /* INTERVAL DAY TO SECOND */ - case 232: /* TIMESTAMP WITH LOCAL TIME ZONE */ - /* actually dependent on NLS default date format*/ - fbh->disize = 75; /* XXX */ - break; - - default: + case ORA_RSET: /* RSET */ + fbh->ftype = fbh->dbtype; + fbh->disize = sizeof(OCIStmt *); + fbh->fetch_func = fetch_func_rset; + fbh->fetch_cleanup = fetch_cleanup_rset; + nested_cursors++; + break; + + case 182: /* INTERVAL YEAR TO MONTH */ + case 183: /* INTERVAL DAY TO SECOND */ + case 185: /* TIME (ocidfn.h) */ + case 186: /* TIME WITH TIME ZONE (ocidfn.h) */ + case 187: /* TIMESTAMP */ + case 188: /* TIMESTAMP WITH TIME ZONE */ + case 189: /* INTERVAL YEAR TO MONTH (ocidfn.h) */ + case 190: /* INTERVAL DAY TO SECOND */ + case 232: /* TIMESTAMP WITH LOCAL TIME ZONE */ + /* actually dependent on NLS default date format*/ + fbh->disize = 75; /* XXX */ + break; + + default: /* XXX unhandled type may lead to errors or worse */ - fbh->ftype = fbh->dbtype; - fbh->disize = fbh->dbsize; - p = "Field %d has an Oracle type (%d) which is not explicitly supported%s"; - if (DBIc_DBISTATE(imp_sth)->debug >= 1 || dbd_verbose >= 3 ) - PerlIO_printf(DBIc_LOGPIO(imp_sth), p, i, fbh->dbtype, "\n"); - if (PL_dowarn) - warn(p, i, fbh->dbtype, ""); - break; + fbh->ftype = fbh->dbtype; + fbh->disize = fbh->dbsize; + p = "Field %d has an Oracle type (%d) which is not explicitly supported%s"; + if (DBIc_DBISTATE(imp_sth)->debug >= 1 || dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_sth), p, i, fbh->dbtype, "\n"); + if (PL_dowarn) + warn(p, i, fbh->dbtype, ""); + break; } if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf( - DBIc_LOGPIO(imp_sth), - "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, " - "name %s\n : dbsize %d, char_used %d, char_size %d, " - "csid %d, csform %d(%s), disize %d\n", - i, fbh->dbtype, sql_typecode_name(fbh->dbtype), fbh->scale, - fbh->prec, fbh->nullok, fbh->name, fbh->dbsize, - fbh->len_char_used, fbh->len_char_size, - fbh->csid,fbh->csform,oci_csform_name(fbh->csform), fbh->disize); + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + "Described col %2d: dbtype %d(%s), scale %d, prec %d, nullok %d, " + "name %s\n : dbsize %d, char_used %d, char_size %d, " + "csid %d, csform %d(%s), disize %d\n", + i, fbh->dbtype, sql_typecode_name(fbh->dbtype), fbh->scale, + fbh->prec, fbh->nullok, fbh->name, fbh->dbsize, + fbh->len_char_used, fbh->len_char_size, + fbh->csid,fbh->csform,oci_csform_name(fbh->csform), fbh->disize); if (fbh->ftype == 5) /* XXX need to handle wide chars somehow */ fbh->disize += 1; /* allow for null terminator */ - /* dbsize can be zero for 'select NULL ...' */ + /* dbsize can be zero for 'select NULL ...' */ imp_sth->t_dbsize += fbh->dbsize; @@ -3828,8 +3830,8 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) imp_sth->est_width = est_width; sth_set_row_cache(h, imp_sth, - (imp_dbh->max_nested_cursors) ? 0 :nested_cursors , - (int)num_fields, has_longs ); + (imp_dbh->max_nested_cursors) ? 0 :nested_cursors , + (int)num_fields, has_longs ); /* Initialise cache counters */ imp_sth->in_cache = 0; imp_sth->eod_errno = 0; @@ -3861,26 +3863,26 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) if (fbh->ftype == ORA_RSET) { /* RSET */ OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, - (dvoid*)&((OCIStmt **)fb_ary->abuf)[0], - OCI_HTYPE_STMT, status); + (dvoid*)&((OCIStmt **)fb_ary->abuf)[0], + OCI_HTYPE_STMT, status); } OCIDefineByPos_log_stat(imp_sth, imp_sth->stmhp, - &fbh->defnp, - imp_sth->errhp, - (ub4) i, - (fbh->desc_h) ? (dvoid*)&fbh->desc_h : fbh->clbk_lob ? (dvoid *) 0: fbh->piece_lob ? (dvoid *) 0:(dvoid*)fb_ary->abuf, - (fbh->desc_h) ? 0 : define_len, - (ub2)fbh->ftype, - fb_ary->aindp, - (ftype==94||ftype==95) ? NULL : fb_ary->arlen, - fb_ary->arcode, - fbh->define_mode, - status); + &fbh->defnp, + imp_sth->errhp, + (ub4) i, + (fbh->desc_h) ? (dvoid*)&fbh->desc_h : fbh->clbk_lob ? (dvoid *) 0: fbh->piece_lob ? (dvoid *) 0:(dvoid*)fb_ary->abuf, + (fbh->desc_h) ? 0 : define_len, + (ub2)fbh->ftype, + fb_ary->aindp, + (ftype==94||ftype==95) ? NULL : fb_ary->arlen, + fb_ary->arcode, + fbh->define_mode, + status); if (fbh->clbk_lob){ - /* use a dynamic callback for persistent binary and char lobs*/ + /* use a dynamic callback for persistent binary and char lobs*/ OCIDefineDynamic_log_stat(imp_sth, fbh->defnp,imp_sth->errhp,(dvoid *) fbh,status); } @@ -3917,14 +3919,14 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) #ifdef OCI_ATTR_CHARSET_FORM if ( (fbh->dbtype == 1) && fbh->csform ) { - /* csform may be 0 when talking to Oracle 8.0 database*/ + /* csform may be 0 when talking to Oracle 8.0 database*/ if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), " calling OCIAttrSet OCI_ATTR_CHARSET_FORM with csform=%d (%s)\n", fbh->csform,oci_csform_name(fbh->csform) ); OCIAttrSet_log_stat(imp_sth, fbh->defnp, (ub4) OCI_HTYPE_DEFINE, (dvoid *) &fbh->csform, - (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status ); + (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, imp_sth->errhp, status ); if (status != OCI_SUCCESS) { oci_error(h, imp_sth->errhp, status, "OCIAttrSet OCI_ATTR_CHARSET_FORM"); ++num_errors; @@ -4016,7 +4018,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ imp_sth->rs_array_idx=0; } - else { /*Array Fetch the New Noraml Super speedy and very nice*/ + else { /*Array Fetch the New Normal Super speedy and very nice*/ imp_sth->rs_array_idx++; @@ -4161,7 +4163,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ char errstr[256]; sts = DBIc_DBISTATE(imp_sth)->sql_type_cast_svpv( - aTHX_ sv, fbh->req_type, fbh->bind_flags, NULL); + aTHX_ sv, fbh->req_type, fbh->bind_flags, NULL); if (sts == 0) { sprintf(errstr, diff --git a/t/26exe_array.t b/t/26exe_array.t index 52107a96..8a4519fe 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -1,15 +1,9 @@ -#!/usr/bin/perl -w -I./t - -## ---------------------------------------------------------------------------- -## 26exe_array.t this is a completly new one -## By Martin J. Evans orgianlly called 70execute_array.t for the ODBC DBD driver -## and adatped into DBD::Oracle (in a very minor way) by John Scoles, The Pythian Group -## ---------------------------------------------------------------------------- -## loads of execute_array and execute_for_fetch tests -## tests both insert and update and row fetching -## with RaiseError on and off and AutoCommit on and off -## ---------------------------------------------------------------------------- - +# $Id$ +# Completely new test for DBD::Oracle which came from DBD::ODBC +# Author: Martin J. Evans +# +# loads of execute_array and execute_for_fetch tests using DBI's methods +# use Test::More; use strict; use Data::Dumper; @@ -17,25 +11,30 @@ require 'nchar_test_lib.pl'; $| = 1; +my $has_test_nowarnings = 1; +eval "require Test::NoWarnings"; +$has_test_nowarnings = undef if $@; + +my ($dbh, $ea); -my $table = 'PERL_DBD_execute_array'; -my $table2 = 'PERL_DBD_execute_array2'; -my @captured_error; # values captured in error handler +use DBI qw(:sql_types); +use ExecuteArray; +END { + if ($dbh && $ea) { + $ea->drop_table($dbh); + $dbh->disconnect(); + } + Test::NoWarnings::had_no_warnings() + if ($has_test_nowarnings); + done_testing(); +} -# create a database handle my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; $ENV{NLS_NCHAR} = "US7ASCII"; $ENV{NLS_LANG} = "AMERICAN"; -my $dbh; -my @p1 = (1,2,3,4,5); -my @p2 = qw(one two three four five); -my $fetch_row = 0; - -use DBI qw(:sql_types); - eval { $dbh = DBI->connect($dsn, $dbuser, '', {PrintError => 0}); }; @@ -43,426 +42,24 @@ eval { if (!$dbh) { plan skip_all => "Unable to connect to Oracle"; } -#$dbh->{PrintError} = 1; -my $has_test_nowarnings = 1; -eval "require Test::NoWarnings"; -$has_test_nowarnings = undef if $@; -use_ok('Data::Dumper'); - -END { - if ($dbh) { - drop_table_local($dbh); - } - Test::NoWarnings::had_no_warnings() - if ($has_test_nowarnings); - done_testing(); -} - -sub error_handler -{ - @captured_error = @_; - note("***** error handler called *****"); - 0; # pass errors on -} - -sub create_table_local -{ - my $dbh = shift; - - eval { - $dbh->do(qq/create table $table (a int primary key, b char(20))/); - }; - if ($@) { - diag("Failed to create test table $table - $@"); - return 0; - } - eval { - $dbh->do(qq/create table $table2 (a int primary key, b char(20))/); - }; - if ($@) { - diag("Failed to create test table $table2 - $@"); - return 0; - } - my $sth = $dbh->prepare(qq/insert into $table2 values(?,?)/); - for (my $row = 0; $row < @p1; $row++) { - $sth->execute($p1[$row], $p2[$row]); - } - 1; -} - -sub drop_table_local -{ - my $dbh = shift; - - eval { - local $dbh->{PrintError} = 0; - local $dbh->{PrintWarn} = 0; - $dbh->do(qq/drop table $table/); - $dbh->do(qq/drop table $table2/); - }; - note("Table dropped"); -} - -# clear the named table of rows -sub clear_table -{ - $_[0]->do(qq/delete from $_[1]/); -} - -# check $table contains the data in $c1, $c2 which are arrayrefs of values -sub check_data -{ - my ($dbh, $c1, $c2) = @_; - - my $data = $dbh->selectall_arrayref(qq/select * from $table order by a/); - my $row = 0; - foreach (@$data) { - is($_->[0], $c1->[$row], "row $row p1 data"); - is($_->[1], $c2->[$row], "row $row p2 data"); - $row++; - } -} - -sub check_tuple_status -{ - my ($tsts, $expected) = @_; - - note(Data::Dumper->Dump([$tsts], [qw(ArrayTupleStatus)])); - my $row = 0; - foreach my $s (@$tsts) { - if (ref($expected->[$row])) { - is(ref($s), 'ARRAY', 'array in array tuple status'); - is(scalar(@$s), 3, '3 elements in array tuple status error'); - } else { - if ($s == -1) { - pass("row $row tuple status unknown"); - } else { - is($s, $expected->[$row], "row $row tuple status"); - } - } - $row++ - } -} - -# insert might return 'mas' which means the caller said the test -# required Multiple Active Statements and the driver appeared to not -# support MAS. -sub insert -{ - my ($dbh, $sth, $ref) = @_; - - die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); - note("insert " . join(", ", map {"$_ = ". DBI::neat($ref->{$_})} keys %$ref )); - # DBD::Oracle supports MAS don't compensate for it not - if ($ref->{requires_mas} && $dbh->{Driver}->{Name} eq 'Oracle') { - delete $ref->{requires_mas}; - } - @captured_error = (); - - if ($ref->{raise}) { - $sth->{RaiseError} = 1; - } else { - $sth->{RaiseError} = 0; - } - - my (@tuple_status, $sts, $total_affected); - $sts = 999999; # to ensure it is overwritten - $total_affected = 999998; - if ($ref->{array_context}) { - eval { - if ($ref->{params}) { - ($sts, $total_affected) = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}, - @{$ref->{params}}); - } elsif ($ref->{fetch}) { - ($sts, $total_affected) = - $sth->execute_array( - {ArrayTupleStatus => \@tuple_status, - ArrayTupleFetch => $ref->{fetch}}); - } else { - ($sts, $total_affected) = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}); - } - }; - } else { - eval { - if ($ref->{params}) { - $sts = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}, - @{$ref->{params}}); - } else { - $sts = - $sth->execute_array({ArrayTupleStatus => \@tuple_status}); - } - }; - } - if ($ref->{error} && $ref->{raise}) { - ok($@, 'error in execute_array eval'); - } else { - if ($ref->{requires_mas} && $@) { - diag("\nThis test died with $@"); - diag("It requires multiple active statement support in the driver and I cannot easily determine if your driver supports MAS. Ignoring the rest of this test."); - foreach (@tuple_status) { - if (ref($_)) { - diag(join(",", @$_)); - } - } - return 'mas'; - } - ok(!$@, 'no error in execute_array eval') or note($@); - } - $dbh->commit if $ref->{commit}; - - if (!$ref->{raise} || ($ref->{error} == 0)) { - if (exists($ref->{sts})) { - is($sts, $ref->{sts}, - "execute_array returned " . DBI::neat($sts) . " rows executed"); - } - if (exists($ref->{affected}) && $ref->{array_context}) { - is($total_affected, $ref->{affected}, - "total affected " . DBI::neat($total_affected)) - } - } - if ($ref->{raise}) { - if ($ref->{error}) { - ok(scalar(@captured_error) > 0, "error captured"); - } else { - is(scalar(@captured_error), 0, "no error captured"); - } - } - if ($ref->{sts}) { - is(scalar(@tuple_status), (($ref->{sts} eq '0E0') ? 0 : $ref->{sts}), - "$ref->{sts} rows in tuple_status"); - } - if ($ref->{tuple}) { - check_tuple_status(\@tuple_status, $ref->{tuple}); - } - return; -} -# simple test on ensure execute_array with no errors: -# o checks returned status and affected is correct -# o checks ArrayTupleStatus is correct -# o checks no error is raised -# o checks rows are inserted -# o run twice with AutoCommit on/off -# o checks if less values are specified for one parameter the right number -# of rows are still inserted and NULLs are placed in the missing rows -# checks binding via bind_param_array and adding params to execute_array -# checks binding no parameters at all -sub simple -{ - my ($dbh, $ref) = @_; - - note('simple tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); - - note(" all param arrays the same size"); - foreach my $commit (1,0) { - note(" Autocommit: $commit"); - clear_table($dbh, $table); - $dbh->begin_work if !$commit; - - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - $sth->bind_param_array(1, \@p1); - $sth->bind_param_array(2, \@p2); - insert($dbh, $sth, - { commit => !$commit, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref}); - check_data($dbh, \@p1, \@p2); - } - - note " Not all param arrays the same size"; - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - - $sth->bind_param_array(1, \@p1); - $sth->bind_param_array(2, [qw(one)]); - insert($dbh, $sth, {commit => 0, error => 0, - raise => 1, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref}); - check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); - - note " Not all param arrays the same size with bind on execute_array"; - clear_table($dbh, $table); - $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - - insert($dbh, $sth, {commit => 0, error => 0, - raise => 1, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - params => [\@p1, [qw(one)]]}); - check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); - - note " no parameters"; - clear_table($dbh, $table); - $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - - insert($dbh, $sth, {commit => 0, error => 0, - raise => 1, sts => '0E0', affected => 0, - tuple => [], %$ref, - params => [[], []]}); - check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); -} - -# error test to ensure correct behavior for execute_array when it errors: -# o execute_array of 5 inserts with last one failing -# o check it raises an error -# o check caught error is passed on from handler for eval -# o check returned status and affected rows -# o check ArrayTupleStatus -# o check valid inserts are inserted -# o execute_array of 5 inserts with 2nd last one failing -# o check it raises an error -# o check caught error is passed on from handler for eval -# o check returned status and affected rows -# o check ArrayTupleStatus -# o check valid inserts are inserted -sub error -{ - my ($dbh, $ref) = @_; - - die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); - - note('error tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); - { - note("Last row in error"); - - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - my @pe1 = @p1; - $pe1[-1] = 1; - $sth->bind_param_array(1, \@pe1); - $sth->bind_param_array(2, \@p2); - insert($dbh, $sth, {commit => 0, error => 1, sts => undef, - affected => undef, tuple => [1, 1, 1, 1, []], - %$ref}); - check_data($dbh, [@pe1[0..4]], [@p2[0..4]]); - } - - { - note("2nd last row in error"); - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - my @pe1 = @p1; - $pe1[-2] = 1; - $sth->bind_param_array(1, \@pe1); - $sth->bind_param_array(2, \@p2); - insert($dbh, $sth, {commit => 0, error => 1, sts => undef, - affected => undef, tuple => [1, 1, 1, [], 1], %$ref}); - check_data($dbh, [@pe1[0..2],$pe1[4]], [@p2[0..2], $p2[4]]); - } -} - -sub fetch_sub -{ - note("fetch_sub $fetch_row"); - if ($fetch_row == @p1) { - note('returning undef'); - $fetch_row = 0; - return; - } - - return [$p1[$fetch_row], $p2[$fetch_row++]]; -} - -# test insertion via execute_array and ArrayTupleFetch -sub row_wise -{ - my ($dbh, $ref) = @_; - - note("row_size via execute_for_fetch"); - - $fetch_row = 0; - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - fetch => \&fetch_sub}); - - # NOTE: I'd like to do the following test but it requires Multiple - # Active Statements and although I can find ODBC drivers which do this - # it is not easy (if at all possible) to know if an ODBC driver can - # handle MAS or not. If it errors the driver probably does not have MAS - # so the error is ignored and a diagnostic is output. - note("row_size via select"); - clear_table($dbh, $table); - $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - my $sth2 = $dbh->prepare(qq/select * from $table2/); - ok($sth2->execute, 'execute on second table') or diag($sth2->errstr); - ok($sth2->{Executed}, 'second statement is in executed state'); - my $res = insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - fetch => $sth2, requires_mas => 1}); - return if $res && $res eq 'mas'; # aborted , does not seem to support MAS - check_data($dbh, \@p1, \@p2); - #my $res = $dbh->selectall_arrayref("select * from $table2"); - #print Dumper($res); -} - -# test updates -sub update -{ - my ($dbh, $ref) = @_; - - note("update test"); - - $fetch_row = 0; - clear_table($dbh, $table); - my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref, - fetch => \&fetch_sub}); - check_data($dbh, \@p1, \@p2); - - $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); - # NOTE, this also checks you can pass a scalar to bind_param_array - $sth->bind_param_array(1, 'fred'); - $sth->bind_param_array(2, \@p1); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 5, - tuple => [1, 1, 1, 1, 1], %$ref}); - check_data($dbh, \@p1, [qw(fred fred fred fred fred)]); - - $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); - # NOTE, this also checks you can pass a scalar to bind_param_array - $sth->bind_param_array(1, 'dave'); - my @pe1 = @p1; - $pe1[-1] = 10; # non-existant row - $sth->bind_param_array(2, \@pe1); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 5, affected => 4, - tuple => [1, 1, 1, 1, '0E0'], %$ref}); - check_data($dbh, \@p1, [qw(dave dave dave dave fred)]); - - $sth = $dbh->prepare(qq/update $table set b = ? where b like ?/); - # NOTE, this also checks you can pass a scalar to bind_param_array - $sth->bind_param_array(1, 'pete'); - $sth->bind_param_array(2, ['dave%', 'fred%']); - insert($dbh, $sth, - {commit => 0, error => 0, sts => 2, affected => 5, - tuple => [4, 1], %$ref}); - check_data($dbh, \@p1, [qw(pete pete pete pete pete)]); - - -} -$dbh->{RaiseError} = 1; -$dbh->{PrintError} = 0; -$dbh->{ChopBlanks} = 1; -$dbh->{HandleError} = \&error_handler; -$dbh->{AutoCommit} = 1; +$ea = ExecuteArray->new($dbh, 1); # set odbc_disable_array_operations +$dbh = $ea->dbh; -eval {drop_table_local($dbh)}; +$ea->drop_table($dbh); +ok($ea->create_table($dbh), "create test table") or exit 1; +$ea->simple($dbh, {array_context => 1, raise => 1}); +$ea->simple($dbh, {array_context => 0, raise => 1}); +$ea->error($dbh, {array_context => 1, raise => 1}); +$ea->error($dbh, {array_context => 0, raise => 1}); +$ea->error($dbh, {array_context => 1, raise => 0}); +$ea->error($dbh, {array_context => 0, raise => 0}); -ok(create_table_local($dbh), "create test table") or exit 1; -simple($dbh, {array_context => 1, raise => 1}); -simple($dbh, {array_context => 0, raise => 1}); -error($dbh, {array_context => 1, raise => 1}); -error($dbh, {array_context => 0, raise => 1}); -error($dbh, {array_context => 1, raise => 0}); -error($dbh, {array_context => 0, raise => 0}); +$ea->row_wise($dbh, {array_context => 1, raise => 1}); -row_wise($dbh, {array_context => 1, raise => 1}); +$ea->update($dbh, {array_context => 1, raise => 1}); -update($dbh, {array_context => 1, raise => 1}); +$ea->error($dbh, {array_context => 1, raise => 1, notuplestatus => 1}); +$ea->error($dbh, {array_context => 0, raise => 1, notuplestatus => 1}); +$ea->error($dbh, {array_context => 1, raise => 0, notuplestatus => 1}); +$ea->error($dbh, {array_context => 0, raise => 0, notuplestatus => 1}); diff --git a/t/ExecuteArray.pm b/t/ExecuteArray.pm new file mode 100644 index 00000000..268641f0 --- /dev/null +++ b/t/ExecuteArray.pm @@ -0,0 +1,519 @@ +# $Id$ +# Author: Martin J. Evans +# This should be an exact copy of the same file in DBD::ODBC +# If you change this file please let me know. +package ExecuteArray; +use Test::More; +use Data::Dumper; +use DBI; +our $VERSION = '0.01'; + +my $table = 'PERL_DBD_execute_array'; +my $table2 = 'PERL_DBD_execute_array2'; +my @p1 = (1,2,3,4,5); +my @p2 = qw(one two three four five); +my $fetch_row = 0; +my @captured_error; # values captured in error handler + +sub error_handler +{ + @captured_error = @_; + note("***** error handler called *****"); + 0; # pass errors on +} + +sub new { + my ($class, $dbh, $dbi_version) = @_; + my $self = {}; + + $dbh = setup($dbh, $dbi_version); + $self->{_dbh} = $dbh; + + # find out how the driver supports row counts and parameter status + $self->{_param_array_row_counts} = $dbh->get_info(153); + # a return of 1 is SQL_PARC_BATCH which means: + # Individual row counts are available for each set of parameters. This is + # conceptually equivalent to the driver generating a batch of SQL + # statements, one for each parameter set in the array. Extended error + # information can be retrieved by using the SQL_PARAM_STATUS_PTR + # descriptor field. + # a return of 2 is SQL_PARC_NO_BATCH which means: + # There is only one row count available, which is the cumulative row + # count resulting from the execution of the statement for the entire + # array of parameters. This is conceptually equivalent to treating + # the statement together with the complete parameter array as one + # atomic unit. Errors are handled the same as if one statement + # were executed. + return bless ($self, $class); +} + +sub dbh { + my $self = shift; + return $self->{_dbh}; +} + +sub setup { + my ($dbh, $dbi_version) = @_; + + $dbh = enable_mars($dbh, $native); + $dbh->{HandleError} = \&error_handler; + if ($dbi_version) { + $dbh->{odbc_disable_array_operations} = 1; + } + #$dbh->{ora_verbose} = 5; + $dbh->{RaiseError} = 1; + $dbh->{PrintError} = 0; + $dbh->{ChopBlanks} = 1; + $dbh->{AutoCommit} = 1; + + return $dbh; +} + +sub create_table +{ + my ($self, $dbh) = @_; + + eval { + $dbh->do(qq/create table $table (a integer not null primary key, b char(20))/); + }; + if ($@) { + diag("Failed to create test table $table - $@"); + return 0; + } + eval { + $dbh->do(qq/create table $table2 (a integer not null primary key, b char(20))/); + }; + if ($@) { + diag("Failed to create test table $table2 - $@"); + return 0; + } + my $sth = $dbh->prepare(qq/insert into $table2 values(?,?)/); + for (my $row = 0; $row < @p1; $row++) { + $sth->execute($p1[$row], $p2[$row]); + } + 1; +} + +sub drop_table +{ + my ($self, $dbh) = @_; + + eval { + local $dbh->{PrintError} = 0; + local $dbh->{PrintWarn} = 0; + $dbh->do(qq/drop table $table/); + $dbh->do(qq/drop table $table2/); + }; + note("Table dropped"); +} + +# clear the named table of rows +sub clear_table +{ + $_[0]->do(qq/delete from $_[1]/); +} + +# check $table contains the data in $c1, $c2 which are arrayrefs of values +sub check_data +{ + my ($dbh, $c1, $c2) = @_; + + my $data = $dbh->selectall_arrayref(qq/select * from $table order by a/); + my $row = 0; + foreach (@$data) { + is($_->[0], $c1->[$row], "row $row p1 data"); + is($_->[1], $c2->[$row], "row $row p2 data"); + $row++; + } +} + +sub check_tuple_status +{ + my ($self, $tsts, $expected) = @_; + + note(Data::Dumper->Dump([$tsts], [qw(ArrayTupleStatus)])); + + BAIL_OUT('expected data must be specified') + if (!$expected || (ref($expected) ne 'ARRAY')); + + is(ref($tsts), 'ARRAY', 'tuple status is an array') or return; + if (!is(scalar(@$tsts), scalar(@$expected), 'status arrays same size')) { + diag(Dumper($tsts)); + diag(Dumper($expected)); + return; + } + + my $row = 0; + foreach my $s (@$expected) { + if (ref($s)) { + unless ($self->{_param_array_row_counts} == 2) { + is(ref($tsts->[$row]), 'ARRAY', 'array in array tuple status'); + is(scalar(@{$tsts->[$row]}), 3, '3 elements in array tuple status error'); + } + } else { + if ($tsts->[$row] == -1) { + pass("row $row tuple status unknown"); + } else { + is($tsts->[$row], $s, "row $row tuple status"); + } + } + $row++; + } + return; +} + +# insert might return 'mas' which means the caller said the test +# required Multiple Active Statements and the driver appeared to not +# support MAS. +# +# ref is a hash ref: +# error (0|1) whether we expect an error +# raise (0|1) means set RaiseError to this +# commit (0|1) do the inserts in a txn +# tuple arrayref of what we expect in the tuple status +# e.g., [1,1,1,1,[]] +# where the empty [] signifies we expect an error for this row +# where 1 signifies we the expect row count for this row +# affected - the total number of rows affected for insert/update +# +sub insert +{ + my ($self, $dbh, $sth, $ref) = @_; + + die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); + note("insert " . join(", ", map {"$_ = ". DBI::neat($ref->{$_})} keys %$ref )); + # DBD::Oracle supports MAS don't compensate for it not + if ($ref->{requires_mas} && $dbh->{Driver}->{Name} eq 'Oracle') { + delete $ref->{requires_mas}; + } + @captured_error = (); + + if ($ref->{raise}) { + $sth->{RaiseError} = 1; + } else { + $sth->{RaiseError} = 0; + } + + my (@tuple_status, $sts, $total_affected); + my $tuple_status_arg = {}; + $tuple_status_arg->{ArrayTupleStatus} = \@tuple_status unless $ref->{notuplestatus}; + + $sts = 999999; # to ensure it is overwritten + $total_affected = 999998; + if ($ref->{array_context}) { + eval { + if ($ref->{params}) { + ($sts, $total_affected) = + $sth->execute_array($tuple_status_arg, + @{$ref->{params}}); + } elsif ($ref->{fetch}) { + ($sts, $total_affected) = + $sth->execute_array( + {%{$tuple_status_arg}, + ArrayTupleFetch => $ref->{fetch}}); + } else { + ($sts, $total_affected) = + $sth->execute_array($tuple_status_arg); + } + }; + } else { + eval { + if ($ref->{params}) { + $sts = + $sth->execute_array($tuple_status_arg, + @{$ref->{params}}); + } else { + $sts = + $sth->execute_array($tuple_status_arg); + } + }; + } + if ($ref->{error} && $ref->{raise}) { + ok($@, 'error in execute_array eval'); + } else { + if ($ref->{requires_mas} && $@) { + diag("\nThis test died with $@"); + diag("It requires multiple active statement support in the driver and I cannot easily determine if your driver supports MAS. Ignoring the rest of this test."); + foreach (@tuple_status) { + if (ref($_)) { + diag(join(",", @$_)); + } + } + return 'mas'; + } + ok(!$@, 'no error in execute_array eval') or note($@); + } + $dbh->commit if $ref->{commit}; + + if (!$ref->{raise} || ($ref->{error} == 0)) { + if (exists($ref->{sts})) { + is($sts, $ref->{sts}, + "execute_array returned " . DBI::neat($sts) . " rows executed"); + } + if (exists($ref->{affected}) && $ref->{array_context}) { + is($total_affected, $ref->{affected}, + "total affected " . DBI::neat($total_affected)) + } + } + if ($ref->{raise}) { + if ($ref->{error}) { + ok(scalar(@captured_error) > 0, "error captured"); + } else { + is(scalar(@captured_error), 0, "no error captured"); + } + } + if ($ref->{sts}) { + is(scalar(@tuple_status), (($ref->{sts} eq '0E0') ? 0 : $ref->{sts}), + "$ref->{sts} rows in tuple_status"); + } + if ($ref->{tuple} && !exists($ref->{notuplestatus})) { + $self->check_tuple_status(\@tuple_status, $ref->{tuple}); + } + return; +} +# simple test on ensure execute_array with no errors: +# o checks returned status and affected is correct +# o checks ArrayTupleStatus is correct +# o checks no error is raised +# o checks rows are inserted +# o run twice with AutoCommit on/off +# o checks if less values are specified for one parameter the right number +# of rows are still inserted and NULLs are placed in the missing rows +# checks binding via bind_param_array and adding params to execute_array +# checks binding no parameters at all +sub simple +{ + my ($self, $dbh, $ref) = @_; + + note('simple tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); + + note(" all param arrays the same size"); + foreach my $commit (1,0) { + note(" Autocommit: $commit"); + clear_table($dbh, $table); + $dbh->begin_work if !$commit; + + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + $sth->bind_param_array(1, \@p1); + $sth->bind_param_array(2, \@p2); + $self->insert($dbh, $sth, + { commit => !$commit, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref}); + check_data($dbh, \@p1, \@p2); + } + + note " Not all param arrays the same size"; + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + + $sth->bind_param_array(1, \@p1); + $sth->bind_param_array(2, [qw(one)]); + $self->insert($dbh, $sth, {commit => 0, error => 0, + raise => 1, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref}); + check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); + + note " Not all param arrays the same size with bind on execute_array"; + clear_table($dbh, $table); + $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + + $self->insert($dbh, $sth, {commit => 0, error => 0, + raise => 1, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + params => [\@p1, [qw(one)]]}); + check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); + + note " no parameters"; + clear_table($dbh, $table); + $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + + $self->insert($dbh, $sth, {commit => 0, error => 0, + raise => 1, sts => '0E0', affected => 0, + tuple => [], %$ref, + params => [[], []]}); + check_data($dbh, \@p1, ['one', undef, undef, undef, undef]); +} + +# error test to ensure correct behavior for execute_array when it errors: +# o execute_array of 5 inserts with last one failing +# o check it raises an error +# o check caught error is passed on from handler for eval +# o check returned status and affected rows +# o check ArrayTupleStatus +# o check valid inserts are inserted +# o execute_array of 5 inserts with 2nd last one failing +# o check it raises an error +# o check caught error is passed on from handler for eval +# o check returned status and affected rows +# o check ArrayTupleStatus +# o check valid inserts are inserted +sub error +{ + my ($self, $dbh, $ref) = @_; + + die "need hashref arg" if (!$ref || (ref($ref) ne 'HASH')); + + note('error tests ' . join(", ", map {"$_ = $ref->{$_}"} keys %$ref )); + { + note("Last row in error"); + + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + my @pe1 = @p1; + $pe1[-1] = 1; + $sth->bind_param_array(1, \@pe1); + $sth->bind_param_array(2, \@p2); + $self->insert($dbh, $sth, {commit => 0, error => 1, sts => undef, + affected => undef, tuple => [1, 1, 1, 1, []], + %$ref}); + check_data($dbh, [@pe1[0..4]], [@p2[0..4]]); + } + + { + note("2nd last row in error"); + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + my @pe1 = @p1; + $pe1[-2] = 1; + $sth->bind_param_array(1, \@pe1); + $sth->bind_param_array(2, \@p2); + $self->insert($dbh, $sth, {commit => 0, error => 1, sts => undef, + affected => undef, tuple => [1, 1, 1, [], 1], %$ref}); + check_data($dbh, [@pe1[0..2],$pe1[4]], [@p2[0..2], $p2[4]]); + } +} + +sub fetch_sub +{ + note("fetch_sub $fetch_row"); + if ($fetch_row == @p1) { + note('returning undef'); + $fetch_row = 0; + return; + } + + return [$p1[$fetch_row], $p2[$fetch_row++]]; +} + +# test insertion via execute_array and ArrayTupleFetch +sub row_wise +{ + my ($self, $dbh, $ref) = @_; + + note("row_size via execute_for_fetch"); + + # Populate the first table via a ArrayTupleFetch which points to a sub + # returning rows + $fetch_row = 0; # reset fetch_sub to start with first row + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + fetch => \&fetch_sub}); + + # NOTE: The following test requires Multiple Active Statements. Although + # I can find ODBC drivers which do this it is not easy (if at all possible) + # to know if an ODBC driver can handle MAS or not. If it errors the + # driver probably does not have MAS so the error is ignored and a + # diagnostic is output. Exceptions are DBD::Oracle which definitely does + # support MAS. + # The data pushed into the first table is retrieved via ArrayTupleFetch + # from the second table by passing an executed select statement handle into + # execute_array. + note("row_size via select"); + clear_table($dbh, $table); + $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + my $sth2 = $dbh->prepare(qq/select * from $table2/); + # some drivers issue warnings when mas fails and this causes + # Test::NoWarnings to output something when we already found + # the test failed and captured it. + # e.g., some ODBC drivers cannot do MAS and this test is then expected to + # fail but we ignore the failure. Unfortunately in failing DBD::ODBC will + # issue a warning in addition to the fail + $sth->{Warn} = 0; + $sth->{Warn} = 0; + ok($sth2->execute, 'execute on second table') or diag($sth2->errstr); + ok($sth2->{Executed}, 'second statement is in executed state'); + my $res = $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + fetch => $sth2, requires_mas => 1}); + return if $res && $res eq 'mas'; # aborted , does not seem to support MAS + check_data($dbh, \@p1, \@p2); +} + +# test updates +# updates are special as you can update more rows than there are parameter rows +sub update +{ + my ($self, $dbh, $ref) = @_; + + note("update test"); + + # populate the first table with the default 5 rows using a ArrayTupleFetch + $fetch_row = 0; + clear_table($dbh, $table); + my $sth = $dbh->prepare(qq/insert into $table values(?,?)/); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref, + fetch => \&fetch_sub}); + check_data($dbh, \@p1, \@p2); + + # update all rows b column to 'fred' checking rows affected is 5 + $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); + # NOTE, this also checks you can pass a scalar to bind_param_array + $sth->bind_param_array(1, 'fred'); + $sth->bind_param_array(2, \@p1); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 5, + tuple => [1, 1, 1, 1, 1], %$ref}); + check_data($dbh, \@p1, [qw(fred fred fred fred fred)]); + + # update 4 rows column b to 'dave' checking rows affected is 4 + $sth = $dbh->prepare(qq/update $table set b = ? where a = ?/); + # NOTE, this also checks you can pass a scalar to bind_param_array + $sth->bind_param_array(1, 'dave'); + my @pe1 = @p1; + $pe1[-1] = 10; # non-existant row + $sth->bind_param_array(2, \@pe1); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 5, affected => 4, + tuple => [1, 1, 1, 1, '0E0'], %$ref}); + check_data($dbh, \@p1, [qw(dave dave dave dave fred)]); + + # now change all rows b column to 'pete' - this will change all 5 + # rows even though we have 2 rows of parameters so we can see if + # the rows affected is > parameter rows + $sth = $dbh->prepare(qq/update $table set b = ? where b like ?/); + # NOTE, this also checks you can pass a scalar to bind_param_array + $sth->bind_param_array(1, 'pete'); + $sth->bind_param_array(2, ['dave%', 'fred%']); + $self->insert($dbh, $sth, + {commit => 0, error => 0, sts => 2, affected => 5, + tuple => [4, 1], %$ref}); + check_data($dbh, \@p1, [qw(pete pete pete pete pete)]); +} + +sub enable_mars { + my $dbh = shift; + + # this test uses multiple active statements + # if we recognise the driver and it supports MAS enable it + my $driver_name = $dbh->get_info(6) || ''; + if (($driver_name eq 'libessqlsrv.so') || + ($driver_name =~ /libsqlncli/)) { + my $dsn = $ENV{DBI_DSN}; + if ($dsn !~ /^dbi:ODBC:DSN=/ && $dsn !~ /DRIVER=/i) { + my @a = split(q/:/, $ENV{DBI_DSN}); + $dsn = join(q/:/, @a[0..($#a - 1)]) . ":DSN=" . $a[-1]; + } + $dsn .= ";MARS_Connection=yes"; + $dbh->disconnect; + $dbh = DBI->connect($dsn, $ENV{DBI_USER}, $ENV{DBI_PASS}); + } + return $dbh; +} + +1; From 6b9cdaad82a3527c55f34b1b82672ab5d5a09a46 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 30 Oct 2012 13:12:45 +0000 Subject: [PATCH 343/637] rt 80487 - skip xmltype test when oracle < 9 fix newly introduced issue in 26exe_array.t - forget to update INC to pickup new pm git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15461 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 3 +++ t/26exe_array.t | 2 ++ t/32xmltype.t | 8 +++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 0e53c81d..0c17753c 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,9 @@ NEXT_VERSION resulted in an undefined warning. Thanks to Steffen Goeldner for RT and patches. + - Fix RT80487. Skip XMLType tests if Oracle less than V9. Thanks to + Steffen Goeldner. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a diff --git a/t/26exe_array.t b/t/26exe_array.t index 8a4519fe..1b4f0e66 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -9,6 +9,8 @@ use strict; use Data::Dumper; require 'nchar_test_lib.pl'; +use lib './t'; + $| = 1; my $has_test_nowarnings = 1; diff --git a/t/32xmltype.t b/t/32xmltype.t index 98544b97..7f413fb3 100644 --- a/t/32xmltype.t +++ b/t/32xmltype.t @@ -13,7 +13,7 @@ require 'nchar_test_lib.pl'; ## By John Scoles, The Pythian Group ## ---------------------------------------------------------------------------- ## Just a few checks to see if one can insert small and large xml files -## Nothing fancy. +## Nothing fancy. ## ---------------------------------------------------------------------------- # create a database handle @@ -21,11 +21,13 @@ my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, +eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, AutoCommit=>1, PrintError => 0 })}; if ($dbh) { + plan skip_all => "XMLTYPE new in Oracle 9" + if $dbh->func('ora_server_version')->[0] < 9; plan tests => 3; } else { plan skip_all => "Unable to connect to Oracle" @@ -65,7 +67,7 @@ $large_xml=$large_xml.""; $stmt = "INSERT INTO ".$table." VALUES (1,?)"; $sth =$dbh-> prepare($stmt); - + $sth-> bind_param(1, $small_xml, { ora_type => ORA_XMLTYPE }); ok ($sth->execute(), '... execute for small XML return true'); From d4708344ec8a70665de21e34641d92cd3f3c330d Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 30 Oct 2012 13:17:25 +0000 Subject: [PATCH 344/637] Improved 31lob_extended.t which supports Oracle 8. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15462 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ t/31lob_extended.t | 40 ++++++++++++---------------------------- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/Changes b/Changes index 0c17753c..8bce3b8b 100644 --- a/Changes +++ b/Changes @@ -16,6 +16,10 @@ NEXT_VERSION - Fix RT80487. Skip XMLType tests if Oracle less than V9. Thanks to Steffen Goeldner. + - Fix RT80486 for 31lob_extended.t. In old old Oracle8, + SYS_REFCURSOR is not defined. Instead of CREATE/DROP PROCEDURE, + use anonymous block. Thanks to Steffen Goeldner. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a diff --git a/t/31lob_extended.t b/t/31lob_extended.t index 3c084065..f507fd24 100644 --- a/t/31lob_extended.t +++ b/t/31lob_extended.t @@ -30,7 +30,7 @@ my $dbh = DBI->connect($dsn, $dbuser, '',{ }); if ($dbh) { - plan tests => 31; + plan tests => 30; $dbh->{LongReadLen} = 7000; } else { plan skip_all => "Unable to connect to Oracle"; @@ -39,6 +39,14 @@ if ($dbh) { my ($table, $data0, $data1) = setup_test($dbh); +my $PLSQL = <<"PLSQL"; +BEGIN + OPEN ? FOR SELECT x FROM $table; +END; +PLSQL + +$dbh->{RaiseError} = 1; + # # bug in DBD::Oracle 1.21 where if ora_auto_lobs is not set and we attempt to # fetch from a table containing lobs which has more than one row @@ -49,9 +57,7 @@ my ($table, $data0, $data1) = setup_test($dbh); my ($sth1, $ev); - eval {$sth1 = $dbh->prepare( - q/begin p_DBD_Oracle_drop_me(?); end;/, {ora_auto_lob => 0}); - }; + eval {$sth1 = $dbh->prepare($PLSQL, {ora_auto_lob => 0});}; ok(!$@, "$testname - prepare call proc"); my $sth2; ok($sth1->bind_param_inout(1, \$sth2, 500, {ora_type => ORA_RSET}), @@ -80,10 +86,8 @@ my ($table, $data0, $data1) = setup_test($dbh); my ($sth1, $ev, $lob); - eval {$sth1 = $dbh->prepare( - # ora_auto_lobs is supposed to default to set - q/begin p_DBD_Oracle_drop_me(?); end;/); - }; + # ora_auto_lobs is supposed to default to set + eval {$sth1 = $dbh->prepare($PLSQL);}; ok(!$@, "$testname prepare call proc"); my $sth2; ok($sth1->bind_param_inout(1, \$sth2, 500, {ora_type => ORA_RSET}), @@ -153,20 +157,6 @@ sub setup_test BAIL_OUT("Failed to insert test data into $table - $@") if $@; ok(!$ev, "created test data"); - my $createproc = << "EOT"; -CREATE OR REPLACE PROCEDURE p_DBD_Oracle_drop_me(pc OUT SYS_REFCURSOR) AS -l_cursor SYS_REFCURSOR; -BEGIN -OPEN l_cursor FOR - SELECT x from $table; -pc := l_cursor; -END; -EOT - - eval {$h->do($createproc);}; - BAIL_OUT("Failed to create test procedure - $@") if $@; - ok(!$ev, "created test procedure"); - return ($table, $data0, $data1); } @@ -176,12 +166,6 @@ END { local $dbh->{PrintError} = 0; local $dbh->{RaiseError} = 1; - eval {$dbh->do(q/drop procedure p_DBD_Oracle_drop_me/);}; - if ($@) { - diag("procedure p_DBD_Oracle_drop_me possibly not dropped" . - "- check - $@\n") if $dbh->err ne '4043'; - } - eval {drop_table($dbh);}; if ($@) { diag("table $table possibly not dropped - check - $@\n") From f5a38bafaebc801965454d2bb0579b4bd2dbedc4 Mon Sep 17 00:00:00 2001 From: byterock Date: Tue, 30 Oct 2012 23:50:07 +0000 Subject: [PATCH 345/637] fix memory leak in execute array (John Scoles, Pierre-Alain Blanc) git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15463 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ dbdimp.c | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 8bce3b8b..a01954a8 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,8 @@ Revision history for DBD::Oracle NEXT_VERSION [BUG FIXES] + + - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails can contain the wrong error count. Thanks to Steffen Goeldner for diff --git a/dbdimp.c b/dbdimp.c index 91099bbd..a69aa4ea 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3684,15 +3684,16 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er STRLEN len; int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0; int *utf8_flgs; - tuples_utf8_av=newAV(); + tuples_utf8_av = newAV(); + sv_2mortal((SV*)tuples_utf8_av); if (debug >= 2 || dbd_verbose >= 3 ) PerlIO_printf( - DBIc_LOGPIO(imp_sth), - " ora_st_execute_array %s count=%d (%s %s %s)...\n", - oci_stmt_type_name(imp_sth->stmt_type), exe_count, - neatsvpv(tuples,0), neatsvpv(tuples_status,0), - neatsvpv(columns, 0)); + DBIc_LOGPIO(imp_sth), + " ora_st_execute_array %s count=%d (%s %s %s)...\n", + oci_stmt_type_name(imp_sth->stmt_type), exe_count, + neatsvpv(tuples,0), neatsvpv(tuples_status,0), + neatsvpv(columns, 0)); if (is_select) { croak("ora_st_execute_array(): SELECT statement not supported " From 2e2a76e803d4a9ed75c236ced3a202f53c02a1bb Mon Sep 17 00:00:00 2001 From: byterock Date: Wed, 31 Oct 2012 00:09:56 +0000 Subject: [PATCH 346/637] simple code clean up, replacing 3 uses of safemalloc with Newz git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15464 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ dbdimp.c | 10 +++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index a01954a8..c52fed89 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,8 @@ NEXT_VERSION [BUG FIXES] + - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) + - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails diff --git a/dbdimp.c b/dbdimp.c index a69aa4ea..1eb8a36d 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1411,7 +1411,7 @@ phs_t *phs; /* allocate room for copy of statement with spare capacity */ /* for editing '?' or ':1' into ':p1' so we can use obndrv. */ /* XXX should use SV and append to it */ - imp_sth->statement = (char*)safemalloc(strlen(statement) * 10); + Newz(0,imp_sth->statement,strlen(statement) * 10,char); /* initialise phs ready to be cloned per placeholder */ memset(&phs_tpl, 0, sizeof(phs_tpl)); @@ -3746,10 +3746,8 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er Still ensures proper OCIBindByName*/ param_count=DBIc_NUM_PARAMS(imp_sth); - phs = safemalloc(param_count*sizeof(*phs)); - utf8_flgs = safemalloc(param_count*sizeof(int)); - memset(phs, 0, param_count*sizeof(*phs)); - memset(utf8_flgs, 0, param_count*sizeof(int)); + Newz(0,phs,param_count*sizeof(*phs),phs_t *); + Newz(0,utf8_flgs,param_count*sizeof(int),int); for(j = 0; (unsigned int) j < exe_count; j++) { /* Fill in 'unknown' exe count in every element (know not how to get @@ -3838,8 +3836,6 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er } } } - Safefree(phs); - Safefree(utf8_flgs); /* Store array of bind typles, for use in OCIBindDynamic() callback. */ imp_sth->bind_tuples = tuples_av; imp_sth->rowwise = (columns_av == NULL); From 2070f1d8ed74165ae29171c8a1edf8db157f914e Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 31 Oct 2012 09:04:53 +0000 Subject: [PATCH 347/637] 39attr.t could fail if using oracle client > 11 but not >= 11.2 minor code formatting changes in Oracle.pm document ora_server_version remove empty h1 in Oracle.pm git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15465 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 12 +++++++++--- lib/DBD/Oracle.pm | 45 ++++++++++++++++++++++++++------------------- t/39attr.t | 34 ++++++++++++++++++++++------------ 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/Changes b/Changes index c52fed89..6b9c6297 100644 --- a/Changes +++ b/Changes @@ -3,9 +3,7 @@ Revision history for DBD::Oracle NEXT_VERSION [BUG FIXES] - - - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) - + - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails @@ -24,6 +22,11 @@ NEXT_VERSION SYS_REFCURSOR is not defined. Instead of CREATE/DROP PROCEDURE, use anonymous block. Thanks to Steffen Goeldner. + - Fix bug in 39attr.t which could fail if using an Oracle Client > + 11 but not >= 11.2 (Martin J. Evans) + + - ora_server_version was not documented. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a @@ -32,6 +35,9 @@ NEXT_VERSION above). To make keeping them in synch easier I've modularised the tests. Hence new ExecuteArray.pm. (Martin J. Evans) + - simple code clean up, replacing 3 uses of safemalloc with Newz + (John Scoles) + 1.52 2012-10-19 diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index e1f4f06a..185b6708 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -976,30 +976,29 @@ SQL } sub dbms_msgpipe_ack { - my $dbh = shift; - my $msg = shift; - my $sth = $dbh->prepare_cached(q{ - begin dbms_msgpipe.acknowledge(:returnpipe, :errormsg, :param); end; - }) or return; - $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); - $sth->bind_param_inout(":proc", \$msg->[1], 30); - $sth->bind_param_inout(":param", \$msg->[2], 4000); - $sth->execute or return undef; - return 1; + my $dbh = shift; + my $msg = shift; + my $sth = $dbh->prepare_cached(q{ + begin dbms_msgpipe.acknowledge(:returnpipe, :errormsg, :param); end;}) or return; + $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); + $sth->bind_param_inout(":proc", \$msg->[1], 30); + $sth->bind_param_inout(":param", \$msg->[2], 4000); + $sth->execute or return undef; + return 1; } sub ora_server_version { - my $dbh = shift; - return $dbh->{ora_server_version} if defined $dbh->{ora_server_version}; - my $banner = $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%'); + my $dbh = shift; + return $dbh->{ora_server_version} if defined $dbh->{ora_server_version}; + my $banner = $dbh->selectrow_array(<<'SQL', undef, 'Oracle%', 'Personal Oracle%'); SELECT banner FROM v$version WHERE banner LIKE ? OR banner LIKE ? SQL - if (defined $banner) { - my @version = $banner =~ /(?:^|\s)(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\s|$)/; - $dbh->{ora_server_version} = \@version if @version; - } + if (defined $banner) { + my @version = $banner =~ /(?:^|\s)(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\s|$)/; + $dbh->{ora_server_version} = \@version if @version; + } } sub ora_nls_parameters { @@ -2188,6 +2187,16 @@ Returns a hash reference containing the current NLS parameters, as given by the v$nls_parameters view. The values fetched are cached between calls. To cause the latest values to be fetched, pass a true value to the function. +=head1 ORACLE-SPECIFIC DATABASE FUNCTIONS + +=head2 B + + $versions = $dbh->func('ora_server_version'); + +Returns an array reference of server version strings e.g., + + [11,2,0,2,0] + =head1 DATABASE HANDLE METHODS =head2 B @@ -5351,8 +5360,6 @@ you may not be aware of. A git mirror of the subversion is also available at `https://github.com/yanick/DBD-Oracle`. -=head1 Oracle Related Links - =head1 WHICH VERSION OF DBD::ORACLE IS FOR ME? From version 1.25 onwards DBD::Oracle only support Oracle clients diff --git a/t/39attr.t b/t/39attr.t index a352977e..12a5a669 100755 --- a/t/39attr.t +++ b/t/39attr.t @@ -33,23 +33,33 @@ sub do_it { my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } or plan skip_all => "Unable to connect to Oracle"; + diag("Oracle version: " . join(".", @{$dbh->func('ora_server_version')})); + diag("client version: " . ORA_OCI()); + SKIP: { my @attrs = (qw(ora_module_name - ora_driver_name - ora_client_info - ora_client_identifier - ora_action)); - skip('Oracle OCI too old', 1 + @attrs) if ORA_OCI() < 11; - - like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); - foreach my $attr (qw(ora_module_name - ora_driver_name - ora_client_info - ora_client_identifier - ora_action)) { + ora_client_info + ora_client_identifier + ora_action)); + my @attrs112 = (qw(ora_driver_name)); + + skip('Oracle OCI too old', 1 + @attrs + @attrs112) if ORA_OCI() < 11; + + foreach my $attr (@attrs) { $dbh->{$attr} = 'fred'; is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); } + + SKIP: { + skip 'Oracle OCI too old', 1 + @attrs112 if ORA_OCI() < 11.2; + + like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); + + foreach my $attr (@attrs) { + $dbh->{$attr} = 'fred'; + is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); + } + } }; foreach my $attr (qw(ora_oci_success_warn From 8581c5ac61f48ff0b9430190ee59714f71dac519 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 2 Nov 2012 19:59:09 +0000 Subject: [PATCH 348/637] Fix RT 80566 - patch from Steffen git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15467 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ lib/DBD/Oracle.pm | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index 6b9c6297..21f9e958 100644 --- a/Changes +++ b/Changes @@ -27,6 +27,10 @@ NEXT_VERSION - ora_server_version was not documented. + - Fix RT80566. 70meta.t test fails with Oracle 8 because + ALL_TAB_COLUMNS.CHAR_LENGTH is new in Oracle 9. Use DATA_LENGTH + instead on pre-9 versions. Thanks to Steffen Goeldner. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9700b04b..661e20a5 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -606,8 +606,9 @@ SQL my $dbh = shift; my $attr = ( ref $_[0] eq 'HASH') ? $_[0] : { 'TABLE_SCHEM' => $_[1],'TABLE_NAME' => $_[2],'COLUMN_NAME' => $_[3] }; + my $ora_server_version = ora_server_version($dbh); my($typecase,$typecaseend) = ('',''); - if (ora_server_version($dbh)->[0] >= 8) { + if ($ora_server_version->[0] >= 8) { $typecase = <<'SQL'; CASE WHEN tc.DATA_TYPE LIKE 'TIMESTAMP% WITH% TIME ZONE' THEN 95 WHEN tc.DATA_TYPE LIKE 'TIMESTAMP%' THEN 93 @@ -617,6 +618,7 @@ ELSE SQL $typecaseend = 'END'; } + my $char_length = $ora_server_version->[0] < 9 ? 'DATA_LENGTH':'CHAR_LENGTH'; my $SQL = <<"SQL"; SELECT * FROM @@ -661,10 +663,10 @@ SELECT * ) , 'FLOAT' , tc.DATA_PRECISION , 'DATE' , 19 - , 'VARCHAR2' , tc.CHAR_LENGTH - , 'CHAR' , tc.CHAR_LENGTH - , 'NVARCHAR2', tc.CHAR_LENGTH - , 'NCHAR' , tc.CHAR_LENGTH + , 'VARCHAR2' , tc.$char_length + , 'CHAR' , tc.$char_length + , 'NVARCHAR2', tc.$char_length + , 'NCHAR' , tc.$char_length , tc.DATA_LENGTH ) COLUMN_SIZE , decode( tc.DATA_TYPE From 6b28b6da73590d6dd76178375e0827e167e4e7b5 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 2 Nov 2012 19:59:09 +0000 Subject: [PATCH 349/637] Fix RT 80566 - patch from Steffen git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15467 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ lib/DBD/Oracle.pm | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index 6b9c6297..21f9e958 100644 --- a/Changes +++ b/Changes @@ -27,6 +27,10 @@ NEXT_VERSION - ora_server_version was not documented. + - Fix RT80566. 70meta.t test fails with Oracle 8 because + ALL_TAB_COLUMNS.CHAR_LENGTH is new in Oracle 9. Use DATA_LENGTH + instead on pre-9 versions. Thanks to Steffen Goeldner. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9700b04b..661e20a5 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -606,8 +606,9 @@ SQL my $dbh = shift; my $attr = ( ref $_[0] eq 'HASH') ? $_[0] : { 'TABLE_SCHEM' => $_[1],'TABLE_NAME' => $_[2],'COLUMN_NAME' => $_[3] }; + my $ora_server_version = ora_server_version($dbh); my($typecase,$typecaseend) = ('',''); - if (ora_server_version($dbh)->[0] >= 8) { + if ($ora_server_version->[0] >= 8) { $typecase = <<'SQL'; CASE WHEN tc.DATA_TYPE LIKE 'TIMESTAMP% WITH% TIME ZONE' THEN 95 WHEN tc.DATA_TYPE LIKE 'TIMESTAMP%' THEN 93 @@ -617,6 +618,7 @@ ELSE SQL $typecaseend = 'END'; } + my $char_length = $ora_server_version->[0] < 9 ? 'DATA_LENGTH':'CHAR_LENGTH'; my $SQL = <<"SQL"; SELECT * FROM @@ -661,10 +663,10 @@ SELECT * ) , 'FLOAT' , tc.DATA_PRECISION , 'DATE' , 19 - , 'VARCHAR2' , tc.CHAR_LENGTH - , 'CHAR' , tc.CHAR_LENGTH - , 'NVARCHAR2', tc.CHAR_LENGTH - , 'NCHAR' , tc.CHAR_LENGTH + , 'VARCHAR2' , tc.$char_length + , 'CHAR' , tc.$char_length + , 'NVARCHAR2', tc.$char_length + , 'NCHAR' , tc.$char_length , tc.DATA_LENGTH ) COLUMN_SIZE , decode( tc.DATA_TYPE From 573c9bf801b0e8e3b313e5eca6bcdb4224927e64 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 2 Nov 2012 20:10:51 +0000 Subject: [PATCH 350/637] Fix consistency in Changes I entered for Steffen. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15468 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index 21f9e958..57e7439f 100644 --- a/Changes +++ b/Changes @@ -13,14 +13,14 @@ NEXT_VERSION - Fix RT80375 - no exception when execute_for_fetch fails and ArrayTupleStatus is not specified. Also the tuple count calculation resulted in an undefined warning. Thanks to Steffen Goeldner for - RT and patches. + RT and patch. - Fix RT80487. Skip XMLType tests if Oracle less than V9. Thanks to - Steffen Goeldner. + Steffen Goeldner for RT and patch. - Fix RT80486 for 31lob_extended.t. In old old Oracle8, SYS_REFCURSOR is not defined. Instead of CREATE/DROP PROCEDURE, - use anonymous block. Thanks to Steffen Goeldner. + use anonymous block. Thanks to Steffen Goeldner for RT and patch. - Fix bug in 39attr.t which could fail if using an Oracle Client > 11 but not >= 11.2 (Martin J. Evans) @@ -29,7 +29,8 @@ NEXT_VERSION - Fix RT80566. 70meta.t test fails with Oracle 8 because ALL_TAB_COLUMNS.CHAR_LENGTH is new in Oracle 9. Use DATA_LENGTH - instead on pre-9 versions. Thanks to Steffen Goeldner. + instead on pre-9 versions. Thanks to Steffen Goeldner for RT and + patch. [MISCELLANEOUS] From 8cd391e9fe012cde91f7349bff953e21126947bb Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 2 Nov 2012 20:10:51 +0000 Subject: [PATCH 351/637] Fix consistency in Changes I entered for Steffen. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15468 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index 21f9e958..57e7439f 100644 --- a/Changes +++ b/Changes @@ -13,14 +13,14 @@ NEXT_VERSION - Fix RT80375 - no exception when execute_for_fetch fails and ArrayTupleStatus is not specified. Also the tuple count calculation resulted in an undefined warning. Thanks to Steffen Goeldner for - RT and patches. + RT and patch. - Fix RT80487. Skip XMLType tests if Oracle less than V9. Thanks to - Steffen Goeldner. + Steffen Goeldner for RT and patch. - Fix RT80486 for 31lob_extended.t. In old old Oracle8, SYS_REFCURSOR is not defined. Instead of CREATE/DROP PROCEDURE, - use anonymous block. Thanks to Steffen Goeldner. + use anonymous block. Thanks to Steffen Goeldner for RT and patch. - Fix bug in 39attr.t which could fail if using an Oracle Client > 11 but not >= 11.2 (Martin J. Evans) @@ -29,7 +29,8 @@ NEXT_VERSION - Fix RT80566. 70meta.t test fails with Oracle 8 because ALL_TAB_COLUMNS.CHAR_LENGTH is new in Oracle 9. Use DATA_LENGTH - instead on pre-9 versions. Thanks to Steffen Goeldner. + instead on pre-9 versions. Thanks to Steffen Goeldner for RT and + patch. [MISCELLANEOUS] From 292188cef5f7695a32090717120e3feafccede6b Mon Sep 17 00:00:00 2001 From: Joe Crotty Date: Fri, 2 Nov 2012 17:04:31 -0600 Subject: [PATCH 352/637] github issue #33 DBI configure dependency fix Configure phase of build now pulls DBI prereq. Change-Id: I60166f40cd4f7448e19a9ef3cfc24a7450427f5f --- Changes | 2 ++ dist.ini | 3 +++ 2 files changed, 5 insertions(+) diff --git a/Changes b/Changes index 6b9c6297..0b2c9b5a 100644 --- a/Changes +++ b/Changes @@ -38,6 +38,8 @@ NEXT_VERSION - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) + - Add DBI as a configure prereq for the META* files (thanks to Joe Crotty) + 1.52 2012-10-19 diff --git a/dist.ini b/dist.ini index 718edb31..ce9f8ac9 100644 --- a/dist.ini +++ b/dist.ini @@ -27,6 +27,9 @@ authority=cpan:PYTHIAN -remove=Test::Compile -remove=Covenant +[Prereqs / ConfigureRequires] +DBI = 1.51 + [FakeRelease] [HelpWanted] positions = coder documentation tester From a9f3f6e9a4723ff2a85add83d268a25ba1e82e74 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 9 Nov 2012 09:48:43 +0000 Subject: [PATCH 353/637] another fix from steffen for 51scroll git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15469 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++++- t/51scroll.t | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 57e7439f..1e45fad7 100644 --- a/Changes +++ b/Changes @@ -32,6 +32,10 @@ NEXT_VERSION instead on pre-9 versions. Thanks to Steffen Goeldner for RT and patch. + - Fix RT80704. 51scroll.t test checks scrollable cursors but assumes + all Oracles support them (only 9 and above). Thanks to Steffen + Goeldner for RT and patch. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a @@ -43,7 +47,6 @@ NEXT_VERSION - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) - 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/t/51scroll.t b/t/51scroll.t index 24266bab..16b5676d 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -24,6 +24,8 @@ eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, AutoCommit=>1, PrintError => 0 })}; if ($dbh) { + plan skip_all => "Scrollable cursors new in Oracle 9" + if $dbh->func('ora_server_version')->[0] < 9; plan tests => 36; } else { plan skip_all => "Unable to connect to Oracle"; From 46d8e3e7013f4d32e6aa412e7fe3a8a1b8407ec4 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 9 Nov 2012 09:48:43 +0000 Subject: [PATCH 354/637] another fix from steffen for 51scroll git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15469 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++++- t/51scroll.t | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 57e7439f..1e45fad7 100644 --- a/Changes +++ b/Changes @@ -32,6 +32,10 @@ NEXT_VERSION instead on pre-9 versions. Thanks to Steffen Goeldner for RT and patch. + - Fix RT80704. 51scroll.t test checks scrollable cursors but assumes + all Oracles support them (only 9 and above). Thanks to Steffen + Goeldner for RT and patch. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a @@ -43,7 +47,6 @@ NEXT_VERSION - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) - 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/t/51scroll.t b/t/51scroll.t index 24266bab..16b5676d 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -24,6 +24,8 @@ eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, AutoCommit=>1, PrintError => 0 })}; if ($dbh) { + plan skip_all => "Scrollable cursors new in Oracle 9" + if $dbh->func('ora_server_version')->[0] < 9; plan tests => 36; } else { plan skip_all => "Unable to connect to Oracle"; From 7f5435f3920706d3e28da68917466bac598b50fc Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 9 Nov 2012 15:51:27 +0000 Subject: [PATCH 355/637] use unix line endings git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15470 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/58object.t | 524 +++++++++++++++++++++++++-------------------------- 1 file changed, 262 insertions(+), 262 deletions(-) diff --git a/t/58object.t b/t/58object.t index 28be915e..9144a453 100644 --- a/t/58object.t +++ b/t/58object.t @@ -1,262 +1,262 @@ -#!perl -w - -use DBI; -use DBD::Oracle qw(ORA_RSET SQLCS_NCHAR); -use strict; -use Data::Dumper; - -use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - -$| = 1; - -$ENV{NLS_DATE_FORMAT} = 'YYYY-MM-DD"T"HH24:MI:SS'; - -# create a database handle -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '',{ RaiseError=>1, - AutoCommit=>1, - PrintError => 0, - ora_objects => 1 })}; - -plan skip_all => "Unable to connect to Oracle" unless $dbh; - -plan tests => 65; - -my ($schema) = $dbuser =~ m{^([^/]*)}; - -# Test ora_objects flag -is $dbh->{ora_objects} => 1, 'ora_objects flag is set to 1'; - -$dbh->{ora_objects} = 0; -is $dbh->{ora_objects} => 0, 'ora_objects flag is set to 0'; - -# check that our db handle is good -isa_ok($dbh, "DBI::db"); - - -ok( $schema = $dbh->selectrow_array( - "select sys_context('userenv', 'current_schema') from dual" -), 'Fetch current schema name'); - - -my $obj_prefix = "dbd_test_"; -my $super_type = "${obj_prefix}_type_A"; -my $sub_type = "${obj_prefix}_type_B"; -my $table = "${obj_prefix}_obj_table"; -my $outer_type = "${obj_prefix}_outer_type"; -my $inner_type = "${obj_prefix}_inner_type"; -my $list_type = "${obj_prefix}_list_type"; -my $nest_table = "${obj_prefix}_nest_table"; -my $list_table = "${obj_prefix}_list_table"; - -sub drop_test_objects { - for my $obj ("TABLE $list_table", "TABLE $nest_table", - "TYPE $list_type", "TYPE $outer_type", "TYPE $inner_type", - "TABLE $table", "TYPE $sub_type", "TYPE $super_type") { - #do not warn if already there - eval { - local $dbh->{PrintError} = 0; - $dbh->do(qq{drop $obj}); - }; - } -} - -&drop_test_objects; - -# get the user's privileges -my $privs_sth = $dbh->prepare( 'SELECT PRIVILEGE from session_privs' ); -$privs_sth->execute; -my @privileges = map { $_->[0] } @{ $privs_sth->fetchall_arrayref }; - - -SKIP: { - skip q{don't have permission to create type} => 61 - unless grep { $_ eq 'CREATE TYPE' } @privileges; - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $super_type AS OBJECT ( - num INTEGER, - name VARCHAR2(20) - ) NOT FINAL } ); - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $sub_type UNDER $super_type ( - datetime DATE, - amount NUMERIC(10,5) - ) NOT FINAL } ); - -sql_do_ok( $dbh, qq{ CREATE TABLE $table (id INTEGER, obj $super_type) }); - -sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (1, $super_type(13, 'obj1')) }); - -sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (2, $sub_type(NULL, 'obj2', - TO_DATE('2004-11-30 14:27:18', 'YYYY-MM-DD HH24:MI:SS'), - 12345.6789)) } - ); - -sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (3, $sub_type(5, 'obj3', NULL, - 777.666)) } ); - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $inner_type AS OBJECT ( - num INTEGER, - name VARCHAR2(20) - ) FINAL }); - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $outer_type AS OBJECT ( - num INTEGER, - obj $inner_type - ) FINAL }); - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $list_type AS - TABLE OF $inner_type }); - -sql_do_ok( $dbh, qq{ CREATE TABLE $nest_table(obj $outer_type) }); - -sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(91, $inner_type(1, 'one'))) } - ); - -sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(92, $inner_type(0, null))) } - ); - -sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(93, null)) } -); - -sql_do_ok( $dbh, qq{ CREATE TABLE $list_table ( id INTEGER, list $list_type ) - NESTED TABLE list STORE AS ${list_table}_list }); - -sql_do_ok( $dbh, qq{ INSERT INTO $list_table VALUES(81,$list_type($inner_type(null, 'listed'))) } ); -# Test old (backward compatible) interface - -# test select testing objects -my $sth = $dbh->prepare("select * from $table order by id"); -ok ($sth, 'old: Prepare select'); -ok ($sth->execute(), 'old: Execute select'); - -my @row1 = $sth->fetchrow(); -ok (scalar @row1, 'old: Fetch first row'); -cmp_ok(ref $row1[1], 'eq', 'ARRAY', 'old: Row 1 column 2 is an ARRAY'); -cmp_ok(scalar(@{$row1[1]}), '==', 2, 'old: Row 1 column 2 is has 2 elements'); - -my @row2 = $sth->fetchrow(); -ok (scalar @row2, 'old: Fetch second row'); -cmp_ok(ref $row2[1], 'eq', 'ARRAY', 'old: Row 2 column 2 is an ARRAY'); -cmp_ok(scalar(@{$row2[1]}), '==', 2, 'old: Row 2 column 2 is has 2 elements'); - -my @row3 = $sth->fetchrow(); -ok (scalar @row3, 'old: Fetch third row'); -cmp_ok(ref $row3[1], 'eq', 'ARRAY', 'old: Row 3 column 2 is an ARRAY'); -cmp_ok(scalar(@{$row3[1]}), '==', 2, 'old: Row 3 column 2 is has 2 elements'); - -ok (!$sth->fetchrow(), 'old: No more rows expected'); - -#print STDERR Dumper(\@row1, \@row2, \@row3); - -# Test new (extended) object interface - -# enable extended object support -$dbh->{ora_objects} = 1; - -# test select testing objects - in extended mode -$sth = $dbh->prepare("select * from $table order by id"); -ok ($sth, 'new: Prepare select'); -ok ($sth->execute(), 'new: Execute select'); - - -@row1 = $sth->fetchrow(); -ok (scalar @row1, 'new: Fetch first row'); -cmp_ok(ref $row1[1], 'eq', 'DBD::Oracle::Object', 'new: Row 1 column 2 is an DBD:Oracle::Object'); -cmp_ok(uc $row1[1]->type_name, "eq", uc "$schema.$super_type", "new: Row 1 column 2 object type"); -is_deeply([$row1[1]->attributes], ['NUM', 13, 'NAME', 'obj1'], "new: Row 1 column 2 object attributes"); - -@row2 = $sth->fetchrow(); -ok (scalar @row2, 'new: Fetch second row'); -cmp_ok(ref $row2[1], 'eq', 'DBD::Oracle::Object', 'new: Row 2 column 2 is an DBD::Oracle::Object'); -cmp_ok(uc $row2[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 2 column 2 object type"); - -my %attrs = $row2[1]->attributes; - -$attrs{AMOUNT} = sprintf "%9.4f", $attrs{AMOUNT}; - -is_deeply( \%attrs, {'NUM', undef, 'NAME', 'obj2', - 'DATETIME', '2004-11-30T14:27:18', 'AMOUNT', '12345.6789'}, "new: Row 1 column 2 object attributes"); - -@row3 = $sth->fetchrow(); -ok (scalar @row3, 'new: Fetch third row'); -cmp_ok(ref $row3[1], 'eq', 'DBD::Oracle::Object', 'new: Row 3 column 2 is an DBD::Oracle::Object'); -cmp_ok(uc $row3[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 3 column 2 object type"); - -%attrs = $row3[1]->attributes; -$attrs{AMOUNT} = sprintf "%6.3f", $attrs{AMOUNT}; - -is_deeply( \%attrs, {'NUM', 5, 'NAME', 'obj3', - 'DATETIME', undef, 'AMOUNT', '777.666'}, "new: Row 1 column 2 object attributes"); - -ok (!$sth->fetchrow(), 'new: No more rows expected'); - -#print STDERR Dumper(\@row1, \@row2, \@row3); - -# Test DBD::Oracle::Object -my $obj = $row3[1]; -my $expected_hash = { - NUM => 5, - NAME => 'obj3', - DATETIME => undef, - AMOUNT => 777.666, - }; -my $attrs = $obj->attr_hash; -$attrs->{AMOUNT} = sprintf "%6.3f", $attrs->{AMOUNT}; - -is_deeply($attrs, $expected_hash, 'DBD::Oracle::Object->attr_hash'); -is_deeply($obj->attr, $expected_hash, 'DBD::Oracle::Object->attr'); -is($obj->attr("NAME"), 'obj3', 'DBD::Oracle::Object->attr("NAME")'); - -# try the list table -$sth = $dbh->prepare("select * from $list_table"); -ok ($sth, 'new: Prepare select with nested table of objects'); -ok ($sth->execute(), 'new: Execute (nested table)'); - -@row1 = $sth->fetchrow(); -ok (scalar @row1, 'new: Fetch first row (nested table)'); -is_deeply($row1[1]->[0]->attr, {NUM=>undef, NAME=>'listed'}, - 'Check propertes of first (and only) item in nested table'); - -ok (!$sth->fetchrow(), 'new: No more rows expected (nested table)'); - -#try the nested table -$sth = $dbh->prepare("select * from $nest_table"); -ok ($sth, 'new: Prepare select with nested object'); -ok ($sth->execute(), 'new: Execute (nested object)'); - -@row1 = $sth->fetchrow(); -ok (scalar @row1, 'new: Fetch first row (nested object)'); -is($row1[0]->attr->{NUM}, '91', 'Check obj.num'); -is_deeply($row1[0]->attr->{OBJ}->attr, {NUM=>'1', NAME=>'one'}, 'Check obj.obj'); - -@row2 = $sth->fetchrow(); -ok (scalar @row2, 'new: Fetch second row (nested object)'); -is($row2[0]->attr->{NUM}, '92', 'Check obj.num'); -is_deeply($row2[0]->attr->{OBJ}->attr, {NUM=>'0', NAME=>undef}, 'Check obj.obj'); - -@row3 = $sth->fetchrow(); -ok (scalar @row3, 'new: Fetch third row (nested object)'); -is_deeply($row3[0]->attr, {NUM=>'93', OBJ=>undef}, 'Check obj'); - -ok (!$sth->fetchrow(), 'new: No more rows expected (nested object)'); - -} - -#cleanup -&drop_test_objects; -$dbh->disconnect; - -1; - - -sub sql_do_ok { - my ( $dbh, $sql, $title ) = @_; - $title = $sql unless defined $title; - ok( $dbh->do( $sql ), $title ) or diag $dbh->errstr; -} - +#!perl -w + +use DBI; +use DBD::Oracle qw(ORA_RSET SQLCS_NCHAR); +use strict; +use Data::Dumper; + +use Test::More; +unshift @INC ,'t'; +require 'nchar_test_lib.pl'; + +$| = 1; + +$ENV{NLS_DATE_FORMAT} = 'YYYY-MM-DD"T"HH24:MI:SS'; + +# create a database handle +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dbh; +eval {$dbh = DBI->connect($dsn, $dbuser, '',{ RaiseError=>1, + AutoCommit=>1, + PrintError => 0, + ora_objects => 1 })}; + +plan skip_all => "Unable to connect to Oracle" unless $dbh; + +plan tests => 65; + +my ($schema) = $dbuser =~ m{^([^/]*)}; + +# Test ora_objects flag +is $dbh->{ora_objects} => 1, 'ora_objects flag is set to 1'; + +$dbh->{ora_objects} = 0; +is $dbh->{ora_objects} => 0, 'ora_objects flag is set to 0'; + +# check that our db handle is good +isa_ok($dbh, "DBI::db"); + + +ok( $schema = $dbh->selectrow_array( + "select sys_context('userenv', 'current_schema') from dual" +), 'Fetch current schema name'); + + +my $obj_prefix = "dbd_test_"; +my $super_type = "${obj_prefix}_type_A"; +my $sub_type = "${obj_prefix}_type_B"; +my $table = "${obj_prefix}_obj_table"; +my $outer_type = "${obj_prefix}_outer_type"; +my $inner_type = "${obj_prefix}_inner_type"; +my $list_type = "${obj_prefix}_list_type"; +my $nest_table = "${obj_prefix}_nest_table"; +my $list_table = "${obj_prefix}_list_table"; + +sub drop_test_objects { + for my $obj ("TABLE $list_table", "TABLE $nest_table", + "TYPE $list_type", "TYPE $outer_type", "TYPE $inner_type", + "TABLE $table", "TYPE $sub_type", "TYPE $super_type") { + #do not warn if already there + eval { + local $dbh->{PrintError} = 0; + $dbh->do(qq{drop $obj}); + }; + } +} + +&drop_test_objects; + +# get the user's privileges +my $privs_sth = $dbh->prepare( 'SELECT PRIVILEGE from session_privs' ); +$privs_sth->execute; +my @privileges = map { $_->[0] } @{ $privs_sth->fetchall_arrayref }; + + +SKIP: { + skip q{don't have permission to create type} => 61 + unless grep { $_ eq 'CREATE TYPE' } @privileges; + +sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $super_type AS OBJECT ( + num INTEGER, + name VARCHAR2(20) + ) NOT FINAL } ); + +sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $sub_type UNDER $super_type ( + datetime DATE, + amount NUMERIC(10,5) + ) NOT FINAL } ); + +sql_do_ok( $dbh, qq{ CREATE TABLE $table (id INTEGER, obj $super_type) }); + +sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (1, $super_type(13, 'obj1')) }); + +sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (2, $sub_type(NULL, 'obj2', + TO_DATE('2004-11-30 14:27:18', 'YYYY-MM-DD HH24:MI:SS'), + 12345.6789)) } + ); + +sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (3, $sub_type(5, 'obj3', NULL, + 777.666)) } ); + +sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $inner_type AS OBJECT ( + num INTEGER, + name VARCHAR2(20) + ) FINAL }); + +sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $outer_type AS OBJECT ( + num INTEGER, + obj $inner_type + ) FINAL }); + +sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $list_type AS + TABLE OF $inner_type }); + +sql_do_ok( $dbh, qq{ CREATE TABLE $nest_table(obj $outer_type) }); + +sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(91, $inner_type(1, 'one'))) } + ); + +sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(92, $inner_type(0, null))) } + ); + +sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(93, null)) } +); + +sql_do_ok( $dbh, qq{ CREATE TABLE $list_table ( id INTEGER, list $list_type ) + NESTED TABLE list STORE AS ${list_table}_list }); + +sql_do_ok( $dbh, qq{ INSERT INTO $list_table VALUES(81,$list_type($inner_type(null, 'listed'))) } ); +# Test old (backward compatible) interface + +# test select testing objects +my $sth = $dbh->prepare("select * from $table order by id"); +ok ($sth, 'old: Prepare select'); +ok ($sth->execute(), 'old: Execute select'); + +my @row1 = $sth->fetchrow(); +ok (scalar @row1, 'old: Fetch first row'); +cmp_ok(ref $row1[1], 'eq', 'ARRAY', 'old: Row 1 column 2 is an ARRAY'); +cmp_ok(scalar(@{$row1[1]}), '==', 2, 'old: Row 1 column 2 is has 2 elements'); + +my @row2 = $sth->fetchrow(); +ok (scalar @row2, 'old: Fetch second row'); +cmp_ok(ref $row2[1], 'eq', 'ARRAY', 'old: Row 2 column 2 is an ARRAY'); +cmp_ok(scalar(@{$row2[1]}), '==', 2, 'old: Row 2 column 2 is has 2 elements'); + +my @row3 = $sth->fetchrow(); +ok (scalar @row3, 'old: Fetch third row'); +cmp_ok(ref $row3[1], 'eq', 'ARRAY', 'old: Row 3 column 2 is an ARRAY'); +cmp_ok(scalar(@{$row3[1]}), '==', 2, 'old: Row 3 column 2 is has 2 elements'); + +ok (!$sth->fetchrow(), 'old: No more rows expected'); + +#print STDERR Dumper(\@row1, \@row2, \@row3); + +# Test new (extended) object interface + +# enable extended object support +$dbh->{ora_objects} = 1; + +# test select testing objects - in extended mode +$sth = $dbh->prepare("select * from $table order by id"); +ok ($sth, 'new: Prepare select'); +ok ($sth->execute(), 'new: Execute select'); + + +@row1 = $sth->fetchrow(); +ok (scalar @row1, 'new: Fetch first row'); +cmp_ok(ref $row1[1], 'eq', 'DBD::Oracle::Object', 'new: Row 1 column 2 is an DBD:Oracle::Object'); +cmp_ok(uc $row1[1]->type_name, "eq", uc "$schema.$super_type", "new: Row 1 column 2 object type"); +is_deeply([$row1[1]->attributes], ['NUM', 13, 'NAME', 'obj1'], "new: Row 1 column 2 object attributes"); + +@row2 = $sth->fetchrow(); +ok (scalar @row2, 'new: Fetch second row'); +cmp_ok(ref $row2[1], 'eq', 'DBD::Oracle::Object', 'new: Row 2 column 2 is an DBD::Oracle::Object'); +cmp_ok(uc $row2[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 2 column 2 object type"); + +my %attrs = $row2[1]->attributes; + +$attrs{AMOUNT} = sprintf "%9.4f", $attrs{AMOUNT}; + +is_deeply( \%attrs, {'NUM', undef, 'NAME', 'obj2', + 'DATETIME', '2004-11-30T14:27:18', 'AMOUNT', '12345.6789'}, "new: Row 1 column 2 object attributes"); + +@row3 = $sth->fetchrow(); +ok (scalar @row3, 'new: Fetch third row'); +cmp_ok(ref $row3[1], 'eq', 'DBD::Oracle::Object', 'new: Row 3 column 2 is an DBD::Oracle::Object'); +cmp_ok(uc $row3[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 3 column 2 object type"); + +%attrs = $row3[1]->attributes; +$attrs{AMOUNT} = sprintf "%6.3f", $attrs{AMOUNT}; + +is_deeply( \%attrs, {'NUM', 5, 'NAME', 'obj3', + 'DATETIME', undef, 'AMOUNT', '777.666'}, "new: Row 1 column 2 object attributes"); + +ok (!$sth->fetchrow(), 'new: No more rows expected'); + +#print STDERR Dumper(\@row1, \@row2, \@row3); + +# Test DBD::Oracle::Object +my $obj = $row3[1]; +my $expected_hash = { + NUM => 5, + NAME => 'obj3', + DATETIME => undef, + AMOUNT => 777.666, + }; +my $attrs = $obj->attr_hash; +$attrs->{AMOUNT} = sprintf "%6.3f", $attrs->{AMOUNT}; + +is_deeply($attrs, $expected_hash, 'DBD::Oracle::Object->attr_hash'); +is_deeply($obj->attr, $expected_hash, 'DBD::Oracle::Object->attr'); +is($obj->attr("NAME"), 'obj3', 'DBD::Oracle::Object->attr("NAME")'); + +# try the list table +$sth = $dbh->prepare("select * from $list_table"); +ok ($sth, 'new: Prepare select with nested table of objects'); +ok ($sth->execute(), 'new: Execute (nested table)'); + +@row1 = $sth->fetchrow(); +ok (scalar @row1, 'new: Fetch first row (nested table)'); +is_deeply($row1[1]->[0]->attr, {NUM=>undef, NAME=>'listed'}, + 'Check propertes of first (and only) item in nested table'); + +ok (!$sth->fetchrow(), 'new: No more rows expected (nested table)'); + +#try the nested table +$sth = $dbh->prepare("select * from $nest_table"); +ok ($sth, 'new: Prepare select with nested object'); +ok ($sth->execute(), 'new: Execute (nested object)'); + +@row1 = $sth->fetchrow(); +ok (scalar @row1, 'new: Fetch first row (nested object)'); +is($row1[0]->attr->{NUM}, '91', 'Check obj.num'); +is_deeply($row1[0]->attr->{OBJ}->attr, {NUM=>'1', NAME=>'one'}, 'Check obj.obj'); + +@row2 = $sth->fetchrow(); +ok (scalar @row2, 'new: Fetch second row (nested object)'); +is($row2[0]->attr->{NUM}, '92', 'Check obj.num'); +is_deeply($row2[0]->attr->{OBJ}->attr, {NUM=>'0', NAME=>undef}, 'Check obj.obj'); + +@row3 = $sth->fetchrow(); +ok (scalar @row3, 'new: Fetch third row (nested object)'); +is_deeply($row3[0]->attr, {NUM=>'93', OBJ=>undef}, 'Check obj'); + +ok (!$sth->fetchrow(), 'new: No more rows expected (nested object)'); + +} + +#cleanup +&drop_test_objects; +$dbh->disconnect; + +1; + + +sub sql_do_ok { + my ( $dbh, $sql, $title ) = @_; + $title = $sql unless defined $title; + ok( $dbh->do( $sql ), $title ) or diag $dbh->errstr; +} + From ae9948f758ab4f1e422f91db82dedf2d74229ad8 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 9 Nov 2012 15:51:27 +0000 Subject: [PATCH 356/637] use unix line endings git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15470 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/58object.t | 524 +++++++++++++++++++++++++-------------------------- 1 file changed, 262 insertions(+), 262 deletions(-) diff --git a/t/58object.t b/t/58object.t index 28be915e..9144a453 100644 --- a/t/58object.t +++ b/t/58object.t @@ -1,262 +1,262 @@ -#!perl -w - -use DBI; -use DBD::Oracle qw(ORA_RSET SQLCS_NCHAR); -use strict; -use Data::Dumper; - -use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - -$| = 1; - -$ENV{NLS_DATE_FORMAT} = 'YYYY-MM-DD"T"HH24:MI:SS'; - -# create a database handle -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '',{ RaiseError=>1, - AutoCommit=>1, - PrintError => 0, - ora_objects => 1 })}; - -plan skip_all => "Unable to connect to Oracle" unless $dbh; - -plan tests => 65; - -my ($schema) = $dbuser =~ m{^([^/]*)}; - -# Test ora_objects flag -is $dbh->{ora_objects} => 1, 'ora_objects flag is set to 1'; - -$dbh->{ora_objects} = 0; -is $dbh->{ora_objects} => 0, 'ora_objects flag is set to 0'; - -# check that our db handle is good -isa_ok($dbh, "DBI::db"); - - -ok( $schema = $dbh->selectrow_array( - "select sys_context('userenv', 'current_schema') from dual" -), 'Fetch current schema name'); - - -my $obj_prefix = "dbd_test_"; -my $super_type = "${obj_prefix}_type_A"; -my $sub_type = "${obj_prefix}_type_B"; -my $table = "${obj_prefix}_obj_table"; -my $outer_type = "${obj_prefix}_outer_type"; -my $inner_type = "${obj_prefix}_inner_type"; -my $list_type = "${obj_prefix}_list_type"; -my $nest_table = "${obj_prefix}_nest_table"; -my $list_table = "${obj_prefix}_list_table"; - -sub drop_test_objects { - for my $obj ("TABLE $list_table", "TABLE $nest_table", - "TYPE $list_type", "TYPE $outer_type", "TYPE $inner_type", - "TABLE $table", "TYPE $sub_type", "TYPE $super_type") { - #do not warn if already there - eval { - local $dbh->{PrintError} = 0; - $dbh->do(qq{drop $obj}); - }; - } -} - -&drop_test_objects; - -# get the user's privileges -my $privs_sth = $dbh->prepare( 'SELECT PRIVILEGE from session_privs' ); -$privs_sth->execute; -my @privileges = map { $_->[0] } @{ $privs_sth->fetchall_arrayref }; - - -SKIP: { - skip q{don't have permission to create type} => 61 - unless grep { $_ eq 'CREATE TYPE' } @privileges; - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $super_type AS OBJECT ( - num INTEGER, - name VARCHAR2(20) - ) NOT FINAL } ); - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $sub_type UNDER $super_type ( - datetime DATE, - amount NUMERIC(10,5) - ) NOT FINAL } ); - -sql_do_ok( $dbh, qq{ CREATE TABLE $table (id INTEGER, obj $super_type) }); - -sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (1, $super_type(13, 'obj1')) }); - -sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (2, $sub_type(NULL, 'obj2', - TO_DATE('2004-11-30 14:27:18', 'YYYY-MM-DD HH24:MI:SS'), - 12345.6789)) } - ); - -sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (3, $sub_type(5, 'obj3', NULL, - 777.666)) } ); - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $inner_type AS OBJECT ( - num INTEGER, - name VARCHAR2(20) - ) FINAL }); - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $outer_type AS OBJECT ( - num INTEGER, - obj $inner_type - ) FINAL }); - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $list_type AS - TABLE OF $inner_type }); - -sql_do_ok( $dbh, qq{ CREATE TABLE $nest_table(obj $outer_type) }); - -sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(91, $inner_type(1, 'one'))) } - ); - -sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(92, $inner_type(0, null))) } - ); - -sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(93, null)) } -); - -sql_do_ok( $dbh, qq{ CREATE TABLE $list_table ( id INTEGER, list $list_type ) - NESTED TABLE list STORE AS ${list_table}_list }); - -sql_do_ok( $dbh, qq{ INSERT INTO $list_table VALUES(81,$list_type($inner_type(null, 'listed'))) } ); -# Test old (backward compatible) interface - -# test select testing objects -my $sth = $dbh->prepare("select * from $table order by id"); -ok ($sth, 'old: Prepare select'); -ok ($sth->execute(), 'old: Execute select'); - -my @row1 = $sth->fetchrow(); -ok (scalar @row1, 'old: Fetch first row'); -cmp_ok(ref $row1[1], 'eq', 'ARRAY', 'old: Row 1 column 2 is an ARRAY'); -cmp_ok(scalar(@{$row1[1]}), '==', 2, 'old: Row 1 column 2 is has 2 elements'); - -my @row2 = $sth->fetchrow(); -ok (scalar @row2, 'old: Fetch second row'); -cmp_ok(ref $row2[1], 'eq', 'ARRAY', 'old: Row 2 column 2 is an ARRAY'); -cmp_ok(scalar(@{$row2[1]}), '==', 2, 'old: Row 2 column 2 is has 2 elements'); - -my @row3 = $sth->fetchrow(); -ok (scalar @row3, 'old: Fetch third row'); -cmp_ok(ref $row3[1], 'eq', 'ARRAY', 'old: Row 3 column 2 is an ARRAY'); -cmp_ok(scalar(@{$row3[1]}), '==', 2, 'old: Row 3 column 2 is has 2 elements'); - -ok (!$sth->fetchrow(), 'old: No more rows expected'); - -#print STDERR Dumper(\@row1, \@row2, \@row3); - -# Test new (extended) object interface - -# enable extended object support -$dbh->{ora_objects} = 1; - -# test select testing objects - in extended mode -$sth = $dbh->prepare("select * from $table order by id"); -ok ($sth, 'new: Prepare select'); -ok ($sth->execute(), 'new: Execute select'); - - -@row1 = $sth->fetchrow(); -ok (scalar @row1, 'new: Fetch first row'); -cmp_ok(ref $row1[1], 'eq', 'DBD::Oracle::Object', 'new: Row 1 column 2 is an DBD:Oracle::Object'); -cmp_ok(uc $row1[1]->type_name, "eq", uc "$schema.$super_type", "new: Row 1 column 2 object type"); -is_deeply([$row1[1]->attributes], ['NUM', 13, 'NAME', 'obj1'], "new: Row 1 column 2 object attributes"); - -@row2 = $sth->fetchrow(); -ok (scalar @row2, 'new: Fetch second row'); -cmp_ok(ref $row2[1], 'eq', 'DBD::Oracle::Object', 'new: Row 2 column 2 is an DBD::Oracle::Object'); -cmp_ok(uc $row2[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 2 column 2 object type"); - -my %attrs = $row2[1]->attributes; - -$attrs{AMOUNT} = sprintf "%9.4f", $attrs{AMOUNT}; - -is_deeply( \%attrs, {'NUM', undef, 'NAME', 'obj2', - 'DATETIME', '2004-11-30T14:27:18', 'AMOUNT', '12345.6789'}, "new: Row 1 column 2 object attributes"); - -@row3 = $sth->fetchrow(); -ok (scalar @row3, 'new: Fetch third row'); -cmp_ok(ref $row3[1], 'eq', 'DBD::Oracle::Object', 'new: Row 3 column 2 is an DBD::Oracle::Object'); -cmp_ok(uc $row3[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 3 column 2 object type"); - -%attrs = $row3[1]->attributes; -$attrs{AMOUNT} = sprintf "%6.3f", $attrs{AMOUNT}; - -is_deeply( \%attrs, {'NUM', 5, 'NAME', 'obj3', - 'DATETIME', undef, 'AMOUNT', '777.666'}, "new: Row 1 column 2 object attributes"); - -ok (!$sth->fetchrow(), 'new: No more rows expected'); - -#print STDERR Dumper(\@row1, \@row2, \@row3); - -# Test DBD::Oracle::Object -my $obj = $row3[1]; -my $expected_hash = { - NUM => 5, - NAME => 'obj3', - DATETIME => undef, - AMOUNT => 777.666, - }; -my $attrs = $obj->attr_hash; -$attrs->{AMOUNT} = sprintf "%6.3f", $attrs->{AMOUNT}; - -is_deeply($attrs, $expected_hash, 'DBD::Oracle::Object->attr_hash'); -is_deeply($obj->attr, $expected_hash, 'DBD::Oracle::Object->attr'); -is($obj->attr("NAME"), 'obj3', 'DBD::Oracle::Object->attr("NAME")'); - -# try the list table -$sth = $dbh->prepare("select * from $list_table"); -ok ($sth, 'new: Prepare select with nested table of objects'); -ok ($sth->execute(), 'new: Execute (nested table)'); - -@row1 = $sth->fetchrow(); -ok (scalar @row1, 'new: Fetch first row (nested table)'); -is_deeply($row1[1]->[0]->attr, {NUM=>undef, NAME=>'listed'}, - 'Check propertes of first (and only) item in nested table'); - -ok (!$sth->fetchrow(), 'new: No more rows expected (nested table)'); - -#try the nested table -$sth = $dbh->prepare("select * from $nest_table"); -ok ($sth, 'new: Prepare select with nested object'); -ok ($sth->execute(), 'new: Execute (nested object)'); - -@row1 = $sth->fetchrow(); -ok (scalar @row1, 'new: Fetch first row (nested object)'); -is($row1[0]->attr->{NUM}, '91', 'Check obj.num'); -is_deeply($row1[0]->attr->{OBJ}->attr, {NUM=>'1', NAME=>'one'}, 'Check obj.obj'); - -@row2 = $sth->fetchrow(); -ok (scalar @row2, 'new: Fetch second row (nested object)'); -is($row2[0]->attr->{NUM}, '92', 'Check obj.num'); -is_deeply($row2[0]->attr->{OBJ}->attr, {NUM=>'0', NAME=>undef}, 'Check obj.obj'); - -@row3 = $sth->fetchrow(); -ok (scalar @row3, 'new: Fetch third row (nested object)'); -is_deeply($row3[0]->attr, {NUM=>'93', OBJ=>undef}, 'Check obj'); - -ok (!$sth->fetchrow(), 'new: No more rows expected (nested object)'); - -} - -#cleanup -&drop_test_objects; -$dbh->disconnect; - -1; - - -sub sql_do_ok { - my ( $dbh, $sql, $title ) = @_; - $title = $sql unless defined $title; - ok( $dbh->do( $sql ), $title ) or diag $dbh->errstr; -} - +#!perl -w + +use DBI; +use DBD::Oracle qw(ORA_RSET SQLCS_NCHAR); +use strict; +use Data::Dumper; + +use Test::More; +unshift @INC ,'t'; +require 'nchar_test_lib.pl'; + +$| = 1; + +$ENV{NLS_DATE_FORMAT} = 'YYYY-MM-DD"T"HH24:MI:SS'; + +# create a database handle +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dbh; +eval {$dbh = DBI->connect($dsn, $dbuser, '',{ RaiseError=>1, + AutoCommit=>1, + PrintError => 0, + ora_objects => 1 })}; + +plan skip_all => "Unable to connect to Oracle" unless $dbh; + +plan tests => 65; + +my ($schema) = $dbuser =~ m{^([^/]*)}; + +# Test ora_objects flag +is $dbh->{ora_objects} => 1, 'ora_objects flag is set to 1'; + +$dbh->{ora_objects} = 0; +is $dbh->{ora_objects} => 0, 'ora_objects flag is set to 0'; + +# check that our db handle is good +isa_ok($dbh, "DBI::db"); + + +ok( $schema = $dbh->selectrow_array( + "select sys_context('userenv', 'current_schema') from dual" +), 'Fetch current schema name'); + + +my $obj_prefix = "dbd_test_"; +my $super_type = "${obj_prefix}_type_A"; +my $sub_type = "${obj_prefix}_type_B"; +my $table = "${obj_prefix}_obj_table"; +my $outer_type = "${obj_prefix}_outer_type"; +my $inner_type = "${obj_prefix}_inner_type"; +my $list_type = "${obj_prefix}_list_type"; +my $nest_table = "${obj_prefix}_nest_table"; +my $list_table = "${obj_prefix}_list_table"; + +sub drop_test_objects { + for my $obj ("TABLE $list_table", "TABLE $nest_table", + "TYPE $list_type", "TYPE $outer_type", "TYPE $inner_type", + "TABLE $table", "TYPE $sub_type", "TYPE $super_type") { + #do not warn if already there + eval { + local $dbh->{PrintError} = 0; + $dbh->do(qq{drop $obj}); + }; + } +} + +&drop_test_objects; + +# get the user's privileges +my $privs_sth = $dbh->prepare( 'SELECT PRIVILEGE from session_privs' ); +$privs_sth->execute; +my @privileges = map { $_->[0] } @{ $privs_sth->fetchall_arrayref }; + + +SKIP: { + skip q{don't have permission to create type} => 61 + unless grep { $_ eq 'CREATE TYPE' } @privileges; + +sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $super_type AS OBJECT ( + num INTEGER, + name VARCHAR2(20) + ) NOT FINAL } ); + +sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $sub_type UNDER $super_type ( + datetime DATE, + amount NUMERIC(10,5) + ) NOT FINAL } ); + +sql_do_ok( $dbh, qq{ CREATE TABLE $table (id INTEGER, obj $super_type) }); + +sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (1, $super_type(13, 'obj1')) }); + +sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (2, $sub_type(NULL, 'obj2', + TO_DATE('2004-11-30 14:27:18', 'YYYY-MM-DD HH24:MI:SS'), + 12345.6789)) } + ); + +sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (3, $sub_type(5, 'obj3', NULL, + 777.666)) } ); + +sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $inner_type AS OBJECT ( + num INTEGER, + name VARCHAR2(20) + ) FINAL }); + +sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $outer_type AS OBJECT ( + num INTEGER, + obj $inner_type + ) FINAL }); + +sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $list_type AS + TABLE OF $inner_type }); + +sql_do_ok( $dbh, qq{ CREATE TABLE $nest_table(obj $outer_type) }); + +sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(91, $inner_type(1, 'one'))) } + ); + +sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(92, $inner_type(0, null))) } + ); + +sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(93, null)) } +); + +sql_do_ok( $dbh, qq{ CREATE TABLE $list_table ( id INTEGER, list $list_type ) + NESTED TABLE list STORE AS ${list_table}_list }); + +sql_do_ok( $dbh, qq{ INSERT INTO $list_table VALUES(81,$list_type($inner_type(null, 'listed'))) } ); +# Test old (backward compatible) interface + +# test select testing objects +my $sth = $dbh->prepare("select * from $table order by id"); +ok ($sth, 'old: Prepare select'); +ok ($sth->execute(), 'old: Execute select'); + +my @row1 = $sth->fetchrow(); +ok (scalar @row1, 'old: Fetch first row'); +cmp_ok(ref $row1[1], 'eq', 'ARRAY', 'old: Row 1 column 2 is an ARRAY'); +cmp_ok(scalar(@{$row1[1]}), '==', 2, 'old: Row 1 column 2 is has 2 elements'); + +my @row2 = $sth->fetchrow(); +ok (scalar @row2, 'old: Fetch second row'); +cmp_ok(ref $row2[1], 'eq', 'ARRAY', 'old: Row 2 column 2 is an ARRAY'); +cmp_ok(scalar(@{$row2[1]}), '==', 2, 'old: Row 2 column 2 is has 2 elements'); + +my @row3 = $sth->fetchrow(); +ok (scalar @row3, 'old: Fetch third row'); +cmp_ok(ref $row3[1], 'eq', 'ARRAY', 'old: Row 3 column 2 is an ARRAY'); +cmp_ok(scalar(@{$row3[1]}), '==', 2, 'old: Row 3 column 2 is has 2 elements'); + +ok (!$sth->fetchrow(), 'old: No more rows expected'); + +#print STDERR Dumper(\@row1, \@row2, \@row3); + +# Test new (extended) object interface + +# enable extended object support +$dbh->{ora_objects} = 1; + +# test select testing objects - in extended mode +$sth = $dbh->prepare("select * from $table order by id"); +ok ($sth, 'new: Prepare select'); +ok ($sth->execute(), 'new: Execute select'); + + +@row1 = $sth->fetchrow(); +ok (scalar @row1, 'new: Fetch first row'); +cmp_ok(ref $row1[1], 'eq', 'DBD::Oracle::Object', 'new: Row 1 column 2 is an DBD:Oracle::Object'); +cmp_ok(uc $row1[1]->type_name, "eq", uc "$schema.$super_type", "new: Row 1 column 2 object type"); +is_deeply([$row1[1]->attributes], ['NUM', 13, 'NAME', 'obj1'], "new: Row 1 column 2 object attributes"); + +@row2 = $sth->fetchrow(); +ok (scalar @row2, 'new: Fetch second row'); +cmp_ok(ref $row2[1], 'eq', 'DBD::Oracle::Object', 'new: Row 2 column 2 is an DBD::Oracle::Object'); +cmp_ok(uc $row2[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 2 column 2 object type"); + +my %attrs = $row2[1]->attributes; + +$attrs{AMOUNT} = sprintf "%9.4f", $attrs{AMOUNT}; + +is_deeply( \%attrs, {'NUM', undef, 'NAME', 'obj2', + 'DATETIME', '2004-11-30T14:27:18', 'AMOUNT', '12345.6789'}, "new: Row 1 column 2 object attributes"); + +@row3 = $sth->fetchrow(); +ok (scalar @row3, 'new: Fetch third row'); +cmp_ok(ref $row3[1], 'eq', 'DBD::Oracle::Object', 'new: Row 3 column 2 is an DBD::Oracle::Object'); +cmp_ok(uc $row3[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 3 column 2 object type"); + +%attrs = $row3[1]->attributes; +$attrs{AMOUNT} = sprintf "%6.3f", $attrs{AMOUNT}; + +is_deeply( \%attrs, {'NUM', 5, 'NAME', 'obj3', + 'DATETIME', undef, 'AMOUNT', '777.666'}, "new: Row 1 column 2 object attributes"); + +ok (!$sth->fetchrow(), 'new: No more rows expected'); + +#print STDERR Dumper(\@row1, \@row2, \@row3); + +# Test DBD::Oracle::Object +my $obj = $row3[1]; +my $expected_hash = { + NUM => 5, + NAME => 'obj3', + DATETIME => undef, + AMOUNT => 777.666, + }; +my $attrs = $obj->attr_hash; +$attrs->{AMOUNT} = sprintf "%6.3f", $attrs->{AMOUNT}; + +is_deeply($attrs, $expected_hash, 'DBD::Oracle::Object->attr_hash'); +is_deeply($obj->attr, $expected_hash, 'DBD::Oracle::Object->attr'); +is($obj->attr("NAME"), 'obj3', 'DBD::Oracle::Object->attr("NAME")'); + +# try the list table +$sth = $dbh->prepare("select * from $list_table"); +ok ($sth, 'new: Prepare select with nested table of objects'); +ok ($sth->execute(), 'new: Execute (nested table)'); + +@row1 = $sth->fetchrow(); +ok (scalar @row1, 'new: Fetch first row (nested table)'); +is_deeply($row1[1]->[0]->attr, {NUM=>undef, NAME=>'listed'}, + 'Check propertes of first (and only) item in nested table'); + +ok (!$sth->fetchrow(), 'new: No more rows expected (nested table)'); + +#try the nested table +$sth = $dbh->prepare("select * from $nest_table"); +ok ($sth, 'new: Prepare select with nested object'); +ok ($sth->execute(), 'new: Execute (nested object)'); + +@row1 = $sth->fetchrow(); +ok (scalar @row1, 'new: Fetch first row (nested object)'); +is($row1[0]->attr->{NUM}, '91', 'Check obj.num'); +is_deeply($row1[0]->attr->{OBJ}->attr, {NUM=>'1', NAME=>'one'}, 'Check obj.obj'); + +@row2 = $sth->fetchrow(); +ok (scalar @row2, 'new: Fetch second row (nested object)'); +is($row2[0]->attr->{NUM}, '92', 'Check obj.num'); +is_deeply($row2[0]->attr->{OBJ}->attr, {NUM=>'0', NAME=>undef}, 'Check obj.obj'); + +@row3 = $sth->fetchrow(); +ok (scalar @row3, 'new: Fetch third row (nested object)'); +is_deeply($row3[0]->attr, {NUM=>'93', OBJ=>undef}, 'Check obj'); + +ok (!$sth->fetchrow(), 'new: No more rows expected (nested object)'); + +} + +#cleanup +&drop_test_objects; +$dbh->disconnect; + +1; + + +sub sql_do_ok { + my ( $dbh, $sql, $title ) = @_; + $title = $sql unless defined $title; + ok( $dbh->do( $sql ), $title ) or diag $dbh->errstr; +} + From 5fe5756570197f0c05f2a8d8264c576b8e240ffa Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 9 Nov 2012 15:58:50 +0000 Subject: [PATCH 357/637] another fix from steffen for 58object git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15471 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ t/58object.t | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/Changes b/Changes index 1e45fad7..f59d8b95 100644 --- a/Changes +++ b/Changes @@ -36,6 +36,10 @@ NEXT_VERSION all Oracles support them (only 9 and above). Thanks to Steffen Goeldner for RT and patch. + - Fix RT81067. 58object.t has some subtype tests and subtypes were + introduced in Oracle 9. Skip if < Oracle 9. Thanks to Steffen + Goeldner for RT and patch. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a diff --git a/t/58object.t b/t/58object.t index 9144a453..4f950c01 100644 --- a/t/58object.t +++ b/t/58object.t @@ -72,6 +72,9 @@ my $privs_sth = $dbh->prepare( 'SELECT PRIVILEGE from session_privs' ); $privs_sth->execute; my @privileges = map { $_->[0] } @{ $privs_sth->fetchall_arrayref }; +my $ora8 = $dbh->func('ora_server_version')->[0] < 9; +my $final = $ora8 ? '':'FINAL'; +my $not_final = $ora8 ? '':'NOT FINAL'; SKIP: { skip q{don't have permission to create type} => 61 @@ -80,17 +83,20 @@ SKIP: { sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $super_type AS OBJECT ( num INTEGER, name VARCHAR2(20) - ) NOT FINAL } ); + ) $not_final } ); +SKIP: { + skip 'Subtypes new in Oracle 9' => 1 if $ora8; sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $sub_type UNDER $super_type ( datetime DATE, amount NUMERIC(10,5) - ) NOT FINAL } ); - + ) $not_final } ); +} sql_do_ok( $dbh, qq{ CREATE TABLE $table (id INTEGER, obj $super_type) }); sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (1, $super_type(13, 'obj1')) }); - +SKIP: { + skip 'Subtypes new in Oracle 9' => 2 if $ora8; sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (2, $sub_type(NULL, 'obj2', TO_DATE('2004-11-30 14:27:18', 'YYYY-MM-DD HH24:MI:SS'), 12345.6789)) } @@ -98,16 +104,16 @@ sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (2, $sub_type(NULL, 'obj2', sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (3, $sub_type(5, 'obj3', NULL, 777.666)) } ); - +} sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $inner_type AS OBJECT ( num INTEGER, name VARCHAR2(20) - ) FINAL }); + ) $final }); sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $outer_type AS OBJECT ( num INTEGER, obj $inner_type - ) FINAL }); + ) $final }); sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $list_type AS TABLE OF $inner_type }); @@ -134,21 +140,23 @@ my $sth = $dbh->prepare("select * from $table order by id"); ok ($sth, 'old: Prepare select'); ok ($sth->execute(), 'old: Execute select'); -my @row1 = $sth->fetchrow(); +my ( @row1, @row2, @row3 ); +@row1 = $sth->fetchrow(); ok (scalar @row1, 'old: Fetch first row'); cmp_ok(ref $row1[1], 'eq', 'ARRAY', 'old: Row 1 column 2 is an ARRAY'); cmp_ok(scalar(@{$row1[1]}), '==', 2, 'old: Row 1 column 2 is has 2 elements'); - -my @row2 = $sth->fetchrow(); +SKIP: { + skip 'Subtypes new in Oracle 9' => 6 if $ora8; +@row2 = $sth->fetchrow(); ok (scalar @row2, 'old: Fetch second row'); cmp_ok(ref $row2[1], 'eq', 'ARRAY', 'old: Row 2 column 2 is an ARRAY'); cmp_ok(scalar(@{$row2[1]}), '==', 2, 'old: Row 2 column 2 is has 2 elements'); -my @row3 = $sth->fetchrow(); +@row3 = $sth->fetchrow(); ok (scalar @row3, 'old: Fetch third row'); cmp_ok(ref $row3[1], 'eq', 'ARRAY', 'old: Row 3 column 2 is an ARRAY'); cmp_ok(scalar(@{$row3[1]}), '==', 2, 'old: Row 3 column 2 is has 2 elements'); - +} ok (!$sth->fetchrow(), 'old: No more rows expected'); #print STDERR Dumper(\@row1, \@row2, \@row3); @@ -169,7 +177,8 @@ ok (scalar @row1, 'new: Fetch first row'); cmp_ok(ref $row1[1], 'eq', 'DBD::Oracle::Object', 'new: Row 1 column 2 is an DBD:Oracle::Object'); cmp_ok(uc $row1[1]->type_name, "eq", uc "$schema.$super_type", "new: Row 1 column 2 object type"); is_deeply([$row1[1]->attributes], ['NUM', 13, 'NAME', 'obj1'], "new: Row 1 column 2 object attributes"); - +SKIP: { + skip 'Subtypes new in Oracle 9' => 8 if $ora8; @row2 = $sth->fetchrow(); ok (scalar @row2, 'new: Fetch second row'); cmp_ok(ref $row2[1], 'eq', 'DBD::Oracle::Object', 'new: Row 2 column 2 is an DBD::Oracle::Object'); @@ -192,11 +201,13 @@ $attrs{AMOUNT} = sprintf "%6.3f", $attrs{AMOUNT}; is_deeply( \%attrs, {'NUM', 5, 'NAME', 'obj3', 'DATETIME', undef, 'AMOUNT', '777.666'}, "new: Row 1 column 2 object attributes"); - +} ok (!$sth->fetchrow(), 'new: No more rows expected'); #print STDERR Dumper(\@row1, \@row2, \@row3); +SKIP: { + skip 'Subtypes new in Oracle 9' => 3 if $ora8; # Test DBD::Oracle::Object my $obj = $row3[1]; my $expected_hash = { @@ -211,7 +222,7 @@ $attrs->{AMOUNT} = sprintf "%6.3f", $attrs->{AMOUNT}; is_deeply($attrs, $expected_hash, 'DBD::Oracle::Object->attr_hash'); is_deeply($obj->attr, $expected_hash, 'DBD::Oracle::Object->attr'); is($obj->attr("NAME"), 'obj3', 'DBD::Oracle::Object->attr("NAME")'); - +} # try the list table $sth = $dbh->prepare("select * from $list_table"); ok ($sth, 'new: Prepare select with nested table of objects'); From 6a2d8b6bf953e13eb61df1a3374ebdab2df05b0f Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 9 Nov 2012 15:58:50 +0000 Subject: [PATCH 358/637] another fix from steffen for 58object git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15471 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ t/58object.t | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/Changes b/Changes index 1e45fad7..f59d8b95 100644 --- a/Changes +++ b/Changes @@ -36,6 +36,10 @@ NEXT_VERSION all Oracles support them (only 9 and above). Thanks to Steffen Goeldner for RT and patch. + - Fix RT81067. 58object.t has some subtype tests and subtypes were + introduced in Oracle 9. Skip if < Oracle 9. Thanks to Steffen + Goeldner for RT and patch. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a diff --git a/t/58object.t b/t/58object.t index 9144a453..4f950c01 100644 --- a/t/58object.t +++ b/t/58object.t @@ -72,6 +72,9 @@ my $privs_sth = $dbh->prepare( 'SELECT PRIVILEGE from session_privs' ); $privs_sth->execute; my @privileges = map { $_->[0] } @{ $privs_sth->fetchall_arrayref }; +my $ora8 = $dbh->func('ora_server_version')->[0] < 9; +my $final = $ora8 ? '':'FINAL'; +my $not_final = $ora8 ? '':'NOT FINAL'; SKIP: { skip q{don't have permission to create type} => 61 @@ -80,17 +83,20 @@ SKIP: { sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $super_type AS OBJECT ( num INTEGER, name VARCHAR2(20) - ) NOT FINAL } ); + ) $not_final } ); +SKIP: { + skip 'Subtypes new in Oracle 9' => 1 if $ora8; sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $sub_type UNDER $super_type ( datetime DATE, amount NUMERIC(10,5) - ) NOT FINAL } ); - + ) $not_final } ); +} sql_do_ok( $dbh, qq{ CREATE TABLE $table (id INTEGER, obj $super_type) }); sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (1, $super_type(13, 'obj1')) }); - +SKIP: { + skip 'Subtypes new in Oracle 9' => 2 if $ora8; sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (2, $sub_type(NULL, 'obj2', TO_DATE('2004-11-30 14:27:18', 'YYYY-MM-DD HH24:MI:SS'), 12345.6789)) } @@ -98,16 +104,16 @@ sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (2, $sub_type(NULL, 'obj2', sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (3, $sub_type(5, 'obj3', NULL, 777.666)) } ); - +} sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $inner_type AS OBJECT ( num INTEGER, name VARCHAR2(20) - ) FINAL }); + ) $final }); sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $outer_type AS OBJECT ( num INTEGER, obj $inner_type - ) FINAL }); + ) $final }); sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $list_type AS TABLE OF $inner_type }); @@ -134,21 +140,23 @@ my $sth = $dbh->prepare("select * from $table order by id"); ok ($sth, 'old: Prepare select'); ok ($sth->execute(), 'old: Execute select'); -my @row1 = $sth->fetchrow(); +my ( @row1, @row2, @row3 ); +@row1 = $sth->fetchrow(); ok (scalar @row1, 'old: Fetch first row'); cmp_ok(ref $row1[1], 'eq', 'ARRAY', 'old: Row 1 column 2 is an ARRAY'); cmp_ok(scalar(@{$row1[1]}), '==', 2, 'old: Row 1 column 2 is has 2 elements'); - -my @row2 = $sth->fetchrow(); +SKIP: { + skip 'Subtypes new in Oracle 9' => 6 if $ora8; +@row2 = $sth->fetchrow(); ok (scalar @row2, 'old: Fetch second row'); cmp_ok(ref $row2[1], 'eq', 'ARRAY', 'old: Row 2 column 2 is an ARRAY'); cmp_ok(scalar(@{$row2[1]}), '==', 2, 'old: Row 2 column 2 is has 2 elements'); -my @row3 = $sth->fetchrow(); +@row3 = $sth->fetchrow(); ok (scalar @row3, 'old: Fetch third row'); cmp_ok(ref $row3[1], 'eq', 'ARRAY', 'old: Row 3 column 2 is an ARRAY'); cmp_ok(scalar(@{$row3[1]}), '==', 2, 'old: Row 3 column 2 is has 2 elements'); - +} ok (!$sth->fetchrow(), 'old: No more rows expected'); #print STDERR Dumper(\@row1, \@row2, \@row3); @@ -169,7 +177,8 @@ ok (scalar @row1, 'new: Fetch first row'); cmp_ok(ref $row1[1], 'eq', 'DBD::Oracle::Object', 'new: Row 1 column 2 is an DBD:Oracle::Object'); cmp_ok(uc $row1[1]->type_name, "eq", uc "$schema.$super_type", "new: Row 1 column 2 object type"); is_deeply([$row1[1]->attributes], ['NUM', 13, 'NAME', 'obj1'], "new: Row 1 column 2 object attributes"); - +SKIP: { + skip 'Subtypes new in Oracle 9' => 8 if $ora8; @row2 = $sth->fetchrow(); ok (scalar @row2, 'new: Fetch second row'); cmp_ok(ref $row2[1], 'eq', 'DBD::Oracle::Object', 'new: Row 2 column 2 is an DBD::Oracle::Object'); @@ -192,11 +201,13 @@ $attrs{AMOUNT} = sprintf "%6.3f", $attrs{AMOUNT}; is_deeply( \%attrs, {'NUM', 5, 'NAME', 'obj3', 'DATETIME', undef, 'AMOUNT', '777.666'}, "new: Row 1 column 2 object attributes"); - +} ok (!$sth->fetchrow(), 'new: No more rows expected'); #print STDERR Dumper(\@row1, \@row2, \@row3); +SKIP: { + skip 'Subtypes new in Oracle 9' => 3 if $ora8; # Test DBD::Oracle::Object my $obj = $row3[1]; my $expected_hash = { @@ -211,7 +222,7 @@ $attrs->{AMOUNT} = sprintf "%6.3f", $attrs->{AMOUNT}; is_deeply($attrs, $expected_hash, 'DBD::Oracle::Object->attr_hash'); is_deeply($obj->attr, $expected_hash, 'DBD::Oracle::Object->attr'); is($obj->attr("NAME"), 'obj3', 'DBD::Oracle::Object->attr("NAME")'); - +} # try the list table $sth = $dbh->prepare("select * from $list_table"); ok ($sth, 'new: Prepare select with nested table of objects'); From 00024efea700633ed08cb1bc33132526c51769a8 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 21 Nov 2012 10:33:43 +0000 Subject: [PATCH 359/637] new faq on solaris and linker path git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15483 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ lib/DBD/Oracle/Troubleshooting/Sun.pod | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Changes b/Changes index f59d8b95..07f5b117 100644 --- a/Changes +++ b/Changes @@ -51,6 +51,8 @@ NEXT_VERSION - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) + - New FAQ entry on Solaris and setting linker library path. + 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index 16995073..f608e12f 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -26,6 +26,22 @@ environment. It seems that having it defined will prevent the error. +=head1 Setting library load path for instant client libraries + +Usually you set LD_LIBRARY_PATH to point to the location of +your Oracle Instant Client (you need to do this when building +DBD::Oracle). However, afterwards it can be a pain to keep +ensuring this is set and changing LD_LIBRARY_PATH in your Perl +script does not work (needs to be done beforehand) as the dynamic +linker caches its value. + +An alternative under newer versions of Solaris is: + +root> crle -u -l /youroracledir/lib/instantclient_11_2 + +however, make sure you check the crle options as you may need to +set the architecture etc as well. + =head1 AUTHORS =over 4 From 63ffc0d952ffc4aae97afce57cabf90068e9a2ae Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 21 Nov 2012 10:33:43 +0000 Subject: [PATCH 360/637] new faq on solaris and linker path git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15483 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ lib/DBD/Oracle/Troubleshooting/Sun.pod | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Changes b/Changes index f59d8b95..07f5b117 100644 --- a/Changes +++ b/Changes @@ -51,6 +51,8 @@ NEXT_VERSION - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) + - New FAQ entry on Solaris and setting linker library path. + 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index 16995073..f608e12f 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -26,6 +26,22 @@ environment. It seems that having it defined will prevent the error. +=head1 Setting library load path for instant client libraries + +Usually you set LD_LIBRARY_PATH to point to the location of +your Oracle Instant Client (you need to do this when building +DBD::Oracle). However, afterwards it can be a pain to keep +ensuring this is set and changing LD_LIBRARY_PATH in your Perl +script does not work (needs to be done beforehand) as the dynamic +linker caches its value. + +An alternative under newer versions of Solaris is: + +root> crle -u -l /youroracledir/lib/instantclient_11_2 + +however, make sure you check the crle options as you may need to +set the architecture etc as well. + =head1 AUTHORS =over 4 From 4d6b08bc31a1ac40af20cb19b1d5cecbf1c82780 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 21 Nov 2012 10:42:16 +0000 Subject: [PATCH 361/637] Fix for RT81317 - persistent lobs not available until Oracle 9 Remove ineffective commit in 34pres_lobs.t git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15484 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 9 ++++++++- t/34pres_lobs.t | 7 +++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index 07f5b117..0f28a40e 100644 --- a/Changes +++ b/Changes @@ -40,6 +40,10 @@ NEXT_VERSION introduced in Oracle 9. Skip if < Oracle 9. Thanks to Steffen Goeldner for RT and patch. + - Fix RT81317. 34pres_lobs.t uses the Data Interface for Persistent + LOBs which is new in Oracle 9. Skip if < Oracle 9. Thanks to + Steffen Goeldner for RT and patch. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a @@ -51,7 +55,10 @@ NEXT_VERSION - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) - - New FAQ entry on Solaris and setting linker library path. + - New FAQ entry on Solaris and setting linker library path + (Martin J. Evans) + + - Removed ineffective commit in 34pres_lobs.t (Martin J. Evans) 1.52 2012-10-19 diff --git a/t/34pres_lobs.t b/t/34pres_lobs.t index 213c4f0d..e5b38dfc 100644 --- a/t/34pres_lobs.t +++ b/t/34pres_lobs.t @@ -31,7 +31,9 @@ eval {$dbh = DBI->connect($dsn, $dbuser, '', AutoCommit=>1, PrintError => 0 ,LongReadLen=>10000000})}; if ($dbh) { - plan tests => 29; + plan skip_all => "Data Interface for Persistent LOBs new in Oracle 9" + if $dbh->func('ora_server_version')->[0] < 9; + plan tests => 28; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -71,9 +73,6 @@ ok($sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}), 'bind p4'); ok($sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}), 'bind p5'); ok($sth->execute(), 'execute'); -ok($dbh->commit(), 'commit'); - - $sql='select * from '.$table; ok($sth=$dbh->prepare($sql,{ora_pers_lob=>1}), 'prepare with ora_pers_lob'); From 4d074a71218ad9b9336a0a8f6407e16355380493 Mon Sep 17 00:00:00 2001 From: mjevans Date: Wed, 21 Nov 2012 10:42:16 +0000 Subject: [PATCH 362/637] Fix for RT81317 - persistent lobs not available until Oracle 9 Remove ineffective commit in 34pres_lobs.t git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15484 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 9 ++++++++- t/34pres_lobs.t | 7 +++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Changes b/Changes index 07f5b117..0f28a40e 100644 --- a/Changes +++ b/Changes @@ -40,6 +40,10 @@ NEXT_VERSION introduced in Oracle 9. Skip if < Oracle 9. Thanks to Steffen Goeldner for RT and patch. + - Fix RT81317. 34pres_lobs.t uses the Data Interface for Persistent + LOBs which is new in Oracle 9. Skip if < Oracle 9. Thanks to + Steffen Goeldner for RT and patch. + [MISCELLANEOUS] - The original 26exe_array test was replaced some time ago with a @@ -51,7 +55,10 @@ NEXT_VERSION - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) - - New FAQ entry on Solaris and setting linker library path. + - New FAQ entry on Solaris and setting linker library path + (Martin J. Evans) + + - Removed ineffective commit in 34pres_lobs.t (Martin J. Evans) 1.52 2012-10-19 diff --git a/t/34pres_lobs.t b/t/34pres_lobs.t index 213c4f0d..e5b38dfc 100644 --- a/t/34pres_lobs.t +++ b/t/34pres_lobs.t @@ -31,7 +31,9 @@ eval {$dbh = DBI->connect($dsn, $dbuser, '', AutoCommit=>1, PrintError => 0 ,LongReadLen=>10000000})}; if ($dbh) { - plan tests => 29; + plan skip_all => "Data Interface for Persistent LOBs new in Oracle 9" + if $dbh->func('ora_server_version')->[0] < 9; + plan tests => 28; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -71,9 +73,6 @@ ok($sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}), 'bind p4'); ok($sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}), 'bind p5'); ok($sth->execute(), 'execute'); -ok($dbh->commit(), 'commit'); - - $sql='select * from '.$table; ok($sth=$dbh->prepare($sql,{ora_pers_lob=>1}), 'prepare with ora_pers_lob'); From 05bbab4fe574bfd8bb35f7082ff71787d0e858f5 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 26 Nov 2012 13:29:40 -0500 Subject: [PATCH 363/637] move test lib in t/lib --- MANIFEST | 2 +- t/26exe_array.t | 2 +- t/{ => lib}/ExecuteArray.pm | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename t/{ => lib}/ExecuteArray.pm (100%) diff --git a/MANIFEST b/MANIFEST index d1564f89..6b41e5b5 100644 --- a/MANIFEST +++ b/MANIFEST @@ -67,7 +67,6 @@ t/23wide_db_al32utf8.t t/24implicit_utf8.t t/25plsql.t t/26exe_array.t -t/ExecuteArray.pm t/28array_bind.t t/30long.t t/31lob.t @@ -86,6 +85,7 @@ t/58object.t t/60reauth.t t/70meta.t t/80ora_charset.t +t/lib/ExecuteArray.pm t/nchar_test_lib.pl t/rt13865.t t/rt74753-utf8-encoded.t diff --git a/t/26exe_array.t b/t/26exe_array.t index 1b4f0e66..eb9fab9d 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -9,7 +9,7 @@ use strict; use Data::Dumper; require 'nchar_test_lib.pl'; -use lib './t'; +use lib 't/lib'; $| = 1; diff --git a/t/ExecuteArray.pm b/t/lib/ExecuteArray.pm similarity index 100% rename from t/ExecuteArray.pm rename to t/lib/ExecuteArray.pm From 7ca45749c53643bc27a47b6f0b961ff91c0ed205 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Nov 2012 18:40:46 +0000 Subject: [PATCH 364/637] github issue #33: add DBI as a dep in the META* files git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15485 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ META.json | 1 + META.yml | 1 + 3 files changed, 4 insertions(+) diff --git a/Changes b/Changes index 0f28a40e..301d0280 100644 --- a/Changes +++ b/Changes @@ -55,6 +55,8 @@ NEXT_VERSION - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) + - Add DBI as a configure prereq for the META* files (thanks to Joe Crotty) + - New FAQ entry on Solaris and setting linker library path (Martin J. Evans) diff --git a/META.json b/META.json index e25b4114..714bf468 100644 --- a/META.json +++ b/META.json @@ -19,6 +19,7 @@ "prereqs" : { "configure" : { "requires" : { + "DBI" : "1.51", "ExtUtils::MakeMaker" : "6.30" } }, diff --git a/META.yml b/META.yml index 2bc02600..80f85e31 100644 --- a/META.yml +++ b/META.yml @@ -18,6 +18,7 @@ build_requires: utf8: 0 vars: 0 configure_requires: + DBI: 1.51 ExtUtils::MakeMaker: 6.30 dynamic_config: 0 generated_by: 'Dist::Zilla version 4.300027, CPAN::Meta::Converter version 2.120921' From 34c31bd7a9b578ac873c5d0e528e1724e0fd5abd Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Nov 2012 18:40:46 +0000 Subject: [PATCH 365/637] github issue #33: add DBI as a dep in the META* files git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15485 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 ++ META.json | 1 + META.yml | 1 + 3 files changed, 4 insertions(+) diff --git a/Changes b/Changes index 0f28a40e..301d0280 100644 --- a/Changes +++ b/Changes @@ -55,6 +55,8 @@ NEXT_VERSION - simple code clean up, replacing 3 uses of safemalloc with Newz (John Scoles) + - Add DBI as a configure prereq for the META* files (thanks to Joe Crotty) + - New FAQ entry on Solaris and setting linker library path (Martin J. Evans) diff --git a/META.json b/META.json index e25b4114..714bf468 100644 --- a/META.json +++ b/META.json @@ -19,6 +19,7 @@ "prereqs" : { "configure" : { "requires" : { + "DBI" : "1.51", "ExtUtils::MakeMaker" : "6.30" } }, diff --git a/META.yml b/META.yml index 2bc02600..80f85e31 100644 --- a/META.yml +++ b/META.yml @@ -18,6 +18,7 @@ build_requires: utf8: 0 vars: 0 configure_requires: + DBI: 1.51 ExtUtils::MakeMaker: 6.30 dynamic_config: 0 generated_by: 'Dist::Zilla version 4.300027, CPAN::Meta::Converter version 2.120921' From 939ffe36f3390418c881bc10babe9ff5766e6ae2 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Nov 2012 18:40:51 +0000 Subject: [PATCH 366/637] updated READMEs git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15486 50811bd7-b8ce-0310-adc1-d9db26280581 --- README | 9 ++++++++- README.mkdn | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/README b/README index c30268b6..b78d5db5 100644 --- a/README +++ b/README @@ -963,6 +963,14 @@ ORACLE-SPECIFIC DATABASE HANDLE METHODS calls. To cause the latest values to be fetched, pass a true value to the function. +ORACLE-SPECIFIC DATABASE FUNCTIONS + ora_server_version + $versions = $dbh->func('ora_server_version'); + + Returns an array reference of server version strings e.g., + + [11,2,0,2,0] + DATABASE HANDLE METHODS selectall_arrayref $ary_ref = $dbh->selectall_arrayref($sql); @@ -4110,7 +4118,6 @@ CONTRIBUTING A git mirror of the subversion is also available at `https://github.com/yanick/DBD-Oracle`. -Oracle Related Links WHICH VERSION OF DBD::ORACLE IS FOR ME? From version 1.25 onwards DBD::Oracle only support Oracle clients 9.2 or greater. Support for ProC connections was dropped in 1.29. diff --git a/README.mkdn b/README.mkdn index 1fd96542..36501021 100644 --- a/README.mkdn +++ b/README.mkdn @@ -1028,6 +1028,16 @@ Returns a hash reference containing the current NLS parameters, as given by the v$nls\_parameters view. The values fetched are cached between calls. To cause the latest values to be fetched, pass a true value to the function. +# ORACLE-SPECIFIC DATABASE FUNCTIONS + +## __ora\_server\_version__ + + $versions = $dbh->func('ora_server_version'); + +Returns an array reference of server version strings e.g., + + [11,2,0,2,0] + # DATABASE HANDLE METHODS ## __selectall\_arrayref__ @@ -4122,8 +4132,6 @@ you may not be aware of. A git mirror of the subversion is also available at \`https://github.com/yanick/DBD-Oracle\`. -# Oracle Related Links - # WHICH VERSION OF DBD::ORACLE IS FOR ME? From version 1.25 onwards DBD::Oracle only support Oracle clients From 6a5741617a81a31fff105be8a209801a7aae5d50 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Nov 2012 18:40:51 +0000 Subject: [PATCH 367/637] updated READMEs git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15486 50811bd7-b8ce-0310-adc1-d9db26280581 --- README | 9 ++++++++- README.mkdn | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/README b/README index c30268b6..b78d5db5 100644 --- a/README +++ b/README @@ -963,6 +963,14 @@ ORACLE-SPECIFIC DATABASE HANDLE METHODS calls. To cause the latest values to be fetched, pass a true value to the function. +ORACLE-SPECIFIC DATABASE FUNCTIONS + ora_server_version + $versions = $dbh->func('ora_server_version'); + + Returns an array reference of server version strings e.g., + + [11,2,0,2,0] + DATABASE HANDLE METHODS selectall_arrayref $ary_ref = $dbh->selectall_arrayref($sql); @@ -4110,7 +4118,6 @@ CONTRIBUTING A git mirror of the subversion is also available at `https://github.com/yanick/DBD-Oracle`. -Oracle Related Links WHICH VERSION OF DBD::ORACLE IS FOR ME? From version 1.25 onwards DBD::Oracle only support Oracle clients 9.2 or greater. Support for ProC connections was dropped in 1.29. diff --git a/README.mkdn b/README.mkdn index 1fd96542..36501021 100644 --- a/README.mkdn +++ b/README.mkdn @@ -1028,6 +1028,16 @@ Returns a hash reference containing the current NLS parameters, as given by the v$nls\_parameters view. The values fetched are cached between calls. To cause the latest values to be fetched, pass a true value to the function. +# ORACLE-SPECIFIC DATABASE FUNCTIONS + +## __ora\_server\_version__ + + $versions = $dbh->func('ora_server_version'); + +Returns an array reference of server version strings e.g., + + [11,2,0,2,0] + # DATABASE HANDLE METHODS ## __selectall\_arrayref__ @@ -4122,8 +4132,6 @@ you may not be aware of. A git mirror of the subversion is also available at \`https://github.com/yanick/DBD-Oracle\`. -# Oracle Related Links - # WHICH VERSION OF DBD::ORACLE IS FOR ME? From version 1.25 onwards DBD::Oracle only support Oracle clients From 0f7733e77861f9ce56b51246bd91e125d7eb5dc7 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Nov 2012 18:40:55 +0000 Subject: [PATCH 368/637] Move 'ExecuteArray' in t/lib git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15487 50811bd7-b8ce-0310-adc1-d9db26280581 --- MANIFEST | 2 +- t/26exe_array.t | 2 +- t/{ => lib}/ExecuteArray.pm | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename t/{ => lib}/ExecuteArray.pm (100%) diff --git a/MANIFEST b/MANIFEST index d1564f89..6b41e5b5 100644 --- a/MANIFEST +++ b/MANIFEST @@ -67,7 +67,6 @@ t/23wide_db_al32utf8.t t/24implicit_utf8.t t/25plsql.t t/26exe_array.t -t/ExecuteArray.pm t/28array_bind.t t/30long.t t/31lob.t @@ -86,6 +85,7 @@ t/58object.t t/60reauth.t t/70meta.t t/80ora_charset.t +t/lib/ExecuteArray.pm t/nchar_test_lib.pl t/rt13865.t t/rt74753-utf8-encoded.t diff --git a/t/26exe_array.t b/t/26exe_array.t index 1b4f0e66..eb9fab9d 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -9,7 +9,7 @@ use strict; use Data::Dumper; require 'nchar_test_lib.pl'; -use lib './t'; +use lib 't/lib'; $| = 1; diff --git a/t/ExecuteArray.pm b/t/lib/ExecuteArray.pm similarity index 100% rename from t/ExecuteArray.pm rename to t/lib/ExecuteArray.pm From 2b1d4ae5b517bf2629804fcdee2cf78357ad0272 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Nov 2012 18:40:55 +0000 Subject: [PATCH 369/637] Move 'ExecuteArray' in t/lib git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15487 50811bd7-b8ce-0310-adc1-d9db26280581 --- MANIFEST | 2 +- t/26exe_array.t | 2 +- t/{ => lib}/ExecuteArray.pm | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename t/{ => lib}/ExecuteArray.pm (100%) diff --git a/MANIFEST b/MANIFEST index d1564f89..6b41e5b5 100644 --- a/MANIFEST +++ b/MANIFEST @@ -67,7 +67,6 @@ t/23wide_db_al32utf8.t t/24implicit_utf8.t t/25plsql.t t/26exe_array.t -t/ExecuteArray.pm t/28array_bind.t t/30long.t t/31lob.t @@ -86,6 +85,7 @@ t/58object.t t/60reauth.t t/70meta.t t/80ora_charset.t +t/lib/ExecuteArray.pm t/nchar_test_lib.pl t/rt13865.t t/rt74753-utf8-encoded.t diff --git a/t/26exe_array.t b/t/26exe_array.t index 1b4f0e66..eb9fab9d 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -9,7 +9,7 @@ use strict; use Data::Dumper; require 'nchar_test_lib.pl'; -use lib './t'; +use lib 't/lib'; $| = 1; diff --git a/t/ExecuteArray.pm b/t/lib/ExecuteArray.pm similarity index 100% rename from t/ExecuteArray.pm rename to t/lib/ExecuteArray.pm From 3bf981d6d25384e70a91601d9e42890d6261f0f3 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 26 Nov 2012 13:58:24 -0500 Subject: [PATCH 370/637] RT-69350: use lob after sth is destroyed Thanks to Rob Davies --- t/31lob.t | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/t/31lob.t b/t/31lob.t index 27d66afb..56366555 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -123,8 +123,10 @@ sub have_v_session { ## test calling PL/SQL with LOB placeholder my $plsql_testcount = 4; - $stmt = "BEGIN ? := DBMS_LOB.GETLENGTH( ? ); END;"; - $sth = $dbh->prepare( $stmt, { ora_auto_lob => 0 } ); + my $sth = $dbh->prepare( + 'BEGIN ? := DBMS_LOB.GETLENGTH( ? ); END;', + { ora_auto_lob => 0 } + ); $sth->bind_param_inout( 1, \$len, 16 ); $sth->bind_param( 2, $loc, { ora_type => ORA_BLOB } ); $sth->execute; From 9736dd71fc173a3ccd425e47b06ca2f7acef5cba Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 26 Nov 2012 14:03:40 -0500 Subject: [PATCH 371/637] needs '/t' as well --- t/26exe_array.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/26exe_array.t b/t/26exe_array.t index eb9fab9d..1e865d3f 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -9,7 +9,7 @@ use strict; use Data::Dumper; require 'nchar_test_lib.pl'; -use lib 't/lib'; +use lib 't/lib', 't'; $| = 1; From 38a4184a36c32594a040ebc36003db5e014cc669 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Nov 2012 19:09:03 +0000 Subject: [PATCH 372/637] RT-69350: use lob after sth is destroyed Thanks to Rob Davies git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15488 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/31lob.t | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/t/31lob.t b/t/31lob.t index 27d66afb..56366555 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -123,8 +123,10 @@ sub have_v_session { ## test calling PL/SQL with LOB placeholder my $plsql_testcount = 4; - $stmt = "BEGIN ? := DBMS_LOB.GETLENGTH( ? ); END;"; - $sth = $dbh->prepare( $stmt, { ora_auto_lob => 0 } ); + my $sth = $dbh->prepare( + 'BEGIN ? := DBMS_LOB.GETLENGTH( ? ); END;', + { ora_auto_lob => 0 } + ); $sth->bind_param_inout( 1, \$len, 16 ); $sth->bind_param( 2, $loc, { ora_type => ORA_BLOB } ); $sth->execute; From e7cf26a5d702b0c791035e98736f50f5c772d730 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Nov 2012 19:09:03 +0000 Subject: [PATCH 373/637] RT-69350: use lob after sth is destroyed Thanks to Rob Davies git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15488 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/31lob.t | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/t/31lob.t b/t/31lob.t index 27d66afb..56366555 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -123,8 +123,10 @@ sub have_v_session { ## test calling PL/SQL with LOB placeholder my $plsql_testcount = 4; - $stmt = "BEGIN ? := DBMS_LOB.GETLENGTH( ? ); END;"; - $sth = $dbh->prepare( $stmt, { ora_auto_lob => 0 } ); + my $sth = $dbh->prepare( + 'BEGIN ? := DBMS_LOB.GETLENGTH( ? ); END;', + { ora_auto_lob => 0 } + ); $sth->bind_param_inout( 1, \$len, 16 ); $sth->bind_param( 2, $loc, { ora_type => ORA_BLOB } ); $sth->execute; From c9ffef197f81e50186ef831330cbbf219fc62e99 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Nov 2012 19:09:07 +0000 Subject: [PATCH 374/637] needs '/t' as well git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15489 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/26exe_array.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/26exe_array.t b/t/26exe_array.t index eb9fab9d..1e865d3f 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -9,7 +9,7 @@ use strict; use Data::Dumper; require 'nchar_test_lib.pl'; -use lib 't/lib'; +use lib 't/lib', 't'; $| = 1; From e64a8f07e56f21ed9fd91d85c7378a73dcc708c4 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 26 Nov 2012 19:09:07 +0000 Subject: [PATCH 375/637] needs '/t' as well git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15489 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/26exe_array.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/26exe_array.t b/t/26exe_array.t index eb9fab9d..1e865d3f 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -9,7 +9,7 @@ use strict; use Data::Dumper; require 'nchar_test_lib.pl'; -use lib 't/lib'; +use lib 't/lib', 't'; $| = 1; From 9ae7030c6ce42598be55b2d337589224f8c64cd9 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 26 Nov 2012 14:11:18 -0500 Subject: [PATCH 376/637] RT69350 note to Changes --- Changes | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 301d0280..55655829 100644 --- a/Changes +++ b/Changes @@ -3,8 +3,10 @@ Revision history for DBD::Oracle NEXT_VERSION [BUG FIXES] + - Fix RT69350 - 31lob.t was using $lob after destroying its parent $sth + (Rob Davies) - - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) + - Fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails can contain the wrong error count. Thanks to Steffen Goeldner for From 8c58b76c942915210e61c777232835689c2cf3c5 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 17 Dec 2012 14:29:10 +0000 Subject: [PATCH 377/637] SvUPGRADE is no longer an expression. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15519 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 +++++ dbdimp.c | 6 +++--- oci8.c | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 301d0280..d6034d4a 100644 --- a/Changes +++ b/Changes @@ -62,6 +62,11 @@ NEXT_VERSION - Removed ineffective commit in 34pres_lobs.t (Martin J. Evans) + - Changed any use of if SvUPGRADE to remove the if test as per email + from Dave Mitchell and posting at + http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2012-12/msg00424.html + (Martin J. Evans) + 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/dbdimp.c b/dbdimp.c index 1eb8a36d..0376adc4 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1707,7 +1707,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) sv_2pv(item, &length); } } else { /* ensure we're at least an SVt_PV (so SvPVX etc work) */ - if(SvUPGRADE(item, SVt_PV)){} + (void)SvUPGRADE(item, SVt_PV); } } if( length == 0 ){ @@ -2513,7 +2513,7 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) sv_2pv(phs->sv, &PL_na); } else /* ensure we're at least an SVt_PV (so SvPVX etc work) */ - if(SvUPGRADE(phs->sv, SVt_PV)){} /* For gcc not to warn on unused result)*/; + (void) SvUPGRADE(phs->sv, SVt_PV); } @@ -3800,7 +3800,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er /*check to see if value sv is a null (undef) if it is upgrade it*/ if (!SvOK(sv)) { - if(SvUPGRADE(sv, SVt_PV)){} /* For GCC not to warn on unused result */ + (void)SvUPGRADE(sv, SVt_PV); } else { SvPV(sv, len); diff --git a/oci8.c b/oci8.c index dafc74ba..14d4485a 100644 --- a/oci8.c +++ b/oci8.c @@ -1644,7 +1644,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) sv_2pv(phs->sv, &PL_na); } else { /* ensure we're at least an SVt_PV (so SvPVX etc work) */ - if(SvUPGRADE(phs->sv, SVt_PV)){} /* For GCC not to warn on unused result */ + (void)SvUPGRADE(phs->sv, SVt_PV); } } @@ -1675,7 +1675,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) imp_sth->stmt_type == OCI_STMT_DECLARE) { ub4 amtp; - if(SvUPGRADE(phs->sv, SVt_PV)){/* For GCC not to warn on unused result */}; /* just in case */ + (void)SvUPGRADE(phs->sv, SVt_PV); amtp = SvCUR(phs->sv); /* XXX UTF8? */ @@ -4812,7 +4812,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl phs_t *phs = (phs_t*)fbh->special; ub4 amtp; - if(SvUPGRADE(phs->sv, SVt_PV)){/* For GCC not to warn on unused result */ }; /* just in case */ + (void)SvUPGRADE(phs->sv, SVt_PV); amtp = SvCUR(phs->sv); /* XXX UTF8? */ if (rc == 1405) { /* NULL - return undef */ From 42e08a4caf28ba032893b11ffc62eee88284aee6 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 17 Dec 2012 14:29:10 +0000 Subject: [PATCH 378/637] SvUPGRADE is no longer an expression. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15519 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 +++++ dbdimp.c | 6 +++--- oci8.c | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 301d0280..d6034d4a 100644 --- a/Changes +++ b/Changes @@ -62,6 +62,11 @@ NEXT_VERSION - Removed ineffective commit in 34pres_lobs.t (Martin J. Evans) + - Changed any use of if SvUPGRADE to remove the if test as per email + from Dave Mitchell and posting at + http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2012-12/msg00424.html + (Martin J. Evans) + 1.52 2012-10-19 - promote 1.51_00 to official release diff --git a/dbdimp.c b/dbdimp.c index 1eb8a36d..0376adc4 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1707,7 +1707,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) sv_2pv(item, &length); } } else { /* ensure we're at least an SVt_PV (so SvPVX etc work) */ - if(SvUPGRADE(item, SVt_PV)){} + (void)SvUPGRADE(item, SVt_PV); } } if( length == 0 ){ @@ -2513,7 +2513,7 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) sv_2pv(phs->sv, &PL_na); } else /* ensure we're at least an SVt_PV (so SvPVX etc work) */ - if(SvUPGRADE(phs->sv, SVt_PV)){} /* For gcc not to warn on unused result)*/; + (void) SvUPGRADE(phs->sv, SVt_PV); } @@ -3800,7 +3800,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er /*check to see if value sv is a null (undef) if it is upgrade it*/ if (!SvOK(sv)) { - if(SvUPGRADE(sv, SVt_PV)){} /* For GCC not to warn on unused result */ + (void)SvUPGRADE(sv, SVt_PV); } else { SvPV(sv, len); diff --git a/oci8.c b/oci8.c index dafc74ba..14d4485a 100644 --- a/oci8.c +++ b/oci8.c @@ -1644,7 +1644,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) sv_2pv(phs->sv, &PL_na); } else { /* ensure we're at least an SVt_PV (so SvPVX etc work) */ - if(SvUPGRADE(phs->sv, SVt_PV)){} /* For GCC not to warn on unused result */ + (void)SvUPGRADE(phs->sv, SVt_PV); } } @@ -1675,7 +1675,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) imp_sth->stmt_type == OCI_STMT_DECLARE) { ub4 amtp; - if(SvUPGRADE(phs->sv, SVt_PV)){/* For GCC not to warn on unused result */}; /* just in case */ + (void)SvUPGRADE(phs->sv, SVt_PV); amtp = SvCUR(phs->sv); /* XXX UTF8? */ @@ -4812,7 +4812,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl phs_t *phs = (phs_t*)fbh->special; ub4 amtp; - if(SvUPGRADE(phs->sv, SVt_PV)){/* For GCC not to warn on unused result */ }; /* just in case */ + (void)SvUPGRADE(phs->sv, SVt_PV); amtp = SvCUR(phs->sv); /* XXX UTF8? */ if (rc == 1405) { /* NULL - return undef */ From 94b2f1edb2478db3c54f22dcdb61dba8a0b4a786 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 18 Dec 2012 10:42:14 -0500 Subject: [PATCH 379/637] Remove mention of README.wingcc.txt (RT#82040) --- lib/DBD/Oracle/Troubleshooting/Win32.pod | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index abe00447..f2cd390a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -6,9 +6,6 @@ In general, on Windows, it's best to just use ActiveState Perl and the PPM package manager to install a pre-built version of DBD::Oracle however only version 1.17 is available there. -If you built Perl with gcc, read README.wingcc.txt as well as this file. - - =head1 Oracle Instant Client 11.1.0.6.0 Notes So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value From 76a2ae737637e0951d94a277953ab84e115a0b03 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 18 Dec 2012 10:49:16 -0500 Subject: [PATCH 380/637] add change to Changelog --- Changes | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changes b/Changes index 55655829..2b1af322 100644 --- a/Changes +++ b/Changes @@ -64,6 +64,9 @@ NEXT_VERSION - Removed ineffective commit in 34pres_lobs.t (Martin J. Evans) + - Remove dead README link in Win32 documentation. (pointed out by Alexandr + Ciornii, RT#82040) + 1.52 2012-10-19 - promote 1.51_00 to official release From 37c8fabfa4134ca97313a8713132df95e5febd42 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 18 Dec 2012 10:59:30 -0500 Subject: [PATCH 381/637] preps for release --- MANIFEST | 2 +- dist.ini | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/MANIFEST b/MANIFEST index 6b41e5b5..95ee2f3e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -50,7 +50,7 @@ mkta.pl oci.def oci8.c ocitrace.h -t/000-report-versions.t +t/000-report-versions-tiny.t t/00versions.t t/01base.t t/10general.t diff --git a/dist.ini b/dist.ini index ce9f8ac9..f56f69a4 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.52 +version = 1.53_00 [Authority] authority=cpan:PYTHIAN @@ -26,6 +26,7 @@ authority=cpan:PYTHIAN -remove=Twitter -remove=Test::Compile -remove=Covenant +-remove=CoderwallEndorse [Prereqs / ConfigureRequires] DBI = 1.51 From fdd4d20d045d7400ef73ae9fffc332ba997cc5c1 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 18 Dec 2012 16:06:45 +0000 Subject: [PATCH 382/637] Preps for release 1.53_00 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15521 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 +- MANIFEST | 2 +- META.json | 18 +- META.yml | 11 +- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 4 +- lib/DBD/Oracle/GetInfo.pm | 4 +- lib/DBD/Oracle/Object.pm | 4 +- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 4 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- t/000-report-versions-tiny.t | 86 +++++ t/000-report-versions.t | 447 ---------------------- 21 files changed, 127 insertions(+), 482 deletions(-) create mode 100644 t/000-report-versions-tiny.t delete mode 100644 t/000-report-versions.t diff --git a/Changes b/Changes index d6034d4a..bedce500 100644 --- a/Changes +++ b/Changes @@ -3,8 +3,10 @@ Revision history for DBD::Oracle NEXT_VERSION [BUG FIXES] + - Fix RT69350 - 31lob.t was using $lob after destroying its parent $sth + (Rob Davies) - - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) + - Fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails can contain the wrong error count. Thanks to Steffen Goeldner for @@ -62,6 +64,9 @@ NEXT_VERSION - Removed ineffective commit in 34pres_lobs.t (Martin J. Evans) + - Remove dead README link in Win32 documentation. (pointed out by Alexandr + Ciornii, RT#82040) + - Changed any use of if SvUPGRADE to remove the if test as per email from Dave Mitchell and posting at http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2012-12/msg00424.html diff --git a/MANIFEST b/MANIFEST index 6b41e5b5..95ee2f3e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -50,7 +50,7 @@ mkta.pl oci.def oci8.c ocitrace.h -t/000-report-versions.t +t/000-report-versions-tiny.t t/00versions.t t/01base.t t/10general.t diff --git a/META.json b/META.json index 714bf468..31c8b503 100644 --- a/META.json +++ b/META.json @@ -23,6 +23,11 @@ "ExtUtils::MakeMaker" : "6.30" } }, + "develop" : { + "requires" : { + "version" : "0.9901" + } + }, "runtime" : { "requires" : { "DBI" : "0", @@ -41,8 +46,7 @@ "Devel::Peek" : "0", "Encode" : "0", "Math::BigInt" : "0", - "Scalar::Util" : "0", - "Test::More" : "0.94", + "Test::More" : "0.88", "Thread::Semaphore" : "0", "utf8" : "0", "vars" : "0" @@ -52,18 +56,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.52" + "version" : "1.53_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.52" + "version" : "1.53_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.52" + "version" : "1.53_00" } }, - "release_status" : "stable", + "release_status" : "testing", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -76,7 +80,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.52", + "version" : "1.53_00", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index 80f85e31..c6f35377 100644 --- a/META.yml +++ b/META.yml @@ -12,8 +12,7 @@ build_requires: Devel::Peek: 0 Encode: 0 Math::BigInt: 0 - Scalar::Util: 0 - Test::More: 0.94 + Test::More: 0.88 Thread::Semaphore: 0 utf8: 0 vars: 0 @@ -30,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.52 + version: 1.53_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.52 + version: 1.53_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.52 + version: 1.53_00 requires: DBI: 0 DynaLoader: 0 @@ -48,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.52 +version: 1.53_00 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index b78d5db5..72c8a686 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.52 + version 1.53_00 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index 36501021..99485c05 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.52 +version 1.53\_00 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 661e20a5..db357a21 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.52'; + $DBD::Oracle::VERSION = '1.53_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1153,7 +1153,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.52 +version 1.53_00 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 15c77bc6..4c83a5a0 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.52'; + $DBD::Oracle::GetInfo::VERSION = '1.53_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.52 +version 1.53_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index c495fc77..c1f26e68 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.52'; + $DBD::Oracle::Object::VERSION = '1.53_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -40,7 +40,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.52 +version 1.53_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index f97f62e5..ae600ee8 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index 7bebe180..4e5429df 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.52 +version 1.53_00 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index a65e7f1e..a4adbbc7 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.52 +version 1.53_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 927e0be9..c3d98e49 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 57f28b4a..a4cafe81 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 3ec94819..74428d1d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index f608e12f..82dedd8c 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.52 +version 1.53_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 7474e52f..827e5a98 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.52 +version 1.53_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index d0ff8edc..28d35b43 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,15 +11,13 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 GENERAL INFO In general, on Windows, it's best to just use ActiveState Perl and the PPM package manager to install a pre-built version of DBD::Oracle however only version 1.17 is available there. -If you built Perl with gcc, read README.wingcc.txt as well as this file. - =head1 Oracle Instant Client 11.1.0.6.0 Notes So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index ca2b5a47..3bf0a981 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 DBD::Oracle and Windows 64bit diff --git a/t/000-report-versions-tiny.t b/t/000-report-versions-tiny.t new file mode 100644 index 00000000..8e81e9c9 --- /dev/null +++ b/t/000-report-versions-tiny.t @@ -0,0 +1,86 @@ +use strict; +use warnings; +use Test::More 0.88; +# This is a relatively nice way to avoid Test::NoWarnings breaking our +# expectations by adding extra tests, without using no_plan. It also helps +# avoid any other test module that feels introducing random tests, or even +# test plans, is a nice idea. +our $success = 0; +END { $success && done_testing; } + +# List our own version used to generate this +my $v = "\nGenerated by Dist::Zilla::Plugin::ReportVersions::Tiny v1.08\n"; + +eval { # no excuses! + # report our Perl details + my $want = '5.006'; + $v .= "perl: $] (wanted $want) on $^O from $^X\n\n"; +}; +defined($@) and diag("$@"); + +# Now, our module version dependencies: +sub pmver { + my ($module, $wanted) = @_; + $wanted = " (want $wanted)"; + my $pmver; + eval "require $module;"; + if ($@) { + if ($@ =~ m/Can't locate .* in \@INC/) { + $pmver = 'module not found.'; + } else { + diag("${module}: $@"); + $pmver = 'died during require.'; + } + } else { + my $version; + eval { $version = $module->VERSION; }; + if ($@) { + diag("${module}: $@"); + $pmver = 'died during VERSION check.'; + } elsif (defined $version) { + $pmver = "$version"; + } else { + $pmver = ''; + } + } + + # So, we should be good, right? + return sprintf('%-45s => %-10s%-15s%s', $module, $pmver, $wanted, "\n"); +} + +eval { $v .= pmver('Carp','any version') }; +eval { $v .= pmver('Config','any version') }; +eval { $v .= pmver('DBI','1.51') }; +eval { $v .= pmver('Data::Dumper','any version') }; +eval { $v .= pmver('Devel::Peek','any version') }; +eval { $v .= pmver('DynaLoader','any version') }; +eval { $v .= pmver('Encode','any version') }; +eval { $v .= pmver('Exporter','any version') }; +eval { $v .= pmver('ExtUtils::MakeMaker','6.30') }; +eval { $v .= pmver('Math::BigInt','any version') }; +eval { $v .= pmver('Test::More','0.88') }; +eval { $v .= pmver('Thread::Semaphore','any version') }; +eval { $v .= pmver('strict','any version') }; +eval { $v .= pmver('utf8','any version') }; +eval { $v .= pmver('vars','any version') }; +eval { $v .= pmver('version','0.9901') }; +eval { $v .= pmver('warnings','any version') }; + + +# All done. +$v .= <<'EOT'; + +Thanks for using my code. I hope it works for you. +If not, please try and include this output in the bug report. +That will help me reproduce the issue and solve your problem. + +EOT + +diag($v); +ok(1, "we really didn't test anything, just reporting data"); +$success = 1; + +# Work around another nasty module on CPAN. :/ +no warnings 'once'; +$Template::Test::NO_FLUSH = 1; +exit 0; diff --git a/t/000-report-versions.t b/t/000-report-versions.t deleted file mode 100644 index 04c53948..00000000 --- a/t/000-report-versions.t +++ /dev/null @@ -1,447 +0,0 @@ -#!perl -use warnings; -use strict; -use Test::More 0.94; - -# Include a cut-down version of YAML::Tiny so we don't introduce unnecessary -# dependencies ourselves. - -package Local::YAML::Tiny; - -use strict; -use Carp 'croak'; - -# UTF Support? -sub HAVE_UTF8 () { $] >= 5.007003 } -BEGIN { - if ( HAVE_UTF8 ) { - # The string eval helps hide this from Test::MinimumVersion - eval "require utf8;"; - die "Failed to load UTF-8 support" if $@; - } - - # Class structure - require 5.004; - $YAML::Tiny::VERSION = '1.40'; - - # Error storage - $YAML::Tiny::errstr = ''; -} - -# Printable characters for escapes -my %UNESCAPES = ( - z => "\x00", a => "\x07", t => "\x09", - n => "\x0a", v => "\x0b", f => "\x0c", - r => "\x0d", e => "\x1b", '\\' => '\\', -); - - -##################################################################### -# Implementation - -# Create an empty YAML::Tiny object -sub new { - my $class = shift; - bless [ @_ ], $class; -} - -# Create an object from a file -sub read { - my $class = ref $_[0] ? ref shift : shift; - - # Check the file - my $file = shift or return $class->_error( 'You did not specify a file name' ); - return $class->_error( "File '$file' does not exist" ) unless -e $file; - return $class->_error( "'$file' is a directory, not a file" ) unless -f _; - return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; - - # Slurp in the file - local $/ = undef; - local *CFG; - unless ( open(CFG, $file) ) { - return $class->_error("Failed to open file '$file': $!"); - } - my $contents = ; - unless ( close(CFG) ) { - return $class->_error("Failed to close file '$file': $!"); - } - - $class->read_string( $contents ); -} - -# Create an object from a string -sub read_string { - my $class = ref $_[0] ? ref shift : shift; - my $self = bless [], $class; - my $string = $_[0]; - unless ( defined $string ) { - return $self->_error("Did not provide a string to load"); - } - - # Byte order marks - # NOTE: Keeping this here to educate maintainers - # my %BOM = ( - # "\357\273\277" => 'UTF-8', - # "\376\377" => 'UTF-16BE', - # "\377\376" => 'UTF-16LE', - # "\377\376\0\0" => 'UTF-32LE' - # "\0\0\376\377" => 'UTF-32BE', - # ); - if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) { - return $self->_error("Stream has a non UTF-8 BOM"); - } else { - # Strip UTF-8 bom if found, we'll just ignore it - $string =~ s/^\357\273\277//; - } - - # Try to decode as utf8 - utf8::decode($string) if HAVE_UTF8; - - # Check for some special cases - return $self unless length $string; - unless ( $string =~ /[\012\015]+\z/ ) { - return $self->_error("Stream does not end with newline character"); - } - - # Split the file into lines - my @lines = grep { ! /^\s*(?:\#.*)?\z/ } - split /(?:\015{1,2}\012|\015|\012)/, $string; - - # Strip the initial YAML header - @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; - - # A nibbling parser - while ( @lines ) { - # Do we have a document header? - if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { - # Handle scalar documents - shift @lines; - if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { - push @$self, $self->_read_scalar( "$1", [ undef ], \@lines ); - next; - } - } - - if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { - # A naked document - push @$self, undef; - while ( @lines and $lines[0] !~ /^---/ ) { - shift @lines; - } - - } elsif ( $lines[0] =~ /^\s*\-/ ) { - # An array at the root - my $document = [ ]; - push @$self, $document; - $self->_read_array( $document, [ 0 ], \@lines ); - - } elsif ( $lines[0] =~ /^(\s*)\S/ ) { - # A hash at the root - my $document = { }; - push @$self, $document; - $self->_read_hash( $document, [ length($1) ], \@lines ); - - } else { - croak("YAML::Tiny failed to classify the line '$lines[0]'"); - } - } - - $self; -} - -# Deparse a scalar string to the actual scalar -sub _read_scalar { - my ($self, $string, $indent, $lines) = @_; - - # Trim trailing whitespace - $string =~ s/\s*\z//; - - # Explitic null/undef - return undef if $string eq '~'; - - # Quotes - if ( $string =~ /^\'(.*?)\'\z/ ) { - return '' unless defined $1; - $string = $1; - $string =~ s/\'\'/\'/g; - return $string; - } - if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) { - # Reusing the variable is a little ugly, - # but avoids a new variable and a string copy. - $string = $1; - $string =~ s/\\"/"/g; - $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; - return $string; - } - - # Special cases - if ( $string =~ /^[\'\"!&]/ ) { - croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); - } - return {} if $string eq '{}'; - return [] if $string eq '[]'; - - # Regular unquoted string - return $string unless $string =~ /^[>|]/; - - # Error - croak("YAML::Tiny failed to find multi-line scalar content") unless @$lines; - - # Check the indent depth - $lines->[0] =~ /^(\s*)/; - $indent->[-1] = length("$1"); - if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { - croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); - } - - # Pull the lines - my @multiline = (); - while ( @$lines ) { - $lines->[0] =~ /^(\s*)/; - last unless length($1) >= $indent->[-1]; - push @multiline, substr(shift(@$lines), length($1)); - } - - my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; - my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; - return join( $j, @multiline ) . $t; -} - -# Parse an array -sub _read_array { - my ($self, $array, $indent, $lines) = @_; - - while ( @$lines ) { - # Check for a new document - if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { - while ( @$lines and $lines->[0] !~ /^---/ ) { - shift @$lines; - } - return 1; - } - - # Check the indent level - $lines->[0] =~ /^(\s*)/; - if ( length($1) < $indent->[-1] ) { - return 1; - } elsif ( length($1) > $indent->[-1] ) { - croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); - } - - if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { - # Inline nested hash - my $indent2 = length("$1"); - $lines->[0] =~ s/-/ /; - push @$array, { }; - $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); - - } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { - # Array entry with a value - shift @$lines; - push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines ); - - } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { - shift @$lines; - unless ( @$lines ) { - push @$array, undef; - return 1; - } - if ( $lines->[0] =~ /^(\s*)\-/ ) { - my $indent2 = length("$1"); - if ( $indent->[-1] == $indent2 ) { - # Null array entry - push @$array, undef; - } else { - # Naked indenter - push @$array, [ ]; - $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines ); - } - - } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { - push @$array, { }; - $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines ); - - } else { - croak("YAML::Tiny failed to classify line '$lines->[0]'"); - } - - } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { - # This is probably a structure like the following... - # --- - # foo: - # - list - # bar: value - # - # ... so lets return and let the hash parser handle it - return 1; - - } else { - croak("YAML::Tiny failed to classify line '$lines->[0]'"); - } - } - - return 1; -} - -# Parse an array -sub _read_hash { - my ($self, $hash, $indent, $lines) = @_; - - while ( @$lines ) { - # Check for a new document - if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { - while ( @$lines and $lines->[0] !~ /^---/ ) { - shift @$lines; - } - return 1; - } - - # Check the indent level - $lines->[0] =~ /^(\s*)/; - if ( length($1) < $indent->[-1] ) { - return 1; - } elsif ( length($1) > $indent->[-1] ) { - croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); - } - - # Get the key - unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { - if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { - croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); - } - croak("YAML::Tiny failed to classify line '$lines->[0]'"); - } - my $key = $1; - - # Do we have a value? - if ( length $lines->[0] ) { - # Yes - $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines ); - } else { - # An indent - shift @$lines; - unless ( @$lines ) { - $hash->{$key} = undef; - return 1; - } - if ( $lines->[0] =~ /^(\s*)-/ ) { - $hash->{$key} = []; - $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines ); - } elsif ( $lines->[0] =~ /^(\s*)./ ) { - my $indent2 = length("$1"); - if ( $indent->[-1] >= $indent2 ) { - # Null hash entry - $hash->{$key} = undef; - } else { - $hash->{$key} = {}; - $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); - } - } - } - } - - return 1; -} - -# Set error -sub _error { - $YAML::Tiny::errstr = $_[1]; - undef; -} - -# Retrieve error -sub errstr { - $YAML::Tiny::errstr; -} - - - -##################################################################### -# Use Scalar::Util if possible, otherwise emulate it - -BEGIN { - eval { - require Scalar::Util; - }; - if ( $@ ) { - # Failed to load Scalar::Util - eval <<'END_PERL'; -sub refaddr { - my $pkg = ref($_[0]) or return undef; - if (!!UNIVERSAL::can($_[0], 'can')) { - bless $_[0], 'Scalar::Util::Fake'; - } else { - $pkg = undef; - } - "$_[0]" =~ /0x(\w+)/; - my $i = do { local $^W; hex $1 }; - bless $_[0], $pkg if defined $pkg; - $i; -} -END_PERL - } else { - Scalar::Util->import('refaddr'); - } -} - - -##################################################################### -# main test -##################################################################### - -package main; - -BEGIN { - - # Skip modules that either don't want to be loaded directly, such as - # Module::Install, or that mess with the test count, such as the Test::* - # modules listed here. - # - # Moose::Role conflicts if Moose is loaded as well, but Moose::Role is in - # the Moose distribution and it's certain that someone who uses - # Moose::Role also uses Moose somewhere, so if we disallow Moose::Role, - # we'll still get the relevant version number. - - my %skip = map { $_ => 1 } qw( - App::FatPacker - Class::Accessor::Classy - Devel::Cover - Module::Install - Moose::Role - POE::Loop::Tk - Template::Test - Test::Kwalitee - Test::Pod::Coverage - Test::Portability::Files - Test::YAML::Meta - open - ); - - my $Test = Test::Builder->new; - - $Test->plan(skip_all => "META.yml could not be found") - unless -f 'META.yml' and -r _; - - my $meta = (Local::YAML::Tiny->read('META.yml'))->[0]; - my %requires; - for my $require_key (grep { /requires/ } keys %$meta) { - my %h = %{ $meta->{$require_key} }; - $requires{$_}++ for keys %h; - } - delete $requires{perl}; - - diag("Testing with Perl $], $^X"); - for my $module (sort keys %requires) { - if ($skip{$module}) { - note "$module doesn't want to be loaded directly, skipping"; - next; - } - local $SIG{__WARN__} = sub { note "$module: $_[0]" }; - require_ok $module or BAIL_OUT("can't load $module"); - my $version = $module->VERSION; - $version = 'undefined' unless defined $version; - diag(" $module version is $version"); - } - done_testing; -} From a19fc40e919cabe52afa12cb1cb605834101cc60 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 18 Dec 2012 16:06:45 +0000 Subject: [PATCH 383/637] Preps for release 1.53_00 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15521 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 +- MANIFEST | 2 +- META.json | 18 +- META.yml | 11 +- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 4 +- lib/DBD/Oracle/GetInfo.pm | 4 +- lib/DBD/Oracle/Object.pm | 4 +- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 4 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- t/000-report-versions-tiny.t | 86 +++++ t/000-report-versions.t | 447 ---------------------- 21 files changed, 127 insertions(+), 482 deletions(-) create mode 100644 t/000-report-versions-tiny.t delete mode 100644 t/000-report-versions.t diff --git a/Changes b/Changes index d6034d4a..bedce500 100644 --- a/Changes +++ b/Changes @@ -3,8 +3,10 @@ Revision history for DBD::Oracle NEXT_VERSION [BUG FIXES] + - Fix RT69350 - 31lob.t was using $lob after destroying its parent $sth + (Rob Davies) - - fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) + - Fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) - Fix RT80349 - The error message in execute_for_fetch when a row fails can contain the wrong error count. Thanks to Steffen Goeldner for @@ -62,6 +64,9 @@ NEXT_VERSION - Removed ineffective commit in 34pres_lobs.t (Martin J. Evans) + - Remove dead README link in Win32 documentation. (pointed out by Alexandr + Ciornii, RT#82040) + - Changed any use of if SvUPGRADE to remove the if test as per email from Dave Mitchell and posting at http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2012-12/msg00424.html diff --git a/MANIFEST b/MANIFEST index 6b41e5b5..95ee2f3e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -50,7 +50,7 @@ mkta.pl oci.def oci8.c ocitrace.h -t/000-report-versions.t +t/000-report-versions-tiny.t t/00versions.t t/01base.t t/10general.t diff --git a/META.json b/META.json index 714bf468..31c8b503 100644 --- a/META.json +++ b/META.json @@ -23,6 +23,11 @@ "ExtUtils::MakeMaker" : "6.30" } }, + "develop" : { + "requires" : { + "version" : "0.9901" + } + }, "runtime" : { "requires" : { "DBI" : "0", @@ -41,8 +46,7 @@ "Devel::Peek" : "0", "Encode" : "0", "Math::BigInt" : "0", - "Scalar::Util" : "0", - "Test::More" : "0.94", + "Test::More" : "0.88", "Thread::Semaphore" : "0", "utf8" : "0", "vars" : "0" @@ -52,18 +56,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.52" + "version" : "1.53_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.52" + "version" : "1.53_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.52" + "version" : "1.53_00" } }, - "release_status" : "stable", + "release_status" : "testing", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -76,7 +80,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.52", + "version" : "1.53_00", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index 80f85e31..c6f35377 100644 --- a/META.yml +++ b/META.yml @@ -12,8 +12,7 @@ build_requires: Devel::Peek: 0 Encode: 0 Math::BigInt: 0 - Scalar::Util: 0 - Test::More: 0.94 + Test::More: 0.88 Thread::Semaphore: 0 utf8: 0 vars: 0 @@ -30,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.52 + version: 1.53_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.52 + version: 1.53_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.52 + version: 1.53_00 requires: DBI: 0 DynaLoader: 0 @@ -48,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.52 +version: 1.53_00 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index b78d5db5..72c8a686 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.52 + version 1.53_00 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index 36501021..99485c05 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.52 +version 1.53\_00 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 661e20a5..db357a21 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.52'; + $DBD::Oracle::VERSION = '1.53_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1153,7 +1153,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.52 +version 1.53_00 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 15c77bc6..4c83a5a0 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.52'; + $DBD::Oracle::GetInfo::VERSION = '1.53_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.52 +version 1.53_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index c495fc77..c1f26e68 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.52'; + $DBD::Oracle::Object::VERSION = '1.53_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -40,7 +40,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.52 +version 1.53_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index f97f62e5..ae600ee8 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index 7bebe180..4e5429df 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.52 +version 1.53_00 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index a65e7f1e..a4adbbc7 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.52 +version 1.53_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 927e0be9..c3d98e49 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 57f28b4a..a4cafe81 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 3ec94819..74428d1d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index f608e12f..82dedd8c 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.52 +version 1.53_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 7474e52f..827e5a98 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.52 +version 1.53_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index d0ff8edc..28d35b43 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,15 +11,13 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 GENERAL INFO In general, on Windows, it's best to just use ActiveState Perl and the PPM package manager to install a pre-built version of DBD::Oracle however only version 1.17 is available there. -If you built Perl with gcc, read README.wingcc.txt as well as this file. - =head1 Oracle Instant Client 11.1.0.6.0 Notes So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index ca2b5a47..3bf0a981 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.52 +version 1.53_00 =head1 DBD::Oracle and Windows 64bit diff --git a/t/000-report-versions-tiny.t b/t/000-report-versions-tiny.t new file mode 100644 index 00000000..8e81e9c9 --- /dev/null +++ b/t/000-report-versions-tiny.t @@ -0,0 +1,86 @@ +use strict; +use warnings; +use Test::More 0.88; +# This is a relatively nice way to avoid Test::NoWarnings breaking our +# expectations by adding extra tests, without using no_plan. It also helps +# avoid any other test module that feels introducing random tests, or even +# test plans, is a nice idea. +our $success = 0; +END { $success && done_testing; } + +# List our own version used to generate this +my $v = "\nGenerated by Dist::Zilla::Plugin::ReportVersions::Tiny v1.08\n"; + +eval { # no excuses! + # report our Perl details + my $want = '5.006'; + $v .= "perl: $] (wanted $want) on $^O from $^X\n\n"; +}; +defined($@) and diag("$@"); + +# Now, our module version dependencies: +sub pmver { + my ($module, $wanted) = @_; + $wanted = " (want $wanted)"; + my $pmver; + eval "require $module;"; + if ($@) { + if ($@ =~ m/Can't locate .* in \@INC/) { + $pmver = 'module not found.'; + } else { + diag("${module}: $@"); + $pmver = 'died during require.'; + } + } else { + my $version; + eval { $version = $module->VERSION; }; + if ($@) { + diag("${module}: $@"); + $pmver = 'died during VERSION check.'; + } elsif (defined $version) { + $pmver = "$version"; + } else { + $pmver = ''; + } + } + + # So, we should be good, right? + return sprintf('%-45s => %-10s%-15s%s', $module, $pmver, $wanted, "\n"); +} + +eval { $v .= pmver('Carp','any version') }; +eval { $v .= pmver('Config','any version') }; +eval { $v .= pmver('DBI','1.51') }; +eval { $v .= pmver('Data::Dumper','any version') }; +eval { $v .= pmver('Devel::Peek','any version') }; +eval { $v .= pmver('DynaLoader','any version') }; +eval { $v .= pmver('Encode','any version') }; +eval { $v .= pmver('Exporter','any version') }; +eval { $v .= pmver('ExtUtils::MakeMaker','6.30') }; +eval { $v .= pmver('Math::BigInt','any version') }; +eval { $v .= pmver('Test::More','0.88') }; +eval { $v .= pmver('Thread::Semaphore','any version') }; +eval { $v .= pmver('strict','any version') }; +eval { $v .= pmver('utf8','any version') }; +eval { $v .= pmver('vars','any version') }; +eval { $v .= pmver('version','0.9901') }; +eval { $v .= pmver('warnings','any version') }; + + +# All done. +$v .= <<'EOT'; + +Thanks for using my code. I hope it works for you. +If not, please try and include this output in the bug report. +That will help me reproduce the issue and solve your problem. + +EOT + +diag($v); +ok(1, "we really didn't test anything, just reporting data"); +$success = 1; + +# Work around another nasty module on CPAN. :/ +no warnings 'once'; +$Template::Test::NO_FLUSH = 1; +exit 0; diff --git a/t/000-report-versions.t b/t/000-report-versions.t deleted file mode 100644 index 04c53948..00000000 --- a/t/000-report-versions.t +++ /dev/null @@ -1,447 +0,0 @@ -#!perl -use warnings; -use strict; -use Test::More 0.94; - -# Include a cut-down version of YAML::Tiny so we don't introduce unnecessary -# dependencies ourselves. - -package Local::YAML::Tiny; - -use strict; -use Carp 'croak'; - -# UTF Support? -sub HAVE_UTF8 () { $] >= 5.007003 } -BEGIN { - if ( HAVE_UTF8 ) { - # The string eval helps hide this from Test::MinimumVersion - eval "require utf8;"; - die "Failed to load UTF-8 support" if $@; - } - - # Class structure - require 5.004; - $YAML::Tiny::VERSION = '1.40'; - - # Error storage - $YAML::Tiny::errstr = ''; -} - -# Printable characters for escapes -my %UNESCAPES = ( - z => "\x00", a => "\x07", t => "\x09", - n => "\x0a", v => "\x0b", f => "\x0c", - r => "\x0d", e => "\x1b", '\\' => '\\', -); - - -##################################################################### -# Implementation - -# Create an empty YAML::Tiny object -sub new { - my $class = shift; - bless [ @_ ], $class; -} - -# Create an object from a file -sub read { - my $class = ref $_[0] ? ref shift : shift; - - # Check the file - my $file = shift or return $class->_error( 'You did not specify a file name' ); - return $class->_error( "File '$file' does not exist" ) unless -e $file; - return $class->_error( "'$file' is a directory, not a file" ) unless -f _; - return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; - - # Slurp in the file - local $/ = undef; - local *CFG; - unless ( open(CFG, $file) ) { - return $class->_error("Failed to open file '$file': $!"); - } - my $contents = ; - unless ( close(CFG) ) { - return $class->_error("Failed to close file '$file': $!"); - } - - $class->read_string( $contents ); -} - -# Create an object from a string -sub read_string { - my $class = ref $_[0] ? ref shift : shift; - my $self = bless [], $class; - my $string = $_[0]; - unless ( defined $string ) { - return $self->_error("Did not provide a string to load"); - } - - # Byte order marks - # NOTE: Keeping this here to educate maintainers - # my %BOM = ( - # "\357\273\277" => 'UTF-8', - # "\376\377" => 'UTF-16BE', - # "\377\376" => 'UTF-16LE', - # "\377\376\0\0" => 'UTF-32LE' - # "\0\0\376\377" => 'UTF-32BE', - # ); - if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) { - return $self->_error("Stream has a non UTF-8 BOM"); - } else { - # Strip UTF-8 bom if found, we'll just ignore it - $string =~ s/^\357\273\277//; - } - - # Try to decode as utf8 - utf8::decode($string) if HAVE_UTF8; - - # Check for some special cases - return $self unless length $string; - unless ( $string =~ /[\012\015]+\z/ ) { - return $self->_error("Stream does not end with newline character"); - } - - # Split the file into lines - my @lines = grep { ! /^\s*(?:\#.*)?\z/ } - split /(?:\015{1,2}\012|\015|\012)/, $string; - - # Strip the initial YAML header - @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines; - - # A nibbling parser - while ( @lines ) { - # Do we have a document header? - if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) { - # Handle scalar documents - shift @lines; - if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) { - push @$self, $self->_read_scalar( "$1", [ undef ], \@lines ); - next; - } - } - - if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) { - # A naked document - push @$self, undef; - while ( @lines and $lines[0] !~ /^---/ ) { - shift @lines; - } - - } elsif ( $lines[0] =~ /^\s*\-/ ) { - # An array at the root - my $document = [ ]; - push @$self, $document; - $self->_read_array( $document, [ 0 ], \@lines ); - - } elsif ( $lines[0] =~ /^(\s*)\S/ ) { - # A hash at the root - my $document = { }; - push @$self, $document; - $self->_read_hash( $document, [ length($1) ], \@lines ); - - } else { - croak("YAML::Tiny failed to classify the line '$lines[0]'"); - } - } - - $self; -} - -# Deparse a scalar string to the actual scalar -sub _read_scalar { - my ($self, $string, $indent, $lines) = @_; - - # Trim trailing whitespace - $string =~ s/\s*\z//; - - # Explitic null/undef - return undef if $string eq '~'; - - # Quotes - if ( $string =~ /^\'(.*?)\'\z/ ) { - return '' unless defined $1; - $string = $1; - $string =~ s/\'\'/\'/g; - return $string; - } - if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) { - # Reusing the variable is a little ugly, - # but avoids a new variable and a string copy. - $string = $1; - $string =~ s/\\"/"/g; - $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; - return $string; - } - - # Special cases - if ( $string =~ /^[\'\"!&]/ ) { - croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); - } - return {} if $string eq '{}'; - return [] if $string eq '[]'; - - # Regular unquoted string - return $string unless $string =~ /^[>|]/; - - # Error - croak("YAML::Tiny failed to find multi-line scalar content") unless @$lines; - - # Check the indent depth - $lines->[0] =~ /^(\s*)/; - $indent->[-1] = length("$1"); - if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { - croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); - } - - # Pull the lines - my @multiline = (); - while ( @$lines ) { - $lines->[0] =~ /^(\s*)/; - last unless length($1) >= $indent->[-1]; - push @multiline, substr(shift(@$lines), length($1)); - } - - my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; - my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; - return join( $j, @multiline ) . $t; -} - -# Parse an array -sub _read_array { - my ($self, $array, $indent, $lines) = @_; - - while ( @$lines ) { - # Check for a new document - if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { - while ( @$lines and $lines->[0] !~ /^---/ ) { - shift @$lines; - } - return 1; - } - - # Check the indent level - $lines->[0] =~ /^(\s*)/; - if ( length($1) < $indent->[-1] ) { - return 1; - } elsif ( length($1) > $indent->[-1] ) { - croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); - } - - if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { - # Inline nested hash - my $indent2 = length("$1"); - $lines->[0] =~ s/-/ /; - push @$array, { }; - $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines ); - - } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) { - # Array entry with a value - shift @$lines; - push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines ); - - } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) { - shift @$lines; - unless ( @$lines ) { - push @$array, undef; - return 1; - } - if ( $lines->[0] =~ /^(\s*)\-/ ) { - my $indent2 = length("$1"); - if ( $indent->[-1] == $indent2 ) { - # Null array entry - push @$array, undef; - } else { - # Naked indenter - push @$array, [ ]; - $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines ); - } - - } elsif ( $lines->[0] =~ /^(\s*)\S/ ) { - push @$array, { }; - $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines ); - - } else { - croak("YAML::Tiny failed to classify line '$lines->[0]'"); - } - - } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { - # This is probably a structure like the following... - # --- - # foo: - # - list - # bar: value - # - # ... so lets return and let the hash parser handle it - return 1; - - } else { - croak("YAML::Tiny failed to classify line '$lines->[0]'"); - } - } - - return 1; -} - -# Parse an array -sub _read_hash { - my ($self, $hash, $indent, $lines) = @_; - - while ( @$lines ) { - # Check for a new document - if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) { - while ( @$lines and $lines->[0] !~ /^---/ ) { - shift @$lines; - } - return 1; - } - - # Check the indent level - $lines->[0] =~ /^(\s*)/; - if ( length($1) < $indent->[-1] ) { - return 1; - } elsif ( length($1) > $indent->[-1] ) { - croak("YAML::Tiny found bad indenting in line '$lines->[0]'"); - } - - # Get the key - unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { - if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { - croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); - } - croak("YAML::Tiny failed to classify line '$lines->[0]'"); - } - my $key = $1; - - # Do we have a value? - if ( length $lines->[0] ) { - # Yes - $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines ); - } else { - # An indent - shift @$lines; - unless ( @$lines ) { - $hash->{$key} = undef; - return 1; - } - if ( $lines->[0] =~ /^(\s*)-/ ) { - $hash->{$key} = []; - $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines ); - } elsif ( $lines->[0] =~ /^(\s*)./ ) { - my $indent2 = length("$1"); - if ( $indent->[-1] >= $indent2 ) { - # Null hash entry - $hash->{$key} = undef; - } else { - $hash->{$key} = {}; - $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); - } - } - } - } - - return 1; -} - -# Set error -sub _error { - $YAML::Tiny::errstr = $_[1]; - undef; -} - -# Retrieve error -sub errstr { - $YAML::Tiny::errstr; -} - - - -##################################################################### -# Use Scalar::Util if possible, otherwise emulate it - -BEGIN { - eval { - require Scalar::Util; - }; - if ( $@ ) { - # Failed to load Scalar::Util - eval <<'END_PERL'; -sub refaddr { - my $pkg = ref($_[0]) or return undef; - if (!!UNIVERSAL::can($_[0], 'can')) { - bless $_[0], 'Scalar::Util::Fake'; - } else { - $pkg = undef; - } - "$_[0]" =~ /0x(\w+)/; - my $i = do { local $^W; hex $1 }; - bless $_[0], $pkg if defined $pkg; - $i; -} -END_PERL - } else { - Scalar::Util->import('refaddr'); - } -} - - -##################################################################### -# main test -##################################################################### - -package main; - -BEGIN { - - # Skip modules that either don't want to be loaded directly, such as - # Module::Install, or that mess with the test count, such as the Test::* - # modules listed here. - # - # Moose::Role conflicts if Moose is loaded as well, but Moose::Role is in - # the Moose distribution and it's certain that someone who uses - # Moose::Role also uses Moose somewhere, so if we disallow Moose::Role, - # we'll still get the relevant version number. - - my %skip = map { $_ => 1 } qw( - App::FatPacker - Class::Accessor::Classy - Devel::Cover - Module::Install - Moose::Role - POE::Loop::Tk - Template::Test - Test::Kwalitee - Test::Pod::Coverage - Test::Portability::Files - Test::YAML::Meta - open - ); - - my $Test = Test::Builder->new; - - $Test->plan(skip_all => "META.yml could not be found") - unless -f 'META.yml' and -r _; - - my $meta = (Local::YAML::Tiny->read('META.yml'))->[0]; - my %requires; - for my $require_key (grep { /requires/ } keys %$meta) { - my %h = %{ $meta->{$require_key} }; - $requires{$_}++ for keys %h; - } - delete $requires{perl}; - - diag("Testing with Perl $], $^X"); - for my $module (sort keys %requires) { - if ($skip{$module}) { - note "$module doesn't want to be loaded directly, skipping"; - next; - } - local $SIG{__WARN__} = sub { note "$module: $_[0]" }; - require_ok $module or BAIL_OUT("can't load $module"); - my $version = $module->VERSION; - $version = 'undefined' unless defined $version; - diag(" $module version is $version"); - } - done_testing; -} From 914e2859823a3ed49d6f3603a342e616afc43c4b Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 3 Jan 2013 13:43:03 -0500 Subject: [PATCH 384/637] bump version to 1.54 --- Changes | 5 ++++- dist.ini | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index bedce500..0a79fec3 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for DBD::Oracle -NEXT_VERSION +{{$NEXT}} + - promote 1.53_00 to official release + +1.53_00 2012-12-18 [BUG FIXES] - Fix RT69350 - 31lob.t was using $lob after destroying its parent $sth diff --git a/dist.ini b/dist.ini index f56f69a4..f094a401 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.53_00 +version = 1.54 [Authority] authority=cpan:PYTHIAN From 1d376d6ef535760b37beeeb1f91aa6252636caa9 Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 3 Jan 2013 18:52:27 +0000 Subject: [PATCH 385/637] bump rev to v1.54 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15549 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++++- META.json | 10 +++++----- META.yml | 8 ++++---- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 4 ++-- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 18 files changed, 31 insertions(+), 28 deletions(-) diff --git a/Changes b/Changes index bedce500..f78ebe98 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for DBD::Oracle -NEXT_VERSION +1.54 2013-01-03 + - promote 1.53_00 to official release + +1.53_00 2012-12-18 [BUG FIXES] - Fix RT69350 - 31lob.t was using $lob after destroying its parent $sth diff --git a/META.json b/META.json index 31c8b503..3fa9df24 100644 --- a/META.json +++ b/META.json @@ -56,18 +56,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.53_00" + "version" : "1.54" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.53_00" + "version" : "1.54" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.53_00" + "version" : "1.54" } }, - "release_status" : "testing", + "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -80,7 +80,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.53_00", + "version" : "1.54", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index c6f35377..ea6163e3 100644 --- a/META.yml +++ b/META.yml @@ -29,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.53_00 + version: 1.54 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.53_00 + version: 1.54 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.53_00 + version: 1.54 requires: DBI: 0 DynaLoader: 0 @@ -47,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.53_00 +version: 1.54 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 72c8a686..91f9ddbb 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.53_00 + version 1.54 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index 99485c05..8c7e5eb1 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.53\_00 +version 1.54 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index db357a21..b84b3c9e 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.53_00'; + $DBD::Oracle::VERSION = '1.54'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1153,7 +1153,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.53_00 +version 1.54 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 4c83a5a0..7b5e68cc 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.53_00'; + $DBD::Oracle::GetInfo::VERSION = '1.54'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.53_00 +version 1.54 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index c1f26e68..9d5abae8 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.53_00'; + $DBD::Oracle::Object::VERSION = '1.54'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -40,7 +40,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.53_00 +version 1.54 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index ae600ee8..995f9250 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index 4e5429df..ef7771b8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.53_00 +version 1.54 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index a4adbbc7..8d8a44e6 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.53_00 +version 1.54 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index c3d98e49..7c5a516d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index a4cafe81..a3c1a8dd 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 74428d1d..04774e8b 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index 82dedd8c..b1796150 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.53_00 +version 1.54 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 827e5a98..d98359c8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.53_00 +version 1.54 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index 28d35b43..50a1d400 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 3bf0a981..8d92097a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 DBD::Oracle and Windows 64bit From 85959c6811da68ea38d741fd28910ab8cc2bc43c Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 3 Jan 2013 18:52:27 +0000 Subject: [PATCH 386/637] bump rev to v1.54 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15549 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 5 ++++- META.json | 10 +++++----- META.yml | 8 ++++---- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 4 ++-- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 18 files changed, 31 insertions(+), 28 deletions(-) diff --git a/Changes b/Changes index bedce500..f78ebe98 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for DBD::Oracle -NEXT_VERSION +1.54 2013-01-03 + - promote 1.53_00 to official release + +1.53_00 2012-12-18 [BUG FIXES] - Fix RT69350 - 31lob.t was using $lob after destroying its parent $sth diff --git a/META.json b/META.json index 31c8b503..3fa9df24 100644 --- a/META.json +++ b/META.json @@ -56,18 +56,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.53_00" + "version" : "1.54" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.53_00" + "version" : "1.54" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.53_00" + "version" : "1.54" } }, - "release_status" : "testing", + "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -80,7 +80,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.53_00", + "version" : "1.54", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index c6f35377..ea6163e3 100644 --- a/META.yml +++ b/META.yml @@ -29,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.53_00 + version: 1.54 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.53_00 + version: 1.54 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.53_00 + version: 1.54 requires: DBI: 0 DynaLoader: 0 @@ -47,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.53_00 +version: 1.54 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 72c8a686..91f9ddbb 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.53_00 + version 1.54 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index 99485c05..8c7e5eb1 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.53\_00 +version 1.54 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index db357a21..b84b3c9e 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.53_00'; + $DBD::Oracle::VERSION = '1.54'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1153,7 +1153,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.53_00 +version 1.54 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 4c83a5a0..7b5e68cc 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.53_00'; + $DBD::Oracle::GetInfo::VERSION = '1.54'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.53_00 +version 1.54 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index c1f26e68..9d5abae8 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.53_00'; + $DBD::Oracle::Object::VERSION = '1.54'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -40,7 +40,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.53_00 +version 1.54 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index ae600ee8..995f9250 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index 4e5429df..ef7771b8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.53_00 +version 1.54 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index a4adbbc7..8d8a44e6 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.53_00 +version 1.54 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index c3d98e49..7c5a516d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index a4cafe81..a3c1a8dd 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 74428d1d..04774e8b 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index 82dedd8c..b1796150 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.53_00 +version 1.54 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 827e5a98..d98359c8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.53_00 +version 1.54 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index 28d35b43..50a1d400 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 3bf0a981..8d92097a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.53_00 +version 1.54 =head1 DBD::Oracle and Windows 64bit From d754dbfe2094bc9632e8ce84271ba43d5ddef24d Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 7 Jan 2013 13:06:29 -0500 Subject: [PATCH 387/637] done_testing() removed from END block (RT82506) ... as that was too little, too late. --- Changes | 4 ++++ t/26exe_array.t | 50 ++++++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Changes b/Changes index 0a79fec3..9c1c87c9 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,10 @@ Revision history for DBD::Oracle {{$NEXT}} + - fix t/26exe_array.t in the case of no db connection (RT82506, + reported by Peter Rabbitson) + +1.54 2013-01-03 - promote 1.53_00 to official release 1.53_00 2012-12-18 diff --git a/t/26exe_array.t b/t/26exe_array.t index 1e865d3f..dce93725 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -13,43 +13,27 @@ use lib 't/lib', 't'; $| = 1; -my $has_test_nowarnings = 1; -eval "require Test::NoWarnings"; -$has_test_nowarnings = undef if $@; - -my ($dbh, $ea); +my $has_test_nowarnings = eval "require Test::NoWarnings; 1"; use DBI qw(:sql_types); use ExecuteArray; -END { - if ($dbh && $ea) { - $ea->drop_table($dbh); - $dbh->disconnect(); - } - Test::NoWarnings::had_no_warnings() - if ($has_test_nowarnings); - done_testing(); -} my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; $ENV{NLS_NCHAR} = "US7ASCII"; $ENV{NLS_LANG} = "AMERICAN"; -eval { - $dbh = DBI->connect($dsn, $dbuser, '', {PrintError => 0}); -}; +my $dbh = eval { + DBI->connect($dsn, $dbuser, '', {PrintError => 0}) +} or plan skip_all => "Unable to connect to Oracle"; -if (!$dbh) { - plan skip_all => "Unable to connect to Oracle"; -} - -$ea = ExecuteArray->new($dbh, 1); # set odbc_disable_array_operations +my $ea = ExecuteArray->new($dbh, 1); # set odbc_disable_array_operations $dbh = $ea->dbh; $ea->drop_table($dbh); ok($ea->create_table($dbh), "create test table") or exit 1; + $ea->simple($dbh, {array_context => 1, raise => 1}); $ea->simple($dbh, {array_context => 0, raise => 1}); $ea->error($dbh, {array_context => 1, raise => 1}); @@ -61,7 +45,21 @@ $ea->row_wise($dbh, {array_context => 1, raise => 1}); $ea->update($dbh, {array_context => 1, raise => 1}); -$ea->error($dbh, {array_context => 1, raise => 1, notuplestatus => 1}); -$ea->error($dbh, {array_context => 0, raise => 1, notuplestatus => 1}); -$ea->error($dbh, {array_context => 1, raise => 0, notuplestatus => 1}); -$ea->error($dbh, {array_context => 0, raise => 0, notuplestatus => 1}); +for my $raise ( 0..1 ) { + for my $context ( 0..1 ) { + $ea->error($dbh, { + array_context => $context, + raise => $raise, + notuplestatus => 1 + }); + } +} + +if ($dbh && $ea) { + $ea->drop_table($dbh); + $dbh->disconnect(); +} + +Test::NoWarnings::had_no_warnings() if $has_test_nowarnings; + +done_testing; From 61083a7b636cce56eb4ab68231477657359c868b Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 7 Jan 2013 18:11:29 +0000 Subject: [PATCH 388/637] done_testing() removed from END block (RT82506) ... as that was too little, too late. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15552 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ t/26exe_array.t | 50 ++++++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Changes b/Changes index f78ebe98..9c1c87c9 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,9 @@ Revision history for DBD::Oracle +{{$NEXT}} + - fix t/26exe_array.t in the case of no db connection (RT82506, + reported by Peter Rabbitson) + 1.54 2013-01-03 - promote 1.53_00 to official release diff --git a/t/26exe_array.t b/t/26exe_array.t index 1e865d3f..dce93725 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -13,43 +13,27 @@ use lib 't/lib', 't'; $| = 1; -my $has_test_nowarnings = 1; -eval "require Test::NoWarnings"; -$has_test_nowarnings = undef if $@; - -my ($dbh, $ea); +my $has_test_nowarnings = eval "require Test::NoWarnings; 1"; use DBI qw(:sql_types); use ExecuteArray; -END { - if ($dbh && $ea) { - $ea->drop_table($dbh); - $dbh->disconnect(); - } - Test::NoWarnings::had_no_warnings() - if ($has_test_nowarnings); - done_testing(); -} my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; $ENV{NLS_NCHAR} = "US7ASCII"; $ENV{NLS_LANG} = "AMERICAN"; -eval { - $dbh = DBI->connect($dsn, $dbuser, '', {PrintError => 0}); -}; +my $dbh = eval { + DBI->connect($dsn, $dbuser, '', {PrintError => 0}) +} or plan skip_all => "Unable to connect to Oracle"; -if (!$dbh) { - plan skip_all => "Unable to connect to Oracle"; -} - -$ea = ExecuteArray->new($dbh, 1); # set odbc_disable_array_operations +my $ea = ExecuteArray->new($dbh, 1); # set odbc_disable_array_operations $dbh = $ea->dbh; $ea->drop_table($dbh); ok($ea->create_table($dbh), "create test table") or exit 1; + $ea->simple($dbh, {array_context => 1, raise => 1}); $ea->simple($dbh, {array_context => 0, raise => 1}); $ea->error($dbh, {array_context => 1, raise => 1}); @@ -61,7 +45,21 @@ $ea->row_wise($dbh, {array_context => 1, raise => 1}); $ea->update($dbh, {array_context => 1, raise => 1}); -$ea->error($dbh, {array_context => 1, raise => 1, notuplestatus => 1}); -$ea->error($dbh, {array_context => 0, raise => 1, notuplestatus => 1}); -$ea->error($dbh, {array_context => 1, raise => 0, notuplestatus => 1}); -$ea->error($dbh, {array_context => 0, raise => 0, notuplestatus => 1}); +for my $raise ( 0..1 ) { + for my $context ( 0..1 ) { + $ea->error($dbh, { + array_context => $context, + raise => $raise, + notuplestatus => 1 + }); + } +} + +if ($dbh && $ea) { + $ea->drop_table($dbh); + $dbh->disconnect(); +} + +Test::NoWarnings::had_no_warnings() if $has_test_nowarnings; + +done_testing; From 180c8df257a88b35ba071e08ea18cf51fad67a24 Mon Sep 17 00:00:00 2001 From: yanick Date: Mon, 7 Jan 2013 18:11:29 +0000 Subject: [PATCH 389/637] done_testing() removed from END block (RT82506) ... as that was too little, too late. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15552 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 4 ++++ t/26exe_array.t | 50 ++++++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Changes b/Changes index f78ebe98..9c1c87c9 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,9 @@ Revision history for DBD::Oracle +{{$NEXT}} + - fix t/26exe_array.t in the case of no db connection (RT82506, + reported by Peter Rabbitson) + 1.54 2013-01-03 - promote 1.53_00 to official release diff --git a/t/26exe_array.t b/t/26exe_array.t index 1e865d3f..dce93725 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -13,43 +13,27 @@ use lib 't/lib', 't'; $| = 1; -my $has_test_nowarnings = 1; -eval "require Test::NoWarnings"; -$has_test_nowarnings = undef if $@; - -my ($dbh, $ea); +my $has_test_nowarnings = eval "require Test::NoWarnings; 1"; use DBI qw(:sql_types); use ExecuteArray; -END { - if ($dbh && $ea) { - $ea->drop_table($dbh); - $dbh->disconnect(); - } - Test::NoWarnings::had_no_warnings() - if ($has_test_nowarnings); - done_testing(); -} my $dsn = oracle_test_dsn(); my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; $ENV{NLS_NCHAR} = "US7ASCII"; $ENV{NLS_LANG} = "AMERICAN"; -eval { - $dbh = DBI->connect($dsn, $dbuser, '', {PrintError => 0}); -}; +my $dbh = eval { + DBI->connect($dsn, $dbuser, '', {PrintError => 0}) +} or plan skip_all => "Unable to connect to Oracle"; -if (!$dbh) { - plan skip_all => "Unable to connect to Oracle"; -} - -$ea = ExecuteArray->new($dbh, 1); # set odbc_disable_array_operations +my $ea = ExecuteArray->new($dbh, 1); # set odbc_disable_array_operations $dbh = $ea->dbh; $ea->drop_table($dbh); ok($ea->create_table($dbh), "create test table") or exit 1; + $ea->simple($dbh, {array_context => 1, raise => 1}); $ea->simple($dbh, {array_context => 0, raise => 1}); $ea->error($dbh, {array_context => 1, raise => 1}); @@ -61,7 +45,21 @@ $ea->row_wise($dbh, {array_context => 1, raise => 1}); $ea->update($dbh, {array_context => 1, raise => 1}); -$ea->error($dbh, {array_context => 1, raise => 1, notuplestatus => 1}); -$ea->error($dbh, {array_context => 0, raise => 1, notuplestatus => 1}); -$ea->error($dbh, {array_context => 1, raise => 0, notuplestatus => 1}); -$ea->error($dbh, {array_context => 0, raise => 0, notuplestatus => 1}); +for my $raise ( 0..1 ) { + for my $context ( 0..1 ) { + $ea->error($dbh, { + array_context => $context, + raise => $raise, + notuplestatus => 1 + }); + } +} + +if ($dbh && $ea) { + $ea->drop_table($dbh); + $dbh->disconnect(); +} + +Test::NoWarnings::had_no_warnings() if $has_test_nowarnings; + +done_testing; From 5fe58ba1a1bcc1bb9b6ae37a89b1c84e54a1d610 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 8 Jan 2013 12:46:04 -0500 Subject: [PATCH 390/637] prepare for release v1.56 --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index f094a401..6704798b 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.54 +version = 1.56 [Authority] authority=cpan:PYTHIAN From 2046fbbabac0c14684dbda6c6d8996585d6c3daf Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 8 Jan 2013 17:55:29 +0000 Subject: [PATCH 391/637] v1.56 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15553 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- META.json | 8 ++++---- META.yml | 8 ++++---- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 4 ++-- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 18 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Changes b/Changes index 9c1c87c9..cfd61a67 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.56 2013-01-08 - fix t/26exe_array.t in the case of no db connection (RT82506, reported by Peter Rabbitson) diff --git a/META.json b/META.json index 3fa9df24..8c2a2eb0 100644 --- a/META.json +++ b/META.json @@ -56,15 +56,15 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.54" + "version" : "1.56" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.54" + "version" : "1.56" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.54" + "version" : "1.56" } }, "release_status" : "stable", @@ -80,7 +80,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.54", + "version" : "1.56", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index ea6163e3..59dd13f8 100644 --- a/META.yml +++ b/META.yml @@ -29,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.54 + version: 1.56 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.54 + version: 1.56 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.54 + version: 1.56 requires: DBI: 0 DynaLoader: 0 @@ -47,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.54 +version: 1.56 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 91f9ddbb..66b14353 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.54 + version 1.56 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index 8c7e5eb1..567beec1 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.54 +version 1.56 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index b84b3c9e..13089f68 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.54'; + $DBD::Oracle::VERSION = '1.56'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1153,7 +1153,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.54 +version 1.56 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 7b5e68cc..57bcca0d 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.54'; + $DBD::Oracle::GetInfo::VERSION = '1.56'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.54 +version 1.56 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 9d5abae8..6aef8e28 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.54'; + $DBD::Oracle::Object::VERSION = '1.56'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -40,7 +40,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.54 +version 1.56 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 995f9250..88765401 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index ef7771b8..c69a0fd8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.54 +version 1.56 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index 8d8a44e6..2877c033 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.54 +version 1.56 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 7c5a516d..f5f1b1b1 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index a3c1a8dd..a4973574 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 04774e8b..91cc5b08 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index b1796150..df6ce782 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.54 +version 1.56 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index d98359c8..ebd93ec5 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.54 +version 1.56 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index 50a1d400..3c92262d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 8d92097a..34c1d0c4 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 DBD::Oracle and Windows 64bit From eec2d605d66d1a60301f61ce2fcf09e5730ba878 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 8 Jan 2013 17:55:29 +0000 Subject: [PATCH 392/637] v1.56 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15553 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- META.json | 8 ++++---- META.yml | 8 ++++---- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 4 ++-- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 18 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Changes b/Changes index 9c1c87c9..cfd61a67 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.56 2013-01-08 - fix t/26exe_array.t in the case of no db connection (RT82506, reported by Peter Rabbitson) diff --git a/META.json b/META.json index 3fa9df24..8c2a2eb0 100644 --- a/META.json +++ b/META.json @@ -56,15 +56,15 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.54" + "version" : "1.56" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.54" + "version" : "1.56" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.54" + "version" : "1.56" } }, "release_status" : "stable", @@ -80,7 +80,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.54", + "version" : "1.56", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index ea6163e3..59dd13f8 100644 --- a/META.yml +++ b/META.yml @@ -29,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.54 + version: 1.56 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.54 + version: 1.56 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.54 + version: 1.56 requires: DBI: 0 DynaLoader: 0 @@ -47,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.54 +version: 1.56 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 91f9ddbb..66b14353 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.54 + version 1.56 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index 8c7e5eb1..567beec1 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.54 +version 1.56 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index b84b3c9e..13089f68 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.54'; + $DBD::Oracle::VERSION = '1.56'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1153,7 +1153,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.54 +version 1.56 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 7b5e68cc..57bcca0d 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.54'; + $DBD::Oracle::GetInfo::VERSION = '1.56'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.54 +version 1.56 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 9d5abae8..6aef8e28 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.54'; + $DBD::Oracle::Object::VERSION = '1.56'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -40,7 +40,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.54 +version 1.56 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 995f9250..88765401 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index ef7771b8..c69a0fd8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.54 +version 1.56 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index 8d8a44e6..2877c033 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.54 +version 1.56 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 7c5a516d..f5f1b1b1 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index a3c1a8dd..a4973574 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 04774e8b..91cc5b08 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index b1796150..df6ce782 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.54 +version 1.56 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index d98359c8..ebd93ec5 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.54 +version 1.56 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index 50a1d400..3c92262d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 8d92097a..34c1d0c4 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.54 +version 1.56 =head1 DBD::Oracle and Windows 64bit From 7b32c35e626aa25ff773b061338822724b5483e5 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 17 Jan 2013 20:13:58 +0000 Subject: [PATCH 393/637] Fix RT46628 and 82663 - output cursors which are never opened cause errors added test case to 50cursor.t git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15557 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 21 +++++++- dbdimp.c | 123 +++++++++++++++++++++++++++++++--------------- lib/DBD/Oracle.pm | 20 ++++++-- ocitrace.h | 4 ++ t/50cursor.t | 31 +++++++++++- 5 files changed, 152 insertions(+), 47 deletions(-) diff --git a/Changes b/Changes index cfd61a67..1b4a7ea6 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,24 @@ Revision history for DBD::Oracle +NEXTVERSION + + [BUG FIXES] + + - fix RT46628 - bind_param_inout ORA_RSET causes MSWin32 access + violation and RT82663 - Errors if a returned SYS_REFCURSOR is not + opened (Martin J. Evans) + + If a procedure/function returns a SYS_REFCURSOR which was never opened + DBD::Oracle magics a DBI statement handle into existence and attempts + to describe it (which fails). This change examines a returned + SYS_REFCURSOR and if it it is initialised but not executed does not + create a DBI statement handle and returns undef instead. So now if you + have a procedure/function which returns a SYS_REFCURSOR and never open + it you'll get undef back instead of a useless statement handle. + Extended 50cursor.t test to check the above fix. + 1.56 2013-01-08 - - fix t/26exe_array.t in the case of no db connection (RT82506, + - fix t/26exe_array.t in the case of no db connection (RT82506, reported by Peter Rabbitson) 1.54 2013-01-03 @@ -10,7 +27,7 @@ Revision history for DBD::Oracle 1.53_00 2012-12-18 [BUG FIXES] - - Fix RT69350 - 31lob.t was using $lob after destroying its parent $sth + - Fix RT69350 - 31lob.t was using $lob after destroying its parent $sth (Rob Davies) - Fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) diff --git a/dbdimp.c b/dbdimp.c index 0376adc4..50da86ab 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -227,7 +227,7 @@ dbd_fbh_dump(imp_sth_t *imp_sth, imp_fbh_t *fbh, int i, int aidx) fbh->dbtype, fbh->ftype, (long)fbh->dbsize,(long)fbh->disize, fbh->prec, fbh->scale); if (fbh->fb_ary) { - PerlIO_printf(DBIc_LOGPIO(imp_sth), " out: ftype %d, bufl %d. indp %d, rlen %d, rcode %d\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), " out: ftype %d, bufl %d. indp %d, rlen %d, rcode %d\n", fbh->ftype, fbh->fb_ary->bufl, fbh->fb_ary->aindp[aidx], fbh->fb_ary->arlen[aidx], fbh->fb_ary->arcode[aidx]); } @@ -2665,11 +2665,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) { dTHX; - if (pre_exec) { /* pre-execute - allocate a statement handle */ - dSP; - D_imp_dbh_from_sth; - HV *init_attr = newHV(); - int count; + if (pre_exec) { /* pre-execute - throw away previous descriptor and rebind */ sword status; if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) @@ -2691,7 +2687,6 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &phs->desc_h, phs->desc_t, status); } - phs->progv = (char*)&phs->desc_h; phs->maxlen = 0; @@ -2701,6 +2696,11 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) phs->progv, 0, (ub2)phs->ftype, + /* I, MJE have no evidence that passing an indicator to this func + causes ORA-01001 (invalid cursor) errors. Also, without it + you cannot test the indicator to check we have a valid output + parameter. However, it would seem when you do specify an + indicator it always comes back as 0 so it is useless. */ NULL, /* using &phs->indp triggers ORA-01001 errors! */ NULL, 0, @@ -2714,6 +2714,51 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) return 0; } + /* + NOTE: The code used to magic a DBI stmt handle into existence + here before even knowing if the output parameter was going to + be a valid open cursor. The code to do this moved to post execute + below. See RT 82663 - Errors if a returned SYS_REFCURSOR is not opened + */ + } + else { /* post-execute - setup the statement handle */ + dTHR; + dSP; + D_imp_dbh_from_sth; + HV *init_attr = newHV(); + int count; + ub4 stmt_state = 99; + sword status; + SV * sth_csr; + + /* Before we go to the bother of attempting to allocate a new sth + for this cursor make sure the Oracle sth is executed i.e., + the returned cursor may never have been opened */ + OCIAttrGet_stmhp_stat2(imp_sth, (OCIStmt*)phs->desc_h, &stmt_state, 0, + OCI_ATTR_STMT_STATE, status); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIAttrGet OCI_ATTR_STMT_STATE"); + return 0; + } + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { + /* initialized=1, executed=2, end of fetch=3 */ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " returned cursor/statement state: %u, indicator=%d\n", + stmt_state, phs->indp2); + } + + /* We seem to get an indp of 0 even for a cursor which was never + opened and set to NULL. If this is the case we check the stmt state + and find the cursor is initialized but not executed - there is no + point in going any further if it is not executed - just return undef. + See RT 82663 */ + if (stmt_state == OCI_STMT_STATE_INITIALIZED) { + phs->sv = newSV(0); /* undef */ + return 1; + } + + /* Now we know we have an executed cursor create a new sth */ ENTER; SAVETMPS; PUSHMARK(SP); @@ -2738,11 +2783,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) " pp_exec_rset bind %s - allocated %s...\n", phs->name, neatsvpv(phs->sv, 0)); - } - else { /* post-execute - setup the statement handle */ - dTHR; - SV * sth_csr = phs->sv; - D_impdata(imp_sth_csr, imp_sth_t, sth_csr); + sth_csr = phs->sv; if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( @@ -2750,32 +2791,36 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) " bind %s - initialising new %s for cursor 0x%lx...\n", phs->name, neatsvpv(sth_csr,0), (unsigned long)phs->progv); - /* copy appropriate handles and atributes from parent statement */ - imp_sth_csr->envhp = imp_sth->envhp; - imp_sth_csr->errhp = imp_sth->errhp; - imp_sth_csr->srvhp = imp_sth->srvhp; - imp_sth_csr->svchp = imp_sth->svchp; - imp_sth_csr->auto_lob = imp_sth->auto_lob; - imp_sth_csr->pers_lob = imp_sth->pers_lob; - imp_sth_csr->clbk_lob = imp_sth->clbk_lob; - imp_sth_csr->piece_size = imp_sth->piece_size; - imp_sth_csr->piece_lob = imp_sth->piece_lob; - imp_sth_csr->is_child = 1; /*no prefetching on a cursor or sp*/ - - - /* assign statement handle from placeholder descriptor */ - imp_sth_csr->stmhp = (OCIStmt*)phs->desc_h; - phs->desc_h = NULL; /* tell phs that we own it now */ - - /* force stmt_type since OCIAttrGet(OCI_ATTR_STMT_TYPE) doesn't work! */ - imp_sth_csr->stmt_type = OCI_STMT_SELECT; - DBIc_IMPSET_on(imp_sth_csr); - - /* set ACTIVE so dbd_describe doesn't do explicit OCI describe */ - DBIc_ACTIVE_on(imp_sth_csr); - if (!dbd_describe(sth_csr, imp_sth_csr)) { - return 0; - } + { + D_impdata(imp_sth_csr, imp_sth_t, sth_csr); /* TO_DO */ + + /* copy appropriate handles and atributes from parent statement */ + imp_sth_csr->envhp = imp_sth->envhp; + imp_sth_csr->errhp = imp_sth->errhp; + imp_sth_csr->srvhp = imp_sth->srvhp; + imp_sth_csr->svchp = imp_sth->svchp; + imp_sth_csr->auto_lob = imp_sth->auto_lob; + imp_sth_csr->pers_lob = imp_sth->pers_lob; + imp_sth_csr->clbk_lob = imp_sth->clbk_lob; + imp_sth_csr->piece_size = imp_sth->piece_size; + imp_sth_csr->piece_lob = imp_sth->piece_lob; + imp_sth_csr->is_child = 1; /*no prefetching on a cursor or sp*/ + + + /* assign statement handle from placeholder descriptor */ + imp_sth_csr->stmhp = (OCIStmt*)phs->desc_h; + phs->desc_h = NULL; /* tell phs that we own it now */ + + /* force stmt_type since OCIAttrGet(OCI_ATTR_STMT_TYPE) doesn't work! */ + imp_sth_csr->stmt_type = OCI_STMT_SELECT; + DBIc_IMPSET_on(imp_sth_csr); + + /* set ACTIVE so dbd_describe doesn't do explicit OCI describe */ + DBIc_ACTIVE_on(imp_sth_csr); + if (!dbd_describe(sth_csr, imp_sth_csr)) { + return 0; + } + } } return 1; @@ -3477,7 +3522,7 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_st_execute(): Analyzing inout a parameter '%s" - "of type=%d name=%s'\n", + " of type=%d name=%s'\n", phs->name,phs->ftype,sql_typecode_name(phs->ftype)); } if( phs->ftype == ORA_VARCHAR2_TABLE ){ diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 13089f68..66aa2f75 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -4984,14 +4984,24 @@ closes a cursor: $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); $sth3->execute; -It is not normally necessary to close a cursor -explicitly in this way. Oracle will close the cursor automatically -at the first client-server interaction after the cursor statement handle is -destroyed. An explicit close may be desirable if the reference to -the cursor handle from the PL/SQL statement handle delays the destruction +It is not normally necessary to close a cursor explicitly in this +way. Oracle will close the cursor automatically at the first +client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to the +cursor handle from the PL/SQL statement handle delays the destruction of the cursor handle for too long. This reference remains until the PL/SQL handle is re-bound, re-executed or destroyed. +NOTE: From DBD::Oracle 1.57 functions or procedures returning +SYS_REFCURSORs which have not been opened (are still in the +initialised state) will return undef for the cursor statement handle +e.g., in the example above if the sp_ListEmp function simply returned l_cursor +instead of opening it. This means you can have a function/procedure +which can elect to open the cursor or not, Before this change if you called +a function/procedure which returned a SYS_REFCURSOR which was not opened +DBD::Oracle would error in the execute for a OCIAttrGet on the uninitialised +cursor. + See the C script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. diff --git a/ocitrace.h b/ocitrace.h index bebe4cb9..0f3c71bf 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -317,6 +317,10 @@ OCIAttrGet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, \ (void*)(p1), (l), (a), imp_sth->errhp, stat) +#define OCIAttrGet_stmhp_stat2(imp_sth, stmhp, p1, l, a, stat) \ + OCIAttrGet_log_stat(imp_sth, stmhp, OCI_HTYPE_STMT, \ + (void*)(p1), (l), (a), imp_sth->errhp, stat) + #define OCIAttrSet_log_stat(impxxh,th,ht,ah,s1,a,eh,stat) \ stat=OCIAttrSet(th,ht,ah,s1,a,eh); \ (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ diff --git a/t/50cursor.t b/t/50cursor.t index fa40a060..fcc870ad 100644 --- a/t/50cursor.t +++ b/t/50cursor.t @@ -37,7 +37,7 @@ if ($dbh) { $limit = 1; } $limit = 100 if $limit > 100; # lets not be greedy or upset DBA's - $tests = 2 + 10 * $limit; + $tests = 2 + 10 * $limit + 7; plan tests => $tests; @@ -83,6 +83,35 @@ foreach ( 1 .. @cursors ) { ok($close_cursor->execute, 'close cursor execute'); } +$dbh->{RaiseError} = 1; +eval { + $dbh->do(<<'EOT'); +create or replace procedure dbd_oracle_test(aref out sys_refcursor) as +begin + aref := NULL; +end; +EOT +}; + +my $ev = $@; +diag($ev) if $@; +SKIP: { + skip 'failed to create proc for test so skipping', 5 if $ev; + + local $dbh->{RaiseError} = 0; + + ok(my $sth1 = $dbh->prepare(q/begin dbd_oracle_test(?); end;/), + 'prepare exec of proc for null cursor'); + ok($sth1->bind_param_inout(1, \my $cursor, 100, {ora_type => ORA_RSET}), + 'binding cursor for null cursor'); + ok($sth1->execute, 'execute for null cursor'); + is($cursor, undef, 'undef returned for null cursor'); + ok($sth1->execute, 'execute 2 for null cursor'); + is($cursor, undef, 'undef 2 returned for null cursor'); + ok($dbh->do(q/drop procedure dbd_oracle_test/), + 'drop dbd_oracle_test proc'); +}; + $dbh->disconnect; exit 0; From 2b9dae001393ed4d7e9db853ad8283e5dd499cfc Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 17 Jan 2013 20:13:58 +0000 Subject: [PATCH 394/637] Fix RT46628 and 82663 - output cursors which are never opened cause errors added test case to 50cursor.t git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15557 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 21 +++++++- dbdimp.c | 123 +++++++++++++++++++++++++++++++--------------- lib/DBD/Oracle.pm | 20 ++++++-- ocitrace.h | 4 ++ t/50cursor.t | 31 +++++++++++- 5 files changed, 152 insertions(+), 47 deletions(-) diff --git a/Changes b/Changes index cfd61a67..1b4a7ea6 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,24 @@ Revision history for DBD::Oracle +NEXTVERSION + + [BUG FIXES] + + - fix RT46628 - bind_param_inout ORA_RSET causes MSWin32 access + violation and RT82663 - Errors if a returned SYS_REFCURSOR is not + opened (Martin J. Evans) + + If a procedure/function returns a SYS_REFCURSOR which was never opened + DBD::Oracle magics a DBI statement handle into existence and attempts + to describe it (which fails). This change examines a returned + SYS_REFCURSOR and if it it is initialised but not executed does not + create a DBI statement handle and returns undef instead. So now if you + have a procedure/function which returns a SYS_REFCURSOR and never open + it you'll get undef back instead of a useless statement handle. + Extended 50cursor.t test to check the above fix. + 1.56 2013-01-08 - - fix t/26exe_array.t in the case of no db connection (RT82506, + - fix t/26exe_array.t in the case of no db connection (RT82506, reported by Peter Rabbitson) 1.54 2013-01-03 @@ -10,7 +27,7 @@ Revision history for DBD::Oracle 1.53_00 2012-12-18 [BUG FIXES] - - Fix RT69350 - 31lob.t was using $lob after destroying its parent $sth + - Fix RT69350 - 31lob.t was using $lob after destroying its parent $sth (Rob Davies) - Fix memory leak in execute_array (John Scoles, Pierre-Alain Blanc) diff --git a/dbdimp.c b/dbdimp.c index 0376adc4..50da86ab 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -227,7 +227,7 @@ dbd_fbh_dump(imp_sth_t *imp_sth, imp_fbh_t *fbh, int i, int aidx) fbh->dbtype, fbh->ftype, (long)fbh->dbsize,(long)fbh->disize, fbh->prec, fbh->scale); if (fbh->fb_ary) { - PerlIO_printf(DBIc_LOGPIO(imp_sth), " out: ftype %d, bufl %d. indp %d, rlen %d, rcode %d\n", + PerlIO_printf(DBIc_LOGPIO(imp_sth), " out: ftype %d, bufl %d. indp %d, rlen %d, rcode %d\n", fbh->ftype, fbh->fb_ary->bufl, fbh->fb_ary->aindp[aidx], fbh->fb_ary->arlen[aidx], fbh->fb_ary->arcode[aidx]); } @@ -2665,11 +2665,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) { dTHX; - if (pre_exec) { /* pre-execute - allocate a statement handle */ - dSP; - D_imp_dbh_from_sth; - HV *init_attr = newHV(); - int count; + if (pre_exec) { /* pre-execute - throw away previous descriptor and rebind */ sword status; if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) @@ -2691,7 +2687,6 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &phs->desc_h, phs->desc_t, status); } - phs->progv = (char*)&phs->desc_h; phs->maxlen = 0; @@ -2701,6 +2696,11 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) phs->progv, 0, (ub2)phs->ftype, + /* I, MJE have no evidence that passing an indicator to this func + causes ORA-01001 (invalid cursor) errors. Also, without it + you cannot test the indicator to check we have a valid output + parameter. However, it would seem when you do specify an + indicator it always comes back as 0 so it is useless. */ NULL, /* using &phs->indp triggers ORA-01001 errors! */ NULL, 0, @@ -2714,6 +2714,51 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) return 0; } + /* + NOTE: The code used to magic a DBI stmt handle into existence + here before even knowing if the output parameter was going to + be a valid open cursor. The code to do this moved to post execute + below. See RT 82663 - Errors if a returned SYS_REFCURSOR is not opened + */ + } + else { /* post-execute - setup the statement handle */ + dTHR; + dSP; + D_imp_dbh_from_sth; + HV *init_attr = newHV(); + int count; + ub4 stmt_state = 99; + sword status; + SV * sth_csr; + + /* Before we go to the bother of attempting to allocate a new sth + for this cursor make sure the Oracle sth is executed i.e., + the returned cursor may never have been opened */ + OCIAttrGet_stmhp_stat2(imp_sth, (OCIStmt*)phs->desc_h, &stmt_state, 0, + OCI_ATTR_STMT_STATE, status); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIAttrGet OCI_ATTR_STMT_STATE"); + return 0; + } + if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) { + /* initialized=1, executed=2, end of fetch=3 */ + PerlIO_printf( + DBIc_LOGPIO(imp_sth), + " returned cursor/statement state: %u, indicator=%d\n", + stmt_state, phs->indp2); + } + + /* We seem to get an indp of 0 even for a cursor which was never + opened and set to NULL. If this is the case we check the stmt state + and find the cursor is initialized but not executed - there is no + point in going any further if it is not executed - just return undef. + See RT 82663 */ + if (stmt_state == OCI_STMT_STATE_INITIALIZED) { + phs->sv = newSV(0); /* undef */ + return 1; + } + + /* Now we know we have an executed cursor create a new sth */ ENTER; SAVETMPS; PUSHMARK(SP); @@ -2738,11 +2783,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) " pp_exec_rset bind %s - allocated %s...\n", phs->name, neatsvpv(phs->sv, 0)); - } - else { /* post-execute - setup the statement handle */ - dTHR; - SV * sth_csr = phs->sv; - D_impdata(imp_sth_csr, imp_sth_t, sth_csr); + sth_csr = phs->sv; if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( @@ -2750,32 +2791,36 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) " bind %s - initialising new %s for cursor 0x%lx...\n", phs->name, neatsvpv(sth_csr,0), (unsigned long)phs->progv); - /* copy appropriate handles and atributes from parent statement */ - imp_sth_csr->envhp = imp_sth->envhp; - imp_sth_csr->errhp = imp_sth->errhp; - imp_sth_csr->srvhp = imp_sth->srvhp; - imp_sth_csr->svchp = imp_sth->svchp; - imp_sth_csr->auto_lob = imp_sth->auto_lob; - imp_sth_csr->pers_lob = imp_sth->pers_lob; - imp_sth_csr->clbk_lob = imp_sth->clbk_lob; - imp_sth_csr->piece_size = imp_sth->piece_size; - imp_sth_csr->piece_lob = imp_sth->piece_lob; - imp_sth_csr->is_child = 1; /*no prefetching on a cursor or sp*/ - - - /* assign statement handle from placeholder descriptor */ - imp_sth_csr->stmhp = (OCIStmt*)phs->desc_h; - phs->desc_h = NULL; /* tell phs that we own it now */ - - /* force stmt_type since OCIAttrGet(OCI_ATTR_STMT_TYPE) doesn't work! */ - imp_sth_csr->stmt_type = OCI_STMT_SELECT; - DBIc_IMPSET_on(imp_sth_csr); - - /* set ACTIVE so dbd_describe doesn't do explicit OCI describe */ - DBIc_ACTIVE_on(imp_sth_csr); - if (!dbd_describe(sth_csr, imp_sth_csr)) { - return 0; - } + { + D_impdata(imp_sth_csr, imp_sth_t, sth_csr); /* TO_DO */ + + /* copy appropriate handles and atributes from parent statement */ + imp_sth_csr->envhp = imp_sth->envhp; + imp_sth_csr->errhp = imp_sth->errhp; + imp_sth_csr->srvhp = imp_sth->srvhp; + imp_sth_csr->svchp = imp_sth->svchp; + imp_sth_csr->auto_lob = imp_sth->auto_lob; + imp_sth_csr->pers_lob = imp_sth->pers_lob; + imp_sth_csr->clbk_lob = imp_sth->clbk_lob; + imp_sth_csr->piece_size = imp_sth->piece_size; + imp_sth_csr->piece_lob = imp_sth->piece_lob; + imp_sth_csr->is_child = 1; /*no prefetching on a cursor or sp*/ + + + /* assign statement handle from placeholder descriptor */ + imp_sth_csr->stmhp = (OCIStmt*)phs->desc_h; + phs->desc_h = NULL; /* tell phs that we own it now */ + + /* force stmt_type since OCIAttrGet(OCI_ATTR_STMT_TYPE) doesn't work! */ + imp_sth_csr->stmt_type = OCI_STMT_SELECT; + DBIc_IMPSET_on(imp_sth_csr); + + /* set ACTIVE so dbd_describe doesn't do explicit OCI describe */ + DBIc_ACTIVE_on(imp_sth_csr); + if (!dbd_describe(sth_csr, imp_sth_csr)) { + return 0; + } + } } return 1; @@ -3477,7 +3522,7 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- PerlIO_printf( DBIc_LOGPIO(imp_sth), "dbd_st_execute(): Analyzing inout a parameter '%s" - "of type=%d name=%s'\n", + " of type=%d name=%s'\n", phs->name,phs->ftype,sql_typecode_name(phs->ftype)); } if( phs->ftype == ORA_VARCHAR2_TABLE ){ diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 13089f68..66aa2f75 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -4984,14 +4984,24 @@ closes a cursor: $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); $sth3->execute; -It is not normally necessary to close a cursor -explicitly in this way. Oracle will close the cursor automatically -at the first client-server interaction after the cursor statement handle is -destroyed. An explicit close may be desirable if the reference to -the cursor handle from the PL/SQL statement handle delays the destruction +It is not normally necessary to close a cursor explicitly in this +way. Oracle will close the cursor automatically at the first +client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to the +cursor handle from the PL/SQL statement handle delays the destruction of the cursor handle for too long. This reference remains until the PL/SQL handle is re-bound, re-executed or destroyed. +NOTE: From DBD::Oracle 1.57 functions or procedures returning +SYS_REFCURSORs which have not been opened (are still in the +initialised state) will return undef for the cursor statement handle +e.g., in the example above if the sp_ListEmp function simply returned l_cursor +instead of opening it. This means you can have a function/procedure +which can elect to open the cursor or not, Before this change if you called +a function/procedure which returned a SYS_REFCURSOR which was not opened +DBD::Oracle would error in the execute for a OCIAttrGet on the uninitialised +cursor. + See the C script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. diff --git a/ocitrace.h b/ocitrace.h index bebe4cb9..0f3c71bf 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -317,6 +317,10 @@ OCIAttrGet_log_stat(imp_sth, imp_sth->stmhp, OCI_HTYPE_STMT, \ (void*)(p1), (l), (a), imp_sth->errhp, stat) +#define OCIAttrGet_stmhp_stat2(imp_sth, stmhp, p1, l, a, stat) \ + OCIAttrGet_log_stat(imp_sth, stmhp, OCI_HTYPE_STMT, \ + (void*)(p1), (l), (a), imp_sth->errhp, stat) + #define OCIAttrSet_log_stat(impxxh,th,ht,ah,s1,a,eh,stat) \ stat=OCIAttrSet(th,ht,ah,s1,a,eh); \ (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ diff --git a/t/50cursor.t b/t/50cursor.t index fa40a060..fcc870ad 100644 --- a/t/50cursor.t +++ b/t/50cursor.t @@ -37,7 +37,7 @@ if ($dbh) { $limit = 1; } $limit = 100 if $limit > 100; # lets not be greedy or upset DBA's - $tests = 2 + 10 * $limit; + $tests = 2 + 10 * $limit + 7; plan tests => $tests; @@ -83,6 +83,35 @@ foreach ( 1 .. @cursors ) { ok($close_cursor->execute, 'close cursor execute'); } +$dbh->{RaiseError} = 1; +eval { + $dbh->do(<<'EOT'); +create or replace procedure dbd_oracle_test(aref out sys_refcursor) as +begin + aref := NULL; +end; +EOT +}; + +my $ev = $@; +diag($ev) if $@; +SKIP: { + skip 'failed to create proc for test so skipping', 5 if $ev; + + local $dbh->{RaiseError} = 0; + + ok(my $sth1 = $dbh->prepare(q/begin dbd_oracle_test(?); end;/), + 'prepare exec of proc for null cursor'); + ok($sth1->bind_param_inout(1, \my $cursor, 100, {ora_type => ORA_RSET}), + 'binding cursor for null cursor'); + ok($sth1->execute, 'execute for null cursor'); + is($cursor, undef, 'undef returned for null cursor'); + ok($sth1->execute, 'execute 2 for null cursor'); + is($cursor, undef, 'undef 2 returned for null cursor'); + ok($dbh->do(q/drop procedure dbd_oracle_test/), + 'drop dbd_oracle_test proc'); +}; + $dbh->disconnect; exit 0; From 2fefdabb1030033cc950727d8ba121574d24094f Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 18 Jan 2013 09:23:17 +0000 Subject: [PATCH 395/637] Oops - in my rush to checkin last stuff in for John I left an undeclared var in a trace statement git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15558 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 50da86ab..2edb06be 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2744,8 +2744,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) /* initialized=1, executed=2, end of fetch=3 */ PerlIO_printf( DBIc_LOGPIO(imp_sth), - " returned cursor/statement state: %u, indicator=%d\n", - stmt_state, phs->indp2); + " returned cursor/statement state: %u\n", stmt_state); } /* We seem to get an indp of 0 even for a cursor which was never From 636ebf6688c9c66d4a9303fd7028db09476dc4ae Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 18 Jan 2013 09:23:17 +0000 Subject: [PATCH 396/637] Oops - in my rush to checkin last stuff in for John I left an undeclared var in a trace statement git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15558 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 50da86ab..2edb06be 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2744,8 +2744,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) /* initialized=1, executed=2, end of fetch=3 */ PerlIO_printf( DBIc_LOGPIO(imp_sth), - " returned cursor/statement state: %u, indicator=%d\n", - stmt_state, phs->indp2); + " returned cursor/statement state: %u\n", stmt_state); } /* We seem to get an indp of 0 even for a cursor which was never From 8566542b8ef8055a4be44bc804a7d94192c9b9c9 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 18 Jan 2013 11:46:44 +0000 Subject: [PATCH 397/637] Fix Oracle stmt handle leak introduced by last commit to sort NULL cursors out I think there is also a leak of a descriptor - fix to come git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15559 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dbdimp.c b/dbdimp.c index 2edb06be..e7d2c91c 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2753,6 +2753,12 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) point in going any further if it is not executed - just return undef. See RT 82663 */ if (stmt_state == OCI_STMT_STATE_INITIALIZED) { + OCIHandleFree_log_stat(imp_sth, (OCIStmt *)phs->desc_h, + OCI_HTYPE_STMT, status); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); + return 0; + } phs->sv = newSV(0); /* undef */ return 1; } From 5bf9bba146137c930790603171548bf05704867e Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 18 Jan 2013 11:46:44 +0000 Subject: [PATCH 398/637] Fix Oracle stmt handle leak introduced by last commit to sort NULL cursors out I think there is also a leak of a descriptor - fix to come git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15559 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dbdimp.c b/dbdimp.c index 2edb06be..e7d2c91c 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2753,6 +2753,12 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) point in going any further if it is not executed - just return undef. See RT 82663 */ if (stmt_state == OCI_STMT_STATE_INITIALIZED) { + OCIHandleFree_log_stat(imp_sth, (OCIStmt *)phs->desc_h, + OCI_HTYPE_STMT, status); + if (status != OCI_SUCCESS) { + oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); + return 0; + } phs->sv = newSV(0); /* undef */ return 1; } From e63638e6334ea67c5d4226b698de3c9252261383 Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 18 Jan 2013 14:00:39 +0000 Subject: [PATCH 399/637] Clear desc_h after freeing. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15560 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dbdimp.c b/dbdimp.c index e7d2c91c..63f0c450 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2759,6 +2759,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); return 0; } + phs->desc_h = NULL; phs->sv = newSV(0); /* undef */ return 1; } From dec7f445d1a5d6bb32ded96904270831efc0deaf Mon Sep 17 00:00:00 2001 From: mjevans Date: Fri, 18 Jan 2013 14:00:39 +0000 Subject: [PATCH 400/637] Clear desc_h after freeing. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15560 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dbdimp.c b/dbdimp.c index e7d2c91c..63f0c450 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2759,6 +2759,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) oci_error(sth, imp_sth->errhp, status, "OCIHandleFree"); return 0; } + phs->desc_h = NULL; phs->sv = newSV(0); /* undef */ return 1; } From 740d9209fab868af4421445e10c2058702ea8aeb Mon Sep 17 00:00:00 2001 From: "David E. Wheeler" Date: Tue, 5 Feb 2013 11:34:31 -0800 Subject: [PATCH 401/637] Update Lion instructions for 64-bit Instant Client. It came out last week. About time! --- lib/DBD/Oracle/Troubleshooting/Macos.pod | 50 ++++++++++++++---------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 36b78b60..8011f3d0 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -54,37 +54,47 @@ database server on your MacOSX box. See below (Instructions for =head1 Instructions for 10.7.x (Lion) -Because the 64 bit instantclient (version 10gr2)is currently -[incompatible with Lion][], DBD::Oracle can only be compiled with the -32-bit instantclient libraries, and therefore requires 32-bit Perl. If -your Perl is 64-bit (which, by default, it is on Mac OS X), you will -not be able to build DBD::Oracle until an updated 64-bit instantclient -is released. +Perl on Lion and later is built with 64-bit support, and therefore requiers +the 64-bit Instant Client. As of this writing, only Instant Client 11.2 +(64-bit) actually works. The 64-bit Instant Client 10.2 is L. +We therefore recommend the 11.2 client. If you must Instant Client 10.2, you +may need to recompile Perl with 32-bit support. -[incompatible with Lion]: http://only4left.jpiwowar.com/2011/08/instant-client-osx-lion-32-bit-only/ +Either way, setup and configuration is the same: -If you have a 32-bit Perl, however, then the following steps should work: +=over -* Download and install the 32-bit basic, sqlplus, and sdk instantclient -libraries and install them in a central location, such as -`/usr/oracle_instantclient`. [Downloads here][]. - - [Downloads here]: http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html +=item * -* Create a symlink from `libclntsh.dylib.10.1` to `libclntsh.dylib`: +Download and install the basic, sqlplus, and sdk instantclient libraries and +install them in a central location, such as F. +L - cd /usr/oracle_instantclient/ - link -s libclntsh.dylib.10.1 libclntsh.dylib +=item * -* Update your environment to point to the libraries: +Create a symlink from F to F: - export ORACLE_HOME=/usr/oracle_instantclient - export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/usr/oracle_instantclient + cd /usr/oracle_instantclient/ + ln -s libclntsh.dylib.* libclntsh.dylib + ln -s libocci.dylib.* libocci.dylib -* You should now be able to install DBD::Oracle from CPAN: +=item * + +Update your environment to point to the libraries: + + export ORACLE_HOME=/usr/oracle_instantclient + export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/usr/oracle_instantclient + +=item * + +You should now be able to install DBD::Oracle from CPAN: cpan DBD::Oracle +=back + =head1 Instructions for 10.6.x (Snow Leopard) These are taken from a stackoverflow answer by "nickisfat" who gave From 131c7c606b89ca2db2e63fa5a6966e1f56619074 Mon Sep 17 00:00:00 2001 From: "David E. Wheeler" Date: Tue, 5 Feb 2013 13:10:32 -0800 Subject: [PATCH 402/637] Might need to add symlinks. --- lib/DBD/Oracle/Troubleshooting/Macos.pod | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 8011f3d0..5f53605b 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -82,6 +82,15 @@ Create a symlink from F to F: =item * +The following directory is hardcoded into the Oracle Instant Client - god +knows why - so we need to create and symlink it: + + sudo mkdir -p /b/227/rdbms/ + sudo cd /b/227/rdbms/ + sudo ln -s /usr/oracle_instantclient/ lib + +=item * + Update your environment to point to the libraries: export ORACLE_HOME=/usr/oracle_instantclient From d410a15d130a7b68094138e38bc4005e5cc041ae Mon Sep 17 00:00:00 2001 From: yanick Date: Wed, 6 Feb 2013 21:10:49 +0000 Subject: [PATCH 403/637] Update Lion instructions for 64-bit Instant Client. git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15569 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 7 ++- META.json | 2 +- META.yml | 2 +- README | 10 +++++ README.mkdn | 20 ++++++--- lib/DBD/Oracle/Troubleshooting/Macos.pod | 57 ++++++++++++++++-------- 6 files changed, 70 insertions(+), 28 deletions(-) diff --git a/Changes b/Changes index 1b4a7ea6..45d5c48d 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,6 @@ Revision history for DBD::Oracle -NEXTVERSION - +{{$NEXT}} [BUG FIXES] - fix RT46628 - bind_param_inout ORA_RSET causes MSWin32 access @@ -17,6 +16,10 @@ NEXTVERSION it you'll get undef back instead of a useless statement handle. Extended 50cursor.t test to check the above fix. + [DOCUMENTATION] + - Update Lion instructions for 64-bit Instant Client. (GH#37, patch by + theory) + 1.56 2013-01-08 - fix t/26exe_array.t in the case of no db connection (RT82506, reported by Peter Rabbitson) diff --git a/META.json b/META.json index 8c2a2eb0..0deab065 100644 --- a/META.json +++ b/META.json @@ -7,7 +7,7 @@ "Martin J. Evans " ], "dynamic_config" : 0, - "generated_by" : "Dist::Zilla version 4.300027, CPAN::Meta::Converter version 2.120921", + "generated_by" : "Dist::Zilla version 4.300028, CPAN::Meta::Converter version 2.120921", "license" : [ "perl_5" ], diff --git a/META.yml b/META.yml index 59dd13f8..6f65d163 100644 --- a/META.yml +++ b/META.yml @@ -20,7 +20,7 @@ configure_requires: DBI: 1.51 ExtUtils::MakeMaker: 6.30 dynamic_config: 0 -generated_by: 'Dist::Zilla version 4.300027, CPAN::Meta::Converter version 2.120921' +generated_by: 'Dist::Zilla version 4.300028, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html diff --git a/README b/README index 66b14353..03a2f9f4 100644 --- a/README +++ b/README @@ -3770,6 +3770,16 @@ OTHER DATA TYPES too long. This reference remains until the PL/SQL handle is re-bound, re-executed or destroyed. + NOTE: From DBD::Oracle 1.57 functions or procedures returning + SYS_REFCURSORs which have not been opened (are still in the initialised + state) will return undef for the cursor statement handle e.g., in the + example above if the sp_ListEmp function simply returned l_cursor + instead of opening it. This means you can have a function/procedure + which can elect to open the cursor or not, Before this change if you + called a function/procedure which returned a SYS_REFCURSOR which was not + opened DBD::Oracle would error in the execute for a OCIAttrGet on the + uninitialised cursor. + See the "curref.pl" script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. diff --git a/README.mkdn b/README.mkdn index 567beec1..b50d03d2 100644 --- a/README.mkdn +++ b/README.mkdn @@ -3769,14 +3769,24 @@ closes a cursor: $sth3->bind_param(":cursor", $sth2, { ora_type => ORA_RSET } ); $sth3->execute; -It is not normally necessary to close a cursor -explicitly in this way. Oracle will close the cursor automatically -at the first client-server interaction after the cursor statement handle is -destroyed. An explicit close may be desirable if the reference to -the cursor handle from the PL/SQL statement handle delays the destruction +It is not normally necessary to close a cursor explicitly in this +way. Oracle will close the cursor automatically at the first +client-server interaction after the cursor statement handle is +destroyed. An explicit close may be desirable if the reference to the +cursor handle from the PL/SQL statement handle delays the destruction of the cursor handle for too long. This reference remains until the PL/SQL handle is re-bound, re-executed or destroyed. +NOTE: From DBD::Oracle 1.57 functions or procedures returning +SYS\_REFCURSORs which have not been opened (are still in the +initialised state) will return undef for the cursor statement handle +e.g., in the example above if the sp\_ListEmp function simply returned l\_cursor +instead of opening it. This means you can have a function/procedure +which can elect to open the cursor or not, Before this change if you called +a function/procedure which returned a SYS\_REFCURSOR which was not opened +DBD::Oracle would error in the execute for a OCIAttrGet on the uninitialised +cursor. + See the `curref.pl` script in the Oracle.ex directory in the DBD::Oracle source distribution for a complete working example. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 91cc5b08..231e2651 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -66,37 +66,56 @@ database server on your MacOSX box. See below (Instructions for =head1 Instructions for 10.7.x (Lion) -Because the 64 bit instantclient (version 10gr2)is currently -[incompatible with Lion][], DBD::Oracle can only be compiled with the -32-bit instantclient libraries, and therefore requires 32-bit Perl. If -your Perl is 64-bit (which, by default, it is on Mac OS X), you will -not be able to build DBD::Oracle until an updated 64-bit instantclient -is released. +Perl on Lion and later is built with 64-bit support, and therefore requires +the 64-bit Instant Client. As of this writing, only Instant Client 11.2 +(64-bit) actually works. The 64-bit Instant Client 10.2 is L. +We therefore recommend the 11.2 client. If you must Instant Client 10.2, you +may need to recompile Perl with 32-bit support. -[incompatible with Lion]: http://only4left.jpiwowar.com/2011/08/instant-client-osx-lion-32-bit-only/ +Either way, setup and configuration is the same: -If you have a 32-bit Perl, however, then the following steps should work: +=over -* Download and install the 32-bit basic, sqlplus, and sdk instantclient -libraries and install them in a central location, such as -`/usr/oracle_instantclient`. [Downloads here][]. +=item * + +Download and install the basic, sqlplus, and sdk instantclient libraries and +install them in a central location, such as F. +L - [Downloads here]: http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html +=item * -* Create a symlink from `libclntsh.dylib.10.1` to `libclntsh.dylib`: +Create a symlink from F to F: - cd /usr/oracle_instantclient/ - link -s libclntsh.dylib.10.1 libclntsh.dylib + cd /usr/oracle_instantclient/ + ln -s libclntsh.dylib.* libclntsh.dylib + ln -s libocci.dylib.* libocci.dylib -* Update your environment to point to the libraries: +=item * - export ORACLE_HOME=/usr/oracle_instantclient - export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/usr/oracle_instantclient +The following directory is hardcoded into the Oracle Instant Client - god +knows why - so we need to create and symlink it: + + sudo mkdir -p /b/227/rdbms/ + sudo cd /b/227/rdbms/ + sudo ln -s /usr/oracle_instantclient/ lib + +=item * -* You should now be able to install DBD::Oracle from CPAN: +Update your environment to point to the libraries: + + export ORACLE_HOME=/usr/oracle_instantclient + export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/usr/oracle_instantclient + +=item * + +You should now be able to install DBD::Oracle from CPAN: cpan DBD::Oracle +=back + =head1 Instructions for 10.6.x (Snow Leopard) These are taken from a stackoverflow answer by "nickisfat" who gave From bfb64a08fb3a55868985d528c1a561fdfb99c00d Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 6 Feb 2013 16:12:29 -0500 Subject: [PATCH 404/637] bump version to 1.57_00 --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 6704798b..7a7d4c95 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.56 +version = 1.57_00 [Authority] authority=cpan:PYTHIAN From 0dbbeaedd26d391b7fb6dc03378864e320141cfd Mon Sep 17 00:00:00 2001 From: yanick Date: Thu, 7 Feb 2013 22:11:28 +0000 Subject: [PATCH 405/637] version bump to v1.57_00 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15570 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 2 +- META.json | 10 +++++----- META.yml | 8 ++++---- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 4 ++-- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 18 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Changes b/Changes index 45d5c48d..a200c868 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.57_00 2013-02-07 [BUG FIXES] - fix RT46628 - bind_param_inout ORA_RSET causes MSWin32 access diff --git a/META.json b/META.json index 0deab065..65482bd8 100644 --- a/META.json +++ b/META.json @@ -56,18 +56,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.56" + "version" : "1.57_00" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.56" + "version" : "1.57_00" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.56" + "version" : "1.57_00" } }, - "release_status" : "stable", + "release_status" : "testing", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -80,7 +80,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.56", + "version" : "1.57_00", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index 6f65d163..fdc267ba 100644 --- a/META.yml +++ b/META.yml @@ -29,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.56 + version: 1.57_00 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.56 + version: 1.57_00 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.56 + version: 1.57_00 requires: DBI: 0 DynaLoader: 0 @@ -47,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.56 +version: 1.57_00 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 03a2f9f4..05bb3493 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.56 + version 1.57_00 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index b50d03d2..c153db55 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.56 +version 1.57\_00 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 66aa2f75..a3f5568f 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.56'; + $DBD::Oracle::VERSION = '1.57_00'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1153,7 +1153,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.56 +version 1.57_00 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index 57bcca0d..cc8fb892 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.56'; + $DBD::Oracle::GetInfo::VERSION = '1.57_00'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.56 +version 1.57_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 6aef8e28..50321334 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.56'; + $DBD::Oracle::Object::VERSION = '1.57_00'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -40,7 +40,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.56 +version 1.57_00 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 88765401..220caac7 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.56 +version 1.57_00 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index c69a0fd8..6c0d7a48 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.56 +version 1.57_00 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index 2877c033..6f5b9c87 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.56 +version 1.57_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index f5f1b1b1..161e7268 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.56 +version 1.57_00 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index a4973574..5ef4cab8 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.56 +version 1.57_00 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 231e2651..7570b207 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.56 +version 1.57_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index df6ce782..4b79ec55 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.56 +version 1.57_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index ebd93ec5..335a65fc 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.56 +version 1.57_00 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index 3c92262d..89f96d67 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.56 +version 1.57_00 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 34c1d0c4..02388994 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.56 +version 1.57_00 =head1 DBD::Oracle and Windows 64bit From 4c7bc57cea8c25f6a8b4e4fbb67cfc1890d145cc Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 5 Mar 2013 10:52:05 +0000 Subject: [PATCH 406/637] Missing rt number in Changes file git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15577 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes b/Changes index a200c868..90baf495 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,7 @@ Revision history for DBD::Oracle violation and RT82663 - Errors if a returned SYS_REFCURSOR is not opened (Martin J. Evans) + Fix RT82663. If a procedure/function returns a SYS_REFCURSOR which was never opened DBD::Oracle magics a DBI statement handle into existence and attempts to describe it (which fails). This change examines a returned From 5a75d016470df8aa2314bffd618ee42fc3f10ae7 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 5 Mar 2013 10:52:58 +0000 Subject: [PATCH 407/637] comment only change git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15578 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbdimp.h b/dbdimp.h index ab893a42..b7eb3705 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -198,7 +198,7 @@ struct imp_fbh_st { /* field buffer EXPERIMENTAL */ /* Oracle's description of the field */ OCIParam *parmdp; OCIDefine *defnp; - void *desc_h; /* descriptor if needed (LOBs etc) */ + void *desc_h; /* descriptor if needed (LOBs, cursors etc) */ ub4 desc_t; /* OCI type of descriptor */ ub4 define_mode; /*the normal case for a define*/ int (*fetch_func) _((SV *sth, imp_fbh_t *fbh, SV *dest_sv)); From 88515d753f3aefd3cae902c1365e45717bc1ddb8 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 5 Mar 2013 10:52:05 +0000 Subject: [PATCH 408/637] Missing rt number in Changes file git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15577 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes b/Changes index 45d5c48d..64282e78 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,7 @@ Revision history for DBD::Oracle violation and RT82663 - Errors if a returned SYS_REFCURSOR is not opened (Martin J. Evans) + Fix RT82663. If a procedure/function returns a SYS_REFCURSOR which was never opened DBD::Oracle magics a DBI statement handle into existence and attempts to describe it (which fails). This change examines a returned From 7e6038ec849243f43233ecdab1365a5bfdcb0318 Mon Sep 17 00:00:00 2001 From: mjevans Date: Tue, 5 Mar 2013 10:52:58 +0000 Subject: [PATCH 409/637] comment only change git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15578 50811bd7-b8ce-0310-adc1-d9db26280581 --- dbdimp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbdimp.h b/dbdimp.h index ab893a42..b7eb3705 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -198,7 +198,7 @@ struct imp_fbh_st { /* field buffer EXPERIMENTAL */ /* Oracle's description of the field */ OCIParam *parmdp; OCIDefine *defnp; - void *desc_h; /* descriptor if needed (LOBs etc) */ + void *desc_h; /* descriptor if needed (LOBs, cursors etc) */ ub4 desc_t; /* OCI type of descriptor */ ub4 define_mode; /*the normal case for a define*/ int (*fetch_func) _((SV *sth, imp_fbh_t *fbh, SV *dest_sv)); From f6049a442f71e74148c871bc6f1701d48bca9959 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 5 Mar 2013 10:25:42 -0500 Subject: [PATCH 410/637] version bump --- Changes | 12 +++++++----- dist.ini | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 64282e78..aac02869 100644 --- a/Changes +++ b/Changes @@ -1,17 +1,19 @@ Revision history for DBD::Oracle {{$NEXT}} + - promote 1.57_00 to official release + +1.57_00 2013-02-07 [BUG FIXES] - fix RT46628 - bind_param_inout ORA_RSET causes MSWin32 access violation and RT82663 - Errors if a returned SYS_REFCURSOR is not opened (Martin J. Evans) - Fix RT82663. - If a procedure/function returns a SYS_REFCURSOR which was never opened - DBD::Oracle magics a DBI statement handle into existence and attempts - to describe it (which fails). This change examines a returned - SYS_REFCURSOR and if it it is initialised but not executed does not + -Fix RT82663. If a procedure/function returns a SYS_REFCURSOR which + was never opened DBD::Oracle magics a DBI statement handle into + existence and attempts to describe it (which fails). This change examines + a returned SYS_REFCURSOR and if it it is initialised but not executed does not create a DBI statement handle and returns undef instead. So now if you have a procedure/function which returns a SYS_REFCURSOR and never open it you'll get undef back instead of a useless statement handle. diff --git a/dist.ini b/dist.ini index 7a7d4c95..c80b28e4 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.57_00 +version = 1.58 [Authority] authority=cpan:PYTHIAN From 71c9168ada0655775bea85c45195518230ddb6a1 Mon Sep 17 00:00:00 2001 From: yanick Date: Tue, 5 Mar 2013 15:35:32 +0000 Subject: [PATCH 411/637] version bump to 1.58 git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15579 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 12 +++++++----- META.json | 10 +++++----- META.yml | 8 ++++---- README | 2 +- README.mkdn | 2 +- lib/DBD/Oracle.pm | 4 ++-- lib/DBD/Oracle/GetInfo.pm | 4 ++-- lib/DBD/Oracle/Object.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Vms.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 18 files changed, 34 insertions(+), 32 deletions(-) diff --git a/Changes b/Changes index 90baf495..20bc28ac 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,8 @@ Revision history for DBD::Oracle +1.58 2013-03-05 + - promote 1.57_00 to official release + 1.57_00 2013-02-07 [BUG FIXES] @@ -7,11 +10,10 @@ Revision history for DBD::Oracle violation and RT82663 - Errors if a returned SYS_REFCURSOR is not opened (Martin J. Evans) - Fix RT82663. - If a procedure/function returns a SYS_REFCURSOR which was never opened - DBD::Oracle magics a DBI statement handle into existence and attempts - to describe it (which fails). This change examines a returned - SYS_REFCURSOR and if it it is initialised but not executed does not + -Fix RT82663. If a procedure/function returns a SYS_REFCURSOR which + was never opened DBD::Oracle magics a DBI statement handle into + existence and attempts to describe it (which fails). This change examines + a returned SYS_REFCURSOR and if it it is initialised but not executed does not create a DBI statement handle and returns undef instead. So now if you have a procedure/function which returns a SYS_REFCURSOR and never open it you'll get undef back instead of a useless statement handle. diff --git a/META.json b/META.json index 65482bd8..6ce2a081 100644 --- a/META.json +++ b/META.json @@ -56,18 +56,18 @@ "provides" : { "DBD::Oracle" : { "file" : "lib/DBD/Oracle.pm", - "version" : "1.57_00" + "version" : "1.58" }, "DBD::Oracle::GetInfo" : { "file" : "lib/DBD/Oracle/GetInfo.pm", - "version" : "1.57_00" + "version" : "1.58" }, "DBD::Oracle::Object" : { "file" : "lib/DBD/Oracle/Object.pm", - "version" : "1.57_00" + "version" : "1.58" } }, - "release_status" : "testing", + "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-dbd-oracle at rt.cpan.org", @@ -80,7 +80,7 @@ "web" : "https://github.com/yanick/DBD-Oracle" } }, - "version" : "1.57_00", + "version" : "1.58", "x_authority" : "cpan:PYTHIAN", "x_help_wanted" : [ "coder", diff --git a/META.yml b/META.yml index fdc267ba..737a2d92 100644 --- a/META.yml +++ b/META.yml @@ -29,13 +29,13 @@ name: DBD-Oracle provides: DBD::Oracle: file: lib/DBD/Oracle.pm - version: 1.57_00 + version: 1.58 DBD::Oracle::GetInfo: file: lib/DBD/Oracle/GetInfo.pm - version: 1.57_00 + version: 1.58 DBD::Oracle::Object: file: lib/DBD/Oracle/Object.pm - version: 1.57_00 + version: 1.58 requires: DBI: 0 DynaLoader: 0 @@ -47,7 +47,7 @@ resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle homepage: http://search.cpan.org/dist/DBD-Oracle/ repository: https://github.com/yanick/DBD-Oracle.git -version: 1.57_00 +version: 1.58 x_authority: cpan:PYTHIAN x_help_wanted: - coder diff --git a/README b/README index 05bb3493..39f6fdf6 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME DBD::Oracle - Oracle database driver for the DBI module VERSION - version 1.57_00 + version 1.58 SYNOPSIS use DBI; diff --git a/README.mkdn b/README.mkdn index c153db55..87fa6367 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ DBD::Oracle - Oracle database driver for the DBI module # VERSION -version 1.57\_00 +version 1.58 # SYNOPSIS diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index a3f5568f..ffe574a3 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -12,7 +12,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; { - $DBD::Oracle::VERSION = '1.57_00'; + $DBD::Oracle::VERSION = '1.58'; } BEGIN { $DBD::Oracle::AUTHORITY = 'cpan:PYTHIAN'; @@ -1153,7 +1153,7 @@ DBD::Oracle - Oracle database driver for the DBI module =head1 VERSION -version 1.57_00 +version 1.58 =head1 SYNOPSIS diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index cc8fb892..bc8e81c2 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,6 +1,6 @@ package DBD::Oracle::GetInfo; { - $DBD::Oracle::GetInfo::VERSION = '1.57_00'; + $DBD::Oracle::GetInfo::VERSION = '1.58'; } BEGIN { $DBD::Oracle::GetInfo::AUTHORITY = 'cpan:PYTHIAN'; @@ -295,7 +295,7 @@ DBD::Oracle::GetInfo - Wrapper to get Oracle information =head1 VERSION -version 1.57_00 +version 1.58 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 50321334..f988560d 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,6 +1,6 @@ package DBD::Oracle::Object; { - $DBD::Oracle::Object::VERSION = '1.57_00'; + $DBD::Oracle::Object::VERSION = '1.58'; } BEGIN { $DBD::Oracle::Object::AUTHORITY = 'cpan:PYTHIAN'; @@ -40,7 +40,7 @@ DBD::Oracle::Object - Wrapper for Oracle objects =head1 VERSION -version 1.57_00 +version 1.58 =head1 AUTHORS diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 220caac7..569f155a 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.57_00 +version 1.58 =head1 CONNECTING TO ORACLE diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index 6c0d7a48..e7ebce34 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Aix - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.57_00 +version 1.58 =head1 Using Visual Age 7 C Compiler diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index 6f5b9c87..50153e4b 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Cygwin - Tips and Hints to Troubleshoot DBD::Oracl =head1 VERSION -version 1.57_00 +version 1.58 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 161e7268..4e5540c9 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Hpux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.57_00 +version 1.58 =head1 INTRODUCTION diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 5ef4cab8..f9ac409d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Linux - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.57_00 +version 1.58 =head1 Installing with Instantclient .rpm files. diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 7570b207..99a13fac 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Macos - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.57_00 +version 1.58 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index 4b79ec55..d4ad4bd1 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Sun - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.57_00 +version 1.58 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 335a65fc..8f608965 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Vms - Tips and Hints to Troubleshoot DBD::Oracle o =head1 VERSION -version 1.57_00 +version 1.58 =head1 General Info diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index 89f96d67..9da8f489 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win32 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.57_00 +version 1.58 =head1 GENERAL INFO diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 02388994..1d4a95b3 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -11,7 +11,7 @@ DBD::Oracle::Troubleshooting::Win64 - Tips and Hints to Troubleshoot DBD::Oracle =head1 VERSION -version 1.57_00 +version 1.58 =head1 DBD::Oracle and Windows 64bit From e2c456f24500440deb7920ed69b4d65758165e75 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 25 Mar 2013 20:08:13 +0000 Subject: [PATCH 412/637] Add test for rt 84170 - fethc off the end of the result-set NOTE: will fail until the patch in rt 84170 is applied simplifiy a few for loops git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15589 50811bd7-b8ce-0310-adc1-d9db26280581 --- t/51scroll.t | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/t/51scroll.t b/t/51scroll.t index 16b5676d..a4900baf 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -26,7 +26,7 @@ eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, if ($dbh) { plan skip_all => "Scrollable cursors new in Oracle 9" if $dbh->func('ora_server_version')->[0] < 9; - plan tests => 36; + plan tests => 37; } else { plan skip_all => "Unable to connect to Oracle"; } @@ -50,25 +50,26 @@ $sql = "INSERT INTO ".$table." VALUES (?)"; $sth =$dbh-> prepare($sql); -for ($i=1;$i<=10;$i++){ - $sth-> bind_param(1, $i); - $sth->execute(); -} +$sth->execute($_) foreach (1..10); $sql="select * from ".$table; -ok($sth=$dbh->prepare($sql,{ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY,ora_prefetch_memory=>200})); +ok($sth=$dbh->prepare($sql, + {ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY, + ora_prefetch_memory=>200})); ok ($sth->execute()); #first loop all the way forward with OCI_FETCH_NEXT -for($i=1;$i<=10;$i++){ +foreach (1..10) { $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); - cmp_ok($value->[0], '==', $i, '... we should get the next record'); + is($value->[0], $_, '... we should get the next record'); } - - $value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); cmp_ok($value->[0], '==', 10, '... we should get the 10th record'); +# fetch off the end of the result-set +$value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT, 0); +is($value, undef, "end of result-set"); + #now loop all the way back for($i=1;$i<=9;$i++){ $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); From 8a44ca923e2bc3be2c2e1049cbac8f9e2b571f73 Mon Sep 17 00:00:00 2001 From: mjevans Date: Mon, 25 Mar 2013 20:16:01 +0000 Subject: [PATCH 413/637] Changes to tests for rt 64170 - note my editor removes trailing blank space git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15590 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index 20bc28ac..7b86e8f6 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,15 @@ Revision history for DBD::Oracle +NEXT_RELEASE + + [BUG FIXES] + + - Changed 51scroll.t to test you cannot fetch off the end of the + result-set with a scrollable cursor - will fail until patch from + RT 84170 committed (REMOVE WHEN RELEASED) + 1.58 2013-03-05 - - promote 1.57_00 to official release + - promote 1.57_00 to official release 1.57_00 2013-02-07 [BUG FIXES] @@ -10,9 +18,9 @@ Revision history for DBD::Oracle violation and RT82663 - Errors if a returned SYS_REFCURSOR is not opened (Martin J. Evans) - -Fix RT82663. If a procedure/function returns a SYS_REFCURSOR which - was never opened DBD::Oracle magics a DBI statement handle into - existence and attempts to describe it (which fails). This change examines + -Fix RT82663. If a procedure/function returns a SYS_REFCURSOR which + was never opened DBD::Oracle magics a DBI statement handle into + existence and attempts to describe it (which fails). This change examines a returned SYS_REFCURSOR and if it it is initialised but not executed does not create a DBI statement handle and returns undef instead. So now if you have a procedure/function which returns a SYS_REFCURSOR and never open From 4ad738e3ce25d7d3493189b1f4dd72ed239e70a8 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 28 Mar 2013 20:21:53 +0000 Subject: [PATCH 414/637] Fix rt84170 - scrollable cursors fail to return undef on last fetch git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15596 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 8 +++++--- oci8.c | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 7b86e8f6..f949f570 100644 --- a/Changes +++ b/Changes @@ -4,9 +4,11 @@ NEXT_RELEASE [BUG FIXES] - - Changed 51scroll.t to test you cannot fetch off the end of the - result-set with a scrollable cursor - will fail until patch from - RT 84170 committed (REMOVE WHEN RELEASED) + - Fixed RT84170 - when using scrollable cursors and you've done a + positioned fetch and then keep fetching until the end of the + result-set calls to fetch never return undef and you keep getting + the last row forever. Also added test case to the 51scroll.t test + (Martin J. Evans). 1.58 2013-03-05 - promote 1.57_00 to official release diff --git a/oci8.c b/oci8.c index 14d4485a..6a3208bb 100644 --- a/oci8.c +++ b/oci8.c @@ -4002,6 +4002,10 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp,1, imp_sth->fetch_orient,imp_sth->fetch_offset, status); /*this will work without a round trip so might as well open it up for all statments handles*/ /* default and OCI_FETCH_NEXT are the same so this avoids miscaluation on the next value*/ + if (status==OCI_NO_DATA){ + return Nullav; + } + OCIAttrGet_stmhp_stat(imp_sth, &imp_sth->fetch_position, 0, OCI_ATTR_CURRENT_POSITION, status); if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) From 9ae2a8d2a6264d1bcde02ac1d71febad15685d44 Mon Sep 17 00:00:00 2001 From: mjevans Date: Thu, 28 Mar 2013 20:31:17 +0000 Subject: [PATCH 415/637] fixed formatting and attribution git-svn-id: http://svn.perl.org/modules/dbd-oracle/trunk@15597 50811bd7-b8ce-0310-adc1-d9db26280581 --- Changes | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index f949f570..1b7bcde5 100644 --- a/Changes +++ b/Changes @@ -20,14 +20,15 @@ NEXT_RELEASE violation and RT82663 - Errors if a returned SYS_REFCURSOR is not opened (Martin J. Evans) - -Fix RT82663. If a procedure/function returns a SYS_REFCURSOR which + - Fix RT82663. If a procedure/function returns a SYS_REFCURSOR which was never opened DBD::Oracle magics a DBI statement handle into - existence and attempts to describe it (which fails). This change examines - a returned SYS_REFCURSOR and if it it is initialised but not executed does not - create a DBI statement handle and returns undef instead. So now if you - have a procedure/function which returns a SYS_REFCURSOR and never open - it you'll get undef back instead of a useless statement handle. - Extended 50cursor.t test to check the above fix. + existence and attempts to describe it (which fails). This change + examines a returned SYS_REFCURSOR and if it it is initialised but + not executed does not create a DBI statement handle and returns + undef instead. So now if you have a procedure/function which + returns a SYS_REFCURSOR and never open it you'll get undef back + instead of a useless statement handle. Extended 50cursor.t test + to check the above fix. (Martin J. Evans) [DOCUMENTATION] - Update Lion instructions for 64-bit Instant Client. (GH#37, patch by From ddd1d4e1b643138cbe9ad99bcad0d77a68006ed5 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 1 Apr 2013 11:39:29 -0400 Subject: [PATCH 416/637] move repo to Pythian org Conflicts: Changes dist.ini --- Changes | 3 +++ dist.ini | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 1b7bcde5..a9be5868 100644 --- a/Changes +++ b/Changes @@ -10,6 +10,9 @@ NEXT_RELEASE the last row forever. Also added test case to the 51scroll.t test (Martin J. Evans). +1.60 2013-04-01 + - Move github repository to github.com/pythian/DBD-Oracle. + 1.58 2013-03-05 - promote 1.57_00 to official release diff --git a/dist.ini b/dist.ini index c80b28e4..1d657870 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.58 +version = 1.60 [Authority] authority=cpan:PYTHIAN From ae12afbdd2bbe6207000174f66a59b7faf12d883 Mon Sep 17 00:00:00 2001 From: Joe Crotty Date: Wed, 9 Jan 2013 14:49:39 -0700 Subject: [PATCH 417/637] Adjust the privs needed for the DROP/CREATE table test. Change-Id: I60e24362a512dc4529c29fa059bddc627b13ea53 --- Changes | 2 ++ t/rt13865.t | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index a9be5868..4eb38f65 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,8 @@ Revision history for DBD::Oracle NEXT_RELEASE [BUG FIXES] + - Adjust the privs needed for the DROP/CREATE table test. [GH#35] + (Joe Crotty) - Fixed RT84170 - when using scrollable cursors and you've done a positioned fetch and then keep fetching until the end of the diff --git a/t/rt13865.t b/t/rt13865.t index 273b85be..bfbe7d86 100644 --- a/t/rt13865.t +++ b/t/rt13865.t @@ -13,8 +13,7 @@ my $dbh = db_handle() or plan skip_all => "can't connect to database"; my %priv = map { $_ => 1 } get_privs( $dbh ); -unless ( ( $priv{'CREATE TABLE'} or $priv{'CREATE ANY TABLE'} ) - and ( $priv{'DROP TABLE'} or $priv{'DROP ANY TABLE'} ) ) { +unless ( $priv{'CREATE TABLE'} ) { plan skip_all => q{requires permissions 'CREATE TABLE' and 'DROP TABLE'}; } From 106e4336c78d818a3bc831b1b31b37218be2e297 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 1 Apr 2013 12:16:40 -0400 Subject: [PATCH 418/637] fix error message --- t/rt13865.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/rt13865.t b/t/rt13865.t index bfbe7d86..78a63c02 100644 --- a/t/rt13865.t +++ b/t/rt13865.t @@ -14,7 +14,7 @@ my $dbh = db_handle() or plan skip_all => "can't connect to database"; my %priv = map { $_ => 1 } get_privs( $dbh ); unless ( $priv{'CREATE TABLE'} ) { - plan skip_all => q{requires permissions 'CREATE TABLE' and 'DROP TABLE'}; + plan skip_all => q{requires permissions 'CREATE TABLE'}; } plan tests => 9; From ece1ec9a7f2d795959799187609e052b7749160a Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 15 Apr 2013 14:37:43 -0400 Subject: [PATCH 419/637] support for CONTRIBUTORS --- .mailmap | 6 ++++++ MANIFEST | 1 + dist.ini | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .mailmap diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000..30322d4f --- /dev/null +++ b/.mailmap @@ -0,0 +1,6 @@ +Yanick Champoux +Yanick Champoux +Tim Bunce +Tim Bunce +Martin J. Evans +John Scoles diff --git a/MANIFEST b/MANIFEST index 95ee2f3e..40cafa72 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,3 +1,4 @@ +CONTRIBUTORS Changes INSTALL LICENSE diff --git a/dist.ini b/dist.ini index 1d657870..86e116d4 100644 --- a/dist.ini +++ b/dist.ini @@ -1,6 +1,6 @@ name = DBD-Oracle author = Tim Bunce -author = John Scoles +author = John Scoles author = Yanick Champoux author = Martin J. Evans license = Perl_5 From 211d45ca3728668e73e03b8cc338ae2cb1ab197d Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 15 Apr 2013 14:37:58 -0400 Subject: [PATCH 420/637] preps for v1.61_00 --- Changes | 2 +- dist.ini | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 4eb38f65..bbe3d287 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -NEXT_RELEASE +{{$NEXT}} [BUG FIXES] - Adjust the privs needed for the DROP/CREATE table test. [GH#35] diff --git a/dist.ini b/dist.ini index 86e116d4..cf56d1fa 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.60 +version = 1.61_00 [Authority] authority=cpan:PYTHIAN @@ -27,6 +27,7 @@ authority=cpan:PYTHIAN -remove=Test::Compile -remove=Covenant -remove=CoderwallEndorse +-remove=Git::CommitBuild [Prereqs / ConfigureRequires] DBI = 1.51 @@ -34,3 +35,6 @@ DBI = 1.51 [FakeRelease] [HelpWanted] positions = coder documentation tester + +[Git::CommitBuild] +multiple_inheritance = 1 From ed2c6b761bc88ab6fe7d8a438bb008971b9686f3 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 15 Apr 2013 15:59:31 -0300 Subject: [PATCH 421/637] add Michael's alias --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 30322d4f..8cbb9907 100644 --- a/.mailmap +++ b/.mailmap @@ -4,3 +4,4 @@ Tim Bunce Tim Bunce Martin J. Evans John Scoles +Michael Portnoy From 36ab5d03e14657089ae582b81db18b21f3f848b8 Mon Sep 17 00:00:00 2001 From: Michael Portnoy Date: Thu, 25 Apr 2013 14:36:30 -0400 Subject: [PATCH 422/637] RT Bug #84657 for DBD-Oracle: Use of uninitialized value $user_only in uc --- Changes | 4 ++++ lib/DBD/Oracle.pm | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index bbe3d287..01ac367c 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,10 @@ Revision history for DBD::Oracle {{$NEXT}} + [ENHANCEMENTS] + - DBD-Oracle: Use of uninitialized value $user_only in uc [RT#84657] + (Steffen Goeldner) + [BUG FIXES] - Adjust the privs needed for the DROP/CREATE table test. [GH#35] (Joe Crotty) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index e3b0dbe8..02dd7f36 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -298,7 +298,7 @@ package DBD::Oracle; unless (length $user_only) { $user_only = $dbh->selectrow_array(q{ SELECT SYS_CONTEXT('userenv','session_user') FROM DUAL - }); + })||''; $dbh_inner->{Username} = $user_only; # these two are just for backwards compatibility $dbh_inner->{USER} = $dbh_inner->{CURRENT_USER} = uc $user_only; From e0a6feced6782dda22a6f9ec449ab3f22128e6c2 Mon Sep 17 00:00:00 2001 From: "David E. Wheeler" Date: Mon, 29 Apr 2013 14:12:52 -0700 Subject: [PATCH 423/637] Bogus 227 directory no longer required! --- lib/DBD/Oracle/Troubleshooting/Macos.pod | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index 3ad9d2f3..c1d28410 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -82,15 +82,6 @@ Create a symlink from F to F: =item * -The following directory is hardcoded into the Oracle Instant Client - god -knows why - so we need to create and symlink it: - - sudo mkdir -p /b/227/rdbms/ - sudo cd /b/227/rdbms/ - sudo ln -s /usr/oracle_instantclient/ lib - -=item * - Update your environment to point to the libraries: export ORACLE_HOME=/usr/oracle_instantclient From c81ca01f5d061c2e232b7040da27eee8106ca8e5 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 29 Apr 2013 21:49:12 -0400 Subject: [PATCH 424/637] add changelog item --- Changes | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changes b/Changes index 01ac367c..849d35d7 100644 --- a/Changes +++ b/Changes @@ -16,6 +16,10 @@ Revision history for DBD::Oracle the last row forever. Also added test case to the 51scroll.t test (Martin J. Evans). + [DOCUMENTATION] + - Bogus 227 directory no longer required for MacOS. (GH#1, patch + by theory) + 1.60 2013-04-01 - Move github repository to github.com/pythian/DBD-Oracle. From 7932b8edff05ce7bede30adae1b570568d64c47f Mon Sep 17 00:00:00 2001 From: Michael Portnoy Date: Tue, 30 Apr 2013 13:32:10 -0400 Subject: [PATCH 425/637] preps for version 1.62 --- Changes | 3 +++ dist.ini | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index bbe3d287..6ff76224 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for DBD::Oracle {{$NEXT}} + - promote 1.61_00 to official release + +1.61_00 2013-04-15 [BUG FIXES] - Adjust the privs needed for the DROP/CREATE table test. [GH#35] diff --git a/dist.ini b/dist.ini index cf56d1fa..ac653ff2 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.61_00 +version = 1.62 [Authority] authority=cpan:PYTHIAN From 84b4639a3a596c6dcdc20878b3acfb5816b47e1c Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 3 May 2013 16:09:19 -0400 Subject: [PATCH 426/637] make 50cursor.t Oracle8-friendly --- Changes | 3 +++ t/50cursor.t | 47 ++++++++++++++++++----------------------------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/Changes b/Changes index a8610d3a..1791ad19 100644 --- a/Changes +++ b/Changes @@ -6,6 +6,9 @@ Revision history for DBD::Oracle - DBD-Oracle: Use of uninitialized value $user_only in uc [RT#84657] (Steffen Goeldner) + [BUG FIXES] + - Make 50cursor.t Oracle8-friendly. (RT#84660, patch by Steffen Goeldner) + [DOCUMENTATION] - Bogus 227 directory no longer required for MacOS. (GH#1, patch by theory) diff --git a/t/50cursor.t b/t/50cursor.t index fcc870ad..b2fea460 100644 --- a/t/50cursor.t +++ b/t/50cursor.t @@ -37,7 +37,7 @@ if ($dbh) { $limit = 1; } $limit = 100 if $limit > 100; # lets not be greedy or upset DBA's - $tests = 2 + 10 * $limit + 7; + $tests = 2 + 10 * $limit + 6; plan tests => $tests; @@ -83,34 +83,23 @@ foreach ( 1 .. @cursors ) { ok($close_cursor->execute, 'close cursor execute'); } -$dbh->{RaiseError} = 1; -eval { - $dbh->do(<<'EOT'); -create or replace procedure dbd_oracle_test(aref out sys_refcursor) as -begin - aref := NULL; -end; -EOT -}; - -my $ev = $@; -diag($ev) if $@; -SKIP: { - skip 'failed to create proc for test so skipping', 5 if $ev; - - local $dbh->{RaiseError} = 0; - - ok(my $sth1 = $dbh->prepare(q/begin dbd_oracle_test(?); end;/), - 'prepare exec of proc for null cursor'); - ok($sth1->bind_param_inout(1, \my $cursor, 100, {ora_type => ORA_RSET}), - 'binding cursor for null cursor'); - ok($sth1->execute, 'execute for null cursor'); - is($cursor, undef, 'undef returned for null cursor'); - ok($sth1->execute, 'execute 2 for null cursor'); - is($cursor, undef, 'undef 2 returned for null cursor'); - ok($dbh->do(q/drop procedure dbd_oracle_test/), - 'drop dbd_oracle_test proc'); -}; +my $PLSQL = <<"PLSQL"; +DECLARE + TYPE t IS REF CURSOR; + c t; +BEGIN + ? := c; +END; +PLSQL + +ok(my $sth1 = $dbh->prepare($PLSQL), + 'prepare exec of proc for null cursor'); +ok($sth1->bind_param_inout(1, \my $cursor, 100, {ora_type => ORA_RSET}), + 'binding cursor for null cursor'); +ok($sth1->execute, 'execute for null cursor'); +is($cursor, undef, 'undef returned for null cursor'); +ok($sth1->execute, 'execute 2 for null cursor'); +is($cursor, undef, 'undef 2 returned for null cursor'); $dbh->disconnect; From e24e5618bb3981d913804efe651d721db6a7e143 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 3 May 2013 16:20:06 -0400 Subject: [PATCH 427/637] tweak Makefile.PL for SUSE --- Changes | 2 ++ Makefile.PL | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 1791ad19..7259f11d 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,8 @@ Revision history for DBD::Oracle [BUG FIXES] - Make 50cursor.t Oracle8-friendly. (RT#84660, patch by Steffen Goeldner) + - Makefile.PL's use of ACL tweaked for Suse Enterprise 11 SP2 + (RT#84530, patch by Alfred Nathaniel) [DOCUMENTATION] - Bogus 227 directory no longer required for MacOS. (GH#1, patch diff --git a/Makefile.PL b/Makefile.PL index 356f5639..d4eb5ae4 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1510,11 +1510,16 @@ sub read_file { sub find_bin{ - use filetest 'access'; my $bin = shift; my $path_sep = $Config{path_sep}; foreach (split(/\Q$path_sep/, $ENV{PATH})){ return "$_/$bin" if -x "$_/$bin"; + { + # let's try harder + # see rt#84530 for why we don't go straight for it + use filetest 'access'; + return "$_/$bin" if -x "$_/$bin"; + } } return undef; } From c1d28e6092d17b69a401b3f349057cbd71fdc999 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 3 May 2013 16:53:18 -0400 Subject: [PATCH 428/637] bump version --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index ac653ff2..4324b2f8 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.62 +version = 1.63_00 [Authority] authority=cpan:PYTHIAN From 7bb83c408fe7af6fda902e586311fdff024d8567 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 22 May 2013 14:56:08 -0400 Subject: [PATCH 429/637] preps for v1.64 --- Changes | 4 ++++ dist.ini | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 7259f11d..26b5ab32 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,10 @@ Revision history for DBD::Oracle {{$NEXT}} + - promote 1.63_00 to stable. + + +1.63_00 2013-05-03 [ENHANCEMENTS] - DBD-Oracle: Use of uninitialized value $user_only in uc [RT#84657] diff --git a/dist.ini b/dist.ini index 4324b2f8..3f123e5a 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.63_00 +version = 1.64 [Authority] authority=cpan:PYTHIAN From 7d5c2268e8a91088aa616fb5f0dccd18dde041aa Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Wed, 5 Jun 2013 15:54:22 +0100 Subject: [PATCH 430/637] Fix RT85886 - type and attribs to bind_col were not sticky --- Changes | 10 ++++++++-- MANIFEST | 1 + dbdimp.c | 8 ++++++-- t/rt85886.t | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100755 t/rt85886.t diff --git a/Changes b/Changes index 26b5ab32..5af74782 100644 --- a/Changes +++ b/Changes @@ -3,12 +3,18 @@ Revision history for DBD::Oracle {{$NEXT}} - promote 1.63_00 to stable. + [BUG FIXES] + + - Fix RT85886. The TYPE passed to bind_col is supposed to be sticky + and it wasn't. Attributes passed to bind_col could be lost later if + bind_col is called again without attributes. Both of these occur + when fetchall_arrayref is called with a slice (Martin J. Evans). 1.63_00 2013-05-03 [ENHANCEMENTS] - DBD-Oracle: Use of uninitialized value $user_only in uc [RT#84657] - (Steffen Goeldner) + (Steffen Goeldner) [BUG FIXES] - Make 50cursor.t Oracle8-friendly. (RT#84660, patch by Steffen Goeldner) @@ -25,7 +31,7 @@ Revision history for DBD::Oracle 1.61_00 2013-04-15 [BUG FIXES] - - Adjust the privs needed for the DROP/CREATE table test. [GH#35] + - Adjust the privs needed for the DROP/CREATE table test. [GH#35] (Joe Crotty) - Fixed RT84170 - when using scrollable cursors and you've done a diff --git a/MANIFEST b/MANIFEST index 40cafa72..91ff3a7c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -90,4 +90,5 @@ t/lib/ExecuteArray.pm t/nchar_test_lib.pl t/rt13865.t t/rt74753-utf8-encoded.t +t/rt85886.t typemap diff --git a/dbdimp.c b/dbdimp.c index 63f0c450..98175df0 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -933,8 +933,12 @@ int dbd_st_bind_col(SV *sth, imp_sth_t *imp_sth, SV *col, SV *ref, IV type, SV * croak("cannot bind to non-existent field %d", field); } - imp_sth->fbh[field-1].req_type = type; - imp_sth->fbh[field-1].bind_flags = 0; /* default to none */ + if (type != 0) { + imp_sth->fbh[field-1].req_type = type; + } + if (attribs) { + imp_sth->fbh[field-1].bind_flags = 0; /* default to none */ + } #if DBIXS_REVISION >= 13590 /* DBIXS 13590 added StrictlyTyped and DiscardString attributes */ diff --git a/t/rt85886.t b/t/rt85886.t new file mode 100755 index 00000000..683d3743 --- /dev/null +++ b/t/rt85886.t @@ -0,0 +1,50 @@ +#!/usr/bin/perl -w + +use strict; +use warnings; + +use Test::More; + +use DBI qw(:sql_types); +use Devel::Peek; +use B qw( svref_2object SVf_IOK SVf_NOK SVf_POK ); + +unshift @INC ,'t'; +require 'nchar_test_lib.pl'; + +sub is_iv { + my $sv = svref_2object(my $ref = \$_[0]); + my $flags = $sv->FLAGS; + + # See http://www.perlmonks.org/?node_id=971411 + my $x = $sv->can('PV') ? $sv->PV : undef; + + if (wantarray) { + return ($flags & SVf_IOK, $x); + } else { + return $flags & SVf_IOK; + } +} + +my $dsn = oracle_test_dsn(); +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; + +my $dbh = DBI->connect( $dsn, $dbuser, '', { + PrintError => 0, FetchHashKeyName =>'NAME_lc'}); + +plan skip_all => "unable to connect to Oracle database" if not $dbh; + +plan tests => 2; + +my $s = $dbh->prepare(q/select 1 as one from dual/); +$s->execute; + +$s->bind_col (1, undef, {TYPE => SQL_INTEGER, DiscardString => 1}); + +my $list = $s->fetchall_arrayref({}); + +is($list->[0]{one}, 1, "correct value returned"); +ok(is_iv($list->[0]{one}), "ivok") or Dump($list->[0]{one}); + +$dbh->disconnect; + From 57bf153cbfc8a5c1e9c8b95edacaa6a3759221a6 Mon Sep 17 00:00:00 2001 From: David Steinbrunner Date: Tue, 16 Jul 2013 07:40:32 -0400 Subject: [PATCH 431/637] typo fixes Fixes #5 --- lib/DBD/Oracle.pm | 4 ++-- lib/DBD/Oracle/Troubleshooting.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 14 +++++++------- lib/DBD/Oracle/Troubleshooting/Linux.pod | 6 +++--- lib/DBD/Oracle/Troubleshooting/Vms.pod | 4 ++-- lib/DBD/Oracle/Troubleshooting/Win32.pod | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 02dd7f36..9d9efd20 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -2181,7 +2181,7 @@ $refresh parameter to it. =head2 B -Returns true if the current connection supports TAF events. False if otherise. +Returns true if the current connection supports TAF events. False if otherwise. =head2 B @@ -3273,7 +3273,7 @@ a reference to a list. Do not use this in a scalar context. $hash_ref = $sth->fetchrow_hashref($name); Fetches the next row of data and returns a hashref containing the name of the columns as the keys -and the data itself as the values. Any NULL value is returned as as undef value. +and the data itself as the values. Any NULL value is returned as undef value. If there are no more rows or if an error occurs, the this method return undef. You should check C<< $sth->err >> afterwards (or use the L attribute) to discover if the undef returned diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 1efeffc2..477df9d8 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -91,7 +91,7 @@ running I<$ORACLE_HOME/lib/genclntsh.sh> and it should create it. Never copy I to a different machine or Oracle version. If DBD::Oracle was built on a machine with a different path to I -then you'll need to set set an environment variable, typically +then you'll need to set an environment variable, typically I, to include the directory containing I. I is typically ignored if the script is running set-uid diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 2e759c5d..bd156d61 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -42,7 +42,7 @@ scope of this document, some information can be found in the section L, or see your friendly Oracle DBA. One final remark, 3 years after this was first written. This has been -updated numberous times over the years. And some of the new biuld +updated numerous times over the years. And some of the new build recipe's see simpler than some of the original instructions in this file. I think one reason the recipe is getting simpler may be that the build @@ -116,7 +116,7 @@ is preferred on PA-RISC, and when an incantation can be concocted that eliminates the noisy warnings the produces at link time, this will probably become the default. Older 64bit versions of GCC, are known to be unable to build a good LP64 perl. And these flags will cause gcc to -barf. On HP-UX 11i (11.11), gcc-3.4.4 or gcc-3.4.5 is prefered over +barf. On HP-UX 11i (11.11), gcc-3.4.4 or gcc-3.4.5 is preferred over gcc-4.0.2 (or older gcc-4 versions) as 64bit builds on PA-RISC with that versions of the compiler are unreliable. @@ -229,7 +229,7 @@ When asked: For example: Any additional cc flags? [-D_HP-UX_SOURCE -Aa] -Ae +Z -z -Though this should be the default inmore recent perl versions. +Though this should be the default in more recent perl versions. Lastly, and this is optional, when asked: @@ -806,7 +806,7 @@ Then unpack and build: Note from H.Merijn Brand: In more recent perl distributions using HP C-ANSI-C should "just work" (TM), provided your C compiler can be -found and used, your database is up and running, and your enviroment +found and used, your database is up and running, and your environment variables are set as noted. Example is for a 64bit build, as Oracle ships Oracle 9 and up for HP-UX only in 64bit builds. @@ -875,7 +875,7 @@ statements, etc.: The appl_setup sets some Oracle variables (specific to our installation), which I then override for the database that I am working on. The script -(which I source) also unse some variables specific to other applications +(which I source) also uses some variables specific to other applications (e.g., Tivoli), mostly to unclutter my debugging. The INSTALL variable is related to building libgdbm. @@ -888,7 +888,7 @@ and DBD-Oracle-1.14 on HPUX 11.0 ( an L2000 machine ) with Oracle 9.0.1 =head2 http://www.sas.com/service/techsup/unotes/SN/001/001875.html -This is a not from from the SAS support people documenting the +This is a note from the SAS support people documenting the LhtStrInsert() and LhtStrCreate() undefined symbols errors, and how to fix them in the Oracle makefiles. @@ -916,7 +916,7 @@ or updates a module. =item 3 It eliminates Dynaloader warning (multiply defined). This occurs with the static build when Perl is run with -w. I fixed -this by removing -w from my #! lines, converting the the pragam "use +this by removing -w from my #! lines, converting the pragam "use warnings;". However, it was annoying, since all my scripts had -w in the #! line. diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 659d8848..c1323e2d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -15,7 +15,7 @@ Nothing special with this you just have to set up you permissions as follows; =head1 undefined symbol: __cmpdi2 comes up when Oracle isn't properly linked to the libgcc.a library. -In version 8, this was correctd by changing the SYSLIBS entry in +In version 8, this was corrected by changing the SYSLIBS entry in $ORACLE_HOME/bin/genclntsh to include "-L/usr/lib/gcc-lib/i386-redhat-linux/3.2 -lgcc". @@ -31,7 +31,7 @@ the linkage with DBD::Oracle proceeds properly. =head1 cc1: invalid option `tune=pentium4'" error -If you get the above it seems that eiter your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. +If you get the above it seems that either your Perl or OS where compiled with a different version of GCC or the GCC that is on your system is very old. No real problem with the above however you will have to @@ -91,7 +91,7 @@ DBD::Oracle seems to hit some sort of bug with the above two versions of DB. The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. -So far there is no patch for this but here are some work arounds +So far there is no patch for this but here are some workarounds use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); ... diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index ff7ec012..5eeeb52e 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -33,9 +33,9 @@ to a central process specific mechanism. But as it is inserted at the very top of LNM$FILE_DEV it also represents a source of misfortune - especially if a user with enough privilege to update the oracle table does so (presumably -unintentionally), as an examble by changing NLS_LANG. +unintentionally), as an example by changing NLS_LANG. -PERL has the abillity to define, redefine and undefine (deassign) +PERL has the ability to define, redefine and undefine (deassign) logical names, but if not told otherwise by the user does it in the first table in above list, and not as one would normally expect in the process table. diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index f2cd390a..fd76cb94 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -148,7 +148,7 @@ perl v5.8.8 built for i486-linux-gnu-thread-multi Oracle Instant client (10.1.0.5) The problem is in Makefile.PL. In line 130 the function find_oracle_home -is used to guess a value form $ORACLE_HOME if it is not set explicitely. +is used to guess a value form $ORACLE_HOME if it is not set explicitly. This value is used in line 138 to setup the environment (regardless which client is used). From 76a2de955e4046782e2a58b91e98d8fb467f8174 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 18 Jul 2013 13:56:18 -0400 Subject: [PATCH 432/637] changelog --- Changes | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changes b/Changes index 5af74782..9f5b91c2 100644 --- a/Changes +++ b/Changes @@ -10,6 +10,10 @@ Revision history for DBD::Oracle bind_col is called again without attributes. Both of these occur when fetchall_arrayref is called with a slice (Martin J. Evans). + [DOCUMENTATION] + + - Fix a bunch of typos. [GH#5, David Steinbrunner] + 1.63_00 2013-05-03 [ENHANCEMENTS] From b34c8f6a3c802f066455047d392bbcd5122e741a Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 18 Jul 2013 13:59:02 -0400 Subject: [PATCH 433/637] changelog --- Changes | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 9f5b91c2..1dfe05e9 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,6 @@ Revision history for DBD::Oracle {{$NEXT}} - - promote 1.63_00 to stable. [BUG FIXES] @@ -14,6 +13,9 @@ Revision history for DBD::Oracle - Fix a bunch of typos. [GH#5, David Steinbrunner] +1.64 2013-05-22 + - promote 1.63_00 to stable. + 1.63_00 2013-05-03 [ENHANCEMENTS] From 8c9b77b0a3c394ae7447eddd17142033d88d58b0 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 23 May 2013 11:37:01 -0400 Subject: [PATCH 434/637] fill the version with a dummy value for dev --- lib/DBD/Oracle.pm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 9d9efd20..f0f059c6 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -18,6 +18,9 @@ package DBD::Oracle; use Exporter (); use DBD::Oracle::Object(); + # for dev version + $DBD::Oracle::VERSION ||= '1.00'; + @ISA = qw(DynaLoader Exporter); %EXPORT_TAGS = ( ora_types => [ qw( @@ -44,7 +47,7 @@ package DBD::Oracle; require_version DBI 1.51; - bootstrap DBD::Oracle $VERSION; + DBD::Oracle->bootstrap($DBD::Oracle::VERSION); $drh = undef; # holds driver handle once initialized From 767750745282538694780c3c23218e437ef7bf50 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 29 Jul 2013 11:48:29 -0400 Subject: [PATCH 435/637] release preps --- .mailmap | 1 + dist.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index 8cbb9907..878ec419 100644 --- a/.mailmap +++ b/.mailmap @@ -3,5 +3,6 @@ Yanick Champoux Tim Bunce Tim Bunce Martin J. Evans +Martin J. Evans John Scoles Michael Portnoy diff --git a/dist.ini b/dist.ini index 3f123e5a..3b634600 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.64 +version = 1.65_00 [Authority] authority=cpan:PYTHIAN From c5b3018df85fecc47f7dac59fbb8e516ba1248b3 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 23 Aug 2013 12:59:02 -0400 Subject: [PATCH 436/637] release preps --- Changes | 3 +++ dist.ini | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 1dfe05e9..129f3c93 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for DBD::Oracle {{$NEXT}} + - promote 1.65_00 to stable. + +1.65_00 2013-07-29 [BUG FIXES] diff --git a/dist.ini b/dist.ini index 3b634600..d8edbe65 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.65_00 +version = 1.66 [Authority] authority=cpan:PYTHIAN From 9a82515c6808541897c5f7cde7bffb691f564959 Mon Sep 17 00:00:00 2001 From: gregor herrmann Date: Fri, 30 Aug 2013 11:22:56 -0400 Subject: [PATCH 437/637] POD syntax fixes --- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index bd156d61..3c30801b 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -949,6 +949,8 @@ The solution from this page is below; To work around this problem, complete the following procedure: +=over + =item 1 Log in to your Oracle account: su - oracle @@ -957,7 +959,7 @@ To work around this problem, complete the following procedure: $ORACLE_HOME/rdbms/admin/shrept.lst -=itme 3 Add the following line: +=item 3 Add the following line: rdbms:OCILobLocatorAssign From b259e1809743aacf9a303adf3bc13b368170836f Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 30 Aug 2013 11:24:42 -0400 Subject: [PATCH 438/637] changelog --- Changes | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Changes b/Changes index 129f3c93..aae6b9ae 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,11 @@ Revision history for DBD::Oracle {{$NEXT}} + + [DOCUMENTATION] + - POD typos (RT#88285, Gregor Herrman). + +1.66 2013-08-23 - promote 1.65_00 to stable. 1.65_00 2013-07-29 From 2f6fd0a89af38f739fb2f66964784373f381346d Mon Sep 17 00:00:00 2001 From: gregor herrmann Date: Fri, 30 Aug 2013 11:36:00 -0400 Subject: [PATCH 439/637] POD typos --- lib/DBD/Oracle/Troubleshooting/Aix.pod | 6 +++--- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Win64.pod | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index 752ba37a..bc17271d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -154,7 +154,7 @@ Stephen de Vries Rafael Caceres - > I dont believe I compiled Oracle. During the installation it was linked + > I don't believe I compiled Oracle. During the installation it was linked > but I am not sure it was compiled > > I used a xlc compiler to compile PERL. @@ -164,7 +164,7 @@ Stephen de Vries > You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV > Also see the README about the -p option > - > this probobly means I need to rebuild PERL with xlc_r?? + > this probably means I need to rebuild PERL with xlc_r?? > > thanx > @@ -190,7 +190,7 @@ Stephen de Vries Message-ID: Here is a tip for compiling DBD::Oracle as a 32 bit application on AIX 5.1 - 64 bit and Oracle 9.2 64 bit without editting any makefiles. I hope people + 64 bit and Oracle 9.2 64 bit without editing any makefiles. I hope people find this useful: First, the versions of products I used: diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 3c30801b..50e1cca7 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -224,7 +224,7 @@ I use this in my standard build now. (See F) When asked: Any additional cc flags? - Answer by prepending: I<+Z> to enable - position independant code. + position independent code. For example: Any additional cc flags? [-D_HP-UX_SOURCE -Aa] -Ae +Z -z diff --git a/lib/DBD/Oracle/Troubleshooting/Win64.pod b/lib/DBD/Oracle/Troubleshooting/Win64.pod index 16d16063..d0575fda 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win64.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win64.pod @@ -161,7 +161,7 @@ else to support this configuration). SET ORACLE_SID=xyz123 <== SID of Production Database - SET NLS_LANG=.WE8ISO8859P1 <== Default Language from Database (preceeding "." Is required) + SET NLS_LANG=.WE8ISO8859P1 <== Default Language from Database (preceding "." Is required) SET PATH=%ORACLE_HOME%\bin;%PATH% <== Add 32-bit Oracle Home to beginning of default PATH From 1ae5bcce092b2d6ef1bb407ee831694f5cef05ad Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 30 Aug 2013 11:36:40 -0400 Subject: [PATCH 440/637] changelog --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index aae6b9ae..33d7222d 100644 --- a/Changes +++ b/Changes @@ -3,7 +3,7 @@ Revision history for DBD::Oracle {{$NEXT}} [DOCUMENTATION] - - POD typos (RT#88285, Gregor Herrman). + - POD typos (RT#88285, RT#88284, Gregor Herrman). 1.66 2013-08-23 - promote 1.65_00 to stable. From e737d30c3b9a2fba6c133054dc0f11efa6feea18 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Fri, 9 Aug 2013 10:00:46 +0100 Subject: [PATCH 441/637] fix pod errors in Hpux troubleshooting --- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 58 +++++++++++++++---------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 50e1cca7..a7575e93 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -642,14 +642,16 @@ F =head3 RE problem with libjava.sl A copy of the message Lincoln received from Jon Stevenson concerning a -problem with the libjava.sl can be found in L. +problem with the libjava.sl can be found in README-files/hpux/libjava.eml. Note that the gcc build described in L also describes a problem with libjava.sl, which was solved by putting it in the extra libraries option at configure time. That is probably a preferable solution. =head1 APPENDICES -=head2 Appendix A (gcc build info from Waldemar Zurowski) +=head2 Appendix A + +(gcc build info from Waldemar Zurowski) This is pretty much verbatim the build information I received from Waldemar Zurowski on building Perl and DBD-Oracle using gcc on HP. Note @@ -731,7 +733,9 @@ document. Using LD_PRELOAD is probably a fragile solution at best. Better to do what Waldemar actually did, which is to include libjava in the extra link options. -=head2 Appendix B (64 bit build with /usr/bin/cc -- bundled C compiler) +=head2 Appendix B + +(64 bit build with /usr/bin/cc -- bundled C compiler) Gram M. Ludlow writes: @@ -829,7 +833,9 @@ ships Oracle 9 and up for HP-UX only in 64bit builds. make test make install -=head2 Appendix C (Miscellaneous links which might be useful) +=head2 Appendix C + +(Miscellaneous links which might be useful) Michael Schuh writes: @@ -892,7 +898,9 @@ This is a note from the SAS support people documenting the LhtStrInsert() and LhtStrCreate() undefined symbols errors, and how to fix them in the Oracle makefiles. -=head1 Appendix D (Why Dynamic Linking) +=head1 Appendix D + +(Why Dynamic Linking) Some one posted to the DBI email list the following question: @@ -930,15 +938,17 @@ Dynamicly linking is what you get by default, so its way better tested. =back -=head1 Appendix E (WebLogic Driver for Oracle with the Oracle8i Server Lob Bug) +=head1 Appendix E -Michael Fox reported a bug when you are using DBD-Oracle-1.18 or later and when using older Oracle versions. -The bug will result in an error report +(WebLogic Driver for Oracle with the Oracle8i Server Lob Bug) + +Michael Fox reported a bug when you are using DBD-Oracle-1.18 or later and when using older Oracle versions. +The bug will result in an error report 'Failed to load Oracle extension and/or shared libraries'. -This problem occurs if you use the WebLogic Driver for Oracle with the Oracle8i Server -- Enterprise Edition 8.1.7 and the corresponding Oracle Call Interface (OCI). +This problem occurs if you use the WebLogic Driver for Oracle with the Oracle8i Server +- Enterprise Edition 8.1.7 and the corresponding Oracle Call Interface (OCI). This problem occurs only in Oracle 8.1.7; it is fixed in Oracle 9i. This link details the problem @@ -953,9 +963,9 @@ To work around this problem, complete the following procedure: =item 1 Log in to your Oracle account: - su - oracle + su - oracle -=item 2 In a text editor, open the following file: +=item 2 In a text editor, open the following file: $ORACLE_HOME/rdbms/admin/shrept.lst @@ -963,23 +973,23 @@ To work around this problem, complete the following procedure: rdbms:OCILobLocatorAssign -=item 4 (optional) Add the names of any other missing functions needed by applications, other than WebLogic Server 7.0, that you want to execute. +=item 4 (optional) Add the names of any other missing functions needed by applications, other than WebLogic Server 7.0, that you want to execute. Note: The OCILobLocatorAssign function is not the only missing function that WebLogic Server 7.0 should be able to call, but it is the only missing function that WebLogic Server 7.0 requires. Other functions that WebLogic Server should be able to call, such as OCIEnvCreate and OCIerminate, are also missing. If these functions are required by other applications that you plan to run, you must add them to your environment by specifying them, too, in $ORACLE_HOME/rdbms/admin/shrept.lst. -=item 5 Rebuild the shared client library: - - $ cd $ORACLE_HOME/rdbms/lib - $ make -f ins_rdbms.mk client_sharedlib +=item 5 Rebuild the shared client library: + + $ cd $ORACLE_HOME/rdbms/lib + $ make -f ins_rdbms.mk client_sharedlib The make command updates the following files in /opt/oracle/product/8.1.7/lib: - clntsh.map - ldap.def libclntsh.so - libclntsh.so.8.0 libclntst8.a - network.def - plsql.def - precomp.def - rdbms.def + clntsh.map + ldap.def libclntsh.so + libclntsh.so.8.0 libclntst8.a + network.def + plsql.def + precomp.def + rdbms.def Because OCILobLocatorAssign is now visible in libclntsh.so, WebLogic Server can call it. From 88b26154d44b2f81796761035fedd847c41db8ba Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sun, 8 Sep 2013 12:18:36 -0400 Subject: [PATCH 442/637] remove mention of deleted files --- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 86 ++----------------------- 1 file changed, 5 insertions(+), 81 deletions(-) diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index a7575e93..b100f20b 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -15,7 +15,7 @@ fact, after resolving some undefined symbol errors, I succeeded where for I had previously despaired of finding the time to hack out the right incantation. -This F describes the combined knowledge of a number of +This document describes the combined knowledge of a number of folks who invested many hours discovering a working set of build options. The instructions in this file, which include building Perl from source, will produce a working dynamically linked DBD-Oracle that can be used @@ -182,19 +182,6 @@ instructions provided by Gram Ludlow, using the default /usr/bin/cc bundled compiler. Please note that perl itself will I build using that compiler. -=head2 Just tell me the recipe... - -If you are using the softbench compiler, just copy and modify my makefile. -A copy of this makefile, which I use to build Perl and the DBI interfaces -(and all other modules I use for that matter) on all platforms (HP, SUN -and Red Hat) can be found in F. If you -want to skip reading the rest of this screed, try copying the makefile into -a directory where you have all your compressed tar balls, editing the macros -at the top, and running make. - -It you are plan to give gcc a go, consider making modifications to this -makefile, and sending it back to me, as a GCC example. - =head2 Configure (doing it manually) Once you have downloaded and unpacked the Perl sources (version 5.8.8 @@ -219,8 +206,6 @@ Do not forget the trailing space inside the single quotes. This is also described by H.Merijn Brand in the README.hpux from the perl core distribution. -I use this in my standard build now. (See F) - When asked: Any additional cc flags? - Answer by prepending: I<+Z> to enable @@ -433,7 +418,7 @@ is b present. and that B present. If the version of Makefile.PL does not include the patch produced at the -time of this README.hpux, then the above conditions will likely not be +time of this document, then the above conditions will likely not be met. You can fix this as follows: @@ -566,7 +551,7 @@ caused problems on HP (the user 'www' may need to be created) =head1 CONTRIBUTORS -The following folks contributed to this README: +The following folks contributed to this document: Lincoln A. Baxter H.Merijn Brand @@ -587,65 +572,7 @@ And probably others unknown to me. Lincoln A. Baxter H.Merijn Brand -=head1 EXAMPLE FILES - -Example files have been split off this document to README-files/hpux/ - -=head2 Lincoln's Makefile - -Lincoln's Makefile can be found in README-files/hpux/Makefile-Lincoln - -It contains the text of the makefile Lincoln uses to build Perl on all -platforms he runs on. - -=head2 Perl Configuration Dumps - -The following to sections provide full dumps of perl -V for three versions -of Perl that were successfully built and linked on HP-UX 11.00. - -=head3 Lincoln Baxter's DBD-Oracle-1.07 Configuration - -See F -=head3 Lincoln Baxter's DBD-Oracle-1.06 Configuration - -See F - -=head3 Roger Foskett's Configuration (works with Apache and mod_perl) - -See F - -Roger also provides a link to some threads containing some of his -DBD-Oracle and HP-UX 11 trials... -L - -=head3 Mike Shuh's Configuration. - -See also appendix C - -See F - -=head3 H.Merijn Brand's Configurations - -See -F, -F, -F, -F, -F, -F, -F, -F, -F, and -F - -=head3 RE problem with libjava.sl - -A copy of the message Lincoln received from Jon Stevenson concerning a -problem with the libjava.sl can be found in README-files/hpux/libjava.eml. -Note that the gcc build described in L also describes a problem -with libjava.sl, which was solved by putting it in the extra libraries option -at configure time. That is probably a preferable solution. =head1 APPENDICES @@ -655,8 +582,7 @@ at configure time. That is probably a preferable solution. This is pretty much verbatim the build information I received from Waldemar Zurowski on building Perl and DBD-Oracle using gcc on HP. Note -that this build was on a PA-RISC1.1 machine. Differences for building on -PA-RISC2.0 would be welcome and incorporated into the next README. +that this build was on a PA-RISC1.1 machine. =head3 Host @@ -707,7 +633,7 @@ Please note output of ldd command: [...] All of this mess is necessary because of weakness of shl_load(3X), -explained in current README.hpux and in some discussion forums at HP.com +explained in this document and in some discussion forums at HP.com site. I have learned, that HP issued patch PHSS_24304 for HP-UX 11.11 and PHSS_24303 for HP-UX 11.00, which introduced variable LD_PRELOAD. I haven't tried it yet, but it seems promising that it would allow you @@ -885,8 +811,6 @@ which I then override for the database that I am working on. The script (e.g., Tivoli), mostly to unclutter my debugging. The INSTALL variable is related to building libgdbm. -The output of perl -V can be found in README-files/hpux/Conf-Mike - =head2 http://www.mail-archive.com/dbi-users@perl.org/msg18687.html Garry Ferguson's notes on a successful build using perl 5.8.0, DBI-1.38 From f3bed5e4c811f16a1bd1a2e12be52713a4138aa7 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sun, 8 Sep 2013 12:20:54 -0400 Subject: [PATCH 443/637] changelog Fixes #7 --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index 33d7222d..4bcc8091 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,8 @@ Revision history for DBD::Oracle [DOCUMENTATION] - POD typos (RT#88285, RT#88284, Gregor Herrman). + - Grooming of Hpux troubleshooting pod (GH#7, Martin J. Evans, + Yanick Champoux) 1.66 2013-08-23 - promote 1.65_00 to stable. From 479ecddf73f5c3f7e4a9770dbbebd756ba88f382 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Tue, 29 Oct 2013 16:06:15 +0000 Subject: [PATCH 444/637] RT88135 and RT89491 fixes --- Changes | 4 ++ lib/DBD/Oracle.pm | 98 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index 4bcc8091..36472b5f 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,10 @@ Revision history for DBD::Oracle {{$NEXT}} + [BUG FIXES] + - Fix RT88135. Add statistics_info support (patch by Steffen Goeldner) + - Fix RT89491. Add RULE hint (patch by Steffen Goeldner) + [DOCUMENTATION] - POD typos (RT#88285, RT#88284, Gregor Herrman). - Grooming of Hpux troubleshooting pod (GH#7, Martin J. Evans, diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index f0f059c6..4789c79f 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -464,7 +464,7 @@ SQL SELECT * FROM ( - SELECT /*+ RULE*/ + SELECT /*+ CHOOSE */ NULL TABLE_CAT , t.OWNER TABLE_SCHEM , t.TABLE_NAME TABLE_NAME @@ -518,7 +518,7 @@ SQL SELECT * FROM ( - SELECT /*+ RULE*/ + SELECT /*+ CHOOSE */ NULL TABLE_CAT , c.OWNER TABLE_SCHEM , c.TABLE_NAME TABLE_NAME @@ -551,7 +551,7 @@ SQL SELECT * FROM ( - SELECT /*+ RULE*/ + SELECT /*+ CHOOSE */ to_char( NULL ) UK_TABLE_CAT , uk.OWNER UK_TABLE_SCHEM , uk.TABLE_NAME UK_TABLE_NAME @@ -620,7 +620,7 @@ SQL SELECT * FROM ( - SELECT /*+ RULE*/ + SELECT /*+ CHOOSE */ to_char( NULL ) TABLE_CAT , tc.OWNER TABLE_SCHEM , tc.TABLE_NAME TABLE_NAME @@ -778,6 +778,62 @@ SQL $sth; } + sub statistics_info { + my($dbh, $catalog, $schema, $table, $unique_only, $quick) = @_; + if (ref $catalog eq 'HASH') { + ($schema, $table) = @$catalog{'TABLE_SCHEM','TABLE_NAME'}; + $catalog = undef; + } + my $SQL = <<'SQL'; +SELECT * + FROM +( + SELECT /*+ CHOOSE */ + NULL TABLE_CAT + , t.OWNER TABLE_SCHEM + , t.TABLE_NAME TABLE_NAME + , to_number( NULL ) NON_UNIQUE + , NULL INDEX_QUALIFIER + , NULL INDEX_NAME + ,'table' TYPE + , to_number( NULL ) ORDINAL_POSITION + , NULL COLUMN_NAME + , NULL ASC_OR_DESC + , t.NUM_ROWS CARDINALITY + , t.BLOCKS PAGES + , NULL FILTER_CONDITION + FROM ALL_TABLES t + UNION + SELECT NULL TABLE_CAT + , t.OWNER TABLE_SCHEM + , t.TABLE_NAME TABLE_NAME + , decode( t.UNIQUENESS,'UNIQUE', 0, 1 ) NON_UNIQUE + , c.INDEX_OWNER INDEX_QUALIFIER + , c.INDEX_NAME INDEX_NAME + , decode( t.INDEX_TYPE,'NORMAL','btree','CLUSTER','clustered','other') TYPE + , c.COLUMN_POSITION ORDINAL_POSITION + , c.COLUMN_NAME COLUMN_NAME + , decode( c.DESCEND,'ASC','A','DESC','D') ASC_OR_DESC + , t.DISTINCT_KEYS CARDINALITY + , t.LEAF_BLOCKS PAGES + , NULL FILTER_CONDITION + FROM ALL_INDEXES t + , ALL_IND_COLUMNS c + WHERE t.OWNER = c.INDEX_OWNER + AND t.INDEX_NAME = c.INDEX_NAME + AND t.TABLE_OWNER = c.TABLE_OWNER + AND t.TABLE_NAME = c.TABLE_NAME + AND t.UNIQUENESS LIKE :3 +) + WHERE TABLE_SCHEM = :1 + AND TABLE_NAME = :2 + ORDER BY NON_UNIQUE, TYPE, INDEX_QUALIFIER, INDEX_NAME, ORDINAL_POSITION +SQL + my $sth = $dbh->prepare($SQL) or return undef; + $sth->execute($schema, $table, $unique_only ?'UNIQUE':'%') or return undef; + $sth; + } + sub type_info_all { my ($dbh) = @_; my $version = ( ora_server_version($dbh)->[0] < DBD::Oracle::ORA_OCI() ) @@ -2563,6 +2619,40 @@ So in the example the exact case "Bla_BLA" must be used to get it info on the co any case can be used to get info on the column. +=head2 B + +Oracle does not support catalogues so TABLE_CAT is ignored as +selection criterion. +The TABLE_CAT field of a fetched row is always NULL (undef). +See L for more detailed information. + +The INDEX_QUALIFIER field of a fetched row is always NULL (undef), +for the same reason as for TABLE_CAT. + +If an index was created without an identifier +(e.g. in the course of a PK creation), +INDEX_NAME contains a system generated name with the form SYS_. + +COLUMN_NAME may contain a system generated name +(e.g. for function-based indexes). + +For the TYPE column, a simple mapping is used: + + NORMAL btree + CLUSTER clustered + ... other + +The C<$quick> parameter is currently ignored. +The method uses the dictionary with the gathered statistics, +thus cannot ensure that the values for CARDINALITY and PAGES are current. + +The result set is ordered by +NON_UNIQUE, TYPE, INDEX_QUALIFIER, INDEX_NAME, ORDINAL_POSITION. + +An identifier is passed I, i.e. as the user provides or +Oracle returns it. +See L for more detailed information. + =head2 B @row_ary = $dbh->selectrow_array($sql); From 2d30bc9b24dfce9503a95afed8552d49f04fad4d Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 5 Nov 2013 18:46:36 -0500 Subject: [PATCH 445/637] release preps --- dist.ini | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dist.ini b/dist.ini index d8edbe65..97118fc3 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.66 +version = 1.67_00 [Authority] authority=cpan:PYTHIAN @@ -27,7 +27,6 @@ authority=cpan:PYTHIAN -remove=Test::Compile -remove=Covenant -remove=CoderwallEndorse --remove=Git::CommitBuild [Prereqs / ConfigureRequires] DBI = 1.51 @@ -36,5 +35,3 @@ DBI = 1.51 [HelpWanted] positions = coder documentation tester -[Git::CommitBuild] -multiple_inheritance = 1 From ff0e52ea0f513890a4627eadfffbf9a73aaaedd6 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 25 Nov 2013 16:35:49 -0500 Subject: [PATCH 446/637] changelog --- Changes | 3 +++ dist.ini | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 36472b5f..bd96f648 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for DBD::Oracle {{$NEXT}} + - promote 1.67_00 to stable. + +1.67_00 2013-11-05 [BUG FIXES] - Fix RT88135. Add statistics_info support (patch by Steffen Goeldner) diff --git a/dist.ini b/dist.ini index 97118fc3..0dde6ba5 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,11 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.67_00 +version = 1.68 + +[Encoding] +encoding = bytes +matches = .* [Authority] authority=cpan:PYTHIAN From a1dc07f0fd25f00cdc38cf7d0ddc26f3e0754dcd Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 25 Nov 2013 17:53:10 -0500 Subject: [PATCH 447/637] release preps --- Changes | 12 ++++++------ dist.ini | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Changes b/Changes index bd96f648..04faae6d 100644 --- a/Changes +++ b/Changes @@ -356,8 +356,8 @@ Revision history for DBD::Oracle [DOCUMENTATION] - Mention the release of Oracle Instant Client 64 bit which does not work on Lion. (Martin J. Evans) - - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] - - fix typos. (patch by Julián Moreno Patiño) [rt73999] + - fix DBD::Oracle::GetInfo blurb (patch by Julián Moreno Patiño) [rt74000] + - fix typos. (patch by Julián Moreno Patiño) [rt73999] - add troubleshoot doc and diag for error with bequeather. [rt75263] [OTHERS] @@ -372,7 +372,7 @@ Revision history for DBD::Oracle [ENHANCEMENTS] - added SYSASM session mode. [RT651211] (patch from - Anthony DeRobertis, reported by Julián Moreno Patiño) + Anthony DeRobertis, reported by Julián Moreno Patiño) [BUG FIXES] @@ -410,7 +410,7 @@ Changes in DBD-Oracle 1.35_00 (18-11-2011) - Added notes to bind_col documenting the fact that setting a TYPE does not affect how the column is bound in Oracle, only what happens after the column data is retrieved (Martin J. Evans) - - fix typo (thanks to Julián Moreno Patiño) [RT72038] + - fix typo (thanks to Julián Moreno Patiño) [RT72038] - shuffle POD around to improve documentation flow [RT72252] - major tidying up of the connect() documentation. (by Gwen Shapira) - Moved LONG examples out of POD and into examples/ @@ -549,7 +549,7 @@ Changes in DBD-Oracle 1.29_1 This release has been prepared specifically for the 'Debian' http://www.debian.org project. It contains no changes to functionality or usage. The following has been changed - Fixed some formatting and typos in Pod from Julián Patiño + Fixed some formatting and typos in Pod from Julián Patiño The Copyright terms for ora_explain have changed and now read as follows: You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. @@ -598,7 +598,7 @@ Changes in DBD-Oracle 1.29_1 Fix for rt.cpan.org Ticket #=21920 Bug with Oracle DBD for Mac OS X Instant Client From boingolover Added a few more constants to get rid of magic numbers from John Scoles Fix for rt.cpan.org Ticket #=38267 Inserts/Updates to BLOB's via synonyms fails from John Scoles - Fix for rt.cpan.org Ticket #=39603 build problem and fix missing functions in oci.def from Zoltán Sebestyén + Fix for rt.cpan.org Ticket #=39603 build problem and fix missing functions in oci.def from Zoltán Sebestyén Fix for rt.cpan.org Ticket #=39374 Makefile.PL: error when reducing echo messages from make from Tippa Fix for rt.cpan.org Ticket #=39232 binding large XMLTYPE fails on 64-bit perl from Jeff Klein Fix for rt.cpan.org Ticket #=38749 Warning of a NULL column in an aggregate function also added ora_oci_success_warn to display silent OCI warnings from John Scoles diff --git a/dist.ini b/dist.ini index 0dde6ba5..e8aae5f6 100644 --- a/dist.ini +++ b/dist.ini @@ -10,8 +10,8 @@ copyright_year = 1994 version = 1.68 [Encoding] -encoding = bytes -matches = .* +encoding = latin-1 +match = META.json [Authority] authority=cpan:PYTHIAN From 6aa9541e0a8ca42a72e761e9603803efd2d9f396 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Thu, 9 Jan 2014 17:09:58 +0000 Subject: [PATCH 448/637] Fix rt91698 repeatedly executing output bound params can cause the bound scalars to continually increase in size --- Changes | 8 +++++++- dbdimp.c | 44 ++++++++++++++++++++++++++++++-------------- oci8.c | 2 +- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/Changes b/Changes index 04faae6d..066f4d30 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,12 @@ Revision history for DBD::Oracle {{$NEXT}} - promote 1.67_00 to stable. + [BUG FIXES] + + - Fix RT91698. If you bound an output parameter to a scalar and + repeatedly called execute the memory allocated in your bound + scalar could increase each time. (Martin J. Evans) + 1.67_00 2013-11-05 [BUG FIXES] @@ -11,7 +17,7 @@ Revision history for DBD::Oracle [DOCUMENTATION] - POD typos (RT#88285, RT#88284, Gregor Herrman). - - Grooming of Hpux troubleshooting pod (GH#7, Martin J. Evans, + - Grooming of Hpux troubleshooting pod (GH#7, Martin J. Evans, Yanick Champoux) 1.66 2013-08-23 diff --git a/dbdimp.c b/dbdimp.c index 98175df0..c913133c 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2549,19 +2549,26 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) if (imp_sth->ora_pad_empty) croak("Can't use ora_pad_empty with bind_param_inout"); if (SvTYPE(phs->sv)!=SVt_RV || !at_exec) { - if (phs->ftype == 96){ - SvGROW(phs->sv,(STRLEN) (unsigned int)phs->maxlen-1); + SvGROW(phs->sv,(STRLEN) (unsigned int)phs->maxlen-1); + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), + "Growing 96 phs sv to %ld resulted in buffer %ld\n", phs->maxlen - 1, SvLEN(phs->sv)); + } } else { STRLEN min_len = 28; (void)SvUPGRADE(phs->sv, SVt_PVNV); - /* ensure room for result, 28 is magic number (see sv_2pv) */ - /* don't apply 28 char min to CHAR types - probably shouldn't */ - /* apply it anywhere really, trying to be too helpful. */ - /* phs->sv _is_ the real live variable, it may 'mutate' later */ - /* pre-upgrade to high'ish type to reduce risk of SvPVX realloc/move */ - SvGROW(phs->sv, (STRLEN)(((unsigned int) phs->maxlen <= min_len) ? min_len : (unsigned int) phs->maxlen)+1/*for null*/); - + /* ensure room for result, 28 is magic number (see sv_2pv) */ + /* don't apply 28 char min to CHAR types - probably shouldn't */ + /* apply it anywhere really, trying to be too helpful. */ + /* phs->sv _is_ the real live variable, it may 'mutate' later */ + /* pre-upgrade to high'ish type to reduce risk of SvPVX realloc/move */ + /* NOTE SvGROW resets SvOOK_offset and we want to do this */ + SvGROW(phs->sv, (STRLEN)(((unsigned int) phs->maxlen <= min_len) ? min_len : (unsigned int) phs->maxlen)); + if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), + "Growing phs sv to %ld resulted in buffer %ld\n", phs->maxlen +1, SvLEN(phs->sv)); + } } } @@ -2591,7 +2598,11 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) phs->maxlen = 4000; /* Just make is a varchar max should be ok for most things*/ } else { - phs->maxlen = ((IV)SvLEN(phs->sv)); /* avail buffer space (64bit safe) Logicaly maxlen should never change but it does why I know not*/ + if (DBIc_DBISTATE(imp_sth)->debug >= 6|| dbd_verbose >= 6 ) { + PerlIO_printf(DBIc_LOGPIO(imp_sth), + "Changing maxlen to %ld\n", SvLEN(phs->sv)); + } + phs->maxlen = ((IV)SvLEN(phs->sv)); /* avail buffer space (64bit safe) Logicaly maxlen should never change but it does why I know not - MJE because SvGROW can allocate more than you ask for - anyway - I fixed that and it doesn't grow anymore */ } @@ -3265,11 +3276,16 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ sv_setsv(phs->sv, newvalue); if (SvAMAGIC(phs->sv)) /* overloaded. XXX hack, logic ought to be pushed deeper */ sv_pvn_force(phs->sv, &PL_na); - } else if (newvalue != phs->sv) { - if (phs->sv) - SvREFCNT_dec(phs->sv); + } else { + if (newvalue != phs->sv) { + if (phs->sv) + SvREFCNT_dec(phs->sv); - phs->sv = SvREFCNT_inc(newvalue); /* point to live var */ + phs->sv = SvREFCNT_inc(newvalue); /* point to live var */ + } + /* Add space for NUL - do it now rather than in rebind as it cause problems + in rebind where maxlen continually grows. */ + phs->maxlen = phs->maxlen + 1; } return dbd_rebind_ph(sth, imp_sth, phs); diff --git a/oci8.c b/oci8.c index 6a3208bb..46a69e8e 100644 --- a/oci8.c +++ b/oci8.c @@ -1226,7 +1226,7 @@ dbd_phs_out(dvoid *octxp, OCIBind *bindp, sv_setpv(sv,""); } - *bufpp = SvGROW(sv, (size_t)(((phs->maxlen < 28) ? 28 : phs->maxlen)+1)/*for null*/); + *bufpp = SvGROW(sv, (size_t)(((phs->maxlen < 28) ? 28 : phs->maxlen))); phs->alen = SvLEN(sv); /* max buffer size now, actual data len later */ } From f10171b9c7d30837e163c0b52ec03d5bb24c3bab Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 14 Jan 2014 10:00:06 -0500 Subject: [PATCH 449/637] tweak changelog --- Changes | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 066f4d30..b06b582b 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,6 @@ Revision history for DBD::Oracle {{$NEXT}} - - promote 1.67_00 to stable. [BUG FIXES] @@ -9,6 +8,9 @@ Revision history for DBD::Oracle repeatedly called execute the memory allocated in your bound scalar could increase each time. (Martin J. Evans) +1.68 2013-11-25 + - promote 1.67_00 to stable. + 1.67_00 2013-11-05 [BUG FIXES] From 92136dfdd70fd0393f5663bc5c25dff046da3ba8 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 14 Jan 2014 10:28:27 -0500 Subject: [PATCH 450/637] changelog --- Changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes b/Changes index b06b582b..13b8fb2c 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.69_01 2014-01-14 [BUG FIXES] From 10383db6e955bb5f41b74f343f7ac470d3849bb9 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 14 Jan 2014 10:29:37 -0500 Subject: [PATCH 451/637] version bump --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index e8aae5f6..ffebd77b 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.68 +version = 1.69_01 [Encoding] encoding = latin-1 From f387cf9991cbe2bb5ee6d3c0fb10877cc740d87c Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sun, 19 Jan 2014 18:27:41 -0500 Subject: [PATCH 452/637] put back OCI_THREADED setting --- Changes | 8 ++++++++ dbdimp.c | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 13b8fb2c..fb9e4fe6 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,13 @@ Revision history for DBD::Oracle +1.69_02 2014-01-19 + + [BUG FIXES] + + - OCI_THREADED setting had been accidentally removed, causing potential + crashes when using threads. (RT#92229, Martin J. Evans, reported + by Detlef Lütticke) + 1.69_01 2014-01-14 [BUG FIXES] diff --git a/dbdimp.c b/dbdimp.c index c913133c..b68ba2e9 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -538,9 +538,13 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!imp_dbh->envhp ) { SV **init_mode_sv; - ub4 init_mode = OCI_OBJECT; /* needed for LOBs (8.0.4) */ + ub4 init_mode = OCI_OBJECT;/* needed for LOBs (8.0.4) */ DBD_ATTRIB_GET_IV(attr, "ora_init_mode",13, init_mode_sv, init_mode); +#if defined(USE_ITHREADS) || defined(MULTIPLICITY) || defined(USE_5005THREADS) + init_mode |= OCI_THREADED; +#endif + { size_t rsize = 0; /* Get CLIENT char and nchar charset id values */ From a029c4bc7982b919de1e2691bac97902e1d2a2fa Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sun, 19 Jan 2014 18:31:16 -0500 Subject: [PATCH 453/637] Fix RT 92134 --- Changes | 5 +++++ dbdimp.c | 16 +++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index fb9e4fe6..dc451783 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,11 @@ Revision history for DBD::Oracle crashes when using threads. (RT#92229, Martin J. Evans, reported by Detlef Lütticke) + - When using fetch*_hashref the values are decoded but + not the keys so if you have unicode column names they were not + returned correctly. (RT#92134, Martin J. Evans, reported by + Marcel Montes) + 1.69_01 2014-01-14 [BUG FIXES] diff --git a/dbdimp.c b/dbdimp.c index b68ba2e9..3f8ab82d 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -4345,10 +4345,20 @@ dbd_st_FETCH_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv) if (kl==4 && strEQ(key, "NAME")) { AV *av = newAV(); - retsv = newRV(sv_2mortal((SV*)av)); - while(--i >= 0) - av_store(av, i, newSVpv((char*)imp_sth->fbh[i].name,0)); + SV *x; + retsv = newRV(sv_2mortal((SV*)av)); + while(--i >= 0) { + x = newSVpv((char*)imp_sth->fbh[i].name,0); + if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { +#ifdef sv_utf8_decode + sv_utf8_decode(x); +#else + SvUTF8_on(x); +#endif + } + av_store(av, i, x); + } } else if (kl==11 && strEQ(key, "ParamValues")) { HV *pvhv = newHV(); From d6671c122158f0bdda135ac831d7c0a8c06c40e6 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Tue, 14 Jan 2014 10:25:14 -0500 Subject: [PATCH 454/637] sid=foo is an alias for 'foo' --- Changes | 6 ++++++ lib/DBD/Oracle.pm | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/Changes b/Changes index dc451783..7e54857c 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,11 @@ Revision history for DBD::Oracle 1.69_02 2014-01-19 + [IMPROVEMENTS] + + - The DSN 'dbi:Oracle:sid=foo' is now an alias for 'dbi:Oracle:foo'. + (RT#91775, Yanick Champoux, requested by David Wheeler) + [BUG FIXES] - OCI_THREADED setting had been accidentally removed, causing potential @@ -13,6 +18,7 @@ Revision history for DBD::Oracle returned correctly. (RT#92134, Martin J. Evans, reported by Marcel Montes) + 1.69_01 2014-01-14 [BUG FIXES] diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 4789c79f..89f5826d 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -197,6 +197,10 @@ package DBD::Oracle; sub connect { my ($drh, $dbname, $user, $auth, $attr)= @_; + # Make 'sid=whatever' an alias for 'whatever'. + # see RT91775 + $dbname =~ s/^sid=([^;]+)$/$1/; + if ($dbname =~ /;/) { my ($n,$v); $dbname =~ s/^\s+//; From b6648cf8e5ad0a3537c7f2058ed5e2e7b4e2ab2f Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sun, 19 Jan 2014 20:46:52 -0500 Subject: [PATCH 455/637] RT91473: added support for ORA_SYSBACKUP, ORA_SYSDG and ORA_SYSKM --- Changes | 3 +++ Oracle.xs | 3 +++ lib/DBD/Oracle.pm | 9 +++++---- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index 7e54857c..4eacf1cc 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,9 @@ Revision history for DBD::Oracle - The DSN 'dbi:Oracle:sid=foo' is now an alias for 'dbi:Oracle:foo'. (RT#91775, Yanick Champoux, requested by David Wheeler) + - Support for ORA_SYSBACKUP, ORA_SYSDG and ORA_SYSKM. (RT#91473, + Kris Lemaire) + [BUG FIXES] - OCI_THREADED setting had been accidentally removed, causing potential diff --git a/Oracle.xs b/Oracle.xs index e5bce1d0..926ae202 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -30,6 +30,9 @@ constant(name=Nullch) ORA_SYSDBA = 0x0002 ORA_SYSOPER = 0x0004 ORA_SYSASM = 0x8000 + ORA_SYSBACKUP = 0x00020000 + ORA_SYSDG = 0x00040000 + ORA_SYSKM = 0x00080000 SQLCS_IMPLICIT = SQLCS_IMPLICIT SQLCS_NCHAR = SQLCS_NCHAR SQLT_INT = SQLT_INT diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 89f5826d..f0f99379 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -29,7 +29,7 @@ package DBD::Oracle; ORA_CLOB ORA_BLOB ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE SQLT_INT SQLT_FLT ORA_OCI SQLT_CHR SQLT_BIN ) ], - ora_session_modes => [ qw( ORA_SYSDBA ORA_SYSOPER ORA_SYSASM) ], + ora_session_modes => [ qw( ORA_SYSDBA ORA_SYSOPER ORA_SYSASM ORA_SYSBACKUP ORA_SYSDG ORA_SYSKM) ], ora_fetch_orient => [ qw( OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST OCI_FETCH_LAST OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE)], @@ -1232,7 +1232,7 @@ consult the L documentation first! =item :ora_session_modes -ORA_SYSDBA ORA_SYSOPER ORA_SYSASM +ORA_SYSDBA ORA_SYSOPER ORA_SYSASM ORA_SYSBACKUP ORA_SYSDG ORA_SYSKM =item :ora_types @@ -1624,8 +1624,9 @@ to sleep between retries simple add a sleep to your callback sub. =head4 ora_session_mode The ora_session_mode attribute can be used to connect with SYSDBA, -SYSOPER and ORA_SYSASM authorization. -The ORA_SYSDBA, ORA_SYSOPER and ORA_SYSASM constants can be imported using +SYSOPER, ORA_SYSASM, ORA_SYSBACKUP, ORA_SYSKM and ORA_SYSDG authorization. +The ORA_SYSDBA, ORA_SYSOPER, ORA_SYSASM, ORA_SYSBACKUP, ORA_SYSKM +and ORA_SYSDG constants can be imported using use DBD::Oracle qw(:ora_session_modes); From 21fd3ad623521358f53f71a7a8ee70464d88232d Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sun, 19 Jan 2014 20:51:00 -0500 Subject: [PATCH 456/637] bump version --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index ffebd77b..37260a3a 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.69_01 +version = 1.69_02 [Encoding] encoding = latin-1 From c986a3b7a7ce3dc7344b540c6ea00ad6bab66409 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 12 Feb 2014 09:52:00 -0500 Subject: [PATCH 457/637] version bump --- Changes | 3 +++ dist.ini | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 4eacf1cc..5b30bca8 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,8 @@ Revision history for DBD::Oracle +1.70 2014-02-12 + - promote 1.69_02 to stable. + 1.69_02 2014-01-19 [IMPROVEMENTS] diff --git a/dist.ini b/dist.ini index 37260a3a..7301468c 100644 --- a/dist.ini +++ b/dist.ini @@ -2,12 +2,12 @@ name = DBD-Oracle author = Tim Bunce author = John Scoles author = Yanick Champoux -author = Martin J. Evans +author = Martin J. Evans license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.69_02 +version = 1.70 [Encoding] encoding = latin-1 From 209bf8aae4132879dee88b82df6e36055f3f0dc7 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Thu, 20 Feb 2014 13:20:03 +0000 Subject: [PATCH 458/637] Fix rt91217 - CHOOSE hint deprecated --- lib/DBD/Oracle.pm | 59 +++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index f0f99379..35bd441e 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -604,27 +604,30 @@ SQL sub column_info { - my $dbh = shift; - my $attr = ( ref $_[0] eq 'HASH') ? $_[0] : { - 'TABLE_SCHEM' => $_[1],'TABLE_NAME' => $_[2],'COLUMN_NAME' => $_[3] }; - my $ora_server_version = ora_server_version($dbh); - my($typecase,$typecaseend) = ('',''); - if ($ora_server_version->[0] >= 8) { - $typecase = <<'SQL'; + my $dbh = shift; + my $attr = ( ref $_[0] eq 'HASH') ? $_[0] : { + 'TABLE_SCHEM' => $_[1],'TABLE_NAME' => $_[2],'COLUMN_NAME' => $_[3] }; + my $ora_server_version = ora_server_version($dbh); + my($typecase,$typecaseend, $choose) = ('','','/*+ CHOOSE */'); + if ($ora_server_version->[0] >= 8) { + $typecase = <<'SQL'; CASE WHEN tc.DATA_TYPE LIKE 'TIMESTAMP% WITH% TIME ZONE' THEN 95 WHEN tc.DATA_TYPE LIKE 'TIMESTAMP%' THEN 93 WHEN tc.DATA_TYPE LIKE 'INTERVAL DAY% TO SECOND%' THEN 110 WHEN tc.DATA_TYPE LIKE 'INTERVAL YEAR% TO MONTH' THEN 107 ELSE SQL - $typecaseend = 'END'; - } - my $char_length = $ora_server_version->[0] < 9 ? 'DATA_LENGTH':'CHAR_LENGTH'; - my $SQL = <<"SQL"; + $typecaseend = 'END'; + } elsif ($ora_server_version->[0] >= 11) { + # rt91217 CHOOSE hint deprecated + $choose = ''; + } + my $char_length = $ora_server_version->[0] < 9 ? 'DATA_LENGTH':'CHAR_LENGTH'; + my $SQL = <<"SQL"; SELECT * FROM ( - SELECT /*+ CHOOSE */ + SELECT $choose to_char( NULL ) TABLE_CAT , tc.OWNER TABLE_SCHEM , tc.TABLE_NAME TABLE_NAME @@ -738,14 +741,14 @@ SELECT * ) WHERE 1 = 1 SQL - my @BindVals = (); - while ( my ( $k, $v ) = each %$attr ) { - if ( $v ) { - $SQL .= " AND $k LIKE ? ESCAPE '\\'\n"; - push @BindVals, $v; - } - } - $SQL .= " ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION\n"; + my @BindVals = (); + while ( my ( $k, $v ) = each %$attr ) { + if ( $v ) { + $SQL .= " AND $k LIKE ? ESCAPE '\\'\n"; + push @BindVals, $v; + } + } + $SQL .= " ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION\n"; # Since DATA_DEFAULT is a LONG, DEFAULT values longer than 80 chars will @@ -778,8 +781,8 @@ SQL return undef if not $sth; - $sth->execute( @BindVals ) or return undef; - $sth; + $sth->execute( @BindVals ) or return undef; + $sth; } sub statistics_info { @@ -788,11 +791,17 @@ SQL ($schema, $table) = @$catalog{'TABLE_SCHEM','TABLE_NAME'}; $catalog = undef; } - my $SQL = <<'SQL'; + my $choose = '/*+ CHOOSE */'; + my $ora_server_version = ora_server_version($dbh); + if ($ora_server_version->[0] >= 11) { + # rt91217 CHOOSE hint deprecated + $choose = ''; + } + my $SQL = <<"SQL"; SELECT * FROM ( - SELECT /*+ CHOOSE */ + SELECT $choose NULL TABLE_CAT , t.OWNER TABLE_SCHEM , t.TABLE_NAME TABLE_NAME @@ -1625,7 +1634,7 @@ to sleep between retries simple add a sleep to your callback sub. The ora_session_mode attribute can be used to connect with SYSDBA, SYSOPER, ORA_SYSASM, ORA_SYSBACKUP, ORA_SYSKM and ORA_SYSDG authorization. -The ORA_SYSDBA, ORA_SYSOPER, ORA_SYSASM, ORA_SYSBACKUP, ORA_SYSKM +The ORA_SYSDBA, ORA_SYSOPER, ORA_SYSASM, ORA_SYSBACKUP, ORA_SYSKM and ORA_SYSDG constants can be imported using use DBD::Oracle qw(:ora_session_modes); From de8eb699859d8d915a5f17e0ef6aa33a71cdfc1b Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 7 Mar 2014 15:26:20 -0500 Subject: [PATCH 459/637] changelog --- Changes | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changes b/Changes index 5b30bca8..0fed6030 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,9 @@ Revision history for DBD::Oracle +{{$NEXT}} + - CHOOSE hint is deprecated. (RT91217, reported by Andy Bucksch, + fix by Martin J Evans) + 1.70 2014-02-12 - promote 1.69_02 to stable. From 0ef5493edfda38ffe9989c5dac3ec70e7dba51f8 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 7 Mar 2014 15:36:52 -0500 Subject: [PATCH 460/637] recognizes __CYGWIN64__ --- Changes | 1 + Oracle.xs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 0fed6030..d0012219 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,7 @@ Revision history for DBD::Oracle {{$NEXT}} + - Recognizes __CYGWIN64__. (RT88709, reported by Witold Petriczek) - CHOOSE hint is deprecated. (RT91217, reported by Andy Bucksch, fix by Martin J Evans) diff --git a/Oracle.xs b/Oracle.xs index 926ae202..3e8b5a18 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -104,7 +104,7 @@ ora_env_var(name) sv_setpv(sv, p); ST(0) = sv; -#ifdef __CYGWIN32__ +#if defined(__CYGWIN32__) || defined(__CYGWIN64__) void ora_cygwin_set_env(name, value) char * name From 957f54750ba8c1972beabd1dcd305bd6c47c4586 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Tue, 17 Dec 2013 17:01:41 +0000 Subject: [PATCH 461/637] possible fix for rt 88185 - UTF-8 flag incorrect with multiple connections This is a rather hairy change as charsetid and ncharsetid were global and used all over the place. NOTE, you cannot actually build this because there is no VERSION in Oracle.pm because the repo is missing dist.ini and is probably using distzilla. To make it build I had to add $DBD::Oracle::VERSION = '1.63_00'; after require 5.006 in Oracle.pm It is also missing ABSTRACT --- dbdimp.c | 32 +++++++++++++++++--------------- dbdimp.h | 6 +++--- oci8.c | 27 ++++++++++++++++++--------- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 3f8ab82d..ed07eaed 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -44,8 +44,6 @@ int ora_ncs_buff_mtpl = 4; /* a mulitplyer for ncs clob buffers */ #define ARRAY_BIND_MIXED (ARRAY_BIND_NATIVE|ARRAY_BIND_UTF8) -ub2 charsetid = 0; -ub2 ncharsetid = 0; ub2 us7ascii_csid = 1; ub2 utf8_csid = 871; ub2 al32utf8_csid = 873; @@ -548,14 +546,14 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S { size_t rsize = 0; /* Get CLIENT char and nchar charset id values */ - OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &charsetid,(size_t) 0, OCI_NLS_CHARSET_ID, 0, &rsize ,status ); + OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &imp_dbh->charsetid,(size_t) 0, OCI_NLS_CHARSET_ID, 0, &rsize ,status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "OCINlsEnvironmentVariableGet(OCI_NLS_CHARSET_ID) Check NLS settings etc."); return 0; } - OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &ncharsetid,(size_t) 0, OCI_NLS_NCHARSET_ID, 0, &rsize ,status ); + OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &imp_dbh->ncharsetid,(size_t) 0, OCI_NLS_NCHARSET_ID, 0, &rsize ,status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "OCINlsEnvironmentVariableGet(OCI_NLS_NCHARSET_ID) Check NLS settings etc."); @@ -583,7 +581,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S }*/ OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, - charsetid, ncharsetid, status ); + imp_dbh->charsetid, imp_dbh->ncharsetid, status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, @@ -620,11 +618,11 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } if (new_charsetid || new_ncharsetid) { /* reset the ENV with the new charset from above*/ - if (new_charsetid) charsetid = new_charsetid; - if (new_ncharsetid) ncharsetid = new_ncharsetid; + if (new_charsetid) imp_dbh->charsetid = new_charsetid; + if (new_ncharsetid) imp_dbh->ncharsetid = new_ncharsetid; imp_dbh->envhp = NULL; OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, - charsetid, ncharsetid, status ); + imp_dbh->charsetid, imp_dbh->ncharsetid, status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc"); @@ -653,7 +651,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &charsetid, (ub4)0 , + OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &imp_dbh->charsetid, (ub4)0 , OCI_ATTR_ENV_CHARSET_ID, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { @@ -661,7 +659,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S return 0; } - OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &ncharsetid, (ub4)0 , + OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &imp_dbh->ncharsetid, (ub4)0 , OCI_ATTR_ENV_NCHARSET_ID, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { @@ -678,13 +676,13 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (DBIc_DBISTATE(imp_dbh)->debug >= 3 || dbd_verbose >= 3 ) { oratext charsetname[OCI_NLS_MAXBUFSZ]; oratext ncharsetname[OCI_NLS_MAXBUFSZ]; - OCINlsCharSetIdToName(imp_dbh->envhp,charsetname, sizeof(charsetname),charsetid ); - OCINlsCharSetIdToName(imp_dbh->envhp,ncharsetname, sizeof(ncharsetname),ncharsetid ); + OCINlsCharSetIdToName(imp_dbh->envhp,charsetname, sizeof(charsetname),imp_dbh->charsetid ); + OCINlsCharSetIdToName(imp_dbh->envhp,ncharsetname, sizeof(ncharsetname),imp_dbh->ncharsetid ); PerlIO_printf( DBIc_LOGPIO(imp_dbh), " charset id=%d, name=%s, ncharset id=%d, name=%s" " (csid: utf8=%d al32utf8=%d)\n", - charsetid,charsetname, ncharsetid,ncharsetname, utf8_csid, al32utf8_csid); + imp_dbh->charsetid,charsetname, imp_dbh->ncharsetid,ncharsetname, utf8_csid, al32utf8_csid); #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) PerlIO_printf(DBIc_LOGPIO(imp_dbh)," Using DRCP Connection\n "); @@ -1651,7 +1649,7 @@ int dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { dTHX; - /*D_imp_dbh_from_sth ;*/ + D_imp_dbh_from_sth; sword status; int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; @@ -2933,6 +2931,7 @@ static int dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { dTHX; + D_imp_dbh_from_sth; /*ub2 *alen_ptr = NULL;*/ sword status; int done = 0; @@ -3302,6 +3301,7 @@ void dbd_phs_sv_complete(imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug) { dTHX; + D_imp_dbh_from_sth; char *note = ""; /* XXX doesn't check arcode for error, caller is expected to */ @@ -3595,6 +3595,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat int parma_index; { dTHX; + D_imp_dbh_from_sth; sword status; ub1 csform; ub2 csid; @@ -4017,6 +4018,7 @@ int dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, SV *destrv, long destoffset) { dTHX; + D_imp_dbh_from_sth; ub4 retl = 0; SV *bufsv; imp_fbh_t *fbh = &imp_sth->fbh[field]; @@ -4026,7 +4028,7 @@ dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, sv_setpvn(bufsv,"",0); /* ensure it's writable string */ #ifdef UTF8_SUPPORT - if (ftype == 112 && CS_IS_UTF8(ncharsetid) ) { + if (ftype == 112 && CS_IS_UTF8(imp_dbh->ncharsetid) ) { return ora_blob_read_mb_piece(sth, imp_sth, fbh, bufsv, offset, len, destoffset); } diff --git a/dbdimp.h b/dbdimp.h index b7eb3705..e5371f76 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -74,6 +74,8 @@ struct imp_dbh_st { int max_nested_cursors; /* limit on cached nested cursors per stmt */ int array_chunk_size; /* the max size for an array bind */ ub4 server_version; /* version of Oracle server */ + ub2 charsetid; + ub2 ncharsetid; }; #define DBH_DUP_OFF sizeof(dbih_dbc_t) @@ -291,8 +293,6 @@ extern int dbd_verbose; extern int oci_warn; extern int ora_objects; extern int ora_ncs_buff_mtpl; -extern ub2 charsetid; -extern ub2 ncharsetid; extern ub2 us7ascii_csid; extern ub2 utf8_csid; extern ub2 al32utf8_csid; @@ -308,7 +308,7 @@ extern ub2 al16utf16_csid; #define CSFORM_IMPLIED_CSID(csform) \ - ((csform==SQLCS_NCHAR) ? ncharsetid : charsetid) + ((csform==SQLCS_NCHAR) ? imp_dbh->ncharsetid : imp_dbh->charsetid) #define CSFORM_IMPLIES_UTF8(csform) \ CS_IS_UTF8( CSFORM_IMPLIED_CSID( csform ) ) diff --git a/oci8.c b/oci8.c index 46a69e8e..74fe94d7 100644 --- a/oci8.c +++ b/oci8.c @@ -815,7 +815,7 @@ oci_fetch_options(ub4 fetchtype) static sb4 -oci_error_get(imp_xxh_t *imp_xxh, +oci_error_get(imp_sth_t *imp_sth, OCIError *errhp, sword status, char *what, SV *errstr, int debug) { dTHX; @@ -838,12 +838,12 @@ oci_error_get(imp_xxh_t *imp_xxh, } while( ++recno - && OCIErrorGet_log_stat(imp_xxh, errhp, recno, (text*)NULL, &eg_errcode, errbuf, + && OCIErrorGet_log_stat(imp_sth, errhp, recno, (text*)NULL, &eg_errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR, eg_status) != OCI_NO_DATA && eg_status != OCI_INVALID_HANDLE && recno < 100) { if (debug >= 4 || recno>1/*XXX temp*/) - PerlIO_printf(DBIc_LOGPIO(imp_xxh), + PerlIO_printf(DBIc_LOGPIO(imp_sth), " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", what ? what : "", (long)recno, (eg_status==OCI_SUCCESS) ? "ok" : oci_status_name(eg_status), @@ -870,16 +870,18 @@ oci_error_get(imp_xxh_t *imp_xxh, int -oci_error_err(SV *h, OCIError *errhp, sword status, char *what, sb4 force_err) +oci_error_err(SV *sth, OCIError *errhp, sword status, char *what, sb4 force_err) { dTHX; - D_imp_xxh(h); + D_imp_sth(sth); + D_imp_dbh_from_sth; + sb4 errcode; SV *errstr_sv = sv_newmortal(); SV *errcode_sv = sv_newmortal(); - errcode = oci_error_get(imp_xxh, errhp, status, what, errstr_sv, - DBIc_DBISTATE(imp_xxh)->debug); + errcode = oci_error_get(imp_sth, errhp, status, what, errstr_sv, + DBIc_DBISTATE(imp_sth)->debug); if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { #ifdef sv_utf8_decode sv_utf8_decode(errstr_sv); @@ -898,7 +900,7 @@ oci_error_err(SV *h, OCIError *errhp, sword status, char *what, sb4 force_err) errcode = (status != 0) ? status : -10000; sv_setiv(errcode_sv, errcode); - DBIh_SET_ERR_SV(h, imp_xxh, errcode_sv, errstr_sv, &PL_sv_undef, &PL_sv_undef); + DBIh_SET_ERR_SV(sth, (imp_xxh_t *)imp_sth, errcode_sv, errstr_sv, &PL_sv_undef, &PL_sv_undef); return 0; /* always returns 0 */ } @@ -1745,6 +1747,7 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, long offset, ub4 len, long destoffset) { dTHX; + D_imp_dbh_from_sth; ub4 loblen = 0; ub4 buflen; ub4 amtp = 0; @@ -1861,6 +1864,7 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, long offset, UV len, long destoffset) { dTHX; + D_imp_dbh_from_sth; ub4 loblen = 0; ub4 buflen; ub4 amtp = 0; @@ -1999,7 +2003,9 @@ static int fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *dest_sv, char *name) { dTHX; - ub4 loblen = 0; + D_imp_dbh_from_sth; + + ub4 loblen = 0; ub4 buflen = 0; ub4 amtp = 0; sword status; @@ -2722,6 +2728,7 @@ fetch_clbk_lob(SV *sth, imp_fbh_t *fbh,SV *dest_sv){ dTHX; D_imp_sth(sth); + D_imp_dbh_from_sth; fb_ary_t *fb_ary = fbh->fb_ary; ub4 actual_bufl=imp_sth->piece_size*(fb_ary->piece_count)+fb_ary->bufl; @@ -2765,6 +2772,7 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) { dTHX; D_imp_sth(sth); + D_imp_dbh_from_sth; fb_ary_t *fb_ary = fbh->fb_ary; ub4 buflen = fb_ary->bufl; ub4 actual_bufl = 0; @@ -4404,6 +4412,7 @@ static int init_lob_refetch(SV *sth, imp_sth_t *imp_sth) { dTHX; + D_imp_dbh_from_sth; SV *sv; SV *sql_select; HV *lob_cols_hv = NULL; From 84f356dd4984d35f2925213b7bd56afef11e3b61 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 7 Mar 2014 15:45:06 -0500 Subject: [PATCH 462/637] changelog --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index d0012219..4742fbfa 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,8 @@ Revision history for DBD::Oracle - Recognizes __CYGWIN64__. (RT88709, reported by Witold Petriczek) - CHOOSE hint is deprecated. (RT91217, reported by Andy Bucksch, fix by Martin J Evans) + - Set UTF8 flag per-connection. (RT88185, reported by Heinrich Mislik, patch by Martin + J. Evans) 1.70 2014-02-12 - promote 1.69_02 to stable. From 8d9350004e6964630b065411d2df085a454f6031 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 7 Mar 2014 15:58:15 -0500 Subject: [PATCH 463/637] steal from ETHER --- CONTRIBUTING.mkd | 112 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 CONTRIBUTING.mkd diff --git a/CONTRIBUTING.mkd b/CONTRIBUTING.mkd new file mode 100644 index 00000000..910899be --- /dev/null +++ b/CONTRIBUTING.mkd @@ -0,0 +1,112 @@ +# CONTRIBUTING + +Thank you for considering contributing to this distribution. This file +contains instructions that will help you work with the source code. + +The distribution is managed with Dist::Zilla. {{ + if ($has_xs = glob('*.xs')) { <<'HAS_XS' +However, you can still compile +and test the code with a small Makefile.PL specifically for use in the +repository. You can do: + + perl Makefile.PL + make + make test + +As well as: + + $ prove -lv t/some_test_file.t +HAS_XS +} else { <<'NO_XS' +This means than many of the +usual files you might expect are not in the repository, but are generated +at release time (e.g. Makefile.PL). + +However, you can run tests directly using the 'prove' tool: + + $ prove -l + $ prove -lv t/some_test_file.t + $ prove -lvr t/ + +In most cases, 'prove' is entirely sufficent for you to test any +patches you have. +NO_XS +} }} +You may need to satisfy some dependencies. The easiest way to satisfy +dependencies is to install the last release -- this is available at +https://metacpan.org/release/{{ $dist->name }}. + +If you use cpanminus, you can do it without downloading the tarball first: + + $ cpanm --reinstall --installdeps --with-recommends {{ $dist->name =~ +s/-/::/gr }} + +Dist::Zilla is a very powerful authoring tool, but requires a number of +author-specific plugins. If you would like to use it for contributing, +install it from CPAN, then run one of the following commands, depending on +your CPAN client: + + $ cpan `dzil authordeps --missing` + $ dzil authordeps --missing | cpanm + +You should then also install any additional requirements not needed by the +dzil build but may be needed by tests or other development: + + # cpan `dzil listdeps --author --missing` + $ dzil listdeps --author --missing | cpanm + +You can also do this via cpanm directly: + + $ cpanm --reinstall --installdeps --with-develop --with-recommends {{ +$dist->name =~ s/-/::/gr }} + +Once installed, here are some dzil commands you might try: + + $ dzil build + $ dzil test + $ dzil test --release + $ dzil xtest + $ dzil listdeps --json + $ dzil build --notgz + +You can learn more about Dist::Zilla at http://dzil.org/. +{{ +if ((my $link = $dist->distmeta->{resources}{repository}{web}) =~ /github/) { +"\n" . 'The code for this distribution is hosted at GitHub. The repository is: +' . $link . ' +You can submit code changes by forking the repository, pushing your code +changes to your clone, and then submitting a pull request. Detailed +instructions for doing that is available here: + +https://help.github.com/ +https://help.github.com/articles/creating-a-pull-request' } +}} + +If you have found a bug, but do not have an accompanying patch to fix it, you +can submit an issue report here: +{{ $dist->distmeta->{resources}{bugtracker}{web} // 'WARNING: bugtracker data +not set!' }} +or via {{ $dist->distmeta->{resources}{bugtracker}{mailto} // 'WARNING: +bugtracker data not set!' }}. +{{ +my $extra = $dist->distmeta->{resources}{x_MailingList} + ? "\n" . 'There is also a mailing list available for users of this +distribution, at' . "\n" . $dist->distmeta->{resources}{x_MailingList} . '.' + : ''; +$extra .= $dist->distmeta->{resources}{x_IRC} + ? "\n" . 'There is also an irc channel available for users of this +distribution, at' . "\n" . $dist->distmeta->{resources}{x_IRC} . '.' + : ''; +# send questions to the bugtracker if nowhere better +$extra ||= 'This is a good place to send your questions about the usage of +this distribution.'; +}} + + +This file was generated via {{ ref($plugin) . ' ' . ($plugin->VERSION || +'') }} from a +template file originating in {{ + my $module = $plugin->dist =~ s/-/::/gr; + eval "require $module"; + $plugin->dist . '-' . $module->VERSION +}}. From c0843bc6f7650b376aa43f286e39245bfce310b3 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 14 Mar 2014 10:55:26 -0400 Subject: [PATCH 464/637] CONTRIBUTING is a template github-flavored markdown fine-tune CONTRIBUTING.mkd --- CONTRIBUTING.mkd | 151 +++++++++++++++++++++++------------------------ MANIFEST | 1 + dist.ini | 3 + 3 files changed, 79 insertions(+), 76 deletions(-) diff --git a/CONTRIBUTING.mkd b/CONTRIBUTING.mkd index 910899be..56885345 100644 --- a/CONTRIBUTING.mkd +++ b/CONTRIBUTING.mkd @@ -1,112 +1,111 @@ # CONTRIBUTING -Thank you for considering contributing to this distribution. This file -contains instructions that will help you work with the source code. +Thank you for considering contributing to {{ $dist }}. +This file contains instructions that will help you work with +the source code. -The distribution is managed with Dist::Zilla. {{ - if ($has_xs = glob('*.xs')) { <<'HAS_XS' -However, you can still compile -and test the code with a small Makefile.PL specifically for use in the -repository. You can do: +## Repository branches structure - perl Makefile.PL - make - make test +The two main branches of this repository are: -As well as: +* **master** - $ prove -lv t/some_test_file.t -HAS_XS -} else { <<'NO_XS' -This means than many of the -usual files you might expect are not in the repository, but are generated -at release time (e.g. Makefile.PL). +The main development branch. This branch has to +be processed by Dist::Zilla to generate the +code as it will appear in the CPAN distribution. See the +next section for more details. + +* **releases** + +Contains the code as it appears on CPAN. Each official +release is also tagged with its version. + +## Working on the master branch + +The distribution is managed with [Dist::Zilla][distzilla]. +This means than many of the usual files you might expect +are not in the repository, but are generated at release time. However, you can run tests directly using the 'prove' tool: - $ prove -l - $ prove -lv t/some_test_file.t - $ prove -lvr t/ +``` bash +$ prove -l +$ prove -lv t/some_test_file.t +$ prove -lvr t/ +``` In most cases, 'prove' is entirely sufficent for you to test any patches you have. -NO_XS -} }} + You may need to satisfy some dependencies. The easiest way to satisfy dependencies is to install the last release -- this is available at -https://metacpan.org/release/{{ $dist->name }}. +https://metacpan.org/release/{{ $dist }}. If you use cpanminus, you can do it without downloading the tarball first: - $ cpanm --reinstall --installdeps --with-recommends {{ $dist->name =~ -s/-/::/gr }} +``` bash +$ cpanm --reinstall --installdeps --with-recommends {{ $dist =~ s/-/::/gr }} +``` Dist::Zilla is a very powerful authoring tool, but requires a number of author-specific plugins. If you would like to use it for contributing, install it from CPAN, then run one of the following commands, depending on your CPAN client: - $ cpan `dzil authordeps --missing` - $ dzil authordeps --missing | cpanm +``` bash +$ cpan `dzil authordeps --missing` +$ dzil authordeps --missing | cpanm +``` You should then also install any additional requirements not needed by the dzil build but may be needed by tests or other development: - # cpan `dzil listdeps --author --missing` - $ dzil listdeps --author --missing | cpanm +``` bash +# cpan `dzil listdeps --author --missing` +$ dzil listdeps --author --missing | cpanm +``` You can also do this via cpanm directly: - $ cpanm --reinstall --installdeps --with-develop --with-recommends {{ -$dist->name =~ s/-/::/gr }} +``` bash +$ cpanm --reinstall --installdeps --with-develop --with-recommends {{ $dist =~ s/-/::/gr }} +``` Once installed, here are some dzil commands you might try: - $ dzil build - $ dzil test - $ dzil test --release - $ dzil xtest - $ dzil listdeps --json - $ dzil build --notgz - -You can learn more about Dist::Zilla at http://dzil.org/. -{{ -if ((my $link = $dist->distmeta->{resources}{repository}{web}) =~ /github/) { -"\n" . 'The code for this distribution is hosted at GitHub. The repository is: -' . $link . ' -You can submit code changes by forking the repository, pushing your code +``` bash +$ dzil build +$ dzil test +$ dzil test --release +$ dzil xtest +$ dzil listdeps --json +$ dzil build --notgz +``` + + +## This Is Complicated. Is There an Easier Way? + +Actually, yes there is. You can also work directly on the `releases` branch, +which corresponds to the code is generated by Dist::Zilla and +correspond to what is uploaded to CPAN. + +It won't contain any of the changes brought to the codebase since the last +CPAN release, but for a small patch that shouldn't be a problem. + +## Sending Patches + +The code for this distribution is hosted on [GitHub][repository]. + +You can submit bug reports via the [repository's issue track][bugtracker]. + +You can also submit code changes by forking the repository, pushing your code changes to your clone, and then submitting a pull request. Detailed instructions for doing that is available here: -https://help.github.com/ -https://help.github.com/articles/creating-a-pull-request' } -}} - -If you have found a bug, but do not have an accompanying patch to fix it, you -can submit an issue report here: -{{ $dist->distmeta->{resources}{bugtracker}{web} // 'WARNING: bugtracker data -not set!' }} -or via {{ $dist->distmeta->{resources}{bugtracker}{mailto} // 'WARNING: -bugtracker data not set!' }}. -{{ -my $extra = $dist->distmeta->{resources}{x_MailingList} - ? "\n" . 'There is also a mailing list available for users of this -distribution, at' . "\n" . $dist->distmeta->{resources}{x_MailingList} . '.' - : ''; -$extra .= $dist->distmeta->{resources}{x_IRC} - ? "\n" . 'There is also an irc channel available for users of this -distribution, at' . "\n" . $dist->distmeta->{resources}{x_IRC} . '.' - : ''; -# send questions to the bugtracker if nowhere better -$extra ||= 'This is a good place to send your questions about the usage of -this distribution.'; -}} - - -This file was generated via {{ ref($plugin) . ' ' . ($plugin->VERSION || -'') }} from a -template file originating in {{ - my $module = $plugin->dist =~ s/-/::/gr; - eval "require $module"; - $plugin->dist . '-' . $module->VERSION -}}. +* https://help.github.com/ +* https://help.github.com/articles/creating-a-pull-request + +[distzilla]: http://dzil.org/. +[repository]: https://github.com/pythian/DBD-Oracle/ +[bugtracker]: https://github.com/pythian/DBD-Oracle/issues + diff --git a/MANIFEST b/MANIFEST index 91ff3a7c..d3ba56c9 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,3 +1,4 @@ +CONTRIBUTING.mkd CONTRIBUTORS Changes INSTALL diff --git a/dist.ini b/dist.ini index 7301468c..d3be2f5b 100644 --- a/dist.ini +++ b/dist.ini @@ -9,6 +9,9 @@ copyright_year = 1994 version = 1.70 +[TemplateCJM] +file = CONTRIBUTING.mkd + [Encoding] encoding = latin-1 match = META.json From ad992142de63c01ed48f63769bb01066d1fae046 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 14 Mar 2014 11:21:43 -0400 Subject: [PATCH 465/637] changelog --- Changes | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes b/Changes index 4742fbfa..d849d248 100644 --- a/Changes +++ b/Changes @@ -6,6 +6,7 @@ Revision history for DBD::Oracle fix by Martin J Evans) - Set UTF8 flag per-connection. (RT88185, reported by Heinrich Mislik, patch by Martin J. Evans) + - Add a CONTRIBUTING.mkd file. (GH#2) 1.70 2014-02-12 - promote 1.69_02 to stable. From a1202d584921579cd6bda39b2bd27ab178dbaf75 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 14 Mar 2014 11:40:52 -0400 Subject: [PATCH 466/637] add SELinux trick --- Changes | 1 + lib/DBD/Oracle/Troubleshooting/Linux.pod | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Changes b/Changes index d849d248..e853cbb7 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,7 @@ Revision history for DBD::Oracle - Set UTF8 flag per-connection. (RT88185, reported by Heinrich Mislik, patch by Martin J. Evans) - Add a CONTRIBUTING.mkd file. (GH#2) + - Add SELinux trick. (RT#87003, patch submitted by Mike Doherty) 1.70 2014-02-12 - promote 1.69_02 to stable. diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index c1323e2d..55ab1e5e 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -1,6 +1,23 @@ #PODNAME: DBD::Oracle::Troubleshooting::Linux #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on Linux +=head1 SELinux and httpd + +If SELinux is running, it can prevents DBD::Oracle running in +an Apache process to load shared libraries it requires (libclntsh.so +or libnnz12.so). A typical symptom is a line like the following in +the Apache error logs: + + [Tue Apr 17 13:22:45 2012] [error] Can't load '.../DBD/Oracle/Oracle.so' for + module DBD::Oracle: libnnz11.so: cannot enable executable stack as shared + object requires: Permission denied at .../DynaLoader.pm line 190.\n at + .../startup.pl line 17\nCompilation failed in require at ... + +The fix: + + /usr/sbin/setsebool -P httpd_execmem + + =head1 Installing with Instantclient .rpm files. Nothing special with this you just have to set up you permissions as follows; From 3af37ce46fc58da0ca6939d6a6c17c693f8cb5a9 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 31 Mar 2014 11:35:20 -0400 Subject: [PATCH 467/637] preps for release --- .mailmap | 1 + dist.ini | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.mailmap b/.mailmap index 878ec419..5bf525fd 100644 --- a/.mailmap +++ b/.mailmap @@ -1,5 +1,6 @@ Yanick Champoux Yanick Champoux +Yanick Champoux Tim Bunce Tim Bunce Martin J. Evans diff --git a/dist.ini b/dist.ini index d3be2f5b..dc389ec4 100644 --- a/dist.ini +++ b/dist.ini @@ -7,15 +7,11 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.70 +version = 1.71_00 [TemplateCJM] file = CONTRIBUTING.mkd -[Encoding] -encoding = latin-1 -match = META.json - [Authority] authority=cpan:PYTHIAN From e2fc06b741a0ade82e8f9a06f7b67b00503ba859 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 14 Apr 2014 15:27:33 -0400 Subject: [PATCH 468/637] release prep --- Changes | 3 +++ dist.ini | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index e853cbb7..7f20229e 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for DBD::Oracle {{$NEXT}} + - promote 1.71_00 to stable. + +1.71_00 2014-03-31 - Recognizes __CYGWIN64__. (RT88709, reported by Witold Petriczek) - CHOOSE hint is deprecated. (RT91217, reported by Andy Bucksch, fix by Martin J Evans) diff --git a/dist.ini b/dist.ini index dc389ec4..490357ef 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.71_00 +version = 1.72 [TemplateCJM] file = CONTRIBUTING.mkd @@ -21,11 +21,9 @@ authority=cpan:PYTHIAN -bundle=@YANICK -remove=NextVersion::Semantic -remove=ChangeStats::Git --remove=Author::YANICK::NextSemanticVersion -remove=ModuleBuild -remove=Authority -remove=Signature --remove=UploadToCPAN -remove=Twitter -remove=Test::Compile -remove=Covenant @@ -34,7 +32,6 @@ authority=cpan:PYTHIAN [Prereqs / ConfigureRequires] DBI = 1.51 -[FakeRelease] [HelpWanted] positions = coder documentation tester From 1ef5f5e9aba4b9014ae3e9bbfec23edff082ecea Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 23 Apr 2014 10:00:52 -0400 Subject: [PATCH 469/637] Revert "possible fix for rt 88185 - UTF-8 flag incorrect with multiple connections" This reverts commit 957f54750ba8c1972beabd1dcd305bd6c47c4586. --- dbdimp.c | 32 +++++++++++++++----------------- dbdimp.h | 6 +++--- oci8.c | 27 +++++++++------------------ 3 files changed, 27 insertions(+), 38 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index ed07eaed..3f8ab82d 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -44,6 +44,8 @@ int ora_ncs_buff_mtpl = 4; /* a mulitplyer for ncs clob buffers */ #define ARRAY_BIND_MIXED (ARRAY_BIND_NATIVE|ARRAY_BIND_UTF8) +ub2 charsetid = 0; +ub2 ncharsetid = 0; ub2 us7ascii_csid = 1; ub2 utf8_csid = 871; ub2 al32utf8_csid = 873; @@ -546,14 +548,14 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S { size_t rsize = 0; /* Get CLIENT char and nchar charset id values */ - OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &imp_dbh->charsetid,(size_t) 0, OCI_NLS_CHARSET_ID, 0, &rsize ,status ); + OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &charsetid,(size_t) 0, OCI_NLS_CHARSET_ID, 0, &rsize ,status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "OCINlsEnvironmentVariableGet(OCI_NLS_CHARSET_ID) Check NLS settings etc."); return 0; } - OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &imp_dbh->ncharsetid,(size_t) 0, OCI_NLS_NCHARSET_ID, 0, &rsize ,status ); + OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &ncharsetid,(size_t) 0, OCI_NLS_NCHARSET_ID, 0, &rsize ,status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "OCINlsEnvironmentVariableGet(OCI_NLS_NCHARSET_ID) Check NLS settings etc."); @@ -581,7 +583,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S }*/ OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, - imp_dbh->charsetid, imp_dbh->ncharsetid, status ); + charsetid, ncharsetid, status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, @@ -618,11 +620,11 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } if (new_charsetid || new_ncharsetid) { /* reset the ENV with the new charset from above*/ - if (new_charsetid) imp_dbh->charsetid = new_charsetid; - if (new_ncharsetid) imp_dbh->ncharsetid = new_ncharsetid; + if (new_charsetid) charsetid = new_charsetid; + if (new_ncharsetid) ncharsetid = new_ncharsetid; imp_dbh->envhp = NULL; OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, - imp_dbh->charsetid, imp_dbh->ncharsetid, status ); + charsetid, ncharsetid, status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, "OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc"); @@ -651,7 +653,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &imp_dbh->charsetid, (ub4)0 , + OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &charsetid, (ub4)0 , OCI_ATTR_ENV_CHARSET_ID, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { @@ -659,7 +661,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S return 0; } - OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &imp_dbh->ncharsetid, (ub4)0 , + OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &ncharsetid, (ub4)0 , OCI_ATTR_ENV_NCHARSET_ID, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { @@ -676,13 +678,13 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (DBIc_DBISTATE(imp_dbh)->debug >= 3 || dbd_verbose >= 3 ) { oratext charsetname[OCI_NLS_MAXBUFSZ]; oratext ncharsetname[OCI_NLS_MAXBUFSZ]; - OCINlsCharSetIdToName(imp_dbh->envhp,charsetname, sizeof(charsetname),imp_dbh->charsetid ); - OCINlsCharSetIdToName(imp_dbh->envhp,ncharsetname, sizeof(ncharsetname),imp_dbh->ncharsetid ); + OCINlsCharSetIdToName(imp_dbh->envhp,charsetname, sizeof(charsetname),charsetid ); + OCINlsCharSetIdToName(imp_dbh->envhp,ncharsetname, sizeof(ncharsetname),ncharsetid ); PerlIO_printf( DBIc_LOGPIO(imp_dbh), " charset id=%d, name=%s, ncharset id=%d, name=%s" " (csid: utf8=%d al32utf8=%d)\n", - imp_dbh->charsetid,charsetname, imp_dbh->ncharsetid,ncharsetname, utf8_csid, al32utf8_csid); + charsetid,charsetname, ncharsetid,ncharsetname, utf8_csid, al32utf8_csid); #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) PerlIO_printf(DBIc_LOGPIO(imp_dbh)," Using DRCP Connection\n "); @@ -1649,7 +1651,7 @@ int dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { dTHX; - D_imp_dbh_from_sth; + /*D_imp_dbh_from_sth ;*/ sword status; int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; @@ -2931,7 +2933,6 @@ static int dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { dTHX; - D_imp_dbh_from_sth; /*ub2 *alen_ptr = NULL;*/ sword status; int done = 0; @@ -3301,7 +3302,6 @@ void dbd_phs_sv_complete(imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug) { dTHX; - D_imp_dbh_from_sth; char *note = ""; /* XXX doesn't check arcode for error, caller is expected to */ @@ -3595,7 +3595,6 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat int parma_index; { dTHX; - D_imp_dbh_from_sth; sword status; ub1 csform; ub2 csid; @@ -4018,7 +4017,6 @@ int dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, SV *destrv, long destoffset) { dTHX; - D_imp_dbh_from_sth; ub4 retl = 0; SV *bufsv; imp_fbh_t *fbh = &imp_sth->fbh[field]; @@ -4028,7 +4026,7 @@ dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, sv_setpvn(bufsv,"",0); /* ensure it's writable string */ #ifdef UTF8_SUPPORT - if (ftype == 112 && CS_IS_UTF8(imp_dbh->ncharsetid) ) { + if (ftype == 112 && CS_IS_UTF8(ncharsetid) ) { return ora_blob_read_mb_piece(sth, imp_sth, fbh, bufsv, offset, len, destoffset); } diff --git a/dbdimp.h b/dbdimp.h index e5371f76..b7eb3705 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -74,8 +74,6 @@ struct imp_dbh_st { int max_nested_cursors; /* limit on cached nested cursors per stmt */ int array_chunk_size; /* the max size for an array bind */ ub4 server_version; /* version of Oracle server */ - ub2 charsetid; - ub2 ncharsetid; }; #define DBH_DUP_OFF sizeof(dbih_dbc_t) @@ -293,6 +291,8 @@ extern int dbd_verbose; extern int oci_warn; extern int ora_objects; extern int ora_ncs_buff_mtpl; +extern ub2 charsetid; +extern ub2 ncharsetid; extern ub2 us7ascii_csid; extern ub2 utf8_csid; extern ub2 al32utf8_csid; @@ -308,7 +308,7 @@ extern ub2 al16utf16_csid; #define CSFORM_IMPLIED_CSID(csform) \ - ((csform==SQLCS_NCHAR) ? imp_dbh->ncharsetid : imp_dbh->charsetid) + ((csform==SQLCS_NCHAR) ? ncharsetid : charsetid) #define CSFORM_IMPLIES_UTF8(csform) \ CS_IS_UTF8( CSFORM_IMPLIED_CSID( csform ) ) diff --git a/oci8.c b/oci8.c index 74fe94d7..46a69e8e 100644 --- a/oci8.c +++ b/oci8.c @@ -815,7 +815,7 @@ oci_fetch_options(ub4 fetchtype) static sb4 -oci_error_get(imp_sth_t *imp_sth, +oci_error_get(imp_xxh_t *imp_xxh, OCIError *errhp, sword status, char *what, SV *errstr, int debug) { dTHX; @@ -838,12 +838,12 @@ oci_error_get(imp_sth_t *imp_sth, } while( ++recno - && OCIErrorGet_log_stat(imp_sth, errhp, recno, (text*)NULL, &eg_errcode, errbuf, + && OCIErrorGet_log_stat(imp_xxh, errhp, recno, (text*)NULL, &eg_errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR, eg_status) != OCI_NO_DATA && eg_status != OCI_INVALID_HANDLE && recno < 100) { if (debug >= 4 || recno>1/*XXX temp*/) - PerlIO_printf(DBIc_LOGPIO(imp_sth), + PerlIO_printf(DBIc_LOGPIO(imp_xxh), " OCIErrorGet after %s (er%ld:%s): %d, %ld: %s\n", what ? what : "", (long)recno, (eg_status==OCI_SUCCESS) ? "ok" : oci_status_name(eg_status), @@ -870,18 +870,16 @@ oci_error_get(imp_sth_t *imp_sth, int -oci_error_err(SV *sth, OCIError *errhp, sword status, char *what, sb4 force_err) +oci_error_err(SV *h, OCIError *errhp, sword status, char *what, sb4 force_err) { dTHX; - D_imp_sth(sth); - D_imp_dbh_from_sth; - + D_imp_xxh(h); sb4 errcode; SV *errstr_sv = sv_newmortal(); SV *errcode_sv = sv_newmortal(); - errcode = oci_error_get(imp_sth, errhp, status, what, errstr_sv, - DBIc_DBISTATE(imp_sth)->debug); + errcode = oci_error_get(imp_xxh, errhp, status, what, errstr_sv, + DBIc_DBISTATE(imp_xxh)->debug); if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { #ifdef sv_utf8_decode sv_utf8_decode(errstr_sv); @@ -900,7 +898,7 @@ oci_error_err(SV *sth, OCIError *errhp, sword status, char *what, sb4 force_err) errcode = (status != 0) ? status : -10000; sv_setiv(errcode_sv, errcode); - DBIh_SET_ERR_SV(sth, (imp_xxh_t *)imp_sth, errcode_sv, errstr_sv, &PL_sv_undef, &PL_sv_undef); + DBIh_SET_ERR_SV(h, imp_xxh, errcode_sv, errstr_sv, &PL_sv_undef, &PL_sv_undef); return 0; /* always returns 0 */ } @@ -1747,7 +1745,6 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, long offset, ub4 len, long destoffset) { dTHX; - D_imp_dbh_from_sth; ub4 loblen = 0; ub4 buflen; ub4 amtp = 0; @@ -1864,7 +1861,6 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, long offset, UV len, long destoffset) { dTHX; - D_imp_dbh_from_sth; ub4 loblen = 0; ub4 buflen; ub4 amtp = 0; @@ -2003,9 +1999,7 @@ static int fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *dest_sv, char *name) { dTHX; - D_imp_dbh_from_sth; - - ub4 loblen = 0; + ub4 loblen = 0; ub4 buflen = 0; ub4 amtp = 0; sword status; @@ -2728,7 +2722,6 @@ fetch_clbk_lob(SV *sth, imp_fbh_t *fbh,SV *dest_sv){ dTHX; D_imp_sth(sth); - D_imp_dbh_from_sth; fb_ary_t *fb_ary = fbh->fb_ary; ub4 actual_bufl=imp_sth->piece_size*(fb_ary->piece_count)+fb_ary->bufl; @@ -2772,7 +2765,6 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) { dTHX; D_imp_sth(sth); - D_imp_dbh_from_sth; fb_ary_t *fb_ary = fbh->fb_ary; ub4 buflen = fb_ary->bufl; ub4 actual_bufl = 0; @@ -4412,7 +4404,6 @@ static int init_lob_refetch(SV *sth, imp_sth_t *imp_sth) { dTHX; - D_imp_dbh_from_sth; SV *sv; SV *sql_select; HV *lob_cols_hv = NULL; From 0ced09bc009975965cdf5e7257fc82e0979bf529 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 23 Apr 2014 10:03:18 -0400 Subject: [PATCH 470/637] changelog --- Changes | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changes b/Changes index 7f20229e..0604b063 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for DBD::Oracle {{$NEXT}} + - Reverts current fix for RT-88185, as it causes breakage. (GH#14) + +1.72 2014-04-14 - promote 1.71_00 to stable. 1.71_00 2014-03-31 From 17c04bed22abbe0d33297eb57a1e5b9fabc6dfca Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 23 Apr 2014 10:03:56 -0400 Subject: [PATCH 471/637] release preps --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 490357ef..989f6dbf 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.72 +version = 1.73_00 [TemplateCJM] file = CONTRIBUTING.mkd From 23c248d1496721861134422e3b74408df6a6eeb9 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 23 Apr 2014 10:03:56 -0400 Subject: [PATCH 472/637] Bring in mje's fix for #14 --- Changes | 3 +++ dbdimp.c | 1 + dist.ini | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 0604b063..2c3c739c 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for DBD::Oracle {{$NEXT}} + - Tweak fix for RT-88185. (GH#14, Martin J. Evans) + +1.73_00 2014-04-23 - Reverts current fix for RT-88185, as it causes breakage. (GH#14) 1.72 2014-04-14 diff --git a/dbdimp.c b/dbdimp.c index 3f8ab82d..a94cbe51 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -4346,6 +4346,7 @@ dbd_st_FETCH_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv) if (kl==4 && strEQ(key, "NAME")) { AV *av = newAV(); SV *x; + D_imp_dbh_from_sth; retsv = newRV(sv_2mortal((SV*)av)); while(--i >= 0) { diff --git a/dist.ini b/dist.ini index 989f6dbf..a954fbf4 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.73_00 +version = 1.73_01 [TemplateCJM] file = CONTRIBUTING.mkd From cb011d20944a969d80278dadedcc3c624598b63a Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 24 Apr 2014 20:57:47 -0400 Subject: [PATCH 473/637] promoting to 1.74 --- Changes | 3 +++ dist.ini | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 2c3c739c..eb1a38a7 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for DBD::Oracle {{$NEXT}} + - Promote to stable. + +1.73_01 2014-04-23 - Tweak fix for RT-88185. (GH#14, Martin J. Evans) 1.73_00 2014-04-23 diff --git a/dist.ini b/dist.ini index a954fbf4..c167187c 100644 --- a/dist.ini +++ b/dist.ini @@ -7,7 +7,7 @@ license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 -version = 1.73_01 +version = 1.74 [TemplateCJM] file = CONTRIBUTING.mkd From 5ac5ac01aaadf4aea766a75eb0082674fee18cca Mon Sep 17 00:00:00 2001 From: "H.Merijn Brand - Tux" Date: Tue, 15 Apr 2014 14:15:58 +0200 Subject: [PATCH 474/637] Allow symbolic links in $LD_LIBRARY_PATH et all --- Makefile.PL | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index d4eb5ae4..fae7724a 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -32,10 +32,8 @@ BEGIN { use VMS::Filespec; 1; } or die $@; - } - my $dbi_arch_dir = dbd_dbi_arch_dir(); my $so = $Config{so}; # typically 'so', 'dylib' on Darwin/OSX my $osvers = $Config{osvers}; $osvers =~ s/^\s*(\d+\.\d+).*/$1/; # drop sub-sub-version: 2.5.1 -> 2.5 @@ -1968,6 +1966,10 @@ sub check_ldlibpthname { return 1 if grep { s:[\\/]$::; $_ eq $libdir } @dirs; + # It is also ok if we are using symbolic links + return 1 if grep { s:[\\/]$::; $_ eq $libdir } + map { Cwd::abs_path ($_) } @dirs; + # on solaris, it can be under LD_LIBRARY_PATH_(32|64) if ( $^O eq 'solaris' ) { my $ld_library_path_name = 'LD_LIBRARY_PATH_' @@ -1980,7 +1982,7 @@ sub check_ldlibpthname { s#[\\/]$## for @dirs; # cut potential final / or \ - return if grep { $_ eq $libdir } @dirs; + return 1 if grep { $_ eq $libdir } @dirs; } warn "WARNING: Your $warn_name env var doesn't include '$libdir' but probably needs to.\n"; From 7810c1146b099717b2408f79418c7dfd35f2506b Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 24 Apr 2014 21:36:23 -0400 Subject: [PATCH 475/637] merge checks --- Makefile.PL | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index fae7724a..15303c38 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1964,11 +1964,9 @@ sub check_ldlibpthname { my $warn_name = $ldlibpthname; - return 1 if grep { s:[\\/]$::; $_ eq $libdir } @dirs; - # It is also ok if we are using symbolic links - return 1 if grep { s:[\\/]$::; $_ eq $libdir } - map { Cwd::abs_path ($_) } @dirs; + return 1 if grep { s:[\\/]$::; $_ eq $libdir } + map { $_, Cwd::abs_path($_) } @dirs; # on solaris, it can be under LD_LIBRARY_PATH_(32|64) if ( $^O eq 'solaris' ) { From 3078313db4f744fabd0270d3e6add10190f27cad Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 26 May 2014 14:10:48 -0400 Subject: [PATCH 476/637] typo in docs --- lib/DBD/Oracle/Troubleshooting.pod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index 477df9d8..beecf304 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -113,7 +113,7 @@ forking). It looks like this was fixed in 0.012 of Module::Runtime. -=head2 bin_param_inout swapping return values +=head2 bind_param_inout swapping return values See RT 71819 (https://rt.cpan.org/Ticket/Display.html?id=71819) From a699ecb1d9c36e80b07a8af17cf993ca040eb51f Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 26 May 2014 15:59:38 -0400 Subject: [PATCH 477/637] cleanup --- t/30long.t | 162 +++++++++++++++++++++++++---------------------------- 1 file changed, 76 insertions(+), 86 deletions(-) diff --git a/t/30long.t b/t/30long.t index 1ad52565..99d70fd1 100644 --- a/t/30long.t +++ b/t/30long.t @@ -1,29 +1,23 @@ -#!perl -w -# vim:ts=8:sw=4 +use strict; use DBI; use DBD::Oracle qw(:ora_types SQLCS_NCHAR SQLCS_IMPLICIT ORA_OCI); -use strict; use Test::More; -*BAILOUT = sub { die "@_\n" } unless defined &BAILOUT; - unshift @INC ,'t'; require 'nchar_test_lib.pl'; -my @test_sets; -push @test_sets, [ "LONG", 0, 0 ]; -push @test_sets, [ "LONG RAW", ORA_LONGRAW, 0 ]; +*BAILOUT = sub { die "@_\n" } unless defined &BAILOUT; + +my @test_sets = ( + [ "LONG", 0, 0 ], + [ "LONG RAW", ORA_LONGRAW, 0 ], + [ "CLOB", ORA_CLOB, 0 ], + [ "BLOB", ORA_BLOB, 0 ], +); push @test_sets, [ "NCLOB", ORA_CLOB, 0 ] unless ORA_OCI() < 9.0 or $ENV{DBD_ALL_TESTS}; -push @test_sets, [ "CLOB", ORA_CLOB, 0 ] ; -push @test_sets, [ "BLOB", ORA_BLOB, 0 ] ; -my $tests_per_set = 96; -my $tests = @test_sets * $tests_per_set-1; -#very odd little thing that took a while to figure out. -#Seems I now have 479 tests which is 9 more so 96 test then -1 to round it off -$| = 1; my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $table = table(); my $use_utf8_data; # set per test_set below @@ -40,40 +34,34 @@ my $sz = 8; my($p1, $p2, $tmp, @tmp); -#my $dbh = db_handle(); +$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dbh = DBI->connect( oracle_test_dsn(), $dbuser, '', { + PrintError => 0, +}) or plan skip_all => "Unable to connect to Oracle"; - $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - my $dsn = oracle_test_dsn(); - my $dbh = DBI->connect($dsn, $dbuser, '',{ - PrintError => 0, - }); - -if ($dbh) { - plan tests => $tests; -} else { - plan skip_all => "Unable to connect to Oracle"; -} +plan tests => scalar @test_sets; +my $tests_per_set = 97; my $ora_server_version = $dbh->func("ora_server_version"); -note("ora_server_version: @$ora_server_version\n"); -show_db_charsets($dbh) if $dbh; + +show_db_charsets($dbh); foreach (@test_sets) { my ($type_name, $type_num, $test_no_type) = @$_; - $use_utf8_data = use_utf8_data($dbh,$type_name); - note( qq( - ========================================================================= - Running long test for $type_name ($type_num) use_utf8_data=$use_utf8_data -)); - run_long_tests($dbh, $type_name, $type_num); - run_long_tests($dbh, $type_name, 0) if $test_no_type; + subtest $type_name => sub { + plan tests => $tests_per_set; + $use_utf8_data = use_utf8_data($dbh,$type_name); + note( qq( + ========================================================================= + Running long test for $type_name ($type_num) use_utf8_data=$use_utf8_data + )); + run_long_tests($dbh, $type_name, $type_num); + run_long_tests($dbh, $type_name, 0) if $test_no_type; + } } -exit 0; - -# end. - +### END OF TESTS, ONLY FUNCTIONS BELOW ### END { drop_table( $dbh ) if not $ENV{DBD_SKIP_TABLE_DROP}; @@ -81,15 +69,16 @@ END { } -sub use_utf8_data -{ +sub use_utf8_data { my ( $dbh, $type_name ) = @_; - if ( ($type_name =~ m/^CLOB/i and db_ochar_is_utf($dbh) && client_ochar_is_utf8()) - or ($type_name =~ m/^NCLOB/i and db_nchar_is_utf($dbh) && client_nchar_is_utf8()) ) { - return 1 unless @skip_unicode; - warn "Skipping Unicode data tests: @skip_unicode\n" if !$warnings{use_utf8_data}++; - } - return 0; + + return 0 + unless ($type_name =~ m/^CLOB/i and db_ochar_is_utf($dbh) && client_ochar_is_utf8()) + or ($type_name =~ m/^NCLOB/i and db_nchar_is_utf($dbh) && client_nchar_is_utf8()); + + return 1 unless @skip_unicode; + + warn "Skipping Unicode data tests: @skip_unicode\n" if !$warnings{use_utf8_data}++; } sub run_long_tests @@ -129,32 +118,25 @@ sub run_long_tests # special hack for long_data[0] since RAW types need pairs of HEX $long_data[0] = "00FF" x (length($long_data[0]) / 2) if $type_name =~ /RAW/i; - my $len_data0 = length($long_data[0]); - my $len_data1 = length($long_data[1]); - my $len_data2 = length($long_data[2]); + my @len_data = map { length($_) } @long_data; # warn if some of the key aspects of the data sizing are tampered with - warn "long_data[0] is > 64KB: $len_data0\n" - if $len_data0 > 65535; - warn "long_data[1] is < 64KB: $len_data1\n" - if $len_data1 < 65535; - warn "long_data[2] is not smaller than $long_data[1] ($len_data2 > $len_data1)\n" - if $len_data2 >= $len_data1; + warn "long_data[0] is > 64KB: $len_data[0]\n" + if $len_data[0] > 65535; + warn "long_data[1] is < 64KB: $len_data[1]\n" + if $len_data[1] < 65535; + warn "long_data[2] is not smaller than $long_data[1] ($len_data[2] > $len_data[1])\n" + if $len_data[2] >= $len_data[1]; my $tdata = { cols => long_test_cols( $type_name ), rows => [] }; - skip "Unable to create test table for '$type_name' data ($DBI::err)." ,$tests_per_set if (!create_table($dbh, $tdata, 1)); # typically OCI 8 client talking to Oracle 7 database - note("long_data[0] length $len_data0\n"); - note("long_data[1] length $len_data1\n"); - note("long_data[2] length $len_data2\n"); - note(" --- insert some $type_name data (ora_type $type_num)\n"); my $sqlstr = "insert into $table values (?, ?, SYSDATE)" ; ok( $sth = $dbh->prepare( $sqlstr ), "prepare: $sqlstr" ); @@ -194,7 +176,7 @@ sub run_long_tests ." due to an Oracle bug and not a DBD::Oracle problem.\n" , 5 ; } cmp_ok(@$tmp ,'==' ,4 ,'four rows' ); - #print "tmp->[0][1] = " .$tmp->[0][1] ."\n" ; + for my $i (0..2) { my $v = $tmp->[$i][1]; cmp_ok_byte_nice($v, substr($long_data[$i],0,$out_len), "truncated to LongReadLen $out_len"); @@ -208,35 +190,37 @@ sub run_long_tests "$type_name UTF8 setting"); } } - # use Data::Dumper; print Dumper($tmp->[3]); ok(!defined $tmp->[3][1], "last row undefined"); # NULL # known bug in DBD::Oracle <= 1.13 } note(" --- fetch $type_name data back again -- truncated - LongTruncOk == 0\n"); - $dbh->{LongReadLen} = $len_data1 - 10; # so $long_data[0] fits but long_data[1] doesn't - $dbh->{LongReadLen} = $dbh->{LongReadLen} / 2 if $type_name =~ /RAW/i; - my $LongReadLen = $dbh->{LongReadLen}; + + $dbh->{LongReadLen} = $len_data[1] - 10; # so $long_data[0] fits but long_data[1] doesn't + $dbh->{LongReadLen} /= 2 if $type_name =~ /RAW/i; + $dbh->{LongTruncOk} = 0; - note("LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"); + + note "LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"; $sqlstr = "select * from $table order by idx"; - ok($sth = $dbh->prepare($sqlstr), "prepare $sqlstr" ); - ok($sth->execute, "execute $sqlstr" ); - ok($tmp = $sth->fetchrow_arrayref, "fetchrow_arrayref $sqlstr" ); - ok($tmp->[1] eq $long_data[0], "length tmp->[1] ".length($tmp->[1]) ); + + ok $sth = $dbh->prepare($sqlstr), "prepare $sqlstr"; + ok $sth->execute, "execute $sqlstr"; + ok $tmp = $sth->fetchrow_arrayref, "fetchrow_arrayref $sqlstr"; + ok $tmp->[1] eq $long_data[0], "length tmp->[1] ".length($tmp->[1]); { local $sth->{PrintError} = 0; ok(!defined $sth->fetchrow_arrayref, "truncation error not triggered " - ."(LongReadLen $LongReadLen, data ".length($tmp->[1]||0).")"); + ."(LongReadLen $dbh->{LongReadLen}, data ".length($tmp->[1]||0).")"); $tmp = $sth->err || 0; ok( ($tmp == 1406 || $tmp == 24345) ,"tmp==1406 || tmp==24345 tmp actually=$tmp" ); } $sth->finish; note(" --- fetch $type_name data back again -- complete - LongTruncOk == 0\n"); - $dbh->{LongReadLen} = $len_data1 +1000; + $dbh->{LongReadLen} = $len_data[1] +1000; $dbh->{LongTruncOk} = 0; note("LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"); @@ -245,16 +229,17 @@ sub run_long_tests ok($sth->execute, "execute $sqlstr" ); for my $i (0..2) { - ok($tmp = $sth->fetchrow_arrayref, "fetchrow_arrayref $sqlstr" ); - ok($tmp->[1] eq $long_data[$i], - cdif($tmp->[1],$long_data[$i], "Len ".length($tmp->[1])) ); + my $result = $sth->fetchrow_arrayref; + ok $result, "fetchrow_arrayref $sqlstr"; + is $result->[1] => $long_data[$i], + cdif($result->[1],$long_data[$i], "Len ".length($result->[1])) ; } $sth->finish; SKIP: { - skip( "blob_read tests for LONGs - not currently supported", 15 ) - if ($type_name =~ /LONG/i) ; + skip "blob_read tests for LONGs - not currently supported", 15 + if $type_name =~ /LONG/i; #$dbh->trace(4); note(" --- fetch $type_name data back again -- via blob_read\n\n"); @@ -290,6 +275,7 @@ sub run_long_tests cmp_ok_byte_nice($p1, $long_data[2], "3rd row via blob_read_all"); note("result is ".(utf8::is_utf8($p1) ? "UTF8" : "non-UTF8")."\n"); + if ($be_utf8) { ok( utf8::is_utf8($p1), "result should be utf8"); } @@ -300,7 +286,7 @@ sub run_long_tests SKIP: { - skip( "ora_auto_lob tests for $type_name" ."s - not supported", 7+(13*3) ) + skip( "ora_auto_lob tests for $type_name" ."s - not supported", 49 ) if not ( $type_name =~ /LOB/i ); note(" --- testing ora_auto_lob to access $type_name LobLocator\n\n"); @@ -311,25 +297,29 @@ sub run_long_tests FOR UPDATE -- needed so lob locator is writable }; my $ll_sth = $dbh->prepare($sqlstr, { ora_auto_lob => 0 } ); # 0: get lob locator instead of lob contents - ok($ll_sth ,"prepare $sqlstr" ); - ok($ll_sth->execute ,"execute $sqlstr" ); + ok $ll_sth ,"prepare $sqlstr"; + + ok $ll_sth->execute ,"execute $sqlstr"; + while (my ($lob_locator, $idx) = $ll_sth->fetchrow_array) { note("$idx: ".DBI::neat($lob_locator)."\n"); last if !defined($lob_locator) && $idx == 43; - ok($lob_locator, '$lob_locator is true' ); - is(ref $lob_locator , 'OCILobLocatorPtr', '$lob_locator is a OCILobLocatorPtr' ); - ok( (ref $lob_locator and $$lob_locator), '$lob_locator deref ptr is true' ) ; + ok $lob_locator, '$lob_locator is true'; + is ref $lob_locator => 'OCILobLocatorPtr', '$lob_locator is a OCILobLocatorPtr'; + ok( (ref $lob_locator and $$lob_locator), '$lob_locator deref ptr is true' ); # check ora_lob_chunk_size: my $chunk_size = $dbh->func($lob_locator, 'ora_lob_chunk_size'); - ok(!$DBI::err, "DBI::errstr"); + ok !$DBI::err, "DBI::errstr"; my $data = sprintf $data_fmt, $idx; #create a little data + note("length of data to be written at offset 1: " .length($data) ."\n" ); ok($dbh->func($lob_locator, 1, $data, 'ora_lob_write') ,"ora_lob_write" ); } + is($ll_sth->rows, 4); note(" --- round again to check contents after $type_name write updates...\n"); From 12ed8f1f928ada69ba8f229141f46b5b92dcc473 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 31 Jul 2014 13:51:01 -0400 Subject: [PATCH 478/637] add TODO --- lib/DBD/Oracle.pm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 35bd441e..09a00222 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1073,6 +1073,9 @@ SQL my @version = $banner =~ /(?:^|\s)(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\s|$)/; $dbh->{ora_server_version} = \@version if @version; } + + # TODO looks like a bug that we don't return + # $dbh->{ora_server_version} here } sub ora_nls_parameters { From b9296c15ba619f133c194a37b0a66581c7f4db25 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Thu, 31 Jul 2014 14:25:23 -0400 Subject: [PATCH 479/637] Move mentions of README to troubleshooting guides Fixes #17 --- Changes | 4 ++++ Makefile.PL | 46 +++++++++++++++++++++++----------------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/Changes b/Changes index eb1a38a7..5c3a006d 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,10 @@ Revision history for DBD::Oracle {{$NEXT}} + - Change mentions of READMEs in Makefile.PL to troubleshooting guides. + (GH#17, reported by Ken Williams) + +1.74 2014-04-24 - Promote to stable. 1.73_01 2014-04-23 diff --git a/Makefile.PL b/Makefile.PL index 15303c38..f584ea29 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,3 @@ -## Makefile.PL for DBD::Oracle - see README file for more information. # Copyright (c) 1994-2006 Tim Bunce. Ireland. # Copyright (c) 2006-2008 John Scoles (The Pythian Group). Canada. @@ -217,12 +216,17 @@ if ($::opt_W) { # --- Introduction -print qq{ +print <<"END_BLURB" unless $::opt_s; Configuring DBD::Oracle for perl $] on $^O ($Config{archname}) -Remember to actually *READ* the README file! Especially if you have any problems. +If you encounter any problem, a collection of troubleshooting +guides are available under lib/DBD/Oracle/Troubleshooting. +'DBD::Oracle::Troubleshooting' is the general troubleshooting +guide, while platform-specific troubleshooting hints +live in their labelled sub-document (e.g., Win32 +hints are gathered in 'lib/DBD/Oracle/Troubleshooting/Win32.pod'). -} unless $::opt_s; +END_BLURB # --- Where is Oracle installed... @@ -238,7 +242,7 @@ if (!$OH) { The $ORACLE_ENV environment variable is not set and I couldn\'t guess it. It must be set to hold the path to an Oracle installation directory on this machine (or a machine with a compatible architecture). - See the appropriate README file for your OS for more information. + See the appropriate troubleshooting guide for your OS for more information. ABORTED! \n}; $ENV{$ORACLE_ENV} = $OH; @@ -252,7 +256,7 @@ die qq{ The $ORACLE_ENV environment variable value ($OH) is not valid. It must be set to hold the path to an Oracle installation directory on this machine (or a machine with a compatible architecture). For an Instant Client install, the directory should include an sdk subdirectory. - See the appropriate README file for your OS for more information. + See the appropriate troubleshooting guide for your OS for more information. ABORTED! } unless (-d $OH and $^O eq 'VMS') or -d "$OH/sdk/." # Instant Client with SDK @@ -323,10 +327,12 @@ elsif (($^O eq 'MSWin32') or ($^O =~ /cygwin/i)) { print "Using OCI directory '$OCIDIR'\n"; if ($Config{cc} =~ /gcc/i) { - system("dlltool --input-def oci.def --output-lib liboci.a") - if ! -f "liboci.a"; - die "Could not find or create liboci.a. See README.wingcc.txt\n" - if ! -f "liboci.a"; + + system "dlltool --input-def oci.def --output-lib liboci.a" + unless -f "liboci.a"; + + die "Could not find or create liboci.a.\n" unless -f "liboci.a"; + my $pwd = cwd(); $opts{LIBS} = [ "-L$pwd -loci" ]; } else { @@ -556,7 +562,6 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l else { print "WARNING: Unable to interpret Oracle build commands from $mkfile.\a\n"; print "(Will continue by using fallback approach.)\n"; - print "Please report this to dbi-users\@perl.org. See README for what to include.\n"; sleep 2; $::opt_b = 0; } @@ -679,13 +684,13 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l if ($Config{cc} =~ /gcc/i) { print "WARNING: perl was not built with -fpic or -fPIC in compiler flags.\n", " You may need to rebuild perl from sources.\n", - " See instructions in README.hpux.txt\n" + " See instructions in DBD::Oracle::Troubleshooting::Hpux\n" unless $ccf =~ m/-fpic\b/i; } else { print "WARNING: perl was not built with +z or +Z in compiler flags.\n", " You may need to rebuild perl from sources.\n", - " See instructions in README.hpux.txt\n" + " See instructions in DBD::Oracle::Troubleshooting::Hpux\n" unless $ccf =~ m/\+[zZ]/; } } @@ -804,7 +809,7 @@ if ($^O eq 'hpux') { $opts{LINKTYPE} = 'static'; } else { - print "WARNING: If you have trouble, see README.hpux.txt...\n" + print "WARNING: If you have trouble, see DBD::Oracle::Troubleshooting::Hpux...\n" ." you may have to build your own perl, or go hunting for libraries\n"; } print "WARNING: If you have trouble, try perl Makefile.PL -l\n" unless $::opt_l; @@ -867,7 +872,7 @@ if ($^O eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { print "WARNING: You will may need to rebuild perl using the xlc_r compiler.\a\n"; print " The important thing is that perl and DBD::Oracle be built with the same compiler.\n"; print " You may also need to: ORACCENV='cc=xlc_r'; export ORACCENV\n"; - print " Also see README.aix for gcc instructions and read about the -p option.\n"; + print " Also see DBD::Oracle::Troubleshooting::Aix for gcc instructions and read about the -p option.\n"; sleep 5; } @@ -888,7 +893,6 @@ print "WARNING: Your GNU C compiler is very old. Please upgrade.\n" if ($opts{LINKTYPE} && $opts{LINKTYPE} eq 'static') { print "** Note: DBD::Oracle will be built *into* a NEW perl binary. You MUST use that new perl.\n"; - print " See README and Makefile.PL for more information.$BELL\n"; } @@ -902,9 +906,6 @@ WriteMakefile( dbd_edit_mm_attribs(\%opts) ); check_security() unless $^O eq 'VMS' or $^O eq 'MSWin32' or $^O =~ /cygwin/i; print "\n"; -print "*** If you have problems...\n"; -print " read all the log printed above, and the README and README.help.txt files.\n"; -print " (Of course, you have read README by now anyway, haven't you?)\n\n"; vms_logical_names_sanity_check(); @@ -1197,7 +1198,7 @@ sub find_mkfile { somewhere non-standard you can specify where it is using the -m option: perl Makefile.PL -m /path/to/your.mk - See the appropriate README file for your OS for more information and some alternatives. + See the appropriate troubleshooting guide for your OS for more information and some alternatives. } unless ($^O eq 'MSWin32') || ($^O eq 'VMS') || ($mkfile && -f $mkfile) || $::opt_F; @@ -1582,7 +1583,7 @@ sub find_headers { print "You probably need to install some more Oracle components.\n"; print "For Instant Client that means the SDK package.\n"; print "I'll keep going, but the compile will probably fail.\n"; - print "See the appropriate README file for your OS for more information.$BELL\n"; + print "See the appropriate troubleshooting guide for your OS for more information.$BELL\n"; print "*********************************************************\n\n"; sleep 5; } @@ -2011,7 +2012,6 @@ sub check_security { print "\n"; warn "*** WARNING - YOUR ORACLE INSTALLATION HAS A SECURITY PROBLEM.$BELL\n"; - warn " Read the README.sec.txt file for more information and patch details.$BELL\n"; warn " This is just a warning. It does not affect DBD::Oracle in any way.\n\n"; sleep 6; } @@ -2034,7 +2034,7 @@ sub check_macos_symbol_table { WARNING: symbol table may need modification in Oracle library: $oracle_lib If the build fails in the linking stage, manual modification is -required - see README.macosx.txt +required - see DBD::Oracle::Troubleshooting::Macos END_WARNING return; From 10f508baad072c69a379a65198b0695676059ae0 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Fri, 1 Aug 2014 10:11:47 -0400 Subject: [PATCH 480/637] remove the test plan and use 'done_testing' Because this test file is a giant mess of way too many tests caught in a clump. They badly need to be cleaned up --- t/30long.t | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/t/30long.t b/t/30long.t index 99d70fd1..cc1020df 100644 --- a/t/30long.t +++ b/t/30long.t @@ -40,7 +40,6 @@ my $dbh = DBI->connect( oracle_test_dsn(), $dbuser, '', { PrintError => 0, }) or plan skip_all => "Unable to connect to Oracle"; -plan tests => scalar @test_sets; my $tests_per_set = 97; my $ora_server_version = $dbh->func("ora_server_version"); @@ -61,6 +60,8 @@ foreach (@test_sets) { } } +done_testing(); + ### END OF TESTS, ONLY FUNCTIONS BELOW ### END { From dbc89437902e6be1e27e611a81109abf069ce2c6 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Mon, 20 Oct 2014 10:02:31 -0400 Subject: [PATCH 481/637] Change DBD::Pg to DBD::Oracle Some documentation was "strongly inspired" by DBD::Pg documentation. So strongly, that we forgot to change 'Pg' to 'Oracle' in a few places. :-) Caught by Martin J. Evans. --- lib/DBD/Oracle.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 09a00222..9386573e 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -2821,7 +2821,7 @@ to change just the type and will be overwriting the value later. The C<\%attr> hash is used to indicate the data type of the placeholder. The default value is "varchar". If you need something else, you must -use one of the values provided by DBI or by DBD::Pg. To use a SQL value, +use one of the values provided by DBI or by DBD::Oracle. To use a SQL value, modify your "use DBI" statement at the top of your script as follows: use DBI qw(:sql_types); @@ -2834,7 +2834,7 @@ encounter are: To use Oracle SQL data types, import the list of values like this: - use DBD::Pg qw(:ora_types); + use DBD::Oracle qw(:ora_types); You can then set the data types by setting the value of the C key in the hash passed to L. @@ -2854,7 +2854,7 @@ doing the next execute. Examples: use DBI qw(:sql_types); - use DBD::Pg qw(:ora_types); + use DBD::Oracle qw(:ora_types); $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?"; $sth = $dbh->prepare($SQL); From 295e1b6221d9e20b1cd676560c1fb10e52aeba1b Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Mon, 10 Nov 2014 15:36:52 +0000 Subject: [PATCH 482/637] Fix git issues 21 and 15 - previous unrelated fix broke this --- Changes | 3 +++ dbdimp.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 5c3a006d..49f209a3 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,9 @@ Revision history for DBD::Oracle - Change mentions of READMEs in Makefile.PL to troubleshooting guides. (GH#17, reported by Ken Williams) + - Fix git issues 15 and 21 (the same problem). Previous change for + RT91698 broke other things in output parameters. + 1.74 2014-04-24 - Promote to stable. diff --git a/dbdimp.c b/dbdimp.c index a94cbe51..6d7684f0 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3287,9 +3287,6 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ phs->sv = SvREFCNT_inc(newvalue); /* point to live var */ } - /* Add space for NUL - do it now rather than in rebind as it cause problems - in rebind where maxlen continually grows. */ - phs->maxlen = phs->maxlen + 1; } return dbd_rebind_ph(sth, imp_sth, phs); From 6999332ac82ed59eaf6c93bc14befaada15e1fc8 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Fri, 16 Jan 2015 13:52:02 +0000 Subject: [PATCH 483/637] Additional changes for 1.75_2 I did not check in Mostly Tux's "Try and set -l when the build would have failed" --- CONTRIBUTING.mkd | 12 ++++++------ Changes | 29 +++++++++++++++++++++-------- Makefile.PL | 17 +++++++++++------ 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/CONTRIBUTING.mkd b/CONTRIBUTING.mkd index 56885345..d3b17746 100644 --- a/CONTRIBUTING.mkd +++ b/CONTRIBUTING.mkd @@ -1,7 +1,7 @@ # CONTRIBUTING -Thank you for considering contributing to {{ $dist }}. -This file contains instructions that will help you work with +Thank you for considering contributing to {{ $dist }}. +This file contains instructions that will help you work with the source code. ## Repository branches structure @@ -17,13 +17,13 @@ next section for more details. * **releases** -Contains the code as it appears on CPAN. Each official +Contains the code as it appears on CPAN. Each official release is also tagged with its version. ## Working on the master branch The distribution is managed with [Dist::Zilla][distzilla]. -This means than many of the usual files you might expect +This means than many of the usual files you might expect are not in the repository, but are generated at release time. However, you can run tests directly using the 'prove' tool: @@ -90,13 +90,13 @@ which corresponds to the code is generated by Dist::Zilla and correspond to what is uploaded to CPAN. It won't contain any of the changes brought to the codebase since the last -CPAN release, but for a small patch that shouldn't be a problem. +CPAN release, but for a small patch that shouldn't be a problem. ## Sending Patches The code for this distribution is hosted on [GitHub][repository]. -You can submit bug reports via the [repository's issue track][bugtracker]. +You can submit bug reports via the [repository's issue track][bugtracker]. You can also submit code changes by forking the repository, pushing your code changes to your clone, and then submitting a pull request. Detailed diff --git a/Changes b/Changes index 49f209a3..33c0f729 100644 --- a/Changes +++ b/Changes @@ -1,11 +1,24 @@ Revision history for DBD::Oracle {{$NEXT}} - - Change mentions of READMEs in Makefile.PL to troubleshooting guides. - (GH#17, reported by Ken Williams) - - Fix git issues 15 and 21 (the same problem). Previous change for - RT91698 broke other things in output parameters. +1.75_2 2014-11-19 + + [ENHANCEMENT] + + Try and set -l when the build would have failed (H.Merijn Brand) + +1.75_1 2014-11-17 + + [DOCUMENTATION] + + Change mentions of READMEs in Makefile.PL to troubleshooting guides. + (GH#17, reported by Ken Williams) + + [BUG FIXES] + + Fix GH#15 and GH#21 (the same problem). Previous change for + RT91698 broke other things in output parameters. 1.74 2014-04-24 - Promote to stable. @@ -21,7 +34,7 @@ Revision history for DBD::Oracle 1.71_00 2014-03-31 - Recognizes __CYGWIN64__. (RT88709, reported by Witold Petriczek) - - CHOOSE hint is deprecated. (RT91217, reported by Andy Bucksch, + - CHOOSE hint is deprecated. (RT91217, reported by Andy Bucksch, fix by Martin J Evans) - Set UTF8 flag per-connection. (RT88185, reported by Heinrich Mislik, patch by Martin J. Evans) @@ -35,16 +48,16 @@ Revision history for DBD::Oracle [IMPROVEMENTS] - - The DSN 'dbi:Oracle:sid=foo' is now an alias for 'dbi:Oracle:foo'. + - The DSN 'dbi:Oracle:sid=foo' is now an alias for 'dbi:Oracle:foo'. (RT#91775, Yanick Champoux, requested by David Wheeler) - - Support for ORA_SYSBACKUP, ORA_SYSDG and ORA_SYSKM. (RT#91473, + - Support for ORA_SYSBACKUP, ORA_SYSDG and ORA_SYSKM. (RT#91473, Kris Lemaire) [BUG FIXES] - OCI_THREADED setting had been accidentally removed, causing potential - crashes when using threads. (RT#92229, Martin J. Evans, reported + crashes when using threads. (RT#92229, Martin J. Evans, reported by Detlef Lütticke) - When using fetch*_hashref the values are decoded but diff --git a/Makefile.PL b/Makefile.PL index f584ea29..44909f51 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -287,6 +287,9 @@ my $linkwith = ""; my $linkwith_msg = ""; my $need_ldlp_env; +# Do these in advance to enable automatic -l +my @libclntsh = glob("$OH/libclntsh.$so*"); + if ($^O eq 'VMS') { my $OCIINCLUDE = join " ", vmsify("$OH/rdbms/"), vmsify("$OH/rdbms/public"), @@ -384,7 +387,7 @@ elsif (($^O eq 'MSWin32') or ($^O =~ /cygwin/i)) { # --- UNIX Variants --- -elsif ($::opt_l and # use -l to enable this direct-link approach +elsif ($::opt_l || !defined $mkfile and # use -l to enable this direct-link approach @_=grep { m:/lib(cl(ie)?ntsh|oracle).\w+$:o } <$OH/lib/lib*> ) { # --- the simple modern way --- @@ -412,7 +415,7 @@ elsif ($::opt_l and # use -l to enable this direct-link approach # --- special case for Oracle 10g instant client (note lack of ../lib/...) -elsif (my @libclntsh = glob("$OH/libclntsh.$so*")) { +elsif (@libclntsh) { print "Looks like an Instant Client installation, okay\n"; @@ -441,7 +444,7 @@ elsif (my @libclntsh = glob("$OH/libclntsh.$so*")) { $opts{INC} = "$inc -I$dbi_arch_dir"; } -elsif ($mkfile = find_mkfile() and $mkfile =~ /\bdemo_xe.mk$/) { # Oracle XE +elsif (defined $mkfile and $mkfile =~ /\bdemo_xe.mk$/) { # Oracle XE print "Looks like Oracle XE ($mkfile)\n"; @@ -1183,7 +1186,9 @@ sub find_mkfile { $mkfile ||= $place; # use first one found print "Found $place\n"; } - die qq{ + unless ($^O eq 'MSWin32' || $^O eq 'VMS' || ($mkfile && -f $mkfile) || $::opt_F) { + $::opt_l or return ($mkfile = undef); + die qq{ Unable to locate an oracle.mk or other suitable *.mk file in your Oracle installation. (I looked in @mkplaces under $OH) @@ -1199,8 +1204,8 @@ sub find_mkfile { perl Makefile.PL -m /path/to/your.mk See the appropriate troubleshooting guide for your OS for more information and some alternatives. - - } unless ($^O eq 'MSWin32') || ($^O eq 'VMS') || ($mkfile && -f $mkfile) || $::opt_F; + }; + } print "Using $mkfile\n"; return $mkfile; From 8275bcec716bcd9535360b0e3c452da4a51d1da1 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Tue, 20 Jan 2015 13:37:56 +0000 Subject: [PATCH 484/637] fix git issue 20 - add instanclient path for mac --- Makefile.PL | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 44909f51..5fc410ef 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -63,7 +63,7 @@ my %opts = ( resources => { bugtracker => { mailto => 'bug-dbd-oracle at rt.cpan.org', - web => + web => 'http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle', }, homepage => 'http://search.cpan.org/dist/DBD-Oracle', @@ -222,8 +222,8 @@ Configuring DBD::Oracle for perl $] on $^O ($Config{archname}) If you encounter any problem, a collection of troubleshooting guides are available under lib/DBD/Oracle/Troubleshooting. 'DBD::Oracle::Troubleshooting' is the general troubleshooting -guide, while platform-specific troubleshooting hints -live in their labelled sub-document (e.g., Win32 +guide, while platform-specific troubleshooting hints +live in their labelled sub-document (e.g., Win32 hints are gathered in 'lib/DBD/Oracle/Troubleshooting/Win32.pod'). END_BLURB @@ -1161,8 +1161,8 @@ sub find_mkfile { 'rdbms/demo/oracle.mk', 'rdbms/demo/demo_rdbms.mk', 'rdbms/demo/demo_rdbms64.mk', - 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client - + 'rdbms/lib/ins_rdbms.mk', #Oracle 11 full client + 'sdk/demo/demo.mk' # git issue 20 - path on mac os ); my @mk_oci = perl_is_64bit() ? @mk_oci64 : @mk_oci32; @@ -1521,7 +1521,7 @@ sub find_bin{ { # let's try harder # see rt#84530 for why we don't go straight for it - use filetest 'access'; + use filetest 'access'; return "$_/$bin" if -x "$_/$bin"; } } @@ -1971,17 +1971,17 @@ sub check_ldlibpthname { my $warn_name = $ldlibpthname; # It is also ok if we are using symbolic links - return 1 if grep { s:[\\/]$::; $_ eq $libdir } + return 1 if grep { s:[\\/]$::; $_ eq $libdir } map { $_, Cwd::abs_path($_) } @dirs; # on solaris, it can be under LD_LIBRARY_PATH_(32|64) if ( $^O eq 'solaris' ) { - my $ld_library_path_name = 'LD_LIBRARY_PATH_' + my $ld_library_path_name = 'LD_LIBRARY_PATH_' . ( perl_is_64bit() ? '64' : '32' ); $warn_name .= " or $ld_library_path_name"; - my @dirs = split quotemeta($Config{path_sep}), + my @dirs = split quotemeta($Config{path_sep}), $ENV{$ld_library_path_name}; s#[\\/]$## for @dirs; # cut potential final / or \ From 08796ebd841b6e35dff7647facedda760af6d6fd Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Tue, 20 Jan 2015 13:57:19 +0000 Subject: [PATCH 485/637] Fix git issue 23 - disabled constraints not ignored and update Changes --- Changes | 7 +++++++ lib/DBD/Oracle.pm | 2 ++ 2 files changed, 9 insertions(+) diff --git a/Changes b/Changes index 33c0f729..f12a6061 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,13 @@ Revision history for DBD::Oracle {{$NEXT}} + [ENHANCEMENT] + + Add new path to find 64 bit Oracle client on MAC OSX - (GH#20, Martin J. Evans) + + Ignore constraints which are not enabled in primary/foreign key_info + (GH#23, Martin J. Evans) + 1.75_2 2014-11-19 [ENHANCEMENT] diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 09a00222..78ceac43 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -535,6 +535,7 @@ SELECT * AND p.TABLE_NAME = c.TABLE_NAME AND p.CONSTRAINT_NAME = c.CONSTRAINT_NAME AND p.CONSTRAINT_TYPE = 'P' + AND p.STATUS = 'ENABLED' ) WHERE TABLE_SCHEM = ? AND TABLE_NAME = ? @@ -586,6 +587,7 @@ SELECT * AND uk.CONSTRAINT_NAME = fk.R_CONSTRAINT_NAME AND uk.OWNER = fk.R_OWNER AND uc.POSITION = fc.POSITION + AND fk.STATUS = 'ENABLED' ) WHERE 1 = 1 SQL From d51447a9e34c926fbe510af967d76f4a88c2d56d Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Fri, 15 May 2015 16:25:12 +0100 Subject: [PATCH 486/637] Connection informational messages were being lost --- Changes | 5 +++++ lib/DBD/Oracle.pm | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/Changes b/Changes index 33c0f729..108b4620 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,11 @@ Revision history for DBD::Oracle {{$NEXT}} + [ENHANCMENT] + + Connection informational messages like "ORA-28002: the password will + expire" were lost. Thanks to J.D. Laub. + 1.75_2 2014-11-19 [ENHANCEMENT] diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 09a00222..d017410e 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -303,9 +303,19 @@ package DBD::Oracle; } unless (length $user_only) { + # It may be we've already encountered a warning by this point, + # such as "ORA-28002: the password will expire within %d days". + # We'll cache it for reinstatement. + my ($err, $errstr, $state) = + ($dbh->err, $dbh->errstr, $dbh->state); $user_only = $dbh->selectrow_array(q{ SELECT SYS_CONTEXT('userenv','session_user') FROM DUAL })||''; + # Now we'll reinstate the earlier warning. We're just + # appending it, so in the extremeley unlikely case that the + # selectrow_array we just issued also issued a warning, the + # 2 warnings will appear out of order. + $dbh->set_err($err, $errstr, $state) if defined $err; $dbh_inner->{Username} = $user_only; # these two are just for backwards compatibility $dbh_inner->{USER} = $dbh_inner->{CURRENT_USER} = uc $user_only; From dceaf07d5efba5cce91ff79de8a9fd83bcd11e66 Mon Sep 17 00:00:00 2001 From: Aaron Crane Date: Wed, 9 Dec 2015 18:39:51 +0000 Subject: [PATCH 487/637] oci8.c: fix format error in PerlIO_printf() call This code was trying to print an OCI ub4 value using the format string "%lu". On systems where unsigned long is wider than ub4 (including several 64-bit Linux systems), this will cause undefined behaviour (which might in turn look like stack-smashing). --- oci8.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oci8.c b/oci8.c index 46a69e8e..7a1d9e90 100644 --- a/oci8.c +++ b/oci8.c @@ -1844,7 +1844,8 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, DBIc_LOGPIO(imp_sth), " blob_read field %d, ftype %d, offset %ld, len %lu, " "destoffset %ld, retlen %lu\n", - fbh->field_num+1, ftype, offset, len, destoffset, ul_t(amtp)); + fbh->field_num+1, ftype, offset, (unsigned long) len, + destoffset, ul_t(amtp)); SvCUR_set(dest_sv, byte_destoffset+amtp); *SvEND(dest_sv) = '\0'; /* consistent with perl sv_setpvn etc */ From 3458dce4be595bd561b4de119e1824d414f4c7f8 Mon Sep 17 00:00:00 2001 From: Aaron Crane Date: Wed, 9 Dec 2015 18:42:56 +0000 Subject: [PATCH 488/637] ocitrace.h: fix format errors in PerlIO_printf() calls This code was trying to print two arguments that are likely to be size_t (as the result of strlen() calls) using the "%d" format string. On systems where size_t is wider than int (including most 64-bit systems), this will cause undefined behaviour (which might in turn look like stack-smashing). --- ocitrace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ocitrace.h b/ocitrace.h index 0f3c71bf..2ea5cbb2 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -71,8 +71,8 @@ stat =OCISessionPoolCreate(envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,OCI_DEFAULT);\ (DBD_OCI_TRACEON(impdbh)) \ ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ - "%sOCISessionPoolCreate(envhp=%p,ph=%p,pn=%p,pnl=%p,min=%d,max=%d,incr=%d, un=%s,unl=%d,pw=%s,pwl=%d)=%s\n",\ - OciTp, envhp,ph,pn,pnl,sn,sm,si,un,unl,pw,pwl,oci_status_name(stat)),stat \ + "%sOCISessionPoolCreate(envhp=%p,ph=%p,pn=%p,pnl=%p,min=%d,max=%d,incr=%d, un=%s,unl=%d,pw=%s,pwl=%lu)=%s\n",\ + OciTp, envhp,ph,pn,pnl,sn,sm,si,un,(unsigned long)unl,pw,(unsigned long)pwl,oci_status_name(stat)),stat \ : stat #if defined(ORA_OCI_102) From 7c6d316621549d3524aa63294122063ca1f218a1 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Mon, 12 Dec 2016 15:55:25 +0000 Subject: [PATCH 489/637] Treat ROWID descriptors differently from ROWIDs - allow more storage --- oci8.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/oci8.c b/oci8.c index 46a69e8e..b36c54a4 100644 --- a/oci8.c +++ b/oci8.c @@ -156,6 +156,7 @@ sql_typecode_name(int dbtype) { case 97: return "CHARZ"; case 100: return "BINARY FLOAT oracle-endian"; case 101: return "BINARY DOUBLE oracle-endian"; + case 104: return "ROWID"; case 106: return "MLSLABEL"; case 102: return "SQLT_CUR OCI 7 cursor variable"; case 112: return "SQLT_CLOB / long"; @@ -3661,10 +3662,13 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) break; case ORA_ROWID: /* ROWID */ - case 104: /* ROWID Desc */ fbh->disize = 20; fbh->prec = fbh->disize; break; + case 104: /* ROWID Desc */ + fbh->disize = 2000; + fbh->prec = fbh->disize; + break; case 108: /* some sort of embedded object */ imp_sth->row_cache_off = 1;/* cant fetch more thatn one at a time */ fbh->ftype = fbh->dbtype; /*varray or alike */ From 6b958448258e2efd33f75eda91a7cec56d83f13b Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Mon, 12 Dec 2016 16:02:57 +0000 Subject: [PATCH 490/637] add change comment for rowid change --- Changes | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 15b3b216..4474b6c2 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,12 @@ Revision history for DBD::Oracle {{$NEXT}} + [BUG FIXES] + + Fix truncation error on ROWIDs from an Index Organized table as they are + not a fixed length. Code now allows up to a size of 2000. + (GH#31, Martin J. Evans) + [ENHANCEMENT] Connection informational messages like "ORA-28002: the password will @@ -12,6 +18,7 @@ Revision history for DBD::Oracle Ignore constraints which are not enabled in primary/foreign key_info (GH#23, Martin J. Evans) + 1.75_2 2014-11-19 [ENHANCEMENT] @@ -1790,4 +1797,3 @@ please enjoy. 19th Sep 1994: DBperl project renamed to DBI. 29th Sep 1992: DBperl project started. - From ce425ad4e8db9754378fcaabef64e62eb2c3be44 Mon Sep 17 00:00:00 2001 From: Alice Maz Date: Tue, 13 Jun 2017 16:27:51 -0700 Subject: [PATCH 491/637] Set zero-length lob to undef when using ora_piece_lob option --- oci8.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/oci8.c b/oci8.c index b36c54a4..dfb7a57e 100644 --- a/oci8.c +++ b/oci8.c @@ -2851,13 +2851,17 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) actual_bufl,fb_ary->piece_count,fbh->piece_size,buflen); } } - sv_setpvn(dest_sv, (char*)fb_ary->cb_abuf,(STRLEN)actual_bufl); - if (fbh->ftype != SQLT_BIN){ + if (actual_bufl > 0){ + sv_setpvn(dest_sv, (char*)fb_ary->cb_abuf,(STRLEN)actual_bufl); + if (fbh->ftype != SQLT_BIN){ - if (CSFORM_IMPLIES_UTF8(fbh->csform) ){ /* do the UTF 8 magic*/ - SvUTF8_on(dest_sv); + if (CSFORM_IMPLIES_UTF8(fbh->csform) ){ /* do the UTF 8 magic*/ + SvUTF8_on(dest_sv); + } } + } else { + sv_set_undef(dest_sv); } return 1; From 2a8ed676fba11b8eaf10df425c6ffbec3e55bf36 Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Fri, 21 Jul 2017 10:29:58 -0500 Subject: [PATCH 492/637] Search for Oracle Instant Client .mk file location when compiling for 32 bit. Previously this was fixed for 64 bit only (git issue #20). --- Makefile.PL | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.PL b/Makefile.PL index 5fc410ef..f21d12d1 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1153,7 +1153,8 @@ sub find_mkfile { 'rdbms/demo/demo_xe.mk', 'rdbms/demo/demo_rdbms32.mk', 'rdbms/demo/demo_rdbms.mk', - 'rdbms/lib/ins_rdbms.mk' #Oracle 11 full client + 'rdbms/lib/ins_rdbms.mk', #Oracle 11 full client + 'sdk/demo/demo.mk' #OIC .mk location ); my @mk_oci64 = ( 'rdbms/demo/demo_xe.mk', From 5b3c9cb9ecf59be6aa7af6da4874f1d8711a48d6 Mon Sep 17 00:00:00 2001 From: Dean Pearce Date: Tue, 1 Aug 2017 12:31:32 -0400 Subject: [PATCH 493/637] GH#48 Fix for error in test where 31lob.t was failing due to a statement handle that was not invalidated. --- t/14threads.t | 8 ++++---- t/31lob.t | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/t/14threads.t b/t/14threads.t index 4f89ecbb..737dc1b6 100644 --- a/t/14threads.t +++ b/t/14threads.t @@ -3,7 +3,7 @@ $| = 1; ## ---------------------------------------------------------------------------- ## 14threads.t -## By Jeffrey Klein, +## By Jeffrey Klein, ## ---------------------------------------------------------------------------- BEGIN { eval "use threads; use threads::shared;" } @@ -68,13 +68,13 @@ for my $i ( 0 .. 4 ) { free_dbh_to_pool($dbh); } )->join; - + } # TESTS: 1 is scalar(@pool), 1, 'one imp_data in pool'; - + # get two sessions in same thread # TESTS: 2 threads->create( @@ -181,7 +181,7 @@ sub connect_dbh { sub session_id { my $dbh = shift; - my ($s) = $dbh->selectrow_array("select userenv('sessionid') from dual"); + my ($s) = $dbh->selectrow_array("select userenv('sid') from dual"); return $s; } __END__ diff --git a/t/31lob.t b/t/31lob.t index 56366555..685ac672 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -113,7 +113,7 @@ sub have_v_session { done_testing(); } else { is( $len, length($large_value), "returned length" ); - + } is( $dbh->ora_lob_read( $loc, 1, length($large_value) ), $large_value, "returned written value" ); @@ -125,7 +125,7 @@ sub have_v_session { my $sth = $dbh->prepare( 'BEGIN ? := DBMS_LOB.GETLENGTH( ? ); END;', - { ora_auto_lob => 0 } + { ora_auto_lob => 0 } ); $sth->bind_param_inout( 1, \$len, 16 ); $sth->bind_param( 2, $loc, { ora_type => ORA_BLOB } ); @@ -212,6 +212,8 @@ END_SQL } } +undef $sth; + $dbh->do("DROP TABLE $table"); $dbh->disconnect; From 2221d8ba7177dabb29bfa48f78c395d609badfcd Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Tue, 1 Aug 2017 13:11:07 -0500 Subject: [PATCH 494/637] Have ora_libdir check $ORACLE_HOME/lib/64 when it exists and the build is for 64 bit. --- Makefile.PL | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile.PL b/Makefile.PL index f21d12d1..0254a7d1 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1121,7 +1121,9 @@ sub perl_is_64bit { sub ora_libdir { my $libdir = 'lib' ; if ( $client_version >= 9 ) { - $libdir = 'lib32' if ! perl_is_64bit() and -d "$OH/lib32"; + $libdir = 'lib32' if ! perl_is_64bit() and -d "$OH/lib32"; + $libdir = 'lib/64' if perl_is_64bit() and -d "$OH/lib/64"; + # Solaris OIC 12+ from pkg } else { $libdir = 'lib64' if perl_is_64bit() and -d "$OH/lib64"; From 091ed01bf30c503f33869defde07d82eab86b880 Mon Sep 17 00:00:00 2001 From: Dean Pearce Date: Tue, 1 Aug 2017 14:59:34 -0400 Subject: [PATCH 495/637] Fix for Oracle version default value. --- Makefile.PL | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index f21d12d1..ddc64af2 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1703,20 +1703,25 @@ sub get_client_version { } if (!$client_version_full) { - $client_version_full = "8.0.0.0"; - print qq{ -WARNING: I could not determine Oracle client version so I\'ll just -default to version $client_version_full. Some features of DBD::Oracle may not work. -Oracle version based logic in Makefile.PL may produce erroneous results. -You can use "perl Makefile.PL -V X.Y.Z" to specify a your client version.\n + + # set a supported client version as default + $client_version_full = "9.2.0.4.0"; + + print qq{ +WARNING: Could not determine Oracle client version, defaulting to +version $client_version_full. Some features of DBD::Oracle may not work. +Oracle version-based logic in Makefile.PL may produce erroneous +results. You can use "perl Makefile.PL -V X.Y.Z" to specify your +client version.\n }; - sleep 5; + # pause for focus + sleep 3; } # hack up a simple floating point form of the version: 8.1.6.2 => 8.1 ($client_version = $client_version_full) =~ s/^(\d+\.\d+).*/$1/; - print "Oracle version $client_version_full ($client_version)\n"; + print "Oracle Version $client_version_full ($client_version)\n"; return $client_version unless wantarray; return ($client_version, $client_version_full); From ceed9e9ec9f801a4064d84f10ff711d826ee3d90 Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Fri, 16 Sep 2016 14:49:27 +0200 Subject: [PATCH 496/637] Fix warnings from gcc/clang, correct a few typos --- dbdimp.c | 33 ++++++++++++++++----------------- oci8.c | 32 ++++++++++++++++---------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 6d7684f0..06bb0a83 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -98,7 +98,7 @@ oci_error_get(imp_xxh_t *imp_xxh, what ? what : "", (long)recno, (eg_status==OCI_SUCCESS) ? "ok" : oci_status_name(eg_status), status, (long)eg_errcode, errbuf); - errcode = eg_errcode; + errcode = eg_errcode; sv_catpv(errstr, (char*)errbuf); if (*(SvEND(errstr)-1) == '\n') --SvCUR(errstr); @@ -407,7 +407,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (DBD_ATTRIB_TRUE(attr,"ora_drcp",8,svp)) imp_dbh->using_drcp = 1; - /* some connection pool atributes */ + /* some connection pool attributes */ if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_drcp_class", 14)) && SvOK(*svp)) { STRLEN svp_len; @@ -501,7 +501,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S shared_dbh_len = SvCUR((shared_dbh_ssv -> sv)) ; if (shared_dbh_len > 0 && shared_dbh_len != sizeof (imp_dbh_t)) - croak ("Invalid value for ora_dbh_dup") ; + croak ("Invalid value for ora_dbh_share") ; if (shared_dbh_len == sizeof (imp_dbh_t)) { /* initialize from shared data */ @@ -582,7 +582,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S form attribute. }*/ - OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, + OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, NULL, charsetid, ncharsetid, status ); if (status != OCI_SUCCESS) { @@ -653,7 +653,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &charsetid, (ub4)0 , + OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &charsetid, NULL, OCI_ATTR_ENV_CHARSET_ID, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { @@ -661,7 +661,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S return 0; } - OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &ncharsetid, (ub4)0 , + OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &ncharsetid, NULL, OCI_ATTR_ENV_NCHARSET_ID, imp_dbh->errhp, status); if (status != OCI_SUCCESS) { @@ -730,14 +730,14 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S (OraText **) &imp_dbh->pool_name, (ub4 *) &imp_dbh->pool_namel, (OraText *) dbname, - strlen(dbname), + (ub4)strlen(dbname), imp_dbh->pool_min, imp_dbh->pool_max, imp_dbh->pool_incr, (OraText *) uid, - strlen(uid), + (ub4)strlen(uid), (OraText *) pwd, - strlen(pwd), + (ub4)strlen(pwd), status); if (status != OCI_SUCCESS) { @@ -1878,7 +1878,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) phs->maxlen, (ub2)SQLT_STR, phs->array_indicators, phs->array_lengths, /* ub2 *alen_ptr not needed with OCIBindDynamic */ - (ub2)0, + NULL, (ub4)phs->ora_maxarray_numentries, /* max elements that can fit in allocated array */ (ub4 *)&(phs->array_numstruct), /* (ptr to) current number of elements in array */ OCI_DEFAULT, /* OCI_DATA_AT_EXEC (bind with callbacks) or OCI_DEFAULT */ @@ -1910,7 +1910,7 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (!phs->csid_orig) { /* get the default csid Oracle would use */ - OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , + OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, NULL, OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); } @@ -2314,7 +2314,7 @@ int dbd_rebind_ph_number_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { phs->maxlen, (ub2)phs->ora_internal_type, phs->array_indicators, phs->array_lengths, - (ub2)0, + NULL, (ub4)phs->ora_maxarray_numentries, /* max elements that can fit in allocated array */ (ub4 *)&(phs->array_numstruct), /* (ptr to) current number of elements in array */ OCI_DEFAULT, /* OCI_DATA_AT_EXEC (bind with callbacks) or OCI_DEFAULT */ @@ -3048,7 +3048,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (!phs->csid_orig) { /* get the default csid Oracle would use */ - OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , + OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, NULL, OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); } @@ -3651,7 +3651,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat } if (!phs->csid_orig) { /* get the default csid Oracle would use */ - OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, (ub4)0 , + OCIAttrGet_log_stat(imp_sth, phs->bndhp, OCI_HTYPE_BIND, &phs->csid_orig, NULL, OCI_ATTR_CHARSET_ID, imp_sth->errhp, status); } @@ -4037,7 +4037,7 @@ dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, ora_free_templob(sth, imp_sth, (OCILobLocator*)fbh->desc_h); return 0; } - ftype = ftype; /* no unused */ + (void)ftype; /* no unused */ if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( @@ -4308,7 +4308,7 @@ dbd_st_STORE_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv) if (cachesv) /* cache value for later DBI 'quick' fetch? */ (void)hv_store((HV*)SvRV(sth), key, kl, cachesv, 0); - return TRUE; + return TRUE; } @@ -4343,7 +4343,6 @@ dbd_st_FETCH_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv) if (kl==4 && strEQ(key, "NAME")) { AV *av = newAV(); SV *x; - D_imp_dbh_from_sth; retsv = newRV(sv_2mortal((SV*)av)); while(--i >= 0) { diff --git a/oci8.c b/oci8.c index a2e03e53..794450e8 100644 --- a/oci8.c +++ b/oci8.c @@ -1128,7 +1128,7 @@ dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, phs->alen = 0; phs->indp = 0; } - else + else if (SvOK(phs->sv)) { *bufpp = SvPV(phs->sv, phs_len); phs->alen = (phs->alen_incnull) ? phs_len+1 : phs_len;; @@ -1139,20 +1139,20 @@ dbd_phs_in(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, phs->alen = 0; phs->indp = -1; } - *alenp = phs->alen; - *indpp = &phs->indp; - *piecep = OCI_ONE_PIECE; - /* MJE commented out as we are avoiding DBIS now but as this is - an Oracle callback there is no way to pass something non - OCI into this func. - - if (DBIS->debug >= 3 || dbd_verbose >= 3 ) - PerlIO_printf(DBILOGFP, " in '%s' [%lu,%lu]: len %2lu, ind %d%s, value=%s\n", - phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), phs->indp, - (phs->desc_h) ? " via descriptor" : "",neatsvpv(phs->sv,10)); - */ - if (!tuples_av && (index > 0 || iter > 0)) - croak(" Arrays and multiple iterations not currently supported by DBD::Oracle (in %d/%d)", index,iter); + *alenp = phs->alen; + *indpp = &phs->indp; + *piecep = OCI_ONE_PIECE; + /* MJE commented out as we are avoiding DBIS now but as this is + an Oracle callback there is no way to pass something non + OCI into this func. + + if (DBIS->debug >= 3 || dbd_verbose >= 3 ) + PerlIO_printf(DBILOGFP, " in '%s' [%lu,%lu]: len %2lu, ind %d%s, value=%s\n", + phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), phs->indp, + (phs->desc_h) ? " via descriptor" : "",neatsvpv(phs->sv,10)); + */ + if (!tuples_av && (index > 0 || iter > 0)) + croak(" Arrays and multiple iterations not currently supported by DBD::Oracle (in %d/%d)", index,iter); return OCI_CONTINUE; } @@ -1843,7 +1843,7 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, if (dbis->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), - " blob_read field %d, ftype %d, offset %ld, len %lu, " + " blob_read field %d, ftype %d, offset %ld, len %u, " "destoffset %ld, retlen %lu\n", fbh->field_num+1, ftype, offset, (unsigned long) len, destoffset, ul_t(amtp)); From d19338a9c4dddcf83da52d8d597c7a2a3cca174b Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Fri, 16 Sep 2016 14:57:12 +0200 Subject: [PATCH 497/637] Avoid use of inactive database handle in statement destructor This error caused a SIGSEGV in t/51scroll.t with ORA_DRCP=1 --- dbdimp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 06bb0a83..1e9fd4ec 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -4215,6 +4215,7 @@ dbd_st_destroy(SV *sth, imp_sth_t *imp_sth) int i; sword status; dTHX ; + D_imp_dbh_from_sth; /* Don't free the OCI statement handle for a nested cursor. It will be reused by Oracle on the next fetch. Indeed, we never @@ -4225,8 +4226,7 @@ dbd_st_destroy(SV *sth, imp_sth_t *imp_sth) /* if we are using a scrolling cursor we should get rid of the cursor by fetching row 0 */ - - if (imp_sth->exe_mode==OCI_STMT_SCROLLABLE_READONLY){ + if (imp_sth->exe_mode==OCI_STMT_SCROLLABLE_READONLY && DBIc_ACTIVE(imp_dbh)) { OCIStmtFetch_log_stat(imp_sth, imp_sth->stmhp, imp_sth->errhp, 0,OCI_FETCH_NEXT,0, status); } From 591617a97ecf55d5b2323d49c366e8638b320d30 Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Sat, 17 Sep 2016 20:56:31 +0200 Subject: [PATCH 498/637] Plug various environment handle leaks This fixes https://github.com/pythian/DBD-Oracle/issues/27 - among other cases. Note that with ithreads, the global imp_drh environment handle still leaks. The previous error paths and the attempted partial fix in https://github.com/pythian/DBD-Oracle/issues/28 could cause crashes because of missing curly brackets in if-statements calling OCIHandleFree_log_stat (which is a macro). The addition of a driver handle destructor also prepares for timely destruction of DRCP session pools. This requires DBI >= 1.623, which adds logic to force destruction of children before parents during global destruction. --- Makefile.PL | 10 +++--- Oracle.h | 1 + Oracle.xs | 11 ++++-- README | 2 +- dbdimp.c | 92 ++++++++++++++++++++++++++++++++--------------- dbdimp.h | 3 ++ dist.ini | 2 +- lib/DBD/Oracle.pm | 2 +- 8 files changed, 84 insertions(+), 39 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 89b9c09b..d4686528 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -17,7 +17,7 @@ use Pod::Usage; # For those not using Dynamic loading this means building a # new static perl in the DBI directory by saying 'make perl' # and then using _that_ perl to make this one. -use DBI 1.51; +use DBI 1.623; use DBI::DBD; # DBD creation tools @@ -45,7 +45,7 @@ my %opts = ( NAME => 'DBD::Oracle', VERSION_FROM => 'lib/DBD/Oracle.pm', PREREQ_PM => { "Test::Simple" => 0.90, # actually Test::More pkg in T::S dist - "DBI" => 1.51}, + "DBI" => 1.623}, OBJECT => '$(O_FILES)', DEFINE => '', DIR => [], @@ -56,8 +56,8 @@ my %opts = ( COMPRESS => 'gzip -v9', SUFFIX => 'gz', }, META_MERGE => { - configure_requires => { "DBI" => '1.51' }, - build_requires => {"DBI" => '1.51', + configure_requires => { "DBI" => '1.623' }, + build_requires => {"DBI" => '1.623', "ExtUtils::MakeMaker" => 0, "Test::Simple" => '0.90'}, resources => { @@ -81,7 +81,7 @@ $eumm =~ tr/_//d; if ($eumm >= 5.43) { $opts{AUTHOR} = 'Tim Bunce (dbi-users@perl.org)'; $opts{ABSTRACT_FROM} = 'lib/DBD/Oracle.pm'; - $opts{PREREQ_PM} = { DBI => 1.51 }; + $opts{PREREQ_PM} = { DBI => 1.623 }; $opts{CAPI} = 'TRUE' if $Config{archname} =~ /-object\b/i; } diff --git a/Oracle.h b/Oracle.h index 8713ee40..24379fee 100644 --- a/Oracle.h +++ b/Oracle.h @@ -60,6 +60,7 @@ void dbd_init _((dbistate_t *dbistate)); void dbd_init_oci_drh _((imp_drh_t * imp_drh)); +void dbd_dr_destroy _((SV *drh, imp_drh_t *imp_drh)); int dbd_db_login _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pwd)); int dbd_db_do _((SV *sv, char *statement)); diff --git a/Oracle.xs b/Oracle.xs index 3e8b5a18..7ec2eaa2 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -712,6 +712,11 @@ init_oci(drh) dbd_init_oci(DBIS) ; dbd_init_oci_drh(imp_drh) ; - - - +void +DESTROY(drh) + SV * drh + PPCODE: + /* keep in sync with default DESTROY in DBI.xs (currently there is no dr default) */ + D_imp_drh(drh); + ST(0) = &PL_sv_yes; + dbd_dr_destroy(drh, imp_drh); diff --git a/README b/README index fd2b28aa..e180ad64 100644 --- a/README +++ b/README @@ -43,7 +43,7 @@ DBD::Oracle -- an Oracle interface for Perl 5. Build, test and install Perl 5 (at least 5.6.1) It is very important to TEST it and INSTALL it! - Build, test and install the DBI module (at least DBI 1.51). + Build, test and install the DBI module (at least DBI 1.623). It is very important to TEST it and INSTALL it! Remember to *read* the DBI README file and this one CAREFULLY! diff --git a/dbdimp.c b/dbdimp.c index 1e9fd4ec..2644bd43 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -202,6 +202,26 @@ dbd_init(dbistate_t *dbistate) } +void +dbd_dr_destroy(SV *drh, imp_drh_t *imp_drh) +{ + dTHX; + sword status; + + /* We rely on the DBI dispatcher to destroy all child handles before we get here (DBI >= 1.623). */ + + if (imp_drh->leak_state) { + /* With ithreads, we can't tell when the last dr handle is destroyed. */ + return; + } + + if (imp_drh->envhp) { + /* Free cached environment handle. */ + OCIHandleFree_log_stat(imp_drh, imp_drh->envhp, OCI_HTYPE_ENV, status); + } +} + + int dbd_discon_all(SV *drh, imp_drh_t *imp_drh) { @@ -395,7 +415,6 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S D_imp_drh_from_dbh; ub2 new_charsetid = 0; ub2 new_ncharsetid = 0; - int forced_new_environment = 0; #if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) SV ** shared_dbh_priv_svp ; SV * shared_dbh_priv_sv ; @@ -514,6 +533,9 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } else { shared_dbh = NULL ; } + + /* With ithreads, we can't tell when the last dr handle is destroyed. */ + imp_drh->leak_state = 1; } #endif @@ -522,17 +544,13 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_envhp", 9)) && SvOK(*svp)) { if (!SvTRUE(*svp)) { imp_dbh->envhp = NULL; /* force new environment */ - forced_new_environment = 1; } } /* RT46739 */ if (imp_dbh->envhp) { - OCIError *errhp; - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &errhp, OCI_HTYPE_ERROR, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); if (status != OCI_SUCCESS) { imp_dbh->envhp = NULL; - } else { - OCIHandleFree_log_stat(imp_dbh, errhp, OCI_HTYPE_ERROR, status); } } @@ -590,8 +608,6 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S "OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc."); return 0; } - if (!imp_drh->envhp) /* cache first envhp info drh as future default */ - imp_drh->envhp = imp_dbh->envhp; svp = DBD_ATTRIB_GET_SVP(attr, "ora_charset", 11);/*get the charset passed in by the user*/ if (svp) { @@ -622,7 +638,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (new_charsetid || new_ncharsetid) { /* reset the ENV with the new charset from above*/ if (new_charsetid) charsetid = new_charsetid; if (new_ncharsetid) ncharsetid = new_ncharsetid; - imp_dbh->envhp = NULL; + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, charsetid, ncharsetid, status ); if (status != OCI_SUCCESS) { @@ -630,10 +646,11 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S "OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc"); return 0; } - if (!imp_drh->envhp) /* cache first envhp info drh as future default */ - imp_drh->envhp = imp_dbh->envhp; } + if (!imp_drh->envhp) /* cache first envhp info drh as future default */ + imp_drh->envhp = imp_dbh->envhp; + /* update the hard-coded csid constants for unicode charsets */ utf8_csid = OCINlsCharSetNameToId(imp_dbh->envhp, (void*)"UTF8"); al32utf8_csid = OCINlsCharSetNameToId(imp_dbh->envhp, (void*)"AL32UTF8"); @@ -642,17 +659,10 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } - if (shared_dbh_ssv) { /*is this a cached or shared handle from DBI*/ - if (!imp_dbh->envhp) { /*no hande so create a new one*/ - OCIEnvInit_log_stat(imp_dbh, &imp_dbh->envhp, OCI_DEFAULT, 0, 0, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, (OCIError*)imp_dbh->envhp, status, "OCIEnvInit"); - return 0; - } - } + if (!imp_dbh->errhp) { + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); } - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &charsetid, NULL, OCI_ATTR_ENV_CHARSET_ID, imp_dbh->errhp, status); @@ -802,8 +812,9 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); - if (forced_new_environment) + if (imp_dbh->envhp != imp_drh->envhp) { OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); + } return 0; } @@ -829,8 +840,9 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); - if (forced_new_environment) + if (imp_dbh->envhp != imp_drh->envhp) { OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); + } return 0; } @@ -848,9 +860,6 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->ph_type = 1; /* SQLT_CHR "(ORANET TYPE) character string" */ imp_dbh->ph_csform = 0; /* meaning auto (see dbd_rebind_ph) */ - if (!imp_drh->envhp) /* cache first envhp info drh as future default */ - imp_drh->envhp = imp_dbh->envhp; - #if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) if (shared_dbh_ssv && !shared_dbh) { /* much of this could be replaced with a single sv_setpvn() */ @@ -1025,6 +1034,7 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) dTHX ; int refcnt = 1 ; sword status; + D_imp_drh_from_dbh; #if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) if (DBIc_IMPSET(imp_dbh) && imp_dbh->shared_dbh) { @@ -1065,19 +1075,45 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) #endif OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); - #ifdef ORA_OCI_112 } #endif OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + if (imp_dbh->envhp != imp_drh->envhp) { + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); + } + } + else { + /* A new error handle is allocated on each new connect, so it is also freed when + refcnt > 1. Note that we cannot have a common free here, since it is an error + to free the environment handle before the error handle. */ + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); } - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); dbd_db_destroy_out: DBIc_IMPSET_off(imp_dbh); } +SV * +dbd_take_imp_data(SV *dbh, imp_xxh_t *imp_xxh, void* foo) +{ + dTHX; + D_imp_dbh(dbh); + D_imp_drh_from_dbh; + + /* With ithreads, we can't tell when the last dr handle is destroyed. */ + imp_drh->leak_state = 1; + + /* Indicate that SUPER::take_imp_data should be called. */ + return &PL_sv_no; +} + + +/* According to Oracle's documentation of OCISessionGet, attributes should not be changed + on the server and session handles attached to OCISessionGet's service context handle. + This would imply that dbd_db_STORE_attrib is wrong for session pooling, however + it seems to work just fine... */ int dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) { diff --git a/dbdimp.h b/dbdimp.h index b7eb3705..5f734e55 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -21,6 +21,7 @@ typedef struct imp_fbh_st imp_fbh_t; struct imp_drh_st { dbih_drc_t com; /* MUST be first element in structure */ OCIEnv *envhp; + bool leak_state; SV *ora_long; SV *ora_trunc; SV *ora_cache; @@ -394,6 +395,7 @@ sb4 reg_taf_callback _((SV *dbh, imp_dbh_t *imp_dbh)); /* These defines avoid name clashes for multiple statically linked DBD's */ #define dbd_init ora_init +#define dbd_dr_destroy ora_dr_destroy #define dbd_db_login ora_db_login #define dbd_db_login6 ora_db_login6 #define dbd_db_do ora_db_do @@ -402,6 +404,7 @@ sb4 reg_taf_callback _((SV *dbh, imp_dbh_t *imp_dbh)); #define dbd_db_cancel ora_db_cancel #define dbd_db_disconnect ora_db_disconnect #define dbd_db_destroy ora_db_destroy +#define dbd_take_imp_data ora_take_imp_data #define dbd_db_STORE_attrib ora_db_STORE_attrib #define dbd_db_FETCH_attrib ora_db_FETCH_attrib #define dbd_st_prepare ora_st_prepare diff --git a/dist.ini b/dist.ini index c167187c..3124479c 100644 --- a/dist.ini +++ b/dist.ini @@ -30,7 +30,7 @@ authority=cpan:PYTHIAN -remove=CoderwallEndorse [Prereqs / ConfigureRequires] -DBI = 1.51 +DBI = 1.623 [HelpWanted] positions = coder documentation tester diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index cd894389..0139e955 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -45,7 +45,7 @@ package DBD::Oracle; my $Revision = substr(q$Revision: 1.103 $, 10); - require_version DBI 1.51; + require_version DBI 1.623; DBD::Oracle->bootstrap($DBD::Oracle::VERSION); From b07d637fac1741256860fc755e28888b892180f4 Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Sat, 17 Sep 2016 21:44:43 +0200 Subject: [PATCH 499/637] Correct setting of default driver name Don't set OCI_ATTR_DRIVER_NAME on an unallocated session handle, potentially causing corruption or crashes. Set the default driver name to "DBD::Oracle : ", using the de facto standard driver naming scheme. This fixes https://github.com/pythian/DBD-Oracle/issues/32 --- dbdimp.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 2644bd43..132158df 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -442,14 +442,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (DBD_ATTRIB_TRUE(attr,"ora_drcp_incr",13,svp)) DBD_ATTRIB_GET_IV( attr, "ora_drcp_incr", 13, svp, imp_dbh->pool_incr); - imp_dbh->driver_name = "DBD01.50_00"; -#endif - -#ifdef ORA_OCI_112 - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, - imp_dbh->driver_name, - (ub4)strlen(imp_dbh->driver_name), - OCI_ATTR_DRIVER_NAME,imp_dbh->errhp, status); + imp_dbh->driver_name = "DBD::Oracle : " VERSION; #endif /* TAF Events */ @@ -721,6 +714,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { /* connect uisng a DRCP */ + OCIAuthInfo *authp; ub4 purity = OCI_ATTR_PURITY_SELF; /* pool Default values */ if (!imp_dbh->pool_min ) @@ -731,6 +725,14 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->pool_incr = 2; OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->poolhp, OCI_HTYPE_SPOOL, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &authp, OCI_HTYPE_AUTHINFO, status); + + OCIAttrSet_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, + imp_dbh->driver_name, (ub4)strlen(imp_dbh->driver_name), + OCI_ATTR_DRIVER_NAME, imp_dbh->errhp, status); + + OCIAttrSet_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL, + authp, (ub4)0, OCI_ATTR_SPOOL_AUTH, imp_dbh->errhp, status); OCISessionPoolCreate_log_stat( imp_dbh, @@ -754,12 +756,15 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S oci_error(dbh, imp_dbh->errhp, status, "OCISessionPoolCreate"); OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); + OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); return 0; } + OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_AUTHINFO, status); OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, @@ -826,6 +831,12 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); +#ifdef ORA_OCI_112 + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, (ub4)OCI_HTYPE_SESSION, + imp_dbh->driver_name, (ub4)strlen(imp_dbh->driver_name), + (ub4)OCI_ATTR_DRIVER_NAME, imp_dbh->errhp, status); +#endif + OCISessionBegin_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp,cred_type, sess_mode_type, status); if (status == OCI_SUCCESS_WITH_INFO) { From acc03fe124af127352327a675a1d0f1464bbedac Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Sat, 17 Sep 2016 21:55:15 +0200 Subject: [PATCH 500/637] Add configuration for Oracle Fast Application Notification (FAN) Facilitate setting of OCI_EVENTS in a new OCI environment via the attribute ora_events or the environment variable ORA_EVENTS. --- dbdimp.c | 4 ++++ lib/DBD/Oracle.pm | 11 +++++++++++ oci8.c | 4 +++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/dbdimp.c b/dbdimp.c index 132158df..6250627e 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -550,6 +550,10 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!imp_dbh->envhp ) { SV **init_mode_sv; ub4 init_mode = OCI_OBJECT;/* needed for LOBs (8.0.4) */ + + if (DBD_ATTRIB_TRUE(attr, "ora_events", 10, svp)) + init_mode |= OCI_EVENTS; /* Needed for Oracle Fast Application Notification (FAN). */ + DBD_ATTRIB_GET_IV(attr, "ora_init_mode",13, init_mode_sv, init_mode); #if defined(USE_ITHREADS) || defined(MULTIPLICITY) || defined(USE_5005THREADS) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 0139e955..d8e77294 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -295,6 +295,10 @@ package DBD::Oracle; $attr->{ora_drcp_incr} = $ENV{ORA_DRCP_INCR} } + if (exists $ENV{ORA_EVENTS}) { + $attr->{ora_events} = $ENV{ORA_EVENTS}; + } + { local @SIG{ @{ $attr->{ora_connect_with_default_signals} } } if $attr->{ora_connect_with_default_signals}; @@ -394,6 +398,7 @@ package DBD::Oracle; ora_svchp => undef, ora_errhp => undef, ora_init_mode => undef, + ora_events => undef, ora_charset => undef, ora_ncharset => undef, ora_session_mode => undef, @@ -1761,6 +1766,12 @@ string. $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; +=head4 ora_events + +Set this attribute to C<1> to enable Oracle Fast Application Notification +(FAN) in a new OCI environment. Can also be set via the C +environment variable. + =head4 ora_envhp The first time a connection is made a new OCI 'environment' is diff --git a/oci8.c b/oci8.c index 794450e8..1e19b287 100644 --- a/oci8.c +++ b/oci8.c @@ -289,7 +289,9 @@ oci_mode(ub4 mode) dTHX; SV *sv; switch (mode) { - case 3: return "THREADED | OBJECT"; + case OCI_THREADED | OCI_OBJECT: return "THREADED | OBJECT"; + case OCI_OBJECT | OCI_EVENTS: return "OBJECT | EVENTS"; + case OCI_THREADED | OCI_OBJECT | OCI_EVENTS: return "THREADED | OBJECT | EVENTS"; case OCI_DEFAULT: return "DEFAULT"; /* the default value for parameters and attributes */ /*-------------OCIInitialize Modes / OCICreateEnvironment Modes -------------*/ From a3472a2fd350ad4a128902dd1dd2f1855fed7983 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 23 Apr 2018 12:14:47 +1000 Subject: [PATCH 501/637] Fix for GH36 --- dbdimp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dbdimp.c b/dbdimp.c index 6250627e..76b93435 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3046,6 +3046,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) (text*)phs->name, (sb4)strlen(phs->name), phs->progv, phs->maxlen ? (sb4)phs->maxlen : 1, /* else bind "" fails */ + (sb4)phs->maxlen, (ub2)phs->ftype, &phs->indp, NULL, /* ub2 *alen_ptr not needed with OCIBindDynamic */ &phs->arcode, @@ -3924,6 +3925,7 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er /*check to see if value sv is a null (undef) if it is upgrade it*/ if (!SvOK(sv)) { (void)SvUPGRADE(sv, SVt_PV); + len = 0; } else { SvPV(sv, len); From 6e1527c92d4a624d84edf5070465195ddf87bd31 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 23 Apr 2018 12:33:07 +1000 Subject: [PATCH 502/637] Fix in/from #56 --- t/25plsql.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/25plsql.t b/t/25plsql.t index da18a8b1..2e5dd531 100644 --- a/t/25plsql.t +++ b/t/25plsql.t @@ -244,7 +244,7 @@ if (1) { # compare results with normal execution of query my $s1 = $dbh->selectall_arrayref($cur_query, undef, "V%"); my @s1 = map { @$_ } @$s1; - is("@r", "@s1", "ref = sql"); + is(join(' ',sort@r), join(' ',sort@s2), 'ref = sql'); # --- test re-bind and re-execute of same 'parent' statement my $cur1_str = "$cur1"; From eed913c403634c12714a52fa39f8e3a02068c5d9 Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Sat, 17 Sep 2016 21:55:15 +0200 Subject: [PATCH 503/637] Add configuration for Oracle Fast Application Notification (FAN) Facilitate setting of OCI_EVENTS in a new OCI environment via the attribute ora_events or the environment variable ORA_EVENTS. --- lib/DBD/Oracle.pm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index d8e77294..10891b03 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -299,6 +299,10 @@ package DBD::Oracle; $attr->{ora_events} = $ENV{ORA_EVENTS}; } + if (exists $ENV{ORA_EVENTS}) { + $attr->{ora_events} = $ENV{ORA_EVENTS}; + } + { local @SIG{ @{ $attr->{ora_connect_with_default_signals} } } if $attr->{ora_connect_with_default_signals}; From 11cac2dbf2837f6d17f59d21f37c30d7dd0584ea Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Sat, 17 Sep 2016 21:59:25 +0200 Subject: [PATCH 504/637] Rewrite DRCP session pooling to work as intended Rewrite of DRCP session pooling, influenced by PHP's oci8.c Enable sharing (reuse) of server sessions, and implement caching of the client side of the session pool(s) between connects, keeping the connection(s) to the DRCP Connection Broker. Depending on server hardware and network latency, subsequent connects are now up to several hundred times faster than before the rewrite. Use session tagging to fetch shared server sessions with correct NLS character sets. The attribute ora_drcp_rlb or the environment variable ORA_DRCP_RLB controls runtime connection load balancing for Oracle RAC. Documentation update. All tests pass with ORA_DRCP=1, with the exception of t/60reauth.t (it goes without saying that reauthentication does not work with session pooling). (updated ocitrace.h - Dean Hamstead) --- dbdimp.c | 482 +++++++++++++++++++++++++++++++--------------- dbdimp.h | 24 ++- lib/DBD/Oracle.pm | 46 ++++- oci8.c | 16 +- ocitrace.h | 24 +-- 5 files changed, 400 insertions(+), 192 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 76b93435..fdfd07d9 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -219,6 +219,31 @@ dbd_dr_destroy(SV *drh, imp_drh_t *imp_drh) /* Free cached environment handle. */ OCIHandleFree_log_stat(imp_drh, imp_drh->envhp, OCI_HTYPE_ENV, status); } + +#ifdef ORA_OCI_112 + /* Free session pool resources. */ + if (imp_drh->pool_hv) { + HE *pool_he; + hv_iterinit(imp_drh->pool_hv); + while ((pool_he = hv_iternext(imp_drh->pool_hv))) { + session_pool_t *pool = (session_pool_t*)SvPVX(HeVAL(pool_he)); + /* Only destroy the session pool if there are no active sessions left. + If there are active sessions left, this is because "InactiveDestroy" + is set on one or more db handles. */ + if (!pool->active_sessions) { + OCISessionPoolDestroy_log_stat(imp_drh, pool->poolhp, pool->errhp, status); + } + OCIHandleFree_log_stat(imp_drh, pool->poolhp, OCI_HTYPE_SPOOL, status); + OCIHandleFree_log_stat(imp_drh, pool->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_drh, pool->envhp, OCI_HTYPE_ENV, status); + } + hv_undef(imp_drh->pool_hv); + } + + if (imp_drh->charset_hv) { + hv_undef(imp_drh->charset_hv); + } +#endif } @@ -382,6 +407,23 @@ fb_ary_free(fb_ary_t *fb_ary) } +#ifdef ORA_OCI_112 +/* Helper functions to fetch cached session pool. */ +static SV * +pool_key(imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, int csid, int ncsid) +{ + return newSVpvf("%s/%s@%s class=%.*s,csid=%d,ncsid=%d", uid, pwd, dbname, imp_dbh->pool_classl, imp_dbh->pool_class, csid, ncsid); +} + +static session_pool_t * +pool_fetch(imp_drh_t *imp_drh, SV *key) +{ + dTHX; + HE *pool_he = hv_fetch_ent(imp_drh->pool_hv, key, 0, 0); + return pool_he ? (session_pool_t *)SvPVX(HeVAL(pool_he)) : NULL; +} +#endif + /* ================================================================== */ @@ -422,6 +464,8 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S #endif #ifdef ORA_OCI_112 + session_pool_t *pool = NULL; + /*check to see if the user is connecting with DRCP */ if (DBD_ATTRIB_TRUE(attr,"ora_drcp",8,svp)) imp_dbh->using_drcp = 1; @@ -441,6 +485,8 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S DBD_ATTRIB_GET_IV( attr, "ora_drcp_max", 12, svp, imp_dbh->pool_max); if (DBD_ATTRIB_TRUE(attr,"ora_drcp_incr",13,svp)) DBD_ATTRIB_GET_IV( attr, "ora_drcp_incr", 13, svp, imp_dbh->pool_incr); + if (DBD_ATTRIB_TRUE(attr,"ora_drcp_rlb",12,svp)) + DBD_ATTRIB_GET_IV( attr, "ora_drcp_rlb", 12, svp, imp_dbh->pool_rlb); imp_dbh->driver_name = "DBD::Oracle : " VERSION; #endif @@ -534,18 +580,79 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->get_oci_handle = oci_db_handle; - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_envhp", 9)) && SvOK(*svp)) { - if (!SvTRUE(*svp)) { - imp_dbh->envhp = NULL; /* force new environment */ +#ifdef ORA_OCI_112 + if (!imp_dbh->using_drcp) { +#endif + if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_envhp", 9)) && SvOK(*svp)) { + if (!SvTRUE(*svp)) { + imp_dbh->envhp = NULL; /* force new environment */ + } } + /* RT46739 */ + if (imp_dbh->envhp) { + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); + if (status != OCI_SUCCESS) { + imp_dbh->envhp = NULL; + } + } +#ifdef ORA_OCI_112 } - /* RT46739 */ - if (imp_dbh->envhp) { - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); - if (status != OCI_SUCCESS) { - imp_dbh->envhp = NULL; - } - } + else if (!shared_dbh) { + /* Try to find session pool in cache. */ + imp_dbh->envhp = NULL; + + if (!imp_drh->charset_hv) { + imp_drh->charset_hv = newHV(); + } + if (!imp_drh->pool_hv) { + imp_drh->pool_hv = newHV(); + } + + /* Get charset and ncharset IDs. */ + if ((svp = DBD_ATTRIB_GET_SVP(attr, "ora_charset", 11))) { + /* Charset name from parameter; try looking up previously used ID. */ + HE *charset_he = hv_fetch_ent(imp_drh->charset_hv, *svp, 0, 0); + charsetid = charset_he ? SvIV(HeVAL(charset_he)) : 0; + } + else { + /* Get charset ID from the NLS environment. */ + size_t rsize; + OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &charsetid, 0, OCI_NLS_CHARSET_ID, 0, &rsize, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, NULL, status, + "OCINlsEnvironmentVariableGet(OCI_NLS_CHARSET_ID) Check NLS settings etc."); + return 0; + } + } + if ((svp = DBD_ATTRIB_GET_SVP(attr, "ora_ncharset", 12))) { + /* Charset name from parameter; try looking up previously used ID. */ + HE *charset_he = hv_fetch_ent(imp_drh->charset_hv, *svp, 0, 0); + ncharsetid = charset_he ? SvIV(HeVAL(charset_he)) : 0; + } + else { + /* Get charset ID from the NLS environment. */ + size_t rsize; + OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &ncharsetid, 0, OCI_NLS_NCHARSET_ID, 0, &rsize, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, NULL, status, + "OCINlsEnvironmentVariableGet(OCI_NLS_NCHARSET_ID) Check NLS settings etc."); + return 0; + } + } + + if (charsetid && ncharsetid) { + /* Look up session pool initialized with the same dbname, uid/pwd, connection class, and charsets. */ + SV *key_sv = pool_key(imp_dbh, dbname, uid, pwd, charsetid, ncharsetid); + + if ((pool = pool_fetch(imp_drh, key_sv))) { + imp_dbh->pool = pool; + imp_dbh->envhp = pool->envhp; + } + + sv_free(key_sv); + } + } +#endif if (!imp_dbh->envhp ) { SV **init_mode_sv; @@ -617,6 +724,13 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!new_charsetid) { croak("ora_charset value (%s) is not valid", SvPV_nolen(*svp)); } + +#ifdef ORA_OCI_112 + if (imp_dbh->using_drcp) { + /* Store lookup from charset name to charset ID. */ + (void)hv_store_ent(imp_drh->charset_hv, *svp, newSViv(new_charsetid), 0); + } +#endif } svp = DBD_ATTRIB_GET_SVP(attr, "ora_ncharset", 12); /*get the ncharset passed in by the user*/ @@ -630,6 +744,13 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!new_ncharsetid) { croak("ora_ncharset value (%s) is not valid", SvPV_nolen(*svp)); } + +#ifdef ORA_OCI_112 + if (imp_dbh->using_drcp) { + /* Store lookup from charset name to charset ID. */ + (void)hv_store_ent(imp_drh->charset_hv, *svp, newSViv(new_ncharsetid), 0); + } +#endif } if (new_charsetid || new_ncharsetid) { /* reset the ENV with the new charset from above*/ @@ -645,8 +766,11 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S } } - if (!imp_drh->envhp) /* cache first envhp info drh as future default */ - imp_drh->envhp = imp_dbh->envhp; +#ifdef ORA_OCI_112 + if (!imp_dbh->using_drcp) +#endif + if (!imp_drh->envhp) /* cache first envhp info drh as future default */ + imp_drh->envhp = imp_dbh->envhp; /* update the hard-coded csid constants for unicode charsets */ utf8_csid = OCINlsCharSetNameToId(imp_dbh->envhp, (void*)"UTF8"); @@ -654,6 +778,21 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S al16utf16_csid = OCINlsCharSetNameToId(imp_dbh->envhp, (void*)"AL16UTF16"); } +#ifdef ORA_OCI_112 + if (imp_dbh->using_drcp) { + /* Try looking up session pool again, in case ora_charsetid/ora_ncharsetid were used to specify previously used charset IDs from the NLS environment. */ + SV *key_sv = pool_key(imp_dbh, dbname, uid, pwd, charsetid, ncharsetid); + + if ((pool = pool_fetch(imp_drh, key_sv))) { + imp_dbh->pool = pool; + /* Free the current environment handle and replace it with the session pool's environment handle. */ + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); + imp_dbh->envhp = pool->envhp; + } + + sv_free(key_sv); + } +#endif } if (!imp_dbh->errhp) { @@ -700,173 +839,190 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (!shared_dbh) { - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCIServerAttach"); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - return 0; - } - - { - SV **sess_mode_type_sv; - ub4 sess_mode_type = OCI_DEFAULT; - ub4 cred_type; - DBD_ATTRIB_GET_IV(attr, "ora_session_mode",16, sess_mode_type_sv, sess_mode_type); - #ifdef ORA_OCI_112 - if (imp_dbh->using_drcp) { /* connect uisng a DRCP */ - OCIAuthInfo *authp; - ub4 purity = OCI_ATTR_PURITY_SELF; - /* pool Default values */ - if (!imp_dbh->pool_min ) - imp_dbh->pool_min = 4; - if (!imp_dbh->pool_max ) - imp_dbh->pool_max = 40; - if (!imp_dbh->pool_incr) - imp_dbh->pool_incr = 2; - - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->poolhp, OCI_HTYPE_SPOOL, status); - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &authp, OCI_HTYPE_AUTHINFO, status); + if (imp_dbh->using_drcp) { /* connect using a DRCP */ + OCIAuthInfo *authp; + ub4 purity = OCI_ATTR_PURITY_SELF; + /* pool Default values */ + if (!imp_dbh->pool_min ) + imp_dbh->pool_min = 0; + if (!imp_dbh->pool_max ) + imp_dbh->pool_max = 40; + if (!imp_dbh->pool_incr) + imp_dbh->pool_incr = 1; + if (!imp_dbh->pool_rlb) + imp_dbh->pool_rlb = 0; + + if (!pool) { + /* Create and cache new session pool struct. */ + SV *key_sv = pool_key(imp_dbh, dbname, uid, pwd, charsetid, ncharsetid); + + session_pool_t pool_data = { }; + SV *pool_sv = newSVpvn((char*)&pool_data, sizeof(pool_data)); + HE *pool_he = hv_store_ent(imp_drh->pool_hv, key_sv, pool_sv, 0); + imp_dbh->pool = pool = (session_pool_t*)SvPVX(HeVAL(pool_he)); + pool->envhp = imp_dbh->envhp; + + sv_free(key_sv); + + OCIHandleAlloc_ok(imp_dbh, pool->envhp, &pool->poolhp, OCI_HTYPE_SPOOL, status); + OCIHandleAlloc_ok(imp_dbh, pool->envhp, &authp, OCI_HTYPE_AUTHINFO, status); + /* Create an unshared error handle for use in pool creation and destruction. */ + OCIHandleAlloc_ok(imp_dbh, pool->envhp, &pool->errhp, OCI_HTYPE_ERROR, status); OCIAttrSet_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, imp_dbh->driver_name, (ub4)strlen(imp_dbh->driver_name), - OCI_ATTR_DRIVER_NAME, imp_dbh->errhp, status); + OCI_ATTR_DRIVER_NAME, pool->errhp, status); - OCIAttrSet_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL, - authp, (ub4)0, OCI_ATTR_SPOOL_AUTH, imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, pool->poolhp, OCI_HTYPE_SPOOL, + authp, (ub4)0, OCI_ATTR_SPOOL_AUTH, pool->errhp, status); + + ora_parse_uid(imp_dbh, &uid, &pwd); OCISessionPoolCreate_log_stat( - imp_dbh, - imp_dbh->envhp, - imp_dbh->errhp, - imp_dbh->poolhp, - (OraText **) &imp_dbh->pool_name, - (ub4 *) &imp_dbh->pool_namel, - (OraText *) dbname, - (ub4)strlen(dbname), - imp_dbh->pool_min, - imp_dbh->pool_max, - imp_dbh->pool_incr, - (OraText *) uid, - (ub4)strlen(uid), - (OraText *) pwd, - (ub4)strlen(pwd), - status); + imp_dbh, + pool->envhp, + pool->errhp, + pool->poolhp, + &pool->pool_name, + &pool->pool_namel, + (OraText *) dbname, + (ub4)strlen(dbname), + imp_dbh->pool_min, + imp_dbh->pool_max, + imp_dbh->pool_incr, + (OraText *) uid, + (ub4)strlen(uid), + (OraText *) pwd, + (ub4)strlen(pwd), + OCI_SPC_HOMOGENEOUS | (imp_dbh->pool_rlb ? 0 : OCI_SPC_NO_RLB), + status); if (status != OCI_SUCCESS) { - - oci_error(dbh, imp_dbh->errhp, status, "OCISessionPoolCreate"); - OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); + oci_error(dbh, pool->errhp, status, "OCISessionPoolCreate"); OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, pool->poolhp, OCI_HTYPE_SPOOL,status); + OCIHandleFree_log_stat(imp_dbh, pool->errhp, OCI_HTYPE_ERROR, status); + /* Free the global error handle as well. */ + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, pool->envhp, OCI_HTYPE_ENV, status); + + (void)hv_delete_ent(imp_drh->pool_hv, HeSVKEY(pool_he), 0, 0); return 0; } OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); + } - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->authp, OCI_HTYPE_AUTHINFO, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &authp, OCI_HTYPE_AUTHINFO, status); - OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, - &purity, (ub4) 0,(ub4) OCI_ATTR_PURITY, imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, authp, (ub4) OCI_HTYPE_AUTHINFO, + &purity, (ub4) 0,(ub4) OCI_ATTR_PURITY, imp_dbh->errhp, status); - if (imp_dbh->pool_class) /*pool_class may or may not be used */ - OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, (ub4) OCI_HTYPE_AUTHINFO, - (OraText *) imp_dbh->pool_class, (ub4) imp_dbh->pool_classl, - (ub4) OCI_ATTR_CONNECTION_CLASS, imp_dbh->errhp, status); + if (imp_dbh->pool_class) /*pool_class may or may not be used */ + OCIAttrSet_log_stat(imp_dbh, authp, (ub4) OCI_HTYPE_AUTHINFO, + (OraText *) imp_dbh->pool_class, (ub4) imp_dbh->pool_classl, + (ub4) OCI_ATTR_CONNECTION_CLASS, imp_dbh->errhp, status); - cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); + /* Use session tagging to get a server session initalized with correct charsets. */ + sprintf((char*)imp_dbh->session_tag, "csid=%d,ncsid=%d", charsetid, ncharsetid); - OCISessionGet_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, &imp_dbh->svchp, imp_dbh->authp, - imp_dbh->pool_name, (ub4)strlen((char *)imp_dbh->pool_name), status); + OCISessionGet_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, &imp_dbh->svchp, authp, + pool->pool_name, (ub4)strlen((char *)pool->pool_name), + imp_dbh->session_tag, (ub4)strlen((char *)imp_dbh->session_tag), &imp_dbh->session_tag_found, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCISessionGet"); + OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); + return 0; + } - if (status != OCI_SUCCESS) { + /* Update number of active sessions in the pool. */ + ++imp_dbh->pool->active_sessions; - oci_error(dbh, imp_dbh->errhp, status, "OCISessionGet"); - OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); - OCISessionPoolDestroy_log_stat( - imp_dbh, imp_dbh->poolhp, imp_dbh->errhp,status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - return 0; - } + OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); - if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { + /* Get server and session handles from service context handle, allocated by OCISessionGet. */ + OCIAttrGet_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, &imp_dbh->srvhp, NULL, + OCI_ATTR_SERVER, imp_dbh->errhp, status); + OCIAttrGet_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, &imp_dbh->seshp, NULL, + OCI_ATTR_SESSION, imp_dbh->errhp, status); + + if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { + PerlIO_printf( + DBIc_LOGPIO(imp_dbh), + "Using DRCP with session settings min=%d, max=%d, and increment=%d\n", + imp_dbh->pool_min, + imp_dbh->pool_max, + imp_dbh->pool_incr); + if (imp_dbh->pool_class) PerlIO_printf( - DBIc_LOGPIO(imp_dbh), - "Using DRCP with session settings min=%d, max=%d, and increment=%d\n", - imp_dbh->pool_min, - imp_dbh->pool_max, - imp_dbh->pool_incr); - if (imp_dbh->pool_class) - PerlIO_printf( - DBIc_LOGPIO(imp_dbh), - "with connection class=%s\n",imp_dbh->pool_class); - } + DBIc_LOGPIO(imp_dbh), + "with connection class=%s\n",imp_dbh->pool_class); + } - } - else { + } + else { #endif /* ORA_OCI_112 */ - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); - OCIServerAttach_log_stat(imp_dbh, dbname,OCI_DEFAULT, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCIServerAttach"); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); - if (imp_dbh->envhp != imp_drh->envhp) { - OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); - } - return 0; - } + SV **sess_mode_type_sv; + ub4 sess_mode_type = OCI_DEFAULT; + ub4 cred_type; + DBD_ATTRIB_GET_IV(attr, "ora_session_mode",16, sess_mode_type_sv, sess_mode_type); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->seshp, OCI_HTYPE_SESSION, status); + OCIServerAttach_log_stat(imp_dbh, dbname,OCI_DEFAULT, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCIServerAttach"); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + if (imp_dbh->envhp != imp_drh->envhp) { + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); + } + return 0; + } - OCIAttrSet_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, - (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp, status); - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->seshp, OCI_HTYPE_SESSION, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, + (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp, status); - cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); + cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); #ifdef ORA_OCI_112 - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, (ub4)OCI_HTYPE_SESSION, - imp_dbh->driver_name, (ub4)strlen(imp_dbh->driver_name), - (ub4)OCI_ATTR_DRIVER_NAME, imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, (ub4)OCI_HTYPE_SESSION, + imp_dbh->driver_name, (ub4)strlen(imp_dbh->driver_name), + (ub4)OCI_ATTR_DRIVER_NAME, imp_dbh->errhp, status); #endif - OCISessionBegin_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp,cred_type, sess_mode_type, status); + OCISessionBegin_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp,cred_type, sess_mode_type, status); - if (status == OCI_SUCCESS_WITH_INFO) { - /* eg ORA-28011: the account will expire soon; change your password now */ - oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); - status = OCI_SUCCESS; - } - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); - OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); - if (imp_dbh->envhp != imp_drh->envhp) { - OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); - } - return 0; - } + if (status == OCI_SUCCESS_WITH_INFO) { + /* eg ORA-28011: the account will expire soon; change your password now */ + oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); + status = OCI_SUCCESS; + } + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); + OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + if (imp_dbh->envhp != imp_drh->envhp) { + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); + } + return 0; + } - OCIAttrSet_log_stat(imp_dbh, imp_dbh->svchp, (ub4) OCI_HTYPE_SVCCTX, - imp_dbh->seshp, (ub4) 0,(ub4) OCI_ATTR_SESSION, imp_dbh->errhp, status); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->svchp, (ub4) OCI_HTYPE_SVCCTX, + imp_dbh->seshp, (ub4) 0,(ub4) OCI_ATTR_SESSION, imp_dbh->errhp, status); #ifdef ORA_OCI_112 - } + } #endif - } } @@ -1018,23 +1174,33 @@ dbd_db_disconnect(SV *dbh, imp_dbh_t *imp_dbh) /* See DBI Driver.xst file for the DBI approach. */ if (refcnt == 1 ) { - sword s_se, s_sd; #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { - OCISessionRelease_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp,s_se); + sword status; + /* Release session, tagged for future retrieval. */ + OCISessionRelease_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, + imp_dbh->session_tag, (ub4)strlen((char *)imp_dbh->session_tag), imp_dbh->session_tag_found ? OCI_DEFAULT : OCI_SESSRLS_RETAG, status); + if (status != OCI_SUCCESS) { + oci_error(dbh, imp_dbh->errhp, status, "OCISessionRelease"); + return 0; + } + + /* Update number of active sessions in the pool */ + --imp_dbh->pool->active_sessions; } else { #endif + sword s_se, s_sd; OCISessionEnd_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, OCI_DEFAULT, s_se); + if (s_se) oci_error(dbh, imp_dbh->errhp, s_se, "OCISessionEnd"); + OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, s_sd); + if (s_sd) oci_error(dbh, imp_dbh->errhp, s_sd, "OCIServerDetach"); + if (s_se != OCI_SUCCESS || s_sd != OCI_SUCCESS) + return 0; #ifdef ORA_OCI_112 } #endif - if (s_se) oci_error(dbh, imp_dbh->errhp, s_se, "OCISessionEnd"); - OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, s_sd); - if (s_sd) oci_error(dbh, imp_dbh->errhp, s_sd, "OCIServerDetach"); - if (s_se || s_sd) - return 0; } /* We don't free imp_dbh since a reference still exists */ /* The DESTROY method is the only one to 'free' memory. */ @@ -1059,8 +1225,6 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) #endif if (refcnt == 1) { - sword status; - if (DBIc_ACTIVE(imp_dbh)) dbd_db_disconnect(dbh, imp_dbh); if (is_extproc) @@ -1082,22 +1246,20 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) #ifdef ORA_OCI_112 if (imp_dbh->using_drcp) { - OCIHandleFree_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION,status); - OCISessionPoolDestroy_log_stat(imp_dbh, imp_dbh->poolhp, imp_dbh->errhp,status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->poolhp, OCI_HTYPE_SPOOL,status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); } else { #endif OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + if (imp_dbh->envhp != imp_drh->envhp) { + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); + } #ifdef ORA_OCI_112 } #endif - OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - if (imp_dbh->envhp != imp_drh->envhp) { - OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); - } } else { /* A new error handle is allocated on each new connect, so it is also freed when @@ -1167,6 +1329,9 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) else if (kl==13 && strEQ(key, "ora_drcp_incr") ) { imp_dbh->pool_incr = SvIV (valuesv); } + else if (kl==12 && strEQ(key, "ora_drcp_rlb") ) { + imp_dbh->pool_rlb = SvIV (valuesv); + } #endif else if (kl==16 && strEQ(key, "ora_taf_function") ) { if (imp_dbh->taf_function) @@ -1288,6 +1453,9 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) else if (kl==13 && strEQ(key, "ora_drcp_incr") ) { retsv = newSViv(imp_dbh->pool_incr); } + else if (kl==12 && strEQ(key, "ora_drcp_rlb") ) { + retsv = newSViv(imp_dbh->pool_rlb); + } #endif else if (kl==16 && strEQ(key, "ora_taf_function") ) { if (imp_dbh->taf_function) { diff --git a/dbdimp.h b/dbdimp.h index 5f734e55..5b48aa21 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -22,12 +22,28 @@ struct imp_drh_st { dbih_drc_t com; /* MUST be first element in structure */ OCIEnv *envhp; bool leak_state; +#ifdef ORA_OCI_112 + HV *charset_hv; + HV *pool_hv; +#endif SV *ora_long; SV *ora_trunc; SV *ora_cache; SV *ora_cache_o; /* for ora_open() cache override */ }; +#ifdef ORA_OCI_112 +typedef struct session_pool_st session_pool_t; +struct session_pool_st { + OCIEnv *envhp; + OCIError *errhp; + OCISPool *poolhp; + OraText *pool_name; + ub4 pool_namel; + int active_sessions; +}; +#endif + /* Define dbh implementor data structure */ struct imp_dbh_st { dbih_dbc_t com; /* MUST be first element in structure */ @@ -45,16 +61,16 @@ struct imp_dbh_st { OCISvcCtx *svchp; OCISession *seshp; #ifdef ORA_OCI_112 - OCIAuthInfo *authp; - OCISPool *poolhp; - text *pool_name; - ub4 pool_namel; + session_pool_t *pool; + OraText session_tag[50]; + boolean session_tag_found; bool using_drcp; text *pool_class; ub4 pool_classl; ub4 pool_min; ub4 pool_max; ub4 pool_incr; + ub4 pool_rlb; char *driver_name;/*driver name user defined*/ #endif SV *taf_function; /*User supplied TAF functiomn*/ diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 10891b03..3ede247c 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -294,6 +294,9 @@ package DBD::Oracle; if (exists $ENV{ORA_DRCP_INCR}) { $attr->{ora_drcp_incr} = $ENV{ORA_DRCP_INCR} } + if (exists $ENV{ORA_DRCP_RLB}) { + $attr->{ora_drcp_rlb} = $ENV{ORA_DRCP_RLB} + } if (exists $ENV{ORA_EVENTS}) { $attr->{ora_events} = $ENV{ORA_EVENTS}; @@ -415,6 +418,7 @@ package DBD::Oracle; ora_drcp_min => undef, ora_drcp_max => undef, ora_drcp_incr => undef, + ora_drcp_rlb => undef, ora_oratab_orahome => undef, ora_module_name => undef, ora_driver_name => undef, @@ -1583,16 +1587,24 @@ than 1024 characters. This value can be also be specified with the C environment variable. +Note that a connection class must be specified in order to enable +inter-process sharing of server side sessions. + =head4 ora_drcp_min This optional value specifies the minimum number of sessions that are -initially opened. New sessions are only opened after this value has -been reached. +initially allocated for the application process. New sessions are only +allocated after this value has been reached. + +The default value is 0 and any value greater than or equal to 0 is valid. -The default value is 4 and any value above 0 is valid. +For multi-process applications, it is recommended to leave the value at 0. +This ensures that each process is only occupying a server session while +the process is doing database work. -Generally, it should be set to the number of concurrent statements the -application is planning or expecting to run. +For multi-threaded applications, the value could be set to the number of +concurrent statements the application is planning or expecting to run. +Please note that DRCP has not been tested with multi-threading. This value can also be specified with the C environment variable. @@ -1601,7 +1613,7 @@ variable. This optional value specifies the maximum number of sessions that can be open at one time. Once reached no more sessions can be opened -until one becomes free. The default value is 40 and any value above 1 +until one becomes free. The default value is 40 and any value above 0 is valid. You should not set this value lower than ora_drcp_min as that will just waste resources. @@ -1612,13 +1624,22 @@ variable. This optional value specifies the next increment for sessions to be started if the current number of sessions are less than -ora_drcp_max. The default value is 2 and any value above 0 is +ora_drcp_max. The default value is 1 and any value above 0 is valid as long as the value of ora_drcp_min + ora_drcp_incr is not greater than ora_drcp_max. This value can also be specified with the C environment variable. +=head4 ora_drcp_rlb + +This optional value controls whether run-time connection load balancing +is used for Oracle RAC. The default value is 0, which disables the feature. +Set the value to 1 to enable the feature. + +This value can also be specified with the C environment +variable. + =head4 ora_taf This attribute was removed in 1.49_00 as it was redundant. To @@ -1681,6 +1702,8 @@ TWO_TASK) environment variable to connect to a local instance. Also the username and password should be empty, and the user executing the script needs to be part of the dba group or osdba group. +Note that this does not work with DRCP. + =head4 ora_oratab_orahome Passing a true value for the ora_oratab_orahome attribute will make @@ -1792,6 +1815,11 @@ such as the local NLS environment. By altering C<%ENV> and setting ora_envhp to 0 you can create connections with different NLS settings. This is most useful for testing. +Note that for DRCP, setting C has no effect. Here, +a new session pool is created, using the current NLS environment, +for each new combination of dbname, uid/pwd, connection class, +and charset/ncharset. + =head4 ora_charset, ora_ncharset For oracle versions >= 9.2 you can specify the client charset and @@ -1949,7 +1977,7 @@ variables. =head2 B Implemented by DBI, no driver-specific impact. -Please note that connect_cached as not been tested with DRCP. +Please note that connect_cached has not been tested with DRCP. =head2 B @@ -2121,7 +2149,7 @@ DBMS_OUTPUT.PUT, or DBMS_OUTPUT.NEW_LINE. =head2 B Starts a new session against the current database using the credentials -supplied. +supplied. Note that this does not work with DRCP. =head2 B diff --git a/oci8.c b/oci8.c index 1e19b287..0d3f2b93 100644 --- a/oci8.c +++ b/oci8.c @@ -4271,16 +4271,7 @@ ora_parse_uid(imp_dbh_t *imp_dbh, char **uidp, char **pwdp) return OCI_CRED_EXT; } #ifdef ORA_OCI_112 - if (imp_dbh->using_drcp){ - OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION, - *uidp, strlen(*uidp), - (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp, status); - - OCIAttrSet_log_stat(imp_dbh, imp_dbh->authp, OCI_HTYPE_SESSION, - (strlen(*pwdp)) ? *pwdp : NULL, strlen(*pwdp), - (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp, status); - } - else { + if (!imp_dbh->using_drcp) { #endif OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, *uidp, strlen(*uidp), @@ -4301,6 +4292,11 @@ ora_db_reauthenticate(SV *dbh, imp_dbh_t *imp_dbh, char *uid, char *pwd) { dTHX; sword status; +#ifdef ORA_OCI_112 + if (imp_dbh->using_drcp) { + return 0; + } +#endif /* XXX should possibly create new session before ending the old so */ /* that if the new one can't be created, the old will still work. */ OCISessionEnd_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, diff --git a/ocitrace.h b/ocitrace.h index 2ea5cbb2..dc3d09f7 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -44,12 +44,12 @@ OciTp, sc,oci_status_name(stat)),stat \ : stat -#define OCISessionRelease_log_stat(impdbh,svchp, errhp,stat) \ - stat =OCISessionRelease(svchp, errhp, NULL, (ub4)0, OCI_DEFAULT);\ +#define OCISessionRelease_log_stat(impdbh,svchp,errhp,tag,tagl,mode,stat) \ + stat =OCISessionRelease(svchp, errhp, tag, tagl, mode);\ (DBD_OCI_TRACEON(impdbh)) \ ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ - "%sOCISessionRelease(svchp=%p)=%s\n",\ - OciTp, svchp,oci_status_name(stat)),stat \ + "%sOCISessionRelease(svchp=%p,tag=\"%s\",mode=%u)=%s\n",\ + OciTp, svchp,tag,mode,oci_status_name(stat)),stat \ : stat #define OCISessionPoolDestroy_log_stat(impdbh, ph, errhp,stat ) \ @@ -59,20 +59,20 @@ "%sOCISessionPoolDestroy(ph=%p)=%s\n",\ OciTp, ph,oci_status_name(stat)),stat \ : stat -#define OCISessionGet_log_stat(impdbh,envhp, errhp, sh, ah,pn,pnl,stat) \ - stat =OCISessionGet(envhp, errhp, sh, ah,pn,pnl,NULL,0, NULL, NULL, NULL, OCI_SESSGET_SPOOL);\ +#define OCISessionGet_log_stat(impdbh,envhp,errhp,sh,ah,pn,pnl,tag,tagl,found,stat) \ + stat =OCISessionGet(envhp, errhp, sh, ah,pn,pnl,tag,tagl, NULL, NULL, found, OCI_SESSGET_SPOOL);\ (DBD_OCI_TRACEON(impdbh)) \ ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ - "%sOCISessionGet(envhp=%p,sh=%p,ah=%p,pn=%p,pnl=%d)=%s\n",\ - OciTp, envhp,sh,ah,pn,pnl,oci_status_name(stat)),stat \ + "%sOCISessionGet(envhp=%p,sh=%p,ah=%p,pn=%p,pnl=%d,tag=\"%s\",found=%d)=%s\n",\ + OciTp, envhp,sh,ah,pn,pnl,tag,*found,oci_status_name(stat)),stat \ : stat -#define OCISessionPoolCreate_log_stat(impdbh,envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,stat) \ - stat =OCISessionPoolCreate(envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,OCI_DEFAULT);\ +#define OCISessionPoolCreate_log_stat(impdbh,envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,mode,stat) \ + stat =OCISessionPoolCreate(envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,mode);\ (DBD_OCI_TRACEON(impdbh)) \ ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ - "%sOCISessionPoolCreate(envhp=%p,ph=%p,pn=%p,pnl=%p,min=%d,max=%d,incr=%d, un=%s,unl=%d,pw=%s,pwl=%lu)=%s\n",\ - OciTp, envhp,ph,pn,pnl,sn,sm,si,un,(unsigned long)unl,pw,(unsigned long)pwl,oci_status_name(stat)),stat \ + "%sOCISessionPoolCreate(envhp=%p,ph=%p,pn=%p,pnl=%p,min=%d,max=%d,incr=%d, un=%s,unl=%d,pw=%s,pwl=%d,mode=%u)=%s\n",\ + OciTp, envhp,ph,pn,pnl,sn,sm,si,un,(unsigned long)unl,pw,(unsigned long)pwl,mode,oci_status_name(stat)),stat \ : stat #if defined(ORA_OCI_102) From e752b47135299487719028c9a1f46b174a3c5bd1 Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Fri, 30 Sep 2016 16:43:30 +0200 Subject: [PATCH 505/637] Get correct "tag found" status from OCISessionGet The caller must pass non-NULL pointers for "retTagInfo" and "retTagInfo_len". --- dbdimp.c | 4 +++- ocitrace.h | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index fdfd07d9..3216c573 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -844,6 +844,8 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (imp_dbh->using_drcp) { /* connect using a DRCP */ OCIAuthInfo *authp; ub4 purity = OCI_ATTR_PURITY_SELF; + OraText *rettag; + ub4 rettagl; /* pool Default values */ if (!imp_dbh->pool_min ) imp_dbh->pool_min = 0; @@ -930,7 +932,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S OCISessionGet_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, &imp_dbh->svchp, authp, pool->pool_name, (ub4)strlen((char *)pool->pool_name), - imp_dbh->session_tag, (ub4)strlen((char *)imp_dbh->session_tag), &imp_dbh->session_tag_found, status); + imp_dbh->session_tag, (ub4)strlen((char *)imp_dbh->session_tag), &rettag, &rettagl, &imp_dbh->session_tag_found, status); if (status != OCI_SUCCESS) { oci_error(dbh, imp_dbh->errhp, status, "OCISessionGet"); OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); diff --git a/ocitrace.h b/ocitrace.h index dc3d09f7..bce83bed 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -59,8 +59,8 @@ "%sOCISessionPoolDestroy(ph=%p)=%s\n",\ OciTp, ph,oci_status_name(stat)),stat \ : stat -#define OCISessionGet_log_stat(impdbh,envhp,errhp,sh,ah,pn,pnl,tag,tagl,found,stat) \ - stat =OCISessionGet(envhp, errhp, sh, ah,pn,pnl,tag,tagl, NULL, NULL, found, OCI_SESSGET_SPOOL);\ +#define OCISessionGet_log_stat(impdbh,envhp,errhp,sh,ah,pn,pnl,tag,tagl,rettag,rettagl,found,stat) \ + stat =OCISessionGet(envhp, errhp, sh, ah,pn,pnl,tag,tagl,rettag,rettagl,found, OCI_SESSGET_SPOOL);\ (DBD_OCI_TRACEON(impdbh)) \ ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ "%sOCISessionGet(envhp=%p,sh=%p,ah=%p,pn=%p,pnl=%d,tag=\"%s\",found=%d)=%s\n",\ From 14c12584c5a84e88cfdf7e40fc14b54f51a0e3e7 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 24 Apr 2018 10:02:25 +1000 Subject: [PATCH 506/637] Fix up for GH36 --- dbdimp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 3216c573..33db809b 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3216,7 +3216,6 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) (text*)phs->name, (sb4)strlen(phs->name), phs->progv, phs->maxlen ? (sb4)phs->maxlen : 1, /* else bind "" fails */ - (sb4)phs->maxlen, (ub2)phs->ftype, &phs->indp, NULL, /* ub2 *alen_ptr not needed with OCIBindDynamic */ &phs->arcode, @@ -3822,7 +3821,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp, (text*)phs->name, (sb4)strlen(phs->name), 0, - phs->maxlen ? (sb4)phs->maxlen : 1, /* else bind "" fails */ + (sb4)phs->maxlen, (ub2)phs->ftype, 0, NULL, /* ub2 *alen_ptr not needed with OCIBindDynamic */ 0, From c4b35e542b3b2f271d695a0681f786e2203a4372 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 24 Apr 2018 10:50:59 +1000 Subject: [PATCH 507/637] Fix compile warnings about int vs long unsigned --- oci8.c | 2 +- ocitrace.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/oci8.c b/oci8.c index 0d3f2b93..d05b1fa2 100644 --- a/oci8.c +++ b/oci8.c @@ -1845,7 +1845,7 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, if (dbis->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), - " blob_read field %d, ftype %d, offset %ld, len %u, " + " blob_read field %d, ftype %d, offset %ld, len %lu, " "destoffset %ld, retlen %lu\n", fbh->field_num+1, ftype, offset, (unsigned long) len, destoffset, ul_t(amtp)); diff --git a/ocitrace.h b/ocitrace.h index bce83bed..3955d6fb 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -71,7 +71,7 @@ stat =OCISessionPoolCreate(envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,mode);\ (DBD_OCI_TRACEON(impdbh)) \ ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ - "%sOCISessionPoolCreate(envhp=%p,ph=%p,pn=%p,pnl=%p,min=%d,max=%d,incr=%d, un=%s,unl=%d,pw=%s,pwl=%d,mode=%u)=%s\n",\ + "%sOCISessionPoolCreate(envhp=%p,ph=%p,pn=%p,pnl=%p,min=%d,max=%d,incr=%d, un=%s,unl=%lu,pw=%s,pwl=%lu,mode=%u)=%s\n",\ OciTp, envhp,ph,pn,pnl,sn,sm,si,un,(unsigned long)unl,pw,(unsigned long)pwl,mode,oci_status_name(stat)),stat \ : stat From d2f40e1a59a9b6a234e998d442dce5e02147be69 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 14 May 2018 16:01:12 +1000 Subject: [PATCH 508/637] Make a passing reference to other authors --- lib/DBD/Oracle.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 3ede247c..7b83da49 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -70,7 +70,7 @@ package DBD::Oracle; 'Version' => $VERSION, 'Err' => \my $err, 'Errstr' => \my $errstr, - 'Attribution' => "DBD::Oracle $VERSION using OCI$oci by Tim Bunce", + 'Attribution' => "DBD::Oracle $VERSION using OCI$oci by Tim Bunce et. al.", }); DBD::Oracle::dr::init_oci($drh) ; From d0a1d0953e91e5e42b218d69121363b1d5e44129 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 17 May 2018 16:27:31 +1000 Subject: [PATCH 509/637] Tidy up TODO --- Todo | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Todo b/Todo index bdd90060..f108860d 100644 --- a/Todo +++ b/Todo @@ -1,37 +1,38 @@ [ In no particular order ] -**************************** NOTE: ora_db_shutdown/ora_dv_startup/StrictlyType/DiscardString not documented +**************************** + +NOTE: ora_db_shutdown/ora_dv_startup/StrictlyType/DiscardString not documented User requested a document/link anywhere that details what Oracle client attributes are supported and which are not for Oracle 11g and interacting with a RAC -and using things like TAF, FAN, etc... - +and using things like TAF, FAN, etc... Seems this file has been neglected for quite a while so I will try to keep it up to date for now - -For release 1.26 or later - -Add support for TAF -Add support for New Lob Functions -Add support for Statement Cacheing -Add support for callbacks?? -Drop support for ProC connections + +For release 1.26 or later + +Add support for TAF +Add support for New Lob Functions +Add support for Statement Cacheing +Add support for callbacks?? +Drop support for ProC connections For release 1.22 or later - ---> done 1.22Drop support for Oralce 8 and earlier + +--> done 1.22 Drop support for Oracle 8 and earlier add support for $dbh->trace('SQL'); Replace OCIInitialize + OCIEnvInit, with OCIEnvCreate - + --> done 1.22 dbd_verbose ora_verbose Add in the DBD only debugging flag --> done 1.22 Add new method oci_exe_mode to get the Name of the Execution Modes Add support for OCIClientVersion(),OCIPing(),OCIServerVersion() --->done 1.22 Expand support for Data Interface for Persistent LOBs by setting up support +--> done 1.22 Expand support for Data Interface for Persistent LOBs by setting up support for Piecewise Fetch and Piecewise Fetch with Callback and perhaps Array Fetch as well Add support for version 2 of lob functions @@ -50,8 +51,6 @@ LOBs http://www.csis.gvsu.edu/GeneralInfo/Oracle/appdev.920/a96595/dci06mlt.htm http://technet.oracle.com/tech/oci/htdocs/faq.html#1000425 -Convert most of test.pl into standard t/*.t tests. - Record ORACLE_HOME when building (auto::DBD::Oracle::mk) Check emails from Oracle about that. From def8071cda369ede6eebf978d073520f9e80601b Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 17 May 2018 16:28:53 +1000 Subject: [PATCH 510/637] Rename from Todo to TODO --- Todo => TODO | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Todo => TODO (100%) diff --git a/Todo b/TODO similarity index 100% rename from Todo rename to TODO From 4ed148361be756a6bcc436f5c5ce621c2248c9b2 Mon Sep 17 00:00:00 2001 From: Jochen Hayek Date: Wed, 25 Apr 2018 13:35:57 +0200 Subject: [PATCH 511/637] https://lintian.debian.org/tags/spelling-error-in-manpage.html etc --- dbdimp.c | 2 +- lib/DBD/Oracle.pm | 2 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 2 +- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 4 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 104 +++++++++++------------ oci8.c | 2 +- 6 files changed, 58 insertions(+), 58 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 33db809b..cef45863 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3040,7 +3040,7 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) { D_impdata(imp_sth_csr, imp_sth_t, sth_csr); /* TO_DO */ - /* copy appropriate handles and atributes from parent statement */ + /* copy appropriate handles and attributes from parent statement */ imp_sth_csr->envhp = imp_sth->envhp; imp_sth_csr->errhp = imp_sth->errhp; imp_sth_csr->srvhp = imp_sth->srvhp; diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 7b83da49..164966fe 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -4972,7 +4972,7 @@ The following code will access the data; print $obj1->attr('NAME')."3\n"; # 'Black' is printed print $obj2->attr('NAME')."3\n"; # 'Smith' is printed - # get all atributes as hash reference + # get all attributes as hash reference my $h1 = $obj1->attr; # returns {'NAME' => 'Black', 'AGE' => 25} my $h2 = $obj2->attr; # returns {'NAME' => 'Smith', 'AGE' => 44, # 'SALARY' => 5000 } diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index bc17271d..d3a1f4bb 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -145,7 +145,7 @@ Stephen de Vries ORACLE_USERID.. ORACLE_SID .. - -Run make, all tests should be successfull -against Oracle 9.x at least. + -Run make, all tests should be successful -against Oracle 9.x at least. You should have no problems with Oracle 8.1.7, but accessing Oracle 7.x or previous is not possible (you'll core dump, or simply hang). The same diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index b100f20b..61788c30 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -190,7 +190,7 @@ Perl from source, the Configure program will ask you a series of questions about how to build Perl. You may supply default answers to the questions when you invoke the Configure program by command line flags. -We want to build a Perl that understands large files (over 2GB, wich is +We want to build a Perl that understands large files (over 2GB, which is the default for building perl on HP-UX), and that is incompatible with v5.005 Perl scripts (compiling with v5.005 compatibility causes mod_perl to complain about malloc pollution). At the command prompt type: @@ -856,7 +856,7 @@ warnings;". However, it was annoying, since all my scripts had -w in the Since almost every OS now supports dynamic linking, I believe that static linking is NOT getting the same level of vetting it maybe used to. -Dynamicly linking is what you get by default, so its way better tested. +Dynamically linking is what you get by default, so its way better tested. =item 5 It's required for Apache and mod_perl. diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index fd76cb94..dc3053cd 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -8,104 +8,104 @@ PPM package manager to install a pre-built version of DBD::Oracle however only v =head1 Oracle Instant Client 11.1.0.6.0 Notes -So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value -in the environment variables. +So far I have managed to get it to Makefile and compile test and install and work. However it seems one needs to set "NLS_LANG" to a valid value +in the environment variables. -As well IC 11 seems to have trouble finding the .ORA files. A quick fix for this is to add "TNS_ADMIN" +As well IC 11 seems to have trouble finding the .ORA files. A quick fix for this is to add "TNS_ADMIN" to the environment variables and point it to where your .ORA files are. =head1 Other information, some of which is out of date --- DBD-Oracle for Windows and Oracle Instantclient and 10XE (Express Edition) - By: John Scoles + By: John Scoles The Pythian Group -The preferred method of getting DBD::Oracle is to use a pre-built version from the ActiveState -repository, which can be installed with PPM. +The preferred method of getting DBD::Oracle is to use a pre-built version from the ActiveState +repository, which can be installed with PPM. -Compiling and installing DBD::Oracle 1.18 or later on a windows 2000 professional or XP OS for use -with Oracle instantClient ver 10.2.0.1 & 10.1.0.5 or Oracle XE requires only a few downloads and -a minimal number of environment setting. The procedures below were tested on a clean +Compiling and installing DBD::Oracle 1.18 or later on a windows 2000 professional or XP OS for use +with Oracle instantClient ver 10.2.0.1 & 10.1.0.5 or Oracle XE requires only a few downloads and +a minimal number of environment setting. The procedures below were tested on a clean Windows platform having no Oracle or other development environment installed. - 1) The first part of the process is to download and install the latest version of + 1) The first part of the process is to download and install the latest version of Active Perl from http://www.activeperl.com/. 2) Use the PPM application to get the latest version of DBI 3) Download the latest DBD::Oracle from http://svn.perl.org/modules/dbd-oracle/trunk/ - 4) Download and unzip the Oracle Instant Client (10.2.0.1 or 10.1.0.5) 32 bit from - http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html + 4) Download and unzip the Oracle Instant Client (10.2.0.1 or 10.1.0.5) 32 bit from + http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html You will need all three of these products i. Instant Client Package - Basic ii. Instant Client Package - SQL*Plus: iii. Instant Client Package - SDK: - or - - install oracle 10XE http://www.oracle.com/technology/products/database/xe/index.html + or - 5) You will now need the Microsoft Visual C++ toolkit 2003. Unfortunately this product is no longer available from Microsoft. + install oracle 10XE http://www.oracle.com/technology/products/database/xe/index.html + + 5) You will now need the Microsoft Visual C++ toolkit 2003. Unfortunately this product is no longer available from Microsoft. The file name was VCToolkitSetup.exe and is available at this mirror site http://www.filewatcher.com/m/VCToolkitSetup.exe.32952488.0.0.html at the time of writing. Microsoft's replacement for this tool kit is Visual C++ 2005 Express Edition and all attempts to compile DBD::Oracle with this product fail. It has been successfully compiled - using a complete edition of Microsoft Visual Studio 2005. + using a complete edition of Microsoft Visual Studio 2005. Download and then install this product. - 6) You will also need the Windows SDK. Which can be found at + 6) You will also need the Windows SDK. Which can be found at http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en - You have the choice to of either to download the entire SDK and install or run an online install from the page. - Both have been tested and proven to work. + You have the choice to of either to download the entire SDK and install or run an online install from the page. + Both have been tested and proven to work. - 7) Next download and install the Microsoft .net framework 1.1 skd from - http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&displaylang=en + 7) Next download and install the Microsoft .net framework 1.1 skd from + http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&displaylang=en 8) You will also need a copy of nmake.exe which you can download here http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe 9) Enough Downloading and installing go have a coffee. - 10) You should at this time attempt to connect to an Oracle database with the version SQL*Plus that - you installed in step 4. If you are unable to connect at this stage then any problems you encounter + 10) You should at this time attempt to connect to an Oracle database with the version SQL*Plus that + you installed in step 4. If you are unable to connect at this stage then any problems you encounter later may have nothing to do with DBD::Oracle - 11) On the path where you installed Visual C++ find and edit the vcvars32.bat file as follows. You may have to modify - these path values depending where you installed the products on you computer, + 11) On the path where you installed Visual C++ find and edit the vcvars32.bat file as follows. You may have to modify + these path values depending where you installed the products on you computer, + + i. Add the local path to the windows platform SDK include directory to the Set INCLUDE + Command Line to include the needed files from the Windows SDK. + + e.g. "C:\Program Files\Microsoft Platform SDK\Include;" - i. Add the local path to the windows platform SDK include directory to the Set INCLUDE - Command Line to include the needed files from the Windows SDK. - - e.g. "C:\Program Files\Microsoft Platform SDK\Include;" - ii. Add the local path to the .net Vc7 lib directory to the Set LIB command to include the needed library file from the .Net SKD - + e.g. C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib; - - iii. Add the local path to the windows platform SDK Lib directory to the Set Lib command + + iii. Add the local path to the windows platform SDK Lib directory to the Set Lib command to include the needed library files from the Windows SDK - + e.g. C:\Program Files\Microsoft Platform SDK\Lib; 12) Open a Windows Visual C++ command window from the start menu. - 13) Add the path to the instant client to the Path command. If you are compiling aginst a 10XE db/client then you can skip steps - 12 to 14. + 13) Add the path to the instant client to the Path command. If you are compiling against a 10XE db/client then you can skip steps + 12 to 14. e.g. PATH = C:/Oracle/instantclient;%PATH% - + 14) Using the "Set" command add "ORACLE_HOME=path to Instant client" to the environment variables. e.g. Set ORACLE_HOME=C:\Oracle\instantclient - - 15) Using the "Set" command add "NLS_LANG=.WE8ISO8859P15" to the environment variables. The globalization variable is required, + + 15) Using the "Set" command add "NLS_LANG=.WE8ISO8859P15" to the environment variables. The globalization variable is required, with this or another compatible value, by Oracle instantclient in order for it to compile correctly. e.g. Set NLS_LANG=.WE8ISO8859P15 - 16) Using the "Set" command add "ORACLE_USERID=test/test@test" substituting test with the username/password@database - you wish to run the make test files against. - Note: it is not necessary to do this step for the compile and install to work. + 16) Using the "Set" command add "ORACLE_USERID=test/test@test" substituting test with the username/password@database + you wish to run the make test files against. + Note: it is not necessary to do this step for the compile and install to work. However: The self-test programs included with Oracle-DBD will mostly fail. 17) Move to the DBD-Oracle directory in the Visual C++ window DOS prompt and enter the following. - c:\oracle-dbd\>perl Makefile.PL + c:\oracle-dbd\>perl Makefile.PL The Makefile should then run and compile Oracle-dbd without reporting any errors. @@ -122,12 +122,12 @@ Windows platform having no Oracle or other development environment installed. As long as you have given a valid user name, password and database name in step 15 you will see some results. If it appears to run but you do not get a connection check the following. - i. User name password and DB Name + i. User name password and DB Name ii. Ensure the a valid TNSNAMES.ORA file is in the Instantclient directory - iii. Attempt to log into the version of SQLPLUS that comes with Instantclient. - If you manage to log on use the username password and TNS name with + iii. Attempt to log into the version of SQLPLUS that comes with Instantclient. + If you manage to log on use the username password and TNS name with the Set ORACLE_USERID = and rerun the tests. - iv If you are compiling against 10XE and have skiped steps 12 to 14 try again bu this time carry out these steps + iv If you are compiling against 10XE and have skipped steps 12 to 14 try again bu this time carry out these steps 20) You can now install DBD-Oracle into you system by entering the following command from the Visual C++ window dos prompt; @@ -136,7 +136,7 @@ Windows platform having no Oracle or other development environment installed. 21) You should now be able to run DBD-Oracle on you system -=head1 09/30 2006 from asu +=head1 09/30 2006 from asu DBD::Oracle 1.18a @@ -163,11 +163,11 @@ in line 1463 immediately before sqlplus is called (but I cannot tell if this fails for full client installations) -11/30/05 -- John Scoles +11/30/05 -- John Scoles I have confirmed that this Makefile.pl will work for both Oracle InstantClient 10.2.0.1 & 10.1.0.4 using same process the Andy Hassall uses. Starting with a clean OD One needs only to get the latest version of Active Perl 5.8.7 use PPM to get DBI and then -install Microsoft Visual C++ toolkit, Windows SDK, and the Microsoft .net +install Microsoft Visual C++ toolkit, Windows SDK, and the Microsoft .net framework 1.1. and modify the vcvars32.bat in C++ dir as follows 1) Add the local path to the windows platform SDK include directory to the @@ -182,7 +182,7 @@ framework 1.1. and modify the vcvars32.bat in C++ dir as follows If one happens to have visual studio installed you may not have to download additional MS products. -12/01/05 --- John Scoles +12/01/05 --- John Scoles Oracle 10XE No big problem here as 10XE seems to use the instantclient as well. Just ensure your NLS_LANG and ORACLE_HOME are set to the same directory that 10XE uses diff --git a/oci8.c b/oci8.c index d05b1fa2..c21d192e 100644 --- a/oci8.c +++ b/oci8.c @@ -2566,7 +2566,7 @@ the concept is simple really The the obj_ind is for the entier object not the properties so you call it once it gets all of the indicators for the objects so you pass it into OCIObjectGetAttr and that function will set attr_null_status as in the get below. - 5. interate over the atributes of the object + 5. interate over the attributes of the object The thing to remember is that OCI and C have no way of representing a DB NULLs so we use the OCIInd find out if the object or any of its properties are NULL, This is one little line in a 20 chapter book and even then From b8dc0fafe9fe9938f983425a32205ac0618720d9 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Fri, 18 May 2018 15:00:33 +1000 Subject: [PATCH 512/637] Overhaul tests, dzil usage, perltidy and tweaks --- .gitignore | 1 + MANIFEST | 15 +- Makefile.PL | 2 +- README.help.txt | 26 +- dist.ini | 105 +- hints/macos_syms.pl | 2 +- hints/svr4.pl | 48 +- lib/DBD/Oracle.pm | 1300 ++++++++++----------- lib/DBD/Oracle/GetInfo.pm | 12 +- lib/DBD/Oracle/Object.pm | 52 +- lib/DBD/Oracle/Troubleshooting.pod | 6 +- lib/DBD/Oracle/Troubleshooting/Aix.pod | 66 +- lib/DBD/Oracle/Troubleshooting/Cygwin.pod | 1 - lib/DBD/Oracle/Troubleshooting/Hpux.pod | 26 +- lib/DBD/Oracle/Troubleshooting/Linux.pod | 26 +- lib/DBD/Oracle/Troubleshooting/Macos.pod | 15 +- lib/DBD/Oracle/Troubleshooting/Sun.pod | 1 - lib/DBD/Oracle/Troubleshooting/Vms.pod | 24 +- lib/DBD/Oracle/Troubleshooting/Win32.pod | 1 - mkta.pl | 54 +- t/00dbdoracletestlib.t | 43 + t/00versions.t | 45 - t/01base.t | 15 +- t/02versions.t | 46 + t/05base.t | 35 + t/10general.t | 156 +-- t/12impdata.t | 48 +- t/14threads.t | 61 +- t/15nls.t | 53 +- t/20select.t | 219 ++-- t/21nchar.t | 65 +- t/22nchar_al32utf8.t | 55 +- t/22nchar_utf8.t | 53 +- t/23wide_db.t | 61 +- t/23wide_db_8bit.t | 57 +- t/23wide_db_al32utf8.t | 36 +- t/24implicit_utf8.t | 70 +- t/25plsql.t | 446 ++++--- t/26exe_array.t | 79 +- t/28array_bind.t | 507 ++++---- t/30long.t | 679 ++++++----- t/31lob.t | 150 +-- t/31lob_extended.t | 132 +-- t/32xmltype.t | 103 +- t/34pres_lobs.t | 205 ++-- t/36lob_leak.t | 336 +++--- t/38taf.t | 49 +- t/39attr.t | 60 +- t/40ph_type.t | 230 ++-- t/50cursor.t | 131 ++- t/51scroll.t | 138 +-- t/55nested.t | 125 +- t/56embbeded.t | 77 +- t/58object.t | 488 ++++---- t/60reauth.t | 36 +- t/70meta.t | 96 +- t/80ora_charset.t | 105 +- t/README | 62 + t/lib/DBDOracleTestLib.pm | 575 +++++++++ t/lib/ExecuteArray.pm | 8 +- t/nchar_test_lib.pl | 523 --------- t/rt13865.t | 156 ++- t/rt74753-utf8-encoded.t | 48 +- t/rt85886.t | 55 +- 64 files changed, 4589 insertions(+), 3911 deletions(-) create mode 100644 t/00dbdoracletestlib.t delete mode 100644 t/00versions.t create mode 100644 t/02versions.t create mode 100755 t/05base.t create mode 100644 t/README create mode 100644 t/lib/DBDOracleTestLib.pm delete mode 100644 t/nchar_test_lib.pl diff --git a/.gitignore b/.gitignore index 27c12ccb..070c8272 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ mk.pm oci8.o DBD-Oracle* project.vim +cpanfile diff --git a/MANIFEST b/MANIFEST index d3ba56c9..2b45ef07 100644 --- a/MANIFEST +++ b/MANIFEST @@ -12,10 +12,12 @@ Oracle.xs README README.help.txt README.mkdn -Todo +TODO +cpanfile dbdimp.c dbdimp.h dbivport.h +doap.xml examples/README examples/bind.pl examples/commit.pl @@ -52,9 +54,13 @@ mkta.pl oci.def oci8.c ocitrace.h -t/000-report-versions-tiny.t -t/00versions.t +t/00-compile.t +t/00-report-prereqs.dd +t/00-report-prereqs.t +t/00dbdoracletestlib.t t/01base.t +t/02versions.t +t/05base.t t/10general.t t/12impdata.t t/14threads.t @@ -87,8 +93,9 @@ t/58object.t t/60reauth.t t/70meta.t t/80ora_charset.t +t/README +t/lib/DBDOracleTestLib.pm t/lib/ExecuteArray.pm -t/nchar_test_lib.pl t/rt13865.t t/rt74753-utf8-encoded.t t/rt85886.t diff --git a/Makefile.PL b/Makefile.PL index d4686528..0b730d47 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -1123,7 +1123,7 @@ sub ora_libdir { if ( $client_version >= 9 ) { $libdir = 'lib32' if ! perl_is_64bit() and -d "$OH/lib32"; $libdir = 'lib/64' if perl_is_64bit() and -d "$OH/lib/64"; - # Solaris OIC 12+ from pkg + # Solaris OIC 12+ from pkg } else { $libdir = 'lib64' if perl_is_64bit() and -d "$OH/lib64"; diff --git a/README.help.txt b/README.help.txt index 7e68453c..47d35154 100644 --- a/README.help.txt +++ b/README.help.txt @@ -11,11 +11,11 @@ build/link process for OCI applications between versions. ------------------------------------------------------------------------------- AIX 4 - core dump on login and similar problems -set - cc='xlc_r' +set + cc='xlc_r' in config.sh. Rebuild everything, and make sure xlc_r is used everywhere. -set environment - ORACCENV='cc=xlc_r'; export ORACCENV +set environment + ORACCENV='cc=xlc_r'; export ORACCENV to enforce this in oraxlc Thanks to Goran Thyni for this information. @@ -76,11 +76,11 @@ For platforms which require static linking. You'll need to build DBD::Oracle statically linked and then link it into a perl binary: - perl Makefile.PL LINKTYPE=static - make - make perl (makes a perl binary in current directory) - make test FULLPERL=./perl (run tests using the new perl binary) - make install + perl Makefile.PL LINKTYPE=static + make + make perl (makes a perl binary in current directory) + make test FULLPERL=./perl (run tests using the new perl binary) + make install You will probably need to have already built and installed a static version of the DBI in order that it be automatically included when @@ -244,10 +244,10 @@ complain to Oracle about bugs in their header files on 64 bit systems. Link errors or test core dumps Try each of these in turn (follow each with a make && make test): - perl Makefile.PL -nob - perl Makefile.PL -c - perl Makefile.PL -l - perl Makefile.PL -n LIBCLNTSH + perl Makefile.PL -nob + perl Makefile.PL -c + perl Makefile.PL -l + perl Makefile.PL -n LIBCLNTSH let me know if any of these help. =============================================================================== diff --git a/dist.ini b/dist.ini index 3124479c..ebdcfeee 100644 --- a/dist.ini +++ b/dist.ini @@ -6,31 +6,106 @@ author = Martin J. Evans license = Perl_5 copyright_holder = Tim Bunce copyright_year = 1994 +main_module = lib/DBD/Oracle.pm version = 1.74 -[TemplateCJM] -file = CONTRIBUTING.mkd +; Generate files -[Authority] -authority=cpan:PYTHIAN +;[TemplateCJM] +;file = CONTRIBUTING.mkd + +;[Authority] +;authority=cpan:PYTHIAN [MakeMaker::Custom] -[@Filter] --bundle=@YANICK --remove=NextVersion::Semantic --remove=ChangeStats::Git --remove=ModuleBuild --remove=Authority --remove=Signature --remove=Twitter --remove=Test::Compile --remove=Covenant --remove=CoderwallEndorse +[Git::Contributors] +[ContributorsFile] +[InstallGuide] +;[GithubMeta] +;remote=github + +[MetaYAML] +[MetaJSON] +[PodWeaver] +[License] + +[ReadmeMarkdownFromPod] +[NextRelease] +time_zone = America/Montreal + +[MetaProvides::Package] +[MatchManifest] +[ManifestSkip] + +[Git::GatherDir] +exclude_filename = cpanfile +[CopyFilesFromBuild] +copy = cpanfile + +[ExecDir] +[OurPkgVersion] +[AutoPrereqs] +[CheckChangesHasContent] +[PreviousVersion::Changelog] + +; Release Stuff + +[ConfirmRelease] +[Git::Check] +[Git::Commit] +[Git::CommitBuild] + release_branch = releases + multiple_inheritance = 1 +[Git::Tag] + tag_format = v%v + branch = releases + +[UploadToCPAN] + +[Git::Push] + push_to = github master releases + +[InstallRelease] +install_command = cpanm . + +;[SchwartzRatio] + +; Tests + +[RunExtraTests] +[MetaTests] +[Test::Compile] +[Test::Kwalitee] +[Test::EOF] +[Test::EOL] +[Test::NoBreakpoints] +[Test::NoTabs] +[Test::Portability] +[Test::ReportPrereqs] +[Test::UnusedVars] +[TestRelease] +[PodCoverageTests] +[PodSyntaxTests] + +[DOAP] +process_changes = 1 + +[CPANFile] + +[CopyrightYearFromGit] + [Prereqs / ConfigureRequires] +Config = 0 +Data::Dumper = 0 DBI = 1.623 +Devel::Peek = 0 +Encode = 0 +Math::BigInt = 0 +Test::More = 0 +Test::NoWarnings = 0 [HelpWanted] positions = coder documentation tester diff --git a/hints/macos_syms.pl b/hints/macos_syms.pl index 8fb418fd..41a07089 100644 --- a/hints/macos_syms.pl +++ b/hints/macos_syms.pl @@ -109,7 +109,7 @@ s/...........(\w+)\n/$1/; $oracle{$_} = 1; } -} +} close FH; diff --git a/hints/svr4.pl b/hints/svr4.pl index 28d9ea91..14a9a8a6 100644 --- a/hints/svr4.pl +++ b/hints/svr4.pl @@ -8,7 +8,7 @@ # modified by Davide Migliavacca if ($archname eq 'RM400-svr4') { - @libs = qw(-lucb); + @libs = qw(-lucb); } push @libs, '-lc'; @@ -31,19 +31,19 @@ On Fri, 18 Aug 1995, Tim Bunce wrote: > > From: Alan Burlison -> > +> > > > Tim, -> > -> > The following hints file is required for DBD::Oracle on svr4, you might +> > +> > The following hints file is required for DBD::Oracle on svr4, you might > > like to add it to the next release :-) -> > +> > > > File: Oracle/hints/svr4.pl -> > +> > > > # Some SVR4 systems may need to link against -lc to pick up things like > > $att{LIBS} = [ '-lsocket -lnsl -lm -ldl -lc' ]; > > Umm, 'some', 'may', 'things like'. Care to clarify? -> +> > Why _exactly_ is this needed, and why doesn't MakeMaker do this already? > (CC'd to the MakeMaker mailing list.) @@ -56,21 +56,21 @@ $att{LIBS} = ['-ldbm -lucb -lc']; ################################################################### -"Some" includes Unisys 6000 (or something like that). I don't know -if it includes anything else. It doesn't include Unixware 2.1, but it +"Some" includes Unisys 6000 (or something like that). I don't know +if it includes anything else. It doesn't include Unixware 2.1, but it might include Esix. It's *really* hard to get accurate info. -"May" because some do and some don't, and any listing gets out of date -quickly as vendors issue different versions, and probably more than -half the info you *do* get about specific versions is wrong. Hence all +"May" because some do and some don't, and any listing gets out of date +quickly as vendors issue different versions, and probably more than +half the info you *do* get about specific versions is wrong. Hence all the vague weasel-words. -"Things like" is ecvt() for Unisys (for ODBM_File). Since some linkers -only report the first missing symbol, it's sometimes hard (and +"Things like" is ecvt() for Unisys (for ODBM_File). Since some linkers +only report the first missing symbol, it's sometimes hard (and sometimes pointless) to get a complete list of things that you need). -Basically, there are *many* SVR4-derived systems out there, and there are -many little idiosyncracies; the best bet is to put someone else's name +Basically, there are *many* SVR4-derived systems out there, and there are +many little idiosyncracies; the best bet is to put someone else's name and email address in the hint file so you can blame them :-). Andy Dougherty doughera@lafcol.lafayette.edu @@ -79,25 +79,25 @@ From: Tye McQueen Subject: Re: [MM] Re: hints file for Oracle Date: Fri, 18 Aug 1995 16:01:39 -0500 (CDT) -Cc: aburlison@cix.compulink.co.uk, perldb-interest@vix.com, +Cc: aburlison@cix.compulink.co.uk, perldb-interest@vix.com, makemaker@franz.ww.tu-berlin.de Excerpts from the mail message of Tim Bunce: ) > From: Alan Burlison -) > -) > The following hints file is required for DBD::Oracle on svr4, you might +) > +) > The following hints file is required for DBD::Oracle on svr4, you might ) > like to add it to the next release :-) -) > +) > ) > File: Oracle/hints/svr4.pl -) > +) > ) > # Some SVR4 systems may need to link against -lc to pick up things like ) > $att{LIBS} = [ '-lsocket -lnsl -lm -ldl -lc' ]; ) ) Umm, 'some', 'may', 'things like'. Care to clarify? -) +) ) Why _exactly_ is this needed, and why doesn't MakeMaker do this already? ) (CC'd to the MakeMaker mailing list.) -) +) ) Is anyone else using DBD::Oracle on an svr4 system (not solaris 2)? That looks like something I wrote. I'll take credit and blame @@ -119,7 +119,7 @@ I'm putting together a README.svr4 for Perl that will describe this and many other things in case people are curious or run into a problem and need to know why some of the strange things were done. --- +-- Tye McQueen tye@metronet.com || tye@doober.usu.edu Nothing is obvious unless you are overlooking something http://www.metronet.com/~tye/ (scripts, links, nothing fancy) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 164966fe..b657f16b 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -11,6 +11,7 @@ my $ORACLE_ENV = ($^O eq 'VMS') ? 'ORA_ROOT' : 'ORACLE_HOME'; { package DBD::Oracle; + # VERSION # ABSTRACT: Oracle database driver for the DBI module use DBI (); @@ -18,58 +19,57 @@ package DBD::Oracle; use Exporter (); use DBD::Oracle::Object(); - # for dev version $DBD::Oracle::VERSION ||= '1.00'; @ISA = qw(DynaLoader Exporter); %EXPORT_TAGS = ( ora_types => [ qw( - ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE - ORA_RAW ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE - ORA_CLOB ORA_BLOB ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE - SQLT_INT SQLT_FLT ORA_OCI SQLT_CHR SQLT_BIN - ) ], - ora_session_modes => [ qw( ORA_SYSDBA ORA_SYSOPER ORA_SYSASM ORA_SYSBACKUP ORA_SYSDG ORA_SYSKM) ], - ora_fetch_orient => [ qw( OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST - OCI_FETCH_LAST OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE - OCI_FETCH_RELATIVE)], - ora_exe_modes => [ qw( OCI_STMT_SCROLLABLE_READONLY)], - ora_fail_over => [ qw( OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN - OCI_FO_ERROR OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT - OCI_FO_TXNAL OCI_FO_RETRY)], + ORA_VARCHAR2 ORA_STRING ORA_NUMBER ORA_LONG ORA_ROWID ORA_DATE + ORA_RAW ORA_LONGRAW ORA_CHAR ORA_CHARZ ORA_MLSLABEL ORA_XMLTYPE + ORA_CLOB ORA_BLOB ORA_RSET ORA_VARCHAR2_TABLE ORA_NUMBER_TABLE + SQLT_INT SQLT_FLT ORA_OCI SQLT_CHR SQLT_BIN + ) ], + ora_session_modes => [ qw( ORA_SYSDBA ORA_SYSOPER ORA_SYSASM ORA_SYSBACKUP ORA_SYSDG ORA_SYSKM) ], + ora_fetch_orient => [ qw( OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST + OCI_FETCH_LAST OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE + OCI_FETCH_RELATIVE)], + ora_exe_modes => [ qw( OCI_STMT_SCROLLABLE_READONLY)], + ora_fail_over => [ qw( OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN + OCI_FO_ERROR OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT + OCI_FO_TXNAL OCI_FO_RETRY)], ); - @EXPORT_OK = qw(OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST OCI_FETCH_LAST OCI_FETCH_PRIOR - OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE ORA_OCI SQLCS_IMPLICIT SQLCS_NCHAR ora_env_var ora_cygwin_set_env ); + @EXPORT_OK = qw( OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST OCI_FETCH_LAST OCI_FETCH_PRIOR + OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE ORA_OCI SQLCS_IMPLICIT SQLCS_NCHAR + ora_env_var ora_cygwin_set_env ); + #unshift @EXPORT_OK, 'ora_cygwin_set_env' if $^O eq 'cygwin'; Exporter::export_ok_tags(qw(ora_types ora_session_modes ora_fetch_orient ora_exe_modes ora_fail_over)); - my $Revision = substr(q$Revision: 1.103 $, 10); - require_version DBI 1.623; DBD::Oracle->bootstrap($DBD::Oracle::VERSION); - $drh = undef; # holds driver handle once initialized + $drh = undef; # holds driver handle once initialized sub CLONE { - $drh = undef ; + $drh = undef; } - sub driver{ + sub driver { return $drh if $drh; my($class, $attr) = @_; my $oci = DBD::Oracle::ORA_OCI(); - $class .= "::dr"; + $class .= '::dr'; # not a 'my' since we use it above to prevent multiple drivers $drh = DBI::_new_drh($class, { - 'Name' => 'Oracle', - 'Version' => $VERSION, - 'Err' => \my $err, - 'Errstr' => \my $errstr, + 'Name' => 'Oracle', + 'Version' => $VERSION, + 'Err' => \my $err, + 'Errstr' => \my $errstr, 'Attribution' => "DBD::Oracle $VERSION using OCI$oci by Tim Bunce et. al.", }); @@ -104,17 +104,17 @@ package DBD::Oracle; END { - # Used to silence 'Bad free() ...' warnings caused by bugs in Oracle's code - # being detected by Perl's malloc. - $ENV{PERL_BADFREE} = 0; - #undef $Win32::TieRegistry::Registry if $Win32::TieRegistry::Registry; + # Used to silence 'Bad free() ...' warnings caused by bugs in Oracle's code + # being detected by Perl's malloc. + $ENV{PERL_BADFREE} = 0; + #undef $Win32::TieRegistry::Registry if $Win32::TieRegistry::Registry; } sub AUTOLOAD { - (my $constname = $AUTOLOAD) =~ s/.*:://; - my $val = constant($constname); - *$AUTOLOAD = sub { $val }; - goto &$AUTOLOAD; + (my $constname = $AUTOLOAD) =~ s/.*:://; + my $val = constant($constname); + *$AUTOLOAD = sub { $val }; + goto &$AUTOLOAD; } } @@ -124,133 +124,132 @@ package DBD::Oracle; DBD::Oracle::dr; # ====== DRIVER ====== use strict; - my %dbnames = (); # holds list of known databases (oratab + tnsnames) + my %dbnames = (); # holds list of known databases (oratab + tnsnames) sub load_dbnames { - my ($drh) = @_; - my $debug = $drh->debug; - my $oracle_home = DBD::Oracle::ora_env_var($ORACLE_ENV); - local *FH; - my $d; - - if (($^O eq 'MSWin32') or ($^O =~ /cygwin/i)) { - # XXX experimental, will probably change - $drh->trace_msg("Trying to fetch ORACLE_HOME and ORACLE_SID from the registry.\n") - if $debug; - my $sid = DBD::Oracle::ora_env_var("ORACLE_SID"); - $dbnames{$sid} = $oracle_home if $sid and $oracle_home; - $drh->trace_msg("Found $sid \@ $oracle_home.\n") if $debug && $sid; - } - - # get list of 'local' database SIDs from oratab - foreach $d (qw(/etc /var/opt/oracle), DBD::Oracle::ora_env_var("TNS_ADMIN")) { - next unless defined $d; - next unless open(FH, "<$d/oratab"); - $drh->trace_msg("Loading $d/oratab\n") if $debug; - my $ot; - while (defined($ot = )) { - next unless $ot =~ m/^\s*(\w+)\s*:\s*(.*?)\s*:/; - $dbnames{$1} = $2; # store ORACLE_HOME value - $drh->trace_msg("Found $1 \@ $2.\n") if $debug; - } - close FH; - last; - } - - # get list of 'remote' database connection identifiers - my @tns_admin = ( DBD::Oracle::ora_env_var("TNS_ADMIN"), '.' ); - push @tns_admin, map { join '/', $oracle_home, $_ } - 'network/admin', # OCI 7 and 8.1 - 'net80/admin', # OCI 8.0 - if $oracle_home; - push @tns_admin, '/var/opt/oracle', '/etc'; + my ($drh) = @_; + my $debug = $drh->debug; + my $oracle_home = DBD::Oracle::ora_env_var($ORACLE_ENV); + my $d; + + if (($^O eq 'MSWin32') or ($^O =~ /cygwin/i)) { + # XXX experimental, will probably change + $drh->trace_msg("Trying to fetch ORACLE_HOME and ORACLE_SID from the registry.\n") + if $debug; + my $sid = DBD::Oracle::ora_env_var("ORACLE_SID"); + $dbnames{$sid} = $oracle_home if $sid and $oracle_home; + $drh->trace_msg("Found $sid \@ $oracle_home.\n") if $debug && $sid; + } + + # get list of 'local' database SIDs from oratab + foreach $d (qw(/etc /var/opt/oracle), DBD::Oracle::ora_env_var("TNS_ADMIN")) { + next unless defined $d; + next unless open(my $FH, '<', "$d/oratab"); + $drh->trace_msg("Loading $d/oratab\n") if $debug; + my $ot; + while (defined($ot = <$FH>)) { + next unless $ot =~ m/^\s*(\w+)\s*:\s*(.*?)\s*:/; + $dbnames{$1} = $2; # store ORACLE_HOME value + $drh->trace_msg("Found $1 \@ $2.\n") if $debug; + } + close $FH; + last; + } + + # get list of 'remote' database connection identifiers + my @tns_admin = ( DBD::Oracle::ora_env_var("TNS_ADMIN"), '.' ); + push @tns_admin, map { join '/', $oracle_home, $_ } + 'network/admin', # OCI 7 and 8.1 + 'net80/admin', # OCI 8.0 + if $oracle_home; + push @tns_admin, '/var/opt/oracle', '/etc'; TNS_ADMIN: - foreach $d ( grep { $_ and -d $_ } @tns_admin ) { - open FH, '<', "$d/tnsnames.ora" or next TNS_ADMIN; - - $drh->trace_msg("Loading $d/tnsnames.ora\n") if $debug; - local *_; - while () { - next unless m/^\s*([-\w\.]+)\s*=/; - my $name = $1; - $drh->trace_msg("Found $name. ".($dbnames{$name} ? "(oratab entry overridden)" : "")."\n") - if $debug; - $dbnames{$name} = 0; # exists but false (to distinguish from oratab) - } - close FH; - last; - } - - $dbnames{0} = 1; # mark as loaded (even if empty) + foreach $d ( grep { $_ and -d $_ } @tns_admin ) { + open my $FH, '<', "$d/tnsnames.ora" or next TNS_ADMIN; + + $drh->trace_msg("Loading $d/tnsnames.ora\n") if $debug; + local *_; + while (<$FH>) { + next unless m/^\s*([-\w\.]+)\s*=/; + my $name = $1; + $drh->trace_msg("Found $name. ".($dbnames{$name} ? "(oratab entry overridden)" : "")."\n") + if $debug; + $dbnames{$name} = 0; # exists but false (to distinguish from oratab) + } + close $FH; + last; + } + + $dbnames{0} = 1; # mark as loaded (even if empty) } sub data_sources { - my $drh = shift; - load_dbnames($drh) unless %dbnames; - my @names = sort keys %dbnames; - my @sources = map { $_ ? ("dbi:Oracle:$_") : () } @names; - return @sources; + my $drh = shift; + load_dbnames($drh) unless %dbnames; + my @names = sort keys %dbnames; + my @sources = map { $_ ? ("dbi:Oracle:$_") : () } @names; + return @sources; } sub connect { - my ($drh, $dbname, $user, $auth, $attr)= @_; + my ($drh, $dbname, $user, $auth, $attr)= @_; # Make 'sid=whatever' an alias for 'whatever'. # see RT91775 $dbname =~ s/^sid=([^;]+)$/$1/; - if ($dbname =~ /;/) { - my ($n,$v); - $dbname =~ s/^\s+//; - $dbname =~ s/\s+$//; - my @dbname = map { - ($n,$v) = split /\s*=\s*/, $_, -1; - Carp::carp("DSN component '$_' is not in 'name=value' format") - unless defined $v && defined $n; + if ($dbname =~ /;/) { + my ($n,$v); + $dbname =~ s/^\s+//; + $dbname =~ s/\s+$//; + my @dbname = map { + ($n,$v) = split /\s*=\s*/, $_, -1; + Carp::carp("DSN component '$_' is not in 'name=value' format") + unless defined $v && defined $n; (uc($n), $v) - } split /\s*;\s*/, $dbname; - my %dbname = ( PROTOCOL => 'tcp', @dbname ); + } split /\s*;\s*/, $dbname; + my %dbname = ( PROTOCOL => 'tcp', @dbname ); - if ((exists $dbname{SERVER}) and ($dbname{SERVER} eq "POOLED")) { + if ((exists $dbname{SERVER}) and ($dbname{SERVER} eq "POOLED")) { $attr->{ora_drcp}=1; - } - - # extract main attributes for connect_data portion - my @connect_data_attr = qw(SID INSTANCE_NAME SERVER SERVICE_NAME ); - my %connect_data = map { ($_ => delete $dbname{$_}) } - grep { exists $dbname{$_} } @connect_data_attr; - - my $connect_data = join "", map { "($_=$connect_data{$_})" } keys %connect_data; - return $drh->DBI::set_err(-1, - "Can't connect using this syntax without specifying a HOST and one of @connect_data_attr") - unless $dbname{HOST} and %connect_data; - - my @addrs = map { "($_=$dbname{$_})" } keys %dbname; - my $addrs = join "", @addrs; - if ($dbname{PORT}) { - $addrs = "(ADDRESS=$addrs)"; - } - else { - $addrs = "(ADDRESS_LIST=(ADDRESS=$addrs(PORT=1526))" - . "(ADDRESS=$addrs(PORT=1521)))"; - } - $dbname = "(DESCRIPTION=$addrs(CONNECT_DATA=$connect_data))"; - $drh->trace_msg("connect using '$dbname'"); - } - - # If the application is asking for specific database - # then we may have to mung the dbname - - $dbname = $1 if !$dbname && $user && $user =~ s/\@(.*)//s; - - $drh->trace_msg("$ORACLE_ENV environment variable not set\n") - if !$ENV{$ORACLE_ENV} and $^O ne "MSWin32"; - - # create a 'blank' dbh - - $user = '' if not defined $user; + } + + # extract main attributes for connect_data portion + my @connect_data_attr = qw(SID INSTANCE_NAME SERVER SERVICE_NAME ); + my %connect_data = map { ($_ => delete $dbname{$_}) } + grep { exists $dbname{$_} } @connect_data_attr; + + my $connect_data = join "", map { "($_=$connect_data{$_})" } keys %connect_data; + return $drh->DBI::set_err(-1, + "Can't connect using this syntax without specifying a HOST and one of @connect_data_attr") + unless $dbname{HOST} and %connect_data; + + my @addrs = map { "($_=$dbname{$_})" } keys %dbname; + my $addrs = join "", @addrs; + if ($dbname{PORT}) { + $addrs = "(ADDRESS=$addrs)"; + } + else { + $addrs = "(ADDRESS_LIST=(ADDRESS=$addrs(PORT=1526))" + . "(ADDRESS=$addrs(PORT=1521)))"; + } + $dbname = "(DESCRIPTION=$addrs(CONNECT_DATA=$connect_data))"; + $drh->trace_msg("connect using '$dbname'"); + } + + # If the application is asking for specific database + # then we may have to mung the dbname + + $dbname = $1 if !$dbname && $user && $user =~ s/\@(.*)//s; + + $drh->trace_msg("$ORACLE_ENV environment variable not set\n") + if !$ENV{$ORACLE_ENV} and $^O ne "MSWin32"; + + # create a 'blank' dbh + + $user = '' if not defined $user; (my $user_only = $user) =~ s:/.*::; if (substr($dbname,-7,7) eq ':POOLED'){ @@ -258,83 +257,83 @@ package DBD::Oracle; $attr->{ora_drcp} = 1; } elsif ($ENV{ORA_DRCP}){ - $attr->{ora_drcp} = 1; - } - - my ($dbh, $dbh_inner) = DBI::_new_dbh($drh, { - 'Name' => $dbname, - 'dbi_imp_data' => $attr->{dbi_imp_data}, - # these two are just for backwards compatibility - 'USER' => uc $user_only, 'CURRENT_USER' => uc $user_only, - }); - - # Call Oracle OCI logon func in Oracle.xs file - # and populate internal handle data. - - - if (exists $ENV{ORA_DRCP_CLASS}) { - $attr->{ora_drcp_class} = $ENV{ORA_DRCP_CLASS} - } - if($attr->{ora_drcp_class}){ - # if using ora_drcp_class it cannot contain more than 1024 bytes - # and cannot contain a * - if (index($attr->{ora_drcp_class},'*') !=-1){ - Carp::croak("ora_drcp_class cannot contain a '*'!"); - } - if (length($attr->{ora_drcp_class}) > 1024){ - Carp::croak("ora_drcp_class must be less than 1024 characters!"); - } - } - if (exists $ENV{ORA_DRCP_MIN}) { - $attr->{ora_drcp_min} = $ENV{ORA_DRCP_MIN} - } - if (exists $ENV{ORA_DRCP_MAX}) { - $attr->{ora_drcp_max} = $ENV{ORA_DRCP_MAX} - } - if (exists $ENV{ORA_DRCP_INCR}) { - $attr->{ora_drcp_incr} = $ENV{ORA_DRCP_INCR} - } - if (exists $ENV{ORA_DRCP_RLB}) { - $attr->{ora_drcp_rlb} = $ENV{ORA_DRCP_RLB} - } - - if (exists $ENV{ORA_EVENTS}) { - $attr->{ora_events} = $ENV{ORA_EVENTS}; - } - - if (exists $ENV{ORA_EVENTS}) { - $attr->{ora_events} = $ENV{ORA_EVENTS}; - } - - { - local @SIG{ @{ $attr->{ora_connect_with_default_signals} } } + $attr->{ora_drcp} = 1; + } + + my ($dbh, $dbh_inner) = DBI::_new_dbh($drh, { + 'Name' => $dbname, + 'dbi_imp_data' => $attr->{dbi_imp_data}, + # these two are just for backwards compatibility + 'USER' => uc $user_only, 'CURRENT_USER' => uc $user_only, + }); + + # Call Oracle OCI logon func in Oracle.xs file + # and populate internal handle data. + + + if (exists $ENV{ORA_DRCP_CLASS}) { + $attr->{ora_drcp_class} = $ENV{ORA_DRCP_CLASS} + } + if($attr->{ora_drcp_class}){ + # if using ora_drcp_class it cannot contain more than 1024 bytes + # and cannot contain a * + if (index($attr->{ora_drcp_class},'*') !=-1){ + Carp::croak("ora_drcp_class cannot contain a '*'!"); + } + if (length($attr->{ora_drcp_class}) > 1024){ + Carp::croak("ora_drcp_class must be less than 1024 characters!"); + } + } + if (exists $ENV{ORA_DRCP_MIN}) { + $attr->{ora_drcp_min} = $ENV{ORA_DRCP_MIN} + } + if (exists $ENV{ORA_DRCP_MAX}) { + $attr->{ora_drcp_max} = $ENV{ORA_DRCP_MAX} + } + if (exists $ENV{ORA_DRCP_INCR}) { + $attr->{ora_drcp_incr} = $ENV{ORA_DRCP_INCR} + } + if (exists $ENV{ORA_DRCP_RLB}) { + $attr->{ora_drcp_rlb} = $ENV{ORA_DRCP_RLB} + } + + if (exists $ENV{ORA_EVENTS}) { + $attr->{ora_events} = $ENV{ORA_EVENTS}; + } + + if (exists $ENV{ORA_EVENTS}) { + $attr->{ora_events} = $ENV{ORA_EVENTS}; + } + + { + local @SIG{ @{ $attr->{ora_connect_with_default_signals} } } if $attr->{ora_connect_with_default_signals}; - DBD::Oracle::db::_login($dbh, $dbname, $user, $auth, $attr) - or return undef; - } - - unless (length $user_only) { - # It may be we've already encountered a warning by this point, - # such as "ORA-28002: the password will expire within %d days". - # We'll cache it for reinstatement. - my ($err, $errstr, $state) = - ($dbh->err, $dbh->errstr, $dbh->state); - $user_only = $dbh->selectrow_array(q{ - SELECT SYS_CONTEXT('userenv','session_user') FROM DUAL - })||''; - # Now we'll reinstate the earlier warning. We're just - # appending it, so in the extremeley unlikely case that the - # selectrow_array we just issued also issued a warning, the - # 2 warnings will appear out of order. - $dbh->set_err($err, $errstr, $state) if defined $err; - $dbh_inner->{Username} = $user_only; - # these two are just for backwards compatibility - $dbh_inner->{USER} = $dbh_inner->{CURRENT_USER} = uc $user_only; - } - if ($ENV{ORA_DBD_NCS_BUFFER}){ - $dbh->{'ora_ncs_buff_mtpl'}= $ENV{ORA_DBD_NCS_BUFFER}; - } - $dbh; + DBD::Oracle::db::_login($dbh, $dbname, $user, $auth, $attr) + or return undef; + } + + unless (length $user_only) { + # It may be we've already encountered a warning by this point, + # such as "ORA-28002: the password will expire within %d days". + # We'll cache it for reinstatement. + my ($err, $errstr, $state) = + ($dbh->err, $dbh->errstr, $dbh->state); + $user_only = $dbh->selectrow_array(q{ + SELECT SYS_CONTEXT('userenv','session_user') FROM DUAL + })||''; + # Now we'll reinstate the earlier warning. We're just + # appending it, so in the extremeley unlikely case that the + # selectrow_array we just issued also issued a warning, the + # 2 warnings will appear out of order. + $dbh->set_err($err, $errstr, $state) if defined $err; + $dbh_inner->{Username} = $user_only; + # these two are just for backwards compatibility + $dbh_inner->{USER} = $dbh_inner->{CURRENT_USER} = uc $user_only; + } + if ($ENV{ORA_DBD_NCS_BUFFER}){ + $dbh->{'ora_ncs_buff_mtpl'}= $ENV{ORA_DBD_NCS_BUFFER}; + } + $dbh; } @@ -351,21 +350,21 @@ package DBD::Oracle; use DBI qw(:sql_types); sub prepare { - my($dbh, $statement, @attribs)= @_; + my($dbh, $statement, @attribs)= @_; - # create a 'blank' sth + # create a 'blank' sth - my $sth = DBI::_new_sth($dbh, { - 'Statement' => $statement, - }); + my $sth = DBI::_new_sth($dbh, { + 'Statement' => $statement, + }); - # Call Oracle OCI parse func in Oracle.xs file. - # and populate internal handle data. + # Call Oracle OCI parse func in Oracle.xs file. + # and populate internal handle data. - DBD::Oracle::st::_prepare($sth, $statement, @attribs) - or return undef; + DBD::Oracle::st::_prepare($sth, $statement, @attribs) + or return undef; - $sth; + $sth; } #Ah! I see you have the machine that goes PING!! @@ -374,74 +373,74 @@ package DBD::Oracle; #not the capital ... sub ping { - my($dbh) = @_; - local $@; - my $ok = 0; - eval { - local $SIG{__DIE__}; - local $SIG{__WARN__}; - $ok=ora_ping($dbh); - }; - return ($@) ? 0 : $ok; + my($dbh) = @_; + local $@; + my $ok = 0; + eval { + local $SIG{__DIE__}; + local $SIG{__WARN__}; + $ok=ora_ping($dbh); + }; + return ($@) ? 0 : $ok; } sub get_info { - my($dbh, $info_type) = @_; - require DBD::Oracle::GetInfo; - my $v = $DBD::Oracle::GetInfo::info{int($info_type)}; - $v = $v->($dbh) if ref $v eq 'CODE'; - return $v; + my($dbh, $info_type) = @_; + require DBD::Oracle::GetInfo; + my $v = $DBD::Oracle::GetInfo::info{int($info_type)}; + $v = $v->($dbh) if ref $v eq 'CODE'; + return $v; } sub private_attribute_info { #this should only be for ones that have setters and getters - return { ora_max_nested_cursors => undef, - ora_array_chunk_size => undef, - ora_ph_type => undef, - ora_ph_csform => undef, + return { ora_max_nested_cursors => undef, + ora_array_chunk_size => undef, + ora_ph_type => undef, + ora_ph_csform => undef, ora_parse_error_offset => undef, - ora_dbh_share => undef, - ora_envhp => undef, - ora_svchp => undef, - ora_errhp => undef, - ora_init_mode => undef, - ora_events => undef, - ora_charset => undef, - ora_ncharset => undef, - ora_session_mode => undef, - ora_verbose => undef, - ora_oci_success_warn => undef, - ora_objects => undef, - ora_ncs_buff_mtpl => undef, - ora_drcp => undef, - ora_drcp_class => undef, - ora_drcp_min => undef, - ora_drcp_max => undef, - ora_drcp_incr => undef, - ora_drcp_rlb => undef, - ora_oratab_orahome => undef, - ora_module_name => undef, - ora_driver_name => undef, - ora_client_info => undef, - ora_client_identifier => undef, - ora_action => undef, - ora_taf_function => undef, + ora_dbh_share => undef, + ora_envhp => undef, + ora_svchp => undef, + ora_errhp => undef, + ora_init_mode => undef, + ora_events => undef, + ora_charset => undef, + ora_ncharset => undef, + ora_session_mode => undef, + ora_verbose => undef, + ora_oci_success_warn => undef, + ora_objects => undef, + ora_ncs_buff_mtpl => undef, + ora_drcp => undef, + ora_drcp_class => undef, + ora_drcp_min => undef, + ora_drcp_max => undef, + ora_drcp_incr => undef, + ora_drcp_rlb => undef, + ora_oratab_orahome => undef, + ora_module_name => undef, + ora_driver_name => undef, + ora_client_info => undef, + ora_client_identifier => undef, + ora_action => undef, + ora_taf_function => undef, }; } sub table_info { - my($dbh, $CatVal, $SchVal, $TblVal, $TypVal) = @_; - # XXX add knowledge of temp tables, etc - # SQL/CLI (ISO/IEC JTC 1/SC 32 N 0595), 6.63 Tables - if (ref $CatVal eq 'HASH') { - ($CatVal, $SchVal, $TblVal, $TypVal) = - @$CatVal{'TABLE_CAT','TABLE_SCHEM','TABLE_NAME','TABLE_TYPE'}; - } - my @Where = (); - my $SQL; - if ( defined $CatVal && $CatVal eq '%' && (!defined $SchVal || $SchVal eq '') && (!defined $TblVal || $TblVal eq '')) { # Rule 19a - $SQL = <<'SQL'; + my($dbh, $CatVal, $SchVal, $TblVal, $TypVal) = @_; + # XXX add knowledge of temp tables, etc + # SQL/CLI (ISO/IEC JTC 1/SC 32 N 0595), 6.63 Tables + if (ref $CatVal eq 'HASH') { + ($CatVal, $SchVal, $TblVal, $TypVal) = + @$CatVal{'TABLE_CAT','TABLE_SCHEM','TABLE_NAME','TABLE_TYPE'}; + } + my @Where = (); + my $SQL; + if ( defined $CatVal && $CatVal eq '%' && (!defined $SchVal || $SchVal eq '') && (!defined $TblVal || $TblVal eq '')) { # Rule 19a + $SQL = <<'SQL'; SELECT NULL TABLE_CAT , NULL TABLE_SCHEM , NULL TABLE_NAME @@ -449,9 +448,9 @@ SELECT NULL TABLE_CAT , NULL REMARKS FROM DUAL SQL - } - elsif ( defined $SchVal && $SchVal eq '%' && (!defined $CatVal || $CatVal eq '') && (!defined $TblVal || $TblVal eq '')) { # Rule 19b - $SQL = <<'SQL'; + } + elsif ( defined $SchVal && $SchVal eq '%' && (!defined $CatVal || $CatVal eq '') && (!defined $TblVal || $TblVal eq '')) { # Rule 19b + $SQL = <<'SQL'; SELECT NULL TABLE_CAT , s TABLE_SCHEM , NULL TABLE_NAME @@ -465,9 +464,9 @@ SELECT NULL TABLE_CAT ) ORDER BY TABLE_SCHEM SQL - } - elsif ( defined $TypVal && $TypVal eq '%' && (!defined $CatVal || $CatVal eq '') && (!defined $SchVal || $SchVal eq '') && (!defined $TblVal || $TblVal eq '')) { # Rule 19c - $SQL = <<'SQL'; + } + elsif ( defined $TypVal && $TypVal eq '%' && (!defined $CatVal || $CatVal eq '') && (!defined $SchVal || $SchVal eq '') && (!defined $TblVal || $TblVal eq '')) { # Rule 19c + $SQL = <<'SQL'; SELECT NULL TABLE_CAT , NULL TABLE_SCHEM , NULL TABLE_NAME @@ -485,9 +484,9 @@ SELECT NULL TABLE_CAT ) t ORDER BY TABLE_TYPE SQL - } - else { - $SQL = <<'SQL'; + } + else { + $SQL = <<'SQL'; SELECT * FROM ( @@ -496,8 +495,8 @@ SELECT * , t.OWNER TABLE_SCHEM , t.TABLE_NAME TABLE_NAME , decode(t.OWNER - , 'SYS' , 'SYSTEM ' - , 'SYSTEM' , 'SYSTEM ' + , 'SYS' , 'SYSTEM ' + , 'SYSTEM' , 'SYSTEM ' , '' ) || t.TABLE_TYPE TABLE_TYPE , c.COMMENTS REMARKS FROM ALL_TAB_COMMENTS c @@ -507,31 +506,31 @@ SELECT * AND c.TABLE_TYPE (+) = t.TABLE_TYPE ) SQL - if ( defined $SchVal ) { - push @Where, "TABLE_SCHEM LIKE '$SchVal' ESCAPE '\\'"; - } - if ( defined $TblVal ) { - push @Where, "TABLE_NAME LIKE '$TblVal' ESCAPE '\\'"; - } - if ( defined $TypVal ) { - my $table_type_list; - $TypVal =~ s/^\s+//; - $TypVal =~ s/\s+$//; - my @ttype_list = split (/\s*,\s*/, $TypVal); - foreach my $table_type (@ttype_list) { - if ($table_type !~ /^'.*'$/) { - $table_type = "'" . $table_type . "'"; - } - $table_type_list = join(", ", @ttype_list); - } - push @Where, "TABLE_TYPE IN ($table_type_list)"; - } - $SQL .= ' WHERE ' . join("\n AND ", @Where ) . "\n" if @Where; - $SQL .= " ORDER BY TABLE_TYPE, TABLE_SCHEM, TABLE_NAME\n"; - } - my $sth = $dbh->prepare($SQL) or return undef; - $sth->execute or return undef; - $sth; + if ( defined $SchVal ) { + push @Where, "TABLE_SCHEM LIKE '$SchVal' ESCAPE '\\'"; + } + if ( defined $TblVal ) { + push @Where, "TABLE_NAME LIKE '$TblVal' ESCAPE '\\'"; + } + if ( defined $TypVal ) { + my $table_type_list; + $TypVal =~ s/^\s+//; + $TypVal =~ s/\s+$//; + my @ttype_list = split (/\s*,\s*/, $TypVal); + foreach my $table_type (@ttype_list) { + if ($table_type !~ /^'.*'$/) { + $table_type = "'" . $table_type . "'"; + } + $table_type_list = join(", ", @ttype_list); + } + push @Where, "TABLE_TYPE IN ($table_type_list)"; + } + $SQL .= ' WHERE ' . join("\n AND ", @Where ) . "\n" if @Where; + $SQL .= " ORDER BY TABLE_TYPE, TABLE_SCHEM, TABLE_NAME\n"; + } + my $sth = $dbh->prepare($SQL) or return undef; + $sth->execute or return undef; + $sth; } @@ -541,7 +540,7 @@ SQL ($schema, $table) = @$catalog{'TABLE_SCHEM','TABLE_NAME'}; $catalog = undef; } - my $SQL = <<'SQL'; + my $SQL = <<'SQL'; SELECT * FROM ( @@ -565,17 +564,17 @@ SELECT * ORDER BY TABLE_SCHEM, TABLE_NAME, KEY_SEQ SQL #warn "@_\n$Sql ($schema, $table)"; - my $sth = $dbh->prepare($SQL) or return undef; - $sth->execute($schema, $table) or return undef; - $sth; + my $sth = $dbh->prepare($SQL) or return undef; + $sth->execute($schema, $table) or return undef; + $sth; } sub foreign_key_info { - my $dbh = shift; - my $attr = ( ref $_[0] eq 'HASH') ? $_[0] : { - 'UK_TABLE_SCHEM' => $_[1],'UK_TABLE_NAME ' => $_[2] - ,'FK_TABLE_SCHEM' => $_[4],'FK_TABLE_NAME ' => $_[5] }; - my $SQL = <<'SQL'; # XXX: DEFERABILITY + my $dbh = shift; + my $attr = ( ref $_[0] eq 'HASH') ? $_[0] : { + 'UK_TABLE_SCHEM' => $_[1],'UK_TABLE_NAME ' => $_[2] + ,'FK_TABLE_SCHEM' => $_[4],'FK_TABLE_NAME ' => $_[5] }; + my $SQL = <<'SQL'; # XXX: DEFERABILITY SELECT * FROM ( @@ -614,17 +613,17 @@ SELECT * ) WHERE 1 = 1 SQL - my @BindVals = (); - while ( my ( $k, $v ) = each %$attr ) { - if ( $v ) { - $SQL .= " AND $k = ?\n"; - push @BindVals, $v; - } - } - $SQL .= " ORDER BY UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, FK_TABLE_NAME, ORDINAL_POSITION\n"; - my $sth = $dbh->prepare( $SQL ) or return undef; - $sth->execute( @BindVals ) or return undef; - $sth; + my @BindVals = (); + while ( my ( $k, $v ) = each %$attr ) { + if ( $v ) { + $SQL .= " AND $k = ?\n"; + push @BindVals, $v; + } + } + $SQL .= " ORDER BY UK_TABLE_SCHEM, UK_TABLE_NAME, FK_TABLE_SCHEM, FK_TABLE_NAME, ORDINAL_POSITION\n"; + my $sth = $dbh->prepare( $SQL ) or return undef; + $sth->execute( @BindVals ) or return undef; + $sth; } @@ -873,215 +872,215 @@ SQL } sub type_info_all { - my ($dbh) = @_; + my ($dbh) = @_; my $version = ( ora_server_version($dbh)->[0] < DBD::Oracle::ORA_OCI() ) ? ora_server_version($dbh)->[0] : DBD::Oracle::ORA_OCI(); - my $vc2len = ( $version < 8 ) ? "2000" : "4000"; - - my $type_info_all = [ - { - TYPE_NAME => 0, - DATA_TYPE => 1, - COLUMN_SIZE => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE => 9, - FIXED_PREC_SCALE => 10, - AUTO_UNIQUE_VALUE => 11, - LOCAL_TYPE_NAME => 12, - MINIMUM_SCALE => 13, - MAXIMUM_SCALE => 14, - SQL_DATA_TYPE => 15, - SQL_DATETIME_SUB => 16, - NUM_PREC_RADIX => 17, - INTERVAL_PRECISION => 18, - }, - [ "LONG RAW", SQL_LONGVARBINARY, 2147483647,"'", "'", - undef, 1,0,0,undef,0,undef, - "LONG RAW", undef,undef,SQL_LONGVARBINARY,undef,undef,undef, ], - [ "RAW", SQL_VARBINARY, 2000, "'", "'", - "max length", 1,0,3,undef,0,undef, - "RAW", undef,undef,SQL_VARBINARY, undef,undef,undef, ], - [ "LONG", SQL_LONGVARCHAR, 2147483647,"'", "'", - undef, 1,1,0,undef,0,undef, - "LONG", undef,undef,SQL_LONGVARCHAR, undef,undef,undef, ], - [ "CHAR", SQL_CHAR, 2000, "'", "'", - "max length", 1,1,3,undef,0,0, - "CHAR", undef,undef,SQL_CHAR, undef,undef,undef, ], - [ "DECIMAL", SQL_DECIMAL, 38, undef,undef, - "precision,scale",1,0,3,0, 0,0, - "DECIMAL", 0, 38, SQL_DECIMAL, undef,10, undef, ], - [ "DOUBLE PRECISION",SQL_DOUBLE, 15, undef,undef, - undef, 1,0,3,0, 0,0, - "DOUBLE PRECISION",undef,undef,SQL_DOUBLE, undef,10, undef, ], - [ "DATE", SQL_TYPE_TIMESTAMP,19, "'", "'", - undef, 1,0,3,undef,0,0, - "DATE", 0, 0, SQL_DATE, 3, undef,undef, ], - [ "VARCHAR2", SQL_VARCHAR, $vc2len, "'", "'", - "max length", 1,1,3,undef,0,0, - "VARCHAR2", undef,undef,SQL_VARCHAR, undef,undef,undef, ], - [ "BLOB", SQL_BLOB, 2147483647,"'", "'", - undef, 1,1,0,undef,0,undef, - "BLOB", undef,undef,SQL_LONGVARBINARY,undef,undef,undef, ], - [ "BFILE", -9114, 2147483647,"'", "'", - undef, 1,1,0,undef,0,undef, - "BFILE", undef,undef,SQL_LONGVARBINARY,undef,undef,undef, ], - [ "CLOB", SQL_CLOB, 2147483647,"'", "'", - undef, 1,1,0,undef,0,undef, - "CLOB", undef,undef,SQL_LONGVARCHAR, undef,undef,undef, ], - ["TIMESTAMP WITH TIME ZONE", # type name - SQL_TYPE_TIMESTAMP_WITH_TIMEZONE, # data type - 40, # column size - "TIMESTAMP'", # literal prefix - "'", # literal suffix - "precision", # create params - 1, # nullable - 0, # case sensitive - 3, # searchable - undef, # unsigned attribute - 0, # fixed prec scale - 0, # auto unique value - undef, # local type name - 0, # minimum scale - 6, # maximum scale - SQL_TIMESTAMP, # sql data type - 5, # sql datetime sub - undef, # num prec radix - undef, # interval precision - ], - [ "INTERVAL DAY TO SECOND", # type name - SQL_INTERVAL_DAY_TO_SECOND, # data type - 22, # column size '+00 11:12:10.222222200' - "INTERVAL'", # literal prefix - "'", # literal suffix - "precision", # create params - 1, # nullable - 0, # case sensitive - 3, # searchable - undef, # unsigned attribute - 0, # fixed prec scale - 0, # auto unique value - undef, # local type name - 0, # minimum scale - 9, # maximum scale - SQL_INTERVAL, # sql data type - 10, # sql datetime sub - undef, # num prec radix - undef, # interval precision - ], - [ "INTERVAL YEAR TO MONTH", # type name - SQL_INTERVAL_YEAR_TO_MONTH, # data type - 13, # column size '+012345678-01' - "INTERVAL'", # literal prefix - "'", # literal suffix - "precision", # create params - 1, # nullable - 0, # case sensitive - 3, # searchable - undef, # unsigned attribute - 0, # fixed prec scale - 0, # auto unique value - undef, # local type name - 0, # minimum scale - 9, # maximum scale - SQL_INTERVAL, # sql data type - 7, # sql datetime sub - undef, # num prec radix - undef, # interval precision - ] - ]; - - return $type_info_all; + my $vc2len = ( $version < 8 ) ? '2000' : '4000'; + + my $type_info_all = [ + { + TYPE_NAME => 0, + DATA_TYPE => 1, + COLUMN_SIZE => 2, + LITERAL_PREFIX => 3, + LITERAL_SUFFIX => 4, + CREATE_PARAMS => 5, + NULLABLE => 6, + CASE_SENSITIVE => 7, + SEARCHABLE => 8, + UNSIGNED_ATTRIBUTE => 9, + FIXED_PREC_SCALE => 10, + AUTO_UNIQUE_VALUE => 11, + LOCAL_TYPE_NAME => 12, + MINIMUM_SCALE => 13, + MAXIMUM_SCALE => 14, + SQL_DATA_TYPE => 15, + SQL_DATETIME_SUB => 16, + NUM_PREC_RADIX => 17, + INTERVAL_PRECISION => 18, + }, + [ 'LONG RAW', SQL_LONGVARBINARY, 2147483647,"'", "'", + undef, 1,0,0,undef,0,undef, + 'LONG RAW', undef,undef,SQL_LONGVARBINARY,undef,undef,undef, ], + [ 'RAW', SQL_VARBINARY, 2000, "'", "'", + 'max length', 1,0,3,undef,0,undef, + 'RAW', undef,undef,SQL_VARBINARY, undef,undef,undef, ], + [ 'LONG', SQL_LONGVARCHAR, 2147483647,"'", "'", + undef, 1,1,0,undef,0,undef, + 'LONG', undef,undef,SQL_LONGVARCHAR, undef,undef,undef, ], + [ 'CHAR', SQL_CHAR, 2000, "'", "'", + 'max length', 1,1,3,undef,0,0, + 'CHAR', undef,undef,SQL_CHAR, undef,undef,undef, ], + [ 'DECIMAL', SQL_DECIMAL, 38, undef,undef, + 'precision,scale',1,0,3,0, 0,0, + 'DECIMAL', 0, 38, SQL_DECIMAL, undef,10, undef, ], + [ "DOUBLE PRECISION",SQL_DOUBLE, 15, undef,undef, + undef, 1,0,3,0, 0,0, + "DOUBLE PRECISION",undef,undef,SQL_DOUBLE, undef,10, undef, ], + [ "DATE", SQL_TYPE_TIMESTAMP,19, "'", "'", + undef, 1,0,3,undef,0,0, + "DATE", 0, 0, SQL_DATE, 3, undef,undef, ], + [ "VARCHAR2", SQL_VARCHAR, $vc2len, "'", "'", + "max length", 1,1,3,undef,0,0, + "VARCHAR2", undef,undef,SQL_VARCHAR, undef,undef,undef, ], + [ "BLOB", SQL_BLOB, 2147483647,"'", "'", + undef, 1,1,0,undef,0,undef, + "BLOB", undef,undef,SQL_LONGVARBINARY,undef,undef,undef, ], + [ "BFILE", -9114, 2147483647,"'", "'", + undef, 1,1,0,undef,0,undef, + "BFILE", undef,undef,SQL_LONGVARBINARY,undef,undef,undef, ], + [ "CLOB", SQL_CLOB, 2147483647,"'", "'", + undef, 1,1,0,undef,0,undef, + "CLOB", undef,undef,SQL_LONGVARCHAR, undef,undef,undef, ], + ["TIMESTAMP WITH TIME ZONE", # type name + SQL_TYPE_TIMESTAMP_WITH_TIMEZONE, # data type + 40, # column size + "TIMESTAMP'", # literal prefix + "'", # literal suffix + "precision", # create params + 1, # nullable + 0, # case sensitive + 3, # searchable + undef, # unsigned attribute + 0, # fixed prec scale + 0, # auto unique value + undef, # local type name + 0, # minimum scale + 6, # maximum scale + SQL_TIMESTAMP, # sql data type + 5, # sql datetime sub + undef, # num prec radix + undef, # interval precision + ], + [ "INTERVAL DAY TO SECOND", # type name + SQL_INTERVAL_DAY_TO_SECOND, # data type + 22, # column size '+00 11:12:10.222222200' + "INTERVAL'", # literal prefix + "'", # literal suffix + "precision", # create params + 1, # nullable + 0, # case sensitive + 3, # searchable + undef, # unsigned attribute + 0, # fixed prec scale + 0, # auto unique value + undef, # local type name + 0, # minimum scale + 9, # maximum scale + SQL_INTERVAL, # sql data type + 10, # sql datetime sub + undef, # num prec radix + undef, # interval precision + ], + [ "INTERVAL YEAR TO MONTH", # type name + SQL_INTERVAL_YEAR_TO_MONTH, # data type + 13, # column size '+012345678-01' + "INTERVAL'", # literal prefix + "'", # literal suffix + "precision", # create params + 1, # nullable + 0, # case sensitive + 3, # searchable + undef, # unsigned attribute + 0, # fixed prec scale + 0, # auto unique value + undef, # local type name + 0, # minimum scale + 9, # maximum scale + SQL_INTERVAL, # sql data type + 7, # sql datetime sub + undef, # num prec radix + undef, # interval precision + ] + ]; + + return $type_info_all; } sub plsql_errstr { - # original version thanks to Bob Menteer - my $sth = shift->prepare_cached(q{ - SELECT name, type, line, position, text - FROM user_errors ORDER BY name, type, sequence - }) or return undef; - $sth->execute or return undef; - my ( @msg, $oname, $otype, $name, $type, $line, $pos, $text ); - $oname = $otype = 0; - while ( ( $name, $type, $line, $pos, $text ) = $sth->fetchrow_array ) { - if ( $oname ne $name || $otype ne $type ) { - push @msg, "Errors for $type $name:"; - $oname = $name; - $otype = $type; - } - push @msg, "$line.$pos: $text"; - } - return join( "\n", @msg ); + # original version thanks to Bob Menteer + my $sth = shift->prepare_cached(q{ + SELECT name, type, line, position, text + FROM user_errors ORDER BY name, type, sequence + }) or return undef; + $sth->execute or return undef; + my ( @msg, $oname, $otype, $name, $type, $line, $pos, $text ); + $oname = $otype = 0; + while ( ( $name, $type, $line, $pos, $text ) = $sth->fetchrow_array ) { + if ( $oname ne $name || $otype ne $type ) { + push @msg, "Errors for $type $name:"; + $oname = $name; + $otype = $type; + } + push @msg, "$line.$pos: $text"; + } + return join( "\n", @msg ); } # # note, dbms_output must be enabled prior to usage # sub dbms_output_enable { - my ($dbh, $buffersize) = @_; - $buffersize ||= 20000; # use oracle 7.x default - $dbh->do("begin dbms_output.enable(:1); end;", undef, $buffersize); + my ($dbh, $buffersize) = @_; + $buffersize ||= 20000; # use oracle 7.x default + $dbh->do("begin dbms_output.enable(:1); end;", undef, $buffersize); } sub dbms_output_get { - my $dbh = shift; - my $sth = $dbh->prepare_cached("begin dbms_output.get_line(:l, :s); end;") - or return; - my ($line, $status, @lines); - my $version = join ".", @{ ora_server_version($dbh) }[0..1]; - my $len = 32767; - if ($version < 10.2){ - $len = 400; - } - # line can be greater that 255 (e.g. 7 byte date is expanded on output) - $sth->bind_param_inout(':l', \$line, $len, { ora_type => 1 }); - $sth->bind_param_inout(':s', \$status, 20, { ora_type => 1 }); - if (!wantarray) { - $sth->execute or return undef; - return $line if $status eq '0'; - return undef; - } - push @lines, $line while($sth->execute && $status eq '0'); - return @lines; + my $dbh = shift; + my $sth = $dbh->prepare_cached("begin dbms_output.get_line(:l, :s); end;") + or return; + my ($line, $status, @lines); + my $version = join ".", @{ ora_server_version($dbh) }[0..1]; + my $len = 32767; + if ($version < 10.2){ + $len = 400; + } + # line can be greater that 255 (e.g. 7 byte date is expanded on output) + $sth->bind_param_inout(':l', \$line, $len, { ora_type => 1 }); + $sth->bind_param_inout(':s', \$status, 20, { ora_type => 1 }); + if (!wantarray) { + $sth->execute or return undef; + return $line if $status eq '0'; + return undef; + } + push @lines, $line while($sth->execute && $status eq '0'); + return @lines; } sub dbms_output_put { - my $dbh = shift; - my $sth = $dbh->prepare_cached("begin dbms_output.put_line(:1); end;") - or return; - my $line; - foreach $line (@_) { - $sth->execute($line) or return; - } - return 1; + my $dbh = shift; + my $sth = $dbh->prepare_cached("begin dbms_output.put_line(:1); end;") + or return; + my $line; + foreach $line (@_) { + $sth->execute($line) or return; + } + return 1; } sub dbms_msgpipe_get { - my $dbh = shift; - my $sth = $dbh->prepare_cached(q{ - begin dbms_msgpipe.get_request(:returnpipe, :proc, :param); end; - }) or return; - my $msg = ['','','']; - $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); - $sth->bind_param_inout(":proc", \$msg->[1], 30); - $sth->bind_param_inout(":param", \$msg->[2], 4000); - $sth->execute or return undef; - return $msg; + my $dbh = shift; + my $sth = $dbh->prepare_cached(q{ + begin dbms_msgpipe.get_request(:returnpipe, :proc, :param); end; + }) or return; + my $msg = ['','','']; + $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); + $sth->bind_param_inout(":proc", \$msg->[1], 30); + $sth->bind_param_inout(":param", \$msg->[2], 4000); + $sth->execute or return undef; + return $msg; } sub dbms_msgpipe_ack { my $dbh = shift; my $msg = shift; my $sth = $dbh->prepare_cached(q{ - begin dbms_msgpipe.acknowledge(:returnpipe, :errormsg, :param); end;}) or return; - $sth->bind_param_inout(":returnpipe", \$msg->[0], 30); - $sth->bind_param_inout(":proc", \$msg->[1], 30); - $sth->bind_param_inout(":param", \$msg->[2], 4000); + begin dbms_msgpipe.acknowledge(:returnpipe, :errormsg, :param); end;}) or return; + $sth->bind_param_inout(':returnpipe', \$msg->[0], 30); + $sth->bind_param_inout(':proc', \$msg->[1], 30); + $sth->bind_param_inout(':param', \$msg->[2], 4000); $sth->execute or return undef; return 1; } @@ -1104,39 +1103,39 @@ SQL } sub ora_nls_parameters { - my $dbh = shift; - my $refresh = shift; + my $dbh = shift; + my $refresh = shift; - if ($refresh || !$dbh->{ora_nls_parameters}) { + if ($refresh || !$dbh->{ora_nls_parameters}) { my $nls_parameters = $dbh->selectall_arrayref(q{ - SELECT parameter, value FROM v$nls_parameters - }) or return; - $dbh->{ora_nls_parameters} = { map { $_->[0] => $_->[1] } @$nls_parameters }; - } - - # return copy of params to protect against accidental editing - my %nls = %{$dbh->{ora_nls_parameters}}; - return \%nls; + SELECT parameter, value FROM v$nls_parameters + }) or return; + $dbh->{ora_nls_parameters} = { map { $_->[0] => $_->[1] } @$nls_parameters }; + } + + # return copy of params to protect against accidental editing + my %nls = %{$dbh->{ora_nls_parameters}}; + return \%nls; } sub ora_can_unicode { - my $dbh = shift; - my $refresh = shift; - # 0 = No Unicode support. - # 1 = National character set is Unicode-based. - # 2 = Database character set is Unicode-based. - # 3 = Both character sets are Unicode-based. + my $dbh = shift; + my $refresh = shift; + # 0 = No Unicode support. + # 1 = National character set is Unicode-based. + # 2 = Database character set is Unicode-based. + # 3 = Both character sets are Unicode-based. - return $dbh->{ora_can_unicode} - if defined $dbh->{ora_can_unicode} && !$refresh; + return $dbh->{ora_can_unicode} + if defined $dbh->{ora_can_unicode} && !$refresh; - my $nls = $dbh->ora_nls_parameters($refresh); + my $nls = $dbh->ora_nls_parameters($refresh); - $dbh->{ora_can_unicode} = 0; - $dbh->{ora_can_unicode} += 1 if $nls->{NLS_NCHAR_CHARACTERSET} =~ /UTF/; - $dbh->{ora_can_unicode} += 2 if $nls->{NLS_CHARACTERSET} =~ /UTF/; + $dbh->{ora_can_unicode} = 0; + $dbh->{ora_can_unicode} += 1 if $nls->{NLS_NCHAR_CHARACTERSET} =~ m/UTF/; + $dbh->{ora_can_unicode} += 2 if $nls->{NLS_CHARACTERSET} =~ m/UTF/; - return $dbh->{ora_can_unicode}; + return $dbh->{ora_can_unicode}; } } # end of package DBD::Oracle::db @@ -1147,23 +1146,23 @@ SQL sub bind_param_inout_array { - my $sth = shift; - my ($p_id, $value_array,$maxlen, $attr) = @_; - return $sth->set_err($DBI::stderr, "Value for parameter $p_id must be an arrayref, not a ".ref($value_array)) - if defined $value_array and ref $value_array and ref $value_array ne 'ARRAY'; + my $sth = shift; + my ($p_id, $value_array,$maxlen, $attr) = @_; + return $sth->set_err($DBI::stderr, "Value for parameter $p_id must be an arrayref, not a ".ref($value_array)) + if defined $value_array and ref $value_array and ref $value_array ne 'ARRAY'; - return $sth->set_err($DBI::stderr, "Can't use named placeholder '$p_id' for non-driver supported bind_param_inout_array") - unless DBI::looks_like_number($p_id); # because we rely on execute(@ary) here + return $sth->set_err($DBI::stderr, "Can't use named placeholder '$p_id' for non-driver supported bind_param_inout_array") + unless DBI::looks_like_number($p_id); # because we rely on execute(@ary) here - return $sth->set_err($DBI::stderr, "Placeholder '$p_id' is out of range") - if $p_id <= 0; # can't easily/reliably test for too big + return $sth->set_err($DBI::stderr, "Placeholder '$p_id' is out of range") + if $p_id <= 0; # can't easily/reliably test for too big - # get/create arrayref to hold params - my $hash_of_arrays = $sth->{ParamArrays} ||= { }; + # get/create arrayref to hold params + my $hash_of_arrays = $sth->{ParamArrays} ||= { }; $$hash_of_arrays{$p_id} = $value_array; - return ora_bind_param_inout_array($sth, $p_id, $value_array,$maxlen, $attr); - 1; + return ora_bind_param_inout_array($sth, $p_id, $value_array,$maxlen, $attr); + 1; } @@ -1198,9 +1197,10 @@ SQL $tuple_batch_status, $err_count ); - if(defined($res)) { #no error + if (defined($res)) { #no error $row_count += $res; - } else { + } + else { $row_count = undef; } @@ -1215,7 +1215,7 @@ SQL } #error check here return $sth->set_err($DBI::stderr, "executing $tuple_count generated $err_total errors") - if $err_total; + if $err_total; return wantarray ? ($tuple_count, defined $row_count ? $row_count : undef) @@ -3078,7 +3078,7 @@ with code like this: $sth->bind_param_inout_array(2,\@out_values,0,{ora_type => ORA_VARCHAR2}); $sth->execute_array({ArrayTupleStatus=>\@status}) or die "error inserting"; foreach my $id (@out_values){ - print 'returned id='.$id.'\n'; + print 'returned id='.$id.'\n'; } Which will return all the ids into @out_values. @@ -3160,9 +3160,9 @@ package. Here's the new package specification and body : CREATE OR REPLACE PACKAGE Array_Example AS -- TYPE tRec IS RECORD ( - Col1 NUMBER, - Col2 VARCHAR2 (10), - Col3 DATE) ; + Col1 NUMBER, + Col2 VARCHAR2 (10), + Col3 DATE) ; -- TYPE taRec IS TABLE OF tRec INDEX BY BINARY_INTEGER ; -- @@ -3177,9 +3177,9 @@ package. Here's the new package specification and body : l_Ret taRec ; BEGIN FOR i IN 1 .. 5 LOOP - l_Ret (i).Col1 := i ; - l_Ret (i).Col2 := 'Row : ' || i ; - l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; + l_Ret (i).Col1 := i ; + l_Ret (i).Col2 := 'Row : ' || i ; + l_Ret (i).Col3 := TRUNC (SYSDATE) + i ; END LOOP ; RETURN l_Ret ; END ; @@ -3189,13 +3189,13 @@ package. Here's the new package specification and body : BEGIN l_Set := Array_Func ; FOR i IN l_Set.FIRST .. l_Set.LAST LOOP - PIPE ROW ( - tArray_Example__taRec ( - l_Set (i).Col1, - l_Set (i).Col2, - l_Set (i).Col3 - ) - ) ; + PIPE ROW ( + tArray_Example__taRec ( + l_Set (i).Col1, + l_Set (i).Col2, + l_Set (i).Col3 + ) + ) ; END LOOP ; RETURN ; END ; @@ -3212,10 +3212,6 @@ the above example, the code would look something like this : ... } - - - - =head3 B DBD::Oracle has built-in support for B @@ -3223,13 +3219,13 @@ and B datatypes. The simple example is here: my $statement=' DECLARE - tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; BEGIN - tbl := :mytable; - :cc := tbl.count(); - tbl(1) := \'def\'; - tbl(2) := \'ijk\'; - :mytable := tbl; + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := \'def\'; + tbl(2) := \'ijk\'; + :mytable := tbl; END; '; @@ -3243,8 +3239,8 @@ and B datatypes. The simple example is here: } ) ; $sth->bind_param_inout(":cc", \$cc, 100 ); $sth->execute(); - print "Result: cc=",$cc,"\n", - "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + print "Result: cc=",$cc,"\n", + "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; =over @@ -3255,8 +3251,6 @@ and B datatypes. The simple example is here: =back - - =head3 B SYS.DBMS_SQL.VARCHAR2_TABLE object is always bound to array reference. @@ -3945,8 +3939,8 @@ an 'ORA-01062: unable to allocate memory for define buffer' error. One solution For example give this table; CREATE TABLE test_long ( - id NUMBER, - long1 long) + id NUMBER, + long1 long) this code; @@ -4173,7 +4167,7 @@ Below are the limitations of Remote LOBs; so the following returns an error: SELECT t1.lobcol, - a2.lobcol + a2.lobcol FROM t1, t2.lobcol@dbs2 a2 W WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol); @@ -4876,9 +4870,9 @@ Array example, given this type and table; CREATE OR REPLACE TYPE "PHONE_NUMBERS" as varray(10) of varchar(30); CREATE TABLE "CONTACT" - ( "COMPANYNAME" VARCHAR2(40), - "ADDRESS" VARCHAR2(100), - "PHONE_NUMBERS" "PHONE_NUMBERS" + ( "COMPANYNAME" VARCHAR2(40), + "ADDRESS" VARCHAR2(100), + "PHONE_NUMBERS" "PHONE_NUMBERS" ) The code to access all the data in the table could be something like this; @@ -5090,17 +5084,17 @@ one can insert data using this code $SQL='insert into books values (1,:p_xml)'; $xml= ' - - Programming the Perl DBI - The Cheetah Book - - T. Bunce - Alligator Descartes - - - - ... - '; + + Programming the Perl DBI + The Cheetah Book + + T. Bunce + Alligator Descartes + + + + ... + '; my $sth =$dbh-> prepare($SQL); $sth-> bind_param("p_xml", $xml, { ora_type => ORA_XMLTYPE }); $sth-> execute(); @@ -5343,7 +5337,7 @@ Most of these PL/SQL examples come from: Eric Bartley . # See the DBI docs now if you're not familiar with RaiseError. $db->{RaiseError} = 1; - # Example 1 Eric Bartley + # Example 1 Eric Bartley # # Calling a PLSQL procedure that takes no parameters. This shows you the # basic's of what you need to execute a PLSQL procedure. Just wrap your @@ -5360,7 +5354,7 @@ Most of these PL/SQL examples come from: Eric Bartley . $csr->execute; - # Example 2 Eric Bartley + # Example 2 Eric Bartley # # Now we call a procedure that has 1 IN parameter. Here we use bind_param # to bind out parameter to the prepared statement just like you might @@ -5373,9 +5367,9 @@ Most of these PL/SQL examples come from: Eric Bartley . my $err_code = -20001; $csr = $db->prepare(q{ - BEGIN - PLSQL_EXAMPLE.PROC_IN(:err_code); - END; + BEGIN + PLSQL_EXAMPLE.PROC_IN(:err_code); + END; }); $csr->bind_param(":err_code", $err_code); @@ -5388,7 +5382,7 @@ Most of these PL/SQL examples come from: Eric Bartley . print 'After proc_in: $@=',"'$@', errstr=$DBI::errstr, ret_val=$ret_val\n"; - # Example 3 Eric Bartley + # Example 3 Eric Bartley # # Building on the last example, I've added 1 IN OUT parameter. We still # use a placeholders in the call to prepare, the difference is that @@ -5403,9 +5397,9 @@ Most of these PL/SQL examples come from: Eric Bartley . my $is_odd; $csr = $db->prepare(q{ - BEGIN - PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); - END; + BEGIN + PLSQL_EXAMPLE.PROC_IN_INOUT(:test_num, :is_odd); + END; }); # The value of $test_num is _copied_ here @@ -5419,7 +5413,7 @@ Most of these PL/SQL examples come from: Eric Bartley . print "$test_num is ", ($is_odd) ? "odd - ok" : "even - error!", "\n"; - # Example 4 Eric Bartley + # Example 4 Eric Bartley # # What about the return value of a PLSQL function? Well treat it the same # as you would a call to a function from SQL*Plus. We add a placeholder @@ -5429,9 +5423,9 @@ Most of these PL/SQL examples come from: Eric Bartley . my $whoami = ""; $csr = $db->prepare(q{ - BEGIN - :whoami := PLSQL_EXAMPLE.FUNC_NP; - END; + BEGIN + :whoami := PLSQL_EXAMPLE.FUNC_NP; + END; }); $csr->bind_param_inout(":whoami", \$whoami, 20); @@ -5466,64 +5460,6 @@ If you'd like DBD::Oracle to do something new or different the best way to make that happen is to do it yourself and email to dbi-dev@perl.org a patch of the source code (using 'diff' - see below) that shows the changes. -=head2 How to create a patch using Subversion - -The DBD::Oracle source code is maintained using Subversion (a replacement -for CVS, see L). To access the source -you'll need to install a Subversion client. Then, to get the source -code, do: - - svn checkout http://svn.perl.org/modules/dbd-oracle/trunk - -If it prompts for a username and password use your perl.org account -if you have one, else just 'guest' and 'guest'. The source code will -be in a new subdirectory called C. - -To keep informed about changes to the source you can send an empty email -to dbd-oracle-changes-subscribe@perl.org after which you'll get an email with the -change log message and diff of each change checked-in to the source. - -After making your changes you can generate a patch file, but before -you do, make sure your source is still upto date using: - - svn update - -If you get any conflicts reported you'll need to fix them first. -Then generate the patch file from within the C directory using: - - svn diff > foo.patch - -Read the patch file, as a sanity check, and then email it to dbi-dev@perl.org. - -=head2 How to create a patch without Subversion - -Unpack a fresh copy of the distribution: - - tar xfz DBD-Oracle-1.40.tar.gz - -Rename the newly created top level directory: - - mv DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo - -Edit the contents of DBD-Oracle-1.40.your_foo/* till it does what you want. - -Test your changes and then remove all temporary files: - - make test && make distclean - -Go back to the directory you originally unpacked the distribution: - - cd .. - -Unpack I copy of the original distribution you started with: - - tar xfz DBD-Oracle-1.40.tar.gz - -Then create a patch file by performing a recursive C on the two -top level directories: - - diff -r -u DBD-Oracle-1.40 DBD-Oracle-1.40.your_foo > DBD-Oracle-1.40.your_foo.patch - =head2 Speak before you patch For anything non-trivial or possibly controversial it's a good idea @@ -5532,11 +5468,6 @@ actually spending time working on them. Otherwise you run the risk of them being rejected because they don't fit into some larger plans you may not be aware of. -=head2 GitHub repository - -A git mirror of the subversion is also available at -`https://github.com/yanick/DBD-Oracle`. - =head1 WHICH VERSION OF DBD::ORACLE IS FOR ME? From version 1.25 onwards DBD::Oracle only support Oracle clients @@ -5607,13 +5538,6 @@ and even get to 10. I am not sure what the 11g client can connect to. =back -=head1 BUGS AND LIMITATIONS - -There is a known problem with the 11.2g Oracle client and the -C PL/SQL function. -See L for the details. - - =head1 SEE ALSO =over diff --git a/lib/DBD/Oracle/GetInfo.pm b/lib/DBD/Oracle/GetInfo.pm index edacde25..0e31d9c4 100644 --- a/lib/DBD/Oracle/GetInfo.pm +++ b/lib/DBD/Oracle/GetInfo.pm @@ -1,8 +1,12 @@ -package DBD::Oracle::GetInfo; +#!perl # ABSTRACT: Wrapper to get Oracle information - use strict; -use DBD::Oracle(); +use warnings; + +package DBD::Oracle::GetInfo; +# VERSION + +use DBD::Oracle (); my $sql_driver = 'Oracle'; my $sql_ver_fmt = '%02d.%02d.%04d'; # ODBC version string: ##.##.##### @@ -18,7 +22,7 @@ my $sql_driver_ver = sprintf $sql_ver_fmt, $a, $b, $c; sub sql_dbms_version { my $dbh = shift; local $^W; # for ora_server_version having too few parts - return sprintf $sql_ver_fmt, @{DBD::Oracle::db::ora_server_version($dbh)}; + return sprintf $sql_ver_fmt, @{DBD::Oracle::db::ora_server_version($dbh)}[0..2]; } my @Keywords = qw( diff --git a/lib/DBD/Oracle/Object.pm b/lib/DBD/Oracle/Object.pm index 39a99498..faca14fc 100644 --- a/lib/DBD/Oracle/Object.pm +++ b/lib/DBD/Oracle/Object.pm @@ -1,25 +1,27 @@ -package DBD::Oracle::Object; -# ABSTRACT: Wrapper for Oracle objects - -use strict; -use warnings; - -sub type_name { shift->{type_name} } - -sub attributes { @{shift->{attributes}} } - -sub attr_hash { - my $self = shift; - return $self->{attr_hash} ||= { $self->attributes }; -} - -sub attr { - my $self = shift; - if (@_) { - my $key = shift; - return $self->attr_hash->{$key}; - } - return $self->attr_hash; -} - -1; +#!perl +# ABSTRACT: Wrapper for Oracle objects +use strict; +use warnings; + +package DBD::Oracle::Object; +# VERSION + +sub type_name { shift->{type_name} } + +sub attributes { @{shift->{attributes}} } + +sub attr_hash { + my $self = shift; + return $self->{attr_hash} ||= { $self->attributes }; +} + +sub attr { + my $self = shift; + if (@_) { + my $key = shift; + return $self->attr_hash->{$key}; + } + return $self->attr_hash; +} + +1; diff --git a/lib/DBD/Oracle/Troubleshooting.pod b/lib/DBD/Oracle/Troubleshooting.pod index beecf304..bb0a82c9 100644 --- a/lib/DBD/Oracle/Troubleshooting.pod +++ b/lib/DBD/Oracle/Troubleshooting.pod @@ -1,4 +1,4 @@ -#PODNAME: DBD::Oracle::Troubleshooting +#PODNAME: DBD::Oracle::Troubleshooting #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle =head1 CONNECTING TO ORACLE @@ -62,8 +62,8 @@ Oracle technical support (and not the dbi-users mailing list). =head2 Connecting using a bequeather If you are using a bequeather to connect to a server -on the same host as the client, you might have -to add +on the same host as the client, you might have +to add bequeath_detach = yes diff --git a/lib/DBD/Oracle/Troubleshooting/Aix.pod b/lib/DBD/Oracle/Troubleshooting/Aix.pod index d3a1f4bb..c2eda4c6 100644 --- a/lib/DBD/Oracle/Troubleshooting/Aix.pod +++ b/lib/DBD/Oracle/Troubleshooting/Aix.pod @@ -1,7 +1,7 @@ #PODNAME: DBD::Oracle::Troubleshooting::Aix #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on AIX -=head1 Using Visual Age 7 C Compiler +=head1 Using Visual Age 7 C Compiler Oracle 9i is only certified as a 64-bit application on AIX 5L (5.1,5.2,5.3) with 32-bit support; in other words, there is no 9i "32-bit" Oracle client @@ -10,12 +10,12 @@ Oracle 10g is certified as both a 64-bit application and a 32-bit Oracle client This information only pertains to deploying: - the DBI (version 1.48) - and DBD-Oracle (version 1.16): - on AIX 5.3 - using Oracle 9i (9.2.0.1/9.2.0.5) - using the existing Perl 5.8.2 (no custom-built Perl) which is 32-bit - using Visual Age 7.0 C/C++ compiler + the DBI (version 1.48) + and DBD-Oracle (version 1.16): + on AIX 5.3 + using Oracle 9i (9.2.0.1/9.2.0.5) + using the existing Perl 5.8.2 (no custom-built Perl) which is 32-bit + using Visual Age 7.0 C/C++ compiler Install the DBI (required for the DBD-Oracle install - no issues here) Untar the DBD-Oracle bundle @@ -40,13 +40,13 @@ I've tested the basics of the DBD-Oracle and it seems fully functional. Stephen de Vries -=head1 Using gcc C Compiler +=head1 Using gcc C Compiler DBD::Oracle with gcc and Oracle Instant Client on AIX - -------------------------------------------------------------------------------------- + -------------------------------------------------------------------------------------- Nathan Vonnahme Dec 15 2005, 4:28 pm Newsgroups: perl.dbi.users See: http://groups.google.com/group/perl.dbi.users/msg/0bd9097f80f2c8a9 - [ with updates 1/31/2006 - DBD::Oracle 1.17 doesn't need makefile hacking + [ with updates 1/31/2006 - DBD::Oracle 1.17 doesn't need makefile hacking to work with instantclient on AIX ] @@ -75,11 +75,11 @@ Stephen de Vries Oracle wasn't providing the sqlplus package for 32 bit AIX so I explicitly told Makefile.PL the version: - perl Makefile.PL -V 10.1 + perl Makefile.PL -V 10.1 make - My test databases were on other machines so I set these environment variables + My test databases were on other machines so I set these environment variables to get the tests to run: export ORACLE_DSN=DBI:Oracle://host/dbinstance @@ -89,11 +89,11 @@ Stephen de Vries make install - NOTE: I have an older full version of Oracle on this machine, and the - ORACLE_HOME environment variable is normally set to point to that, so + NOTE: I have an older full version of Oracle on this machine, and the + ORACLE_HOME environment variable is normally set to point to that, so my perl scripts that use DBD::Oracle have to make sure to first set $ENV{ORACLE_HOME}='/usr/local/oracle/instantclient'; - + @@ -120,9 +120,9 @@ Stephen de Vries --Adrian Terranova -=head1 Using xlc_r C Compiler +=head1 Using xlc_r C Compiler - From: Rafael Caceres + From: Rafael Caceres Date: 22 Jul 2003 10:05:20 -0500 The following sequence worked for me on AIX 5.1: @@ -132,12 +132,12 @@ Stephen de Vries -use the xlc_r version of IBM's compiler and build a 32 bit Perl (which xlc_r will do by default). All tests should be successful. - -get and install DBI + -get and install DBI -get DBD::Oracle. Edit the Makefile.PL or Makefile for DBD::Oracle, changing references to Oracle's ../lib to ../lib32. and change crt0_64.o to crt0_r.o. Remove the -q32 and/or -q64 options from the list of - libraries to link with. Do the make and make test. + libraries to link with. Do the make and make test. -Set up the environment for making DBD::Oracle: ORACLE_HOME="your oracle home" @@ -156,40 +156,40 @@ Stephen de Vries > I don't believe I compiled Oracle. During the installation it was linked > but I am not sure it was compiled - > + > > I used a xlc compiler to compile PERL. > Got this message in the Perl Makefile.PL output - > + > > Warning: You will may need to rebuild perl using the xlc_r compiler. > You may also need do: ORACCENV='cc=xlc_r'; export ORACCENV > Also see the README about the -p option - > + > > this probably means I need to rebuild PERL with xlc_r?? - > + > > thanx - > + > > Mike Paladino > Database Administrator - From: Rafael Caceres - > + From: Rafael Caceres + > > Make sure you use the same compiler to build Oracle and Perl. We have > used xlc_r on Aix 5.1 with no problems. Your Perl build is 32 bit, so > when building DBD::Oracle, you should use the 32bit libraries (change > references to .../oracle/lib to .../oracle/lib32 in your Makefile). > Remove the references to the -q64 or -q32 parameters for ld in Makefile, > as they shouldn't be there. - > + > > Rafael Caceres - From: "cartman ltd" + From: "cartman ltd" Subject: Tip for DBI and DBD::Oracle on AIX 5.1 and Oracle 9.2 Date: Mon, 11 Aug 2003 18:15:38 +0000 Message-ID: - Here is a tip for compiling DBD::Oracle as a 32 bit application on AIX 5.1 + Here is a tip for compiling DBD::Oracle as a 32 bit application on AIX 5.1 64 bit and Oracle 9.2 64 bit without editing any makefiles. I hope people find this useful: @@ -200,16 +200,16 @@ Stephen de Vries AIX 5.1 ML03 - 64 bit kernel - ships with Perl as a 32 bit application. VisualAge C/C++ 5.0.2 - Basically DBD must be compiled as 32 bit to link with Perl's 32 bit + Basically DBD must be compiled as 32 bit to link with Perl's 32 bit libraries. gunzip -c DBD-Oracle-1.14.tar.gz | tar xvf  cd DBD-Oracle-1.14 perl Makefile.PL -m $ORACLE_HOME/rdbms/demo/demo_rdbms32.mk make - NB: I think there is a bug in the Oracle 9.2.0.3 file + NB: I think there is a bug in the Oracle 9.2.0.3 file $ORACLE_HOME/rdbms/lib/env_rdbms.mk - I corrected this (before running the above commands) by replacing the + I corrected this (before running the above commands) by replacing the invalid linker option LDFLAGS32=-q32 with @@ -219,7 +219,7 @@ Stephen de Vries -------------------------------------------------------------------------------------- Date: Wed, 30 Jun 2004 23:34:24 -0500 - From: "SCHULTZ, DARYLE (SBCSI)" + From: "SCHULTZ, DARYLE (SBCSI)" Got it to work. Using dbd 1.16 diff --git a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod index e994bd77..ba1ab97d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Cygwin.pod +++ b/lib/DBD/Oracle/Troubleshooting/Cygwin.pod @@ -65,4 +65,3 @@ this: my $dbh = DBI->connect('dbi:Oracle:host=oraclehost;sid=oracledb1', 'username', 'password'); - diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 61788c30..4f849029 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -127,7 +127,7 @@ versions of the compiler are unreliable. Both Roger Foskett, I and most others have been using the HP Softbench C compiler normally installed in: - /opt/softbench/bin/cc. + /opt/softbench/bin/cc. While the DBD-Oracle F checks for some of the conditions which, when met, we know will produce a working build, there are many @@ -318,9 +318,9 @@ If you have trouble, see the L instructions below, for hints of what might be wrong... and send me a note, describing your configuration, and what you did to fix it. -=head1 Trouble Shooting +=head1 Trouble Shooting -=head2 "Unresolved symbol" +=head2 "Unresolved symbol" In general, find the symbols, edit the Makefile, and make test. @@ -374,9 +374,9 @@ and add the missing libraries. When you add those library files to OTHERLDFLAGS you must convert the name from the actual name to the notation that OTHERLDFLAGS uses. - libclntsh.sl becomes => -lclntsh - libagtsh.sl becomes => -lagtsh - libwtc8.sl becomes => -lwtc8 + libclntsh.sl becomes => -lclntsh + libagtsh.sl becomes => -lagtsh + libwtc8.sl becomes => -lwtc8 That is, you replace the "lib" in the name to "-l" and remove the ".sl" (or the .so). @@ -422,7 +422,7 @@ time of this document, then the above conditions will likely not be met. You can fix this as follows: - perl -pi -e's/-Wl,\+[sn]//' Makefile + perl -pi -e's/-Wl,\+[sn]//' Makefile =head1 Building on a Oracle Client Machine @@ -560,7 +560,7 @@ The following folks contributed to this document: Weiguo Sun Tony Foiani Hugh J. Hitchcock - Heiko Herms + Heiko Herms Waldemar Zurowski Michael Schuh Gram M. Ludlow @@ -572,8 +572,6 @@ And probably others unknown to me. Lincoln A. Baxter H.Merijn Brand - - =head1 APPENDICES =head2 Appendix A @@ -582,7 +580,7 @@ And probably others unknown to me. This is pretty much verbatim the build information I received from Waldemar Zurowski on building Perl and DBD-Oracle using gcc on HP. Note -that this build was on a PA-RISC1.1 machine. +that this build was on a PA-RISC1.1 machine. =head3 Host @@ -885,7 +883,7 @@ To work around this problem, complete the following procedure: =over -=item 1 Log in to your Oracle account: +=item 1 Log in to your Oracle account: su - oracle @@ -893,8 +891,8 @@ To work around this problem, complete the following procedure: $ORACLE_HOME/rdbms/admin/shrept.lst -=item 3 Add the following line: - +=item 3 Add the following line: + rdbms:OCILobLocatorAssign =item 4 (optional) Add the names of any other missing functions needed by applications, other than WebLogic Server 7.0, that you want to execute. diff --git a/lib/DBD/Oracle/Troubleshooting/Linux.pod b/lib/DBD/Oracle/Troubleshooting/Linux.pod index 55ab1e5e..d42d728a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Linux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Linux.pod @@ -3,8 +3,8 @@ =head1 SELinux and httpd -If SELinux is running, it can prevents DBD::Oracle running in -an Apache process to load shared libraries it requires (libclntsh.so +If SELinux is running, it can prevents DBD::Oracle running in +an Apache process to load shared libraries it requires (libclntsh.so or libnnz12.so). A typical symptom is a line like the following in the Apache error logs: @@ -60,9 +60,9 @@ No real problem with the above however you will have to 4) do the make install and it should work fine for you -=head1 Oracle 9i Lite +=head1 Oracle 9i Lite -The advice is to use the regular Oracle9i not the lite version. +The advice is to use the regular Oracle9i not the lite version. Another great source of help was: http://www.puschitz.com/InstallingOracle9i.html @@ -87,28 +87,28 @@ smooth as just about every other CPAN module. =head1 Oracle 10g Instantclient The Makefile.PL will now work for Oracle 10g Instantclient. To have both the Compile and -the test.pl to work you must first have the LD_LIBRARY_PATH correctly set to your -"instantclient" directory. (http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html) +the test.pl to work you must first have the LD_LIBRARY_PATH correctly set to your +"instantclient" directory. (http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html) The present version of the make creates a link on your "instantclient" directory as follows -"ln -s libclntsh.so.10.1 libclntsh.so". It is needed for both the makefile creation and the compile +"ln -s libclntsh.so.10.1 libclntsh.so". It is needed for both the makefile creation and the compile but is not need for the test.pl. It should be removed after the compile. If the Makefile.PL or make fails try creating this link directly in your "instantclient" directory. =head1 Oracle Database 10g Express Edition 10.2 -To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY_PATH -as you would for an install against 10g Standard Edition, Standard Edition One, or -Enterprise Edition +To get 10Xe to compile correctly I had to add $ORACLE_HOME/lib to the LD_LIBRARY_PATH +as you would for an install against 10g Standard Edition, Standard Edition One, or +Enterprise Edition =head1 UTF8 bug in Oracle 9.2.0.5.0 and 9.2.0.7.0 DBD::Oracle seems to hit some sort of bug with the above two versions of DB. The bug seems to hit when you when the Oracle database charset: US7ASCII and the Oracle nchar charset: AL16UTF16 and it has also -been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. +been reported when the Oracle database charset: WE8ISO8850P1 Oracle nchar charset: AL32UTF16. -So far there is no patch for this but here are some workarounds +So far there is no patch for this but here are some workarounds use DBD::Oracle qw( SQLCS_IMPLICIT SQLCS_NCHAR ); ... @@ -121,5 +121,3 @@ So far there is no patch for this but here are some workarounds or this way utf8::downgrade($parameter, 1); - - diff --git a/lib/DBD/Oracle/Troubleshooting/Macos.pod b/lib/DBD/Oracle/Troubleshooting/Macos.pod index c1d28410..21b3352a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Macos.pod +++ b/lib/DBD/Oracle/Troubleshooting/Macos.pod @@ -1,7 +1,7 @@ #PODNAME: DBD::Oracle::Troubleshooting::Macos #ABSTRACT: Tips and Hints to Troubleshoot DBD::Oracle on MacOs -=head1 General Info +=head1 General Info These instructions allow for the compilation and successful testing of DBD::Oracle on MacOS X 10.2.4 and higher, using Oracle 9iR2 DR @@ -14,8 +14,8 @@ with a Perl version of 5.6.0., which I can report to work with DBD::Oracle 1.14 and higher once you take certain steps (see below). You may want to install a later perl, e.g., Perl 5.8.x. Please refer to: - Installing Perl 5.8 on Jaguar - http://developer.apple.com/internet/macosx/perl.html + Installing Perl 5.8 on Jaguar + http://developer.apple.com/internet/macosx/perl.html for Perl 5.8.0 installation instructions. @@ -510,14 +510,13 @@ instructions, and the Perl IO patch is credit to Hilmar Lapp, hlapp at gmx.net. Earlier and original instructions thanks to: - Andy Lester - Steve Sapovits - Tom Mornini - + Andy Lester + Steve Sapovits + Tom Mornini Date: Tue, 15 Apr 2003 16:02:17 +1000 Subject: Compilation bug in DBI on OSX with threaded Perl 5.8.0 -From: Danial Pearce +From: Danial Pearce In regards to a previous message on this list: diff --git a/lib/DBD/Oracle/Troubleshooting/Sun.pod b/lib/DBD/Oracle/Troubleshooting/Sun.pod index 94f7ec63..3fe61c40 100644 --- a/lib/DBD/Oracle/Troubleshooting/Sun.pod +++ b/lib/DBD/Oracle/Troubleshooting/Sun.pod @@ -29,4 +29,3 @@ root> crle -u -l /youroracledir/lib/instantclient_11_2 however, make sure you check the crle options as you may need to set the architecture etc as well. - diff --git a/lib/DBD/Oracle/Troubleshooting/Vms.pod b/lib/DBD/Oracle/Troubleshooting/Vms.pod index 5eeeb52e..ec4aff78 100644 --- a/lib/DBD/Oracle/Troubleshooting/Vms.pod +++ b/lib/DBD/Oracle/Troubleshooting/Vms.pod @@ -3,8 +3,8 @@ =head1 General Info -This is related to Oracle RDBMS 9.2 and later, since Oracle -made fundamental changes to oracle installation requirements +This is related to Oracle RDBMS 9.2 and later, since Oracle +made fundamental changes to oracle installation requirements and factual installation with this release. Oracle's goal was to make VMS installation be more like on @@ -26,7 +26,7 @@ table is inserted in LNM$FILE_DEV in LNM$PROCESS_DIRECTORY. = "LNM$SYSTEM" = "DECW$LOGICAL_NAMES" -This ensures that any process that needs to have access to +This ensures that any process that needs to have access to oracle gets the environment by just adding one logical name table to a central process specific mechanism. @@ -44,14 +44,14 @@ Installing DBI and DBD::Oracle has influence upon this since in both cases a few environment variables are read or set in the test phase. For DBI it is the logical SYS$SCRATCH, which is a JOB logical. -For DBD-Oracle it is when testing a new feature in the Oracle -RDBMS: UTF8 and UTF16 character set functionality, and in order -to do this it sets and unsets the related environment variables +For DBD-Oracle it is when testing a new feature in the Oracle +RDBMS: UTF8 and UTF16 character set functionality, and in order +to do this it sets and unsets the related environment variables NLS_NCHAR and NLS_LANG. -If one is not careful this changes the values set in the oracle -table - and in the worst case stays active until the next major -system reset. It can also be a very hard error to track down +If one is not careful this changes the values set in the oracle +table - and in the worst case stays active until the next major +system reset. It can also be a very hard error to track down since it happens in a place where one normally never looks. Furthermore, it is very possibly that some or all of the UTF tests @@ -60,7 +60,7 @@ table, then even though 'mms test' sets it in the wrong table it is not invoked as it is overruled by the process logical... The way to ensure that no logicals are set in the oracle table and -that the UTF tests get the best environment to test in, and that +that the UTF tests get the best environment to test in, and that DBI correctly translates the SYS$SCRATCH logical, use the logical @@ -78,10 +78,8 @@ LNM$JOB table is read when SYS$SCRATCH is to be translated. PERL_ENV_TABLES is well documented in the PERLVMS man page. -Oracle8 releases are not affected, as they don't have the +Oracle8 releases are not affected, as they don't have the oracle table implementation, and no UTF support. Oracle 9.0 is uncertain, since testing has not been possible yet, but the remedy will not hurt :) - - diff --git a/lib/DBD/Oracle/Troubleshooting/Win32.pod b/lib/DBD/Oracle/Troubleshooting/Win32.pod index dc3053cd..59130f5a 100644 --- a/lib/DBD/Oracle/Troubleshooting/Win32.pod +++ b/lib/DBD/Oracle/Troubleshooting/Win32.pod @@ -236,4 +236,3 @@ is not set. If neither module is installed, you must set ORACLE_HOME before running Makefile.PL. Since the registry location of the current Oracle Home is in different locations in different Oracle versions, it is usually safer to set ORACLE_HOME before running Makefile.PL. - diff --git a/mkta.pl b/mkta.pl index f6da46b4..8db6b51e 100755 --- a/mkta.pl +++ b/mkta.pl @@ -1,4 +1,4 @@ -#!/bin/env perl -w +#!/bin/env perl # mkta - make-test-all # @@ -7,6 +7,8 @@ # keep log files from failures use strict; +use warnings; + use Symbol; local $| = 1; @@ -26,13 +28,13 @@ my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my (@queue, @run, %running, %skipped, @fail, $tested); -my @cs_utf8 = (ORA_OCI() < 9.2) ? ("UTF8") : ("AL32UTF8", ($opt_full) ? ("UTF8") : ()); -my @cs_8bit = ($opt_full) ? ("WE8ISO8859P1", "WE8MSWIN1252") : ("WE8MSWIN1252"); -my @charsets = ("", @cs_utf8, @cs_8bit); +my @cs_utf8 = (ORA_OCI() < 9.2) ? ('UTF8') : ('AL32UTF8', ($opt_full) ? ('UTF8') : ()); +my @cs_8bit = ($opt_full) ? ('WE8ISO8859P1', 'WE8MSWIN1252') : ('WE8MSWIN1252'); +my @charsets = (q||, @cs_utf8, @cs_8bit); # need to add in: -# multiple perl versions/achitectures -# multiple oracle versions +# multiple perl versions/achitectures +# multiple oracle versions for my $sid (@sid) { mkta_sid_cs($sid, \@charsets); @@ -43,34 +45,34 @@ sub mkta_sid_cs { my $start_time = time; local $ENV{ORACLE_SID} = $sid; - my $dbh = DBI->connect("dbi:Oracle:", $dbuser, undef, { PrintError=>0 }); + my $dbh = DBI->connect('dbi:Oracle:', $dbuser, undef, { PrintError=>0 }); unless ($dbh) { (my $errstr = $DBI::errstr) =~ s/\n.*//s; - push @{ $skipped{$errstr} }, $sid; - return; + push @{ $skipped{$errstr} }, $sid; + return; } mkdir $opt_dir, 0771 unless -d $opt_dir; print "$sid: testing with @$charsets ...\n"; - system("make") == 0 + system('make') == 0 or die "$0 aborted - make failed\n"; system("rm -f $opt_dir/$sid-*-*.log"); for my $ochar (@$charsets) { for my $nchar (@$charsets) { - # because empty NLS_NCHAR is same as NLS_LANG charset - next if $nchar eq '' && $ochar ne ''; - push @queue, [ $sid, $ochar, $nchar ]; - } + # because empty NLS_NCHAR is same as NLS_LANG charset + next if $nchar eq '' && $ochar ne ''; + push @queue, [ $sid, $ochar, $nchar ]; + } } while (@queue) { while (@queue && keys %running < $opt_j) { - my ($tag, $fh) = start_test(@{ shift @queue }); - $running{$tag} = $fh; - push @run, $tag; - ++$tested; - } - wait_for_tests(); + my ($tag, $fh) = start_test(@{ shift @queue }); + $running{$tag} = $fh; + push @run, $tag; + ++$tested; + } + wait_for_tests(); } wait_for_tests(); printf "$sid: completed in %.1f minutes\n", (time-$start_time)/60; @@ -92,13 +94,13 @@ sub start_test { } sub wait_for_tests { - while(%running) { + while (keys %running) { my @running = grep { $running{$_} } @run; - my $tag = $running[0] or die; - close $running{ $tag }; - printf "$tag: %s\n", ($?) ? "FAILED" : "pass"; - push @fail, $tag if $?; - delete $running{$tag}; + my $tag = $running[0] or die; + close $running{ $tag }; + printf "$tag: %s\n", ($?) ? "FAILED" : "pass"; + push @fail, $tag if $?; + delete $running{$tag}; } } diff --git a/t/00dbdoracletestlib.t b/t/00dbdoracletestlib.t new file mode 100644 index 00000000..4c690cb3 --- /dev/null +++ b/t/00dbdoracletestlib.t @@ -0,0 +1,43 @@ +#!perl + +use strict; +use warnings; + +use Test::More; +use Symbol qw( delete_package ); + +use lib 't/lib'; + +require_ok('DBDOracleTestLib') + or BAIL_OUT 'DBDOracleTestLib require problem... impossible to proceed'; + +my @functions = qw/ + db_handle extra_wide_rows long_test_cols + oracle_test_dsn show_test_data test_data + select_test_count select_rows + cmp_ok_byte_nice show_db_charsets + db_ochar_is_utf db_nchar_is_utf + client_ochar_is_utf8 client_nchar_is_utf8 + set_nls_nchar set_nls_lang_charset + insert_test_count nice_string + create_table table drop_table insert_rows dump_table + force_drop_table +/; + +can_ok('DBDOracleTestLib', @functions); + +sub is_exported_by { + my ($imports, $expect, $msg) = @_; + delete_package 'Clean'; + eval ' + package Clean; + DBDOracleTestLib->import(@$imports); + ::is_deeply([sort keys %Clean::], [sort @$expect], $msg); + ' or die "# $@"; +} + +is_exported_by([], [], 'nothing is exported by default'); + +done_testing; + +1; diff --git a/t/00versions.t b/t/00versions.t deleted file mode 100644 index 9307e49f..00000000 --- a/t/00versions.t +++ /dev/null @@ -1,45 +0,0 @@ -# reports on all interesting versions - -use strict; -use warnings; - -use lib 't'; - -use Test::More tests => 2; - -use DBD::Oracle qw/ ORA_OCI /; -require 'nchar_test_lib.pl'; - -my $oci_version = ORA_OCI(); - -diag "OCI client library version: ", $oci_version; - -ok $oci_version; - -SKIP: { - my $dsn = oracle_test_dsn(); - my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - - my $dbh = DBI->connect($dsn, $dbuser, '',{ PrintError => 0, }) or - note <<'END_NOTE' or skip q{can't connect to database} => 1; - -Can't connect to an Oracle instance. - -Without a database connection, most of DBD::Oracle's test suite will -be skipped. To let the tests use a database, set up the -environment variables ORACLE_USERID and ORACLE_DSN. E.g.: - - $ export ORACLE_USERID='scott/tiger' - $ export ORACLE_DSN='dbi:Oracle:testdb' - -END_NOTE - - my $sth = $dbh->prepare( q{select * from v$version where banner like 'Oracle%'} ); - $sth->execute; - - my $version = join ' ', $sth->fetchrow; - - diag 'database version: ', $version; - - ok $version; -} diff --git a/t/01base.t b/t/01base.t index a243ea66..6cce01de 100755 --- a/t/01base.t +++ b/t/01base.t @@ -1,4 +1,4 @@ -#!perl -w +#!perl use strict; use warnings; @@ -9,25 +9,26 @@ use Test::More tests => 6; require_ok('DBI'); eval { - import DBI; + DBI->import }; -is $@ => '', 'successfully import DBI'; +is( $@ => '', 'successfully import DBI' ); -is ref DBI->internal => 'DBI::dr', 'internal'; +is( ref DBI->internal => 'DBI::dr', 'internal' ); my $drh = eval { # This is a special case. install_driver should not normally be used. DBI->install_driver('Oracle'); }; -is $@ => '', 'install_driver' +is( $@ => '', q|install_driver('Oracle') doesnt fail| ) or diag "Failed to load Oracle extension and/or shared libraries"; SKIP: { skip 'install_driver failed - skipping remaining', 2 if $@; - is ref $drh => 'DBI::dr', 'install_driver'; + is( ref $drh => 'DBI::dr', 'install_driver(Oracle) returns the correct object' ) + or diag '$drh wrong object type, found: ' . ref $drh; - ok $drh->{Version}, 'version'; + ok( do { $drh && $drh->{Version} }, 'version found in $drh object'); } diff --git a/t/02versions.t b/t/02versions.t new file mode 100644 index 00000000..a1687e0e --- /dev/null +++ b/t/02versions.t @@ -0,0 +1,46 @@ +#!perl +# reports on all interesting versions + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + +use Test::More tests => 2; + +use DBD::Oracle qw/ ORA_OCI /; + +my $oci_version = ORA_OCI(); + +diag 'OCI client library version: ', $oci_version; + +ok $oci_version; + +SKIP: { + my $dbh = db_handle( { PrintError => 0 } ) + or note <<'END_NOTE' or skip q{Can't connect to Oracle Database} => 1; + +Can't connect to an Oracle instance. + +Without a database connection, most of DBD::Oracle's test suite will +be skipped. To let the tests use a database, set up the +environment variables ORACLE_USERID and ORACLE_DSN. E.g.: + + $ export ORACLE_USERID='scott/tiger' + $ export ORACLE_DSN='dbi:Oracle:testdb' + +END_NOTE + + my $sth = + $dbh->prepare(q{select * from v$version where banner like 'Oracle%'}); + $sth->execute; + + my $version = join ' ', $sth->fetchrow; + + $sth->finish; + + diag 'Database version: ', $version; + + ok $version, 'Version exists'; +} diff --git a/t/05base.t b/t/05base.t new file mode 100755 index 00000000..a8ed9102 --- /dev/null +++ b/t/05base.t @@ -0,0 +1,35 @@ +#!perl + +use strict; +use warnings; + +# Base DBD Driver Test +use Test::More tests => 6; + +require_ok('DBI'); + +eval { DBI->import }; + +is( $@ => '', 'Successfully import DBI' ); + +is( ref DBI->internal => 'DBI::dr', 'internal' ); + +my $drh = eval { + + # This is a special case. install_driver should not normally be used. + DBI->install_driver('Oracle'); +}; + +is( $@ => '', q|install_driver('Oracle') doesnt fail| ) + or diag "Failed to load Oracle extension and/or shared libraries"; + +SKIP: { + skip 'install_driver failed - skipping remaining', 2 if $@; + + is( + ref $drh => 'DBI::dr', + 'install_driver(Oracle) returns the correct object' + ) or diag '$drh wrong object type, found: ' . ref $drh; + + ok( do { $drh && $drh->{Version} }, 'version found in $drh object' ); +} diff --git a/t/10general.t b/t/10general.t index 7098ff0f..9e95175c 100644 --- a/t/10general.t +++ b/t/10general.t @@ -1,54 +1,52 @@ +#!perl + use strict; use warnings; +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + use Test::More; use DBI; use Config; use DBD::Oracle qw(ORA_OCI); -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - $| = 1; -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -my $dbh = DBI->connect($dsn, $dbuser, '', - { - PrintError => 0, - }); +my $dbh = db_handle( { PrintError => 0 } ); if ($dbh) { plan tests => 28; -} else { - plan skip_all => "Unable to connect to Oracle"; +} +else { + plan skip_all => 'Unable to connect to Oracle'; } -my($sth, $p1, $p2, $tmp); +my ( $sth, $p1, $p2, $tmp ); SKIP: { - skip "not unix-like", 2 unless $Config{d_semctl}; + skip 'not unix-like', 2 unless $Config{d_semctl}; my @ora_oci_version = split /\./, ORA_OCI(); - skip 'solaris with OCI>9.x', 2 - if $^O eq 'solaris' and $ora_oci_version[0] > 9; + skip 'solaris with OCI>9.x', 2 + if $^O eq 'solaris' and $ora_oci_version[0] > 9; # basic check that we can fork subprocesses and wait for the status # after having connected to Oracle # at some point, this should become a subtest - - my $success = is system("exit 1;"), 1<<8, 'system exit 1 should return 256'; - $success &&= is system("exit 0;"), 0, 'system exit 0 should return 0'; - unless ( $success ) { - diag <prepare(q{ - /* also test preparse doesn't get confused by ? :1 */ +$sth = $dbh->prepare( + q{ + /* also test preparse doesn't get confused by ? :1 */ /* also test placeholder binding is case insensitive */ - select :a, :A from user_tables -- ? :1 -}); -ok($sth->{ParamValues}, 'preparse, case insensitive, placeholders in comments'); -is(keys %{$sth->{ParamValues}}, 1, 'number of parameters'); -is($sth->{NUM_OF_PARAMS}, 1, 'expected number of parameters'); -ok($sth->bind_param(':a', 'a value'), 'bind_param for select parameter'); -ok($sth->execute, 'execute for select parameter'); -ok($sth->{NUM_OF_FIELDS}, 'NUM_OF_FIELDS'); + select :a, :A from user_tables -- ? :1 +} +); +ok( $sth->{ParamValues}, + 'preparse, case insensitive, placeholders in comments' ); +is( keys %{ $sth->{ParamValues} }, 1, 'number of parameters' ); +is( $sth->{NUM_OF_PARAMS}, 1, 'expected number of parameters' ); +ok( $sth->bind_param( ':a', 'a value' ), 'bind_param for select parameter' ); +ok( $sth->execute, 'execute for select parameter' ); +ok( $sth->{NUM_OF_FIELDS}, 'NUM_OF_FIELDS' ); eval { - local $SIG{__WARN__} = sub { die @_ }; # since DBI 1.43 - $p1=$sth->{NUM_OFFIELDS_typo}; + local $SIG{__WARN__} = sub { die @_ }; # since DBI 1.43 + $p1 = $sth->{NUM_OFFIELDS_typo}; }; -ok($@ =~ /attribute/, 'unrecognised attribute'); -ok($sth->{Active}, 'statement is active'); -ok($sth->finish, 'finish'); -ok(!$sth->{Active}, 'statement is not active'); +ok( $@ =~ /attribute/, 'unrecognised attribute' ); +ok( $sth->{Active}, 'statement is active' ); +ok( $sth->finish, 'finish' ); +ok( !$sth->{Active}, 'statement is not active' ); $sth = $dbh->prepare("select * from user_tables"); -ok($sth->execute, 'execute for user_tables'); -ok($sth->{Active}, 'active for user_tables'); -1 while ($sth->fetch); # fetch through to end -ok(!$sth->{Active}, 'user_tables not active after fetch'); +ok( $sth->execute, 'execute for user_tables' ); +ok( $sth->{Active}, 'active for user_tables' ); +1 while ( $sth->fetch ); # fetch through to end +ok( !$sth->{Active}, 'user_tables not active after fetch' ); # so following test works with other NLS settings/locations -ok($dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"), - 'set NLS_NUMERIC_CHARACTERS'); - -ok($tmp = $dbh->selectall_arrayref(q{ - select 1 * power(10,-130) "smallest?", - 9.9999999999 * power(10,125) "biggest?" - from dual -}), 'select all for arithmetic'); -my @tmp = @{$tmp->[0]}; -#warn "@tmp"; $tmp[0]+=0; $tmp[1]+=0; warn "@tmp"; -ok($tmp[0] <= 1.0000000000000000000000000000000001e-130, "tmp0=$tmp[0]"); -ok($tmp[1] >= 9.99e+125, "tmp1=$tmp[1]"); +ok( $dbh->do("ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'"), + 'set NLS_NUMERIC_CHARACTERS' ); + +ok( + $tmp = $dbh->selectall_arrayref( + q{ + select 1 * power(10,-130) "smallest?", + 9.9999999999 * power(10,125) "biggest?" + from dual +} + ), + 'select all for arithmetic' +); +my @tmp = @{ $tmp->[0] }; +#warn "@tmp"; $tmp[0]+=0; $tmp[1]+=0; warn "@tmp"; +ok( $tmp[0] <= 1.0000000000000000000000000000000001e-130, "tmp0=$tmp[0]" ); +ok( $tmp[1] >= 9.99e+125, "tmp1=$tmp[1]" ); -my $warn=''; +my $warn = ''; eval { - local $SIG{__WARN__} = sub { $warn = $_[0] }; - $dbh->{RaiseError} = 1; - $dbh->{PrintError} = 1; - $dbh->do("some invalid sql statement"); + local $SIG{__WARN__} = sub { $warn = $_[0] }; + $dbh->{RaiseError} = 1; + $dbh->{PrintError} = 1; + $dbh->do('some invalid sql statement'); }; -ok($@ =~ /DBD::Oracle::db do failed:/, "eval error: ``$@'' expected 'do failed:'"); +ok( + $@ =~ m/DBD::Oracle::db do failed:/, + "eval error: ``$@'' expected 'do failed:'" +); + #print "''$warn''"; -ok($warn =~ /DBD::Oracle::db do failed:/, "warn error: ``$warn'' expected 'do failed:'"); -ok($DBI::err, 'err defined'); +ok( + $warn =~ m/DBD::Oracle::db do failed:/, + "warn error: ``$warn'' expected 'do failed:'" +); +ok( $DBI::err, 'err defined' ); $dbh->{RaiseError} = 0; $dbh->{PrintError} = 0; + # --- -ok( $dbh->ping, 'ping - connected'); +ok( $dbh->ping, 'ping - connected' ); -my $ora_oci = DBD::Oracle::ORA_OCI(); # dualvar +my $ora_oci = DBD::Oracle::ORA_OCI(); # dualvar note sprintf "ORA_OCI = %d (%s)\n", $ora_oci, $ora_oci; -ok("$ora_oci", 'ora_oci defined'); -ok($ora_oci >= 8, "ora_oci $ora_oci >= 8"); -my @ora_oci = split(/\./, $ora_oci,-1); -ok(scalar @ora_oci >= 2, 'version has 2 or more components'); -ok((scalar @ora_oci == grep { DBI::looks_like_number($_) } @ora_oci), - 'version looks like numbers'); -is($ora_oci[0], int($ora_oci), 'first number is int'); +ok( "$ora_oci", 'ora_oci defined' ); +ok( $ora_oci >= 8, "ora_oci $ora_oci >= 8" ); +my @ora_oci = split( /\./, $ora_oci, -1 ); +ok( scalar @ora_oci >= 2, 'version has 2 or more components' ); +ok( ( scalar @ora_oci == grep { DBI::looks_like_number($_) } @ora_oci ), + 'version looks like numbers' ); +is( $ora_oci[0], int($ora_oci), 'first number is int' ); diff --git a/t/12impdata.t b/t/12impdata.t index d66dc414..6eaa6d82 100644 --- a/t/12impdata.t +++ b/t/12impdata.t @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!perl $| = 1; ## ---------------------------------------------------------------------------- @@ -7,49 +7,51 @@ $| = 1; ## ---------------------------------------------------------------------------- use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + use DBI; use Config qw(%Config); + # must be done before Test::More - see Threads in Test::More pod BEGIN { eval "use threads; use threads::shared;" } my $use_threads_err = $@; use Test::More; BEGIN { - if ($DBI::VERSION <= 1.601){ - plan skip_all => "DBI version ".$DBI::VERSION." does not support iThreads. Use version 1.602 or later."; + if ( $DBI::VERSION <= 1.601 ) { + plan skip_all => "DBI version " + . $DBI::VERSION + . " does not support iThreads. Use version 1.602 or later."; } die $use_threads_err if $use_threads_err; # need threads } -unshift @INC, 't'; -require 'nchar_test_lib.pl'; - -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect( $dsn, $dbuser, '', { - PrintError => 0, - }); +my $dbh = db_handle( { PrintError => 0 } ); if ($dbh) { plan tests => 7; -} else { - plan skip_all => "Unable to connect to Oracle"; +} +else { + plan skip_all => 'Unable to connect to Oracle'; } my $drh = $dbh->{Driver}; -my ($sess_1) = $dbh->selectrow_array("select userenv('sessionid') from dual"); +my ($sess_1) = $dbh->selectrow_array(q/select userenv('sessionid') from dual/); -is $drh->{Kids}, 1, "1 kid"; -is $drh->{ActiveKids}, 1, "1 active kid"; +is $drh->{Kids}, 1, '1 kid'; +is $drh->{ActiveKids}, 1, '1 active kid'; my $imp_data = $dbh->take_imp_data; -is $drh->{Kids}, 0, "no kids"; -is $drh->{ActiveKids}, 0, "no active kids"; +is $drh->{Kids}, 0, 'no kids'; +is $drh->{ActiveKids}, 0, 'no active kids'; -$dbh = DBI->connect( $dsn, $dbuser, '', { dbi_imp_data => $imp_data } ); -my ($sess_2) = $dbh->selectrow_array("select userenv('sessionid') from dual"); -is $sess_1, $sess_2, "got same session"; +$dbh = db_handle( { dbi_imp_data => $imp_data } ); +my ($sess_2) = $dbh->selectrow_array(q/select userenv('sessionid') from dual/); +is $sess_1, $sess_2, 'got same session'; -is $drh->{Kids}, 1, "1 kid"; -is $drh->{ActiveKids}, 1, "1 active kid"; +is $drh->{Kids}, 1, '1 kid'; +is $drh->{ActiveKids}, 1, '1 active kid'; __END__ diff --git a/t/14threads.t b/t/14threads.t index 737dc1b6..078b40b7 100644 --- a/t/14threads.t +++ b/t/14threads.t @@ -1,4 +1,5 @@ -#!/usr/bin/perl +#!perl + $| = 1; ## ---------------------------------------------------------------------------- @@ -6,7 +7,14 @@ $| = 1; ## By Jeffrey Klein, ## ---------------------------------------------------------------------------- -BEGIN { eval "use threads; use threads::shared;" } +# This needs to be the very very first thing +BEGIN { eval 'use threads; use threads::shared;' } +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + my $use_threads_err = $@; use DBI; use Config qw(%Config); @@ -15,31 +23,26 @@ use Test::More; BEGIN { if ( !$Config{useithreads} || $] < 5.008 ) { plan skip_all => "this $^O perl $] not configured to support iThreads"; - } elsif ($DBI::VERSION <= 1.601){ - plan skip_all => "DBI version ".$DBI::VERSION." does not support iThreads. Use version 1.602 or later."; - } + } + elsif ( $DBI::VERSION <= 1.601 ) { + plan skip_all => 'DBI version ' + . $DBI::VERSION + . ' does not support iThreads. Use version 1.602 or later.'; + } die $use_threads_err if $use_threads_err; # need threads } -use strict; use DBI; use Test::More; -unshift @INC, 't'; -require 'nchar_test_lib.pl'; - -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '',{ - PrintError => 0, - }); +my $dbh = db_handle( { PrintError => 0 } ); if ($dbh) { - plan tests => 19; $dbh->disconnect; -} else { - plan skip_all => "Unable to connect to Oracle"; +} +else { + plan skip_all => 'Unable to connect to Oracle'; } my $last_session : shared; @@ -60,8 +63,9 @@ for my $i ( 0 .. 4 ) { if ( $i > 0 ) { is $session, $last_session, "session $i matches previous session"; - } else { - ok $session, "session $i created", + } + else { + ok $session, "session $i created",; } $last_session = $session; @@ -69,7 +73,6 @@ for my $i ( 0 .. 4 ) { } )->join; - } # TESTS: 1 @@ -108,15 +111,15 @@ my @sem; use Thread::Semaphore; # create locked semaphores -for my $i (0..2) { - push @sem, Thread::Semaphore->new(0); +for my $i ( 0 .. 2 ) { + push @sem, Thread::Semaphore->new(0); } undef $last_session; # 3 threads, 3 iterations # TESTS: 9 -for my $t ( 0..2 ) { +for my $t ( 0 .. 2 ) { $thr[$t] = threads->create( sub { my $partner = ( $t + 1 ) % 3; @@ -129,9 +132,9 @@ for my $t ( 0..2 ) { if ( defined $last_session ) { is $session, $last_session, "thread $t, loop $i matches previous session"; - } else { - ok $session, - "thread $t, loop $i created session"; + } + else { + ok $session, "thread $t, loop $i created session"; } $last_session = $session; free_dbh_to_pool($dbh); @@ -153,6 +156,8 @@ empty_pool(); is scalar(@pool), 0, 'pool empty'; +done_testing; + exit; sub get_dbh_from_pool { @@ -174,9 +179,7 @@ sub empty_pool { sub connect_dbh { my $imp_data = shift; - my $dsn = oracle_test_dsn(); - my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - DBI->connect( $dsn, $dbuser, '', { dbi_imp_data => $imp_data } ); + return db_handle( { dbi_imp_data => $imp_data } ); } sub session_id { diff --git a/t/15nls.t b/t/15nls.t index b9c23a16..c1990a66 100644 --- a/t/15nls.t +++ b/t/15nls.t @@ -1,48 +1,55 @@ #!perl + use strict; use warnings; +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + use DBI; use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - my $testcount = 9; $| = 1; -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -my $dbh = DBI->connect($dsn, $dbuser, '',{ - PrintError => 0, - }); +my $dbh = db_handle( { PrintError => 0 } ); if ($dbh) { plan tests => $testcount; -} else { - plan skip_all => "Unable to connect to Oracle"; +} +else { + plan skip_all => 'Unable to connect to Oracle'; } -my ($nls_parameters_before, $nls_parameters_after); +my ( $nls_parameters_before, $nls_parameters_after ); my $old_date_format = 'HH24:MI:SS DD/MM/YYYY'; my $new_date_format = 'YYYYMMDDHH24MISS'; -ok($dbh->do("alter session set nls_date_format='$old_date_format'"), 'set date format'); +ok( $dbh->do("alter session set nls_date_format='$old_date_format'"), + 'set date format' ); -like($dbh->ora_can_unicode, qr/^[0123]/, 'ora_can_unicode'); +like( $dbh->ora_can_unicode, qr/^[0123]/, 'ora_can_unicode' ); -ok($nls_parameters_before = $dbh->ora_nls_parameters, 'fetch ora_nls_parameters'); -is(ref($nls_parameters_before), 'HASH', 'check ora_nls_parameters returned hashref'); -is($nls_parameters_before->{'NLS_DATE_FORMAT'}, $old_date_format, 'check returned nls_date_format'); +ok( $nls_parameters_before = $dbh->ora_nls_parameters, + 'fetch ora_nls_parameters' ); +is( ref($nls_parameters_before), + 'HASH', 'check ora_nls_parameters returned hashref' ); +is( $nls_parameters_before->{'NLS_DATE_FORMAT'}, + $old_date_format, 'check returned nls_date_format' ); -ok($dbh->do("alter session set nls_date_format='$new_date_format'"), 'alter date format'); -ok(eq_hash($nls_parameters_before, $dbh->ora_nls_parameters), 'check ora_nls_parameters caches old values'); +ok( $dbh->do("alter session set nls_date_format='$new_date_format'"), + 'alter date format' ); +ok( eq_hash( $nls_parameters_before, $dbh->ora_nls_parameters ), + 'check ora_nls_parameters caches old values' ); $nls_parameters_before->{NLS_DATE_FORMAT} = 'foo'; -isnt($nls_parameters_before->{NLS_DATE_FORMAT}, - $dbh->ora_nls_parameters->{NLS_DATE_FORMAT}, 'check ora_nls_parameters returns a copy'); - -is($dbh->ora_nls_parameters(1)->{'NLS_DATE_FORMAT'}, $new_date_format, 'refetch and check new nls_date_format value'); +isnt( + $nls_parameters_before->{NLS_DATE_FORMAT}, + $dbh->ora_nls_parameters->{NLS_DATE_FORMAT}, + 'check ora_nls_parameters returns a copy' +); + +is( $dbh->ora_nls_parameters(1)->{'NLS_DATE_FORMAT'}, + $new_date_format, 'refetch and check new nls_date_format value' ); __END__ diff --git a/t/20select.t b/t/20select.t index c19d23d3..ba861bc1 100644 --- a/t/20select.t +++ b/t/20select.t @@ -1,170 +1,183 @@ -#!perl -w +#!perl + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn client_ochar_is_utf8 table drop_table +db_handle /; + use Test::More; use DBI; use DBD::Oracle qw(:ora_types ORA_OCI); use Data::Dumper; use Math::BigInt; -use strict; - -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; $| = 1; -my @test_sets = ( - [ "CHAR(10)", 10 ], - [ "VARCHAR(10)", 10 ], - [ "VARCHAR2(10)", 10 ], -); +my @test_sets = + ( [ 'CHAR(10)', 10 ], [ 'VARCHAR(10)', 10 ], [ 'VARCHAR2(10)', 10 ], ); # Set size of test data (in 10KB units) -# Minimum value 3 (else tests fail because of assumptions) -# Normal value 8 (to test 64KB threshold well) +# Minimum value 3 (else tests fail because of assumptions) +# Normal value 8 (to test 64KB threshold well) my $sz = 8; -my $tests = 3; +my $tests = 3; my $tests_per_set = 11; $tests += @test_sets * $tests_per_set; -my $t = 0; +my $t = 0; my $failed = 0; my %ocibug; -my $table = "dbd_ora__drop_me" . ($ENV{DBD_ORACLE_SEQ}||''); - -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', { - PrintError => 0, - }); +my $table = table(); +my $dbh = db_handle( { PrintError => 0 } ); if ($dbh) { - plan tests=>$tests; -} else { + plan tests => $tests; +} +else { plan skip_all => "Unable to connect to oracle\n"; } # test simple select statements with [utf8] -my $utf8_test = ($] >= 5.006) - && client_ochar_is_utf8() # for correct output (utf8 bind vars should be fine regardless) - && ($dbh->ora_can_unicode() & 2); -diag("Including unicode data in test") if $utf8_test; +my $utf8_test = ( $] >= 5.006 ) + && client_ochar_is_utf8( + ) # for correct output (utf8 bind vars should be fine regardless) + && ( $dbh->ora_can_unicode() & 2 ); +diag('Including unicode data in test') if $utf8_test; -unless(create_test_table("str CHAR(10)", 1)) { +unless ( create_test_table( 'str CHAR(10)', 1 ) ) { BAIL_OUT("Unable to create test table ($DBI::errstr)\n"); print "1..0\n"; exit 0; } -my($sth, $p1, $p2, $tmp, @tmp); +my ( $sth, $p1, $p2, $tmp, @tmp ); -foreach (@test_sets) { - run_select_tests( @$_ ); +for (@test_sets) { + run_select_tests(@$_); } -my $ora_server_version = $dbh->func("ora_server_version"); +my $ora_server_version = $dbh->func('ora_server_version'); SKIP: { - skip "Oracle < 10", 1 if ($ora_server_version->[0] < 10); - my $data = $dbh->selectrow_array(q! + skip 'Oracle < 10', 1 if ( $ora_server_version->[0] < 10 ); + my $data = $dbh->selectrow_array( + q! select to_dsinterval(?) from dual - !, {}, "1 07:00:00"); - ok ((defined $data and $data eq '+000000001 07:00:00.000000000'), - "ds_interval"); - } + !, {}, '1 07:00:00' + ); + ok( ( defined $data and $data eq '+000000001 07:00:00.000000000' ), + 'ds_interval' ); +} +# FIXME - maybe remove this if (0) { + # UNION ALL causes Oracle 9 (not 8) to describe col1 as zero length # causing "ORA-24345: A Truncation or null fetch error occurred" error # Looks like an Oracle bug $dbh->trace(9); - ok 0, $sth = $dbh->prepare(qq{ - SELECT :HeadCrncy FROM DUAL - UNION ALL - SELECT :HeadCrncy FROM DUAL}); + ok 0, $sth = $dbh->prepare( + qq{ + SELECT :HeadCrncy FROM DUAL + UNION ALL + SELECT :HeadCrncy FROM DUAL} + ); $dbh->trace(0); - ok 0, $sth->execute("EUR"); + ok 0, $sth->execute('EUR'); ok 0, $tmp = $sth->fetchall_arrayref; use Data::Dumper; die Dumper $tmp; } - # $dbh->{USER} is just there so it works for old DBI's before Username was added -my @pk = $dbh->primary_key(undef, $dbh->{USER}||$dbh->{Username}, uc $table); -ok(@pk, 'primary key on table'); -is(join(",",@pk), 'DT,IDX', 'DT,IDX'); +my @pk = + $dbh->primary_key( undef, $dbh->{USER} || $dbh->{Username}, uc $table ); +ok( @pk, 'primary key on table' ); +is( join( ',', @pk ), 'DT,IDX', 'DT,IDX' ); exit 0; END { - $dbh->do(qq{ drop table $table }) if $dbh; + eval { drop_table($dbh) } } sub run_select_tests { - my ($type_name, $field_len) = @_; - - my $data0; - if ($utf8_test) { - $data0 = eval q{ "0\x{263A}xyX" }; #this includes the smiley from perlunicode (lab) BTW: it is busted - } else { - $data0 = "0\177x\0X"; - } - my $data1 = "1234567890"; - my $data2 = "2bcdefabcd"; - - SKIP: { - if (!create_test_table("lng $type_name", 1)) { - # typically OCI 8 client talking to Oracle 7 database - diag("Unable to create test table for '$type_name' data ($DBI::err)"); - skip $tests_per_set; - } - - $sth = $dbh->prepare("insert into $table values (?, ?, SYSDATE)"); - ok($sth, "prepare for insert of $type_name"); - ok($sth->execute(40, $data0), "insert 8bit or utf8"); - ok($sth->execute(Math::BigInt->new(41), $data1), 'bind overloaded value'); - ok($sth->execute(42, $data2), "insert data2"); - - ok(!$sth->execute(43, "12345678901234567890"), 'insert string too long'); - - ok($sth = $dbh->prepare("select * from $table order by idx"), - "prepare select ordered by idx"); - ok($sth->execute, "execute"); - # allow for padded blanks - $sth->{ChopBlanks} = 1; - ok($tmp = $sth->fetchall_arrayref, 'fetchall'); - my $dif; - if ($utf8_test) { - $dif = DBI::data_diff($tmp->[0][1], $data0); - ok(!defined($dif) || $dif eq '', 'first row matches'); - diag($dif) if $dif; - } else { - is($tmp->[0][1], $data0, 'first row matches'); - } - is($tmp->[1][1], $data1, 'second row matches'); - is($tmp->[2][1], $data2, 'third row matches'); - - } -} # end of run_select_tests + my ( $type_name, $field_len ) = @_; -# end. + my $data0; + if ($utf8_test) { + $data0 = eval q{ "0\x{263A}xyX" } + ; #this includes the smiley from perlunicode (lab) BTW: it is busted + } + else { + $data0 = "0\177x\0X"; + } + my $data1 = '1234567890'; + my $data2 = '2bcdefabcd'; + + SKIP: { + if ( !create_test_table( "lng $type_name", 1 ) ) { + + # typically OCI 8 client talking to Oracle 7 database + diag("Unable to create test table for '$type_name' data ($DBI::err)" + ); + skip $tests_per_set; + } + + $sth = $dbh->prepare("insert into $table values (?, ?, SYSDATE)"); + ok( $sth, "prepare for insert of $type_name" ); + ok( $sth->execute( 40, $data0 ), 'insert 8bit or utf8' ); + ok( $sth->execute( Math::BigInt->new(41), $data1 ), + 'bind overloaded value' ); + ok( $sth->execute( 42, $data2 ), 'insert data2' ) + or diag '$sth->errstr: ' . $sth->errstr; + + ok( !$sth->execute( 43, '12345678901234567890' ), + 'insert string too long' ); + + ok( $sth = $dbh->prepare("select * from $table order by idx"), + 'prepare select ordered by idx' ); + ok( $sth->execute, 'execute' ); + + # allow for padded blanks + $sth->{ChopBlanks} = 1; + ok( $tmp = $sth->fetchall_arrayref, 'fetchall' ); + my $dif; + if ($utf8_test) { + $dif = DBI::data_diff( $tmp->[0][1], $data0 ); + ok( !defined($dif) || $dif eq '', 'first row matches' ); + diag($dif) if $dif; + } + else { + is( $tmp->[0][1], $data0, 'first row matches' ); + } + is( $tmp->[1][1], $data1, 'second row matches' ); + is( $tmp->[2][1], $data2, 'third row matches' ); + + } +} # end of run_select_tests +# end. sub create_test_table { - my ($fields, $drop) = @_; + my ( $fields, $drop ) = @_; my $sql = qq{create table $table ( - idx integer, - $fields, - dt date, - primary key (dt, idx) + idx integer, + $fields, + dt date, + primary key (dt, idx) )}; $dbh->do(qq{ drop table $table }) if $drop; $dbh->do($sql); - if ($dbh->err && $dbh->err==955) { - $dbh->do(qq{ drop table $table }); - warn "Unexpectedly had to drop old test table '$table'\n" unless $dbh->err; - $dbh->do($sql); + if ( $dbh->err && $dbh->err == 955 ) { + $dbh->do(qq{ drop table $table }); + warn "Unexpectedly had to drop old test table '$table'\n" + unless $dbh->err; + $dbh->do($sql); } return 0 if $dbh->err; return 1; diff --git a/t/21nchar.t b/t/21nchar.t index 70faf494..36955b2c 100644 --- a/t/21nchar.t +++ b/t/21nchar.t @@ -1,66 +1,71 @@ -#!perl -w +#!perl #written by Lincoln A Baxter (lab@lincolnbaxter.com) use strict; -#use warnings; -use Test::More; +use warnings; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; +use lib 't/lib'; +use DBDOracleTestLib qw/ db_handle show_db_charsets set_nls_nchar test_data + insert_test_count select_test_count show_test_data + drop_table create_table insert_rows dump_table select_rows + force_drop_table +/; +use Test::More; use DBI qw(:sql_types); use DBD::Oracle qw(:ora_types ORA_OCI SQLCS_NCHAR ); my $dbh; $| = 1; SKIP: { - plan skip_all => "Unable to run 8bit char test, perl version is less than 5.6" unless ( $] >= 5.006 ); + plan skip_all => + 'Unable to run 8bit char test, perl version is less than 5.6' + unless ( $] >= 5.006 ); $dbh = db_handle(); - # $dbh->{PrintError} = 1; - plan skip_all => "Unable to connect to Oracle" if not $dbh; - note("testing control and 8 bit chars:\n") ; - note(" Database and client versions and character sets:\n"); - show_db_charsets( $dbh); + # $dbh->{PrintError} = 1; + plan skip_all => 'Unable to connect to Oracle' unless $dbh; - plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" - if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; + note("Testing control and 8 bit chars...\n"); + note("Database and client versions and character sets:\n"); + show_db_charsets($dbh); + + plan skip_all => 'Oracle charset tests unreliable for Oracle 8 client' + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; # get the database NCHARSET before we begin... if it is not UTF, then # use it as the client side ncharset, otherwise, use WE8ISO8859P1 my $ncharset = $dbh->ora_nls_parameters()->{'NLS_NCHAR_CHARACTERSET'}; - $dbh->disconnect(); # we want to start over with the ncharset we select + $dbh->disconnect(); # we want to start over with the ncharset we select undef $dbh; if ( $ncharset =~ m/UTF/i ) { - $ncharset = 'WE8ISO8859P1' ; #WE8MSWIN1252 + $ncharset = 'WE8ISO8859P1'; #WE8MSWIN1252 } - set_nls_nchar( $ncharset ,1 ); + set_nls_nchar( $ncharset, 1 ); $dbh = db_handle(); - my $tdata = test_data( 'narrow_nchar' ); - my $testcount = 0 #create table - + insert_test_count( $tdata ) - + select_test_count( $tdata ) * 1; - ; + my $tdata = test_data('narrow_nchar'); + my $testcount = 0 #create table + + insert_test_count($tdata) + select_test_count($tdata) * 1; - plan tests => $testcount ; - show_test_data( $tdata ,0 ); + plan tests => $testcount; + show_test_data( $tdata, 0 ); - drop_table($dbh); + force_drop_table($dbh); create_table( $dbh, $tdata ); - insert_rows( $dbh, $tdata ,SQLCS_NCHAR); - dump_table( $dbh ,'nch' ,'descr' ); + insert_rows( $dbh, $tdata, SQLCS_NCHAR ); + dump_table( $dbh, 'nch', 'descr' ); select_rows( $dbh, $tdata ); -# view_with_sqlplus(1,$tcols) if $ENV{DBD_NCHAR_SQLPLUS_VIEW}; -# view_with_sqlplus(0,$tcols) if $ENV{DBD_NCHAR_SQLPLUS_VIEW}; + + # view_with_sqlplus(1,$tcols) if $ENV{DBD_NCHAR_SQLPLUS_VIEW}; + # view_with_sqlplus(0,$tcols) if $ENV{DBD_NCHAR_SQLPLUS_VIEW}; } END { eval { - local $dbh->{PrintError} = 0; - drop_table( $dbh ) if $dbh and not $ENV{'DBD_SKIP_TABLE_DROP'}; + drop_table($dbh) }; } diff --git a/t/22nchar_al32utf8.t b/t/22nchar_al32utf8.t index 8a28f317..85f32dac 100644 --- a/t/22nchar_al32utf8.t +++ b/t/22nchar_al32utf8.t @@ -1,51 +1,54 @@ -#!perl -w +#!perl #written by Lincoln A Baxter (lab@lincolnbaxter.com) use strict; -#use warnings; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ set_nls_nchar db_handle db_nchar_is_utf + show_db_charsets test_data insert_test_count + select_test_count show_test_data drop_table + create_table insert_rows dump_table select_rows + force_drop_table +/; + use Test::More; use DBI qw(:sql_types); use DBD::Oracle qw( :ora_types ORA_OCI SQLCS_NCHAR ); -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - my $dbh; $| = 1; SKIP: { - plan skip_all => "Unable to run unicode test, perl version is less than 5.6" unless ( $] >= 5.006 ); - plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" - if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; + plan skip_all => 'Unable to run unicode test, perl version is less than 5.6' + unless ( $] >= 5.006 ); + plan skip_all => 'Oracle charset tests unreliable for Oracle 8 client' + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; - set_nls_nchar( (ORA_OCI >= 9.2) ? 'AL32UTF8' : 'UTF8', 1 ); + set_nls_nchar( ( ORA_OCI >= 9.2 ) ? 'AL32UTF8' : 'UTF8', 1 ); $dbh = db_handle(); - plan skip_all => "Unable to connect to Oracle" if not $dbh; - plan skip_all => "Database NCHAR character set is not Unicode" if not db_nchar_is_utf($dbh) ; - print "testing utf8 with nchar columns\n" ; + plan skip_all => 'Unable to connect to Oracle' unless $dbh; + plan skip_all => 'Database NCHAR character set is not Unicode' + unless db_nchar_is_utf($dbh); + diag "testing utf8 with nchar columns\n"; - show_db_charsets( $dbh ); - my $tdata = test_data( 'wide_nchar' ); - my $testcount = 0 #create table - + insert_test_count( $tdata ) - + select_test_count( $tdata ) * 1; - ; + show_db_charsets($dbh); + my $tdata = test_data('wide_nchar'); + my $testcount = 0 #create table + + insert_test_count($tdata) + select_test_count($tdata) * 1; plan tests => $testcount; - show_test_data( $tdata ,0 ); - drop_table($dbh); + show_test_data( $tdata, 0 ); + force_drop_table($dbh); create_table( $dbh, $tdata ); - insert_rows( $dbh, $tdata ,SQLCS_NCHAR); - dump_table( $dbh ,'nch' ,'descr' ); + insert_rows( $dbh, $tdata, SQLCS_NCHAR ); + dump_table( $dbh, 'nch', 'descr' ); select_rows( $dbh, $tdata ); } END { - eval { - local $dbh->{PrintError} = 0; - drop_table($dbh) if $dbh and not $ENV{'DBD_SKIP_TABLE_DROP'}; - }; + eval { drop_table($dbh) }; } diff --git a/t/22nchar_utf8.t b/t/22nchar_utf8.t index 68e08040..1ebc9da0 100644 --- a/t/22nchar_utf8.t +++ b/t/22nchar_utf8.t @@ -1,58 +1,65 @@ -#!perl -w +#!perl #written by Lincoln A Baxter (lab@lincolnbaxter.com) use strict; -#use warnings; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ set_nls_nchar db_handle db_nchar_is_utf select_rows + show_db_charsets test_data extra_wide_rows + insert_test_count select_test_count dump_table + show_test_data drop_table create_table insert_rows + force_drop_table +/; + use Test::More; use DBI qw(:sql_types); use DBD::Oracle qw( :ora_types ORA_OCI SQLCS_NCHAR ); -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - my $dbh; $| = 1; SKIP: { - plan skip_all => "Unable to run unicode test, perl version is less than 5.6" unless ( $] >= 5.006 ); - plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" - if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; + plan skip_all => 'Unable to run unicode test, perl version is less than 5.6' + unless ( $] >= 5.006 ); + plan skip_all => 'Oracle charset tests unreliable for Oracle 8 client' + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; - set_nls_nchar( (ORA_OCI >= 9.2) ? 'AL32UTF8' : 'UTF8' ,1 ); + set_nls_nchar( ( ORA_OCI >= 9.2 ) ? 'AL32UTF8' : 'UTF8', 1 ); $dbh = db_handle(); - plan skip_all => "Unable to connect to Oracle" if not $dbh; - plan skip_all => "Database NCHAR character set is not Unicode" if not db_nchar_is_utf($dbh) ; + plan skip_all => 'Unable to connect to Oracle' unless $dbh; + plan skip_all => 'Database NCHAR character set is not Unicode' + unless db_nchar_is_utf($dbh); # testing utf8 with nchar columns - show_db_charsets( $dbh ); - my $tdata = test_data( 'wide_nchar' ); + show_db_charsets($dbh); + my $tdata = test_data('wide_nchar'); if ( $dbh->ora_can_unicode & 1 ) { - push( @{$tdata->{rows}} ,extra_wide_rows() ) ; + push( @{ $tdata->{rows} }, extra_wide_rows() ); + # added 2 rows with extra wide chars to test data } - my $testcount = 0 #create table - + insert_test_count( $tdata ) - + select_test_count( $tdata ) * 1; - ; + my $testcount = 0 #create table + + insert_test_count($tdata) + select_test_count($tdata) * 1; plan tests => $testcount; - show_test_data( $tdata ,0 ); - drop_table($dbh); + show_test_data( $tdata, 0 ); + force_drop_table($dbh); create_table( $dbh, $tdata ); - insert_rows( $dbh, $tdata ,SQLCS_NCHAR); - dump_table( $dbh ,'nch' ,'descr' ); + insert_rows( $dbh, $tdata, SQLCS_NCHAR ); + dump_table( $dbh, 'nch', 'descr' ); select_rows( $dbh, $tdata ); } END { eval { local $dbh->{PrintError} = 0; - drop_table($dbh) if $dbh and not $ENV{'DBD_SKIP_TABLE_DROP'}; + drop_table($dbh) if ( $dbh and not $ENV{'DBD_SKIP_TABLE_DROP'} ); }; } diff --git a/t/23wide_db.t b/t/23wide_db.t index 25541111..a7869738 100644 --- a/t/23wide_db.t +++ b/t/23wide_db.t @@ -1,54 +1,59 @@ -#!perl -w +#!perl #written by Lincoln A Baxter (lab@lincolnbaxter.com) use strict; -#use warnings; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ + set_nls_lang_charset db_handle db_ochar_is_utf test_data + insert_test_count select_test_count show_test_data + force_drop_table create_table insert_rows dump_table + select_rows + /; + use Test::More; use DBI qw(:sql_types); use DBD::Oracle qw( :ora_types ORA_OCI SQLCS_NCHAR ); -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - my $dbh; $| = 1; SKIP: { - plan skip_all => "Unable to run unicode test, perl version is less than 5.6" unless ( $] >= 5.006 ); - plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" - if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; + plan skip_all => 'Unable to run unicode test, perl version is less than 5.6' + unless ( $] >= 5.006 ); + plan skip_all => 'Oracle charset tests unreliable for Oracle 8 client' + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; + + #! #force Ncharset to NON UTF8! we are testing a wide database where someone + #! #perversely sets nchar to non utf8, and nls_lang to utf8.... + set_nls_lang_charset( ( ORA_OCI >= 9.2 ) ? 'AL32UTF8' : 'UTF8', 1 ); -#! #force Ncharset to NON UTF8! we are testing a wide database where someone -#! #perversely sets nchar to non utf8, and nls_lang to utf8.... - set_nls_lang_charset( (ORA_OCI >= 9.2) ? 'AL32UTF8' : 'UTF8', 1 ); #! #set_nls_nchar( 'WE8ISO8859P1' ,1 ); #it breaks and it is stupid to do this... doc it XXX $dbh = db_handle(); - plan skip_all => "Unable to connect to Oracle" if not $dbh; - plan skip_all => "Database character set is not Unicode" if not db_ochar_is_utf($dbh) ; + plan skip_all => 'Unable to connect to Oracle' unless $dbh; + plan skip_all => 'Database character set is not Unicode' + unless db_ochar_is_utf($dbh); # testing utf8 with char columns (wide mode database) - my $tdata = test_data( 'wide_char' ); - my $testcount = 0 #create table - + insert_test_count( $tdata ) - + select_test_count( $tdata ) * 1; - ; + my $tdata = test_data('wide_char'); + my $testcount = 0 #create table + + insert_test_count($tdata) + select_test_count($tdata) * 1; - plan tests => $testcount; - show_test_data( $tdata ,0 ); - drop_table($dbh); + plan tests => $testcount; + show_test_data( $tdata, 0 ); + force_drop_table($dbh); create_table( $dbh, $tdata ); - insert_rows( $dbh, $tdata ,SQLCS_NCHAR); - dump_table( $dbh ,'ch' ,'descr' ); + insert_rows( $dbh, $tdata, SQLCS_NCHAR ); + dump_table( $dbh, 'ch', 'descr' ); select_rows( $dbh, $tdata ); -} + +} # SKIP END { - eval { - local $dbh->{PrintError} = 0; - drop_table($dbh) if $dbh and not $ENV{'DBD_SKIP_TABLE_DROP'}; - }; + eval { drop_table($dbh); $dbh->disconnect if $dbh }; } diff --git a/t/23wide_db_8bit.t b/t/23wide_db_8bit.t index dcd1980e..83928c29 100644 --- a/t/23wide_db_8bit.t +++ b/t/23wide_db_8bit.t @@ -1,51 +1,54 @@ -#!perl -w +#!perl #written by Lincoln A Baxter (lab@lincolnbaxter.com) use strict; -#use warnings; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ + set_nls_lang_charset db_handle db_ochar_is_utf + force_drop_table create_table insert_rows + dump_table select_rows drop_table test_data + insert_test_count select_test_count + show_test_data +/; + use Test::More; use DBI qw(:sql_types); use DBD::Oracle qw( :ora_types ORA_OCI SQLCS_NCHAR ); -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - my $dbh; $| = 1; SKIP: { - plan skip_all => "Unable to run unicode test, perl version is less than 5.6" unless ( $] >= 5.006 ); - plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" - if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; + plan skip_all => 'Unable to run unicode test, perl version is less than 5.6' + unless ( $] >= 5.006 ); + plan skip_all => 'Oracle charset tests unreliable for Oracle 8 client' + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; - set_nls_lang_charset( 'WE8MSWIN1252' ,1 ); + set_nls_lang_charset( 'WE8MSWIN1252', 1 ); $dbh = db_handle(); - plan skip_all => "Unable to connect to Oracle" if not $dbh; - plan skip_all => "Database character set is not Unicode" if not db_ochar_is_utf($dbh) ; - print "testing utf8 with char columns (wide mode database)\n" ; + plan skip_all => 'Unable to connect to Oracle' unless $dbh; + plan skip_all => 'Database character set is not Unicode' + unless db_ochar_is_utf($dbh); + print "testing utf8 with char columns (wide mode database)\n"; - my $tdata = test_data( 'narrow_char' ); - my $testcount = 0 #create table - + insert_test_count( $tdata ) - + select_test_count( $tdata ) * 1; - ; + my $tdata = test_data('narrow_char'); + my $testcount = 0 #create table + + insert_test_count($tdata) + select_test_count($tdata) * 1; - plan tests => $testcount; - show_test_data( $tdata ,0 ); - drop_table($dbh); + plan tests => $testcount; + show_test_data( $tdata, 0 ); + force_drop_table($dbh); create_table( $dbh, $tdata ); - insert_rows( $dbh, $tdata ,SQLCS_NCHAR); - dump_table( $dbh ,'ch' ,'descr' ); + insert_rows( $dbh, $tdata, SQLCS_NCHAR ); + dump_table( $dbh, 'ch', 'descr' ); select_rows( $dbh, $tdata ); } END { - local($?, $!); - eval { - local $dbh->{PrintError} = 0 if $dbh; - drop_table($dbh) if $dbh and not $ENV{'DBD_SKIP_TABLE_DROP'}; - }; + eval { drop_table($dbh) }; } diff --git a/t/23wide_db_al32utf8.t b/t/23wide_db_al32utf8.t index b0ba18a6..ba5ee218 100644 --- a/t/23wide_db_al32utf8.t +++ b/t/23wide_db_al32utf8.t @@ -1,30 +1,36 @@ -#!perl -w +#!perl #written by Lincoln A Baxter (lab@lincolnbaxter.com) use strict; -#use warnings; +use warnings; use Test::More; use DBI qw(:sql_types); use DBD::Oracle qw( :ora_types ORA_OCI SQLCS_NCHAR ); -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; +use lib 't/lib'; +use DBDOracleTestLib qw/ + db_handle drop_table force_drop_table + test_data show_test_data select_rows + create_table insert_rows dump_table + set_nls_lang_charset db_ochar_is_utf + insert_test_count select_test_count +/; my $dbh; $| = 1; SKIP: { - plan skip_all => "Unable to run unicode test, perl version is less than 5.6" - unless ( $] >= 5.006 ); - plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" - if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; + plan skip_all => 'Unable to run unicode test, perl version is less than 5.6' + unless ( $] >= 5.006 ); + plan skip_all => 'Oracle charset tests unreliable for Oracle 8 client' + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; set_nls_lang_charset( (ORA_OCI >= 9.2) ? 'AL32UTF8' : 'UTF8', 1 ); $dbh = db_handle(); - plan skip_all => "Unable to connect to Oracle" if not $dbh; - plan skip_all => "Database character set is not Unicode" if not db_ochar_is_utf($dbh) ; + plan skip_all => 'Unable to connect to Oracle' unless $dbh; + plan skip_all => 'Database character set is not Unicode' unless db_ochar_is_utf($dbh) ; # testing utf8 with char columns (wide mode database) my $tdata = test_data( 'wide_char' ); @@ -35,17 +41,15 @@ SKIP: { plan tests => $testcount; show_test_data( $tdata ,0 ); - drop_table($dbh); + force_drop_table($dbh); create_table( $dbh, $tdata ); insert_rows( $dbh, $tdata ,SQLCS_NCHAR); dump_table( $dbh ,'ch' ,'descr' ); select_rows( $dbh, $tdata ); -} + +} # SKIP END { - eval { - local $dbh->{PrintError} = 0; - drop_table($dbh) if $dbh and not $ENV{'DBD_SKIP_TABLE_DROP'}; - }; + drop_table($dbh) } diff --git a/t/24implicit_utf8.t b/t/24implicit_utf8.t index e61b03f6..ce697b90 100644 --- a/t/24implicit_utf8.t +++ b/t/24implicit_utf8.t @@ -1,12 +1,18 @@ -#!perl -w +#!perl #written by Lincoln A Baxter (lab@lincolnbaxter.com) use strict; -#use warnings; -use Test::More; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ + db_handle db_nchar_is_utf db_ochar_is_utf test_data + insert_test_count select_test_count show_test_data + set_nls_nchar show_db_charsets force_drop_table + create_table insert_rows dump_table select_rows +/; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; +use Test::More; use DBI qw(:sql_types); use DBD::Oracle qw(:ora_types ORA_OCI SQLCS_NCHAR ); @@ -14,50 +20,52 @@ use DBD::Oracle qw(:ora_types ORA_OCI SQLCS_NCHAR ); my $dbh; $| = 1; SKIP: { - plan skip_all => "Unable to run 8bit char test, perl version is less than 5.6" unless ( $] >= 5.006 ); - plan skip_all => "Oracle charset tests unreliable for Oracle 8 client" - if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; - $dbh = db_handle(); # just to check connection and db NCHAR character set + plan skip_all => + 'Unable to run 8bit char test, perl version is less than 5.6' + unless ( $] >= 5.006 ); + plan skip_all => 'Oracle charset tests unreliable for Oracle 8 client' + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; + $dbh = db_handle(); # just to check connection and db NCHAR character set - plan skip_all => "Unable to connect to Oracle" if not $dbh; - plan skip_all => "Database NCHAR character set is not Unicode" if not db_nchar_is_utf($dbh) ; - plan skip_all => "database character set is not Unicode" unless db_ochar_is_utf($dbh); + plan skip_all => 'Unable to connect to Oracle' unless $dbh; + plan skip_all => 'Database NCHAR character set is not Unicode' + unless db_nchar_is_utf($dbh); + plan skip_all => 'Database character set is not Unicode' + unless db_ochar_is_utf($dbh); $dbh->disconnect(); # testing implicit csform (dbhimp.c sets csform implicitly) - my $tdata = test_data( 'wide_nchar' ); - my $testcount = 0 - + insert_test_count( $tdata ) - + select_test_count( $tdata ) * 1; - ; + my $tdata = test_data('wide_nchar'); + my $testcount = + 0 + insert_test_count($tdata) + select_test_count($tdata) * 1; - my @nchar_cset = (ORA_OCI >= 9.2) ? qw(UTF8 AL32UTF8) : qw(UTF8); + my @nchar_cset = ( ORA_OCI >= 9.2 ) ? qw(UTF8 AL32UTF8) : qw(UTF8); plan tests => $testcount * @nchar_cset; - show_test_data( $tdata ,0 ); + show_test_data( $tdata, 0 ); - foreach my $nchar_cset (@nchar_cset) { + foreach my $nchar_cset (@nchar_cset) { $dbh->disconnect() if $dbh; - undef $dbh; + undef $dbh; + # testing with NLS_NCHAR=$nchar_cset - SKIP: { - set_nls_nchar( $nchar_cset ,1 ); + SKIP: { + set_nls_nchar( $nchar_cset, 1 ); $dbh = db_handle(); - show_db_charsets($dbh); - skip "failed to connect to oracle with NLS_NCHAR=$nchar_cset" ,$testcount if not $dbh; - drop_table($dbh); + show_db_charsets($dbh); + skip "failed to connect to oracle with NLS_NCHAR=$nchar_cset", + $testcount + unless $dbh; + force_drop_table($dbh); create_table( $dbh, $tdata ); insert_rows( $dbh, $tdata ); - dump_table( $dbh ,'nch' ,'descr' ); + dump_table( $dbh, 'nch', 'descr' ); select_rows( $dbh, $tdata ); } } } END { - eval { - local $dbh->{PrintError} = 0; - drop_table( $dbh ) if $dbh and not $ENV{'DBD_SKIP_TABLE_DROP'}; - }; + eval { drop_table($dbh); $dbh->disconnect if $dbh }; } __END__ diff --git a/t/25plsql.t b/t/25plsql.t index 2e5dd531..c8cc9df4 100644 --- a/t/25plsql.t +++ b/t/25plsql.t @@ -1,269 +1,334 @@ -#!perl -w +#!perl + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + use Test::More; use DBI; use DBD::Oracle qw(ORA_RSET SQLCS_NCHAR); -use strict; - -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; $| = 1; -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', { PrintError => 0 }); +my $dbh = db_handle( { PrintError => 0 } ); if ($dbh) { + # ORA-00900: invalid SQL statement # ORA-06553: PLS-213: package STANDARD not accessible - my $tst = $dbh->prepare(q{declare foo char(50); begin RAISE INVALID_NUMBER; end;}); - if ($dbh->err && ($dbh->err==900 || $dbh->err==6553 || $dbh->err==600)) { - diag("Your Oracle server doesn't support PL/SQL") if $dbh->err== 900; - diag("Your Oracle PL/SQL is not properly installed") - if $dbh->err==6553||$dbh->err==600; - plan skip_all => 'Oracle server either does not support pl/sql or it is not properly installed'; + my $tst = + $dbh->prepare(q{declare foo char(50); begin RAISE INVALID_NUMBER; end;}); + if ( $dbh->err + && ( $dbh->err == 900 || $dbh->err == 6553 || $dbh->err == 600 ) ) + { + diag("Your Oracle server doesn't support PL/SQL") if $dbh->err == 900; + diag('Your Oracle PL/SQL is not properly installed') + if $dbh->err == 6553 || $dbh->err == 600; + plan skip_all => +'Oracle server either does not support pl/sql or it is not properly installed'; } - plan tests=>82; -} else { + plan tests => 82; +} +else { plan skip_all => "Unable to connect to Oracle \n"; } +my ( $csr, $p1, $p2, $tmp, @tmp ); -my($csr, $p1, $p2, $tmp, @tmp); #DBI->trace(4,"trace.log"); - # --- test raising predefined exception -ok($csr = $dbh->prepare(q{ - begin RAISE INVALID_NUMBER; end;}), 'prepare raising predefined exception'); +ok( + $csr = $dbh->prepare( + q{ + begin RAISE INVALID_NUMBER; end;} + ), + 'prepare raising predefined exception' +); # ORA-01722: invalid number -ok(! $csr->execute, 'execute predefined exception'); -is($DBI::err, 1722, 'err expected 1722 error'); -is($DBI::err, 1722, 'err does not get cleared'); - +ok( !$csr->execute, 'execute predefined exception' ); +is( $DBI::err, 1722, 'err expected 1722 error' ); +is( $DBI::err, 1722, 'err does not get cleared' ); # --- test raising user defined exception -ok($csr = $dbh->prepare(q{ +ok( + $csr = $dbh->prepare( + q{ DECLARE FOO EXCEPTION; - begin raise FOO; end;}), 'prepare user defined expcetion'); + begin raise FOO; end;} + ), + 'prepare user defined expcetion' +); # ORA-06510: PL/SQL: unhandled user-defined exception -ok(! $csr->execute, 'execute user defined exception'); -is($DBI::err, 6510, 'user exception 6510 error'); - +ok( !$csr->execute, 'execute user defined exception' ); +is( $DBI::err, 6510, 'user exception 6510 error' ); # --- test raise_application_error with literal values -ok($csr = $dbh->prepare(q{ +ok( + $csr = $dbh->prepare( + q{ declare err_num number; err_msg char(510); - begin RAISE_APPLICATION_ERROR(-20101,'app error'); end;}), - 'prepare raise application error with literal values'); + begin RAISE_APPLICATION_ERROR(-20101,'app error'); end;} + ), + 'prepare raise application error with literal values' +); # ORA-20101: app error -ok(! $csr->execute, 'execite raise application error with literal values'); -is($DBI::err, 20101, 'expected 20101 error'); -like($DBI::errstr, qr/app error/, 'app error'); - +ok( !$csr->execute, 'execute raise application error with literal values' ); +is( $DBI::err, 20101, 'expected 20101 error' ); +like( $DBI::errstr, qr/app error/, 'app error' ); # --- test raise_application_error with 'in' parameters -ok($csr = $dbh->prepare(q{ +ok( + $csr = $dbh->prepare( + q{ declare err_num varchar2(555); err_msg varchar2(510); --declare err_num number; err_msg char(510); begin - err_num := :1; - err_msg := :2; - raise_application_error(-20000-err_num, 'msg is '||err_msg); + err_num := :1; + err_msg := :2; + raise_application_error(-20000-err_num, 'msg is '||err_msg); end; -}), 'prepare raise application error with in params'); +} + ), + 'prepare raise application error with in params' +); -ok(! $csr->execute(42, "hello world"), - 'execute raise application error with in params'); -is($DBI::err, 20042, 'expected 20042 error'); -like($DBI::errstr, qr/msg is hello world/, 'hello world msg'); +ok( !$csr->execute( 42, 'hello world' ), + 'execute raise application error with in params' ); +is( $DBI::err, 20042, 'expected 20042 error' ); +like( $DBI::errstr, qr/msg is hello world/, 'hello world msg' ); # --- test named numeric in/out parameters -ok($csr = $dbh->prepare(q{ +ok( + $csr = $dbh->prepare( + q{ begin - :arg := :arg * :mult; - end;}), 'prepare named numeric in/out params'); + :arg := :arg * :mult; + end;} + ), + 'prepare named numeric in/out params' +); $p1 = 3; -ok($csr->bind_param_inout(':arg', \$p1, 50), 'bind arg'); -ok($csr->bind_param(':mult', 2), 'bind mult'); -ok($csr->execute, 'execute named numeric in/out params'); -is($p1, 6, 'expected 3 * 3 = 6'); +ok( $csr->bind_param_inout( ':arg', \$p1, 50 ), 'bind arg' ); +ok( $csr->bind_param( ':mult', 2 ), 'bind mult' ); +ok( $csr->execute, 'execute named numeric in/out params' ); +is( $p1, 6, 'expected 3 * 3 = 6' ); + # execute 10 times from $p1=1, 2, 4, 8, ... 1024 $p1 = 1; eval { - foreach (1..10) { $csr->execute || die $DBI::errstr; }; + foreach ( 1 .. 10 ) { $csr->execute || die $DBI::errstr; } }; my $ev = $@; -ok(!$ev, 'execute named numeric in/out params 10 times'); -is($p1, 1024, 'expected p1 = 1024'); +ok( !$ev, 'execute named numeric in/out params 10 times' ); +is( $p1, 1024, 'expected p1 = 1024' ); # --- test undef parameters -ok($csr = $dbh->prepare(q{ - declare foo char(500); - begin foo := :arg; end;}), 'prepare undef parameters'); +ok( + $csr = $dbh->prepare( + q{ + declare foo char(500); + begin foo := :arg; end;} + ), + 'prepare undef parameters' +); my $undef; -ok($csr->bind_param_inout(':arg', \$undef,10), 'bind arg'); -ok($csr->execute, 'execute undef parameters'); +ok( $csr->bind_param_inout( ':arg', \$undef, 10 ), 'bind arg' ); +ok( $csr->execute, 'execute undef parameters' ); # --- test named string in/out parameters -ok($csr = $dbh->prepare(q{ +ok( + $csr = $dbh->prepare( + q{ declare str varchar2(1000); begin - :arg := nvl(upper(:arg), 'null'); - :arg := :arg || :append; - end;}), 'prepare named string in/out parameters'); + :arg := nvl(upper(:arg), 'null'); + :arg := :arg || :append; + end;} + ), + 'prepare named string in/out parameters' +); undef $p1; -$p1 = "hello world"; -ok($csr->bind_param_inout(':arg', \$p1, 1000), 'bind arg'); -ok($csr->bind_param(':append', "!"), 'bind append'); -ok($csr->execute, 'execute named string in/out parameters'); -is($p1, "HELLO WORLD!", 'expected HELLO WORLD'); +$p1 = 'hello world'; +ok( $csr->bind_param_inout( ':arg', \$p1, 1000 ), 'bind arg' ); +ok( $csr->bind_param( ':append', '!' ), 'bind append' ); +ok( $csr->execute, 'execute named string in/out parameters' ); +is( $p1, 'HELLO WORLD!', 'expected HELLO WORLD' ); + # execute 10 times growing $p1 to force realloc eval { - foreach (1..10) { - $p1 .= " xxxxxxxxxx"; + for ( 1 .. 10 ) { + $p1 .= ' xxxxxxxxxx'; $csr->execute || die $DBI::errstr; - }; + } }; $ev = $@; -ok(!$ev, 'execute named string in/out parameters 1- times'); -my $expect = "HELLO WORLD!" . (" XXXXXXXXXX!" x 10); -is($p1, $expect, 'p1 as expected'); +ok( !$ev, 'execute named string in/out parameters 1- times' ); +my $expect = 'HELLO WORLD!' . ( ' XXXXXXXXXX!' x 10 ); +is( $p1, $expect, 'p1 as expected' ); # --- test binding a null and getting a string back undef $p1; -ok($csr->execute, 'execute binding a null'); -is($p1, 'null!', 'get a null string back'); +ok( $csr->execute, 'execute binding a null' ); +is( $p1, 'null!', 'get a null string back' ); $csr->finish; - -ok($csr = $dbh->prepare(q{ +ok( + $csr = $dbh->prepare( + q{ begin - :out := nvl(upper(:in), 'null'); - end;}), 'prepare nvl'); + :out := nvl(upper(:in), 'null'); + end;} + ), + 'prepare nvl' +); + #$csr->trace(3); my $out; -ok($csr->bind_param_inout(':out', \$out, 1000), 'bind out'); -ok($csr->bind_param(':in', "foo", DBI::SQL_CHAR()), 'bind in'); -ok($csr->execute, 'execute nvl'); -is($out, "FOO", 'expected FOO'); +ok( $csr->bind_param_inout( ':out', \$out, 1000 ), 'bind out' ); +ok( $csr->bind_param( ':in', 'foo', DBI::SQL_CHAR() ), 'bind in' ); +ok( $csr->execute, 'execute nvl' ); +is( $out, 'FOO', 'expected FOO' ); -ok($csr->bind_param(':in', ""), 'bind empty string'); -ok($csr->execute, 'execute empty string'); -is($out, "null", 'returned null string'); +ok( $csr->bind_param( ':in', '' ), 'bind empty string' ); +ok( $csr->execute, 'execute empty string' ); +is( $out, 'null', 'returned null string' ); # --- test out buffer being too small -ok($csr = $dbh->prepare(q{ +ok( + $csr = $dbh->prepare( + q{ begin - select rpad('foo',200) into :arg from dual; - end;}), 'prepare test output buffer too small'); + select rpad('foo',200) into :arg from dual; + end;} + ), + 'prepare test output buffer too small' +); + #$csr->trace(3); -undef $p1; # force buffer to be freed -ok($csr->bind_param_inout(':arg', \$p1, 20), 'bind arg'); +undef $p1; # force buffer to be freed +ok( $csr->bind_param_inout( ':arg', \$p1, 20 ), 'bind arg' ); + # Execute fails with: -# ORA-06502: PL/SQL: numeric or value error -# ORA-06512: at line 3 (DBD ERROR: OCIStmtExecute) +# ORA-06502: PL/SQL: numeric or value error +# ORA-06512: at line 3 (DBD ERROR: OCIStmtExecute) $tmp = $csr->execute; + #$tmp = undef if DBD::Oracle::ORA_OCI()>=8; # because BindByName given huge max len -ok(!defined $tmp, 'output buffer too small'); -# rebind with more space - and it should work -ok($csr->bind_param_inout(':arg', \$p1, 200), 'rebind arg with more space'); -ok($csr->execute, 'execute rebind with more space'); -is(length($p1), 200, 'expected return length'); +ok( !defined $tmp, 'output buffer too small' ); +# rebind with more space - and it should work +ok( $csr->bind_param_inout( ':arg', \$p1, 200 ), 'rebind arg with more space' ); +ok( $csr->execute, 'execute rebind with more space' ); +is( length($p1), 200, 'expected return length' ); # --- test plsql_errstr function #$csr = $dbh->prepare(q{ # create or replace procedure perl_dbd_oracle_test as # begin -# procedure filltab( stuff out tab ); asdf +# procedure filltab( stuff out tab ); asdf # end; #}); #ok(0, ! $csr); -#if ($dbh->err && $dbh->err == 6550) { # PL/SQL error -# warn "errstr: ".$dbh->errstr; -# my $msg = $dbh->func('plsql_errstr'); -# warn "plsql_errstr: $msg"; -# ok(0, $msg =~ /Encountered the symbol/, "plsql_errstr: $msg"); +#if ($dbh->err && $dbh->err == 6550) { # PL/SQL error +# warn "errstr: ".$dbh->errstr; +# my $msg = $dbh->func('plsql_errstr'); +# warn "plsql_errstr: $msg"; +# ok(0, $msg =~ /Encountered the symbol/, "plsql_errstr: $msg"); #} #else { -# warn "plsql_errstr test skipped ($DBI::err)\n"; -# ok(0, 1); +# warn "plsql_errstr test skipped ($DBI::err)\n"; +# ok(0, 1); #} #die; # --- test dbms_output_* functions $dbh->{PrintError} = 1; -ok($dbh->func(30000, 'dbms_output_enable'), 'dbms_output_enable'); +ok( $dbh->func( 30000, 'dbms_output_enable' ), 'dbms_output_enable' ); #$dbh->trace(3); -my @ary = ("foo", ("bar" x 15), "baz", "boo"); -ok($dbh->func(@ary, 'dbms_output_put'), 'dbms_output_put'); +my @ary = ( 'foo', ( 'bar' x 15 ), 'baz', 'boo' ); +ok( $dbh->func( @ary, 'dbms_output_put' ), 'dbms_output_put' ); -@ary = scalar $dbh->func('dbms_output_get'); # scalar context -ok(@ary==1 && $ary[0] && $ary[0] eq 'foo', 'dbms_output_get foo'); +@ary = scalar $dbh->func('dbms_output_get'); # scalar context +ok( @ary == 1 && $ary[0] && $ary[0] eq 'foo', 'dbms_output_get foo' ); -@ary = scalar $dbh->func('dbms_output_get'); # scalar context -ok(@ary==1 && $ary[0] && $ary[0] eq 'bar' x 15, 'dbms_output_get bar'); +@ary = scalar $dbh->func('dbms_output_get'); # scalar context +ok( @ary == 1 && $ary[0] && $ary[0] eq 'bar' x 15, 'dbms_output_get bar' ); -@ary = $dbh->func('dbms_output_get'); # list context -is(join(':',@ary), 'baz:boo', 'dbms_output_get baz:boo'); +@ary = $dbh->func('dbms_output_get'); # list context +is( join( ':', @ary ), 'baz:boo', 'dbms_output_get baz:boo' ); $dbh->{PrintError} = 0; + #$dbh->trace(0); # --- test cursor variables if (1) { my $cur_query = q{ - SELECT object_name, owner - FROM all_objects - WHERE object_name LIKE :p1 - ORDER BY object_name + SELECT object_name, owner + FROM all_objects + WHERE object_name LIKE :p1 + ORDER BY object_name }; my $cur1 = 42; + #$dbh->trace(4); - my $parent = $dbh->prepare(qq{ - BEGIN OPEN :cur1 FOR $cur_query; END; - }); - ok($parent, 'prepare cursor'); - ok($parent->bind_param(":p1", "V%"), 'bind p1'); - ok($parent->bind_param_inout( - ":cur1", \$cur1, 0, { ora_type => ORA_RSET }), 'bind cursor'); - ok($parent->execute(), 'execute for cursor'); + my $parent = $dbh->prepare( + qq{ + BEGIN OPEN :cur1 FOR $cur_query; END; + } + ); + ok( $parent, 'prepare cursor' ); + ok( $parent->bind_param( ':p1', 'V%' ), 'bind p1' ); + ok( + $parent->bind_param_inout( + ':cur1', \$cur1, 0, { ora_type => ORA_RSET } + ), + 'bind cursor' + ); + ok( $parent->execute(), 'execute for cursor' ); my @r; push @r, @tmp while @tmp = $cur1->fetchrow_array; - ok(@r>0, "rows: ".@r); + ok( @r > 0, 'rows: ' . @r ); + #$dbh->trace(0); $parent->trace(0); # compare results with normal execution of query - my $s1 = $dbh->selectall_arrayref($cur_query, undef, "V%"); + my $s1 = $dbh->selectall_arrayref( $cur_query, undef, 'V%' ); my @s1 = map { @$_ } @$s1; - is(join(' ',sort@r), join(' ',sort@s2), 'ref = sql'); + is( join( ' ', sort @r ), join( ' ', sort @s1 ), 'ref = sql' ); # --- test re-bind and re-execute of same 'parent' statement my $cur1_str = "$cur1"; + #$dbh->trace(4); $parent->trace(4); - ok($parent->bind_param(":p1", "U%"), 'bind p1'); - ok($parent->execute(), 'execute for cursor'); + ok( $parent->bind_param( ':p1', 'U%' ), 'bind p1' ); + ok( $parent->execute(), 'execute for cursor' ); + # must be ref to new handle object - isnt("$cur1", $cur1_str, 'expected ref to new handle'); + isnt( "$cur1", $cur1_str, 'expected ref to new handle' ); @r = (); push @r, @tmp while @tmp = $cur1->fetchrow_array; + #$dbh->trace(0); $parent->trace(0); $cur1->trace(0); - my $s2 = $dbh->selectall_arrayref($cur_query, undef, "U%"); + my $s2 = $dbh->selectall_arrayref( $cur_query, undef, 'U%' ); my @s2 = map { @$_ } @$s2; - is("@r", "@s2", "ref = sql"); + is( "@r", "@s2", 'ref = sql' ); } # test bind_param_inout of param that's not assigned to in executed statement # See http://www.mail-archive.com/dbi-users@perl.org/msg18835.html -my $sth = $dbh->prepare (q( +my $sth = $dbh->prepare( + q( BEGIN -- :p1 := :p1 ; -- :p2 := :p2 ; @@ -271,68 +336,77 @@ my $sth = $dbh->prepare (q( :p1 := 'AAA' ; :p2 := 'Z' ; END IF ; -END ;)); +END ;) +); { - my ($p1, $p2, $p3) = ('Hello', 'Y', 'Y') ; - $sth->bind_param_inout(':p1', \$p1, 30) ; - $sth->bind_param_inout(':p2', \$p2, 1) ; - $sth->bind_param_inout(':p3', \$p3, 1) ; + my ( $p1, $p2, $p3 ) = ( 'Hello', 'Y', 'Y' ); + $sth->bind_param_inout( ':p1', \$p1, 30 ); + $sth->bind_param_inout( ':p2', \$p2, 1 ); + $sth->bind_param_inout( ':p3', \$p3, 1 ); note("Before p1=[$p1] p2=[$p2] p3=[$p3]\n"); - ok($sth->execute, 'test bind_param_inout for non assigned'); - is($p1, 'Hello', 'p1 ok'); - is($p2, 'Y', 'p2 ok'); - is($p3, 'Y', 'p3 ok'); + ok( $sth->execute, 'test bind_param_inout for non assigned' ); + is( $p1, 'Hello', 'p1 ok' ); + is( $p2, 'Y', 'p2 ok' ); + is( $p3, 'Y', 'p3 ok' ); note("After p1=[$p1] p2=[$p2] p3=[$p3]\n"); } SKIP: { # test nvarchar2 arg passing to functions # http://www.nntp.perl.org/group/perl.dbi.users/24217 - my $ora_server_version = $dbh->func("ora_server_version"); - skip "Client/server version < 9.0", 15 - if DBD::Oracle::ORA_OCI() < 9.0 || $ora_server_version->[0] < 9; - - my $func_name = "dbd_oracle_nvctest".($ENV{DBD_ORACLE_SEQ}||''); - $dbh->do(qq{ - CREATE OR REPLACE FUNCTION $func_name(arg nvarchar2, arg2 nvarchar2) - RETURN int IS - BEGIN - if arg is null or arg2 is null then - return -1; - else - return 1; - end if; - END; - }) or skip "Can't create a function ($DBI::errstr)", 15; - my $sth = $dbh->prepare(qq{SELECT $func_name(?, ?) FROM DUAL}, { - # Oracle 8 describe fails with ORA-06553: PLS-561: charset mismatch - ora_check_sql => 0, - }); - ok($sth, sprintf("Can't prepare select from function (%s)",$DBI::errstr||'')); + my $ora_server_version = $dbh->func('ora_server_version'); + skip 'Client/server version < 9.0', 15 + if DBD::Oracle::ORA_OCI() < 9.0 || $ora_server_version->[0] < 9; + + my $func_name = 'dbd_oracle_nvctest' . ( $ENV{DBD_ORACLE_SEQ} || '' ); + $dbh->do( + qq{ + CREATE OR REPLACE FUNCTION $func_name(arg nvarchar2, arg2 nvarchar2) + RETURN int IS + BEGIN + if arg is null or arg2 is null then + return -1; + else + return 1; + end if; + END; + } + ) or skip "Can't create a function ($DBI::errstr)", 15; + my $sth = $dbh->prepare( + qq{SELECT $func_name(?, ?) FROM DUAL}, + { + # Oracle 8 describe fails with ORA-06553: PLS-561: charset mismatch + ora_check_sql => 0, + } + ); + ok( + $sth, + sprintf( + q/Can't prepare select from function (%s)/, $DBI::errstr || '' + ) + ); skip "Can't select from function ($DBI::errstr)", 14 unless $sth; - for (1..2) { - ok($sth->bind_param(1, "foo", { ora_csform => SQLCS_NCHAR }), - 'bind foo'); - ok($sth->bind_param(2, "bar", { ora_csform => SQLCS_NCHAR }), - 'bind bar'); - ok($sth->execute(), 'execute'); - ok(my($returnVal) = $sth->fetchrow_array, 'fetchrow returns value'); - is($returnVal, "1", 'expected return value of 1'); + for ( 1 .. 2 ) { + ok( $sth->bind_param( 1, 'foo', { ora_csform => SQLCS_NCHAR } ), + 'bind foo' ); + ok( $sth->bind_param( 2, 'bar', { ora_csform => SQLCS_NCHAR } ), + 'bind bar' ); + ok( $sth->execute(), 'execute' ); + ok( my ($returnVal) = $sth->fetchrow_array, 'fetchrow returns value' ); + is( $returnVal, '1', 'expected return value of 1' ); } - ok($sth->execute("baz",undef), 'execute with baz'); - ok(my($returnVal) = $sth->fetchrow_array, 'fetchrow_returns value'); - is($returnVal, "-1", 'expected -1 return'); - ok($dbh->do(qq{drop function $func_name}), "drop $func_name"); + ok( $sth->execute( 'baz', undef ), 'execute with baz' ); + ok( my ($returnVal) = $sth->fetchrow_array, 'fetchrow_returns value' ); + is( $returnVal, '-1', 'expected -1 return' ); + ok( $dbh->do(qq{drop function $func_name}), "drop $func_name" ); } - # --- To do - # test NULLs at first bind - # NULLs later binds. - # returning NULLs - # multiple params, mixed types and in only vs inout - +# test NULLs at first bind +# NULLs later binds. +# returning NULLs +# multiple params, mixed types and in only vs inout exit 0; diff --git a/t/26exe_array.t b/t/26exe_array.t index dce93725..b5fd12cd 100644 --- a/t/26exe_array.t +++ b/t/26exe_array.t @@ -1,65 +1,64 @@ -# $Id$ +#!perl # Completely new test for DBD::Oracle which came from DBD::ODBC # Author: Martin J. Evans # # loads of execute_array and execute_for_fetch tests using DBI's methods -# -use Test::More; + use strict; -use Data::Dumper; -require 'nchar_test_lib.pl'; +use warnings; -use lib 't/lib', 't'; +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; -$| = 1; +use Test::More; +use Data::Dumper; +require Test::NoWarnings; # deliberately not calling import() -my $has_test_nowarnings = eval "require Test::NoWarnings; 1"; +$| = 1; use DBI qw(:sql_types); use ExecuteArray; +$ENV{NLS_NCHAR} = 'US7ASCII'; +$ENV{NLS_LANG} = 'AMERICAN'; -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -$ENV{NLS_NCHAR} = "US7ASCII"; -$ENV{NLS_LANG} = "AMERICAN"; - -my $dbh = eval { - DBI->connect($dsn, $dbuser, '', {PrintError => 0}) -} or plan skip_all => "Unable to connect to Oracle"; +my $dbh = db_handle( { PrintError => 0 } ) + or plan skip_all => 'Unable to connect to Oracle'; -my $ea = ExecuteArray->new($dbh, 1); # set odbc_disable_array_operations +my $ea = ExecuteArray->new( $dbh, 1 ); # set odbc_disable_array_operations $dbh = $ea->dbh; $ea->drop_table($dbh); -ok($ea->create_table($dbh), "create test table") or exit 1; - -$ea->simple($dbh, {array_context => 1, raise => 1}); -$ea->simple($dbh, {array_context => 0, raise => 1}); -$ea->error($dbh, {array_context => 1, raise => 1}); -$ea->error($dbh, {array_context => 0, raise => 1}); -$ea->error($dbh, {array_context => 1, raise => 0}); -$ea->error($dbh, {array_context => 0, raise => 0}); - -$ea->row_wise($dbh, {array_context => 1, raise => 1}); - -$ea->update($dbh, {array_context => 1, raise => 1}); - -for my $raise ( 0..1 ) { - for my $context ( 0..1 ) { - $ea->error($dbh, { - array_context => $context, - raise => $raise, - notuplestatus => 1 - }); +ok( $ea->create_table($dbh), 'create test table' ) or exit 1; + +$ea->simple( $dbh, { array_context => 1, raise => 1 } ); +$ea->simple( $dbh, { array_context => 0, raise => 1 } ); +$ea->error( $dbh, { array_context => 1, raise => 1 } ); +$ea->error( $dbh, { array_context => 0, raise => 1 } ); +$ea->error( $dbh, { array_context => 1, raise => 0 } ); +$ea->error( $dbh, { array_context => 0, raise => 0 } ); + +$ea->row_wise( $dbh, { array_context => 1, raise => 1 } ); + +$ea->update( $dbh, { array_context => 1, raise => 1 } ); + +for my $raise ( 0 .. 1 ) { + for my $context ( 0 .. 1 ) { + $ea->error( + $dbh, + { + array_context => $context, + raise => $raise, + notuplestatus => 1 + } + ); } } -if ($dbh && $ea) { +if ( $dbh && $ea ) { $ea->drop_table($dbh); - $dbh->disconnect(); } -Test::NoWarnings::had_no_warnings() if $has_test_nowarnings; +Test::NoWarnings::had_no_warnings(); done_testing; diff --git a/t/28array_bind.t b/t/28array_bind.t index d107bbc0..6b4eb4a4 100644 --- a/t/28array_bind.t +++ b/t/28array_bind.t @@ -1,20 +1,24 @@ -#!perl -w -use strict; +#!perl ## ---------------------------------------------------------------------------- ## 26array_bind.t ## By Alexander V Alekseev ## and John Scoles, The Pythian Group -## +## ## ---------------------------------------------------------------------------- ## Checking bind_param_inout to an varchar2_table and number_table ## Checking bind_param_inout_array with execute_array -## +## ## ---------------------------------------------------------------------------- use strict; use warnings; +use lib 't/lib'; +use DBDOracleTestLib qw/ + set_nls_lang_charset set_nls_nchar oracle_test_dsn db_handle +/; + use Encode; use Devel::Peek; @@ -23,278 +27,319 @@ use DBD::Oracle qw(:ora_types ORA_OCI); use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - use Data::Dumper; - -$Data::Dumper::Useqq=1; +$Data::Dumper::Useqq = 1; my $dbh; -my $utf8_charset = (ORA_OCI >= 9.2) ? 'AL32UTF8' : 'UTF8'; +my $utf8_charset = ( ORA_OCI >= 9.2 ) ? 'AL32UTF8' : 'UTF8'; my $eight_bit_charset = 'WE8ISO8859P1'; -sub db_connect($) { +sub db_connect { my $utf8 = shift; # Make sure we really are overriding the environment settings. - my ($charset, $ncharset); + my ( $charset, $ncharset ); if ($utf8) { set_nls_lang_charset($eight_bit_charset); set_nls_nchar($eight_bit_charset); - $charset = $utf8_charset; + $charset = $utf8_charset; $ncharset = $utf8_charset; } else { set_nls_lang_charset($utf8_charset); set_nls_nchar($utf8_charset); - $charset = $eight_bit_charset; + $charset = $eight_bit_charset; $ncharset = $eight_bit_charset; } - my $dsn = oracle_test_dsn(); - my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - my $p = { - AutoCommit => 1, - PrintError => 0, + AutoCommit => 1, + PrintError => 0, FetchHashKeyName => 'NAME_lc', - ora_envhp => 0, # force fresh environment (with current NLS env vars) + ora_envhp => 0, # force fresh environment (with current NLS env vars) }; - $p->{ora_charset} = $charset if $charset; + $p->{ora_charset} = $charset if $charset; $p->{ora_ncharset} = $ncharset if $ncharset; - my $dbh = DBI->connect($dsn, $dbuser, '', $p); + my $dbh = db_handle( $p ); return $dbh; } -sub test_varchar2_table_3_tests($){ - my $dbh=shift; - my $statement=' - DECLARE - tbl SYS.DBMS_SQL.VARCHAR2_TABLE; - BEGIN - tbl := :mytable; - :cc := tbl.count(); - tbl(1) := \'def\'; - tbl(2) := \'ijk\'; - :mytable := tbl; - END; - '; - - my $sth=$dbh->prepare( $statement ); - - if( ! defined($sth) ){ - BAIL_OUT("Prapare(varchar2) error: ".$dbh->errstr); - } - - my @arr=( "abc", "cde","lalala" ); - - if( not $sth->bind_param_inout(":mytable", \\@arr, 5, { - ora_type => ORA_VARCHAR2_TABLE, - ora_maxarray_numentries => 2 - } - ) ){ - BAIL_OUT("bind :mytable (VARCHAR2) error: ".$dbh->errstr); - } - my $cc; - if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ - BAIL_OUT("bind :cc (at VARCHAR2) error: ".$dbh->errstr); - } - - if( not $sth->execute() ){ - BAIL_OUT("Execute (at VARCHAR2) failed: ".$dbh->errstr); - } - # print "Result: cc=",$cc,"\n", - # "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; - - #Result: cc=2, l=3 - # arr=$VAR1 = [ - # 'def', - # 'ijk' - # ]; - # - - ok( $cc == 2, "VARCHAR2_TABLE input count correctness"); - ok( scalar(@arr) == 2,"VARCHAR2_TABLE output count correctness"); - ok( (($arr[0] eq 'def') and ($arr[1] eq 'ijk')) , "VARCHAR2_TABLE output content") or - diag( "arr[0]='",$arr[0],"', arr[1]='",$arr[1],"', arr=", Data::Dumper::Dumper(\@arr)); +sub test_varchar2_table_3_tests($) { + my $dbh = shift; + my $statement = q| + DECLARE + tbl SYS.DBMS_SQL.VARCHAR2_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(1) := 'def'; + tbl(2) := 'ijk'; + :mytable := tbl; + END; + |; + + my $sth = $dbh->prepare($statement); + + if ( !defined($sth) ) { + BAIL_OUT( 'Prapare(varchar2) error: ' . $dbh->errstr ); + } + + my @arr = ( 'abc', 'cde', 'lalala' ); + + if ( + not $sth->bind_param_inout( + ':mytable', + \\@arr, + 5, + { + ora_type => ORA_VARCHAR2_TABLE, + ora_maxarray_numentries => 2 + } + ) + ) + { + BAIL_OUT( 'bind :mytable (VARCHAR2) error: ' . $dbh->errstr ); + } + my $cc; + if ( not $sth->bind_param_inout( ':cc', \$cc, 100 ) ) { + BAIL_OUT( 'bind :cc (at VARCHAR2) error: ' . $dbh->errstr ); + } + + if ( not $sth->execute() ) { + BAIL_OUT( 'Execute (at VARCHAR2) failed: ' . $dbh->errstr ); + } + + # print "Result: cc=",$cc,"\n", + # "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + #Result: cc=2, l=3 + # arr=$VAR1 = [ + # 'def', + # 'ijk' + # ]; + # + + ok( $cc == 2, 'VARCHAR2_TABLE input count correctness' ); + ok( scalar(@arr) == 2, 'VARCHAR2_TABLE output count correctness' ); + ok( ( ( $arr[0] eq 'def' ) and ( $arr[1] eq 'ijk' ) ), + 'VARCHAR2_TABLE output content' ) + or diag( "arr[0]='", $arr[0], "', arr[1]='", $arr[1], "', arr=", + Data::Dumper::Dumper( \@arr ) ); } -sub test_number_table_3_tests($){ - my $dbh=shift; - my $statement=' - DECLARE - tbl SYS.DBMS_SQL.NUMBER_TABLE; - BEGIN - tbl := :mytable; - :cc := tbl.count(); - tbl(4) := -1; - tbl(5) := -2; - :mytable := tbl; - END; - '; - - my $sth=$dbh->prepare( $statement ); - - if( ! defined($sth) ){ - BAIL_OUT("Prapare(NUMBER_TABLE) error: ".$dbh->errstr); - } - - my @arr=( 1,"2E0","3.5" ); - - # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . - - if( not $sth->bind_param_inout(":mytable", \\@arr, 10, { - ora_type => ORA_NUMBER_TABLE, - ora_maxarray_numentries => (scalar(@arr)+2), - ora_internal_type => SQLT_INT - } - ) ) - { - BAIL_OUT("bind(NUMBER_TABLE) :mytable error: ".$dbh->errstr); - } - my $cc=undef; - if( not $sth->bind_param_inout(":cc", \$cc, 100 ) ){ - BAIL_OUT("bind(NUMBER_TABLE) :cc error: ".$dbh->errstr); - } - - if( not $sth->execute() ){ - BAIL_OUT("Execute(NUMBER_TABLE) failed: ".$dbh->errstr); - } - # print "Result: cc=",$cc,"\n", - # "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; - - #Result: cc=3 - # arr=$VAR1 = [ - # '5', - # '8', - # '3.5', - # '-1', - # '-2' - # ]; - - ok( $cc == 3, "NUMBER_TABLE input count correctness"); - ok( scalar(@arr) == 5,"NUMBER_TABLE output count correctness"); - my $result=1; - my @r=(1, 2, 3, -1, -2); - for( my $i=0 ; $i< scalar(@arr) ; $i++){ - if( $r[$i] != $arr[$i] ){ - $result=0; - last; - } - } - ok( $result , "NUMBER_TABLE output content") or - diag( "arr=", Data::Dumper::Dumper(\@arr),"\nThough must be: ",Data::Dumper::Dumper(\@r)); + +sub test_number_table_3_tests { + my $dbh = shift; + my $statement = q| + DECLARE + tbl SYS.DBMS_SQL.NUMBER_TABLE; + BEGIN + tbl := :mytable; + :cc := tbl.count(); + tbl(4) := -1; + tbl(5) := -2; + :mytable := tbl; + END; + |; + + my $sth = $dbh->prepare($statement); + + if ( !defined($sth) ) { + BAIL_OUT( 'Prapare(NUMBER_TABLE) error: ' . $dbh->errstr ); + } + + my @arr = ( 1, '2E0', '3.5' ); + + # note, that ora_internal_type defaults to SQLT_FLT for ORA_NUMBER_TABLE . + + if ( + not $sth->bind_param_inout( + ':mytable', + \\@arr, + 10, + { + ora_type => ORA_NUMBER_TABLE, + ora_maxarray_numentries => ( scalar(@arr) + 2 ), + ora_internal_type => SQLT_INT + } + ) + ) + { + BAIL_OUT( 'bind(NUMBER_TABLE) :mytable error: ' . $dbh->errstr ); + } + my $cc = undef; + if ( not $sth->bind_param_inout( ':cc', \$cc, 100 ) ) { + BAIL_OUT( 'bind(NUMBER_TABLE) :cc error: ' . $dbh->errstr ); + } + + if ( not $sth->execute() ) { + BAIL_OUT( 'Execute(NUMBER_TABLE) failed: ' . $dbh->errstr ); + } + + # print "Result: cc=",$cc,"\n", + # "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; + + #Result: cc=3 + # arr=$VAR1 = [ + # '5', + # '8', + # '3.5', + # '-1', + # '-2' + # ]; + + ok( $cc == 3, 'NUMBER_TABLE input count correctness' ); + ok( scalar(@arr) == 5, 'NUMBER_TABLE output count correctness' ); + my $result = 1; + my @r = ( 1, 2, 3, -1, -2 ); + for ( my $i = 0 ; $i < scalar(@arr) ; $i++ ) { + if ( $r[$i] != $arr[$i] ) { + $result = 0; + last; + } + } + ok( $result, 'NUMBER_TABLE output content' ) + or diag( + 'arr=', + Data::Dumper::Dumper( \@arr ), + "\nThough must be: ", + Data::Dumper::Dumper( \@r ) + ); } -sub test_inout_array_tests($){ - my $dbh=shift; - $dbh->do("create table array_in_out_test (id number(12,0), name varchar2(20), value varchar2(2000))"); - $dbh->do("create sequence seq_array_in_out_test start with 1"); - $dbh->do(" - create or replace trigger trg_array_in_out_testst - before insert - on array_in_out_test - for each row - DECLARE - iCounter array_in_out_test.id%TYPE; - BEGIN - if INSERTING THEN - Select seq_array_in_out_test.nextval INTO iCounter FROM Dual; - :new.id := iCounter; - END IF; - END; - "); - - my @in_array1=('one','two','three','four','five'); - my @in_array2=('5','4','3','2','1'); - my @out_array; - my @tuple_status; - - my $sql = "insert into array_in_out_test (name, value) values (?,?) returning id into ?" ; - - my $sth = $dbh->prepare($sql); - - $sth->bind_param_array(1,\@in_array1 ); - $sth->bind_param_array(2,\@in_array2); - ok ( $sth->bind_param_inout_array(3,\@out_array,0,{ora_type => ORA_VARCHAR2}),'... bind_param_inout_array should return false'); - - ok ( $sth->execute_array({ArrayTupleStatus=>\@tuple_status}),'... execute_array should return false'); - - cmp_ok(scalar (@tuple_status), '==',5 , '... we should have 19 tuple_status'); - cmp_ok(scalar (@out_array), '==',5 , '... we should have 5 out_array'); - cmp_ok($out_array[0], '==', 1,'... out values should match 1'); - cmp_ok($out_array[1], '==', 2,'... out values should match 2'); - cmp_ok($out_array[2], '==', 3,'... out values should match 3'); - cmp_ok($out_array[3], '==', 4,'... out values should match 3'); - cmp_ok($out_array[4], '==', 5,'... out values should match 5'); - - $dbh->do("drop table array_in_out_test") or warn $dbh->errstr; - $dbh->do("drop sequence seq_array_in_out_test") or die $dbh->errstr; - +sub test_inout_array_tests { + my $dbh = shift; + my $table = 'array_io_test__drop_me' . ( $ENV{DBD_ORACLE_SEQ} || '' ); + my $seq = 'seq_io_test__drop_me' . ( $ENV{DBD_ORACLE_SEQ} || '' ); + my $trigger = 'trg_io_test__drop_me' . ( $ENV{DBD_ORACLE_SEQ} || '' ); + $dbh->do( +"create table $table (id number(12,0), name varchar2(20), value varchar2(2000))" + ); + $dbh->do("create sequence $seq start with 1"); + $dbh->do( + qq/ + create or replace trigger $trigger + before insert + on $table + for each row + DECLARE + iCounter $table.id%TYPE; + BEGIN + if INSERTING THEN + Select $seq.nextval INTO iCounter FROM Dual; + :new.id := iCounter; + END IF; + END; + / + ); + + my @in_array1 = ( 'one', 'two', 'three', 'four', 'five' ); + my @in_array2 = ( '5', '4', '3', '2', '1' ); + my @out_array; + my @tuple_status; + + my $sql = + "insert into $table (name, value) values (?,?) returning id into ?"; + + my $sth = $dbh->prepare($sql); + + $sth->bind_param_array( 1, \@in_array1 ); + $sth->bind_param_array( 2, \@in_array2 ); + ok( + $sth->bind_param_inout_array( + 3, \@out_array, 0, { ora_type => ORA_VARCHAR2 } + ), + '... bind_param_inout_array should return false' + ); + + ok( $sth->execute_array( { ArrayTupleStatus => \@tuple_status } ), + '... execute_array should return false' ); + + cmp_ok( scalar(@tuple_status), '==', 5, + '... we should have 19 tuple_status' ); + cmp_ok( scalar(@out_array), '==', 5, '... we should have 5 out_array' ); + cmp_ok( $out_array[0], '==', 1, '... out values should match 1' ); + cmp_ok( $out_array[1], '==', 2, '... out values should match 2' ); + cmp_ok( $out_array[2], '==', 3, '... out values should match 3' ); + cmp_ok( $out_array[3], '==', 4, '... out values should match 3' ); + cmp_ok( $out_array[4], '==', 5, '... out values should match 5' ); + + $dbh->do("drop table $table") or warn $dbh->errstr; + $dbh->do("drop sequence $seq") or die $dbh->errstr; + } -sub test_number_SP($){ - my $dbh=shift; - $dbh->do(" - create or replace procedure tox_test_proc0( - result in out varchar2, - ids in SYS.dbms_sql.number_table - ) - as - begin - result := ''; - for i in 1..ids.count loop - result := result || to_char(ids(i)); - end loop; - end; - - - - "); - - my $sth = $dbh->prepare("begin tox_test_proc0( ?, ?); end;"); - - - my $result = ""; - my @array = (1, 2, 3, 4, 7); - - $sth->bind_param_inout(1, \$result, 5); - ok ($sth->bind_param(2, \@array, { ora_type => ORA_NUMBER_TABLE, ora_internal_type => SQLT_INT }),'... bind_param_inout_array should bind 12345'); - $sth->execute() ; - cmp_ok($result, '==','12347' , '... we should have 12347 out string'); - - @array = (3, 4, 5); - - $sth->bind_param_inout(1, \$result, 3); - ok ($sth->bind_param(2, \@array, { ora_type => ORA_NUMBER_TABLE, ora_internal_type => SQLT_INT }),'... bind_param_inout_array should bind 345'); - $sth->execute() ; - cmp_ok($result, '==','345' , '... we should have 345 out string'); - - $dbh->do("drop procedure tox_test_proc0") or warn $dbh->errstr; - +# FIXME this is orphaned? See https://github.com/pythian/DBD-Oracle/issues/64 +sub test_number_SP { + my $dbh = shift; + $dbh->do( + <<'EOF' + create or replace procedure tox_test_proc0( + result in out varchar2, + ids in SYS.dbms_sql.number_table + ) + as + begin + result := ''; + for i in 1..ids.count loop + result := result || to_char(ids(i)); + end loop; + end; +EOF + ); + + my $sth = $dbh->prepare('begin tox_test_proc0( ?, ?); end;'); + + my $result = ''; + my @array = ( 1, 2, 3, 4, 7 ); + + $sth->bind_param_inout( 1, \$result, 5 ); + ok( + $sth->bind_param( + 2, \@array, + { ora_type => ORA_NUMBER_TABLE, ora_internal_type => SQLT_INT } + ), + '... bind_param_inout_array should bind 12345' + ); + $sth->execute(); + cmp_ok( $result, '==', '12347', '... we should have 12347 out string' ); + + @array = ( 3, 4, 5 ); + + $sth->bind_param_inout( 1, \$result, 3 ); + ok( + $sth->bind_param( + 2, \@array, + { ora_type => ORA_NUMBER_TABLE, ora_internal_type => SQLT_INT } + ), + '... bind_param_inout_array should bind 345' + ); + $sth->execute(); + cmp_ok( $result, '==', '345', '... we should have 345 out string' ); + + $dbh->do('drop procedure tox_test_proc0') or warn $dbh->errstr; + } + SKIP: { $dbh = db_connect(0); if ($dbh) { plan tests => 15; - } else { - plan skip_all => "Unable to connect to Oracle" if not $dbh; + } + else { + plan skip_all => 'Unable to connect to Oracle' if not $dbh; } test_varchar2_table_3_tests($dbh); test_number_table_3_tests($dbh); test_inout_array_tests($dbh); - -}; -END { - eval { - local $dbh->{PrintError} = 0; - }; } +END { + eval { local $dbh->{PrintError} = 0; }; +} -+1; +1; diff --git a/t/30long.t b/t/30long.t index cc1020df..dfb0df4f 100644 --- a/t/30long.t +++ b/t/30long.t @@ -1,63 +1,70 @@ +#!perl + use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ table drop_table oracle_test_dsn db_handle + show_db_charsets long_test_cols create_table + cmp_ok_byte_nice db_ochar_is_utf client_ochar_is_utf8 + nice_string db_nchar_is_utf client_nchar_is_utf8 +/; use DBI; use DBD::Oracle qw(:ora_types SQLCS_NCHAR SQLCS_IMPLICIT ORA_OCI); use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - -*BAILOUT = sub { die "@_\n" } unless defined &BAILOUT; +*BAILOUT = sub { die "@_\n" } + unless defined &BAILOUT; my @test_sets = ( - [ "LONG", 0, 0 ], - [ "LONG RAW", ORA_LONGRAW, 0 ], - [ "CLOB", ORA_CLOB, 0 ], - [ "BLOB", ORA_BLOB, 0 ], + [ 'LONG', 0, 0 ], + [ 'LONG RAW', ORA_LONGRAW, 0 ], + [ 'CLOB', ORA_CLOB, 0 ], + [ 'BLOB', ORA_BLOB, 0 ], ); -push @test_sets, [ "NCLOB", ORA_CLOB, 0 ] unless ORA_OCI() < 9.0 or $ENV{DBD_ALL_TESTS}; +push @test_sets, [ 'NCLOB', ORA_CLOB, 0 ] + unless ORA_OCI() < 9.0 or $ENV{DBD_ALL_TESTS}; - -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $table = table(); -my $use_utf8_data; # set per test_set below +my $use_utf8_data; # set per test_set below my %warnings; my @skip_unicode; -push @skip_unicode, "Perl < 5.6 " if $] < 5.006; -push @skip_unicode, "Oracle client < 9.0 " if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; +push @skip_unicode, 'Perl < 5.6 ' if $] < 5.006; +push @skip_unicode, 'Oracle client < 9.0 ' + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; # Set size of test data (in 10KB units) -# Minimum value 3 (else tests fail because of assumptions) -# Normal value 8 (to test old 64KB threshold well) +# Minimum value 3 (else tests fail because of assumptions) +# Normal value 8 (to test old 64KB threshold well) my $sz = 8; -my($p1, $p2, $tmp, @tmp); - -$dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my ( $p1, $p2, $tmp, @tmp ); -my $dbh = DBI->connect( oracle_test_dsn(), $dbuser, '', { - PrintError => 0, -}) or plan skip_all => "Unable to connect to Oracle"; +my $dbh = db_handle( { PrintError => 0 } ) + or plan skip_all => 'Unable to connect to Oracle'; my $tests_per_set = 97; -my $ora_server_version = $dbh->func("ora_server_version"); +my $ora_server_version = $dbh->func('ora_server_version'); show_db_charsets($dbh); foreach (@test_sets) { - my ($type_name, $type_num, $test_no_type) = @$_; + my ( $type_name, $type_num, $test_no_type ) = @$_; subtest $type_name => sub { plan tests => $tests_per_set; - $use_utf8_data = use_utf8_data($dbh,$type_name); - note( qq( - ========================================================================= - Running long test for $type_name ($type_num) use_utf8_data=$use_utf8_data - )); - run_long_tests($dbh, $type_name, $type_num); - run_long_tests($dbh, $type_name, 0) if $test_no_type; - } + $use_utf8_data = use_utf8_data( $dbh, $type_name ); + note( + qq( + ========================================================================= + Running long test for $type_name ($type_num) use_utf8_data=$use_utf8_data + ) + ); + run_long_tests( $dbh, $type_name, $type_num ); + run_long_tests( $dbh, $type_name, 0 ) if $test_no_type; + } } done_testing(); @@ -65,420 +72,496 @@ done_testing(); ### END OF TESTS, ONLY FUNCTIONS BELOW ### END { - drop_table( $dbh ) if not $ENV{DBD_SKIP_TABLE_DROP}; - $dbh->disconnect if $dbh; + eval{ drop_table($dbh) } } - sub use_utf8_data { my ( $dbh, $type_name ) = @_; - return 0 - unless ($type_name =~ m/^CLOB/i and db_ochar_is_utf($dbh) && client_ochar_is_utf8()) - or ($type_name =~ m/^NCLOB/i and db_nchar_is_utf($dbh) && client_nchar_is_utf8()); + return 0 + unless ( $type_name =~ m/^CLOB/i + and db_ochar_is_utf($dbh) && client_ochar_is_utf8() ) + or ( $type_name =~ m/^NCLOB/i + and db_nchar_is_utf($dbh) && client_nchar_is_utf8() ); return 1 unless @skip_unicode; - warn "Skipping Unicode data tests: @skip_unicode\n" if !$warnings{use_utf8_data}++; + warn "Skipping Unicode data tests: @skip_unicode\n" + if !$warnings{use_utf8_data}++; } -sub run_long_tests -{ - my ($dbh, $type_name, $type_num) = @_; +sub run_long_tests { + my ( $dbh, $type_name, $type_num ) = @_; my ($sth); my $append_len; - SKIP: - { #it all + SKIP: + { #it all # relationships between these lengths are important # e.g. my %long_data; my @long_data; - $long_data[2] = ("2bcdefabcd" x 1024) x ($sz-1); # 70KB > 64KB && < long_data1 - $long_data[1] = ("1234567890" x 1024) x ($sz ); # 80KB >> 64KB && > long_data2 - $long_data[0] = ("0\177x\0X" x 2048) x (1 ); # 10KB < 64KB - - if ( $use_utf8_data ) { # make $long_data0 be UTF8 - my $utf_x = "0\x{263A}xyX"; #lab: the ubiquitous smiley face - $long_data[0] = ($utf_x x 2048) x (1 ); # 10KB < 64KB - if (length($long_data[0]) > 10240) { - note "known bug in perl5.6.0 utf8 support, applying workaround\n"; - my $utf_z = "0\x{263A}xyZ" ; + $long_data[2] = + ( '2bcdefabcd' x 1024 ) x ( $sz - 1 ); # 70KB > 64KB && < long_data1 + $long_data[1] = + ( '1234567890' x 1024 ) x ($sz); # 80KB >> 64KB && > long_data2 + $long_data[0] = ( "0\177x\0X" x 2048 ) x (1); # 10KB < 64KB + + if ($use_utf8_data) { # make $long_data0 be UTF8 + my $utf_x = "0\x{263A}xyX"; #lab: the ubiquitous smiley face + $long_data[0] = ( $utf_x x 2048 ) x (1); # 10KB < 64KB + if ( length( $long_data[0] ) > 10240 ) { + note + "known bug in perl5.6.0 utf8 support, applying workaround\n"; + my $utf_z = "0\x{263A}xyZ"; $long_data[0] = $utf_z; - $long_data[0] .= $utf_z foreach (1..2047); + $long_data[0] .= $utf_z foreach ( 1 .. 2047 ); } - if ($type_name eq 'BLOB') { + if ( $type_name eq 'BLOB' ) { + # convert string from utf-8 to byte encoding XXX - $long_data[0] = pack "C*", (unpack "C*", $long_data[0]); + $long_data[0] = pack 'C*', ( unpack 'C*', $long_data[0] ); } } - my $be_utf8 = ($type_name eq 'BLOB') ? 0 - : ($type_name eq 'CLOB') ? client_ochar_is_utf8() - : ($type_name eq 'NCLOB') ? client_nchar_is_utf8() - : 0; # XXX umm, what about LONGs? + my $be_utf8 = + ( $type_name eq 'BLOB' ) ? 0 + : ( $type_name eq 'CLOB' ) ? client_ochar_is_utf8() + : ( $type_name eq 'NCLOB' ) ? client_nchar_is_utf8() + : 0; # XXX umm, what about LONGs? # special hack for long_data[0] since RAW types need pairs of HEX - $long_data[0] = "00FF" x (length($long_data[0]) / 2) if $type_name =~ /RAW/i; + $long_data[0] = '00FF' x ( length( $long_data[0] ) / 2 ) + if $type_name =~ /RAW/i; - my @len_data = map { length($_) } @long_data; + my @len_data = map { length($_) } @long_data; # warn if some of the key aspects of the data sizing are tampered with warn "long_data[0] is > 64KB: $len_data[0]\n" - if $len_data[0] > 65535; + if $len_data[0] > 65535; warn "long_data[1] is < 64KB: $len_data[1]\n" - if $len_data[1] < 65535; - warn "long_data[2] is not smaller than $long_data[1] ($len_data[2] > $len_data[1])\n" - if $len_data[2] >= $len_data[1]; + if $len_data[1] < 65535; + warn +"long_data[2] is not smaller than $long_data[1] ($len_data[2] > $len_data[1])\n" + if $len_data[2] >= $len_data[1]; my $tdata = { - cols => long_test_cols( $type_name ), + cols => long_test_cols($type_name), rows => [] }; - skip "Unable to create test table for '$type_name' data ($DBI::err)." ,$tests_per_set - if (!create_table($dbh, $tdata, 1)); - # typically OCI 8 client talking to Oracle 7 database + skip "Unable to create test table for '$type_name' data ($DBI::err).", + $tests_per_set + if ( !create_table( $dbh, $tdata, 1 ) ); + + # typically OCI 8 client talking to Oracle 7 database note(" --- insert some $type_name data (ora_type $type_num)\n"); - my $sqlstr = "insert into $table values (?, ?, SYSDATE)" ; - ok( $sth = $dbh->prepare( $sqlstr ), "prepare: $sqlstr" ); + my $sqlstr = "insert into $table values (?, ?, SYSDATE)"; + ok( $sth = $dbh->prepare($sqlstr), "prepare: $sqlstr" ); my $bind_attr = { ora_type => $type_num }; - # The explicit SQLCS_IMPLICIT is needed in some odd cases - $bind_attr->{ora_csform} = ($type_name =~ /^NCLOB/) ? SQLCS_NCHAR : SQLCS_IMPLICIT; - $sth->bind_param(2, undef, $bind_attr ) - or die "$type_name: $DBI::errstr" if $type_num; + # The explicit SQLCS_IMPLICIT is needed in some odd cases + $bind_attr->{ora_csform} = + ( $type_name =~ /^NCLOB/ ) ? SQLCS_NCHAR : SQLCS_IMPLICIT; + + $sth->bind_param( 2, undef, $bind_attr ) + or die "$type_name: $DBI::errstr" + if $type_num; - ok($sth->execute(40, $long_data{40} = $long_data[0] ), "insert long data 40" ); - ok($sth->execute(41, $long_data{41} = $long_data[1] ), "insert long data 41" ); - ok($sth->execute(42, $long_data{42} = $long_data[2] ), "insert long data 42" ); - ok($sth->execute(43, $long_data{43} = undef), "insert long data undef 43" ); # NULL + ok( $sth->execute( 40, $long_data{40} = $long_data[0] ), + 'insert long data 40' ); + ok( $sth->execute( 41, $long_data{41} = $long_data[1] ), + 'insert long data 41' ); + ok( $sth->execute( 42, $long_data{42} = $long_data[2] ), + 'insert long data 42' ); + ok( $sth->execute( 43, $long_data{43} = undef ), + 'insert long data undef 43' ); # NULL array_test($dbh); - note(" --- fetch $type_name data back again -- truncated - LongTruncOk == 1\n"); + note( +" --- fetch $type_name data back again -- truncated - LongTruncOk == 1\n" + ); $dbh->{LongReadLen} = 20; - $dbh->{LongTruncOk} = 1; - note("LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"); + $dbh->{LongTruncOk} = 1; + note( + "LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n" + ); # This behaviour isn't specified anywhere, sigh: my $out_len = $dbh->{LongReadLen}; - $out_len *= 2 if ($type_name =~ /RAW/i); + $out_len *= 2 if ( $type_name =~ /RAW/i ); $sqlstr = "select * from $table order by idx"; - ok($sth = $dbh->prepare($sqlstr), "prepare: $sqlstr" ); + ok( $sth = $dbh->prepare($sqlstr), "prepare: $sqlstr" ); $sth->trace(0); - ok($sth->execute, "execute: $sqlstr" ); - ok($tmp = $sth->fetchall_arrayref, "fetch_arrayref for $sqlstr" ); + ok( $sth->execute, "execute: $sqlstr" ); + ok( $tmp = $sth->fetchall_arrayref, "fetch_arrayref for $sqlstr" ); $sth->trace(0); - SKIP: { - if ($DBI::err && $DBI::errstr =~ /ORA-01801:/) { + SKIP: { + if ( $DBI::err && $DBI::errstr =~ m/ORA-01801:/ ) { + # ORA-01801: date format is too long for internal buffer - skip " If you're using Oracle <= 8.1.7 then this error is probably\n" - ." due to an Oracle bug and not a DBD::Oracle problem.\n" , 5 ; + skip +" If you're using Oracle <= 8.1.7 then this error is probably\n" + . " due to an Oracle bug and not a DBD::Oracle problem.\n", 5; + } + cmp_ok( @$tmp, '==', 4, 'four rows' ); + + for my $i ( 0 .. 2 ) { + my $v = $tmp->[$i][1]; + cmp_ok_byte_nice( + $v, + substr( $long_data[$i], 0, $out_len ), + "truncated to LongReadLen $out_len" + ); + if ( $type_name eq 'BLOB' ) { + ok( !utf8::is_utf8($v), 'BLOB non-UTF8' ); + } + else { + # allow result to have UTF8 flag even if source data didn't + # (not ideal but would need better test data) + ok( utf8::is_utf8($v) >= utf8::is_utf8( $long_data[$i] ), + "$type_name UTF8 setting" ); + } } - cmp_ok(@$tmp ,'==' ,4 ,'four rows' ); - - for my $i (0..2) { - my $v = $tmp->[$i][1]; - cmp_ok_byte_nice($v, substr($long_data[$i],0,$out_len), "truncated to LongReadLen $out_len"); - if ($type_name eq 'BLOB') { - ok( !utf8::is_utf8($v), "BLOB non-UTF8"); - } - else { - # allow result to have UTF8 flag even if source data didn't - # (not ideal but would need better test data) - ok( utf8::is_utf8($v) >= utf8::is_utf8($long_data[$i]), - "$type_name UTF8 setting"); - } - } - ok(!defined $tmp->[3][1], "last row undefined"); # NULL # known bug in DBD::Oracle <= 1.13 + ok( !defined $tmp->[3][1], 'last row undefined' ) + ; # NULL # known bug in DBD::Oracle <= 1.13 } - note(" --- fetch $type_name data back again -- truncated - LongTruncOk == 0\n"); + note( +" --- fetch $type_name data back again -- truncated - LongTruncOk == 0\n" + ); - $dbh->{LongReadLen} = $len_data[1] - 10; # so $long_data[0] fits but long_data[1] doesn't - $dbh->{LongReadLen} /= 2 if $type_name =~ /RAW/i; + $dbh->{LongReadLen} = + $len_data[1] - 10; # so $long_data[0] fits but long_data[1] doesn't + $dbh->{LongReadLen} /= 2 if $type_name =~ m/RAW/i; $dbh->{LongTruncOk} = 0; - note "LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"; + note + "LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"; $sqlstr = "select * from $table order by idx"; ok $sth = $dbh->prepare($sqlstr), "prepare $sqlstr"; ok $sth->execute, "execute $sqlstr"; ok $tmp = $sth->fetchrow_arrayref, "fetchrow_arrayref $sqlstr"; - ok $tmp->[1] eq $long_data[0], "length tmp->[1] ".length($tmp->[1]); + ok $tmp->[1] eq $long_data[0], "length tmp->[1] " . length( $tmp->[1] ); { local $sth->{PrintError} = 0; - ok(!defined $sth->fetchrow_arrayref, - "truncation error not triggered " - ."(LongReadLen $dbh->{LongReadLen}, data ".length($tmp->[1]||0).")"); + ok( + !defined $sth->fetchrow_arrayref, + 'truncation error not triggered ' + . "(LongReadLen $dbh->{LongReadLen}, data " + . length( $tmp->[1] || 0 ) . ")" + ); $tmp = $sth->err || 0; - ok( ($tmp == 1406 || $tmp == 24345) ,"tmp==1406 || tmp==24345 tmp actually=$tmp" ); + ok( + ( $tmp == 1406 || $tmp == 24345 ), + "tmp==1406 || tmp==24345 tmp actually=$tmp" + ); } - $sth->finish; + $sth->finish; - note(" --- fetch $type_name data back again -- complete - LongTruncOk == 0\n"); - $dbh->{LongReadLen} = $len_data[1] +1000; + note( +" --- fetch $type_name data back again -- complete - LongTruncOk == 0\n" + ); + $dbh->{LongReadLen} = $len_data[1] + 1000; $dbh->{LongTruncOk} = 0; - note("LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n"); + note( + "LongReadLen $dbh->{LongReadLen}, LongTruncOk $dbh->{LongTruncOk}\n" + ); $sqlstr = "select * from $table order by idx"; - ok($sth = $dbh->prepare($sqlstr), "prepare: $sqlstr" ); - ok($sth->execute, "execute $sqlstr" ); - - for my $i (0..2) { - my $result = $sth->fetchrow_arrayref; - ok $result, "fetchrow_arrayref $sqlstr"; - is $result->[1] => $long_data[$i], - cdif($result->[1],$long_data[$i], "Len ".length($result->[1])) ; - } - $sth->finish; - + ok( $sth = $dbh->prepare($sqlstr), "prepare: $sqlstr" ); + ok( $sth->execute, "execute $sqlstr" ); + + for my $i ( 0 .. 2 ) { + my $result = $sth->fetchrow_arrayref; + ok $result, "fetchrow_arrayref $sqlstr"; + is $result->[1] => $long_data[$i], + cdif( $result->[1], $long_data[$i], + "Len " . length( $result->[1] ) ); + } + $sth->finish; - SKIP: { - skip "blob_read tests for LONGs - not currently supported", 15 - if $type_name =~ /LONG/i; + SKIP: { + skip 'blob_read tests for LONGs - not currently supported', 15 + if $type_name =~ /LONG/i; #$dbh->trace(4); note(" --- fetch $type_name data back again -- via blob_read\n\n"); $dbh->{LongReadLen} = 1024 * 90; - $dbh->{LongTruncOk} = 1; + $dbh->{LongTruncOk} = 1; $sqlstr = "select idx, lng, dt from $table order by idx"; - ok($sth = $dbh->prepare($sqlstr) ,"prepare $sqlstr" ); - ok($sth->execute, "execute $sqlstr" ); - - - note("fetch via fetchrow_arrayref\n"); - ok($tmp = $sth->fetchrow_arrayref, "fetchrow_arrayref 1: $sqlstr" ); - cmp_ok_byte_nice($tmp->[1], $long_data[0], "truncated to LongReadLen $out_len"); - - note("read via blob_read_all\n"); - cmp_ok(blob_read_all($sth, 1, \$p1, 4096) ,'==', length($long_data[0]), - "blob_read_all = length(\$long_data[0])" ); - ok($p1 eq $long_data[0], cdif($p1, $long_data[0]) ); - $sth->trace(0); - - - ok($tmp = $sth->fetchrow_arrayref, "fetchrow_arrayref 2: $sqlstr" ); - cmp_ok(blob_read_all($sth, 1, \$p1, 12345) ,'==', length($long_data[1]), - "blob_read_all = length(long_data[1])" ); - ok($p1 eq $long_data[1], cdif($p1, $long_data[1]) ); - - - ok($tmp = $sth->fetchrow_arrayref, "fetchrow_arrayref 3: $sqlstr" ); - my $len = blob_read_all($sth, 1, \$p1, 34567); - - cmp_ok($len,'==', length($long_data[2]), "length of long_data[2] = $len" ); - cmp_ok_byte_nice($p1, $long_data[2], "3rd row via blob_read_all"); - - note("result is ".(utf8::is_utf8($p1) ? "UTF8" : "non-UTF8")."\n"); - - if ($be_utf8) { - ok( utf8::is_utf8($p1), "result should be utf8"); - } - else { - ok( !utf8::is_utf8($p1), "result should not be utf8"); - } - } #skip - + ok( $sth = $dbh->prepare($sqlstr), "prepare $sqlstr" ); + ok( $sth->execute, "execute $sqlstr" ); + + note("fetch via fetchrow_arrayref\n"); + ok( $tmp = $sth->fetchrow_arrayref, + "fetchrow_arrayref 1: $sqlstr" ); + cmp_ok_byte_nice( $tmp->[1], $long_data[0], + "truncated to LongReadLen $out_len" ); + + note("read via blob_read_all\n"); + cmp_ok( + blob_read_all( $sth, 1, \$p1, 4096 ), + '==', + length( $long_data[0] ), + "blob_read_all = length(\$long_data[0])" + ); + ok( $p1 eq $long_data[0], cdif( $p1, $long_data[0] ) ); + $sth->trace(0); + + ok( $tmp = $sth->fetchrow_arrayref, + "fetchrow_arrayref 2: $sqlstr" ); + cmp_ok( + blob_read_all( $sth, 1, \$p1, 12345 ), + '==', + length( $long_data[1] ), + "blob_read_all = length(long_data[1])" + ); + ok( $p1 eq $long_data[1], cdif( $p1, $long_data[1] ) ); + + ok( $tmp = $sth->fetchrow_arrayref, + "fetchrow_arrayref 3: $sqlstr" ); + my $len = blob_read_all( $sth, 1, \$p1, 34567 ); + + cmp_ok( + $len, '==', + length( $long_data[2] ), + "length of long_data[2] = $len" + ); + cmp_ok_byte_nice( $p1, $long_data[2], "3rd row via blob_read_all" ); + + note( "result is " + . ( utf8::is_utf8($p1) ? "UTF8" : "non-UTF8" ) + . "\n" ); + + if ($be_utf8) { + ok( utf8::is_utf8($p1), 'result should be utf8' ); + } + else { + ok( !utf8::is_utf8($p1), 'result should not be utf8' ); + } + } #skip - SKIP: { - skip( "ora_auto_lob tests for $type_name" ."s - not supported", 49 ) - if not ( $type_name =~ /LOB/i ); + SKIP: { + skip( "ora_auto_lob tests for $type_name" . "s - not supported", + 49 ) + unless ( $type_name =~ /LOB/i ); - note(" --- testing ora_auto_lob to access $type_name LobLocator\n\n"); - my $data_fmt = "%03d foo!"; + note(" --- testing ora_auto_lob to access $type_name LobLocator\n\n" + ); + my $data_fmt = '%03d foo!'; $sqlstr = qq{ SELECT lng, idx FROM $table ORDER BY idx FOR UPDATE -- needed so lob locator is writable }; - my $ll_sth = $dbh->prepare($sqlstr, { ora_auto_lob => 0 } ); # 0: get lob locator instead of lob contents + my $ll_sth = $dbh->prepare( $sqlstr, { ora_auto_lob => 0 } ) + ; # 0: get lob locator instead of lob contents - ok $ll_sth ,"prepare $sqlstr"; + ok $ll_sth , "prepare $sqlstr"; - ok $ll_sth->execute ,"execute $sqlstr"; + ok $ll_sth->execute, "execute $sqlstr"; - while (my ($lob_locator, $idx) = $ll_sth->fetchrow_array) { - note("$idx: ".DBI::neat($lob_locator)."\n"); + while ( my ( $lob_locator, $idx ) = $ll_sth->fetchrow_array ) { + note( "$idx: " . DBI::neat($lob_locator) . "\n" ); last if !defined($lob_locator) && $idx == 43; ok $lob_locator, '$lob_locator is true'; - is ref $lob_locator => 'OCILobLocatorPtr', '$lob_locator is a OCILobLocatorPtr'; - ok( (ref $lob_locator and $$lob_locator), '$lob_locator deref ptr is true' ); - + is ref $lob_locator => 'OCILobLocatorPtr', + '$lob_locator is a OCILobLocatorPtr'; + ok( + ( ref $lob_locator and $$lob_locator ), + '$lob_locator deref ptr is true' + ); + # check ora_lob_chunk_size: - my $chunk_size = $dbh->func($lob_locator, 'ora_lob_chunk_size'); - ok !$DBI::err, "DBI::errstr"; - - my $data = sprintf $data_fmt, $idx; #create a little data + my $chunk_size = + $dbh->func( $lob_locator, 'ora_lob_chunk_size' ); + ok !$DBI::err, 'DBI::errstr'; - note("length of data to be written at offset 1: " .length($data) ."\n" ); - ok($dbh->func($lob_locator, 1, $data, 'ora_lob_write') ,"ora_lob_write" ); + my $data = sprintf $data_fmt, $idx; #create a little data + + note( 'length of data to be written at offset 1: ' + . length($data) + . "\n" ); + ok( $dbh->func( $lob_locator, 1, $data, 'ora_lob_write' ), + 'ora_lob_write' ); } - is($ll_sth->rows, 4); + is( $ll_sth->rows, 4 ); - note(" --- round again to check contents after $type_name write updates...\n"); - ok($ll_sth->execute,"execute (again 1) $sqlstr" ); - while (my ($lob_locator, $idx) = $ll_sth->fetchrow_array) { - note("$idx locator: ".DBI::neat($lob_locator)."\n"); + note( +" --- round again to check contents after $type_name write updates...\n" + ); + ok( $ll_sth->execute, "execute (again 1) $sqlstr" ); + while ( my ( $lob_locator, $idx ) = $ll_sth->fetchrow_array ) { + note( "$idx locator: " . DBI::neat($lob_locator) . "\n" ); next if !defined($lob_locator) && $idx == 43; - diag("DBI::errstr=$DBI::errstr\n") if $DBI::err ; - - my $content = $dbh->func($lob_locator, 1, 20, 'ora_lob_read'); - diag("DBI::errstr=$DBI::errstr\n") if $DBI::err ; - ok($content,"content is true" ); - note("$idx content: ".nice_string($content)."\n"); #.DBI::neat($content)."\n"; - cmp_ok(length($content) ,'==', 20 ,"lenth(content)" ); - - # but prefix has been overwritten: - my $data = sprintf $data_fmt, $idx; - ok(substr($content,0,length($data)) eq $data ,"length(content)=length(data)" ); - - # ora_lob_length agrees: - my $len = $dbh->func($lob_locator, 'ora_lob_length'); - ok(!$DBI::err ,"DBI::errstr" ); - cmp_ok($len ,'==', length($long_data{$idx}) ,"length(long_data{idx}) = length of locator data" ); - - # now trim the length - $dbh->func($lob_locator, $idx, 'ora_lob_trim'); - ok(!$DBI::err, "DBI::errstr" ); - - # and append some text - SKIP: { - $append_len = 0; - skip( "ora_lob_append() not reliable in Oracle 8 (Oracle bug #886191)", 1 ) - if ORA_OCI() < 9 or $ora_server_version->[0] < 9; - - my $append_data = "12345"; - $append_len = length($append_data); - $dbh->func($lob_locator, $append_data, 'ora_lob_append'); - ok(!$DBI::err ,"ora_lob_append DBI::errstr" ); - # XXX ought to test data was actually appended - } - - } #while fetchrow - is($ll_sth->rows, 4); + diag("DBI::errstr=$DBI::errstr\n") if $DBI::err; + + my $content = $dbh->func( $lob_locator, 1, 20, 'ora_lob_read' ); + diag("DBI::errstr=$DBI::errstr\n") if $DBI::err; + ok( $content, 'content is true' ); + note( "$idx content: " . nice_string($content) . "\n" ) + ; #.DBI::neat($content)."\n"; + cmp_ok( length($content), '==', 20, 'lenth(content)' ); + + # but prefix has been overwritten: + my $data = sprintf $data_fmt, $idx; + ok( substr( $content, 0, length($data) ) eq $data, + 'length(content)=length(data)' ); + + # ora_lob_length agrees: + my $len = $dbh->func( $lob_locator, 'ora_lob_length' ); + ok( !$DBI::err, 'DBI::errstr' ); + cmp_ok( + $len, '==', + length( $long_data{$idx} ), + 'length(long_data{idx}) = length of locator data' + ); + + # now trim the length + $dbh->func( $lob_locator, $idx, 'ora_lob_trim' ); + ok( !$DBI::err, 'DBI::errstr' ); + + # and append some text + SKIP: { + $append_len = 0; + skip( +'ora_lob_append() not reliable in Oracle 8 (Oracle bug #886191)', + 1 + ) + if ORA_OCI() < 9 + or $ora_server_version->[0] < 9; + + my $append_data = '12345'; + $append_len = length($append_data); + $dbh->func( $lob_locator, $append_data, 'ora_lob_append' ); + ok( !$DBI::err, 'ora_lob_append DBI::errstr' ); + + # XXX ought to test data was actually appended + } + + } #while fetchrow + is( $ll_sth->rows, 4 ); note(" --- round again to check the $type_name length...\n"); - ok($ll_sth->execute ,"execute (again 2) $sqlstr" ); - while (my ($lob_locator, $idx) = $ll_sth->fetchrow_array) { - note("$idx locator: ".DBI::neat($lob_locator)."\n"); - next if !defined($lob_locator) && $idx == 43; - my $len = $dbh->func($lob_locator, 'ora_lob_length'); - #lab: possible logic error here w/resp. to len - ok(!$DBI::err ,"DBI::errstr" ); - cmp_ok( $len ,'==', $idx + $append_len ,"len == idx+5" ); - } - is($ll_sth->rows, 4); - - } #skip for LONG types + ok( $ll_sth->execute, "execute (again 2) $sqlstr" ); + while ( my ( $lob_locator, $idx ) = $ll_sth->fetchrow_array ) { + note( "$idx locator: " . DBI::neat($lob_locator) . "\n" ); + next if !defined($lob_locator) && $idx == 43; + my $len = $dbh->func( $lob_locator, 'ora_lob_length' ); - } #skip it all (tests_per_set) + #lab: possible logic error here w/resp. to len + ok( !$DBI::err, 'DBI::errstr' ); + cmp_ok( $len, '==', $idx + $append_len, 'len == idx+5' ); + } + is( $ll_sth->rows, 4 ); - $sth->finish if $sth; - drop_table( $dbh ) + } #skip for LONG types -} # end of run_long_tests + } #skip it all (tests_per_set) + $sth->finish if $sth; + drop_table($dbh); +} # end of run_long_tests sub array_test { my ($dbh) = @_; - return 0; # XXX disabled + return 0; # FIXME disabled eval { - $dbh->{RaiseError}=1; - $dbh->trace(0); - my $sth = $dbh->prepare(qq{ - UPDATE $table set idx=idx+1 RETURNING idx INTO ? - }); - my ($a,$b); - $a = []; - $sth->bind_param_inout(1,\$a, 2); - $sth->execute; - note("a=$a\n"); - note("a=@$a\n"); + $dbh->{RaiseError} = 1; + $dbh->trace(0); + my $sth = $dbh->prepare( + qq{ + UPDATE $table set idx=idx+1 RETURNING idx INTO ? + } + ); + my ( $a, $b ); + $a = []; + $sth->bind_param_inout( 1, \$a, 2 ); + $sth->execute; + note("a=$a\n"); + note("a=@$a\n"); }; die "RETURNING array: $@"; } - -sub print_substrs -{ - my ($dbh,$len) = @_; - my $tsql = "select substr(lng,1,$len),idx from $table order by idx" ; - diag("-- prepare: $tsql\n") ; - my $tsth = $dbh->prepare( $tsql ); +sub print_substrs { + my ( $dbh, $len ) = @_; + my $tsql = "select substr(lng,1,$len),idx from $table order by idx"; + diag("-- prepare: $tsql\n"); + my $tsth = $dbh->prepare($tsql); $tsth->execute(); - while ( my ( $d,$i ) = $tsth->fetchrow_array() ) - { + while ( my ( $d, $i ) = $tsth->fetchrow_array() ) { last if not defined $d; diag("$i: $d\n"); } } -sub print_lengths -{ +sub print_lengths { my ($dbh) = @_; - my $tsql = "select length(lng),idx from $table order by idx" ; + my $tsql = "select length(lng),idx from $table order by idx"; diag("-- prepare: $tsql\n"); - my $tsth = $dbh->prepare( $tsql ); + my $tsth = $dbh->prepare($tsql); $tsth->execute(); - while ( my ( $l,$i ) = $tsth->fetchrow_array() ) - { + while ( my ( $l, $i ) = $tsth->fetchrow_array() ) { last if not defined $l; diag("$i: $l\n"); } } - sub blob_read_all { - my ($sth, $field_idx, $blob_ref, $lump) = @_; + my ( $sth, $field_idx, $blob_ref, $lump ) = @_; - $lump ||= 4096; # use benchmarks to get best value for you + $lump ||= 4096; # use benchmarks to get best value for you my $offset = 0; my @frags; while (1) { - my $frag = $sth->blob_read($field_idx, $offset, $lump); - last unless defined $frag; - my $len = length $frag; - last unless $len; - push @frags, $frag; - $offset += $len; - #print "blob_read_all: offset $offset, len $len\n"; + my $frag = $sth->blob_read( $field_idx, $offset, $lump ); + last unless defined $frag; + my $len = length $frag; + last unless $len; + push @frags, $frag; + $offset += $len; + + #print "blob_read_all: offset $offset, len $len\n"; } - $$blob_ref = join "", @frags; + $$blob_ref = join q||, @frags; return length($$blob_ref); } sub unc { my @str = @_; foreach (@str) { s/([\000-\037\177-\377])/ sprintf "\\%03o", ord($_) /eg; } - return join "", @str unless wantarray; + return join q(), @str unless wantarray; return @str; } sub cdif { - my ($s1, $s2, $msg) = @_; - $msg = ($msg) ? ", $msg" : ""; - my ($l1, $l2) = (length($s1), length($s2)); + my ( $s1, $s2, $msg ) = @_; + $msg = ($msg) ? ", $msg" : q(); + my ( $l1, $l2 ) = ( length($s1), length($s2) ); return "Strings are identical$msg" if $s1 eq $s2; - return "Strings are of different lengths ($l1 vs $l2)$msg" # check substr matches? - if $l1 != $l2; + return + "Strings are of different lengths ($l1 vs $l2)$msg" # check substr matches? + if $l1 != $l2; my $i; - for($i=0; $i < $l1; ++$i) { - my ($c1,$c2) = (ord(substr($s1,$i,1)), ord(substr($s2,$i,1))); - next if $c1 == $c2; + for ( $i = 0 ; $i < $l1 ; ++$i ) { + my ( $c1, $c2 ) = + ( ord( substr( $s1, $i, 1 ) ), ord( substr( $s2, $i, 1 ) ) ); + next if $c1 == $c2; return sprintf "Strings differ at position %d (\\%03o vs \\%03o)$msg", - $i,$c1,$c2; + $i, $c1, $c2; } return "(cdif error $l1/$l2/$i)"; } - __END__ diff --git a/t/31lob.t b/t/31lob.t index 685ac672..ba785079 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -1,70 +1,67 @@ -#!/usr/bin/perl +#!perl use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn table drop_table db_handle force_drop_table /; + use Test::More; use DBD::Oracle qw(:ora_types ORA_OCI ); use DBI; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -my $dbh = DBI->connect($dsn, $dbuser, '',{ PrintError => 0, }); +my $dbh = db_handle( { PrintError => 0 } ); -plan $dbh ? ( tests => 12 ) - : ( skip_all => "Unable to connect to Oracle" ); +plan $dbh + ? ( tests => 12 ) + : ( skip_all => 'Unable to connect to Oracle' ); my $table = table(); -drop_table($dbh); +force_drop_table($dbh); -$dbh->do( <<"END_SQL" ); - CREATE TABLE $table ( - id INTEGER NOT NULL, - data BLOB - ) -END_SQL +$dbh->do("CREATE TABLE $table ( id INTEGER NOT NULL, data BLOB )"); -my ($stmt, $sth, $id, $loc); +my ( $stmt, $sth, $id, $loc ); ## test with insert empty blob and select locator. $stmt = "INSERT INTO $table (id,data) VALUES (1, EMPTY_BLOB())"; $dbh->do($stmt); $stmt = "SELECT data FROM $table WHERE id = ?"; -$sth = $dbh->prepare($stmt, {ora_auto_lob => 0}); -$id = 1; -$sth->bind_param(1, $id); +$sth = $dbh->prepare( $stmt, { ora_auto_lob => 0 } ); +$id = 1; +$sth->bind_param( 1, $id ); $sth->execute; ($loc) = $sth->fetchrow; -is (ref $loc, "OCILobLocatorPtr", "returned valid locator"); +is( ref $loc, 'OCILobLocatorPtr', 'returned valid locator' ); +$sth->finish; ## test inserting a large value $stmt = "INSERT INTO $table (id,data) VALUES (666, ?)"; -$sth = $dbh->prepare($stmt); -my $content = join(q{}, map { chr } ( 32 .. 64 )) x 16384; -$sth->bind_param(1, $content, { ora_type => ORA_BLOB, ora_field => 'data' }); +$sth = $dbh->prepare($stmt); +my $content = join( q{}, map { chr } ( 32 .. 64 ) ) x 16384; +$sth->bind_param( 1, $content, { ora_type => ORA_BLOB, ora_field => 'data' } ); eval { $sth->execute($content) }; is $@, '', 'inserted into BLOB successfully'; { - local $dbh->{LongReadLen} = 1_000_000; - my ($fetched) = $dbh->selectrow_array("select data from $table where id = 666"); - is $fetched, $content, 'got back what we put in'; + local $dbh->{LongReadLen} = 1_000_000; + my ($fetched) = + $dbh->selectrow_array("select data from $table where id = 666"); + is $fetched, $content, 'got back what we put in'; } - ## test with insert empty blob returning blob to a var. -($id, $loc) = (2, undef); -$stmt = "INSERT INTO $table (id,data) VALUES (?, EMPTY_BLOB()) RETURNING data INTO ?"; -$sth = $dbh->prepare($stmt, {ora_auto_lob => 0}); -$sth->bind_param(1, $id); -$sth->bind_param_inout(2, \$loc, 0, {ora_type => ORA_BLOB}); +( $id, $loc ) = ( 2, undef ); +$stmt = + "INSERT INTO $table (id,data) VALUES (?, EMPTY_BLOB()) RETURNING data INTO ?"; +$sth = $dbh->prepare( $stmt, { ora_auto_lob => 0 } ); +$sth->bind_param( 1, $id ); +$sth->bind_param_inout( 2, \$loc, 0, { ora_type => ORA_BLOB } ); $sth->execute; -is (ref $loc, "OCILobLocatorPtr", "returned valid locator"); +is( ref $loc, 'OCILobLocatorPtr', 'returned valid locator' ); sub temp_lob_count { - my $dbh = shift; + my $dbh = shift; return $dbh->selectrow_array(<<'END_SQL'); SELECT cache_lobs + nocache_lobs AS temp_lob_count FROM v$temporary_lobs templob, @@ -76,11 +73,9 @@ END_SQL sub have_v_session { $dbh->do('select * from v$session where 0=1'); - return defined($dbh->err) ? $dbh->err != 942 : 1; + return defined( $dbh->err ) ? $dbh->err != 942 : 1; } - - ## test writing / reading large data { # LOB locators cannot span transactions - turn off AutoCommit @@ -97,36 +92,34 @@ sub have_v_session { $sth->execute; ($loc) = $sth->fetchrow; - is( ref $loc, "OCILobLocatorPtr", "returned valid locator" ); + is( ref $loc, 'OCILobLocatorPtr', 'returned valid locator' ); - is( $dbh->ora_lob_is_init($loc), 1, "returned initialized locator" ); + is( $dbh->ora_lob_is_init($loc), 1, 'returned initialized locator' ); # write string > 32k $large_value = 'ABCD' x 10_000; $dbh->ora_lob_write( $loc, 1, $large_value ); - eval { - $len = $dbh->ora_lob_length($loc); - }; + eval { $len = $dbh->ora_lob_length($loc); }; if ($@) { - note ("It appears your Oracle or Oracle client has problems with ora_lob_length(lob_locator). We have seen this before - see RT 69350. The test is not going to fail because of this because we have seen it before but if you are using lob locators you might want to consider upgrading your Oracle client to 11.2 where we know this test works"); + note( +'It appears your Oracle or Oracle client has problems with ora_lob_length(lob_locator). We have seen this before - see RT 69350. The test is not going to fail because of this because we have seen it before but if you are using lob locators you might want to consider upgrading your Oracle client to 11.2 where we know this test works' + ); done_testing(); - } else { - is( $len, length($large_value), "returned length" ); - + } + else { + is( $len, length($large_value), 'returned length' ); } is( $dbh->ora_lob_read( $loc, 1, length($large_value) ), - $large_value, "returned written value" ); + $large_value, 'returned written value' ); ## PL/SQL TESTS SKIP: { - ## test calling PL/SQL with LOB placeholder + ## test calling PL/SQL with LOB placeholder my $plsql_testcount = 4; - my $sth = $dbh->prepare( - 'BEGIN ? := DBMS_LOB.GETLENGTH( ? ); END;', - { ora_auto_lob => 0 } - ); + my $sth = $dbh->prepare( 'BEGIN ? := DBMS_LOB.GETLENGTH( ? ); END;', + { ora_auto_lob => 0 } ); $sth->bind_param_inout( 1, \$len, 16 ); $sth->bind_param( 2, $loc, { ora_type => ORA_BLOB } ); $sth->execute; @@ -137,20 +130,23 @@ sub have_v_session { # ORA-06553: PLS-00213: package STANDARD not accessible if ( $dbh->err && grep { $dbh->err == $_ } ( 600, 900, 6550, 6553 ) ) { - skip "Your Oracle server doesn't support PL/SQL", $plsql_testcount + skip q|Your Oracle server doesn't support PL/SQL|, $plsql_testcount if $dbh->err == 900; skip - "Your Oracle PL/SQL package DBMS_LOB is not properly installed", $plsql_testcount + 'Your Oracle PL/SQL package DBMS_LOB is not properly installed', + $plsql_testcount if $dbh->err == 6550; - skip "Your Oracle PL/SQL is not properly installed", $plsql_testcount + skip 'Your Oracle PL/SQL is not properly installed', + $plsql_testcount if $dbh->err == 6553 || $dbh->err == 600; } - TODO: { - local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" - if ORA_OCI() =~ /^11\.2\./; + TODO: { + local $TODO = + 'problem reported w/ lobs and Oracle 11.2.*, see RT#69350' + if ORA_OCI() =~ m/^11\.2\./; - is( $len, length($large_value), "returned length via PL/SQL" ); + is( $len, length($large_value), 'returned length via PL/SQL' ); } $dbh->{LongReadLen} = length($large_value) * 2; @@ -188,33 +184,41 @@ sub have_v_session { END; END_SQL - $sth->bind_param( ':in', $large_value, { ora_type => ORA_BLOB }); + $sth->bind_param( ':in', $large_value, { ora_type => ORA_BLOB } ); - $sth->bind_param_inout( ':out', \$out, 100, { ora_type => ORA_BLOB } ); - $sth->bind_param_inout( ':inout', \$inout, 100, { ora_type => ORA_BLOB } ); + $sth->bind_param_inout( ':out', \$out, 100, + { ora_type => ORA_BLOB } ); + $sth->bind_param_inout( ':inout', \$inout, 100, + { ora_type => ORA_BLOB } ); $sth->execute; }; - local $TODO = "problem reported w/ lobs and Oracle 11.2.*, see RT#69350" - if ORA_OCI() =~ /^11\.2\./; + local $TODO = 'problem reported w/ lobs and Oracle 11.2.*, see RT#69350' + if ORA_OCI() =~ m/^11\.2\./; - skip "Your Oracle PL/SQL installation does not implement temporary LOBS", 3 + skip + 'Your Oracle PL/SQL installation does not implement temporary LOBS', 3 if $dbh->err && $dbh->err == 6550; - is($out, lc($large_value), "returned LOB as string"); - is($inout, lc($large_value).$large_value, "returned IN/OUT LOB as string"); + is( $out, lc($large_value), 'returned LOB as string' ); + is( + $inout, + lc($large_value) . $large_value, + 'returned IN/OUT LOB as string' + ); undef $sth; + # lobs are freed with statement handle - skip q{can't check num of temp lobs, no access to v$session}, 1, unless have_v_session(); - is(temp_lob_count($dbh), 0, "no temp lobs left"); + skip q{can't check num of temp lobs, no access to v$session}, 1, + unless have_v_session(); + is( temp_lob_count($dbh), 0, 'no temp lobs left' ); } } undef $sth; -$dbh->do("DROP TABLE $table"); -$dbh->disconnect; +END { eval { drop_table($dbh); $dbh->disconnect if $dbh } } 1; diff --git a/t/31lob_extended.t b/t/31lob_extended.t index f507fd24..578a68da 100644 --- a/t/31lob_extended.t +++ b/t/31lob_extended.t @@ -1,4 +1,4 @@ -#!perl -w +#!perl ## ---------------------------------------------------------------------------- ## 31lob_extended.t @@ -9,35 +9,32 @@ ## Basically this is testing the use of LOBs when returned via stored procedures with bind_param_inout ## ---------------------------------------------------------------------------- +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn drop_table create_table db_handle /; + use Test::More; use DBI; use Config; use DBD::Oracle qw(:ora_types); -use strict; -use warnings; -use Data::Dumper; - -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; $| = 1; -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '',{ - PrintError => 0, - }); +my $dbh = db_handle( { PrintError => 0 } ); if ($dbh) { plan tests => 30; $dbh->{LongReadLen} = 7000; -} else { - plan skip_all => "Unable to connect to Oracle"; +} +else { + plan skip_all => 'Unable to connect to Oracle'; diag('Test reported bugs'); } -my ($table, $data0, $data1) = setup_test($dbh); +my ( $table, $data0, $data1 ) = setup_test($dbh); my $PLSQL = <<"PLSQL"; BEGIN @@ -53,27 +50,26 @@ $dbh->{RaiseError} = 1; # we get a segfault. This was due to prefetching more than one row. # { - my $testname = "ora_auto_lobs prefetch"; + my $testname = 'ora_auto_lobs prefetch'; - my ($sth1, $ev); + my ( $sth1, $ev ); - eval {$sth1 = $dbh->prepare($PLSQL, {ora_auto_lob => 0});}; - ok(!$@, "$testname - prepare call proc"); + eval { $sth1 = $dbh->prepare( $PLSQL, { ora_auto_lob => 0 } ); }; + ok( !$@, "$testname - prepare call proc" ); my $sth2; - ok($sth1->bind_param_inout(1, \$sth2, 500, {ora_type => ORA_RSET}), - "$testname - bind out cursor"); - ok($sth1->execute, "$testname - execute to get out cursor"); + ok( $sth1->bind_param_inout( 1, \$sth2, 500, { ora_type => ORA_RSET } ), + "$testname - bind out cursor" ); + ok( $sth1->execute, "$testname - execute to get out cursor" ); my ($lobl); ($lobl) = $sth2->fetchrow; - test_lob($dbh, $lobl, $testname, 6000, $data0); + test_lob( $dbh, $lobl, $testname, 6000, $data0 ); ($lobl) = $sth2->fetchrow; - test_lob($dbh, $lobl, $testname, 6000, $data1); - + test_lob( $dbh, $lobl, $testname, 6000, $data1 ); - ok($sth2->finish, "$testname - finished returned sth"); - ok($sth1->finish, "$testname - finished sth"); + ok( $sth2->finish, "$testname - finished returned sth" ); + ok( $sth1->finish, "$testname - finished sth" ); } # @@ -82,82 +78,78 @@ $dbh->{RaiseError} = 1; # were not automatically fetched. # { - my $testname = "ora_auto_lobs not fetching"; + my $testname = 'ora_auto_lobs not fetching'; - my ($sth1, $ev, $lob); + my ( $sth1, $ev, $lob ); # ora_auto_lobs is supposed to default to set - eval {$sth1 = $dbh->prepare($PLSQL);}; - ok(!$@, "$testname prepare call proc"); + eval { $sth1 = $dbh->prepare($PLSQL); }; + ok( !$@, "$testname prepare call proc" ); my $sth2; - ok($sth1->bind_param_inout(1, \$sth2, 500, {ora_type => ORA_RSET}), - "$testname - bind out cursor"); - ok($sth1->execute, "$testname - execute to get out cursor"); + ok( $sth1->bind_param_inout( 1, \$sth2, 500, { ora_type => ORA_RSET } ), + "$testname - bind out cursor" ); + ok( $sth1->execute, "$testname - execute to get out cursor" ); ($lob) = $sth2->fetchrow; - ok($lob, "$testname - fetch returns something"); - isnt(ref $lob, 'OCILobLocatorPtr', "$testname - not a lob locator"); - is($lob, $data0, "$testname, first lob matches"); + ok( $lob, "$testname - fetch returns something" ); + isnt( ref $lob, 'OCILobLocatorPtr', "$testname - not a lob locator" ); + is( $lob, $data0, "$testname, first lob matches" ); ($lob) = $sth2->fetchrow; - ok($lob, "$testname - fetch returns something"); - isnt(ref $lob, 'OCILobLocatorPtr', "$testname - not a lob locator"); - is($lob, $data1, "$testname, second lob matches"); + ok( $lob, "$testname - fetch returns something" ); + isnt( ref $lob, 'OCILobLocatorPtr', "$testname - not a lob locator" ); + is( $lob, $data1, "$testname, second lob matches" ); - ok($sth2->finish, "$testname - finished returned sth"); - ok($sth1->finish, "$testname - finished sth"); + ok( $sth2->finish, "$testname - finished returned sth" ); + ok( $sth1->finish, "$testname - finished sth" ); } -sub test_lob -{ - my ($h, $lobl, $testname, $size, $data) = @_; +sub test_lob { + my ( $h, $lobl, $testname, $size, $data ) = @_; - ok($lobl, "$testname - lob locator retrieved"); - is(ref($lobl), 'OCILobLocatorPtr', "$testname - is a lob locator"); + ok( $lobl, "$testname - lob locator retrieved" ); + is( ref($lobl), 'OCILobLocatorPtr', "$testname - is a lob locator" ); SKIP: { - skip "did not receive a lob locator", 4 - unless ref($lobl) eq 'OCILobLocatorPtr'; + skip 'did not receive a lob locator', 4 + unless ref($lobl) eq 'OCILobLocatorPtr'; - my ($lob_length, $lob, $ev); + my ( $lob_length, $lob, $ev ); - eval {$lob_length = $h->ora_lob_length($lobl);}; + eval { $lob_length = $h->ora_lob_length($lobl); }; $ev = $@; diag($ev) if $ev; - ok(!$ev, "$testname - first lob length $lob_length"); - is($lob_length, $size, "$testname - correct lob length"); - eval {$lob = $h->ora_lob_read($lobl, 1, $lob_length);}; + ok( !$ev, "$testname - first lob length $lob_length" ); + is( $lob_length, $size, "$testname - correct lob length" ); + eval { $lob = $h->ora_lob_read( $lobl, 1, $lob_length ); }; $ev = $@; diag($ev) if ($ev); - ok(!$ev, "$testname - read lob"); + ok( !$ev, "$testname - read lob" ); - is($lob, $data, "$testname - lob returned matches lob inserted"); + is( $lob, $data, "$testname - lob returned matches lob inserted" ); } } -sub setup_test -{ +sub setup_test { my ($h) = @_; - my ($table, $sth, $ev); + my ( $table, $sth, $ev ); - eval {$table = create_table($h, {cols => [['x', 'clob']]}, 1)}; + eval { $table = create_table( $h, { cols => [ [ 'x', 'clob' ] ] }, 1 ) }; BAIL_OUT("test table not created- $@") if $@; - ok(!$ev, "created test table"); + ok( !$ev, 'created test table' ); - eval { - $sth = $h->prepare(qq/insert into $table (idx, x) values(?,?)/); - }; + eval { $sth = $h->prepare(qq/insert into $table (idx, x) values(?,?)/); }; BAIL_OUT("Failed to prepare insert into $table - $@") if $@; my $data0 = 'x' x 6000; my $data1 = 'y' x 6000; eval { - $sth->execute(1, $data0); - $sth->execute(2, $data1); + $sth->execute( 1, $data0 ); + $sth->execute( 2, $data1 ); }; BAIL_OUT("Failed to insert test data into $table - $@") if $@; - ok(!$ev, "created test data"); + ok( !$ev, 'created test data' ); - return ($table, $data0, $data1); + return ( $table, $data0, $data1 ); } END { @@ -166,10 +158,10 @@ END { local $dbh->{PrintError} = 0; local $dbh->{RaiseError} = 1; - eval {drop_table($dbh);}; + eval { drop_table($dbh); }; if ($@) { diag("table $table possibly not dropped - check - $@\n") - if $dbh->err ne '942'; + if $dbh->err ne '942'; } } diff --git a/t/32xmltype.t b/t/32xmltype.t index 7f413fb3..5ccf9e17 100644 --- a/t/32xmltype.t +++ b/t/32xmltype.t @@ -1,13 +1,15 @@ -#!/usr/bin/perl +#!perl use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn table drop_table db_handle force_drop_table /; + use Test::More; use DBD::Oracle qw(:ora_types); use DBI; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - ## ---------------------------------------------------------------------------- ## 03xmlype.t ## By John Scoles, The Pythian Group @@ -17,69 +19,70 @@ require 'nchar_test_lib.pl'; ## ---------------------------------------------------------------------------- # create a database handle -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh; - -eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, - AutoCommit=>1, - PrintError => 0 })}; +my $dbh = eval{ db_handle( { + RaiseError => 1, + AutoCommit => 1, + PrintError => 0 + }) }; if ($dbh) { - plan skip_all => "XMLTYPE new in Oracle 9" - if $dbh->func('ora_server_version')->[0] < 9; + plan skip_all => 'XMLTYPE new in Oracle 9' + if $dbh->func('ora_server_version')->[0] < 9; plan tests => 3; -} else { - plan skip_all => "Unable to connect to Oracle" } -# check that our db handle is good -isa_ok($dbh, "DBI::db"); - +else { + plan skip_all => 'Unable to connect to Oracle'; +} +# check that our db handle is good +isa_ok( $dbh, 'DBI::db' ); my $table = table(); -eval { $dbh->do("DROP TABLE $table") }; - -$dbh->do(qq{ - CREATE TABLE $table ( - id INTEGER NOT NULL, - XML_DATA XMLTYPE - ) - }); - -my ($stmt, $sth); -my $small_xml=""; -my $large_xml=""; -my $i=0; - -for ($i=0;$i<=10;$i++){ - $small_xml=$small_xml."the book ".$i." title"; +eval { force_drop_table($dbh, $table) }; + +$dbh->do( + qq{ CREATE TABLE $table ( id INTEGER NOT NULL, XML_DATA XMLTYPE ) } +); + +my ( $stmt, $sth ); +my $small_xml = ''; +my $large_xml = ''; +my $i = 0; + +for ( $i = 0 ; $i <= 10 ; $i++ ) { + $small_xml = + $small_xml + . "the book " + . $i + . " title"; } -$small_xml=$small_xml.""; +$small_xml = $small_xml . ''; -for ($i=0;$i<=10000;$i++){ - $large_xml=$large_xml."the book ".$i." title"; +for ( $i = 0 ; $i <= 10000 ; $i++ ) { + $large_xml = + $large_xml + . "the book " + . $i + . " title"; } -$large_xml=$large_xml.""; - -$stmt = "INSERT INTO ".$table." VALUES (1,?)"; +$large_xml = $large_xml . ''; -$sth =$dbh-> prepare($stmt); +$stmt = "INSERT INTO $table VALUES (1,?)"; -$sth-> bind_param(1, $small_xml, { ora_type => ORA_XMLTYPE }); +$sth = $dbh->prepare($stmt); -ok ($sth->execute(), '... execute for small XML return true'); +$sth->bind_param( 1, $small_xml, { ora_type => ORA_XMLTYPE } ); -$sth-> bind_param(1, $large_xml, { ora_type => ORA_XMLTYPE }); +ok( $sth->execute(), '... execute for small XML return true' ); -ok ($sth->execute(), '... execute for large XML return true'); +$sth->bind_param( 1, $large_xml, { ora_type => ORA_XMLTYPE } ); +ok( $sth->execute(), '... execute for large XML return true' ); drop_table($dbh); - -$dbh->disconnect; - -1; - diff --git a/t/34pres_lobs.t b/t/34pres_lobs.t index e5b38dfc..b721f52a 100644 --- a/t/34pres_lobs.t +++ b/t/34pres_lobs.t @@ -1,4 +1,10 @@ -#!perl -w +#!perl + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn table drop_table db_handle force_drop_table /; use Test::More; @@ -6,8 +12,6 @@ use DBI; use Config; use DBD::Oracle qw(:ora_types); - - ## ---------------------------------------------------------------------------- ## 33pres_lobs.t ## By John Scoles, The Pythian Group @@ -17,107 +21,114 @@ use DBD::Oracle qw(:ora_types); ## of oci being used ## ---------------------------------------------------------------------------- -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - $| = 1; # create a database handle -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '', - { RaiseError=>1, - AutoCommit=>1, - PrintError => 0 ,LongReadLen=>10000000})}; +my $dbh = eval{ db_handle( { + RaiseError => 1, + AutoCommit => 1, + PrintError => 0, + LongReadLen => 10000000 + })}; if ($dbh) { - plan skip_all => "Data Interface for Persistent LOBs new in Oracle 9" - if $dbh->func('ora_server_version')->[0] < 9; + plan skip_all => 'Data Interface for Persistent LOBs new in Oracle 9' + if $dbh->func('ora_server_version')->[0] < 9; plan tests => 28; -} else { - plan skip_all => "Unable to connect to Oracle"; } -# check that our db handle is good -my $ora_oci = DBD::Oracle::ORA_OCI(); # dualvar - -SKIP: { - skip "OCI version less than 9.2\n Persistent LOBs Tests skiped.", 29 unless $ora_oci >= 9.2; - - -my $table = table(); - -eval { $dbh->do("DROP TABLE $table") }; - -ok($dbh->do(qq{ - CREATE TABLE $table ( - id NUMBER, - clob1 CLOB, - clob2 CLOB, - blob1 BLOB, - blob2 BLOB) - }), 'create test table'); - - -my $in_clob='ABCD' x 10_000; -my $in_blob=("0\177x\0X"x 2048) x (1); -my ($sql, $sth,$value); - -$sql = "insert into ".$table." - (id,clob1,clob2, blob1,blob2) - values(?,?,?,?,?)"; -ok($sth=$dbh->prepare($sql ), 'prepare for insert into lobs'); -$sth->bind_param(1,3); -ok($sth->bind_param(2,$in_clob,{ora_type=>SQLT_CHR}), 'bind p2'); -ok($sth->bind_param(3,$in_clob,{ora_type=>SQLT_CHR}), 'bind p3'); -ok($sth->bind_param(4,$in_blob,{ora_type=>SQLT_BIN}), 'bind p4'); -ok($sth->bind_param(5,$in_blob,{ora_type=>SQLT_BIN}), 'bind p5'); -ok($sth->execute(), 'execute'); - -$sql='select * from '.$table; - -ok($sth=$dbh->prepare($sql,{ora_pers_lob=>1}), 'prepare with ora_pers_lob'); - -ok($sth->execute(), 'execute with ora_pers_lob'); -my ($p_id,$log,$log2,$log3,$log4); - -ok(( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow(), - 'fetcheow for ora_pers_lob'); - -is($log, $in_clob, 'clob1 = in_clob'); -is($log2, $in_clob, 'clob2 = in_clob'); -is($log3, $in_blob, 'clob1 = in_blob'); -is($log4, $in_blob, 'clob2 = in_blob'); - -ok($sth=$dbh->prepare($sql,{ora_clbk_lob=>1,ora_piece_size=>.5*1024*1024}), - 'prepare for ora_piece_size'); - -ok($sth->execute(), 'execute for ora_piece_size'); - -ok(( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow(), 'fetchrow'); -ok($log eq $in_clob, 'clob1 = in_clob'); -ok($log2 eq $in_clob, 'clob2 = in_clob'); -ok($log3 eq $in_blob, 'clob1 = in_clob'); -ok($log4 eq $in_blob, 'clob2 = in_clob'); - -ok($sth=$dbh->prepare($sql,{ora_piece_lob=>1,ora_piece_size=>.5*1024*1024}), - 'prepare with ora_piece_lob/ora_piece_size'); - -ok($sth->execute(), 'execute'); -ok( ( $p_id,$log,$log2,$log3,$log4 )=$sth->fetchrow(), - 'fetchrow'); - -ok($log eq $in_clob, 'clob1 = in_clob'); -ok($log2 eq $in_clob, 'clob2 = in_clob'); -ok($log3 eq $in_blob, 'clob1 = in_clob'); -ok($log4 eq $in_blob, 'clob2 = in_clob'); - -#no neeed to look at the data is should be ok - -$sth->finish(); -drop_table($dbh); +else { + plan skip_all => 'Unable to connect to Oracle'; } +# check that our db handle is good +my $ora_oci = DBD::Oracle::ORA_OCI(); # dualvar -$dbh->disconnect; +SKIP: { -1; + skip "OCI version less than 9.2\n Persistent LOBs Tests skiped.", 29 + unless $ora_oci >= 9.2; + + my $table = table(); + + eval { force_drop_table( $dbh, $table ) }; + + ok( + $dbh->do( + qq{ + CREATE TABLE $table ( + id NUMBER, + clob1 CLOB, + clob2 CLOB, + blob1 BLOB, + blob2 BLOB) + } + ), + 'create test table' + ); + + my $in_clob = 'ABCD' x 10_000; + my $in_blob = ( "0\177x\0X" x 2048 ) x (1); + my ( $sql, $sth, $value ); + + $sql = 'insert into ' . $table . ' (id,clob1,clob2,blob1,blob2) + values (?,?,?,?,?)'; + + ok( $sth = $dbh->prepare($sql), 'prepare for insert into lobs' ); + $sth->bind_param( 1, 3 ); # ID: 3 + ok( $sth->bind_param( 2, $in_clob, { ora_type => SQLT_CHR } ), 'bind p2' ); + ok( $sth->bind_param( 3, $in_clob, { ora_type => SQLT_CHR } ), 'bind p3' ); + ok( $sth->bind_param( 4, $in_blob, { ora_type => SQLT_BIN } ), 'bind p4' ); + ok( $sth->bind_param( 5, $in_blob, { ora_type => SQLT_BIN } ), 'bind p5' ); + ok( $sth->execute(), 'execute' ); + + $sql = "select * from $table"; + + ok( $sth = $dbh->prepare( $sql, { ora_pers_lob => 1 } ), + 'prepare with ora_pers_lob' ); + + ok( $sth->execute(), 'execute with ora_pers_lob' ); + my ( $p_id, $log, $log2, $log3, $log4 ); + + ok( ( $p_id, $log, $log2, $log3, $log4 ) = $sth->fetchrow(), + 'fetchrow for ora_pers_lob' ); + + is( $log, $in_clob, 'clob1 = in_clob' ); + is( $log2, $in_clob, 'clob2 = in_clob' ); + is( $log3, $in_blob, 'clob1 = in_blob' ); + is( $log4, $in_blob, 'clob2 = in_blob' ); + + ok( + $sth = $dbh->prepare( + $sql, { ora_clbk_lob => 1, ora_piece_size => .5 * 1024 * 1024 } + ), + 'prepare for ora_piece_size' + ); + + ok( $sth->execute(), 'execute for ora_piece_size' ); + + ok( ( $p_id, $log, $log2, $log3, $log4 ) = $sth->fetchrow(), 'fetchrow' ); + cmp_ok( $log, 'eq', $in_clob, 'clob1 = in_clob' ); + cmp_ok( $log2, 'eq', $in_clob, 'clob2 = in_clob' ); + cmp_ok( $log3, 'eq', $in_blob, 'clob1 = in_clob' ); + cmp_ok( $log4, 'eq', $in_blob, 'clob2 = in_clob' ); + + ok( + $sth = $dbh->prepare( + $sql, { ora_piece_lob => 1, ora_piece_size => .5 * 1024 * 1024 } + ), + 'prepare with ora_piece_lob/ora_piece_size' + ); + + ok( $sth->execute(), 'execute' ); + ok( ( $p_id, $log, $log2, $log3, $log4 ) = $sth->fetchrow(), 'fetchrow' ); + + cmp_ok( $log, 'eq', $in_clob, 'clob1 = in_clob' ); + cmp_ok( $log2, 'eq', $in_clob, 'clob2 = in_clob' ); + cmp_ok( $log3, 'eq', $in_blob, 'clob1 = in_clob' ); + cmp_ok( $log4, 'eq', $in_blob, 'clob2 = in_clob' ); + + #no neeed to look at the data is should be ok + + $sth->finish(); + drop_table($dbh); + +} # SKIP diff --git a/t/36lob_leak.t b/t/36lob_leak.t index 119662a5..55b52219 100644 --- a/t/36lob_leak.t +++ b/t/36lob_leak.t @@ -1,167 +1,169 @@ -#!perl -w - -##---------------------------------------------------------------------------- -## 36lob_leak.pl -## By Martin Evans, Easysoft Limited -##---------------------------------------------------------------------------- -## Test we are not leaking temporary lobs -##---------------------------------------------------------------------------- - -use Test::More; - -use DBI; -use Config; -use DBD::Oracle qw(:ora_types); -use strict; -use warnings; -use Data::Dumper; - -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - -$| = 1; - -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '',,{ - PrintError => 0, - }); - -if ($dbh) { - plan tests => 7; -} else { - $dbh->{PrintError}=1; - plan skip_all => "Unable to connect to Oracle"; -} - -# get SID and cached lobs -# if sid not passed in we run 2 tests, get the sid and the cached lobs -# if sid passed in we run 1 test which is to get the cached lobs -sub get_cached_lobs -{ - my ($dbh, $sid) = @_; - my $cached_lobs; - - if (!defined($sid)) { - SKIP: { - eval { - ($sid) = $dbh->selectrow_array( - q/select sid from v$session where audsid = -SYS_CONTEXT('userenv', 'sessionid')/); - }; - skip 'unable to find sid', 2 if ($@ || !defined($sid)); - - pass("found sid $sid"); - }; - } - if (defined($sid)) { - SKIP: { - eval { - $cached_lobs = $dbh->selectrow_array( - q/select CACHE_LOBS from V$TEMPORARY_LOBS where sid -= ?/, undef, $sid); - }; - skip 'unable to find cached lobs', 1 - if ($@ || !defined($cached_lobs)); - pass("found $cached_lobs cached lobs"); - }; - } - return ($sid, $cached_lobs); -} - -sub setup_test -{ - my ($h) = @_; - my ($sth, $ev); - - my $fn = 'p_DBD_Oracle_drop_me'; - - my $createproc = << "EOT"; -CREATE OR REPLACE FUNCTION $fn(pc IN CLOB) RETURN NUMBER AS -BEGIN - NULL; - RETURN 0; -END; -EOT - - eval {$h->do($createproc);}; - BAIL_OUT("Failed to create test function - $@") if $@; - pass("created test function"); - - return $fn; -} - -sub call_func -{ - my ($dbh, $function, $how) = @_; - - eval { - my $sth; - my $sql = qq/BEGIN ? := $function(?); END;/; - if ($how eq 'prepare') { - $sth = $dbh->prepare($sql) or die($dbh->errstr); - } elsif ($how eq 'prepare_cached') { - $sth = $dbh->prepare_cached($sql) or die($dbh->errstr); - } else { - BAIL_OUT("Unknown prepare type $how"); - } - $sth->{RaiseError} = 1; - - BAIL_OUT("Cannot prepare a call to $function") if !$sth; - - my ($return, $clob); - $clob = 'x' x 1000; - $sth->bind_param_inout(1, \$return, 10); - $sth->bind_param(2, $clob, {ora_type => ORA_CLOB}); - $sth->execute; - }; - BAIL_OUT("Cannot call $function successfully") if $@; -} - - -my ($sid, $cached_lobs); -my ($function); -SKIP: { - ($sid, $cached_lobs) = get_cached_lobs($dbh); # 1 2 - skip 'Cannot find sid/cached lobs', 5 if !defined($cached_lobs); - - $function = setup_test($dbh); # 3 - my $new_cached_lobs; - - foreach my $type (qw(prepare prepare_cached)) { - for my $count(1..100) { - call_func($dbh, $function, $type); - }; - ($sid, $new_cached_lobs) = get_cached_lobs($dbh, $sid); - - # we expect to leak 1 temporary lob as the last statement is - # cached and the temp lob is not thrown away until you next - # execute - if ($new_cached_lobs > ($cached_lobs + 1)) { - diag("Looks like we might be leaking temporary lobs from -$type"); - fail("old cached lobs: $cached_lobs " . - "new cached lobs: $new_cached_lobs"); - } else { - pass("Not leaking temporary lobs on $type"); - } - $cached_lobs = $new_cached_lobs; - } - -}; - -END { - if ($dbh) { - local $dbh->{PrintError} = 0; - local $dbh->{RaiseError} = 1; - if ($function){ - eval {$dbh->do(qq/drop function $function/);}; - if ($@) { - diag("function p_DBD_Oracle_drop_me possibly not dropped" . - "- check - $@\n") if $dbh->err ne '4043'; - } else { - note("function p_DBD_Oracle_drop_me dropped"); - } - } - } -} +#!perl + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + +##---------------------------------------------------------------------------- +## 36lob_leak.pl +## By Martin Evans, Easysoft Limited +##---------------------------------------------------------------------------- +## Test we are not leaking temporary lobs +##---------------------------------------------------------------------------- + +use Test::More; + +use DBI; +use Config; +use DBD::Oracle qw(:ora_types); + +$| = 1; + +my $dbh = db_handle( { PrintError => 0 }); + +if ($dbh) { + plan tests => 7; +} +else { + $dbh->{PrintError} = 1; + plan skip_all => 'Unable to connect to Oracle'; +} + +# get SID and cached lobs +# if sid not passed in we run 2 tests, get the sid and the cached lobs +# if sid passed in we run 1 test which is to get the cached lobs +sub get_cached_lobs { + my ( $dbh, $sid ) = @_; + my $cached_lobs; + + if ( !defined($sid) ) { + SKIP: { + eval { + ($sid) = $dbh->selectrow_array( + q/select sid from v$session where audsid = +SYS_CONTEXT('userenv', 'sessionid')/ + ); + }; + skip 'unable to find sid', 2 if ( $@ || !defined($sid) ); + + pass("found sid $sid"); + } + } + if ( defined($sid) ) { + SKIP: { + eval { + $cached_lobs = $dbh->selectrow_array( + q/select CACHE_LOBS from V$TEMPORARY_LOBS where sid += ?/, undef, $sid + ); + }; + skip 'unable to find cached lobs', 1 + if ( $@ || !defined($cached_lobs) ); + pass("found $cached_lobs cached lobs"); + } + } + return ( $sid, $cached_lobs ); +} + +sub setup_test { + my ($h) = @_; + my ( $sth, $ev ); + + my $fn = 'p_DBD_Oracle_drop_me' . ( $ENV{DBD_ORACLE_SEQ} || '' ); + + my $createproc = << "EOT"; +CREATE OR REPLACE FUNCTION $fn(pc IN CLOB) RETURN NUMBER AS +BEGIN + NULL; + RETURN 0; +END; +EOT + + eval { $h->do($createproc); }; + BAIL_OUT("Failed to create test function - $@") if $@; + pass('created test function'); + + return $fn; +} + +sub call_func { + my ( $dbh, $function, $how ) = @_; + + eval { + my $sth; + my $sql = qq/BEGIN ? := $function(?); END;/; + if ( $how eq 'prepare' ) { + $sth = $dbh->prepare($sql) or die( $dbh->errstr ); + } + elsif ( $how eq 'prepare_cached' ) { + $sth = $dbh->prepare_cached($sql) or die( $dbh->errstr ); + } + else { + BAIL_OUT("Unknown prepare type $how"); + } + $sth->{RaiseError} = 1; + + BAIL_OUT("Cannot prepare a call to $function") if !$sth; + + my ( $return, $clob ); + $clob = 'x' x 1000; + $sth->bind_param_inout( 1, \$return, 10 ); + $sth->bind_param( 2, $clob, { ora_type => ORA_CLOB } ); + $sth->execute; + }; + BAIL_OUT("Cannot call $function successfully") if $@; +} + +my ( $sid, $cached_lobs ); +my ($function); +SKIP: { + ( $sid, $cached_lobs ) = get_cached_lobs($dbh); # 1 2 + skip 'Cannot find sid/cached lobs', 5 if !defined($cached_lobs); + + $function = setup_test($dbh); # 3 + my $new_cached_lobs; + + foreach my $type (qw(prepare prepare_cached)) { + for my $count ( 1 .. 100 ) { + call_func( $dbh, $function, $type ); + } + ( $sid, $new_cached_lobs ) = get_cached_lobs( $dbh, $sid ); + + # we expect to leak 1 temporary lob as the last statement is + # cached and the temp lob is not thrown away until you next + # execute + if ( $new_cached_lobs > ( $cached_lobs + 1 ) ) { + diag( + "Looks like we might be leaking temporary lobs from +$type" + ); + fail( "old cached lobs: $cached_lobs " + . "new cached lobs: $new_cached_lobs" ); + } + else { + pass("Not leaking temporary lobs on $type"); + } + $cached_lobs = $new_cached_lobs; + } + +} + +END { + if ($dbh and not $ENV{DBD_SKIP_TABLE_DROP}) { + local $dbh->{PrintError} = 0; + local $dbh->{RaiseError} = 1; + if ($function) { + eval { $dbh->do(qq/drop function $function/); }; + if ($@) { + diag( "function '$function' possibly not dropped" + . "- check - $@\n" ) + if $dbh->err ne '4043'; + } + else { + note("function '$function' dropped"); + } + } + } +} diff --git a/t/38taf.t b/t/38taf.t index 8f40d868..ba7d0398 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -1,51 +1,46 @@ -#!perl -w -# $Id$ +#!perl + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; use DBI; use DBD::Oracle(qw(:ora_fail_over)); -use strict; + #use Devel::Peek qw(SvREFCNT Dump); use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - $| = 1; # create a database handle -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } - or plan skip_all => "Unable to connect to Oracle"; +my $dbh = db_handle() + or plan skip_all => 'Unable to connect to Oracle'; $dbh->disconnect; -if ( !$dbh->ora_can_taf ){ +if ( !$dbh->ora_can_taf ) { eval { - $dbh = DBI->connect( - $dsn, $dbuser, '', - {ora_taf_function => 'taf'}) + $dbh = db_handle( { ora_taf_function => 'taf' } ); }; my $ev = $@; - like($ev, qr/You are attempting to enable TAF/, "'$ev' (expected)"); + like( $ev, qr/You are attempting to enable TAF/, "'$ev' (expected)" ); } else { - ok $dbh = DBI->connect($dsn, $dbuser, '', - {ora_taf_function=>'taf'}); + ok $dbh = db_handle( { ora_taf_function => 'taf' } ); - is($dbh->{ora_taf_function}, 'taf', 'TAF callback'); + is( $dbh->{ora_taf_function}, 'taf', 'TAF callback' ); - my $x = sub {}; -# diag(SvREFCNT($x)); -# diag(Dump($x)); - $dbh->{ora_taf_function} = $x; - is(ref($dbh->{ora_taf_function}), 'CODE', 'TAF code ref'); + my $x = sub { }; -# diag(SvREFCNT($x)); -} + # diag(SvREFCNT($x)); + # diag(Dump($x)); + $dbh->{ora_taf_function} = $x; + is( ref( $dbh->{ora_taf_function} ), 'CODE', 'TAF code ref' ); -$dbh->disconnect; + # diag(SvREFCNT($x)); +} done_testing(); diff --git a/t/39attr.t b/t/39attr.t index 12a5a669..7e582601 100755 --- a/t/39attr.t +++ b/t/39attr.t @@ -1,74 +1,86 @@ -#!perl -w -# $Id$ +#!perl # # Test you can set and retrieve some attributes after connect # MJE wrote this after discovering the code to set these attributes # was duplicated in connect/login6 and STORE and it did not need to be # because DBI passes attributes to STORE for you. # + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + use DBI; use DBD::Oracle(qw(ORA_OCI)); -use strict; + #use Devel::Peek qw(SvREFCNT Dump); use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; $| = 1; -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; #use Devel::Leak; #use Test::LeakTrace; #no_leaks_ok { - do_it(); +do_it(); + #} -verbose; sub do_it { + #my $handle; #my $count = Devel::Leak::NoteSV($handle); - my $dbh = eval { DBI->connect($dsn, $dbuser, '',) } - or plan skip_all => "Unable to connect to Oracle"; + my $dbh = db_handle() + or plan skip_all => 'Unable to connect to Oracle'; - diag("Oracle version: " . join(".", @{$dbh->func('ora_server_version')})); - diag("client version: " . ORA_OCI()); + diag( 'Oracle version: ' + . join( '.', @{ $dbh->func('ora_server_version') } ) ); + diag( 'client version: ' . ORA_OCI() ); SKIP: { - my @attrs = (qw(ora_module_name - ora_client_info - ora_client_identifier - ora_action)); + my @attrs = ( + qw(ora_module_name + ora_client_info + ora_client_identifier + ora_action) + ); my @attrs112 = (qw(ora_driver_name)); - skip('Oracle OCI too old', 1 + @attrs + @attrs112) if ORA_OCI() < 11; + skip( 'Oracle OCI too old', 1 + @attrs + @attrs112 ) if ORA_OCI() < 11; foreach my $attr (@attrs) { $dbh->{$attr} = 'fred'; - is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); + is( $dbh->{$attr}, 'fred', "attribute $attr set and retrieved" ); } SKIP: { skip 'Oracle OCI too old', 1 + @attrs112 if ORA_OCI() < 11.2; - like($dbh->{ora_driver_name}, qr/DBD/, 'Default driver name'); + like( $dbh->{ora_driver_name}, qr/DBD/, 'Default driver name' ); foreach my $attr (@attrs) { $dbh->{$attr} = 'fred'; - is($dbh->{$attr}, 'fred', "attribute $attr set and retrieved"); + is( $dbh->{$attr}, 'fred', + "attribute $attr set and retrieved" ); } } - }; + } - foreach my $attr (qw(ora_oci_success_warn - ora_objects)) { + for my $attr ( + qw(ora_oci_success_warn + ora_objects) + ) + { $dbh->{$attr} = 1; - is($dbh->{$attr}, 1, "attribute $attr set and retrieved"); + is( $dbh->{$attr}, 1, "attribute $attr set and retrieved" ); } $dbh->disconnect; + #Devel::Leak::CheckSV($handle); } diff --git a/t/40ph_type.t b/t/40ph_type.t index 38239b82..3d7253d9 100644 --- a/t/40ph_type.t +++ b/t/40ph_type.t @@ -1,131 +1,165 @@ -#!perl -w -use Test::More; +#!perl use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle drop_table force_drop_table table /; + +use Test::More; + use DBI qw(neat); use DBD::Oracle qw(ORA_OCI); use vars qw($tests); -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - -$| = 1; +$| = 1; $^W = 1; # XXX ought to extend tests to check 'blank padded comparision semantics' my @tests = ( - # type: oracle internal type to use for placeholder values - # name: oracle name for type above - # chops_space: set true if type trims trailing space characters - # embed_nul: set true if type allows embedded nul characters - # (also SKIP=1 to skip test, ti=N to trace insert, ts=N to trace select) - { type=> 1, name=>"VARCHAR2", chops_space=>1, embed_nul=>1, }, # current DBD::Oracle - { type=> 5, name=>"STRING", chops_space=>0, embed_nul=>0, SKIP=>1, ti=>8 }, # old Oraperl - { type=>96, name=>"CHAR", chops_space=>0, embed_nul=>1, }, - { type=>97, name=>"CHARZ", chops_space=>0, embed_nul=>0, SKIP=>1, ti=>8 }, + + # type: oracle internal type to use for placeholder values + # name: oracle name for type above + # chops_space: set true if type trims trailing space characters + # embed_nul: set true if type allows embedded nul characters + # (also SKIP=1 to skip test, ti=N to trace insert, ts=N to trace select) + { type => 1, name => 'VARCHAR2', chops_space => 1, embed_nul => 1, } + , # current DBD::Oracle + { + type => 5, + name => 'STRING', + chops_space => 0, + embed_nul => 0, + SKIP => 1, + ti => 8 + }, # old Oraperl + { type => 96, name => 'CHAR', chops_space => 0, embed_nul => 1, }, + { + type => 97, + name => 'CHARZ', + chops_space => 0, + embed_nul => 0, + SKIP => 1, + ti => 8 + }, ); -$tests = 3; -$_->{SKIP} or $tests+=8 for @tests; +$tests = 1; +$_->{SKIP} or $tests += 8 for @tests; -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dsn = oracle_test_dsn(); -my $dbh = DBI->connect($dsn, $dbuser, '', { - AutoCommit => 0, - PrintError => 0, - FetchHashKeyName => 'NAME_lc', -}); +my $dbh = db_handle( + { + AutoCommit => 0, + PrintError => 0, + FetchHashKeyName => 'NAME_lc', + } +); if ($dbh) { plan tests => $tests; -} else { - plan skip_all => - "Unable to connect to Oracle"; +} +else { + plan skip_all => 'Unable to connect to Oracle'; } eval { require Data::Dumper; - $Data::Dumper::Useqq = $Data::Dumper::Useqq =1; - $Data::Dumper::Terse = $Data::Dumper::Terse =1; - $Data::Dumper::Indent= $Data::Dumper::Indent=1; + $Data::Dumper::Useqq = $Data::Dumper::Useqq = 1; + $Data::Dumper::Terse = $Data::Dumper::Terse = 1; + $Data::Dumper::Indent = $Data::Dumper::Indent = 1; }; -my ($sth,$tmp); -my $table = "dbd_ora__drop_me" . ($ENV{DBD_ORACLE_SEQ}||''); +my ( $sth, $tmp ); +my $table = table(); # drop table but don't warn if not there -eval { - local $dbh->{PrintError} = 0; - $dbh->do("DROP TABLE $table"); -}; +eval { force_drop_table($dbh, $table) }; -ok($dbh->do("CREATE TABLE $table (name VARCHAR2(2), vc VARCHAR2(20), c CHAR(20))"), 'create test table'); +ok( + $dbh->do( + "CREATE TABLE $table (name VARCHAR2(2), vc VARCHAR2(20), c CHAR(20))"), + 'create test table' +); -my $val_with_trailing_space = "trailing "; -my $val_with_embedded_nul = "embedded\0nul"; +my $val_with_trailing_space = 'trailing '; +my $val_with_embedded_nul = "embedded\0nul"; for my $test_info (@tests) { - next if $test_info->{SKIP}; - - my $ph_type = $test_info->{type} || die; - my $name = $test_info->{name} || die; - note("\ntesting @{[ %$test_info ]} ...\n\n"); - - SKIP: { - skip "skipping tests", 12 if ($test_info->{SKIP}); - - $dbh->{ora_ph_type} = $ph_type; - ok($dbh->{ora_ph_type} == $ph_type, 'set ora_ph_type'); - - $sth = $dbh->prepare("INSERT INTO $table(name,vc,c) VALUES (?,?,?)"); - $sth->trace($test_info->{ti}) if $test_info->{ti}; - $sth->execute("ts", $val_with_trailing_space, $val_with_trailing_space); - $sth->execute("en", $val_with_embedded_nul, $val_with_embedded_nul); - $sth->execute("es", '', ''); # empty string - $sth->trace(0) if $test_info->{ti}; - - $dbh->trace($test_info->{ts}) if $test_info->{ts}; - $tmp = $dbh->selectall_hashref(qq{ - SELECT name, vc, length(vc) as len, nvl(vc,'ISNULL') as isnull, c - FROM $table}, "name"); - ok(keys(%$tmp) == 3, 'right keys'); - $dbh->trace(0) if $test_info->{ts}; - $dbh->rollback; - - delete $_->{name} foreach values %$tmp; - note(Data::Dumper::Dumper($tmp)); - - # check trailing_space behaviour - my $expect = $val_with_trailing_space; - $expect =~ s/\s+$// if $test_info->{chops_space}; - my $ok = ($tmp->{ts}->{vc} eq $expect); - if (!$ok && $ph_type==1 && $name eq 'VARCHAR2') { - note " Placeholder behaviour for ora_type=1 VARCHAR2 (the default) varies with Oracle version.\n" - . " Oracle 7 didn't strip trailing spaces, Oracle 8 did, until 9.2.x\n" - . " Your system doesn't. If that seems odd, let us know.\n"; - $ok = 1; - } - ok($ok, sprintf(" using ora_type %d expected %s but got %s for $name", - $ph_type, neat($expect), neat($tmp->{ts}->{vc})) ); - - # check embedded nul char behaviour - $expect = $val_with_embedded_nul; - $expect =~ s/\0.*// unless $test_info->{embed_nul}; - is($tmp->{en}->{vc}, $expect, sprintf(" expected %s but got %s for $name", - neat($expect),neat($tmp->{en}->{vc})) ); - - # check empty string is NULL (irritating Oracle behaviour) - ok(!defined $tmp->{es}->{vc}, 'vc defined'); - ok(!defined $tmp->{es}->{c}, 'c defined'); - ok(!defined $tmp->{es}->{len}, 'len defined'); - is($tmp->{es}->{isnull}, 'ISNULL', 'ISNULL'); - - exit 1 if $test_info->{ti} || $test_info->{ts}; - } + next if $test_info->{SKIP}; + + my $ph_type = $test_info->{type} || die; + my $name = $test_info->{name} || die; + note("\ntesting @{[ %$test_info ]} ...\n\n"); + + SKIP: { + skip "skipping tests", 12 if ( $test_info->{SKIP} ); + + $dbh->{ora_ph_type} = $ph_type; + ok( $dbh->{ora_ph_type} == $ph_type, 'set ora_ph_type' ); + + $sth = $dbh->prepare("INSERT INTO $table(name,vc,c) VALUES (?,?,?)"); + $sth->trace( $test_info->{ti} ) if $test_info->{ti}; + $sth->execute( 'ts', $val_with_trailing_space, + $val_with_trailing_space ); + $sth->execute( 'en', $val_with_embedded_nul, $val_with_embedded_nul ); + $sth->execute( 'es', '', '' ); # empty string + $sth->trace(0) if $test_info->{ti}; + + $dbh->trace( $test_info->{ts} ) if $test_info->{ts}; + $tmp = $dbh->selectall_hashref( + qq{ + SELECT name, vc, length(vc) as len, nvl(vc,'ISNULL') as isnull, c + FROM $table}, 'name' + ); + ok( keys(%$tmp) == 3, 'right keys' ); + $dbh->trace(0) if $test_info->{ts}; + $dbh->rollback; + + delete $_->{name} foreach values %$tmp; + note( Data::Dumper::Dumper($tmp) ); + + # check trailing_space behaviour + my $expect = $val_with_trailing_space; + $expect =~ s/\s+$// if $test_info->{chops_space}; + my $ok = ( $tmp->{ts}->{vc} eq $expect ); + if ( !$ok && $ph_type == 1 && $name eq 'VARCHAR2' ) { + note +" Placeholder behaviour for ora_type=1 VARCHAR2 (the default) varies with Oracle version.\n" + . " Oracle 7 didn't strip trailing spaces, Oracle 8 did, until 9.2.x\n" + . " Your system doesn't. If that seems odd, let us know.\n"; + $ok = 1; + } + ok( + $ok, + sprintf( + " using ora_type %d expected %s but got %s for $name", + $ph_type, neat($expect), neat( $tmp->{ts}->{vc} ) + ) + ); + + # check embedded nul char behaviour + $expect = $val_with_embedded_nul; + $expect =~ s/\0.*// unless $test_info->{embed_nul}; + is( + $tmp->{en}->{vc}, + $expect, + sprintf( + " expected %s but got %s for $name", + neat($expect), neat( $tmp->{en}->{vc} ) + ) + ); + + # check empty string is NULL (irritating Oracle behaviour) + ok( !defined $tmp->{es}->{vc}, 'vc defined' ); + ok( !defined $tmp->{es}->{c}, 'c defined' ); + ok( !defined $tmp->{es}->{len}, 'len defined' ); + is( $tmp->{es}->{isnull}, 'ISNULL', 'ISNULL' ); + + exit 1 if $test_info->{ti} || $test_info->{ts}; + } } -ok($dbh->do("DROP TABLE $table"), 'drop table'); -ok($dbh->disconnect, 'disconnect'); +END { eval { drop_table($dbh,$table); $dbh->disconnect if $dbh }; } __END__ diff --git a/t/50cursor.t b/t/50cursor.t index b2fea460..93e05dc8 100644 --- a/t/50cursor.t +++ b/t/50cursor.t @@ -1,89 +1,108 @@ -#!perl -w +#!perl # From: Jeffrey Horn + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + use Test::More; use DBI; use DBD::Oracle qw(ORA_RSET); -use strict; - -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; $| = 1; -my ($limit, $tests); +my ( $limit, $tests ); -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', { PrintError => 0 }); +my $dbh = db_handle( { PrintError => 0 } ); if ($dbh) { + # ORA-00900: invalid SQL statement # ORA-06553: PLS-213: package STANDARD not accessible - my $tst = $dbh->prepare( - q{declare foo char(50); begin RAISE INVALID_NUMBER; end;}); - if ($dbh->err && ($dbh->err==900 || $dbh->err==6553 || $dbh->err==600)) { - warn "Your Oracle server doesn't support PL/SQL" if $dbh->err== 900; - warn "Your Oracle PL/SQL is not properly installed" - if $dbh->err==6553||$dbh->err==600; - plan skip_all => 'server does not support pl/sql or not installed'; + my $tst = + $dbh->prepare(q{declare foo char(50); begin RAISE INVALID_NUMBER; end;}); + if ( $dbh->err + && ( $dbh->err == 900 || $dbh->err == 6553 || $dbh->err == 600 ) ) + { + warn 'Your Oracle server doesn\'t support PL/SQL' if $dbh->err == 900; + warn 'Your Oracle PL/SQL is not properly installed' + if $dbh->err == 6553 || $dbh->err == 600; + plan skip_all => 'Server does not support pl/sql or not installed'; } $limit = $dbh->selectrow_array( q{SELECT value-2 FROM v$parameter WHERE name = 'open_cursors'}); + # allow for our open and close cursor 'cursors' $limit -= 2 if $limit && $limit >= 2; - unless (defined $limit) { # v$parameter open_cursors could be 0 :) - warn("Can't determine open_cursors from v\$parameter, so using default\n"); + unless ( defined $limit ) { # v$parameter open_cursors could be 0 :) + warn( + "Can't determine open_cursors from v\$parameter, so using default\n" + ); $limit = 1; } - $limit = 100 if $limit > 100; # lets not be greedy or upset DBA's + $limit = 100 if $limit > 100; # lets not be greedy or upset DBA's $tests = 2 + 10 * $limit + 6; plan tests => $tests; note "Max cursors: $limit"; -} else { - plan skip_all => "Unable to connect to Oracle"; +} +else { + plan skip_all => 'Unable to connect to Oracle'; } my @cursors; my @row; note("opening cursors\n"); -my $open_cursor = $dbh->prepare( qq{ - BEGIN OPEN :kursor FOR - SELECT * FROM all_objects WHERE rownum < 5; - END; -} ); -ok($open_cursor, 'open cursor' ); +my $open_cursor = $dbh->prepare(qq{ +BEGIN OPEN :kursor FOR + SELECT * FROM all_objects WHERE rownum < 5; +END; +} +); +ok( $open_cursor, 'open cursor' ); foreach ( 1 .. $limit ) { - note("opening cursor $_\n"); - ok( $open_cursor->bind_param_inout( ":kursor", \my $cursor, 0, { ora_type => ORA_RSET } ), 'open cursor bind param inout' ); - ok( $open_cursor->execute, 'open cursor execute' ); - ok(!$open_cursor->{Active}, 'open cursor Active'); - - ok($cursor->{Active}, 'cursor Active' ); - ok($cursor->fetchrow_arrayref, 'cursor fetcharray'); - ok($cursor->fetchrow_arrayref, 'cursor fetcharray'); - ok($cursor->finish, 'cursor finish' ); # finish early - ok(!$cursor->{Active}, 'cursor not Active'); - - push @cursors, $cursor; + note("opening cursor $_\n"); + ok( + $open_cursor->bind_param_inout( + ':kursor', \my $cursor, 0, { ora_type => ORA_RSET } + ), + 'open cursor bind param inout' + ); + ok( $open_cursor->execute, 'open cursor execute' ); + ok( !$open_cursor->{Active}, 'open cursor Active' ); + + ok( $cursor->{Active}, 'cursor Active' ); + ok( $cursor->fetchrow_arrayref, 'cursor fetcharray' ); + ok( $cursor->fetchrow_arrayref, 'cursor fetcharray' ); + ok( $cursor->finish, 'cursor finish' ); # finish early + ok( !$cursor->{Active}, 'cursor not Active' ); + + push @cursors, $cursor; } note("closing cursors\n"); -my $close_cursor = $dbh->prepare( qq{ BEGIN CLOSE :kursor; END; } ); -ok($close_cursor, 'close cursor'); +my $close_cursor = $dbh->prepare(qq{ BEGIN CLOSE :kursor; END; }); +ok( $close_cursor, 'close cursor' ); foreach ( 1 .. @cursors ) { - print "closing cursor $_\n"; - my $cursor = $cursors[$_-1]; - ok($close_cursor->bind_param( ":kursor", $cursor, { ora_type => ORA_RSET }), 'close cursor bind param'); - ok($close_cursor->execute, 'close cursor execute'); + print "closing cursor $_\n"; + my $cursor = $cursors[ $_ - 1 ]; + ok( + $close_cursor->bind_param( + ':kursor', $cursor, { ora_type => ORA_RSET } + ), + 'close cursor bind param' + ); + ok( $close_cursor->execute, 'close cursor execute' ); } -my $PLSQL = <<"PLSQL"; +my $PLSQL = <<'PLSQL'; DECLARE TYPE t IS REF CURSOR; c t; @@ -92,16 +111,10 @@ BEGIN END; PLSQL -ok(my $sth1 = $dbh->prepare($PLSQL), - 'prepare exec of proc for null cursor'); -ok($sth1->bind_param_inout(1, \my $cursor, 100, {ora_type => ORA_RSET}), - 'binding cursor for null cursor'); -ok($sth1->execute, 'execute for null cursor'); -is($cursor, undef, 'undef returned for null cursor'); -ok($sth1->execute, 'execute 2 for null cursor'); -is($cursor, undef, 'undef 2 returned for null cursor'); - -$dbh->disconnect; - -exit 0; - +ok( my $sth1 = $dbh->prepare($PLSQL), 'prepare exec of proc for null cursor' ); +ok( $sth1->bind_param_inout( 1, \my $cursor, 100, { ora_type => ORA_RSET } ), + 'binding cursor for null cursor' ); +ok( $sth1->execute, 'execute for null cursor' ); +is( $cursor, undef, 'undef returned for null cursor' ); +ok( $sth1->execute, 'execute 2 for null cursor' ); +is( $cursor, undef, 'undef 2 returned for null cursor' ); diff --git a/t/51scroll.t b/t/51scroll.t index a4900baf..eba4e2b1 100644 --- a/t/51scroll.t +++ b/t/51scroll.t @@ -1,13 +1,15 @@ -#!/usr/bin/perl +#!perl use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn table drop_table db_handle force_drop_table /; + use Test::More; use DBD::Oracle qw(:ora_types :ora_fetch_orient :ora_exe_modes); use DBI; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - ## ---------------------------------------------------------------------------- ## 51scroll.t ## By John Scoles, The Pythian Group @@ -17,125 +19,123 @@ require 'nchar_test_lib.pl'; ## ---------------------------------------------------------------------------- # create a database handle -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, - AutoCommit=>1, - PrintError => 0 })}; +my $dbh = eval { db_handle( { + RaiseError => 1, + AutoCommit => 1, + PrintError => 0 + })}; if ($dbh) { - plan skip_all => "Scrollable cursors new in Oracle 9" - if $dbh->func('ora_server_version')->[0] < 9; + plan skip_all => 'Scrollable cursors new in Oracle 9' + if $dbh->func('ora_server_version')->[0] < 9; plan tests => 37; -} else { - plan skip_all => "Unable to connect to Oracle"; } -ok ($dbh->{RowCacheSize} = 10); +else { + plan skip_all => 'Unable to connect to Oracle'; +} +ok( $dbh->{RowCacheSize} = 10 ); # check that our db handle is good -isa_ok($dbh, "DBI::db"); +isa_ok( $dbh, 'DBI::db' ); my $table = table(); +eval { force_drop_table( $dbh, $table ) }; +$dbh->do(qq{ CREATE TABLE $table ( id INTEGER ) }); -$dbh->do(qq{ - CREATE TABLE $table ( - id INTEGER ) - }); - +my ( $sql, $sth, $value ); +my $i = 0; +$sql = "INSERT INTO $table VALUES (?)"; -my ($sql, $sth,$value); -my $i=0; -$sql = "INSERT INTO ".$table." VALUES (?)"; +$sth = $dbh->prepare($sql); -$sth =$dbh-> prepare($sql); +$sth->execute($_) foreach ( 1 .. 10 ); -$sth->execute($_) foreach (1..10); - -$sql="select * from ".$table; -ok($sth=$dbh->prepare($sql, - {ora_exe_mode=>OCI_STMT_SCROLLABLE_READONLY, - ora_prefetch_memory=>200})); -ok ($sth->execute()); +$sql = "select * from $table"; +ok( + $sth = $dbh->prepare( + $sql, + { + ora_exe_mode => OCI_STMT_SCROLLABLE_READONLY, + ora_prefetch_memory => 200 + } + ) +); +ok( $sth->execute() ); #first loop all the way forward with OCI_FETCH_NEXT -foreach (1..10) { - $value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT,0); - is($value->[0], $_, '... we should get the next record'); +foreach ( 1 .. 10 ) { + $value = $sth->ora_fetch_scroll( OCI_FETCH_NEXT, 0 ); + is( $value->[0], $_, '... we should get the next record' ); } -$value = $sth->ora_fetch_scroll(OCI_FETCH_CURRENT,0); -cmp_ok($value->[0], '==', 10, '... we should get the 10th record'); +$value = $sth->ora_fetch_scroll( OCI_FETCH_CURRENT, 0 ); +cmp_ok( $value->[0], '==', 10, '... we should get the 10th record' ); # fetch off the end of the result-set -$value = $sth->ora_fetch_scroll(OCI_FETCH_NEXT, 0); -is($value, undef, "end of result-set"); +$value = $sth->ora_fetch_scroll( OCI_FETCH_NEXT, 0 ); +is( $value, undef, 'end of result-set' ); #now loop all the way back -for($i=1;$i<=9;$i++){ - $value = $sth->ora_fetch_scroll(OCI_FETCH_PRIOR,0); - cmp_ok($value->[0], '==', 10-$i, '... we should get the prior record'); +for ( $i = 1 ; $i <= 9 ; $i++ ) { + $value = $sth->ora_fetch_scroll( OCI_FETCH_PRIOR, 0 ); + cmp_ok( $value->[0], '==', 10 - $i, '... we should get the prior record' ); } #now +4 records relative from the present position of 0; -$value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,4); -cmp_ok($value->[0], '==', 5, '... we should get the 5th record'); +$value = $sth->ora_fetch_scroll( OCI_FETCH_RELATIVE, 4 ); +cmp_ok( $value->[0], '==', 5, '... we should get the 5th record' ); #now +2 records relative from the present position of 4; -$value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,2); -cmp_ok($value->[0], '==', 7, '... we should get the 7th record'); +$value = $sth->ora_fetch_scroll( OCI_FETCH_RELATIVE, 2 ); +cmp_ok( $value->[0], '==', 7, '... we should get the 7th record' ); #now -3 records relative from the present position of 6; -$value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,-3); +$value = $sth->ora_fetch_scroll( OCI_FETCH_RELATIVE, -3 ); -cmp_ok($value->[0], '==', 4, '... we should get the 4th record'); +cmp_ok( $value->[0], '==', 4, '... we should get the 4th record' ); #now get the 9th record from the start -$value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE,9); +$value = $sth->ora_fetch_scroll( OCI_FETCH_ABSOLUTE, 9 ); -cmp_ok($value->[0], '==', 9, '... we should get the 9th record'); +cmp_ok( $value->[0], '==', 9, '... we should get the 9th record' ); #now get the last record -$value = $sth->ora_fetch_scroll(OCI_FETCH_LAST,0); +$value = $sth->ora_fetch_scroll( OCI_FETCH_LAST, 0 ); -cmp_ok($value->[0], '==', 10, '... we should get the 10th record'); +cmp_ok( $value->[0], '==', 10, '... we should get the 10th record' ); #now get the ora_scroll_position -cmp_ok($sth->ora_scroll_position(), '==', 10, '... we should get the 10 for the ora_scroll_position'); +cmp_ok( $sth->ora_scroll_position(), + '==', 10, '... we should get the 10 for the ora_scroll_position' ); #now back to the first -$value = $sth->ora_fetch_scroll(OCI_FETCH_FIRST,0); -cmp_ok($value->[0], '==', 1, '... we should get the 1st record'); +$value = $sth->ora_fetch_scroll( OCI_FETCH_FIRST, 0 ); +cmp_ok( $value->[0], '==', 1, '... we should get the 1st record' ); #check the ora_scroll_position one more time -cmp_ok($sth->ora_scroll_position(), '==', 1, '... we should get the 1 for the ora_scroll_position'); +cmp_ok( $sth->ora_scroll_position(), + '==', 1, '... we should get the 1 for the ora_scroll_position' ); # rt 76695 - fetch after fetch scroll maintains offset # now fetch forward 2 places then just call fetch # it should give us the 4th rcord and not the 5th -$value = $sth->ora_fetch_scroll(OCI_FETCH_RELATIVE,2); -is($value->[0], 3, '... we should get the 3rd record rt76695'); +$value = $sth->ora_fetch_scroll( OCI_FETCH_RELATIVE, 2 ); +cmp_ok( $value->[0], '==', 3, '... we should get the 3rd record rt76695' ); ($value) = $sth->fetchrow; -is($value, 4, '... we should get the 4th record rt 76695'); +cmp_ok( $value, '==', 4, '... we should get the 4th record rt 76695' ); # rt 76410 - fetch after fetch absolute always returns the same row -$value = $sth->ora_fetch_scroll(OCI_FETCH_ABSOLUTE, 2); -is($value->[0], 2, "... we should get the 2nd row rt76410_2"); +$value = $sth->ora_fetch_scroll( OCI_FETCH_ABSOLUTE, 2 ); +cmp_ok( $value->[0], '==', 2, '... we should get the 2nd row rt76410_2' ); ($value) = $sth->fetchrow; -is($value, 3, "... we should get the 3rd row rt76410_2"); +cmp_ok( $value, '==', 3, '... we should get the 3rd row rt76410_2' ); $sth->finish(); -drop_table($dbh); - - -$dbh->disconnect; - -1; - +drop_table($dbh, $table); diff --git a/t/55nested.t b/t/55nested.t index a311d80c..276586f8 100644 --- a/t/55nested.t +++ b/t/55nested.t @@ -1,23 +1,25 @@ -#!perl -w +#!perl + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + use Test::More; use DBI; use DBD::Oracle qw(ORA_RSET); -use strict; - -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; $| = 1; -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', { PrintError => 0 }); +my $dbh = db_handle( { PrintError => 0 } ); if ($dbh) { - plan tests=> 29; -} else { - plan skip_all =>"Unable to connect to Oracle"; + plan tests => 29; +} +else { + plan skip_all => 'Unable to connect to Oracle'; } # ref cursors may be slow due to oracle bug 3735785 @@ -26,56 +28,60 @@ if ($dbh) { # 10.1.0.4 (Server Patch Set) # 10.2.0.1 (Base Release) -my $outer = $dbh->prepare(q{ +{ + +my $outer = $dbh->prepare( + q{ SELECT object_name, CURSOR(SELECT object_name FROM dual) - FROM all_objects WHERE rownum <= 5}); -ok($outer, 'prepare select'); + FROM all_objects WHERE rownum <= 5} +); +ok( $outer, 'prepare select' ); -ok( $outer->{ora_types}[1] == ORA_RSET, 'set ORA_RSET'); -ok( $outer->execute, 'outer execute'); -ok( my @row1 = $outer->fetchrow_array, 'outer fetchrow'); +ok( $outer->{ora_types}[1] == ORA_RSET, 'set ORA_RSET' ); +ok( $outer->execute, 'outer execute' ); +ok( my @row1 = $outer->fetchrow_array, 'outer fetchrow' ); my $inner1 = $row1[1]; -is( ref $inner1, 'DBI::st', 'inner DBI::st'); -ok( $inner1->{Active}, 'inner Active'); -ok( my @row1_1 = $inner1->fetchrow_array, 'inner fetchrow_array'); -is( $row1[0], $row1_1[0], 'rows equal'); -ok( $inner1->{Active}, 'inner Active'); -ok(my @row2 = $outer->fetchrow_array, 'outer fetchrow_array'); -ok(!$inner1->{Active}, 'inner not Active'); -ok(!$inner1->fetch, 'inner fetch finished'); -is($dbh->err, -1, 'err = -1'); -like($dbh->errstr, qr/ defunct /, 'defunct'); -ok($outer->finish, 'outer finish'); -is($dbh->{ActiveKids}, 0, 'ActiveKids'); +is( ref $inner1, 'DBI::st', 'inner DBI::st' ); +ok( $inner1->{Active}, 'inner Active' ); +ok( my @row1_1 = $inner1->fetchrow_array, 'inner fetchrow_array' ); +is( $row1[0], $row1_1[0], 'rows equal' ); +ok( $inner1->{Active}, 'inner Active' ); +ok( my @row2 = $outer->fetchrow_array, 'outer fetchrow_array' ); +ok( !$inner1->{Active}, 'inner not Active' ); +ok( !$inner1->fetch, 'inner fetch finished' ); +is( $dbh->err, -1, 'err = -1' ); +like( $dbh->errstr, qr/ defunct /, 'defunct' ); +ok( $outer->finish, 'outer finish' ); +is( $dbh->{ActiveKids}, 0, 'ActiveKids' ); ######################################################################### # Same test again but this time with 2 cursors ######################################################################### -$outer = $dbh->prepare(q{ - SELECT object_name, +$outer = $dbh->prepare( + q{ + SELECT object_name, CURSOR(SELECT object_name FROM dual), CURSOR(SELECT object_name FROM dual) - FROM all_objects WHERE rownum <= 5}); -ok($outer, 'prepare select'); - -ok( $outer->{ora_types}[1] == ORA_RSET, 'set ORA_RSET'); -ok( $outer->{ora_types}[2] == ORA_RSET, 'set ORA_RSET'); -ok( $outer->execute, 'outer execute'); -ok( @row1 = $outer->fetchrow_array, 'outer fetchrow'); + FROM all_objects WHERE rownum <= 5} +); +ok( $outer, 'prepare select' ); + +ok( $outer->{ora_types}[1] == ORA_RSET, 'set ORA_RSET' ); +ok( $outer->{ora_types}[2] == ORA_RSET, 'set ORA_RSET' ); +ok( $outer->execute, 'outer execute' ); +ok( @row1 = $outer->fetchrow_array, 'outer fetchrow' ); $inner1 = $row1[1]; my $inner2 = $row1[2]; -is( ref $inner1, 'DBI::st', 'inner DBI::st'); -is( ref $inner2, 'DBI::st', 'inner DBI::st'); - -ok( $inner1->{Active}, 'inner Active'); -ok( $inner2->{Active}, 'inner Active'); -ok( @row1_1 = $inner1->fetchrow_array, 'inner fetchrow_array'); -ok( my @row2_1 = $inner2->fetchrow_array, 'inner fetchrow_array'); -is( $row1[0], $row1_1[0], 'rows equal'); -is( $row1[0], $row2_1[0], 'rows equal'); - +is( ref $inner1, 'DBI::st', 'inner DBI::st' ); +is( ref $inner2, 'DBI::st', 'inner DBI::st' ); +ok( $inner1->{Active}, 'inner Active' ); +ok( $inner2->{Active}, 'inner Active' ); +ok( @row1_1 = $inner1->fetchrow_array, 'inner fetchrow_array' ); +ok( my @row2_1 = $inner2->fetchrow_array, 'inner fetchrow_array' ); +is( $row1[0], $row1_1[0], 'rows equal' ); +is( $row1[0], $row2_1[0], 'rows equal' ); ######################################################################### # Fetch speed test: START @@ -84,15 +90,15 @@ is( $row1[0], $row2_1[0], 'rows equal'); $dbh->{RaiseError} = 1; sub timed_fetch { - my ($rs,$caption) = @_; - my $row_count = 0; - my $tm_start = DBI::dbi_time(); - $row_count++ while $rs->fetch; - my $elapsed = DBI::dbi_time() - $tm_start; + my ( $rs, $caption ) = @_; + my $row_count = 0; + my $tm_start = DBI::dbi_time(); + $row_count++ while $rs->fetch; + my $elapsed = DBI::dbi_time() - $tm_start; - note "Fetched $row_count rows ($caption): $elapsed secs."; + note "Fetched $row_count rows ($caption): $elapsed secs."; - return $elapsed; + return $elapsed; } ################################################## @@ -101,11 +107,11 @@ sub timed_fetch { my $sql1 = q{ SELECT object_name FROM (SELECT object_name FROM all_objects WHERE ROWNUM<=70), - (SELECT 1 FROM all_objects WHERE ROWNUM<=70) + (SELECT 1 FROM all_objects WHERE ROWNUM<=70) }; $outer = $dbh->prepare($sql1); $outer->execute(); -my $dur_std = timed_fetch($outer,'select'); +my $dur_std = timed_fetch( $outer, 'select' ); ################################################## # nested cursor @@ -113,11 +119,10 @@ my $dur_std = timed_fetch($outer,'select'); $outer = $dbh->prepare("SELECT CURSOR($sql1) FROM DUAL"); $outer->execute(); my $ref_csr = $outer->fetchrow_arrayref->[0]; -my $dur_ref = timed_fetch($ref_csr,'nested cursor'); +my $dur_ref = timed_fetch( $ref_csr, 'nested cursor' ); ######################################################################### # Fetch speed test: END ######################################################################### -exit 0; - +} diff --git a/t/56embbeded.t b/t/56embbeded.t index d495b663..4ba67303 100644 --- a/t/56embbeded.t +++ b/t/56embbeded.t @@ -1,13 +1,15 @@ -#!perl -w +#!perl + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle force_drop_table drop_table table /; use DBI; use DBD::Oracle qw(ORA_RSET SQLCS_NCHAR); -use strict; use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - $| = 1; ## ---------------------------------------------------------------------------- @@ -15,67 +17,50 @@ $| = 1; ## By John Scoles, The Pythian Group ## ---------------------------------------------------------------------------- ## Just a few checks to see if I can select embedded objectes with Oracle::DBD -## Nothing fancy. +## Nothing fancy. ## ---------------------------------------------------------------------------- # create a database handle -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, - AutoCommit=>1, - PrintError => 0 })}; +my $dbh = eval{ db_handle( { RaiseError => 1, AutoCommit => 1, PrintError => 0 } )}; + if ($dbh) { plan tests => 4; -} else { - plan skip_all => "Unable to connect to Oracle"; } - +else { + plan skip_all => 'Unable to connect to Oracle'; +} # check that our db handle is good -isa_ok($dbh, "DBI::db"); +isa_ok( $dbh, 'DBI::db' ); -my $table = "table_embed"; -my $type = $table.'a_type'; +my $table = table('table_embed'); +my $type = $table . 'a_type'; #do not warn if already there -eval { - local $dbh->{PrintError} = 0; - $dbh->do(qq{drop TABLE $table }); -}; -eval { - local $dbh->{PrintError} = 0; - $dbh->do(qq{drop TYPE $type }); +eval { + local $dbh->{PrintError} = 0; + force_drop_table( $dbh, $table ); + $dbh->do(qq{DROP TYPE $type }); }; -$dbh->do(qq{CREATE or replace TYPE $type as varray(10) of varchar(30) }); - -$dbh->do(qq{ - CREATE TABLE $table - ( aa_type $type) - }); - -$dbh->do("insert into $table values ($type('1','2','3','4','5'))"); +$dbh->do(qq{CREATE OR REPLACE TYPE $type AS varray(10) OF varchar(30) }); +$dbh->do(qq{ CREATE TABLE $table ( aa_type $type) }); +$dbh->do("insert into $table values ($type('1','2','3','4','5'))"); # simple execute my $sth; -ok ($sth = $dbh->prepare("select * from $table"), '... Prepare should return true'); +ok( $sth = $dbh->prepare("select * from $table"), + '... Prepare should return true' ); my $problems; -ok ($sth->execute(), '... Select should return true'); +ok( $sth->execute(), '... Select should return true' ); -while (my ($a)=$sth->fetchrow()){ - $problems= scalar(@$a); +while ( my ($a) = $sth->fetchrow() ) { + $problems = scalar(@$a); } -cmp_ok(scalar($problems), '==',5, '... we should have 5 items'); - - -$dbh->do("drop table $table"); - -$dbh->do("drop type $type"); - -$dbh->disconnect; +cmp_ok( scalar($problems), '==', 5, '... we should have 5 items' ); -1; +drop_table($dbh, $table); +$dbh->do("drop type $type") unless $ENV{DBD_SKIP_TABLE_DROP}; diff --git a/t/58object.t b/t/58object.t index 4f950c01..9d39defc 100644 --- a/t/58object.t +++ b/t/58object.t @@ -1,62 +1,78 @@ -#!perl -w +#!perl + +use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; use DBI; use DBD::Oracle qw(ORA_RSET SQLCS_NCHAR); -use strict; -use Data::Dumper; use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; $| = 1; $ENV{NLS_DATE_FORMAT} = 'YYYY-MM-DD"T"HH24:MI:SS'; # create a database handle -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh; -eval {$dbh = DBI->connect($dsn, $dbuser, '',{ RaiseError=>1, - AutoCommit=>1, - PrintError => 0, - ora_objects => 1 })}; +my $dbh = eval{ db_handle( { + RaiseError => 1, + AutoCommit => 1, + PrintError => 0, + ora_objects => 1 + })}; -plan skip_all => "Unable to connect to Oracle" unless $dbh; +plan skip_all => 'Unable to connect to Oracle' unless $dbh; plan tests => 65; +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my ($schema) = $dbuser =~ m{^([^/]*)}; -# Test ora_objects flag +# Test ora_objects flag is $dbh->{ora_objects} => 1, 'ora_objects flag is set to 1'; $dbh->{ora_objects} = 0; is $dbh->{ora_objects} => 0, 'ora_objects flag is set to 0'; # check that our db handle is good -isa_ok($dbh, "DBI::db"); - +isa_ok( $dbh, 'DBI::db' ); -ok( $schema = $dbh->selectrow_array( - "select sys_context('userenv', 'current_schema') from dual" -), 'Fetch current schema name'); - +ok( + $schema = $dbh->selectrow_array( + q|select sys_context('userenv', 'current_schema') from dual|), + 'Fetch current schema name' +); -my $obj_prefix = "dbd_test_"; +my $obj_prefix = 'dbd_test_' . ( $ENV{DBD_ORACLE_SEQ} || '' ); my $super_type = "${obj_prefix}_type_A"; -my $sub_type = "${obj_prefix}_type_B"; -my $table = "${obj_prefix}_obj_table"; +my $sub_type = "${obj_prefix}_type_B"; +my $table = "${obj_prefix}_obj_table"; my $outer_type = "${obj_prefix}_outer_type"; my $inner_type = "${obj_prefix}_inner_type"; -my $list_type = "${obj_prefix}_list_type"; +my $list_type = "${obj_prefix}_list_type"; my $nest_table = "${obj_prefix}_nest_table"; my $list_table = "${obj_prefix}_list_table"; +sub sql_do_ok { + my ( $dbh, $sql, $title ) = @_; + $title = $sql unless defined $title; + ok( $dbh->do($sql), $title ) or diag $dbh->errstr; +} + sub drop_test_objects { - for my $obj ("TABLE $list_table", "TABLE $nest_table", - "TYPE $list_type", "TYPE $outer_type", "TYPE $inner_type", - "TABLE $table", "TYPE $sub_type", "TYPE $super_type") { + for my $obj ( + "TABLE $list_table", + "TABLE $nest_table", + "TYPE $list_type", + "TYPE $outer_type", + "TYPE $inner_type", + "TABLE $table", + "TYPE $sub_type", + "TYPE $super_type" + ) + { #do not warn if already there eval { local $dbh->{PrintError} = 0; @@ -68,206 +84,274 @@ sub drop_test_objects { &drop_test_objects; # get the user's privileges -my $privs_sth = $dbh->prepare( 'SELECT PRIVILEGE from session_privs' ); +my $privs_sth = $dbh->prepare('SELECT PRIVILEGE from session_privs'); $privs_sth->execute; my @privileges = map { $_->[0] } @{ $privs_sth->fetchall_arrayref }; -my $ora8 = $dbh->func('ora_server_version')->[0] < 9; -my $final = $ora8 ? '':'FINAL'; -my $not_final = $ora8 ? '':'NOT FINAL'; +my $ora8 = $dbh->func('ora_server_version')->[0] < 9; +my $final = $ora8 ? '' : 'FINAL'; +my $not_final = $ora8 ? '' : 'NOT FINAL'; SKIP: { skip q{don't have permission to create type} => 61 - unless grep { $_ eq 'CREATE TYPE' } @privileges; + unless grep { $_ eq 'CREATE TYPE' } @privileges; -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $super_type AS OBJECT ( + sql_do_ok( + $dbh, qq{ CREATE OR REPLACE TYPE $super_type AS OBJECT ( num INTEGER, name VARCHAR2(20) - ) $not_final } ); + ) $not_final } + ); -SKIP: { - skip 'Subtypes new in Oracle 9' => 1 if $ora8; -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $sub_type UNDER $super_type ( + SKIP: { + skip 'Subtypes new in Oracle 9' => 1 if $ora8; + sql_do_ok( + $dbh, qq{ CREATE OR REPLACE TYPE $sub_type UNDER $super_type ( datetime DATE, amount NUMERIC(10,5) - ) $not_final } ); -} -sql_do_ok( $dbh, qq{ CREATE TABLE $table (id INTEGER, obj $super_type) }); - -sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (1, $super_type(13, 'obj1')) }); -SKIP: { - skip 'Subtypes new in Oracle 9' => 2 if $ora8; -sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (2, $sub_type(NULL, 'obj2', + ) $not_final } + ); + } + sql_do_ok( $dbh, qq{ CREATE TABLE $table (id INTEGER, obj $super_type) } ); + + sql_do_ok( $dbh, + qq{ INSERT INTO $table VALUES (1, $super_type(13, 'obj1')) } ); + SKIP: { + skip 'Subtypes new in Oracle 9' => 2 if $ora8; + sql_do_ok( + $dbh, qq{ INSERT INTO $table VALUES (2, $sub_type(NULL, 'obj2', TO_DATE('2004-11-30 14:27:18', 'YYYY-MM-DD HH24:MI:SS'), 12345.6789)) } - ); + ); -sql_do_ok( $dbh, qq{ INSERT INTO $table VALUES (3, $sub_type(5, 'obj3', NULL, - 777.666)) } ); -} -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $inner_type AS OBJECT ( + sql_do_ok( + $dbh, qq{ INSERT INTO $table VALUES (3, $sub_type(5, 'obj3', NULL, + 777.666)) } + ); + } + sql_do_ok( + $dbh, qq{ CREATE OR REPLACE TYPE $inner_type AS OBJECT ( num INTEGER, name VARCHAR2(20) - ) $final }); + ) $final } + ); -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $outer_type AS OBJECT ( + sql_do_ok( + $dbh, qq{ CREATE OR REPLACE TYPE $outer_type AS OBJECT ( num INTEGER, obj $inner_type - ) $final }); - -sql_do_ok( $dbh, qq{ CREATE OR REPLACE TYPE $list_type AS - TABLE OF $inner_type }); - -sql_do_ok( $dbh, qq{ CREATE TABLE $nest_table(obj $outer_type) }); - -sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(91, $inner_type(1, 'one'))) } - ); - -sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(92, $inner_type(0, null))) } - ); - -sql_do_ok( $dbh, qq{ INSERT INTO $nest_table VALUES($outer_type(93, null)) } -); - -sql_do_ok( $dbh, qq{ CREATE TABLE $list_table ( id INTEGER, list $list_type ) - NESTED TABLE list STORE AS ${list_table}_list }); - -sql_do_ok( $dbh, qq{ INSERT INTO $list_table VALUES(81,$list_type($inner_type(null, 'listed'))) } ); -# Test old (backward compatible) interface - -# test select testing objects -my $sth = $dbh->prepare("select * from $table order by id"); -ok ($sth, 'old: Prepare select'); -ok ($sth->execute(), 'old: Execute select'); - -my ( @row1, @row2, @row3 ); -@row1 = $sth->fetchrow(); -ok (scalar @row1, 'old: Fetch first row'); -cmp_ok(ref $row1[1], 'eq', 'ARRAY', 'old: Row 1 column 2 is an ARRAY'); -cmp_ok(scalar(@{$row1[1]}), '==', 2, 'old: Row 1 column 2 is has 2 elements'); -SKIP: { - skip 'Subtypes new in Oracle 9' => 6 if $ora8; -@row2 = $sth->fetchrow(); -ok (scalar @row2, 'old: Fetch second row'); -cmp_ok(ref $row2[1], 'eq', 'ARRAY', 'old: Row 2 column 2 is an ARRAY'); -cmp_ok(scalar(@{$row2[1]}), '==', 2, 'old: Row 2 column 2 is has 2 elements'); - -@row3 = $sth->fetchrow(); -ok (scalar @row3, 'old: Fetch third row'); -cmp_ok(ref $row3[1], 'eq', 'ARRAY', 'old: Row 3 column 2 is an ARRAY'); -cmp_ok(scalar(@{$row3[1]}), '==', 2, 'old: Row 3 column 2 is has 2 elements'); -} -ok (!$sth->fetchrow(), 'old: No more rows expected'); - -#print STDERR Dumper(\@row1, \@row2, \@row3); - -# Test new (extended) object interface - -# enable extended object support -$dbh->{ora_objects} = 1; - -# test select testing objects - in extended mode -$sth = $dbh->prepare("select * from $table order by id"); -ok ($sth, 'new: Prepare select'); -ok ($sth->execute(), 'new: Execute select'); - - -@row1 = $sth->fetchrow(); -ok (scalar @row1, 'new: Fetch first row'); -cmp_ok(ref $row1[1], 'eq', 'DBD::Oracle::Object', 'new: Row 1 column 2 is an DBD:Oracle::Object'); -cmp_ok(uc $row1[1]->type_name, "eq", uc "$schema.$super_type", "new: Row 1 column 2 object type"); -is_deeply([$row1[1]->attributes], ['NUM', 13, 'NAME', 'obj1'], "new: Row 1 column 2 object attributes"); -SKIP: { - skip 'Subtypes new in Oracle 9' => 8 if $ora8; -@row2 = $sth->fetchrow(); -ok (scalar @row2, 'new: Fetch second row'); -cmp_ok(ref $row2[1], 'eq', 'DBD::Oracle::Object', 'new: Row 2 column 2 is an DBD::Oracle::Object'); -cmp_ok(uc $row2[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 2 column 2 object type"); - -my %attrs = $row2[1]->attributes; - -$attrs{AMOUNT} = sprintf "%9.4f", $attrs{AMOUNT}; - -is_deeply( \%attrs, {'NUM', undef, 'NAME', 'obj2', - 'DATETIME', '2004-11-30T14:27:18', 'AMOUNT', '12345.6789'}, "new: Row 1 column 2 object attributes"); - -@row3 = $sth->fetchrow(); -ok (scalar @row3, 'new: Fetch third row'); -cmp_ok(ref $row3[1], 'eq', 'DBD::Oracle::Object', 'new: Row 3 column 2 is an DBD::Oracle::Object'); -cmp_ok(uc $row3[1]->type_name, "eq", uc "$schema.$sub_type", "new: Row 3 column 2 object type"); - -%attrs = $row3[1]->attributes; -$attrs{AMOUNT} = sprintf "%6.3f", $attrs{AMOUNT}; - -is_deeply( \%attrs, {'NUM', 5, 'NAME', 'obj3', - 'DATETIME', undef, 'AMOUNT', '777.666'}, "new: Row 1 column 2 object attributes"); -} -ok (!$sth->fetchrow(), 'new: No more rows expected'); - -#print STDERR Dumper(\@row1, \@row2, \@row3); - -SKIP: { - skip 'Subtypes new in Oracle 9' => 3 if $ora8; -# Test DBD::Oracle::Object -my $obj = $row3[1]; -my $expected_hash = { - NUM => 5, - NAME => 'obj3', - DATETIME => undef, - AMOUNT => 777.666, - }; -my $attrs = $obj->attr_hash; -$attrs->{AMOUNT} = sprintf "%6.3f", $attrs->{AMOUNT}; - -is_deeply($attrs, $expected_hash, 'DBD::Oracle::Object->attr_hash'); -is_deeply($obj->attr, $expected_hash, 'DBD::Oracle::Object->attr'); -is($obj->attr("NAME"), 'obj3', 'DBD::Oracle::Object->attr("NAME")'); -} -# try the list table -$sth = $dbh->prepare("select * from $list_table"); -ok ($sth, 'new: Prepare select with nested table of objects'); -ok ($sth->execute(), 'new: Execute (nested table)'); - -@row1 = $sth->fetchrow(); -ok (scalar @row1, 'new: Fetch first row (nested table)'); -is_deeply($row1[1]->[0]->attr, {NUM=>undef, NAME=>'listed'}, - 'Check propertes of first (and only) item in nested table'); - -ok (!$sth->fetchrow(), 'new: No more rows expected (nested table)'); - -#try the nested table -$sth = $dbh->prepare("select * from $nest_table"); -ok ($sth, 'new: Prepare select with nested object'); -ok ($sth->execute(), 'new: Execute (nested object)'); - -@row1 = $sth->fetchrow(); -ok (scalar @row1, 'new: Fetch first row (nested object)'); -is($row1[0]->attr->{NUM}, '91', 'Check obj.num'); -is_deeply($row1[0]->attr->{OBJ}->attr, {NUM=>'1', NAME=>'one'}, 'Check obj.obj'); - -@row2 = $sth->fetchrow(); -ok (scalar @row2, 'new: Fetch second row (nested object)'); -is($row2[0]->attr->{NUM}, '92', 'Check obj.num'); -is_deeply($row2[0]->attr->{OBJ}->attr, {NUM=>'0', NAME=>undef}, 'Check obj.obj'); - -@row3 = $sth->fetchrow(); -ok (scalar @row3, 'new: Fetch third row (nested object)'); -is_deeply($row3[0]->attr, {NUM=>'93', OBJ=>undef}, 'Check obj'); + ) $final } + ); + + sql_do_ok( + $dbh, qq{ CREATE OR REPLACE TYPE $list_type AS + TABLE OF $inner_type } + ); + + sql_do_ok( $dbh, qq{ CREATE TABLE $nest_table(obj $outer_type) } ); + + sql_do_ok( $dbh, +qq{ INSERT INTO $nest_table VALUES($outer_type(91, $inner_type(1, 'one'))) } + ); + + sql_do_ok( $dbh, +qq{ INSERT INTO $nest_table VALUES($outer_type(92, $inner_type(0, null))) } + ); + + sql_do_ok( $dbh, + qq{ INSERT INTO $nest_table VALUES($outer_type(93, null)) } ); + + sql_do_ok( + $dbh, qq{ CREATE TABLE $list_table ( id INTEGER, list $list_type ) + NESTED TABLE list STORE AS ${list_table}_list } + ); + + sql_do_ok( $dbh, +qq{ INSERT INTO $list_table VALUES(81,$list_type($inner_type(null, 'listed'))) } + ); + + # Test old (backward compatible) interface + + # test select testing objects + my $sth = $dbh->prepare("select * from $table order by id"); + ok( $sth, 'old: Prepare select' ); + ok( $sth->execute(), 'old: Execute select' ); + + my ( @row1, @row2, @row3 ); + @row1 = $sth->fetchrow(); + ok( scalar @row1, 'old: Fetch first row' ); + cmp_ok( ref $row1[1], 'eq', 'ARRAY', 'old: Row 1 column 2 is an ARRAY' ); + cmp_ok( scalar( @{ $row1[1] } ), + '==', 2, 'old: Row 1 column 2 is has 2 elements' ); + SKIP: { + skip 'Subtypes new in Oracle 9' => 6 if $ora8; + @row2 = $sth->fetchrow(); + ok( scalar @row2, 'old: Fetch second row' ); + cmp_ok( ref $row2[1], 'eq', 'ARRAY', + 'old: Row 2 column 2 is an ARRAY' ); + cmp_ok( scalar( @{ $row2[1] } ), + '==', 2, 'old: Row 2 column 2 is has 2 elements' ); + + @row3 = $sth->fetchrow(); + ok( scalar @row3, 'old: Fetch third row' ); + cmp_ok( ref $row3[1], 'eq', 'ARRAY', + 'old: Row 3 column 2 is an ARRAY' ); + cmp_ok( scalar( @{ $row3[1] } ), + '==', 2, 'old: Row 3 column 2 is has 2 elements' ); + } + ok( !$sth->fetchrow(), 'old: No more rows expected' ); + + #print STDERR Dumper(\@row1, \@row2, \@row3); + + # Test new (extended) object interface + + # enable extended object support + $dbh->{ora_objects} = 1; + + # test select testing objects - in extended mode + $sth = $dbh->prepare("select * from $table order by id"); + ok( $sth, 'new: Prepare select' ); + ok( $sth->execute(), 'new: Execute select' ); + + @row1 = $sth->fetchrow(); + ok( scalar @row1, 'new: Fetch first row' ); + cmp_ok( ref $row1[1], + 'eq', 'DBD::Oracle::Object', + 'new: Row 1 column 2 is an DBD:Oracle::Object' ); + cmp_ok( + uc $row1[1]->type_name, + 'eq', + uc "$schema.$super_type", + 'new: Row 1 column 2 object type' + ); + is_deeply( + [ $row1[1]->attributes ], + [ 'NUM', 13, 'NAME', 'obj1' ], + 'new: Row 1 column 2 object attributes' + ); + SKIP: { + skip 'Subtypes new in Oracle 9' => 8 if $ora8; + @row2 = $sth->fetchrow(); + ok( scalar @row2, 'new: Fetch second row' ); + cmp_ok( ref $row2[1], + 'eq', 'DBD::Oracle::Object', + 'new: Row 2 column 2 is an DBD::Oracle::Object' ); + cmp_ok( + uc $row2[1]->type_name, + 'eq', + uc "$schema.$sub_type", + 'new: Row 2 column 2 object type' + ); + + my %attrs = $row2[1]->attributes; + + $attrs{AMOUNT} = sprintf '%9.4f', $attrs{AMOUNT}; + + is_deeply( + \%attrs, + { + 'NUM', undef, + 'NAME', 'obj2', + 'DATETIME', '2004-11-30T14:27:18', + 'AMOUNT', '12345.6789' + }, + 'new: Row 1 column 2 object attributes' + ); + + @row3 = $sth->fetchrow(); + ok( scalar @row3, 'new: Fetch third row' ); + cmp_ok( ref $row3[1], + 'eq', 'DBD::Oracle::Object', + 'new: Row 3 column 2 is an DBD::Oracle::Object' ); + cmp_ok( + uc $row3[1]->type_name, + 'eq', + uc "$schema.$sub_type", + 'new: Row 3 column 2 object type' + ); + + %attrs = $row3[1]->attributes; + $attrs{AMOUNT} = sprintf '%6.3f', $attrs{AMOUNT}; + + is_deeply( + \%attrs, + { + 'NUM', 5, 'NAME', 'obj3', + 'DATETIME', undef, 'AMOUNT', '777.666' + }, + 'new: Row 1 column 2 object attributes' + ); + } + ok( !$sth->fetchrow(), 'new: No more rows expected' ); -ok (!$sth->fetchrow(), 'new: No more rows expected (nested object)'); + #print STDERR Dumper(\@row1, \@row2, \@row3); -} + SKIP: { + skip 'Subtypes new in Oracle 9' => 3 if $ora8; -#cleanup -&drop_test_objects; -$dbh->disconnect; + # Test DBD::Oracle::Object + my $obj = $row3[1]; + my $expected_hash = { + NUM => 5, + NAME => 'obj3', + DATETIME => undef, + AMOUNT => 777.666, + }; + my $attrs = $obj->attr_hash; + $attrs->{AMOUNT} = sprintf '%6.3f', $attrs->{AMOUNT}; -1; + is_deeply( $attrs, $expected_hash, 'DBD::Oracle::Object->attr_hash' ); + is_deeply( $obj->attr, $expected_hash, 'DBD::Oracle::Object->attr' ); + is( $obj->attr('NAME'), 'obj3', + q|DBD::Oracle::Object->attr(' NAME ')| ); + } + # try the list table + $sth = $dbh->prepare("select * from $list_table"); + ok( $sth, 'new: Prepare select with nested table of objects' ); + ok( $sth->execute(), 'new: Execute (nested table)' ); + + @row1 = $sth->fetchrow(); + ok( scalar @row1, 'new: Fetch first row (nested table)' ); + is_deeply( + $row1[1]->[0]->attr, + { NUM => undef, NAME => 'listed' }, + 'Check propertes of first (and only) item in nested table' + ); + + ok( !$sth->fetchrow(), 'new: No more rows expected (nested table)' ); + + #try the nested table + $sth = $dbh->prepare("select * from $nest_table"); + ok( $sth, 'new: Prepare select with nested object' ); + ok( $sth->execute(), 'new: Execute (nested object)' ); + + @row1 = $sth->fetchrow(); + ok( scalar @row1, 'new: Fetch first row (nested object)' ); + is( $row1[0]->attr->{NUM}, '91', 'Check obj.num' ); + is_deeply( + $row1[0]->attr->{OBJ}->attr, + { NUM => '1', NAME => 'one' }, + 'Check obj.obj' + ); + + @row2 = $sth->fetchrow(); + ok( scalar @row2, 'new: Fetch second row (nested object)' ); + is( $row2[0]->attr->{NUM}, '92', 'Check obj.num' ); + is_deeply( + $row2[0]->attr->{OBJ}->attr, + { NUM => '0', NAME => undef }, + 'Check obj.obj' + ); + + @row3 = $sth->fetchrow(); + ok( scalar @row3, 'new: Fetch third row (nested object)' ); + is_deeply( $row3[0]->attr, { NUM => '93', OBJ => undef }, 'Check obj' ); + + ok( !$sth->fetchrow(), 'new: No more rows expected (nested object)' ); -sub sql_do_ok { - my ( $dbh, $sql, $title ) = @_; - $title = $sql unless defined $title; - ok( $dbh->do( $sql ), $title ) or diag $dbh->errstr; } +#cleanup +&drop_test_objects unless $ENV{DBD_SKIP_TABLE_DROP}; +$dbh->disconnect if $dbh; # see also GH65 diff --git a/t/60reauth.t b/t/60reauth.t index b62fa43a..32a95611 100644 --- a/t/60reauth.t +++ b/t/60reauth.t @@ -1,37 +1,41 @@ -#!perl -w -use Test::More; +#!perl + +use strict; +use warnings; +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn /; + +use Test::More; use DBI; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; $| = 1; -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; my $dbuser_2 = $ENV{ORACLE_USERID_2} || ''; -if ($dbuser_2 eq '') { +if ( $dbuser_2 eq '' ) { plan skip_all => "ORACLE_USERID_2 not defined.\n"; } + # strip off @ on userid_2, as the reauth presumes current server $dbuser_2 =~ s/@.*//; -(my $uid1 = uc $dbuser) =~ s:/.*::; -(my $uid2 = uc $dbuser_2) =~ s:/.*::; -if ($uid1 eq $uid2) { +( my $uid1 = uc $dbuser ) =~ s:/.*::; +( my $uid2 = uc $dbuser_2 ) =~ s:/.*::; +if ( $uid1 eq $uid2 ) { plan skip_all => "ORACLE_USERID_2 not unique.\n"; } my $dsn = oracle_test_dsn(); -my $dbh = DBI->connect($dsn, $dbuser, ''); +my $dbh = DBI->connect( $dsn, $dbuser, '' ); if ($dbh) { plan tests => 3; -} else { +} +else { plan skip_all => "Unable to connect to Oracle\n"; } -is(($dbh->selectrow_array("SELECT USER FROM DUAL"))[0], $uid1, 'uid1' ); -ok($dbh->func($dbuser_2, '', 'reauthenticate'), 'reauthenticate'); -is(($dbh->selectrow_array("SELECT USER FROM DUAL"))[0], $uid2, 'uid2' ); - -$dbh->disconnect; +is( ( $dbh->selectrow_array('SELECT USER FROM DUAL') )[0], $uid1, 'uid1' ); +ok( $dbh->func( $dbuser_2, '', 'reauthenticate' ), 'reauthenticate' ); +is( ( $dbh->selectrow_array('SELECT USER FROM DUAL') )[0], $uid2, 'uid2' ); diff --git a/t/70meta.t b/t/70meta.t index 7c193357..5bc4977b 100644 --- a/t/70meta.t +++ b/t/70meta.t @@ -1,88 +1,96 @@ -#!perl -w -use Test::More; +#!perl use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle drop_table table force_drop_table /; + +use Test::More; use DBI qw(:sql_types); use Data::Dumper; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - $| = 1; -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; -my $dbh = DBI->connect($dsn, $dbuser, '', {PrintError => 0 }); +my $dbh = db_handle( { PrintError => 0 } ); if ($dbh) { - plan tests=>21; + plan tests => 20; $dbh->{RaiseError} = 1; -} else { - plan skip_all => "Unable to connect to Oracle"; +} +else { + plan skip_all => 'Unable to connect to Oracle'; } note("type_info_all\n"); my @types = $dbh->type_info(SQL_ALL_TYPES); -ok(@types >= 8, 'more than 8 types'); -note(Dumper( @types )); +cmp_ok( scalar @types, '>=', 8, 'more than 8 types' ); +note( Dumper(@types) ); note("tables():\n"); my @tables = $dbh->tables; -note(@tables." tables\n"); -ok(scalar @tables, 'tables'); +note( @tables . " tables\n" ); +ok( scalar @tables, 'some tables exist' ); my @table_info_params = ( - [ 'schema list', undef, '%', undef, undef ], - [ 'type list', undef, undef, undef, '%' ], - [ 'table list', undef, undef, undef, undef ], + [ 'schema list', undef, '%', undef, undef ], + [ 'type list', undef, undef, undef, '%' ], + [ 'table list', undef, undef, undef, undef ], ); -foreach my $table_info_params (@table_info_params) { + +for my $table_info_params (@table_info_params) { my ($name) = shift @$table_info_params; my $start = time; - note("$name: table_info(".DBI::neat_list($table_info_params).")\n"); + note( "$name: table_info(" . DBI::neat_list($table_info_params) . ")\n" ); my $table_info_sth = $dbh->table_info(@$table_info_params); - ok($table_info_sth, 'table_info'); + ok( $table_info_sth, 'table_info' ); my $data = $table_info_sth->fetchall_arrayref; - ok($data, 'table_info fetch'); - ok(scalar @$data, 'table_info data returned'); + ok( $data, 'table_info fetch' ); + ok( scalar @$data, 'table_info data returned' ); my $dur = time - $start; - note("$name: ".@$data." rows, $dur seconds\n"); + note( "$name: " . @$data . " rows, $dur seconds\n" ); } my $sql_dbms_version = $dbh->get_info(18); -ok($sql_dbms_version, 'dbms_version'); +ok( $sql_dbms_version, 'dbms_version' ); note "sql_dbms_version=$sql_dbms_version"; -like($sql_dbms_version, qr/^\d+\.\d+\.\d+$/, 'matched'); +like( $sql_dbms_version, qr/^\d+\.\d+\.\d+$/, 'version patterned matched' ); # test long DEFAULT from column_info SKIP: { - my $table = "dbd_ora__drop_me" . ($ENV{DBD_ORACLE_SEQ}||''); + my $table = table(); - eval { $dbh->do("DROP TABLE $table") }; + eval { force_drop_table( $dbh, $table ) }; # ok if its fails - my $created = eval { $dbh->do("CREATE TABLE $table (testcol NUMBER(15) DEFAULT to_number(decode(substrb(userenv('CLIENT_INFO'),1,1),' ', null,substrb(userenv('CLIENT_INFO'),1,10))))") }; + my $created = eval { + $dbh->do( +"CREATE TABLE $table (testcol NUMBER(15) DEFAULT to_number(decode(substrb(userenv('CLIENT_INFO'),1,1),' ', null,substrb(userenv('CLIENT_INFO'),1,10))))" + ); + }; - skip 'could not create test table', 8 unless $created; + die "Could not create test table $table\n" unless $created; - is $dbh->{LongReadLen}, 80, 'LongReadLen is at default'; + cmp_ok( $dbh->{LongReadLen}, '==', 80, 'LongReadLen is at default' ); - ok((my $sth = $dbh->column_info(undef, '%', uc($table), '%')), 'column_info sth'); + ok( ( my $sth = $dbh->column_info( undef, '%', uc($table), '%' ) ), + 'column_info sth' ); - is $dbh->{LongReadLen}, 80, 'LongReadLen still at default'; + cmp_ok( $dbh->{LongReadLen}, '==', 80, 'LongReadLen still at default' ); - ok((my $info = eval { $sth->fetchrow_hashref }), 'sth->fetchrow_hashref lived') - or diag $@; + ok( ( my $info = eval { $sth->fetchrow_hashref } ), + 'sth->fetchrow_hashref lived' ) + or diag $@; - is $info->{COLUMN_DEF}, "to_number(decode(substrb(userenv('CLIENT_INFO'),1,1),' ', null,substrb(userenv('CLIENT_INFO'),1,10)))", 'long DEFAULT matched'; + cmp_ok( + $info->{COLUMN_DEF}, + 'eq', +q|to_number(decode(substrb(userenv('CLIENT_INFO'),1,1),' ', null,substrb(userenv('CLIENT_INFO'),1,10)))|, + 'long DEFAULT matched' + ); - ok($sth->finish, 'sth->finish'); + ok( $sth->finish, 'sth->finish is true' ); - is $dbh->{LongReadLen}, 80, 'LongReadLen still at default'; + cmp_ok( $dbh->{LongReadLen}, 'eq', 80, 'LongReadLen still at default' ); - ok($dbh->do("DROP TABLE $table"), 'drop table'); + drop_table( $dbh, $table ); } - -$dbh->disconnect; - -exit 0; - diff --git a/t/80ora_charset.t b/t/80ora_charset.t index 6a7b8c63..b1654381 100644 --- a/t/80ora_charset.t +++ b/t/80ora_charset.t @@ -1,5 +1,13 @@ -#!perl -w +#!perl + use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ + table insert_test_count set_nls_lang_charset set_nls_nchar oracle_test_dsn + drop_table force_drop_table db_handle show_test_data create_table insert_rows + /; use Encode; use Devel::Peek; @@ -9,125 +17,112 @@ use DBD::Oracle qw(ORA_OCI); use Test::More; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - my $tdata = { cols => [ - [ 'ch', 'varchar2(20)', ], - [ 'nch', 'nvarchar2(20)', ], + [ 'ch', 'varchar2(20)', ], + [ 'nch', 'nvarchar2(20)', ], [ 'descr', 'varchar2(50)', ], ], 'dump' => 'DUMP(%s)', - rows => [ - [ - "\xb0", - "\xb0", - 'DEGREE SIGN', - ], - ], + rows => [ [ "\xb0", "\xb0", 'DEGREE SIGN', ], ], }; my $table = table(); -my $utf8_charset = (ORA_OCI >= 9.2) ? 'AL32UTF8' : 'UTF8'; +my $utf8_charset = ( ORA_OCI >= 9.2 ) ? 'AL32UTF8' : 'UTF8'; my $eight_bit_charset = 'WE8ISO8859P1'; my $dbh_utf8; my $dbh; SKIP: { - plan skip_all => "Oracle 9.2 or newer required" unless ORA_OCI >= 9.2; + plan skip_all => 'Oracle 9.2 or newer required' unless ORA_OCI >= 9.2; + + if ( $ENV{ORA_CHARSET_FAIL} ) { - if ($ENV{ORA_CHARSET_FAIL}) { # Connecting up here breaks because of the charset and ncharset # global variables defined in dbdimp.c $dbh_utf8 = db_connect(1); } - my $testcount = 8 + insert_test_count( $tdata ); + my $testcount = 8 + insert_test_count($tdata); $dbh = db_connect(0); if ($dbh) { - $dbh->ora_nls_parameters ()->{NLS_CHARACTERSET} =~ m/US7ASCII/ and plan skip_all => "Database is set up as US7ASCII"; + $dbh->ora_nls_parameters()->{NLS_CHARACTERSET} =~ m/US7ASCII/ + and plan skip_all => 'Database is set up as US7ASCII'; plan tests => $testcount; - } else { - plan skip_all => "Unable to connect to Oracle"; + } + else { + plan skip_all => 'Unable to connect to Oracle'; } - show_test_data( $tdata ,0 ); + show_test_data( $tdata, 0 ); - drop_table($dbh); - create_table($dbh, $tdata); - insert_rows( $dbh, $tdata); + force_drop_table($dbh); + create_table( $dbh, $tdata ); + insert_rows( $dbh, $tdata ); - my ($ch, $nch) = $dbh->selectrow_array("select ch, nch from $table"); - check($ch, $nch, 0); + my ( $ch, $nch ) = $dbh->selectrow_array("select ch, nch from $table"); + check( $ch, $nch, 0 ); - unless ($ENV{ORA_CHARSET_FAIL}) { + unless ( $ENV{ORA_CHARSET_FAIL} ) { $dbh_utf8 = db_connect(1); } - ($ch, $nch) = $dbh_utf8->selectrow_array("select ch, nch from $table"); - check($ch, $nch, 1); -}; + ( $ch, $nch ) = $dbh_utf8->selectrow_array("select ch, nch from $table"); + check( $ch, $nch, 1 ); +} sub check { - my $ch = shift; - my $nch = shift; + my $ch = shift; + my $nch = shift; my $is_utf8 = shift; if ($is_utf8) { - ok(Encode::is_utf8($ch)); - ok(Encode::is_utf8($nch)); + ok( Encode::is_utf8($ch), '$ch should be utf8' ); + ok( Encode::is_utf8($nch), '$nch should be utf8' ); } else { - ok(!Encode::is_utf8($ch)); - ok(!Encode::is_utf8($nch)); + ok( !Encode::is_utf8($ch), '$ch should NOT be utf8' ); + ok( !Encode::is_utf8($nch), '$nch should NOT be utf8' ); } - is($ch, "\xb0", "match char"); - is($nch, "\xb0", "match char"); + is( $ch, "\xb0", 'match char' ); + is( $nch, "\xb0", 'match char' ); } -sub db_connect -{ +sub db_connect { my $utf8 = shift; # Make sure we really are overriding the environment settings. - my ($charset, $ncharset); + my ( $charset, $ncharset ); if ($utf8) { set_nls_lang_charset($eight_bit_charset); set_nls_nchar($eight_bit_charset); - $charset = $utf8_charset; + $charset = $utf8_charset; $ncharset = $utf8_charset; } else { set_nls_lang_charset($utf8_charset); set_nls_nchar($utf8_charset); - $charset = $eight_bit_charset; + $charset = $eight_bit_charset; $ncharset = $eight_bit_charset; } - my $dsn = oracle_test_dsn(); - my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - my $p = { - AutoCommit => 1, - PrintError => 0, + AutoCommit => 1, + PrintError => 0, FetchHashKeyName => 'NAME_lc', - ora_envhp => 0, # force fresh environment (with current NLS env vars) + ora_envhp => 0, # force fresh environment (with current NLS env vars) }; - $p->{ora_charset} = $charset if $charset; + $p->{ora_charset} = $charset if $charset; $p->{ora_ncharset} = $ncharset if $ncharset; - my $dbh = DBI->connect($dsn, $dbuser, '', $p); + my $dbh = db_handle( $p ); return $dbh; } END { - eval { - local $dbh->{PrintError} = 0; - drop_table( $dbh ) if $dbh and not $ENV{'DBD_SKIP_TABLE_DROP'}; - }; + drop_table($dbh) } 1; diff --git a/t/README b/t/README new file mode 100644 index 00000000..518ed169 --- /dev/null +++ b/t/README @@ -0,0 +1,62 @@ +Variables used in tests +----------------------- + +** Connecting to Oracle ** + +ORACLE_USERID - important + +Which user & password to use when running tests against a real Oracle database + +Should be 'user/password' or a longer string with connection details. + + $ export ORACLE_USERID='scott/tiger' + +ORACLE_USERID_2 + +Provides a second set of user credentials when needed + +ORACLE_DSN + +DSN details when connecting to real Oracle for tests + + $ export ORACLE_DSN='dbi:Oracle:testdb' + +DBI_DSN + +If ORACLE_DSN is not provided, this will be used. Otherwise falls back to internal default. + +** Creation of tables, views, functions etc ** + +DBD_ORACLE_SEQ - important + +Appended to table, view, function (etc) that are created during testing to help +prevent collisions + +DBD_SKIP_TABLE_DROP + +Skips dropping temporary tables when tests complete. Use to examine the mess. + +** Other ** + +NLS_DATE_FORMAT + +Sets the date format as normal + +Need more details +----------------- + +NLS_NCHAR + +NLS_LANG + + +??? + +DBI_USER + +DBI_PASS + +DBD_ALL_TESTS + +Forces some tests to run, that otherwise wouldn't + diff --git a/t/lib/DBDOracleTestLib.pm b/t/lib/DBDOracleTestLib.pm new file mode 100644 index 00000000..33ec8f62 --- /dev/null +++ b/t/lib/DBDOracleTestLib.pm @@ -0,0 +1,575 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +package DBDOracleTestLib; +use Test::More; + +use Exporter 'import'; + +use vars qw( @EXPORT_OK ); + +@EXPORT_OK = ( + qw/ db_handle extra_wide_rows long_test_cols + oracle_test_dsn show_test_data test_data + select_test_count select_rows + cmp_ok_byte_nice show_db_charsets + db_ochar_is_utf db_nchar_is_utf + client_ochar_is_utf8 client_nchar_is_utf8 + set_nls_nchar set_nls_lang_charset + insert_test_count nice_string force_drop_table + create_table table drop_table insert_rows dump_table +/, +); + +use Carp; +use Data::Dumper; +use DBI; +use DBD::Oracle qw(ORA_OCI ora_env_var); + +require utf8; + +# perl 5.6 doesn't define utf8::is_utf8() +unless ( defined &{'utf8::is_utf8'} ) { + die "Can't run this test using Perl $] without DBI >= 1.38" + unless $DBI::VERSION >= 1.38; + *utf8::is_utf8 = sub { + my $raw = shift; + return 0 if !defined $raw; + my $v = DBI::neat($raw); + return 1 if $v =~ m/^"/; # XXX ugly hack, sufficient here + return 0 if $v =~ m/^'/; # XXX ugly hack, sufficient here + carp "Emulated utf8::is_utf8 is unreliable for $v ($raw)"; + return 0; + } +} + +=head binmode STDOUT, ':utf8' + + Wide character in print at t/nchar_test_lib.pl line 134 (#1) + (W utf8) Perl met a wide character (>255) when it wasn't expecting + one. This warning is by default on for I/O (like print). The easiest + way to quiet this warning is simply to add the :utf8 layer to the + output, e.g. binmode STDOUT, ':utf8'. Another way to turn off the + warning is to add no warnings 'utf8'; but that is often closer to + cheating. In general, you are supposed to explicitly mark the + filehandle with an encoding, see open and perlfunc/binmode. +=cut + +eval { binmode STDOUT, ':utf8' }; # Fails for perl 5.6 +diag("Can't set binmode(STDOUT, ':utf8'): $@") if $@; +eval { binmode STDERR, ':utf8' }; # Fails for perl 5.6 +diag("Can't set binmode(STDERR, ':utf8'): $@") if $@; + +# Test::More duplicates STDOUT/STDERR at the start but does not copy the IO +# layers from our STDOUT/STDERR. As a result any calls to Test::More::diag +# with utf8 data will show warnings. Similarly, if we pass utf8 into +# Test::More::pass, ok, etc etc. To get around this we specifically tell +# Test::More to use our newly changed STDOUT and STDERR for failure_output +# and output. +my $tb = Test::More->builder; +binmode( $tb->failure_output, ':utf8' ); +binmode( $tb->output, ':utf8' ); + +sub long_test_cols { + my ($type) = @_; + return [ [ lng => $type ], ]; +} + + +sub extra_wide_rows { + + # Non-BMP characters require use of surrogates with UTF-16 + # So U+10304 becomes U+D800 followed by U+DF04 (I think) in UTF-16. + # + # When encoded as standard UTF-8, which Oracle calls AL32UTF8, it should + # be a single UTF-8 code point (that happens to occupy 4 bytes). + # + # When encoded as "CESU-8", which Oracle calls "UTF8", each surrogate + # is treated as a code point so you get 2 UTF-8 code points + # (that happen to occupy 3 bytes each). That is not valid UTF-8. + # See http://www.unicode.org/reports/tr26/ for more information. + return unless ORA_OCI >= 9.2; # need AL32UTF8 for these to work + return ( + [ "\x{10304}", 'SMP Plane 1 wide char' ], # OLD ITALIC LETTER E + [ "\x{20301}", 'SIP Plane 2 wide char' ] + , # CJK Unified Ideographs Extension B + ); +} + +{ + +my $char_cols = + [ [ ch => 'varchar2(20)' ], [ descr => 'varchar2(50)' ], ]; + +my $nchar_cols = + [ [ nch => 'nvarchar2(20)' ], [ descr => 'varchar2(50)' ], ]; + +my $wide_data = + [ + [ "\x{03}", 'control-C' ], + [ 'a', 'lowercase a' ], + [ 'b', 'lowercase b' ], + [ "\x{263A}", 'smiley face' ], + + # These are not safe for db's with US7ASCII + # [ "\x{A1}", "upside down bang" ], + # [ "\x{A2}", "cent char" ], + # [ "\x{A3}", "british pound" ], + ]; + +sub _narrow_data # Assuming WE8ISO8859P1 or WE8MSWIN1252 character set +{ + my $highbitset = [ + + # These non-unicode strings are not safe if client charset is utf8 + # because we have to let oracle assume they're utf8 but they're not + [ chr(161), 'upside down bang' ], + [ chr(162), 'cent char' ], + [ chr(163), 'british pound' ], + ]; + [ + [ 'a', 'lowercase a' ], + [ 'b', 'lowercase b' ], + [ chr(3), 'control-C' ], + ( _nls_local_has_utf8() ) ? () : @$highbitset + ]; +} + +my $tdata_hr = { + narrow_char => { + cols => $char_cols, + rows => _narrow_data() + }, + narrow_nchar => { + cols => $nchar_cols, + rows => _narrow_data() + }, + wide_char => { + cols => $char_cols, + rows => $wide_data + }, + wide_nchar => { + cols => $nchar_cols, + rows => $wide_data + }, +}; + +sub test_data { + my ($which) = @_; + my $test_data = $tdata_hr->{$which} or die; + $test_data->{dump} = 'DUMP(%s)'; + if ( $ENV{DBD_ORACLE_TESTLOB} ) { # XXX temp. needs reworking + # Nvarchar -> Nclob and varchar -> clob + $test_data->{cols}[0][1] =~ s/varchar.*/CLOB/; + $test_data->{dump} = 'DUMP(DBMS_LOB.SUBSTR(%s))'; + } + return $test_data; +} + +} + +sub oracle_test_dsn { + my ( $default, $dsn ) = ( 'dbi:Oracle:', $ENV{ORACLE_DSN} ); + + $dsn ||= $ENV{DBI_DSN} + if $ENV{DBI_DSN} && ( $ENV{DBI_DSN} =~ m/^$default/io ); + $dsn ||= $default; + + return $dsn; +} + +sub db_handle { + + my $p = shift; + + $p ||= { + AutoCommit => 1, + PrintError => 0, + ora_envhp => 0, # force fresh environment (with current NLS env vars) + }; + + my $dsn = oracle_test_dsn(); + my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; + my $dbh = DBI->connect( $dsn, $dbuser, '', $p ); + return $dbh + +} + +sub show_test_data { + my ($tdata) = @_; + my $rowsR = $tdata->{rows}; + my $cnt = 0; + my $vcnt = 0; + foreach my $recR (@$rowsR) { + $cnt++; + my $v = $$recR[0]; + my $byte_string = _byte_string($v); + my $nice_string = nice_string($v); + my $out = sprintf( "row: %3d: nice_string=%s byte_string=%s (%s, %s)\n", + $cnt, $nice_string, $byte_string, $v, DBI::neat($v) ); + note($out); + } + return $cnt; +} + +sub table { + my $table = shift || 'dbd_ora__drop_me'; + $table .= ( $ENV{DBD_ORACLE_SEQ} || '' ); + die "Test table name '$table' is too long for Oracle < 12.1" + if length $table > 30; + # In Oracle 12.2 and above the maximum object name length is 128 bytes. + # In Oracle 12.1 and below the maximum object name length is 30 bytes. + return $table +} + +sub force_drop_table { + my $dbh = shift; + return unless $dbh; + my $tname = shift || table(); + local $dbh->{PrintError} = 0; + if ($dbh->{Active}) { + $dbh->do(qq{ drop table $tname }) + } +} + +sub drop_table { + my @args = @_; + return if $ENV{'DBD_SKIP_TABLE_DROP'}; + force_drop_table( @args ) +} + +sub _insert_handle { + my ( $dbh, $tcols ) = @_; + my $table = table(); + my $sql = "insert into $table ( idx, "; + my $cnt = 1; + for my $col (@$tcols) { + $sql .= $$col[0] . ', '; + $cnt++; + } + $sql .= 'dt ) values( ' . '?, ' x $cnt . 'sysdate )'; + my $h = $dbh->prepare($sql); + ok( $h, "prepared: $sql" ); + return $h; +} + +sub insert_test_count { + my ($tdata) = @_; + my $rcnt = @{ $tdata->{rows} }; + my $ccnt = @{ $tdata->{cols} }; + return 1 + $rcnt * 2 + $rcnt * $ccnt; +} + +sub insert_rows #1 + rows*2 +rows*ncols tests +{ + my ( $dbh, $tdata, $csform ) = @_; + my $trows = $tdata->{rows}; + my $tcols = $tdata->{cols}; + my $table = table(); + + # local $dbh->{TraceLevel} = 4; + my $sth = _insert_handle( $dbh, $tcols ); + + my $cnt = 0; + foreach my $rowR (@$trows) { + my $colnum = 1; + my $attrR = $csform ? { ora_csform => $csform } : {}; + ok( $sth->bind_param( $colnum++ , $cnt ), 'bind_param idx' ); + for ( my $i = 0 ; $i < @$rowR ; $i++ ) { + my $note = 'withOUT attribute ora_csform'; + my $val = $$rowR[$i]; + my $type = $$tcols[$i][1]; + + #print "type=$type\n"; + my $attr = {}; + if ( $type =~ m/^nchar|^nvar|^nclob/i ) { + $attr = $attrR; + $note = $attr + && $csform ? "with attribute { ora_csform => $csform }" : q||; + } + ok( + $sth->bind_param( $colnum++ , $val, $attr ), + 'bind_param ' . $$tcols[$i][0] . " $note" + ); + } + $cnt++; + ok( $sth->execute, "insert row $cnt: $rowR->[-1]" ); + } +} + +sub dump_table { + my ( $dbh, @cols ) = @_; + return; # not needed now select_handle() includes a DUMP column + my $table = table(); + my $colstr = ''; + foreach my $col (@cols) { + $colstr .= ', ' if $colstr; + $colstr .= "dump($col)"; + } + my $sql = "select $colstr from $table order by idx"; + print "dumping $table\nprepared: $sql\n"; + my $colnum = 0; + my $data = eval { $dbh->selectall_arrayref($sql) } || []; + my $cnt = 0; + while ( my $aref = shift @$data ) { + $cnt++; + my $colnum = 0; + for my $col (@cols) { + print "row $cnt: "; + print "$col=" . $$aref[$colnum] . "\n"; + $colnum++; + } + } +} + +sub _select_handle #1 test +{ + my ( $dbh, $tdata ) = @_; + my $table = table(); + my $sql = 'select '; + for my $col ( @{ $tdata->{cols} } ) { + $sql .= $$col[0] . ', '; + } + $sql .= sprintf "$tdata->{dump}, ", $tdata->{cols}[0][0]; + $sql .= "dt from $table order by idx"; + my $h = $dbh->prepare($sql); + ok( $h, "prepared: $sql" ); + return $h; +} + +sub select_test_count { + my ($tdata) = @_; + my $rcnt = @{ $tdata->{rows} }; + my $ccnt = @{ $tdata->{cols} }; + return 2 + $ccnt + $rcnt * $ccnt * 2; +} + +sub select_rows # 1 + numcols + rows * cols * 2 +{ + my ( $dbh, $tdata, $csform ) = @_; + my $table = table(); + my $trows = $tdata->{rows}; + my $tcols = $tdata->{cols}; + my $sth = _select_handle( $dbh, $tdata ) + or do { fail(); return }; + my @data = (); + my $colnum = 0; + foreach my $col (@$tcols) { + ok( + $sth->bind_col( $colnum + 1, \$data[$colnum] ), + 'bind column ' . $$tcols[$colnum][0] + ); + $colnum++; + } + my $dumpcol = sprintf $tdata->{dump}, $tdata->{cols}[0][0]; + +#ok( $sth->bind_col( $colnum+1 ,\$data[$colnum] ), "bind column DUMP(" .$tdata->{cols}[0][0] .")" ); + $sth->bind_col( $colnum + 1, \$data[$colnum] ); + my $cnt = 0; + $sth->execute(); + while ( $sth->fetch() ) { + my $row = $cnt + 1; + my $error = 0; + my $i = 0; + for ( $i = 0 ; $i < @$tcols ; $i++ ) { + my $res = $data[$i]; + my $charname = $trows->[$cnt][1] || ''; + my $is_utf8 = utf8::is_utf8($res) ? ' (uft8)' : q||; + my $description = + "row $row: column: $tcols->[$i][0] $is_utf8 $charname"; + + $error += + not cmp_ok_byte_nice( $res, $$trows[$cnt][$i], $description ); + + #$sth->trace(0) if $cnt >= 3 ; + } + if ($error) { + warn "# row $row: $dumpcol = " . $data[$i] . "\n"; + } + $cnt++; + } + + #$sth->trace(0); + my $trow_cnt = @$trows; + cmp_ok( $cnt, '==', $trow_cnt, 'number of rows fetched' ); +} + +sub cmp_ok_byte_nice { + my ( $got, $expected, $description ) = @_; + my $ok1 = cmp_ok( _byte_string($got), 'eq', _byte_string($expected), + "byte_string test of $description" ); + my $ok2 = cmp_ok( nice_string($got), 'eq', nice_string($expected), + "nice_string test of $description" ); + return $ok1 && $ok2; +} + +sub create_table { + my ( $dbh, $tdata, $drop ) = @_; + my $tcols = $tdata->{cols}; + my $table = table(); + my $sql = "create table $table ( idx integer, "; + foreach my $col (@$tcols) { + $sql .= $$col[0] . ' ' . $$col[1] . ', '; + } + $sql .= ' dt date )'; + + drop_table($dbh) if $drop; + + #$dbh->do(qq{ drop table $table }) if $drop; + $dbh->do($sql); + if ( $dbh->err && $dbh->err == 955 ) { + $dbh->do(qq{ drop table $table }); + warn "Unexpectedly had to drop old test table '$table'\n" + unless $dbh->err; + $dbh->do($sql); + } + elsif ( $dbh->err ) { + return; + } + else { + #$sql =~ s/ \( */(\n\t/g; + #$sql =~ s/, */,\n\t/g; + note("$sql\n"); + } + return $table; + + # ok( not $dbh->err, "create table $table..." ); +} + +sub show_db_charsets { + my ($dbh) = @_; + my $out; + my $ora_server_version = join '.', + @{ $dbh->func('ora_server_version') || [] }; + my $paramsH = $dbh->ora_nls_parameters(); + $out = + sprintf +"Database $ora_server_version CHAR set is %s (%s), NCHAR set is %s (%s)\n", + $paramsH->{NLS_CHARACTERSET}, + db_ochar_is_utf($dbh) ? 'Unicode' : 'Non-Unicode', + $paramsH->{NLS_NCHAR_CHARACTERSET}, + db_nchar_is_utf($dbh) ? 'Unicode' : 'Non-Unicode'; + note($out); + my $ora_client_version = ORA_OCI(); + $out = + sprintf + "Client $ora_client_version NLS_LANG is '%s', NLS_NCHAR is '%s'\n", + ora_env_var('NLS_LANG') || '', + ora_env_var('NLS_NCHAR') || ''; + note($out); +} + +sub db_ochar_is_utf { return shift->ora_can_unicode & 2 } +sub db_nchar_is_utf { return shift->ora_can_unicode & 1 } + +sub client_ochar_is_utf8 { + my $NLS_LANG = ora_env_var('NLS_LANG') || q(); + $NLS_LANG =~ s/.*\.//; + return $NLS_LANG =~ m/utf8/i; +} + +sub client_nchar_is_utf8 { + my $NLS_LANG = ora_env_var('NLS_LANG') || q(); + $NLS_LANG =~ s/.*\.//; + my $NLS_NCHAR = ora_env_var('NLS_NCHAR') || $NLS_LANG; + return $NLS_NCHAR =~ m/utf8/i; +} + +sub _nls_local_has_utf8 { + return client_ochar_is_utf8() || client_nchar_is_utf8(); +} + +sub set_nls_nchar { + my ( $cset, $verbose ) = @_; + if ( defined $cset ) { + $ENV{NLS_NCHAR} = "$cset"; + } + else { + undef $ENV{NLS_NCHAR}; # XXX windows? (perhaps $ENV{NLS_NCHAR}=""?) + } + + # Special treatment for environment variables under Cygwin - + # see comments in dbdimp.c for details. + DBD::Oracle::ora_cygwin_set_env( 'NLS_NCHAR', $ENV{NLS_NCHAR} || '' ) + if $^O eq 'cygwin'; + note( + defined ora_env_var('NLS_NCHAR') + ? # defined? + "set \$ENV{NLS_NCHAR}=$cset\n" + : "set \$ENV{NLS_LANG}=undef\n" + ) # XXX ? + if defined $verbose; +} + +sub set_nls_lang_charset { + my ( $lang, $verbose ) = @_; + + $ENV{NLS_LANG} = $lang ? "AMERICAN_AMERICA.$lang" : q(); + + note sprintf( q|set $ENV{NLS_LANG}='%s'|, $ENV{NLS_LANG} ); + + # Special treatment for environment variables under Cygwin - + # see comments in dbdimp.c for details. + DBD::Oracle::ora_cygwin_set_env( 'NLS_LANG', $ENV{NLS_LANG} || '' ) + if $^O eq 'cygwin'; +} + +sub _byte_string { + my $ret = join( '|', unpack( 'C*', $_[0] ) ); + return $ret; +} + +sub nice_string { + my @raw_chars = ( utf8::is_utf8( $_[0] ) ) + ? unpack( 'U*', $_[0] ) # unpack unicode characters + : unpack( 'C*', $_[0] ); # not unicode, so unpack as bytes + my @chars = map { + $_ > 255 + ? # if wide character... + sprintf( "\\x{%04X}", $_ ) + : # \x{...} + chr($_) =~ /[[:cntrl:]]/ + ? # else if control character ... + sprintf( "\\x%02X", $_ ) + : # \x.. + chr($_) # else as themselves + } @raw_chars; + + for my $c (@chars) { + if ( $c =~ m/\\x\{08(..)}/ ) { + $c .= q|='| . chr( hex($1) ) . q('); + } + } + my $ret = join( q||, @chars ); + +} + +sub view_with_sqlplus { + my ( $use_nls_lang, $tdata ) = @_; + my $table = table(); + my $tcols = $tdata->{cols}; + my $sqlfile = 'sql.txt'; + my $cols = 'idx,nch_col'; + open my $F, '>', $sqlfile or die "could open $sqlfile"; + print $F $ENV{ORACLE_USERID} . "\n"; + my $str = qq( +col idx form 99 +col ch_col form a8 +col nch_col form a16 +select $cols from $table; +); + print $F $str; + print $F "exit;\n"; + close $F; + + my $nls = 'unset'; + $nls = ora_env_var('NLS_LANG') if ora_env_var('NLS_LANG'); + local $ENV{NLS_LANG} = '' if not $use_nls_lang; + print "From sqlplus...$str\n ...with NLS_LANG = $nls\n"; + system("sqlplus -s \@$sqlfile"); + unlink $sqlfile; +} + +1; diff --git a/t/lib/ExecuteArray.pm b/t/lib/ExecuteArray.pm index 268641f0..8d67147b 100644 --- a/t/lib/ExecuteArray.pm +++ b/t/lib/ExecuteArray.pm @@ -1,4 +1,4 @@ -# $Id$ +#!perl # Author: Martin J. Evans # This should be an exact copy of the same file in DBD::ODBC # If you change this file please let me know. @@ -8,8 +8,8 @@ use Data::Dumper; use DBI; our $VERSION = '0.01'; -my $table = 'PERL_DBD_execute_array'; -my $table2 = 'PERL_DBD_execute_array2'; +my $table = 'PERL_DBD_execute_array'.($ENV{DBD_ORACLE_SEQ}||''); +my $table2 = 'PERL_DBD_execute_array2'.($ENV{DBD_ORACLE_SEQ}||''); my @p1 = (1,2,3,4,5); my @p2 = qw(one two three four five); my $fetch_row = 0; @@ -18,7 +18,7 @@ my @captured_error; # values captured in error handler sub error_handler { @captured_error = @_; - note("***** error handler called *****"); + note('***** error handler called *****'); 0; # pass errors on } diff --git a/t/nchar_test_lib.pl b/t/nchar_test_lib.pl deleted file mode 100644 index 1b249962..00000000 --- a/t/nchar_test_lib.pl +++ /dev/null @@ -1,523 +0,0 @@ -use strict; -use warnings; -use Carp; -use Data::Dumper; -use DBI; -use DBD::Oracle qw(ORA_OCI ora_env_var); - -require utf8; - -# perl 5.6 doesn't define utf8::is_utf8() -unless (defined &{"utf8::is_utf8"}) { - die "Can't run this test using Perl $] without DBI >= 1.38" - unless $DBI::VERSION >= 1.38; - *utf8::is_utf8 = sub { - my $raw = shift; - return 0 if !defined $raw; - my $v = DBI::neat($raw); - return 1 if $v =~ /^"/; # XXX ugly hack, sufficient here - return 0 if $v =~ /^'/; # XXX ugly hack, sufficient here - carp "Emulated utf8::is_utf8 is unreliable for $v ($raw)"; - return 0; - } -} - -=head binmode STDOUT, ':utf8' - - Wide character in print at t/nchar_test_lib.pl line 134 (#1) - (W utf8) Perl met a wide character (>255) when it wasn't expecting - one. This warning is by default on for I/O (like print). The easiest - way to quiet this warning is simply to add the :utf8 layer to the - output, e.g. binmode STDOUT, ':utf8'. Another way to turn off the - warning is to add no warnings 'utf8'; but that is often closer to - cheating. In general, you are supposed to explicitly mark the - filehandle with an encoding, see open and perlfunc/binmode. -=cut -eval { binmode STDOUT, ':utf8' }; # Fails for perl 5.6 -diag("Can't set binmode(STDOUT, ':utf8'): $@") if $@; -eval { binmode STDERR, ':utf8' }; # Fails for perl 5.6 -diag("Can't set binmode(STDERR, ':utf8'): $@") if $@; - -# Test::More duplicates STDOUT/STDERR at the start but does not copy the IO -# layers from our STDOUT/STDERR. As a result any calls to Test::More::diag -# with utf8 data will show warnings. Similarly, if we pass utf8 into -# Test::More::pass, ok, etc etc. To get around this we specifically tell -# Test::More to use our newly changed STDOUT and STDERR for failure_output -# and output. -my $tb = Test::More->builder; -binmode($tb->failure_output, ':utf8'); -binmode($tb->output, ':utf8'); - -sub long_test_cols -{ - my ($type) = @_ ; - return - [ - [ lng => $type ], - ]; -} -sub char_cols -{ - [ - [ ch => 'varchar2(20)' ], - [ descr => 'varchar2(50)' ], - ]; -} -sub nchar_cols -{ - [ - [ nch => 'nvarchar2(20)' ], - [ descr => 'varchar2(50)' ], - ]; -} -sub wide_data -{ - [ - [ "\x{03}", "control-C" ], - [ "a", "lowercase a" ], - [ "b", "lowercase b" ], - [ "\x{263A}", "smiley face" ], -# These are not safe for db's with US7ASCII -# [ "\x{A1}", "upside down bang" ], -# [ "\x{A2}", "cent char" ], -# [ "\x{A3}", "british pound" ], - ]; -} -sub extra_wide_rows -{ - # Non-BMP characters require use of surrogates with UTF-16 - # So U+10304 becomes U+D800 followed by U+DF04 (I think) in UTF-16. - # - # When encoded as standard UTF-8, which Oracle calls AL32UTF8, it should - # be a single UTF-8 code point (that happens to occupy 4 bytes). - # - # When encoded as "CESU-8", which Oracle calls "UTF8", each surrogate - # is treated as a code point so you get 2 UTF-8 code points - # (that happen to occupy 3 bytes each). That is not valid UTF-8. - # See http://www.unicode.org/reports/tr26/ for more information. - return unless ORA_OCI >= 9.2; # need AL32UTF8 for these to work - return ( - [ "\x{10304}", "SMP Plane 1 wide char" ], # OLD ITALIC LETTER E - [ "\x{20301}", "SIP Plane 2 wide char" ], # CJK Unified Ideographs Extension B - ); -} -sub narrow_data # Assuming WE8ISO8859P1 or WE8MSWIN1252 character set -{ - my $highbitset = [ - # These non-unicode strings are not safe if client charset is utf8 - # because we have to let oracle assume they're utf8 but they're not - [ chr(161), "upside down bang" ], - [ chr(162), "cent char" ], - [ chr(163), "british pound" ], - ]; - [ - [ "a", "lowercase a" ], - [ "b", "lowercase b" ], - [ chr(3), "control-C" ], - (nls_local_has_utf8()) ? () : @$highbitset - ]; -} - -my $tdata_hr = { - narrow_char => { - cols => char_cols(), - rows => narrow_data() - } - , - narrow_nchar => { - cols => nchar_cols(), - rows => narrow_data() - } - , - wide_char => { - cols => char_cols(), - rows => wide_data() - } - , - wide_nchar => { - cols => nchar_cols(), - rows => wide_data() - } - , -}; -sub test_data -{ - my ($which) = @_; - my $test_data = $tdata_hr->{$which} or die; - $test_data->{dump} = "DUMP(%s)"; - if ($ENV{DBD_ORACLE_TESTLOB}) { # XXX temp. needs reworking - # Nvarchar -> Nclob and varchar -> clob - $test_data->{cols}[0][1] =~ s/varchar.*/CLOB/; - $test_data->{dump} = "DUMP(DBMS_LOB.SUBSTR(%s))"; - } - return $test_data; -} - -sub oracle_test_dsn -{ - my( $default, $dsn ) = ( 'dbi:Oracle:', $ENV{ORACLE_DSN} ); - - - $dsn ||= $ENV{DBI_DSN} if $ENV{DBI_DSN} && ($ENV{DBI_DSN} =~ /^$default/io); - $dsn ||= $default; - - return $dsn; -} - -sub db_handle -{ - my $dsn = oracle_test_dsn(); - my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - my $dbh = DBI->connect($dsn, $dbuser, '', { - AutoCommit => 1, - PrintError => 0, - ora_envhp => 0, # force fresh environment (with current NLS env vars) - }); - return $dbh; -} -sub show_test_data -{ - my ($tdata) = @_; - my $rowsR = $tdata->{rows}; - my $cnt = 0; - my $vcnt = 0; - foreach my $recR ( @$rowsR ) - { - $cnt++; - my $v = $$recR[0]; - my $byte_string = byte_string($v); - my $nice_string = nice_string($v); - my $out = sprintf( "row: %3d: nice_string=%s byte_string=%s (%s, %s)\n", - $cnt, $nice_string, $byte_string, $v, DBI::neat($v)); - note($out); - } - return $cnt; -} - -sub table { 'dbd_ora__drop_me'.($ENV{DBD_ORACLE_SEQ}||''); } -sub drop_table -{ - my ($dbh) = @_; - my $table = table(); - local $dbh->{PrintError} = 0; - $dbh->do(qq{ drop table $table }) if $dbh->{Active}; -} - -sub insert_handle -{ - my ($dbh,$tcols) = @_; - my $table = table(); - my $sql = "insert into $table ( idx, "; - my $cnt = 1; - foreach my $col ( @$tcols ) - { - $sql .= $$col[0] . ", "; - $cnt++; - } - $sql .= "dt ) values( " . "?, " x $cnt ."sysdate )"; - my $h = $dbh->prepare( $sql ); - ok( $h ,"prepared: $sql" ); - return $h; -} -sub insert_test_count -{ - my ( $tdata ) = @_; - my $rcnt = @{$tdata->{rows}}; - my $ccnt = @{$tdata->{cols}}; - return 1 + $rcnt*2 + $rcnt * $ccnt; -} -sub insert_rows #1 + rows*2 +rows*ncols tests -{ - my ($dbh, $tdata ,$csform) = @_; - my $trows = $tdata->{rows}; - my $tcols = $tdata->{cols}; - my $table = table(); - # local $dbh->{TraceLevel} = 4; - my $sth = insert_handle($dbh, $tcols); - - my $cnt = 0; - foreach my $rowR ( @$trows ) - { - my $colnum = 1; - my $attrR = $csform ? { ora_csform => $csform } : {}; - ok( $sth->bind_param( $colnum++ ,$cnt ) ,"bind_param idx" ); - for( my $i = 0; $i < @$rowR; $i++ ) - { - my $note = 'withOUT attribute ora_csform'; - my $val = $$rowR[$i]; - my $type = $$tcols[$i][1]; - #print "type=$type\n"; - my $attr = {}; - if ( $type =~ m/^nchar|^nvar|^nclob/i ) - { - $attr = $attrR; - $note = $attr && $csform ? "with attribute { ora_csform => $csform }" : ""; - } - ok( $sth->bind_param( $colnum++ ,$val ,$attr ) ,"bind_param " . $$tcols[$i][0] ." $note" ); - } - $cnt++; - ok( $sth->execute ,"insert row $cnt: $rowR->[-1]" ); - } -} -sub dump_table -{ - my ( $dbh ,@cols ) = @_; -return; # not needed now select_handle() includes a DUMP column - my $table = table(); - my $colstr = ''; - foreach my $col ( @cols ) { - $colstr .= ", " if $colstr; - $colstr .= "dump($col)" - } - my $sql = "select $colstr from $table order by idx" ; - print "dumping $table\nprepared: $sql\n" ; - my $colnum = 0; - my $data = eval { $dbh->selectall_arrayref( $sql ) } || []; - my $cnt = 0; - while ( my $aref = shift @$data ) { - $cnt++; - my $colnum = 0; - foreach my $col ( @cols ) { - print "row $cnt: " ; - print "$col=" .$$aref[$colnum] ."\n"; - $colnum++; - } - } -} -sub select_handle #1 test -{ - my ($dbh,$tdata) = @_; - my $table = table(); - my $sql = "select "; - foreach my $col ( @{$tdata->{cols}} ) - { - $sql .= $$col[0] . ", "; - } - $sql .= sprintf "$tdata->{dump}, ", $tdata->{cols}[0][0]; - $sql .= "dt from $table order by idx" ; - my $h = $dbh->prepare( $sql ); - ok( $h ,"prepared: $sql" ); - return $h; -} -sub select_test_count -{ - my ( $tdata ) = @_; - my $rcnt = @{$tdata->{rows}}; - my $ccnt = @{$tdata->{cols}}; - return 2 + $ccnt + $rcnt * $ccnt * 2; -} -sub select_rows # 1 + numcols + rows * cols * 2 -{ - my ($dbh,$tdata,$csform) = @_; - my $table = table(); - my $trows = $tdata->{rows}; - my $tcols = $tdata->{cols}; - my $sth = select_handle($dbh,$tdata) - or do { fail(); return }; - my @data = (); - my $colnum = 0; - foreach my $col ( @$tcols ) - { - ok( $sth->bind_col( $colnum+1 ,\$data[$colnum] ), "bind column " .$$tcols[$colnum][0] ); - $colnum++; - } - my $dumpcol = sprintf $tdata->{dump}, $tdata->{cols}[0][0]; - #ok( $sth->bind_col( $colnum+1 ,\$data[$colnum] ), "bind column DUMP(" .$tdata->{cols}[0][0] .")" ); - $sth->bind_col( $colnum+1 ,\$data[$colnum] ); - my $cnt = 0; - $sth->execute(); - while ( $sth->fetch() ) - { - my $row = $cnt + 1; - my $error = 0; - my $i = 0; - for( $i = 0 ; $i < @$tcols; $i++ ) - { - my $res = $data[$i]; - my $charname = $trows->[$cnt][1] || ''; - my $is_utf8 = utf8::is_utf8( $res ) ? " (uft8)" : ""; - my $description = "row $row: column: $tcols->[$i][0] $is_utf8 $charname"; - - $error += not cmp_ok_byte_nice($res, $$trows[$cnt][$i], $description); - #$sth->trace(0) if $cnt >= 3 ; - } - if ( $error ) - { - warn "# row $row: $dumpcol = " .$data[$i]. "\n" ; - } - $cnt++; - } - #$sth->trace(0); - my $trow_cnt = @$trows; - cmp_ok( $cnt, '==', $trow_cnt, "number of rows fetched" ); -} - -sub cmp_ok_byte_nice { - my ($got, $expected, $description) = @_; - my $ok1 = cmp_ok( byte_string($got), 'eq', byte_string($expected), - "byte_string test of $description" - ); - my $ok2 = cmp_ok( nice_string($got), 'eq', nice_string($expected), - "nice_string test of $description" - ); - return $ok1 && $ok2; -} - -sub create_table -{ - my ($dbh,$tdata,$drop) = @_; - my $tcols = $tdata->{cols}; - my $table = table(); - my $sql = "create table $table ( idx integer, "; - foreach my $col ( @$tcols ) - { - $sql .= $$col[0] . " " .$$col[1] .", "; - } - $sql .= " dt date )"; - - drop_table( $dbh ) if $drop; - #$dbh->do(qq{ drop table $table }) if $drop; - $dbh->do($sql); - if ($dbh->err && $dbh->err==955) { - $dbh->do(qq{ drop table $table }); - warn "Unexpectedly had to drop old test table '$table'\n" unless $dbh->err; - $dbh->do($sql); - } elsif ($dbh->err) { - return; - } else { - #$sql =~ s/ \( */(\n\t/g; - #$sql =~ s/, */,\n\t/g; - note("$sql\n") ; - } - return $table; -# ok( not $dbh->err, "create table $table..." ); -} - - - -sub show_db_charsets -{ - my ( $dbh) = @_; - my $out; - my $ora_server_version = join ".", @{$dbh->func("ora_server_version")||[]}; - my $paramsH = $dbh->ora_nls_parameters(); - $out = sprintf "Database $ora_server_version CHAR set is %s (%s), NCHAR set is %s (%s)\n", - $paramsH->{NLS_CHARACTERSET}, - db_ochar_is_utf($dbh) ? "Unicode" : "Non-Unicode", - $paramsH->{NLS_NCHAR_CHARACTERSET}, - db_nchar_is_utf($dbh) ? "Unicode" : "Non-Unicode"; - note($out); - my $ora_client_version = ORA_OCI(); - $out = sprintf "Client $ora_client_version NLS_LANG is '%s', NLS_NCHAR is '%s'\n", - ora_env_var("NLS_LANG") || "", ora_env_var("NLS_NCHAR") || ""; - note($out); -} -sub db_ochar_is_utf { return shift->ora_can_unicode & 2 } -sub db_nchar_is_utf { return shift->ora_can_unicode & 1 } - -sub client_ochar_is_utf8 { - my $NLS_LANG = ora_env_var("NLS_LANG") || ''; - $NLS_LANG =~ s/.*\.//; - return $NLS_LANG =~ m/utf8/i; -} -sub client_nchar_is_utf8 { - my $NLS_LANG = ora_env_var("NLS_LANG") || ''; - $NLS_LANG =~ s/.*\.//; - my $NLS_NCHAR = ora_env_var("NLS_NCHAR") || $NLS_LANG; - return $NLS_NCHAR =~ m/utf8/i; -} - -sub nls_local_has_utf8 -{ - return client_ochar_is_utf8() || client_nchar_is_utf8(); -} - -sub set_nls_nchar -{ - my ($cset,$verbose) = @_; - if ( defined $cset ) { - $ENV{NLS_NCHAR} = "$cset" - } else { - undef $ENV{NLS_NCHAR}; # XXX windows? (perhaps $ENV{NLS_NCHAR}=""?) - } - # Special treatment for environment variables under Cygwin - - # see comments in dbdimp.c for details. - DBD::Oracle::ora_cygwin_set_env('NLS_NCHAR', $ENV{NLS_NCHAR}||'') - if $^O eq 'cygwin'; - note(defined ora_env_var("NLS_NCHAR") ? # defined? - "set \$ENV{NLS_NCHAR}=$cset\n" : - "set \$ENV{NLS_LANG}=undef\n") # XXX ? - if defined $verbose; -} - -sub set_nls_lang_charset -{ - my ($lang,$verbose) = @_; - - $ENV{NLS_LANG} = $lang ? "AMERICAN_AMERICA.$lang" : ''; - - note "set \$ENV{NLS_LANG='$ENV{NLS_LANG}'"; - - # Special treatment for environment variables under Cygwin - - # see comments in dbdimp.c for details. - DBD::Oracle::ora_cygwin_set_env('NLS_LANG', $ENV{NLS_LANG}||'') - if $^O eq 'cygwin'; -} - -sub byte_string { - my $ret = join( "|" ,unpack( "C*" ,$_[0] ) ); - return $ret; -} -sub nice_string { - my @raw_chars = (utf8::is_utf8($_[0])) - ? unpack("U*", $_[0]) # unpack unicode characters - : unpack("C*", $_[0]); # not unicode, so unpack as bytes - my @chars = map { - $_ > 255 ? # if wide character... - sprintf("\\x{%04X}", $_) : # \x{...} - chr($_) =~ /[[:cntrl:]]/ ? # else if control character ... - sprintf("\\x%02X", $_) : # \x.. - chr($_) # else as themselves - } @raw_chars; - - foreach my $c ( @chars ) - { - if ( $c =~ m/\\x\{08(..)}/ ) { - $c .= "='" .chr(hex($1)) ."'"; - } - } - my $ret = join("",@chars); - -} - - -sub view_with_sqlplus -{ - my ( $use_nls_lang ,$tdata ) = @_ ; - my $table = table(); - my $tcols = $tdata->{cols}; - my $sqlfile = "sql.txt" ; - my $cols = 'idx,nch_col' ; - open F , ">$sqlfile" or die "could open $sqlfile"; - print F $ENV{ORACLE_USERID} ."\n"; - my $str = qq( -col idx form 99 -col ch_col form a8 -col nch_col form a16 -select $cols from $table; -) ; - print F $str; - print F "exit;\n" ; - close F; - - my $nls='unset'; - $nls = ora_env_var("NLS_LANG") if ora_env_var("NLS_LANG"); - local $ENV{NLS_LANG} = '' if not $use_nls_lang; - print "From sqlplus...$str\n ...with NLS_LANG = $nls\n" ; - system( "sqlplus -s \@$sqlfile" ); - unlink $sqlfile; -} - - - -1; diff --git a/t/rt13865.t b/t/rt13865.t index 78a63c02..f0196012 100644 --- a/t/rt13865.t +++ b/t/rt13865.t @@ -1,28 +1,30 @@ -# $Id$ +#!perl + use strict; +use warnings; + +use lib 't/lib'; +use DBDOracleTestLib qw/ db_handle table drop_table force_drop_table /; use DBI; use DBD::Oracle; use Test::More; -use lib 't'; -require 'nchar_test_lib.pl'; +my $dbh = db_handle() + or plan skip_all => q|Can't connect to database|; -my $dbh = db_handle() or plan skip_all => "can't connect to database"; - -my %priv = map { $_ => 1 } get_privs( $dbh ); +my %priv = map { $_ => 1 } get_privs($dbh); unless ( $priv{'CREATE TABLE'} ) { plan skip_all => q{requires permissions 'CREATE TABLE'}; } -plan tests => 9; - -$dbh->do( 'DROP TABLE RT13865' ); +my $table = table('rt13865__drop_me'); +force_drop_table($dbh, $table); -$dbh->do( <<'END_SQL' ) or die $dbh->errstr; -CREATE TABLE RT13865( +my $create_sql = <<"END_SQL"; +CREATE TABLE $table( COL_INTEGER INTEGER, COL_NUMBER NUMBER, COL_NUMBER_37 NUMBER(37), @@ -37,52 +39,108 @@ CREATE TABLE RT13865( ) END_SQL -my $col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_INTEGER' ); - -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 38, - "INTEGER is alias for NUMBER(38)"; - -$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NUMBER_37' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 37, - "NUMBER(37)"; - -$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NUMBER' ); -cmp_ok $col_h->fetchrow_hashref->{COLUMN_SIZE}, '>', 0, - "NUMBER"; - -$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_VC2' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, - "VARCHAR(67)"; +my @tests = ( + { + col => 'COL_INTEGER', + size => 38, + cmp => '==', + name => 'INTEGER is alias for NUMBER(38)' + }, + { + col => 'COL_NUMBER_37', + size => 37, + cmp => '==', + name => 'NUMBER(37)' + }, + { + col => 'COL_NUMBER', + size => 0, + cmp => '>', + name => 'NUMBER' + }, + { + col => 'COL_VC2', + size => 67, + cmp => '==', + name => 'VARCHAR2(67)' + }, + { + col => 'COL_VC2_69CHAR', + size => 69, + cmp => '==', + name => 'VARCHAR2(69)' + }, + { + col => 'COL_NVC2', + size => 69, + cmp => '==', + name => 'NVARCHAR2(69)' + }, + { + col => 'COL_NC', + size => 69, + cmp => '==', + name => 'NCHAR(69)' + }, + { + col => 'COL_CHAR', + size => 67, + cmp => '==', + name => 'CHAR(67)' + }, + { + col => 'COL_CHAR_69CHAR', + size => 69, + cmp => '==', + name => 'CHAR(69)' + }, +); # @tests + +ok( $dbh->do($create_sql), "Create database: $table" ) + or die $dbh->errstr; + +for my $test (@tests) { + + my $col_h = $dbh->column_info( undef, undef, uc($table), $test->{col} ); + + # if column_info() returns undef, then the driver doesnt support column_info. DBD::Oracle should support it. + ok( + $col_h, + sprintf( + 'column_info() returns something for test: %s', $test->{name} + ) + ) or next; + cmp_ok( ref $col_h, 'eq', 'DBI::st', + sprintf( 'returned object is correct for test: %s', $test->{name} ) ); + +# if there is no row, then the table/column couldnt be found... this should not happen either + my $row = $col_h->fetchrow_hashref; + cmp_ok( + ref $row, + 'eq', 'HASH', + sprintf( +'column/table now found - fetchrow_hashref returned a hash for test: %s', + $test->{name} ) + ) or next; + + # this is the actual test, everything above it sanity checking / pre-diagnosis + cmp_ok( $row->{COLUMN_SIZE}, $test->{cmp}, $test->{size}, $test->{name} ); -$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_VC2_69CHAR' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, - "VARCHAR(69)"; - -$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NVC2' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, - "NVARCHAR2(69)"; - -$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_NC' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, - "NCHAR(69)"; - -$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_CHAR' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 67, - "CHAR(67)"; - -$col_h = $dbh->column_info( undef, undef, 'RT13865', 'COL_CHAR_69CHAR' ); -is $col_h->fetchrow_hashref->{COLUMN_SIZE} => 69, - "CHAR(69)"; +} -$dbh->do( 'DROP TABLE RT13865' ); +drop_table($dbh, $table); # utility functions -sub get_privs { +sub get_privs { my $dbh = shift; - my $sth = $dbh->prepare( 'SELECT PRIVILEGE from session_privs' ); + my $sth = $dbh->prepare('SELECT PRIVILEGE from session_privs'); $sth->execute; return map { $_->[0] } @{ $sth->fetchall_arrayref }; } + +$dbh->disconnect if $dbh; + +done_testing(); diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index e184c98f..16a7bdd4 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -1,34 +1,35 @@ -#!/usr/bin/perl -w +#!perl use strict; use warnings; +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_ochar_is_utf db_handle /; + use Test::More; use DBI; use Encode; -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; - -$ENV{NLS_LANG} = 'AMERICAN_AMERICA.UTF8'; +$ENV{NLS_LANG} = 'AMERICAN_AMERICA.UTF8'; $ENV{NLS_NCHAR} = 'UTF8'; -my $dbh = DBI->connect( $dsn, $dbuser, '', { - PrintError => 0, AutoCommit => 0 -}); +my $dbh = db_handle( + { + PrintError => 0, + AutoCommit => 0 + } +); -plan skip_all => "unable to connect to Oracle database" if not $dbh; -plan skip_all => "database character set is not Unicode" unless db_ochar_is_utf($dbh); +plan skip_all => 'Unable to connect to Oracle database' if not $dbh; +plan skip_all => 'Database character set is not Unicode' + unless db_ochar_is_utf($dbh); plan tests => 3; $dbh->do(q(alter session set nls_territory = 'GERMANY')); -my $sth = $dbh->prepare(<<"END_SQL"); +my $sth = $dbh->prepare(<<'END_SQL'); SELECT ltrim(rtrim(to_char(0, 'L'))) FROM dual END_SQL @@ -39,7 +40,7 @@ $sth->bind_columns( \($val) ); $sth->fetch; -is Encode::is_utf8($val) => 1, "utf8 encoded"; +is Encode::is_utf8($val) => 1, 'utf8 encoded'; $sth->finish; @@ -57,18 +58,18 @@ begin end; END_SQL -$sth->bind_param_inout(':ret', \$val, 100); +$sth->bind_param_inout( ':ret', \$val, 100 ); $sth->execute; -is Encode::is_utf8($val) => 1, "utf8 encoded"; +is Encode::is_utf8($val) => 1, 'utf8 encoded'; $sth = $dbh->prepare(<<'END_SQL'); declare l_ret varchar2(10); begin - select ltrim(rtrim(to_char(0, 'L'))) - || ltrim(rtrim(to_char(0, 'L'))) - || ltrim(rtrim(to_char(0, 'L'))) + select ltrim(rtrim(to_char(0, 'L'))) + || ltrim(rtrim(to_char(0, 'L'))) + || ltrim(rtrim(to_char(0, 'L'))) into l_ret from dual; -- @@ -79,10 +80,9 @@ END_SQL $val = undef; # WARNING: does *not* truncate. DBD::Oracle doesn't heed the 3rd parameter -$sth->bind_param_inout(':ret', \$val, 1); +$sth->bind_param_inout( ':ret', \$val, 1 ); $sth->execute; -is Encode::is_utf8($val) => 1, "truncated, yet utf8 encoded"; - -$dbh->disconnect; +is Encode::is_utf8($val) => 1, 'truncated, yet utf8 encoded'; +$dbh->disconnect if $dbh; diff --git a/t/rt85886.t b/t/rt85886.t index 683d3743..3d43a202 100755 --- a/t/rt85886.t +++ b/t/rt85886.t @@ -1,50 +1,49 @@ -#!/usr/bin/perl -w +#!perl use strict; use warnings; +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; + use Test::More; use DBI qw(:sql_types); use Devel::Peek; use B qw( svref_2object SVf_IOK SVf_NOK SVf_POK ); -unshift @INC ,'t'; -require 'nchar_test_lib.pl'; - sub is_iv { - my $sv = svref_2object(my $ref = \$_[0]); - my $flags = $sv->FLAGS; - - # See http://www.perlmonks.org/?node_id=971411 - my $x = $sv->can('PV') ? $sv->PV : undef; - - if (wantarray) { - return ($flags & SVf_IOK, $x); - } else { - return $flags & SVf_IOK; - } + my $sv = svref_2object( my $ref = \$_[0] ); + my $flags = $sv->FLAGS; + + # See http://www.perlmonks.org/?node_id=971411 + my $x = $sv->can('PV') ? $sv->PV : undef; + + if (wantarray) { + return ( $flags & SVf_IOK, $x ); + } + else { + return $flags & SVf_IOK; + } } -my $dsn = oracle_test_dsn(); -my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; +my $dbh = db_handle( + { + PrintError => 0, + FetchHashKeyName => 'NAME_lc' + } +); -my $dbh = DBI->connect( $dsn, $dbuser, '', { - PrintError => 0, FetchHashKeyName =>'NAME_lc'}); - -plan skip_all => "unable to connect to Oracle database" if not $dbh; +plan skip_all => 'Unable to connect to Oracle database' if not $dbh; plan tests => 2; my $s = $dbh->prepare(q/select 1 as one from dual/); $s->execute; -$s->bind_col (1, undef, {TYPE => SQL_INTEGER, DiscardString => 1}); - -my $list = $s->fetchall_arrayref({}); - -is($list->[0]{one}, 1, "correct value returned"); -ok(is_iv($list->[0]{one}), "ivok") or Dump($list->[0]{one}); +$s->bind_col( 1, undef, { TYPE => SQL_INTEGER, DiscardString => 1 } ); -$dbh->disconnect; +my $list = $s->fetchall_arrayref( {} ); +is( $list->[0]{one}, 1, 'correct value returned' ); +ok( is_iv( $list->[0]{one} ), 'ivok' ) or Dump( $list->[0]{one} ); From 2816e07fd50c6b68612464a1f1840ca7bb61031c Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 18 Jun 2018 10:45:41 +1000 Subject: [PATCH 513/637] Update mailmap file --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index 5bf525fd..0803ca49 100644 --- a/.mailmap +++ b/.mailmap @@ -7,3 +7,5 @@ Martin J. Evans John Scoles Michael Portnoy +Dean Hamstead +Dean Hamstead From 9d1160a257357c889cfa96b8640d4a519fc0d0aa Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 18 Jun 2018 11:08:11 +1000 Subject: [PATCH 514/637] Add Travis CI file --- .travis.yml | 206 ++++++++++++++++++ MANIFEST.SKIP | 1 + .../01_install_oracle_xe.bash | 56 +++++ .../02_install_oracle_instantclient.bash | 83 +++++++ 4 files changed, 346 insertions(+) create mode 100644 .travis.yml create mode 100755 maint/travis-ci_scripts/01_install_oracle_xe.bash create mode 100755 maint/travis-ci_scripts/02_install_oracle_instantclient.bash diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..33471c45 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,206 @@ +language: perl + +# See https://docs.travis-ci.com/user/reference/overview/#Virtualisation-Environment-vs-Operating-System +os: linux +dist: trusty +sudo: required + +env: + global: + - AUTHOR_TESTING=1 + - AUTOMATED_TESTING=1 + - EXTENDED_TESTING=1 + - RELEASE_TESTING=0 + - CFLAGS="-g -O2 -fstack-protector -Wformat -Werror=format-security" + - CPPFLAGS="-D_FORTIFY_SOURCE=2" + - CXXFLAGS="-g -O2 -fstack-protector -Wformat -Werror=format-security" + - LDFLAGS="-Wl,-z,relro" + +addons: + apt: + packages: + - unzip + - libaio1 + +matrix: + fast_finish: true + + allow_failures: + - perl: 'blead' + - perl: '5.8' + +# FYI Oracle XE only comes in utf8, so we can't run USASCII version of tests + + include: +# Perl 5.26 variations + - perl: '5.26' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.26' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.26-shrplib' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.26-shrplib' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + +# Perl 5.24 variations + - perl: '5.24' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.24' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.24-shrplib' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.24-shrplib' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.24-extras' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.24-extras' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + +# Perl 5.22 variations + - perl: '5.22' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.22' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.22-shrplib' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.22-shrplib' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.22-extras' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.22-extras' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + +# Test without database, all tests should skip + - perl: '5.26' + env: + - ORACLEV=11.2 + - COVERAGE=1 + - perl: '5.26' + env: + - ORACLEV=12.2 + - COVERAGE=1 + +before_install: + - sudo maint/travis-ci_scripts/01_install_oracle_xe.bash + - sudo maint/travis-ci_scripts/02_install_oracle_instantclient.bash + - . /etc/profile + - git config --global user.name "TravisCI" + - git config --global user.email $HOSTNAME":not-for-mail@travis-ci.org" + - git clone git://github.com/travis-perl/helpers ~/travis-perl-helpers + - source ~/travis-perl-helpers/init + - build-perl + - perl -V + - build-dist + - cd $BUILD_DIR + +install: + - perl -M5.014 -e1 2>/dev/null || cpan-install Dist::Zilla@5.047 + - cpan-install --deps + - cpan-install --coverage + +before_script: + - pwd + - coverage-setup + +script: + - perl Makefile.PL + - make +# - make test + - prove -bv -r -s -j1 $(test-files) + - ORACLE_USERID_2="" prove -bv t/60reauth.t +# - dzil smoke --release --author + +after_success: + - coverage-report diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index be8ec702..34807e80 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -13,6 +13,7 @@ ^info/ ^oci8/ ^oracle/ +^maint/ ^tags$ ~$ ^\.git diff --git a/maint/travis-ci_scripts/01_install_oracle_xe.bash b/maint/travis-ci_scripts/01_install_oracle_xe.bash new file mode 100755 index 00000000..8b96169e --- /dev/null +++ b/maint/travis-ci_scripts/01_install_oracle_xe.bash @@ -0,0 +1,56 @@ +#!/bin/bash + +set -ex + +# maybe in the future this will be more specific +if [ -n "$ORACLEDBV" ]; then + +# wget --content-disposition https://packagecloud.io/mojotech/cloud/packages/debian/jessie/oracle-xe_11.2.0-1.0_amd64.deb/download.deb + +## This is a pile of sucky suck suck + +pwd +wget --quiet https://raw.githubusercontent.com/wnameless/docker-oracle-xe-11g/master/assets/oracle-xe_11.2.0-1.0_amd64.debaa +wget --quiet https://raw.githubusercontent.com/wnameless/docker-oracle-xe-11g/master/assets/oracle-xe_11.2.0-1.0_amd64.debab +wget --quiet https://raw.githubusercontent.com/wnameless/docker-oracle-xe-11g/master/assets/oracle-xe_11.2.0-1.0_amd64.debac +cat oracle-xe_11.2.0-1.0_amd64.deba* > oracle-xe_11.2.0-1.0_amd64.deb +dpkg --install oracle-xe_11.2.0-1.0_amd64.deb + +# Hack needed because oracle configuration looks for awk in /bin instead of $PATH +ln -s /usr/bin/awk /bin/awk +# Oracle also needs this: +mkdir /var/lock/subsys + +# Docker containers and stuff dont work with memory_target +perl -pi -e 's/^(memory_target=.*)/#$1/' /u01/app/oracle/product/11.2.0/xe/config/scripts/init.ora +perl -pi -e 's/^(memory_target=.*)/#$1/' /u01/app/oracle/product/11.2.0/xe/config/scripts/initXETemp.ora + +# These seem to be needed too +echo -e "pga_aggregate_target=200540160\nsga_target=601620480" >> /u01/app/oracle/product/11.2.0/xe/config/scripts/init.ora +echo -e "pga_aggregate_target=200540160\nsga_target=601620480" >> /u01/app/oracle/product/11.2.0/xe/config/scripts/initXETemp.ora + +# Now configure Oracle XE +printf 8080\\n1521\\nadminpass\\nadminpass\\ny\\n | /etc/init.d/oracle-xe configure + +sqlplusbin="/u01/app/oracle/product/11.2.0/xe/bin/sqlplus" +# ORACLE_SID=XE ORACLE_HOME="/u01/app/oracle/product/11.2.0/xe" $sqlplusbin -H +USER1=`echo $ORACLE_USERID|sed 's/\/.*//'` +USER2=`echo $ORACLE_USERID_2|sed 's/\/.*//'` +PASS1=`echo $ORACLE_USERID|sed 's/.*\///'` +PASS2=`echo $ORACLE_USERID_2|sed 's/.*\///'` + +echo "create user $USER1 identified by $PASS1;" \ + | ORACLE_SID=XE ORACLE_HOME="/u01/app/oracle/product/11.2.0/xe" \ + $sqlplusbin -L -S SYSTEM/adminpass +ORACLE_SID=XE ORACLE_HOME="/u01/app/oracle/product/11.2.0/xe" $sqlplusbin -L -S SYSTEM/adminpass <<< "grant connect,resource to $USER1;" + +echo "create user $USER2 identified by $PASS2;" \ + | ORACLE_SID=XE ORACLE_HOME="/u01/app/oracle/product/11.2.0/xe" \ + $sqlplusbin -L -S SYSTEM/adminpass +ORACLE_SID=XE ORACLE_HOME="/u01/app/oracle/product/11.2.0/xe" $sqlplusbin -L -S SYSTEM/adminpass <<< "grant connect,resource to $USER2;" + +# ORACLE_SID=XE ORACLE_HOME="/u01/app/oracle/product/11.2.0/xe" $sqlplusbin -L -S SYSTEM/adminpass @/dev/stdin <<< "create database dbusasci character set US7ASCII national character set utf8 undo tablespace undotbs1 default temporary tablespace temp;" +# ORACLE_SID=XE ORACLE_HOME="/u01/app/oracle/product/11.2.0/xe" $sqlplusbin -L -S SYSTEM/adminpass @/dev/stdin <<< "create database dbutf character set AL32UTF8 national character set AL16UTF16 undo tablespace undotbs1 default temporary tablespace temp;" + + +fi diff --git a/maint/travis-ci_scripts/02_install_oracle_instantclient.bash b/maint/travis-ci_scripts/02_install_oracle_instantclient.bash new file mode 100755 index 00000000..d915887e --- /dev/null +++ b/maint/travis-ci_scripts/02_install_oracle_instantclient.bash @@ -0,0 +1,83 @@ +#!/bin/bash + +set -ex + +if [ "$ORACLEV" = "11.2" ]; then + export LONGV="11.2.0.4.0" +fi +if [ "$ORACLEV" = "12.2" ]; then + export LONGV="12.2.0.1.0" +fi + +if [ -n "$ORACLEV" ]; then + echo "Install Oracle SDK $ORACLEV" + mkdir /etc/oracle + mkdir -p /usr/lib/oracle/$ORACLEV/client/bin + mkdir -p /usr/lib/oracle/$ORACLEV/client/lib + mkdir -p /usr/include/oracle/$ORACLEV/client + mkdir -p /usr/share/oracle/$ORACLEV/client + pushd `pwd` + cd /usr/lib/oracle + for i in "basic" "sdk" "sqlplus"; do + # Repo intended for Dockerfiles, see https://github.com/bumpx/oracle-instantclient/blob/master/README.md + wget --quiet https://github.com/bumpx/oracle-instantclient/raw/master/instantclient-$i-linux.x64-$LONGV.zip + done + for i in `ls *zip`; do unzip $i; done +fi +if [ "$ORACLEV" = "12.2" ]; then + echo "# Contents of instantclient-basic-linux.x64-$LONGV.zip" + find instantclient_12_2 + mv instantclient_12_2/adrci $ORACLEV/client/bin/ + mv instantclient_12_2/genezi $ORACLEV/client/bin/ + mv instantclient_12_2/uidrvci $ORACLEV/client/bin/ + mv instantclient_12_2/{libclntshcore.so.12.1,libclntsh.so.12.1,libipc1.so,libmql1.so,libnnz12.so,libocci.so.12.1,libociei.so,libocijdbc12.so,libons.so,liboramysql12.so,ojdbc8.jar,xstreams.jar} $ORACLEV/client/lib/ + echo "# Contents of instantclient-sqlplus-linux.x64-$LONGV.zip" + mv instantclient_12_2/sqlplus $ORACLEV/client/bin/ + mv instantclient_12_2/glogin.sql instantclient_12_2/libsqlplus.so instantclient_12_2/libsqlplusic.so $ORACLEV/client/lib/ + echo "# Contents of instantclient-sdk-linux.x64-$LONGV.zip" + mv instantclient_12_2/sdk/include/*h /usr/include/oracle/$ORACLEV/client/ + mv instantclient_12_2/sdk/demo/* /usr/share/oracle/$ORACLEV/client/ + mv instantclient_12_2/sdk/ott /usr/share/oracle/$ORACLEV/client/ + mv instantclient_12_2/sdk/ottclasses.zip $ORACLEV/client/lib/ottclasses.zip + ln -s libclntshcore.so.12.1 $ORACLEV/client/lib/libclntshcore.so + ln -s libclntsh.so.12.1 $ORACLEV/client/lib/libclntsh.so + ln -s libocci.so.12.1 $ORACLEV/client/lib/libocci.so + echo "# FYI What wasnt moved from Oracle zip files:" + find instantclient_12_2 + echo "# Clean up" + rm -rf instantclient_12_2 +fi +if [ "$ORACLEV" = "11.2" ]; then + echo "# Contents of instantclient-basic-linux.x64-$LONGV.zip" + mv instantclient_11_2/adrci $ORACLEV/client/bin/ + mv instantclient_11_2/genezi $ORACLEV/client/bin/ + mv instantclient_11_2/uidrvci $ORACLEV/client/bin/ + mv instantclient_11_2/{libclntsh.so.11.1,libnnz11.so,libocci.so.11.1,libociei.so,libocijdbc11.so,ojdbc5.jar,ojdbc6.jar,xstreams.jar} $ORACLEV/client/lib/ + echo "# Contents of instantclient-sqlplus-linux.x64-$LONGV.zip" + mv instantclient_11_2/sqlplus $ORACLEV/client/bin/ + mv instantclient_11_2/glogin.sql instantclient_11_2/libsqlplus.so instantclient_11_2/libsqlplusic.so $ORACLEV/client/lib/ + echo "# Contents of instantclient-sdk-linux.x64-$LONGV.zip" + mv instantclient_11_2/sdk/include/*h /usr/include/oracle/$ORACLEV/client/ + mv instantclient_11_2/sdk/demo/* /usr/share/oracle/$ORACLEV/client/ + mv instantclient_11_2/sdk/ott /usr/share/oracle/$ORACLEV/client/ + mv instantclient_11_2/sdk/ottclasses.zip $ORACLEV/client/lib/ottclasses.zip + ln -s libclntsh.so.11.1 $ORACLEV/client/lib/libclntsh.so + ln -s libocci.so.11.1 $ORACLEV/client/lib/libocci.so + echo "# FYI What wasnt moved from Oracle zip files:" + find instantclient_11_2 + echo "# Clean up" + rm -rf instantclient_11_2 +fi +if [ -n "$ORACLEV" ]; then + echo "# Place paths in ENV" + echo "export ORACLE_HOME=/usr/lib/oracle/$ORACLEV/client" >> /etc/profile.d/oracle.sh + echo "export PATH=\$PATH:\$ORACLE_HOME/bin" >> /etc/profile.d/oracle.sh + echo "export TNS_ADMIN=/etc/oracle" >> /etc/profile.d/oracle.sh + echo "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$ORACLE_HOME/lib" >> /etc/profile.d/oracle.sh + echo "/usr/lib/oracle/$ORACLEV/client/lib" > /etc/ld.so.conf.d/oracle-instantclient.conf + echo "# Make sure stuff is +x" + chmod +x $ORACLEV/client/bin/* + ldconfig + popd + cat /etc/profile +fi From 22b04e454762e4ee7d8632b8772f0f3c8b35df6b Mon Sep 17 00:00:00 2001 From: Mike O'Regan Date: Fri, 12 Jan 2018 17:47:16 -0600 Subject: [PATCH 515/637] Fix awkwardness and spelling --- README.help.txt | 2 +- examples/bind.pl | 2 +- examples/ora_explain.pl | 2 +- examples/proc.pl | 2 +- lib/DBD/Oracle.pm | 34 +++++++++++++++++----------------- t/58object.t | 6 +++--- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/README.help.txt b/README.help.txt index 47d35154..ec4b4c21 100644 --- a/README.help.txt +++ b/README.help.txt @@ -156,7 +156,7 @@ Environment: Solaris, GCC Do not use GNU as or GNU ld on Solaris. Delete or rename them, they are just bad news. In the words of John D Groenveld : -Run, dont walk, to your console and 'mv /opt/gnu/bin/as /opt/gnu/bin/gas; +Run, don't walk, to your console and 'mv /opt/gnu/bin/as /opt/gnu/bin/gas; mv /opt/gnu/bin/ld /opt/gnu/bin/gld'. You can add -v to the gcc command in the Makefile to see what GCC is using. diff --git a/examples/bind.pl b/examples/bind.pl index 1a4f71dd..1f179822 100755 --- a/examples/bind.pl +++ b/examples/bind.pl @@ -31,7 +31,7 @@ last if ! $_; $sth->execute( uc( $_ ) ); - # Note that the variable is in parenthesis to give an array context + # Note that the variable is in parentheses to force array context if ( ( $created ) = $sth->fetchrow_array ) { print "$created\n"; } diff --git a/examples/ora_explain.pl b/examples/ora_explain.pl index 36e2b3d5..3f123d1d 100644 --- a/examples/ora_explain.pl +++ b/examples/ora_explain.pl @@ -1063,7 +1063,7 @@ ($$) } busy(0); -# Display the formated info +# Display the formatted info return(1); } diff --git a/examples/proc.pl b/examples/proc.pl index 48dedec6..f15a16d0 100755 --- a/examples/proc.pl +++ b/examples/proc.pl @@ -130,7 +130,7 @@ BEGIN # What about the return value of a PL/SQL function? Well treat it the same # as you would a call to a function from SQL*Plus. We add a placeholder # for the return value and bind it with a call to bind_param_inout so -# we can access it's value after execute. +# we can access its value after execute. my $whoami = ""; diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index b657f16b..f75f60d7 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -3411,7 +3411,7 @@ DBI documentation for more details. Fetches the next row of data from the statement handle, and returns a reference to an array holding the column values. Any columns that are NULL are returned as undef within the array. -If there are no more rows or if an error occurs, the this method return undef. You should +If there are no more rows or if an error occurs, this method returns undef. You should check C<< $sth->err >> afterwards (or use the L attribute) to discover if the undef returned was due to an error. @@ -3434,7 +3434,7 @@ a reference to a list. Do not use this in a scalar context. Fetches the next row of data and returns a hashref containing the name of the columns as the keys and the data itself as the values. Any NULL value is returned as undef value. -If there are no more rows or if an error occurs, the this method return undef. You should +If there are no more rows or if an error occurs, this method returns undef. You should check C<< $sth->err >> afterwards (or use the L attribute) to discover if the undef returned was due to an error. @@ -3885,7 +3885,7 @@ With this interface DBD::Oracle handles your data utilizing LOB Locator OCI call =item L -This allows the user direct access to the LOB Locator methods, so you have to take case of the LOB Locator operations yourself. +This allows the user direct access to the LOB Locator methods, so you have to take care of the LOB Locator operations yourself. =back @@ -3931,8 +3931,8 @@ used, normally one can get an entire LOB is a single round trip. =head3 Simple Fetch for LONGs and LONG RAWs As the name implies this is the simplest way to use this interface. DBD::Oracle just attempts to get your LONG datatypes as a single large piece. -There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LONG or LONG RAW. -If the size of the LONG or LONG RAW exceeds the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +There are no special settings, simply set the database handle's 'LongReadLen' attribute to a value that will be larger than the expected size of the LONG or LONG RAW. +If the size of the LONG or LONG RAW exceeds 'LongReadLen' DBD::Oracle will return an 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on. You have most likely reached this limit if you run into an 'ORA-01062: unable to allocate memory for define buffer' error. One solution is to set the size of 'LongReadLen' to a lower value. @@ -3996,13 +3996,13 @@ In the case above the query Got 28 characters (well really only 20 characters of =head3 Simple Fetch for CLOBs and BLOBs -To use this interface for CLOBs and LOBs datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, as well -set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected size of the LOB. If the size of the LOB exceeds -the 'LongReadLen' DBD::Oracle will return a 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. +To use this interface for the CLOB and BLOB datatypes set the 'ora_pers_lob' attribute of the statement handle to '1' with the prepare method, and +set the database handle's 'LongReadLen' attribute to a value that will be larger than the expected size of the LOB. If the size of the LOB exceeds +'LongReadLen' DBD::Oracle will return an 'ORA-24345: A Truncation' error. To stop this set the database handle's 'LongTruncOk' attribute to '1'. The maximum value of 'LongReadLen' seems to be dependent on the physical memory limits of the box that Oracle is running on in the same way that LONGs and LONG RAWs are. -For CLOBs and NCLOBs the limit is 64k chars if there is no truncation, this is an internal OCI limit complain to them if you want it changed. However if you CLOB is longer than this -and also larger than the 'LongReadLen' than the 'LongReadLen' in chars is returned. +For CLOBs and NCLOBs the limit is 64k chars if there is no truncation. This is an internal OCI limit--complain to them if you want it changed. However if your CLOB is longer than this +and also larger than 'LongReadLen' then 'LongReadLen' chars are returned. It seems with BLOBs you are not limited by the 64k. @@ -4038,9 +4038,9 @@ before the execute will return all the lobs but they will be truncated at 2MBs. With a piecewise callback fetch DBD::Oracle sets up a function that will 'callback' to the DB during the fetch and gets your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_clbk_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that -you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected -size of the LOB. Like the L and L the if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB -or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be larger than the expected +size of the LOB. Like the L and L the if the size of the LOB exceeds 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on the Simple Fetch interface. If you encounter an 'ORA-01062' error try setting the value of 'ora_piece_size' to a smaller value. The value for 'LongReadLen' is dependent on the version and settings of the Oracle DB you are using. In theory it ranges from 8GBs in 9iR1 up to 128 terabytes with 11g but you will also be limited by the physical memory of your PERL instance. @@ -4080,9 +4080,9 @@ maximum of 4 pieces (4*5MB=20MB). Like the other examples long1 fields longer th With a polling piecewise fetch DBD::Oracle iterates (Polls) over the LOB during the fetch getting your LOB (LONG, LONG RAW, CLOB, BLOB) piece by piece. To use this interface set the 'ora_piece_lob' attribute of the statement handle to '1' with the prepare method. Next set the 'ora_piece_size' to the size of the piece that -you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be the larger than the expected -size of the LOB. Like the L and Simple Fetches if the size of the LOB exceeds the is 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB -or set the 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on +you want to return on the callback. Finally set the database handle's 'LongReadLen' attribute to a value that will be larger than the expected +size of the LOB. Like the L and Simple Fetches if the size of the LOB exceeds 'LongReadLen' you can use the 'LongTruncOk' attribute to truncate the LOB +or set 'LongReadLen' to a higher value. With this interface the value of 'ora_piece_size' seems to be constrained by the same memory limit as found on the L. Using the table from the example above this code; @@ -5418,7 +5418,7 @@ Most of these PL/SQL examples come from: Eric Bartley . # What about the return value of a PLSQL function? Well treat it the same # as you would a call to a function from SQL*Plus. We add a placeholder # for the return value and bind it with a call to bind_param_inout so - # we can access it's value after execute. + # we can access its value after execute. my $whoami = ""; diff --git a/t/58object.t b/t/58object.t index 9d39defc..c5e03880 100644 --- a/t/58object.t +++ b/t/58object.t @@ -182,7 +182,7 @@ qq{ INSERT INTO $list_table VALUES(81,$list_type($inner_type(null, 'listed'))) } ok( scalar @row1, 'old: Fetch first row' ); cmp_ok( ref $row1[1], 'eq', 'ARRAY', 'old: Row 1 column 2 is an ARRAY' ); cmp_ok( scalar( @{ $row1[1] } ), - '==', 2, 'old: Row 1 column 2 is has 2 elements' ); + '==', 2, 'old: Row 1 column 2 has 2 elements' ); SKIP: { skip 'Subtypes new in Oracle 9' => 6 if $ora8; @row2 = $sth->fetchrow(); @@ -190,14 +190,14 @@ qq{ INSERT INTO $list_table VALUES(81,$list_type($inner_type(null, 'listed'))) } cmp_ok( ref $row2[1], 'eq', 'ARRAY', 'old: Row 2 column 2 is an ARRAY' ); cmp_ok( scalar( @{ $row2[1] } ), - '==', 2, 'old: Row 2 column 2 is has 2 elements' ); + '==', 2, 'old: Row 2 column 2 has 2 elements' ); @row3 = $sth->fetchrow(); ok( scalar @row3, 'old: Fetch third row' ); cmp_ok( ref $row3[1], 'eq', 'ARRAY', 'old: Row 3 column 2 is an ARRAY' ); cmp_ok( scalar( @{ $row3[1] } ), - '==', 2, 'old: Row 3 column 2 is has 2 elements' ); + '==', 2, 'old: Row 3 column 2 has 2 elements' ); } ok( !$sth->fetchrow(), 'old: No more rows expected' ); From 68fe0c5848b8b467b6a5c3597db2164dcf17e99f Mon Sep 17 00:00:00 2001 From: Mike O'Regan Date: Fri, 12 Jan 2018 17:49:00 -0600 Subject: [PATCH 516/637] Change misspelling of SH_LIBRARY_PATH in quoted text --- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 4f849029..7b6acd1d 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -664,7 +664,7 @@ the extra link options. Gram M. Ludlow writes: I recently had a problem with Oracle 9 64-bit on HPUX 11i. We have -another application that required SH_LIBARY_PATH to point to the 64-bit +another application that required SH_LIBRARY_PATH to point to the 64-bit libraries, which "broke" the Oraperl module. So I did some research and successfully recompiled and re-installed with the most recent versions of everything (perl, DBI, DBD) that works with 64-bit shared libraries. This From 533527e6c11dd66f5f9f4cd4d36bf52e9979432b Mon Sep 17 00:00:00 2001 From: Mike O'Regan Date: Wed, 17 Jan 2018 10:04:47 -0600 Subject: [PATCH 517/637] stop referring to the VARCHAR2 as deprecated --- lib/DBD/Oracle.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index f75f60d7..6604c0dd 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -3866,7 +3866,7 @@ cursor has to be explicitly cancelled on the server. If you do not do this you m =head1 LOBS AND LONGS The key to working with LOBs (CLOB, BLOBs) is to remember the value of an Oracle LOB column is not the content of the LOB. It's a -'LOB Locator' which, after being selected or inserted needs extra processing to read or write the content of the LOB. There are also legacy LONG types (LONG, LONG RAW, VARCHAR2) +'LOB Locator' which, after being selected or inserted needs extra processing to read or write the content of the LOB. There are also legacy LONG types (LONG, LONG RAW) which are presently deprecated by Oracle but are still in use. These LONG types do not utilize a 'LOB Locator' and also are more limited in functionality than CLOB or BLOB fields. From d388c97ac3b9cba855d403b47317b01161355037 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 21 Jun 2018 09:47:09 +1000 Subject: [PATCH 518/637] Update changes based on included PR's and GH bugs --- Changes | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Changes b/Changes index 4474b6c2..1c2ba1a4 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,19 @@ Revision history for DBD::Oracle not a fixed length. Code now allows up to a size of 2000. (GH#31, Martin J. Evans) + Various fixes for compiler warnings, OCI handle leaks, and OCI programming + errors. - (PR#38, Dag Lem) + + Corrections to t/25plsql.t - (GH#56, kjetillll) + + Fix: Invalid binding call for large undef arrays. - (GH#36, GH ghost) + + Fix: compile warnings about int vs long unsigned. - (PR#62, Dean Hamstead) + + Fix: Spelling errors in pod. - (PR#63, Jochen Hayek) + + Fox: Various changes in pod. - (PR#54, Mike O'Regan) + [ENHANCEMENT] Connection informational messages like "ORA-28002: the password will @@ -18,6 +31,20 @@ Revision history for DBD::Oracle Ignore constraints which are not enabled in primary/foreign key_info (GH#23, Martin J. Evans) + dist.init overhaul. - (PR#62, Dean Hamstead) + + Mailmap and TODO changes. - (PR#62, Dean Hamstead) + + Travis CI testing. - (PR#62, Dean Hamstead) + Note: this uses Oracle XE which doesn't provide enough features to test + the entire suite. Nor does it test anything other than Linux on Linux. + Release tests are also NOT yet run in Travis. + + Rewrite of DRCP session pooling to make it work as intended - (PR#38, Dag Lem) + + Support for Oracle Fast Application Notification (FAN). - (PR#38, Dag Lem) + + Work by Dag Lem was sponsored by EVRY Information Services. Thank you! 1.75_2 2014-11-19 From b3fafb125fe7ddec67330130d88901f8b41f552e Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 21 Aug 2018 09:31:19 +1000 Subject: [PATCH 519/637] Fix #57 based upon suggestions from @tonycoz. See https://github.com/pythian/DBD-Oracle/issues/57#issuecomment-414253275 --- dbdimp.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index cef45863..1e9c1ce8 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1740,10 +1740,15 @@ phs_t *phs; laststyle = style; if (imp_sth->all_params_hv == NULL) imp_sth->all_params_hv = newHV(); - phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)+namelen+1); - phs = (phs_t*)(void*)SvPVX(phs_sv); + /* allocate and copy enough for phs_tpl */ + phs_sv = newSVpvn((char*)&phs_tpl, sizeof(phs_tpl)); (void)hv_store(imp_sth->all_params_hv, start, namelen, phs_sv, 0); - phs->idx = idx-1; /* Will be 0 for :1, -1 for :foo. */ + /* allocate extra room for the name (returns the PV) */ + phs = (phs_t*)(void*)SvGROW(phs_sv, sizeof(phs_tpl)+namelen+1); + phs->idx = idx-1; /* Will be 0 for :1, -1 for :foo. */ + /* tell the SV the full length */ + SvCUR_set(phs_sv, sizeof(phs_tpl)+namelen); + /* copy the name */ strcpy(phs->name, start); } *dest = '\0'; From 357f7bbc7ce58c7e9a136599100a27f2a8652b57 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 22 Aug 2018 16:16:46 +1000 Subject: [PATCH 520/637] Update changelog for GH#57 --- Changes | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 1c2ba1a4..b552511d 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,8 @@ Revision history for DBD::Oracle [BUG FIXES] + Fix potential buffer overflow in dbdimp.c - (GH#57, Various) + Fix truncation error on ROWIDs from an Index Organized table as they are not a fixed length. Code now allows up to a size of 2000. (GH#31, Martin J. Evans) @@ -19,7 +21,7 @@ Revision history for DBD::Oracle Fix: Spelling errors in pod. - (PR#63, Jochen Hayek) - Fox: Various changes in pod. - (PR#54, Mike O'Regan) + Fix: Various changes in pod. - (PR#54, Mike O'Regan) [ENHANCEMENT] From 1a510be93548cc4148021589b8826ac70cdbd844 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 14 Nov 2018 20:41:16 +1100 Subject: [PATCH 521/637] Update Changes file for 1.75_42 --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index b552511d..3cb39ada 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} +1.75_42 2018-08-22 + [BUG FIXES] Fix potential buffer overflow in dbdimp.c - (GH#57, Various) From 03b744e5152f902feb87f43b958520135ba716da Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Thu, 15 Nov 2018 13:49:18 -0600 Subject: [PATCH 522/637] Find ORACLE_HOME based off Operating System (Linux) when other attempts in find_oracle_home() have failed Determine Oracle client version from ORACLE_HOME path when other attempts in get_client_version() have failed --- Makefile.PL | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Makefile.PL b/Makefile.PL index 89b9c09b..b34b6387 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -979,6 +979,13 @@ sub find_oracle_home { @oh = grep { (glob("$_/../lib*/libclntsh.$so*"))[0] } @path; s:/[^/]/?$:: for @oh; } + if (!@oh && lc($^O) eq 'linux') { # Try the standard Linux RPM location + my @loh = glob("/usr/lib/oracle/*/*/lib/libclntsh.$so*"); + @loh = sort { $a cmp $b } @loh; + my $loh = pop(@loh); + $loh =~ s/\/lib\/libclntsh.*$//g; + push(@oh,$loh); + } print "Found @oh\n" if @oh; return $oh[0]; } @@ -1691,6 +1698,9 @@ sub get_client_version { elsif ( "$OH/" =~ m!/10g!) { # scary but handy $client_version_full = "10.0.0.0"; } + elsif ( "$OH/" =~ m!/usr/lib/oracle/(\d+\.\d)/!) { # Linux RPM + $client_version_full = "$1.0.0"; + } } if ($force_version && $force_version ne $client_version_full) { From 57b8e8f7a2020516c484b08e3553af83c1fd6d39 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 22 Nov 2018 10:44:41 +1100 Subject: [PATCH 523/637] Bump to 1.75 --- Changes | 2 ++ dist.ini | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 3cb39ada..c1997a68 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} + No Changes from 1.75_42 + 1.75_42 2018-08-22 [BUG FIXES] diff --git a/dist.ini b/dist.ini index ebdcfeee..24d2d25e 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.74 +version = 1.75 ; Generate files From 2b533cbc6d4e04d8d4e5aca3adcfd45f43f4996a Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 22 Nov 2018 10:49:01 +1100 Subject: [PATCH 524/637] Adjust NextRelease to be consistent with Changes format we're using --- dist.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 24d2d25e..2637f829 100644 --- a/dist.ini +++ b/dist.ini @@ -33,7 +33,8 @@ version = 1.75 [ReadmeMarkdownFromPod] [NextRelease] -time_zone = America/Montreal +time_zone = UTC +format = %-9v %{yyyy-MM-dd}d [MetaProvides::Package] [MatchManifest] From 43a7127f254d9ba22ca140dcaf46bd4873aa3d70 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 22 Nov 2018 16:19:55 +1100 Subject: [PATCH 525/637] Bump to v1.76 --- Changes | 6 ++++++ dist.ini | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index c1997a68..c6eacbe1 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,12 @@ Revision history for DBD::Oracle {{$NEXT}} +1.76 2018-11-22 + + No Changes from 1.75, we just botched up publishing to CPAN + +1.75 2018-11-22 + No Changes from 1.75_42 1.75_42 2018-08-22 diff --git a/dist.ini b/dist.ini index 2637f829..18408e67 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.75 +version = 1.76 ; Generate files From a6ff09c5722d0559a75976526031b332ec2fbffd Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Tue, 15 Jan 2019 08:20:32 +1100 Subject: [PATCH 526/637] correct the type passed to OCIAttrGet() for OCI_ATTR_TAF_ENABLED should fix #35 --- dbdimp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbdimp.c b/dbdimp.c index 1e9c1ce8..3b766857 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -4776,7 +4776,7 @@ static int enable_taf( SV *dbh, imp_dbh_t *imp_dbh) { - bool can_taf = 0; + boolean can_taf = 0; sword status; #ifdef OCI_ATTR_TAF_ENABLED From 8f3c9eb6ba6fb38873e8eed3ca63bcf13f855b8e Mon Sep 17 00:00:00 2001 From: Carsten Grohmann Date: Sat, 30 Mar 2019 14:00:44 +0100 Subject: [PATCH 527/637] A few typos --- Changes | 4 ++-- dbdimp.c | 4 ++-- dbdimp.h | 8 ++++---- t/lib/ExecuteArray.pm | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index c6eacbe1..e99dff81 100644 --- a/Changes +++ b/Changes @@ -738,7 +738,7 @@ Changes in DBD-Oracle 1.29_1 * Changes in DBD-Oracle 1.22(svn rev 11618) 1st Aug 2008 Patch to remove compiler warnings from H.Merijn Brand - Patch to Makfile for 64bit boxes from Alex Laslavic + Patch to Makefile for 64bit boxes from Alex Laslavic Added OCILobGetLength to lob functions from Milo van der Leij Updated readmes to state the test user has to have create, call and drop a procedure privileges by John Scoles suggested by Gisle Aas Patch to Makfile to prevent the installation of the lib/DBD/mkta.pl fil from Gisle Aas @@ -917,7 +917,7 @@ please enjoy. Changed ORA_OCI constant from being just 7 or 8 to being a dualvar: in numeric context returns the major.minor version number (8.1, 9.2 etc) in string context it returns the full "major.minor.foo.bar" version string. - Changed some SUCCESS_WITH_INFO situtions to be treated as a "warning" + Changed some SUCCESS_WITH_INFO situations to be treated as a "warning" by setting $DBI::err to "0" (and so trigger PrintWarn in DBI >= 1.43) eg "ORA-28011: the account will expire soon; change your password now" and package compilation errors. diff --git a/dbdimp.c b/dbdimp.c index 3b766857..d03f4b51 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -709,7 +709,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, - "OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc."); + "OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc."); return 0; } @@ -761,7 +761,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S charsetid, ncharsetid, status ); if (status != OCI_SUCCESS) { oci_error(dbh, NULL, status, - "OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc"); + "OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc"); return 0; } } diff --git a/dbdimp.h b/dbdimp.h index 5b48aa21..d42cb4dc 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -192,17 +192,17 @@ struct fbh_obj_st { /* embedded object or table will work recursively*/ OCIParam *parmdp; /*Describe attributes of the object OCI_DTYPE_PARAM*/ OCIParam *parmap; /*Describe attributes of the object OCI_ATTR_COLLECTION_ELEMENT OCI_ATTR_PARAM*/ OCIType *tdo; /*object's TDO handle */ - OCITypeCode typecode; /*object's OOCI_ATTR_TYPECODE */ + OCITypeCode typecode; /*object's OCI_ATTR_TYPECODE */ OCITypeCode col_typecode; /*if collection this is its OCI_ATTR_COLLECTION_TYPECODE */ OCITypeCode element_typecode; /*if collection this is its element's OCI_ATTR_TYPECODE*/ - OCIRef *obj_ref; /*if an embeded object this is ref handle to its TDO*/ - OCIInd *obj_ind; /*Null indictator for object */ + OCIRef *obj_ref; /*if an embedded object this is ref handle to its TDO*/ + OCIInd *obj_ind; /*Null indicator for object */ OCIComplexObject *obj_value; /*the actual value from the DB*/ OCIType *obj_type; /*if an embeded object this is the OCIType returned by a OCIObjectPin*/ ub1 is_final_type; /*object's OCI_ATTR_IS_FINAL_TYPE*/ fbh_obj_t *fields; /*one object for each field/property*/ ub2 field_count; /*The number of fields Not really needed but nice to have*/ - fbh_obj_t *next_subtype; /*There is strored information about subtypes for inteherited objects*/ + fbh_obj_t *next_subtype; /*There is stored information about subtypes for inherited objects*/ AV *value; /*The value to send back to Perl This way there are no memory leaks*/ SV *full_type_name; /*Perl value of full type name = schema_name "." type_name*/ diff --git a/t/lib/ExecuteArray.pm b/t/lib/ExecuteArray.pm index 8d67147b..4f53180b 100644 --- a/t/lib/ExecuteArray.pm +++ b/t/lib/ExecuteArray.pm @@ -476,7 +476,7 @@ sub update # NOTE, this also checks you can pass a scalar to bind_param_array $sth->bind_param_array(1, 'dave'); my @pe1 = @p1; - $pe1[-1] = 10; # non-existant row + $pe1[-1] = 10; # non-existent row $sth->bind_param_array(2, \@pe1); $self->insert($dbh, $sth, {commit => 0, error => 0, sts => 5, affected => 4, From b19e9885b2c36bc17645920939619181d0c6f6d9 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sat, 6 Apr 2019 13:30:25 +1100 Subject: [PATCH 528/637] Remove Authority section as PYTHIAN is no longer involved --- dist.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/dist.ini b/dist.ini index 18408e67..51657f16 100644 --- a/dist.ini +++ b/dist.ini @@ -15,9 +15,6 @@ version = 1.76 ;[TemplateCJM] ;file = CONTRIBUTING.mkd -;[Authority] -;authority=cpan:PYTHIAN - [MakeMaker::Custom] [Git::Contributors] From 872417e76f9d4e5f3d2609754ae69cf8d2f5b847 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sun, 7 Apr 2019 13:23:07 +1000 Subject: [PATCH 529/637] Minor adjustments to README file --- README | 64 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/README b/README index e180ad64..10c4b3fd 100644 --- a/README +++ b/README @@ -10,21 +10,21 @@ DBD::Oracle -- an Oracle interface for Perl 5. AND THEN READ ANY README.* FILES RELEVANT TO YOUR PLATFORM: - README.aix.txt - AIX - README.hpux.txt - HP-UX - README.java.txt - Java/thread problem on Solaris - README.macosx.txt - Mac OS/X - README.win32.txt - MS Windows - README.wingcc.txt - MS Windows using GCC - README.* - see if there's a file for your platform + README.aix.txt - AIX + README.hpux.txt - HP-UX + README.java.txt - Java/thread problem on Solaris + README.macosx.txt - Mac OS/X + README.win32.txt - MS Windows + README.wingcc.txt - MS Windows using GCC + README.* - see if there's a file for your platform You may find these useful - README.help.txt - Help and hints on build problems - README.sec.txt - Oracle security issues to be aware of - README.login.txt - Help on how to connect to Oracle - README.longs.txt - Help on handling LONGs - README.clients.txt - What Oracle client files you need installed + README.help.txt - Help and hints on build problems + README.sec.txt - Oracle security issues to be aware of + README.login.txt - Help on how to connect to Oracle + README.longs.txt - Help on handling LONGs + README.clients.txt - What Oracle client files you need installed *** QUICK START GUIDE: @@ -57,10 +57,10 @@ DBD::Oracle -- an Oracle interface for Perl 5. your configuration and DBD::Oracle determine your Oracle version. For full Oracle installs: that usually includes Pro*C and SQL*Net. - (That's not very specific because it varies between Oracle releases.). + (That's not very specific because it varies between Oracle releases.). As of release 1.22 support of Oracle clients before 9 was dropped. The main reason for this is that next few versions of DBD::Oracle will introduce a number of new features - whicht will required a great deal of extra coding to make the OCI 8 work. + whicht will required a great deal of extra coding to make the OCI 8 work. As well it is getting harder to find an Oracle client 8 to test against as well Oracle no longer supports clients before 9. @@ -109,10 +109,10 @@ See the oracle_test_dsn() sub in t/nchar_test_lib.pl The supplied tests will connect to the database using the value of the ORACLE_USERID environment variable to supply the username/password. So you should set that to a valid user (e.g. 'scott/tiger') and ensure that -this user has sufficient privileges to create, insert into, select from and -drop a table, is also able to create, call and drop a procedure and is able to select from -systemtables like 'v$sessions'. Using 'system/manager' might work but is not -recommended! See also +this user has sufficient privileges to create, insert into, select from and +drop a table, is also able to create, call and drop a procedure and is able +to select from systemtables like 'v$sessions'. Using 'system/manager' might +work but is not recommended! See also README.login.txt. @@ -136,9 +136,9 @@ It's also important to use the same compiler that was used to build the Perl you are using. If you have build/link or core dump problems try: - perl Makefile.PL -p + perl Makefile.PL -p or - perl Makefile.PL -nob + perl Makefile.PL -nob If it helps then please let me know (and please include a copy of the log from the failed default build, the log from the build that worked, plus the output of the "perl -V" command). @@ -178,7 +178,7 @@ Please do NOT post problems to comp.lang.perl.*, perl5-porters@perl.org, http://www.cpanforum.com/dist/DBD-Oracle, or google groups etc. If you're *sure* the problem is a bug then you can post a bug report -to http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle +to https://github.com/perl5-dbi/DBD-Oracle/issues Problem reports that don't include sufficient detail (including the information listed below and how to reproduce the problem) are unlikely to get resolved. @@ -224,7 +224,7 @@ dbi-users@perl.org. 5. If you get a core dump, rebuild DBD::Oracle with debugging enabled by executing: perl Makefile.PL -g (note the -g option) - then rerun the code to get a new core dump file, finally use a + then rerun the code to get a new core dump file, finally use a debugger (gdb, sdb, dbx, adb etc) to get a stack trace from it. NOTE: I may not be able to help you much without a stack trace! It is worth fetching and building the GNU GDB debugger (>=4.15) if @@ -272,16 +272,16 @@ Perl 4 Oraperl (v2.4) /perl4/oraperl/ Jeff Stander's stuff stands out for Oraperl: Directories of interest might be - /pub/Oracle/sources - /pub/Oracle/sources/jstander - /pub/Oracle/sources/jstander/distrib - /pub/Oracle/sources/jstander/tsmlib - /pub/Oracle/sources/jstander/wdbex - /pub/Oracle/sources/web/scripts - /pub/Oracle/sources/dba - /pub/Oracle/sources/dba/imp2sql7 - /pub/Oracle/sources/Lonnroth - /pub/Oracle/sources/harrison + /pub/Oracle/sources + /pub/Oracle/sources/jstander + /pub/Oracle/sources/jstander/distrib + /pub/Oracle/sources/jstander/tsmlib + /pub/Oracle/sources/jstander/wdbex + /pub/Oracle/sources/web/scripts + /pub/Oracle/sources/dba + /pub/Oracle/sources/dba/imp2sql7 + /pub/Oracle/sources/Lonnroth + /pub/Oracle/sources/harrison http://www.bf.rmit.edu.au/~orafaq/perlish.html ftp://ftp.bf.rmit.edu.au/pub/perl/db From 736eb8990faa56f28e5cbf4c2566253ac9c19b36 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sun, 7 Apr 2019 13:26:40 +1000 Subject: [PATCH 530/637] Keep all lines under 80 columns --- README | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README b/README index 10c4b3fd..9044c221 100644 --- a/README +++ b/README @@ -59,10 +59,12 @@ DBD::Oracle -- an Oracle interface for Perl 5. For full Oracle installs: that usually includes Pro*C and SQL*Net. (That's not very specific because it varies between Oracle releases.). As of release 1.22 support of Oracle clients before 9 was dropped. - The main reason for this is that next few versions of DBD::Oracle will introduce a number of new features - whicht will required a great deal of extra coding to make the OCI 8 work. - As well it is getting harder to find an Oracle client 8 to test against as well - Oracle no longer supports clients before 9. + The main reason for this is that next few versions of DBD::Oracle will + introduce a number of new features which will required a great deal of extra + coding to make the OCI 8 work. + + As well it is getting harder to find an Oracle client 8 to test against as + well Oracle no longer supports clients before 9. The ORACLE_HOME environment variable must point to the Oracle Home used to create DBD::Oracle. (Not essential under MS Windows). @@ -252,14 +254,14 @@ directly - use the dbi-users mailing list. Regards, Tim. -=============================================================================== +================================================================================ Examples and other info: README.help.txt -- READ IT FIRST IF YOU HAVE ANY PROBLEMS README.win32.txt -- building DBD::Oracle under MS Windows README.wingcc.txt -- building DBD::Oracle under MS Windows with gcc README.macosx.txt -- building DBD::Oracle under MacOS X -README.clients.txt -- building/using DBD::Oracle on minimally configured systems +README.clients.txt -- building/using DBD::Oracle on minimally configured system README.login.txt -- help for login problems README.longs.txt -- examples dealing with LONG types (blobs) @@ -292,7 +294,7 @@ ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip DBI and DBD::Oracle are very portable. If Perl and Oracle run on a platform then the chances are that DBD::Oracle will as well. -=============================================================================== +================================================================================ See the large README.help.txt file for lots of hints and advice about building and runtime issues. From d80e5672bd17add1ee843b4d2ac19de70831ce62 Mon Sep 17 00:00:00 2001 From: Carsten Grohmann Date: Sun, 14 Apr 2019 10:45:38 +0200 Subject: [PATCH 531/637] Move freeing global envhp to destruction of last dbh As the order of object destruction during "global destruction" is undefined. DBI traces show that the global environment is freed in the driver destruction process before all database connections are closed and their resources freed. This causes the segfault in #65. This change moved freeing of the global environment handle from the destruction of the driver handle (dbd_dr_destroy()) to the destruction of the database handle (dbd_db_destroy()). This implementation closes the global environment handle during the DBI shutdown process if the last database handle uses the global environment handle. If the last database handles uses a session environment handle, the global environment handle will not be destroyed. --- dbdimp.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) mode change 100644 => 100755 dbdimp.c diff --git a/dbdimp.c b/dbdimp.c old mode 100644 new mode 100755 index d03f4b51..d2419070 --- a/dbdimp.c +++ b/dbdimp.c @@ -215,11 +215,6 @@ dbd_dr_destroy(SV *drh, imp_drh_t *imp_drh) return; } - if (imp_drh->envhp) { - /* Free cached environment handle. */ - OCIHandleFree_log_stat(imp_drh, imp_drh->envhp, OCI_HTYPE_ENV, status); - } - #ifdef ORA_OCI_112 /* Free session pool resources. */ if (imp_drh->pool_hv) { @@ -1256,8 +1251,19 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); + /* free session environment handle */ if (imp_dbh->envhp != imp_drh->envhp) { OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); + if ( status == OCI_SUCCESS ) { + imp_dbh->envhp = NULL; + } + /* free global environment handle during destruction of last connection */ + } else if ( (imp_dbh->envhp == imp_drh->envhp) && (SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) ) { + OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); + if ( status == OCI_SUCCESS ) { + imp_dbh->envhp = NULL; + imp_drh->envhp = NULL; + } } #ifdef ORA_OCI_112 } From d0bffb907ce282714be06a210a7c13b98a9bc077 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sun, 14 Apr 2019 20:34:32 +1000 Subject: [PATCH 532/637] Enable testing against 5.28 --- .travis.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.travis.yml b/.travis.yml index 33471c45..2c967dd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,38 @@ matrix: # FYI Oracle XE only comes in utf8, so we can't run USASCII version of tests include: +# Perl 5.28 variations + - perl: '5.28' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.28' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.28-shrplib' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.28-shrplib' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + # Perl 5.26 variations - perl: '5.26' env: From bcc5f5d75e92ae1e45b31c542b878e863f636bd0 Mon Sep 17 00:00:00 2001 From: Carsten Grohmann Date: Thu, 25 Apr 2019 21:06:36 +0200 Subject: [PATCH 533/637] A few typos more --- CONTRIBUTING.mkd | 2 +- Oracle.h | 4 +-- dbdimp.c | 4 +-- examples/ora_explain.pl | 12 ++++----- examples/proc.pl | 2 +- lib/DBD/Oracle.pm | 56 ++++++++++++++++++++--------------------- oci8.c | 18 ++++++------- t/34pres_lobs.t | 2 +- t/56embbeded.t | 2 +- t/58object.t | 2 +- 10 files changed, 52 insertions(+), 52 deletions(-) diff --git a/CONTRIBUTING.mkd b/CONTRIBUTING.mkd index d3b17746..22a055c9 100644 --- a/CONTRIBUTING.mkd +++ b/CONTRIBUTING.mkd @@ -34,7 +34,7 @@ $ prove -lv t/some_test_file.t $ prove -lvr t/ ``` -In most cases, 'prove' is entirely sufficent for you to test any +In most cases, 'prove' is entirely sufficient for you to test any patches you have. You may need to satisfy some dependencies. The easiest way to satisfy diff --git a/Oracle.h b/Oracle.h index 24379fee..c933de2f 100644 --- a/Oracle.h +++ b/Oracle.h @@ -120,8 +120,8 @@ ub4 ora_blob_read_mb_piece _((SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV * /* other Oracle not in noraml API defines -most of these are largly undocumented XML functions that are in the API but not defined -not noramlly found in the defines the prototypes of OCI functions in most clients +most of these are largely undocumented XML functions that are in the API but not defined +not normally found in the defines the prototypes of OCI functions in most clients Normally can be found in ociap.h (Oracle Call Interface - Ansi Prototypes ) and ocikp.h (functions in K&R style) diff --git a/dbdimp.c b/dbdimp.c index d03f4b51..513c4e76 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -316,7 +316,7 @@ oratype_bind_ok(int dbtype) /* It's a type we support for placeholders */ case 116: /* SQLT_RSET OCI 8 cursor variable */ case ORA_VARCHAR2_TABLE: /* 201 */ case ORA_NUMBER_TABLE: /* 202 */ - case ORA_XMLTYPE: /* SQLT_NTY must be carefull here as its value (108) is the same for an embedded object Well realy only XML clobs not embedded objects */ + case ORA_XMLTYPE: /* SQLT_NTY must be careful here as its value (108) is the same for an embedded object Well really only XML clobs not embedded objects */ return 1; } return 0; @@ -3736,7 +3736,7 @@ dbd_st_execute(SV *sth, imp_sth_t *imp_sth) /* <= -2:error, >=0:ok row count, (- DBIc_ROW_COUNT(imp_sth) = 0; /* reset (possibly re-exec'ing) */ row_count = 0; /*reinit the rs_array as well - as we may have more thatn one exe on a prepare*/ + as we may have more than one exe on a prepare*/ rs_array_init(imp_sth); } else { diff --git a/examples/ora_explain.pl b/examples/ora_explain.pl index 3f123d1d..ef6f41b3 100644 --- a/examples/ora_explain.pl +++ b/examples/ora_explain.pl @@ -1309,7 +1309,7 @@ sub grab_main ### SQL selection $frame = $GrabMain->Frame(-borderwidth => 3, -relief => "raised"); -$frame->Label(-text => "SQL Selection Criterea")->pack(-anchor => "w"); +$frame->Label(-text => "SQL Selection Criteria")->pack(-anchor => "w"); $frame1 = $frame->Frame(-highlightthickness => 1); ## SQL sort frame @@ -1584,7 +1584,7 @@ =head1 DESCRIPTION path to use. Needless to say, understanding such plans requires a fairly sophisticated knowledge of Oracle architecture and internals. -Explain allows a user to interactively edit a SQL statemant and view the +Explain allows a user to interactively edit a SQL statement and view the resulting query plan with the click of a single button. The effects of modifying the SQL or of adding hints can be rapidly established. @@ -1698,7 +1698,7 @@ =head2 Capture SQL Cache functionality The explain window has an option on the "File" menu labelled "SQL Cache ...", as well as a button with the same function. Selecting this will popup a new top-level window containing a menu bar and three frames, labelled "SQL Cache", -"SQL Statement Statistics" and "SQL Selection Criterea". At the bottom of the +"SQL Statement Statistics" and "SQL Selection Criteria". At the bottom of the window are three buttons labelled "Capture SQL", "Explain" and "Close". The menu bar has two pulldown menus "File" and "Help". "File" allows you to @@ -1708,16 +1708,16 @@ =head2 Capture SQL Cache functionality The "SQL Cache" frame shows the statements currently in the Oracle SQL cache. As you move the cursor over this window, each SQL statement will be highlighted with an outline box. Single-clicking on a statement in the SQL Cache pane will -highlight the stamement in green and display more detailed information on that +highlight the statement in green and display more detailed information on that statement in the SQL Statement Statistics frame. If you want to save the entire contents of the SQL Cache pane, you can do this from the "File" menu. -The "SQL Selection Criterea" frame allows you to specify which SQL statements +The "SQL Selection Criteria" frame allows you to specify which SQL statements you are interested in, and how you want them sorted. The pattern used to select statements is a normal perl regexp. Once you have defined the selection -criterea, clicking the "Capture SQL" button will read all the matching +criteria, clicking the "Capture SQL" button will read all the matching statements from the SQL cache and display them in the top frame. Double-clicking on a statement in the "SQL Cache" pane, selecting "Explain" diff --git a/examples/proc.pl b/examples/proc.pl index f15a16d0..6e06b42e 100755 --- a/examples/proc.pl +++ b/examples/proc.pl @@ -121,7 +121,7 @@ BEGIN $sth->bind_param( ":test_num", $test_num ); $sth->bind_param_inout( ":is_odd", \$is_odd, 1 ); -# The execute will automagically update the value of $is_odd +# The execute will automatically update the value of $is_odd $sth->execute; print "$test_num is ", $is_odd ? "odd - ok" : "even - error!", "\n"; diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 6604c0dd..fedd625b 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -322,7 +322,7 @@ package DBD::Oracle; SELECT SYS_CONTEXT('userenv','session_user') FROM DUAL })||''; # Now we'll reinstate the earlier warning. We're just - # appending it, so in the extremeley unlikely case that the + # appending it, so in the extremely unlikely case that the # selectrow_array we just issued also issued a warning, the # 2 warnings will appear out of order. $dbh->set_err($err, $errstr, $state) if defined $err; @@ -2833,7 +2833,7 @@ In the above example 10 rows will be prefetched up to a maximum of 10000 bytes o suggests a good row cache value for a scrollable cursor is about 20% of expected size of the record set. The prefetch settings tell the DBD::Oracle to grab x rows (or x-bytes) when it needs to get new rows. This happens on the first -fetch that sets the current_positon to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are +fetch that sets the current position to any value other than 0. In the above example if we do a OCI_FETCH_FIRST the first 10 rows are loaded into the buffer and DBD::Oracle will not have to go back to the server for more rows. When record 11 is fetched DBD::Oracle fetches and returns this row and the next 9 rows are loaded into the buffer. In this case if you fetch backwards from 10 to 1 no server round trips are made. @@ -3698,26 +3698,26 @@ The valid orientation constant and fetch offset values combination are detailed OCI_FETCH_RELATIVE, and a fetch offset value of 1 is equivalent to a OCI_FETCH_NEXT. OCI_FETCH_RELATIVE, and a fetch offset value of -1 is equivalent to a OCI_FETCH_PRIOR. -The effect that a ora_fetch_scroll method call has on the current_positon attribute is detailed below. +The effect that a ora_fetch_scroll method call has on the current position attribute is detailed below. - OCI_FETCH_CURRENT, has no effect on the current_positon attribute. - OCI_FETCH_NEXT, increments current_positon attribute by 1 - OCI_FETCH_NEXT, when at the last row in the record set does not change current_positon + OCI_FETCH_CURRENT, has no effect on the current position attribute. + OCI_FETCH_NEXT, increments current position attribute by 1 + OCI_FETCH_NEXT, when at the last row in the record set does not change current position attribute, it is equivalent to a OCI_FETCH_CURRENT - OCI_FETCH_FIRST, sets the current_positon attribute to 1. - OCI_FETCH_LAST, sets the current_positon attribute to the total number of rows in the + OCI_FETCH_FIRST, sets the current position attribute to 1. + OCI_FETCH_LAST, sets the current position attribute to the total number of rows in the record set. - OCI_FETCH_PRIOR, decrements current_positon attribute by 1. - OCI_FETCH_PRIOR, when at the first row in the record set does not change current_positon + OCI_FETCH_PRIOR, decrements current position attribute by 1. + OCI_FETCH_PRIOR, when at the first row in the record set does not change current position attribute, it is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_ABSOLUTE, sets the current_positon attribute to the fetch offset value. + OCI_FETCH_ABSOLUTE, sets the current position attribute to the fetch offset value. OCI_FETCH_ABSOLUTE, and a fetch offset value that is less than 1 does not change - current_positon attribute, it is equivalent to a OCI_FETCH_CURRENT. + current position attribute, it is equivalent to a OCI_FETCH_CURRENT. OCI_FETCH_ABSOLUTE, and a fetch offset value that is greater than the number of records in - the record set, does not change current_positon attribute, it is + the record set, does not change current position attribute, it is equivalent to a OCI_FETCH_CURRENT. - OCI_FETCH_RELATIVE, sets the current_positon attribute to (current_positon attribute + + OCI_FETCH_RELATIVE, sets the current position attribute to (current position attribute + fetch offset value). OCI_FETCH_RELATIVE, and a fetch offset value that makes the current position less than 1, does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. @@ -3725,11 +3725,11 @@ The effect that a ora_fetch_scroll method call has on the current_positon attrib in the record set, does not change fetch offset value so it is equivalent to a OCI_FETCH_CURRENT. -The effects of the differing orientation constants on the first fetch (current_postion attribute at 0) are as follows. +The effects of the differing orientation constants on the first fetch (current position attribute at 0) are as follows. - OCI_FETCH_CURRENT, dose not fetch a row or change the current_positon attribute. - OCI_FETCH_FIRST, fetches row 1 and sets the current_positon attribute to 1. - OCI_FETCH_LAST, fetches the last row in the record set and sets the current_positon + OCI_FETCH_CURRENT, dose not fetch a row or change the current position attribute. + OCI_FETCH_FIRST, fetches row 1 and sets the current position attribute to 1. + OCI_FETCH_LAST, fetches the last row in the record set and sets the current position attribute to the total number of rows in the record set. OCI_FETCH_NEXT, equivalent to a OCI_FETCH_FIRST. OCI_FETCH_PRIOR, equivalent to a OCI_FETCH_CURRENT. @@ -3771,7 +3771,7 @@ method; print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, +The current position attribute to will be 20 after this snippet. This is also a way to get the number of rows in the record set, however, if the record set is large this could take some time. =item Fetching the Current Row @@ -3780,7 +3780,7 @@ if the record set is large this could take some time. print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will still be 20 after this snippet. +The current position attribute will still be 20 after this snippet. =item Fetching the First Row @@ -3788,7 +3788,7 @@ The current_positon attribute will still be 20 after this snippet. print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 1 after this snippet. +The current position attribute will be 1 after this snippet. =item Fetching the Next Row @@ -3798,7 +3798,7 @@ The current_positon attribute will be 1 after this snippet. } print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 5 after this snippet. +The current position attribute will be 5 after this snippet. =item Fetching the Prior Row @@ -3808,7 +3808,7 @@ The current_positon attribute will be 5 after this snippet. } print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 1 after this snippet. +The current position attribute will be 1 after this snippet. =item Fetching the 10th Row @@ -3816,7 +3816,7 @@ The current_positon attribute will be 1 after this snippet. print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 10 after this snippet. +The current position attribute will be 10 after this snippet. =item Fetching the 10th to 14th Row @@ -3826,7 +3826,7 @@ The current_positon attribute will be 10 after this snippet. } print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 14 after this snippet. +The current position attribute will be 14 after this snippet. =item Fetching the 14th to 10th Row @@ -3836,7 +3836,7 @@ The current_positon attribute will be 14 after this snippet. } print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 10 after this snippet. +The current position attribute will be 10 after this snippet. =item Fetching the 5th Row From the Present Position. @@ -3844,7 +3844,7 @@ The current_positon attribute will be 10 after this snippet. print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 15 after this snippet. +The current position attribute will be 15 after this snippet. =item Fetching the 9th Row Prior From the Present Position @@ -3852,7 +3852,7 @@ The current_positon attribute will be 15 after this snippet. print "id=".$value->[0].", First Name=".$value->[1].", Last Name=".$value->[2]."\n"; print "current scroll position=".$sth->ora_scroll_position()."\n"; -The current_positon attribute will be 6 after this snippet. +The current position attribute will be 6 after this snippet. =item Use Finish diff --git a/oci8.c b/oci8.c index c21d192e..4aa268b5 100644 --- a/oci8.c +++ b/oci8.c @@ -164,7 +164,7 @@ sql_typecode_name(int dbtype) { case 116: return "SQLT_RSET OCI 8 cursor variable"; case ORA_VARCHAR2_TABLE:return "ORA_VARCHAR2_TABLE"; case ORA_NUMBER_TABLE: return "ORA_NUMBER_TABLE"; - case ORA_XMLTYPE: return "ORA_XMLTYPE or SQLT_NTY";/* SQLT_NTY must be carefull here as its value (108) is the same for an embedded object Well realy only XML clobs not embedded objects */ + case ORA_XMLTYPE: return "ORA_XMLTYPE or SQLT_NTY";/* SQLT_NTY must be careful here as its value (108) is the same for an embedded object Well really only XML clobs not embedded objects */ } sv = sv_2mortal(newSVpv("",0)); @@ -326,10 +326,10 @@ oci_mode(ub4 mode) /*case OCI_LOGON2_SPOOL: return "LOGON2_SPOOL"; Use session pool */ case OCI_LOGON2_CPOOL: return "LOGON2_CPOOL"; /* Use connection pool */ /*case OCI_LOGON2_STMTCACHE: return "LOGON2_STMTCACHE"; Use Stmt Caching */ - case OCI_LOGON2_PROXY: return "LOGON2_PROXY"; /* Proxy authentiaction */ + case OCI_LOGON2_PROXY: return "LOGON2_PROXY"; /* Proxy authentication */ /*------------------------- OCISessionPoolCreate Modes ----------------------*/ /*case OCI_SPC_REINITIALIZE: return "SPC_REINITIALIZE"; Reinitialize the session pool */ -/*case OCI_SPC_HOMOGENEOUS: return "SPC_HOMOGENEOUS"; ""; Session pool is homogeneneous */ +/*case OCI_SPC_HOMOGENEOUS: return "SPC_HOMOGENEOUS"; ""; Session pool is homogeneous */ /*case OCI_SPC_STMTCACHE: return "SPC_STMTCACHE"; Session pool has stmt cache */ /*case OCI_SPC_NO_RLB: return "SPC_NO_RLB "; Do not enable Runtime load balancing. */ /*--------------------------- OCISessionGet Modes ---------------------------*/ @@ -545,7 +545,7 @@ oci_attr_name(ub4 attr) case OCI_ATTR_TRANS_NAME: return "OCI_ATTR_TRANS_NAME"; /* string to identify a global transaction */ case OCI_ATTR_HEAPALLOC: return "OCI_ATTR_HEAPALLOC"; /* memory allocated on the heap */ case OCI_ATTR_CHARSET_FORM: return "OCI_ATTR_CHARSET_FORM"; /* Character Set Form */ - case OCI_ATTR_MAXDATA_SIZE: return "OCI_ATTR_MAXDATA_SIZE"; /* Maximumsize of data on the server */ + case OCI_ATTR_MAXDATA_SIZE: return "OCI_ATTR_MAXDATA_SIZE"; /* Maximum size of data on the server */ case OCI_ATTR_CACHE_OPT_SIZE: return "OCI_ATTR_CACHE_OPT_SIZE"; /* object cache optimal size */ case OCI_ATTR_CACHE_MAX_SIZE: return "OCI_ATTR_CACHE_MAX_SIZE"; /* object cache maximum size percentage */ case OCI_ATTR_PINOPTION: return "OCI_ATTR_PINOPTION"; /* object cache default pin option */ @@ -684,8 +684,8 @@ oci_attr_name(ub4 attr) case OCI_ATTR_RESERVED_2: return "OCI_ATTR_RESERVED_2"; /* reserved */ - case OCI_ATTR_SUBSCR_RECPT: return "OCI_ATTR_SUBSCR_RECPT"; /* recepient of subscription */ - case OCI_ATTR_SUBSCR_RECPTPROTO: return "OCI_ATTR_SUBSCR_RECPTPROTO";/* protocol for recepient */ + case OCI_ATTR_SUBSCR_RECPT: return "OCI_ATTR_SUBSCR_RECPT"; /* recipient of subscription */ + case OCI_ATTR_SUBSCR_RECPTPROTO: return "OCI_ATTR_SUBSCR_RECPTPROTO";/* protocol for recipient */ /* 8.2 dpapi support of ADTs */ case OCI_ATTR_DIRPATH_EXPR_TYPE: return "OCI_ATTR_DIRPATH_EXPR_TYPE"; /* expr type of OCI_ATTR_NAME */ @@ -700,7 +700,7 @@ oci_attr_name(ub4 attr) case OCI_ATTR_LDAP_CRED: return "OCI_ATTR_LDAP_CRED"; /* credentials to connect to LDAP */ case OCI_ATTR_WALL_LOC: return "OCI_ATTR_WALL_LOC"; /* client wallet location */ case OCI_ATTR_LDAP_AUTH: return "OCI_ATTR_LDAP_AUTH"; /* LDAP authentication method */ - case OCI_ATTR_LDAP_CTX: return "OCI_ATTR_LDAP_CTX"; /* LDAP adminstration context DN */ + case OCI_ATTR_LDAP_CTX: return "OCI_ATTR_LDAP_CTX"; /* LDAP administration context DN */ case OCI_ATTR_SERVER_DNS: return "OCI_ATTR_SERVER_DNS"; /* list of registration server DNs */ case OCI_ATTR_DN_COUNT: return "OCI_ATTR_DN_COUNT"; /* the number of server DNs */ @@ -743,7 +743,7 @@ oci_attr_name(ub4 attr) case OCI_ATTR_BIND_COUNT: return "OCI_ATTR_BIND_COUNT"; /* number of bind postions */ case OCI_ATTR_HANDLE_POSITION: return "OCI_ATTR_HANDLE_POSITION"; /* pos of bind/define handle */ - case OCI_ATTR_RESERVED_5: return "OCI_ATTR_RESERVED_5"; /* reserverd */ + case OCI_ATTR_RESERVED_5: return "OCI_ATTR_RESERVED_5"; /* reserved */ case OCI_ATTR_SERVER_BUSY: return "OCI_ATTR_SERVER_BUSY"; /* call in progress on server*/ case OCI_ATTR_DIRPATH_SID: return "OCI_ATTR_DIRPATH_SID"; /* loading into an SID col */ @@ -757,7 +757,7 @@ oci_attr_name(ub4 attr) case OCI_ATTR_SCN_BASE: return "OCI_ATTR_SCN_BASE"; /* snapshot base */ case OCI_ATTR_SCN_WRAP: return "OCI_ATTR_SCN_WRAP"; /* snapshot wrap */ - /* --------------------------- Miscellanous attributes --------------------- */ + /* --------------------------- Miscellaneous attributes --------------------- */ case OCI_ATTR_RESERVED_6: return "OCI_ATTR_RESERVED_6"; /* reserved */ case OCI_ATTR_READONLY_TXN: return "OCI_ATTR_READONLY_TXN"; /* txn is readonly */ case OCI_ATTR_RESERVED_7: return "OCI_ATTR_RESERVED_7"; /* reserved */ diff --git a/t/34pres_lobs.t b/t/34pres_lobs.t index b721f52a..e56a3e3c 100644 --- a/t/34pres_lobs.t +++ b/t/34pres_lobs.t @@ -126,7 +126,7 @@ SKIP: { cmp_ok( $log3, 'eq', $in_blob, 'clob1 = in_clob' ); cmp_ok( $log4, 'eq', $in_blob, 'clob2 = in_clob' ); - #no neeed to look at the data is should be ok + #no need to look at the data is should be ok $sth->finish(); drop_table($dbh); diff --git a/t/56embbeded.t b/t/56embbeded.t index 4ba67303..0970f3e4 100644 --- a/t/56embbeded.t +++ b/t/56embbeded.t @@ -16,7 +16,7 @@ $| = 1; ## 56embbeded.t ## By John Scoles, The Pythian Group ## ---------------------------------------------------------------------------- -## Just a few checks to see if I can select embedded objectes with Oracle::DBD +## Just a few checks to see if I can select embedded objects with Oracle::DBD ## Nothing fancy. ## ---------------------------------------------------------------------------- diff --git a/t/58object.t b/t/58object.t index c5e03880..b365cefe 100644 --- a/t/58object.t +++ b/t/58object.t @@ -316,7 +316,7 @@ qq{ INSERT INTO $list_table VALUES(81,$list_type($inner_type(null, 'listed'))) } is_deeply( $row1[1]->[0]->attr, { NUM => undef, NAME => 'listed' }, - 'Check propertes of first (and only) item in nested table' + 'Check properties of first (and only) item in nested table' ); ok( !$sth->fetchrow(), 'new: No more rows expected (nested table)' ); From ec90eded4d3ba1baa4e2dd37278d65f205c9052b Mon Sep 17 00:00:00 2001 From: Carsten Grohmann Date: Sat, 22 Jun 2019 13:42:26 +0200 Subject: [PATCH 534/637] Enable travis helpers DEBUG options --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 33471c45..31b82569 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,8 @@ env: - AUTOMATED_TESTING=1 - EXTENDED_TESTING=1 - RELEASE_TESTING=0 + - TRAVIS_PERL_DEBUG=1 + - HELPERS_DEBUG=1 - CFLAGS="-g -O2 -fstack-protector -Wformat -Werror=format-security" - CPPFLAGS="-D_FORTIFY_SOURCE=2" - CXXFLAGS="-g -O2 -fstack-protector -Wformat -Werror=format-security" From 6f30bb5ed4cd38ea96a33b5a2d4cff839a7d0fac Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 15 Apr 2019 11:40:52 +1000 Subject: [PATCH 535/637] Remove disconnect() which should no longer be needed --- t/23wide_db.t | 2 +- t/24implicit_utf8.t | 2 +- t/31lob.t | 2 +- t/40ph_type.t | 2 +- t/58object.t | 1 - t/rt13865.t | 2 -- t/rt74753-utf8-encoded.t | 2 -- 7 files changed, 4 insertions(+), 9 deletions(-) diff --git a/t/23wide_db.t b/t/23wide_db.t index a7869738..00682d88 100644 --- a/t/23wide_db.t +++ b/t/23wide_db.t @@ -54,6 +54,6 @@ SKIP: { } # SKIP END { - eval { drop_table($dbh); $dbh->disconnect if $dbh }; + eval { drop_table($dbh); }; } diff --git a/t/24implicit_utf8.t b/t/24implicit_utf8.t index ce697b90..8a4be443 100644 --- a/t/24implicit_utf8.t +++ b/t/24implicit_utf8.t @@ -65,7 +65,7 @@ SKIP: { } END { - eval { drop_table($dbh); $dbh->disconnect if $dbh }; + eval { drop_table($dbh); }; } __END__ diff --git a/t/31lob.t b/t/31lob.t index ba785079..2e513edc 100644 --- a/t/31lob.t +++ b/t/31lob.t @@ -219,6 +219,6 @@ END_SQL undef $sth; -END { eval { drop_table($dbh); $dbh->disconnect if $dbh } } +END { eval { drop_table($dbh); } } 1; diff --git a/t/40ph_type.t b/t/40ph_type.t index 3d7253d9..c0ef384b 100644 --- a/t/40ph_type.t +++ b/t/40ph_type.t @@ -159,7 +159,7 @@ for my $test_info (@tests) { } } -END { eval { drop_table($dbh,$table); $dbh->disconnect if $dbh }; } +END { eval { drop_table($dbh,$table); } } __END__ diff --git a/t/58object.t b/t/58object.t index c5e03880..17bce9d9 100644 --- a/t/58object.t +++ b/t/58object.t @@ -354,4 +354,3 @@ qq{ INSERT INTO $list_table VALUES(81,$list_type($inner_type(null, 'listed'))) } #cleanup &drop_test_objects unless $ENV{DBD_SKIP_TABLE_DROP}; -$dbh->disconnect if $dbh; # see also GH65 diff --git a/t/rt13865.t b/t/rt13865.t index f0196012..2df27b17 100644 --- a/t/rt13865.t +++ b/t/rt13865.t @@ -141,6 +141,4 @@ sub get_privs { return map { $_->[0] } @{ $sth->fetchall_arrayref }; } -$dbh->disconnect if $dbh; - done_testing(); diff --git a/t/rt74753-utf8-encoded.t b/t/rt74753-utf8-encoded.t index 16a7bdd4..f5998864 100644 --- a/t/rt74753-utf8-encoded.t +++ b/t/rt74753-utf8-encoded.t @@ -84,5 +84,3 @@ $sth->bind_param_inout( ':ret', \$val, 1 ); $sth->execute; is Encode::is_utf8($val) => 1, 'truncated, yet utf8 encoded'; - -$dbh->disconnect if $dbh; From 24835167dfa4f870893017bee7477a65f2ff8837 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sun, 7 Jul 2019 23:12:00 +1000 Subject: [PATCH 536/637] Try the dzil build command again manually --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 31b82569..5024d88a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -184,7 +184,7 @@ before_install: - source ~/travis-perl-helpers/init - build-perl - perl -V - - build-dist + - build-dist || dzil build -v --in=/home/travis/build/perl5-dbi/DBD-Oracle/build_dir - cd $BUILD_DIR install: From 5f10aac076f2c5a9b9683d6fe70fa48d519f6aba Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sun, 7 Jul 2019 23:31:00 +1000 Subject: [PATCH 537/637] Try something different --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5024d88a..d4598a32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,6 @@ env: - AUTOMATED_TESTING=1 - EXTENDED_TESTING=1 - RELEASE_TESTING=0 - - TRAVIS_PERL_DEBUG=1 - - HELPERS_DEBUG=1 - CFLAGS="-g -O2 -fstack-protector -Wformat -Werror=format-security" - CPPFLAGS="-D_FORTIFY_SOURCE=2" - CXXFLAGS="-g -O2 -fstack-protector -Wformat -Werror=format-security" @@ -184,7 +182,8 @@ before_install: - source ~/travis-perl-helpers/init - build-perl - perl -V - - build-dist || dzil build -v --in=/home/travis/build/perl5-dbi/DBD-Oracle/build_dir + - dzil authordeps --missing + - build-dist - cd $BUILD_DIR install: From a83998a5f95d40f49cdce28afe51773fc49cd09f Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sun, 7 Jul 2019 23:40:37 +1000 Subject: [PATCH 538/637] Try excluding cpanfile stuff --- dist.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist.ini b/dist.ini index 51657f16..ff04ae57 100644 --- a/dist.ini +++ b/dist.ini @@ -38,9 +38,9 @@ format = %-9v %{yyyy-MM-dd}d [ManifestSkip] [Git::GatherDir] -exclude_filename = cpanfile -[CopyFilesFromBuild] -copy = cpanfile +;exclude_filename = cpanfile +;[CopyFilesFromBuild] +;copy = cpanfile [ExecDir] [OurPkgVersion] From ff66d4c8a748e984297bf70f989b65332c9820dc Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sun, 7 Jul 2019 23:49:52 +1000 Subject: [PATCH 539/637] Revert "Try excluding cpanfile stuff" This reverts commit a83998a5f95d40f49cdce28afe51773fc49cd09f. --- dist.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist.ini b/dist.ini index ff04ae57..51657f16 100644 --- a/dist.ini +++ b/dist.ini @@ -38,9 +38,9 @@ format = %-9v %{yyyy-MM-dd}d [ManifestSkip] [Git::GatherDir] -;exclude_filename = cpanfile -;[CopyFilesFromBuild] -;copy = cpanfile +exclude_filename = cpanfile +[CopyFilesFromBuild] +copy = cpanfile [ExecDir] [OurPkgVersion] From ae237d5a3f129824a0ff5ec8ed0976283e6e5b10 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sun, 7 Jul 2019 23:50:58 +1000 Subject: [PATCH 540/637] Try excluding Git::Check --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 51657f16..cb55fa25 100644 --- a/dist.ini +++ b/dist.ini @@ -51,7 +51,7 @@ copy = cpanfile ; Release Stuff [ConfirmRelease] -[Git::Check] +;[Git::Check] [Git::Commit] [Git::CommitBuild] release_branch = releases From 783019723f07098eca7d5dde9528e04fe0518231 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 8 Jul 2019 10:05:22 +1000 Subject: [PATCH 541/637] Avoid GCC-ism so that HP-UX can compile. GH#92 --- dbdimp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbdimp.c b/dbdimp.c index 513c4e76..26d8ce50 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -860,7 +860,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S /* Create and cache new session pool struct. */ SV *key_sv = pool_key(imp_dbh, dbname, uid, pwd, charsetid, ncharsetid); - session_pool_t pool_data = { }; + session_pool_t pool_data = {0}; SV *pool_sv = newSVpvn((char*)&pool_data, sizeof(pool_data)); HE *pool_he = hv_store_ent(imp_drh->pool_hv, key_sv, pool_sv, 0); imp_dbh->pool = pool = (session_pool_t*)SvPVX(HeVAL(pool_he)); From e6a7c66cbf0aace958aebd6fa130a91f6eda8b79 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 8 Jul 2019 10:16:25 +1000 Subject: [PATCH 542/637] Revert "Try excluding Git::Check" This reverts commit ae237d5a3f129824a0ff5ec8ed0976283e6e5b10. --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index cb55fa25..51657f16 100644 --- a/dist.ini +++ b/dist.ini @@ -51,7 +51,7 @@ copy = cpanfile ; Release Stuff [ConfirmRelease] -;[Git::Check] +[Git::Check] [Git::Commit] [Git::CommitBuild] release_branch = releases From 56bb947a394c07063fb5ebed6ca77945bb3d17c0 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 8 Jul 2019 10:17:58 +1000 Subject: [PATCH 543/637] Try disabling Git::CommitBuild as recommended by @kentnl --- dist.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist.ini b/dist.ini index 51657f16..e6d09d46 100644 --- a/dist.ini +++ b/dist.ini @@ -53,9 +53,9 @@ copy = cpanfile [ConfirmRelease] [Git::Check] [Git::Commit] -[Git::CommitBuild] - release_branch = releases - multiple_inheritance = 1 +;[Git::CommitBuild] +; release_branch = releases +; multiple_inheritance = 1 [Git::Tag] tag_format = v%v branch = releases From c0a0ca00ea65258ec7a319b39443bdb6f40b8a18 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Mon, 8 Jul 2019 13:12:48 +0100 Subject: [PATCH 544/637] disable Git::CommitBuild --- dist.ini | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dist.ini b/dist.ini index 51657f16..528c5ea7 100644 --- a/dist.ini +++ b/dist.ini @@ -53,9 +53,9 @@ copy = cpanfile [ConfirmRelease] [Git::Check] [Git::Commit] -[Git::CommitBuild] - release_branch = releases - multiple_inheritance = 1 +;[Git::CommitBuild] +; release_branch = releases +; multiple_inheritance = 1 [Git::Tag] tag_format = v%v branch = releases @@ -107,4 +107,3 @@ Test::NoWarnings = 0 [HelpWanted] positions = coder documentation tester - From 106b3fa49937097907e374f646e28b63ad6e0f6c Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Mon, 8 Jul 2019 14:05:41 +0100 Subject: [PATCH 545/637] Delete dist.ini Already applied --- dist.ini | 110 ------------------------------------------------------- 1 file changed, 110 deletions(-) delete mode 100644 dist.ini diff --git a/dist.ini b/dist.ini deleted file mode 100644 index e6d09d46..00000000 --- a/dist.ini +++ /dev/null @@ -1,110 +0,0 @@ -name = DBD-Oracle -author = Tim Bunce -author = John Scoles -author = Yanick Champoux -author = Martin J. Evans -license = Perl_5 -copyright_holder = Tim Bunce -copyright_year = 1994 -main_module = lib/DBD/Oracle.pm - -version = 1.76 - -; Generate files - -;[TemplateCJM] -;file = CONTRIBUTING.mkd - -[MakeMaker::Custom] - -[Git::Contributors] -[ContributorsFile] -[InstallGuide] -;[GithubMeta] -;remote=github - -[MetaYAML] -[MetaJSON] -[PodWeaver] -[License] - -[ReadmeMarkdownFromPod] -[NextRelease] -time_zone = UTC -format = %-9v %{yyyy-MM-dd}d - -[MetaProvides::Package] -[MatchManifest] -[ManifestSkip] - -[Git::GatherDir] -exclude_filename = cpanfile -[CopyFilesFromBuild] -copy = cpanfile - -[ExecDir] -[OurPkgVersion] -[AutoPrereqs] -[CheckChangesHasContent] -[PreviousVersion::Changelog] - -; Release Stuff - -[ConfirmRelease] -[Git::Check] -[Git::Commit] -;[Git::CommitBuild] -; release_branch = releases -; multiple_inheritance = 1 -[Git::Tag] - tag_format = v%v - branch = releases - -[UploadToCPAN] - -[Git::Push] - push_to = github master releases - -[InstallRelease] -install_command = cpanm . - -;[SchwartzRatio] - -; Tests - -[RunExtraTests] -[MetaTests] -[Test::Compile] -[Test::Kwalitee] -[Test::EOF] -[Test::EOL] -[Test::NoBreakpoints] -[Test::NoTabs] -[Test::Portability] -[Test::ReportPrereqs] -[Test::UnusedVars] -[TestRelease] -[PodCoverageTests] -[PodSyntaxTests] - -[DOAP] -process_changes = 1 - -[CPANFile] - -[CopyrightYearFromGit] - - -[Prereqs / ConfigureRequires] -Config = 0 -Data::Dumper = 0 -DBI = 1.623 -Devel::Peek = 0 -Encode = 0 -Math::BigInt = 0 -Test::More = 0 -Test::NoWarnings = 0 - -[HelpWanted] -positions = coder documentation tester - From 89eeded70e3992d0ea218e75fe5925a2b961e936 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 9 Jul 2019 11:46:55 +1000 Subject: [PATCH 546/637] Remove debug line, this wasnt supposed to go to master --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e1abce76..2c967dd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -214,7 +214,6 @@ before_install: - source ~/travis-perl-helpers/init - build-perl - perl -V - - dzil authordeps --missing - build-dist - cd $BUILD_DIR From 529d6237cb84360bc4a1b0e207deba713c12725f Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 9 Jul 2019 11:47:09 +1000 Subject: [PATCH 547/637] Remove Git things we arent using or worried about --- dist.ini | 8 -------- 1 file changed, 8 deletions(-) diff --git a/dist.ini b/dist.ini index 528c5ea7..7930bede 100644 --- a/dist.ini +++ b/dist.ini @@ -53,23 +53,15 @@ copy = cpanfile [ConfirmRelease] [Git::Check] [Git::Commit] -;[Git::CommitBuild] -; release_branch = releases -; multiple_inheritance = 1 [Git::Tag] tag_format = v%v branch = releases [UploadToCPAN] -[Git::Push] - push_to = github master releases - [InstallRelease] install_command = cpanm . -;[SchwartzRatio] - ; Tests [RunExtraTests] From 6804a45309e26954ae6aa6a04675202d2c993348 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 9 Jul 2019 23:50:01 +1000 Subject: [PATCH 548/637] Update github path --- CONTRIBUTING.mkd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.mkd b/CONTRIBUTING.mkd index 22a055c9..a104d62d 100644 --- a/CONTRIBUTING.mkd +++ b/CONTRIBUTING.mkd @@ -106,6 +106,6 @@ instructions for doing that is available here: * https://help.github.com/articles/creating-a-pull-request [distzilla]: http://dzil.org/. -[repository]: https://github.com/pythian/DBD-Oracle/ -[bugtracker]: https://github.com/pythian/DBD-Oracle/issues +[repository]: https://github.com/perl5-dbi/DBD-Oracle/ +[bugtracker]: https://github.com/perl5-dbi/DBD-Oracle/issues From 18547fa8ded4254b035cc383fee0f00d70688d15 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 9 Jul 2019 23:54:43 +1000 Subject: [PATCH 549/637] Add another mailmap entry for Dean Hamstead --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 0803ca49..b18039c6 100644 --- a/.mailmap +++ b/.mailmap @@ -9,3 +9,4 @@ John Scoles Dean Hamstead Dean Hamstead +Dean Hamstead From 41f043e28564689f7db0699f6c28852f0673be76 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 10 Jul 2019 00:02:29 +1000 Subject: [PATCH 550/637] Update mailmap file --- .mailmap | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/.mailmap b/.mailmap index b18039c6..4dd39cf0 100644 --- a/.mailmap +++ b/.mailmap @@ -1,12 +1,17 @@ -Yanick Champoux -Yanick Champoux -Yanick Champoux -Tim Bunce -Tim Bunce -Martin J. Evans -Martin J. Evans -John Scoles -Michael Portnoy Dean Hamstead Dean Hamstead Dean Hamstead +Dean Pearce +John Scoles +Martin J. Evans +Martin J. Evans +Martin J. Evans +Martin J. Evans +Martin J. Evans +Michael Portnoy +Mike O'Regan +Tim Bunce +Tim Bunce +Yanick Champoux +Yanick Champoux +Yanick Champoux From 3f21ba7e09e54073c48295aafdf8c470bba0104d Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Tue, 9 Jul 2019 15:07:37 +0100 Subject: [PATCH 551/637] up version for deve release --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 528c5ea7..33dfcdca 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.76 +version = 1.77_1 ; Generate files From cd711f1ffe13fb1c5e0b5910911f3fd7f26d9df3 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 10 Jul 2019 09:02:18 +1000 Subject: [PATCH 552/637] Remove x flag --- Makefile.PL | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 Makefile.PL diff --git a/Makefile.PL b/Makefile.PL old mode 100755 new mode 100644 From 0356931e98288715c4be32381d50a0e39c22bfa8 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 10 Jul 2019 09:15:20 +1000 Subject: [PATCH 553/637] Remove references to long gone EXAMPLE FILES section --- lib/DBD/Oracle/Troubleshooting/Hpux.pod | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/DBD/Oracle/Troubleshooting/Hpux.pod b/lib/DBD/Oracle/Troubleshooting/Hpux.pod index 7b6acd1d..26e98b01 100644 --- a/lib/DBD/Oracle/Troubleshooting/Hpux.pod +++ b/lib/DBD/Oracle/Troubleshooting/Hpux.pod @@ -89,9 +89,6 @@ start with a Perl that as been built with the correct compiler flags and shared libraries. This means that you must build your own version of Perl from source. -See L for a copy of a makefile used by me to build Perl on -HP-UX and all other platforms on which he works (Sun and Red Hat). - The instructions below have been used for building a dynamically linked working DBD-Oracle driver that works with mod_perl and Apache. These instructions are based on Perl 5.6.0 and 5.6.1, and 5.8.0. To this @@ -169,11 +166,6 @@ While I have not reproduced either of these configurations, I believe the information is complete enough (particularly in the aggregate) to be helpful to others who might wish to replicate it. -If someone would be willing to submit a makefile equivalent to the -makefile in any of the examples from L, which uses gcc -to build Perl and the DBI/DBD-Oracle interfaces, I will be happy to -include it in the next README. - =head2 The "default" built in compiler 64bit build (/usr/bin/cc) And now, at long last, we have a recipe for building perl and DBD-Oracle From e63c8a58a44e67e8ff8a0c56a09a7ed553f8bba6 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 10 Jul 2019 09:24:05 +1000 Subject: [PATCH 554/637] Unlink 'LOB Locator Method Interface' as there is no section for it --- lib/DBD/Oracle.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index fedd625b..898a1035 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -3883,7 +3883,7 @@ BLOBs and CLOBs treating them exactly as if they were the same as the legacy LON With this interface DBD::Oracle handles your data utilizing LOB Locator OCI calls so it only works with CLOB and BLOB datatypes. With this interface DBD::Oracle takes care of the LOB Locator operations for you. -=item L +=item LOB Locator Method Interface This allows the user direct access to the LOB Locator methods, so you have to take care of the LOB Locator operations yourself. From 212392f24de78e00eef97338f798f4d0fe3f899b Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Fri, 19 Jul 2019 17:47:39 +0100 Subject: [PATCH 555/637] Bump to 1.78 --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 46ae09b4..7865e4fe 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.77_1 +version = 1.78 ; Generate files From 4c61703473b8ba0f26eb367ba2f6fdc485bd71ff Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Sat, 20 Jul 2019 09:56:15 +0100 Subject: [PATCH 556/637] Bump version --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 7865e4fe..78baca28 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.78 +version = 1.79 ; Generate files From 38776a05a47cd1091d2a775c33e6c39958dc3f7c Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Mon, 22 Jul 2019 15:01:47 +0100 Subject: [PATCH 557/637] Bump to 1.791 --- Changes | 2 ++ dist.ini | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 26532a26..139f85b2 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} +1.791 2019-07-22 + [BUG FIXES] Fix Avoid GCC-ism so that HP-UX can compile (GH#92, Dean Hamstead) diff --git a/dist.ini b/dist.ini index 78baca28..ac4f2df9 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.79 +version = 1.791 ; Generate files From 50c22b2c7b28b4c03b8e5d24a019bfebc4a6ae68 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Mon, 22 Jul 2019 18:29:34 +0100 Subject: [PATCH 558/637] Run orphaned test code --- Changes | 5 +++++ t/28array_bind.t | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 139f85b2..a026ac22 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,11 @@ Revision history for DBD::Oracle {{$NEXT}} + [BUG FIXES] + + orphaned test code in t/28_array_bind.t - (GH#64, dzort) + Made the code run so it is nolonger orphaned + 1.791 2019-07-22 [BUG FIXES] diff --git a/t/28array_bind.t b/t/28array_bind.t index 6b4eb4a4..c37e845b 100644 --- a/t/28array_bind.t +++ b/t/28array_bind.t @@ -326,7 +326,7 @@ SKIP: { $dbh = db_connect(0); if ($dbh) { - plan tests => 15; + plan tests => 19; } else { plan skip_all => 'Unable to connect to Oracle' if not $dbh; @@ -335,6 +335,7 @@ SKIP: { test_varchar2_table_3_tests($dbh); test_number_table_3_tests($dbh); test_inout_array_tests($dbh); + test_number_SP($dbh); } From cfc917669469cb841e3c953e7ea544aa3a3ba71e Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Mon, 22 Jul 2019 19:08:28 +0100 Subject: [PATCH 559/637] Updated bugtracker to git Updated home page to metacpan Updated Changes Updated dis.ini to bump to 1.792 --- Changes | 5 +++++ Makefile.PL | 8 ++------ dist.ini | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index a026ac22..2ef3c17b 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,11 @@ Revision history for DBD::Oracle orphaned test code in t/28_array_bind.t - (GH#64, dzort) Made the code run so it is nolonger orphaned + [MISCELLANEOUS] + + Updated bugtracker to git + updated home page to metacpan + 1.791 2019-07-22 [BUG FIXES] diff --git a/Makefile.PL b/Makefile.PL index 8d3aebe0..d678d713 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -61,12 +61,8 @@ my %opts = ( "ExtUtils::MakeMaker" => 0, "Test::Simple" => '0.90'}, resources => { - bugtracker => { - mailto => 'bug-dbd-oracle at rt.cpan.org', - web => - 'http://rt.cpan.org/Public/Dist/Display.html?Name=DBD-Oracle', - }, - homepage => 'http://search.cpan.org/dist/DBD-Oracle', + bugtracker => 'https://github.com/perl5-dbi/DBD-Oracle/issues', + homepage => 'https://metacpan.org/pod/DBD::Oracle', repository => { type => 'git', url => 'git://github.com/yanick/DBD-Oracle.git', diff --git a/dist.ini b/dist.ini index ac4f2df9..3ee6ddb0 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.791 +version = 1.792 ; Generate files From dc7492cd70ba6fca4564d1c2a9a9c2e01f536d82 Mon Sep 17 00:00:00 2001 From: "Martin J. Evans" Date: Thu, 25 Jul 2019 15:23:01 +0100 Subject: [PATCH 560/637] Update version to 1.80 because it causes packagers a problem --- Changes | 2 ++ dist.ini | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 2ef3c17b..e2e9be47 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} +1.80 2019-07-25 + [BUG FIXES] orphaned test code in t/28_array_bind.t - (GH#64, dzort) diff --git a/dist.ini b/dist.ini index 3ee6ddb0..bc327258 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.792 +version = 1.80 ; Generate files From 5d93619183b09aaf12d856b55f8411a6d7c20818 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 23 Jun 2020 21:46:26 -0700 Subject: [PATCH 561/637] Add perl 5.30 to travis --- .travis.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2c967dd1..376ea6d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,38 @@ matrix: # FYI Oracle XE only comes in utf8, so we can't run USASCII version of tests include: +# Perl 5.30 variations + - perl: '5.30' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.30' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.30-shrplib' + env: + - ORACLEV=11.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.30-shrplib' + env: + - ORACLEV=12.2 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + # Perl 5.28 variations - perl: '5.28' env: From 65d1cff31d665939b57806c6380868732ec1fa58 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 23 Jun 2020 21:55:49 -0700 Subject: [PATCH 562/637] Remove dead links from README --- README | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/README b/README index 9044c221..fb5519ea 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ DBD::Oracle -- an Oracle interface for Perl 5. - Copyright (c) 1994-2006 Tim Bunce, Ireland. + Copyright (c) 1994-2020 Tim Bunce, et. al. See the COPYRIGHT section in the Oracle.pm file for terms. See also the MAINTAINER section in the Oracle.pm @@ -267,30 +267,6 @@ README.longs.txt -- examples dealing with LONG types (blobs) DBI 'home page': http://dbi.perl.org -Old archive site for Perl DB information: - ftp://ftp.demon.co.uk/pub/perl/db/ -Mailing list archive: /DBI/perldb-interest/ -Perl 4 Oraperl (v2.4) /perl4/oraperl/ - -Jeff Stander's stuff stands out for Oraperl: -Directories of interest might be - /pub/Oracle/sources - /pub/Oracle/sources/jstander - /pub/Oracle/sources/jstander/distrib - /pub/Oracle/sources/jstander/tsmlib - /pub/Oracle/sources/jstander/wdbex - /pub/Oracle/sources/web/scripts - /pub/Oracle/sources/dba - /pub/Oracle/sources/dba/imp2sql7 - /pub/Oracle/sources/Lonnroth - /pub/Oracle/sources/harrison - -http://www.bf.rmit.edu.au/~orafaq/perlish.html -ftp://ftp.bf.rmit.edu.au/pub/perl/db -ftp://ftp.bf.rmit.edu.au/pub/Oracle -ftp://ftp.bf.rmit.edu.au/pub/Oracle/sources -ftp://ftp.bf.rmit.edu.au/pub/Oracle/OS/MS/NT/ntoraperl.zip - DBI and DBD::Oracle are very portable. If Perl and Oracle run on a platform then the chances are that DBD::Oracle will as well. From a75ce7f7614f160a3aead79a0b5b014d6b6495d7 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 23 Jun 2020 22:03:13 -0700 Subject: [PATCH 563/637] Adjust deprecated .travis.yml syntax --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 376ea6d1..8b802ce3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ language: perl # See https://docs.travis-ci.com/user/reference/overview/#Virtualisation-Environment-vs-Operating-System os: linux dist: trusty -sudo: required env: global: @@ -22,7 +21,7 @@ addons: - unzip - libaio1 -matrix: +jobs: fast_finish: true allow_failures: From 5705cf2ca190459b473a681d6119f4ccd5ac20b4 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 23 Jun 2020 22:04:36 -0700 Subject: [PATCH 564/637] Add perl 5.32 --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8b802ce3..4e9088f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,8 +31,8 @@ jobs: # FYI Oracle XE only comes in utf8, so we can't run USASCII version of tests include: -# Perl 5.30 variations - - perl: '5.30' +# Perl 5.32 variations + - perl: '5.32' env: - ORACLEV=11.2 - ORACLEDBV=11.2 @@ -40,14 +40,14 @@ jobs: - ORACLE_USERID_2=mspiggy/barfoo - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - perl: '5.30' + - perl: '5.32' env: - ORACLEV=12.2 - ORACLEDBV=11.2 - ORACLE_USERID=kermit/foobar - ORACLE_USERID_2=mspiggy/barfoo - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - perl: '5.30-shrplib' + - perl: '5.32-shrplib' env: - ORACLEV=11.2 - ORACLEDBV=11.2 @@ -55,7 +55,7 @@ jobs: - ORACLE_USERID_2=mspiggy/barfoo - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - perl: '5.30-shrplib' + - perl: '5.32-shrplib' env: - ORACLEV=12.2 - ORACLEDBV=11.2 From edd35224c60a15dcf745c11f2331afe6f0c8f94b Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 23 Jun 2020 22:13:06 -0700 Subject: [PATCH 565/637] Tweaks to dist.ini to make the release cleaner --- dist.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dist.ini b/dist.ini index bc327258..5813e339 100644 --- a/dist.ini +++ b/dist.ini @@ -39,6 +39,8 @@ format = %-9v %{yyyy-MM-dd}d [Git::GatherDir] exclude_filename = cpanfile +exclude_filename = dist.ini +exclude_match = ^maint/ [CopyFilesFromBuild] copy = cpanfile @@ -86,6 +88,8 @@ process_changes = 1 [CopyrightYearFromGit] +[PruneCruft] + [Prereqs / ConfigureRequires] Config = 0 From 1b194e1cda2c75af6cfd1d2ce8f4e236cebebd3f Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 23 Jun 2020 22:13:26 -0700 Subject: [PATCH 566/637] Remove POD sections that are now being inserted automatically --- lib/DBD/Oracle.pm | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 898a1035..0671df86 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -5582,27 +5582,10 @@ Also PL/Vision from RevealNet and Steven Feuerstein, and =back -=head1 AUTHORS - -DBI by Tim Bunce L. - -The original C was by Tim Bunce. -Maintained as of release 1.17 (February 2006) by John Scoles, then Yanick Champoux, under the -auspice of the Pythian Group (L). - =head1 ACKNOWLEDGEMENTS A great many people have helped with DBD::Oracle over the 17 years between 1994 and 2011. Far too many to name, but we thank them all. Many are named in the Changes file. -=head1 COPYRIGHT - -The DBD::Oracle module is Copyright (c) 1994-2006 Tim Bunce. Ireland. -The DBD::Oracle module is Copyright (c) 2006-2011 John Scoles (The Pythian Group). Canada. -The DBD::Oracle module is Copyright (c) 2011 John Scoles. Canada. - -The DBD::Oracle module is free open source software; you can -redistribute it and/or modify it under the same terms as Perl 5. - =cut From 09bd6588c11ea348df7149a2490345553daa51e1 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 24 Jun 2020 23:04:00 -0700 Subject: [PATCH 567/637] Small adjustments to the script that installs oracle xe for testing --- maint/travis-ci_scripts/01_install_oracle_xe.bash | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/maint/travis-ci_scripts/01_install_oracle_xe.bash b/maint/travis-ci_scripts/01_install_oracle_xe.bash index 8b96169e..cc1b41f6 100755 --- a/maint/travis-ci_scripts/01_install_oracle_xe.bash +++ b/maint/travis-ci_scripts/01_install_oracle_xe.bash @@ -2,8 +2,8 @@ set -ex -# maybe in the future this will be more specific -if [ -n "$ORACLEDBV" ]; then +# 11.2 +if [ "$ORACLEDBV" = "11.2" ]; then # wget --content-disposition https://packagecloud.io/mojotech/cloud/packages/debian/jessie/oracle-xe_11.2.0-1.0_amd64.deb/download.deb @@ -32,6 +32,10 @@ echo -e "pga_aggregate_target=200540160\nsga_target=601620480" >> /u01/app/oracl # Now configure Oracle XE printf 8080\\n1521\\nadminpass\\nadminpass\\ny\\n | /etc/init.d/oracle-xe configure +# Replace the containers hostname with 0.0.0.0 +sed -i 's/'$(hostname)'/0.0.0.0/g' /u01/app/oracle/product/11.2.0/xe/network/admin/listener.ora +sed -i 's/'$(hostname)'/0.0.0.0/g' /u01/app/oracle/product/11.2.0/xe/network/admin/tnsnames.ora + sqlplusbin="/u01/app/oracle/product/11.2.0/xe/bin/sqlplus" # ORACLE_SID=XE ORACLE_HOME="/u01/app/oracle/product/11.2.0/xe" $sqlplusbin -H USER1=`echo $ORACLE_USERID|sed 's/\/.*//'` @@ -54,3 +58,10 @@ ORACLE_SID=XE ORACLE_HOME="/u01/app/oracle/product/11.2.0/xe" $sqlplusbin -L -S fi + + +if [ "$ORACLEDBV" = "18" ]; then + +echo "TODO See https://github.com/fuzziebrain/docker-oracle-xe/blob/master/Dockerfile" + +fi From 016b04447cf022c957ae4bd76f823ad8940354c6 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 25 Jun 2020 09:38:58 -0700 Subject: [PATCH 568/637] spit out the sha256 of oracle-xe. maybe check it later --- maint/travis-ci_scripts/01_install_oracle_xe.bash | 1 + 1 file changed, 1 insertion(+) diff --git a/maint/travis-ci_scripts/01_install_oracle_xe.bash b/maint/travis-ci_scripts/01_install_oracle_xe.bash index cc1b41f6..4db70dba 100755 --- a/maint/travis-ci_scripts/01_install_oracle_xe.bash +++ b/maint/travis-ci_scripts/01_install_oracle_xe.bash @@ -14,6 +14,7 @@ wget --quiet https://raw.githubusercontent.com/wnameless/docker-oracle-xe-11g/ma wget --quiet https://raw.githubusercontent.com/wnameless/docker-oracle-xe-11g/master/assets/oracle-xe_11.2.0-1.0_amd64.debab wget --quiet https://raw.githubusercontent.com/wnameless/docker-oracle-xe-11g/master/assets/oracle-xe_11.2.0-1.0_amd64.debac cat oracle-xe_11.2.0-1.0_amd64.deba* > oracle-xe_11.2.0-1.0_amd64.deb +sha256sum oracle-xe_11.2.0-1.0_amd64.deb dpkg --install oracle-xe_11.2.0-1.0_amd64.deb # Hack needed because oracle configuration looks for awk in /bin instead of $PATH From 23cd1a26f448bf1b210a16ad5acec28d08f4d968 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 25 Jun 2020 09:39:24 -0700 Subject: [PATCH 569/637] Add a Dockfile to help people hack on DBD::Oracle quickly --- maint/Dockerfile | 37 +++++++++++++++++++++++++++++++++++++ maint/docker-init.sh | 7 +++++++ 2 files changed, 44 insertions(+) create mode 100644 maint/Dockerfile create mode 100755 maint/docker-init.sh diff --git a/maint/Dockerfile b/maint/Dockerfile new file mode 100644 index 00000000..1869e9ae --- /dev/null +++ b/maint/Dockerfile @@ -0,0 +1,37 @@ +FROM perl:5.32-threaded-buster + +# This will install Oracle XE database and the Oracle SDK to make developing easier +# It leans on the same scripts used by travis, so they can be tweaked here too + +# build then run this throw away docker image with: +# cd DBD-Oracle +# docker build -f maint/Dockerfile . -t testoracle +# docker run -it testoracle bash +# . /etc/profile.d/oracle.sh +# perl Makefile.PL +# make +# /etc/init.d/oracle-xe start +# prove -lbv t/ + +# Adjust the FROM line to pick a perl version and distro. See also https://hub.docker.com/_/perl +# Adjust the two variables below to set the Oracle XE server version and client version + +ENV ORACLEDBV=11.2 \ + ORACLEV=12.2 + +# These are used by DBD::Oracle unit tests +ENV ORACLE_USERID=kermit/foobar \ + ORACLE_USERID_2=mspiggy/barfoo \ + ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + +COPY . /usr/src/DBD-Oracle +RUN apt-get update && apt-get install -y libaio-dev && \ + apt-get install -y vim less net-tools && \ + cpanm --notest --installdeps /usr/src/DBD-Oracle && \ + /usr/src/DBD-Oracle/maint/travis-ci_scripts/01_install_oracle_xe.bash && \ + /usr/src/DBD-Oracle/maint/travis-ci_scripts/02_install_oracle_instantclient.bash && \ + sync && /etc/init.d/oracle-xe stop && apt-get clean + +WORKDIR /usr/src/DBD-Oracle + +CMD /usr/src/DBD-Oracle/maint/docker-init.sh diff --git a/maint/docker-init.sh b/maint/docker-init.sh new file mode 100755 index 00000000..4ab8db49 --- /dev/null +++ b/maint/docker-init.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -ex + +/etc/init.d/oracle-xe start + +bash -l From 51c94dd2ca43fe351e7715f49d319c78722b903f Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 25 Jun 2020 09:56:11 -0700 Subject: [PATCH 570/637] Update comments in Dockerfile --- maint/Dockerfile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/maint/Dockerfile b/maint/Dockerfile index 1869e9ae..c8d96605 100644 --- a/maint/Dockerfile +++ b/maint/Dockerfile @@ -6,12 +6,10 @@ FROM perl:5.32-threaded-buster # build then run this throw away docker image with: # cd DBD-Oracle # docker build -f maint/Dockerfile . -t testoracle -# docker run -it testoracle bash -# . /etc/profile.d/oracle.sh +# docker run -it testoracle # perl Makefile.PL # make -# /etc/init.d/oracle-xe start -# prove -lbv t/ +# make test # Adjust the FROM line to pick a perl version and distro. See also https://hub.docker.com/_/perl # Adjust the two variables below to set the Oracle XE server version and client version From c05f112fb2fb3defeee1929deffc79212519c68d Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Fri, 26 Jun 2020 08:55:27 -0700 Subject: [PATCH 571/637] Add some debugging --- maint/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maint/Dockerfile b/maint/Dockerfile index c8d96605..f7e8c43b 100644 --- a/maint/Dockerfile +++ b/maint/Dockerfile @@ -25,7 +25,7 @@ ENV ORACLE_USERID=kermit/foobar \ COPY . /usr/src/DBD-Oracle RUN apt-get update && apt-get install -y libaio-dev && \ apt-get install -y vim less net-tools && \ - cpanm --notest --installdeps /usr/src/DBD-Oracle && \ + cpanm --verbose --notest --installdeps /usr/src/DBD-Oracle && \ /usr/src/DBD-Oracle/maint/travis-ci_scripts/01_install_oracle_xe.bash && \ /usr/src/DBD-Oracle/maint/travis-ci_scripts/02_install_oracle_instantclient.bash && \ sync && /etc/init.d/oracle-xe stop && apt-get clean From 20b7f1889d6829fbb4c596e925b08a86e6105be7 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 2 Sep 2020 23:47:46 -0700 Subject: [PATCH 572/637] Move t/README to /TESTING.md for GH#119 --- t/README => TESTING.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) rename t/README => TESTING.md (91%) diff --git a/t/README b/TESTING.md similarity index 91% rename from t/README rename to TESTING.md index 518ed169..986067b9 100644 --- a/t/README +++ b/TESTING.md @@ -1,5 +1,4 @@ -Variables used in tests ------------------------ +# Variables used in tests ** Connecting to Oracle ** @@ -19,7 +18,9 @@ ORACLE_DSN DSN details when connecting to real Oracle for tests - $ export ORACLE_DSN='dbi:Oracle:testdb' +``` bash +$ export ORACLE_DSN='dbi:Oracle:testdb' +``` DBI_DSN From 9a78fec97e013d8ceba98bed5635bedcab1fadec Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 2 Sep 2020 23:55:19 -0700 Subject: [PATCH 573/637] Update README with some minor improvements --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index fb5519ea..fe3891c9 100644 --- a/README +++ b/README @@ -114,9 +114,9 @@ So you should set that to a valid user (e.g. 'scott/tiger') and ensure that this user has sufficient privileges to create, insert into, select from and drop a table, is also able to create, call and drop a procedure and is able to select from systemtables like 'v$sessions'. Using 'system/manager' might -work but is not recommended! See also +work but is not recommended! See also README.login.txt and TESTING.md. -README.login.txt. +Run tests with: make test From e08a7f8cb6ba71d6f5d1cfd2a0f9dd3063a10c2d Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 2 Sep 2020 23:59:37 -0700 Subject: [PATCH 574/637] Update markdown in TESTING.md --- TESTING.md | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/TESTING.md b/TESTING.md index 986067b9..52c9daab 100644 --- a/TESTING.md +++ b/TESTING.md @@ -1,20 +1,22 @@ # Variables used in tests -** Connecting to Oracle ** +**Connecting to Oracle** -ORACLE_USERID - important +`ORACLE_USERID` - important Which user & password to use when running tests against a real Oracle database Should be 'user/password' or a longer string with connection details. - $ export ORACLE_USERID='scott/tiger' +``` bash +$ export ORACLE_USERID='scott/tiger' +``` -ORACLE_USERID_2 +`ORACLE_USERID_2` Provides a second set of user credentials when needed -ORACLE_DSN +`ORACLE_DSN` DSN details when connecting to real Oracle for tests @@ -22,42 +24,37 @@ DSN details when connecting to real Oracle for tests $ export ORACLE_DSN='dbi:Oracle:testdb' ``` -DBI_DSN +`DBI_DSN` -If ORACLE_DSN is not provided, this will be used. Otherwise falls back to internal default. +If `ORACLE_DSN` is not provided, this will be used. Otherwise falls back to internal default. -** Creation of tables, views, functions etc ** +**Creation of tables, views, functions etc** -DBD_ORACLE_SEQ - important +`DBD_ORACLE_SEQ` - important Appended to table, view, function (etc) that are created during testing to help prevent collisions -DBD_SKIP_TABLE_DROP +`DBD_SKIP_TABLE_DROP` -Skips dropping temporary tables when tests complete. Use to examine the mess. +Skips dropping temporary tables when tests complete. Use to examine the mess after failed tests. -** Other ** +**Other** -NLS_DATE_FORMAT +`NLS_DATE_FORMAT` Sets the date format as normal -Need more details ------------------ - -NLS_NCHAR +## Vars that need more detail -NLS_LANG +`NLS_NCHAR` +`NLS_LANG` ??? -DBI_USER - -DBI_PASS - -DBD_ALL_TESTS +`DBI_USER` -Forces some tests to run, that otherwise wouldn't +`DBI_PASS` +`DBD_ALL_TESTS` - Forces some tests to run, that otherwise wouldn't From b4174a3d451f1398566136903be5fa946c3b1a80 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 3 Sep 2020 00:06:14 -0700 Subject: [PATCH 575/637] Dont test 5.32 as Travi's perl install for it seems broken --- .travis.yml | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4e9088f0..01d06a4c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,21 +32,22 @@ jobs: include: # Perl 5.32 variations - - perl: '5.32' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.32' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' +## At 2020-09-03 Travis's 5.32 is broken +## - perl: '5.32' +## env: +## - ORACLEV=11.2 +## - ORACLEDBV=11.2 +## - ORACLE_USERID=kermit/foobar +## - ORACLE_USERID_2=mspiggy/barfoo +## - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' +## +## - perl: '5.32' +## env: +## - ORACLEV=12.2 +## - ORACLEDBV=11.2 +## - ORACLE_USERID=kermit/foobar +## - ORACLE_USERID_2=mspiggy/barfoo +## - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - perl: '5.32-shrplib' env: - ORACLEV=11.2 From e51badefe54c18cac2b7c91693df7529f31f29ac Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 3 Sep 2020 00:14:30 -0700 Subject: [PATCH 576/637] Mention mkta.pl in TESTING.md --- TESTING.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TESTING.md b/TESTING.md index 52c9daab..a27efc5e 100644 --- a/TESTING.md +++ b/TESTING.md @@ -45,7 +45,11 @@ Skips dropping temporary tables when tests complete. Use to examine the mess aft Sets the date format as normal -## Vars that need more detail +# Test all script + +The mkta.pl script might be useful as for testing against multiple DB's quickly + +# Vars that need more detail `NLS_NCHAR` From 1a113257f02f76588ed607b2f4e237ad33979e1b Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 3 Sep 2020 00:27:25 -0700 Subject: [PATCH 577/637] Update project links in Makefile.PL --- Makefile.PL | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index d678d713..928641eb 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -65,8 +65,8 @@ my %opts = ( homepage => 'https://metacpan.org/pod/DBD::Oracle', repository => { type => 'git', - url => 'git://github.com/yanick/DBD-Oracle.git', - web => 'http://github.com/yanick/DBD-Oracle/tree', + url => 'git://github.com/perl5-dbi/DBD-Oracle.git', + web => 'http://github.com/perl5-dbi/DBD-Oracle', }, }, }, @@ -97,7 +97,6 @@ my %mk_target_rules; Try to use Oracle's own 'build' rule. Defaults to true. - =item -r With I<-b>, use this names build rule (eg -r=build64). From ab7e8a346708189659dba826c1c08dce1434ecd2 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 3 Sep 2020 00:35:34 -0700 Subject: [PATCH 578/637] Update MANIFEST --- MANIFEST | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST b/MANIFEST index 2b45ef07..c16e2f5a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -12,6 +12,7 @@ Oracle.xs README README.help.txt README.mkdn +TESTING.md TODO cpanfile dbdimp.c @@ -93,7 +94,6 @@ t/58object.t t/60reauth.t t/70meta.t t/80ora_charset.t -t/README t/lib/DBDOracleTestLib.pm t/lib/ExecuteArray.pm t/rt13865.t From da936b5c790523ac9bae439584004f1f8327f114 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 24 Jul 2019 16:48:58 +1000 Subject: [PATCH 579/637] Adjust prerequisites in dist.ini --- dist.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dist.ini b/dist.ini index 5813e339..8da5eba7 100644 --- a/dist.ini +++ b/dist.ini @@ -91,10 +91,12 @@ process_changes = 1 [PruneCruft] -[Prereqs / ConfigureRequires] +[Prereqs] +DBI = 1.623 + +[Prereqs / TestRequires] Config = 0 Data::Dumper = 0 -DBI = 1.623 Devel::Peek = 0 Encode = 0 Math::BigInt = 0 From 7c323840950ed09fd8ccd8b7ab518718c39bb75a Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 23 Dec 2019 14:39:00 +1100 Subject: [PATCH 580/637] Add $OH/include as a possible header location --- Makefile.PL | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.PL b/Makefile.PL index 928641eb..c16c01f4 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1546,6 +1546,7 @@ sub find_headers { "$OH/plsql", # oratypes.h sometimes here (eg HPUX 11.23 Itanium Oracle 9.2.0), # --- Oracle SDK Instant Client locations "$OH/sdk/include", + "$OH/include", # --- Oracle RPM Instant Client locations map { ( $_, $_."64" ) } map { ( $_, "/usr$_" ) } From cfb2073f6e978d700ad369ef60114546fee8277b Mon Sep 17 00:00:00 2001 From: Carsten Grohmann Date: Fri, 20 Sep 2019 21:54:05 +0200 Subject: [PATCH 581/637] Extend documentation about leaking handles and rename leak_state to leak_handles for better understanding. --- Oracle.xs | 14 ++++++++++++-- dbdimp.c | 14 +++++++------- dbdimp.h | 20 +++++++++++++------- lib/DBD/Oracle.pm | 19 ++++++++++++------- 4 files changed, 44 insertions(+), 23 deletions(-) diff --git a/Oracle.xs b/Oracle.xs index 7ec2eaa2..bb5d61e9 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -114,9 +114,13 @@ ora_cygwin_set_env(name, value) #endif /* __CYGWIN32__ */ - INCLUDE: Oracle.xsi + + +# ------------------------------------------------------------ +# statement interface +# ------------------------------------------------------------ MODULE = DBD::Oracle PACKAGE = DBD::Oracle::st @@ -281,7 +285,9 @@ cancel(sth) - +# ------------------------------------------------------------ +# database level interface +# ------------------------------------------------------------ MODULE = DBD::Oracle PACKAGE = DBD::Oracle::db void @@ -702,6 +708,10 @@ ora_lob_chunk_size(dbh, locator) } + +# ------------------------------------------------------------ +# driver level interface +# ------------------------------------------------------------ MODULE = DBD::Oracle PACKAGE = DBD::Oracle::dr void diff --git a/dbdimp.c b/dbdimp.c index 210a69d2..30449d81 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -210,8 +210,8 @@ dbd_dr_destroy(SV *drh, imp_drh_t *imp_drh) /* We rely on the DBI dispatcher to destroy all child handles before we get here (DBI >= 1.623). */ - if (imp_drh->leak_state) { - /* With ithreads, we can't tell when the last dr handle is destroyed. */ + if (imp_drh->leak_handles) { + /* By using ithread, handles will leak in dbd_dr_destroy() */ return; } @@ -568,8 +568,8 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S shared_dbh = NULL ; } - /* With ithreads, we can't tell when the last dr handle is destroyed. */ - imp_drh->leak_state = 1; + /* By using ithread, handles will leak in dbd_dr_destroy() */ + imp_drh->leak_handles = 1; } #endif @@ -583,7 +583,7 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S imp_dbh->envhp = NULL; /* force new environment */ } } - /* RT46739 */ + /* Test if a cached environment handle it still usable (see RT46739) */ if (imp_dbh->envhp) { OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); if (status != OCI_SUCCESS) { @@ -1287,8 +1287,8 @@ dbd_take_imp_data(SV *dbh, imp_xxh_t *imp_xxh, void* foo) D_imp_dbh(dbh); D_imp_drh_from_dbh; - /* With ithreads, we can't tell when the last dr handle is destroyed. */ - imp_drh->leak_state = 1; + /* By using ithread, handles will leak in dbd_dr_destroy() */ + imp_drh->leak_handles = 1; /* Indicate that SUPER::take_imp_data should be called. */ return &PL_sv_no; diff --git a/dbdimp.h b/dbdimp.h index d42cb4dc..bb21ac39 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -11,17 +11,21 @@ typedef struct taf_callback_st taf_callback_t; struct taf_callback_st { - SV *function; /*User supplied TAF functiomn*/ - SV *dbh_ref; + SV *function; /*User supplied TAF function*/ + SV *dbh_ref; }; typedef struct imp_fbh_st imp_fbh_t; +/* Define implementation specific driver handle data structure */ struct imp_drh_st { dbih_drc_t com; /* MUST be first element in structure */ - OCIEnv *envhp; - bool leak_state; + OCIEnv *envhp; /* global environment handler, see also */ + /* connect attr ora_envhp */ + bool leak_handles; /* shared dbh's will leak handles in */ + /* dbd_dr_destroy(), see connect attr */ + /* ora_dbh_share for more information */ #ifdef ORA_OCI_112 HV *charset_hv; HV *pool_hv; @@ -44,7 +48,7 @@ struct session_pool_st { }; #endif -/* Define dbh implementor data structure */ +/* Define implementation specific database handle data structure */ struct imp_dbh_st { dbih_dbc_t com; /* MUST be first element in structure */ @@ -55,7 +59,9 @@ struct imp_dbh_st { #endif void *(*get_oci_handle) _((imp_dbh_t *imp_dbh, int handle_type, int flags)); - OCIEnv *envhp; /* copy of drh pointer */ + OCIEnv *envhp; /* session environment handler, this is mostly */ + /* a copy of imp_drh->envhp, see also connect */ + /* attr ora_envhp */ OCIError *errhp; OCIServer *srvhp; OCISvcCtx *svchp; @@ -101,7 +107,7 @@ struct imp_dbh_st { typedef struct lob_refetch_st lob_refetch_t; /* Define sth implementor data structure */ -/*statement structure */ +/* Define implementation specific statement data structure */ struct imp_sth_st { dbih_stc_t com; /* MUST be first element in structure */ diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 0671df86..4481bade 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1780,19 +1780,24 @@ NOTE: You will need an Oracle client 10.1 or later to use this. =head4 ora_dbh_share -Requires at least Perl 5.8.0 compiled with ithreads. +Requires at least Perl 5.8.0 compiled with ithreads (interpreter-based +threads). -Allows you to share -database connections between threads. The first connect will make the -connection, all following calls to connect with the same ora_dbh_share -attribute will use the same database connection. The value must be a -reference to a already shared scalar which is initialized to an empty -string. +Allows you to share database connections between threads. The first +connect will make the connection, all following calls to connect with +the same ora_dbh_share attribute will use the same database connection. +The value must be a reference to a already shared scalar which is +initialized to an empty string. our $orashr : shared = '' ; $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; +With ithreads DBD::Oracle will leak handles, because it can't tell +when the last driver handle is destroyed. + +Please keep in mind, that ithreads are officially discouraged. + =head4 ora_events Set this attribute to C<1> to enable Oracle Fast Application Notification From 3610ab2322df04c69839ebe1be4bd50549eae790 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 8 Sep 2020 23:58:30 -0700 Subject: [PATCH 582/637] Add instantclient 18.3 and 18.5 to travis, use xenial instead of trusty --- .travis.yml | 69 +++++++++++++++++-- dist.ini | 15 +++- maint/Dockerfile | 2 +- .../01_install_oracle_xe.bash | 2 +- .../02_install_oracle_instantclient.bash | 49 +++++++++++-- 5 files changed, 122 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 01d06a4c..107e0035 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: perl # See https://docs.travis-ci.com/user/reference/overview/#Virtualisation-Environment-vs-Operating-System os: linux -dist: trusty +dist: xenial env: global: @@ -64,6 +64,22 @@ jobs: - ORACLE_USERID_2=mspiggy/barfoo - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.32-shrplib' + env: + - ORACLEV=18.3 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.32-shrplib' + env: + - ORACLEV=18.5 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + # Perl 5.28 variations - perl: '5.28' env: @@ -80,6 +96,23 @@ jobs: - ORACLE_USERID=kermit/foobar - ORACLE_USERID_2=mspiggy/barfoo - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.28' + env: + - ORACLEV=18.3 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.28' + env: + - ORACLEV=18.5 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.28-shrplib' env: - ORACLEV=11.2 @@ -96,6 +129,22 @@ jobs: - ORACLE_USERID_2=mspiggy/barfoo - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.28-shrplib' + env: + - ORACLEV=18.3 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + + - perl: '5.28-shrplib' + env: + - ORACLEV=18.5 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + # Perl 5.26 variations - perl: '5.26' env: @@ -112,6 +161,7 @@ jobs: - ORACLE_USERID=kermit/foobar - ORACLE_USERID_2=mspiggy/barfoo - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.26-shrplib' env: - ORACLEV=11.2 @@ -227,14 +277,22 @@ jobs: - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' # Test without database, all tests should skip - - perl: '5.26' + - perl: '5.32' env: - ORACLEV=11.2 - COVERAGE=1 - - perl: '5.26' + - perl: '5.32' env: - ORACLEV=12.2 - COVERAGE=1 + - perl: '5.32' + env: + - ORACLEV=18.3 + - COVERAGE=1 + - perl: '5.32' + env: + - ORACLEV=18.5 + - COVERAGE=1 before_install: - sudo maint/travis-ci_scripts/01_install_oracle_xe.bash @@ -248,11 +306,12 @@ before_install: - perl -V - build-dist - cd $BUILD_DIR + - cat cpanfile install: - perl -M5.014 -e1 2>/dev/null || cpan-install Dist::Zilla@5.047 - - cpan-install --deps - - cpan-install --coverage + - cpan-install --update-prereqs --deps + - cpan-install --update-prereqs --coverage before_script: - pwd diff --git a/dist.ini b/dist.ini index 8da5eba7..dcc1ef70 100644 --- a/dist.ini +++ b/dist.ini @@ -90,13 +90,24 @@ process_changes = 1 [PruneCruft] +[MinimumPerl] [Prereqs] +Data::Dumper = 0 DBI = 1.623 +DynaLoader = 0 +Exporter = 0 -[Prereqs / TestRequires] +[Prereqs / DevelopRequires] +DBI = 1.623 +Test::NoWarnings = 0 + +[Prereqs / BuildRequires] Config = 0 -Data::Dumper = 0 + +[Prereqs / TestRequires] +warnings = 0 +strict = 0 Devel::Peek = 0 Encode = 0 Math::BigInt = 0 diff --git a/maint/Dockerfile b/maint/Dockerfile index f7e8c43b..a569ce9a 100644 --- a/maint/Dockerfile +++ b/maint/Dockerfile @@ -15,7 +15,7 @@ FROM perl:5.32-threaded-buster # Adjust the two variables below to set the Oracle XE server version and client version ENV ORACLEDBV=11.2 \ - ORACLEV=12.2 + ORACLEV=18.3 # These are used by DBD::Oracle unit tests ENV ORACLE_USERID=kermit/foobar \ diff --git a/maint/travis-ci_scripts/01_install_oracle_xe.bash b/maint/travis-ci_scripts/01_install_oracle_xe.bash index 4db70dba..06796910 100755 --- a/maint/travis-ci_scripts/01_install_oracle_xe.bash +++ b/maint/travis-ci_scripts/01_install_oracle_xe.bash @@ -20,7 +20,7 @@ dpkg --install oracle-xe_11.2.0-1.0_amd64.deb # Hack needed because oracle configuration looks for awk in /bin instead of $PATH ln -s /usr/bin/awk /bin/awk # Oracle also needs this: -mkdir /var/lock/subsys +mkdir -p /var/lock/subsys # Docker containers and stuff dont work with memory_target perl -pi -e 's/^(memory_target=.*)/#$1/' /u01/app/oracle/product/11.2.0/xe/config/scripts/init.ora diff --git a/maint/travis-ci_scripts/02_install_oracle_instantclient.bash b/maint/travis-ci_scripts/02_install_oracle_instantclient.bash index d915887e..b36531bf 100755 --- a/maint/travis-ci_scripts/02_install_oracle_instantclient.bash +++ b/maint/travis-ci_scripts/02_install_oracle_instantclient.bash @@ -8,22 +8,59 @@ fi if [ "$ORACLEV" = "12.2" ]; then export LONGV="12.2.0.1.0" fi +if [ "$ORACLEV" = "18.3" ]; then + export LONGV="18.3.0.0.0" +fi +if [ "$ORACLEV" = "18.5" ]; then + export LONGV="18.5.0.0.0" +fi +if [ "$ORACLEV" = "19.6" ]; then + export LONGV="19.6.0.0.0" +fi if [ -n "$ORACLEV" ]; then - echo "Install Oracle SDK $ORACLEV" + SUFFIX="" + if [[ "$ORACLEV" = "18.3" || "$ORACLEV" = "18.5" ]]; then + SUFFIX="dbru" + fi + echo "Installing Oracle SDK $ORACLEV" mkdir /etc/oracle - mkdir -p /usr/lib/oracle/$ORACLEV/client/bin - mkdir -p /usr/lib/oracle/$ORACLEV/client/lib - mkdir -p /usr/include/oracle/$ORACLEV/client - mkdir -p /usr/share/oracle/$ORACLEV/client + mkdir -p "/usr/lib/oracle/$ORACLEV/client/bin" + mkdir -p "/usr/lib/oracle/$ORACLEV/client/lib" + mkdir -p "/usr/include/oracle/$ORACLEV/client" + mkdir -p "/usr/share/oracle/$ORACLEV/client" pushd `pwd` cd /usr/lib/oracle for i in "basic" "sdk" "sqlplus"; do # Repo intended for Dockerfiles, see https://github.com/bumpx/oracle-instantclient/blob/master/README.md - wget --quiet https://github.com/bumpx/oracle-instantclient/raw/master/instantclient-$i-linux.x64-$LONGV.zip + wget --quiet "https://github.com/bumpx/oracle-instantclient/raw/master/instantclient-$i-linux.x64-$LONGV$SUFFIX.zip" done for i in `ls *zip`; do unzip $i; done fi +if [[ "$ORACLEV" = "18.3" || "$ORACLEV" = "18.5" ]]; then + STUB=$(echo $ORACLEV | sed 's/\./_/') + echo "# Contents of instantclient-basic-linux.x64-$LONGV.zip" + find "instantclient_$STUB" + mv "instantclient_$STUB/adrci" "$ORACLEV/client/bin/" + mv "instantclient_$STUB/genezi" "$ORACLEV/client/bin/" + mv "instantclient_$STUB/uidrvci" "$ORACLEV/client/bin/" + mv instantclient_$STUB/{libclntshcore.so.18.1,libclntsh.so.18.1,libipc1.so,libmql1.so,libnnz18.so,libocci.so.18.1,libociei.so,libocijdbc18.so,libons.so,liboramysql18.so,ojdbc8.jar,xstreams.jar} $ORACLEV/client/lib/ + echo "# Contents of instantclient-sqlplus-linux.x64-$LONGV.zip" + mv instantclient_$STUB/sqlplus $ORACLEV/client/bin/ + mv instantclient_$STUB/glogin.sql instantclient_$STUB/libsqlplus.so instantclient_$STUB/libsqlplusic.so $ORACLEV/client/lib/ + echo "# Contents of instantclient-sdk-linux.x64-$LONGV.zip" + mv instantclient_$STUB/sdk/include/*h /usr/include/oracle/$ORACLEV/client/ + mv instantclient_$STUB/sdk/demo/* /usr/share/oracle/$ORACLEV/client/ + mv instantclient_$STUB/sdk/ott /usr/share/oracle/$ORACLEV/client/ + mv instantclient_$STUB/sdk/ottclasses.zip $ORACLEV/client/lib/ottclasses.zip + ln -s libclntshcore.so.18.1 "$ORACLEV/client/lib/libclntshcore.so" + ln -s libclntsh.so.18.1 "$ORACLEV/client/lib/libclntsh.so" + ln -s libocci.so.18.1 "$ORACLEV/client/lib/libocci.so" + echo "# FYI What wasnt moved from Oracle zip files:" + find "instantclient_$STUB" + echo "# Clean up" + rm -rf "instantclient_$STUB" +fi if [ "$ORACLEV" = "12.2" ]; then echo "# Contents of instantclient-basic-linux.x64-$LONGV.zip" find instantclient_12_2 From f3d640f36a2be23cbd770400d40b0ef462555720 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 9 Sep 2020 22:51:10 -0700 Subject: [PATCH 583/637] Add instantclient 19.6 to travis --- .travis.yml | 24 +++++++ maint/Dockerfile | 2 +- .../02_install_oracle_instantclient.bash | 67 +++++++------------ 3 files changed, 49 insertions(+), 44 deletions(-) diff --git a/.travis.yml b/.travis.yml index 107e0035..0b45c3c7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -80,6 +80,14 @@ jobs: - ORACLE_USERID_2=mspiggy/barfoo - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.32-shrplib' + env: + - ORACLEV=19.6 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + # Perl 5.28 variations - perl: '5.28' env: @@ -113,6 +121,14 @@ jobs: - ORACLE_USERID_2=mspiggy/barfoo - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.28' + env: + - ORACLEV=19.6 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.28-shrplib' env: - ORACLEV=11.2 @@ -145,6 +161,14 @@ jobs: - ORACLE_USERID_2=mspiggy/barfoo - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + - perl: '5.28-shrplib' + env: + - ORACLEV=19.6 + - ORACLEDBV=11.2 + - ORACLE_USERID=kermit/foobar + - ORACLE_USERID_2=mspiggy/barfoo + - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' + # Perl 5.26 variations - perl: '5.26' env: diff --git a/maint/Dockerfile b/maint/Dockerfile index a569ce9a..18f47313 100644 --- a/maint/Dockerfile +++ b/maint/Dockerfile @@ -15,7 +15,7 @@ FROM perl:5.32-threaded-buster # Adjust the two variables below to set the Oracle XE server version and client version ENV ORACLEDBV=11.2 \ - ORACLEV=18.3 + ORACLEV=19.6 # These are used by DBD::Oracle unit tests ENV ORACLE_USERID=kermit/foobar \ diff --git a/maint/travis-ci_scripts/02_install_oracle_instantclient.bash b/maint/travis-ci_scripts/02_install_oracle_instantclient.bash index b36531bf..6d69cc43 100755 --- a/maint/travis-ci_scripts/02_install_oracle_instantclient.bash +++ b/maint/travis-ci_scripts/02_install_oracle_instantclient.bash @@ -2,25 +2,25 @@ set -ex -if [ "$ORACLEV" = "11.2" ]; then +if [ "$ORACLEV" == "11.2" ]; then export LONGV="11.2.0.4.0" fi -if [ "$ORACLEV" = "12.2" ]; then +if [ "$ORACLEV" == "12.2" ]; then export LONGV="12.2.0.1.0" fi -if [ "$ORACLEV" = "18.3" ]; then +if [ "$ORACLEV" == "18.3" ]; then export LONGV="18.3.0.0.0" fi -if [ "$ORACLEV" = "18.5" ]; then +if [ "$ORACLEV" == "18.5" ]; then export LONGV="18.5.0.0.0" fi -if [ "$ORACLEV" = "19.6" ]; then +if [ "$ORACLEV" == "19.6" ]; then export LONGV="19.6.0.0.0" fi +SUFFIX="" if [ -n "$ORACLEV" ]; then - SUFFIX="" - if [[ "$ORACLEV" = "18.3" || "$ORACLEV" = "18.5" ]]; then + if [[ "$ORACLEV" == "18.3" || "$ORACLEV" == "18.5" || "$ORACLEV" == "19.6" ]]; then SUFFIX="dbru" fi echo "Installing Oracle SDK $ORACLEV" @@ -37,63 +37,44 @@ if [ -n "$ORACLEV" ]; then done for i in `ls *zip`; do unzip $i; done fi -if [[ "$ORACLEV" = "18.3" || "$ORACLEV" = "18.5" ]]; then +if [[ "$ORACLEV" == "12.2" || "$ORACLEV" == "18.3" || "$ORACLEV" == "18.5" || "$ORACLEV" == "19.6" ]]; then STUB=$(echo $ORACLEV | sed 's/\./_/') - echo "# Contents of instantclient-basic-linux.x64-$LONGV.zip" + MAJOR=$(echo $ORACLEV | sed 's/\.[0-9]//') + echo "# Moving contents of instantclient-basic-linux.x64-$LONGV$SUFFIX.zip" find "instantclient_$STUB" mv "instantclient_$STUB/adrci" "$ORACLEV/client/bin/" mv "instantclient_$STUB/genezi" "$ORACLEV/client/bin/" mv "instantclient_$STUB/uidrvci" "$ORACLEV/client/bin/" - mv instantclient_$STUB/{libclntshcore.so.18.1,libclntsh.so.18.1,libipc1.so,libmql1.so,libnnz18.so,libocci.so.18.1,libociei.so,libocijdbc18.so,libons.so,liboramysql18.so,ojdbc8.jar,xstreams.jar} $ORACLEV/client/lib/ - echo "# Contents of instantclient-sqlplus-linux.x64-$LONGV.zip" - mv instantclient_$STUB/sqlplus $ORACLEV/client/bin/ - mv instantclient_$STUB/glogin.sql instantclient_$STUB/libsqlplus.so instantclient_$STUB/libsqlplusic.so $ORACLEV/client/lib/ - echo "# Contents of instantclient-sdk-linux.x64-$LONGV.zip" + mv instantclient_$STUB/{libclntshcore.so.$MAJOR.1,libclntsh.so.$MAJOR.1,libipc1.so,libmql1.so,libnnz$MAJOR.so,libocci.so.$MAJOR.1,libociei.so,libocijdbc$MAJOR.so,liboramysql$MAJOR.so,ojdbc8.jar,xstreams.jar} $ORACLEV/client/lib/ + if [ "$MAJOR" != "19" ]; then + mv "instantclient_$STUB/libons.so" "$ORACLEV/client/lib/" + fi + echo "# Moving contents of instantclient-sqlplus-linux.x64-$LONGV.zip" + mv "instantclient_$STUB/sqlplus" "$ORACLEV/client/bin/" + mv "instantclient_$STUB/glogin.sql" "instantclient_$STUB/libsqlplus.so" "instantclient_$STUB/libsqlplusic.so" "$ORACLEV/client/lib/" + echo "# Moving contents of instantclient-sdk-linux.x64-$LONGV$SUFFIX.zip" mv instantclient_$STUB/sdk/include/*h /usr/include/oracle/$ORACLEV/client/ mv instantclient_$STUB/sdk/demo/* /usr/share/oracle/$ORACLEV/client/ mv instantclient_$STUB/sdk/ott /usr/share/oracle/$ORACLEV/client/ mv instantclient_$STUB/sdk/ottclasses.zip $ORACLEV/client/lib/ottclasses.zip - ln -s libclntshcore.so.18.1 "$ORACLEV/client/lib/libclntshcore.so" - ln -s libclntsh.so.18.1 "$ORACLEV/client/lib/libclntsh.so" - ln -s libocci.so.18.1 "$ORACLEV/client/lib/libocci.so" + ln -s "libclntshcore.so.$MAJOR.1" "$ORACLEV/client/lib/libclntshcore.so" + ln -s "libclntsh.so.$MAJOR.1" "$ORACLEV/client/lib/libclntsh.so" + ln -s "libocci.so.$MAJOR.1" "$ORACLEV/client/lib/libocci.so" echo "# FYI What wasnt moved from Oracle zip files:" find "instantclient_$STUB" echo "# Clean up" rm -rf "instantclient_$STUB" fi -if [ "$ORACLEV" = "12.2" ]; then - echo "# Contents of instantclient-basic-linux.x64-$LONGV.zip" - find instantclient_12_2 - mv instantclient_12_2/adrci $ORACLEV/client/bin/ - mv instantclient_12_2/genezi $ORACLEV/client/bin/ - mv instantclient_12_2/uidrvci $ORACLEV/client/bin/ - mv instantclient_12_2/{libclntshcore.so.12.1,libclntsh.so.12.1,libipc1.so,libmql1.so,libnnz12.so,libocci.so.12.1,libociei.so,libocijdbc12.so,libons.so,liboramysql12.so,ojdbc8.jar,xstreams.jar} $ORACLEV/client/lib/ - echo "# Contents of instantclient-sqlplus-linux.x64-$LONGV.zip" - mv instantclient_12_2/sqlplus $ORACLEV/client/bin/ - mv instantclient_12_2/glogin.sql instantclient_12_2/libsqlplus.so instantclient_12_2/libsqlplusic.so $ORACLEV/client/lib/ - echo "# Contents of instantclient-sdk-linux.x64-$LONGV.zip" - mv instantclient_12_2/sdk/include/*h /usr/include/oracle/$ORACLEV/client/ - mv instantclient_12_2/sdk/demo/* /usr/share/oracle/$ORACLEV/client/ - mv instantclient_12_2/sdk/ott /usr/share/oracle/$ORACLEV/client/ - mv instantclient_12_2/sdk/ottclasses.zip $ORACLEV/client/lib/ottclasses.zip - ln -s libclntshcore.so.12.1 $ORACLEV/client/lib/libclntshcore.so - ln -s libclntsh.so.12.1 $ORACLEV/client/lib/libclntsh.so - ln -s libocci.so.12.1 $ORACLEV/client/lib/libocci.so - echo "# FYI What wasnt moved from Oracle zip files:" - find instantclient_12_2 - echo "# Clean up" - rm -rf instantclient_12_2 -fi if [ "$ORACLEV" = "11.2" ]; then - echo "# Contents of instantclient-basic-linux.x64-$LONGV.zip" + echo "# Moving contents of instantclient-basic-linux.x64-$LONGV.zip" mv instantclient_11_2/adrci $ORACLEV/client/bin/ mv instantclient_11_2/genezi $ORACLEV/client/bin/ mv instantclient_11_2/uidrvci $ORACLEV/client/bin/ mv instantclient_11_2/{libclntsh.so.11.1,libnnz11.so,libocci.so.11.1,libociei.so,libocijdbc11.so,ojdbc5.jar,ojdbc6.jar,xstreams.jar} $ORACLEV/client/lib/ - echo "# Contents of instantclient-sqlplus-linux.x64-$LONGV.zip" + echo "# Moving contents of instantclient-sqlplus-linux.x64-$LONGV.zip" mv instantclient_11_2/sqlplus $ORACLEV/client/bin/ mv instantclient_11_2/glogin.sql instantclient_11_2/libsqlplus.so instantclient_11_2/libsqlplusic.so $ORACLEV/client/lib/ - echo "# Contents of instantclient-sdk-linux.x64-$LONGV.zip" + echo "# Moving contents of instantclient-sdk-linux.x64-$LONGV.zip" mv instantclient_11_2/sdk/include/*h /usr/include/oracle/$ORACLEV/client/ mv instantclient_11_2/sdk/demo/* /usr/share/oracle/$ORACLEV/client/ mv instantclient_11_2/sdk/ott /usr/share/oracle/$ORACLEV/client/ From 8e3eac408aa4b569fc49951ec0c777fa233b8628 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 9 Sep 2020 22:56:25 -0700 Subject: [PATCH 584/637] Ensure strict and warnings are first --- t/14threads.t | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/t/14threads.t b/t/14threads.t index 078b40b7..e702842b 100644 --- a/t/14threads.t +++ b/t/14threads.t @@ -1,5 +1,8 @@ #!perl +use strict; +use warnings; + $| = 1; ## ---------------------------------------------------------------------------- @@ -9,8 +12,6 @@ $| = 1; # This needs to be the very very first thing BEGIN { eval 'use threads; use threads::shared;' } -use strict; -use warnings; use lib 't/lib'; use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; From 7704961330cdb8d8f32051ef8bac597a2712233f Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 10 Sep 2020 00:23:43 -0700 Subject: [PATCH 585/637] Swap tabs to spaces in Makefile.PL --- Makefile.PL | 1403 +++++++++++++++++++++++++-------------------------- 1 file changed, 700 insertions(+), 703 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index c16c01f4..bd581321 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -18,7 +18,7 @@ use Pod::Usage; # new static perl in the DBI directory by saying 'make perl' # and then using _that_ perl to make this one. use DBI 1.623; -use DBI::DBD; # DBD creation tools +use DBI::DBD; # DBD creation tools # Some MakeMaker's forged some FileHandle methods @@ -49,11 +49,11 @@ my %opts = ( OBJECT => '$(O_FILES)', DEFINE => '', DIR => [], - clean => { FILES => 'xstmp.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def mk.pm DBD_ORA_OBJ.*' }, + clean => { FILES => 'xstmp.c Oracle.xsi dll.base dll.exp sqlnet.log libOracle.def mk.pm DBD_ORA_OBJ.*' }, dist => { - DIST_DEFAULT => 'clean distcheck disttest tardist', - PREOP => '$(MAKE) -f Makefile.old distdir', - COMPRESS => 'gzip -v9', SUFFIX => 'gz', + DIST_DEFAULT => 'clean distcheck disttest tardist', + PREOP => '$(MAKE) -f Makefile.old distdir', + COMPRESS => 'gzip -v9', SUFFIX => 'gz', }, META_MERGE => { configure_requires => { "DBI" => '1.623' }, @@ -85,7 +85,7 @@ $opts{LICENSE} = 'perl' if $eumm >= 6.3002; $opts{CCFLAGS} = "-P $Config{ccflags}" if $Config{cc} eq 'bcc32'; # force C++ $opts{LINKTYPE} = 'static' if $Config{dlsrc} =~ /dl_none/; -my(@MK, %MK, $MK_TEXT, %MK_expanding); # parsed macros from Oracle's makefiles +my(@MK, %MK, $MK_TEXT, %MK_expanding); # parsed macros from Oracle's makefiles my %mk_target_deps; my %mk_target_rules; @@ -174,32 +174,32 @@ and we force our emulation of OCILobWriteAppend. # Options (rarely needed) # to turn off an option prefix with 'no', ie 'perl Makefile.PL -nob' #$::opt_ic10 = 1; # Build for Oracle 10g instantclient -$::opt_b = 1; # try to use Oracle's own 'build' rule -$::opt_r = ''; # With -b above, use this names build rule (eg -r=build64) -$::opt_m = ''; # path to oracle.mk file to read -$::opt_h = ''; # path to oracle header files -$::opt_p = ''; # alter preference for oracle.mk -$::opt_n = ''; # Oracle .mk macro name to use for library list to link with -$::opt_c = 0; # don't encourage use of shared library -$::opt_l = 0; # try direct-link to libclntsh -$::opt_g = ''; # enable debugging (-g for compiler and linker) -$::opt_s = ''; # Find a symbol in oracle libs, Don't build a Makefile -$::opt_S = ''; # Find a symbol in oracle & system libs, Don't build a Makefile -$::opt_v = 0; # be more verbose -$::opt_d = 0; # much more verbose for debugging -$::opt_f = 0; # include text of oracle's .mk file within generated Makefile -$::opt_F = 0; # force - ignore errors -$::opt_W = 0; # just write a basic default Makefile (won't build) -$::opt_w = 0; # enable many gcc compiler warnings +$::opt_b = 1; # try to use Oracle's own 'build' rule +$::opt_r = ''; # With -b above, use this names build rule (eg -r=build64) +$::opt_m = ''; # path to oracle.mk file to read +$::opt_h = ''; # path to oracle header files +$::opt_p = ''; # alter preference for oracle.mk +$::opt_n = ''; # Oracle .mk macro name to use for library list to link with +$::opt_c = 0; # don't encourage use of shared library +$::opt_l = 0; # try direct-link to libclntsh +$::opt_g = ''; # enable debugging (-g for compiler and linker) +$::opt_s = ''; # Find a symbol in oracle libs, Don't build a Makefile +$::opt_S = ''; # Find a symbol in oracle & system libs, Don't build a Makefile +$::opt_v = 0; # be more verbose +$::opt_d = 0; # much more verbose for debugging +$::opt_f = 0; # include text of oracle's .mk file within generated Makefile +$::opt_F = 0; # force - ignore errors +$::opt_W = 0; # just write a basic default Makefile (won't build) +$::opt_w = 0; # enable many gcc compiler warnings $::opt_V = 0; # force assumption of specified Oracle version - # If == 8 then we don't use the new OCI_INIT code - # and we force our emulation of OCILobWriteAppend + # If == 8 then we don't use the new OCI_INIT code + # and we force our emulation of OCILobWriteAppend Getopt::Long::config( qw( no_ignore_case ) ); GetOptions(qw(b! r=s v! d! g! p! l! c! f! F! W! w! m=s h=s n=s s=s S=s V=s )) or die pod2usage( -verbose => 99, -sections => [ 'OPTIONS' ] ); -$::opt_g &&= '-g'; # convert to actual string +$::opt_g &&= '-g'; # convert to actual string $::opt_v = 1 if $::opt_d; $Verbose = 1 if $::opt_v; my $is_developer = (-d ".svn" && -f "MANIFEST.SKIP"); @@ -254,10 +254,10 @@ die qq{ The $ORACLE_ENV environment variable value ($OH) is not valid. See the appropriate troubleshooting guide for your OS for more information. ABORTED! } unless (-d $OH and $^O eq 'VMS') - or -d "$OH/sdk/." # Instant Client with SDK - or -d "$OH/lib/." # normal Oracle installation + or -d "$OH/sdk/." # Instant Client with SDK + or -d "$OH/lib/." # normal Oracle installation or glob("$OH/libclntsh.$so*") # pre-sdk instant client or rpm - or -e "$OH/oci.dll"; # Windows Instant Client + or -e "$OH/oci.dll"; # Windows Instant Client print "Installing on a $^O, Ver#$osvers\n"; print "Using Oracle in $OH\n"; @@ -276,8 +276,8 @@ symbol_search() if $::opt_s or $::opt_S; # --- How shall we link with Oracle? Let me count the ways... -my $mkfile; # primary .mk file to use -my @mkfiles; # $mkfile plus any files it 'includes' +my $mkfile; # primary .mk file to use +my @mkfiles; # $mkfile plus any files it 'includes' my $linkwith = ""; my $linkwith_msg = ""; my $need_ldlp_env; @@ -286,16 +286,16 @@ my $need_ldlp_env; my @libclntsh = glob("$OH/libclntsh.$so*"); if ($^O eq 'VMS') { - my $OCIINCLUDE = join " ", vmsify("$OH/rdbms/"), - vmsify("$OH/rdbms/public"), - vmsify("$OH/rdbms/demo/"), - vmsify("$OH/rdbms/demo/oci_demo/"), - vmsify("$OH/netconfig/demo/"); # eg nzt.h in 8.1.7 on VMS + my $OCIINCLUDE = join " ", vmsify("$OH/rdbms/"), + vmsify("$OH/rdbms/public"), + vmsify("$OH/rdbms/demo/"), + vmsify("$OH/rdbms/demo/oci_demo/"), + vmsify("$OH/netconfig/demo/"); # eg nzt.h in 8.1.7 on VMS $opts{INC} = "$OCIINCLUDE $dbi_arch_dir"; $opts{OBJECT} = 'oracle.obj dbdimp.obj oci7.obj oci8.obj' if $] < 5.005; unless ($ENV{PERL_ENV_TABLES}) { - print qq{ + print qq{ The logical PERL_ENV_TABLES is not set. This may mean that some of the UTF functionallity tests may fail, @@ -305,7 +305,7 @@ if ($^O eq 'VMS') { table, please set this logical: \$ DEFINE PERL_ENV_TABLES LNM\$PROCESS - \a\n}; + \a\n}; sleep 3; } } @@ -314,9 +314,9 @@ elsif (($^O eq 'MSWin32') or ($^O =~ /cygwin/i)) { my $OCIDIR = ""; find( sub { - print "Found $_ directory\n" if /^OCI\d*$/i; - $OCIDIR = $_ if /^OCI\d*$/i && $OCIDIR lt $_; - $File::Find::prune = 1 if -d $_ && $_ !~ /^\./; + print "Found $_ directory\n" if /^OCI\d*$/i; + $OCIDIR = $_ if /^OCI\d*$/i && $OCIDIR lt $_; + $File::Find::prune = 1 if -d $_ && $_ !~ /^\./; }, $OH ); $OCIDIR = 'sdk' if !$OCIDIR && -d "$OH/sdk"; # Instant Client SDK @@ -337,14 +337,14 @@ elsif (($^O eq 'MSWin32') or ($^O =~ /cygwin/i)) { my %OCILIB; my $oci_compiler_dir; my @oci_compiler_dirs = - map { -d "$OH/$OCIDIR/lib/$_" ? "$OH/$OCIDIR/lib/$_": () } - $Config{cc} eq 'bcc32' ? qw(BORLAND BC) : qw(MSVC); + map { -d "$OH/$OCIDIR/lib/$_" ? "$OH/$OCIDIR/lib/$_": () } + $Config{cc} eq 'bcc32' ? qw(BORLAND BC) : qw(MSVC); find( sub { - $File::Find::prune = 1 if -d $_ && $_ !~ /^\./; - return unless /^(OCI|ORA).*\.LIB$/i; - ($oci_compiler_dir = $File::Find::dir) =~ s:^.*/::; - print "Found $OCIDIR/lib/$oci_compiler_dir/$_ library\n"; - $OCILIB{uc($_)} = $_; + $File::Find::prune = 1 if -d $_ && $_ !~ /^\./; + return unless /^(OCI|ORA).*\.LIB$/i; + ($oci_compiler_dir = $File::Find::dir) =~ s:^.*/::; + print "Found $OCIDIR/lib/$oci_compiler_dir/$_ library\n"; + $OCILIB{uc($_)} = $_; }, @oci_compiler_dirs ); # sort the version numbered libs into assending order my @OCILIB = sort grep { /(OCI|ORA)\d\d+\./i } keys %OCILIB; @@ -358,8 +358,8 @@ elsif (($^O eq 'MSWin32') or ($^O =~ /cygwin/i)) { that you have your OCI installed in your oracle home ($OH) directory and that it has the following files (and probably more): - $OH\\$OCIDIR\\include\\oratypes.h - $OH\\$OCIDIR\\lib\\$oci_compiler_dir\\$OCILIB.lib + $OH\\$OCIDIR\\include\\oratypes.h + $OH\\$OCIDIR\\lib\\$oci_compiler_dir\\$OCILIB.lib Please install OCI or send comments back to dbi-users\@perl.org if you have an OCI directory other than $OCIDIR. @@ -369,8 +369,8 @@ elsif (($^O eq 'MSWin32') or ($^O =~ /cygwin/i)) { ppm install ftp://ftp.esoftmatic.com/outgoing/DBI/5.8.3/DBD-Oracle.ppd } unless (-e "$OH/$OCIDIR/include/oratypes.h" - && -e "$OH/$OCIDIR/lib/$oci_compiler_dir/$OCILIB.lib") - or $::opt_F; + && -e "$OH/$OCIDIR/lib/$oci_compiler_dir/$OCILIB.lib") + or $::opt_F; print "Using $OCIDIR/lib/$oci_compiler_dir/$OCILIB.lib\n"; $opts{LIBS} = [ "-L$OH/$OCIDIR/LIB/$oci_compiler_dir $OCILIB" ]; @@ -417,11 +417,11 @@ elsif (@libclntsh) { # the libclntsh.$so (without version suffix) may be missing # we need it to link to so try to create it eval { - print "You don't have a libclntsh.$so file, only @libclntsh\n"; - my $libclntsh_v = (grep { /\d$/ } sort @libclntsh)[0]; # tacky but sufficient - print "So I'm going to create a $OH/libclntsh.$so symlink to $libclntsh_v\n"; + print "You don't have a libclntsh.$so file, only @libclntsh\n"; + my $libclntsh_v = (grep { /\d$/ } sort @libclntsh)[0]; # tacky but sufficient + print "So I'm going to create a $OH/libclntsh.$so symlink to $libclntsh_v\n"; symlink($libclntsh_v, "$OH/libclntsh.$so") - or warn "Can't create symlink $OH/libclntsh.$so to $libclntsh_v: $!\n"; + or warn "Can't create symlink $OH/libclntsh.$so to $libclntsh_v: $!\n"; } unless -e "$OH/libclntsh.$so"; check_ldlibpthname($OH); @@ -447,12 +447,12 @@ elsif (defined $mkfile and $mkfile =~ /\bdemo_xe.mk$/) { # Oracle XE $MK{CCINCLUDES} = '-I$(ICINCHOME)'; # undo odd refinition in demo_xe.mk # From linux Oracle XE (10.2.0): - # ICINCHOME=$(ORACLE_HOME)/rdbms/public/ - # ICLIBHOME=$(ORACLE_HOME)/lib/ - # ICLIBPATH=-L$(ICLIBHOME) - # THREADLIBS=-lpthread [initially -lthread then redefined] - # CCLIB=$(ICLIBPATH) -lclntsh $(THREADLIBS) - # CCINCLUDES = -I$(ICINCHOME) [see above] + # ICINCHOME=$(ORACLE_HOME)/rdbms/public/ + # ICLIBHOME=$(ORACLE_HOME)/lib/ + # ICLIBPATH=-L$(ICLIBHOME) + # THREADLIBS=-lpthread [initially -lthread then redefined] + # CCLIB=$(ICLIBPATH) -lclntsh $(THREADLIBS) + # CCINCLUDES = -I$(ICINCHOME) [see above] # CCFLAGS=$(CCINCLUDES) -DLINUX -D_GNU_SOURCE -D_REENTRANT -g [initially without -DLINUX -D_GNU_SOURCE] my $cclib = expand_mkvars($MK{CCLIB}, 0, 1); my $ccflags = expand_mkvars($MK{CCFLAGS}, 0, 1); @@ -464,27 +464,27 @@ elsif (defined $mkfile and $mkfile =~ /\bdemo_xe.mk$/) { # Oracle XE check_ldlibpthname(); } -else { # --- trawl the guts of Oracle's make files looking the how it wants to link +else { # --- trawl the guts of Oracle's make files looking the how it wants to link #Lincoln: pick the right library path check_ldlibpthname(); my $libdir = ora_libdir(); my @ora_libs = <$OH/$libdir/lib*>; if (@ora_libs < 6) { # just a helpful hint - warn "\nYou don't seem to have many Oracle libraries installed. If the" - ."\nbuild fails you probably need to install more Oracle software.\n\n"; - sleep 6; + warn "\nYou don't seem to have many Oracle libraries installed. If the" + ."\nbuild fails you probably need to install more Oracle software.\n\n"; + sleep 6; } # can we give the shared library a helping hand? my @shared = grep { m:/lib(cl(ie)?ntsh|oracle).\w+$:o } @ora_libs; # show original value of ORA_CLIENT_LIB if defined ... print "\$ORA_CLIENT_LIB=$ENV{ORA_CLIENT_LIB}\n" - if defined $ENV{ORA_CLIENT_LIB}; + if defined $ENV{ORA_CLIENT_LIB}; # ... before we then set it how it probably should be set # XXX but we still need to write it into the generated Makefile. $ENV{ORA_CLIENT_LIB} = 'shared' - if !defined $ENV{ORA_CLIENT_LIB} - && ($opts{LINKTYPE}||'') ne 'static' && @shared && !$::opt_c; + if !defined $ENV{ORA_CLIENT_LIB} + && ($opts{LINKTYPE}||'') ne 'static' && @shared && !$::opt_c; my $linkvia = fetch_oci_macros($mkfile) if -f $mkfile; @@ -500,83 +500,83 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l my @build_rules = grep { $mk_target_rules{$_} } qw(build build64 build32); my $build_target = "build"; if (@build_rules && $::opt_b) { - print "\n"; + print "\n"; - $build_target = "build32" if $mk_target_rules{build32}; - $build_target = "build64" if $mk_target_rules{build64} && perl_is_64bit(); - $build_target = $::opt_r if $::opt_r; + $build_target = "build32" if $mk_target_rules{build32}; + $build_target = "build64" if $mk_target_rules{build64} && perl_is_64bit(); + $build_target = $::opt_r if $::opt_r; - print "Attempting to discover Oracle OCI $build_target rules\n"; + print "Attempting to discover Oracle OCI $build_target rules\n"; - # create dummy C file to keep 'make $mkfile' happy - my $DBD_ORA_OBJ = 'DBD_ORA_OBJ'; + # create dummy C file to keep 'make $mkfile' happy + my $DBD_ORA_OBJ = 'DBD_ORA_OBJ'; open DBD_ORA_C, ">$DBD_ORA_OBJ.c" - or die "Can't create temporary $DBD_ORA_OBJ.c file in current directory: $!\n"; + or die "Can't create temporary $DBD_ORA_OBJ.c file in current directory: $!\n"; print DBD_ORA_C "int main() { return 1; }\n"; close DBD_ORA_C; - sleep 2; # - system("make $DBD_ORA_OBJ.o CC='$Config{cc}'"); # make a valid .o file. - - my $make = "$Config{make} -f $mkfile $build_target" - ." ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh' CC=true" - ." OPTIMIZE= CCFLAGS=" - ." EXE=DBD_ORA_EXE OBJS=$DBD_ORA_OBJ.o"; - print "by executing: [$make]\n"; - my @cmds = `$make 2>&1`; - chomp @cmds; - print "returned:\n[".join("]\n[",@cmds)."]\n" if $::opt_v; - warn "WARNING: Oracle build rule discovery failed ($?)\n" if $?; - warn "Add path to $Config{make} command into your PATH environment variable.\n" - if $? && "@cmds" =~ /make.*not found/; # hint - - my @filtered_cmds; + sleep 2; # + system("make $DBD_ORA_OBJ.o CC='$Config{cc}'"); # make a valid .o file. + + my $make = "$Config{make} -f $mkfile $build_target" + . q/ ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh' CC=true/ + . q/ OPTIMIZE= CCFLAGS=/ + . qq/ EXE=DBD_ORA_EXE OBJS=$DBD_ORA_OBJ.o/; + print "by executing: [$make]\n"; + my @cmds = `$make 2>&1`; + chomp @cmds; + print "returned:\n[".join("]\n[",@cmds)."]\n" if $::opt_v; + warn "WARNING: Oracle build rule discovery failed ($?)\n" if $?; + warn "Add path to $Config{make} command into your PATH environment variable.\n" + if $? && "@cmds" =~ /make.*not found/; # hint + + my @filtered_cmds; while (my $line = shift @cmds) { - # join lines split with \'s - while ($line =~ s/\\$/ /) { $line .= shift @cmds; } - # remove any echo's as the following line should be the result of the echo - next if $line =~ /^\s*\S*echo\s+/; - next if $line =~ /^\s*\S*make\s+/; # remove recursive calls to make - next if $line =~ /^\s*\S*make(\[\d\])?:/; # remove message rom "make:" or "make[x]:" - - next if $line =~ /^\s*$/; # remove any blank lines - push @filtered_cmds, $line; - } - print "reduced to:\n[".join("]\n[",@filtered_cmds)."]\n" - if $::opt_v && "@filtered_cmds" ne "@cmds"; - @cmds = @filtered_cmds; - - my @prolog; push @prolog, shift @cmds while @cmds && $cmds[0] !~ /DBD_ORA_EXE/; - print "Oracle oci build prolog:\n \t[", join("]\n\t[", @prolog), "]\n" if @prolog; - print "Oracle oci build command:\n\t[", join("]\n\t[", @cmds ), "]\n"; - if (@cmds == 1 && (my $build = shift @cmds) =~ /DBD_ORA_EXE/) { - $build =~ s/\s*true\s+//; # remove dummy compiler - $build =~ s/$DBD_ORA_OBJ.o//; # remove dummy object file - $build =~ s/\S+\s+DBD_ORA_EXE//; # remove dummy exe file and preceding flag - $build =~ s/-o build\S*//; # remove -o target that confuses gcc at least on Sun - $linkwith = $build; - # delete problematic crt?.o on solaris - $linkwith = del_crtobj($linkwith, 1) if $^O eq 'solaris'; - } - else { - print "WARNING: Unable to interpret Oracle build commands from $mkfile.\a\n"; - print "(Will continue by using fallback approach.)\n"; - sleep 2; - $::opt_b = 0; - } - unlink "$DBD_ORA_OBJ.c", "$DBD_ORA_OBJ.o" - unless $^O eq 'darwin'; # why? - print "\n"; + # join lines split with \'s + while ($line =~ s/\\$/ /) { $line .= shift @cmds; } + # remove any echo's as the following line should be the result of the echo + next if $line =~ m/^\s*\S*echo\s+/; + next if $line =~ m/^\s*\S*make\s+/; # remove recursive calls to make + next if $line =~ m/^\s*\S*make(\[\d\])?:/; # remove message rom "make:" or "make[x]:" + + next if $line =~ m/^\s*$/; # remove any blank lines + push @filtered_cmds, $line; + } + print "reduced to:\n[".join("]\n[",@filtered_cmds)."]\n" + if $::opt_v && "@filtered_cmds" ne "@cmds"; + @cmds = @filtered_cmds; + + my @prolog; push @prolog, shift @cmds while @cmds && $cmds[0] !~ /DBD_ORA_EXE/; + print "Oracle oci build prolog:\n \t[", join("]\n\t[", @prolog), "]\n" if @prolog; + print "Oracle oci build command:\n\t[", join("]\n\t[", @cmds ), "]\n"; + if (@cmds == 1 && (my $build = shift @cmds) =~ /DBD_ORA_EXE/) { + $build =~ s/\s*true\s+//; # remove dummy compiler + $build =~ s/$DBD_ORA_OBJ.o//; # remove dummy object file + $build =~ s/\S+\s+DBD_ORA_EXE//; # remove dummy exe file and preceding flag + $build =~ s/-o build\S*//; # remove -o target that confuses gcc at least on Sun + $linkwith = $build; + # delete problematic crt?.o on solaris + $linkwith = del_crtobj($linkwith, 1) if $^O eq 'solaris'; + } + else { + print "WARNING: Unable to interpret Oracle build commands from $mkfile.\a\n"; + print "(Will continue by using fallback approach.)\n"; + sleep 2; + $::opt_b = 0; + } + unlink "$DBD_ORA_OBJ.c", "$DBD_ORA_OBJ.o" + unless $^O eq 'darwin'; # why? + print "\n"; } else { - print "WARNING: Oracle $mkfile doesn't define a 'build' rule.\n" if $::opt_b; - $::opt_b = 0; - print "\n"; - print "WARNING: I will now try to guess how to build and link DBD::Oracle for you.$BELL\n"; - print " This kind of guess work is very error prone and Oracle-version sensitive.\n"; - print " It is possible that it won't be supported in future versions of DBD::Oracle.\n"; - print " *PLEASE* notify dbi-users about exactly _why_ you had to build it this way.\n"; - print "\n"; - sleep 6; + print "WARNING: Oracle $mkfile doesn't define a 'build' rule.\n" if $::opt_b; + $::opt_b = 0; + print "\n"; + print "WARNING: I will now try to guess how to build and link DBD::Oracle for you.$BELL\n"; + print " This kind of guess work is very error prone and Oracle-version sensitive.\n"; + print " It is possible that it won't be supported in future versions of DBD::Oracle.\n"; + print " *PLEASE* notify dbi-users about exactly _why_ you had to build it this way.\n"; + print "\n"; + sleep 6; } $linkwith =~ s/-Y P,/-YP,/g if $Config{gccversion}; @@ -650,8 +650,8 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l # # Jay: Add Librarys where one gets Unresolved symbols # - if ( ( $osvers >= 11 and $client_version_full =~ /^8\.1\.6/ ) - or ( $osvers >= 11 and $OH =~ m,/8\.1\.6, ) ) { + if ( ( $osvers >= 11 and $client_version_full =~ m/^8\.1\.6/ ) + or ( $osvers >= 11 and $OH =~ m|/8\.1\.6| ) ) { my @extraLib = qw[libqsmashr.sl libclntsh.sl]; foreach my $extraLib (@extraLib) { if (-r "$OH/lib/$extraLib") { @@ -662,9 +662,9 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l } if ($osvers >= 11 and $linkwith =~ m/-l:libcl.a/) { - print "WARNING: stripping -l:libcl.a from liblist (conflict with ld looking for shared libs)\n"; - $linkwith =~ s/\s*-l:libcl.a\b//g; - } + print "WARNING: stripping -l:libcl.a from liblist (conflict with ld looking for shared libs)\n"; + $linkwith =~ s/\s*-l:libcl.a\b//g; + } #lincoln: this is bringing back everything we thought we removed... (like libcl.a) # I wonder if this should targetted less specifically than only HPUX 11 @@ -679,59 +679,59 @@ else { # --- trawl the guts of Oracle's make files looking the how it wants to l } my $ccf = join " ", map { $_ || '' } @Config{qw(ccflags ccldflags cccdlflags)}; - if ($Config{cc} =~ /gcc/i) { - print "WARNING: perl was not built with -fpic or -fPIC in compiler flags.\n", - " You may need to rebuild perl from sources.\n", - " See instructions in DBD::Oracle::Troubleshooting::Hpux\n" - unless $ccf =~ m/-fpic\b/i; + if ($Config{cc} =~ m/gcc/i) { + print "WARNING: perl was not built with -fpic or -fPIC in compiler flags.\n", + " You may need to rebuild perl from sources.\n", + " See instructions in DBD::Oracle::Troubleshooting::Hpux\n" + unless $ccf =~ m/-fpic\b/i; } else { print "WARNING: perl was not built with +z or +Z in compiler flags.\n", " You may need to rebuild perl from sources.\n", " See instructions in DBD::Oracle::Troubleshooting::Hpux\n" - unless $ccf =~ m/\+[zZ]/; + unless $ccf =~ m/\+[zZ]/; } } - if ($::opt_b) { # The simple approach - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g $linkwith" }; - $linkwith_msg = "OTHERLDFLAGS = $linkwith [from '$build_target' rule]"; + if ($::opt_b) { # The simple approach + $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g $linkwith" }; + $linkwith_msg = "OTHERLDFLAGS = $linkwith [from '$build_target' rule]"; } - else { # the not-so-simple approach! - # get a cut down $linkwith to pass to MakeMaker liblist - my $linkwith_s = expand_mkvars($linkwith, 1, 1); - - # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" - # to cater for lack of smarts in MakeMaker / Liblist - # which ignores /foo/bar.a entries! - my $lib_ext_re = "(a|$Config{dlext}|$Config{so})"; - $linkwith_s =~ s!(\S+)/lib(\w+)\.($lib_ext_re)\b!-L$1 -l$2!g; - - # Platform specific fix-ups: - # delete problematic crt?.o on solaris - $linkwith_s = del_crtobj($linkwith_s) if $^O eq 'solaris'; - $linkwith_s =~ s/-l:lib(\w+)\.sl\b/-l$1/g; # for hp-ux - # this kind of stuff should be in a ./hints/* file: - $linkwith_s .= " -lc" if $Config{osname} eq 'dynixptx' - or $Config{archname} =~ /-pc-sco3\.2v5/; - if ($^O eq 'solaris' and $linkwith_s =~ /-lthread/ - and $osvers >= 2.3 and $osvers <= 2.6 - ) { - print "WARNING: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; - print "Deleting -lthread from link list as a possible workround ($osvers).\n"; - $linkwith_s =~ s/\s*-lthread\b/ /g; - } - - # extract object files, keep for use later - my @linkwith_o; - push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; - # also extract AIX .exp files since they confuse MakeMaker - push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; - - $linkwith_msg = "@linkwith_o $linkwith_s [from $linkvia]"; - $opts{LIBS} = [ "-L$libhome $linkwith_s" ]; - $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o \$(COMPOBJS)" }; + else { # the not-so-simple approach! + # get a cut down $linkwith to pass to MakeMaker liblist + my $linkwith_s = expand_mkvars($linkwith, 1, 1); + + # convert "/full/path/libFOO.a" into "-L/full/path -lFOO" + # to cater for lack of smarts in MakeMaker / Liblist + # which ignores /foo/bar.a entries! + my $lib_ext_re = "(a|$Config{dlext}|$Config{so})"; + $linkwith_s =~ s!(\S+)/lib(\w+)\.($lib_ext_re)\b!-L$1 -l$2!g; + + # Platform specific fix-ups: + # delete problematic crt?.o on solaris + $linkwith_s = del_crtobj($linkwith_s) if $^O eq 'solaris'; + $linkwith_s =~ s/-l:lib(\w+)\.sl\b/-l$1/g; # for hp-ux + # this kind of stuff should be in a ./hints/* file: + $linkwith_s .= " -lc" if $Config{osname} eq 'dynixptx' + or $Config{archname} =~ /-pc-sco3\.2v5/; + if ($^O eq 'solaris' and $linkwith_s =~ /-lthread/ + and $osvers >= 2.3 and $osvers <= 2.6 + ) { + print "WARNING: Solaris 2.5 bug #1224467 may cause '_rmutex_unlock' error.\n"; + print "Deleting -lthread from link list as a possible workround ($osvers).\n"; + $linkwith_s =~ s/\s*-lthread\b/ /g; + } + + # extract object files, keep for use later + my @linkwith_o; + push @linkwith_o, $1 while $linkwith_s =~ s/(\S+\.[oa])\b//; + # also extract AIX .exp files since they confuse MakeMaker + push @linkwith_o, $1 while $linkwith_s =~ s/(-bI:\S+\.exp)\b//; + + $linkwith_msg = "@linkwith_o $linkwith_s [from $linkvia]"; + $opts{LIBS} = [ "-L$libhome $linkwith_s" ]; + $opts{dynamic_lib} = { OTHERLDFLAGS => "$::opt_g @linkwith_o \$(COMPOBJS)" }; } my $OCIINCLUDE = expand_mkvars($MK{INCLUDE} || '', 0, 0); @@ -749,7 +749,7 @@ if ($::opt_g && $^O eq "MSWin32" && $Config::Config{cc} eq "cl") { $opts{DEFINE} .= ' -Wall -Wno-comment' if $Config{gccversion}; -$opts{DEFINE} .= ' -Xa' if $Config{cc} eq 'clcc'; # CenterLine CC +$opts{DEFINE} .= ' -Xa' if $Config{cc} eq 'clcc'; # CenterLine CC @@ -762,8 +762,8 @@ $opts{DEFINE} .= ' -DUTF8_SUPPORT' if ($] >= 5.006); # Use OCIEnvNlsCreate if available for best unicode behaviour #$opts{DEFINE} .= ' -DNEW_OCI_INIT' if $client_version >= 9.2; $opts{DEFINE} .= ($^O ne 'VMS') - ? " -DORA_OCI_VERSION=\\\"$client_version_full\\\"" - : " -DORA_OCI_VERSION=\"$client_version_full\""; + ? " -DORA_OCI_VERSION=\\\"$client_version_full\\\"" + : " -DORA_OCI_VERSION=\"$client_version_full\""; # force additional special behavior for oci 8. For now, this means # emulating OciLobWriteAppend # use this if, for some reason the default handling for this function @@ -774,10 +774,10 @@ $opts{DEFINE} .= ($^O ne 'VMS') print "\nclient_version=$client_version\n\n"; $opts{DEFINE} .= " -DORA_OCI_102" if ($::opt_V && $client_version == 10.2) - or ( $client_version >= 10.2); + or ( $client_version >= 10.2); $opts{DEFINE} .= " -DORA_OCI_112" if ($::opt_V && $client_version == 11.2) - or ( $client_version >= 11.2); + or ( $client_version >= 11.2); print "\nDEFINE=$opts{DEFINE}\n\n"; # OCIStmntFetch2() is a feature of OCI 9.0.0 @@ -789,11 +789,11 @@ if ($is_developer){ # a reasonable guess $BELL = "" if ($ENV{LOGNAME}||'') eq 'timbo'; $::opt_g = '-g'; if ($Config{gccversion}) { - $opts{DEFINE} .= ' -Wall -Wcast-align -Wpointer-arith'; - $opts{DEFINE} .= ' -Wbad-function-cast -Wcast-qual'; - #$opts{DEFINE} .= ' -Wconversion'; # very noisy so remove to see what people say - $opts{DEFINE} .= ' -Wimplicit -Wimplicit-int -Wimplicit-function-declaration -Werror-implicit-function-declaration -Wimport -Winline -Wlong-long -Wmissing-braces -Wmissing-format-attribute -Wmissing-noreturn -Wmultichar -Wpacked -Wparentheses -Wpointer-arith -Wreturn-type -Wsequence-point -Wsign-compare -Wswitch -Wtrigraphs -Wundef -Wuninitialized -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wwrite-strings -Wbad-function-cast -Wmissing-declarations -Wnested-externs' - if $::opt_w; + $opts{DEFINE} .= ' -Wall -Wcast-align -Wpointer-arith'; + $opts{DEFINE} .= ' -Wbad-function-cast -Wcast-qual'; + #$opts{DEFINE} .= ' -Wconversion'; # very noisy so remove to see what people say + $opts{DEFINE} .= ' -Wimplicit -Wimplicit-int -Wimplicit-function-declaration -Werror-implicit-function-declaration -Wimport -Winline -Wlong-long -Wmissing-braces -Wmissing-format-attribute -Wmissing-noreturn -Wmultichar -Wpacked -Wparentheses -Wpointer-arith -Wreturn-type -Wsequence-point -Wsign-compare -Wswitch -Wtrigraphs -Wundef -Wuninitialized -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wwrite-strings -Wbad-function-cast -Wmissing-declarations -Wnested-externs' + if $::opt_w; } $opts{dynamic_lib}->{OTHERLDFLAGS} .= " $::opt_g"; } @@ -803,12 +803,12 @@ if ($is_developer){ # a reasonable guess # files, we sadly have to build static on HP-UX 9 :( if ($^O eq 'hpux') { if ($osvers < 10) { - print "WARNING: Forced to build static not dynamic on $^O $osvers.$BELL\n"; - $opts{LINKTYPE} = 'static'; + print "WARNING: Forced to build static not dynamic on $^O $osvers.$BELL\n"; + $opts{LINKTYPE} = 'static'; } else { - print "WARNING: If you have trouble, see DBD::Oracle::Troubleshooting::Hpux...\n" - ." you may have to build your own perl, or go hunting for libraries\n"; + print "WARNING: If you have trouble, see DBD::Oracle::Troubleshooting::Hpux...\n" + ." you may have to build your own perl, or go hunting for libraries\n"; } print "WARNING: If you have trouble, try perl Makefile.PL -l\n" unless $::opt_l; sleep 5; @@ -844,11 +844,11 @@ print "Compiler: @Config{qw(cc optimize ccflags)}\n"; print "Linker: ". (find_bin('ld')||"not found") ."\n" unless $^O eq 'VMS'; print "Sysliblist: ".read_sysliblist()."\n"; print "Oracle makefiles would have used these definitions but we override them:\n" - if $MK{CFLAGS} || $MK{LDFLAGS} || $MK{LDSTRING}; -print " CC: $MK{CC}\n" if $MK{CC}; -print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; + if $MK{CFLAGS} || $MK{LDFLAGS} || $MK{LDSTRING}; +print " CC: $MK{CC}\n" if $MK{CC}; +print " CFLAGS: $MK{CFLAGS}\n" if $MK{CFLAGS}; print " [".mkvar('CFLAGS',0,1,0). "]\n" if $MK{CFLAGS}; -print " CLIBS: $MK{CLIBS}\n" if $MK{CLIBS}; +print " CLIBS: $MK{CLIBS}\n" if $MK{CLIBS}; print " [".mkvar('CLIBS',0,1,0). "]\n" if $MK{CLIBS}; if ($mk_target_rules{build} && !$::opt_b) { my $rules = join "\n", '', @{ $mk_target_rules{build} }; @@ -962,17 +962,17 @@ sub find_oracle_home { my @oh = grep { (glob("$_/libclntsh.$so*"))[0] } @path; if (!@oh) { # failing that, try LD_LIBRARY_PATH or equiv - my (undef, undef, @ldlibpth) = ldlibpth_info(1); - print "using ldlib @ldlibpth\n" if $::opt_v; - @oh = grep { (glob("$_/libclntsh.$so*"))[0] } @ldlibpth; - # for instant client @oh may be actual ORACLE_HOME - # but for non-IC ORACLE_HOME may be dir above a /lib* - s:/lib\w*/?$:: for @oh; # remove possible trailing lib dir + my (undef, undef, @ldlibpth) = ldlibpth_info(1); + print "using ldlib @ldlibpth\n" if $::opt_v; + @oh = grep { (glob("$_/libclntsh.$so*"))[0] } @ldlibpth; + # for instant client @oh may be actual ORACLE_HOME + # but for non-IC ORACLE_HOME may be dir above a /lib* + s:/lib\w*/?$:: for @oh; # remove possible trailing lib dir } if (!@oh) { # else try the traditional kind of install - # this should work for non-instant-client installs ($OH/bin & $OH/lib*) - @oh = grep { (glob("$_/../lib*/libclntsh.$so*"))[0] } @path; - s:/[^/]/?$:: for @oh; + # this should work for non-instant-client installs ($OH/bin & $OH/lib*) + @oh = grep { (glob("$_/../lib*/libclntsh.$so*"))[0] } @path; + s:/[^/]/?$:: for @oh; } if (!@oh && lc($^O) eq 'linux') { # Try the standard Linux RPM location my @loh = glob("/usr/lib/oracle/*/*/lib/libclntsh.$so*"); @@ -993,37 +993,37 @@ sub win32_oracle_home { my $default_home; if ( ! $oh ) { if ( $Config{osname} eq "MSWin32") { - # Win32::TieRegistry is prefered, but it requires Win32API::Registry - # which is not available in mingw or cygwin - eval { - require Win32::TieRegistry; - $Win32::TieRegistry::Registry->Delimiter("/"); - $hkey = $Win32::TieRegistry::Registry->{"LMachine/SOFTWARE/Oracle/"} + # Win32::TieRegistry is prefered, but it requires Win32API::Registry + # which is not available in mingw or cygwin + eval { + require Win32::TieRegistry; + $Win32::TieRegistry::Registry->Delimiter("/"); + $hkey = $Win32::TieRegistry::Registry->{"LMachine/SOFTWARE/Oracle/"} and $req_ok = 1; - }; - eval { # older name of Win32::TieRegistry - require Tie::Registry; - $Tie::Registry::Registry->Delimiter("/"); - $hkey = $Tie::Registry::Registry->{"LMachine/SOFTWARE/Oracle/"} + }; + eval { # older name of Win32::TieRegistry + require Tie::Registry; + $Tie::Registry::Registry->Delimiter("/"); + $hkey = $Tie::Registry::Registry->{"LMachine/SOFTWARE/Oracle/"} and $req_ok = 1; - } unless $req_ok; - eval { - $default_home = $hkey->{ORACLE_HOME} || ''; - }; - eval { - $Val = sub { - # Return value - my ($hkey) = @_; - return $hkey->{ORACLE_HOME} || ''; - }; - $Keys = sub { - # Return list of sub-folder keys - my ($hkey) = @_; - # MAC: %$hkey and related method calls don't work under - # perl5db, so don't try single stepping through here - return map {m:/$: ? $hkey->{$_} : ()} keys %$hkey; - }; - } if $hkey; + } unless $req_ok; + eval { + $default_home = $hkey->{ORACLE_HOME} || ''; + }; + eval { + $Val = sub { + # Return value + my ($hkey) = @_; + return $hkey->{ORACLE_HOME} || ''; + }; + $Keys = sub { + # Return list of sub-folder keys + my ($hkey) = @_; + # MAC: %$hkey and related method calls don't work under + # perl5db, so don't try single stepping through here + return map {m:/$: ? $hkey->{$_} : ()} keys %$hkey; + }; + } if $hkey; } # Win32::Registry imports some symbols into main:: @@ -1031,29 +1031,29 @@ sub win32_oracle_home { # MAC: it is available under mingw and might be available under cygwin # If cygwin doesn't have it, move the rest inside the other if block eval { - require Win32::Registry; - $main::HKEY_LOCAL_MACHINE->Open('SOFTWARE\\ORACLE', $hkey); - my $dummy = $main::HKEY_LOCAL_MACHINE; # avoid single use complaint - eval { - my $hval; - $hkey->GetValues($hval); - $default_home = $hval->{ORACLE_HOME}[2] || ''; - }; - $Val = sub { - # Return value - my ($hkey) = @_; - my $hval; - $hkey->GetValues($hval); - return $hval->{ORACLE_HOME}[2] || ''; - }; - $Keys = sub { - # Return list of sub-folder keys - my ($hkey) = @_; - my @hkey; - $hkey->GetKeys(\@hkey); - @hkey = map { $hkey->Open($_, $_); $_ } @hkey; - return @hkey; - }; + require Win32::Registry; + $main::HKEY_LOCAL_MACHINE->Open('SOFTWARE\\ORACLE', $hkey); + my $dummy = $main::HKEY_LOCAL_MACHINE; # avoid single use complaint + eval { + my $hval; + $hkey->GetValues($hval); + $default_home = $hval->{ORACLE_HOME}[2] || ''; + }; + $Val = sub { + # Return value + my ($hkey) = @_; + my $hval; + $hkey->GetValues($hval); + return $hval->{ORACLE_HOME}[2] || ''; + }; + $Keys = sub { + # Return list of sub-folder keys + my ($hkey) = @_; + my @hkey; + $hkey->GetKeys(\@hkey); + @hkey = map { $hkey->Open($_, $_); $_ } @hkey; + return @hkey; + }; } unless $req_ok; # Workaround Win32::TieRegistry FETCH error during global destruction. @@ -1062,38 +1062,38 @@ sub win32_oracle_home { # Look for ORACLE_HOME in all ORACLE sub-folders, use last one found # before 8.1.5, there should be only one eval { - my ($oh1, %oh); - my @hkey = ($hkey); - # JLU: December 5, 2002: if the "default" home is set and has - # an OCI directory, then use it. - if ($default_home && -d $default_home && -d $default_home . "/oci") { - $oh = $default_home; - } else { - # use previous logic if default home doesn't have OCI - # directory - while (@hkey) { - $hkey = shift @hkey; - $oh = $oh1, $oh{$oh1} = 1 - if ($oh1 = &$Val($hkey)) && -d $oh1; - push @hkey, &$Keys($hkey); - } - if (1 < keys %oh) { - # JLU: 8/21/01 Oracle's default home is the first one in - # the path, at least with 8i - print "\n\007Multiple Oracle homes: ", join(" ", sort keys %oh), "\n\n"; - my @path = split(";", $ENV{PATH}); - my $dir; - foreach $dir (@path) { - # the path will be c:\path\to\home\bin, so remove \bin if it's there. - $dir =~ s/\\bin$//; - if (defined($oh{$dir})) { - print "$dir is first in the PATH, so we'll use that as Oracle's default home.\n\n"; - $oh = $dir; - last; - } - } - } - } + my ($oh1, %oh); + my @hkey = ($hkey); + # JLU: December 5, 2002: if the "default" home is set and has + # an OCI directory, then use it. + if ($default_home && -d $default_home && -d $default_home . "/oci") { + $oh = $default_home; + } else { + # use previous logic if default home doesn't have OCI + # directory + while (@hkey) { + $hkey = shift @hkey; + $oh = $oh1, $oh{$oh1} = 1 + if ($oh1 = &$Val($hkey)) && -d $oh1; + push @hkey, &$Keys($hkey); + } + if (1 < keys %oh) { + # JLU: 8/21/01 Oracle's default home is the first one in + # the path, at least with 8i + print "\n\007Multiple Oracle homes: ", join(" ", sort keys %oh), "\n\n"; + my @path = split(";", $ENV{PATH}); + my $dir; + foreach $dir (@path) { + # the path will be c:\path\to\home\bin, so remove \bin if it's there. + $dir =~ s/\\bin$//; + if (defined($oh{$dir})) { + print "$dir is first in the PATH, so we'll use that as Oracle's default home.\n\n"; + $oh = $dir; + last; + } + } + } + } } if defined $Keys; } @@ -1105,8 +1105,8 @@ sub win32_oracle_home { sub read_sysliblist { my $syslibs = (-f "$OH/lib/sysliblist") - ? read_file("$OH/lib/sysliblist") - : (-f "$OH/rdbms/lib/sysliblist") ? read_file("$OH/rdbms/lib/sysliblist") : ''; + ? read_file("$OH/lib/sysliblist") + : (-f "$OH/rdbms/lib/sysliblist") ? read_file("$OH/rdbms/lib/sysliblist") : ''; if ($^O eq "hpux") { $syslibs =~ s/-l:lib(\w+).(sl|a)\b/-l$1/g; $syslibs =~ s/\s*-ldld\b//g; @@ -1144,8 +1144,8 @@ sub del_crtobj { my @del; push @del, $1 while $str =~ s:([^\s=]*\bcrt[1in]\.o)\b::; if ($orig ne $str) { - print "Deleted @del from link args.\n" if $verbose; - print "del_crtobj: $orig\n : $str\n@del\n" if $::opt_v; + print "Deleted @del from link args.\n" if $verbose; + print "del_crtobj: $orig\n : $str\n@del\n" if $::opt_v; } return $str; } @@ -1154,19 +1154,19 @@ sub del_crtobj { sub find_mkfile { my @mk_oci32 = ( - 'rdbms/demo/demo_xe.mk', + 'rdbms/demo/demo_xe.mk', 'rdbms/demo/demo_rdbms32.mk', 'rdbms/demo/demo_rdbms.mk', 'rdbms/lib/ins_rdbms.mk', #Oracle 11 full client 'sdk/demo/demo.mk' #OIC .mk location ); my @mk_oci64 = ( - 'rdbms/demo/demo_xe.mk', - 'rdbms/lib/oracle.mk', - 'rdbms/demo/oracle.mk', - 'rdbms/demo/demo_rdbms.mk', - 'rdbms/demo/demo_rdbms64.mk', - 'rdbms/lib/ins_rdbms.mk', #Oracle 11 full client + 'rdbms/demo/demo_xe.mk', + 'rdbms/lib/oracle.mk', + 'rdbms/demo/oracle.mk', + 'rdbms/demo/demo_rdbms.mk', + 'rdbms/demo/demo_rdbms64.mk', + 'rdbms/lib/ins_rdbms.mk', #Oracle 11 full client 'sdk/demo/demo.mk' # git issue 20 - path on mac os ); my @mk_oci = perl_is_64bit() ? @mk_oci64 : @mk_oci32; @@ -1179,37 +1179,37 @@ sub find_mkfile { my @mkplaces = ($::opt_p) ? (@mk_oci) : (@mk_oci); if ($::opt_m) { - $::opt_m = cwd()."/$::opt_m" unless $::opt_m =~ m:^/:; - die "-m $::opt_m: not found" unless -f $::opt_m; - unshift @mkplaces, $::opt_m; + $::opt_m = cwd()."/$::opt_m" unless $::opt_m =~ m:^/:; + die "-m $::opt_m: not found" unless -f $::opt_m; + unshift @mkplaces, $::opt_m; } my $mkfile; - foreach my $place (@mkplaces) { - $place = "$OH/$place" - unless $place =~ m:^[/\.]:; # abs or relative path - next unless -f $place; - $mkfile ||= $place; # use first one found - print "Found $place\n"; + for my $place (@mkplaces) { + $place = "$OH/$place" + unless $place =~ m:^[/\.]:; # abs or relative path + next unless -f $place; + $mkfile ||= $place; # use first one found + print "Found $place\n"; } unless ($^O eq 'MSWin32' || $^O eq 'VMS' || ($mkfile && -f $mkfile) || $::opt_F) { - $::opt_l or return ($mkfile = undef); - die qq{ - Unable to locate an oracle.mk or other suitable *.mk - file in your Oracle installation. (I looked in - @mkplaces under $OH) - - The oracle.mk (or demo_rdbms.mk) file is part of the Oracle - RDBMS product. You need to build DBD::Oracle on a - system which has one of these Oracle components installed. - (Other *.mk files such as the env_*.mk files will not work.) - Alternatively you can use Oracle Instant Client. - - In the unlikely event that a suitable *.mk file is installed - somewhere non-standard you can specify where it is using the -m option: - perl Makefile.PL -m /path/to/your.mk - - See the appropriate troubleshooting guide for your OS for more information and some alternatives. - }; + $::opt_l or return ($mkfile = undef); + die qq{ + Unable to locate an oracle.mk or other suitable *.mk + file in your Oracle installation. (I looked in + @mkplaces under $OH) + + The oracle.mk (or demo_rdbms.mk) file is part of the Oracle + RDBMS product. You need to build DBD::Oracle on a + system which has one of these Oracle components installed. + (Other *.mk files such as the env_*.mk files will not work.) + Alternatively you can use Oracle Instant Client. + + In the unlikely event that a suitable *.mk file is installed + somewhere non-standard you can specify where it is using the -m option: + perl Makefile.PL -m /path/to/your.mk + + See the appropriate troubleshooting guide for your OS for more information and some alternatives. + }; } print "Using $mkfile\n"; @@ -1226,32 +1226,32 @@ sub fetch_oci_macros { # Don't include the following definitions in the generated # makefile (note that %MK stills gets these values). my @edit = qw( - SHELL CC CPP CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS - AR AS CHMOD ECHO EXE OBJS PERL OBJ_EXT LIB_EXT VERSION + SHELL CC CPP CFLAGS CCFLAGS OPTIMIZE ASFLAGS RCC LD LDFLAGS + AR AS CHMOD ECHO EXE OBJS PERL OBJ_EXT LIB_EXT VERSION ); my %edit; @edit{@edit} = ('$_ = ""') x @edit; $edit{ORA_NLS} = $edit{ORA_NLS33} = $edit{ORA_NLS32} = q{ - print "Deleting $_\n", - " because it is not already set in the environment\n", - " and it can cause ORA-01019 errors.\n"; - $_ = ''; + print "Deleting $_\n", + " because it is not already set in the environment\n", + " and it can cause ORA-01019 errors.\n"; + $_ = ''; } unless $ENV{ORA_NLS} || $ENV{ORA_NLS33} || $ENV{ORA_NLS32} - || 1; # Old problem? Let's try without it for a while + || 1; # Old problem? Let's try without it for a while $edit{COMPOBJS} = q{ - # Firstly a Solaris specific edit: - $_ = del_crtobj($_) if $^O eq 'solaris'; - - # Delete any object files in COMPOBJS that don't actually exist - my $of; - foreach $of (split(/=|\s+/)) { - next if !$of or $of eq "COMPOBJS"; - my $obj = expand_mkvars($of,0,0); - next if -e $obj; - print "Deleting $of from COMPOBJS because $obj doesn't exist.\n"; - s:\Q$of::; - } + # Firstly a Solaris specific edit: + $_ = del_crtobj($_) if $^O eq 'solaris'; + + # Delete any object files in COMPOBJS that don't actually exist + my $of; + foreach $of (split(/=|\s+/)) { + next if !$of or $of eq "COMPOBJS"; + my $obj = expand_mkvars($of,0,0); + next if -e $obj; + print "Deleting $of from COMPOBJS because $obj doesn't exist.\n"; + s:\Q$of::; + } }; # deal with (some subversions) of Oracle8.0.3's incompatible use of OBJ_EXT @@ -1265,117 +1265,117 @@ sub fetch_oci_macros { my $lastline = ''; my @lines = read_inc_file($file); for(1; $_ = shift(@lines); $lastline = $_){ - # Join split lines but retain backwack and newlines: - $_ .= shift @lines while(m/\\[\r\n]+$/); - chomp; - push @MK, '' if $_ eq '' and $lastline ne ''; # squeeze multiple blank lines - next unless $_; - - if ($incompat_ext) { - s/\.(\$\(OBJ_EXT\))/$1/g; - s/\.(\$\(LIB_EXT\))/$1/g; - } - # skip compiler options for undesirable compilers - m/^ifdef (\w+)/ and do { - if ($ignore_def{$1}) { - $_ = shift @lines until m/^endif/; - next; - } - }; + # Join split lines but retain backwack and newlines: + $_ .= shift @lines while(m/\\[\r\n]+$/); + chomp; + push @MK, '' if $_ eq '' and $lastline ne ''; # squeeze multiple blank lines + next unless $_; + + if ($incompat_ext) { + s/\.(\$\(OBJ_EXT\))/$1/g; + s/\.(\$\(LIB_EXT\))/$1/g; + } + # skip compiler options for undesirable compilers + m/^ifdef (\w+)/ and do { + if ($ignore_def{$1}) { + $_ = shift @lines until m/^endif/; + next; + } + }; if (m!^([-\w/+.\$()\s]+)\s*:+\s*([^=]*)!) { # skip targets my @tgts = split(/ /, $1); # multiple target names in Oracle9i's demo_rdbms.mk - for (@tgts) { $mk_target_deps{$_} = $2 || '' } - my @rules; + for (@tgts) { $mk_target_deps{$_} = $2 || '' } + my @rules; while (@lines && $lines[0] =~ m!^\t! && chomp $lines[0]) { my $tmp_line = shift @lines; - while($tmp_line =~ m!\\$!) { # continuations! + while($tmp_line =~ m!\\$!) { # continuations! $tmp_line =~ s/\s+\\$/ /; $tmp_line .= shift @lines; chomp($tmp_line); } - push @rules, $tmp_line; - #print "target @tgts => $mk_target_deps{$tgt} => @{$mk_target_rules{$tgt}}\n"; + push @rules, $tmp_line; + #print "target @tgts => $mk_target_deps{$tgt} => @{$mk_target_rules{$tgt}}\n"; } - for (@tgts) { push @{ $mk_target_rules{$_} ||= [] }, @rules } + for (@tgts) { push @{ $mk_target_rules{$_} ||= [] }, @rules } next; } - next if m!^\t!; # skip target build rules - next if m/^\s*\.SUFFIXES/; - - unless($MK{mkver}) { # still want to get version number - my $line = $_; $line =~ s/[\\\r\n]/ /g; - $MK{mkver} = $mkver = $1 - if $line =~ m/\$Header:.*?\.mk.+(\d+\.\d+)/; - } - - # We always store values into %MK before checking %edit - # %edit can edit this in addition to $_ if needed. - my $name; - if (m/^\s*(\w+)\s*(\+?)=\s*/) { - $name = $1; - my $append = $2; - my $value = $'; - $value =~ s/^\@`/`/; - if ($append) { - my $expanded = expand_mkvars($value, 0, 1); - print "Appending '$expanded' to $name\n" if $::opt_v; - $value = $MK{$name} ? "$MK{$name} $expanded" : $expanded; - } - elsif ($MK{$name} && $MK{$name} ne $value) { - print "$name macro redefined by Oracle\n from $MK{$name}\n to $value\n" - if $::opt_d; - } - $MK{$name} = $value; - $MK{$name} =~ s/^([^#]*)#.*/$1/; # remove comments - - if (exists $edit{$name}) { - my $pre = $_; - eval $edit{$name}; # execute code to edit $_ - print "Edit $name ($edit{$name}) failed: $@\n" if $@; - if ($_ ne $pre and $::opt_v) { - $_ ? print "Edited $name definition\n from: $pre\n to: $_\n" - : print "Deleted $name definition: $pre\n"; - } - } - } - - push(@MK, $_); + next if m!^\t!; # skip target build rules + next if m/^\s*\.SUFFIXES/; + + unless($MK{mkver}) { # still want to get version number + my $line = $_; $line =~ s/[\\\r\n]/ /g; + $MK{mkver} = $mkver = $1 + if $line =~ m/\$Header:.*?\.mk.+(\d+\.\d+)/; + } + + # We always store values into %MK before checking %edit + # %edit can edit this in addition to $_ if needed. + my $name; + if (m/^\s*(\w+)\s*(\+?)=\s*/) { + $name = $1; + my $append = $2; + my $value = $'; + $value =~ s/^\@`/`/; + if ($append) { + my $expanded = expand_mkvars($value, 0, 1); + print "Appending '$expanded' to $name\n" if $::opt_v; + $value = $MK{$name} ? "$MK{$name} $expanded" : $expanded; + } + elsif ($MK{$name} && $MK{$name} ne $value) { + print "$name macro redefined by Oracle\n from $MK{$name}\n to $value\n" + if $::opt_d; + } + $MK{$name} = $value; + $MK{$name} =~ s/^([^#]*)#.*/$1/; # remove comments + + if (exists $edit{$name}) { + my $pre = $_; + eval $edit{$name}; # execute code to edit $_ + print "Edit $name ($edit{$name}) failed: $@\n" if $@; + if ($_ ne $pre and $::opt_v) { + $_ ? print "Edited $name definition\n from: $pre\n to: $_\n" + : print "Deleted $name definition: $pre\n"; + } + } + } + + push(@MK, $_); } # --- now decide what to link with --- my $linkvia; if ($::opt_n) { - $linkvia = "\$($::opt_n)" if $MK{$::opt_n}; - warn "Can't use '$::opt_n': not defined by .mk files\n" - unless $linkvia; + $linkvia = "\$($::opt_n)" if $MK{$::opt_n}; + warn "Can't use '$::opt_n': not defined by .mk files\n" + unless $linkvia; } # modern Oracle .mk files define OCISTATICLIBS and OCISHAREDLIBS if (!$linkvia && ($MK{OCISHAREDLIBS} || $MK{OCISTATICLIBS})) { - $linkvia = ''; - if ($MK{OCISTATICLIBS} && - ( ($opts{LINKTYPE}||'') eq 'static' - || "@ARGV" =~ m/\bLINKTYPE=static\b/ - || $::opt_c) + $linkvia = ''; + if ($MK{OCISTATICLIBS} && + ( ($opts{LINKTYPE}||'') eq 'static' + || "@ARGV" =~ m/\bLINKTYPE=static\b/ + || $::opt_c) ) { - $linkvia .= '$(DEF_ON) ' if $MK{DEF_ON}; - $linkvia .= '$(SSCOREED) ' if $MK{SSCOREED}; - $linkvia .= '$(OCISTATICLIBS)'; - } - else { - $linkvia .= '$(SSDBED) ' if $MK{SSDBED}; - $linkvia .= '$(DEF_OPT) ' if $MK{DEF_OPT}; - if ($client_version_full =~ /^8\.0\./ and $^O eq 'dec_osf' and $osvers >= 4.0) { - $linkvia .= '$(SCOREPT) $(NAETAB) $(NAEDHS) $(LLIBRDBMS_CLT) $(LLIBMM) '; - $linkvia .= '$(NETLIBS) $(CORELIBS) $(LLIBCOMMON) $(LLIBEPC) '; - $need_ldlp_env = "LD_LIBRARY_PATH"; - } - $linkvia .= '$(OCISHAREDLIBS)'; - } + $linkvia .= '$(DEF_ON) ' if $MK{DEF_ON}; + $linkvia .= '$(SSCOREED) ' if $MK{SSCOREED}; + $linkvia .= '$(OCISTATICLIBS)'; + } + else { + $linkvia .= '$(SSDBED) ' if $MK{SSDBED}; + $linkvia .= '$(DEF_OPT) ' if $MK{DEF_OPT}; + if ($client_version_full =~ m/^8\.0\./ and $^O eq 'dec_osf' and $osvers >= 4.0) { + $linkvia .= '$(SCOREPT) $(NAETAB) $(NAEDHS) $(LLIBRDBMS_CLT) $(LLIBMM) '; + $linkvia .= '$(NETLIBS) $(CORELIBS) $(LLIBCOMMON) $(LLIBEPC) '; + $need_ldlp_env = "LD_LIBRARY_PATH"; + } + $linkvia .= '$(OCISHAREDLIBS)'; + } } $linkvia = '$(LIBCLNTSH)' if !$linkvia && $MK{LIBCLNTSH}; @@ -1384,29 +1384,29 @@ sub fetch_oci_macros { $linkvia = '$(OCILDLIBS)' if !$linkvia && $MK{OCILDLIBS}; # Now we get into strange land of twisty turny macros - if (!$linkvia && $MK{PROLDLIBS}) { # Oracle 7.3.x - # XXX tweak for threaded perl? - use PROLLSsharedthread - if ($MK{PROLDLIBS} =~ /thread/i && $MK{PROLLSshared}) { - $linkvia = '$(PROLLSshared)'; - } - else { - $linkvia = '$(PROLDLIBS)'; - } + if (!$linkvia && $MK{PROLDLIBS}) { # Oracle 7.3.x + # XXX tweak for threaded perl? - use PROLLSsharedthread + if ($MK{PROLDLIBS} =~ /thread/i && $MK{PROLLSshared}) { + $linkvia = '$(PROLLSshared)'; + } + else { + $linkvia = '$(PROLDLIBS)'; + } } elsif (!$linkvia && int($mkver) == 1) { - if ($MK{LLIBOCIC}) { - $linkvia = '$(LLIBOCIC) $(TTLIBS)'; - } else { - print "WARNING: Guessing what to link with.\n"; - $linkvia = '-locic $(TTLIBS)'; # XXX GUESS HACK - } + if ($MK{LLIBOCIC}) { + $linkvia = '$(LLIBOCIC) $(TTLIBS)'; + } else { + print "WARNING: Guessing what to link with.\n"; + $linkvia = '-locic $(TTLIBS)'; # XXX GUESS HACK + } } - elsif (!$linkvia && $MK{CCLIB}) { # Oracle XE - $linkvia = '$(CCLIB)'; + elsif (!$linkvia && $MK{CCLIB}) { # Oracle XE + $linkvia = '$(CCLIB)'; } unless ($linkvia){ - die "ERROR parsing $file: Unable to determine what to link with.\n" - ."Please send me copies of these files (one per mail message):\n@mkfiles\n"; + die "ERROR parsing $file: Unable to determine what to link with.\n" + ."Please send me copies of these files (one per mail message):\n@mkfiles\n"; } $MK_TEXT = join("\n", @MK); return $linkvia; @@ -1417,23 +1417,23 @@ sub read_inc_file { my $file = shift; my $fh; unless ($fh = new FileHandle "<$file") { - # Workaround more oracle bungling (Oracle 7.3.2/Solaris x86) - my $alt; ($alt = $file) =~ s/\.dk\.mk$/\.mk/; - $fh = new FileHandle "<$alt"; - die "Unable to read $file: $!" unless $fh; + # Workaround more oracle bungling (Oracle 7.3.2/Solaris x86) + my $alt; ($alt = $file) =~ s/\.dk\.mk$/\.mk/; + $fh = new FileHandle "<$alt"; + die "Unable to read $file: $!" unless $fh; } print "Reading $file\n"; my @lines; push(@mkfiles, $file); while(<$fh>) { - # soak up while looking for include directives - push(@lines, $_), next - unless /^\s*include\s+(.*?)\s*$/m; - my $inc_file = $1; - # deal with "include $(ORACLE_HOME)/..." - # (can't use expand_mkvars() here) - $inc_file =~ s/\$\((ORACLE_HOME|ORACLE_ROOT)\)/$ENV{$ORACLE_ENV}/og; - push(@lines, read_inc_file($inc_file)); + # soak up while looking for include directives + push(@lines, $_), next + unless /^\s*include\s+(.*?)\s*$/m; + my $inc_file = $1; + # deal with "include $(ORACLE_HOME)/..." + # (can't use expand_mkvars() here) + $inc_file =~ s/\$\((ORACLE_HOME|ORACLE_ROOT)\)/$ENV{$ORACLE_ENV}/og; + push(@lines, read_inc_file($inc_file)); } print "Read a total of ".@lines." lines from $file (including inclusions)\n" if $::opt_v; return @lines; @@ -1446,14 +1446,14 @@ sub expand_shellescape { my $cmd = $orig; my $debug = $::opt_d || $::opt_v; print "Evaluating `$orig`\n" - if $debug && !$expand_shellescape{$orig}; + if $debug && !$expand_shellescape{$orig}; # ensure we have no $(...) vars left - strip out undefined ones: $cmd =~ s/\$[({](\w+)[})]/mkvar("$1", 1, 0, $level+1)/ge; print " expanded `$cmd`\n" if $debug and $cmd ne $orig; my $result = `$cmd`; $result =~ s/\s+$/ /; # newlines etc to single space print " returned '$result'\n" - if $debug && !$expand_shellescape{$orig}; + if $debug && !$expand_shellescape{$orig}; $expand_shellescape{$orig} = $result; $result; } @@ -1461,22 +1461,22 @@ sub expand_shellescape { sub expand_mkvars { my ($string, $strip, $backtick, $level, $maxlevel) = @_; - return if(!defined $string); + return if(!defined $string); $level ||= 1; local($_) = $string; print "$level Expanding $_\n" if $::opt_d; # handle whizzo AIX make feature used by Oracle s/\$[({] (\w+) \? ([^(]*?) : ([^(]*?) [})]/ - my ($vname, $vT, $vF) = ($1,$2,$3); - $MK{$vname} = (mkvar($vname, 1, $backtick, $level+1)) ? $vT : $vF + my ($vname, $vT, $vF) = ($1,$2,$3); + $MK{$vname} = (mkvar($vname, 1, $backtick, $level+1)) ? $vT : $vF /xge; # can recurse s/\$[({] (\w+) [})]/ - mkvar("$1", $strip, $backtick, $level+1, $maxlevel) + mkvar("$1", $strip, $backtick, $level+1, $maxlevel) /xge; # can recurse s/`(.*?[^\\])`/expand_shellescape("$1", $level+1)/esg if $backtick; # can recurse - s/\s*\\\n\s*/ /g; # merge continuations - s/\s+/ /g; # shrink whitespace + s/\s*\\\n\s*/ /g; # merge continuations + s/\s+/ /g; # shrink whitespace print "$level Expanded $string\n to $_\n\n" if $::opt_d and $_ ne $string; $_; } @@ -1490,14 +1490,14 @@ sub mkvar { return $ENV{$ORACLE_ENV} if $var eq 'ORACLE_HOME'; my $val = $MK{$var}; if (!defined $val and exists $ENV{$var}) { - $val = $ENV{$var}; - print "Using value of $var from environment: $val\n" - unless $var eq 'LD_LIBRARY_PATH'; + $val = $ENV{$var}; + print "Using value of $var from environment: $val\n" + unless $var eq 'LD_LIBRARY_PATH'; } return $default unless defined $val; if ($MK_expanding{$var}) { - print "Definition of \$($var) includes \$($var).\n"; - return "\$($var)"; + print "Definition of \$($var) includes \$($var).\n"; + return "\$($var)"; } local($MK_expanding{$var}) = 1; return $val if $maxlevel && $level >= $maxlevel; @@ -1508,8 +1508,8 @@ sub mkvar { sub read_file { my $file = shift; unless (open(ROL, "<$file")) { - warn "WARNING: Unable to open $file: $!\n"; - return ""; + warn "WARNING: Unable to open $file: $!\n"; + return ""; } my $text = join "", ; $text =~ s/\n+/ /g; @@ -1539,7 +1539,7 @@ sub find_headers { # compensate for case where final .0 isn't in the install directory name (my $client_version_trim = $client_version_full) =~ s/\.0$//; - my @try = grep { -d $_ } ( # search the ORACLE_HOME we're using first + my @try = grep { -d $_ } ( # search the ORACLE_HOME we're using first # --- Traditional full-install locations "$OH/rdbms/public", # prefer public over others "$OH/rdbms", @@ -1551,9 +1551,9 @@ sub find_headers { map { ( $_, $_."64" ) } map { ( $_, "/usr$_" ) } map { "/include/oracle/$_/client" } - $client_version, - $client_version_trim, - $client_version_full, + $client_version, + $client_version_trim, + $client_version_full, #"/include/oracle/$client_version_full/client", # Instant Client for RedHat FC3 #"/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC3 @@ -1589,14 +1589,14 @@ sub find_headers { print "Found header files in @h_dir.\n" if @h_dir; if (!$h_file{'oratypes.h'} || !$h_file{'ocidfn.h'}) { - print "\n\n*********************************************************\n"; - print "I can't find the header files I need in your Oracle installation.\n"; - print "You probably need to install some more Oracle components.\n"; - print "For Instant Client that means the SDK package.\n"; - print "I'll keep going, but the compile will probably fail.\n"; - print "See the appropriate troubleshooting guide for your OS for more information.$BELL\n"; - print "*********************************************************\n\n"; - sleep 5; + print "\n\n*********************************************************\n"; + print "I can't find the header files I need in your Oracle installation.\n"; + print "You probably need to install some more Oracle components.\n"; + print "For Instant Client that means the SDK package.\n"; + print "I'll keep going, but the compile will probably fail.\n"; + print "See the appropriate troubleshooting guide for your OS for more information.$BELL\n"; + print "*********************************************************\n\n"; + sleep 5; } return @h_dir; } @@ -1622,92 +1622,90 @@ sub get_client_version { print "PATH=$ENV{PATH}\n" if $::opt_v; if (find_bin($sqlplus_exe)) { - local $ENV{SQLPATH} = ""; # avoid $SQLPATH/login.sql causing sqlplus to hang - # Try to use the _SQLPLUS_RELEASE predefined variable from sqlplus - # Documented in the SQL*Plus reference guide: - # http://download-west.oracle.com/docs/cd/B12037_01/server.101/b12170/ch13.htm#i2675128 - # Output is in the following format: - # DEFINE _SQLPLUS_RELEASE = "902000400" (CHAR) Representing 9.2.0.4.0 - # DEFINE _SQLPLUS_RELEASE = "1001000200" (CHAR) Representing 10.1.0.2.0 - open FH, ">define.sql" or warn "Can't create define.sql: $!"; - print FH "DEFINE _SQLPLUS_RELEASE\nQUIT\n"; - close FH; - my $sqlplus_release = `$sqlplus_exe -S /nolog \@define.sql 2>&1`; - if ($sqlplus_release =~ /(SP2-0750)|(SP2-0642)/) { - - - my $x = $ENV{ORACLE_HOME}; - delete $ENV{ORACLE_HOME}; - $sqlplus_release = `$sqlplus_exe -S /nolog \@define.sql 2>&1`; - $ENV{ORACLE_HOME} = $x; + local $ENV{SQLPATH} = ""; # avoid $SQLPATH/login.sql causing sqlplus to hang + # Try to use the _SQLPLUS_RELEASE predefined variable from sqlplus + # Documented in the SQL*Plus reference guide: + # http://download-west.oracle.com/docs/cd/B12037_01/server.101/b12170/ch13.htm#i2675128 + # Output is in the following format: + # DEFINE _SQLPLUS_RELEASE = "902000400" (CHAR) Representing 9.2.0.4.0 + # DEFINE _SQLPLUS_RELEASE = "1001000200" (CHAR) Representing 10.1.0.2.0 + open my $FH, '>', 'define.sql' or warn "Can't create define.sql: $!"; + print $FH "DEFINE _SQLPLUS_RELEASE\nQUIT\n"; + close $FH; + my $sqlplus_release = `$sqlplus_exe -S /nolog \@define.sql 2>&1`; + if ($sqlplus_release =~ m/(SP2-0750)|(SP2-0642)/) { + my $x = $ENV{ORACLE_HOME}; + delete $ENV{ORACLE_HOME}; + $sqlplus_release = `$sqlplus_exe -S /nolog \@define.sql 2>&1`; + $ENV{ORACLE_HOME} = $x; + } + unlink "define.sql"; + print $sqlplus_release; # the _SQLPLUS_RELEASE may not be on first line: + if ($sqlplus_release =~ /DEFINE _SQLPLUS_RELEASE = "(\d?\d)(\d\d)(\d\d)(\d\d)(\d\d)"/) { + $client_version_full = sprintf("%d.%d.%d.%d", $1, $2, $3, $4); + } + else { + my $ldlib_note = ($Config{ldlibpthname}) + ? "Specifically, your $Config{ldlibpthname} environment variable" + : "Many systems need an environment variable (such as LD_LIBRARY_PATH, DYLD_LIBRARY_PATH)"; + warn qq{ + If sqlplus failed due to a linker/symbol/relocation/library error or similar problem + then it's likely that you've not configured your environment correctly. + $ldlib_note + set to include the directory containing the Oracle libraries. + \a\n}; + sleep 5; } - unlink "define.sql"; - print $sqlplus_release; # the _SQLPLUS_RELEASE may not be on first line: - if ($sqlplus_release =~ /DEFINE _SQLPLUS_RELEASE = "(\d?\d)(\d\d)(\d\d)(\d\d)(\d\d)"/) { - $client_version_full = sprintf("%d.%d.%d.%d", $1, $2, $3, $4); - } - else { - my $ldlib_note = ($Config{ldlibpthname}) - ? "Specifically, your $Config{ldlibpthname} environment variable" - : "Many systems need an environment variable (such as LD_LIBRARY_PATH, DYLD_LIBRARY_PATH)"; - warn qq{ - If sqlplus failed due to a linker/symbol/relocation/library error or similar problem - then it's likely that you've not configured your environment correctly. - $ldlib_note - set to include the directory containing the Oracle libraries. - \a\n}; - sleep 5; - } } else { - warn "Can't find sqlplus. Pity, it would have helped.\n"; + warn "Can't find sqlplus. Pity, it would have helped.\n"; } if (!$client_version_full && $OH && open INST, "<$OH/install/unix.rgs") { - local $/ = undef; - =~ m/^(rdbms|sql\*plus)\s+([\d.]+)/m; - $client_version_full = $2 if $2; - close INST; + local $/ = undef; + =~ m/^(rdbms|sql\*plus)\s+([\d.]+)/m; + $client_version_full = $2 if $2; + close INST; } if (!$client_version_full && $OH && -x "$OH/orainst/inspdver" ) { - open INST, "$OH/orainst/inspdver |"; # client only install does not have this - my @inspdver = ; - close INST; - foreach (@inspdver) { - $client_version_full = $1 if m/^(\d+\.\d+\.\d+)\S*\s+.*RDBMS/; - next unless $::opt_v - or m/RDBMS/i or m/PL.SQL/i - or m/Precomp/i or m/Pro\*C/i; - print $_; - } + open my $INST, "$OH/orainst/inspdver |"; # client only install does not have this + my @inspdver = <$INST>; + close $INST; + foreach (@inspdver) { + $client_version_full = $1 if m/^(\d+\.\d+\.\d+)\S*\s+.*RDBMS/; + next unless $::opt_v + or m/RDBMS/i or m/PL.SQL/i + or m/Precomp/i or m/Pro\*C/i; + print $_; + } } if (!$client_version_full) { - print "I'm having trouble finding your Oracle version number... trying harder\n" - unless $force_version; - if ( $OH =~ m![^\d\.]((?:8|9|1\d)\.\d+\.\d+(\.\d+)?)! ) { #decode it from $OH if possible - $client_version_full = $1; - } - elsif ( "$OH/" =~ m!\D(8|9|10)(\d)(\d?)\D!) { # scary but handy - $client_version_full = join ".", $1, $2, ($3||'0'); - } - elsif ( "$OH/" =~ m!/10g!) { # scary but handy - $client_version_full = "10.0.0.0"; - } + print "I'm having trouble finding your Oracle version number... trying harder\n" + unless $force_version; + if ( $OH =~ m![^\d\.]((?:8|9|1\d)\.\d+\.\d+(\.\d+)?)! ) { #decode it from $OH if possible + $client_version_full = $1; + } + elsif ( "$OH/" =~ m!\D(8|9|10)(\d)(\d?)\D!) { # scary but handy + $client_version_full = join ".", $1, $2, ($3||'0'); + } + elsif ( "$OH/" =~ m!/10g!) { # scary but handy + $client_version_full = "10.0.0.0"; + } elsif ( "$OH/" =~ m!/usr/lib/oracle/(\d+\.\d)/!) { # Linux RPM $client_version_full = "$1.0.0"; } } if ($force_version && $force_version ne $client_version_full) { - print "Forcing Oracle version to be treated as $force_version\n"; - $client_version_full = $force_version; + print "Forcing Oracle version to be treated as $force_version\n"; + $client_version_full = $force_version; } if ($client_version_full && $client_version_full !~ m/^(7|8|9|1\d)\.\d+/ ) { - print "Oracle version seems to be $client_version_full but that looks wrong so I'll ignore it.\n"; - $client_version_full = ""; + print "Oracle version seems to be $client_version_full but that looks wrong so I'll ignore it.\n"; + $client_version_full = ""; } if (!$client_version_full) { @@ -1740,16 +1738,16 @@ sub symbol_search { $::opt_s ||= $::opt_S; print "Searching for symbol '$::opt_s' in $OH ...\n"; my $dlext = $Config{dlext}; - system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; - do echo " searching oracle \$i ..."; PATH=/usr/ccs/bin:\$PATH nm \$i | grep $::opt_s; done + system(qq{ cd $OH; for i in lib/*.[ao] lib/*.$dlext */lib/*.[ao]; + do echo " searching oracle \$i ..."; PATH=/usr/ccs/bin:\$PATH nm \$i | grep $::opt_s; done }); if ($::opt_S) { - my @libpth = split ' ', $Config{libpth}; - print "Searching for symbol '$::opt_s' in @libpth ...\n"; - @libpth = map { ("$_/lib*.$dlext", "$_/lib*.a") } @libpth; - system(qq{ cd $OH; for i in @libpth; - do echo " searching \$i ..."; PATH=/usr/ccs/bin:\$PATH nm \$i | grep $::opt_s; done - }); + my @libpth = split ' ', $Config{libpth}; + print "Searching for symbol '$::opt_s' in @libpth ...\n"; + @libpth = map { ("$_/lib*.$dlext", "$_/lib*.a") } @libpth; + system(qq{ cd $OH; for i in @libpth; + do echo " searching \$i ..."; PATH=/usr/ccs/bin:\$PATH nm \$i | grep $::opt_s; done + }); } print "Search done.\n"; print "(Please only include the 'interesting' parts when mailing.)\n"; @@ -1774,75 +1772,75 @@ sub symbol_search { sub post_initialize { - my $self = shift; - - print "\nNote: \$ORACLE_HOME/lib must be added to your $need_ldlp_env environment variable\n", - "before running \"make test\" and whenever DBD::Oracle is used.\n\n" - if $need_ldlp_env && ($ENV{$need_ldlp_env}||'') !~ m:\Q$OH/lib\b:; - - eval { # This chunk is for Oracle::OCI - require Data::Dumper; - print main::MK_PM Data::Dumper->Purity(1)->Terse(0)->Indent(1)->Useqq(1) - ->Dump([\%opts, $self], [qw(dbd_oracle_mm_opts dbd_oracle_mm_self)]); - }; - if ($@) { - warn "Can't dump config to mk.pm so you won't be able to build Oracle::OCI later if you wanted to: $@\n"; - print main::MK_PM qq{die "You need to reinstall DBD::Oracle after installing Data::Dumper\n"; }; - } - close main::MK_PM or die "Error closing mk.pm: $!\n"; - - foreach (qw(mk.pm Oracle.h dbdimp.h ocitrace.h)) { - $self->{PM}->{$_} = '$(INST_ARCHAUTODIR)/'.$_; - } - - # Add $linkwith to EXTRALIBS for those doing static linking - $self->{EXTRALIBS} .= " -L\$(LIBHOME)"; - $self->{EXTRALIBS} .= " $linkwith" if $linkwith; - - ''; + my $self = shift; + + print "\nNote: \$ORACLE_HOME/lib must be added to your $need_ldlp_env environment variable\n", + "before running \"make test\" and whenever DBD::Oracle is used.\n\n" + if $need_ldlp_env && ($ENV{$need_ldlp_env}||'') !~ m:\Q$OH/lib\b:; + + eval { # This chunk is for Oracle::OCI + require Data::Dumper; + print main::MK_PM Data::Dumper->Purity(1)->Terse(0)->Indent(1)->Useqq(1) + ->Dump([\%opts, $self], [qw(dbd_oracle_mm_opts dbd_oracle_mm_self)]); + }; + if ($@) { + warn "Can't dump config to mk.pm so you won't be able to build Oracle::OCI later if you wanted to: $@\n"; + print main::MK_PM qq{die "You need to reinstall DBD::Oracle after installing Data::Dumper\n"; }; + } + close main::MK_PM or die "Error closing mk.pm: $!\n"; + + foreach (qw(mk.pm Oracle.h dbdimp.h ocitrace.h)) { + $self->{PM}->{$_} = '$(INST_ARCHAUTODIR)/'.$_; + } + + # Add $linkwith to EXTRALIBS for those doing static linking + $self->{EXTRALIBS} .= " -L\$(LIBHOME)"; + $self->{EXTRALIBS} .= " $linkwith" if $linkwith; + + ''; } sub postamble { - return main::dbd_postamble(@_); + return main::dbd_postamble(@_); } sub const_loadlibs { - my $self = shift; + my $self = shift; - # ExtUtils::MM_Unix v1.50 (invoked by ExtUtils::MakeMaker) - # requires that $self->{LD_RUN_PATH} be defined and not be - # an empty string for Makefile to specify its use during the - # build. This is required by both SUPER::const_loadlibs - # and SUPER::dynamic_lib. hence it is best if we define - # or modify $self->{LD_RUN_PATH} here *before* calling - # SUPER::const_loadlibs. + # ExtUtils::MM_Unix v1.50 (invoked by ExtUtils::MakeMaker) + # requires that $self->{LD_RUN_PATH} be defined and not be + # an empty string for Makefile to specify its use during the + # build. This is required by both SUPER::const_loadlibs + # and SUPER::dynamic_lib. hence it is best if we define + # or modify $self->{LD_RUN_PATH} here *before* calling + # SUPER::const_loadlibs. - # edit LD_RUN_PATH ... - my ($ldrp) = $self->{LD_RUN_PATH}; - # remove redundant /lib or /usr/lib as it can cause problems - $ldrp =~ s!:(/usr)?/lib$!! if $ldrp; + # edit LD_RUN_PATH ... + my ($ldrp) = $self->{LD_RUN_PATH}; + # remove redundant /lib or /usr/lib as it can cause problems + $ldrp =~ s!:(/usr)?/lib$!! if $ldrp; # if it's empty then set it manually #Lincoln: if pick the right library path my $libdir = main::ora_libdir(); $ldrp ||= "$OH/$libdir:$OH/rdbms/$libdir"; - $self->{LD_RUN_PATH} = $ldrp; + $self->{LD_RUN_PATH} = $ldrp; - local($_) = $self->SUPER::const_loadlibs(@_); + local($_) = $self->SUPER::const_loadlibs(@_); - print "Ignoring LD_RUN_PATH='$ENV{LD_RUN_PATH}' in environment\n" if $ENV{LD_RUN_PATH}; - print "LD_RUN_PATH=$ldrp\n"; - return $_; + print "Ignoring LD_RUN_PATH='$ENV{LD_RUN_PATH}' in environment\n" if $ENV{LD_RUN_PATH}; + print "LD_RUN_PATH=$ldrp\n"; + return $_; } sub post_constants { - my $self = shift; - return '' unless $::opt_f; - # Oracle Definitions, based on $(ORACLE_HOME)/proc/lib/proc.mk - ' + my $self = shift; + return '' unless $::opt_f; + # Oracle Definitions, based on $(ORACLE_HOME)/proc/lib/proc.mk + ' ################################################################### # ORACLE_HOME = '.$OH.' @@ -1859,96 +1857,96 @@ ORACLE_HOME = '.$OH.' sub const_cccmd { - my ($self) = shift; - print "Using DBD::Oracle $self->{VERSION}.\n"; - - local($_) = $self->SUPER::const_cccmd(@_); - # If perl Makefile.PL *-g* then switch on debugging - if ($::opt_g) { - if ($^O eq "MSWin32" and $Config::Config{cc} eq 'cl') { - s/\s-/ -Zi -/; - s/-O1//; - } else { - s/\s-O\d?\b//; # delete optimise option - s/\s-/ -g -/; # add -g option - } - } - # are we using the non-bundled hpux compiler? - if ($^O eq "hpux" and $Config::Config{ccflags} =~ /-Aa\b/) { - print "Changing -Aa to -Ae for HP-UX in ccmd.\n" - if s/-Aa\b/-Ae/g; # allow "long long" in oratypes.h - } - - $_; + my ($self) = shift; + print "Using DBD::Oracle $self->{VERSION}.\n"; + + local($_) = $self->SUPER::const_cccmd(@_); + # If perl Makefile.PL *-g* then switch on debugging + if ($::opt_g) { + if ($^O eq "MSWin32" and $Config::Config{cc} eq 'cl') { + s/\s-/ -Zi -/; + s/-O1//; + } else { + s/\s-O\d?\b//; # delete optimise option + s/\s-/ -g -/; # add -g option + } + } + # are we using the non-bundled hpux compiler? + if ($^O eq "hpux" and $Config::Config{ccflags} =~ /-Aa\b/) { + print "Changing -Aa to -Ae for HP-UX in ccmd.\n" + if s/-Aa\b/-Ae/g; # allow "long long" in oratypes.h + } + + $_; } sub cflags { - my ($self) = shift; - local($_) = $self->SUPER::cflags(@_); - # If perl Makefile.PL *-g* then switch on debugging - if ($::opt_g) { - if ($^O eq "MSWin32" and $Config::Config{cc} eq 'cl') { - s/\s-/ -Zi -/; - s/-O1//; - - } else { - s/\s-O\d?\b//; # delete optimise option - s/\s-/ -g -/; # add -g option - } - } - # are we using the non-bundled hpux compiler? - if ($^O eq "hpux" and $Config::Config{ccflags} =~ /-Aa\b/) { - print "Changing -Aa to -Ae for HP-UX in cflags.\n" - if s/-Aa\b/-Ae/g; # allow "long long" in oratypes.h - } - $_; + my ($self) = shift; + local($_) = $self->SUPER::cflags(@_); + # If perl Makefile.PL *-g* then switch on debugging + if ($::opt_g) { + if ($^O eq "MSWin32" and $Config::Config{cc} eq 'cl') { + s/\s-/ -Zi -/; + s/-O1//; + + } else { + s/\s-O\d?\b//; # delete optimise option + s/\s-/ -g -/; # add -g option + } + } + # are we using the non-bundled hpux compiler? + if ($^O eq "hpux" and $Config::Config{ccflags} =~ /-Aa\b/) { + print "Changing -Aa to -Ae for HP-UX in cflags.\n" + if s/-Aa\b/-Ae/g; # allow "long long" in oratypes.h + } + $_; } sub dynamic_lib { - my($self) = shift; - - unless ($^O eq 'VMS') { - my $m = $self->SUPER::dynamic_lib(@_); - if ($^O eq 'darwin') { - $m = "NMEDIT = nmedit\n" . $m . - "\t\$(NMEDIT) -R ./hints/macos_bundle.syms \$(INST_DYNAMIC) || true\n"; - } - elsif (($^O eq 'hpux') and ($osvers <11)) { - $m =~ s/LD_RUN_PATH=(\S+)\s+(\S+)/$2 -Wl,+b $1/; - - } - return ($m); - } - - # special code for VMS only - my(%attribs) = @_; - return '' unless $self->needs_linking(); #might be because of a subdir - return '' unless $self->has_link_code(); - - my $OtherText; - my($otherldflags) = $attribs{OTHERLDFLAGS} || ""; - my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || ""; - my @m; - push @m, "OTHERLDFLAGS = $otherldflags\n"; - push @m, "INST_DYNAMIC_DEP = $inst_dynamic_dep\n"; + my($self) = shift; + + unless ($^O eq 'VMS') { + my $m = $self->SUPER::dynamic_lib(@_); + if ($^O eq 'darwin') { + $m = "NMEDIT = nmedit\n" . $m . + "\t\$(NMEDIT) -R ./hints/macos_bundle.syms \$(INST_DYNAMIC) || true\n"; + } + elsif (($^O eq 'hpux') and ($osvers <11)) { + $m =~ s/LD_RUN_PATH=(\S+)\s+(\S+)/$2 -Wl,+b $1/; + + } + return ($m); + } + + # special code for VMS only + my(%attribs) = @_; + return '' unless $self->needs_linking(); #might be because of a subdir + return '' unless $self->has_link_code(); + + my $OtherText; + my($otherldflags) = $attribs{OTHERLDFLAGS} || ""; + my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || ""; + my @m; + push @m, "OTHERLDFLAGS = $otherldflags\n"; + push @m, "INST_DYNAMIC_DEP = $inst_dynamic_dep\n"; if ($] < 5.00450) { - push @m, ' + push @m, ' $(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt rtls.opt $(INST_ARCHAUTODIR).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) - $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) - $(NOECHO) If F$TrnLNm("PerlShr").eqs."" Then Define/NoLog/User PerlShr Sys$Share:PerlShr.',$Config::Config{'dlext'},' - Lnproc $(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,rtls.opt/Option,$(PERL_INC)perlshr_attr.opt/Option i + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) If F$TrnLNm("PerlShr").eqs."" Then Define/NoLog/User PerlShr Sys$Share:PerlShr.',$Config::Config{'dlext'},' + Lnproc $(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,rtls.opt/Option,$(PERL_INC)perlshr_attr.opt/Option i '; } else { - push @m, ' + push @m, ' $(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt $(INST_ARCHAUTODIR).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) - $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) - $(NOECHO) If F$TrnLNm("PerlShr").eqs."" Then Define/NoLog/User PerlShr Sys$Share:PerlShr.',$Config::Config{'dlext'},' - Lnproc $(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,$(PERL_INC)perlshr_attr.opt/Option i + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) If F$TrnLNm("PerlShr").eqs."" Then Define/NoLog/User PerlShr Sys$Share:PerlShr.',$Config::Config{'dlext'},' + Lnproc $(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,$(PERL_INC)perlshr_attr.opt/Option i '; } - push @m, $self->dir_target('$(INST_ARCHAUTODIR)'); - join('',@m); + push @m, $self->dir_target('$(INST_ARCHAUTODIR)'); + join('',@m); } } @@ -2014,18 +2012,17 @@ sub check_security { # SUID and SGID, and warn if either is set my @files = map { ($_,$_.'0') } qw( - oratclsh lsnrctl oemevent onrsd osslogin tnslsnr - tnsping trcasst trcroute cmctl cmadmin cmgw names namesctl otrccref - otrcfmt otrcrep otrccol + oratclsh lsnrctl oemevent onrsd osslogin tnslsnr + tnsping trcasst trcroute cmctl cmadmin cmgw names namesctl otrccref + otrcfmt otrcrep otrccol ); my @bad; - foreach (@files) { - my $file = "$ENV{ORACLE_HOME}/bin/$_"; - my ($mode) = (stat($file))[2]; - next unless defined $mode; - push @bad, $file if ($mode & 04000 and $mode & 00111) - or ($mode & 02000 and $mode & 00111); + for my $file (map { "$ENV{ORACLE_HOME}/bin/$_" } @files) { + my ($mode) = (stat($file))[2]; + next unless defined $mode; + push @bad, $file if ($mode & 04000 and $mode & 00111) + or ($mode & 02000 and $mode & 00111); } return unless @bad; @@ -2049,7 +2046,7 @@ sub check_macos_symbol_table { return if /^\s+U _(dlsym|dlclose)/; } - warn <<"END_WARNING"; + warn <<"END_WARNING"; WARNING: symbol table may need modification in Oracle library: $oracle_lib If the build fails in the linking stage, manual modification is From 026fdabb23200832cf53546ae0401f8de0fd1fb2 Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Thu, 17 Sep 2020 13:45:18 -0500 Subject: [PATCH 586/637] Run nonassigned pl/sql tests based off versions known to have the issue. GH#70. --- t/25plsql.t | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/t/25plsql.t b/t/25plsql.t index c8cc9df4..58ea3e32 100644 --- a/t/25plsql.t +++ b/t/25plsql.t @@ -30,7 +30,7 @@ if ($dbh) { plan skip_all => 'Oracle server either does not support pl/sql or it is not properly installed'; } - plan tests => 82; + plan tests => 86; } else { plan skip_all => "Unable to connect to Oracle \n"; @@ -325,13 +325,47 @@ if (1) { is( "@r", "@s2", 'ref = sql' ); } -# test bind_param_inout of param that's not assigned to in executed statement -# See http://www.mail-archive.com/dbi-users@perl.org/msg18835.html +SKIP: { + # test bind_param_inout of param that's not assigned to in executed statement + # Github Issue #70 + # Also see http://www.mail-archive.com/dbi-users@perl.org/msg18835.html + + # Known bad OCI versions + my @bad_oci_vers = (9.2,18.3,18.5,19.6); + + skip 'Client version is known to have issue', 4 + if grep { $_ == DBD::Oracle::ORA_OCI() } @bad_oci_vers; + + my $sth = $dbh->prepare( + q( + BEGIN + -- :p1 := :p1 ; + -- :p2 := :p2 ; + IF :p2 != :p3 THEN + :p1 := 'AAA' ; + :p2 := 'Z' ; + END IF ; + END ;) + ); + + my ( $p1, $p2, $p3 ) = ( 'Hello', 'Y', 'Y' ); + $sth->bind_param_inout( ':p1', \$p1, 30 ); + $sth->bind_param_inout( ':p2', \$p2, 1 ); + $sth->bind_param_inout( ':p3', \$p3, 1 ); + note("Before p1=[$p1] p2=[$p2] p3=[$p3]\n"); + ok( $sth->execute, 'test bind_param_inout for non assigned' ); + is( $p1, 'Hello', 'p1 ok' ); + is( $p2, 'Y', 'p2 ok' ); + is( $p3, 'Y', 'p3 ok' ); + note("After p1=[$p1] p2=[$p2] p3=[$p3]\n"); +} + +# test bind_paraminout the correct way (avoids the above issue if present) my $sth = $dbh->prepare( q( BEGIN - -- :p1 := :p1 ; - -- :p2 := :p2 ; + :p1 := :p1 ; + :p2 := :p2 ; IF :p2 != :p3 THEN :p1 := 'AAA' ; :p2 := 'Z' ; @@ -345,7 +379,7 @@ END ;) $sth->bind_param_inout( ':p2', \$p2, 1 ); $sth->bind_param_inout( ':p3', \$p3, 1 ); note("Before p1=[$p1] p2=[$p2] p3=[$p3]\n"); - ok( $sth->execute, 'test bind_param_inout for non assigned' ); + ok( $sth->execute, 'test bind_param_inout for properly assigned' ); is( $p1, 'Hello', 'p1 ok' ); is( $p2, 'Y', 'p2 ok' ); is( $p3, 'Y', 'p3 ok' ); From 406b546d9e31d10f0638dcb27d27d07c770f5535 Mon Sep 17 00:00:00 2001 From: "H.Merijn Brand - Tux" Date: Mon, 14 Dec 2020 11:51:18 +0100 Subject: [PATCH 587/637] Oracle Instant Client 21 has been released --- Makefile.PL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.PL b/Makefile.PL index bd581321..0aa991a5 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1702,7 +1702,7 @@ sub get_client_version { $client_version_full = $force_version; } - if ($client_version_full && $client_version_full !~ m/^(7|8|9|1\d)\.\d+/ + if ($client_version_full && $client_version_full !~ m/^([789]|[12][0-9])\.[0-9]+/ ) { print "Oracle version seems to be $client_version_full but that looks wrong so I'll ignore it.\n"; $client_version_full = ""; From 7b8bf9a517f9190c0913c7a84368d92db7abd997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20H=C3=A6gland?= Date: Wed, 14 Apr 2021 00:20:26 +0200 Subject: [PATCH 588/637] Add rpath to ORACLE_HOME to DBD/Oracle/Oracle.bundle Fixes issue #128 by adding rpath to ORACLE_HOME to DBD/Oracle/Oracle.bundle. --- Makefile.PL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.PL b/Makefile.PL index 0aa991a5..0331c16e 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -433,7 +433,7 @@ elsif (@libclntsh) { my $lib = "clntsh"; $linkwith_msg = "-l$lib."; - $opts{LIBS} = [ "-L$OH -l$lib $syslibs" ]; + $opts{LIBS} = [ "-L$OH -Wl,-rpath,$OH -l$lib $syslibs" ]; my $inc = join " ", map { "-I$_" } find_headers(); $opts{INC} = "$inc -I$dbi_arch_dir"; From 4fcf394b3ee3dfeea75543991bc6238528f90089 Mon Sep 17 00:00:00 2001 From: John Smith Date: Fri, 24 Dec 2021 12:10:35 +1100 Subject: [PATCH 589/637] fix materialised views being misclassified as tables in ->table_info - github #132 --- lib/DBD/Oracle.pm | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index 4481bade..a524cff9 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -487,24 +487,23 @@ SQL } else { $SQL = <<'SQL'; -SELECT * - FROM -( - SELECT /*+ CHOOSE */ - NULL TABLE_CAT - , t.OWNER TABLE_SCHEM - , t.TABLE_NAME TABLE_NAME - , decode(t.OWNER - , 'SYS' , 'SYSTEM ' - , 'SYSTEM' , 'SYSTEM ' - , '' ) || t.TABLE_TYPE TABLE_TYPE - , c.COMMENTS REMARKS - FROM ALL_TAB_COMMENTS c - , ALL_CATALOG t - WHERE c.OWNER (+) = t.OWNER - AND c.TABLE_NAME (+) = t.TABLE_NAME - AND c.TABLE_TYPE (+) = t.TABLE_TYPE -) + select * FROM ( + select /*+ CHOOSE */ + NULL TABLE_CAT + , t.OWNER TABLE_SCHEM + , t.TABLE_NAME TABLE_NAME + , decode(t.OWNER + , 'SYS' , 'SYSTEM ' + , 'SYSTEM' , 'SYSTEM ' + , '' ) || DECODE(mv.MVIEW_NAME, NULL, t.TABLE_TYPE, 'VIEW' ) TABLE_TYPE + , c.COMMENTS REMARKS + FROM ALL_TAB_COMMENTS c + RIGHT JOIN ALL_CATALOG t on t.OWNER = c.OWNER + and t.TABLE_NAME = c.TABLE_NAME + and t.TABLE_TYPE = c.TABLE_TYPE + LEFT JOIN ALL_MVIEWS mv on mv.OWNER = t.OWNER + and mv.MVIEW_NAME = t.TABLE_NAME + ) SQL if ( defined $SchVal ) { push @Where, "TABLE_SCHEM LIKE '$SchVal' ESCAPE '\\'"; From 250e165ed31c56e55d9e35afbd5579d75661dd7e Mon Sep 17 00:00:00 2001 From: John Smith Date: Fri, 24 Dec 2021 12:27:16 +1100 Subject: [PATCH 590/637] Fix bugtracker ref in dist metadata github #130 --- Makefile.PL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.PL b/Makefile.PL index 0331c16e..37885e14 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -61,7 +61,7 @@ my %opts = ( "ExtUtils::MakeMaker" => 0, "Test::Simple" => '0.90'}, resources => { - bugtracker => 'https://github.com/perl5-dbi/DBD-Oracle/issues', + bugtracker => { web => 'https://github.com/perl5-dbi/DBD-Oracle/issues'}, homepage => 'https://metacpan.org/pod/DBD::Oracle', repository => { type => 'git', From 9d13079991fb13f76d53e87424fec24f739c1afc Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 23 Dec 2021 23:18:09 -0800 Subject: [PATCH 591/637] Update Changes --- Changes | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Changes b/Changes index e2e9be47..2810a9a2 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,20 @@ Revision history for DBD::Oracle {{$NEXT}} + [BUG FIXES] + + Run nonassigned pl/sql tests based off versions known to have the issue. - (GH#70, Wesley Hinds) + Oracle Instant Client 21 support - (Tux) + Add rpath to ORACLE_HOME to DBD/Oracle/Oracle.bundle - (GH#128, hakonhagland) + fix materialised views being misclassified as tables in ->table_info - (GH#132, John Smith) + Fix bugtracker ref in dist metadata github - (GH#130, John Smith) + + [MISCELLANEOUS] + + Updates to POD and README file + Moved old README file to t/TESTING.md + Updated links + 1.80 2019-07-25 [BUG FIXES] From 0508f7565a51d7bc4948bf1735e3026232ae12e7 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 23 Dec 2021 23:25:40 -0800 Subject: [PATCH 592/637] v1.81 [BUG FIXES] Run nonassigned pl/sql tests based off versions known to have the issue. - (GH#70, Wesley Hinds) Oracle Instant Client 21 support - (Tux) Add rpath to ORACLE_HOME to DBD/Oracle/Oracle.bundle - (GH#128, hakonhagland) fix materialised views being misclassified as tables in ->table_info - (GH#132, John Smith) Fix bugtracker ref in dist metadata github - (GH#130, John Smith) [MISCELLANEOUS] Updates to POD and README file Moved old README file to t/TESTING.md Updated links --- Changes | 2 ++ dist.ini | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 2810a9a2..cceea2cc 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} +1.81 2021-12-24 + [BUG FIXES] Run nonassigned pl/sql tests based off versions known to have the issue. - (GH#70, Wesley Hinds) diff --git a/dist.ini b/dist.ini index dcc1ef70..b810522a 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.80 +version = 1.81 ; Generate files From 8857dbf90467f6b0b90dc132b3f61e7586aeaf1c Mon Sep 17 00:00:00 2001 From: John Smith Date: Wed, 29 Dec 2021 10:24:46 +1100 Subject: [PATCH 593/637] fix github metadata woes as best as possible For some reason the github dzil plugin is not fining the issues page, so for now adding it to Meta.yml manually - i.e. `bugtracker: https://github.com/perl5-dbi/DBD-Oracle/issues` on release will have to do. --- Changes | 4 ++++ MANIFEST | 3 --- dist.ini | 13 +++++-------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Changes b/Changes index cceea2cc..e2454dad 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,10 @@ Revision history for DBD::Oracle {{$NEXT}} +1.82 2021-12-29 + + Second try at github #130. Still not fully cooperating but better. + 1.81 2021-12-24 [BUG FIXES] diff --git a/MANIFEST b/MANIFEST index c16e2f5a..a7b68aaa 100644 --- a/MANIFEST +++ b/MANIFEST @@ -4,21 +4,18 @@ Changes INSTALL LICENSE MANIFEST -META.json META.yml Makefile.PL Oracle.h Oracle.xs README README.help.txt -README.mkdn TESTING.md TODO cpanfile dbdimp.c dbdimp.h dbivport.h -doap.xml examples/README examples/bind.pl examples/commit.pl diff --git a/dist.ini b/dist.ini index b810522a..d6ae6854 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.81 +version = 1.82 ; Generate files @@ -20,15 +20,15 @@ version = 1.81 [Git::Contributors] [ContributorsFile] [InstallGuide] -;[GithubMeta] -;remote=github +[GithubMeta] +; fork = 1 +bugs = 1 +; remote = upstream [MetaYAML] -[MetaJSON] [PodWeaver] [License] -[ReadmeMarkdownFromPod] [NextRelease] time_zone = UTC format = %-9v %{yyyy-MM-dd}d @@ -81,9 +81,6 @@ install_command = cpanm . [PodCoverageTests] [PodSyntaxTests] -[DOAP] -process_changes = 1 - [CPANFile] [CopyrightYearFromGit] From fe94f7a76b80745e542d4092a7e943d36aba2e35 Mon Sep 17 00:00:00 2001 From: Alex Muntada Date: Thu, 31 Oct 2019 22:12:27 +0100 Subject: [PATCH 594/637] Build DBD::Oracle on Debian systems without LD_LIBRARY_PATH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch based on a proposed fix by Slaven Rezić in https://github.com/perl5-dbi/DBD-Oracle/issues/72 and improved by me afterwards. The patch has been successfully applied to Debian for a few releases now: https://salsa.debian.org/perl-team/modules/packages/libdbd-oracle-perl/blob/master/debian/patches/build-without-ld-libray-path.patch --- Makefile.PL | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.PL b/Makefile.PL index 37885e14..ef25899b 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1113,6 +1113,7 @@ sub read_sysliblist { $linkwith =~ m/-lcl\b/ or $syslibs =~ s/\s*-lcl\b//g; } + $syslibs .= " -lnnz12 -lons -lclntshcore -lipc1 -lmql1"; return $syslibs; } From 0940787f780d870b94a0f20cea834435f75a0e15 Mon Sep 17 00:00:00 2001 From: Alex Muntada Date: Mon, 2 Dec 2019 11:16:50 +0100 Subject: [PATCH 595/637] Apply fix to debian only As suggested by Wesley Hinds : https://github.com/perl5-dbi/DBD-Oracle/pull/112#issuecomment-559244350 --- Makefile.PL | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile.PL b/Makefile.PL index ef25899b..51709e31 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1113,7 +1113,9 @@ sub read_sysliblist { $linkwith =~ m/-lcl\b/ or $syslibs =~ s/\s*-lcl\b//g; } - $syslibs .= " -lnnz12 -lons -lclntshcore -lipc1 -lmql1"; + if (lc(@Config{qw(myuname)}) =~ /debian/) { + $syslibs .= " -lnnz12 -lons -lclntshcore -lipc1 -lmql1"; + } return $syslibs; } From 0b1ccddae3206d774f4b6b9b6026feb8639e72e8 Mon Sep 17 00:00:00 2001 From: Alex Muntada Date: Fri, 13 Nov 2020 01:05:09 +0100 Subject: [PATCH 596/637] Hint ld that libclntsh deps are needed Otherwise the references to the extra libs needed by -lclntsh would be removed and LD_LIBRARY_PATH would be necessary again. --- Makefile.PL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.PL b/Makefile.PL index 51709e31..d3fb3ba5 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1114,7 +1114,7 @@ sub read_sysliblist { $syslibs =~ s/\s*-lcl\b//g; } if (lc(@Config{qw(myuname)}) =~ /debian/) { - $syslibs .= " -lnnz12 -lons -lclntshcore -lipc1 -lmql1"; + $syslibs .= " -Wl,--no-as-needed -lnnz12 -lons -lclntshcore -lipc1 -lmql1"; } return $syslibs; } From 62918b933db6604bd4519a49c50f14fbe0d5055a Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 28 Dec 2021 22:55:34 -0800 Subject: [PATCH 597/637] The CPAN doesnt recognize .mkd as markdown. Move to .md --- CONTRIBUTING.mkd => CONTRIBUTING.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CONTRIBUTING.mkd => CONTRIBUTING.md (100%) diff --git a/CONTRIBUTING.mkd b/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.mkd rename to CONTRIBUTING.md From bec4df47f527883033fde19e5fdf5d636c7ec20a Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 28 Dec 2021 22:56:19 -0800 Subject: [PATCH 598/637] Note merged PR --- Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changes b/Changes index e2454dad..2fd8ebae 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBD::Oracle {{$NEXT}} + Build improvements on Debian-ish systems (GH#112, Alex Muntada) + 1.82 2021-12-29 Second try at github #130. Still not fully cooperating but better. From 3f21a161cc56761f93dd255249bfb1e06e13da06 Mon Sep 17 00:00:00 2001 From: John Smith Date: Mon, 17 Jan 2022 13:03:48 +1100 Subject: [PATCH 599/637] prep 1.83 for release --- Changes | 3 ++- MANIFEST | 2 +- dist.ini | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index 2fd8ebae..a6c2f078 100644 --- a/Changes +++ b/Changes @@ -1,8 +1,9 @@ Revision history for DBD::Oracle -{{$NEXT}} +1.83 Build improvements on Debian-ish systems (GH#112, Alex Muntada) + Add rpath to ORACLE_HOME to DBD/Oracle/Oracle.bundle (GH#129, hackonhagland). 1.82 2021-12-29 diff --git a/MANIFEST b/MANIFEST index a7b68aaa..8ffe2150 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,4 +1,4 @@ -CONTRIBUTING.mkd +CONTRIBUTING.md CONTRIBUTORS Changes INSTALL diff --git a/dist.ini b/dist.ini index d6ae6854..2beb0cf5 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.82 +version = 1.83 ; Generate files From 3759e7077b316d8c70964e3373e50f6fb8233034 Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Wed, 19 Jan 2022 09:04:10 -0600 Subject: [PATCH 600/637] Updated list of OCI versions known to have bind_param_inout nonassigned bug. These versions will be skipped in 25plsql.t. Originally reported in GH#70. --- t/25plsql.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/25plsql.t b/t/25plsql.t index 58ea3e32..bac611f7 100644 --- a/t/25plsql.t +++ b/t/25plsql.t @@ -331,7 +331,7 @@ SKIP: { # Also see http://www.mail-archive.com/dbi-users@perl.org/msg18835.html # Known bad OCI versions - my @bad_oci_vers = (9.2,18.3,18.5,19.6); + my @bad_oci_vers = (9.2,18.3,18.5,19.6,19.9,19.13); skip 'Client version is known to have issue', 4 if grep { $_ == DBD::Oracle::ORA_OCI() } @bad_oci_vers; From 978a88b3e5eba329e66d11facdf2268f6696df32 Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Wed, 19 Jan 2022 14:01:52 -0600 Subject: [PATCH 601/637] Include 21.4 in OCI versions known to have bind_param_inout nonassigned bug. Originally reported in GH#70. --- t/25plsql.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/25plsql.t b/t/25plsql.t index bac611f7..02b441eb 100644 --- a/t/25plsql.t +++ b/t/25plsql.t @@ -331,7 +331,7 @@ SKIP: { # Also see http://www.mail-archive.com/dbi-users@perl.org/msg18835.html # Known bad OCI versions - my @bad_oci_vers = (9.2,18.3,18.5,19.6,19.9,19.13); + my @bad_oci_vers = (9.2,18.3,18.5,19.6,19.9,19.13,21.4); skip 'Client version is known to have issue', 4 if grep { $_ == DBD::Oracle::ORA_OCI() } @bad_oci_vers; From 3d7b77495455e12b2bf9c474d3f227b888955181 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Fri, 21 Jan 2022 22:35:00 -0800 Subject: [PATCH 602/637] Update changes for GH#140 --- Changes | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changes b/Changes index a6c2f078..df47c06d 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,9 @@ Revision history for DBD::Oracle +{{$NEXT}} + + Exclude 19.9 and 19.13 from 25plsql.t - (GH#140, Wesley Hinds) + 1.83 Build improvements on Debian-ish systems (GH#112, Alex Muntada) From caa11e3694febfb2eb053df02b9aa68b9d42f705 Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Fri, 21 Jan 2022 08:40:45 -0600 Subject: [PATCH 603/637] Check for appropriate permissions before running 28array_bind.t tests. --- t/28array_bind.t | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/t/28array_bind.t b/t/28array_bind.t index c37e845b..b618906e 100644 --- a/t/28array_bind.t +++ b/t/28array_bind.t @@ -83,7 +83,7 @@ sub test_varchar2_table_3_tests($) { my $sth = $dbh->prepare($statement); if ( !defined($sth) ) { - BAIL_OUT( 'Prapare(varchar2) error: ' . $dbh->errstr ); + BAIL_OUT( 'Prepare(varchar2) error: ' . $dbh->errstr ); } my @arr = ( 'abc', 'cde', 'lalala' ); @@ -111,16 +111,6 @@ sub test_varchar2_table_3_tests($) { BAIL_OUT( 'Execute (at VARCHAR2) failed: ' . $dbh->errstr ); } - # print "Result: cc=",$cc,"\n", - # "\tarr=",Data::Dumper::Dumper(\@arr),"\n"; - - #Result: cc=2, l=3 - # arr=$VAR1 = [ - # 'def', - # 'ijk' - # ]; - # - ok( $cc == 2, 'VARCHAR2_TABLE input count correctness' ); ok( scalar(@arr) == 2, 'VARCHAR2_TABLE output count correctness' ); ok( ( ( $arr[0] eq 'def' ) and ( $arr[1] eq 'ijk' ) ), @@ -146,7 +136,7 @@ sub test_number_table_3_tests { my $sth = $dbh->prepare($statement); if ( !defined($sth) ) { - BAIL_OUT( 'Prapare(NUMBER_TABLE) error: ' . $dbh->errstr ); + BAIL_OUT( 'Prepare(NUMBER_TABLE) error: ' . $dbh->errstr ); } my @arr = ( 1, '2E0', '3.5' ); @@ -209,7 +199,20 @@ sub test_number_table_3_tests { } sub test_inout_array_tests { - my $dbh = shift; + my $dbh = shift; + + my $privs_sth = $dbh->prepare('SELECT PRIVILEGE from session_privs'); + $privs_sth->execute; + my @privileges = map { $_->[0] } @{ $privs_sth->fetchall_arrayref }; + + SKIP: { + skip q{don't have permission to create table} => 9 + unless grep { $_ eq 'CREATE TABLE' } @privileges; + skip q{don't have permission to create sequence} => 9 + unless grep { $_ eq 'CREATE SEQUENCE' } @privileges; + skip q{don't have permission to create trigger} => 9 + unless grep { $_ eq 'CREATE TRIGGER' } @privileges; + my $table = 'array_io_test__drop_me' . ( $ENV{DBD_ORACLE_SEQ} || '' ); my $seq = 'seq_io_test__drop_me' . ( $ENV{DBD_ORACLE_SEQ} || '' ); my $trigger = 'trg_io_test__drop_me' . ( $ENV{DBD_ORACLE_SEQ} || '' ); @@ -267,12 +270,20 @@ sub test_inout_array_tests { $dbh->do("drop table $table") or warn $dbh->errstr; $dbh->do("drop sequence $seq") or die $dbh->errstr; - + } } -# FIXME this is orphaned? See https://github.com/pythian/DBD-Oracle/issues/64 sub test_number_SP { - my $dbh = shift; + my $dbh = shift; + + my $privs_sth = $dbh->prepare('SELECT PRIVILEGE from session_privs'); + $privs_sth->execute; + my @privileges = map { $_->[0] } @{ $privs_sth->fetchall_arrayref }; + + SKIP: { + skip q{don't have permission to create procedure} => 4 + unless grep { $_ eq 'CREATE PROCEDURE' } @privileges; + $dbh->do( <<'EOF' create or replace procedure tox_test_proc0( @@ -319,7 +330,7 @@ EOF cmp_ok( $result, '==', '345', '... we should have 345 out string' ); $dbh->do('drop procedure tox_test_proc0') or warn $dbh->errstr; - + } } SKIP: { From 73d6dcc0c23cb4778d58938ea7dd652a2db591a3 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Fri, 21 Jan 2022 22:36:09 -0800 Subject: [PATCH 604/637] Update Changes for GH#141 --- Changes | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes b/Changes index df47c06d..2fc3a685 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,7 @@ Revision history for DBD::Oracle {{$NEXT}} + Check permissions for tests in 28array_bind.t - (GH#141, Wesley Hinds) Exclude 19.9 and 19.13 from 25plsql.t - (GH#140, Wesley Hinds) 1.83 From 2238685d17a041d1c19b56ab6dcfe25265bb3f7b Mon Sep 17 00:00:00 2001 From: kjetillll Date: Sat, 29 Jan 2022 01:46:12 +0100 Subject: [PATCH 605/637] Update 25plsql.t Tested with instantclient version 21.5 and also this version should be added to @bad_oci_vers. --- t/25plsql.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/25plsql.t b/t/25plsql.t index 02b441eb..7f505414 100644 --- a/t/25plsql.t +++ b/t/25plsql.t @@ -331,7 +331,7 @@ SKIP: { # Also see http://www.mail-archive.com/dbi-users@perl.org/msg18835.html # Known bad OCI versions - my @bad_oci_vers = (9.2,18.3,18.5,19.6,19.9,19.13,21.4); + my @bad_oci_vers = (9.2, 18.3, 18.5, 19.6, 19.9, 19.13, 21.4, 21.5); skip 'Client version is known to have issue', 4 if grep { $_ == DBD::Oracle::ORA_OCI() } @bad_oci_vers; From d4b2b7bf77fff12592c42669a1026bbbb2a3470e Mon Sep 17 00:00:00 2001 From: kjetillll Date: Sat, 29 Jan 2022 01:49:11 +0100 Subject: [PATCH 606/637] Update Oracle.pm --- lib/DBD/Oracle.pm | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index a524cff9..e6ccc484 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -5554,11 +5554,11 @@ Oracle.ex directory =item DBD::Oracle Tutorial -http://www.pythian.com/blogs/wp-content/uploads/introduction-dbd-oracle.html +https://blog.pythian.com/wp-content/uploads/introduction-dbd-oracle.html =item Oracle Instant Client -http://www.oracle.com/technology/tech/oci/instantclient/index.html +https://www.oracle.com/database/technologies/instant-client/downloads.html =item Oracle on Linux @@ -5568,18 +5568,16 @@ http://www.ixora.com.au/ ora_explain supplied and installed with DBD::Oracle. -http://www.orafaq.com/ +https://www.orafaq.com/ -http://vonnieda.org/oracletool/ +https://www.oracletool.com/ =item Commercial Oracle Tools and Links Assorted tools and references for general information. No recommendation implied. -http://www.platinum.com - -http://www.SoftTreeTech.com +https://www.SoftTreeTech.com Also PL/Vision from RevealNet and Steven Feuerstein, and "Q" from Savant Corporation. From 21c907e1f48185e24202f4bffd38214cdfbb8e8a Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Thu, 27 Jan 2022 13:46:03 -0600 Subject: [PATCH 607/637] Check for appropriate permissions before running 56embbeded.t tests. --- t/56embbeded.t | 70 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/t/56embbeded.t b/t/56embbeded.t index 0970f3e4..970eef25 100644 --- a/t/56embbeded.t +++ b/t/56embbeded.t @@ -33,34 +33,48 @@ else { # check that our db handle is good isa_ok( $dbh, 'DBI::db' ); -my $table = table('table_embed'); -my $type = $table . 'a_type'; - -#do not warn if already there -eval { - local $dbh->{PrintError} = 0; - force_drop_table( $dbh, $table ); - $dbh->do(qq{DROP TYPE $type }); -}; -$dbh->do(qq{CREATE OR REPLACE TYPE $type AS varray(10) OF varchar(30) }); - -$dbh->do(qq{ CREATE TABLE $table ( aa_type $type) }); - -$dbh->do("insert into $table values ($type('1','2','3','4','5'))"); - -# simple execute -my $sth; -ok( $sth = $dbh->prepare("select * from $table"), - '... Prepare should return true' ); -my $problems; -ok( $sth->execute(), '... Select should return true' ); - -while ( my ($a) = $sth->fetchrow() ) { - $problems = scalar(@$a); -} +# get the user's privileges +my $privs_sth = $dbh->prepare('SELECT PRIVILEGE from session_privs'); +$privs_sth->execute; +my @privileges = map { $_->[0] } @{ $privs_sth->fetchall_arrayref }; + +SKIP: { + + skip q{don't have permission to create type} => 3 + unless grep { $_ eq 'CREATE TYPE' } @privileges; + skip q{don't have permission to create table} => 3 + unless grep { $_ eq 'CREATE TABLE' } @privileges; + + my $table = table('table_embed'); + my $type = $table . 'a_type'; + + #do not warn if already there + eval { + local $dbh->{PrintError} = 0; + force_drop_table( $dbh, $table ); + $dbh->do(qq{DROP TYPE $type }); + }; + $dbh->do(qq{CREATE OR REPLACE TYPE $type AS varray(10) OF varchar(30) }); + + $dbh->do(qq{ CREATE TABLE $table ( aa_type $type) }); -cmp_ok( scalar($problems), '==', 5, '... we should have 5 items' ); + $dbh->do("insert into $table values ($type('1','2','3','4','5'))"); -drop_table($dbh, $table); + # simple execute + my $sth; + ok( $sth = $dbh->prepare("select * from $table"), + '... Prepare should return true' ); + my $problems; + ok( $sth->execute(), '... Select should return true' ); -$dbh->do("drop type $type") unless $ENV{DBD_SKIP_TABLE_DROP}; + while ( my ($a) = $sth->fetchrow() ) { + $problems = scalar(@$a); + } + + cmp_ok( scalar($problems), '==', 5, '... we should have 5 items' ); + + drop_table($dbh, $table); + + $dbh->do("drop type $type") unless $ENV{DBD_SKIP_TABLE_DROP}; + +} From cac781ed0c39e94d94eb2a40f17dc74f66d04e36 Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Mon, 24 Jan 2022 15:11:35 -0600 Subject: [PATCH 608/637] Have find_headers() also search for header files based off the major version number. --- Makefile.PL | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile.PL b/Makefile.PL index d3fb3ba5..26f089c1 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1541,6 +1541,8 @@ sub find_headers { # compensate for case where final .0 isn't in the install directory name (my $client_version_trim = $client_version_full) =~ s/\.0$//; + # for case where point is not in install directory name. OCI 21+ + (my $client_version_major = $client_version) =~ s/\..*$//; my @try = grep { -d $_ } ( # search the ORACLE_HOME we're using first # --- Traditional full-install locations @@ -1557,15 +1559,19 @@ sub find_headers { $client_version, $client_version_trim, $client_version_full, + $client_version_major, #"/include/oracle/$client_version_full/client", # Instant Client for RedHat FC3 #"/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC3 + #"/include/oracle/$client_version_major/client", # Instant Client RPM (21+) #"/usr/include/oracle/$client_version/client64", # Instant Client 11.1 and up #"/usr/include/oracle/$client_version/client", # Instant Client 11.1 and up #"/usr/include/oracle/$client_version_full/client64", # Instant Client 64 #"/usr/include/oracle/$client_version_full/client", # Instant Client for RedHat FC4 #"/usr/include/oracle/$client_version_trim/client64", # Instant Client 64 + #"/usr/include/oracle/$client_version_major/client64",# Instant Client RPM (21+) #"/usr/include/oracle/$client_version_trim/client", # Instant Client for RedHat FC4 + #"/usr/include/oracle/$client_version_major/client", # Instant Client RPM (21+) ); # Add /usr/include/oracle based on the oracle home location if oracle home is under From a4545c29fb0fb2a9400df42c3109b63be7e3873d Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 1 Feb 2022 00:17:14 -0800 Subject: [PATCH 609/637] Update Changes from serveral merged PR --- Changes | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changes b/Changes index 2fc3a685..594aeb54 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,10 @@ Revision history for DBD::Oracle {{$NEXT}} + Have find_headers() also search for header files based off the major version number - (GH#142, Wesley Hinds) + Check for appropriate permissions before running 56embbeded.t tests - (#143, Wesley Hinds) + Updated links in doc in Oracle.pm - (Gh#145, kjetillll) + Update 25plsql.t and add 21.5 to @bad_oci_vers - (GH#144, kjetillll) Check permissions for tests in 28array_bind.t - (GH#141, Wesley Hinds) Exclude 19.9 and 19.13 from 25plsql.t - (GH#140, Wesley Hinds) From 2511625ff795cc2ac7892d32421f75abc6668330 Mon Sep 17 00:00:00 2001 From: Dean Pearce Date: Thu, 17 Feb 2022 16:39:03 -0500 Subject: [PATCH 610/637] Update .mailmap Removing outdated information from the list. --- .mailmap | 1 - 1 file changed, 1 deletion(-) diff --git a/.mailmap b/.mailmap index 4dd39cf0..16559fcf 100644 --- a/.mailmap +++ b/.mailmap @@ -1,7 +1,6 @@ Dean Hamstead Dean Hamstead Dean Hamstead -Dean Pearce John Scoles Martin J. Evans Martin J. Evans From 644904097e1cf35978999d08b90edb6c8f8b8d88 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sat, 19 Feb 2022 23:34:16 -0800 Subject: [PATCH 611/637] Update MANIFEST --- MANIFEST | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MANIFEST b/MANIFEST index 8ffe2150..d713efee 100644 --- a/MANIFEST +++ b/MANIFEST @@ -63,8 +63,10 @@ t/10general.t t/12impdata.t t/14threads.t t/15nls.t +t/16cached.t t/20select.t t/21nchar.t +t/22cset.t t/22nchar_al32utf8.t t/22nchar_utf8.t t/23wide_db.t @@ -91,6 +93,7 @@ t/58object.t t/60reauth.t t/70meta.t t/80ora_charset.t +t/cache2.pl t/lib/DBDOracleTestLib.pm t/lib/ExecuteArray.pm t/rt13865.t From a69f0cacc993b7ef33d55d07fe9109f796c461b1 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sat, 19 Feb 2022 23:40:16 -0800 Subject: [PATCH 612/637] Update mailmap --- .mailmap | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.mailmap b/.mailmap index 16559fcf..37fc2dc4 100644 --- a/.mailmap +++ b/.mailmap @@ -1,6 +1,9 @@ +Alex Muntada Dean Hamstead Dean Hamstead Dean Hamstead +Dean Pearce +H.Merijn Brand - Tux John Scoles Martin J. Evans Martin J. Evans @@ -11,6 +14,7 @@ Michael Portnoy Mike O'Regan Tim Bunce Tim Bunce +Wesley Hinds Yanick Champoux Yanick Champoux Yanick Champoux From 4dd996e84725ec122e5f2fa2365ca7109bbf1d98 Mon Sep 17 00:00:00 2001 From: Andrei Voropaev Date: Thu, 17 Mar 2022 18:12:20 +0100 Subject: [PATCH 613/637] Rewrite of login6 This changes the way things are done during login6 (connect). In particular: 1. OCIEnv is cached based on character sets and mode. One copy is used in all threads (so OCI_THREADED is important!) 2. There are no more global variables for character sets. So each connection uses exactly what is specified at connection time. Thus option ora_envhp is removed. 3. Improved support for DRCP. Now the pools are independent from threads. The pool is defined by DSN and UID. No more leaking of connections or pools. When last imp_drh goes away the pools are released. It is now also possible to tag sessions in addition to using connection_class (the latter works only with DRCP). 4. Reauthenticate now keeps old session as long as possible, so if new identity is wrong, then old session stays intact. 5. Support for using shared variables is also improved. There is now additional function ora_shared_release that cleans up shared connection, when it is not needed anymore. Though it is still cleaner to used DRCP. No more handles are leaking. 6. Support for imp_take is improved. No handles are leaking. But it is cleaner to use DRCP. 7. Small fixes for compilation and handling of attributes. --- MANIFEST | 3 + Oracle.h | 4 +- Oracle.xs | 47 +- dbdcnx.c | 1120 +++++++++++++++++++++++++++++++++++++ dbdimp.c | 1360 ++++++++++++++++++--------------------------- dbdimp.h | 130 +++-- lib/DBD/Oracle.pm | 98 ++-- oci8.c | 231 +++++--- ocitrace.h | 30 +- t/15threads.t | 102 ++++ t/16cached.t | 30 + t/16drcp.t | 112 ++++ t/22cset.t | 125 +++++ t/25plsql.t | 2 +- t/38taf.t | 6 +- t/58object.t | 9 +- t/cache2.pl | 63 +++ 17 files changed, 2454 insertions(+), 1018 deletions(-) create mode 100644 dbdcnx.c create mode 100644 t/15threads.t create mode 100644 t/16cached.t create mode 100644 t/16drcp.t create mode 100644 t/22cset.t create mode 100644 t/cache2.pl diff --git a/MANIFEST b/MANIFEST index d713efee..c0d11526 100644 --- a/MANIFEST +++ b/MANIFEST @@ -13,6 +13,7 @@ README.help.txt TESTING.md TODO cpanfile +dbdcnx.c dbdimp.c dbdimp.h dbivport.h @@ -63,7 +64,9 @@ t/10general.t t/12impdata.t t/14threads.t t/15nls.t +t/15threads.t t/16cached.t +t/16drcp.t t/20select.t t/21nchar.t t/22cset.t diff --git a/Oracle.h b/Oracle.h index c933de2f..b2dca39e 100644 --- a/Oracle.h +++ b/Oracle.h @@ -26,7 +26,7 @@ #endif /* egcs-1.1.2 does not have _int64 */ -#if defined(__MINGW32__) || defined(__CYGWIN32__) +#if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__) #define _int64 long long #endif @@ -61,6 +61,8 @@ void dbd_init _((dbistate_t *dbistate)); void dbd_init_oci_drh _((imp_drh_t * imp_drh)); void dbd_dr_destroy _((SV *drh, imp_drh_t *imp_drh)); +void dbd_dr_globals_init _(()); +void dbd_dr_mng _(()); int dbd_db_login _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pwd)); int dbd_db_do _((SV *sv, char *statement)); diff --git a/Oracle.xs b/Oracle.xs index bb5d61e9..85ba4986 100644 --- a/Oracle.xs +++ b/Oracle.xs @@ -72,6 +72,10 @@ constant(name=Nullch) OCI_DBSHUTDOWN_IMMEDIATE = 3 OCI_DBSHUTDOWN_ABORT = 4 OCI_DBSHUTDOWN_FINAL = 5 + OCI_SPOOL_ATTRVAL_WAIT = OCI_SPOOL_ATTRVAL_WAIT + OCI_SPOOL_ATTRVAL_TIMEDWAIT = OCI_SPOOL_ATTRVAL_TIMEDWAIT + OCI_SPOOL_ATTRVAL_NOWAIT = OCI_SPOOL_ATTRVAL_NOWAIT + OCI_SPOOL_ATTRVAL_FORCEGET = OCI_SPOOL_ATTRVAL_FORCEGET SQLT_CHR = SQLT_CHR SQLT_BIN = SQLT_BIN CODE: @@ -104,7 +108,7 @@ ora_env_var(name) sv_setpv(sv, p); ST(0) = sv; -#if defined(__CYGWIN32__) || defined(__CYGWIN64__) +#if defined(__CYGWIN32__) || defined(__CYGWIN64__) || defined(__CYGWIN__) void ora_cygwin_set_env(name, value) char * name @@ -114,6 +118,12 @@ ora_cygwin_set_env(name, value) #endif /* __CYGWIN32__ */ +void +ora_shared_release(sv) + SV * sv + CODE: + ora_shared_release(aTHX_ sv); + INCLUDE: Oracle.xsi @@ -433,12 +443,29 @@ ora_ping(dbh) void -reauthenticate(dbh, uid, pwd) +reauthenticate(dbh, usv, psv) SV * dbh - char * uid - char * pwd + SV * usv + SV * psv CODE: + STRLEN ulen, plen; + char * uid, * pwd; D_imp_dbh(dbh); + + uid = (char*)SvPV(usv, ulen); + pwd = (char*)SvPV(psv, plen); + if(plen == 0 && ulen != 0) + { + char * b = strchr(uid, '/'); + if(b != NULL && b != uid) + { + size_t off = b - uid; + SV * tmp = sv_mortalcopy(usv); + uid = (char *)SvPV(tmp, ulen); + uid[off] = 0; + pwd = uid + off + 1; + } + } ST(0) = ora_db_reauthenticate(dbh, imp_dbh, uid, pwd) ? &PL_sv_yes : &PL_sv_no; void @@ -485,7 +512,7 @@ ora_lob_write(dbh, locator, offset, data) } #endif /* OCI_ATTR_CHARSET_ID */ /* if data is utf8 but charset isn't then switch to utf8 csid */ - csid = (SvUTF8(data) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); + csid = (SvUTF8(data) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(imp_dbh, csform); OCILobWrite_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &amtp, (ub4)offset, @@ -546,7 +573,7 @@ ora_lob_append(dbh, locator, data) } #endif /* OCI_ATTR_CHARSET_ID */ /* if data is utf8 but charset isn't then switch to utf8 csid */ - csid = (SvUTF8(data) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); + csid = (SvUTF8(data) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(imp_dbh, csform); OCILobWriteAppend_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, locator, &amtp, bufp, (ub4)data_len, OCI_ONE_PIECE, NULL, NULL, @@ -625,7 +652,7 @@ ora_lob_read(dbh, locator, offset, length) SvCUR(dest_sv) = amtp; /* always bytes here */ *SvEND(dest_sv) = '\0'; if (csform){ - if (CSFORM_IMPLIES_UTF8(csform)){ + if (CSFORM_IMPLIES_UTF8(imp_dbh, csform)){ SvUTF8_on(dest_sv); } } @@ -714,6 +741,11 @@ ora_lob_chunk_size(dbh, locator) # ------------------------------------------------------------ MODULE = DBD::Oracle PACKAGE = DBD::Oracle::dr +void +init_globals() + CODE: + dbd_dr_globals_init(); + void init_oci(drh) SV * drh @@ -721,6 +753,7 @@ init_oci(drh) D_imp_drh(drh); dbd_init_oci(DBIS) ; dbd_init_oci_drh(imp_drh) ; + dbd_dr_mng(); void DESTROY(drh) diff --git a/dbdcnx.c b/dbdcnx.c new file mode 100644 index 00000000..608269f4 --- /dev/null +++ b/dbdcnx.c @@ -0,0 +1,1120 @@ +/* notes {{{ + * This module attempts to provide reuse of OCIEnv + * and storage for session pool(s). + * + * Note, configuration uses acronym "drcp", which is + * somewhat misleading. DRCP stands for "connection pooling" + * and DBD::Oracle offers "session pooling", which is + * not "connection pooling" (that is also offered by Oracle). + * + * To make things complex DBD::Oracle offers 2 ways to + * share connections between threads. Such sharing + * requires that one thread does not use pointers + * to data allocated in another thread. In perl, + * each thread gets copy of perl interpreter, and each + * thread has its own heap for memory allocation. + * When the thread ends, that memory may get released, + * which leads to problems if the memory is referenced + * from another thread. + * + * It appears, that OCI uses itsown memory pool for + * allocation, so the data allocated in one thread + * is still accessible in another thread. At least + * tests don't fail in such cases. There are + * also OCI internal mutexes that protect access to + * that memory. The good news, one may ask OCI to allocate + * some memory for the caller. That is what this + * module is using. + * + * When OCIEnv is created, it uses 3 parameters + * that define the functionality of new OCIEnv. + * Those are: mode, charset and ncharset. So, when + * we need some OCIEnv we have to check for existing + * ones that have matching parameters. If charset + * or ncharset is 0, then current value from environment + * is used (OCINlsEnvironmentVariableGet) + * + * The session pool is identified (in addition to + * charsets and mode for OCIEnv) by dbname, user + * and "rlb" (activity of load-balancer). Since all + * sessions are "homogenous", Oracle won't check + * password when new session is requested. So probably + * it makes sense to check it here. So password + * is also saved. + * + * This module does not use HV to find cached + * handles because HV may need to allocate memory + * from current thread, and that is not good. Still + * it is very unlikely that someone uses thousands + * of different pools/characters, so simple + * running through doubly-linked list should be + * fast enough (and maybe even faster) than hashing. + * + * Now, how long shall be cached all handles? As long + * as there are users. Each open connection is a user. + * Additionally every "driver"-object is a user. + * The drivier-object is allocated in each thread + * that tries to connect to DB and is released when + * thread ends. + }}} */ +#include "Oracle.h" +DBISTATE_DECLARE; + +typedef struct llist_t llist_t; +/* small implementation for doubly-linked list {{{ */ +struct llist_t{ + llist_t * left; + llist_t * right; +}; + +PERL_STATIC_INLINE int +llist_empty(const llist_t * list) +{ + return list->left == list; +} + +PERL_STATIC_INLINE void +llist_init(llist_t *list) +{ + list->right = list->left = list; +} + +PERL_STATIC_INLINE void +llist_add(llist_t * left, llist_t * right) +{ + llist_t * old; + + // first save the pointer from the left->rigth + old = left->right; + + // now left->right shall point to right + left->right = right; + + // now the old left pointer shall point to what the + // new right->left was pointing + old->left = right->left; + + // now right->left shall contain the left + right->left = left; + + // finally + old->left->right = old; +} + +PERL_STATIC_INLINE void +llist_drop(llist_t * el) +{ + if(llist_empty(el)) return; + el->left->right = el->right; + el->right->left = el->left; + llist_init(el); +} + +// this is pointer to the left element in chain +PERL_STATIC_INLINE llist_t * +llist_left(const llist_t * list) +{ + return list->left; +} + +// this one is a pointer to the right element in chain +PERL_STATIC_INLINE llist_t * +llist_right(const llist_t *list) +{ + return list->right; +} +/* }}} */ + +#if defined(USE_ITHREADS) +static perl_mutex mng_lock; +#endif +static llist_t mng_list; +static int dr_instances; +/* to get information about charsets we need these */ +static OCIEnv * mng_env; +static OCIError * mng_err; + +/*dbd_dr_globals_init{{{*/ +void +dbd_dr_globals_init() +{ +#if defined(USE_ITHREADS) + dTHX; + MUTEX_INIT(&mng_lock); +#endif + llist_init(&mng_list); + dr_instances = 0; + mng_env = NULL; + mng_err = NULL; +} +/*}}}*/ + +struct box_st{ + llist_t lock; + int refs; /* this shall be positiv for OCIEnv and negativ for Session Pool */ +}; + +struct env_box_st +{ + box_t base; + OCIEnv * envhp; + ub4 mode; + ub2 cset; + ub2 ncset; +}; +typedef struct env_box_st env_box_t; + +#ifdef ORA_OCI_112 +struct pool_box_st{ + box_t base; + env_box_t * env; + OCISPool *poolhp; + OCIError *errhp; + OraText *name; + ub4 name_len; + ub2 pass_len; + ub2 dbname_len; + /* all text strings are stored below. The buffer + * is long enough to contain dbname_len+user_len+pass_len + 4 bytes. + * So pass is box->buf + 1; + * dbname is box->buf + 2 + box->pass_len + * user is box->buf + 3 + box->dbname_len + box->pass_len + * First byte is 0 if RLB is not desired. + */ + char buf[1]; +}; +typedef struct pool_box_st pool_box_t; +#endif + +#define tracer(imp, dlvl, vlvl, ...) if \ + (DBIc_DBISTATE(imp)->debug >= (dlvl) || dbd_verbose >= (vlvl) )\ + PerlIO_printf(DBIc_LOGPIO(imp), __VA_ARGS__) + +/* local_error{{{*/ +static int +local_error(pTHX_ SV * h, const char * fmt, ...) +{ + va_list ap; + SV * txt_sv = sv_newmortal(); + SV * code_sv = get_sv("DBI::stderr", 0); + D_imp_xxh(h); + if(code_sv == NULL) + { + code_sv = sv_newmortal(); + sv_setiv(code_sv, 2000000000); + } + va_start(ap, fmt); + sv_vsetpvf(txt_sv, fmt, &ap); + va_end(ap); + DBIh_SET_ERR_SV(h, imp_xxh, code_sv, txt_sv, &PL_sv_undef, &PL_sv_undef); + return FALSE; +} +/*}}}*/ +/* release_env{{{*/ +static void +release_env(pTHX_ env_box_t * box) +{ + llist_drop(&box->base.lock); + if(dbd_verbose >= 3) + warn("Releasing OCIEnv %p\n", box->envhp); + (void)OCIHandleFree(box->envhp, OCI_HTYPE_ENV); +}/*}}}*/ + +/* new_envhp_box{{{*/ +static int +new_envhp_box(pTHX_ env_box_t ** slot, dblogin_info_t * ctrl) +{ + imp_dbh_t * imp_dbh = ctrl->imp_dbh; + env_box_t * box; + OCIEnv * envhp; + sword status = OCIEnvNlsCreate( + &envhp, ctrl->mode, + 0, NULL, NULL, NULL, + sizeof(*box), (dvoid**)&box, + imp_dbh->cset, imp_dbh->ncset + ); + if (status != OCI_SUCCESS) + return local_error(aTHX_ ctrl->dbh, "Failed to allocate OCIEnv"); + tracer(imp_dbh, 3, 3, "allocated new OCIEnv %p (cset %d, ncset %d, mode %d)\n", + envhp, (int)imp_dbh->cset, (int)imp_dbh->ncset, (int)ctrl->mode); + llist_init(&box->base.lock); + box->envhp = envhp; + box->base.refs = dr_instances; + box->cset = imp_dbh->cset; + box->ncset = imp_dbh->ncset; + box->mode = ctrl->mode; + llist_add(&mng_list, &box->base.lock); + *slot = box; + return TRUE; +}/*}}}*/ +/* figure_out_charsets {{{*/ +static int +figure_out_charsets(pTHX_ dblogin_info_t * ctrl) +{ + imp_dbh_t * imp_dbh = ctrl->imp_dbh; + if(ctrl->cset != NULL) + { + imp_dbh->cset = OCINlsCharSetNameToId( + mng_env, (OraText*)ctrl->cset + ); + if(imp_dbh->cset == 0) return local_error( + aTHX_ ctrl->dbh, "Invalid ora_charset '%s'", ctrl->cset + ); + } + else if(imp_dbh->cset == 0) + { + size_t rsize; + sword status = OCINlsEnvironmentVariableGet( + &imp_dbh->cset, 0, OCI_NLS_CHARSET_ID, 0, &rsize + ); + if(status != OCI_SUCCESS || imp_dbh->cset == 0) + return local_error(aTHX_ ctrl->dbh, "NLS_LANG appears to be invalid"); + } + if(ctrl->ncset != NULL) + { + imp_dbh->ncset = OCINlsCharSetNameToId( + mng_env, (OraText*)ctrl->ncset + ); + if(imp_dbh->ncset == 0) return local_error( + aTHX_ ctrl->dbh, "Invalid ora_ncharset '%s'", ctrl->ncset + ); + } + else if(imp_dbh->ncset == 0) + { + size_t rsize; + sword status = OCINlsEnvironmentVariableGet( + &imp_dbh->ncset, 0, OCI_NLS_NCHARSET_ID, 0, &rsize + ); + if(status != OCI_SUCCESS || imp_dbh->ncset == 0) + return local_error(aTHX_ ctrl->dbh, "NLS_NCHAR appears to be invalid"); + } + + return TRUE; +}/*}}}*/ +/*find_env{{{*/ +static env_box_t * +find_env(ub4 mode, ub2 cset, ub2 ncset) +{ + llist_t * base = llist_left(&mng_list); + while(base != &mng_list) + { + env_box_t * box = (env_box_t *)base; + if(box->base.refs > 0 + && box->mode == mode + && box->ncset == ncset + && box->cset == cset + ) + { + /* check if this handle is still valid */ + if(box->base.refs == dr_instances) + { + OCIError *errhp; + sword status=OCIHandleAlloc( + box->envhp, + (dvoid**)&errhp, + OCI_HTYPE_ERROR, 0, NULL + ); + if(status != OCI_SUCCESS) + { + llist_drop(base); + OCIHandleFree(box->envhp, OCI_HTYPE_ENV); + return NULL; + } + } + return box; + } + base = llist_left(base); + } + return NULL; +} +/*}}}*/ +/* simple_connect {{{*/ +static int +simple_connect(pTHX_ dblogin_info_t * ctrl) +{ + imp_dbh_t * imp_dbh = ctrl->imp_dbh; + sword status; + ub4 ulen, plen, ctype; + + tracer(imp_dbh, 3, 3, "using OCIEnv %p to connect\n", imp_dbh->envhp); + + OCIHandleAlloc_ok( + imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, + OCI_HTYPE_ERROR, status + ); + if(status != OCI_SUCCESS) + return local_error(aTHX_ ctrl->dbh, "Failed to allocate OCIError\n"); + + OCIHandleAlloc_ok( + imp_dbh, imp_dbh->envhp, &imp_dbh->srvhp, + OCI_HTYPE_SERVER, status + ); + if(status != OCI_SUCCESS) + return local_error(aTHX_ ctrl->dbh, "Failed to allocate OCIServer\n"); + + OCIHandleAlloc_ok( + imp_dbh, imp_dbh->envhp, &imp_dbh->svchp, + OCI_HTYPE_SVCCTX, status + ); + if(status != OCI_SUCCESS) + return local_error(aTHX_ ctrl->dbh, "Failed to allocate OCISvcCtx\n"); + + OCIHandleAlloc_ok( + imp_dbh, imp_dbh->envhp, &imp_dbh->seshp, + OCI_HTYPE_SESSION, status + ); + if(status != OCI_SUCCESS) + return local_error(aTHX_ ctrl->dbh, "Failed to allocate OCISession\n"); + + OCIServerAttach_log_stat(imp_dbh, ctrl->dbname,OCI_DEFAULT, status); + if (status != OCI_SUCCESS) + return oci_error(ctrl->dbh, imp_dbh->errhp, status, "OCIServerAttach"); + + OCIAttrSet_log_stat( + imp_dbh, imp_dbh->svchp, + OCI_HTYPE_SVCCTX, + imp_dbh->srvhp, + (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp, status + ); + if (status != OCI_SUCCESS) return oci_error( + ctrl->dbh, imp_dbh->errhp, status, "OCIAttrSet OCI_HTYPE_SVCCTX" + ); + plen = (ub4)strlen(ctrl->pwd); + ulen = (ub4)strlen(ctrl->uid); + if(plen == 0 && ulen == 0) ctype = OCI_CRED_EXT; + else + { + ctype = OCI_CRED_RDBMS; + OCIAttrSet_log_stat( + imp_dbh, imp_dbh->seshp, + OCI_HTYPE_SESSION, + ctrl->uid, ulen, + (ub4) OCI_ATTR_USERNAME, + imp_dbh->errhp, status + ); + if (status != OCI_SUCCESS) return oci_error( + ctrl->dbh, imp_dbh->errhp, status, "OCIAttrSet OCI_ATTR_USERNAME" + ); + + OCIAttrSet_log_stat( + imp_dbh, imp_dbh->seshp, + OCI_HTYPE_SESSION, + ((plen) ? ctrl->pwd : NULL), plen, + (ub4) OCI_ATTR_PASSWORD, + imp_dbh->errhp, status + ); + if (status != OCI_SUCCESS) return oci_error( + ctrl->dbh, imp_dbh->errhp, status, "OCIAttrSet OCI_ATTR_PASSWORD" + ); + } +#ifdef ORA_OCI_112 + if(ctrl->driver_name_len != 0) + { + OCIAttrSet_log_stat( + imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, + ctrl->driver_name, ctrl->driver_name_len, + OCI_ATTR_DRIVER_NAME, + imp_dbh->errhp, status + ); + if (status != OCI_SUCCESS) return oci_error( + ctrl->dbh, imp_dbh->errhp, status, "OCIAttrSet OCI_ATTR_DRIVER_NAME" + ); + } +#endif + + OCISessionBegin_log_stat( + imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, + ctype, ctrl->session_mode, status + ); + if (status == OCI_SUCCESS_WITH_INFO) + { + /* eg ORA-28011: the account will expire soon; change your password now */ + oci_error(ctrl->dbh, imp_dbh->errhp, status, "OCISessionBegin"); + status = OCI_SUCCESS; + } + if (status != OCI_SUCCESS) + return oci_error(ctrl->dbh, imp_dbh->errhp, status, "OCISessionBegin"); + + OCIAttrSet_log_stat( + imp_dbh, imp_dbh->svchp, + (ub4) OCI_HTYPE_SVCCTX, + imp_dbh->seshp, (ub4) 0, + (ub4) OCI_ATTR_SESSION, + imp_dbh->errhp, status + ); + if (status != OCI_SUCCESS) return oci_error( + ctrl->dbh, imp_dbh->errhp, status, "OCIAttrSet OCI_ATTR_SESSION" + ); + return TRUE; +}/*}}}*/ +#ifdef ORA_OCI_112 +/*release_pool{{{*/ +static void +release_pool(pTHX_ pool_box_t * box) +{ + env_box_t * ebox; + if(dbd_verbose >= 3) + warn("Releasing pool %p\n", box->poolhp); + + ebox = box->env; + llist_drop(&box->base.lock); + (void)OCISessionPoolDestroy (box->poolhp, box->errhp, OCI_DEFAULT); + (void)OCIHandleFree(box->poolhp, OCI_HTYPE_SPOOL); + ebox->base.refs--; + if(ebox->base.refs == 0) release_env(aTHX_ ebox); +}/*}}}*/ +/*cnx_pool_min{{{*/ +void +cnx_pool_min(pTHX_ SV * dbh, imp_dbh_t * imp_dbh, ub4 val) +{ + pool_box_t * box; + sword status; + if(imp_dbh->lock->refs > 0) return; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrSet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&val, sizeof(val), + OCI_ATTR_SPOOL_MIN, box->errhp + ); + if(status != OCI_SUCCESS) + (void)oci_error(dbh, box->errhp, status, "OCIAttrSet POOL_MIN"); +}/*}}}*/ +/*cnx_pool_max{{{*/ +void +cnx_pool_max(pTHX_ SV * dbh, imp_dbh_t * imp_dbh, ub4 val) +{ + pool_box_t * box; + sword status; + if(imp_dbh->lock->refs > 0) return; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrSet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&val, sizeof(val), + OCI_ATTR_SPOOL_MAX, box->errhp + ); + if(status != OCI_SUCCESS) + (void)oci_error(dbh, box->errhp, status, "OCIAttrSet POOL_MAX"); +}/*}}}*/ +/*cnx_pool_incr{{{*/ +void +cnx_pool_incr(pTHX_ SV * dbh, imp_dbh_t * imp_dbh, ub4 val) +{ + pool_box_t * box; + sword status; + if(imp_dbh->lock->refs > 0) return; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrSet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&val, sizeof(val), + OCI_ATTR_SPOOL_INCR, box->errhp + ); + if(status != OCI_SUCCESS) + (void)oci_error(dbh, box->errhp, status, "OCIAttrSet POOL_INCR"); +}/*}}}*/ +/*cnx_pool_mode{{{*/ +void +cnx_pool_mode(pTHX_ SV * dbh, imp_dbh_t * imp_dbh, ub4 val) +{ + pool_box_t * box; + sword status; + if(imp_dbh->lock->refs > 0) return; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrSet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&val, sizeof(val), + OCI_ATTR_SPOOL_GETMODE, box->errhp + ); + if(status != OCI_SUCCESS) + (void)oci_error(dbh, box->errhp, status, "OCIAttrSet POOL_GETMODE"); +}/*}}}*/ +/*cnx_pool_wait{{{*/ +void +cnx_pool_wait(pTHX_ SV * dbh, imp_dbh_t * imp_dbh, ub4 val) +{ + pool_box_t * box; + sword status; + if(imp_dbh->lock->refs > 0) return; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrSet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&val, sizeof(val), + OCI_ATTR_SPOOL_WAIT_TIMEOUT, box->errhp + ); + if(status != OCI_SUCCESS) + (void)oci_error(dbh, box->errhp, status, "OCIAttrSet POOL_WAIT_TIMEOUT"); +}/*}}}*/ +/*cnx_is_pooled_session{{{*/ +int +cnx_is_pooled_session(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) +{ + return (imp_dbh->lock->refs < 0); +}/*}}}*/ +/*cnx_get_pool_mode{{{*/ +int +cnx_get_pool_mode(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) +{ + pool_box_t * box; + ub4 v, l; + sword status; + if(imp_dbh->lock->refs > 0) return 0; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrGet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&v, &l, + OCI_ATTR_SPOOL_GETMODE, box->errhp + ); + if(status == OCI_SUCCESS) return (int)v; + (void)oci_error(dbh, box->errhp, status, "OCIAttrGet POOL_METHOD"); + return 0; +}/*}}}*/ +/*cnx_get_pool_wait{{{*/ +int +cnx_get_pool_wait(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) +{ + pool_box_t * box; + ub4 v, l; + sword status; + if(imp_dbh->lock->refs > 0) return 0; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrGet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&v, &l, + OCI_ATTR_SPOOL_WAIT_TIMEOUT, box->errhp + ); + if(status == OCI_SUCCESS) return (int)v; + (void)oci_error(dbh, box->errhp, status, "OCIAttrGet POOL_WAIT_TIMEOUT"); + return 0; +}/*}}}*/ +/*cnx_get_pool_used{{{*/ +int +cnx_get_pool_used(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) +{ + pool_box_t * box; + ub4 v, l; + sword status; + if(imp_dbh->lock->refs > 0) return 0; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrGet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&v, &l, + OCI_ATTR_SPOOL_BUSY_COUNT, box->errhp + ); + if(status == OCI_SUCCESS) return (int)v; + (void)oci_error(dbh, box->errhp, status, "OCIAttrGet POOL_USED"); + return 0; +}/*}}}*/ +/*cnx_get_pool_max{{{*/ +int +cnx_get_pool_max(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) +{ + pool_box_t * box; + ub4 v, l; + sword status; + if(imp_dbh->lock->refs > 0) return 0; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrGet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&v, &l, + OCI_ATTR_SPOOL_MAX, box->errhp + ); + if(status == OCI_SUCCESS) return (int)v; + (void)oci_error(dbh, box->errhp, status, "OCIAttrGet POOL_MAX"); + return 0; +}/*}}}*/ +/*cnx_get_pool_min{{{*/ +int +cnx_get_pool_min(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) +{ + pool_box_t * box; + ub4 v, l; + sword status; + if(imp_dbh->lock->refs > 0) return 0; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrGet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&v, &l, + OCI_ATTR_SPOOL_MIN, box->errhp + ); + if(status == OCI_SUCCESS) return (int)v; + (void)oci_error(dbh, box->errhp, status, "OCIAttrGet POOL_MIN"); + return 0; +}/*}}}*/ +/*cnx_get_pool_incr{{{*/ +int +cnx_get_pool_incr(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) +{ + pool_box_t * box; + ub4 v, l; + sword status; + if(imp_dbh->lock->refs > 0) return 0; + box = ((pool_box_t*)imp_dbh->lock); + status = OCIAttrGet( + box->poolhp, OCI_HTYPE_SPOOL, + (dvoid*)&v, &l, + OCI_ATTR_SPOOL_INCR, box->errhp + ); + if(status == OCI_SUCCESS) return (int)v; + (void)oci_error(dbh, box->errhp, status, "OCIAttrGet POOL_INCR"); + return 0; +}/*}}}*/ +/*cnx_get_pool_rlb{{{*/ +int +cnx_get_pool_rlb(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) +{ + if(imp_dbh->lock->refs > 0) return 0; + return (int)(((pool_box_t*)imp_dbh->lock)->buf[0]); +}/*}}}*/ +/*find_pool{{{*/ +static pool_box_t * +find_pool(dblogin_info_t * ctrl) +{ + imp_dbh_t * imp_dbh = ctrl->imp_dbh; + llist_t * base = llist_left(&mng_list); + while(base != &mng_list) + { + char * name; + pool_box_t * box = (pool_box_t *)base; + base = llist_left(base); + if(box->base.refs > 0) continue; + if(box->env->mode != ctrl->mode) continue; + if(box->env->ncset != imp_dbh->ncset) continue; + if(box->env->cset != imp_dbh->cset) continue; + name = box->buf + 2 + box->pass_len; + if(0 != strcmp(name, ctrl->dbname)) continue; + name += box->dbname_len + 1; + if(0 != strcmp(name, ctrl->uid)) continue; + if((int)(box->buf[0]) != (int)(ctrl->pool_rlb)) continue; + return box; + } + return NULL; +} +/*}}}*/ +/* new_pool_box{{{*/ +int +new_pool_box(pTHX_ pool_box_t ** slot, dblogin_info_t * ctrl) +{ + imp_dbh_t * imp_dbh = ctrl->imp_dbh; + OCIEnv * envhp = imp_dbh->envhp; + pool_box_t * box; + char * name; + OCISPool *poolhp; + ub4 mode; + ub4 dbname_len = strlen(ctrl->dbname); + ub4 user_len = strlen(ctrl->uid); + ub4 pwd_len = strlen(ctrl->pwd); + size_t boxlen = sizeof(*box) + dbname_len + user_len + pwd_len + 3; + + sword status = OCIHandleAlloc( + envhp, (dvoid*)&poolhp, OCI_HTYPE_SPOOL, boxlen, (dvoid**)&box + ); + if (status != OCI_SUCCESS) + return local_error(aTHX_ ctrl->dbh, "Failed to allocate OCISPool"); + + status = OCIHandleAlloc(envhp, (dvoid*)&box->errhp, OCI_HTYPE_ERROR, 0, NULL); + if (status != OCI_SUCCESS) + { + OCIHandleFree(poolhp, OCI_HTYPE_SPOOL); + return local_error(aTHX_ ctrl->dbh, "Failed to allocate OCIError"); + } +#ifdef ORA_OCI_112 + if(ctrl->driver_name_len != 0) + { + OCIAuthInfo * authp; + status = OCIHandleAlloc(envhp, (dvoid*)&authp, OCI_HTYPE_AUTHINFO, 0, NULL); + if(status != OCI_SUCCESS) + { + OCIHandleFree(box->errhp, OCI_HTYPE_ERROR); + OCIHandleFree(poolhp, OCI_HTYPE_SPOOL); + return local_error(aTHX_ ctrl->dbh, "Failed to allocate OCIAuthInfo"); + } + status = OCIAttrSet( + authp, OCI_HTYPE_AUTHINFO, + (OraText*)ctrl->driver_name, ctrl->driver_name_len, + OCI_ATTR_DRIVER_NAME, + box->errhp + ); + if(status != OCI_SUCCESS) + { + (void)oci_error(ctrl->dbh, box->errhp, status, "OCIAttrSet DriverName"); + OCIHandleFree(box->errhp, OCI_HTYPE_ERROR); + OCIHandleFree(authp, OCI_HTYPE_AUTHINFO); + OCIHandleFree(poolhp, OCI_HTYPE_SPOOL); + return FALSE; + } + status = OCIAttrSet( + poolhp, OCI_HTYPE_SPOOL, + authp, 0, + OCI_ATTR_SPOOL_AUTH, + box->errhp + ); + if(status != OCI_SUCCESS) + { + (void)oci_error(ctrl->dbh, box->errhp, status, "OCIAttrSet OCIAuthInfo"); + OCIHandleFree(box->errhp, OCI_HTYPE_ERROR); + OCIHandleFree(authp, OCI_HTYPE_AUTHINFO); + OCIHandleFree(poolhp, OCI_HTYPE_SPOOL); + return FALSE; + } + } +#endif + + + mode = OCI_SPC_HOMOGENEOUS; + if(!ctrl->pool_rlb) mode |= OCI_SPC_NO_RLB; + status = OCISessionPoolCreate( + envhp, + box->errhp, + poolhp, + &box->name, + &box->name_len, + (OraText *) ctrl->dbname, + dbname_len, + ctrl->pool_min, + ctrl->pool_max, + ctrl->pool_incr, + (OraText *) ctrl->uid, + user_len, + (OraText *) ctrl->pwd, + pwd_len, + mode + ); + if (status != OCI_SUCCESS) + { + (void)oci_error(ctrl->dbh, box->errhp, status, "OCISessionPoolCreate"); + OCIHandleFree(box->errhp, OCI_HTYPE_ERROR); + OCIHandleFree(poolhp, OCI_HTYPE_SPOOL); + return FALSE; + } + llist_init(&box->base.lock); + box->env = (env_box_t *)imp_dbh->lock; + box->buf[0] = ctrl->pool_rlb; + name = box->buf + 1; + strcpy(name, ctrl->pwd); + box->pass_len = pwd_len; + name += pwd_len + 1; + strcpy(name, ctrl->dbname); + box->dbname_len = dbname_len; + name += dbname_len + 1; + strcpy(name, ctrl->uid); + + box->base.refs = -dr_instances; + llist_add(&mng_list, &box->base.lock); + box->poolhp = poolhp; + + *slot = box; + return TRUE; +}/*}}}*/ +/* session_from_pool {{{*/ +static int +session_from_pool(pTHX_ dblogin_info_t * ctrl) +{ + imp_dbh_t * imp_dbh = ctrl->imp_dbh; + sword status; + OCIAuthInfo *authp; + OraText *rettag; + OraText *tag; + ub4 rettagl; + STRLEN tagl; + boolean session_tag_found; + /* try to find existing pool */ + pool_box_t * box = find_pool(ctrl); + if(box != NULL) + { + if(0 != strcmp(box->buf + 1, ctrl->pwd)) + return local_error(aTHX_ ctrl->dbh, "Password for session is wrong"); + } + else if(!new_pool_box(aTHX_ &box, ctrl)) return FALSE; + + /* replace env-box with pool-box. It shall be cleared by DESTROY */ + imp_dbh->lock = &box->base; + box->base.refs--; /* refcount for pool is negative! I know, I know... */ + + OCIHandleAlloc_ok( + imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status + ); + if(status != OCI_SUCCESS) + return local_error(aTHX_ ctrl->dbh, "OCIError alloc failed"); + + OCIHandleAlloc_ok( + imp_dbh, imp_dbh->envhp, &authp, OCI_HTYPE_AUTHINFO, status + ); + if(status != OCI_SUCCESS) + return local_error(aTHX_ ctrl->dbh, "OCIAuthInfo alloc failed"); + if(ctrl->pool_class != NULL) + { + tag = (OraText*)SvPV(ctrl->pool_class, tagl); + OCIAttrSet_log_stat( + imp_dbh, authp, + OCI_HTYPE_AUTHINFO, + tag, (ub4) tagl, + OCI_ATTR_CONNECTION_CLASS, imp_dbh->errhp, status + ); + if(status != OCI_SUCCESS) return local_error(aTHX_ ctrl->dbh, + "OCIAuthInfo setting connection class failed"); + } + + tag = NULL; + tagl = 0; + if(ctrl->pool_tag != NULL) + { + tag = (OraText*)SvPV(ctrl->pool_tag, tagl); + if(tagl == 0) tag = NULL; + } + + OCISessionGet_log_stat( + imp_dbh, imp_dbh->envhp, + imp_dbh->errhp, + &imp_dbh->svchp, + authp, + box->name, box->name_len, + tag, (ub4)tagl, + &rettag, &rettagl, &session_tag_found, + status + ); + if (status != OCI_SUCCESS) + { + (void)oci_error(ctrl->dbh, imp_dbh->errhp, status, "OCISessionGet"); + OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); + return FALSE; + } + if(session_tag_found && rettagl != 0) + { + if(imp_dbh->session_tag != NULL) SvREFCNT_dec(imp_dbh->session_tag); + imp_dbh->session_tag = newSVpv((char*)rettag, rettagl); + } + + OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); + + /* Get server and session handles from service context handle, + * allocated by OCISessionGet. */ + OCIAttrGet_log_stat( + imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, &imp_dbh->srvhp, NULL, + OCI_ATTR_SERVER, imp_dbh->errhp, status + ); + if(status != OCI_SUCCESS) + return oci_error(ctrl->dbh, imp_dbh->errhp, status, "Server get"); + OCIAttrGet_log_stat( + imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, &imp_dbh->seshp, NULL, + OCI_ATTR_SESSION, imp_dbh->errhp, status + ); + if(status != OCI_SUCCESS) + return oci_error(ctrl->dbh, imp_dbh->errhp, status, "Session get"); + + return 1; +} +/*}}}*/ +#endif + +#if defined(USE_ITHREADS) +static int _cnx_establish +#else +int cnx_establish +#endif +(pTHX_ dblogin_info_t * ctrl) +{ + imp_dbh_t * imp_dbh = ctrl->imp_dbh; + env_box_t * env_box; + + if(!figure_out_charsets(aTHX_ ctrl)) return FALSE; + /* try to find existing OCIEnv */ + env_box = find_env(ctrl->mode, imp_dbh->cset, imp_dbh->ncset); + if(env_box == NULL && !new_envhp_box(aTHX_ &env_box, ctrl)) return FALSE; + + env_box->base.refs++; + imp_dbh->envhp = env_box->envhp; + imp_dbh->lock = &env_box->base; + imp_dbh->errhp = NULL; + imp_dbh->srvhp = NULL; + imp_dbh->svchp = NULL; + imp_dbh->seshp = NULL; + /* Now I want DESTROY to be called if something goes wrong */ + DBIc_IMPSET_on(imp_dbh); +#ifdef ORA_OCI_112 + if(ctrl->pool_max != 0) + return session_from_pool(aTHX_ ctrl); +#endif + return simple_connect(aTHX_ ctrl); +} + +#if defined(USE_ITHREADS) +int +cnx_establish(pTHX_ dblogin_info_t * ctrl) +{ + int rv; + MUTEX_LOCK(&mng_lock); + rv = _cnx_establish(aTHX_ ctrl); + MUTEX_UNLOCK(&mng_lock); + return rv; +} +#endif + +/*dbd_dr_mng{{{ + * this function is called every time new DR object is created. + * It is responsible for incrementing refs on all cached objects + */ +void +dbd_dr_mng() +{ + llist_t * el; +#if defined(USE_ITHREADS) + dTHX; + MUTEX_LOCK(&mng_lock); +#endif + dr_instances++; + el = llist_left(&mng_list); + while(el != &mng_list) + { + box_t * base = (box_t *)el; +#ifdef ORA_OCI_112 + if(base->refs < 0) base->refs--; + else +#endif + base->refs++; + el = llist_left(el); + } + if(mng_env == NULL) + { + sword status = OCIEnvNlsCreate( + &mng_env, OCI_DEFAULT, + 0, NULL, NULL, NULL, + 0, NULL, 0, 0 + ); + if(status == OCI_SUCCESS) + status=OCIHandleAlloc( + mng_env, + (dvoid**)&mng_err, + OCI_HTYPE_ERROR, + 0, NULL + ); + utf8_csid = OCINlsCharSetNameToId(mng_env, (void*)"UTF8"); + al32utf8_csid = OCINlsCharSetNameToId(mng_env, (void*)"AL32UTF8"); + al16utf16_csid = OCINlsCharSetNameToId(mng_env, (void*)"AL16UTF16"); + } +#if defined(USE_ITHREADS) + MUTEX_UNLOCK(&mng_lock); +#endif +} +/*}}}*/ + +/* cnx_detach{{{*/ +void +cnx_detach(pTHX_ imp_dbh_t * imp_dbh) +{ + /* Oracle will commit on an orderly disconnect. */ + /* See DBI Driver.xst file for the DBI approach. */ +#ifdef ORA_OCI_112 + if (imp_dbh->lock->refs < 0) + { + /* Release session, tagged for future retrieval. */ + if(imp_dbh->session_tag != NULL) + { + STRLEN tlen; + char * tag = SvPV(imp_dbh->session_tag, tlen); + (void)OCISessionRelease( + imp_dbh->svchp, imp_dbh->errhp, + (OraText*)tag, (ub4)tlen, OCI_SESSRLS_RETAG + ); + SvREFCNT_dec(imp_dbh->session_tag); + imp_dbh->session_tag = NULL; + } + else (void)OCISessionRelease( + imp_dbh->svchp, imp_dbh->errhp, + NULL, 0, OCI_DEFAULT + ); + /* all handles are gone now */ + imp_dbh->seshp = NULL; + imp_dbh->svchp = NULL; + imp_dbh->srvhp = NULL; + } + else { +#endif + (void)OCISessionEnd( + imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, OCI_DEFAULT + ); + (void)OCIServerDetach(imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT); +#ifdef ORA_OCI_112 + } +#endif +}/*}}}*/ +/*cnx_clean{{{*/ +void +cnx_clean(pTHX_ imp_dbh_t * imp_dbh) +{ + if(imp_dbh->errhp != NULL) + { + (void)OCIHandleFree(imp_dbh->errhp, OCI_HTYPE_ERROR); + imp_dbh->errhp = NULL; + } + if(imp_dbh->seshp != NULL) + { + (void)OCIHandleFree(imp_dbh->seshp, OCI_HTYPE_SESSION); + imp_dbh->seshp = NULL; + } + if(imp_dbh->svchp != NULL) + { + (void)OCIHandleFree(imp_dbh->svchp, OCI_HTYPE_SVCCTX); + imp_dbh->svchp = NULL; + } + if(imp_dbh->srvhp != NULL) + { + (void)OCIHandleFree(imp_dbh->srvhp, OCI_HTYPE_SERVER); + imp_dbh->srvhp = NULL; + } + +#ifdef ORA_OCI_112 + if(imp_dbh->lock->refs < 0) + { + imp_dbh->lock->refs++; + if(imp_dbh->lock->refs == 0) + release_pool(aTHX_ (pool_box_t *)imp_dbh->lock); + } + else + { +#endif + imp_dbh->lock->refs--; + if(imp_dbh->lock->refs == 0) + release_env(aTHX_ (env_box_t *)imp_dbh->lock); +#ifdef ORA_OCI_112 + } +#endif +}/*}}}*/ + +void +cnx_drop_dr(pTHX_ imp_drh_t * imp_drh) +{ + llist_t * el; +#if defined(USE_ITHREADS) + MUTEX_LOCK(&mng_lock); +#endif + dr_instances--; + el = llist_left(&mng_list); + while(el != &mng_list) + { + box_t * base = (box_t *)el; +#ifdef ORA_OCI_112 + int is_pool = 0; + if(base->refs < 0) + { + base->refs++; + is_pool = 1; + } + else +#endif + base->refs--; + el = llist_left(el); + if(base->refs == 0) + { +#ifdef ORA_OCI_112 + if(is_pool) + release_pool(aTHX_ (pool_box_t *)base); + else +#endif + release_env(aTHX_ (env_box_t *)base); + } + } +#if defined(USE_ITHREADS) + MUTEX_UNLOCK(&mng_lock); +#endif +} + +/* in vim: set foldmethod=marker: */ diff --git a/dbdimp.c b/dbdimp.c index 30449d81..d16408b6 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -13,10 +13,10 @@ #define strcasecmp strcmpi #endif -#ifdef __CYGWIN32__ -#include "w32api/windows.h" -#include "w32api/winbase.h" -#endif /* __CYGWIN32__ */ +#if defined(__CYGWIN__) || defined(__CYGWIN32__) +#include +#include +#endif /* __CYGWIN__ */ #include "Oracle.h" @@ -32,7 +32,6 @@ DBISTATE_DECLARE; int ora_fetchtest; /* internal test only, not thread safe */ -int is_extproc = 0; /* not ProC but ExtProc.pm */ int dbd_verbose = 0; /* DBD only debugging*/ int oci_warn = 0; /* show oci warnings */ int ora_objects = 0; /* get oracle embedded objects as instance of DBD::Oracle::Object */ @@ -44,13 +43,14 @@ int ora_ncs_buff_mtpl = 4; /* a mulitplyer for ncs clob buffers */ #define ARRAY_BIND_MIXED (ARRAY_BIND_NATIVE|ARRAY_BIND_UTF8) -ub2 charsetid = 0; -ub2 ncharsetid = 0; ub2 us7ascii_csid = 1; ub2 utf8_csid = 871; ub2 al32utf8_csid = 873; ub2 al16utf16_csid = 2000; +/* reduce noise in the login6 function */ +#define tracer(dlvl, vlvl, ...) if (DBIc_DBISTATE(imp_dbh)->debug >= (dlvl) || dbd_verbose >= (vlvl) )\ + PerlIO_printf(DBIc_LOGPIO(imp_dbh), __VA_ARGS__) typedef struct sql_fbh_st sql_fbh_t; struct sql_fbh_st { @@ -58,9 +58,18 @@ struct sql_fbh_st { int prec; int scale; }; +typedef struct login_info_st login_info_t; +struct login_info_st { + SV * dbh; + imp_dbh_t * imp_dbh; + char *dbname; + char *uid; + char *pwd; + ub4 mode; +}; static sql_fbh_t ora2sql_type _((imp_fbh_t* fbh)); static void disable_taf(imp_dbh_t *imp_dbh); -static int enable_taf(SV *dbh, imp_dbh_t *imp_dbh); +static int enable_taf(pTHX_ SV *dbh, imp_dbh_t *imp_dbh); void ora_free_phs_contents _((imp_sth_t *imp_sth, phs_t *phs)); static void dump_env_to_trace(imp_dbh_t *imp_dbh); @@ -116,6 +125,28 @@ oci_error_get(imp_xxh_t *imp_xxh, return errcode; } + +/* report to DBI errors that are not comming from Oracle */ +static int +local_error(pTHX_ SV * h, const char * fmt, ...) +{ + va_list ap; + SV * txt_sv = sv_newmortal(); + SV * code_sv = get_sv("DBI::stderr", 0); + D_imp_xxh(h); + if(code_sv == NULL) + { + code_sv = sv_newmortal(); + sv_setiv(code_sv, 2000000000); + } + va_start(ap, fmt); + sv_vsetpvf(txt_sv, fmt, &ap); + va_end(ap); + DBIh_SET_ERR_SV(h, imp_xxh, code_sv, txt_sv, &PL_sv_undef, &PL_sv_undef); + return FALSE; +} + + static int GetRegKey(char *key, char *val, char *data, unsigned long *size) { @@ -127,7 +158,7 @@ GetRegKey(char *key, char *val, char *data, unsigned long *size) ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE, &hKey); if (ret != ERROR_SUCCESS) return 0; - ret = RegQueryValueEx(hKey, val, NULL, NULL, data, size); + ret = RegQueryValueEx(hKey, val, NULL, NULL, (LPBYTE)data, size); RegCloseKey(hKey); if ((ret != ERROR_SUCCESS) || (*size >= len)) return 0; @@ -164,7 +195,7 @@ ora_env_var(char *name, char *buf, unsigned long size) return buf; } -#ifdef __CYGWIN32__ +#if defined(__CYGWIN__) || defined(__CYGWIN32__) /* Under Cygwin there are issues with setting environment variables * at runtime such that Windows-native libraries loaded by a Cygwin * process can see those changes. @@ -190,9 +221,25 @@ ora_cygwin_set_env(char *name, char *value) { SetEnvironmentVariable(name, value); } -#endif /* __CYGWIN32__ */ +#endif /* __CYGWIN__ */ +void +ora_shared_release(pTHX_ SV * sv) +{ + STRLEN len; + imp_dbh_t *imp_dbh; + while (SvROK(sv)) sv = SvRV(sv) ; + imp_dbh = (imp_dbh_t *)SvPV(sv, len); + if(len == sizeof(*imp_dbh)) + { + if(dbd_verbose >= 3) + warn("clearing shared session %p\n", imp_dbh->seshp); + cnx_detach(aTHX_ imp_dbh); + cnx_clean(aTHX_ imp_dbh); + } +} + void dbd_init(dbistate_t *dbistate) { @@ -201,44 +248,13 @@ dbd_init(dbistate_t *dbistate) dbd_init_oci(dbistate); } - void dbd_dr_destroy(SV *drh, imp_drh_t *imp_drh) { dTHX; - sword status; - - /* We rely on the DBI dispatcher to destroy all child handles before we get here (DBI >= 1.623). */ - - if (imp_drh->leak_handles) { - /* By using ithread, handles will leak in dbd_dr_destroy() */ - return; - } - -#ifdef ORA_OCI_112 - /* Free session pool resources. */ - if (imp_drh->pool_hv) { - HE *pool_he; - hv_iterinit(imp_drh->pool_hv); - while ((pool_he = hv_iternext(imp_drh->pool_hv))) { - session_pool_t *pool = (session_pool_t*)SvPVX(HeVAL(pool_he)); - /* Only destroy the session pool if there are no active sessions left. - If there are active sessions left, this is because "InactiveDestroy" - is set on one or more db handles. */ - if (!pool->active_sessions) { - OCISessionPoolDestroy_log_stat(imp_drh, pool->poolhp, pool->errhp, status); - } - OCIHandleFree_log_stat(imp_drh, pool->poolhp, OCI_HTYPE_SPOOL, status); - OCIHandleFree_log_stat(imp_drh, pool->errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(imp_drh, pool->envhp, OCI_HTYPE_ENV, status); - } - hv_undef(imp_drh->pool_hv); - } - - if (imp_drh->charset_hv) { - hv_undef(imp_drh->charset_hv); - } -#endif + if (dbd_verbose >= 3 ) + PerlIO_printf(DBIc_LOGPIO(imp_drh), "dr_destroy %p\n", imp_drh); + cnx_drop_dr(aTHX_ imp_drh); } @@ -402,24 +418,6 @@ fb_ary_free(fb_ary_t *fb_ary) } -#ifdef ORA_OCI_112 -/* Helper functions to fetch cached session pool. */ -static SV * -pool_key(imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, int csid, int ncsid) -{ - return newSVpvf("%s/%s@%s class=%.*s,csid=%d,ncsid=%d", uid, pwd, dbname, imp_dbh->pool_classl, imp_dbh->pool_class, csid, ncsid); -} - -static session_pool_t * -pool_fetch(imp_drh_t *imp_drh, SV *key) -{ - dTHX; - HE *pool_he = hv_fetch_ent(imp_drh->pool_hv, key, 0, 0); - return pool_he ? (session_pool_t *)SvPVX(HeVAL(pool_he)) : NULL; -} -#endif - - /* ================================================================== */ @@ -430,14 +428,58 @@ dbd_db_login(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd) } -/* from shared.xs */ -typedef struct { - SV *sv; /* The actual SV - in shared space */ - /* we don't need the following two */ - /*recursive_lock_t lock; */ - /*perl_cond user_cond;*/ /* For user-level conditions */ -} shared_sv; +static sword +get_env_charset(OCIEnv *envhp, OCIError * errhp, ub2 * charset_p, ub2 * ncharset_p) +{ + sword status = OCIAttrGet(envhp, OCI_HTYPE_ENV, + charset_p, NULL, + OCI_ATTR_ENV_CHARSET_ID,errhp + ); + if (status != OCI_SUCCESS) return status; + return OCIAttrGet(envhp, OCI_HTYPE_ENV, + ncharset_p, NULL, + OCI_ATTR_ENV_NCHARSET_ID,errhp + ); +} +/* this function makes final adjustments to connected handle */ +static int +activate_dbh(pTHX_ dblogin_info_t * ctrl) +{ + imp_dbh_t * imp_dbh = ctrl->imp_dbh; + DBIc_IMPSET_on(imp_dbh); /* just in case */ + DBIc_ACTIVE_on(imp_dbh); /* call disconnect before freeing */ + imp_dbh->ph_type = 1; /* SQLT_CHR "(ORANET TYPE) character string" */ + imp_dbh->ph_csform = 0; /* meaning auto (see dbd_rebind_ph) */ + + if (DBIc_DBISTATE(imp_dbh)->debug >= 3 || dbd_verbose >= 3 ) { + sword status; + oratext charsetname[OCI_NLS_MAXBUFSZ]; + oratext ncharsetname[OCI_NLS_MAXBUFSZ]; + ub2 charsetid_l = 0; + ub2 ncharsetid_l = 0; + + /* Report charsets used in the environment */ + status = get_env_charset(imp_dbh->envhp, imp_dbh->errhp, &charsetid_l, &ncharsetid_l); + if (status != OCI_SUCCESS) { + oci_error(ctrl->dbh, imp_dbh->errhp, status, + "OCIAttrGet OCI_ATTR_ENV_CHARSET_ID"); + return 0; + } + OCINlsCharSetIdToName(imp_dbh->envhp,charsetname, sizeof(charsetname),charsetid_l ); + OCINlsCharSetIdToName(imp_dbh->envhp,ncharsetname, sizeof(ncharsetname),ncharsetid_l ); + PerlIO_printf( DBIc_LOGPIO(imp_dbh), + " charset id=%d, name=%s, ncharset id=%d, name=%s, session=%p" + " (csid: utf8=%d al32utf8=%d)\n", + charsetid_l,charsetname, ncharsetid_l,ncharsetname, imp_dbh->seshp, + utf8_csid, al32utf8_csid); +#ifdef ORA_OCI_112 + if (ctrl->pool_max) + PerlIO_printf(DBIc_LOGPIO(imp_dbh)," Using DRCP Connection\n "); +#endif + } + return TRUE; +} int @@ -445,610 +487,213 @@ dbd_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *uid, char *pwd, S { dTHR; dTHX; - sword status; + dblogin_info_t ctrl = {0}; SV **svp; - shared_sv * shared_dbh_ssv = NULL ; - imp_dbh_t * shared_dbh = NULL ; - D_imp_drh_from_dbh; - ub2 new_charsetid = 0; - ub2 new_ncharsetid = 0; #if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) - SV ** shared_dbh_priv_svp ; - SV * shared_dbh_priv_sv ; STRLEN shared_dbh_len = 0 ; + SV * shared_sv = NULL; #endif -#ifdef ORA_OCI_112 - session_pool_t *pool = NULL; - - /*check to see if the user is connecting with DRCP */ - if (DBD_ATTRIB_TRUE(attr,"ora_drcp",8,svp)) - imp_dbh->using_drcp = 1; - - /* some connection pool attributes */ - - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_drcp_class", 14)) && SvOK(*svp)) { - STRLEN svp_len; - if (!SvPOK(*svp)) - croak("ora_drcp_class is not a string"); - imp_dbh->pool_class = (text *) SvPV (*svp, svp_len ); - imp_dbh->pool_classl= (ub4) svp_len; - } - if (DBD_ATTRIB_TRUE(attr,"ora_drcp_min",12,svp)) - DBD_ATTRIB_GET_IV( attr, "ora_drcp_min", 12, svp, imp_dbh->pool_min); - if (DBD_ATTRIB_TRUE(attr,"ora_drcp_max",12,svp)) - DBD_ATTRIB_GET_IV( attr, "ora_drcp_max", 12, svp, imp_dbh->pool_max); - if (DBD_ATTRIB_TRUE(attr,"ora_drcp_incr",13,svp)) - DBD_ATTRIB_GET_IV( attr, "ora_drcp_incr", 13, svp, imp_dbh->pool_incr); - if (DBD_ATTRIB_TRUE(attr,"ora_drcp_rlb",12,svp)) - DBD_ATTRIB_GET_IV( attr, "ora_drcp_rlb", 12, svp, imp_dbh->pool_rlb); - - imp_dbh->driver_name = "DBD::Oracle : " VERSION; -#endif - - /* TAF Events */ - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_taf_function", 16)) && SvOK(*svp)) { - if ((SvROK(*svp) && (SvTYPE(SvRV(*svp)) == SVt_PVCV)) || - (SvPOK(*svp))) { - imp_dbh->taf_function = newSVsv(*svp); - } else { - croak("ora_taf_function needs to be a string or code reference"); - } - /* avoid later STORE: */ - /* See DBI::DBB problem with ATTRIB_DELETE until DBI 1.607 */ - /* DBD_ATTRIB_DELETE(attr, "ora_taf_function", 16); */ - (void)hv_delete((HV*)SvRV(attr), "ora_taf_function", 16, G_DISCARD); - } - - imp_dbh->server_version = 0; - /* check to see if DBD_verbose or ora_verbose is set*/ - if (DBD_ATTRIB_TRUE(attr,"dbd_verbose",11,svp)) - DBD_ATTRIB_GET_IV( attr, "dbd_verbose", 11, svp, dbd_verbose); - if (DBD_ATTRIB_TRUE(attr,"ora_verbose",11,svp)) - DBD_ATTRIB_GET_IV( attr, "ora_verbose", 11, svp, dbd_verbose); + DBD_ATTRIB_GET_IV( attr, "dbd_verbose", 11, svp, dbd_verbose); + DBD_ATTRIB_GET_IV( attr, "ora_verbose", 11, svp, dbd_verbose); if (DBIc_DBISTATE(imp_dbh)->debug >= 6 || dbd_verbose >= 6 ) dump_env_to_trace(imp_dbh); /* dbi_imp_data code adapted from DBD::mysql */ - if (DBIc_has(imp_dbh, DBIcf_IMPSET)) { - /* dbi_imp_data from take_imp_data */ - if (DBIc_has(imp_dbh, DBIcf_ACTIVE)) { - if (DBIc_DBISTATE(imp_dbh)->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBIc_LOGPIO(imp_dbh), "dbd_db_login6 skip connect\n"); - /* tell our parent we've adopted an active child */ - ++DBIc_ACTIVE_KIDS(DBIc_PARENT_COM(imp_dbh)); - - return 1; - } - /* not ACTIVE so connect not skipped */ - if (DBIc_DBISTATE(imp_dbh)->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBIc_LOGPIO(imp_dbh), - "dbd_db_login6 IMPSET but not ACTIVE so connect not skipped\n"); - } - - imp_dbh->envhp = imp_drh->envhp; /* will be NULL on first connect */ - -#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) - shared_dbh_priv_svp = (DBD_ATTRIB_OK(attr)?hv_fetch((HV*)SvRV(attr), "ora_dbh_share", 13, 0):NULL) ; - shared_dbh_priv_sv = shared_dbh_priv_svp?*shared_dbh_priv_svp:NULL ; - - if (shared_dbh_priv_sv && SvROK(shared_dbh_priv_sv)) - shared_dbh_priv_sv = SvRV(shared_dbh_priv_sv) ; - - if (shared_dbh_priv_sv) { - MAGIC * mg ; - - SvLOCK (shared_dbh_priv_sv) ; - - /* some magic from shared.xs (no public api yet :-( */ - mg = mg_find(shared_dbh_priv_sv, PERL_MAGIC_shared_scalar) ; - - shared_dbh_ssv = (shared_sv * )(mg?mg -> mg_ptr:NULL) ; /*sharedsv_find(*shared_dbh_priv_sv) ;*/ - - if (!shared_dbh_ssv) - croak ("value of ora_dbh_share must be a scalar that is shared") ; - - shared_dbh = (imp_dbh_t *)SvPVX(shared_dbh_ssv -> sv) ; - shared_dbh_len = SvCUR((shared_dbh_ssv -> sv)) ; - - if (shared_dbh_len > 0 && shared_dbh_len != sizeof (imp_dbh_t)) - croak ("Invalid value for ora_dbh_share") ; - - if (shared_dbh_len == sizeof (imp_dbh_t)) { - /* initialize from shared data */ - memcpy (((char *)imp_dbh) + DBH_DUP_OFF, ((char *)shared_dbh) + DBH_DUP_OFF, DBH_DUP_LEN) ; - shared_dbh -> refcnt++ ; - imp_dbh -> shared_dbh_priv_sv = shared_dbh_priv_sv ; - imp_dbh -> shared_dbh = shared_dbh ; - if (DBIc_DBISTATE(imp_dbh)->debug >= 2 || dbd_verbose >= 3 ) - PerlIO_printf(DBIc_LOGPIO(imp_dbh), " dbd_db_login: use shared Oracle database handles.\n"); - } else { - shared_dbh = NULL ; - } - - /* By using ithread, handles will leak in dbd_dr_destroy() */ - imp_drh->leak_handles = 1; - } -#endif - - imp_dbh->get_oci_handle = oci_db_handle; - -#ifdef ORA_OCI_112 - if (!imp_dbh->using_drcp) { -#endif - if ((svp=DBD_ATTRIB_GET_SVP(attr, "ora_envhp", 9)) && SvOK(*svp)) { - if (!SvTRUE(*svp)) { - imp_dbh->envhp = NULL; /* force new environment */ - } - } - /* Test if a cached environment handle it still usable (see RT46739) */ - if (imp_dbh->envhp) { - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); - if (status != OCI_SUCCESS) { - imp_dbh->envhp = NULL; - } - } -#ifdef ORA_OCI_112 - } - else if (!shared_dbh) { - /* Try to find session pool in cache. */ - imp_dbh->envhp = NULL; - - if (!imp_drh->charset_hv) { - imp_drh->charset_hv = newHV(); - } - if (!imp_drh->pool_hv) { - imp_drh->pool_hv = newHV(); - } - - /* Get charset and ncharset IDs. */ - if ((svp = DBD_ATTRIB_GET_SVP(attr, "ora_charset", 11))) { - /* Charset name from parameter; try looking up previously used ID. */ - HE *charset_he = hv_fetch_ent(imp_drh->charset_hv, *svp, 0, 0); - charsetid = charset_he ? SvIV(HeVAL(charset_he)) : 0; - } - else { - /* Get charset ID from the NLS environment. */ - size_t rsize; - OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &charsetid, 0, OCI_NLS_CHARSET_ID, 0, &rsize, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, NULL, status, - "OCINlsEnvironmentVariableGet(OCI_NLS_CHARSET_ID) Check NLS settings etc."); - return 0; - } - } - if ((svp = DBD_ATTRIB_GET_SVP(attr, "ora_ncharset", 12))) { - /* Charset name from parameter; try looking up previously used ID. */ - HE *charset_he = hv_fetch_ent(imp_drh->charset_hv, *svp, 0, 0); - ncharsetid = charset_he ? SvIV(HeVAL(charset_he)) : 0; - } - else { - /* Get charset ID from the NLS environment. */ - size_t rsize; - OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &ncharsetid, 0, OCI_NLS_NCHARSET_ID, 0, &rsize, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, NULL, status, - "OCINlsEnvironmentVariableGet(OCI_NLS_NCHARSET_ID) Check NLS settings etc."); - return 0; - } - } - - if (charsetid && ncharsetid) { - /* Look up session pool initialized with the same dbname, uid/pwd, connection class, and charsets. */ - SV *key_sv = pool_key(imp_dbh, dbname, uid, pwd, charsetid, ncharsetid); - - if ((pool = pool_fetch(imp_drh, key_sv))) { - imp_dbh->pool = pool; - imp_dbh->envhp = pool->envhp; - } - - sv_free(key_sv); - } + if (DBIc_has(imp_dbh, DBIcf_IMPSET)) + { + /* dbi_imp_data from take_imp_data */ + if (DBIc_has(imp_dbh, DBIcf_ACTIVE)) + { + tracer(2, 3, "dbd_db_login6 impset. Env is %p\n", imp_dbh->envhp); + /* tell our parent we've adopted an active child */ + ++DBIc_ACTIVE_KIDS(DBIc_PARENT_COM(imp_dbh)); + return TRUE; + } + /* not ACTIVE so connect not skipped */ + tracer(2, 3, "dbd_db_login6 IMPSET but not ACTIVE\n"); } -#endif - - if (!imp_dbh->envhp ) { - SV **init_mode_sv; - ub4 init_mode = OCI_OBJECT;/* needed for LOBs (8.0.4) */ - if (DBD_ATTRIB_TRUE(attr, "ora_events", 10, svp)) - init_mode |= OCI_EVENTS; /* Needed for Oracle Fast Application Notification (FAN). */ + ctrl.mode = OCI_OBJECT;/* needed for LOBs (8.0.4) */ + if (DBD_ATTRIB_TRUE(attr, "ora_events", 10, svp)) + { + ctrl.mode |= OCI_EVENTS; + /* Needed for Oracle Fast Application Notification (FAN). */ + } - DBD_ATTRIB_GET_IV(attr, "ora_init_mode",13, init_mode_sv, init_mode); + /* Undocumented, this overrides all previous settings */ + DBD_ATTRIB_GET_IV(attr, "ora_init_mode",13, svp, ctrl.mode); #if defined(USE_ITHREADS) || defined(MULTIPLICITY) || defined(USE_5005THREADS) - init_mode |= OCI_THREADED; + ctrl.mode |= OCI_THREADED; #endif - - { - size_t rsize = 0; - /* Get CLIENT char and nchar charset id values */ - OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &charsetid,(size_t) 0, OCI_NLS_CHARSET_ID, 0, &rsize ,status ); - if (status != OCI_SUCCESS) { - oci_error(dbh, NULL, status, - "OCINlsEnvironmentVariableGet(OCI_NLS_CHARSET_ID) Check NLS settings etc."); - return 0; - } - - OCINlsEnvironmentVariableGet_log_stat(imp_dbh, &ncharsetid,(size_t) 0, OCI_NLS_NCHARSET_ID, 0, &rsize ,status ); - if (status != OCI_SUCCESS) { - oci_error(dbh, NULL, status, - "OCINlsEnvironmentVariableGet(OCI_NLS_NCHARSET_ID) Check NLS settings etc."); - return 0; - } - - /*{ - After using OCIEnvNlsCreate() to create the environment handle, - **the actual lengths and returned lengths of bind and define handles are - always in number of bytes**. This applies to the following calls: - - * OCIBindByName() * OCIBindByPos() * OCIBindDynamic() - * OCIDefineByPos() * OCIDefineDynamic() - - This function enables you to set charset and ncharset ids at - environment creation time. [...] - - This function sets nonzero charset and ncharset as client side - database and national character sets, replacing the ones specified - by NLS_LANG and NLS_NCHAR. When charset and ncharset are 0, it - behaves exactly the same as OCIEnvCreate(). Specifically, charset - controls the encoding for metadata and data with implicit form - attribute and ncharset controls the encoding for data with SQLCS_NCHAR - form attribute. - }*/ - - OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, NULL, - charsetid, ncharsetid, status ); - - if (status != OCI_SUCCESS) { - oci_error(dbh, NULL, status, - "OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc."); - return 0; - } - - svp = DBD_ATTRIB_GET_SVP(attr, "ora_charset", 11);/*get the charset passed in by the user*/ - if (svp) { - if (!SvPOK(*svp)) { - croak("ora_charset is not a string"); - } - - new_charsetid = OCINlsCharSetNameToId(imp_dbh->envhp, (oratext*)SvPV_nolen(*svp)); - - if (!new_charsetid) { - croak("ora_charset value (%s) is not valid", SvPV_nolen(*svp)); - } - -#ifdef ORA_OCI_112 - if (imp_dbh->using_drcp) { - /* Store lookup from charset name to charset ID. */ - (void)hv_store_ent(imp_drh->charset_hv, *svp, newSViv(new_charsetid), 0); - } -#endif - } - - svp = DBD_ATTRIB_GET_SVP(attr, "ora_ncharset", 12); /*get the ncharset passed in by the user*/ - - if (svp) { - if (!SvPOK(*svp)) { - croak("ora_ncharset is not a string"); - } - - new_ncharsetid = OCINlsCharSetNameToId(imp_dbh->envhp, (oratext*)SvPV_nolen(*svp)); - if (!new_ncharsetid) { - croak("ora_ncharset value (%s) is not valid", SvPV_nolen(*svp)); - } - -#ifdef ORA_OCI_112 - if (imp_dbh->using_drcp) { - /* Store lookup from charset name to charset ID. */ - (void)hv_store_ent(imp_drh->charset_hv, *svp, newSViv(new_ncharsetid), 0); - } -#endif - } - - if (new_charsetid || new_ncharsetid) { /* reset the ENV with the new charset from above*/ - if (new_charsetid) charsetid = new_charsetid; - if (new_ncharsetid) ncharsetid = new_ncharsetid; - OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); - OCIEnvNlsCreate_log_stat(imp_dbh, &imp_dbh->envhp, init_mode, 0, NULL, NULL, NULL, 0, 0, - charsetid, ncharsetid, status ); - if (status != OCI_SUCCESS) { - oci_error(dbh, NULL, status, - "OCIEnvNlsCreate. Check ORACLE_HOME (Linux) env var or PATH (Windows) and or NLS settings, permissions, etc"); - return 0; - } - } + ctrl.dbname = dbname; + ctrl.dbh = dbh; + ctrl.imp_dbh = imp_dbh; + ctrl.uid = uid; + ctrl.pwd = pwd; #ifdef ORA_OCI_112 - if (!imp_dbh->using_drcp) -#endif - if (!imp_drh->envhp) /* cache first envhp info drh as future default */ - imp_drh->envhp = imp_dbh->envhp; - - /* update the hard-coded csid constants for unicode charsets */ - utf8_csid = OCINlsCharSetNameToId(imp_dbh->envhp, (void*)"UTF8"); - al32utf8_csid = OCINlsCharSetNameToId(imp_dbh->envhp, (void*)"AL32UTF8"); - al16utf16_csid = OCINlsCharSetNameToId(imp_dbh->envhp, (void*)"AL16UTF16"); - } - -#ifdef ORA_OCI_112 - if (imp_dbh->using_drcp) { - /* Try looking up session pool again, in case ora_charsetid/ora_ncharsetid were used to specify previously used charset IDs from the NLS environment. */ - SV *key_sv = pool_key(imp_dbh, dbname, uid, pwd, charsetid, ncharsetid); - - if ((pool = pool_fetch(imp_drh, key_sv))) { - imp_dbh->pool = pool; - /* Free the current environment handle and replace it with the session pool's environment handle. */ - OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); - imp_dbh->envhp = pool->envhp; - } + /*check to see if the user is connecting with DRCP */ + if (DBD_ATTRIB_TRUE(attr,"ora_drcp",8,svp)) + { + ctrl.pool_max = 40; + hv_delete((HV*)SvRV(attr), "ora_drcp", 8, G_DISCARD); + } - sv_free(key_sv); - } + /* some connection pool attributes */ + if(ctrl.pool_max) + { + svp = DBD_ATTRIB_GET_SVP(attr, "ora_drcp_min",12); + if (svp != NULL) + { + ctrl.pool_min = SvIV(*svp); + hv_delete((HV*)SvRV(attr), "ora_drcp_min", 12, G_DISCARD); + } + svp = DBD_ATTRIB_GET_SVP(attr,"ora_drcp_max",12); + if (svp != NULL) + { + ctrl.pool_max = SvIV(*svp); + if (ctrl.pool_max == 0) ctrl.pool_max = 40; + hv_delete((HV*)SvRV(attr), "ora_drcp_max", 12, G_DISCARD); + } + svp = DBD_ATTRIB_GET_SVP(attr,"ora_drcp_incr",13); + if (svp != NULL) + { + ctrl.pool_incr = SvIV(*svp); + hv_delete((HV*)SvRV(attr), "ora_drcp_incr", 13, G_DISCARD); + } + svp = DBD_ATTRIB_GET_SVP(attr,"ora_drcp_rlb",12); + if (svp != NULL) + { + ctrl.pool_rlb = (0 != SvIV(*svp)) ? 1 : 0; + hv_delete((HV*)SvRV(attr), "ora_drcp_rlb", 12, G_DISCARD); + } + svp = DBD_ATTRIB_GET_SVP(attr,"ora_drcp_class",14); + if (svp != NULL) + ctrl.pool_class = hv_delete((HV*)SvRV(attr), "ora_drcp_class", 14, 0); + /* save session tag to be used during session-get + * it won't be passed to STORE. The found tag shall + * be stored in imp_dbh->session_tag + */ + svp = DBD_ATTRIB_GET_SVP(attr,"ora_drcp_tag",12); + if (svp != NULL) + ctrl.pool_tag = hv_delete((HV*)SvRV(attr), "ora_drcp_tag", 12, 0); + /* pool Default values */ + if (!ctrl.pool_incr) ctrl.pool_incr = 1; + } + svp = DBD_ATTRIB_GET_SVP(attr,"ora_driver_name",15); + if (svp != NULL) + { + STRLEN l; + SV * v = hv_delete((HV*)SvRV(attr), "ora_driver_name", 15, 0); + ctrl.driver_name = SvPV(v, l); + ctrl.driver_name_len = (ub4)l; + } + else + { + ctrl.driver_name = "DBD::Oracle : " VERSION; + ctrl.driver_name_len = strlen(ctrl.driver_name); + } #endif - } - - if (!imp_dbh->errhp) { - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->errhp, OCI_HTYPE_ERROR, status); - } - - OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &charsetid, NULL, - OCI_ATTR_ENV_CHARSET_ID, imp_dbh->errhp, status); - - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCIAttrGet OCI_ATTR_ENV_CHARSET_ID"); - return 0; - } + /* TAF Events shall be processed from STORE*/ - OCIAttrGet_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, &ncharsetid, NULL, - OCI_ATTR_ENV_NCHARSET_ID, imp_dbh->errhp, status); + imp_dbh->server_version = 0; + imp_dbh->get_oci_handle = oci_db_handle; - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCIAttrGet OCI_ATTR_ENV_NCHARSET_ID"); - return 0; +#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) + imp_dbh->is_shared = 0; + svp = DBD_ATTRIB_GET_SVP(attr,"ora_dbh_share",13); + if(svp != NULL) + { + MAGIC * mg; + shared_sv = *svp; + tracer(2, 3, "trying to find shared session\n"); + while (SvROK(shared_sv)) shared_sv = SvRV(shared_sv) ; + /* check if this is shared scalar by finding appropriate magic */ + if(SvTYPE(shared_sv) < SVt_PVMG || + (mg = mg_find(shared_sv, PERL_MAGIC_shared_scalar)) == NULL) + return local_error( + aTHX_ dbh,"value of ora_dbh_share must be a scalar that is shared" + ) ; + + /* now we should lock access. Note, locking of unshared variable croaks */ + /* this is unlocked automatically when current XS function ends */ + SvLOCK (shared_sv) ; + /* copy value from shared part, just in case */ + SvGETMAGIC(shared_sv); + shared_dbh_len = SvCUR(shared_sv) ; + + if (shared_dbh_len == sizeof (imp_dbh_t)) { + imp_dbh_t * shared_dbh = (imp_dbh_t *)SvPVX(shared_sv) ; + /* initialize from shared data */ + memcpy ( + ((char *)imp_dbh) + DBH_DUP_OFF, + ((char *)shared_dbh) + DBH_DUP_OFF, + DBH_DUP_LEN + ); + imp_dbh->is_shared = 1; + + /* using private errhp does not make sense really because + * one can not use this copy of connection at the same + * time in different threads. There are transactions and + * if some threads starts transaction, then other thread + * should not accidently finish it. So if the connections + * are used carefully, then they don't need separate errhp + */ + tracer(2, 3, "dbd_db_login: shared session %p\n", shared_dbh->seshp); + (void)hv_delete((HV*)SvRV(attr), "ora_dbh_share", 13, G_DISCARD); + /* nothing else to do with this handle */ + return activate_dbh(aTHX_ &ctrl); + } + else if (shared_dbh_len != 0) + return local_error(aTHX_ dbh, "Invalid value for ora_dbh_share %d vs %d", + (int)shared_dbh_len, (int)sizeof(imp_dbh_t)) ; + /* indicate that this connection is shared */ + imp_dbh->is_shared = 1; } - - /* At this point we have charsetid & ncharsetid - * note that it is possible for charsetid and ncharestid to - * be distinct if NLS_LANG and NLS_NCHAR are both used. - * BTW: NLS_NCHAR is set as follows: NSL_LANG=AL32UTF8 - */ - - if (DBIc_DBISTATE(imp_dbh)->debug >= 3 || dbd_verbose >= 3 ) { - oratext charsetname[OCI_NLS_MAXBUFSZ]; - oratext ncharsetname[OCI_NLS_MAXBUFSZ]; - OCINlsCharSetIdToName(imp_dbh->envhp,charsetname, sizeof(charsetname),charsetid ); - OCINlsCharSetIdToName(imp_dbh->envhp,ncharsetname, sizeof(ncharsetname),ncharsetid ); - PerlIO_printf( - DBIc_LOGPIO(imp_dbh), - " charset id=%d, name=%s, ncharset id=%d, name=%s" - " (csid: utf8=%d al32utf8=%d)\n", - charsetid,charsetname, ncharsetid,ncharsetname, utf8_csid, al32utf8_csid); -#ifdef ORA_OCI_112 - if (imp_dbh->using_drcp) - PerlIO_printf(DBIc_LOGPIO(imp_dbh)," Using DRCP Connection\n "); #endif - } - - if (!shared_dbh) { - -#ifdef ORA_OCI_112 - - if (imp_dbh->using_drcp) { /* connect using a DRCP */ - OCIAuthInfo *authp; - ub4 purity = OCI_ATTR_PURITY_SELF; - OraText *rettag; - ub4 rettagl; - /* pool Default values */ - if (!imp_dbh->pool_min ) - imp_dbh->pool_min = 0; - if (!imp_dbh->pool_max ) - imp_dbh->pool_max = 40; - if (!imp_dbh->pool_incr) - imp_dbh->pool_incr = 1; - if (!imp_dbh->pool_rlb) - imp_dbh->pool_rlb = 0; - - if (!pool) { - /* Create and cache new session pool struct. */ - SV *key_sv = pool_key(imp_dbh, dbname, uid, pwd, charsetid, ncharsetid); - - session_pool_t pool_data = {0}; - SV *pool_sv = newSVpvn((char*)&pool_data, sizeof(pool_data)); - HE *pool_he = hv_store_ent(imp_drh->pool_hv, key_sv, pool_sv, 0); - imp_dbh->pool = pool = (session_pool_t*)SvPVX(HeVAL(pool_he)); - pool->envhp = imp_dbh->envhp; - - sv_free(key_sv); - - OCIHandleAlloc_ok(imp_dbh, pool->envhp, &pool->poolhp, OCI_HTYPE_SPOOL, status); - OCIHandleAlloc_ok(imp_dbh, pool->envhp, &authp, OCI_HTYPE_AUTHINFO, status); - /* Create an unshared error handle for use in pool creation and destruction. */ - OCIHandleAlloc_ok(imp_dbh, pool->envhp, &pool->errhp, OCI_HTYPE_ERROR, status); - - OCIAttrSet_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, - imp_dbh->driver_name, (ub4)strlen(imp_dbh->driver_name), - OCI_ATTR_DRIVER_NAME, pool->errhp, status); - - OCIAttrSet_log_stat(imp_dbh, pool->poolhp, OCI_HTYPE_SPOOL, - authp, (ub4)0, OCI_ATTR_SPOOL_AUTH, pool->errhp, status); - - ora_parse_uid(imp_dbh, &uid, &pwd); - - OCISessionPoolCreate_log_stat( - imp_dbh, - pool->envhp, - pool->errhp, - pool->poolhp, - &pool->pool_name, - &pool->pool_namel, - (OraText *) dbname, - (ub4)strlen(dbname), - imp_dbh->pool_min, - imp_dbh->pool_max, - imp_dbh->pool_incr, - (OraText *) uid, - (ub4)strlen(uid), - (OraText *) pwd, - (ub4)strlen(pwd), - OCI_SPC_HOMOGENEOUS | (imp_dbh->pool_rlb ? 0 : OCI_SPC_NO_RLB), - status); - - if (status != OCI_SUCCESS) { - oci_error(dbh, pool->errhp, status, "OCISessionPoolCreate"); - OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); - OCIHandleFree_log_stat(imp_dbh, pool->poolhp, OCI_HTYPE_SPOOL,status); - OCIHandleFree_log_stat(imp_dbh, pool->errhp, OCI_HTYPE_ERROR, status); - /* Free the global error handle as well. */ - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(imp_dbh, pool->envhp, OCI_HTYPE_ENV, status); - - (void)hv_delete_ent(imp_drh->pool_hv, HeSVKEY(pool_he), 0, 0); - return 0; - } - - OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); - } - - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &authp, OCI_HTYPE_AUTHINFO, status); - - OCIAttrSet_log_stat(imp_dbh, authp, (ub4) OCI_HTYPE_AUTHINFO, - &purity, (ub4) 0,(ub4) OCI_ATTR_PURITY, imp_dbh->errhp, status); - if (imp_dbh->pool_class) /*pool_class may or may not be used */ - OCIAttrSet_log_stat(imp_dbh, authp, (ub4) OCI_HTYPE_AUTHINFO, - (OraText *) imp_dbh->pool_class, (ub4) imp_dbh->pool_classl, - (ub4) OCI_ATTR_CONNECTION_CLASS, imp_dbh->errhp, status); - - /* Use session tagging to get a server session initalized with correct charsets. */ - sprintf((char*)imp_dbh->session_tag, "csid=%d,ncsid=%d", charsetid, ncharsetid); - - OCISessionGet_log_stat(imp_dbh, imp_dbh->envhp, imp_dbh->errhp, &imp_dbh->svchp, authp, - pool->pool_name, (ub4)strlen((char *)pool->pool_name), - imp_dbh->session_tag, (ub4)strlen((char *)imp_dbh->session_tag), &rettag, &rettagl, &imp_dbh->session_tag_found, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCISessionGet"); - OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); - return 0; - } - - /* Update number of active sessions in the pool. */ - ++imp_dbh->pool->active_sessions; - - OCIHandleFree_log_stat(imp_dbh, authp, OCI_HTYPE_AUTHINFO, status); - - /* Get server and session handles from service context handle, allocated by OCISessionGet. */ - OCIAttrGet_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, &imp_dbh->srvhp, NULL, - OCI_ATTR_SERVER, imp_dbh->errhp, status); - OCIAttrGet_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, &imp_dbh->seshp, NULL, - OCI_ATTR_SESSION, imp_dbh->errhp, status); - - if (DBIc_DBISTATE(imp_dbh)->debug >= 4 || dbd_verbose >= 4 ) { - PerlIO_printf( - DBIc_LOGPIO(imp_dbh), - "Using DRCP with session settings min=%d, max=%d, and increment=%d\n", - imp_dbh->pool_min, - imp_dbh->pool_max, - imp_dbh->pool_incr); - if (imp_dbh->pool_class) - PerlIO_printf( - DBIc_LOGPIO(imp_dbh), - "with connection class=%s\n",imp_dbh->pool_class); - } - - } - else { -#endif /* ORA_OCI_112 */ - - SV **sess_mode_type_sv; - ub4 sess_mode_type = OCI_DEFAULT; - ub4 cred_type; - DBD_ATTRIB_GET_IV(attr, "ora_session_mode",16, sess_mode_type_sv, sess_mode_type); - - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); - OCIHandleAlloc_ok(imp_dbh, imp_dbh->envhp, &imp_dbh->seshp, OCI_HTYPE_SESSION, status); - OCIServerAttach_log_stat(imp_dbh, dbname,OCI_DEFAULT, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCIServerAttach"); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); - if (imp_dbh->envhp != imp_drh->envhp) { - OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); - } - return 0; - } + /* Get desired charset and ncharset */ + if ((svp = DBD_ATTRIB_GET_SVP(attr, "ora_charset", 11))) { + if (!SvPOK(*svp)) return local_error( + aTHX_ dbh, "ora_charset is not a string" + ); + ctrl.cset = SvPV_nolen(*svp); + /* don't remove attribute because I need pointer */ + } - OCIAttrSet_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, imp_dbh->srvhp, - (ub4) 0, OCI_ATTR_SERVER, imp_dbh->errhp, status); + if ((svp = DBD_ATTRIB_GET_SVP(attr, "ora_ncharset", 12))) { + if (!SvPOK(*svp)) return local_error( + aTHX_ dbh, "ora_ncharset is not a string" + ); + ctrl.ncset = SvPV_nolen(*svp); + } + ctrl.session_mode = OCI_DEFAULT; + if ((svp = DBD_ATTRIB_GET_SVP(attr, "ora_session_mode", 16))) { + ctrl.session_mode = SvIV(*svp); + hv_delete((HV*)SvRV(attr), "ora_session_mode", 16, G_DISCARD); + } + if(!cnx_establish(aTHX_ &ctrl)) return FALSE; - cred_type = ora_parse_uid(imp_dbh, &uid, &pwd); +#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) + if (imp_dbh->is_shared != 0 && 0 == shared_dbh_len) { #ifdef ORA_OCI_112 - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, (ub4)OCI_HTYPE_SESSION, - imp_dbh->driver_name, (ub4)strlen(imp_dbh->driver_name), - (ub4)OCI_ATTR_DRIVER_NAME, imp_dbh->errhp, status); + SV * tag = imp_dbh->session_tag; + imp_dbh->session_tag = NULL; #endif - - OCISessionBegin_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp,cred_type, sess_mode_type, status); - - if (status == OCI_SUCCESS_WITH_INFO) { - /* eg ORA-28011: the account will expire soon; change your password now */ - oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); - status = OCI_SUCCESS; - } - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); - OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); - if (imp_dbh->envhp != imp_drh->envhp) { - OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); - } - return 0; - } - - OCIAttrSet_log_stat(imp_dbh, imp_dbh->svchp, (ub4) OCI_HTYPE_SVCCTX, - imp_dbh->seshp, (ub4) 0,(ub4) OCI_ATTR_SESSION, imp_dbh->errhp, status); + tracer(2, 3, "saving shared session %p\n", imp_dbh->seshp); + sv_setpvn_mg(shared_sv, (char*)imp_dbh, sizeof(*imp_dbh)); #ifdef ORA_OCI_112 - } + imp_dbh->session_tag = tag; #endif - - } - - DBIc_IMPSET_on(imp_dbh); /* imp_dbh set up now */ - DBIc_ACTIVE_on(imp_dbh); /* call disconnect before freeing */ - imp_dbh->ph_type = 1; /* SQLT_CHR "(ORANET TYPE) character string" */ - imp_dbh->ph_csform = 0; /* meaning auto (see dbd_rebind_ph) */ - -#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) - if (shared_dbh_ssv && !shared_dbh) { - /* much of this could be replaced with a single sv_setpvn() */ - (void)SvUPGRADE(shared_dbh_priv_sv, SVt_PV); - SvGROW(shared_dbh_priv_sv, sizeof(imp_dbh_t) + 1) ; - SvCUR (shared_dbh_priv_sv) = sizeof(imp_dbh_t) ; - imp_dbh->refcnt = 1 ; - imp_dbh->shared_dbh_priv_sv = shared_dbh_priv_sv ; - memcpy(SvPVX(shared_dbh_priv_sv) + DBH_DUP_OFF, ((char *)imp_dbh) + DBH_DUP_OFF, DBH_DUP_LEN) ; - SvSETMAGIC(shared_dbh_priv_sv); - imp_dbh->shared_dbh = (imp_dbh_t *)SvPVX(shared_dbh_ssv->sv); } #endif - - /* set up TAF callback if wanted */ - - if (imp_dbh->taf_function){ - if (enable_taf(dbh, imp_dbh) == 0) return 0; - } - - return 1; + return activate_dbh(aTHX_ &ctrl); } @@ -1154,55 +799,33 @@ dbd_db_disconnect(SV *dbh, imp_dbh_t *imp_dbh) { dTHX; dTHR; - int refcnt = 1 ; - -#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) - if (DBIc_IMPSET(imp_dbh) && imp_dbh->shared_dbh) { - SvLOCK (imp_dbh->shared_dbh_priv_sv) ; - refcnt = imp_dbh -> shared_dbh -> refcnt ; - } -#endif /* We assume that disconnect will always work */ /* since most errors imply already disconnected. */ DBIc_ACTIVE_off(imp_dbh); - /* Oracle will commit on an orderly disconnect. */ - /* See DBI Driver.xst file for the DBI approach. */ - - if (refcnt == 1 ) { +#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) + /* do nothing for connections stored in shared variables */ + if(imp_dbh->is_shared != 0) + { #ifdef ORA_OCI_112 - if (imp_dbh->using_drcp) { - sword status; - /* Release session, tagged for future retrieval. */ - OCISessionRelease_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, - imp_dbh->session_tag, (ub4)strlen((char *)imp_dbh->session_tag), imp_dbh->session_tag_found ? OCI_DEFAULT : OCI_SESSRLS_RETAG, status); - if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCISessionRelease"); - return 0; - } - - /* Update number of active sessions in the pool */ - --imp_dbh->pool->active_sessions; - } - else { + /* just in case, drop session_tag if it is set + * normally it is used during session release */ + if(imp_dbh->session_tag != NULL) + { + SvREFCNT_dec(imp_dbh->session_tag); + imp_dbh->session_tag = NULL; + } #endif - sword s_se, s_sd; - OCISessionEnd_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, - OCI_DEFAULT, s_se); - if (s_se) oci_error(dbh, imp_dbh->errhp, s_se, "OCISessionEnd"); - OCIServerDetach_log_stat(imp_dbh, imp_dbh->srvhp, imp_dbh->errhp, OCI_DEFAULT, s_sd); - if (s_sd) oci_error(dbh, imp_dbh->errhp, s_sd, "OCIServerDetach"); - if (s_se != OCI_SUCCESS || s_sd != OCI_SUCCESS) - return 0; -#ifdef ORA_OCI_112 - } + return TRUE; + } #endif - } + cnx_detach(aTHX_ imp_dbh); + /* We don't free imp_dbh since a reference still exists */ /* The DESTROY method is the only one to 'free' memory. */ /* Note that statement objects may still exists for this dbh! */ - return 1; + return TRUE; } @@ -1210,28 +833,10 @@ void dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) { dTHX ; - int refcnt = 1 ; - sword status; - D_imp_drh_from_dbh; - -#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) - if (DBIc_IMPSET(imp_dbh) && imp_dbh->shared_dbh) { - SvLOCK (imp_dbh->shared_dbh_priv_sv) ; - refcnt = imp_dbh -> shared_dbh -> refcnt-- ; - } -#endif - - if (refcnt == 1) { - if (DBIc_ACTIVE(imp_dbh)) - dbd_db_disconnect(dbh, imp_dbh); - if (is_extproc) - goto dbd_db_destroy_out; - - if (imp_dbh->taf_function){ - disable_taf(imp_dbh); - } - + if (DBIc_ACTIVE(imp_dbh)) dbd_db_disconnect(dbh, imp_dbh); + DBIc_IMPSET_off(imp_dbh); if (imp_dbh->taf_function) { + disable_taf(imp_dbh); SvREFCNT_dec(imp_dbh->taf_function); imp_dbh->taf_function = NULL; } @@ -1240,43 +845,12 @@ dbd_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) imp_dbh->taf_ctx.dbh_ref = NULL; } - -#ifdef ORA_OCI_112 - if (imp_dbh->using_drcp) { - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - } - else { -#endif - OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION,status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->svchp, OCI_HTYPE_SVCCTX, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->srvhp, OCI_HTYPE_SERVER, status); - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - /* free session environment handle */ - if (imp_dbh->envhp != imp_drh->envhp) { - OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); - if ( status == OCI_SUCCESS ) { - imp_dbh->envhp = NULL; - } - /* free global environment handle during destruction of last connection */ - } else if ( (imp_dbh->envhp == imp_drh->envhp) && (SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) ) { - OCIHandleFree_log_stat(imp_dbh, imp_dbh->envhp, OCI_HTYPE_ENV, status); - if ( status == OCI_SUCCESS ) { - imp_dbh->envhp = NULL; - imp_drh->envhp = NULL; - } - } -#ifdef ORA_OCI_112 - } +#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) + /* on shared cnx only decrement reference count */ + if(imp_dbh->is_shared != 0) return; #endif - } - else { - /* A new error handle is allocated on each new connect, so it is also freed when - refcnt > 1. Note that we cannot have a common free here, since it is an error - to free the environment handle before the error handle. */ - OCIHandleFree_log_stat(imp_dbh, imp_dbh->errhp, OCI_HTYPE_ERROR, status); - } -dbd_db_destroy_out: - DBIc_IMPSET_off(imp_dbh); + tracer(3, 3, "clearing session %p\n", imp_dbh->seshp); + cnx_clean(aTHX_ imp_dbh); } @@ -1285,11 +859,28 @@ dbd_take_imp_data(SV *dbh, imp_xxh_t *imp_xxh, void* foo) { dTHX; D_imp_dbh(dbh); - D_imp_drh_from_dbh; - - /* By using ithread, handles will leak in dbd_dr_destroy() */ - imp_drh->leak_handles = 1; - + tracer(3, 3, "take_imp for %p (session %p)\n", imp_dbh, imp_dbh->seshp); + if (imp_dbh->taf_function) { + disable_taf(imp_dbh); + SvREFCNT_dec(imp_dbh->taf_function); + imp_dbh->taf_function = NULL; + } + if (imp_dbh->taf_ctx.dbh_ref) { + SvREFCNT_dec(SvRV(imp_dbh->taf_ctx.dbh_ref)); + imp_dbh->taf_ctx.dbh_ref = NULL; + } +#ifdef ORA_OCI_112 + if(imp_dbh->session_tag != NULL) + { + SvREFCNT_dec(imp_dbh->session_tag); + imp_dbh->session_tag = NULL; + } +#endif + /* we do nothing else here because the copy of current state is saved by + * SUPER::take_imp_data and no other method shall be called on this + * handle. If user calls something, then it is not our problem. + * Wether DESTROY nor DISCONNECT are called by DBI + */ /* Indicate that SUPER::take_imp_data should be called. */ return &PL_sv_no; } @@ -1315,70 +906,112 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) } #ifdef ORA_OCI_112 else if (kl==15 && strEQ(key, "ora_driver_name") ) { - imp_dbh->driver_name = (char *) SvPV (valuesv, vl ); - OCIAttrSet_log_stat( - imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, imp_dbh->driver_name, - (ub4)vl, OCI_ATTR_DRIVER_NAME, imp_dbh->errhp, status); + (void)local_error( + aTHX_ dbh, "ora_driver_name can not be changed" + ); } else if (kl==8 && strEQ(key, "ora_drcp") ) { - imp_dbh->using_drcp = 1; + (void)local_error( + aTHX_ dbh, "ora_drcp can not be changed" + ); } else if (kl==14 && strEQ(key, "ora_drcp_class") ) { - STRLEN vl; - imp_dbh->pool_class = (text *) SvPV (valuesv, vl ); - imp_dbh->pool_classl= (ub4) vl; + (void)local_error( + aTHX_ dbh, "ora_drcp_class can not be changed" + ); + } + else if (kl==12 && strEQ(key, "ora_drcp_tag") ) { +#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) + if(imp_dbh->is_shared != 0) + { + (void)local_error( + aTHX_ dbh, "ora_drcp_tag not supported for shared DBH" + ); + } + else +#endif + if(cnx_is_pooled_session(aTHX_ dbh, imp_dbh)) + { + if(imp_dbh->session_tag != NULL) SvREFCNT_dec(imp_dbh->session_tag); + imp_dbh->session_tag = newSVsv(valuesv); + } + else (void)local_error( + aTHX_ dbh, "ora_drcp_tag is not used without DRCP" + ); } else if (kl==12 && strEQ(key, "ora_drcp_min") ) { - imp_dbh->pool_min = SvIV (valuesv); + cnx_pool_min(aTHX_ dbh, imp_dbh, (ub4)SvIV(valuesv)); + } + else if (kl==13 && strEQ(key, "ora_drcp_mode") ) { + cnx_pool_mode(aTHX_ dbh, imp_dbh, (ub4)SvIV(valuesv)); + } + else if (kl==13 && strEQ(key, "ora_drcp_wait") ) { + cnx_pool_wait(aTHX_ dbh, imp_dbh, (ub4)SvIV(valuesv)); } else if (kl==12 && strEQ(key, "ora_drcp_max") ) { - imp_dbh->pool_max = SvIV (valuesv); + cnx_pool_max(aTHX_ dbh, imp_dbh, (ub4)SvIV(valuesv)); } else if (kl==13 && strEQ(key, "ora_drcp_incr") ) { - imp_dbh->pool_incr = SvIV (valuesv); + cnx_pool_incr(aTHX_ dbh, imp_dbh, (ub4)SvIV(valuesv)); } else if (kl==12 && strEQ(key, "ora_drcp_rlb") ) { - imp_dbh->pool_rlb = SvIV (valuesv); + /* ignore it here, too late to do anything */ } #endif else if (kl==16 && strEQ(key, "ora_taf_function") ) { - if (imp_dbh->taf_function) - SvREFCNT_dec(imp_dbh->taf_function); - imp_dbh->taf_function = newSVsv(valuesv); - - if (SvTRUE(valuesv)) { - enable_taf(dbh, imp_dbh); - } else { - disable_taf(imp_dbh); - } + if (imp_dbh->taf_function) + SvREFCNT_dec(imp_dbh->taf_function); + imp_dbh->taf_function = newSVsv(valuesv); + + if (SvTRUE(valuesv)) { + if(!enable_taf(aTHX_ dbh, imp_dbh)) return FALSE; + } else { + disable_taf(imp_dbh); + } } #ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action") ) { - imp_dbh->action = (char *) SvPV (valuesv, vl ); - imp_dbh->actionl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->action,imp_dbh->actionl,OCI_ATTR_ACTION,imp_dbh->errhp, status); - + char * action = (char *) SvPV (valuesv, vl ); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, + action,(ub4)vl, OCI_ATTR_ACTION, imp_dbh->errhp, status); + if(status != OCI_SUCCESS) (void)oci_error( + dbh, imp_dbh->errhp, status, "OCIAttrSet OCI_ATTR_ACTION"); } #endif else if (kl==21 && strEQ(key, "ora_client_identifier") ) { - imp_dbh->client_identifier = (char *) SvPV (valuesv, vl ); - imp_dbh->client_identifierl= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_identifier,imp_dbh->client_identifierl,OCI_ATTR_CLIENT_IDENTIFIER,imp_dbh->errhp, status); - + char * cid = (char *) SvPV (valuesv, vl ); + OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, + cid,(ub4)vl,OCI_ATTR_CLIENT_IDENTIFIER, + imp_dbh->errhp, status + ); + if(status != OCI_SUCCESS) (void)oci_error( + dbh, imp_dbh->errhp, status, + "OCIAttrSet OCI_ATTR_CLIENT_IDENTIFIER"); } #ifdef OCI_ATTR_CLIENT_INFO else if (kl==15 && strEQ(key, "ora_client_info") ) { - imp_dbh->client_info = (char *) SvPV (valuesv, vl ); - imp_dbh->client_infol= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->client_info,imp_dbh->client_infol,OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status); + char * client_info = (char *) SvPV (valuesv, vl ); + OCIAttrSet_log_stat(imp_dbh, + imp_dbh->seshp,OCI_HTYPE_SESSION, + client_info,(ub4)vl, + OCI_ATTR_CLIENT_INFO,imp_dbh->errhp, status + ); + if(status != OCI_SUCCESS) (void)oci_error( + dbh, imp_dbh->errhp, status, + "OCIAttrSet OCI_ATTR_CLIENT_INFO"); } #endif #ifdef OCI_ATTR_MODULE else if (kl==15 && strEQ(key, "ora_module_name") ) { - imp_dbh->module_name = (char *) SvPV (valuesv, vl ); - imp_dbh->module_namel= (ub4) vl; - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp,OCI_HTYPE_SESSION, imp_dbh->module_name,imp_dbh->module_namel,OCI_ATTR_MODULE,imp_dbh->errhp, status); - + char * module_name = (char *) SvPV (valuesv, vl ); + OCIAttrSet_log_stat(imp_dbh, + imp_dbh->seshp,OCI_HTYPE_SESSION, + module_name, (ub4)vl, + OCI_ATTR_MODULE,imp_dbh->errhp, status + ); + if(status != OCI_SUCCESS) (void)oci_error( + dbh, imp_dbh->errhp, status, + "OCIAttrSet OCI_ATTR_MODULE"); } #endif else if (kl==20 && strEQ(key, "ora_oci_success_warn") ) { @@ -1436,6 +1069,7 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) SV *retsv = Nullsv; /* Default to caching results for DBI dispatch quick_FETCH */ int cacheit = FALSE; + sword status; /* AutoCommit FETCH via DBI */ @@ -1444,25 +1078,57 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) } #ifdef ORA_OCI_112 else if (kl==15 && strEQ(key, "ora_driver_name") ) { - retsv = newSVpv((char *)imp_dbh->driver_name,0); + char * driver_name; + ub4 namelen; + OCIAttrGet_log_stat( + imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, &driver_name, + &namelen, OCI_ATTR_DRIVER_NAME, imp_dbh->errhp, status + ); + if(status == OCI_SUCCESS) + retsv = newSVpv(driver_name, namelen); } else if (kl==8 && strEQ(key, "ora_drcp") ) { - retsv = newSViv(imp_dbh->using_drcp); + retsv = newSViv(cnx_is_pooled_session(aTHX_ dbh, imp_dbh)); } else if (kl==14 && strEQ(key, "ora_drcp_class") ) { - retsv = newSVpv((char *)imp_dbh->pool_class, 0); - } + char * pool_name; + ub4 namelen; + OCIAttrGet_log_stat( + imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, &pool_name, + &namelen, OCI_ATTR_CONNECTION_CLASS, imp_dbh->errhp, status + ); + if(status == OCI_SUCCESS) + retsv = newSVpv(pool_name, namelen); + else (void)oci_error(dbh, imp_dbh->errhp, status, + "OCIAttrGet OCI_ATTR_CONNECTION_CLASS"); + } + else if (kl==12 && strEQ(key, "ora_drcp_tag") ) { + if(imp_dbh->session_tag) + { + retsv = imp_dbh->session_tag; + SvREFCNT_inc(retsv); + } + } else if (kl==12 && strEQ(key, "ora_drcp_min") ) { - retsv = newSViv(imp_dbh->pool_min); + retsv = newSViv(cnx_get_pool_min(aTHX_ dbh, imp_dbh)); + } + else if (kl==13 && strEQ(key, "ora_drcp_mode") ) { + retsv = newSViv(cnx_get_pool_mode(aTHX_ dbh, imp_dbh)); + } + else if (kl==13 && strEQ(key, "ora_drcp_wait") ) { + retsv = newSViv(cnx_get_pool_wait(aTHX_ dbh, imp_dbh)); } else if (kl==12 && strEQ(key, "ora_drcp_max") ) { - retsv = newSViv(imp_dbh->pool_max); + retsv = newSViv(cnx_get_pool_max(aTHX_ dbh, imp_dbh)); } else if (kl==13 && strEQ(key, "ora_drcp_incr") ) { - retsv = newSViv(imp_dbh->pool_incr); + retsv = newSViv(cnx_get_pool_incr(aTHX_ dbh, imp_dbh)); } else if (kl==12 && strEQ(key, "ora_drcp_rlb") ) { - retsv = newSViv(imp_dbh->pool_rlb); + retsv = newSViv(cnx_get_pool_rlb(aTHX_ dbh, imp_dbh)); + } + else if (kl==13 && strEQ(key, "ora_drcp_used") ) { + retsv = newSViv(cnx_get_pool_used(aTHX_ dbh, imp_dbh)); } #endif else if (kl==16 && strEQ(key, "ora_taf_function") ) { @@ -1472,18 +1138,54 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) } #ifdef OCI_ATTR_ACTION else if (kl==10 && strEQ(key, "ora_action")) { - retsv = newSVpv((char *)imp_dbh->action,0); + char * name; + ub4 namelen; + OCIAttrGet_log_stat( + imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, &name, + &namelen, OCI_ATTR_ACTION, imp_dbh->errhp, status + ); + if(status == OCI_SUCCESS) retsv = newSVpv(name, namelen); + else (void)oci_error(dbh, imp_dbh->errhp, status, + "OCIAttrGet OCI_ATTR_ACTION"); } #endif else if (kl==21 && strEQ(key, "ora_client_identifier")) { - retsv = newSVpv((char *)imp_dbh->client_identifier,0); + char * name; + ub4 namelen; + OCIAttrGet_log_stat( + imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, &name, + &namelen, OCI_ATTR_CLIENT_IDENTIFIER, imp_dbh->errhp, status + ); + if(status == OCI_SUCCESS) retsv = newSVpv(name, namelen); + else (void)oci_error(dbh, imp_dbh->errhp, status, + "OCIAttrGet OCI_ATTR_CLIENT_IDENTIFIER"); } +#ifdef OCI_ATTR_CLIENT_INFO else if (kl==15 && strEQ(key, "ora_client_info")) { - retsv = newSVpv((char *)imp_dbh->client_info,0); + char * name; + ub4 namelen; + OCIAttrGet_log_stat( + imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, &name, + &namelen, OCI_ATTR_CLIENT_INFO, imp_dbh->errhp, status + ); + if(status == OCI_SUCCESS) retsv = newSVpv(name, namelen); + else (void)oci_error(dbh, imp_dbh->errhp, status, + "OCIAttrGet OCI_ATTR_CLIENT_INFO"); } +#endif +#ifdef OCI_ATTR_MODULE else if (kl==15 && strEQ(key, "ora_module_name")) { - retsv = newSVpv((char *)imp_dbh->module_name,0); + char * name; + ub4 namelen; + OCIAttrGet_log_stat( + imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, &name, + &namelen, OCI_ATTR_MODULE, imp_dbh->errhp, status + ); + if(status == OCI_SUCCESS) retsv = newSVpv(name, namelen); + else (void)oci_error(dbh, imp_dbh->errhp, status, + "OCIAttrGet OCI_ATTR_MODULE"); } +#endif else if (kl==20 && strEQ(key, "ora_oci_success_warn")) { retsv = newSViv (oci_warn); } @@ -1574,7 +1276,7 @@ createxmlfromstring(SV *sth, imp_sth_t *imp_sth, SV *source){ if (status != OCI_SUCCESS) { oci_error(sth, imp_sth->errhp, status, "OCILobCreateTemporary"); } - csid = (SvUTF8(source) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); + csid = (SvUTF8(source) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(imp_dbh, csform); buflen = len; OCILobWriteAppend_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, src_ptr, &buflen, bufp, (ub4)len, OCI_ONE_PIECE, @@ -1883,7 +1585,7 @@ int dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { dTHX; - /*D_imp_dbh_from_sth ;*/ + D_imp_dbh_from_sth; sword status; int trace_level = DBIc_DBISTATE(imp_sth)->debug; AV *arr; @@ -1972,9 +1674,9 @@ dbd_rebind_ph_varchar2_table(SV *sth, imp_sth_t *imp_sth, phs_t *phs) } if (csform != SQLCS_NCHAR) { /* try to default csform to avoid translation through non-unicode */ - if (CSFORM_IMPLIES_UTF8(SQLCS_NCHAR)) /* prefer NCHAR */ + if (CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_NCHAR)) /* prefer NCHAR */ csform = SQLCS_NCHAR; - else if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) + else if (CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_IMPLICIT)) csform = SQLCS_IMPLICIT; /* else leave csform == 0 */ if (trace_level || dbd_verbose >= 3 ) @@ -2789,7 +2491,8 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) SvGROW(phs->sv,(STRLEN) (unsigned int)phs->maxlen-1); if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6) { PerlIO_printf(DBIc_LOGPIO(imp_sth), - "Growing 96 phs sv to %ld resulted in buffer %ld\n", phs->maxlen - 1, SvLEN(phs->sv)); + "Growing 96 phs sv to %ld resulted in buffer %ld\n", + (long)(phs->maxlen - 1), (long)SvLEN(phs->sv)); } } else { STRLEN min_len = 28; @@ -2803,7 +2506,8 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) SvGROW(phs->sv, (STRLEN)(((unsigned int) phs->maxlen <= min_len) ? min_len : (unsigned int) phs->maxlen)); if (DBIc_DBISTATE(imp_sth)->debug >= 6 || dbd_verbose >= 6) { PerlIO_printf(DBIc_LOGPIO(imp_sth), - "Growing phs sv to %ld resulted in buffer %ld\n", phs->maxlen +1, SvLEN(phs->sv)); + "Growing phs sv to %ld resulted in buffer %ld\n", + (long)(phs->maxlen +1), (long)SvLEN(phs->sv)); } } } @@ -2836,7 +2540,7 @@ dbd_rebind_ph_char(imp_sth_t *imp_sth, phs_t *phs) } else { if (DBIc_DBISTATE(imp_sth)->debug >= 6|| dbd_verbose >= 6 ) { PerlIO_printf(DBIc_LOGPIO(imp_sth), - "Changing maxlen to %ld\n", SvLEN(phs->sv)); + "Changing maxlen to %ld\n", (long)SvLEN(phs->sv)); } phs->maxlen = ((IV)SvLEN(phs->sv)); /* avail buffer space (64bit safe) Logicaly maxlen should never change but it does why I know not - MJE because SvGROW can allocate more than you ask for - anyway - I fixed that and it doesn't grow anymore */ @@ -2925,10 +2629,6 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) " pp_exec_rset bind %s - allocating new sth...\n", phs->name); - /* extproc deallocates everything for us */ - if (is_extproc) - return 1; - if (!phs->desc_h || 1) { /* XXX phs->desc_t != OCI_HTYPE_STMT) */ if (phs->desc_h) { OCIHandleFree_log_stat(imp_sth, phs->desc_h, phs->desc_t, status); @@ -3045,8 +2745,8 @@ pp_exec_rset(SV *sth, imp_sth_t *imp_sth, phs_t *phs, int pre_exec) if (DBIc_DBISTATE(imp_sth)->debug >= 3 || dbd_verbose >= 3 ) PerlIO_printf( DBIc_LOGPIO(imp_sth), - " bind %s - initialising new %s for cursor 0x%lx...\n", - phs->name, neatsvpv(sth_csr,0), (unsigned long)phs->progv); + " bind %s - initialising new %s for cursor 0x%p...\n", + phs->name, neatsvpv(sth_csr,0), phs->progv); { D_impdata(imp_sth_csr, imp_sth_t, sth_csr); /* TO_DO */ @@ -3166,6 +2866,7 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) { dTHX; /*ub2 *alen_ptr = NULL;*/ + D_imp_dbh_from_sth; sword status; int done = 0; int at_exec; @@ -3256,9 +2957,9 @@ dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs) if (!csform && SvUTF8(phs->sv)) { /* try to default csform to avoid translation through non-unicode */ - if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) /* prefer IMPLICIT */ + if (CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_IMPLICIT)) /* prefer IMPLICIT */ csform = SQLCS_IMPLICIT; - else if (CSFORM_IMPLIES_UTF8(SQLCS_NCHAR)) + else if (CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_NCHAR)) csform = SQLCS_NCHAR; /* else leave csform == 0 */ if (trace_level || dbd_verbose >= 3) PerlIO_printf( @@ -3378,8 +3079,8 @@ dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue, IV sql_typ DBIc_LOGPIO(imp_sth), "dbd_bind_ph(1): bind %s <== %s (type %ld (%s)", name, neatsvpv(newvalue,0), (long)sql_type,sql_typecode_name(sql_type)); if (is_inout) - PerlIO_printf(DBIc_LOGPIO(imp_sth), ", inout 0x%lx, maxlen %ld", - (long)newvalue, (long)maxlen); + PerlIO_printf(DBIc_LOGPIO(imp_sth), ", inout 0x%p, maxlen %ld", + newvalue, (long)maxlen); if (attribs) PerlIO_printf(DBIc_LOGPIO(imp_sth), ", attribs: %s", neatsvpv(attribs,0)); PerlIO_printf(DBIc_LOGPIO(imp_sth), ")\n"); @@ -3531,6 +3232,7 @@ void dbd_phs_sv_complete(imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug) { dTHX; + D_imp_dbh_from_sth; char *note = ""; /* XXX doesn't check arcode for error, caller is expected to */ @@ -3549,7 +3251,7 @@ dbd_phs_sv_complete(imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug) SvCUR_set(sv, phs->alen); *SvEND(sv) = '\0'; SvPOK_only_UTF8(sv); - if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { + if (CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_IMPLICIT)) { #ifdef sv_utf8_decode sv_utf8_decode(sv); #else @@ -3573,7 +3275,7 @@ dbd_phs_sv_complete(imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug) SvCUR_set(sv, phs->alen); *SvEND(sv) = '\0'; SvPOK_only_UTF8(sv); - if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { + if (CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_IMPLICIT)) { #ifdef sv_utf8_decode sv_utf8_decode(sv); #else @@ -3824,6 +3526,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat int parma_index; { dTHX; + D_imp_dbh_from_sth; sword status; ub1 csform; ub2 csid; @@ -3859,9 +3562,9 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat if (!csform && (utf8 & ARRAY_BIND_UTF8)) { /* try to default csform to avoid translation through non-unicode */ - if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) /* prefer IMPLICIT */ + if (CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_IMPLICIT)) /* prefer IMPLICIT */ csform = SQLCS_IMPLICIT; - else if (CSFORM_IMPLIES_UTF8(SQLCS_NCHAR)) + else if (CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_NCHAR)) csform = SQLCS_NCHAR; /* else leave csform == 0 */ if (trace_level || dbd_verbose >= 3 ) PerlIO_printf( @@ -4249,6 +3952,7 @@ dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, dTHX; ub4 retl = 0; SV *bufsv; + D_imp_dbh_from_sth; imp_fbh_t *fbh = &imp_sth->fbh[field]; int ftype = fbh->ftype; @@ -4256,7 +3960,7 @@ dbd_st_blob_read(SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, sv_setpvn(bufsv,"",0); /* ensure it's writable string */ #ifdef UTF8_SUPPORT - if (ftype == 112 && CS_IS_UTF8(ncharsetid) ) { + if (ftype == 112 && CS_IS_UTF8(imp_dbh->ncset) ) { return ora_blob_read_mb_piece(sth, imp_sth, fbh, bufsv, offset, len, destoffset); } @@ -4549,6 +4253,7 @@ SV * dbd_st_FETCH_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv) { dTHX; + D_imp_dbh_from_sth; STRLEN kl; char *key = SvPV(keysv,kl); int i; @@ -4580,7 +4285,7 @@ dbd_st_FETCH_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv) retsv = newRV(sv_2mortal((SV*)av)); while(--i >= 0) { x = newSVpv((char*)imp_sth->fbh[i].name,0); - if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { + if (CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_IMPLICIT)) { #ifdef sv_utf8_decode sv_utf8_decode(x); #else @@ -4748,20 +4453,25 @@ dump_env_to_trace(imp_dbh_t *imp_dbh) { dTHX; int i = 0; char *p; + char ** env; #if defined (__APPLE__) #include - #define environ (*_NSGetEnviron()) -#elif defined (__BORLANDC__) + env = *_NSGetEnviron(); +#else +#if defined (__BORLANDC__) extern char **environ; #endif + env = environ; +#endif PerlIO_printf(DBIc_LOGPIO(imp_dbh), "Environment variables:\n"); - do { - p = (char*)environ[i++]; - PerlIO_printf(DBIc_LOGPIO(imp_dbh),"\t%s\n",p); - } while ((char*)environ[i] != '\0'); + while(env[i] != NULL) + { + p = env[i++]; + PerlIO_printf(DBIc_LOGPIO(imp_dbh),"\t%s\n",p); + } } static void disable_taf( @@ -4778,9 +4488,8 @@ static void disable_taf( return; } -static int enable_taf( - SV *dbh, - imp_dbh_t *imp_dbh) { +static int enable_taf( pTHX_ SV *dbh, imp_dbh_t *imp_dbh) +{ boolean can_taf = 0; sword status; @@ -4790,15 +4499,14 @@ static int enable_taf( OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status); #endif - if (!can_taf){ - croak("You are attempting to enable TAF on a server that is not TAF Enabled \n"); - } + if (!can_taf) + return local_error(aTHX_ dbh, + "You are attempting to enable TAF on a server that is not TAF Enabled"); + - status = reg_taf_callback(dbh, imp_dbh); - if (status != OCI_SUCCESS) { - oci_error(dbh, NULL, status, "Setting TAF Callback Failed! "); - return 0; - } + status = reg_taf_callback(dbh, imp_dbh); + if (status != OCI_SUCCESS) + return oci_error(dbh, NULL, status, "Setting TAF Callback Failed! "); return 1; } diff --git a/dbdimp.h b/dbdimp.h index bb21ac39..a5ac7ddb 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -15,50 +15,51 @@ struct taf_callback_st { SV *dbh_ref; }; + +typedef struct box_st box_t; typedef struct imp_fbh_st imp_fbh_t; +/* this structure is used to communicate parameters of login */ +typedef struct dblogin_info_st dblogin_info_t; +struct dblogin_info_st { + SV * dbh; + imp_dbh_t * imp_dbh; + SV * pool_class; /* this and next SV * is "mortal" */ + SV * pool_tag; + char *dbname; + char *uid; + char *pwd; + char * cset; + char * ncset; + ub4 mode; + ub4 session_mode; +#ifdef ORA_OCI_112 + ub4 pool_min; + ub4 pool_max; + ub4 pool_incr; + ub4 pool_rlb; + ub4 driver_name_len; + char * driver_name; +#endif +}; + /* Define implementation specific driver handle data structure */ struct imp_drh_st { dbih_drc_t com; /* MUST be first element in structure */ - OCIEnv *envhp; /* global environment handler, see also */ - /* connect attr ora_envhp */ - bool leak_handles; /* shared dbh's will leak handles in */ - /* dbd_dr_destroy(), see connect attr */ - /* ora_dbh_share for more information */ -#ifdef ORA_OCI_112 - HV *charset_hv; - HV *pool_hv; -#endif SV *ora_long; SV *ora_trunc; SV *ora_cache; SV *ora_cache_o; /* for ora_open() cache override */ }; -#ifdef ORA_OCI_112 -typedef struct session_pool_st session_pool_t; -struct session_pool_st { - OCIEnv *envhp; - OCIError *errhp; - OCISPool *poolhp; - OraText *pool_name; - ub4 pool_namel; - int active_sessions; -}; -#endif /* Define implementation specific database handle data structure */ struct imp_dbh_st { dbih_dbc_t com; /* MUST be first element in structure */ -#ifdef USE_ITHREADS - int refcnt ; /* keep track of duped handles. MUST be first after com */ - struct imp_dbh_st * shared_dbh ; /* pointer to shared space from which to dup and keep refcnt */ - SV * shared_dbh_priv_sv ; -#endif - void *(*get_oci_handle) _((imp_dbh_t *imp_dbh, int handle_type, int flags)); + box_t *lock; /* this contains pointer to slot that holds lock */ OCIEnv *envhp; /* session environment handler, this is mostly */ /* a copy of imp_drh->envhp, see also connect */ /* attr ora_envhp */ @@ -66,37 +67,24 @@ struct imp_dbh_st { OCIServer *srvhp; OCISvcCtx *svchp; OCISession *seshp; -#ifdef ORA_OCI_112 - session_pool_t *pool; - OraText session_tag[50]; - boolean session_tag_found; - bool using_drcp; - text *pool_class; - ub4 pool_classl; - ub4 pool_min; - ub4 pool_max; - ub4 pool_incr; - ub4 pool_rlb; - char *driver_name;/*driver name user defined*/ -#endif SV *taf_function; /*User supplied TAF functiomn*/ taf_callback_t taf_ctx; - char *client_info; /*user defined*/ - ub4 client_infol; - char *module_name; /*module user defined */ - ub4 module_namel; - char *client_identifier; /*user defined*/ - ub4 client_identifierl; - char *action; /*user defined*/ - ub4 actionl; int RowCacheSize; /* both of these are defined by DBI spec*/ int RowsInCache; /* this vaue is RO and cannot be set*/ int ph_type; /* default oratype for placeholders */ - ub1 ph_csform; /* default charset for placeholders */ int parse_error_offset; /* position in statement of last error */ int max_nested_cursors; /* limit on cached nested cursors per stmt */ int array_chunk_size; /* the max size for an array bind */ ub4 server_version; /* version of Oracle server */ +#ifdef ORA_OCI_112 + SV * session_tag; +#endif + ub2 cset; + ub2 ncset; + ub1 ph_csform; /* default charset for placeholders */ +#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) + ub1 is_shared; +#endif }; #define DBH_DUP_OFF sizeof(dbih_dbc_t) @@ -153,7 +141,7 @@ struct imp_sth_st { int eod_errno; int est_width; /* est'd avg row width on-the-wire */ /* (In/)Out Parameter Details */ - bool has_inout_params; + int has_inout_params; /* execute mode*/ /* will be using this alot later me thinks */ ub4 exe_mode; @@ -314,8 +302,6 @@ extern int dbd_verbose; extern int oci_warn; extern int ora_objects; extern int ora_ncs_buff_mtpl; -extern ub2 charsetid; -extern ub2 ncharsetid; extern ub2 us7ascii_csid; extern ub2 utf8_csid; extern ub2 al32utf8_csid; @@ -330,11 +316,11 @@ extern ub2 al16utf16_csid; #define CS_IS_UTF16( cs ) ( cs == al16utf16_csid ) -#define CSFORM_IMPLIED_CSID(csform) \ - ((csform==SQLCS_NCHAR) ? ncharsetid : charsetid) +#define CSFORM_IMPLIED_CSID(imp_xxh, csform) \ + ((csform==SQLCS_NCHAR) ? (imp_xxh)->ncset : (imp_xxh)->cset) -#define CSFORM_IMPLIES_UTF8(csform) \ - CS_IS_UTF8( CSFORM_IMPLIED_CSID( csform ) ) +#define CSFORM_IMPLIES_UTF8(imp_xxh, csform) \ + CS_IS_UTF8( CSFORM_IMPLIED_CSID(imp_xxh, csform ) ) void dbd_init_oci _((dbistate_t *dbistate)); @@ -388,14 +374,13 @@ void ora_free_lob_refetch _((SV *sth, imp_sth_t *imp_sth)); void dbd_phs_avsv_complete _((imp_sth_t *imp_sth, phs_t *phs, I32 index, I32 debug)); void dbd_phs_sv_complete _((imp_sth_t *imp_sth, phs_t *phs, SV *sv, I32 debug)); int post_execute_lobs _((SV *sth, imp_sth_t *imp_sth, ub4 row_count)); -ub4 ora_parse_uid _((imp_dbh_t *imp_dbh, char **uidp, char **pwdp)); char *ora_sql_error _((imp_sth_t *imp_sth, char *msg)); char *ora_env_var(char *name, char *buf, unsigned long size); -#ifdef __CYGWIN32__ +#if defined(__CYGWIN__) || defined(__CYGWIN32__) void ora_cygwin_set_env(char *name, char *value); -#endif /* __CYGWIN32__ */ +#endif /* __CYGWIN__ */ sb4 dbd_phs_in _((dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 *alenp, ub1 *piecep, dvoid **indpp)); @@ -414,6 +399,35 @@ void rs_array_init(imp_sth_t *imp_sth); ub4 ora_db_version _((SV *dbh, imp_dbh_t *imp_dbh)); sb4 reg_taf_callback _((SV *dbh, imp_dbh_t *imp_dbh)); +int cnx_establish (pTHX_ dblogin_info_t * ); +void cnx_drop_dr(pTHX_ imp_drh_t *); +void cnx_clean(pTHX_ imp_dbh_t * ); +void cnx_detach(pTHX_ imp_dbh_t * ); +void ora_shared_release(pTHX_ SV * ); + +#ifdef ORA_OCI_112 +int cnx_get_pool_mode(pTHX_ SV *, imp_dbh_t * ); +void cnx_pool_mode(pTHX_ SV * , imp_dbh_t * , ub4); + +int cnx_get_pool_wait(pTHX_ SV *, imp_dbh_t * ); +void cnx_pool_wait(pTHX_ SV * , imp_dbh_t * , ub4); + +int cnx_get_pool_used(pTHX_ SV *, imp_dbh_t * ); + +int cnx_get_pool_rlb(pTHX_ SV *, imp_dbh_t * ); + +int cnx_get_pool_incr(pTHX_ SV *, imp_dbh_t * ); +void cnx_pool_incr(pTHX_ SV * , imp_dbh_t * , ub4); + +int cnx_get_pool_min(pTHX_ SV *, imp_dbh_t * ); +void cnx_pool_min(pTHX_ SV * , imp_dbh_t * , ub4); + +int cnx_get_pool_max(pTHX_ SV *, imp_dbh_t * ); +void cnx_pool_max(pTHX_ SV * , imp_dbh_t * , ub4); + +int cnx_is_pooled_session(pTHX_ SV *, imp_dbh_t *); +#endif + /* These defines avoid name clashes for multiple statically linked DBD's */ #define dbd_init ora_init diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index e6ccc484..ec775e9a 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -40,7 +40,9 @@ package DBD::Oracle; ); @EXPORT_OK = qw( OCI_FETCH_NEXT OCI_FETCH_CURRENT OCI_FETCH_FIRST OCI_FETCH_LAST OCI_FETCH_PRIOR OCI_FETCH_ABSOLUTE OCI_FETCH_RELATIVE ORA_OCI SQLCS_IMPLICIT SQLCS_NCHAR - ora_env_var ora_cygwin_set_env ); + OCI_SPOOL_ATTRVAL_FORCEGET OCI_SPOOL_ATTRVAL_NOWAIT OCI_SPOOL_ATTRVAL_TIMEDWAIT + OCI_SPOOL_ATTRVAL_WAIT + ora_env_var ora_cygwin_set_env ora_shared_release); #unshift @EXPORT_OK, 'ora_cygwin_set_env' if $^O eq 'cygwin'; Exporter::export_ok_tags(qw(ora_types ora_session_modes ora_fetch_orient ora_exe_modes ora_fail_over)); @@ -48,6 +50,7 @@ package DBD::Oracle; require_version DBI 1.623; DBD::Oracle->bootstrap($DBD::Oracle::VERSION); + DBD::Oracle::dr::init_globals() ; $drh = undef; # holds driver handle once initialized @@ -305,6 +308,22 @@ package DBD::Oracle; $attr->{ora_events} = $ENV{ORA_EVENTS}; } + # ORA8 does not like when "user/passwd" is used. + # so, it makes sense to separate those. This was done + # in XS, but there one didn't distinguish between + # undef and '' as password. So, to make it backward + # compatible I do the same here. + # Ignore $user eq '/' since it is special case + if((!defined $auth || $auth eq '') && length($user) > 1) + { + my $idx = index($user, '/'); + if($idx >= 0) + { + $auth = substr($user, $idx + 1); + $user = substr($user, 0, $idx); + } + } + { local @SIG{ @{ $attr->{ora_connect_with_default_signals} } } if $attr->{ora_connect_with_default_signals}; @@ -400,7 +419,6 @@ package DBD::Oracle; ora_ph_csform => undef, ora_parse_error_offset => undef, ora_dbh_share => undef, - ora_envhp => undef, ora_svchp => undef, ora_errhp => undef, ora_init_mode => undef, @@ -1572,12 +1590,26 @@ For Oracle 11.2 or greater. Set to I<1> to enable DRCP. Can also be set via the C environment variable. +Note, this really enables Session pools on Client side. Each pool is identified +by DB, user, charsets and pool mode. The latter one can be affected by +B. Sessions are kept open after disconnect, so next connect may +pick up session that was previously used. That means that any "alter session" +changes can be still in effect. One may use B to mark such sessions. + +Of course this allows saving resources and speeding up connecting. This also works +across thread-boundaries, unlike connect_cached. So, if there are multiple threads +that constantly connect and disconnect, then this option is the best solution. +It may even work in situations of single thread where libraries have to obtain connection +only for short operation and then release it. + +The feature can be combined with actual configuring of DRCP on the Server side. +Then connecting to ':pooled' DNS shall also optimize use of resources on the Server +side, since this enables sharing of server sessions between client sessions. + =head4 ora_drcp_class If you are using DRCP, you can set a CONNECTION_CLASS for your pools -as well. As sessions from a DRCP cannot be shared by users, you can -use this setting to identify the same user across different -applications. OCI will ensure that sessions belonging to a 'class' are +as well. OCI will ensure that connections belonging to a 'class' are not shared outside the class'. The values for ora_drcp_class cannot contain a '*' and must be less @@ -1587,7 +1619,7 @@ This value can be also be specified with the C environment variable. Note that a connection class must be specified in order to enable -inter-process sharing of server side sessions. +inter-process sharing of Server side sessions (:pooled connections) =head4 ora_drcp_min @@ -1630,6 +1662,23 @@ greater than ora_drcp_max. This value can also be specified with the C environment variable. +=head4 ora_drcp_mode + +By default, when count of open session reaches ora_drcp_max, the call to +connect shall block untill some session becomes free. One can change it +by setting this attribute to one of OCI_SPOOL_ATTRVAL_NOWAIT, +OCI_SPOOL_ATTRVAL_FORCEGET, OCI_SPOOL_ATTRVAL_TIMEDWAIT. The latter one +needs time in milliseconds, which is passed using attribute ora_drcp_wait. +Default value is OCI_SPOOL_ATTRVAL_WAIT. These contants can be imported +from DBD::Oracle. + +=head4 ora_drcp_tag + +This is similar to ora_drcp_class, but it is not so strict. If session +with given tag does not exist, then another session is returned, One can +check tag of that session after connection. The tag can be changed by changing +this attribute. But change happens only at "disconnect". + =head4 ora_drcp_rlb This optional value controls whether run-time connection load balancing @@ -1792,10 +1841,17 @@ initialized to an empty string. $dbh = DBI->connect ($dsn, $user, $passwd, {ora_dbh_share => \$orashr}) ; -With ithreads DBD::Oracle will leak handles, because it can't tell -when the last driver handle is destroyed. +After shared connection is not needed any more, one should call + + DBD::Oracle::ora_shared_release($orashr); -Please keep in mind, that ithreads are officially discouraged. +This shall close shared connection. The function can be imported into +current namespace (use DBD::Oracle qw/ora_shared_release/) + +Please keep in mind, this functionality is rather dangerous. One should not +use single connection in multiple threads at the same time, since access to server +is not atomic. There can be problems with transactions or fetching of rows. +It is much better to use sessions-pooling activated with B. =head4 ora_events @@ -1803,32 +1859,10 @@ Set this attribute to C<1> to enable Oracle Fast Application Notification (FAN) in a new OCI environment. Can also be set via the C environment variable. -=head4 ora_envhp - -The first time a connection is made a new OCI 'environment' is -created by DBD::Oracle and stored in the driver handle. -Subsequent connects reuse (share) that same OCI environment -by default. - -The ora_envhp attribute can be used to disable the reuse of the OCI -environment from a previous connect. If the value is C<0> then -a new OCI environment is allocated and used for this connection. - -The OCI environment holds information about the client side context, -such as the local NLS environment. By altering C<%ENV> and setting -ora_envhp to 0 you can create connections with different NLS -settings. This is most useful for testing. - -Note that for DRCP, setting C has no effect. Here, -a new session pool is created, using the current NLS environment, -for each new combination of dbname, uid/pwd, connection class, -and charset/ncharset. - =head4 ora_charset, ora_ncharset For oracle versions >= 9.2 you can specify the client charset and -ncharset with the ora_charset and ora_ncharset attributes. You -still need to pass C for all but the first connect. +ncharset with the ora_charset and ora_ncharset attributes. These attributes override the settings from environment variables. diff --git a/oci8.c b/oci8.c index 4aa268b5..b01dbe99 100644 --- a/oci8.c +++ b/oci8.c @@ -15,6 +15,7 @@ #include #endif +#undef sv_set_undef #define sv_set_undef(sv) if (SvROK(sv)) sv_unref(sv); else SvOK_off(sv) DBISTATE_DECLARE; @@ -879,15 +880,28 @@ oci_error_err(SV *h, OCIError *errhp, sword status, char *what, sb4 force_err) dTHX; D_imp_xxh(h); sb4 errcode; + int utf8_is_implied = 0; SV *errstr_sv = sv_newmortal(); SV *errcode_sv = sv_newmortal(); errcode = oci_error_get(imp_xxh, errhp, status, what, errstr_sv, DBIc_DBISTATE(imp_xxh)->debug); - if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) { + + if(DBIc_TYPE(imp_xxh) == DBIt_ST) + { + imp_sth_t * imp_sth = (imp_sth_t*)imp_xxh; + D_imp_dbh_from_sth; + utf8_is_implied = CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_IMPLICIT); + } + else if(DBIc_TYPE(imp_xxh) == DBIt_DB) + utf8_is_implied = CSFORM_IMPLIES_UTF8((imp_dbh_t *)imp_xxh, SQLCS_IMPLICIT); + else if(DBIc_TYPE(imp_xxh) == DBIt_DR) + utf8_is_implied = 0; + + if (utf8_is_implied) { #ifdef sv_utf8_decode - sv_utf8_decode(errstr_sv); + sv_utf8_decode(errstr_sv); #else - SvUTF8_on(errstr_sv); + SvUTF8_on(errstr_sv); #endif } @@ -1468,7 +1482,7 @@ fetch_func_varfield(SV *sth, imp_fbh_t *fbh, SV *dest_sv) } } sv_setpvn(dest_sv, p, (STRLEN)datalen); - if (CSFORM_IMPLIES_UTF8(fbh->csform)) + if (CSFORM_IMPLIES_UTF8(imp_dbh, fbh->csform)) SvUTF8_on(dest_sv); } else { #else @@ -1717,7 +1731,7 @@ dbd_rebind_ph_lob(SV *sth, imp_sth_t *imp_sth, phs_t *phs) return oci_error(sth, imp_sth->errhp, status, "OCILobCharSetId"); #endif /* OCI_ATTR_CHARSET_ID */ /* if data is utf8 but charset isn't then switch to utf8 csid */ - csid = (SvUTF8(phs->sv) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); + csid = (SvUTF8(phs->sv) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(imp_dbh, csform); phs->csid = csid; phs->csform = csform; } @@ -1748,6 +1762,7 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, long offset, ub4 len, long destoffset) { dTHX; + D_imp_dbh_from_sth; ub4 loblen = 0; ub4 buflen; ub4 amtp = 0; @@ -1853,7 +1868,7 @@ ora_blob_read_mb_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SvCUR_set(dest_sv, byte_destoffset+amtp); *SvEND(dest_sv) = '\0'; /* consistent with perl sv_setpvn etc */ SvPOK_on(dest_sv); - if (ftype == ORA_CLOB && CSFORM_IMPLIES_UTF8(csform)) + if (ftype == ORA_CLOB && CSFORM_IMPLIES_UTF8(imp_dbh, csform)) SvUTF8_on(dest_sv); return 1; @@ -1865,6 +1880,7 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, long offset, UV len, long destoffset) { dTHX; + D_imp_dbh_from_sth; ub4 loblen = 0; ub4 buflen; ub4 amtp = 0; @@ -1929,7 +1945,7 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, /* so for CLOBs that'll be returned as UTF8 we need more bytes that chars */ /* XXX the x4 here isn't perfect - really the code should be changed to loop */ - if (ftype == ORA_CLOB && CSFORM_IMPLIES_UTF8(csform)) { + if (ftype == ORA_CLOB && CSFORM_IMPLIES_UTF8(imp_dbh, csform)) { buflen = amtp * 4; /* XXX destoffset would be counting chars here as well */ SvGROW(dest_sv, (destoffset*4) + buflen + 1); @@ -1972,7 +1988,7 @@ ora_blob_read_piece(SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV *dest_sv, sv_set_undef(dest_sv); /* signal error */ return 0; } - if (ftype == ORA_CLOB && CSFORM_IMPLIES_UTF8(csform)) + if (ftype == ORA_CLOB && CSFORM_IMPLIES_UTF8(imp_dbh, csform)) SvUTF8_on(dest_sv); } else { @@ -2003,6 +2019,7 @@ static int fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *dest_sv, char *name) { dTHX; + D_imp_dbh_from_sth; ub4 loblen = 0; ub4 buflen = 0; ub4 amtp = 0; @@ -2155,9 +2172,9 @@ fetch_lob(SV *sth, imp_sth_t *imp_sth, OCILobLocator* lobloc, int ftype, SV *des /* tell perl what we've put in its dest_sv */ SvCUR(dest_sv) = amtp; *SvEND(dest_sv) = '\0'; - if (ftype == ORA_CLOB && CSFORM_IMPLIES_UTF8(csform)) /* Don't set UTF8 on BLOBs */ + if (ftype == ORA_CLOB && CSFORM_IMPLIES_UTF8(imp_dbh, csform)) /* Don't set UTF8 on BLOBs */ SvUTF8_on(dest_sv); - ora_free_templob(sth, imp_sth, lobloc); + ora_free_templob(sth, imp_sth, lobloc); } else { /* LOB length is 0 */ assert(amtp == 0); @@ -2321,8 +2338,8 @@ static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text *name , OCITypeC status); if (typecode == OCI_TYPECODE_TIMESTAMP_TZ || typecode == OCI_TYPECODE_TIMESTAMP_LTZ){ - char s_tz_hour[3]="000"; - char s_tz_min[3]="000"; + char s_tz_hour[6]="000"; + char s_tz_min[6]="000"; sb1 tz_hour; sb1 tz_minute; status = OCIDateTimeGetTimeZoneOffset (fbh->imp_sth->envhp, @@ -2694,7 +2711,7 @@ static int fetch_func_oci_object(SV *sth, imp_fbh_t *fbh,SV *dest_sv) { dTHX; - D_imp_sth(sth); + D_imp_sth(sth); if (DBIc_DBISTATE(imp_sth)->debug >= 4 || dbd_verbose >= 4 ) { PerlIO_printf(DBIc_LOGPIO(imp_sth), @@ -2726,6 +2743,7 @@ fetch_clbk_lob(SV *sth, imp_fbh_t *fbh,SV *dest_sv){ dTHX; D_imp_sth(sth); + D_imp_dbh_from_sth; fb_ary_t *fb_ary = fbh->fb_ary; ub4 actual_bufl=imp_sth->piece_size*(fb_ary->piece_count)+fb_ary->bufl; @@ -2756,7 +2774,7 @@ fetch_clbk_lob(SV *sth, imp_fbh_t *fbh,SV *dest_sv){ sv_setpvn(dest_sv, (char*)fb_ary->cb_abuf,(STRLEN)actual_bufl); } else { sv_setpvn(dest_sv, (char*)fb_ary->cb_abuf,(STRLEN)actual_bufl); - if (CSFORM_IMPLIES_UTF8(fbh->csform) ){ + if (CSFORM_IMPLIES_UTF8(imp_dbh, fbh->csform) ){ SvUTF8_on(dest_sv); } } @@ -2769,6 +2787,7 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) { dTHX; D_imp_sth(sth); + D_imp_dbh_from_sth; fb_ary_t *fb_ary = fbh->fb_ary; ub4 buflen = fb_ary->bufl; ub4 actual_bufl = 0; @@ -2859,7 +2878,7 @@ fetch_get_piece(SV *sth, imp_fbh_t *fbh,SV *dest_sv) sv_setpvn(dest_sv, (char*)fb_ary->cb_abuf,(STRLEN)actual_bufl); if (fbh->ftype != SQLT_BIN){ - if (CSFORM_IMPLIES_UTF8(fbh->csform) ){ /* do the UTF 8 magic*/ + if (CSFORM_IMPLIES_UTF8(imp_dbh, fbh->csform) ){ /* do the UTF 8 magic*/ SvUTF8_on(dest_sv); } } @@ -3554,7 +3573,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) avg_width = fbh->dbsize / 2; /* FALLTHRU */ case ORA_CHAR: /* CHAR */ - if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) + if ( CSFORM_IMPLIES_UTF8(imp_dbh, fbh->csform) && !CS_IS_UTF8(fbh->csid) ) fbh->disize = fbh->dbsize * 4; else fbh->disize = fbh->dbsize; @@ -3616,7 +3635,7 @@ dbd_describe(SV *h, imp_sth_t *imp_sth) } else { - if ( CSFORM_IMPLIES_UTF8(fbh->csform) && !CS_IS_UTF8(fbh->csid) ) + if ( CSFORM_IMPLIES_UTF8(imp_dbh, fbh->csform) && !CS_IS_UTF8(fbh->csid) ) fbh->disize = long_readlen * 4; else fbh->disize = long_readlen; @@ -4182,19 +4201,19 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ if (sts == 0) { sprintf(errstr, - "over/under flow converting column %d to type %"IVdf"", - i+1, fbh->req_type); + "over/under flow converting column %d to type %ld", + i+1, (long)fbh->req_type); oci_error(sth, imp_sth->errhp, OCI_ERROR, errstr); return Nullav; } else if (sts == -2) { sprintf(errstr, - "unsupported bind type %"IVdf" for column %d", - fbh->req_type, i+1); + "unsupported bind type %ld for column %d", + (long)fbh->req_type, i+1); /* issue warning */ DBIh_SET_ERR_CHAR(sth, imp_xxh, "0", 1, errstr, Nullch, Nullch); - if (CSFORM_IMPLIES_UTF8(fbh->csform) ){ + if (CSFORM_IMPLIES_UTF8(imp_dbh, fbh->csform) ){ SvUTF8_on(sv); } } @@ -4202,7 +4221,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ else #endif /* DBISTATE_VERSION > 94 */ { - if (CSFORM_IMPLIES_UTF8(fbh->csform) ){ + if (CSFORM_IMPLIES_UTF8(imp_dbh, fbh->csform) ){ SvUTF8_on(sv); } } @@ -4222,7 +4241,7 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ /* Copy the truncated value anyway, it may be of use, */ /* but it'll only be accessible via prior bind_column() */ sv_setpvn(sv, (char *)row_data,fb_ary->arlen[imp_sth->rs_array_idx]); - if ((CSFORM_IMPLIES_UTF8(fbh->csform)) && (fbh->ftype != SQLT_BIN)){ + if ((CSFORM_IMPLIES_UTF8(imp_dbh, fbh->csform)) && (fbh->ftype != SQLT_BIN)){ SvUTF8_on(sv); } } @@ -4252,61 +4271,124 @@ dbd_st_fetch(SV *sth, imp_sth_t *imp_sth){ } -ub4 -ora_parse_uid(imp_dbh_t *imp_dbh, char **uidp, char **pwdp) +static int +local_error(pTHX_ SV * h, const char * fmt, ...) { - dTHX; - sword status; - - /* OCI 8 does not seem to allow uid to be "name/pass" :-( */ - /* so we have to split it up ourselves */ - if (strlen(*pwdp)==0 && strchr(*uidp,'/')) { - SV *tmpsv = sv_2mortal(newSVpv(*uidp,0)); - *uidp = SvPVX(tmpsv); - *pwdp = strchr(*uidp, '/'); - *(*pwdp)++ = '\0'; - /* XXX look for '@', e.g. "u/p@d" and "u@d" and maybe "@d"? */ - } - if (**uidp == '\0' && **pwdp == '\0') { - return OCI_CRED_EXT; - } -#ifdef ORA_OCI_112 - if (!imp_dbh->using_drcp) { -#endif - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, - *uidp, strlen(*uidp), - (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp, status); - - OCIAttrSet_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, - (strlen(*pwdp)) ? *pwdp : NULL, strlen(*pwdp), - (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp, status); -#ifdef ORA_OCI_112 - } -#endif - return OCI_CRED_RDBMS; + va_list ap; + SV * txt_sv = sv_newmortal(); + SV * code_sv = get_sv("DBI::stderr", 0); + D_imp_xxh(h); + if(code_sv == NULL) + { + code_sv = sv_newmortal(); + sv_setiv(code_sv, 2000000000); + } + va_start(ap, fmt); + sv_vsetpvf(txt_sv, fmt, &ap); + va_end(ap); + DBIh_SET_ERR_SV(h, imp_xxh, code_sv, txt_sv, &PL_sv_undef, &PL_sv_undef); + return FALSE; } - int ora_db_reauthenticate(SV *dbh, imp_dbh_t *imp_dbh, char *uid, char *pwd) { dTHX; sword status; + OCISession *seshp; + char * driver_name; + ub4 namelen, ulen, plen, credt; #ifdef ORA_OCI_112 - if (imp_dbh->using_drcp) { - return 0; - } + if (cnx_is_pooled_session(aTHX_ dbh, imp_dbh)) + return local_error(aTHX_ dbh, "Can't reauthenticate pooled session"); #endif - /* XXX should possibly create new session before ending the old so */ - /* that if the new one can't be created, the old will still work. */ - OCISessionEnd_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, - imp_dbh->seshp, OCI_DEFAULT, status); /* XXX check status here?*/ - OCISessionBegin_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, imp_dbh->seshp, - ora_parse_uid(imp_dbh, &uid, &pwd), (ub4) OCI_DEFAULT, status); +#if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar) + if (imp_dbh->is_shared) + return local_error(aTHX_ dbh, "Can't reauthenticate shared session"); +#endif + OCIHandleAlloc_ok( + imp_dbh, imp_dbh->envhp, + &seshp, OCI_HTYPE_SESSION, status + ); + OCIAttrGet_log_stat( + imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, + &driver_name, &namelen, OCI_ATTR_DRIVER_NAME, + imp_dbh->errhp, status + ); + if(status == OCI_SUCCESS && namelen != 0) + { + OCIAttrSet_log_stat( + imp_dbh, seshp, OCI_HTYPE_SESSION, + driver_name, namelen, OCI_ATTR_DRIVER_NAME, + imp_dbh->errhp, status + ); + if (status != OCI_SUCCESS) + { + (void)oci_error(dbh, imp_dbh->errhp, + status, "OCIAttrSet OCI_ATTR_DRIVER_NAME" + ); + OCIHandleFree_log_stat(imp_dbh, seshp, OCI_HTYPE_SESSION, status); + return 0; + } + } + plen = (ub4)strlen(pwd); + ulen = (ub4)strlen(uid); + if (plen == 0 && ulen == 0) credt = OCI_CRED_EXT; + else + { + OCIAttrSet_log_stat(imp_dbh, seshp, OCI_HTYPE_SESSION, + uid, ulen, + (ub4) OCI_ATTR_USERNAME, imp_dbh->errhp, status); + if (status != OCI_SUCCESS) + { + (void)oci_error(dbh, imp_dbh->errhp, + status, "OCIAttrSet OCI_ATTR_USERNAME" + ); + OCIHandleFree_log_stat(imp_dbh, seshp, OCI_HTYPE_SESSION, status); + return 0; + } + + OCIAttrSet_log_stat(imp_dbh, seshp, OCI_HTYPE_SESSION, + ((plen) ? pwd : NULL), plen, + (ub4) OCI_ATTR_PASSWORD, imp_dbh->errhp, status); + if (status != OCI_SUCCESS) + { + (void)oci_error(dbh, imp_dbh->errhp, + status, "OCIAttrSet OCI_ATTR_PASSWORD" + ); + OCIHandleFree_log_stat(imp_dbh, seshp, OCI_HTYPE_SESSION, status); + return 0; + } + credt = OCI_CRED_RDBMS; + } + + OCISessionBegin_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, seshp, + credt, OCI_DEFAULT, status); if (status != OCI_SUCCESS) { - oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); - return 0; - } + oci_error(dbh, imp_dbh->errhp, status, "OCISessionBegin"); + OCIHandleFree_log_stat(imp_dbh, seshp, OCI_HTYPE_SESSION, status); + return 0; + } + OCIAttrSet_log_stat( + imp_dbh, imp_dbh->svchp, + (ub4) OCI_HTYPE_SVCCTX, + seshp, 0, OCI_ATTR_SESSION, + imp_dbh->errhp, status + ); + if (status != OCI_SUCCESS) + { + (void)oci_error( + dbh, imp_dbh->errhp, status, "OCIAttrSet OCI_ATTR_SESSION" + ); + OCISessionEnd_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, + seshp, OCI_DEFAULT, status); + OCIHandleFree_log_stat(imp_dbh, seshp, OCI_HTYPE_SESSION, status); + return 0; + } + OCISessionEnd_log_stat(imp_dbh, imp_dbh->svchp, imp_dbh->errhp, + imp_dbh->seshp, OCI_DEFAULT, status); + OCIHandleFree_log_stat(imp_dbh, imp_dbh->seshp, OCI_HTYPE_SESSION, status); + imp_dbh->seshp = seshp; return 1; } @@ -4411,6 +4493,7 @@ static int init_lob_refetch(SV *sth, imp_sth_t *imp_sth) { dTHX; + D_imp_dbh_from_sth; SV *sv; SV *sql_select; HV *lob_cols_hv = NULL; @@ -4457,10 +4540,12 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) if (status == OCI_SUCCESS) { /* There is a synonym, get the schema */ char *syn_schema=NULL; - char syn_name[100]; + char *syn_name; ub4 tn_len = 0, syn_schema_len = 0; - strncpy(syn_name,tablename,strlen(tablename)); + Newx(syn_name, 1 + strlen(tablename), char); + + strcpy(syn_name,tablename); /* Put the synonym name here for later user */ OCIAttrGet_log_stat(imp_sth, imp_sth->dschp, OCI_HTYPE_DESCRIBE, @@ -4486,7 +4571,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) " lob refetch using a synonym named=%s for %s \n", syn_name,tablename); - + Safefree(syn_name); } OCIDescribeAny_log_stat(imp_sth, imp_sth->svchp, errhp, tablename, strlen(tablename), (ub1)OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_TABLE, imp_sth->dschp, status); @@ -4558,7 +4643,7 @@ init_lob_refetch(SV *sth, imp_sth_t *imp_sth) sv = newSViv(col_dbtype); (void)sv_setpvn(sv, col_name, col_name_len); - if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) + if (CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_IMPLICIT)) SvUTF8_on(sv); (void)SvIOK_on(sv); /* "what a wonderful hack!" */ @@ -4854,7 +4939,7 @@ post_execute_lobs(SV *sth, imp_sth_t *imp_sth, ub4 row_count) /* XXX leaks handl return oci_error(sth, errhp, status, "OCILobCharSetId"); #endif /* OCI_ATTR_CHARSET_ID */ /* if data is utf8 but charset isn't then switch to utf8 csid */ - csid = (SvUTF8(phs->sv) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(csform); + csid = (SvUTF8(phs->sv) && !CS_IS_UTF8(csid)) ? utf8_csid : CSFORM_IMPLIED_CSID(imp_dbh, csform); fbh->csid = csid; fbh->csform = csform; } diff --git a/ocitrace.h b/ocitrace.h index 3955d6fb..1adc8a7c 100644 --- a/ocitrace.h +++ b/ocitrace.h @@ -48,8 +48,8 @@ stat =OCISessionRelease(svchp, errhp, tag, tagl, mode);\ (DBD_OCI_TRACEON(impdbh)) \ ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ - "%sOCISessionRelease(svchp=%p,tag=\"%s\",mode=%u)=%s\n",\ - OciTp, svchp,tag,mode,oci_status_name(stat)),stat \ + "%sOCISessionRelease(svchp=%p,mode=%u)=%s\n",\ + OciTp, svchp,mode,oci_status_name(stat)),stat \ : stat #define OCISessionPoolDestroy_log_stat(impdbh, ph, errhp,stat ) \ @@ -63,8 +63,8 @@ stat =OCISessionGet(envhp, errhp, sh, ah,pn,pnl,tag,tagl,rettag,rettagl,found, OCI_SESSGET_SPOOL);\ (DBD_OCI_TRACEON(impdbh)) \ ? PerlIO_printf(DBD_OCI_TRACEFP(impdbh), \ - "%sOCISessionGet(envhp=%p,sh=%p,ah=%p,pn=%p,pnl=%d,tag=\"%s\",found=%d)=%s\n",\ - OciTp, envhp,sh,ah,pn,pnl,tag,*found,oci_status_name(stat)),stat \ + "%sOCISessionGet(envhp=%p,sh=%p,ah=%p,pn=%p,pnl=%d,found=%d)=%s\n",\ + OciTp, envhp,sh,ah,pn,pnl,*found,oci_status_name(stat)),stat \ : stat #define OCISessionPoolCreate_log_stat(impdbh,envhp,errhp,ph,pn,pnl,dbn,dbl,sn,sm,si,un,unl,pw,pwl,mode,stat) \ @@ -321,12 +321,12 @@ OCIAttrGet_log_stat(imp_sth, stmhp, OCI_HTYPE_STMT, \ (void*)(p1), (l), (a), imp_sth->errhp, stat) -#define OCIAttrSet_log_stat(impxxh,th,ht,ah,s1,a,eh,stat) \ +#define OCIAttrSet_log_stat(impxxh,th,ht,ah,s1,a,eh,stat) do{\ stat=OCIAttrSet(th,ht,ah,s1,a,eh); \ (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sAttrSet(%p,%s, %p,%lu,Attr=%s,%p)=%s\n", \ OciTp, (void*)th,oci_hdtype_name(ht),(void *)ah,ul_t(s1),oci_attr_name(a),(void*)eh, \ - oci_status_name(stat)),stat : stat + oci_status_name(stat)),stat : stat; }while(0) #define OCIBindByName_log_stat(impsth,sh,bp,eh,p1,pl,v,vs,dt,in,al,rc,mx,cu,md,stat) \ stat=OCIBindByName(sh,bp,eh,p1,pl,v,vs,dt,in,al,rc,mx,cu,md); \ @@ -369,17 +369,17 @@ (ub1)opt,(ub1)il,(ub1)ot,(void*)dh, \ oci_status_name(stat)),stat : stat -#define OCIDescriptorAlloc_ok(impxxh,envhp, p1, t) \ +#define OCIDescriptorAlloc_ok(impxxh,envhp, p1, t) do{ \ if (DBD_OCI_TRACEON(impxxh)) PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sDescriptorAlloc(%p,%p,%s,0,0)\n", \ OciTp,(void*)envhp,(void*)(p1),oci_hdtype_name(t)); \ if (OCIDescriptorAlloc((envhp), (void**)(p1), (t), 0, 0)==OCI_SUCCESS); \ - else croak("OCIDescriptorAlloc (type %d) failed",t) + else croak("OCIDescriptorAlloc (type %d) failed",t); }while(0) -#define OCIDescriptorFree_log(impxxh,d,t) \ +#define OCIDescriptorFree_log(impxxh,d,t) do{\ if (DBD_OCI_TRACEON(impxxh)) PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sDescriptorFree(%p,%s)\n", OciTp, (void*)d,oci_hdtype_name(t)); \ - OCIDescriptorFree(d,t) + OCIDescriptorFree(d,t); }while(0) #define OCIEnvInit_log_stat(impdbh,ev,md,xm,um,stat) \ stat=OCIEnvInit(ev,md,xm,um); \ @@ -407,18 +407,18 @@ if (stat==OCI_SUCCESS) ; \ else croak("OCIHandleAlloc(%s) failed",oci_hdtype_name(t)) -#define OCIHandleFree_log_stat(impxxh,hp,t,stat) \ +#define OCIHandleFree_log_stat(impxxh,hp,t,stat) do{ \ stat=OCIHandleFree( (hp), (t)); \ - (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ + if(DBD_OCI_TRACEON(impxxh)) PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sHandleFree(%p,%s)=%s\n",OciTp,(void*)hp,oci_hdtype_name(t), \ - oci_status_name(stat)),stat : stat + oci_status_name(stat)); }while(0) -#define OCILobGetLength_log_stat(impxxh,sh,eh,lh,l,stat) \ +#define OCILobGetLength_log_stat(impxxh,sh,eh,lh,l,stat) do{ \ stat=OCILobGetLength(sh,eh,lh,l); \ (DBD_OCI_TRACEON(impxxh)) ? PerlIO_printf(DBD_OCI_TRACEFP(impxxh), \ "%sLobGetLength(%p,%p,%p,%p)=%s\n", \ OciTp, (void*)sh,(void*)eh,(void*)lh,pul_t(l), \ - oci_status_name(stat)),stat : stat + oci_status_name(stat)),stat : stat; }while(0) #define OCILobGetChunkSize_log_stat(impdbh,sh,eh,lh,cs,stat) \ diff --git a/t/15threads.t b/t/15threads.t new file mode 100644 index 00000000..e067daf2 --- /dev/null +++ b/t/15threads.t @@ -0,0 +1,102 @@ +#!perl + +use strict; +use warnings; +# This needs to be the very very first thing +BEGIN { eval 'use threads; use threads::shared;' } +use Config qw(%Config); +use Test::More; +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; +use DBD::Oracle qw(ora_shared_release); + +$| = 1; +if ( !$Config{useithreads} || "$]" < 5.008 ) { + plan skip_all => "this $^O perl $] not configured to support iThreads"; + exit(0); +} +if ( $DBI::VERSION <= 1.601 ) { + plan skip_all => 'DBI version ' + . $DBI::VERSION + . ' does not support iThreads. Use version 1.602 or later.'; + exit(0); +} +my $dbh = db_handle( { PrintError => 0 } ); + +if ($dbh) { + $dbh->disconnect; +} +else { + plan skip_all => 'Unable to connect to Oracle'; +} +my $last_session : shared; +my $holder : shared; + +for my $i ( 0 .. 4 ) { + threads->create( + sub { + my $dbh = db_handle( { ora_dbh_share => \$holder, PrintError => 0 } ); + if($dbh) + { + my $session = session_id($dbh); + + if ( $i > 0 ) { + is $session, $last_session, + "session $i matches previous session"; + } + else { + ok $session, "session $i created",; + } + + $last_session = $session; + $dbh->disconnect(); + } + else + { + ok 0, "no connection " . $DBI::errstr; + } + } + )->join; +} +ora_shared_release($holder); + +# now the same, but let shared variable be destroyed +threads->create( + sub { + my $other : shared; + for my $i ( 0 .. 4 ) { + threads->create( + sub { + my $dbh = db_handle( { ora_dbh_share => \$other, PrintError => 0 } ); + if($dbh) + { + my $session = session_id($dbh); + + if ( $i > 0 ) { + is $session, $last_session, + "session $i matches previous session"; + } + else { + ok $session, "session $i created",; + } + + $last_session = $session; + $dbh->disconnect(); + } + else + { + ok 0, "no connection " . $DBI::errstr; + } + } + )->join; + } + ora_shared_release($other); + } +)->join; +done_testing; + +sub session_id { + my $dbh = shift; + my ($s) = $dbh->selectrow_array("select userenv('sid') from dual"); + return $s; +} diff --git a/t/16cached.t b/t/16cached.t new file mode 100644 index 00000000..1177d1d0 --- /dev/null +++ b/t/16cached.t @@ -0,0 +1,30 @@ +#!perl +#written by Andrey A Voropaev (avorop@mail.ru) + +use strict; +use warnings; + +use Test::More; +use DBI; +use FindBin qw($Bin); +use lib 't/lib'; +use DBDOracleTestLib qw/ db_handle /; + +my $dbh; +$| = 1; +SKIP: { + $dbh = db_handle(); + + # $dbh->{PrintError} = 1; + plan skip_all => 'Unable to connect to Oracle' unless $dbh; + + note("Testing multiple cached connections...\n"); + + plan tests => 1; + + system("perl -MExtUtils::testlib $Bin/cache2.pl"); + ok($? == 0, "clean termination with multiple cached connections"); +} + +__END__ + diff --git a/t/16drcp.t b/t/16drcp.t new file mode 100644 index 00000000..9b6a4ca1 --- /dev/null +++ b/t/16drcp.t @@ -0,0 +1,112 @@ +#!perl + +use strict; +use warnings; +# This needs to be the very very first thing +BEGIN { eval 'use threads; use threads::shared;' } + +$| = 1; + +## ---------------------------------------------------------------------------- +## 16drcp.t +## By Andrey A. Voropaev +## ---------------------------------------------------------------------------- +use lib 't/lib'; +use DBDOracleTestLib qw/ oracle_test_dsn db_handle /; +use DBD::Oracle qw(OCI_SPOOL_ATTRVAL_NOWAIT); +use DBI; +use Test::More; + +{ + my $dbh = db_handle( { PrintError => 0 } ); + + if ($dbh) { + $dbh->disconnect; + } + else { + plan skip_all => 'Unable to connect to Oracle'; + } +} + +{ + my $dbh = db_handle( { ora_drcp=>1, ora_drcp_max => 2, PrintError => 0 } ); + ok defined $dbh, 'first connection from pool'; + my $dbh1 = db_handle( { ora_drcp=>1, PrintError => 0 } ); + ok defined $dbh1, 'second connection from pool'; + is $dbh->{ora_drcp_used}, 2, 'count of used connections is 2'; + $dbh->{ora_drcp_mode} = OCI_SPOOL_ATTRVAL_NOWAIT; + my $dbh2 = db_handle( { ora_drcp=>1, PrintError => 0 } ); + ok !defined $dbh2, 'third connection from pool not allowed'; + + $dbh->do(q(alter session set NLS_DATE_FORMAT='yyyy.mm.dd')); + $dbh->{ora_drcp_tag} = 's1'; + $dbh1->do(q(alter session set NLS_DATE_FORMAT='dd.mm.yyyy')); + $dbh1->{ora_drcp_tag} = 's2'; + + $dbh->disconnect(); + $dbh1->disconnect(); +} +{ + my $dbh = db_handle( { ora_drcp=>1, ora_drcp_tag=> 's1', PrintError => 0 } ); + if ($dbh) { + my $found_tag = $dbh->{ora_drcp_tag}; + ok((defined $found_tag && $found_tag eq 's1'), 's1 session from pool'); + my $sth = $dbh->prepare('select sysdate from dual'); + $sth->execute(); + my $x = $sth->fetchall_arrayref(); + ok($x->[0][0] =~ /^\d{4}\.\d\d\.\d\d$/, "date in format yyyy.mm.dd"); + $dbh->disconnect(); + } + else { + ok 0, 'finding session s1'; + } +} +{ + my $dbh = db_handle( { ora_drcp=>1, ora_drcp_tag=> 's2', PrintError => 0 } ); + if ($dbh) { + my $found_tag = $dbh->{ora_drcp_tag}; + ok((defined $found_tag && $found_tag eq 's2'), 's2 session from pool'); + my $sth = $dbh->prepare('select sysdate from dual'); + $sth->execute(); + my $x = $sth->fetchall_arrayref(); + ok($x->[0][0] =~ /^\d\d\.\d\d\.\d{4}$/, "date in format dd.mm.yyyy"); + $dbh->disconnect(); + } + else { + ok 0, 'finding session s2'; + } +} + +eval{ + my @sts : shared;; + my $th1 = threads->create( + sub{ chk('s1', qr(\d{4}\.\d\d\.\d\d), $sts[0]) } + ); + my $th2 = threads->create( + sub {chk('s2', qr(\d\d\.\d\d\.\d{4}), $sts[1]) } + ); + $th1->join(); + $th2->join(); + ok($sts[0], 'first thread'); + ok($sts[1], 'second thread'); +}; + +done_testing; + +sub chk +{ + my $tag = shift; + my $p = shift; + my $dbh = db_handle( { ora_drcp=>1, ora_drcp_tag=> $tag, PrintError => 0 } ); + if ($dbh) { + my $found_tag = $dbh->{ora_drcp_tag}; + my $sth = $dbh->prepare('select sysdate from dual'); + $sth->execute(); + my $x = $sth->fetchall_arrayref(); + $_[0] = $found_tag eq $tag && $x->[0][0] =~ /^$p$/; + $dbh->disconnect(); + } + else { + $_[0] = 0; + } +} diff --git a/t/22cset.t b/t/22cset.t new file mode 100644 index 00000000..5efee25a --- /dev/null +++ b/t/22cset.t @@ -0,0 +1,125 @@ +#!perl +#written by Andrey A Voropaev (avorop@mail.ru) + +use strict; +use warnings; + +use Test::More; +use DBI; +use DBD::Oracle qw(ORA_OCI); +use Encode; +use lib 't/lib'; +use DBDOracleTestLib qw/ db_handle drop_table table force_drop_table /; + +my $dbh1; +my $dbh2; +$| = 1; +SKIP: { + plan skip_all => + 'Unable to run multiple cset test, perl version is less than 5.6' + unless ( $] >= 5.006 ); + + $dbh1 = db_handle({ + RaiseError => 0, + PrintError => 0, + AutoCommit => 1, + ora_charset => 'WE8MSWIN1252', + }); + + plan skip_all => 'Unable to connect to Oracle' unless $dbh1; + + plan skip_all => 'Oracle charset tests unreliable for Oracle 8 client' + if ORA_OCI() < 9.0 and !$ENV{DBD_ALL_TESTS}; + + my $h = $dbh1->ora_nls_parameters(); + my $chs = $h->{NLS_CHARACTERSET}; + if($chs ne 'WE8MSWIN1252' && $chs ne 'WE8ISO8859P1' && $chs !~ /^AL[13]/) + { + plan skip_all => 'Oracle uses incompatible charset'; + } + note("Testing multiple connections with different charsets...\n"); + + $dbh2 = db_handle({ + RaiseError => 0, + PrintError => 0, + AutoCommit => 1, + ora_charset => 'AL32UTF8', + }); + + my $testcount = 3; + + plan tests => $testcount; + + my $tname = table(); + force_drop_table($dbh1); + $dbh1->do( + qq{create table $tname (idx number, txt varchar2(50))} + ); + die "Failed to create test table\n" if($dbh1->err); + + my $sth = $dbh1->prepare( + qq{insert into $tname (idx, txt) values(?, ?)} + ); + my $utf8_txt = 'äöüÜÖÄ'; + my $x = $utf8_txt; + Encode::from_to($x, 'UTF-8', 'Latin1'); + $sth->execute(1, $x); + + $sth = $dbh1->prepare( + qq{select txt from $tname where idx=1} + ); + $sth->execute(); + my $r = $sth->fetchall_arrayref(); + ok(must_be_latin1($r, $utf8_txt), "Latin1 support"); + + $sth = $dbh2->prepare( + qq{insert into $tname (idx, txt) values(?, ?)} + ); + # insert bytes + $x = $utf8_txt; + $sth->execute(2, $x); + # insert characters + $x = $utf8_txt; + $sth->execute(3, Encode::decode('UTF-8', $x)); + + $sth = $dbh2->prepare( + qq{select txt from $tname where idx=?} + ); + $sth->execute(2); + $r = $sth->fetchall_arrayref(); + ok(must_be_utf8($r, $utf8_txt), "UTF-8 as bytes"); + $sth->execute(3); + $r = $sth->fetchall_arrayref(); + ok(must_be_utf8($r, $utf8_txt), "UTF-8 as characters"); +} + +sub must_be_latin1 +{ + my $r = shift; + return unless @$r == 1; + my $x = $r->[0][0]; + # it shouldn't be encoded + return if Encode::is_utf8($x); + Encode::from_to($x, 'Latin1', 'UTF-8'); + return $x eq $_[0]; +} + +sub must_be_utf8 +{ + my $r = shift; + return unless @$r == 1; + my $x = $r->[0][0]; + # it should be encoded + return unless Encode::is_utf8($x); + return Encode::encode('UTF-8', $x) eq $_[0]; +} + + +END { + eval { + drop_table($dbh1) + }; +} + +__END__ + diff --git a/t/25plsql.t b/t/25plsql.t index 7f505414..680874cc 100644 --- a/t/25plsql.t +++ b/t/25plsql.t @@ -331,7 +331,7 @@ SKIP: { # Also see http://www.mail-archive.com/dbi-users@perl.org/msg18835.html # Known bad OCI versions - my @bad_oci_vers = (9.2, 18.3, 18.5, 19.6, 19.9, 19.13, 21.4, 21.5); + my @bad_oci_vers = (9.2, 18.3, 18.5, 19.6, 19.9, 19.13, 21.3, 21.4, 21.5); skip 'Client version is known to have issue', 4 if grep { $_ == DBD::Oracle::ORA_OCI() } @bad_oci_vers; diff --git a/t/38taf.t b/t/38taf.t index ba7d0398..3fd6e898 100644 --- a/t/38taf.t +++ b/t/38taf.t @@ -22,10 +22,8 @@ $dbh->disconnect; if ( !$dbh->ora_can_taf ) { - eval { - $dbh = db_handle( { ora_taf_function => 'taf' } ); - }; - my $ev = $@; + $dbh = db_handle( { PrintError => 0, RaiseError => 0, ora_taf_function => 'taf' } ); + my $ev = $dbh->errstr; like( $ev, qr/You are attempting to enable TAF/, "'$ev' (expected)" ); } else { diff --git a/t/58object.t b/t/58object.t index de602a6f..0a05116b 100644 --- a/t/58object.t +++ b/t/58object.t @@ -13,7 +13,14 @@ use Test::More; $| = 1; -$ENV{NLS_DATE_FORMAT} = 'YYYY-MM-DD"T"HH24:MI:SS'; +if($^O eq 'cygwin') +{ + DBD::Oracle::ora_cygwin_set_env('NLS_DATE_FORMAT', 'YYYY-MM-DD"T"HH24:MI:SS'); +} +else +{ + $ENV{NLS_DATE_FORMAT} = 'YYYY-MM-DD"T"HH24:MI:SS'; +} # create a database handle my $dbh = eval{ db_handle( { diff --git a/t/cache2.pl b/t/cache2.pl new file mode 100644 index 00000000..6738b2c6 --- /dev/null +++ b/t/cache2.pl @@ -0,0 +1,63 @@ +#!perl +#written by Andrey A Voropaev (avorop@mail.ru) + +use strict; + +use DBI; + +tst1(); +tst2(); +tst1(); +tst2(); + +sub tst1 +{ + my $dbh = db_handle({ + RaiseError => 0, + PrintError => 0, + AutoCommit => 1, + ora_charset => 'WE8MSWIN1252', + }); + my $sth = $dbh->prepare( + q{ select 1 from dual } + ); + $sth->execute(); + my $r = $sth->fetchall_arrayref(); +} + +sub tst2 +{ + my $dbh = db_handle({ + RaiseError => 0, + PrintError => 0, + AutoCommit => 1, + ora_charset => 'AL32UTF8', + }); + my $sth = $dbh->prepare( + q{ select 2 from dual } + ); + $sth->execute(); + my $r = $sth->fetchall_arrayref(); +} + + +sub oracle_test_dsn { + my ( $default, $dsn ) = ( 'dbi:Oracle:', $ENV{ORACLE_DSN} ); + + $dsn ||= $ENV{DBI_DSN} + if $ENV{DBI_DSN} && ( $ENV{DBI_DSN} =~ m/^$default/io ); + $dsn ||= $default; + + return $dsn; +} + +sub db_handle { + + my $p = shift; + my $dsn = oracle_test_dsn(); + my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger'; + my $dbh = DBI->connect_cached( $dsn, $dbuser, '', $p ); + return $dbh + +} + From d516423b5240f21df89df1278c6b222ef02b77e0 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 23 Mar 2022 20:08:03 -0700 Subject: [PATCH 614/637] Update changes for PR#150 --- Changes | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes b/Changes index 594aeb54..49b7ead6 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,7 @@ Revision history for DBD::Oracle {{$NEXT}} + Rewrite of login6. This is an enormous rewrite which should fix many problems - (PR#150, Andrei Voropaev) Have find_headers() also search for header files based off the major version number - (GH#142, Wesley Hinds) Check for appropriate permissions before running 56embbeded.t tests - (#143, Wesley Hinds) Updated links in doc in Oracle.pm - (Gh#145, kjetillll) From ac43585e8428f203c647533a9b9d31ece75ad8da Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 23 Mar 2022 20:08:16 -0700 Subject: [PATCH 615/637] Bump version to dev of v1.90 --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 2beb0cf5..eeed0a5f 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.83 +version = 1.90_1 ; Generate files From ba9d91dd039d4cb87e2e7151f11f55e24febf9c9 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 23 Mar 2022 20:25:43 -0700 Subject: [PATCH 616/637] Swap from MetaYAML to MetaJSON --- MANIFEST | 2 +- dist.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MANIFEST b/MANIFEST index c0d11526..68b6dd78 100644 --- a/MANIFEST +++ b/MANIFEST @@ -4,7 +4,7 @@ Changes INSTALL LICENSE MANIFEST -META.yml +META.json Makefile.PL Oracle.h Oracle.xs diff --git a/dist.ini b/dist.ini index eeed0a5f..cdadf4b7 100644 --- a/dist.ini +++ b/dist.ini @@ -25,7 +25,7 @@ version = 1.90_1 bugs = 1 ; remote = upstream -[MetaYAML] +[MetaJSON] [PodWeaver] [License] From 3ad9cd2421de7c804c28ab70dc3fb688dbacbd96 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 23 Mar 2022 20:31:34 -0700 Subject: [PATCH 617/637] Fix up bugtracker data in META information --- dist.ini | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dist.ini b/dist.ini index cdadf4b7..dbf7fbed 100644 --- a/dist.ini +++ b/dist.ini @@ -21,9 +21,7 @@ version = 1.90_1 [ContributorsFile] [InstallGuide] [GithubMeta] -; fork = 1 -bugs = 1 -; remote = upstream +issues = 1 [MetaJSON] [PodWeaver] From ad42341c938ba18ac7c56932526af2b93e7a828c Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 24 Mar 2022 22:31:41 -0700 Subject: [PATCH 618/637] Bump docker image to 5.32.1 --- maint/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maint/Dockerfile b/maint/Dockerfile index 18f47313..10057c4d 100644 --- a/maint/Dockerfile +++ b/maint/Dockerfile @@ -1,4 +1,4 @@ -FROM perl:5.32-threaded-buster +FROM perl:5.32.1-threaded-buster # This will install Oracle XE database and the Oracle SDK to make developing easier # It leans on the same scripts used by travis, so they can be tweaked here too From d37ca32e80e6933fc18d9fc07f3fd4daf0fa79c6 Mon Sep 17 00:00:00 2001 From: Andrei Voropaev Date: Sat, 9 Apr 2022 10:15:12 +0200 Subject: [PATCH 619/637] Add protection for older OCI This version uses to defines from oci.h, which where added after version 12. Since I don't know exact version, when they were added, I protect their usage by check for OCI above 18. For older OCI these variables will be unavailable. Additionally I've tried to fix some warnings in Makefile.PL and stopped t/25plsql.t from checking if OCI has bug. After all DBD::Oracle does not protect against this bug, so there is no sense to check if OCI has it. --- Makefile.PL | 8 ++++---- Oracle.h | 7 +++++++ dbdcnx.c | 10 ++++++++-- dbdimp.c | 4 ++++ dbdimp.h | 2 ++ lib/DBD/Oracle.pm | 10 +++++++++- t/25plsql.t | 4 +--- 7 files changed, 35 insertions(+), 10 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 26f089c1..75056ec2 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -874,7 +874,7 @@ if ($^O eq 'aix' and $osvers >= 4 and $Config{cc} ne 'xlc_r') { sleep 5; } -if ($Config{archname} !~ /-thread\b/i) { +if ($Config{archname} !~ /-threads?\b/i) { print "\n"; print "WARNING: If you have problems you may need to rebuild perl with threading enabled.$BELL\n"; sleep 5; @@ -887,7 +887,7 @@ if ($Config{usemymalloc} eq 'y') { } print "WARNING: Your GNU C compiler is very old. Please upgrade.\n" - if ($Config{gccversion} and $Config{gccversion} =~ m/^(1|2\.[1-5])/); + if ($Config{gccversion} and $Config{gccversion} =~ m/^(1\.|2\.[1-5])/); if ($opts{LINKTYPE} && $opts{LINKTYPE} eq 'static') { print "** Note: DBD::Oracle will be built *into* a NEW perl binary. You MUST use that new perl.\n"; @@ -1789,8 +1789,8 @@ sub symbol_search { eval { # This chunk is for Oracle::OCI require Data::Dumper; - print main::MK_PM Data::Dumper->Purity(1)->Terse(0)->Indent(1)->Useqq(1) - ->Dump([\%opts, $self], [qw(dbd_oracle_mm_opts dbd_oracle_mm_self)]); + my $dmp = Data::Dumper->new([\%opts, $self], [qw(dbd_oracle_mm_opts dbd_oracle_mm_self)]); + print main::MK_PM $dmp->Purity(1)->Terse(0)->Indent(1)->Useqq(1)->Dump; }; if ($@) { warn "Can't dump config to mk.pm so you won't be able to build Oracle::OCI later if you wanted to: $@\n"; diff --git a/Oracle.h b/Oracle.h index b2dca39e..6c42c2c7 100644 --- a/Oracle.h +++ b/Oracle.h @@ -118,6 +118,13 @@ ub4 ora_blob_read_mb_piece _((SV *sth, imp_sth_t *imp_sth, imp_fbh_t *fbh, SV * #define ORA_XMLTYPE 108 +/* define some constants from newer OCI versions */ +#ifndef OCI_SPOOL_ATTRVAL_TIMEDWAIT +#define OCI_SPOOL_ATTRVAL_TIMEDWAIT 3 +#endif +#ifndef OCI_SPOOL_ATTRVAL_NOWAIT +#define OCI_SPOOL_ATTRVAL_NOWAIT 1 +#endif /* other Oracle not in noraml API defines diff --git a/dbdcnx.c b/dbdcnx.c index 608269f4..6e6b6c83 100644 --- a/dbdcnx.c +++ b/dbdcnx.c @@ -528,6 +528,7 @@ cnx_pool_mode(pTHX_ SV * dbh, imp_dbh_t * imp_dbh, ub4 val) (void)oci_error(dbh, box->errhp, status, "OCIAttrSet POOL_GETMODE"); }/*}}}*/ /*cnx_pool_wait{{{*/ +#if OCI_MAJOR_VERSION > 18 void cnx_pool_wait(pTHX_ SV * dbh, imp_dbh_t * imp_dbh, ub4 val) { @@ -542,7 +543,9 @@ cnx_pool_wait(pTHX_ SV * dbh, imp_dbh_t * imp_dbh, ub4 val) ); if(status != OCI_SUCCESS) (void)oci_error(dbh, box->errhp, status, "OCIAttrSet POOL_WAIT_TIMEOUT"); -}/*}}}*/ +} +#endif +/*}}}*/ /*cnx_is_pooled_session{{{*/ int cnx_is_pooled_session(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) @@ -568,6 +571,7 @@ cnx_get_pool_mode(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) return 0; }/*}}}*/ /*cnx_get_pool_wait{{{*/ +#if OCI_MAJOR_VERSION > 18 int cnx_get_pool_wait(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) { @@ -584,7 +588,9 @@ cnx_get_pool_wait(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) if(status == OCI_SUCCESS) return (int)v; (void)oci_error(dbh, box->errhp, status, "OCIAttrGet POOL_WAIT_TIMEOUT"); return 0; -}/*}}}*/ +} +#endif +/*}}}*/ /*cnx_get_pool_used{{{*/ int cnx_get_pool_used(pTHX_ SV *dbh, imp_dbh_t * imp_dbh) diff --git a/dbdimp.c b/dbdimp.c index d16408b6..06ade41b 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -945,9 +945,11 @@ dbd_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) else if (kl==13 && strEQ(key, "ora_drcp_mode") ) { cnx_pool_mode(aTHX_ dbh, imp_dbh, (ub4)SvIV(valuesv)); } +#if OCI_MAJOR_VERSION > 18 else if (kl==13 && strEQ(key, "ora_drcp_wait") ) { cnx_pool_wait(aTHX_ dbh, imp_dbh, (ub4)SvIV(valuesv)); } +#endif else if (kl==12 && strEQ(key, "ora_drcp_max") ) { cnx_pool_max(aTHX_ dbh, imp_dbh, (ub4)SvIV(valuesv)); } @@ -1115,9 +1117,11 @@ dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) else if (kl==13 && strEQ(key, "ora_drcp_mode") ) { retsv = newSViv(cnx_get_pool_mode(aTHX_ dbh, imp_dbh)); } +#if OCI_MAJOR_VERSION > 18 else if (kl==13 && strEQ(key, "ora_drcp_wait") ) { retsv = newSViv(cnx_get_pool_wait(aTHX_ dbh, imp_dbh)); } +#endif else if (kl==12 && strEQ(key, "ora_drcp_max") ) { retsv = newSViv(cnx_get_pool_max(aTHX_ dbh, imp_dbh)); } diff --git a/dbdimp.h b/dbdimp.h index a5ac7ddb..c909caa3 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -409,8 +409,10 @@ void ora_shared_release(pTHX_ SV * ); int cnx_get_pool_mode(pTHX_ SV *, imp_dbh_t * ); void cnx_pool_mode(pTHX_ SV * , imp_dbh_t * , ub4); +#if OCI_MAJOR_VERSION > 18 int cnx_get_pool_wait(pTHX_ SV *, imp_dbh_t * ); void cnx_pool_wait(pTHX_ SV * , imp_dbh_t * , ub4); +#endif int cnx_get_pool_used(pTHX_ SV *, imp_dbh_t * ); diff --git a/lib/DBD/Oracle.pm b/lib/DBD/Oracle.pm index ec775e9a..dee46fe6 100644 --- a/lib/DBD/Oracle.pm +++ b/lib/DBD/Oracle.pm @@ -1256,6 +1256,10 @@ SQL __END__ +=head1 NAME + +DBD::Oracle - Perl module for accessing Oracle + =head1 SYNOPSIS @@ -1670,7 +1674,11 @@ by setting this attribute to one of OCI_SPOOL_ATTRVAL_NOWAIT, OCI_SPOOL_ATTRVAL_FORCEGET, OCI_SPOOL_ATTRVAL_TIMEDWAIT. The latter one needs time in milliseconds, which is passed using attribute ora_drcp_wait. Default value is OCI_SPOOL_ATTRVAL_WAIT. These contants can be imported -from DBD::Oracle. +from DBD::Oracle. Important, functionality with OCI_SPOOL_ATTRVAL_TIMEDWAIT +and OCI_SPOOL_ATTRVAL_NOWAIT was added by Oracle somewhere after version +12, so to make it safe, DBD::Oracle supports it when compiled against +OCI with Version > 18 + =head4 ora_drcp_tag diff --git a/t/25plsql.t b/t/25plsql.t index 680874cc..79ab89fe 100644 --- a/t/25plsql.t +++ b/t/25plsql.t @@ -331,10 +331,8 @@ SKIP: { # Also see http://www.mail-archive.com/dbi-users@perl.org/msg18835.html # Known bad OCI versions - my @bad_oci_vers = (9.2, 18.3, 18.5, 19.6, 19.9, 19.13, 21.3, 21.4, 21.5); - skip 'Client version is known to have issue', 4 - if grep { $_ == DBD::Oracle::ORA_OCI() } @bad_oci_vers; + if DBD::Oracle::ORA_OCI() > 18.0; my $sth = $dbh->prepare( q( From 376714fedbf01b65bc47c394cb851179dba99bc8 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Thu, 14 Apr 2022 10:09:41 -0700 Subject: [PATCH 620/637] Update changelog and bump version to 1.90_2 --- Changes | 1 + dist.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 49b7ead6..d63206a7 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,7 @@ Revision history for DBD::Oracle {{$NEXT}} Rewrite of login6. This is an enormous rewrite which should fix many problems - (PR#150, Andrei Voropaev) + Improvements to Makefile.PL - (PR#150, Andrei Voropaev) Have find_headers() also search for header files based off the major version number - (GH#142, Wesley Hinds) Check for appropriate permissions before running 56embbeded.t tests - (#143, Wesley Hinds) Updated links in doc in Oracle.pm - (Gh#145, kjetillll) diff --git a/dist.ini b/dist.ini index dbf7fbed..1849dcaa 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.90_1 +version = 1.90_2 ; Generate files From 3614e6a8d5c5885e3725012d9a43bf2d31673bca Mon Sep 17 00:00:00 2001 From: avorop <32192493+avorop@users.noreply.github.com> Date: Wed, 20 Apr 2022 09:09:55 +0200 Subject: [PATCH 621/637] Update dbdcnx.c Added freeing of allocated handle. It is not needed anymore since OCIAttrSet copies its conent (according to Oracle developers) --- dbdcnx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dbdcnx.c b/dbdcnx.c index 6e6b6c83..e5946f8d 100644 --- a/dbdcnx.c +++ b/dbdcnx.c @@ -761,6 +761,7 @@ new_pool_box(pTHX_ pool_box_t ** slot, dblogin_info_t * ctrl) OCIHandleFree(poolhp, OCI_HTYPE_SPOOL); return FALSE; } + OCIHandleFree(authp, OCI_HTYPE_AUTHINFO); } #endif From 8d1950294bd47735b060512c557071af860c8daf Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 20 Apr 2022 21:34:42 -0700 Subject: [PATCH 622/637] Update Changes, bump version --- Changes | 1 + dist.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index d63206a7..60b45fe0 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,7 @@ Revision history for DBD::Oracle {{$NEXT}} + Update dbdcnx.c - (PR#152, Andrei Voropaev) Rewrite of login6. This is an enormous rewrite which should fix many problems - (PR#150, Andrei Voropaev) Improvements to Makefile.PL - (PR#150, Andrei Voropaev) Have find_headers() also search for header files based off the major version number - (GH#142, Wesley Hinds) diff --git a/dist.ini b/dist.ini index 1849dcaa..e559e492 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.90_2 +version = 1.90_3 ; Generate files From d176dcd4355ae79e5b9c1a29c5fb132e6e32af31 Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Thu, 7 Apr 2022 14:20:12 -0500 Subject: [PATCH 623/637] Move from TravisCI to Github Actions (GHA). The GHA will build against the "latest" Ubuntu/Perl/OracleXE/InstantClient that is currently available. --- .github/workflows/action.yml | 54 +++ .travis.yml | 353 ------------------ maint/Dockerfile | 4 +- .../01_install_oracle_xe.bash | 0 .../02_install_oracle_instantclient.bash | 0 .../03_install_oracle_instantclient_rpm.bash | 29 ++ 6 files changed, 85 insertions(+), 355 deletions(-) create mode 100644 .github/workflows/action.yml delete mode 100644 .travis.yml rename maint/{travis-ci_scripts => scripts}/01_install_oracle_xe.bash (100%) rename maint/{travis-ci_scripts => scripts}/02_install_oracle_instantclient.bash (100%) create mode 100755 maint/scripts/03_install_oracle_instantclient_rpm.bash diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml new file mode 100644 index 00000000..acd85282 --- /dev/null +++ b/.github/workflows/action.yml @@ -0,0 +1,54 @@ +name: build + +on: + push: + branches: + - "*" + pull_request: + branches: + - "*" + workflow_dispatch: + +## +# Adjust container-image for different Perl version +# Adjust services-oracle-image for different OracleXE DB versions +# Adjust container-env-ORACLEV for different InstantClient versions +## +jobs: + build-job: + name: Build Latest + runs-on: ubuntu-latest + container: + image: perldocker/perl-tester:latest + env: + ORACLEV: latest + ORACLE_USERID: kermit/foobar + ORACLE_DSN: 'dbi:Oracle://oracle:1521/XEPDB1' + services: + # Oracle service (label used to access the service container) + oracle: + # Docker Hub image (change the tag "latest" to any other available one) + image: gvenzl/oracle-xe:latest + # Provide passwords and other environment variables to container + env: + ORACLE_PASSWORD: adminpass + APP_USER: kermit + APP_USER_PASSWORD: foobar + # Forward Oracle port + ports: + - 1521:1521 + # Provide healthcheck script options for startup + options: >- + --health-cmd healthcheck.sh + --health-interval 10s + --health-timeout 5s + --health-retries 10 + steps: + - uses: actions/checkout@v2 + - run: apt-get update -y + - run: apt-get install -y libaio1 libaio-dev bc sudo alien + - run: sudo -E maint/scripts/03_install_oracle_instantclient_rpm.bash + - run: . /etc/profile + - run: perl -V + - run: cpanm DBI Test::NoWarnings + - run: perl Makefile.PL && make && make test diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0b45c3c7..00000000 --- a/.travis.yml +++ /dev/null @@ -1,353 +0,0 @@ -language: perl - -# See https://docs.travis-ci.com/user/reference/overview/#Virtualisation-Environment-vs-Operating-System -os: linux -dist: xenial - -env: - global: - - AUTHOR_TESTING=1 - - AUTOMATED_TESTING=1 - - EXTENDED_TESTING=1 - - RELEASE_TESTING=0 - - CFLAGS="-g -O2 -fstack-protector -Wformat -Werror=format-security" - - CPPFLAGS="-D_FORTIFY_SOURCE=2" - - CXXFLAGS="-g -O2 -fstack-protector -Wformat -Werror=format-security" - - LDFLAGS="-Wl,-z,relro" - -addons: - apt: - packages: - - unzip - - libaio1 - -jobs: - fast_finish: true - - allow_failures: - - perl: 'blead' - - perl: '5.8' - -# FYI Oracle XE only comes in utf8, so we can't run USASCII version of tests - - include: -# Perl 5.32 variations -## At 2020-09-03 Travis's 5.32 is broken -## - perl: '5.32' -## env: -## - ORACLEV=11.2 -## - ORACLEDBV=11.2 -## - ORACLE_USERID=kermit/foobar -## - ORACLE_USERID_2=mspiggy/barfoo -## - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' -## -## - perl: '5.32' -## env: -## - ORACLEV=12.2 -## - ORACLEDBV=11.2 -## - ORACLE_USERID=kermit/foobar -## - ORACLE_USERID_2=mspiggy/barfoo -## - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - perl: '5.32-shrplib' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.32-shrplib' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.32-shrplib' - env: - - ORACLEV=18.3 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.32-shrplib' - env: - - ORACLEV=18.5 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.32-shrplib' - env: - - ORACLEV=19.6 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - -# Perl 5.28 variations - - perl: '5.28' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.28' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.28' - env: - - ORACLEV=18.3 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.28' - env: - - ORACLEV=18.5 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.28' - env: - - ORACLEV=19.6 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.28-shrplib' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.28-shrplib' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.28-shrplib' - env: - - ORACLEV=18.3 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.28-shrplib' - env: - - ORACLEV=18.5 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.28-shrplib' - env: - - ORACLEV=19.6 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - -# Perl 5.26 variations - - perl: '5.26' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.26' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.26-shrplib' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.26-shrplib' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - -# Perl 5.24 variations - - perl: '5.24' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.24' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.24-shrplib' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.24-shrplib' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.24-extras' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.24-extras' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - -# Perl 5.22 variations - - perl: '5.22' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.22' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.22-shrplib' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.22-shrplib' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.22-extras' - env: - - ORACLEV=11.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - - - perl: '5.22-extras' - env: - - ORACLEV=12.2 - - ORACLEDBV=11.2 - - ORACLE_USERID=kermit/foobar - - ORACLE_USERID_2=mspiggy/barfoo - - ORACLE_DSN='dbi:Oracle://localhost:1521/XE' - -# Test without database, all tests should skip - - perl: '5.32' - env: - - ORACLEV=11.2 - - COVERAGE=1 - - perl: '5.32' - env: - - ORACLEV=12.2 - - COVERAGE=1 - - perl: '5.32' - env: - - ORACLEV=18.3 - - COVERAGE=1 - - perl: '5.32' - env: - - ORACLEV=18.5 - - COVERAGE=1 - -before_install: - - sudo maint/travis-ci_scripts/01_install_oracle_xe.bash - - sudo maint/travis-ci_scripts/02_install_oracle_instantclient.bash - - . /etc/profile - - git config --global user.name "TravisCI" - - git config --global user.email $HOSTNAME":not-for-mail@travis-ci.org" - - git clone git://github.com/travis-perl/helpers ~/travis-perl-helpers - - source ~/travis-perl-helpers/init - - build-perl - - perl -V - - build-dist - - cd $BUILD_DIR - - cat cpanfile - -install: - - perl -M5.014 -e1 2>/dev/null || cpan-install Dist::Zilla@5.047 - - cpan-install --update-prereqs --deps - - cpan-install --update-prereqs --coverage - -before_script: - - pwd - - coverage-setup - -script: - - perl Makefile.PL - - make -# - make test - - prove -bv -r -s -j1 $(test-files) - - ORACLE_USERID_2="" prove -bv t/60reauth.t -# - dzil smoke --release --author - -after_success: - - coverage-report diff --git a/maint/Dockerfile b/maint/Dockerfile index 10057c4d..cc0e0bfa 100644 --- a/maint/Dockerfile +++ b/maint/Dockerfile @@ -26,8 +26,8 @@ COPY . /usr/src/DBD-Oracle RUN apt-get update && apt-get install -y libaio-dev && \ apt-get install -y vim less net-tools && \ cpanm --verbose --notest --installdeps /usr/src/DBD-Oracle && \ - /usr/src/DBD-Oracle/maint/travis-ci_scripts/01_install_oracle_xe.bash && \ - /usr/src/DBD-Oracle/maint/travis-ci_scripts/02_install_oracle_instantclient.bash && \ + /usr/src/DBD-Oracle/maint/scripts/01_install_oracle_xe.bash && \ + /usr/src/DBD-Oracle/maint/scripts/02_install_oracle_instantclient.bash && \ sync && /etc/init.d/oracle-xe stop && apt-get clean WORKDIR /usr/src/DBD-Oracle diff --git a/maint/travis-ci_scripts/01_install_oracle_xe.bash b/maint/scripts/01_install_oracle_xe.bash similarity index 100% rename from maint/travis-ci_scripts/01_install_oracle_xe.bash rename to maint/scripts/01_install_oracle_xe.bash diff --git a/maint/travis-ci_scripts/02_install_oracle_instantclient.bash b/maint/scripts/02_install_oracle_instantclient.bash similarity index 100% rename from maint/travis-ci_scripts/02_install_oracle_instantclient.bash rename to maint/scripts/02_install_oracle_instantclient.bash diff --git a/maint/scripts/03_install_oracle_instantclient_rpm.bash b/maint/scripts/03_install_oracle_instantclient_rpm.bash new file mode 100755 index 00000000..c5a6efe2 --- /dev/null +++ b/maint/scripts/03_install_oracle_instantclient_rpm.bash @@ -0,0 +1,29 @@ +#!/bin/bash + +set -ex + +if [ "$ORACLEV" = "latest" ]; then + # Get lastest RPMs from Oracle Client permanent links + for i in "basic" "devel" "sqlplus"; do + wget --quiet "https://download.oracle.com/otn_software/linux/instantclient/oracle-instantclient-$i-linuxx64.rpm" + done + + # Convert rpm to deb pkgs + alien -k *.rpm + dpkg -i *.deb + + ls -l /usr/lib/oracle/21/client64 + + ORACLEV=$(ls /usr/lib/oracle | sed 's/\///') + + echo "# Place paths in ENV" + echo "export ORACLE_HOME=/usr/lib/oracle/$ORACLEV/client64" >> /etc/profile.d/oracle.sh + echo "export PATH=\$PATH:\$ORACLE_HOME/bin" >> /etc/profile.d/oracle.sh + echo "export TNS_ADMIN=/etc/oracle" >> /etc/profile.d/oracle.sh + echo "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$ORACLE_HOME/lib" >> /etc/profile.d/oracle.sh + echo "/usr/lib/oracle/$ORACLEV/client64/lib" > /etc/ld.so.conf.d/oracle-instantclient.conf + echo "# Make sure stuff is +x" + chmod +x /usr/lib/oracle/$ORACLEV/client64/bin/* + ldconfig + cat /etc/profile +fi From 423d737b8ca032af2b5644627de601b332ad7ab4 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 20 Apr 2022 21:44:09 -0700 Subject: [PATCH 624/637] Update changes for PR#152 --- Changes | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes b/Changes index 60b45fe0..06ea1e85 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,7 @@ Revision history for DBD::Oracle {{$NEXT}} + Move from TravisCI to Github Actions (GHA) - (PR#152, Wesley Hinds) Update dbdcnx.c - (PR#152, Andrei Voropaev) Rewrite of login6. This is an enormous rewrite which should fix many problems - (PR#150, Andrei Voropaev) Improvements to Makefile.PL - (PR#150, Andrei Voropaev) From 3ecb172c17f94d21f692915703c4310a2bd23807 Mon Sep 17 00:00:00 2001 From: avorop <32192493+avorop@users.noreply.github.com> Date: Sat, 13 Aug 2022 08:41:56 +0100 Subject: [PATCH 625/637] Convert inline functions to macros Some old systems can not use inline function --- dbdcnx.c | 73 +++++++++++++++++++------------------------------------- 1 file changed, 24 insertions(+), 49 deletions(-) diff --git a/dbdcnx.c b/dbdcnx.c index e5946f8d..b0550bb3 100644 --- a/dbdcnx.c +++ b/dbdcnx.c @@ -67,62 +67,37 @@ struct llist_t{ llist_t * right; }; -PERL_STATIC_INLINE int -llist_empty(const llist_t * list) -{ - return list->left == list; -} +#define llist_empty(list) ((list)->left == (list)) -PERL_STATIC_INLINE void -llist_init(llist_t *list) -{ - list->right = list->left = list; -} +#define llist_init(lst) do{\ + llist_t * list = lst;\ + list->right = list->left = list;\ +}while(0) -PERL_STATIC_INLINE void -llist_add(llist_t * left, llist_t * right) -{ - llist_t * old; +#define llist_add(aleft, aright) do{\ + llist_t * old;\ + llist_t * left = aleft;\ + llist_t * right = aright;\ + old = left->right;\ + left->right = right;\ + old->left = right->left;\ + right->left = left;\ + old->left->right = old;\ +}while(0) - // first save the pointer from the left->rigth - old = left->right; - - // now left->right shall point to right - left->right = right; - - // now the old left pointer shall point to what the - // new right->left was pointing - old->left = right->left; - - // now right->left shall contain the left - right->left = left; - - // finally - old->left->right = old; -} - -PERL_STATIC_INLINE void -llist_drop(llist_t * el) -{ - if(llist_empty(el)) return; - el->left->right = el->right; - el->right->left = el->left; - llist_init(el); -} +#define llist_drop(ael) do{\ + llist_t * el = ael;\ + if(llist_empty(el)) return;\ + el->left->right = el->right;\ + el->right->left = el->left;\ + llist_init(el);\ +}while(0) // this is pointer to the left element in chain -PERL_STATIC_INLINE llist_t * -llist_left(const llist_t * list) -{ - return list->left; -} +#define llist_left(list) (list)->left // this one is a pointer to the right element in chain -PERL_STATIC_INLINE llist_t * -llist_right(const llist_t *list) -{ - return list->right; -} +#define llist_right(list) (list)->right /* }}} */ #if defined(USE_ITHREADS) From d3b371805225325aa2937934dfd47cc7a2707ad8 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 29 Aug 2022 20:20:35 -0700 Subject: [PATCH 626/637] Add DBI to ConfigureRequires, BuildRequires, and Test Requires - (GH#155) --- Changes | 1 + dist.ini | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Changes b/Changes index 06ea1e85..533eff5c 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,7 @@ Revision history for DBD::Oracle {{$NEXT}} + Add DBI to ConfigureRequires, BuildRequires, and Test Requires - (GH#155) Move from TravisCI to Github Actions (GHA) - (PR#152, Wesley Hinds) Update dbdcnx.c - (PR#152, Andrei Voropaev) Rewrite of login6. This is an enormous rewrite which should fix many problems - (PR#150, Andrei Voropaev) diff --git a/dist.ini b/dist.ini index e559e492..91c05563 100644 --- a/dist.ini +++ b/dist.ini @@ -93,16 +93,21 @@ DBI = 1.623 DynaLoader = 0 Exporter = 0 +[Prereqs / ConfigureRequires] +DBI = 1.623 + [Prereqs / DevelopRequires] DBI = 1.623 Test::NoWarnings = 0 [Prereqs / BuildRequires] Config = 0 +DBI = 1.623 [Prereqs / TestRequires] warnings = 0 strict = 0 +DBI = 1.623 Devel::Peek = 0 Encode = 0 Math::BigInt = 0 From 30849ecac6e2d26c8f6fafaf88519c16a42ec0ac Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 29 Aug 2022 20:22:22 -0700 Subject: [PATCH 627/637] Bump to v1.90_4 --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 91c05563..c14906ce 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.90_3 +version = 1.90_4 ; Generate files From a432797de131e7a331dfc96d9d415f0c9bc71221 Mon Sep 17 00:00:00 2001 From: Wesley Hinds Date: Thu, 29 Dec 2022 13:05:35 -0600 Subject: [PATCH 628/637] dbivport.h should be installed as well. GH#159 --- Makefile.PL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.PL b/Makefile.PL index 75056ec2..7023a614 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1798,7 +1798,7 @@ sub symbol_search { } close main::MK_PM or die "Error closing mk.pm: $!\n"; - foreach (qw(mk.pm Oracle.h dbdimp.h ocitrace.h)) { + foreach (qw(mk.pm Oracle.h dbdimp.h dbivport.h ocitrace.h)) { $self->{PM}->{$_} = '$(INST_ARCHAUTODIR)/'.$_; } From 6d0a466f5e6d1d3e9ee637edc63599f5efbf3869 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Sat, 14 Jan 2023 00:22:10 -0800 Subject: [PATCH 629/637] Update changes file and bump version to 1.90_5 --- Changes | 1 + dist.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 533eff5c..3ba83bcb 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,7 @@ Revision history for DBD::Oracle {{$NEXT}} + Ensure dbivport.h is installed- (GH#150, Wesley Hinds) Add DBI to ConfigureRequires, BuildRequires, and Test Requires - (GH#155) Move from TravisCI to Github Actions (GHA) - (PR#152, Wesley Hinds) Update dbdcnx.c - (PR#152, Andrei Voropaev) diff --git a/dist.ini b/dist.ini index c14906ce..fe8de5bc 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.90_4 +version = 1.90_5 ; Generate files From aa8687e049b48b5a970ea2877e9c41ef1db8eae5 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Tue, 28 Feb 2023 18:27:26 -0800 Subject: [PATCH 630/637] Update README. Point to ::Troubleshooting:: and remove files long deleted GH#156 --- README | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/README b/README index fe3891c9..30e02953 100644 --- a/README +++ b/README @@ -1,31 +1,32 @@ DBD::Oracle -- an Oracle interface for Perl 5. - Copyright (c) 1994-2020 Tim Bunce, et. al. + Copyright (c) 1994-2023 Tim Bunce, et. al. See the COPYRIGHT section in the Oracle.pm file for terms. See also the MAINTAINER section in the Oracle.pm PLEASE READ THE ENTIRE README FILE CAREFULLY ! - AND THEN READ ANY README.* FILES RELEVANT TO YOUR PLATFORM: + AND THEN READ ANY TROUBLESHOOTING POD FILES RELEVANT TO YOUR PLATFORM: - README.aix.txt - AIX - README.hpux.txt - HP-UX - README.java.txt - Java/thread problem on Solaris - README.macosx.txt - Mac OS/X - README.win32.txt - MS Windows - README.wingcc.txt - MS Windows using GCC - README.* - see if there's a file for your platform + DBD::Oracle::Troubleshooting - General Tips + DBD::Oracle::Troubleshooting::Aix - AIX + DBD::Oracle::Troubleshooting::Cygwin - MS Windows using GCC + DBD::Oracle::Troubleshooting::Hpux - HP-UX + DBD::Oracle::Troubleshooting::Linux - Linux + DBD::Oracle::Troubleshooting::Macos - Mac OS + DBD::Oracle::Troubleshooting::Sun - Sun + DBD::Oracle::Troubleshooting::Vms - OpenVMS + DBD::Oracle::Troubleshooting::Win32 - MS Windows (32bit) + DBD::Oracle::Troubleshooting::Win64 - MS Windows (64bit) + DBD::Oracle::Troubleshooting::* - see if there's a file for your platform + + DBD::Oracle::Troubleshooting::java.txt - Java/thread problem on Solaris You may find these useful README.help.txt - Help and hints on build problems - README.sec.txt - Oracle security issues to be aware of - README.login.txt - Help on how to connect to Oracle - README.longs.txt - Help on handling LONGs - README.clients.txt - What Oracle client files you need installed - *** QUICK START GUIDE: @@ -258,12 +259,7 @@ Tim. Examples and other info: README.help.txt -- READ IT FIRST IF YOU HAVE ANY PROBLEMS -README.win32.txt -- building DBD::Oracle under MS Windows -README.wingcc.txt -- building DBD::Oracle under MS Windows with gcc -README.macosx.txt -- building DBD::Oracle under MacOS X -README.clients.txt -- building/using DBD::Oracle on minimally configured system -README.login.txt -- help for login problems -README.longs.txt -- examples dealing with LONG types (blobs) +DBD::Oracle::Troubleshooting::* -- Various platform specific info DBI 'home page': http://dbi.perl.org From 49dbeaaa951886e802931a2a873b7c1f4fa11c99 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Tue, 21 Mar 2023 16:31:41 +0100 Subject: [PATCH 631/637] specify resources metadata explicitly in dist.ini The latest stable release of DBD::Oracle listed the wrong bug tracker and repository because it was released from a fork, and the [GithubMeta] plugin used that fork to set the metadata. Remove that plugin, and instead specify the bug tracker and repository explicitly. --- Makefile.PL | 9 --------- dist.ini | 8 ++++++-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 7023a614..c793c117 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -60,15 +60,6 @@ my %opts = ( build_requires => {"DBI" => '1.623', "ExtUtils::MakeMaker" => 0, "Test::Simple" => '0.90'}, - resources => { - bugtracker => { web => 'https://github.com/perl5-dbi/DBD-Oracle/issues'}, - homepage => 'https://metacpan.org/pod/DBD::Oracle', - repository => { - type => 'git', - url => 'git://github.com/perl5-dbi/DBD-Oracle.git', - web => 'http://github.com/perl5-dbi/DBD-Oracle', - }, - }, }, ); my $eumm = $ExtUtils::MakeMaker::VERSION; diff --git a/dist.ini b/dist.ini index fe8de5bc..3f9820c8 100644 --- a/dist.ini +++ b/dist.ini @@ -20,8 +20,12 @@ version = 1.90_5 [Git::Contributors] [ContributorsFile] [InstallGuide] -[GithubMeta] -issues = 1 +[MetaResources] +homepage = https://metacpan.org/pod/DBD::Oracle +bugtracker.web = https://github.com/perl5-dbi/DBD-Oracle/issues +repository.url = https://github.com/perl5-dbi/DBD-Oracle.git +repository.web = https://github.com/perl5-dbi/DBD-Oracle +repository.type = git [MetaJSON] [PodWeaver] From c9b21c179dd2740bed939490f879d3b39f199b8f Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 15 Apr 2024 22:32:05 -0700 Subject: [PATCH 632/637] It's now 2024 --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 30e02953..5c794eed 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ DBD::Oracle -- an Oracle interface for Perl 5. - Copyright (c) 1994-2023 Tim Bunce, et. al. + Copyright (c) 1994-2024 Tim Bunce, et. al. See the COPYRIGHT section in the Oracle.pm file for terms. See also the MAINTAINER section in the Oracle.pm From 70ef408c28ee60da4d276180380ac98f3f7d9cb4 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 15 Apr 2024 22:42:31 -0700 Subject: [PATCH 633/637] Update changes for GH#162 --- Changes | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes b/Changes index 3ba83bcb..fd4e5cb4 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,7 @@ Revision history for DBD::Oracle {{$NEXT}} + Specify resources metadata explicitly in dist.ini (HG#162, Graham Knop) Ensure dbivport.h is installed- (GH#150, Wesley Hinds) Add DBI to ConfigureRequires, BuildRequires, and Test Requires - (GH#155) Move from TravisCI to Github Actions (GHA) - (PR#152, Wesley Hinds) From 120e777e39931863e3d992ca2f15cb095ea5ec5f Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Mon, 15 Apr 2024 22:42:52 -0700 Subject: [PATCH 634/637] Bump version to 1.90 --- dist.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist.ini b/dist.ini index 3f9820c8..c696d64f 100644 --- a/dist.ini +++ b/dist.ini @@ -8,7 +8,7 @@ copyright_holder = Tim Bunce copyright_year = 1994 main_module = lib/DBD/Oracle.pm -version = 1.90_5 +version = 1.90 ; Generate files From 9dc2ca0bc4f249075d179014aed5e1bc346f8dc4 Mon Sep 17 00:00:00 2001 From: Lorinczy Zsigmond Date: Tue, 25 Jun 2024 21:21:20 +0200 Subject: [PATCH 635/637] Changing 'return' to block statement, fixing a problem created while transforming inline function to macro --- dbdcnx.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dbdcnx.c b/dbdcnx.c index b0550bb3..569f46f2 100644 --- a/dbdcnx.c +++ b/dbdcnx.c @@ -87,10 +87,11 @@ struct llist_t{ #define llist_drop(ael) do{\ llist_t * el = ael;\ - if(llist_empty(el)) return;\ - el->left->right = el->right;\ - el->right->left = el->left;\ - llist_init(el);\ + if(!llist_empty(el)) {\ + el->left->right = el->right;\ + el->right->left = el->left;\ + llist_init(el);\ + } \ }while(0) // this is pointer to the left element in chain From 5122724db82a29041f8f05675b76ba7357f0e78e Mon Sep 17 00:00:00 2001 From: Sam James Date: Sat, 27 May 2023 13:13:43 +0100 Subject: [PATCH 636/637] Makefile.PL: help ora_libdir find ORACLE_HOME on Gentoo On Gentoo, for better or worse, we install oracle-instantclient on 64-bit systems to /usr/lib64/oracle/client/ with: * /usr/lib64/oracle/client/lib for 32-bit libraries (multilib) * /usr/lib64/oracle/client/lib64 for native 64-bit libraries Adapt the logic to handle lib64 if it exists and we're using a 64-bit Perl. (And fix some whitespace while at it.) --- Makefile.PL | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index c793c117..bb5e6289 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1115,14 +1115,15 @@ sub perl_is_64bit { return defined $Config{use64bitall} ; } sub ora_libdir { - my $libdir = 'lib' ; + my $libdir = 'lib'; if ( $client_version >= 9 ) { $libdir = 'lib32' if ! perl_is_64bit() and -d "$OH/lib32"; + $libdir = 'lib64' if perl_is_64bit() and -d "$OH/lib64"; + # Solaris OIC 12+ from pkg $libdir = 'lib/64' if perl_is_64bit() and -d "$OH/lib/64"; - # Solaris OIC 12+ from pkg } else { - $libdir = 'lib64' if perl_is_64bit() and -d "$OH/lib64"; + $libdir = 'lib64' if perl_is_64bit() and -d "$OH/lib64"; } return $libdir; From a02c0d980c4ce273e7f8d7b2ec51c1b0fa5c1929 Mon Sep 17 00:00:00 2001 From: Dean Hamstead Date: Wed, 17 Jul 2024 22:25:41 -0700 Subject: [PATCH 637/637] Remove oracle v21 specific code --- maint/scripts/03_install_oracle_instantclient_rpm.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maint/scripts/03_install_oracle_instantclient_rpm.bash b/maint/scripts/03_install_oracle_instantclient_rpm.bash index c5a6efe2..91e30ca4 100755 --- a/maint/scripts/03_install_oracle_instantclient_rpm.bash +++ b/maint/scripts/03_install_oracle_instantclient_rpm.bash @@ -8,11 +8,11 @@ if [ "$ORACLEV" = "latest" ]; then wget --quiet "https://download.oracle.com/otn_software/linux/instantclient/oracle-instantclient-$i-linuxx64.rpm" done - # Convert rpm to deb pkgs + # Convert rpm to deb pkgs alien -k *.rpm dpkg -i *.deb - ls -l /usr/lib/oracle/21/client64 + find /usr/lib/oracle ORACLEV=$(ls /usr/lib/oracle | sed 's/\///')